Commit 8637c6c1 authored by Simon Barner's avatar Simon Barner
Browse files

Merge branch '4072' into 'master'

DSE: Add Synthesis Categories to Objectives

See merge request af3/af3!378
parents d3f79bff becc1a14
SMTExplorationTargetMigrator.java c5cf1a5f40ea0a3c1b0940bdbb57950584d44af6 GREEN
SMTExplorationTargetMigrator.java 0c7c94bae31eab03bdafe69d62606d7042845027 GREEN
......@@ -84,7 +84,8 @@ public class SMTExplorationTargetMigrator implements IMigrationProvider {
for(SMTObjective objective : getChildrenWithType(dse, SMTObjective.class)) {
ExplorationObjective<Double> newObjective = createExplorationObjective(Double.class,
createUserDefinedDimension(objective.getDimension()),
objective.getExpression(), objective.getName());
newHashSet(IDeploymentSynthesis.class), objective.getExpression(),
objective.getName());
replace(objective, newObjective);
oldNewMap.put(objective, newObjective);
......
ConstraintDefinitionUtils.java b33123ce448cb168ddc80457604a1743c198c57e GREEN
ConstraintDefinitionUtils.java 8f1d3cf09780365a639e2ffa12e5599bade0ed6a GREEN
SMTTransformationUtils.java 858765e735f7a8ea8b9e13e12f3c5fba93d36ed3 GREEN
......@@ -16,6 +16,7 @@
package org.fortiss.af3.exploration.smt.util;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.newHashSet;
import static java.math.BigDecimal.ZERO;
import static java.util.stream.Collectors.toSet;
import static org.fortiss.af3.exploration.smt.modeltransformation.EnergyConstraintDefinition.STD_FREQ;
......@@ -39,6 +40,7 @@ import static org.fortiss.tooling.base.utils.AnnotationUtils.hasAnnotation;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import org.eclipse.emf.common.util.EList;
......@@ -60,6 +62,8 @@ import org.fortiss.af3.exploration.dseml.model.function.Start;
import org.fortiss.af3.exploration.dseml.model.function.StronglyCausal;
import org.fortiss.af3.exploration.model.IExplorationObjective;
import org.fortiss.af3.exploration.model.project.RuleSet;
import org.fortiss.af3.exploration.model.synthesiscategory.IScheduleSynthesis;
import org.fortiss.af3.exploration.model.synthesiscategory.ISynthesisCategory;
import org.fortiss.af3.exploration.smt.model.dseml.DsemlFactory;
import org.fortiss.af3.exploration.smt.model.dseml.FrequencyAssigned;
import org.fortiss.af3.platform.model.ExecutionUnit;
......@@ -98,8 +102,11 @@ public class ConstraintDefinitionUtils {
List<IFunction> objectives = newArrayList(createMinimizeSumObjective(rsAllocs));
int i = 0;
for(IFunction o : objectives) {
IExplorationObjective<?> oSmt = createExplorationObjective(Double.class,
createTemporalDimension(), o, "Latency Minimization Objective " + i++);
@SuppressWarnings("unchecked") HashSet<Class<? extends ISynthesisCategory>> categories =
newHashSet(IScheduleSynthesis.class);
IExplorationObjective<?> oSmt =
createExplorationObjective(Double.class, createTemporalDimension(), categories,
o, "Latency Minimization Objective " + i++);
rs.getExplorationTargets().add(oSmt);
}
......
......@@ -33,6 +33,7 @@ import static test.org.fortiss.af3.exploration.smt.util.TestDeploymentUtils.getT
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.stream.Collectors;
import org.fortiss.af3.exploration.dseml.model.expression.IExpression;
......@@ -107,7 +108,6 @@ public class BusBandwidthOptimizationTest extends SMTTestBase {
}
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override
public Collection<IExplorationTarget<?>> createAdditionalConstraints() throws Exception {
Collection<IExplorationTarget<?>> explorationTargets = new ArrayList<>();
......@@ -118,23 +118,26 @@ public class BusBandwidthOptimizationTest extends SMTTestBase {
superSetMap.get(TransmissionUnit.class).getEntries().stream()
.filter(t -> t.getName().equals(transmissionUnitName)).findAny().get();
@SuppressWarnings("unchecked") HashSet<Class<? extends ISynthesisCategory>> categories =
newHashSet(IDeploymentSynthesis.class);
// Assign tasks to different ECUs
IExpression allocate0 = createAllocationPatternExpression(dse, true, asList(tasks[0]),
asList(executionUnits[0]));
IExpression allocate1 = createAllocationPatternExpression(dse, true, asList(tasks[1]),
asList(executionUnits[1]));
explorationTargets.add(createExplorationConstraint(Boolean.class,
createResourceDimension(), newHashSet(IDeploymentSynthesis.class), allocate0,
"Allocation: Task 0 - ECU 0", false));
explorationTargets.add(createExplorationConstraint(Boolean.class,
createResourceDimension(), newHashSet(IDeploymentSynthesis.class), allocate1,
"Allocation: Task 1 - ECU 1", false));
explorationTargets
.add(createExplorationConstraint(Boolean.class, createResourceDimension(),
categories, allocate0, "Allocation: Task 0 - ECU 0", false));
explorationTargets
.add(createExplorationConstraint(Boolean.class, createResourceDimension(),
categories, allocate1, "Allocation: Task 1 - ECU 1", false));
// Specify the transmission unit's weight
IExpression routeWeightExpression = createRouteWeightConstraintPatternExpression(dse);
explorationTargets.add(createExplorationConstraint(Boolean.class,
createResourceDimension(), newHashSet(IDeploymentSynthesis.class),
routeWeightExpression, "BandwidthWeight", false));
explorationTargets
.add(createExplorationConstraint(Boolean.class, createResourceDimension(),
categories, routeWeightExpression, "BandwidthWeight", false));
for(TransmissionUnit bus : dse.getCurrentStep().getSuperSetMap()
.get(TransmissionUnit.class).getEntries()) {
......@@ -142,9 +145,9 @@ public class BusBandwidthOptimizationTest extends SMTTestBase {
.getEntries()) {
IExpression routeUsesBusExpression =
createRouteUsesBusConstraintPatternExpression(dse, bus, route);
explorationTargets.add(createExplorationConstraint(Boolean.class,
createResourceDimension(), newHashSet(IDeploymentSynthesis.class),
routeUsesBusExpression, "RouteUsesBus", false));
explorationTargets.add(
createExplorationConstraint(Boolean.class, createResourceDimension(),
categories, routeUsesBusExpression, "RouteUsesBus", false));
}
}
......@@ -152,7 +155,7 @@ public class BusBandwidthOptimizationTest extends SMTTestBase {
IExpression bandwidthOptimization =
createBusWeightOptimizationPatternExpression(dse, testTransmissionUnit, true);
explorationTargets.add(createExplorationObjective(Double.class,
createResourceDimension(), bandwidthOptimization,
createResourceDimension(), categories, bandwidthOptimization,
"Bandwidth Optimization: " + transmissionUnitName));
return explorationTargets;
......
......@@ -27,6 +27,7 @@ import static test.org.fortiss.af3.exploration.smt.util.TestSchedulingUtils.getF
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import org.fortiss.af3.exploration.dseml.model.function.Minimize;
import org.fortiss.af3.exploration.model.IExplorationTarget;
......@@ -94,8 +95,10 @@ public class EnergyOptimizationTest extends SMTTestBase {
Minimize minConFunc =
createMinimizeConsumptionObjective(superSetMap.get(ResourceAllocation.class),
superSetMap.get(Task.class), superSetMap.get(ExecutionUnit.class));
@SuppressWarnings("unchecked") HashSet<Class<? extends ISynthesisCategory>> categories =
newHashSet(IScheduleSynthesis.class);
explorationTargets.add(createExplorationObjective(Double.class, createEnergyDimension(),
minConFunc, "Energy optimization objective"));
categories, minConFunc, "Energy optimization objective"));
return explorationTargets;
}
......
......@@ -29,12 +29,14 @@ import static test.org.fortiss.af3.exploration.smt.util.TestDeploymentUtils.getE
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.stream.Collectors;
import org.fortiss.af3.exploration.dseml.model.expression.IExpression;
import org.fortiss.af3.exploration.model.IExplorationTarget;
import org.fortiss.af3.exploration.model.SuperSetMap;
import org.fortiss.af3.exploration.model.solutions.ExplorationSolution;
import org.fortiss.af3.exploration.model.synthesiscategory.IDeploymentSynthesis;
import org.fortiss.af3.exploration.model.synthesiscategory.IScheduleSynthesis;
import org.fortiss.af3.exploration.model.synthesiscategory.ISynthesisCategory;
import org.fortiss.af3.exploration.smt.solver.DeploymentRun;
......@@ -113,9 +115,11 @@ public class HardwareOptimizationTest extends SMTTestBase {
IExpression ramMinimization = createHardwareOptimizationPatternExpression(dse, true, 0,
asList(tasks), asList(testExecutionUnit), RamSize.class);
@SuppressWarnings("unchecked") HashSet<Class<? extends ISynthesisCategory>> categories =
newHashSet(IDeploymentSynthesis.class);
explorationTargets
.add(createExplorationObjective(Double.class, createResourceDimension(),
ramMinimization, "RAM Minimization: " + executionUnitName));
categories, ramMinimization, "RAM Minimization: " + executionUnitName));
return explorationTargets;
}
......
......@@ -27,6 +27,7 @@ import static test.org.fortiss.af3.exploration.smt.util.TestSchedulingUtils.getF
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import org.fortiss.af3.exploration.dseml.model.function.Minimize;
import org.fortiss.af3.exploration.model.IExplorationTarget;
......@@ -92,8 +93,11 @@ public class LatencyOptimizationTest extends SMTTestBase {
SuperSetMap superSetMap = expSpec.getSearchSpace();
Minimize minRaSet =
createMinimizeSumObjective(superSetMap.get(ResourceAllocation.class));
explorationTargets.add(createExplorationObjective(Double.class,
createTemporalDimension(), minRaSet, "Latency optimization objective"));
@SuppressWarnings("unchecked") HashSet<Class<? extends ISynthesisCategory>> categories =
newHashSet(IScheduleSynthesis.class);
explorationTargets
.add(createExplorationObjective(Double.class, createTemporalDimension(),
categories, minRaSet, "Latency optimization objective"));
return explorationTargets;
}
......
BusBandwidthOptimizationPatternFXController.java 5dbbcafc47024082740945f87eae4bc88adcea63 GREEN
EnergyMinimizationPatternFXController.java b9141332a056e7cea3ce2e1cd7c77fdcf851e828 GREEN
HardwareOptimizationPatternFXController.java 4a2a05d9dab1e1ba7d81aa982049946c4bf79cae GREEN
LatencyMinimizationPatternFXController.java 322b476e7dad27160db54764f887c04406644b76 GREEN
BusBandwidthOptimizationPatternFXController.java d4aae6314b3b6b197bc18e2099c67d9b78c42484 GREEN
EnergyMinimizationPatternFXController.java 5da8dd709ec5053dd610384dce2a535a4781da53 GREEN
HardwareOptimizationPatternFXController.java c0592786a0b11be6ffc57d10c85eacbcc00064d4 GREEN
LatencyMinimizationPatternFXController.java bda2f2c4d4d1329fe93ffa1f0fc7741a64f584d5 GREEN
......@@ -29,6 +29,7 @@ import static org.fortiss.af3.exploration.util.PatternFactoryUtils.createRouteWe
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import org.fortiss.af3.exploration.dseml.model.expression.IExpression;
......@@ -38,6 +39,7 @@ import org.fortiss.af3.exploration.model.IExplorationObjective;
import org.fortiss.af3.exploration.model.IExplorationTarget;
import org.fortiss.af3.exploration.model.project.DSE;
import org.fortiss.af3.exploration.model.synthesiscategory.IDeploymentSynthesis;
import org.fortiss.af3.exploration.model.synthesiscategory.ISynthesisCategory;
import org.fortiss.af3.exploration.ui.perspective.service.IDSEPerspectiveManager;
import org.fortiss.af3.exploration.ui.perspective.targetdef.PatternFXControllerBase;
import org.fortiss.af3.platform.model.Route;
......@@ -86,7 +88,6 @@ public class BusBandwidthOptimizationPatternFXController extends PatternFXContro
}
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override
public IExplorationTarget<?> getExplorationTarget() {
DSE dse = IDSEPerspectiveManager.INSTANCE.getCurrentlySelectedDSE();
......@@ -97,24 +98,26 @@ public class BusBandwidthOptimizationPatternFXController extends PatternFXContro
Collection<IExplorationConstraint<?>> constraints = new ArrayList<>();
IExpression routeWeightExpression = createRouteWeightConstraintPatternExpression(dse);
@SuppressWarnings("unchecked") HashSet<Class<? extends ISynthesisCategory>> categories =
newHashSet(IDeploymentSynthesis.class);
constraints.add(createExplorationConstraint(Boolean.class, createResourceDimension(),
newHashSet(IDeploymentSynthesis.class), routeWeightExpression, "BandwidthWeight",
true));
categories, routeWeightExpression, "BandwidthWeight", true));
for(TransmissionUnit bus : dse.getCurrentStep().getSuperSetMap().get(TransmissionUnit.class)
.getEntries()) {
for(Route route : dse.getCurrentStep().getSuperSetMap().get(Route.class).getEntries()) {
IExpression routeUsesBusExpression =
createRouteUsesBusConstraintPatternExpression(dse, bus, route);
constraints.add(createExplorationConstraint(Boolean.class,
createResourceDimension(), newHashSet(IDeploymentSynthesis.class),
routeUsesBusExpression, "RouteUsesBus", true));
constraints
.add(createExplorationConstraint(Boolean.class, createResourceDimension(),
categories, routeUsesBusExpression, "RouteUsesBus", true));
}
}
IExpression expr = createBusWeightOptimizationPatternExpression(dse, selectedBus,
minButton.isSelected());
IExplorationObjective<Double> objective = createExplorationObjective(Double.class,
createUserDefinedDimension(getCategory()), expr, getExplorationTargetName());
IExplorationObjective<Double> objective =
createExplorationObjective(Double.class, createUserDefinedDimension(getCategory()),
categories, expr, getExplorationTargetName());
objective.getImplicitConstraints().addAll(constraints);
return objective;
......
......@@ -15,17 +15,21 @@
+--------------------------------------------------------------------------*/
package org.fortiss.af3.exploration.ui.perspective.targetdef.objective.pattern;
import static com.google.common.collect.Sets.newHashSet;
import static java.util.Collections.emptyList;
import static org.fortiss.af3.exploration.smt.modeltransformation.EnergyConstraintDefinition.createMinimizeConsumptionObjective;
import static org.fortiss.af3.exploration.util.ExplorationModelElementFactory.createExplorationObjective;
import static org.fortiss.af3.exploration.util.ExplorationModelElementFactory.createUserDefinedDimension;
import java.util.Collection;
import java.util.HashSet;
import org.fortiss.af3.exploration.dseml.model.expression.SuperSet;
import org.fortiss.af3.exploration.dseml.model.function.Minimize;
import org.fortiss.af3.exploration.model.ExplorationObjective;
import org.fortiss.af3.exploration.model.IExplorationTarget;
import org.fortiss.af3.exploration.model.synthesiscategory.IScheduleSynthesis;
import org.fortiss.af3.exploration.model.synthesiscategory.ISynthesisCategory;
import org.fortiss.af3.exploration.ui.perspective.targetdef.PatternFXControllerBase;
import org.fortiss.af3.platform.model.ExecutionUnit;
import org.fortiss.af3.schedule.model.ResourceAllocation;
......@@ -66,8 +70,11 @@ public class EnergyMinimizationPatternFXController extends PatternFXControllerBa
SuperSet<Task> taskSet = getSuperSet(Task.class).get();
SuperSet<ExecutionUnit> execUnitSet = getSuperSet(ExecutionUnit.class).get();
Minimize energyMin = createMinimizeConsumptionObjective(raSet, taskSet, execUnitSet);
ExplorationObjective<?> objective = createExplorationObjective(Double.class,
createUserDefinedDimension(getCategory()), energyMin, getExplorationTargetName());
@SuppressWarnings("unchecked") HashSet<Class<? extends ISynthesisCategory>> categories =
newHashSet(IScheduleSynthesis.class);
ExplorationObjective<?> objective =
createExplorationObjective(Double.class, createUserDefinedDimension(getCategory()),
categories, energyMin, getExplorationTargetName());
return objective;
}
......
......@@ -15,6 +15,7 @@
+--------------------------------------------------------------------------*/
package org.fortiss.af3.exploration.ui.perspective.targetdef.objective.pattern;
import static com.google.common.collect.Sets.newHashSet;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
import static org.fortiss.af3.exploration.ui.util.ExplorationUiUtils.createNameProvider;
......@@ -26,6 +27,7 @@ import static org.fortiss.tooling.common.util.LambdaUtils.getFirst;
import static org.fortiss.tooling.kernel.utils.UniqueIDUtils.prepareUniqueID;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import org.fortiss.af3.exploration.dseml.model.expression.IExpression;
......@@ -33,6 +35,8 @@ import org.fortiss.af3.exploration.dseml.model.expression.SuperSet;
import org.fortiss.af3.exploration.model.ExplorationObjective;
import org.fortiss.af3.exploration.model.IExplorationTarget;
import org.fortiss.af3.exploration.model.project.DSE;
import org.fortiss.af3.exploration.model.synthesiscategory.IDeploymentSynthesis;
import org.fortiss.af3.exploration.model.synthesiscategory.ISynthesisCategory;
import org.fortiss.af3.exploration.ui.perspective.service.IDSEPerspectiveManager;
import org.fortiss.af3.exploration.ui.perspective.targetdef.PatternFXControllerBase;
import org.fortiss.af3.platform.model.ExecutionUnit;
......@@ -126,8 +130,11 @@ public class HardwareOptimizationPatternFXController extends PatternFXController
IExpression expr = createHardwareOptimizationPatternExpression(dse, minButton.isSelected(),
operation, getSelectedTasks(), getSelectedExecutionUnits(), property);
ExplorationObjective<?> objective = createExplorationObjective(Double.class,
createUserDefinedDimension(getCategory()), expr, getExplorationTargetName());
@SuppressWarnings("unchecked") HashSet<Class<? extends ISynthesisCategory>> categories =
newHashSet(IDeploymentSynthesis.class);
ExplorationObjective<?> objective =
createExplorationObjective(Double.class, createUserDefinedDimension(getCategory()),
categories, expr, getExplorationTargetName());
prepareUniqueID(objective, dse);
return objective;
}
......
......@@ -15,17 +15,21 @@
+--------------------------------------------------------------------------*/
package org.fortiss.af3.exploration.ui.perspective.targetdef.objective.pattern;
import static com.google.common.collect.Sets.newHashSet;
import static java.util.Collections.emptyList;
import static org.fortiss.af3.exploration.smt.modeltransformation.EnergyConstraintDefinition.createMinimizeSumObjective;
import static org.fortiss.af3.exploration.util.ExplorationModelElementFactory.createExplorationObjective;
import static org.fortiss.af3.exploration.util.ExplorationModelElementFactory.createUserDefinedDimension;
import java.util.Collection;
import java.util.HashSet;
import org.fortiss.af3.exploration.dseml.model.expression.SuperSet;
import org.fortiss.af3.exploration.dseml.model.function.Minimize;
import org.fortiss.af3.exploration.model.ExplorationObjective;
import org.fortiss.af3.exploration.model.IExplorationTarget;
import org.fortiss.af3.exploration.model.synthesiscategory.IScheduleSynthesis;
import org.fortiss.af3.exploration.model.synthesiscategory.ISynthesisCategory;
import org.fortiss.af3.exploration.ui.perspective.targetdef.PatternFXControllerBase;
import org.fortiss.af3.schedule.model.ResourceAllocation;
......@@ -61,8 +65,11 @@ public class LatencyMinimizationPatternFXController extends PatternFXControllerB
public IExplorationTarget<?> getExplorationTarget() {
SuperSet<ResourceAllocation> raSet = getSuperSet(ResourceAllocation.class).get();
Minimize latencyMin = createMinimizeSumObjective(raSet);
ExplorationObjective<?> objective = createExplorationObjective(Double.class,
createUserDefinedDimension(getCategory()), latencyMin, getExplorationTargetName());
@SuppressWarnings("unchecked") HashSet<Class<? extends ISynthesisCategory>> categories =
newHashSet(IScheduleSynthesis.class);
ExplorationObjective<?> objective =
createExplorationObjective(Double.class, createUserDefinedDimension(getCategory()),
categories, latencyMin, getExplorationTargetName());
return objective;
}
......
......@@ -3,7 +3,7 @@ DSESolutionConversionUtils.java a6ccbba92864c653d1518a92455e87c17f7cc72b GREEN
DSMLModelElementFactory.java fa4a735ff40ab8f7d9898cecc0b04cfd8997572f GREEN
DSMLUtils.java 1113377031374cef7e29afcef458c4aeecad2b21 GREEN
ExplorationCLIUtils.java 32a4b2fc5f52e77c5e50b61912dcfe0f7f0c4cfd GREEN
ExplorationModelElementFactory.java 0f870e8ce015fb4719b5cb0c35a8699b4f261d80 GREEN
ExplorationModelElementFactory.java e2faa562a5896c0a26919e42cb9e1e42a3ff6fd5 GREEN
ExplorationReflectionUtils.java 62731e1cef32fe93f2c2017f93f5ba1f054d5197 GREEN
ExplorationScheduleUtils.java 95c9877ab2caa779a46fc20b8fdd63cd1cc392b1 GREEN
ExplorationTimingConstraintUtils.java 44f83e7630b52f8213b96f162bf94a2de009eb3e GREEN
......
......@@ -61,6 +61,19 @@ public class ExplorationModelElementFactory {
return ExplorationFactory.eINSTANCE.createExplorationSpecification();
}
/** Helper method to initialize an {@link IExplorationTarget}. */
private static <T> void initializeExplorationTarget(IExplorationTarget<T> explorationTarget,
Class<T> returnType, IProblemDimension probDim,
Collection<Class<? extends ISynthesisCategory>> synthCategory, IExpression expr,
String name) {
explorationTarget.setResultType(returnType);
explorationTarget.setExpression(expr);
explorationTarget.setProblemDimension(probDim);
explorationTarget.getSynthesisCategories().addAll(synthCategory);
explorationTarget.setName(name);
}
/**
* Creates an {@link ExplorationObjective} whose evaluation is of type {@code T}.
*
......@@ -68,6 +81,8 @@ public class ExplorationModelElementFactory {
* evaluation type.
* @param probDim
* dimension of the problem such as "Energy".
* @param synthCategory
* syntheses to which the {@link IExplorationTarget} applies.
* @param expr
* {@link IExpression} to evaluate.
* @param name
......@@ -75,13 +90,13 @@ public class ExplorationModelElementFactory {
* @return created constraint.
*/
public static <T> ExplorationObjective<T> createExplorationObjective(Class<T> returnType,
IProblemDimension probDim, IExpression expr, String name) {
IProblemDimension probDim,
Collection<Class<? extends ISynthesisCategory>> synthCategory, IExpression expr,
String name) {
ExplorationObjective<T> objective =
ExplorationFactory.eINSTANCE.createExplorationObjective();
objective.setResultType(returnType);
objective.setExpression(expr);
objective.setProblemDimension(probDim);
objective.setName(name);
initializeExplorationTarget(objective, returnType, probDim, synthCategory, expr, name);
return objective;
}
......@@ -109,11 +124,7 @@ public class ExplorationModelElementFactory {
String name, boolean isImplicit) {
ExplorationConstraint<T> constraint =
ExplorationFactory.eINSTANCE.createExplorationConstraint();
constraint.setResultType(returnType);
constraint.setExpression(expr);
constraint.setProblemDimension(probDim);
constraint.getSynthesisCategories().addAll(synthCategory);
constraint.setName(name);
initializeExplorationTarget(constraint, returnType, probDim, synthCategory, expr, name);
constraint.setImplicit(isImplicit);
return constraint;
}
......
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