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