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 }