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