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