001/* 002 * $Id$ 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 {}, port = {}", mfile, 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); 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 {}, nn = {}, al(i) = {}", i, nn, al.get(i)); 327 } 328 } 329 // wait for arrival 330 while (theList.size() < al.size()) { 331 logger.info("#distributed list = {}, #pairlist list = {}", theList.size(), 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 = {}, #pairlist list = {}", theList.size(), 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 {}, port = {}, dhtport = {}", host, port, 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 {}, pairChannel = {}", host, 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 {} reductions", red); 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 = {} reducer client running", pairChannel); 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 = {}, pjx = {}", pair.i, pair.j); 781 } 782 } 783 if (pp instanceof GBTransportMessPairIndex) { 784 GBTransportMessPairIndex tmpi = (GBTransportMessPairIndex) pp; 785 pix = tmpi.i; 786 pjx = tmpi.j; 787 psx = tmpi.s; 788 pi = theList.getWait(pix); 789 pj = theList.getWait(pjx); 790 ps = theList.getWait(psx); 791 //logger.info("pix = {}, pjx = {}, psx = {}", pix, pjx, psx); 792 } 793 794 if (pi != null && pj != null) { 795 S = red.SPolynomial(pi, pj); 796 //System.out.println("S = " + S); 797 if (S.isZERO()) { 798 // pair.setZero(); does not work in dist 799 } else { 800 if (logger.isDebugEnabled()) { 801 logger.debug("ht(S) = {}", S.leadingExpVector()); 802 } 803 H = red.normalform(theList, S); 804 reduction++; 805 if (H.isZERO()) { 806 // pair.setZero(); does not work in dist 807 } else { 808 H = H.monic(); 809 if (logger.isInfoEnabled()) { 810 logger.info("ht(H) = {}", H.leadingExpVector()); 811 } 812 } 813 } 814 } else { 815 logger.info("pi = {}, pj = {}, ps = {}", pi, pj, ps); 816 } 817 } 818 819 // send H or must send null 820 if (logger.isDebugEnabled()) { 821 logger.debug("#distributed list = {}", theList.size()); 822 logger.debug("send H polynomial = {}", H); 823 } 824 try { 825 pairChannel.send(new GBTransportMessPoly<C>(H)); 826 } catch (IOException e) { 827 goon = false; 828 e.printStackTrace(); 829 } 830 } 831 logger.info("terminated, {} reductions, {} polynomials", reduction, theList.size()); 832 pairChannel.close(); 833 } 834} 835 836 837/** 838 * Distributed server reducing worker threads for minimal GB Not jet distributed 839 * but threaded. 840 */ 841 842class MiReducerServerEC<C extends RingElem<C>> implements Runnable { 843 844 845 private final List<GenPolynomial<C>> G; 846 847 848 private GenPolynomial<C> H; 849 850 851 private final Semaphore done = new Semaphore(0); 852 853 854 private final Reduction<C> red; 855 856 857 private static final Logger logger = LogManager.getLogger(MiReducerServerEC.class); 858 859 860 MiReducerServerEC(List<GenPolynomial<C>> G, GenPolynomial<C> p) { 861 this.G = G; 862 H = p; 863 red = new ReductionPar<C>(); 864 } 865 866 867 /** 868 * getNF. Blocks until the normal form is computed. 869 * @return the computed normal form. 870 */ 871 public GenPolynomial<C> getNF() { 872 try { 873 done.acquire(); //done.P(); 874 } catch (InterruptedException e) { 875 } 876 return H; 877 } 878 879 880 public void run() { 881 if (logger.isDebugEnabled()) { 882 logger.debug("ht(H) = {}", H.leadingExpVector()); 883 } 884 H = red.normalform(G, H); //mod 885 done.release(); //done.V(); 886 if (logger.isDebugEnabled()) { 887 logger.debug("ht(H) = {}", H.leadingExpVector()); 888 } 889 // H = H.monic(); 890 } 891} 892 893 894/** 895 * Distributed clients reducing worker threads for minimal GB. Not jet used. 896 */ 897 898class MiReducerClientEC<C extends RingElem<C>> implements Runnable { 899 900 901 private final List<GenPolynomial<C>> G; 902 903 904 private GenPolynomial<C> H; 905 906 907 private final Reduction<C> red; 908 909 910 private final Semaphore done = new Semaphore(0); 911 912 913 private static final Logger logger = LogManager.getLogger(MiReducerClientEC.class); 914 915 916 MiReducerClientEC(List<GenPolynomial<C>> G, GenPolynomial<C> p) { 917 this.G = G; 918 H = p; 919 red = new ReductionPar<C>(); 920 } 921 922 923 /** 924 * getNF. Blocks until the normal form is computed. 925 * @return the computed normal form. 926 */ 927 public GenPolynomial<C> getNF() { 928 try { 929 done.acquire(); //done.P(); 930 } catch (InterruptedException u) { 931 Thread.currentThread().interrupt(); 932 } 933 return H; 934 } 935 936 937 public void run() { 938 if (logger.isDebugEnabled()) { 939 logger.debug("ht(S) = {}", H.leadingExpVector()); 940 } 941 H = red.normalform(G, H); //mod 942 done.release(); //done.V(); 943 if (logger.isDebugEnabled()) { 944 logger.debug("ht(H) = {}", H.leadingExpVector()); 945 } 946 // H = H.monic(); 947 } 948} 949 950 951/** 952 * Objects of this class are to be send to a ExecutableServer. 953 */ 954 955class GBExerClient<C extends RingElem<C>> implements RemoteExecutable { 956 957 958 String host; 959 960 961 int port; 962 963 964 int dhtport; 965 966 967 /** 968 * GBExerClient. 969 * @param host 970 * @param port 971 * @param dhtport 972 */ 973 public GBExerClient(String host, int port, int dhtport) { 974 this.host = host; 975 this.port = port; 976 this.dhtport = dhtport; 977 } 978 979 980 /** 981 * run. 982 */ 983 public void run() { 984 //System.out.println("running " + this); 985 try { 986 GroebnerBaseDistributedEC.<C> clientPart(host, port, dhtport); 987 } catch (Exception e) { 988 e.printStackTrace(); 989 } 990 } 991 992 993 /** 994 * String representation. 995 */ 996 @Override 997 public String toString() { 998 StringBuffer s = new StringBuffer("GBExerClient("); 999 s.append("host=" + host); 1000 s.append(", port=" + port); 1001 s.append(", dhtport=" + dhtport); 1002 s.append(")"); 1003 return s.toString(); 1004 } 1005 1006}