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