Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
edu.jas.gb.GroebnerBaseDistributed Maven / Gradle / Ivy
/*
* $Id: GroebnerBaseDistributed.java 4235 2012-10-03 21:17:59Z kredel $
*/
package edu.jas.gb;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.Semaphore;
import org.apache.log4j.Logger;
import edu.jas.poly.ExpVector;
import edu.jas.poly.GenPolynomial;
import edu.jas.structure.RingElem;
import edu.jas.util.ChannelFactory;
import edu.jas.util.DistHashTable;
import edu.jas.util.DistHashTableServer;
import edu.jas.util.SocketChannel;
import edu.jas.util.Terminator;
import edu.jas.util.ThreadPool;
/**
* Groebner Base distributed algorithm. Implements a distributed memory parallel
* version of Groebner bases. Using pairlist class, distributed tasks do
* reduction, one communication channel per task.
* @param coefficient type
* @author Heinz Kredel
* @deprecated use GroebnerBaseDistributedEC
*/
public class GroebnerBaseDistributed> extends GroebnerBaseAbstract {
private static final Logger logger = Logger.getLogger(GroebnerBaseDistributed.class);
/**
* Number of threads to use.
*/
protected final int threads;
/**
* Default number of threads.
*/
protected static final int DEFAULT_THREADS = 2;
/**
* Pool of threads to use. Note: No ComputerThreads for one node
* tests
*/
protected transient final ThreadPool pool;
/**
* Default server port.
*/
protected static final int DEFAULT_PORT = 4711;
/**
* Server port to use.
*/
protected final int port;
/**
* Constructor.
*/
public GroebnerBaseDistributed() {
this(DEFAULT_THREADS, DEFAULT_PORT);
}
/**
* Constructor.
* @param threads number of threads to use.
*/
public GroebnerBaseDistributed(int threads) {
this(threads, new ThreadPool(threads), DEFAULT_PORT);
}
/**
* Constructor.
* @param threads number of threads to use.
* @param port server port to use.
*/
public GroebnerBaseDistributed(int threads, int port) {
this(threads, new ThreadPool(threads), port);
}
/**
* Constructor.
* @param threads number of threads to use.
* @param pool ThreadPool to use.
* @param port server port to use.
*/
public GroebnerBaseDistributed(int threads, ThreadPool pool, int port) {
this(threads, pool, new OrderedPairlist(), port);
}
/**
* Constructor.
* @param threads number of threads to use.
* @param pl pair selection strategy
* @param port server port to use.
*/
public GroebnerBaseDistributed(int threads, PairList pl, int port) {
this(threads, new ThreadPool(threads), pl, port);
}
/**
* Constructor.
* @param threads number of threads to use.
* @param pool ThreadPool to use.
* @param pl pair selection strategy
* @param port server port to use.
*/
public GroebnerBaseDistributed(int threads, ThreadPool pool, PairList pl, int port) {
super(new ReductionPar(), pl);
if (threads < 1) {
threads = 1;
}
this.threads = threads;
this.pool = pool;
this.port = port;
}
/**
* Cleanup and terminate ThreadPool.
*/
@Override
public void terminate() {
if (pool == null) {
return;
}
pool.terminate();
}
/**
* 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.
*/
public List> GB(int modv, List> F) {
final int DL_PORT = port + 100;
ChannelFactory cf = new ChannelFactory(port);
cf.init();
DistHashTableServer dls = new DistHashTableServer(DL_PORT);
dls.init();
logger.debug("dist-list server running");
GenPolynomial p;
List> G = new ArrayList>();
PairList pairlist = null;
boolean oneInGB = false;
int l = F.size();
int unused;
ListIterator> 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 = new OrderedPairlist(modv, p.ring);
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.debug("looking for clients");
//long t = System.currentTimeMillis();
// now in DL, uses resend for late clients
//while ( dls.size() < threads ) { sleep(); }
DistHashTable> theList = new DistHashTable>(
"localhost", DL_PORT);
theList.init();
List> al = pairlist.getList();
for (int i = 0; i < al.size(); i++) {
// no wait required
GenPolynomial 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);
ReducerServer R;
for (int i = 0; i < threads; i++) {
R = new ReducerServer(fin, cf, theList, G, pairlist);
pool.addJob(R);
}
logger.debug("main loop waiting");
fin.waitDone();
int ps = theList.size();
logger.debug("#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> Gp;
Gp = minimalGB(G); // not jet distributed but threaded
time = System.currentTimeMillis() - time;
logger.info("parallel gbmi = " + time);
/*
time = System.currentTimeMillis();
G = GroebnerBase.GBmi(G); // sequential
time = System.currentTimeMillis() - time;
logger.info("sequential gbmi = " + time);
*/
G = Gp;
logger.debug("cf.terminate()");
cf.terminate();
// no more required // pool.terminate();
logger.info("theList.terminate()");
theList.terminate();
logger.info("dls.terminate()");
dls.terminate();
logger.info("" + pairlist);
return G;
}
/**
* GB distributed client.
* @param host the server runns on.
* @throws IOException
*/
public void clientPart(String host) throws IOException {
ChannelFactory cf = new ChannelFactory(port + 10); // != port for localhost
cf.init();
SocketChannel pairChannel = cf.getChannel(host, port);
final int DL_PORT = port + 100;
DistHashTable> theList = new DistHashTable>(host,
DL_PORT);
theList.init();
ReducerClient R = new ReducerClient(pairChannel, theList);
R.run();
pairChannel.close();
theList.terminate();
cf.terminate();
return;
}
/**
* Minimal ordered groebner basis.
* @param Fp a Groebner base.
* @return a reduced Groebner base of Fp.
*/
@Override
public List> minimalGB(List> Fp) {
GenPolynomial a;
ArrayList> G;
G = new ArrayList>(Fp.size());
ListIterator> 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 p;
ArrayList> F;
F = new ArrayList>(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
MiReducerServer[] mirs = (MiReducerServer[]) new MiReducerServer[G.size()];
int i = 0;
F = new ArrayList>(G.size());
while (G.size() > 0) {
a = G.remove(0);
// System.out.println("doing " + a.length());
List> R = new ArrayList>(G.size() + F.size());
R.addAll(G);
R.addAll(F);
mirs[i] = new MiReducerServer(R, a);
pool.addJob(mirs[i]);
i++;
F.add(a);
}
G = F;
F = new ArrayList>(G.size());
for (i = 0; i < mirs.length; i++) {
a = mirs[i].getNF();
F.add(a);
}
return F;
}
}
/**
* Distributed server reducing worker threads.
* @param coefficient type
*/
class ReducerServer> implements Runnable {
private final Terminator pool;
private final ChannelFactory cf;
private SocketChannel pairChannel;
private final DistHashTable> theList;
//private List> G;
private final PairList pairlist;
private static final Logger logger = Logger.getLogger(ReducerServer.class);
ReducerServer(Terminator fin, ChannelFactory cf, DistHashTable> dl,
List> G, PairList L) {
pool = fin;
this.cf = cf;
theList = dl;
//this.G = G;
pairlist = L;
}
public void run() {
logger.debug("reducer server running");
try {
pairChannel = cf.getChannel();
} catch (InterruptedException e) {
logger.debug("get pair channel interrupted");
e.printStackTrace();
return;
}
if (logger.isDebugEnabled()) {
logger.debug("pairChannel = " + pairChannel);
}
Pair pair;
//GenPolynomial pi;
//GenPolynomial pj;
//GenPolynomial S;
GenPolynomial H = null;
boolean set = false;
boolean goon = true;
int polIndex = -1;
int red = 0;
int sleeps = 0;
// while more requests
while (goon) {
// receive request
logger.debug("receive request");
Object req = null;
try {
req = pairChannel.receive();
} catch (IOException e) {
goon = false;
e.printStackTrace();
} catch (ClassNotFoundException e) {
goon = false;
e.printStackTrace();
}
//logger.debug("received request, req = " + req);
if (req == null) {
goon = false;
break;
}
if (!(req instanceof GBTransportMessReq)) {
goon = false;
break;
}
// find pair
logger.debug("find pair");
while (!pairlist.hasNext()) { // wait
if (!set) {
pool.beIdle();
set = true;
}
if (!pool.hasJobs() && !pairlist.hasNext()) {
goon = false;
break;
}
try {
sleeps++;
if (sleeps % 10 == 0) {
logger.info(" reducer is sleeping");
}
Thread.sleep(100);
} catch (InterruptedException e) {
goon = false;
break;
}
}
if (!pairlist.hasNext() && !pool.hasJobs()) {
goon = false;
break; //continue; //break?
}
if (set) {
set = false;
pool.notIdle();
}
pair = pairlist.removeNext();
/*
* send pair to client, receive H
*/
logger.debug("send pair = " + pair);
GBTransportMess msg = null;
if (pair != null) {
msg = new GBTransportMessPairIndex(pair);
} else {
msg = new GBTransportMess(); //End();
// goon ?= false;
}
try {
pairChannel.send(msg);
} catch (IOException e) {
e.printStackTrace();
goon = false;
break;
}
logger.debug("#distributed list = " + theList.size());
Object rh = null;
try {
rh = pairChannel.receive();
} catch (IOException e) {
e.printStackTrace();
goon = false;
break;
} catch (ClassNotFoundException e) {
e.printStackTrace();
goon = false;
break;
}
//logger.debug("received H polynomial");
if (rh == null) {
if (pair != null) {
pair.setZero();
}
} else if (rh instanceof GBTransportMessPoly) {
// update pair list
red++;
H = ((GBTransportMessPoly) rh).pol;
if (logger.isDebugEnabled()) {
logger.debug("H = " + H);
}
if (H == null) {
if (pair != null) {
pair.setZero();
}
} else {
if (H.isZERO()) {
pair.setZero();
} else {
if (H.isONE()) {
// pool.allIdle();
polIndex = pairlist.putOne();
GenPolynomial nn = theList.put(Integer.valueOf(polIndex), H);
if (nn != null) {
logger.info("double polynomials nn = " + nn + ", H = " + H);
}
goon = false;
break;
}
polIndex = pairlist.put(H);
// use putWait ? but still not all distributed
GenPolynomial nn = theList.put(Integer.valueOf(polIndex), H);
if (nn != null) {
logger.info("double polynomials nn = " + nn + ", H = " + H);
}
}
}
}
}
logger.info("terminated, done " + red + " reductions");
/*
* send end mark to client
*/
logger.debug("send end");
try {
pairChannel.send(new GBTransportMessEnd());
} catch (IOException e) {
if (logger.isDebugEnabled()) {
e.printStackTrace();
}
}
pool.beIdle();
pairChannel.close();
}
}
/**
* Distributed clients reducing worker threads.
*/
class ReducerClient> implements Runnable {
private final SocketChannel pairChannel;
private final DistHashTable> theList;
private final ReductionPar red;
private static final Logger logger = Logger.getLogger(ReducerClient.class);
ReducerClient(SocketChannel pc, DistHashTable> dl) {
pairChannel = pc;
theList = dl;
red = new ReductionPar();
}
public void run() {
logger.debug("pairChannel = " + pairChannel + " reducer client running");
Pair pair = null;
GenPolynomial pi;
GenPolynomial pj;
GenPolynomial S;
GenPolynomial H = null;
//boolean set = false;
boolean goon = true;
int reduction = 0;
//int sleeps = 0;
Integer pix;
Integer pjx;
while (goon) {
/* protocol:
* request pair, process pair, send result
*/
// pair = (Pair) pairlist.removeNext();
Object req = new GBTransportMessReq();
logger.debug("send request = " + req);
try {
pairChannel.send(req);
} catch (IOException e) {
goon = false;
e.printStackTrace();
break;
}
logger.debug("receive pair, goon = " + goon);
Object pp = null;
try {
pp = pairChannel.receive();
} catch (IOException e) {
goon = false;
if (logger.isDebugEnabled()) {
e.printStackTrace();
}
break;
} catch (ClassNotFoundException e) {
goon = false;
e.printStackTrace();
}
if (logger.isDebugEnabled()) {
logger.debug("received pair = " + pp);
}
H = null;
if (pp == null) { // should not happen
continue;
}
if (pp instanceof GBTransportMessEnd) {
goon = false;
continue;
}
if (pp instanceof GBTransportMessPair || pp instanceof GBTransportMessPairIndex) {
pi = pj = null;
if (pp instanceof GBTransportMessPair) {
pair = ((GBTransportMessPair) pp).pair;
if (pair != null) {
pi = pair.pi;
pj = pair.pj;
//logger.debug("pair: pix = " + pair.i
// + ", pjx = " + pair.j);
}
}
if (pp instanceof GBTransportMessPairIndex) {
pix = ((GBTransportMessPairIndex) pp).i;
pjx = ((GBTransportMessPairIndex) pp).j;
pi = (GenPolynomial) theList.getWait(pix);
pj = (GenPolynomial) theList.getWait(pjx);
//logger.info("pix = " + pix + ", pjx = " +pjx);
}
if (pi != null && pj != null) {
S = red.SPolynomial(pi, pj);
//System.out.println("S = " + S);
if (S.isZERO()) {
// pair.setZero(); does not work in dist
} else {
if (logger.isDebugEnabled()) {
logger.debug("ht(S) = " + S.leadingExpVector());
}
H = red.normalform(theList, S);
reduction++;
if (H.isZERO()) {
// pair.setZero(); does not work in dist
} else {
H = H.monic();
if (logger.isInfoEnabled()) {
logger.info("ht(H) = " + H.leadingExpVector());
}
}
}
}
}
// send H or must send null
if (logger.isDebugEnabled()) {
logger.debug("#distributed list = " + theList.size());
logger.debug("send H polynomial = " + H);
}
try {
pairChannel.send(new GBTransportMessPoly(H));
} catch (IOException e) {
goon = false;
e.printStackTrace();
}
}
logger.info("terminated, done " + reduction + " reductions");
pairChannel.close();
}
}
/**
* Distributed server reducing worker threads for minimal GB Not jet distributed
* but threaded.
*/
class MiReducerServer> implements Runnable {
private final List> G;
private GenPolynomial H;
private final Semaphore done = new Semaphore(0);
private final Reduction red;
private static final Logger logger = Logger.getLogger(MiReducerServer.class);
MiReducerServer(List> G, GenPolynomial p) {
this.G = G;
H = p;
red = new ReductionPar();
}
/**
* getNF. Blocks until the normal form is computed.
* @return the computed normal form.
*/
public GenPolynomial getNF() {
try {
done.acquire(); //done.P();
} catch (InterruptedException e) {
}
return H;
}
public void run() {
if (logger.isDebugEnabled()) {
logger.debug("ht(H) = " + H.leadingExpVector());
}
H = red.normalform(G, H); //mod
done.release(); //done.V();
if (logger.isDebugEnabled()) {
logger.debug("ht(H) = " + H.leadingExpVector());
}
// H = H.monic();
}
}
/**
* Distributed clients reducing worker threads for minimal GB. Not jet used.
*/
class MiReducerClient> implements Runnable {
private final List> G;
private GenPolynomial H;
private final Reduction red;
private final Semaphore done = new Semaphore(0);
private static final Logger logger = Logger.getLogger(MiReducerClient.class);
MiReducerClient(List> G, GenPolynomial p) {
this.G = G;
H = p;
red = new ReductionPar();
}
/**
* getNF. Blocks until the normal form is computed.
* @return the computed normal form.
*/
public GenPolynomial getNF() {
try {
done.acquire(); //done.P();
} catch (InterruptedException u) {
Thread.currentThread().interrupt();
}
return H;
}
public void run() {
if (logger.isDebugEnabled()) {
logger.debug("ht(S) = " + H.leadingExpVector());
}
H = red.normalform(G, H); //mod
done.release(); //done.V();
if (logger.isDebugEnabled()) {
logger.debug("ht(H) = " + H.leadingExpVector());
}
// H = H.monic();
}
}