001/*
002 * $Id: GroebnerBaseSeqPairDistributed.java 5245 2015-05-01 14:03:06Z 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 */
038@Deprecated
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        @SuppressWarnings("unused")
188        int unused;
189        ListIterator<GenPolynomial<C>> it = F.listIterator();
190        while (it.hasNext()) {
191            p = it.next();
192            if (p.length() > 0) {
193                p = p.monic();
194                if (p.isONE()) {
195                    oneInGB = true;
196                    G.clear();
197                    G.add(p);
198                    //return G; must signal termination to others
199                }
200                if (!oneInGB) {
201                    G.add(p);
202                }
203                if (pairlist == null) {
204                    pairlist = new CriticalPairList<C>(modv, p.ring);
205                }
206                // theList not updated here
207                if (p.isONE()) {
208                    unused = pairlist.putOne();
209                } else {
210                    unused = pairlist.put(p);
211                }
212            } else {
213                //l--;
214            }
215        }
216        //if (l <= 1) {
217        //return G; must signal termination to others
218        //}
219
220        logger.debug("looking for clients");
221        //long t = System.currentTimeMillis();
222        // now in DL, uses resend for late clients
223        //while ( dls.size() < threads ) { sleep(); }
224
225        DistHashTable<Integer, GenPolynomial<C>> theList = new DistHashTable<Integer, GenPolynomial<C>>(
226                        "localhost", DL_PORT);
227        theList.init();
228        List<GenPolynomial<C>> al = pairlist.getList();
229        for (int i = 0; i < al.size(); i++) {
230            // no wait required
231            GenPolynomial<C> nn = theList.put(Integer.valueOf(i), al.get(i));
232            if (nn != null) {
233                logger.info("double polynomials " + i + ", nn = " + nn + ", al(i) = " + al.get(i));
234            }
235        }
236
237        Terminator fin = new Terminator(threads);
238        ReducerServerSeqPair<C> R;
239        for (int i = 0; i < threads; i++) {
240            R = new ReducerServerSeqPair<C>(fin, cf, theList, G, pairlist);
241            pool.addJob(R);
242        }
243        logger.debug("main loop waiting");
244        fin.waitDone();
245        int ps = theList.size();
246        //logger.debug("#distributed list = "+ps);
247        // make sure all polynomials arrived: not needed in master
248        // G = (ArrayList)theList.values();
249        G = pairlist.getList();
250        //logger.debug("#pairlist list = "+G.size());
251        if (ps != G.size()) {
252            logger.info("#distributed list = " + theList.size() + " #pairlist list = " + G.size());
253        }
254        long time = System.currentTimeMillis();
255        List<GenPolynomial<C>> Gp;
256        Gp = minimalGB(G); // not jet distributed but threaded
257        time = System.currentTimeMillis() - time;
258        logger.info("parallel gbmi = " + time);
259        /*
260        time = System.currentTimeMillis();
261        G = GroebnerBase.<C>GBmi(G); // sequential
262        time = System.currentTimeMillis() - time;
263        logger.info("sequential gbmi = " + time);
264        */
265        G = Gp;
266        //logger.info("cf.terminate()");
267        cf.terminate();
268        // no more required // pool.terminate();
269        logger.info("theList.terminate()");
270        theList.terminate();
271        logger.info("dls.terminate()");
272        dls.terminate();
273        logger.info("" + pairlist);
274        return G;
275    }
276
277
278    /**
279     * GB distributed client.
280     * @param host the server runns on.
281     * @throws IOException
282     */
283    public void clientPart(String host) throws IOException {
284
285        ChannelFactory cf = new ChannelFactory(port + 10); // != port for localhost
286        cf.init();
287        SocketChannel pairChannel = cf.getChannel(host, port);
288
289        final int DL_PORT = port + 100;
290        DistHashTable<Integer, GenPolynomial<C>> theList = new DistHashTable<Integer, GenPolynomial<C>>(host,
291                        DL_PORT);
292        theList.init();
293
294        ReducerClientSeqPair<C> R = new ReducerClientSeqPair<C>(pairChannel, theList);
295        R.run();
296
297        pairChannel.close();
298        theList.terminate();
299        cf.terminate();
300        return;
301    }
302
303
304    /**
305     * Minimal ordered groebner basis.
306     * @param Fp a Groebner base.
307     * @return a reduced Groebner base of Fp.
308     */
309    @SuppressWarnings("cast")
310    @Override
311    public List<GenPolynomial<C>> minimalGB(List<GenPolynomial<C>> Fp) {
312        GenPolynomial<C> a;
313        ArrayList<GenPolynomial<C>> G;
314        G = new ArrayList<GenPolynomial<C>>(Fp.size());
315        ListIterator<GenPolynomial<C>> it = Fp.listIterator();
316        while (it.hasNext()) {
317            a = it.next();
318            if (a.length() != 0) { // always true
319                // already monic  a = a.monic();
320                G.add(a);
321            }
322        }
323        if (G.size() <= 1) {
324            return G;
325        }
326
327        ExpVector e;
328        ExpVector f;
329        GenPolynomial<C> p;
330        ArrayList<GenPolynomial<C>> F;
331        F = new ArrayList<GenPolynomial<C>>(G.size());
332        boolean mt;
333
334        while (G.size() > 0) {
335            a = G.remove(0);
336            e = a.leadingExpVector();
337
338            it = G.listIterator();
339            mt = false;
340            while (it.hasNext() && !mt) {
341                p = it.next();
342                f = p.leadingExpVector();
343                mt = e.multipleOf(f);
344            }
345            it = F.listIterator();
346            while (it.hasNext() && !mt) {
347                p = it.next();
348                f = p.leadingExpVector();
349                mt = e.multipleOf(f);
350            }
351            if (!mt) {
352                F.add(a);
353            } else {
354                // System.out.println("dropped " + a.length());
355            }
356        }
357        G = F;
358        if (G.size() <= 1) {
359            return G;
360        }
361        Collections.reverse(G); // important for lex GB
362
363        MiReducerServerSeqPair<C>[] mirs = (MiReducerServerSeqPair<C>[]) new MiReducerServerSeqPair[G.size()];
364        int i = 0;
365        F = new ArrayList<GenPolynomial<C>>(G.size());
366        while (G.size() > 0) {
367            a = G.remove(0);
368            // System.out.println("doing " + a.length());
369            List<GenPolynomial<C>> R = new ArrayList<GenPolynomial<C>>(G.size() + F.size());
370            R.addAll(G);
371            R.addAll(F);
372            mirs[i] = new MiReducerServerSeqPair<C>(R, a);
373            pool.addJob(mirs[i]);
374            i++;
375            F.add(a);
376        }
377        G = F;
378        F = new ArrayList<GenPolynomial<C>>(G.size());
379        for (i = 0; i < mirs.length; i++) {
380            a = mirs[i].getNF();
381            F.add(a);
382        }
383        return F;
384    }
385
386}
387
388
389/**
390 * Distributed server reducing worker threads.
391 * @param <C> coefficient type
392 */
393
394class ReducerServerSeqPair<C extends RingElem<C>> implements Runnable {
395
396
397    private final Terminator pool;
398
399
400    private final ChannelFactory cf;
401
402
403    private SocketChannel pairChannel;
404
405
406    private final DistHashTable<Integer, GenPolynomial<C>> theList;
407
408
409    //private List<GenPolynomial<C>> G;
410    private final CriticalPairList<C> pairlist;
411
412
413    private static final Logger logger = Logger.getLogger(ReducerServerSeqPair.class);
414
415
416    ReducerServerSeqPair(Terminator fin, ChannelFactory cf, DistHashTable<Integer, GenPolynomial<C>> dl,
417                    List<GenPolynomial<C>> G, CriticalPairList<C> L) {
418        pool = fin;
419        this.cf = cf;
420        theList = dl;
421        //this.G = G;
422        pairlist = L;
423    }
424
425
426    public void run() {
427        logger.debug("reducer server running");
428        try {
429            pairChannel = cf.getChannel();
430        } catch (InterruptedException e) {
431            logger.debug("get pair channel interrupted");
432            e.printStackTrace();
433            return;
434        }
435        if (logger.isDebugEnabled()) {
436            logger.debug("pairChannel = " + pairChannel);
437        }
438        CriticalPair<C> pair;
439        //GenPolynomial<C> pi;
440        //GenPolynomial<C> pj;
441        //GenPolynomial<C> S;
442        GenPolynomial<C> H = null;
443        boolean set = false;
444        boolean goon = true;
445        int polIndex = -1;
446        int red = 0;
447        int sleeps = 0;
448
449        // while more requests
450        while (goon) {
451            // receive request
452            logger.debug("receive request");
453            Object req = null;
454            try {
455                req = pairChannel.receive();
456            } catch (IOException e) {
457                goon = false;
458                e.printStackTrace();
459            } catch (ClassNotFoundException e) {
460                goon = false;
461                e.printStackTrace();
462            }
463            //logger.debug("received request, req = " + req);
464            if (req == null) {
465                goon = false;
466                break;
467            }
468            if (!(req instanceof GBSPTransportMessReq)) {
469                goon = false;
470                break;
471            }
472
473            // find pair
474            if (logger.isDebugEnabled()) {
475                logger.debug("find pair");
476                logger.debug("pool.hasJobs() " + pool.hasJobs() + " pairlist.hasNext() " + 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}