001/*
002 * $Id: GroebnerBaseSeqPairDistributed.java 5891 2018-07-29 21:02:51Z kredel $
003 */
004
005package edu.jas.gb;
006
007
008import java.io.IOException;
009import java.io.Serializable;
010import java.util.ArrayList;
011import java.util.Collections;
012import java.util.List;
013import java.util.ListIterator;
014import java.util.concurrent.Semaphore;
015
016import org.apache.logging.log4j.Logger;
017import org.apache.logging.log4j.LogManager; 
018
019import edu.jas.poly.ExpVector;
020import edu.jas.poly.GenPolynomial;
021import edu.jas.structure.RingElem;
022import edu.jas.util.ChannelFactory;
023import edu.jas.util.DistHashTable;
024import edu.jas.util.DistHashTableServer;
025import edu.jas.util.SocketChannel;
026import edu.jas.util.Terminator;
027import edu.jas.util.ThreadPool;
028
029
030/**
031 * Groebner Base distributed algorithm. Implements a distributed memory parallel
032 * version of Groebner bases. Using pairlist class, distributed tasks do
033 * reduction. Makes some effort to produce the same sequence of critical pairs
034 * as in the sequential version. However already reduced pairs are not rereduced
035 * if new polynomials appear.
036 * @param <C> coefficient type
037 * @author Heinz Kredel
038 * @deprecated no direct alternative, use GroebnerBaseDistributedEC
039 */
040@Deprecated
041public class GroebnerBaseSeqPairDistributed<C extends RingElem<C>> extends GroebnerBaseAbstract<C> {
042
043
044    private static final Logger logger = LogManager.getLogger(GroebnerBaseSeqPairDistributed.class);
045
046
047    /**
048     * Number of threads to use.
049     */
050    protected final int threads;
051
052
053    /**
054     * Default number of threads.
055     */
056    protected static final int DEFAULT_THREADS = 2;
057
058
059    /**
060     * Pool of threads to use.
061     */
062    protected transient final ThreadPool pool;
063
064
065    /**
066     * Default server port.
067     */
068    protected static final int DEFAULT_PORT = 4711;
069
070
071    /**
072     * Server port to use.
073     */
074    protected final int port;
075
076
077    /**
078     * Constructor.
079     */
080    public GroebnerBaseSeqPairDistributed() {
081        this(DEFAULT_THREADS, DEFAULT_PORT);
082    }
083
084
085    /**
086     * Constructor.
087     * @param threads number of threads to use.
088     */
089    public GroebnerBaseSeqPairDistributed(int threads) {
090        this(threads, new ThreadPool(threads), DEFAULT_PORT);
091    }
092
093
094    /**
095     * Constructor.
096     * @param threads number of threads to use.
097     * @param red parallelism aware reduction engine
098     */
099    public GroebnerBaseSeqPairDistributed(int threads, Reduction<C> red) {
100        this(threads, new ThreadPool(threads), DEFAULT_PORT, red);
101    }
102
103
104    /**
105     * Constructor.
106     * @param threads number of threads to use.
107     * @param port server port to use.
108     * @param red parallelism aware reduction engine
109     */
110    public GroebnerBaseSeqPairDistributed(int threads, int port, Reduction<C> red) {
111        this(threads, new ThreadPool(threads), port, red);
112    }
113
114
115    /**
116     * Constructor.
117     * @param threads number of threads to use.
118     * @param port server port to use.
119     */
120    public GroebnerBaseSeqPairDistributed(int threads, int port) {
121        this(threads, new ThreadPool(threads), port);
122    }
123
124
125    /**
126     * Constructor.
127     * @param threads number of threads to use.
128     * @param pool ThreadPool to use.
129     * @param port server port to use.
130     */
131    public GroebnerBaseSeqPairDistributed(int threads, ThreadPool pool, int port) {
132        this(threads, pool, port, new ReductionPar<C>());
133    }
134
135
136    /**
137     * Constructor.
138     * @param threads number of threads to use.
139     * @param pool ThreadPool to use.
140     * @param port server port to use.
141     * @param red parallelism aware reduction engine
142     */
143    public GroebnerBaseSeqPairDistributed(int threads, ThreadPool pool, int port, Reduction<C> red) {
144        super(red);
145        if (!(red instanceof ReductionPar)) {
146            logger.warn("parallel GB should use parallel aware reduction");
147        }
148        if (threads < 1) {
149            threads = 1;
150        }
151        this.threads = threads;
152        this.pool = pool;
153        this.port = port;
154    }
155
156
157    /**
158     * Cleanup and terminate ThreadPool.
159     */
160    @Override
161    public void terminate() {
162        if (pool == null) {
163            return;
164        }
165        pool.terminate();
166    }
167
168
169    /**
170     * Distributed Groebner base. Slaves maintain pairlist.
171     * @param modv number of module variables.
172     * @param F polynomial list.
173     * @return GB(F) a Groebner base of F or null, if a IOException occurs.
174     */
175    public List<GenPolynomial<C>> GB(int modv, List<GenPolynomial<C>> F) {
176
177        final int DL_PORT = port + 100;
178        ChannelFactory cf = new ChannelFactory(port);
179        cf.init();
180        DistHashTableServer<Integer> dls = new DistHashTableServer<Integer>(DL_PORT);
181        dls.init();
182        logger.debug("dist-list server running");
183
184        GenPolynomial<C> p;
185        //List<GenPolynomial<C>> G = new ArrayList<GenPolynomial<C>>();
186        CriticalPairList<C> pairlist = null;
187        boolean oneInGB = false;
188        //int l = F.size();
189        @SuppressWarnings("unused")
190        int unused;
191        ListIterator<GenPolynomial<C>> it = F.listIterator();
192        while (it.hasNext()) {
193            p = it.next();
194            if (p.length() > 0) {
195                p = p.monic();
196                if (p.isONE()) {
197                    oneInGB = true;
198                    //G.clear();
199                    //G.add(p);
200                    //return G; must signal termination to others
201                }
202                //if (!oneInGB) {
203                //    //G.add(p);
204                //}
205                if (pairlist == null) {
206                    pairlist = new CriticalPairList<C>(modv, p.ring);
207                }
208                // theList not updated here
209                if (p.isONE()) {
210                    unused = pairlist.putOne();
211                } else {
212                    unused = pairlist.put(p);
213                }
214            } else {
215                //l--;
216            }
217        }
218        //if (l <= 1) {
219        //return G; must signal termination to others
220        //}
221
222        logger.debug("looking for clients");
223        //long t = System.currentTimeMillis();
224        // now in DL, uses resend for late clients
225        //while ( dls.size() < threads ) { sleep(); }
226
227        DistHashTable<Integer, GenPolynomial<C>> theList = new DistHashTable<Integer, GenPolynomial<C>>(
228                        "localhost", DL_PORT);
229        theList.init();
230        List<GenPolynomial<C>> G = pairlist.getList();
231        for (int i = 0; i < G.size(); i++) {
232            // no wait required
233            GenPolynomial<C> nn = theList.put(Integer.valueOf(i), G.get(i));
234            if (nn != null) {
235                logger.info("double polynomials " + i + ", nn = " + nn + ", G(i) = " + G.get(i));
236            }
237        }
238
239        Terminator fin = new Terminator(threads);
240        ReducerServerSeqPair<C> R;
241        for (int i = 0; i < threads; i++) {
242            R = new ReducerServerSeqPair<C>(fin, cf, theList, pairlist);
243            pool.addJob(R);
244        }
245        logger.debug("main loop waiting");
246        fin.waitDone();
247        int ps = theList.size();
248        //logger.debug("#distributed list = "+ps);
249        // make sure all polynomials arrived: not needed in master
250        // G = (ArrayList)theList.values();
251        G = pairlist.getList();
252        //logger.debug("#pairlist list = "+G.size());
253        if (ps != G.size()) {
254            logger.info("#distributed list = " + theList.size() + " #pairlist list = " + G.size());
255        }
256        long time = System.currentTimeMillis();
257        List<GenPolynomial<C>> Gp;
258        Gp = minimalGB(G); // not jet distributed but threaded
259        time = System.currentTimeMillis() - time;
260        logger.info("parallel gbmi = " + time);
261        /*
262        time = System.currentTimeMillis();
263        G = GroebnerBase.<C>GBmi(G); // sequential
264        time = System.currentTimeMillis() - time;
265        logger.info("sequential gbmi = " + time);
266        */
267        G = Gp;
268        //logger.info("cf.terminate()");
269        cf.terminate();
270        // no more required // pool.terminate();
271        logger.info("theList.terminate()");
272        theList.terminate();
273        logger.info("dls.terminate()");
274        dls.terminate();
275        logger.info("" + pairlist);
276        return G;
277    }
278
279
280    /**
281     * GB distributed client.
282     * @param host the server runns on.
283     * @throws IOException
284     */
285    public void clientPart(String host) throws IOException {
286
287        ChannelFactory cf = new ChannelFactory(port + 10); // != port for localhost
288        cf.init();
289        SocketChannel pairChannel = cf.getChannel(host, port);
290
291        final int DL_PORT = port + 100;
292        DistHashTable<Integer, GenPolynomial<C>> theList = new DistHashTable<Integer, GenPolynomial<C>>(host,
293                        DL_PORT);
294        theList.init();
295
296        ReducerClientSeqPair<C> R = new ReducerClientSeqPair<C>(pairChannel, theList);
297        R.run();
298
299        pairChannel.close();
300        theList.terminate();
301        cf.terminate();
302        return;
303    }
304
305
306    /**
307     * Minimal ordered groebner basis.
308     * @param Fp a Groebner base.
309     * @return a reduced Groebner base of Fp.
310     */
311    @SuppressWarnings("cast")
312    @Override
313    public List<GenPolynomial<C>> minimalGB(List<GenPolynomial<C>> Fp) {
314        GenPolynomial<C> a;
315        ArrayList<GenPolynomial<C>> G;
316        G = new ArrayList<GenPolynomial<C>>(Fp.size());
317        ListIterator<GenPolynomial<C>> it = Fp.listIterator();
318        while (it.hasNext()) {
319            a = it.next();
320            if (a.length() != 0) { // always true
321                // already monic  a = a.monic();
322                G.add(a);
323            }
324        }
325        if (G.size() <= 1) {
326            return G;
327        }
328
329        ExpVector e;
330        ExpVector f;
331        GenPolynomial<C> p;
332        ArrayList<GenPolynomial<C>> F;
333        F = new ArrayList<GenPolynomial<C>>(G.size());
334        boolean mt;
335
336        while (G.size() > 0) {
337            a = G.remove(0);
338            e = a.leadingExpVector();
339
340            it = G.listIterator();
341            mt = false;
342            while (it.hasNext() && !mt) {
343                p = it.next();
344                f = p.leadingExpVector();
345                mt = e.multipleOf(f);
346            }
347            it = F.listIterator();
348            while (it.hasNext() && !mt) {
349                p = it.next();
350                f = p.leadingExpVector();
351                mt = e.multipleOf(f);
352            }
353            if (!mt) {
354                F.add(a);
355            } else {
356                // System.out.println("dropped " + a.length());
357            }
358        }
359        G = F;
360        if (G.size() <= 1) {
361            return G;
362        }
363        Collections.reverse(G); // important for lex GB
364
365        MiReducerServerSeqPair<C>[] mirs = (MiReducerServerSeqPair<C>[]) new MiReducerServerSeqPair[G.size()];
366        int i = 0;
367        F = new ArrayList<GenPolynomial<C>>(G.size());
368        while (G.size() > 0) {
369            a = G.remove(0);
370            // System.out.println("doing " + a.length());
371            List<GenPolynomial<C>> R = new ArrayList<GenPolynomial<C>>(G.size() + F.size());
372            R.addAll(G);
373            R.addAll(F);
374            mirs[i] = new MiReducerServerSeqPair<C>(R, a);
375            pool.addJob(mirs[i]);
376            i++;
377            F.add(a);
378        }
379        G = F;
380        F = new ArrayList<GenPolynomial<C>>(G.size());
381        for (i = 0; i < mirs.length; i++) {
382            a = mirs[i].getNF();
383            F.add(a);
384        }
385        return F;
386    }
387
388}
389
390
391/**
392 * Distributed server reducing worker threads.
393 * @param <C> coefficient type
394 */
395
396class ReducerServerSeqPair<C extends RingElem<C>> implements Runnable {
397
398
399    private final Terminator pool;
400
401
402    private final ChannelFactory cf;
403
404
405    private SocketChannel pairChannel;
406
407
408    private final DistHashTable<Integer, GenPolynomial<C>> theList;
409
410
411    //private List<GenPolynomial<C>> G;
412    private final CriticalPairList<C> pairlist;
413
414
415    private static final Logger logger = LogManager.getLogger(ReducerServerSeqPair.class);
416
417
418    ReducerServerSeqPair(Terminator fin, ChannelFactory cf, DistHashTable<Integer, GenPolynomial<C>> dl,
419                    CriticalPairList<C> L) {
420        pool = fin;
421        this.cf = cf;
422        theList = dl;
423        //this.G = G;
424        pairlist = L;
425    }
426
427
428    public void run() {
429        logger.debug("reducer server running");
430        try {
431            pairChannel = cf.getChannel();
432        } catch (InterruptedException e) {
433            logger.debug("get pair channel interrupted");
434            e.printStackTrace();
435            return;
436        }
437        if (logger.isDebugEnabled()) {
438            logger.debug("pairChannel = " + pairChannel);
439        }
440        CriticalPair<C> pair;
441        //GenPolynomial<C> pi;
442        //GenPolynomial<C> pj;
443        //GenPolynomial<C> S;
444        GenPolynomial<C> H = null;
445        boolean set = false;
446        boolean goon = true;
447        int polIndex = -1;
448        int red = 0;
449        int sleeps = 0;
450
451        // while more requests
452        while (goon) {
453            // receive request
454            logger.debug("receive request");
455            Object req = null;
456            try {
457                req = pairChannel.receive();
458            } catch (IOException e) {
459                goon = false;
460                e.printStackTrace();
461            } catch (ClassNotFoundException e) {
462                goon = false;
463                e.printStackTrace();
464            }
465            //logger.debug("received request, req = " + req);
466            if (req == null) {
467                goon = false;
468                break;
469            }
470            if (!(req instanceof GBSPTransportMessReq)) {
471                goon = false;
472                break;
473            }
474
475            // find pair
476            if (logger.isDebugEnabled()) {
477                logger.debug("find pair");
478                logger.debug("pool.hasJobs() " + pool.hasJobs() + " pairlist.hasNext() " + pairlist.hasNext());
479            }
480            while (!pairlist.hasNext()) { // wait
481                pairlist.update();
482                if (!set) {
483                    pool.beIdle();
484                    set = true;
485                }
486                if (!pool.hasJobs() && !pairlist.hasNext()) {
487                    goon = false;
488                    break;
489                }
490                try {
491                    sleeps++;
492                    if (sleeps % 10 == 0) {
493                        logger.info(" reducer is sleeping");
494                    }
495                    Thread.sleep(100);
496                } catch (InterruptedException e) {
497                    goon = false;
498                    break;
499                }
500            }
501            if (!pairlist.hasNext() && !pool.hasJobs()) {
502                goon = false;
503                break; //continue; //break?
504            }
505            if (set) {
506                set = false;
507                pool.notIdle();
508            }
509
510            pair = pairlist.getNext();
511            /*
512             * send pair to client, receive H
513             */
514            if (logger.isDebugEnabled()) {
515                logger.debug("send pair = " + pair);
516                logger.info("theList keys " + theList.keySet());
517            }
518            if (logger.isDebugEnabled()) {
519                logger.info("inWork " + pairlist.inWork());
520            }
521            GBSPTransportMess msg = null;
522            if (pair != null) {
523                msg = new GBSPTransportMessPairIndex(pair);
524            } else {
525                msg = new GBSPTransportMess(); //End();
526                // goon ?= false;
527            }
528            try {
529                pairChannel.send(msg);
530            } catch (IOException e) {
531                e.printStackTrace();
532                goon = false;
533                break;
534            }
535            // use idle time to update pairlist
536            pairlist.update();
537            //logger.debug("#distributed list = "+theList.size());
538            //logger.debug("receive H polynomial");
539            Object rh = null;
540            try {
541                rh = pairChannel.receive();
542            } catch (IOException e) {
543                e.printStackTrace();
544                goon = false;
545                break;
546            } catch (ClassNotFoundException e) {
547                e.printStackTrace();
548                goon = false;
549                break;
550            }
551            if (logger.isDebugEnabled()) {
552                logger.info("received H polynomial rh = " + rh);
553            }
554            if (rh == null) {
555                if (pair != null) {
556                    polIndex = pairlist.record(pair, null);
557                    //pair.setZero();
558                }
559                pairlist.update();
560            } else if (rh instanceof GBSPTransportMessPoly) {
561                // update pair list
562                red++;
563                H = ((GBSPTransportMessPoly<C>) rh).pol;
564                //logger.info("H = " + H);
565                if (H == null) {
566                    if (pair != null) {
567                        polIndex = pairlist.record(pair, null);
568                        //pair.setZero();
569                    }
570                    pairlist.update();
571                } else {
572                    if (H.isZERO()) {
573                        polIndex = pairlist.record(pair, H);
574                        //pair.setZero();
575                    } else {
576                        if (H.isONE()) {
577                            // pool.allIdle();
578                            pairlist.putOne();
579                            theList.put(Integer.valueOf(0), H);
580                            goon = false;
581                            //break;
582                        } else {
583                            polIndex = pairlist.record(pair, H);
584                            // not correct:
585                            // polIndex = pairlist.getList().size(); 
586                            // pairlist.update();
587                            // polIndex = pairlist.put( H );
588                            // use putWait ? but still not all distributed
589                            theList.put(Integer.valueOf(polIndex), H);
590                        }
591                    }
592                }
593            } else {
594                if (pair != null) {
595                    polIndex = pairlist.record(pair, null);
596                    //pair.setZero();
597                }
598                if (logger.isDebugEnabled()) {
599                    logger.debug("invalid message " + rh);
600                }
601            }
602        }
603        logger.info("terminated, done " + red + " reductions");
604
605        /*
606         * send end mark to client
607         */
608        logger.debug("send end");
609        try {
610            pairChannel.send(new GBSPTransportMessEnd());
611        } catch (IOException e) {
612            if (logger.isDebugEnabled()) {
613                e.printStackTrace();
614            }
615        }
616        pool.beIdle();
617        pairChannel.close();
618    }
619
620}
621
622
623/**
624 * Distributed GB transport message.
625 */
626
627class GBSPTransportMess implements Serializable {
628
629
630    /**
631     * toString.
632     */
633    @Override
634    public String toString() {
635        return "" + this.getClass().getName();
636    }
637}
638
639
640/**
641 * Distributed GB transport message for requests.
642 */
643
644class GBSPTransportMessReq extends GBSPTransportMess {
645
646
647    public GBSPTransportMessReq() {
648    }
649}
650
651
652/**
653 * Distributed GB transport message for termination.
654 */
655
656class GBSPTransportMessEnd extends GBSPTransportMess {
657
658
659    public GBSPTransportMessEnd() {
660    }
661}
662
663
664/**
665 * Distributed GB transport message for polynomial.
666 */
667
668class GBSPTransportMessPoly<C extends RingElem<C>> extends GBSPTransportMess {
669
670
671    /**
672     * The polynomial for transport.
673     */
674    public final GenPolynomial<C> pol;
675
676
677    /**
678     * GBSPTransportMessPoly.
679     * @param p polynomial to transfered.
680     */
681    public GBSPTransportMessPoly(GenPolynomial<C> p) {
682        this.pol = p;
683    }
684
685
686    /**
687     * toString.
688     */
689    @Override
690    public String toString() {
691        return super.toString() + "( " + pol + " )";
692    }
693}
694
695
696/**
697 * Distributed GB transport message for pairs.
698 */
699
700class GBSPTransportMessPair<C extends RingElem<C>> extends GBSPTransportMess {
701
702
703    public final CriticalPair<C> pair;
704
705
706    /**
707     * GBSPTransportMessPair.
708     * @param p pair for transfer.
709     */
710    public GBSPTransportMessPair(CriticalPair<C> p) {
711        this.pair = p;
712    }
713
714
715    /**
716     * toString.
717     */
718    @Override
719    public String toString() {
720        return super.toString() + "( " + pair + " )";
721    }
722}
723
724
725/**
726 * Distributed GB transport message for index pairs.
727 */
728
729class GBSPTransportMessPairIndex extends GBSPTransportMess {
730
731
732    public final Integer i;
733
734
735    public final Integer j;
736
737
738    /**
739     * GBSPTransportMessPairIndex.
740     * @param p pair for transport.
741     */
742    public GBSPTransportMessPairIndex(CriticalPair p) {
743        if (p == null) {
744            throw new NullPointerException("pair may not be null");
745        }
746        this.i = Integer.valueOf(p.i);
747        this.j = Integer.valueOf(p.j);
748    }
749
750
751    /**
752     * GBSPTransportMessPairIndex.
753     * @param i first index.
754     * @param j second index.
755     */
756    public GBSPTransportMessPairIndex(int i, int j) {
757        this.i = Integer.valueOf(i);
758        this.j = Integer.valueOf(j);
759    }
760
761
762    /**
763     * GBSPTransportMessPairIndex.
764     * @param i first index.
765     * @param j second index.
766     */
767    public GBSPTransportMessPairIndex(Integer i, Integer j) {
768        this.i = i;
769        this.j = j;
770    }
771
772
773    /**
774     * toString.
775     */
776    @Override
777    public String toString() {
778        return super.toString() + "( " + i + "," + j + " )";
779    }
780}
781
782
783/**
784 * Distributed clients reducing worker threads.
785 */
786
787class ReducerClientSeqPair<C extends RingElem<C>> implements Runnable {
788
789
790    private final SocketChannel pairChannel;
791
792
793    private final DistHashTable<Integer, GenPolynomial<C>> theList;
794
795
796    private final ReductionPar<C> red;
797
798
799    private static final Logger logger = LogManager.getLogger(ReducerClientSeqPair.class);
800
801
802    ReducerClientSeqPair(SocketChannel pc, DistHashTable<Integer, GenPolynomial<C>> dl) {
803        pairChannel = pc;
804        theList = dl;
805        red = new ReductionPar<C>();
806    }
807
808
809    public void run() {
810        if (logger.isDebugEnabled()) {
811            logger.debug("pairChannel = " + pairChannel + "reducer client running");
812        }
813        CriticalPair<C> pair = null;
814        GenPolynomial<C> pi;
815        GenPolynomial<C> pj;
816        GenPolynomial<C> S;
817        GenPolynomial<C> H = null;
818        //boolean set = false;
819        boolean goon = true;
820        int reduction = 0;
821        //int sleeps = 0;
822        Integer pix;
823        Integer pjx;
824
825        while (goon) {
826            /* protocol:
827             * request pair, process pair, send result
828             */
829            // pair = (Pair) pairlist.removeNext();
830            Object req = new GBSPTransportMessReq();
831            if (logger.isDebugEnabled()) {
832                logger.debug("send request = " + req);
833            }
834            try {
835                pairChannel.send(req);
836            } catch (IOException e) {
837                goon = false;
838                e.printStackTrace();
839                break;
840            }
841            if (logger.isDebugEnabled()) {
842                logger.debug("receive pair, goon = " + goon);
843            }
844            Object pp = null;
845            try {
846                pp = pairChannel.receive();
847            } catch (IOException e) {
848                goon = false;
849                if (logger.isDebugEnabled()) {
850                    e.printStackTrace();
851                }
852                break;
853            } catch (ClassNotFoundException e) {
854                goon = false;
855                e.printStackTrace();
856            }
857            if (logger.isDebugEnabled()) {
858                logger.info("received pair = " + pp);
859            }
860            H = null;
861            if (pp == null) { // should not happen
862                //logger.debug("received pair = " + pp);
863                continue;
864            }
865            if (pp instanceof GBSPTransportMessEnd) {
866                goon = false;
867                continue;
868            }
869            if (pp instanceof GBSPTransportMessPair || pp instanceof GBSPTransportMessPairIndex) {
870                pi = pj = null;
871                if (pp instanceof GBSPTransportMessPair) {
872                    pair = ((GBSPTransportMessPair<C>) pp).pair;
873                    if (pair != null) {
874                        pi = pair.pi;
875                        pj = pair.pj;
876                        //logger.debug("pair: pix = " + pair.i 
877                        //               + ", pjx = " + pair.j);
878                    }
879                }
880                if (pp instanceof GBSPTransportMessPairIndex) {
881                    pix = ((GBSPTransportMessPairIndex) pp).i;
882                    pjx = ((GBSPTransportMessPairIndex) pp).j;
883                    //logger.info("waiting for pix = " + pix); 
884                    pi = theList.getWait(pix);
885                    //logger.info("waiting for pjx = " + pjx); 
886                    pj = theList.getWait(pjx);
887                    //logger.info("pix = " + pix + ", pjx = " +pjx);
888                }
889
890                if (logger.isDebugEnabled()) {
891                    logger.info("pi = " + pi.leadingExpVector() + ", pj = " + pj.leadingExpVector());
892                }
893                if (pi != null && pj != null) {
894                    S = red.SPolynomial(pi, pj);
895                    //System.out.println("S   = " + S);
896                    if (S.isZERO()) {
897                        // pair.setZero(); does not work in dist
898                        H = S;
899                    } else {
900                        if (logger.isDebugEnabled()) {
901                            logger.debug("ht(S) = " + S.leadingExpVector());
902                        }
903                        H = red.normalform(theList, S);
904                        reduction++;
905                        if (H.isZERO()) {
906                            // pair.setZero(); does not work in dist
907                        } else {
908                            H = H.monic();
909                            if (logger.isDebugEnabled()) {
910                                logger.info("ht(H) = " + H.leadingExpVector());
911                            }
912                        }
913                    }
914                }
915            } else {
916                if (logger.isDebugEnabled()) {
917                    logger.debug("invalid message = " + pp);
918                }
919                try {
920                    Thread.sleep(100);
921                } catch (InterruptedException e) {
922                    e.printStackTrace();
923                }
924            }
925
926            // send H or must send null
927            //logger.debug("#distributed list = "+theList.size());
928            if (logger.isDebugEnabled()) {
929                logger.info("send H polynomial = " + H);
930            }
931            try {
932                pairChannel.send(new GBSPTransportMessPoly<C>(H));
933            } catch (IOException e) {
934                goon = false;
935                e.printStackTrace();
936                break;
937            }
938        }
939        logger.info("terminated, done " + reduction + " reductions");
940        pairChannel.close();
941    }
942}
943
944
945/**
946 * Distributed server reducing worker threads for minimal GB Not jet distributed
947 * but threaded.
948 */
949
950class MiReducerServerSeqPair<C extends RingElem<C>> implements Runnable {
951
952
953    private final List<GenPolynomial<C>> G;
954
955
956    private GenPolynomial<C> H;
957
958
959    private final Semaphore done = new Semaphore(0);
960
961
962    private final Reduction<C> red;
963
964
965    private static final Logger logger = LogManager.getLogger(MiReducerServerSeqPair.class);
966
967
968    MiReducerServerSeqPair(List<GenPolynomial<C>> G, GenPolynomial<C> p) {
969        this.G = G;
970        H = p;
971        red = new ReductionPar<C>();
972    }
973
974
975    /**
976     * getNF. Blocks until the normal form is computed.
977     * @return the computed normal form.
978     */
979    public GenPolynomial<C> getNF() {
980        try {
981            done.acquire(); //done.P();
982        } catch (InterruptedException e) {
983        }
984        return H;
985    }
986
987
988    public void run() {
989        if (logger.isDebugEnabled()) {
990            logger.debug("ht(H) = " + H.leadingExpVector());
991        }
992        H = red.normalform(G, H); //mod
993        done.release(); //done.V();
994        if (logger.isDebugEnabled()) {
995            logger.debug("ht(H) = " + H.leadingExpVector());
996        }
997        // H = H.monic();
998    }
999}
1000
1001
1002/**
1003 * Distributed clients reducing worker threads for minimal GB. Not jet used.
1004 */
1005
1006class MiReducerClientSeqPair<C extends RingElem<C>> implements Runnable {
1007
1008
1009    private final List<GenPolynomial<C>> G;
1010
1011
1012    private GenPolynomial<C> H;
1013
1014
1015    private final Reduction<C> red;
1016
1017
1018    private final Semaphore done = new Semaphore(0);
1019
1020
1021    private static final Logger logger = LogManager.getLogger(MiReducerClientSeqPair.class);
1022
1023
1024    MiReducerClientSeqPair(List<GenPolynomial<C>> G, GenPolynomial<C> p) {
1025        this.G = G;
1026        H = p;
1027        red = new ReductionPar<C>();
1028    }
1029
1030
1031    /**
1032     * getNF. Blocks until the normal form is computed.
1033     * @return the computed normal form.
1034     */
1035    public GenPolynomial<C> getNF() {
1036        try {
1037            done.acquire(); //done.P();
1038        } catch (InterruptedException u) {
1039            Thread.currentThread().interrupt();
1040        }
1041        return H;
1042    }
1043
1044
1045    public void run() {
1046        if (logger.isDebugEnabled()) {
1047            logger.debug("ht(H) = " + H.leadingExpVector());
1048        }
1049        H = red.normalform(G, H); // mod
1050        done.release(); //done.V();
1051        if (logger.isDebugEnabled()) {
1052            logger.debug("ht(H) = " + H.leadingExpVector());
1053        }
1054        // H = H.monic();
1055    }
1056}