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