001/*
002 * $Id$
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 {}, port = {}", mfile, 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);
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 {}, nn = {}, al(i) = {}", i, nn, al.get(i));
327            }
328        }
329        // wait for arrival
330        while (theList.size() < al.size()) {
331            logger.info("#distributed list = {}, #pairlist list = {}", theList.size(), 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 = {}, #pairlist list = {}", theList.size(), 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 {}, port = {}, dhtport = {}", host, port, 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 {}, pairChannel = {}", host, 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 {} reductions", red);
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 = {} reducer client running", pairChannel);
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 = {}, pjx = {}", pair.i, pair.j);
781                    }
782                }
783                if (pp instanceof GBTransportMessPairIndex) {
784                    GBTransportMessPairIndex tmpi = (GBTransportMessPairIndex) pp;
785                    pix = tmpi.i;
786                    pjx = tmpi.j;
787                    psx = tmpi.s;
788                    pi = theList.getWait(pix);
789                    pj = theList.getWait(pjx);
790                    ps = theList.getWait(psx);
791                    //logger.info("pix = {}, pjx = {}, psx = {}", pix, pjx, psx);
792                }
793
794                if (pi != null && pj != null) {
795                    S = red.SPolynomial(pi, pj);
796                    //System.out.println("S   = " + S);
797                    if (S.isZERO()) {
798                        // pair.setZero(); does not work in dist
799                    } else {
800                        if (logger.isDebugEnabled()) {
801                            logger.debug("ht(S) = {}", S.leadingExpVector());
802                        }
803                        H = red.normalform(theList, S);
804                        reduction++;
805                        if (H.isZERO()) {
806                            // pair.setZero(); does not work in dist
807                        } else {
808                            H = H.monic();
809                            if (logger.isInfoEnabled()) {
810                                logger.info("ht(H) = {}", H.leadingExpVector());
811                            }
812                        }
813                    }
814                } else {
815                    logger.info("pi = {}, pj = {}, ps = {}", pi, pj, ps);
816                }
817            }
818
819            // send H or must send null
820            if (logger.isDebugEnabled()) {
821                logger.debug("#distributed list = {}", theList.size());
822                logger.debug("send H polynomial = {}", H);
823            }
824            try {
825                pairChannel.send(new GBTransportMessPoly<C>(H));
826            } catch (IOException e) {
827                goon = false;
828                e.printStackTrace();
829            }
830        }
831        logger.info("terminated, {} reductions, {} polynomials", reduction, theList.size());
832        pairChannel.close();
833    }
834}
835
836
837/**
838 * Distributed server reducing worker threads for minimal GB Not jet distributed
839 * but threaded.
840 */
841
842class MiReducerServerEC<C extends RingElem<C>> implements Runnable {
843
844
845    private final List<GenPolynomial<C>> G;
846
847
848    private GenPolynomial<C> H;
849
850
851    private final Semaphore done = new Semaphore(0);
852
853
854    private final Reduction<C> red;
855
856
857    private static final Logger logger = LogManager.getLogger(MiReducerServerEC.class);
858
859
860    MiReducerServerEC(List<GenPolynomial<C>> G, GenPolynomial<C> p) {
861        this.G = G;
862        H = p;
863        red = new ReductionPar<C>();
864    }
865
866
867    /**
868     * getNF. Blocks until the normal form is computed.
869     * @return the computed normal form.
870     */
871    public GenPolynomial<C> getNF() {
872        try {
873            done.acquire(); //done.P();
874        } catch (InterruptedException e) {
875        }
876        return H;
877    }
878
879
880    public void run() {
881        if (logger.isDebugEnabled()) {
882            logger.debug("ht(H) = {}", H.leadingExpVector());
883        }
884        H = red.normalform(G, H); //mod
885        done.release(); //done.V();
886        if (logger.isDebugEnabled()) {
887            logger.debug("ht(H) = {}", H.leadingExpVector());
888        }
889        // H = H.monic();
890    }
891}
892
893
894/**
895 * Distributed clients reducing worker threads for minimal GB. Not jet used.
896 */
897
898class MiReducerClientEC<C extends RingElem<C>> implements Runnable {
899
900
901    private final List<GenPolynomial<C>> G;
902
903
904    private GenPolynomial<C> H;
905
906
907    private final Reduction<C> red;
908
909
910    private final Semaphore done = new Semaphore(0);
911
912
913    private static final Logger logger = LogManager.getLogger(MiReducerClientEC.class);
914
915
916    MiReducerClientEC(List<GenPolynomial<C>> G, GenPolynomial<C> p) {
917        this.G = G;
918        H = p;
919        red = new ReductionPar<C>();
920    }
921
922
923    /**
924     * getNF. Blocks until the normal form is computed.
925     * @return the computed normal form.
926     */
927    public GenPolynomial<C> getNF() {
928        try {
929            done.acquire(); //done.P();
930        } catch (InterruptedException u) {
931            Thread.currentThread().interrupt();
932        }
933        return H;
934    }
935
936
937    public void run() {
938        if (logger.isDebugEnabled()) {
939            logger.debug("ht(S) = {}", H.leadingExpVector());
940        }
941        H = red.normalform(G, H); //mod
942        done.release(); //done.V();
943        if (logger.isDebugEnabled()) {
944            logger.debug("ht(H) = {}", H.leadingExpVector());
945        }
946        // H = H.monic();
947    }
948}
949
950
951/**
952 * Objects of this class are to be send to a ExecutableServer.
953 */
954
955class GBExerClient<C extends RingElem<C>> implements RemoteExecutable {
956
957
958    String host;
959
960
961    int port;
962
963
964    int dhtport;
965
966
967    /**
968     * GBExerClient.
969     * @param host
970     * @param port
971     * @param dhtport
972     */
973    public GBExerClient(String host, int port, int dhtport) {
974        this.host = host;
975        this.port = port;
976        this.dhtport = dhtport;
977    }
978
979
980    /**
981     * run.
982     */
983    public void run() {
984        //System.out.println("running " + this);
985        try {
986            GroebnerBaseDistributedEC.<C> clientPart(host, port, dhtport);
987        } catch (Exception e) {
988            e.printStackTrace();
989        }
990    }
991
992
993    /**
994     * String representation.
995     */
996    @Override
997    public String toString() {
998        StringBuffer s = new StringBuffer("GBExerClient(");
999        s.append("host=" + host);
1000        s.append(", port=" + port);
1001        s.append(", dhtport=" + dhtport);
1002        s.append(")");
1003        return s.toString();
1004    }
1005
1006}