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