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