/** * Distributed Groebner base. * * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F or null, if a IOException occurs or on MPI client part. */ public List<GenPolynomial<C>> GB(int modv, List<GenPolynomial<C>> F) { try { if (engine.Rank() == 0) { return GBmaster(modv, F); } } catch (MPIException e) { logger.info("GBmaster: " + e); e.printStackTrace(); return null; } catch (IOException e) { logger.info("GBmaster: " + e); e.printStackTrace(); return null; } pool.terminate(); // not used on clients try { clientPart(0); } catch (IOException e) { logger.info("clientPart: " + e); e.printStackTrace(); } catch (MPIException e) { logger.info("clientPart: " + e); e.printStackTrace(); } return null; }
/** Cleanup and terminate ThreadPool. */ @Override public void terminate() { if (pool == null) { return; } // pool.terminate(); pool.cancel(); }
/** * Constructor. * * @param threads number of threads to use. * @param pool ThreadPool to use. * @param pl pair selection strategy */ public GroebnerBaseDistributedMPI(int threads, ThreadPool pool, PairList<C> pl) throws IOException { super(new ReductionPar<C>(), pl); int size = 0; try { engine = MPIEngine.getCommunicator(); size = engine.Size(); } catch (MPIException e) { throw new IOException(e); } if (size < 2) { throw new IllegalArgumentException("Minimal 2 MPI processes required, not " + size); } if (threads != size || pool.getNumber() != size) { throw new IllegalArgumentException( "threads != size: " + threads + " != " + size + ", #pool " + pool.getNumber()); } this.threads = threads; this.pool = pool; }
/** * Minimal ordered groebner basis. * * @param Fp a Groebner base. * @return a reduced Groebner base of Fp. */ @SuppressWarnings("cast") @Override public List<GenPolynomial<C>> minimalGB(List<GenPolynomial<C>> Fp) { GenPolynomial<C> a; ArrayList<GenPolynomial<C>> G; G = new ArrayList<GenPolynomial<C>>(Fp.size()); ListIterator<GenPolynomial<C>> it = Fp.listIterator(); while (it.hasNext()) { a = it.next(); if (a.length() != 0) { // always true // already monic a = a.monic(); G.add(a); } } if (G.size() <= 1) { return G; } ExpVector e; ExpVector f; GenPolynomial<C> p; ArrayList<GenPolynomial<C>> F; F = new ArrayList<GenPolynomial<C>>(G.size()); boolean mt; while (G.size() > 0) { a = G.remove(0); e = a.leadingExpVector(); it = G.listIterator(); mt = false; while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } it = F.listIterator(); while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } if (!mt) { F.add(a); } else { // System.out.println("dropped " + a.length()); } } G = F; if (G.size() <= 1) { return G; } Collections.reverse(G); // important for lex GB MiMPIReducerServer<C>[] mirs = (MiMPIReducerServer<C>[]) new MiMPIReducerServer[G.size()]; int i = 0; F = new ArrayList<GenPolynomial<C>>(G.size()); while (G.size() > 0) { a = G.remove(0); // System.out.println("doing " + a.length()); List<GenPolynomial<C>> R = new ArrayList<GenPolynomial<C>>(G.size() + F.size()); R.addAll(G); R.addAll(F); mirs[i] = new MiMPIReducerServer<C>(R, a); pool.addJob(mirs[i]); i++; F.add(a); } G = F; F = new ArrayList<GenPolynomial<C>>(G.size()); for (i = 0; i < mirs.length; i++) { a = mirs[i].getNF(); F.add(a); } return F; }
/** * Distributed Groebner base, part for MPI master. * * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F or null, if a IOException occurs. */ public List<GenPolynomial<C>> GBmaster(int modv, List<GenPolynomial<C>> F) throws MPIException, IOException { List<GenPolynomial<C>> G = new ArrayList<GenPolynomial<C>>(); GenPolynomial<C> p; PairList<C> pairlist = null; boolean oneInGB = false; // int l = F.size(); int unused = 0; ListIterator<GenPolynomial<C>> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = p.monic(); if (p.isONE()) { oneInGB = true; G.clear(); G.add(p); // return G; must signal termination to others } if (!oneInGB) { G.add(p); } if (pairlist == null) { pairlist = strategy.create(modv, p.ring); if (!p.ring.coFac.isField()) { throw new IllegalArgumentException("coefficients not from a field"); } } // theList not updated here if (p.isONE()) { unused = pairlist.putOne(); } else { unused = pairlist.put(p); } } else { // l--; } } // if (l <= 1) { // return G; must signal termination to others // } logger.info("done pairlist, initialize DHT: " + unused); DistHashTableMPI<Integer, GenPolynomial<C>> theList = new DistHashTableMPI<Integer, GenPolynomial<C>>(engine); theList.init(); // logger.info("done DHT: " + theList); List<GenPolynomial<C>> al = pairlist.getList(); for (int i = 0; i < al.size(); i++) { // no wait required GenPolynomial<C> nn = theList.put(Integer.valueOf(i), al.get(i)); if (nn != null) { logger.info("double polynomials " + i + ", nn = " + nn + ", al(i) = " + al.get(i)); } } Terminator fin = new Terminator(threads - 1); MPIReducerServer<C> R; for (int i = 1; i < threads; i++) { logger.debug("addJob " + i + " of " + threads); MPIChannel chan = new MPIChannel(engine, i); // closed in server R = new MPIReducerServer<C>(i, fin, chan, theList, pairlist); pool.addJob(R); } logger.debug("main loop waiting"); fin.waitDone(); int ps = theList.size(); logger.info("#distributed list = " + ps); // make sure all polynomials arrived: not needed in master // G = (ArrayList)theList.values(); G = pairlist.getList(); if (ps != G.size()) { logger.info("#distributed list = " + theList.size() + " #pairlist list = " + G.size()); } long time = System.currentTimeMillis(); List<GenPolynomial<C>> Gp = minimalGB(G); // not jet distributed but threaded time = System.currentTimeMillis() - time; logger.debug("parallel gbmi = " + time); G = Gp; logger.info("theList.terminate()"); theList.terminate(); logger.info("end" + pairlist); return G; }