Commit bd8d39a2 authored by Christoph Richter's avatar Christoph Richter
Browse files

Merge branch 'richter-dev' into 'master'

Richter dev

See merge request !1
parents 48d42bd3 26229f4d
Pipeline #67183 failed with stage
in 10 seconds
......@@ -9,7 +9,7 @@
<groupId>de.monticore.lang.monticar</groupId>
<artifactId>embedded-montiarc-math-opt-generator</artifactId>
<version>0.0.7-SNAPSHOT</version>
<version>0.0.8-SNAPSHOT</version>
<!-- == PROJECT DEPENDENCIES ============================================= -->
......@@ -22,11 +22,11 @@
<Common-MontiCar.version>0.0.14-SNAPSHOT</Common-MontiCar.version>
<Embedded-MontiArc.version>0.0.18-SNAPSHOT</Embedded-MontiArc.version>
<Embedded-MontiArc-Behaviour.version>0.0.14-SNAPSHOT</Embedded-MontiArc-Behaviour.version>
<Math.version>0.0.18-SNAPSHOT</Math.version>
<MathOpt.version>0.0.18-SNAPSHOT</MathOpt.version>
<Math.version>0.0.19-SNAPSHOT</Math.version>
<MathOpt.version>0.0.19-SNAPSHOT</MathOpt.version>
<Embedded-MontiArc-Math.version>0.0.19-SNAPSHOT</Embedded-MontiArc-Math.version>
<Embedded-MontiArc-Math-Opt.version>0.0.6-SNAPSHOT</Embedded-MontiArc-Math-Opt.version>
<Embedded-montiarc-math-generator.version>0.0.22-SNAPSHOT</Embedded-montiarc-math-generator.version>
<Embedded-MontiArc-Math-Opt.version>0.0.7-SNAPSHOT</Embedded-MontiArc-Math-Opt.version>
<Embedded-montiarc-math-generator.version>0.0.23-SNAPSHOT</Embedded-montiarc-math-generator.version>
<Embedded-montiarc-math-middleware-generator.version>0.0.4-SNAPSHOT</Embedded-montiarc-math-middleware-generator.version>
<!-- .. Libraries .................................................. -->
<guava.version>18.0</guava.version>
......
......@@ -14,6 +14,7 @@ public class GeneratorEMAMOpt2CMake extends CMakeGenerator {
super();
// set generator to EMAM2CppOpt
GeneratorEMAMOpt2CPP generatorEMAMOpt2CPP = new GeneratorEMAMOpt2CPP();
generatorEMAMOpt2CPP.setGenerateCMake(true);
// add implementation
add(generatorEMAMOpt2CPP, "cpp");
}
......
package de.monticore.lang.monticar.generator.cpp;
import de.monticore.lang.embeddedmontiarcmathopt._symboltable.EMAMOptSymbolTableHelper;
import de.monticore.lang.monticar.generator.cpp.converter.MathConverter;
import de.monticore.lang.monticar.generator.optimization.MathOptimizer;
import de.monticore.lang.monticar.generator.optimization.ThreadingOptimizer;
import de.monticore.lang.monticar.generator.order.nfp.TagBreakpointsTagSchema.TagBreakpointsTagSchema;
import de.monticore.lang.monticar.generator.order.nfp.TagDelayTagSchema.TagDelayTagSchema;
import de.monticore.lang.monticar.generator.order.nfp.TagExecutionOrderTagSchema.TagExecutionOrderTagSchema;
......@@ -31,6 +34,9 @@ public class EMAMOpt2CPPSymbolTableHelper extends EMAMOptSymbolTableHelper {
}
public TaggingResolver createSymTabAndTaggingResolver(String... modelPath) {
MathConverter.resetIDs();
ThreadingOptimizer.resetID();
MathOptimizer.resetIDs();
Scope scope = createSymTab(modelPath);
TaggingResolver tagging = new TaggingResolver(scope, Arrays.asList(modelPath));
TagMinMaxTagSchema.registerTagTypes(tagging);
......
......@@ -3,6 +3,8 @@ package de.monticore.lang.monticar.generator.cpp;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.cpp.converter.ExecuteMethodGenerator;
import de.monticore.lang.monticar.generator.cpp.converter.OptimizationSymbolHandler;
import de.monticore.lang.monticar.generator.cpp.optimizationSolver.solver.Solver;
import de.monticore.lang.monticar.generator.cpp.optimizationSolver.solver.SolverOptions;
import de.monticore.lang.monticar.generator.middleware.impls.GeneratorImpl;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
......@@ -21,6 +23,9 @@ public class GeneratorEMAMOpt2CPP extends GeneratorCPP implements GeneratorImpl
// fields
private OptimizationSymbolHandler executeMethodGeneratorOpt = new OptimizationSymbolHandler();
private MathOptFunctionFixer mathOptFunctionFixer = new MathOptFunctionFixer();
private Solver preferedSolver = Solver.none;
private boolean forceUsePreferredSolver = false;
private SolverOptions solverOptions = new SolverOptions();
public GeneratorEMAMOpt2CPP() {
super();
......@@ -57,4 +62,28 @@ public class GeneratorEMAMOpt2CPP extends GeneratorCPP implements GeneratorImpl
public MathOptFunctionFixer getMathOptFunctionFixer() {
return mathOptFunctionFixer;
}
public Solver getPreferedSolver() {
return preferedSolver;
}
public void setPreferedSolver(Solver preferedSolver) {
this.preferedSolver = preferedSolver;
}
public SolverOptions getSolverOptions() {
return solverOptions;
}
public void setSolverOptions(SolverOptions solverOptions) {
this.solverOptions = solverOptions;
}
public boolean forceUsePreferredSolver() {
return forceUsePreferredSolver;
}
public void setForceUsePreferredSolver(boolean forceUsePreferredSolver) {
this.forceUsePreferredSolver = forceUsePreferredSolver;
}
}
package de.monticore.lang.monticar.generator.cpp;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.cpp.optimizationSolver.solver.Solver;
import de.monticore.lang.monticar.generator.cpp.resolver.Resolver;
import de.monticore.lang.monticar.generator.order.simulator.AbstractSymtab;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import de.se_rwth.commons.logging.Log;
import org.apache.commons.cli.*;
......@@ -22,6 +22,13 @@ public class GeneratorEMAMOpt2CppCli {
public static final Option OPTION_FLAG_AUTOPILOT_ADAPTER = Option.builder().longOpt("flag-generate-autopilot-adapter").desc("optional flag indicating if autopilot adapter should be generated").hasArg(false).required(false).build();
public static final Option OPTION_FLAG_CHECK_MODEL_DIR = Option.builder().longOpt("check-model-dir").desc("optional flag indicating if model dir should be checked for creation of component and stream list").hasArg(false).required(false).build();
public static final Option OPTION_FLAG_SERVER_WRAPPER = Option.builder().longOpt("flag-generate-server-wrapper").desc("optional flag indicating if model should be wrapped into a server").hasArg(false).required(false).build();
public static final Option OPTION_FLAG_GENERATE_CMAKE = Option.builder().longOpt("flag-generate-cmake").desc("optional flag indicating if model should be additionally generate CMake files").hasArg(false).required(false).build();
public static final Option OPTION_PREFERED_SOLVER = Option.builder("s").longOpt("prefered-solver").desc("prefered solver (IPOPT, CPLEX)").hasArg(true).required(false).build();
public static final Option OPTION_IPOPT_PRINT_LEVEL = Option.builder().longOpt("print-level").desc("verbosity of IPOPT solver output from 0-12").hasArg(true).required(false).build();
public static final Option OPTION_IPOPT_MAX_ITER = Option.builder().longOpt("max-iter").desc("maximal number of iterations.").hasArg(true).required(false).build();
public static final Option OPTION_IPOPT_NUMERIC_TOL = Option.builder().longOpt("numeric-tol").desc("approximate accuracy in first order necessary conditions").hasArg(true).required(false).build();
public static final Option OPTION_IPOPT_POINT_PERMUTATION = Option.builder().longOpt("point-permutation-radius").desc("maximum amount of random permutation").hasArg(true).required(false).build();
private GeneratorEMAMOpt2CppCli() {
}
......@@ -47,6 +54,8 @@ public class GeneratorEMAMOpt2CppCli {
options.addOption(OPTION_FLAG_SERVER_WRAPPER);
options.addOption(OPTION_FLAG_ALGEBRAIC);
options.addOption(OPTION_FLAG_THREADING);
options.addOption(OPTION_FLAG_GENERATE_CMAKE);
options.addOption(OPTION_PREFERED_SOLVER);
return options;
}
......@@ -79,6 +88,8 @@ public class GeneratorEMAMOpt2CppCli {
g.setGenerateAutopilotAdapter(cliArgs.hasOption(OPTION_FLAG_AUTOPILOT_ADAPTER.getLongOpt()));
g.setUseAlgebraicOptimizations(cliArgs.hasOption(OPTION_FLAG_ALGEBRAIC.getLongOpt()));
g.setUseThreadingOptimization(cliArgs.hasOption(OPTION_FLAG_THREADING.getLongOpt()));
g.setGenerateCMake(cliArgs.hasOption(OPTION_FLAG_GENERATE_CMAKE.getLongOpt()));
setPreferedSolverFromArg(g, cliArgs.getOptionValue(OPTION_PREFERED_SOLVER.getOpt()));
try {
if (componentSymbol != null) {
......@@ -93,6 +104,18 @@ public class GeneratorEMAMOpt2CppCli {
}
private static void setPreferedSolverFromArg(GeneratorEMAMOpt2CPP g, String optionValue) {
if (optionValue != null) {
if (optionValue.contentEquals("IPOPT")) {
g.setPreferedSolver(Solver.Cplex);
} else if (optionValue.contentEquals("CPLEX")) {
g.setPreferedSolver(Solver.Cplex);
} else {
Log.warn(String.format("Solver %s not found. Using default solver instead."));
}
}
}
private static ExpandedComponentInstanceSymbol resolveSymbol(Resolver resolver, String rootModelName) {
ExpandedComponentInstanceSymbol componentSymbol = (ExpandedComponentInstanceSymbol) resolver.getExpandedComponentInstanceSymbol(rootModelName).orElse(null);
if (componentSymbol == null) {
......
......@@ -3,13 +3,14 @@ package de.monticore.lang.monticar.generator.cpp.converter;
import de.monticore.lang.math._symboltable.expression.MathValueSymbol;
import de.monticore.lang.math._symboltable.expression.MathValueType;
import de.monticore.lang.mathopt._symboltable.MathOptimizationStatementSymbol;
import de.monticore.lang.monticar.generator.BluePrint;
import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.monticar.generator.cpp.BluePrintCPP;
import de.monticore.lang.monticar.generator.cpp.GeneratorCPP;
import de.monticore.lang.monticar.generator.cpp.GeneratorEMAMOpt2CPP;
import de.monticore.lang.monticar.generator.cpp.optimizationSolver.problem.OptimizationProblemClassification;
import de.monticore.lang.monticar.generator.cpp.optimizationSolver.problem.Problem;
import de.monticore.lang.monticar.generator.cpp.optimizationSolver.solver.SolverGenerator;
import de.monticore.lang.monticar.generator.cpp.optimizationSolver.solver.SolverGeneratorFactory;
import de.monticore.lang.monticar.generator.cpp.optimizationSolver.solver.factory.SolverGeneratorFactory;
import de.monticore.lang.monticar.types2._ast.ASTElementType;
import de.se_rwth.commons.logging.Log;
......@@ -51,7 +52,8 @@ public class OptimizationSolverConverter {
Problem problemType = problemClassification.getProblemType();
// second step: decide for implementation
SolverGenerator solverGenerator = SolverGeneratorFactory.getInstance().createDefaultSolverForProblem(problemType);
GeneratorEMAMOpt2CPP gen = getInstance().getGenerator(bluePrint);
SolverGenerator solverGenerator = SolverGeneratorFactory.getInstance().createPreferredSolverForProblem(problemType, gen.getPreferedSolver(), gen.forceUsePreferredSolver());
// third step: generate code from solver generator
......@@ -63,12 +65,10 @@ public class OptimizationSolverConverter {
result += solverGenerator.generateSolverInstruction(problemType, auxiliaryFiles, bluePrint);
// also generate auxiliaryFiles
if (bluePrint.getGenerator() instanceof GeneratorCPP) {
try {
((GeneratorCPP) bluePrint.getGenerator()).saveFilesToDisk(auxiliaryFiles);
} catch (IOException e) {
Log.error(e.toString());
}
try {
getInstance().getGenerator(bluePrint).saveFilesToDisk(auxiliaryFiles);
} catch (IOException e) {
Log.error(e.toString());
}
// do not forget to add include strings
......@@ -82,7 +82,7 @@ public class OptimizationSolverConverter {
boolean defined = false;
if (optimizationVariable.getType() == null) {
defined = true;
} else if (bluePrint.getMathInformationRegister().getMathValueSymbol(optimizationVariable.getName()) != null) {
} else if (bluePrint.getMathInformationRegister().getMathValueSymbol(optimizationVariable.getName()) != null) {
defined = true;
}
return defined;
......@@ -110,4 +110,11 @@ public class OptimizationSolverConverter {
return result;
}
protected GeneratorEMAMOpt2CPP getGenerator(BluePrint bluePrint) {
GeneratorEMAMOpt2CPP g = null;
if (bluePrint.getGenerator() instanceof GeneratorEMAMOpt2CPP)
g = (GeneratorEMAMOpt2CPP) bluePrint.getGenerator();
return g;
}
}
......@@ -5,5 +5,5 @@ package de.monticore.lang.monticar.generator.cpp.optimizationSolver.problem;
*
* @author Christoph Richter
*/
public class ConvexProblem extends NLPProblem {
public class ConvexProblem extends QPProblem {
}
package de.monticore.lang.monticar.generator.cpp.optimizationSolver.problem;
/**
* Represents an abstract non linear optimization problem
*
* @author Christoph Richter
* Discontinious NLP problem
*/
public class GeneralNLPProblem extends Problem {
public class DNLPProblem extends Problem {
}
......@@ -5,5 +5,5 @@ package de.monticore.lang.monticar.generator.cpp.optimizationSolver.problem;
*
* @author Christoph Richter
*/
public class LPProblem {
public class LPProblem extends Problem {
}
package de.monticore.lang.monticar.generator.cpp.optimizationSolver.problem;
/**
* Mixed integer non linear programming
*/
public class MINLPProblem extends MIQPProblem {
}
package de.monticore.lang.monticar.generator.cpp.optimizationSolver.problem;
public class MIPProblem extends Problem {
}
package de.monticore.lang.monticar.generator.cpp.optimizationSolver.problem;
/**
* Mixed Integer Quadratic (constraint) Programming
*/
public class MIQPProblem extends MIPProblem{
}
......@@ -15,92 +15,7 @@ import java.util.Vector;
*
* @author Christoph Richter
*/
public class NLPProblem extends GeneralNLPProblem {
public class NLPProblem extends ConvexProblem {
/**
* Default value if no lower bound is set
*/
public final static String LOWER_BOUND_INF = "-1E+19";
/**
* Default value if no upper bound is set
*/
public final static String UPPER_BOUND_INF = "1E+19";
/**
* number of constraints in function g
*/
private int m;
/**
* function g: R^n -> R^m
*/
private Vector<String> constraintFunctions = new Vector<>();
/**
* lower bound of x
*/
private Vector<String> xL = new Vector<>();
/**
* upper bound of x
*/
private Vector<String> xU = new Vector<>();
/**
* lower bound of g
*/
private Vector<String> gL = new Vector<>();
/**
* upper bound of g
*/
private Vector<String> gU = new Vector<>();
// getter setter
public int getM() {
return m;
}
public void setM(int m) {
this.m = m;
}
public Vector<String> getConstraintFunctions() {
return constraintFunctions;
}
public void setConstraintFunctions(Vector<String> constraintFunctions) {
this.constraintFunctions = constraintFunctions;
}
public Vector<String> getxL() {
return xL;
}
public void setxL(Vector<String> xL) {
this.xL = xL;
}
public Vector<String> getxU() {
return xU;
}
public void setxU(Vector<String> xU) {
this.xU = xU;
}
public Vector<String> getgL() {
return gL;
}
public void setgL(Vector<String> gL) {
this.gL = gL;
}
public Vector<String> getgU() {
return gU;
}
public void setgU(Vector<String> gU) {
this.gU = gU;
}
}
package de.monticore.lang.monticar.generator.cpp.optimizationSolver.problem;
import de.monticore.lang.math._symboltable.expression.MathConditionalExpressionSymbol;
import de.monticore.lang.math._symboltable.expression.MathConditionalExpressionsSymbol;
import de.monticore.lang.math._symboltable.expression.MathExpressionSymbol;
import de.monticore.lang.math._symboltable.expression.MathValueType;
import de.monticore.lang.mathopt._symboltable.MathOptimizationStatementSymbol;
import de.se_rwth.commons.logging.Log;
import java.util.Arrays;
import java.util.List;
/**
* Analyses a MathOptimizationStatementSymbol for its problem class.
*
......@@ -30,18 +37,69 @@ public class OptimizationProblemClassification {
public static Problem classifySymbol(MathOptimizationStatementSymbol symbol) {
Problem result = null;
// TODO not only check for NLP
if (checkIfNLP(symbol)) {
result = SymbolToNLP.getInstance().getNLPFromSymbol(symbol);
if (checkIfLP(symbol)) {
if (isMixedInteger(symbol))
result = SymbolToProblemConverter.getInstance().getMIPFromSymbol(symbol);
else
result = SymbolToProblemConverter.getInstance().getLPFromSymbol(symbol);
} else if (checkIfQP(symbol)) {
if (isMixedInteger(symbol))
result = SymbolToProblemConverter.getInstance().getMIQPFromSymbol(symbol);
else
result = SymbolToProblemConverter.getInstance().getQPFromSymbol(symbol);
} else if (checkIfNLP(symbol)) {
result = SymbolToProblemConverter.getInstance().getNLPFromSymbol(symbol);
} else if (checkIfDNLP(symbol)) {
result = SymbolToProblemConverter.getInstance().getDNLPFromSymbol(symbol);
} else {
Log.error(String.format("Can not classify %s: %s", symbol.getClass().toString(), symbol.getFullName()));
}
return result;
}
protected static boolean checkIfNLP(MathOptimizationStatementSymbol symbol) {
// TODO really analyse problem type instead of just saying NLP
return true;
private static boolean checkIfQP(MathOptimizationStatementSymbol symbol) {
boolean result = false;
String optvar = symbol.getOptimizationVariable().getName();
String text = symbol.getTextualRepresentation();
if (!containsNonLinearFunctions(text)) {
}
return result;
}
private static boolean containsNonLinearFunctions(String text) {
List<String> nonLinFunctions = Arrays.asList("sin", "cos", "tan");
for (String fun : nonLinFunctions) {
if (text.contains(fun))
return true;
}
return false;
}
private static boolean checkIfLP(MathOptimizationStatementSymbol symbol) {
return false;
}
private static boolean checkIfNLP(MathOptimizationStatementSymbol symbol) {
// if it is not dnlp it must be nlp
return !checkIfDNLP(symbol);
}
private static boolean checkIfDNLP(MathOptimizationStatementSymbol symbol) {
boolean result = false;
// if objective function contains branches like if it must be discontius
MathExpressionSymbol objFunc = symbol.getObjectiveExpression();
if (objFunc instanceof MathConditionalExpressionsSymbol || objFunc instanceof MathConditionalExpressionSymbol)
result = true;
return result;
}
private static boolean isMixedInteger(MathOptimizationStatementSymbol symbol) {
boolean result = false;
MathValueType type = ProblemAssignmentHandler.getInstance().getVariableWithTypeInformations(symbol.getOptimizationVariable()).getType();
if (type.getType().isWholeNumber())
result = true;
return result;
}
// methods
......
......@@ -9,7 +9,7 @@ import java.util.Vector;
*
* @author Christoph Richter
*/
public abstract class Problem {
public class Problem {
/**
* identification number for problem
......@@ -120,4 +120,103 @@ public abstract class Problem {
public void setOptimizationProblemType(MathOptimizationType optimizationProblemType) {
this.optimizationProblemType = optimizationProblemType;
}
/**
* Default value if no lower bound is set
*/
public final static String LOWER_BOUND_INF = "-1E+19";
/**
* Default value if no upper bound is set
*/
public final static String UPPER_BOUND_INF = "1E+19";
/**
* number of constraints in function g
*/
private int m;
/**
* function g: R^n -> R^m
*/
private Vector<String> constraintFunctions = new Vector<>();
/**
* lower bound of x
*/
private Vector<String> xL = new Vector<>();
/**
* upper bound of x
*/
private Vector<String> xU = new Vector<>();
/**
* lower bound of g
*/
private Vector<String> gL = new Vector<>();
/**
* upper bound of g
*/
private Vector<String> gU = new Vector<>();
/**
* Additional constraints on optimization variable
*/
private Vector<String> xMatrixElementConstraints = new Vector<>();
// getter setter
public int getM() {
return m;
}
public void setM(int m) {
this.m = m;
}
public Vector<String> getConstraintFunctions() {
return constraintFunctions;
}
public void setConstraintFunctions(Vector<String> constraintFunctions) {
this.constraintFunctions = constraintFunctions;
}
public Vector<String> getxL() {
return xL;
}
public void setxL(Vector<String> xL) {
this.xL = xL;
}
public Vector<String> getxU() {
return xU;
}
public void setxU(Vector<String> xU) {
this.xU = xU;
}
public Vector<String> getgL() {
return gL;
}
public void setgL(Vector<String> gL) {
this.gL = gL;