Author: bpoussin Date: 2014-04-02 15:25:29 +0200 (Wed, 02 Apr 2014) New Revision: 3916 Url: http://forge.codelutin.com/projects/isis-fish/repository/revisions/3916 Log: - add all code needed for optimization plan, but not the ui this code doesn't work for this moment (Executor thread number probleme, directory probleme) Added: branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/OptimizationPrepareJob.java branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationPlanPrepareJob.java branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/sensitivity/FactorHelper.java Modified: branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/Optimization.java branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/OptimizationContext.java branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/SimulationParameter.java branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/SimulationParameterCache.java branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/SimulationParameterImpl.java branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/SimulationPreScriptListener.java branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationJob.java branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationService.java branches/4.0.1/src/main/resources/templates/script/optimization.ftl Modified: branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/Optimization.java =================================================================== --- branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/Optimization.java 2014-04-02 12:36:19 UTC (rev 3915) +++ branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/Optimization.java 2014-04-02 13:25:29 UTC (rev 3916) @@ -38,12 +38,24 @@ public interface Optimization { /** + * Appele lors de l'initialisation. La premiere generation doit etre construite + * dans l'init. + * + * @param context + */ + void init(OptimizationContext context); + + /** * Génère une nouvelle série de simulation suivant le context d'optimisation. * * @param context context - * @param region region - * @return simulations serie */ - List<SimulationStorage> getNextGeneration(OptimizationContext context, FisheryRegion region); + void getNextSimulation(OptimizationContext context); + /** + * Cette methode est appelee lorsqu'il n'y a plus de simulation a faire + * (init ou getNextSimulation n'ont pas fait appel a context.addSimulation) + * @param context + */ + void endSimulation(OptimizationContext context); } Modified: branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/OptimizationContext.java =================================================================== --- branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/OptimizationContext.java 2014-04-02 12:36:19 UTC (rev 3915) +++ branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/OptimizationContext.java 2014-04-02 13:25:29 UTC (rev 3916) @@ -24,40 +24,118 @@ */ package fr.ifremer.isisfish.simulator; +import fr.ifremer.isisfish.IsisFishRuntimeException; +import fr.ifremer.isisfish.datastore.SimulationStorage; +import fr.ifremer.isisfish.simulator.launcher.SimulationJob; +import fr.ifremer.isisfish.simulator.sensitivity.Factor; +import fr.ifremer.isisfish.simulator.sensitivity.FactorHelper; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; +import org.apache.commons.collections4.CollectionUtils; -import fr.ifremer.isisfish.datastore.SimulationStorage; -import fr.ifremer.isisfish.entities.FisheryRegion; - /** * Context utilisé pour gérer les différentes simulation lancées par un script d'optimisation. * * @author Eric Chatellier * @since 4.3.0.0 */ -public class OptimizationContext { +public class OptimizationContext extends SimulationPlanContext { - public FisheryRegion copyRegion(FisheryRegion region) { - return null; + protected SimulationJob job; + + protected List<List<SimulationStorage>> generations = + new ArrayList<List<SimulationStorage>>(); + + /** Simulation to do during next generation simulation */ + protected List<SimulationStorage> nextSimulations; + + protected int currentGeneration = 0; + protected int simNumber = 0; + + public OptimizationContext(String id, SimulationParameter param, SimulationJob job) { + super(id, param); + this.job = job; } - public void createSimulation(FisheryRegion region) { - + public List<SimulationStorage> getNextSimulations() { + if (nextSimulations == null) { + nextSimulations = new ArrayList<SimulationStorage>(); + } + return nextSimulations; } - public int getCurrentGenerationNumber() { - return 0; + /** + * Get simulation to do, put it generations and increment currentGeneration + * This method must be call be Simulator when it want to get next simulations + * to do. + * @return null or empty collection if no more simulation to do + */ + public List<SimulationStorage> clearNextSimulation() { + List<SimulationStorage> result = nextSimulations; + + if (CollectionUtils.isNotEmpty(result)) { + generations.add(result); + nextSimulations = null; + currentGeneration++; + } + + return result; } - - public List<SimulationStorage> getLastGeneration() { - return null; + + public List<SimulationStorage> getLastSimulations() { + List<SimulationStorage> result = getGeneration(generations.size() - 1); + return result; } + public SimulationStorage getNewSimulation() { + try { + String simId = id + "_" + simNumber; + SimulationParameter childParam = param.copy(); + childParam.setSimulationPlanNumber(simNumber); + SimulationStorage result = SimulationStorage.importAndRenameZip(job.getItem().getSimulationZip(), simId); + + simNumber++; + + return result; + } catch (Exception eee) { + throw new IsisFishRuntimeException("can't create new simulation", eee); + } + } + + public void addSimulation(SimulationStorage s) { + getNextSimulations().add(s); + } + + public void addSimulation(Factor ... factors) { + SimulationStorage s = getNewSimulation(); + + Collection<Factor> colFactors = new ArrayList<Factor>(); + Collections.addAll(colFactors, factors); + String script = FactorHelper.generatePreScript(colFactors); + + SimulationParameter childParam = s.getParameter(); + childParam.setGeneratedPreScript(script); + + addSimulation(s); + } + + public int getCurrentGeneration() { + return currentGeneration; + } + + public int getSimulationNumber() { + return simNumber; + } + public List<SimulationStorage> getGeneration(int n) { - return null; + List<SimulationStorage> result = null; + if (n >= 0 && CollectionUtils.isNotEmpty(generations)) { + result = generations.get(n); + } + + return result; } - public int getGenerationNumber() { - return 0; - } } Modified: branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/SimulationParameter.java =================================================================== --- branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/SimulationParameter.java 2014-04-02 12:36:19 UTC (rev 3915) +++ branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/SimulationParameter.java 2014-04-02 13:25:29 UTC (rev 3916) @@ -349,7 +349,7 @@ /** * Set simulation optimization. - * + * * @param optimization optimization */ public void setOptimization(Optimization optimization); @@ -433,12 +433,26 @@ /** * Set pre script content. - * + * * @param preScript prescript content */ public void setPreScript(String preScript); /** + * Generated pre script is internal script generated by isis. This script + * must be executed before user defined preScript + */ + public String getGeneratedPreScript(); + + /** + * Generated pre script is internal script generated by isis. This script + * must be executed before user defined preScript + * + * @param preScript prescript content + */ + public void setGeneratedPreScript(String preScript); + + /** * Get region name. * * @return region name Modified: branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/SimulationParameterCache.java =================================================================== --- branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/SimulationParameterCache.java 2014-04-02 12:36:19 UTC (rev 3915) +++ branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/SimulationParameterCache.java 2014-04-02 13:25:29 UTC (rev 3916) @@ -584,10 +584,29 @@ SimulationParameter param = getParam(); param.setPreScript(preScript); store(param); - + } /* + * @see fr.ifremer.isisfish.simulator.SimulationParameter#getGeneratedPreScript() + */ + @Override + public String getGeneratedPreScript() { + SimulationParameter param = getParam(); + return param.getGeneratedPreScript(); + } + + /* + * @see fr.ifremer.isisfish.simulator.SimulationParameter#setGeneratedPreScript(java.lang.String) + */ + @Override + public void setGeneratedPreScript(String preScript) { + SimulationParameter param = getParam(); + param.setGeneratedPreScript(preScript); + store(param); + } + + /* * @see fr.ifremer.isisfish.simulator.SimulationParameter#getRegionName() */ @Override @@ -916,6 +935,6 @@ param.setObjective(objective); store(param); } + - } Modified: branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/SimulationParameterImpl.java =================================================================== --- branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/SimulationParameterImpl.java 2014-04-02 12:36:19 UTC (rev 3915) +++ branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/SimulationParameterImpl.java 2014-04-02 13:25:29 UTC (rev 3916) @@ -140,6 +140,9 @@ /** Le script de pre simulation a utiliser. */ protected String preScript; + /** Le script de pre simulation defini par Isis */ + protected String generatedPreScript; + /** Utilisation du plan de simulation. */ protected Boolean useSimulationPlan; @@ -660,9 +663,9 @@ if (useOptimization == null) { if (propertiesParameters != null) { - useOptimization = Boolean.valueOf(propertiesParameters.getProperty("useOptimization", "true")); + useOptimization = Boolean.valueOf(propertiesParameters.getProperty("useOptimization", "false")); } else { - useOptimization = Boolean.TRUE; + useOptimization = Boolean.FALSE; } } return useOptimization.booleanValue(); @@ -876,7 +879,7 @@ if (!StringUtils.isEmpty(optimizationName)) { try { OptimizationStorage optimizationStorage = OptimizationStorage.getOptimization(optimizationName); - optimizationName = optimizationStorage.getNewInstance(); + optimization = optimizationStorage.getNewInstance(); // 0 = only single sensitivity StorageHelper.populateStorageParams(0, getRegion().getStorage(), optimization, propertiesParameters, "optimization"); @@ -1074,6 +1077,26 @@ this.preScript = preScript; } + @Override + public String getGeneratedPreScript() { + + if (generatedPreScript == null) { + + if (propertiesParameters != null) { + generatedPreScript = propertiesParameters.getProperty("generatedPreScript", ""); + } else { + generatedPreScript = ""; + } + } + + return generatedPreScript; + } + + @Override + public void setGeneratedPreScript(String preScript) { + this.generatedPreScript = preScript; + } + /* * @see fr.ifremer.isisfish.simulator.SimulationParameter#getRegionName() */ @@ -1408,7 +1431,9 @@ result.useStatistic = getUseStatistic(); result.usePreScript = getUsePreScript(); result.preScript = getPreScript(); + result.generatedPreScript = getGeneratedPreScript(); result.useSimulationPlan = getUseSimulationPlan(); + result.useOptimization = getUseOptimization(); result.simulationPlanNumber = getSimulationPlanNumber(); if (exportNames != null) { result.exportNames = new LinkedList<String>(exportNames); @@ -1425,6 +1450,12 @@ if (simulationPlans != null) { result.simulationPlans = new LinkedList<SimulationPlan>(simulationPlans); } + if (objective != null) { + result.objective = objective; + } + if (optimization != null) { + result.optimization = optimization; + } if (resultEnabled != null) { result.resultEnabled = new LinkedList<String>(resultEnabled); } @@ -1475,6 +1506,11 @@ getSimulationPlanNumber())); } + if (getUseOptimization()) { + result.append(t("isisfish.params.toString.use.optimization", + getUseOptimization())); + } + RegionStorage region = getRegion(); result.append(t("isisfish.params.toString.fishery", region.getName())); result.append(t("isisfish.params.toString.number.years", @@ -1521,7 +1557,7 @@ // simulation plans for (SimulationPlan plan : getSimulationPlans()) { - String name = RuleStorage.getName(plan); + String name = SimulationPlanStorage.getName(plan); String param = ""; try { param = SimulationPlanStorage.getParamAsString(plan); @@ -1537,7 +1573,46 @@ result.append('\n'); } + + if (objective != null) { + String name = ObjectiveStorage.getName(objective); + String param = ""; + try { + param = ObjectiveStorage.getParamAsString(objective); + } catch (IsisFishException eee) { + if (log.isWarnEnabled()) { + log.warn("Can't convert objective parameter to string for " + + name, eee); + } + } + result.append(t("isisfish.params.toString.objective", name)); + result.append('\n'); + result.append(param); + result.append('\n'); + } + + if (optimization != null) { + String name = OptimizationStorage.getName(optimization); + String param = ""; + try { + param = OptimizationStorage.getParamAsString(optimization); + } catch (IsisFishException eee) { + if (log.isWarnEnabled()) { + log.warn("Can't convert optimization parameter to string for " + + name, eee); + } + } + result.append(t("isisfish.params.toString.optimization", name)); + result.append('\n'); + result.append(param); + result.append('\n'); + } + result.append('\n'); + result.append(t("isisfish.params.toString.script.generatedpresimulation")) + .append(":\n"); + result.append(getGeneratedPreScript()); + result.append('\n'); result.append(t("isisfish.params.toString.script.presimulation")) .append(":\n"); result.append(getPreScript()); @@ -1654,6 +1729,46 @@ } } + // objective + if (objective != null) { + String objectiveName = ObjectiveStorage.getName(objective); + Properties objectiveProp = StorageHelper.getParamsAsProperties(0, + getRegion().getStorage(), objective, "objective"); + result.putAll(objectiveProp); + result.setProperty("objective", objectiveName); + } else { + if (propertiesParameters != null + && propertiesParameters.containsKey("objective")) { + result.setProperty("objective", propertiesParameters + .getProperty("objective")); + for (String key : propertiesParameters.stringPropertyNames()) { + if (key.startsWith("objective.")) { + result.setProperty(key, propertiesParameters.getProperty(key)); + } + } + } + } + + // optimization + if (optimization != null) { + String optimizationName = ObjectiveStorage.getName(optimization); + Properties optimizationProp = StorageHelper.getParamsAsProperties(0, + getRegion().getStorage(), optimization, "optimization"); + result.putAll(optimizationProp); + result.setProperty("optimization", optimizationName); + } else { + if (propertiesParameters != null + && propertiesParameters.containsKey("optimization")) { + result.setProperty("optimization", propertiesParameters + .getProperty("optimization")); + for (String key : propertiesParameters.stringPropertyNames()) { + if (key.startsWith("optimization.")) { + result.setProperty(key, propertiesParameters.getProperty(key)); + } + } + } + } + // export names String exportList = ""; for (String export : getExportNames()) { @@ -1717,10 +1832,12 @@ // sensitivity params result.setProperty("sensitivityAnalysisOnlyKeepFirst", String.valueOf(isSensitivityAnalysisOnlyKeepFirst())); + result.setProperty("generatedPreScript", getGeneratedPreScript()); result.setProperty("usePreScript", String.valueOf(getUsePreScript())); result.setProperty("preScript", getPreScript()); result.setProperty("useSimulationPlan", String.valueOf(getUseSimulationPlan())); result.setProperty("simulationPlanNumber", String.valueOf(getSimulationPlanNumber())); + result.setProperty("useOptimization", String.valueOf(getUseOptimization())); String resultList = ""; for (String r : getResultEnabled()) { Modified: branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/SimulationPreScriptListener.java =================================================================== --- branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/SimulationPreScriptListener.java 2014-04-02 12:36:19 UTC (rev 3915) +++ branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/SimulationPreScriptListener.java 2014-04-02 13:25:29 UTC (rev 3916) @@ -66,18 +66,29 @@ SimulationStorage simulation = context.getSimulationStorage(); SimulationParameter parameters = simulation.getParameter(); + + String generatedPreScript = parameters.getGeneratedPreScript(); String presimulationScript = parameters.getPreScript(); - if ((parameters.getUsePreScript() || parameters.getUseSimulationPlan()) - && StringUtils.isNotBlank(presimulationScript)) { + + if (StringUtils.isNotBlank(generatedPreScript) || + (parameters.getUsePreScript() && StringUtils.isNotBlank(presimulationScript))) { // utilisation de la db en memoire que l'on commitera TopiaContext tx = context.getDB(); Map<String, Object> args = new HashMap<>(); args.put("context", context); - EvaluatorHelper.evaluate(SimulationPreScript.class.getPackage().getName(), - "PreScript", SimulationPreScript.class, presimulationScript, args); + if (StringUtils.isNotBlank(generatedPreScript)) { + EvaluatorHelper.evaluate(SimulationPreScript.class.getPackage().getName(), + "GeneratedPreScript", SimulationPreScript.class, generatedPreScript, args); + } + + if (parameters.getUsePreScript() && StringUtils.isNotBlank(presimulationScript)) { + EvaluatorHelper.evaluate(SimulationPreScript.class.getPackage().getName(), + "PreScript", SimulationPreScript.class, presimulationScript, args); + } + tx.commitTransaction(); } } catch (Exception eee) { Added: branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/OptimizationPrepareJob.java =================================================================== --- branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/OptimizationPrepareJob.java (rev 0) +++ branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/OptimizationPrepareJob.java 2014-04-02 13:25:29 UTC (rev 3916) @@ -0,0 +1,143 @@ +package fr.ifremer.isisfish.simulator.launcher; + + +import fr.ifremer.isisfish.IsisFishRuntimeException; +import fr.ifremer.isisfish.datastore.SimulationStorage; +import fr.ifremer.isisfish.simulator.Objective; +import fr.ifremer.isisfish.simulator.Optimization; +import fr.ifremer.isisfish.simulator.OptimizationContext; +import fr.ifremer.isisfish.simulator.SimulationControl; +import fr.ifremer.isisfish.simulator.SimulationParameter; +import fr.ifremer.isisfish.simulator.launcher.SimulationItem; +import fr.ifremer.isisfish.simulator.launcher.SimulationJob; +import fr.ifremer.isisfish.simulator.launcher.SimulationService; +import java.io.File; +import java.util.List; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.io.FileUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.i18n.I18n; +import org.nuiton.util.FileUtil; + +/** + * Permet de generer l'enchainement des simulations d'optimisation. + * Gere les differentes generation (plusieurs simulations par generation) + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class OptimizationPrepareJob implements Runnable, SimulationJob.PostAction { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private final Log log = LogFactory.getLog(OptimizationPrepareJob.class); + + protected SimulationService simulationService; + protected OptimizationContext optimizationContext; + protected SimulationJob job; + protected String id; + protected SimulationControl control; + protected SimulationParameter param; + protected Objective objective; + protected Optimization optimization; + + /** nombre de simulation faite ou en cours */ + protected int simNumber = 0; + /** nombre de simulation faite */ + protected int done = 0; + /** true if exception occure in one simulation */ + protected boolean exception = false; + + public OptimizationPrepareJob(SimulationService simulationService, SimulationJob job) { + this.simulationService = simulationService; + this.job = job; + + id = job.getItem().getControl().getId(); + control = job.getItem().getControl(); + param = job.getItem().getParameter(); + + objective = param.getObjective(); + optimization = param.getOptimization(); + optimizationContext = new OptimizationContext(id, param, job); + } + + @Override + public void run() { + try { + optimization.init(optimizationContext); + + List<SimulationStorage> sims = optimizationContext.clearNextSimulation(); + while (!exception && !control.isStopSimulationRequest() + && CollectionUtils.isNotEmpty(sims)) { + for (SimulationStorage s : sims) { + if (!exception && !control.isStopSimulationRequest()) { + String simId = s.getName(); + + File zip = s.createZip(); + SimulationParameter childParam = s.getParameter(); + int childNumber = childParam.getSimulationPlanNumber(); + SimulationControl childControl = new SimulationControl(simId); + SimulationItem item = new SimulationItem(childControl, childParam); + item.setStandaloneSimulation(false); + item.setSimulationNumber(childNumber); + item.setSimulationZip(zip); + + SimulationJob subJob = new SimulationJob(simulationService, job, item, job.getPriority()); + subJob.setLauncher(job.getLauncher()); + + subJob.addPostAction(this); + simulationService.submitSubJob(subJob); + + simNumber++; + } + } + + // wait until wall simulation for this generation are done + while(!exception && !control.isStopSimulationRequest() + && simNumber > done) { + Thread.sleep(2000); + } + + if (!exception && !control.isStopSimulationRequest()) { + optimization.getNextSimulation(optimizationContext); + sims = optimizationContext.clearNextSimulation(); + } + } + + if (!exception && !control.isStopSimulationRequest()) { + optimization.endSimulation(optimizationContext); + } + + // on enleve le master plan des simulations en cours, vu que + // toutes les simu sont terminees + simulationService.fireStopEvent(this.job); + } catch (Exception eee) { + // add manual log + // we are in a thread, IsisFishRuntimeException is displayed + // outside a log + if (log.isErrorEnabled()) { + log.error(I18n._("isisfish.error.evaluate.optimization.script"), eee); + } + throw new IsisFishRuntimeException(I18n._("isisfish.error.evaluate.optimization.script"), eee); + } + + } + + @Override + public void finished(SimulationJob job, SimulationStorage sim) { + objective.eval(optimizationContext, null, null); // FIXME mettre les bons arguments + done++; + } + + @Override + public void exception(SimulationJob job, Throwable eee) { + // il y a une simulation d'echoue, on ne fait pas les suivantes + // cela n'impacte pas les plan independant puisque toutes les + // simulation on deja ete generee + exception = true; + } + +} Property changes on: branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/OptimizationPrepareJob.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Modified: branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationJob.java =================================================================== --- branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationJob.java 2014-04-02 12:36:19 UTC (rev 3915) +++ branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationJob.java 2014-04-02 13:25:29 UTC (rev 3916) @@ -215,7 +215,7 @@ && param.getUseSimulationPlan() && !param.isIndependentPlan()) { // on est sur un plan de simulation dependant, il faut generer les // simulation les unes apres les autres - SimulationService.PrepareSimulationJob i = new SimulationService.PrepareSimulationJob( + SimulationPlanPrepareJob i = new SimulationPlanPrepareJob( simulationService, this); while (!control.isStopSimulationRequest() && i.hasNext()) { log.info(t("Generate next simulation")); @@ -261,6 +261,12 @@ } } + } else if (!onlyCheckControl && getParentJob() == null + && param.getUseOptimization()) { + // on est sur une optimisation, il faut faire toutes les simulations demandees + OptimizationPrepareJob optiPreJob = + new OptimizationPrepareJob(simulationService, this); + optiPreJob.run(); } else { // on est sur une simple simulation, ou le resultat d'un plan Added: branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationPlanPrepareJob.java =================================================================== --- branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationPlanPrepareJob.java (rev 0) +++ branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationPlanPrepareJob.java 2014-04-02 13:25:29 UTC (rev 3916) @@ -0,0 +1,253 @@ +package fr.ifremer.isisfish.simulator.launcher; + + +import fr.ifremer.isisfish.IsisFishRuntimeException; +import fr.ifremer.isisfish.datastore.SimulationStorage; +import fr.ifremer.isisfish.simulator.SimulationControl; +import fr.ifremer.isisfish.simulator.SimulationParameter; +import fr.ifremer.isisfish.simulator.SimulationPlan; +import fr.ifremer.isisfish.simulator.SimulationPlanContext; +import java.io.File; +import java.util.Iterator; +import java.util.List; +import org.apache.commons.io.FileUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.i18n.I18n; +import org.nuiton.util.FileUtil; + +/** + * Permet de genere les sous simulations d'un plan de simulation. Pour les + * plan independant, on l'utilise en Runnable pour genere tous les plans + * possible et les soumettre a la queue. Pour les plans dependant + * on l'utilise seulement comme iterator. La methode afterSimulation des plans + * est appelee automatiquement a la fin de la simulation grace au mecanisme + * de PostAction sur les {@link SimulationJob}. + */ +public class SimulationPlanPrepareJob implements Runnable, Iterator<SimulationJob>, SimulationJob.PostAction { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + private static final Log log = LogFactory.getLog(SimulationPlanPrepareJob.class); + + protected SimulationService simulationService; + protected SimulationPlanContext planContext; + protected SimulationJob job; + protected SimulationJob nextJob; + protected boolean doNext = true; + protected String id; + protected SimulationControl control; + protected SimulationParameter param; + protected int done = 0; + protected List<SimulationPlan> simulationPlan; + + public SimulationPlanPrepareJob(SimulationService simulationService, SimulationJob job) { + this.simulationService = simulationService; + this.job = job; + id = job.getItem().getControl().getId(); + control = job.getItem().getControl(); + param = job.getItem().getParameter(); + // take a copy of simulation paln list + // because they a freed during simulation (soft reference) + // is there is not enought memory available + simulationPlan = param.getSimulationPlans(); + this.planContext = new SimulationPlanContext(control.getId(), param); + try { + // appel de init sur chaque plan + for (SimulationPlan plan : simulationPlan) { + plan.init(planContext); + } + } catch (Exception eee) { + // add manual log + // we are in a thread, IsisFishRuntimeException is displayed + // outside a log + if (log.isErrorEnabled()) { + log.error(I18n._("isisfish.error.evaluate.preplan.script"), eee); + } + throw new IsisFishRuntimeException(I18n._("isisfish.error.evaluate.preplan.script"), eee); + } + } + + /** + * Genere toutes les sous simulations et les places dans la queue. + * + * Cette methode {@code run()} est appelée seulement dans le cas de la + * génération de plans indépendants. + * + * @see SimulationJob#run() pour les plans dépendants + */ + public void run() { + /* Original code + while (hasNext()) { + try { + SimulationJob subJob = next(); + if (log.isInfoEnabled()) { + log.info("Simulation generee: " + subJob.getId()); + } + simulationService.submitSubJob(subJob); + } catch (Exception eee) { + if (log.isErrorEnabled()) { + log.error(_("Can't add simulation: %s", job.getItem() + .getControl().getId()), eee); + } + } + }*/ + // New iteration remember always simulation N and N+1 + // needed to know witch simulation is the last one + // get simulation N + SimulationJob subJobN = null; + if (hasNext()) { + subJobN = next(); + } + while (subJobN != null) { + try { + if (log.isInfoEnabled()) { + log.info("Simulation generated: " + subJobN.getId()); + } + // set item additionnal informations + SimulationItem itemN = subJobN.getItem(); + itemN.setStandaloneSimulation(false); // independant plan + // - 1 because planContext.getNumber() is set to next simulation to generate + itemN.setSimulationNumber(planContext.getNumber() - 1); + // job N+1 + // carefull call this next after itemN.setSimulationNumber() + SimulationJob subJobNp1 = next(); + if (subJobNp1 == null) { + // there is no N+1 job, N is the last one + itemN.setLastSimulation(true); + } + simulationService.submitSubJob(subJobN); + subJobN = subJobNp1; + } catch (Exception eee) { + if (log.isErrorEnabled()) { + log.error(I18n._("Can't add simulation: %s", job.getItem().getControl().getId()), eee); + } + } + } + } + + /** + * Indique s'il y a encore des simulations dans le plan. Par defaut pour + * Eviter les plans sans fin, le nombre de plan genere par simulation + * est limite a {@link SimulationService#MAX_PLAN_SIMULATION} + * + * @return <tt>true</tt> if has next + */ + public boolean hasNext() { + try { + // if user request stop simulation, stop all futur planned simulation + // and if last doNext is false not do next simulation + boolean result = !control.isStopSimulationRequest() && doNext; + if (result) { + // hasNext() est appelee par un autre thread concurrent + // via la methode finished(SimulationJob, SimulationStorage) + synchronized (this) { + // si deja creer on ne le refait pas + if (nextJob == null) { + // Prepration de la simulation a faire + // create next id simulation + // this start a 0 + int planNumber = planContext.getNumber(); + if (planNumber > SimulationService.MAX_PLAN_SIMULATION) { + log.error(I18n._("Analyse plan error, too many simulation for %s : %s", id, planNumber)); + doNext = false; + result = false; + } else { + String simId = id + "_" + planNumber; + param.setSimulationPlanNumber(planNumber); + File tmpDirectory = FileUtil.createTempDirectory("isisfish-simulation-", "-preparation"); + SimulationStorage sim = SimulationStorage.importAndRenameZip(tmpDirectory, job.getItem().getSimulationZip(), simId); + sim.getParameter().setSimulationPlanNumber(planNumber); + // appel de tous les plans pour modifier la simulation + for (SimulationPlan plan : simulationPlan) { + result = result && plan.beforeSimulation(planContext, sim); + if (!result) { + nextJob = null; + break; + } + } + doNext = result; + if (result) { + File zip = sim.createZip(); + SimulationControl childControl = new SimulationControl(simId); + SimulationParameter childParam = param.copy(); + SimulationItem item = new SimulationItem(childControl, childParam); + item.setSimulationZip(zip); + nextJob = new SimulationJob(simulationService, job, item, job.getPriority()); + nextJob.setLauncher(job.getLauncher()); + // FIXME on retire la post action pour les plan dépendants + // sera appelé directement par le job de preparations + if (param.isIndependentPlan()) { + nextJob.addPostAction(this); // pour l'appel des after des plans + } + } + // close context for plan generator + // FIXME echatellier 20120904 could throw + //org.nuiton.topia.TopiaException: Ce contexte a deja ete ferme + sim.closeStorage(); + // quoi qu'il arrive on supprime le repertoire temporaire + if (!FileUtils.deleteQuietly(tmpDirectory)) { + log.warn(I18n._("isisfish.error.remove.directory", tmpDirectory)); + } + } + // increment number for next simulation job + planContext.incNumber(); + } + } + } + return result; + } catch (Exception eee) { + throw new IsisFishRuntimeException(I18n._("isisfish.error.evalute.plan.script"), eee); + } + } + + public SimulationJob next() { + hasNext(); // pour etre sur qu'il a ete appele au moins une fois + SimulationJob result = null; + // next est appelee par un autre thread concurrent + // via la methode finished(SimulationJob, SimulationStorage) + synchronized (this) { + result = nextJob; + nextJob = null; + } + return result; + } + + @Override + public void remove() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public void finished(SimulationJob job, SimulationStorage sim) { + // doNext = true; + // appel de tous les plans pour modifier la simulation + // EC20090716 : use param.getSimulationPlans() instances, + // not sim.getParameters().getSimulationPlans() not sames !!! + for (SimulationPlan plan : simulationPlan) { + try { + boolean result = plan.afterSimulation(planContext, sim); + doNext = doNext && result; + } catch (Exception eee) { + log.error(I18n._("Stop simulation plan, because can't call afterSimulation correctly on plan %s", plan.getClass().getName()), eee); + doNext = false; + } + } + // une sim vient de se finir, on incremente le compteur + done++; + if (!hasNext() && (done + 1 == planContext.getNumber())) { + // on enleve le master plan des simulations en cours, vu que + // toutes les simu sont terminees + simulationService.fireStopEvent(this.job); + } + } + + @Override + public void exception(SimulationJob job, Throwable eee) { + // il y a une simulation d'echoue, on ne fait pas les suivantes + // cela n'impacte pas les plan independant puisque toutes les + // simulation on deja ete generee + doNext = false; + simulationService.fireStopEvent(this.job); + } + +} Property changes on: branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationPlanPrepareJob.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Modified: branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationService.java =================================================================== --- branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationService.java 2014-04-02 12:36:19 UTC (rev 3915) +++ branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationService.java 2014-04-02 13:25:29 UTC (rev 3916) @@ -25,6 +25,7 @@ package fr.ifremer.isisfish.simulator.launcher; +import fr.ifremer.isisfish.simulator.sensitivity.FactorHelper; import static org.nuiton.i18n.I18n.t; import java.beans.PropertyChangeListener; @@ -37,7 +38,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -87,7 +87,6 @@ import fr.ifremer.isisfish.simulator.SimulationException; import fr.ifremer.isisfish.simulator.SimulationParameter; import fr.ifremer.isisfish.simulator.SimulationPlan; -import fr.ifremer.isisfish.simulator.SimulationPlanContext; import fr.ifremer.isisfish.simulator.sensitivity.DesignPlan; import fr.ifremer.isisfish.simulator.sensitivity.Domain; import fr.ifremer.isisfish.simulator.sensitivity.Factor; @@ -100,6 +99,7 @@ import fr.ifremer.isisfish.simulator.sensitivity.domain.RuleDiscreteDomain; import fr.ifremer.isisfish.util.CompileHelper; import fr.ifremer.isisfish.util.ConverterUtil; +import java.util.concurrent.atomic.AtomicInteger; /** * Cette classe est responsable de conservation de toutes les simulations faites @@ -392,12 +392,12 @@ job.setLauncher(launcher); fireStartEvent(job); - // Attention, dans le cas d'un plan de simulation, le new PrepareSimulationJob + // Attention, dans le cas d'un plan de simulation, le new SimulationPlanPrepareJob // doit etre fait AVANT de faire le prepareSimulationZipFile // car, il est possible que l'init des plans ajoute des regles !!! - PrepareSimulationJob task = null; + SimulationPlanPrepareJob task = null; if (localParameters.getUseSimulationPlan()) { - task = new PrepareSimulationJob(this, job); + task = new SimulationPlanPrepareJob(this, job); } // on construit le zip de la simulation @@ -488,10 +488,9 @@ // subParam only convenient for add pre script // for launcher SimulationParameter subParam = localParameters.copy(); - String preScriptContent = generatePreScript(scenario); + String generatedScriptContent = FactorHelper.generatePreScript(scenario); // usefull next two line ? - subParam.setUsePreScript(true); - subParam.setPreScript(preScriptContent); + subParam.setGeneratedPreScript(generatedScriptContent); // build new simulation id String subsimulationId = id + "_" + simulationIndex; @@ -512,7 +511,7 @@ if (subParam.getUseSimulationPlan() && subParam.isIndependentPlan()) { // c un plan de simulation independant, on construit toute les sous simu - Runnable task = new PrepareSimulationJob(this, job); + Runnable task = new SimulationPlanPrepareJob(this, job); subSimulationComputationExecutor.execute(task); } else { // l'item est fini d'etre initialise, on peut l'ajouter a la queue @@ -565,154 +564,6 @@ } } - /** Permet de manipuler un int entre plusieurs appele de methodes recursive. */ - public static class Counter { - protected int counter = 0; - public void inc() { - counter++; - } - public int getCounter() { - return counter; - } - } - - /** - * Generate prescript to set factor values before simulation start. - * - * @param scenario to generate prescript - * @return simulation pre script with correct values - */ - protected String generatePreScript(Scenario scenario) { - ConvertUtilsBean beanUtils = ConverterUtil.getConverter(null); - - // n'utilise plus freemarker, car il y avait plus d'instruction - // freemarker compliqué que de code a afficher - StringBuffer buffer = new StringBuffer(); - buffer.append("import org.apache.commons.beanutils.BeanUtils;\n"); - buffer.append("import org.apache.commons.beanutils.ConvertUtilsBean;\n"); - buffer.append("import fr.ifremer.isisfish.util.ConverterUtil;\n"); - buffer.append("import fr.ifremer.isisfish.simulator.SimulationParameter;\n"); - buffer.append("ConvertUtilsBean beanUtils = ConverterUtil.getConverter(db);\n"); - buffer.append("SimulationParameter params = context.getSimulationStorage().getParameter();\n"); - - generatePreScript(beanUtils, buffer, new Counter(), scenario.getFactors()); - - String scriptContent = buffer.toString(); - if (log.isTraceEnabled()) { - log.trace("Simulation prescript content = " + scriptContent); - } - return scriptContent; - } - - /** - * Generate prescript for a factor list that can be called recursively to - * manage factor group. - * - * @param beanUtils beanUtils converter - * @param buffer buffer to fill - * @param counter call counter used to avoid variables name collision - * @param factors factor list to manage - */ - protected void generatePreScript(ConvertUtilsBean beanUtils, StringBuffer buffer, Counter counter, Collection<Factor> factors) { - - for (Factor factor : factors) { - if (factor instanceof FactorGroup) { - buffer.append("/* factor group : ").append(factor.getName()).append(" */\n"); - FactorGroup factorGroup = (FactorGroup)factor; - generatePreScript(beanUtils, buffer, counter, factorGroup.getFactors()); - } - else { - int factorIndex = counter.getCounter(); - buffer.append("/* factor : ").append(factor.getName()).append(" */\n"); - - // cas special 1 : population de départ - if (factor.getPath().matches("parameters.population\\.\\w+\\.number")) { - String paramName = StringUtils.removeStart(factor.getPath(), "parameters."); - // pas de convert, c'est fait comme ca dans - // SimulationParameters.toProperties(); - MatrixND matrix = (MatrixND)factor.getValue(); - Object stringValue = String.valueOf(matrix.toList()); - buffer.append("params.setProperty(\"").append(paramName).append("\",\"").append(stringValue).append("\");\n"); - } - // cas special 2 : regles - else if (factor.getPath().equals("parameters.rules")) { - List<Rule> rules = (List<Rule>)factor.getValue(); - List<String> rulesNames = new ArrayList<String>(); - int ruleIndex = 0; - for (Rule rule : rules) { - rulesNames.add(rule.getClass().getSimpleName()); - Properties rulesProps = RuleHelper.getRuleAsProperties(ruleIndex++, null, rule); - for (String rulesProp : rulesProps.stringPropertyNames()) { - String value = rulesProps.getProperty(rulesProp); - buffer.append("params.setProperty(\"").append(rulesProp).append("\",\"").append(value).append("\");\n"); - } - } - buffer.append("params.setProperty(\"rules\",\"").append(StringUtils.join(rulesNames, ",")).append("\");\n"); - } - // cas special 3 : facteur sur les parametres des regles - else if (factor.getPath().startsWith("parameters.rule.")) { - // special case for rule parameter with - Pattern pattern = Pattern.compile("^parameters\\.(rule\\.\\d+\\.parameter\\.\\w+)(\\..+)?$"); - Matcher matcher = pattern.matcher(factor.getPath()); - String paramName = null; - if (matcher.matches()) { - paramName = matcher.group(1); - } else { - paramName = StringUtils.removeStart(factor.getPath(), "parameters."); - } - String stringValue = ConvertUtils.convert(factor.getValue()); - buffer.append("params.setProperty(\"").append(paramName).append("\",\"").append(stringValue).append("\");\n"); - } - // cas special 4 : equation - else if (StringUtils.isNotBlank(factor.getEquationVariableName())) { - buffer.append("context.setComputeValue(\"").append(factor.getName() + "." + factor.getEquationVariableName()); - buffer.append("\",").append(factor.getValue()).append(");\n"); - } - // cas pas si special - else { - Object value = factor.getValue(); - String stringValue = beanUtils.convert(value); - String escValue = stringValue; - if (factor.getDomain() instanceof EquationDiscreteDomain) { - // echatellier: equation can contains quotes that break - // prescript, only quote, not all java replacements - // a ne pas faire pour le reste, pour les - // matrice par exemple, ca passe mal - escValue = StringUtils.replace(escValue, "\n", ""); - escValue = StringUtils.replace(escValue, "\r", ""); - escValue = StringUtils.replace(escValue, "\"", "\\\""); - } - String path = factor.getPath(); - String topiaId = path.substring(0, path.lastIndexOf('#')); - String property = path.substring(path.lastIndexOf('#') + 1); - // Double value123 = beanUtils.convert("mystringvalue", Double.class); - buffer.append(value.getClass().getName()).append(" value"); - buffer.append(factorIndex).append(" = beanUtils.convert(\""); - buffer.append(escValue).append("\", ").append(value.getClass().getName()); - buffer.append(".class);\n"); - // TopiaEntity entity123 = db.findByTopiaId(topiaId); - buffer.append("TopiaEntity entity").append(factorIndex); - buffer.append(" = db.findByTopiaId(\"").append(topiaId); - buffer.append("\");\n"); - - if (factor.getDomain() instanceof EquationDiscreteDomain) { - // BeanUtils.setProperty(entity123, "propertyContent", value123); - buffer.append("BeanUtils.setProperty(entity").append(factorIndex); - buffer.append(", \"").append(property).append("Content\", "); - buffer.append("value").append(factorIndex).append(");\n"); - } else { - // BeanUtils.setProperty(entity123, "property", value123); - buffer.append("BeanUtils.setProperty(entity").append(factorIndex); - buffer.append(", \"").append(property).append("\", "); - buffer.append("value").append(factorIndex).append(");\n"); - } - } - } - - counter.inc(); - } - } - protected void submit(SimulationJob job) { SimulatorLauncher launcher = job.getLauncher(); // on ajoute a la queue qui utilise le launcher defini dans le job @@ -827,276 +678,8 @@ } /** - * Permet de genere les sous simulations d'un plan de simulation. Pour les - * plan independant, on l'utilise en Runnable pour genere tous les plans - * possible et les soumettre a la queue. Pour les plans dependant - * on l'utilise seulement comme iterator. La methode afterSimulation des plans - * est appelee automatiquement a la fin de la simulation grace au mecanisme - * de PostAction sur les {@link SimulationJob}. - */ - public static class PrepareSimulationJob implements Runnable, - Iterator<SimulationJob>, SimulationJob.PostAction { - - protected SimulationService simulationService; - protected SimulationPlanContext planContext; - protected SimulationJob job; - protected SimulationJob nextJob; - protected boolean doNext = true; - protected String id; - protected SimulationControl control; - protected SimulationParameter param; - protected int done = 0; - protected List<SimulationPlan> simulationPlan; - - public PrepareSimulationJob(SimulationService simulationService, - SimulationJob job) { - this.simulationService = simulationService; - this.job = job; - id = job.getItem().getControl().getId(); - control = job.getItem().getControl(); - param = job.getItem().getParameter(); - // take a copy of simulation paln list - // because they a freed during simulation (soft reference) - // is there is not enought memory available - simulationPlan = param.getSimulationPlans(); - this.planContext = new SimulationPlanContext(control.getId(), param); - - try { - // appel de init sur chaque plan - for (SimulationPlan plan : simulationPlan) { - plan.init(planContext); - } - } catch (Exception eee) { - // add manual log - // we are in a thread, IsisFishRuntimeException is displayed - // outside a log - if (log.isErrorEnabled()) { - log.error(t("isisfish.error.evaluate.preplan.script"), eee); - } - throw new IsisFishRuntimeException(t("isisfish.error.evaluate.preplan.script"), eee); - } - } - - /** - * Genere toutes les sous simulations et les places dans la queue. - * - * Cette methode {@code run()} est appelée seulement dans le cas de la - * génération de plans indépendants. - * - * @see SimulationJob#run() pour les plans dépendants - */ - public void run() { - /* Original code - while (hasNext()) { - try { - SimulationJob subJob = next(); - - if (log.isInfoEnabled()) { - log.info("Simulation generee: " + subJob.getId()); - } - simulationService.submitSubJob(subJob); - } catch (Exception eee) { - if (log.isErrorEnabled()) { - log.error(t("Can't add simulation: %s", job.getItem() - .getControl().getId()), eee); - } - } - }*/ - - // New iteration remember always simulation N and N+1 - // needed to know witch simulation is the last one - // get simulation N - SimulationJob subJobN = null; - if (hasNext()) { - subJobN = next(); - } - - while (subJobN != null) { - - try { - if (log.isInfoEnabled()) { - log.info("Simulation generated: " + subJobN.getId()); - } - - // set item additionnal informations - SimulationItem itemN = subJobN.getItem(); - itemN.setStandaloneSimulation(false); // independant plan - // - 1 because planContext.getNumber() is set to next simulation to generate - itemN.setSimulationNumber(planContext.getNumber() - 1); - - // job N+1 - // carefull call this next after itemN.setSimulationNumber() - SimulationJob subJobNp1 = next(); - if (subJobNp1 == null) { - // there is no N+1 job, N is the last one - itemN.setLastSimulation(true); - } - - simulationService.submitSubJob(subJobN); - - subJobN = subJobNp1; - } - catch (Exception eee) { - if (log.isErrorEnabled()) { - log.error(t("Can't add simulation: %s", job.getItem() - .getControl().getId()), eee); - } - } - } - } - - /** - * Indique s'il y a encore des simulations dans le plan. Par defaut pour - * Eviter les plans sans fin, le nombre de plan genere par simulation - * est limite a {@link SimulationService#MAX_PLAN_SIMULATION} - * - * @return <tt>true</tt> if has next - */ - public boolean hasNext() { - try { - // if user request stop simulation, stop all futur planned simulation - // and if last doNext is false not do next simulation - boolean result = !control.isStopSimulationRequest() && doNext; - if (result) { - - // hasNext() est appelee par un autre thread concurrent - // via la methode finished(SimulationJob, SimulationStorage) - synchronized (this) { - - // si deja creer on ne le refait pas - if (nextJob == null) { - // Prepration de la simulation a faire - // create next id simulation - - // this start a 0 - int planNumber = planContext.getNumber(); - - if (planNumber > MAX_PLAN_SIMULATION) { - log.error(t("Analyse plan error, too many simulation for %s : %s", - id, planNumber)); - doNext = false; - result = false; - } else { - String simId = id + "_" + planNumber; - param.setSimulationPlanNumber(planNumber); - - File tmpDirectory = FileUtil.createTempDirectory( - "isisfish-simulation-", "-preparation"); - SimulationStorage sim = SimulationStorage - .importAndRenameZip(tmpDirectory, job - .getItem().getSimulationZip(), - simId); - sim.getParameter().setSimulationPlanNumber(planNumber); - - // appel de tous les plans pour modifier la simulation - for (SimulationPlan plan : simulationPlan) { - result = result - && plan.beforeSimulation(planContext, sim); - if (!result) { - nextJob = null; - break; - } - } - doNext = result; - if (result) { - - File zip = sim.createZip(); - SimulationControl childControl = new SimulationControl(simId); - SimulationParameter childParam = param.copy(); - SimulationItem item = new SimulationItem(childControl, childParam); - item.setSimulationZip(zip); - - nextJob = new SimulationJob(simulationService, job, item, job.getPriority()); - nextJob.setLauncher(job.getLauncher()); - - // FIXME on retire la post action pour les plan dépendants - // sera appelé directement par le job de preparations - if (param.isIndependentPlan()) { - nextJob.addPostAction(this); // pour l'appel des after des plans - } - } - - // close context for plan generator - // FIXME echatellier 20120904 could throw - //org.nuiton.topia.TopiaException: Ce contexte a deja ete ferme - sim.closeStorage(); - - // quoi qu'il arrive on supprime le repertoire temporaire - if (!FileUtils.deleteQuietly(tmpDirectory)) { - log.warn(t("isisfish.error.remove.directory", - tmpDirectory)); - } - } - - // increment number for next simulation job - planContext.incNumber(); - } - } - } - return result; - } catch (Exception eee) { - throw new IsisFishRuntimeException( - t("isisfish.error.evalute.plan.script"), eee); - } - - } - - public SimulationJob next() { - hasNext(); // pour etre sur qu'il a ete appele au moins une fois - SimulationJob result = null; - - // next est appelee par un autre thread concurrent - // via la methode finished(SimulationJob, SimulationStorage) - synchronized (this) { - result = nextJob; - nextJob = null; - } - - return result; - - } - - public void remove() { - throw new UnsupportedOperationException("Not supported."); - } - - public void finished(SimulationJob job, SimulationStorage sim) { - // doNext = true; - - // appel de tous les plans pour modifier la simulation - // EC20090716 : use param.getSimulationPlans() instances, - // not sim.getParameters().getSimulationPlans() not sames !!! - for (SimulationPlan plan : simulationPlan) { - try { - boolean result = plan.afterSimulation(planContext, sim); - doNext = doNext && result; - } catch (Exception eee) { - log.error(t("Stop simulation plan, because can't call afterSimulation correctly on plan %s", - plan.getClass().getName()), eee); - doNext = false; - } - } - - // une sim vient de se finir, on incremente le compteur - done++; - if (!hasNext() && (done + 1 == planContext.getNumber())) { - // on enleve le master plan des simulations en cours, vu que - // toutes les simu sont terminees - simulationService.fireStopEvent(this.job); - } - } - - public void exception(SimulationJob job, Throwable eee) { - // il y a une simulation d'echoue, on ne fait pas les suivantes - // cela n'impacte pas les plan independant puisque toutes les - // simulation on deja ete generee - doNext = false; - simulationService.fireStopEvent(this.job); - } - } - - /** * Prepare les fichiers qui seront utilsé à la simulation: + * Prepare les fichiers qui seront utilsé à la simulation: * <ul> * <li> scripts</li> * <li> rules</li> Added: branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/sensitivity/FactorHelper.java =================================================================== --- branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/sensitivity/FactorHelper.java (rev 0) +++ branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/sensitivity/FactorHelper.java 2014-04-02 13:25:29 UTC (rev 3916) @@ -0,0 +1,170 @@ +package fr.ifremer.isisfish.simulator.sensitivity; + + +import fr.ifremer.isisfish.rule.Rule; +import fr.ifremer.isisfish.rule.RuleHelper; +import fr.ifremer.isisfish.simulator.sensitivity.domain.EquationDiscreteDomain; +import fr.ifremer.isisfish.util.ConverterUtil; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.commons.beanutils.ConvertUtils; +import org.apache.commons.beanutils.ConvertUtilsBean; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.math.matrix.MatrixND; + +/** + * Useful method for factor + * - create prescript with factor list + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class FactorHelper { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + private static final Log log = LogFactory.getLog(FactorHelper.class); + + /** + * Generate prescript to set factor values before simulation start. + * + * @param scenario to generate prescript + * @return simulation pre script with correct values + */ + public static String generatePreScript(Scenario scenario) { + return generatePreScript(scenario.getFactors()); + } + + public static String generatePreScript(Collection<Factor> factors) { + ConvertUtilsBean beanUtils = ConverterUtil.getConverter(null); + // n'utilise plus freemarker, car il y avait plus d'instruction + // freemarker compliqué que de code a afficher + StringBuffer buffer = new StringBuffer(); + buffer.append("import org.apache.commons.beanutils.BeanUtils;\n"); + buffer.append("import org.apache.commons.beanutils.ConvertUtilsBean;\n"); + buffer.append("import fr.ifremer.isisfish.util.ConverterUtil;\n"); + buffer.append("import fr.ifremer.isisfish.simulator.SimulationParameter;\n"); + buffer.append("ConvertUtilsBean beanUtils = ConverterUtil.getConverter(db);\n"); + buffer.append("SimulationParameter params = context.getSimulationStorage().getParameter();\n"); + generatePreScript(beanUtils, buffer, new AtomicInteger(), factors); + String scriptContent = buffer.toString(); + if (log.isTraceEnabled()) { + log.trace("Simulation prescript content = " + scriptContent); + } + return scriptContent; + } + + /** + * Generate prescript for a factor list that can be called recursively to + * manage factor group. + * + * @param beanUtils beanUtils converter + * @param buffer buffer to fill + * @param counter call counter used to avoid variables name collision + * @param factors factor list to manage + */ + protected static void generatePreScript(ConvertUtilsBean beanUtils, StringBuffer buffer, AtomicInteger counter, Collection<Factor> factors) { + for (Factor factor : factors) { + if (factor instanceof FactorGroup) { + buffer.append("/* factor group : ").append(factor.getName()).append(" */\n"); + FactorGroup factorGroup = (FactorGroup) factor; + generatePreScript(beanUtils, buffer, counter, factorGroup.getFactors()); + } else { + int factorIndex = counter.get(); + buffer.append("/* factor : ").append(factor.getName()).append(" */\n"); + // cas special 1 : population de départ + if (factor.getPath().matches("parameters.population\\.\\w+\\.number")) { + String paramName = StringUtils.removeStart(factor.getPath(), "parameters."); + // pas de convert, c'est fait comme ca dans + // SimulationParameters.toProperties(); + MatrixND matrix = (MatrixND) factor.getValue(); + Object stringValue = String.valueOf(matrix.toList()); + buffer.append("params.setProperty(\"").append(paramName).append("\",\"").append(stringValue).append("\");\n"); + } + // cas special 2 : regles + else if (factor.getPath().equals("parameters.rules")) { + List<Rule> rules = (List<Rule>) factor.getValue(); + List<String> rulesNames = new ArrayList<String>(); + int ruleIndex = 0; + for (Rule rule : rules) { + rulesNames.add(rule.getClass().getSimpleName()); + Properties rulesProps = RuleHelper.getRuleAsProperties(ruleIndex++, null, rule); + for (String rulesProp : rulesProps.stringPropertyNames()) { + String value = rulesProps.getProperty(rulesProp); + buffer.append("params.setProperty(\"").append(rulesProp).append("\",\"").append(value).append("\");\n"); + } + } + buffer.append("params.setProperty(\"rules\",\"").append(StringUtils.join(rulesNames, ",")).append("\");\n"); + } + // cas special 3 : facteur sur les parametres des regles + else if (factor.getPath().startsWith("parameters.rule.")) { + // special case for rule parameter with + Pattern pattern = Pattern.compile("^parameters\\.(rule\\.\\d+\\.parameter\\.\\w+)(\\..+)?$"); + Matcher matcher = pattern.matcher(factor.getPath()); + String paramName = null; + if (matcher.matches()) { + paramName = matcher.group(1); + } else { + paramName = StringUtils.removeStart(factor.getPath(), "parameters."); + } + String stringValue = ConvertUtils.convert(factor.getValue()); + buffer.append("params.setProperty(\"").append(paramName).append("\",\"").append(stringValue).append("\");\n"); + } + // cas special 4 : equation + else if (StringUtils.isNotBlank(factor.getEquationVariableName())) { + buffer.append("context.setComputeValue(\"").append(factor.getName() + "." + factor.getEquationVariableName()); + buffer.append("\",").append(factor.getValue()).append(");\n"); + } + // cas pas si special + else { + Object value = factor.getValue(); + String stringValue = beanUtils.convert(value); + String escValue = stringValue; + if (factor.getDomain() instanceof EquationDiscreteDomain) { + // echatellier: equation can contains quotes that break + // prescript, only quote, not all java replacements + // a ne pas faire pour le reste, pour les + // matrice par exemple, ca passe mal + escValue = StringUtils.replace(escValue, "\n", ""); + escValue = StringUtils.replace(escValue, "\r", ""); + escValue = StringUtils.replace(escValue, "\"", "\\\""); + } + String path = factor.getPath(); + String topiaId = path.substring(0, path.lastIndexOf('#')); + String property = path.substring(path.lastIndexOf('#') + 1); + // Double value123 = beanUtils.convert("mystringvalue", Double.class); + buffer.append(value.getClass().getName()).append(" value"); + buffer.append(factorIndex).append(" = beanUtils.convert(\""); + buffer.append(escValue).append("\", ").append(value.getClass().getName()); + buffer.append(".class);\n"); + // TopiaEntity entity123 = db.findByTopiaId(topiaId); + buffer.append("TopiaEntity entity").append(factorIndex); + buffer.append(" = db.findByTopiaId(\"").append(topiaId); + buffer.append("\");\n"); + if (factor.getDomain() instanceof EquationDiscreteDomain) { + // BeanUtils.setProperty(entity123, "propertyContent", value123); + buffer.append("BeanUtils.setProperty(entity").append(factorIndex); + buffer.append(", \"").append(property).append("Content\", "); + buffer.append("value").append(factorIndex).append(");\n"); + } else { + // BeanUtils.setProperty(entity123, "property", value123); + buffer.append("BeanUtils.setProperty(entity").append(factorIndex); + buffer.append(", \"").append(property).append("\", "); + buffer.append("value").append(factorIndex).append(");\n"); + } + } + } + counter.incrementAndGet(); + } + } + +} Property changes on: branches/4.0.1/src/main/java/fr/ifremer/isisfish/simulator/sensitivity/FactorHelper.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Modified: branches/4.0.1/src/main/resources/templates/script/optimization.ftl =================================================================== --- branches/4.0.1/src/main/resources/templates/script/optimization.ftl 2014-04-02 12:36:19 UTC (rev 3915) +++ branches/4.0.1/src/main/resources/templates/script/optimization.ftl 2014-04-02 13:25:29 UTC (rev 3916) @@ -76,14 +76,33 @@ private static Log log = LogFactory.getLog(${name}.class); /** + * Appele lors de l'initialisation. La premiere generation doit etre construite + * dans l'init via des appels a context.addSimulation(...) + * + * @param context + */ + void init(OptimizationContext context); + + + /** * Génère une nouvelle série de simulation suivant le context d'optimisation. - * + * Pour cela vous devez appeler context.addSimulation(...) pour ajouter + * des simulations pour la prochaine generation. + * * @param context context * @param region region * @return simulations serie */ - public List<SimulationStorage> getNextGeneration(OptimizationContext context, FisheryRegion region) { + public void getNextSimulation(OptimizationContext context) { // TODO return null; } + + /** + * Cette methode est appelee lorsqu'il n'y a plus de simulation a faire + * (init ou getNextSimulation n'ont pas fait appel a context.addSimulation) + * @param context + */ + void endSimulation(OptimizationContext context); + }
participants (1)
-
bpoussin@users.forge.codelutin.com