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