Adds first tiny working example

This commit is contained in:
Maximilian Kratz 2023-11-17 09:57:10 +01:00
parent 8524585745
commit 084689e119
3 changed files with 390 additions and 16 deletions

View file

@ -1,16 +1,16 @@
Manifest-Version: 1.0
Automatic-Module-Name: org.emoflon.gips.gipsl.examples.mdvne.seq
Bundle-ManifestVersion: 2
Bundle-Name: org.emoflon.gips.gipsl.examples.mdvne.seq
Bundle-Vendor: My Company
Bundle-Version: 1.0.0.qualifier
Bundle-SymbolicName: org.emoflon.gips.gipsl.examples.mdvne.seq; 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,
network.metrics
Manifest-Version: 1.0
Automatic-Module-Name: org.emoflon.gips.gipsl.examples.mdvne.seq
Bundle-ManifestVersion: 2
Bundle-Name: org.emoflon.gips.gipsl.examples.mdvne.seq
Bundle-Vendor: My Company
Bundle-Version: 1.0.0.qualifier
Export-Package: org.emoflon.gips.gipsl.examples.mdvne.seq
Bundle-SymbolicName: org.emoflon.gips.gipsl.examples.mdvne.seq; 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,
network.model

View file

@ -0,0 +1,118 @@
package org.emoflon.gips.gipsl.examples.mdvne.seq;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.emoflon.gips.core.ilp.ILPSolverOutput;
import org.emoflon.gips.gipsl.examples.mdvne.seq.api.gips.SeqGipsAPI;
/**
* Implementation adapter for GIPS and iflye. This is used to run the GIPS-based
* MdVNE adapter from the iflye framework. Basically, this is an external entry
* point to trigger the GIPS-based MdVNE implementation from other frameworks.
*
* @author Maximilian Kratz {@literal <maximilian.kratz@es.tu-darmstadt.de>}
*/
public class MdvneGipsIflyeAdapter {
/**
* MdVNE GIPS API object.
*/
static SeqGipsAPI api;
/**
* If false, the API must be initialized.
*/
static boolean init = false;
/**
* Executes the embedding GIPS-based VNE algorithm.
*
* @param model Resource set that contains the model (= the root node of the
* model).
* @return True if embedding was successful.
*/
public static boolean execute(final ResourceSet model) {
if (model == null) {
throw new IllegalArgumentException("Model was null.");
}
if (model.getResources() == null || model.getResources().isEmpty()) {
throw new IllegalArgumentException("Model resource set was null or empty.");
}
// Initialize the API, if necessary
if (!init) {
api = new SeqGipsAPI();
api.init(model);
init = true;
}
// Build the ILP problem (including updates)
api.buildILPProblem(true);
// Solve the ILP problem
final ILPSolverOutput output = api.solveILPProblem();
// TODO: Remove system outputs
System.out.println("=> GIPS iflye adapter: Solver status: " + output.status());
System.out.println("=> GIPS iflye adapter: Objective value: " + output.objectiveValue());
final var srv2srvMappings = api.getSrv2srv().getNonZeroVariableMappings();
final var srv2srvRule = api.getSrv2srv().getGTRule();
srv2srvMappings.forEach(m -> {
System.out.println("srv2srv: " + m.getName() + ": " + m.getFreeVariables().get("index").getValue());
// m.getFreeVariables().get(0);
srv2srvRule.apply(m.getMatch(), true);
});
final var sw2nodeMappings = api.getSw2node().getNonZeroVariableMappings();
final var sw2nodeRule = api.getSw2node().getGTRule();
sw2nodeMappings.forEach(m -> {
System.out.println("sw2node: " + m.getName() + ": " + m.getFreeVariables().get("index").getValue());
sw2nodeRule.apply(m.getMatch(), true);
});
final var l2sMappings = api.getL2s().getNonZeroVariableMappings();
final var l2sRule = api.getL2s().getGTRule();
l2sMappings.forEach(m -> {
System.out.println("l2s: " + m.getName() + ": " + m.getFreeVariables().get("index").getValue());
l2sRule.apply(m.getMatch(), true);
});
// // TODO: Print all variable values
// api.getSrv2srv().getNonZeroVariableMappings().forEach(c -> {
// // TODO: Fix print out
// System.out.println(c.getName() + ": " + c.getFreeVariableNames());
// });
//
// // TODO: This must be done in the order of the index variables
// // Apply all valid mappings
// api.getSrv2srv().applyNonZeroMappings();
// api.getSw2node().applyNonZeroMappings();
//// api.getL2p().applyNonZeroMappings();
// api.getL2s().applyNonZeroMappings();
//// api.getNet2net().applyNonZeroMappings();
// Terminate API
// api.terminate();
// TODO: Currently, this throws an Exception:
//
// java.lang.IllegalArgumentException: Cannot remove a consumer which was not
// registered before!
// at
// org.emoflon.ibex.gt.api.GraphTransformationPattern.unsubscribeAppearing(GraphTransformationPattern.java:310)
// at org.emoflon.gips.core.gt.GTMapper.terminate(GTMapper.java:69)
// at org.emoflon.gips.core.GipsEngine.lambda$1(GIPSEngine.java:71)
// at java.base/java.util.HashMap.forEach(HashMap.java:1421)
// at org.emoflon.gips.core.GipsEngine.terminate(GIPSEngine.java:71)
return output.solutionCount() > 0;
}
/**
* Resets the initialized state of the GIPS API.
*/
public static void resetInit() {
init = false;
}
}

View file

@ -10,3 +10,259 @@ config {
debugOutput := true;
tolerance := true [value := 0.00001];
}
// NACS
condition serverNotMapped = forbid serverIsMapped
pattern serverIsMapped {
host: SubstrateServer
virtualNode: VirtualServer {
-host -> host
}
}
condition switchNotMapped = forbid switchIsMapped
pattern switchIsMapped {
host: SubstrateNode
virtualSwitch: VirtualSwitch {
-host -> host
}
}
condition linkNotMapped = forbid linkIsMapped
pattern linkIsMapped {
host: SubstrateHostLink
virtualLink: VirtualLink {
-host -> host
}
}
condition networkNotMapped = forbid networkIsMapped && forbid networkIsMappedSrv
pattern networkIsMapped {
host: SubstrateNetwork
virtualNetwork: VirtualNetwork {
-host -> host
}
}
pattern networkIsMappedSrv {
host: SubstrateServer
virtualNetwork: VirtualNetwork {
-hostServer -> host
}
}
// Patterns for finding non embedded virtual elements
pattern vsrvNotMapped {
virtualServer: VirtualServer
}
when serverNotMapped
pattern vswNotMapped {
virtualSwitch: VirtualSwitch
}
when switchNotMapped
pattern vlNotMapped {
virtualLink: VirtualLink
}
when linkNotMapped
// Actual rules
rule serverMatchPositive {
root: Root {
-networks -> substrateNetwork
-networks -> virtualNetwork
}
substrateServer: SubstrateServer {
.residualCpu := substrateServer.residualCpu - virtualNode.cpu
.residualMemory := substrateServer.residualMemory - virtualNode.memory
.residualStorage := substrateServer.residualStorage - virtualNode.storage
}
virtualNode: VirtualServer {
++ -host -> substrateServer
}
substrateNetwork: SubstrateNetwork {
-nodes -> substrateServer
}
virtualNetwork: VirtualNetwork {
-nodes -> virtualNode
}
# virtualNode.cpu <= substrateServer.residualCpu
# virtualNode.memory <= substrateServer.residualMemory
# virtualNode.storage <= substrateServer.residualStorage
}
when serverNotMapped
rule switchNodeMatchPositive {
root: Root {
-networks -> substrateNetwork
-networks -> virtualNetwork
}
substrateNode: SubstrateNode
virtualSwitch : VirtualSwitch {
++ -host -> substrateNode
}
substrateNetwork: SubstrateNetwork {
-nodes -> substrateNode
}
virtualNetwork: VirtualNetwork {
-nodes -> virtualSwitch
}
}
when switchNotMapped
rule linkPathMatchPositive {
root: Root {
-networks -> substrateNetwork
-networks -> virtualNetwork
}
substratePath: SubstratePath {
.residualBandwidth := substratePath.residualBandwidth - virtualLink.bandwidth
// Update all substrate links
forEach links->l {
iterator::l.residualBandwidth := iterator::l.residualBandwidth - virtualLink.bandwidth
}
}
virtualLink: VirtualLink {
++ -host -> substratePath
}
substrateNetwork: SubstrateNetwork {
-paths -> substratePath
}
virtualNetwork: VirtualNetwork {
-links -> virtualLink
}
# virtualLink.bandwidth <= substratePath.residualBandwidth
// Explicitly exclude substrate paths with a residual bandwidth equals to 0
# substratePath.residualBandwidth > 0
}
when linkNotMapped
rule linkServerMatchPositive {
root: Root {
-networks -> substrateNetwork
-networks -> virtualNetwork
}
substrateServer: SubstrateServer
virtualLink: VirtualLink {
++ -host -> substrateServer
}
substrateNetwork: SubstrateNetwork {
-nodes -> substrateServer
}
virtualNetwork: VirtualNetwork {
-links -> virtualLink
}
}
when linkNotMapped
rule networkRule {
root: Root {
-networks -> substrateNetwork
-networks -> virtualNetwork
}
substrateNetwork: SubstrateNetwork
virtualNetwork: VirtualNetwork {
++ -host -> substrateNetwork
}
}
when networkNotMapped
//
// GIPSL starts here!
//
// Server 2 Server
mapping srv2srv with serverMatchPositive {
var index : EInt
};
constraint -> pattern::vsrvNotMapped {
mappings.srv2srv->filter(m | m.nodes().virtualNode == self.nodes().virtualServer)->sum(m | m.value()) == 1
}
constraint -> mapping::srv2srv {
self.value() >= 0 + 0.001 => self.variables().index >= 0 + 0.001
}
// Switch 2 Node
mapping sw2node with switchNodeMatchPositive{
var index : EInt
};
constraint -> pattern::vswNotMapped {
mappings.sw2node->filter(m | m.nodes().virtualSwitch == self.nodes().virtualSwitch)->sum(m | m.value()) == 1
}
constraint -> mapping::sw2node {
self.value() >= 0 + 0.001 => self.variables().index >= 0 + 0.001
}
// Link 2 Server
mapping l2s with linkServerMatchPositive {
var index : EInt
};
//constraint -> pattern::linkServerMatchPositive {
// (mappings.srv2srv->filter(mpp | mpp.nodes().virtualNode == self.nodes().virtualLink.source & mpp.nodes().substrateServer == self.nodes().substrateServer)->sum(m | m.value()) +
// mappings.sw2node->filter(mpp | mpp.nodes().virtualSwitch == self.nodes().virtualLink.source & mpp.nodes().substrateNode == self.nodes().substrateServer)->sum(m | m.value())) +
// (mappings.srv2srv->filter(mpp | mpp.nodes().virtualNode == self.nodes().virtualLink.target & mpp.nodes().substrateServer == self.nodes().substrateServer)->sum(m | m.value()) +
// mappings.sw2node->filter(mpp | mpp.nodes().virtualSwitch == self.nodes().virtualLink.target & mpp.nodes().substrateNode == self.nodes().substrateServer)->sum(m | m.value()))
// >= 2 * mappings.l2s->filter(mpp | mpp.nodes().substrateServer == self.nodes().substrateServer & mpp.nodes().virtualLink == self.nodes().virtualLink)->sum(m | m.value())
//}
constraint -> pattern::vlNotMapped {
mappings.l2s->filter(m | m.nodes().virtualLink == self.nodes().virtualLink)->sum(m | m.value()) == 1
}
constraint -> mapping::l2s {
self.value() >= 0 + 0.001 => self.variables().index >= 0 + 0.001
}
// Connect link to node mappings via the index variable
constraint -> pattern::linkServerMatchPositive {
mappings.l2s->filter(m | m.nodes().virtualLink == self.nodes().virtualLink & m.nodes().substrateServer == self.nodes().substrateServer)->sum(m | m.variables().index)
>=
mappings.srv2srv->filter(m | m.nodes().virtualNode == self.nodes().virtualLink.source)->sum(m | m.variables().index)
+ 0.001
&
mappings.l2s->filter(m | m.nodes().virtualLink == self.nodes().virtualLink & m.nodes().substrateServer == self.nodes().substrateServer)->sum(m | m.variables().index)
>=
mappings.sw2node->filter(m | m.nodes().virtualSwitch == self.nodes().virtualLink.target)->sum(m | m.variables().index)
+ 0.001
}
// TODO: Implement the same mechanism for link 2 path!
//// TODO: There must be no duplicate index variable value
//constraint -> mapping::srv2srv {
// mappings.srv2srv->filter(m | m.variables().index == self.variables().index)->count() == 1
//}