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