/*
* SPDX-FileCopyrightText: 2021-2023 The Refinery Authors
*
* SPDX-License-Identifier: EPL-2.0
*/
package tools.refinery.store.dse;
import org.junit.jupiter.api.Test;
import tools.refinery.store.model.ModelStore;
import tools.refinery.store.query.ModelQueryAdapter;
import tools.refinery.store.query.dnf.Query;
import tools.refinery.store.dse.internal.TransformationRule;
import tools.refinery.store.dse.strategy.BestFirstStrategy;
import tools.refinery.store.dse.strategy.DepthFirstStrategy;
import tools.refinery.store.query.viatra.ViatraModelQueryAdapter;
import tools.refinery.store.query.view.AnySymbolView;
import tools.refinery.store.query.view.KeyOnlyView;
import tools.refinery.store.representation.Symbol;
import tools.refinery.store.tuple.Tuple;
import static org.junit.jupiter.api.Assertions.assertEquals;
class DesignSpaceExplorationTest {
// private static final Symbol namedElement = Symbol.of("NamedElement", 1);
// private static final Symbol attribute = Symbol.of("Attribute", 1);
// private static final Symbol method = Symbol.of("Method", 1);
// private static final Symbol dataDependency = Symbol.of("DataDependency", 2);
// private static final Symbol functionalDependency = Symbol.of("FunctionalDependency", 2);
private static final Symbol classModel = Symbol.of("ClassModel", 1);
private static final Symbol classElement = Symbol.of("ClassElement", 1);
private static final Symbol feature = Symbol.of("Feature", 1);
private static final Symbol isEncapsulatedBy = Symbol.of("IsEncapsulatedBy", 2);
private static final Symbol encapsulates = Symbol.of("Encapsulates", 2);
private static final Symbol features = Symbol.of("Features", 2);
private static final Symbol classes = Symbol.of("Classes", 2);
private static final AnySymbolView classModelView = new KeyOnlyView<>(classModel);
private static final AnySymbolView classElementView = new KeyOnlyView<>(classElement);
private static final AnySymbolView featureView = new KeyOnlyView<>(feature);
private static final AnySymbolView isEncapsulatedByView = new KeyOnlyView<>(isEncapsulatedBy);
private static final AnySymbolView encapsulatesView = new KeyOnlyView<>(encapsulates);
private static final AnySymbolView featuresView = new KeyOnlyView<>(features);
private static final AnySymbolView classesView = new KeyOnlyView<>(classes);
@Test
void createObjectTest() {
var store = ModelStore.builder()
.with(ViatraModelQueryAdapter.builder())
.with(DesignSpaceExplorationAdapter.builder()
.strategy(new DepthFirstStrategy().withDepthLimit(0)))
.build();
var model = store.createEmptyModel();
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
assertEquals(0, dseAdapter.getModelSize());
var newModel = dseAdapter.createObject();
var newModelId = newModel.get(0);
var newClass1 = dseAdapter.createObject();
var newClass1Id = newClass1.get(0);
var newClass2 = dseAdapter.createObject();
var newClass2Id = newClass2.get(0);
var newField = dseAdapter.createObject();
var newFieldId = newField.get(0);
assertEquals(0, newModelId);
assertEquals(1, newClass1Id);
assertEquals(2, newClass2Id);
assertEquals(3, newFieldId);
assertEquals(4, dseAdapter.getModelSize());
}
@Test
void deleteMiddleObjectTest() {
var store = ModelStore.builder()
.with(ViatraModelQueryAdapter.builder())
.with(DesignSpaceExplorationAdapter.builder()
.strategy(new DepthFirstStrategy()))
.build();
var model = store.createEmptyModel();
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
assertEquals(0, dseAdapter.getModelSize());
var newObject0 = dseAdapter.createObject();
var newObject0Id = newObject0.get(0);
var newObject1 = dseAdapter.createObject();
var newObject1Id = newObject1.get(0);
var newObject2 = dseAdapter.createObject();
var newObject2Id = newObject2.get(0);
var newObject3 = dseAdapter.createObject();
var newObject3Id = newObject3.get(0);
assertEquals(0, newObject0Id);
assertEquals(1, newObject1Id);
assertEquals(2, newObject2Id);
assertEquals(3, newObject3Id);
assertEquals(4, dseAdapter.getModelSize());
dseAdapter.deleteObject(newObject1);
assertEquals(4, dseAdapter.getModelSize());
var newObject4 = dseAdapter.createObject();
var newObject4Id = newObject4.get(0);
assertEquals(4, newObject4Id);
assertEquals(5, dseAdapter.getModelSize());
dseAdapter.deleteObject(newObject4);
assertEquals(5, dseAdapter.getModelSize());
}
@Test
void DFSTrivialTest() {
var store = ModelStore.builder()
.symbols(classModel)
.with(ViatraModelQueryAdapter.builder())
.with(DesignSpaceExplorationAdapter.builder()
.strategy(new DepthFirstStrategy().withDepthLimit(0)))
.build();
var model = store.createEmptyModel();
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var states = dseAdapter.explore();
assertEquals(1, states.size());
}
@Test
void DFSOneRuleTest() {
var createClassPrecondition = Query.of("CreateClassPrecondition",
(builder, model) -> builder.clause(
classModelView.call(model)
));
var createClassRule = new TransformationRule("CreateClass",
createClassPrecondition,
(model) -> {
var classesInterpretation = model.getInterpretation(classes);
var classElementInterpretation = model.getInterpretation(classElement);
return ((Tuple activation) -> {
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var modelElement = activation.get(0);
var newClassElement = dseAdapter.createObject();
var newClassElementId = newClassElement.get(0);
classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
classElementInterpretation.put(Tuple.of(newClassElementId), true);
});
});
var store = ModelStore.builder()
.symbols(classModel, classElement, classes)
.with(ViatraModelQueryAdapter.builder()
.queries(createClassPrecondition))
.with(DesignSpaceExplorationAdapter.builder()
.transformations(createClassRule)
.strategy(new DepthFirstStrategy().withDepthLimit(0)
))
.build();
var model = store.createEmptyModel();
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var queryEngine = model.getAdapter(ModelQueryAdapter.class);
var modelElementInterpretation = model.getInterpretation(classModel);
modelElementInterpretation.put(dseAdapter.createObject(), true);
queryEngine.flushChanges();
var states = dseAdapter.explore();
assertEquals(1, states.size());
}
@Test
void DFSContinueTest() {
var createClassPrecondition = Query.of("CreateClassPrecondition",
(builder, model) -> builder.clause(
classModelView.call(model)
));
var createClassRule = new TransformationRule("CreateClass",
createClassPrecondition,
(model) -> {
var classesInterpretation = model.getInterpretation(classes);
var classElementInterpretation = model.getInterpretation(classElement);
return ((Tuple activation) -> {
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var modelElement = activation.get(0);
var newClassElement = dseAdapter.createObject();
var newClassElementId = newClassElement.get(0);
classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
classElementInterpretation.put(Tuple.of(newClassElementId), true);
});
});
var store = ModelStore.builder()
.symbols(classModel, classElement, classes)
.with(ViatraModelQueryAdapter.builder()
.queries(createClassPrecondition))
.with(DesignSpaceExplorationAdapter.builder()
.transformations(createClassRule)
.strategy(new DepthFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled()
))
.build();
var model = store.createEmptyModel();
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var queryEngine = model.getAdapter(ModelQueryAdapter.class);
var modelElementInterpretation = model.getInterpretation(classModel);
modelElementInterpretation.put(dseAdapter.createObject(), true);
queryEngine.flushChanges();
var states = dseAdapter.explore();
assertEquals(5, states.size());
}
@Test
void DFSCompletenessTest() {
var createClassPrecondition = Query.of("CreateClassPrecondition",
(builder, model) -> builder.clause(
classModelView.call(model)
));
var createClassRule = new TransformationRule("CreateClass",
createClassPrecondition,
(model) -> {
var classesInterpretation = model.getInterpretation(classes);
var classElementInterpretation = model.getInterpretation(classElement);
return ((Tuple activation) -> {
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var modelElement = activation.get(0);
var newClassElement = dseAdapter.createObject();
var newClassElementId = newClassElement.get(0);
classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
classElementInterpretation.put(Tuple.of(newClassElementId), true);
});
});
var createFeaturePrecondition = Query.of("CreateFeaturePrecondition",
(builder, model) -> builder.clause(
classModelView.call(model)
));
var createFeatureRule = new TransformationRule("CreateFeature",
createFeaturePrecondition,
(model) -> {
var featuresInterpretation = model.getInterpretation(features);
var featureInterpretation = model.getInterpretation(feature);
return ((Tuple activation) -> {
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var modelElement = activation.get(0);
var newClassElement = dseAdapter.createObject();
var newClassElementId = newClassElement.get(0);
featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
featureInterpretation.put(Tuple.of(newClassElementId), true);
});
});
var store = ModelStore.builder()
.symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates)
.with(ViatraModelQueryAdapter.builder()
.queries(createClassPrecondition, createFeaturePrecondition))
.with(DesignSpaceExplorationAdapter.builder()
.transformations(createClassRule, createFeatureRule)
.strategy(new DepthFirstStrategy().withDepthLimit(10).continueIfHardObjectivesFulfilled()
))
.build();
var model = store.createEmptyModel();
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var queryEngine = model.getAdapter(ModelQueryAdapter.class);
var modelElementInterpretation = model.getInterpretation(classModel);
modelElementInterpretation.put(dseAdapter.createObject(), true);
queryEngine.flushChanges();
var states = dseAdapter.explore();
assertEquals(2047, states.size());
}
@Test
void DFSSolutionLimitTest() {
var createClassPrecondition = Query.of("CreateClassPrecondition",
(builder, model) -> builder.clause(
classModelView.call(model)
));
var createClassRule = new TransformationRule("CreateClass",
createClassPrecondition,
(model) -> {
var classesInterpretation = model.getInterpretation(classes);
var classElementInterpretation = model.getInterpretation(classElement);
return ((Tuple activation) -> {
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var modelElement = activation.get(0);
var newClassElement = dseAdapter.createObject();
var newClassElementId = newClassElement.get(0);
classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
classElementInterpretation.put(Tuple.of(newClassElementId), true);
});
});
var createFeaturePrecondition = Query.of("CreateFeaturePrecondition",
(builder, model) -> builder.clause(
classModelView.call(model)
));
var createFeatureRule = new TransformationRule("CreateFeature",
createFeaturePrecondition,
(model) -> {
var featuresInterpretation = model.getInterpretation(features);
var featureInterpretation = model.getInterpretation(feature);
return ((Tuple activation) -> {
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var modelElement = activation.get(0);
var newClassElement = dseAdapter.createObject();
var newClassElementId = newClassElement.get(0);
featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
featureInterpretation.put(Tuple.of(newClassElementId), true);
});
});
var store = ModelStore.builder()
.symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates)
.with(ViatraModelQueryAdapter.builder()
.queries(createClassPrecondition, createFeaturePrecondition))
.with(DesignSpaceExplorationAdapter.builder()
.transformations(createClassRule, createFeatureRule)
.strategy(new DepthFirstStrategy().withSolutionLimit(222)
.continueIfHardObjectivesFulfilled()
))
.build();
var model = store.createEmptyModel();
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var queryEngine = model.getAdapter(ModelQueryAdapter.class);
var modelElementInterpretation = model.getInterpretation(classModel);
modelElementInterpretation.put(dseAdapter.createObject(), true);
queryEngine.flushChanges();
var states = dseAdapter.explore();
assertEquals(222, states.size());
}
@Test
void BeFSTrivialTest() {
var store = ModelStore.builder()
.symbols(classModel)
.with(ViatraModelQueryAdapter.builder())
.with(DesignSpaceExplorationAdapter.builder()
.strategy(new BestFirstStrategy().withDepthLimit(0)))
.build();
var model = store.createEmptyModel();
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var states = dseAdapter.explore();
assertEquals(1, states.size());
}
@Test
void BeFSOneRuleTest() {
var createClassPrecondition = Query.of("CreateClassPrecondition",
(builder, model) -> builder.clause(
classModelView.call(model)
));
var createClassRule = new TransformationRule("CreateClass",
createClassPrecondition,
(model) -> {
var classesInterpretation = model.getInterpretation(classes);
var classElementInterpretation = model.getInterpretation(classElement);
return ((Tuple activation) -> {
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var modelElement = activation.get(0);
var newClassElement = dseAdapter.createObject();
var newClassElementId = newClassElement.get(0);
classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
classElementInterpretation.put(Tuple.of(newClassElementId), true);
});
});
var store = ModelStore.builder()
.symbols(classModel, classElement, classes)
.with(ViatraModelQueryAdapter.builder()
.queries(createClassPrecondition))
.with(DesignSpaceExplorationAdapter.builder()
.transformations(createClassRule)
.strategy(new BestFirstStrategy().withDepthLimit(4)
))
.build();
var model = store.createEmptyModel();
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var queryEngine = model.getAdapter(ModelQueryAdapter.class);
var modelElementInterpretation = model.getInterpretation(classModel);
modelElementInterpretation.put(dseAdapter.createObject(), true);
queryEngine.flushChanges();
var states = dseAdapter.explore();
assertEquals(1, states.size());
}
@Test
void BeFSContinueTest() {
var createClassPrecondition = Query.of("CreateClassPrecondition",
(builder, model) -> builder.clause(
classModelView.call(model)
));
var createClassRule = new TransformationRule("CreateClass",
createClassPrecondition,
(model) -> {
var classesInterpretation = model.getInterpretation(classes);
var classElementInterpretation = model.getInterpretation(classElement);
return ((Tuple activation) -> {
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var modelElement = activation.get(0);
var newClassElement = dseAdapter.createObject();
var newClassElementId = newClassElement.get(0);
classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
classElementInterpretation.put(Tuple.of(newClassElementId), true);
});
});
var store = ModelStore.builder()
.symbols(classModel, classElement, classes)
.with(ViatraModelQueryAdapter.builder()
.queries(createClassPrecondition))
.with(DesignSpaceExplorationAdapter.builder()
.transformations(createClassRule)
.strategy(new BestFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled()
))
.build();
var model = store.createEmptyModel();
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var queryEngine = model.getAdapter(ModelQueryAdapter.class);
var modelElementInterpretation = model.getInterpretation(classModel);
modelElementInterpretation.put(dseAdapter.createObject(), true);
queryEngine.flushChanges();
var states = dseAdapter.explore();
assertEquals(5, states.size());
}
@Test
void BeFSCompletenessTest() {
var createClassPrecondition = Query.of("CreateClassPrecondition",
(builder, model) -> builder.clause(
classModelView.call(model)
));
var createClassRule = new TransformationRule("CreateClass",
createClassPrecondition,
(model) -> {
var classesInterpretation = model.getInterpretation(classes);
var classElementInterpretation = model.getInterpretation(classElement);
return ((Tuple activation) -> {
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var modelElement = activation.get(0);
var newClassElement = dseAdapter.createObject();
var newClassElementId = newClassElement.get(0);
classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
classElementInterpretation.put(Tuple.of(newClassElementId), true);
});
});
var createFeaturePrecondition = Query.of("CreateFeaturePrecondition",
(builder, model) -> builder.clause(
classModelView.call(model)
));
var createFeatureRule = new TransformationRule("CreateFeature",
createFeaturePrecondition,
(model) -> {
var featuresInterpretation = model.getInterpretation(features);
var featureInterpretation = model.getInterpretation(feature);
return ((Tuple activation) -> {
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var modelElement = activation.get(0);
var newClassElement = dseAdapter.createObject();
var newClassElementId = newClassElement.get(0);
featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
featureInterpretation.put(Tuple.of(newClassElementId), true);
});
});
var store = ModelStore.builder()
.symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates)
.with(ViatraModelQueryAdapter.builder()
.queries(createClassPrecondition, createFeaturePrecondition))
.with(DesignSpaceExplorationAdapter.builder()
.transformations(createClassRule, createFeatureRule)
.strategy(new BestFirstStrategy().withDepthLimit(10).continueIfHardObjectivesFulfilled()
))
.build();
var model = store.createEmptyModel();
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var queryEngine = model.getAdapter(ModelQueryAdapter.class);
var modelElementInterpretation = model.getInterpretation(classModel);
modelElementInterpretation.put(dseAdapter.createObject(), true);
queryEngine.flushChanges();
var states = dseAdapter.explore();
assertEquals(2047, states.size());
}
@Test
void BeFSSolutionLimitTest() {
var createClassPrecondition = Query.of("CreateClassPrecondition",
(builder, model) -> builder.clause(
classModelView.call(model)
));
var createClassRule = new TransformationRule("CreateClass",
createClassPrecondition,
(model) -> {
var classesInterpretation = model.getInterpretation(classes);
var classElementInterpretation = model.getInterpretation(classElement);
return ((Tuple activation) -> {
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var modelElement = activation.get(0);
var newClassElement = dseAdapter.createObject();
var newClassElementId = newClassElement.get(0);
classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
classElementInterpretation.put(Tuple.of(newClassElementId), true);
});
});
var createFeaturePrecondition = Query.of("CreateFeaturePrecondition",
(builder, model) -> builder.clause(
classModelView.call(model)
));
var createFeatureRule = new TransformationRule("CreateFeature",
createFeaturePrecondition,
(model) -> {
var featuresInterpretation = model.getInterpretation(features);
var featureInterpretation = model.getInterpretation(feature);
return ((Tuple activation) -> {
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var modelElement = activation.get(0);
var newClassElement = dseAdapter.createObject();
var newClassElementId = newClassElement.get(0);
featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
featureInterpretation.put(Tuple.of(newClassElementId), true);
});
});
var store = ModelStore.builder()
.symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates)
.with(ViatraModelQueryAdapter.builder()
.queries(createClassPrecondition, createFeaturePrecondition))
.with(DesignSpaceExplorationAdapter.builder()
.transformations(createClassRule, createFeatureRule)
.strategy(new BestFirstStrategy().withSolutionLimit(222)
.continueIfHardObjectivesFulfilled()
))
.build();
var model = store.createEmptyModel();
var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
var queryEngine = model.getAdapter(ModelQueryAdapter.class);
var modelElementInterpretation = model.getInterpretation(classModel);
modelElementInterpretation.put(dseAdapter.createObject(), true);
queryEngine.flushChanges();
var states = dseAdapter.explore();
assertEquals(222, states.size());
}
}