diff --git a/gips.gttermination/.classpath b/gips.gttermination/.classpath new file mode 100644 index 0000000..8aced94 --- /dev/null +++ b/gips.gttermination/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/gips.gttermination/.project b/gips.gttermination/.project new file mode 100644 index 0000000..7f37720 --- /dev/null +++ b/gips.gttermination/.project @@ -0,0 +1,25 @@ + + + gips.gttermination + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + + org.emoflon.gips.gipsl.ui.gipsNature + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + org.eclipse.xtext.ui.shared.xtextNature + + diff --git a/gips.gttermination/.settings/org.eclipse.jdt.core.prefs b/gips.gttermination/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..d4540a5 --- /dev/null +++ b/gips.gttermination/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,10 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/gips.gttermination/META-INF/MANIFEST.MF b/gips.gttermination/META-INF/MANIFEST.MF new file mode 100644 index 0000000..ecb1573 --- /dev/null +++ b/gips.gttermination/META-INF/MANIFEST.MF @@ -0,0 +1,17 @@ +Manifest-Version: 1.0 +Automatic-Module-Name: gips.gttermination +Bundle-ManifestVersion: 2 +Bundle-Name: gips.gttermination +Bundle-Vendor: My Company +Bundle-Version: 1.0.0.qualifier +Export-Package: gips.gttermination.connector +Import-Package: test.suite.gips.utils +Bundle-SymbolicName: gips.gttermination; singleton:=true +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-17 +Require-Bundle: org.emoflon.ibex.common, + org.emoflon.ibex.gt, + org.emoflon.gips.core, + org.emoflon.ibex.gt.democles, + org.emoflon.ibex.gt.hipe, + gipsl.all.build.model diff --git a/gips.gttermination/build.properties b/gips.gttermination/build.properties new file mode 100644 index 0000000..14acfb7 --- /dev/null +++ b/gips.gttermination/build.properties @@ -0,0 +1,5 @@ +source.. = src/,\ + src-gen/ +bin.includes = META-INF/,\ + .,\ + plugin.xml diff --git a/gips.gttermination/src/gips/gttermination/Model.gipsl b/gips.gttermination/src/gips/gttermination/Model.gipsl new file mode 100644 index 0000000..1665c34 --- /dev/null +++ b/gips.gttermination/src/gips/gttermination/Model.gipsl @@ -0,0 +1,51 @@ +package "gips.gttermination" +import "platform:/resource/gipsl.all.build.model/model/Model.ecore" + +config { + solver := GLPK [home:="fu", license:="bar"]; + launchConfig := true [main := "TODO"]; + timeLimit := true [value := 10.0]; + randomSeed := true [value := 73]; + presolve := true; + debugOutput := true; +} + +rule mapVnode { + root: Root { + -containers -> substrateContainer + -containers -> virtualContainer + } + + substrateContainer: SubstrateContainer { + -substrateNodes -> snode + } + + virtualContainer: VirtualContainer { + -virtualNodes -> vnode + } + + snode: SubstrateResourceNode + + vnode: VirtualResourceNode { + ++ -host -> snode + } +} + +// +// GIPSL starts here! +// + +mapping n2n with mapVnode; + +// AND +constraint -> global { + mappings.n2n->count() == 1 +} + +objective nObj -> mapping::n2n { + 1 +} + +global objective : max { + nObj +} diff --git a/gips.gttermination/src/gips/gttermination/connector/GtTerminationConnector.java b/gips.gttermination/src/gips/gttermination/connector/GtTerminationConnector.java new file mode 100644 index 0000000..5870157 --- /dev/null +++ b/gips.gttermination/src/gips/gttermination/connector/GtTerminationConnector.java @@ -0,0 +1,31 @@ +package gips.gttermination.connector; + +import org.emoflon.gips.core.ilp.ILPSolverOutput; +import org.emoflon.ibex.gt.api.GraphTransformationAPI; + +import gips.gttermination.api.gips.GtterminationGipsAPI; +import test.suite.gips.utils.AConnector; +import test.suite.gips.utils.GipsTestUtils; +import test.suite.gips.utils.GlobalTestConfig; + +public class GtTerminationConnector extends AConnector { + + public GtTerminationConnector(final String modelPath) { + api = new GtterminationGipsAPI(); + api.init(GipsTestUtils.pathToAbsUri(modelPath)); + GlobalTestConfig.overrideSolver(api); + } + + @Override + public ILPSolverOutput run(final String outputPath) { + final ILPSolverOutput output = solve(); + ((GtterminationGipsAPI) api).getN2n().applyNonZeroMappings(); + save(outputPath); + return output; + } + + public GraphTransformationAPI getEmoflonApi() { + return api.getEMoflonAPI(); + } + +} diff --git a/test.suite.gips/META-INF/MANIFEST.MF b/test.suite.gips/META-INF/MANIFEST.MF index 23a6cd1..c6e0952 100644 --- a/test.suite.gips/META-INF/MANIFEST.MF +++ b/test.suite.gips/META-INF/MANIFEST.MF @@ -20,6 +20,7 @@ Require-Bundle: junit-jupiter-api;bundle-version="5.9.0", gips.nullmodel;bundle-version="0.0.1", gips.scheduling.taskmodel;bundle-version="0.0.1" Import-Package: gips.generic.scheduling.connector, + gips.gttermination.connector, gips.ilp.lpoutput.connector, gips.ilp.timeout.clsnotinmodel.connector, gips.ilp.timeout.connector, diff --git a/test.suite.gips/src/test/suite/gips/gttermination/GipsGtTerminationTest.java b/test.suite.gips/src/test/suite/gips/gttermination/GipsGtTerminationTest.java new file mode 100644 index 0000000..17d8f03 --- /dev/null +++ b/test.suite.gips/src/test/suite/gips/gttermination/GipsGtTerminationTest.java @@ -0,0 +1,70 @@ +package test.suite.gips.gttermination; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Collection; +import java.util.Iterator; + +import org.emoflon.gips.core.ilp.ILPSolverOutput; +import org.emoflon.gips.core.ilp.ILPSolverStatus; +import org.emoflon.ibex.common.operational.IMatch; +import org.junit.jupiter.api.Test; + +import gips.gttermination.connector.GtTerminationConnector; +import model.Root; +import test.suite.gipsl.all.build.AGipslAllBuildTest; + +public class GipsGtTerminationTest extends AGipslAllBuildTest { + + // Setup method/utilities + + public void callableSetUp() { + gen.persistModel(MODEL_PATH); + con = new GtTerminationConnector(MODEL_PATH); + } + + @Override + protected void terminateApi() { + // Disable the automatic termination of the GIPS API of the super class + } + + // Actual tests + + @Test + public void testGtTermination() { + gen.genSubstrateNode("s1", 2); + gen.genVirtualNode("v1", 1); + gen.genVirtualNode("v2", 1); + callableSetUp(); + + final ILPSolverOutput ret = con.run(OUTPUT_PATH); + assertEquals(ILPSolverStatus.OPTIMAL, ret.status()); + + // Get the interpreter and check number of matches before the termination + // (must be 2) + final var interpreter = ((GtTerminationConnector) con).getEmoflonApi().getInterpreter(); + final Iterator> it = interpreter.getMatches().values().iterator(); + assertTrue(it.hasNext()); + final var matches = it.next(); + assertEquals(2, matches.size()); + + // Terminate the GIPS API; this should also terminate the GT interpreter + ((GtTerminationConnector) con).terminate(); + + // Remove model elements such that all matches are invalid + var res = ((GtTerminationConnector) con).getEmoflonApi().getModel().getResources().get(0); + final Root root = (Root) res.getContents().get(0); + root.getContainers().clear(); + + // Update matches + interpreter.updateMatches(); + + // Now, **two** matches must still be present + final Iterator> it2 = interpreter.getMatches().values().iterator(); + assertTrue(it2.hasNext()); + final var matches2 = it2.next(); + assertEquals(2, matches2.size(), "GT engine termination failed."); + } + +}