Commit 55921de6 authored by Christoph Richter's avatar Christoph Richter
Browse files

OptimizationProblemClassification: Support for loops in subject to conditions

parent 112f0189
package de.monticore.lang.monticar.generator.cpp.converter;
import de.monticore.lang.math.math._symboltable.MathForLoopHeadSymbol;
import de.monticore.lang.math.math._symboltable.expression.MathExpressionSymbol;
import de.monticore.lang.math.math._symboltable.matrix.MathMatrixExpressionSymbol;
import de.monticore.lang.math.math._symboltable.matrix.MathMatrixVectorExpressionSymbol;
import de.monticore.lang.monticar.generator.Variable;
import de.se_rwth.commons.logging.Log;
import java.util.List;
import java.util.Optional;
/**
* @author Sascha Schneiders
* @author Christoph Richter
*/
public class ForLoopHeadConverter {
public static String getForLoopHeadCode(MathForLoopHeadSymbol mathForLoopHeadSymbol, List<String> includeStrings) {
......@@ -37,4 +39,39 @@ public class ForLoopHeadConverter {
}
return result;
}
private static MathMatrixVectorExpressionSymbol getLoopMatrixVectorExpressionSymbol(MathForLoopHeadSymbol mathForLoopHeadSymbol) {
MathMatrixVectorExpressionSymbol result = null;
if (mathForLoopHeadSymbol.getMathExpression().isMatrixExpression()) {
MathMatrixExpressionSymbol mathMatrixExpressionSymbol = (MathMatrixExpressionSymbol) mathForLoopHeadSymbol.getMathExpression();
if (mathMatrixExpressionSymbol.isMatrixVectorExpression()) {
result = (MathMatrixVectorExpressionSymbol) mathMatrixExpressionSymbol;
}
}
return result;
}
public static Optional<MathExpressionSymbol> getForLoopStart(MathForLoopHeadSymbol mathForLoopHeadSymbol) {
Optional<MathExpressionSymbol> start = Optional.empty();
MathMatrixVectorExpressionSymbol loopExpr = getLoopMatrixVectorExpressionSymbol(mathForLoopHeadSymbol);
if (loopExpr != null)
start = Optional.ofNullable(loopExpr.getStart());
return start;
}
public static Optional<MathExpressionSymbol> getForLoopEnd(MathForLoopHeadSymbol mathForLoopHeadSymbol) {
Optional<MathExpressionSymbol> end = Optional.empty();
MathMatrixVectorExpressionSymbol loopExpr = getLoopMatrixVectorExpressionSymbol(mathForLoopHeadSymbol);
if (loopExpr != null)
end = Optional.ofNullable(loopExpr.getEnd());
return end;
}
public static Optional<MathExpressionSymbol> getForLoopStep(MathForLoopHeadSymbol mathForLoopHeadSymbol) {
Optional<MathExpressionSymbol> end = Optional.empty();
MathMatrixVectorExpressionSymbol loopExpr = getLoopMatrixVectorExpressionSymbol(mathForLoopHeadSymbol);
if (loopExpr != null)
end = loopExpr.getStep();
return end;
}
}
......@@ -2,12 +2,12 @@ package de.monticore.lang.monticar.generator.cpp.optimizationSolver.problem;
import de.monticore.lang.math.math._symboltable.MathOptimizationConditionSymbol;
import de.monticore.lang.math.math._symboltable.expression.*;
import de.monticore.lang.monticar.generator.cpp.converter.ExecuteMethodGenerator;
import de.monticore.lang.monticar.generator.cpp.converter.TypeConverter;
import de.monticore.lang.monticar.generator.cpp.converter.*;
import de.se_rwth.commons.logging.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Vector;
import static de.monticore.lang.monticar.generator.cpp.optimizationSolver.problem.NLPProblem.LOWER_BOUND_INF;
......@@ -122,16 +122,14 @@ public class OptimizationProblemClassification {
setBoundsOnXFromTypeDeclaration(symbol.getOptimizationVariable().getType(), xL, xU, nlp.getN());
for (MathOptimizationConditionSymbol constraint : symbol.getSubjectToExpressions()) {
for (MathExpressionSymbol constraint : symbol.getSubjectToExpressions()) {
// find function
MathExpressionSymbol expr = constraint.getBoundedExpression();
String[] bounds = getBoundsFromConstraint(nlp, constraint);
if (isConstraintOnOptVar(nlp, expr)) {
mergeBoundsInX(nlp, xL, xU, expr, bounds[0], bounds[1]);
} else {
g.add(ExecuteMethodGenerator.generateExecuteCode(expr, new ArrayList<String>()));
gL.add(bounds[0]);
gU.add(bounds[1]);
if (constraint instanceof MathOptimizationConditionSymbol) {
MathOptimizationConditionSymbol singleConstraint = (MathOptimizationConditionSymbol) constraint;
addSingleConstraint(nlp, g, gL, gU, xL, xU, singleConstraint);
} else if (constraint instanceof MathForLoopExpressionSymbol) {
MathForLoopExpressionSymbol loopConstraint = (MathForLoopExpressionSymbol) constraint;
addLoopConstraints(nlp, g, gL, gU, xL, xU, loopConstraint);
}
}
nlp.setM(g.size());
......@@ -142,6 +140,67 @@ public class OptimizationProblemClassification {
nlp.setxU(xU);
}
private static void addLoopConstraints(NLPProblem nlp, Vector<String> g, Vector<String> gL, Vector<String> gU, Vector<String> xL, Vector<String> xU, MathForLoopExpressionSymbol loopConstraint) {
Optional<MathExpressionSymbol> startExpr = ForLoopHeadConverter.getForLoopStart(loopConstraint.getForLoopHead());
Optional<MathExpressionSymbol> endExpr = ForLoopHeadConverter.getForLoopEnd(loopConstraint.getForLoopHead());
Optional<MathExpressionSymbol> stepExpr = ForLoopHeadConverter.getForLoopStep(loopConstraint.getForLoopHead());
if (startExpr.isPresent() && endExpr.isPresent()) {
Optional<Double> startValue = ComponentConverter.currentBluePrint.getMathInformationRegister().tryGetDoubleValue(startExpr.get());
Optional<Double> endValue = ComponentConverter.currentBluePrint.getMathInformationRegister().tryGetDoubleValue(endExpr.get());
if (startValue.isPresent() && endValue.isPresent()) {
double loopStart = startValue.get();
double loopEnd = endValue.get();
double loopStep = 1;
if (stepExpr.isPresent()) {
Optional<Double> stepValue = ComponentConverter.currentBluePrint.getMathInformationRegister().tryGetDoubleValue(stepExpr.get());
if (stepValue.isPresent())
loopStep = stepValue.get();
else
errorMessageForLoopConstraint(loopConstraint);
}
if (MathConverter.curBackend.usesZeroBasedIndexing()) {
loopStart--;
loopEnd--;
}
for (double i = loopStart; i <= loopEnd; i += loopStep) {
for (MathExpressionSymbol constraint : loopConstraint.getForLoopBody()) {
if (constraint instanceof MathOptimizationConditionSymbol) {
addSingleConstraint(nlp, g, gL, gU, xL, xU, (MathOptimizationConditionSymbol) constraint);
if (!isConstraintOnOptVar(nlp, constraint)) {
g.set(g.size() - 1, replaceLoopVariable(g.lastElement(), loopConstraint.getForLoopHead().getNameLoopVariable(), Double.toString(i)));
}
}
}
}
} else {
errorMessageForLoopConstraint(loopConstraint);
}
} else {
errorMessageForLoopConstraint(loopConstraint);
}
}
private static String replaceLoopVariable(String expr, String loopVar, String replacement) {
expr = expr.replaceAll("[()+\\-\\*/\\^\\']", " $0 ");
return expr.replaceAll(" " + loopVar + " ", " " + replacement + " ");
}
private static void errorMessageForLoopConstraint(MathForLoopExpressionSymbol loopExpressionSymbol) {
Log.error(String.format("Cannot resolve value of \"%s\"", loopExpressionSymbol.getForLoopHead().getTextualRepresentation()), loopExpressionSymbol.getForLoopHead().getSourcePosition());
}
private static void addSingleConstraint(NLPProblem nlp, Vector<String> g, Vector<String> gL, Vector<String> gU, Vector<String> xL, Vector<String> xU, MathOptimizationConditionSymbol singleConstraint) {
MathExpressionSymbol expr = singleConstraint.getBoundedExpression();
String[] bounds = getBoundsFromConstraint(nlp, singleConstraint);
if (isConstraintOnOptVar(nlp, expr)) {
mergeBoundsInX(nlp, xL, xU, expr, bounds[0], bounds[1]);
} else {
g.add(ExecuteMethodGenerator.generateExecuteCode(expr, new ArrayList<String>()));
gL.add(bounds[0]);
gU.add(bounds[1]);
}
}
private static MathNumberExpressionSymbol getNumber(MathExpressionSymbol symbol) {
MathNumberExpressionSymbol numberExpr = null;
if (symbol.isValueExpression()) {
......
......@@ -371,7 +371,7 @@ public class IpoptViewModel extends ViewModelBase {
for (Variable v : bluePrint.getMathInformationRegister().getVariables()) {
String name = v.getNameTargetLanguageFormat();
String type = v.getVariableType().getTypeNameTargetLanguage();
if ((!name.contentEquals(optimizationVariableName)) && (!name.contentEquals(objectiveVariableName))) {
if ((!name.contentEquals(optimizationVariableName)) && (!name.contentEquals(objectiveVariableName)) && (!v.isForLoopVariable())) {
knownVariables.add(name);
knownVariablesWithType.add(String.format("%s %s", type, name));
}
......
package de.monticore.lang.monticar.generator.optimization;
import de.monticore.lang.math.math._symboltable.expression.MathExpressionSymbol;
import de.monticore.lang.math.math._symboltable.expression.MathNumberExpressionSymbol;
import de.monticore.lang.math.math._symboltable.expression.MathValueExpressionSymbol;
import de.monticore.lang.math.math._symboltable.expression.MathValueSymbol;
import de.monticore.lang.math.math._symboltable.matrix.MathMatrixAccessOperatorSymbol;
import de.monticore.lang.math.math._symboltable.matrix.MathMatrixAccessSymbol;
......@@ -13,6 +15,7 @@ import de.se_rwth.commons.logging.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* This class stores information of already encountered math information
......@@ -178,4 +181,19 @@ public class MathInformationRegister {
}*/
return v.getNameTargetLanguageFormat();
}
public Optional<Double> tryGetDoubleValue(MathExpressionSymbol symbol) {
Optional<Double> result = Optional.empty();
if (symbol.isValueExpression()) {
if (((MathValueExpressionSymbol) symbol).isNumberExpression()) {
// is number
MathNumberExpressionSymbol numberSymbol = (MathNumberExpressionSymbol) symbol;
result = Optional.of(numberSymbol.getValue().getRealNumber().doubleValue());
}
else {
// TODO resolve variable
}
}
return result;
}
}
......@@ -91,6 +91,19 @@ public class MathOptimizationSolverTest extends AbstractSymtabTest {
// testFilesAreEqual(files, restPath);
}
/**
* test loops in conditions
*/
@Test
public void testForLoopConditions() throws IOException {
List<File> files = doGenerateOptimizationModel("forLoopConditionsTest");
// TODO: create reference solution
// String restPath = "testMath/optimizationSolver/";
// testFilesAreEqual(files, restPath);
}
/**
* Model predicive control
* Kindematic bicyle model
......
package test.math.optimization;
component ForLoopConditionsTest{
implementation Math{
minimize(Q^{3} x)
Q y = x(1) * x(1) + x(2) * x(2) + x(3) * x(3);
subject to
for i = 1:3
x(i) >= 0;
0 <= 2 * x(i) <= 2;
end
end
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment