diff --git a/src/javaeva/server/go/problems/MatlabEvalMediator.java b/src/javaeva/server/go/problems/MatlabEvalMediator.java new file mode 100644 index 00000000..00f5f46b --- /dev/null +++ b/src/javaeva/server/go/problems/MatlabEvalMediator.java @@ -0,0 +1,146 @@ +package javaeva.server.go.problems; + +/** + * This implements a thread acting as a mediator between JavaEvA and Matlab. Thanks to the idea + * of Henning Schmidt! + * As Java calling Matlab directly causes problems (due to Matlabs single-threadedness), Matlab + * now starts a mediator thread which receives the data necessary to perform the evaluation in matlab + * from the optimization thread. On receiving this "question" from the optimizer, the mediator thread + * finishes, returning to Matlab and signaling that there is work to do. + * However, the mediator object remains persistent, and the optimization thread keeps running + * and waits for the mediator to signal that there is a result, which happens if Matlab calls setAnswer(). + * Then the optimizer thread resumes, while Matlab has to restart the mediator thread, so that it may + * be informed about the next question, and so on. I havent checked how much performance is lost compared + * to the earlier, asynchronous version, but it feels similar, a difference being that both cpu's + * are now at 100% load, which is because two threads are running (and always at least waiting actively). + * Adding sleep time reduces CPU load a lot but reduces efficiency badly at the same time, probably because + * theres so much going on. For cases where the evaluation function is very time-consuming, adding sleep time + * might be an option. + * + * @author mkron + * + */ +public class MatlabEvalMediator implements Runnable { + volatile boolean requesting = false; +// final static boolean TRACE = false; + volatile boolean fin = false; + volatile double[] question = null; + volatile double[] answer = null; + volatile boolean quit = false; + volatile double[] optSolution = null; + volatile double[][] optSolSet = null; +// MatlabProblem mp = null; + // no good: even when waiting for only 1 ms the Matlab execution time increases by a factor of 5-10 + final static int sleepTime = 0; + + /** + * Request evaluation from Matlab for the given params. + * + * @param x + * @return + */ + double[] requestEval(MatlabProblem mp, double[] x) { +// this.mp = mp; + question = x; + requesting = true; +// int k=0; +// mp.log("Requesting eval for " + BeanInspector.toString(x) + ", req state is " + requesting + "\n"); + while (requesting && !quit) { + // wait for matlab to answer the question + if (sleepTime > 0) try { Thread.sleep(sleepTime); } catch(Exception e) {}; +// k++; +// if (k>100) { +// System.out.println("waiting for matlab to answer..."); +// k=0; +// } + } +// mp.log("Requesting done \n"); + // matlab is finished, answer is here + return getAnswer(); // return to JE with answer + } + + /** + * Wait loop, wait until the MatlabProblem requests an evaluation (or finishes), then return. + */ + public void run() { +// int k=0; + while (!requesting && !isFinished() && !quit) { + // wait for JE to pose a question or finish all + if (sleepTime > 0) try { Thread.sleep(sleepTime); } catch(Exception e) {}; +// k++; +// if (k>100) { +// System.out.println("waiting for JE to ask..."); +// k=0; +// } + } +// mp.log("-- Request arrived in MP thread\n"); + // requesting is true, now finish and let Matlab work + } + + /** + * Cancel waiting in any case. + */ + public void quit() { + quit = true; + } + + /** + * To be called from Matlab. + * @return + */ + public double[] getQuestion() { +// mp.log("-- Question: " + BeanInspector.toString(question) + "\n"); + return question; + } + + double[] getAnswer() { + return answer; + } + + /** + * To be called from Matlab giving the result of the question. + * + * @param y + */ + public void setAnswer(double[] y) { +// mp.log("-- setAnswer: " + BeanInspector.toString(y) + "\n"); + answer = y; + requesting = false; // answer is finished, break request loop + } + + void setFinished(boolean val) { + fin = val; + } + + /** + * To be called from Matlab signalling when optimizaton is completely finished. + * @return + */ + public boolean isFinished() { + return fin; + } + + void setSolution(double[] sol) { + optSolution = sol; + } + + void setSolutionSet(double[][] solSet) { + optSolSet = solSet; + } + + /** + * Matlab may retrieve result. + * @return + */ + public double[] getSolution() { + return optSolution; + } + + /** + * Matlab may retrieve result. + * @return + */ + public double[][] getSolutionSet() { + return optSolSet; + } +} \ No newline at end of file diff --git a/src/javaeva/server/go/problems/MatlabProblem.java b/src/javaeva/server/go/problems/MatlabProblem.java new file mode 100644 index 00000000..1dfacf16 --- /dev/null +++ b/src/javaeva/server/go/problems/MatlabProblem.java @@ -0,0 +1,453 @@ +package javaeva.server.go.problems; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Serializable; +import java.io.StringWriter; + +import javaeva.OptimizerFactory; +import javaeva.OptimizerRunnable; +import javaeva.gui.BeanInspector; +import javaeva.server.go.individuals.AbstractEAIndividual; +import javaeva.server.go.individuals.ESIndividualDoubleData; +import javaeva.server.go.individuals.InterfaceDataTypeDouble; +import javaeva.server.go.operators.distancemetric.PhenotypeMetric; +import javaeva.server.go.operators.postprocess.InterfacePostProcessParams; +import javaeva.server.go.operators.postprocess.PostProcess; +import javaeva.server.go.operators.postprocess.PostProcessParams; +import javaeva.server.go.populations.Population; +import javaeva.server.go.strategies.InterfaceOptimizer; +import javaeva.server.stat.InterfaceTextListener; + +public class MatlabProblem extends AbstractProblemDouble implements InterfaceTextListener, Serializable { + private static final long serialVersionUID = 4913310869887420815L; + public static final boolean TRACE = false; +// transient protected Matlab matlab = null; + transient OptimizerRunnable runnable = null; + protected boolean allowSingleRunnable = true; +// protected String jmInterface; + protected int problemDimension = 10; + transient PrintStream dos = null; + protected double[][] range = null; + private static final String defTestOut = "matlabproblem-testout.dat"; + boolean forwardStatisticsOutput = false; + private MatlabEvalMediator handler = null; + + + private F1Problem f1 = new F1Problem(); // TODO + +// transient private double[] currArray = null; +// private String mtCmd = null; + + public MatlabProblem(MatlabProblem o) { +// this.matlab = o.matlab; + this.handler = o.handler; + this.runnable = o.runnable; + this.allowSingleRunnable = o.allowSingleRunnable; +// this.jmInterface = new String(o.jmInterface); + this.problemDimension = o.problemDimension; +// this.res = new ResultArr(); +// if (o.res != null) if (o.res.get() != null) res.set(o.res.get()); + this.range = o.makeRange(); +// this.mtCmd = o.mtCmd; +// currArray = null; + } + + public Object clone() { + return new MatlabProblem(this); + } + + public MatlabProblem(String nameJEInterface, int dim) { + this(nameJEInterface, dim, null); + range = super.makeRange(); + } + + public MatlabProblem(String nameJEInterface, int dim, double[][] range) { + init(nameJEInterface, dim, range, defTestOut); + } + + public MatlabProblem(String nameJEInterface, int dim, double lower, double upper) { + this(nameJEInterface, dim, null); + double[][] range = new double[dim][2]; + for (int i=0; i 0)) { + if ((specValues == null) || (specValues.length != specParams.length)) { + System.err.println("mismatching value list for parameter arguments: " + specValues); + } else { + log("setting specific parameters...\n"); + InterfaceOptimizer opt = runnable.getGOParams().getOptimizer(); + for (int i=0; i>>>>>>>>> Stop event!\n"); + if (runnable != null) { + runnable.stopOpt(); + } + PostProcess.stopHC(); + } + + public String getInfoString() { + if (runnable == null) return ""; + StringBuffer sb = new StringBuffer(""); + sb.append(runnable.terminatedBecause()); + return sb.toString(); + } + + public int getFunctionCalls() { + if (runnable == null) return 0; + return runnable.getGOParams().getOptimizer().getPopulation().getFunctionCalls(); + } +// +// Matlab getMatlab() { +// return matlab; +// } +// + void exportResultPopulationToMatlab(Population pop) { + double[][] solSet; + + if ((pop != null) && (pop.size()>0)) { + solSet = new double[pop.size()][]; + for (int i=0; i