From: miettinen Date: Wed, 3 Jul 2013 12:23:10 +0000 (+0000) Subject: Added interface for different parameter value generators for sensitivity analysis. X-Git-Tag: 1.8.1~271 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=23d9cd7ac791d1b06605df6626f69083cd101c39;p=simantics%2Fsysdyn.git Added interface for different parameter value generators for sensitivity analysis. Implemented Halton sequence generator. (refs #4365) git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@27681 ac1ea38d-2e2b-0410-8846-a27921b304fc --- diff --git a/org.simantics.sysdyn.ontology/graph.tg b/org.simantics.sysdyn.ontology/graph.tg index a01167be..d242b0ba 100644 Binary files a/org.simantics.sysdyn.ontology/graph.tg and b/org.simantics.sysdyn.ontology/graph.tg differ diff --git a/org.simantics.sysdyn.ontology/graph/Sysdyn.pgraph b/org.simantics.sysdyn.ontology/graph/Sysdyn.pgraph index 9b887312..a4b4fdc6 100644 --- a/org.simantics.sysdyn.ontology/graph/Sysdyn.pgraph +++ b/org.simantics.sysdyn.ontology/graph/Sysdyn.pgraph @@ -351,6 +351,7 @@ SYSDYN.PlaybackExperiment -- SYSDYN.SensitivityAnalysisExperiment.parameterList --> L0.List -- SYSDYN.SensitivityAnalysisExperiment.randomSeed --> L0.Integer -- SYSDYN.SensitivityAnalysisExperiment.method --> SYSDYN.ValueGeneratorMethod -- SYSDYN.SensitivityAnalysisExperiment.resultRefreshRate --> L0.Integer -- SYSDYN.SensitivityAnalysisExperiment.numberOfValues --> L0.Integer > contentListener; @Override public void createControls(Composite body, IWorkbenchSite site, - final ISessionContext context, WidgetSupport support) { + final ISessionContext context, final WidgetSupport support) { support.register(this); Composite composite = new RemoveFocusBeforeExperimentComposite(body, SWT.NONE); @@ -129,7 +130,7 @@ public class SensitivityAnalysisExperimentTab extends LabelPropertyTabContributo // Label Composite labelComposite = new Composite(content, SWT.NONE); GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(labelComposite); - GridLayoutFactory.fillDefaults().numColumns(6).applyTo(labelComposite); + GridLayoutFactory.fillDefaults().numColumns(8).applyTo(labelComposite); Label label = new Label(labelComposite, SWT.NONE); label.setText("Name"); @@ -148,7 +149,80 @@ public class SensitivityAnalysisExperimentTab extends LabelPropertyTabContributo n.addModifyListener(new IntegerPropertyModifier(context, SysdynResource.URIs.SensitivityAnalysisExperiment_numberOfValues)); n.setInputValidator(new IntegerValidator()); n.setColorProvider(new SysdynBasicColorProvider(new LocalResourceManager(JFaceResources.getResources(), n.getWidget()))); - GridDataFactory.fillDefaults().hint(80, SWT.DEFAULT).applyTo(n.getWidget()); + GridDataFactory.fillDefaults().hint(50, SWT.DEFAULT).applyTo(n.getWidget()); + + label = new Label(labelComposite, SWT.NONE); + label.setText("Method"); + + TrackedCombo methodSelector = new TrackedCombo(labelComposite, support, SWT.DROP_DOWN); + methodSelector.setItemFactory(new ReadFactoryImpl>() { + + @Override + public Map perform(ReadGraph graph, Resource input) throws DatabaseException { + SysdynResource SR = SysdynResource.getInstance(graph); + Map items = new HashMap(); + + items.put("Halton", SR.HaltonSequenceGenerator); + items.put("Random", SR.RandomGenerator); + + return items; + } + + }); + methodSelector.setSelectionFactory(new ReadFactoryImpl() { + + @Override + public String perform(ReadGraph graph, Resource parameter) throws DatabaseException { + SysdynResource SR = SysdynResource.getInstance(graph); + Resource method = graph.getPossibleObject(parameter, SR.SensitivityAnalysisExperiment_method); + if(method == null) + return null; + + if(graph.isInstanceOf(method, SR.RandomGenerator)) + return "Random"; + else if(graph.isInstanceOf(method, SR.HaltonSequenceGenerator)) + return "Halton"; + else + return ""; + + } + }); + methodSelector.addModifyListener(new ComboModifyListenerImpl() { + + @Override + public void applyText(WriteGraph graph, Resource input, String text) + throws DatabaseException { + if(text == null || text.isEmpty()) + return; + + SysdynResource SR = SysdynResource.getInstance(graph); + + Resource type = SR.RandomGenerator; + + if("Halton".equals(text)) + type = SR.HaltonSequenceGenerator; + + graph.deny(input, SR.SensitivityAnalysisExperiment_method); + + GraphUtils.create2(graph, type, + SR.SensitivityAnalysisExperiment_method_Inverse, input); + + dirtyMethod = true; + } + }); + methodSelector.addModifyListener(new TextModifyListener() { + + @Override + public void modifyText(TrackedModifyEvent e) { + if(dirtyMethod) { + support.update(); + dirtyMethod = false; + propertyContainer.setContent(content); + Point size = content.computeSize(SWT.DEFAULT, SWT.DEFAULT); + propertyContainer.setMinSize(size); + } + } + }); label = new Label(labelComposite, SWT.NONE); label.setText("Seed"); @@ -158,7 +232,7 @@ public class SensitivityAnalysisExperimentTab extends LabelPropertyTabContributo seed.addModifyListener(new IntegerPropertyModifier(context, SysdynResource.URIs.SensitivityAnalysisExperiment_randomSeed)); seed.setInputValidator(new IntegerValidator()); seed.setColorProvider(new SysdynBasicColorProvider(new LocalResourceManager(JFaceResources.getResources(), seed.getWidget()))); - GridDataFactory.fillDefaults().hint(80, SWT.DEFAULT).applyTo(seed.getWidget()); + GridDataFactory.fillDefaults().hint(50, SWT.DEFAULT).applyTo(seed.getWidget()); // (Ontology-based) GraphExplorer displaying range axis and variables mapped to those axis explorer = new AxisAndVariablesExplorerComposite(ArrayMap.keys( diff --git a/org.simantics.sysdyn/adapters.xml b/org.simantics.sysdyn/adapters.xml index e370bc2c..509cd5ea 100644 --- a/org.simantics.sysdyn/adapters.xml +++ b/org.simantics.sysdyn/adapters.xml @@ -43,6 +43,22 @@ + + + + + + + + + + + primes; + + private void getPrimes() { + int newPrime = 2; + while (primes.size() < dimension) { + boolean isPrime = true; + for (int p : primes) { + if (newPrime % p == 0) { + ++newPrime; + isPrime = false; + break; + } + } + if (isPrime) { + primes.add(newPrime); + } + } + } + + public HaltonSequenceGenerator(ReadGraph graph, Resource method) { + + try { + SysdynResource SR = SysdynResource.getInstance(graph); + Resource experiment = graph.getPossibleObject(method, SR.SensitivityAnalysisExperiment_method_Inverse); + Resource parameterListResource = graph.getPossibleObject(experiment, SR.SensitivityAnalysisExperiment_parameterList); + dimension = ListUtils.getListNodes(graph, parameterListResource).size(); + + primes = new ArrayList(); + getPrimes(); + + initialize(); + } catch (DatabaseException e) { + + } + } + + public static double getHalton(int index, int base) { + ++index; // Map indexes to start from 1; + double result = 0; + double f = 1.0 / base; + while (index > 0) { + result = result + f * (index % base); + index = index / base; + f = f / base; + } + return result; + } + + public List next() { + ArrayList retval = new ArrayList(); + for (int i = 0; i < dimension; ++i) { + int base = primes.get(i); + double halton = getHalton(index, base); + retval.add(halton); + } + ++index; + return retval; + } + + public void initialize() { + index = 0; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/generator/IGenerator.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/generator/IGenerator.java new file mode 100644 index 00000000..59792648 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/generator/IGenerator.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2013 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.sysdyn.adapter.generator; + +import java.util.List; + +/** + * Interface for parameter value generators. + * + * @author Tuomas Miettinen + * + */ +public interface IGenerator { + + /** + * Get the next parameter combination. + * @return list of generated parameter values + */ + public List next(); + + /** + * Initialize the generator. + */ + public void initialize(); +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/generator/RandomGenerator.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/generator/RandomGenerator.java new file mode 100644 index 00000000..e4a920fe --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/generator/RandomGenerator.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2013 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.sysdyn.adapter.generator; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.utils.ListUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.SysdynResource; + +/** + * Random generator that creates ArrayLists of random Doubles between 0 and 1. + * + * @author Tuomas Miettinen + */ + +public class RandomGenerator implements IGenerator { + + private int seed; + private int dimension; + private Random random; + + public RandomGenerator(ReadGraph graph, Resource method) { + + try { + SysdynResource SR = SysdynResource.getInstance(graph); + Resource experiment = graph.getPossibleObject(method, SR.SensitivityAnalysisExperiment_method_Inverse); + seed = graph.getPossibleRelatedValue(experiment, SR.SensitivityAnalysisExperiment_randomSeed, Bindings.INTEGER); + + Resource parameterListResource = graph.getPossibleObject(experiment, SR.SensitivityAnalysisExperiment_parameterList); + dimension = ListUtils.getListNodes(graph, parameterListResource).size(); + + initialize(); + } catch (DatabaseException e) { + + } + } + + public List next() { + ArrayList randoms = new ArrayList(); + for (int i = 0; i < dimension; ++i) + randoms.add(random.nextDouble()); + return randoms; + } + + public void initialize() { + random = new Random(this.seed); + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/RandomGenerator.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/RandomGenerator.java deleted file mode 100644 index d58578b8..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/RandomGenerator.java +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in - * Industry THTH ry. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.sysdyn.manager; - -import java.util.ArrayList; -import java.util.Random; - -/** - * Random generator that creates ArrayLists of random Doubles between 0 and 1. - * - * @author Tuomas Miettinen - */ - -public class RandomGenerator { - - private int seed; - private int dimension; - private Random random; - - public RandomGenerator(int seed, int dimension) { - this.dimension = dimension; - this.seed = seed; - random = new Random(this.seed); - } - - public ArrayList next() { - ArrayList randoms = new ArrayList(); - for (int i = 0; i < dimension; ++i) - randoms.add(random.nextDouble()); - return randoms; - } - - public void initialize() { - random = new Random(this.seed); - } - -} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynSensitivityAnalysisExperiment.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynSensitivityAnalysisExperiment.java index ea5f7990..c1b8ad50 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynSensitivityAnalysisExperiment.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynSensitivityAnalysisExperiment.java @@ -23,10 +23,13 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.common.request.WriteRequest; import org.simantics.db.common.utils.ListUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.request.Read; +import org.simantics.layer0.utils.direct.GraphUtils; import org.simantics.modelica.IModelicaMonitor; import org.simantics.modelica.ModelicaKeys; import org.simantics.modelica.ModelicaManager; @@ -36,6 +39,7 @@ import org.simantics.modelica.data.MatSimulationResult; import org.simantics.modelica.data.SimulationResult; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.adapter.SensitivityExperimentParameter; +import org.simantics.sysdyn.adapter.generator.IGenerator; /** * Sensitivity analysis experiment @@ -45,8 +49,8 @@ import org.simantics.sysdyn.adapter.SensitivityExperimentParameter; public class SysdynSensitivityAnalysisExperiment extends SysdynExperiment { private ArrayList results = null; - private int seed = 124; private int numberOfRuns = 0; + private IGenerator valueGenerator = null; public SysdynSensitivityAnalysisExperiment(Resource experiment, Resource model) { super(experiment, model); @@ -56,15 +60,21 @@ public class SysdynSensitivityAnalysisExperiment extends SysdynExperiment { ArrayList> parameterMaps = new ArrayList>(); int parametersSize = parameters.size(); - // Get seed and number of runs + // Get method and number of runs try { - session.syncRequest(new ReadRequest() { + session.syncRequest(new WriteRequest() { @Override - public void run(ReadGraph graph) throws DatabaseException { + public void perform(WriteGraph graph) throws DatabaseException { SysdynResource SR = SysdynResource.getInstance(graph); - seed = graph.getPossibleRelatedValue(experiment, SR.SensitivityAnalysisExperiment_randomSeed, Bindings.INTEGER); numberOfRuns = graph.getPossibleRelatedValue(experiment, SR.SensitivityAnalysisExperiment_numberOfValues, Bindings.INTEGER); + Resource methodResource = graph.getPossibleObject(experiment, SR.SensitivityAnalysisExperiment_method); + if (methodResource == null) { + methodResource = GraphUtils.create2(graph, SR.RandomGenerator); + graph.claim(experiment, SR.SensitivityAnalysisExperiment_method, methodResource); + } + valueGenerator = graph.adapt(methodResource, IGenerator.class); } + }); } catch (DatabaseException e) { e.printStackTrace(); @@ -73,12 +83,12 @@ public class SysdynSensitivityAnalysisExperiment extends SysdynExperiment { // Refresh rate for charts refreshRate = numberOfRuns / 20 + 1; - // Generate values for parameters (randomly) - RandomGenerator randomGenerator = new RandomGenerator(seed, parametersSize); + // Initialize the random generator + valueGenerator.initialize(); - // Determine the changed paramters and their values for each individual run + // Determine the changed parameters and their values for each individual run for (int i = 0; i < numberOfRuns; ++i) { - ArrayList randoms = randomGenerator.next();// multi-dimensional random + List randoms = valueGenerator.next();// multi-dimensional random HashMap parameterMap = new HashMap(parametersSize); for (int j = 0; j < parametersSize; ++j) { SensitivityExperimentParameter p = parameters.get(j);