From: jkauttio Date: Mon, 16 Jun 2014 13:02:51 +0000 (+0000) Subject: Add fixes for foo^-bar expresisons and value arrays into vensim import X-Git-Tag: 1.8.1~28 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=d8fe4f1ec481e4da21aee601bb60221cba85cdd5;p=simantics%2Fsysdyn.git Add fixes for foo^-bar expresisons and value arrays into vensim import refs #2924 git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@29619 ac1ea38d-2e2b-0410-8846-a27921b304fc --- diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlParser.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlParser.java index bd23088e..5fd35182 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlParser.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlParser.java @@ -89,7 +89,7 @@ public class MdlParser { Valve symbol = valve.getSymbol(); if (symbol != null) { valve.setModelObject(symbol); - model.addSymbol(symbol); + model.addVariable(symbol); } } @@ -97,7 +97,7 @@ public class MdlParser { Variable symbol = variable.getSymbol(); if (symbol != null) { variable.setModelObject(symbol); - model.addSymbol(symbol); + model.addVariable(symbol); } } @@ -108,10 +108,20 @@ public class MdlParser { for (Sketch sketch : mdl.getSketches()) { for (SketchVariable variable : sketch.getShadowVariables()) { Variable original = model.getVariable(variable.getName()); - Symbol symbol = original != null ? new Shadow(variable.getDimensions(), original) : variable.getSymbol(); - if (symbol != null) { + if (original != null) { + // create a shadow variable if the original variable exists + Shadow symbol = new Shadow(variable.getDimensions(), original); variable.setModelObject(symbol); - model.addSymbol(symbol); + model.addShadow(symbol); + } + else { + // create a new original variable instead of a shadow variable if + // the original variable does not exist + Variable symbol = variable.getSymbol(); + if (symbol != null) { + variable.setModelObject(symbol); + model.addVariable(symbol); + } } } @@ -127,22 +137,22 @@ public class MdlParser { // Set simulation parameters MdlVariable start = mdl.getVariable(PARAMETER_START); if (start != null && Pattern.matches(MdlUtil.DBL, start.getExpressionString())) - model.setStart(Double.parseDouble(start.getExpressionString())); + model.setStartTime(Double.parseDouble(start.getExpressionString())); MdlVariable stop = mdl.getVariable(PARAMETER_STOP); if (stop != null && Pattern.matches(MdlUtil.DBL, stop.getExpressionString())) - model.setStop(Double.parseDouble(stop.getExpressionString())); + model.setStopTime(Double.parseDouble(stop.getExpressionString())); MdlVariable step = mdl.getVariable(PARAMETER_STEP); if (step != null && Pattern.matches(MdlUtil.DBL, step.getExpressionString())) { - model.setStep(Double.parseDouble(step.getExpressionString())); + model.setTimeStep(Double.parseDouble(step.getExpressionString())); // TODO: for some reason sysdyn only accepts certain time units // so this most definitely does not work in all cases String unit = step.getUnit(); if (unit.contains("[")) { unit = unit.substring(0, unit.indexOf('[')).trim(); } - model.setUnit(unit.toLowerCase()); + model.setTimeUnit(unit.toLowerCase()); } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlUtil.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlUtil.java index 2b80696b..ceef8068 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlUtil.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlUtil.java @@ -1,6 +1,5 @@ package org.simantics.sysdyn.modelImport; -import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -59,8 +58,12 @@ public class MdlUtil { str = str.replaceAll(":AND:", " and "); str = str.replaceAll(":OR:", " or "); - // NOTE: this might not be correct - str = str.replaceAll("=", "=="); + // foo^-bar does not work in Modelica, it needs to be changed to foo^(-bar) + str = addParenthesesToExponents(str); + + // NOTE: something like this must be done to replace Vensim comparison + // "=" with Modelica comparison "==" but this solution breaks geq and leq + //str = str.replaceAll("=", "=="); return str; } @@ -93,7 +96,7 @@ public class MdlUtil { } else { // in all other cases, manipulate variable names slightly to - // make them conform to modelica syntax (the proper way to do + // make them conform to Modelica syntax (the proper way to do // this would be to simply quote problematic variable names // but quoted variable names are currently broken in sysdyn so // that is not an option) @@ -156,6 +159,29 @@ public class MdlUtil { return result.toString(); } + + private static String addParenthesesToExponents(String expression) { + if (!expression.contains("^")) { + return expression; + } + + StringBuilder result = new StringBuilder(); + int offset = 0; + + Matcher matcher = Pattern.compile("\\^\\s*-\\s*"+VARIABLE_EXPRESSION).matcher(expression); + while (matcher.find()) { + result.append(expression.substring(offset, matcher.start())); + + result.append("^(-").append(matcher.group(1)).append(")"); + + offset = matcher.end(); + } + if (offset < expression.length()) { + result.append(expression.substring(offset)); + } + + return result.toString(); + } public static String finalize(String expression, MdlModel mdl) { expression = expandIterations(expression, mdl); @@ -269,40 +295,6 @@ public class MdlUtil { return result.toString(); } - - public static String[] splitFunctionParameters(String str) { - ArrayList list = new ArrayList(); - - int i; - int last = 0; - int level = 0; - boolean comment = false; - boolean brackets = false; - - for (i = 0; i < str.length(); i++) { - char current = str.charAt(i); - if (current == '"') - // note that this does not currently support escaped quotation marks inside quoted variable names - comment = !comment; - else if (current == '[' && !comment) - brackets = true; - else if (current == ']' && !comment) - brackets = false; - else if (current == '(' && !comment && !brackets) - level++; - else if (current == ')' && !comment && !brackets) - level--; - else if (current == ',' && !comment && !brackets && level == 0) { - list.add(str.substring(last, i).trim()); - last = i + 1; - } - } - if (last < i) { - list.add(str.substring(last, i).trim()); - } - - return list.toArray(new String[list.size()]); - } public static double[] getSysdynDimensions(int x, int y, int width, int height) { return new double[] { diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/MdlVariable.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/MdlVariable.java index 6e45c926..ad63d003 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/MdlVariable.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/MdlVariable.java @@ -1,5 +1,6 @@ package org.simantics.sysdyn.modelImport.mdl; +import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -69,7 +70,12 @@ public class MdlVariable extends Declaration { } public Expression getExpression() { - return parseExpression(MdlUtil.finalize(expression, getMdl())); + if (expression == null) { + return null; + } + else { + return parseExpression(MdlUtil.finalize(expression, getMdl())); + } } protected static Expression parseExpression(String expression) { @@ -81,10 +87,10 @@ public class MdlVariable extends Declaration { return new NormalExpression(expression); } - String function = matcher.group(1); - String[] parameters = MdlUtil.splitFunctionParameters(matcher.group(2)); + String function = matcher.group(1).toUpperCase(); + String[] parameters = splitFunctionParameters(matcher.group(2)); - if (function.startsWith("INTEG")) { + if (function.equals("INTEG")) { // an integral expression if (parameters.length != 2) { System.err.println("malformed integral expression: "+expression); @@ -92,7 +98,16 @@ public class MdlVariable extends Declaration { } return new IntegralExpression(parameters[0], parameters[1]); } - else if (function.startsWith("DELAY N")) { + else if (function.equals("INITIAL")) { + // as we do not have a proper replacement for Vensim "initial" + // function in sysdyn, replace it with a stock with no flows + if (parameters.length != 1) { + System.err.println("malformed initial expression: "+expression); + return null; + } + return new IntegralExpression("0", parameters[0]); + } + else if (function.equals("DELAY N")) { // a delay expression if (parameters.length != 4) { System.err.println("malformed delay expression: "+expression); @@ -100,21 +115,35 @@ public class MdlVariable extends Declaration { } return new DelayExpression(parameters[0], parameters[1], parameters[2], Integer.parseInt(parameters[3])); } - else if (function.startsWith("SMOOTHI")) { + else if (function.equals("SMOOTH3I")) { + if (parameters.length != 3) { + System.err.println("malformed smoothi expression: "+expression); + } + // what is the correct degree for smooth? + return new DelayExpression(parameters[0], parameters[1], parameters[2], 3); + } + else if (function.equals("SMOOTH3")) { + if (parameters.length != 2) { + System.err.println("malformed smooth expression: "+expression); + } + // what is the correct degree and initial value for smooth? + return new DelayExpression(parameters[0], parameters[1], parameters[0], 3); + } + else if (function.equals("SMOOTHI")) { if (parameters.length != 3) { System.err.println("malformed smoothi expression: "+expression); } // what is the correct degree for smooth? return new DelayExpression(parameters[0], parameters[1], parameters[2], 1); } - else if (function.startsWith("SMOOTH")) { + else if (function.equals("SMOOTH")) { if (parameters.length != 2) { System.err.println("malformed smooth expression: "+expression); } // what is the correct degree and initial value for smooth? return new DelayExpression(parameters[0], parameters[1], parameters[0], 1); } - else if (function.startsWith("GAME")) { + else if (function.equals("GAME")) { // a game expression, currently treated as a normal expression if (parameters.length != 1) { System.err.println("malformed game expression: "+expression); @@ -152,4 +181,38 @@ public class MdlVariable extends Declaration { return null; } } + + private static String[] splitFunctionParameters(String str) { + ArrayList list = new ArrayList(); + + int i; + int last = 0; + int level = 0; + boolean comment = false; + boolean brackets = false; + + for (i = 0; i < str.length(); i++) { + char current = str.charAt(i); + if (current == '"') + // note that this does not currently support escaped quotation marks inside quoted variable names + comment = !comment; + else if (current == '[' && !comment) + brackets = true; + else if (current == ']' && !comment) + brackets = false; + else if (current == '(' && !comment && !brackets) + level++; + else if (current == ')' && !comment && !brackets) + level--; + else if (current == ',' && !comment && !brackets && level == 0) { + list.add(str.substring(last, i).trim()); + last = i + 1; + } + } + if (last < i) { + list.add(str.substring(last, i).trim()); + } + + return list.toArray(new String[list.size()]); + } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchVariable.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchVariable.java index 9bcbeba8..48c7ab88 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchVariable.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchVariable.java @@ -7,6 +7,7 @@ import org.simantics.sysdyn.modelImport.MdlUtil; import org.simantics.sysdyn.modelImport.model.Auxiliary; import org.simantics.sysdyn.modelImport.model.Variable; import org.simantics.sysdyn.modelImport.model.Stock; +import org.simantics.sysdyn.modelImport.model.expression.IntegralExpression; public class SketchVariable extends SketchElement { @@ -50,8 +51,9 @@ public class SketchVariable extends SketchElement { } Variable var; - if (variable.getExpressionString() != null && variable.getExpressionString().startsWith("INTEG")) + if ((variable.getExpression() instanceof IntegralExpression)) { var = new Stock(); + } else var = new Auxiliary(); var.setDimensions(getDimensions()); diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SubscriptVariable.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SubscriptVariable.java index 2bbe092b..ada64c8a 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SubscriptVariable.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SubscriptVariable.java @@ -104,10 +104,7 @@ public class SubscriptVariable extends MdlVariable { Subscript potential = getMdl().resolveSubscript(values); if (potential == null) { System.err.println("subscript indices could not be resolved "); - for (String value : values) { - System.err.println(" "+value); - } - System.err.println(); + return null; } enumerations.add(potential.getEnumeration()); } @@ -116,14 +113,29 @@ public class SubscriptVariable extends MdlVariable { // populate the created expression - // TODO: is this check correct? - if (next == null && enumerations.size() == 2) { - double[][] values = getPossibleValueArray(getExpressionString()); - if (values != null) { + // first check if the expression is just a (either one or two + // dimensional) list of values and just parse it if this is + // the case (should only happen if there is only one expression) + + if (next == null) { + // number(,number)* + if (enumerations.size() == 1 && + Pattern.matches(MdlUtil.DBL+"(,"+MdlUtil.DBL+")*", getExpressionString())) { + String[] values = getExpressionString().split(","); for (int i = 0; i < values.length; i++) { - for (int j = 0; j < values[i].length; j++) { - expr.addExpression( - new NormalExpression(Double.toString(values[i][j])), + expr.addExpression(new NormalExpression(values[i]), + enumerations.get(0).getValues().get(i)); + } + return expr; + } + // (number(,number)*;)* + else if (enumerations.size() == 2 && + Pattern.matches("("+MdlUtil.DBL+"(,"+MdlUtil.DBL+")*;)*", getExpressionString())) { + String[] rows = getExpressionString().split(";"); + for (int i = 0; i < rows.length; i++) { + String[] values = rows[i].split(","); + for (int j = 0; j < values.length; j++) { + expr.addExpression(new NormalExpression(values[j]), enumerations.get(0).getValues().get(i), enumerations.get(1).getValues().get(j)); } @@ -183,29 +195,6 @@ public class SubscriptVariable extends MdlVariable { } } - private static double[][] getPossibleValueArray(String expression) { - // (number(,number)*;)* - Matcher matcher = Pattern.compile( - "("+MdlUtil.DBL+"(,"+MdlUtil.DBL+")*;)*" - ).matcher(expression); - - if (!matcher.matches()) { - return null; - } - - String[] rows = expression.split(";"); - double[][] result = new double[rows.length][]; - for (int i = 0; i < rows.length; i++) { - String[] columns = rows[i].split(","); - result[i] = new double[columns.length]; - for (int j = 0; j < columns.length; j++) { - result[i][j] = Double.parseDouble(columns[j]); - } - } - - return result; - } - private static String removeComparisons(String expression, String[] subscripts, String[] values) { if (!expression.contains("=")) { diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Model.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Model.java index 61e663ea..14a82c80 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Model.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Model.java @@ -20,6 +20,7 @@ import java.util.Map; import org.simantics.databoard.Bindings; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; +import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.layer0.Layer0; @@ -60,39 +61,39 @@ public class Model implements IWriteableObject { connections = new ArrayList(); } - public double getStart() { + public double getStartTime() { return start; } - public void setStart(double start) { + public void setStartTime(double start) { this.start = start; } - public double getStop() { + public double getStopTime() { return stop; } - public void setStop(double stop) { + public void setStopTime(double stop) { this.stop = stop; } - public double getStep() { + public double getTimeStep() { return step; } - public void setStep(double step) { + public void setTimeStep(double step) { this.step = step; } - public String getUnit() { + public String getTimeUnit() { return unit; } - public void setUnit(String unit) { + public void setTimeUnit(String unit) { this.unit = unit; } - public void addSymbol(Variable variable) { + public void addVariable(Variable variable) { if (variables.get(variable.getName()) != null) { System.err.println("variable "+variable.getName()+" already defined"); return; @@ -111,7 +112,7 @@ public class Model implements IWriteableObject { return variables.values(); } - public void addSymbol(Shadow shadow) { + public void addShadow(Shadow shadow) { shadows.add(shadow); } @@ -165,7 +166,11 @@ public class Model implements IWriteableObject { SysdynResource sr = SysdynResource.getInstance(graph); model = ModelUtils.createModel(graph); - graph.claimLiteral(model, l0.HasLabel, name, Bindings.STRING); + + Resource container = graph.getSingleObject(model, l0.PartOf); + String freshName = NameUtils.findFreshName(graph, name, container, l0.ConsistsOf, "%s%d"); + graph.claimLiteral(model, l0.HasName, freshName, Bindings.STRING); + graph.claimLiteral(model, l0.HasLabel, freshName, Bindings.STRING); // TODO: this must be updated if/when simulation parameters are moved // from model to experiment