From 6b751d1c3cf6294f589364acc1b8fe0f2d113bf4 Mon Sep 17 00:00:00 2001 From: 20001LastOrder Date: Mon, 27 May 2019 15:50:05 -0400 Subject: add project for metric calculator --- .../.classpath | 8 ++ .../.gitignore | 5 + .../.project | 34 +++++++ .../.settings/org.eclipse.jdt.core.prefs | 7 ++ .../Inputs/.gitignore | 4 + .../META-INF/MANIFEST.MF | 18 ++++ .../build.properties | 4 + .../realistic/metrics/calculator/app/Main.xtend | 72 ++++++++++++++ .../app/PartialInterpretationMetric.xtend | 61 ++++++++++++ .../metrics/calculator/graph/EMFGraph.xtend | 101 +++++++++++++++++++ .../realistic/metrics/calculator/graph/Graph.xtend | 41 ++++++++ .../metrics/calculator/graph/GraphStatistic.xtend | 107 +++++++++++++++++++++ .../graph/PartialInterpretationGraph.xtend | 73 ++++++++++++++ .../metrics/calculator/input/GraphReader.xtend | 81 ++++++++++++++++ .../input/PartialInterpretationReader.xtend | 7 ++ .../metrics/calculator/metrics/Metric.xtend | 7 ++ .../MultiplexParticipationCoefficientMetric.xtend | 65 +++++++++++++ .../calculator/metrics/NodeActivityMetric.xtend | 37 +++++++ .../calculator/metrics/OutDegreeMetric.xtend | 38 ++++++++ .../metrics/calculator/output/CsvFileWriter.xtend | 37 +++++++ 20 files changed, 807 insertions(+) create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.classpath create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.gitignore create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.project create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.settings/org.eclipse.jdt.core.prefs create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/Inputs/.gitignore create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/META-INF/MANIFEST.MF create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/build.properties create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/Main.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/PartialInterpretationMetric.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/EMFGraph.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/Graph.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/GraphStatistic.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/PartialInterpretationGraph.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/GraphReader.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/PartialInterpretationReader.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/Metric.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/MultiplexParticipationCoefficientMetric.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/NodeActivityMetric.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/OutDegreeMetric.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/output/CsvFileWriter.xtend (limited to 'Metrics') diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.classpath b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.classpath new file mode 100644 index 00000000..428337e5 --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.gitignore b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.gitignore new file mode 100644 index 00000000..b75ad9db --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.gitignore @@ -0,0 +1,5 @@ +/bin/ +bin/ +testInput/ +testOutput/ +xtend-gen/ \ No newline at end of file diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.project b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.project new file mode 100644 index 00000000..5154dea0 --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.project @@ -0,0 +1,34 @@ + + + ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator + + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.eclipse.xtext.ui.shared.xtextNature + + diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.settings/org.eclipse.jdt.core.prefs b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..0c68a61d --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/Inputs/.gitignore b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/Inputs/.gitignore new file mode 100644 index 00000000..17126b28 --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/Inputs/.gitignore @@ -0,0 +1,4 @@ +# ignore everything in this folder except for this folder it self + +* +!.gitignore \ No newline at end of file diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/META-INF/MANIFEST.MF b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/META-INF/MANIFEST.MF new file mode 100644 index 00000000..da19e07c --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/META-INF/MANIFEST.MF @@ -0,0 +1,18 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Graph_metrics_calculation +Bundle-SymbolicName: ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator +Bundle-Version: 1.0.0.qualifier +Automatic-Module-Name: graph_metrics_calculation +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: com.google.guava, + org.eclipse.xtext.xbase.lib, + org.eclipse.xtend.lib, + org.eclipse.xtend.lib.macro, + org.eclipse.emf.ecore;bundle-version="2.17.0", + org.eclipse.emf.ecore.xmi;bundle-version="2.15.0", + hu.bme.mit.inf.dslreasoner.viatra2logic;bundle-version="1.0.0", + hu.bme.mit.inf.dslreasoner.domains.yakindu.sgraph;bundle-version="1.0.0", + hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage;bundle-version="1.0.0", + org.eclipse.viatra.dse;bundle-version="0.21.2" +Export-Package: ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/build.properties b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/build.properties new file mode 100644 index 00000000..34d2e4d2 --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/Main.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/Main.xtend new file mode 100644 index 00000000..2e793b23 --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/Main.xtend @@ -0,0 +1,72 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app + +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.EMFGraph +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.input.GraphReader +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.output.CsvFileWriter +import hu.bme.mit.inf.dslreasoner.domains.yakindu.sgraph.yakindumm.impl.YakindummPackageImpl +import java.util.ArrayList + +//import yakindumm2.impl.Yakindumm2PackageImpl + +class Main { + static class RWInformation{ + public var String inputFolder; + public var String outputFolder; + public var int numRuns; + + new(String inputFolder, String outputFolder, int numRuns){ + this.inputFolder = inputFolder; + this.outputFolder = outputFolder; + this.numRuns = numRuns; + } + } + + def static void main(String[] args){ + //init model + YakindummPackageImpl.eINSTANCE.eClass; +// Yakindumm2PackageImpl.eINSTANCE.eClass; + val infos = initData(); + + println("Start Reading Models..."); + var reader = new GraphReader(YakindummPackageImpl.eINSTANCE); + for(info : infos){ + calculateAllModels(info.inputFolder, info.outputFolder,info.numRuns, reader); + } + + //human input has different package declaration +// reader = new GraphReader(Yakindumm2PackageImpl.eINSTANCE); + val human = new RWInformation("inputs/humanInput/", "../plot/statistics/humanOutput/", 1); + calculateAllModels(human.inputFolder, human.outputFolder,human.numRuns, reader); + + + println("finished"); + } + + static def initData(){ + val infos = new ArrayList(); + infos.add(new RWInformation("inputs/alloyInput/models/", "../plot/statistics/alloyOutput/", 20)); + infos.add(new RWInformation("inputs/randomInput/models/", "../plot/statistics/randomOutput/", 20)); + infos.add(new RWInformation("inputs/viatraInput30/", "../plot/statistics/viatraOutput30/", 20)); + infos.add(new RWInformation("inputs/viatraInput100/", "../plot/statistics/viatraOutput100/", 10)); + return infos; + } + + static def calculateAllModels(String inputFolder, String outputFolder, int numRuns, GraphReader reader){ + for(var i = 1; i <= numRuns; i++){ + val models = new ArrayList(); + models.addAll(reader.readModels(inputFolder + "run" + i)); + for(model : models){ + calculateAndOutputMetrics(model, YakindummPackageImpl.eNAME, outputFolder+model.name+"_run_"+i+".csv"); + } + } + println("output results Ended for: " + outputFolder); + + + } + + static def calculateAndOutputMetrics(EMFGraph model, String metaModel, String fileName){ + //println("evaluating for " + model.name); + model.metaModel = metaModel; + CsvFileWriter.write(model.evaluateAllMetrics(), fileName); + } +} \ No newline at end of file diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/PartialInterpretationMetric.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/PartialInterpretationMetric.xtend new file mode 100644 index 00000000..5f958cfa --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/PartialInterpretationMetric.xtend @@ -0,0 +1,61 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app + +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.PartialInterpretationGraph +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.output.CsvFileWriter +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation +import java.io.File +import java.io.FileNotFoundException +import java.io.PrintWriter +import java.util.ArrayList +import java.util.List +import org.eclipse.emf.ecore.util.EcoreUtil +import org.eclipse.viatra.dse.api.Solution + +class PartialInterpretationMetric { + var static state = 0; + def static void calculateMetric(PartialInterpretation partial, String path, int id, String currentStateId){ + val metrics = new ArrayList(); + metrics.add(new OutDegreeMetric()); + metrics.add(new NodeActivityMetric()); + metrics.add(new MultiplexParticipationCoefficientMetric()); + + new File(path).mkdir(); + val filename = path + "/state_"+state+".csv"; + state++; + val metricCalculator = new PartialInterpretationGraph(partial, metrics, currentStateId); + + CsvFileWriter.write(metricCalculator.evaluateAllMetrics(), filename); + } + + def static void outputTrajectories(PartialInterpretation empty, List solutions){ + + for(solution : solutions){ + val emptySolutionCopy = EcoreUtil.copy(empty) + val trajectory = solution.shortestTrajectory; + trajectory.modelWithEditingDomain = emptySolutionCopy + val stateCodes = newArrayList() + + while(trajectory.doNextTransformation){ + println(trajectory.stateCoder.createStateCode) + stateCodes.add(trajectory.stateCoder.createStateCode.toString) + } + + try{ + val path = "debug/metric/trajectories/trajectory"+trajectory.stateCoder.createStateCode.toString+".csv" + val PrintWriter writer = new PrintWriter(new File(path)) + val output = new StringBuilder + for(stateCode : stateCodes){ + output.append(stateCode+'\n') + } + writer.write(output.toString()) + writer.close() + }catch(FileNotFoundException e) { + e.printStackTrace() + } + } + } +} \ No newline at end of file diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/EMFGraph.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/EMFGraph.xtend new file mode 100644 index 00000000..b20ffa01 --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/EMFGraph.xtend @@ -0,0 +1,101 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph + +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric +import java.util.ArrayList +import java.util.List +import org.eclipse.emf.common.util.EList +import org.eclipse.emf.ecore.EObject +import org.eclipse.emf.ecore.EReference + +class EMFGraph extends Graph{ + + def void init (EObject root, List metrics, String name, List referenceTypes){ + val otherContents = root.eAllContents.toList(); + otherContents.add(root); + init(otherContents, metrics, name, referenceTypes); + } + + /** + * init the graph with all nodes and reference types in the meta model + * @param objects: objects in the instance model (exclude root) + * @param metrics: metrics to be evaluated + * @param name: name of the instance model + * @param ReferenceTypes: reference types defined in the meta model + */ + def void init(List objects, List metrics, String name, List referenceTypes){ + objects.forEach[it| + statistic.addNode(it); + ] + + referenceTypes.forEach[it| + statistic.addType(it); + ]; + + objects.forEach[source| + source.eClass.EAllReferences.forEach[r| + //add the type first (if it is not added already) + //many references + if(r.isMany){ + source.getNeighbours(r).forEach[target| + addEdge(source, target, r); + ] + }else{ + //single references + val target = source.eGet(r) as EObject; + addEdge(source, target, r); + } + ] + ] + + this.metrics = metrics; + this.name = name; + } + + /** + * Set basic information for the output + */ + override setBasicInformation(ArrayList> output){ + val metaInfo = new ArrayList(); + metaInfo.add(META_MODEL_HEADER); + metaInfo.add(this.metaModel); + + val edgeInfo = new ArrayList(); + edgeInfo.add(NUM_EDGE_TYPE_HEADER); + edgeInfo.add(this.statistic.allTypes.size()+""); + + val nodeInfo = new ArrayList(); + nodeInfo.add(NUM_NODE_HEADER); + nodeInfo.add(this.statistic.allNodes.size()+""); + + output.add(metaInfo); + output.add(edgeInfo); + output.add(nodeInfo); + } + + def EList getNeighbours(EObject o, EReference r){ + return (o.eGet(r, true) as EList); + } + + def addEdge(EObject source, EObject target, EReference r){ + if(target !== null && r !== null){ + statistic.addEdge(source, target, r.name); + } + } + + override GraphStatistic getStatistic(){ + return this.statistic; + } + + override String getName(){ + return this.name; + } + + def void setMetaModel(String model){ + this.metaModel = model; + } + + def String getMetaModel(){ + return this.metaModel; + } + +} \ No newline at end of file diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/Graph.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/Graph.xtend new file mode 100644 index 00000000..6d65367f --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/Graph.xtend @@ -0,0 +1,41 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph + +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric +import java.util.ArrayList +import java.util.List + +abstract class Graph { + + protected static val String META_MODEL_HEADER = "Meta Mode" + protected static val String NUM_NODE_HEADER = "Number Of Nodes"; + protected static val String NUM_EDGE_TYPE_HEADER = "Number of Edge types"; + protected static val String STATE_ID_HEADER = "State Id"; + + protected val statistic = new GraphStatistic(); + protected var List metrics; + protected var String name = ""; + protected var String metaModel = ""; + + /** + * evaluate all metrics for this model + * return the result as a two dimentional list + */ + def ArrayList> evaluateAllMetrics(){ + val result = new ArrayList>(); + setBasicInformation(result); + + for(metric : this.metrics){ + val datas = metric.evaluate(this.statistic); + for(row : datas){ + result.add(new ArrayList(row)); + } + } + return result; + } + + def void setBasicInformation(ArrayList> result); + + def GraphStatistic getStatistic(); + + def String getName(); +} \ No newline at end of file diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/GraphStatistic.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/GraphStatistic.xtend new file mode 100644 index 00000000..7ed58094 --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/GraphStatistic.xtend @@ -0,0 +1,107 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph + +import com.google.common.collect.ArrayListMultimap +import com.google.common.collect.Multimap +import java.util.HashMap +import java.util.HashSet +import java.util.List +import org.eclipse.emf.ecore.EObject + +class GraphStatistic { + val incomingEdges = new HashMap>; + val outcomingEdges = new HashMap>; + + val edgeTypes = new HashSet(); + val nodes = new HashSet(); + + /** + * Add an edge type to to the graph + * @param type: type to add + */ + def void addType(String type){ + if(edgeTypes.contains(type)){ + return; + } + edgeTypes.add(type); + incomingEdges.put(type, ArrayListMultimap.create()); + outcomingEdges.put(type, ArrayListMultimap.create()); + } + + /** + * Add a node to he graph + * @param node: node to add + */ + def void addNode(EObject n){ + if(nodes.contains(n)){ + return; + } + + nodes.add(n); + } + + /** + * Add an edge to the graph + * @param source: source node + * @param target: target node + * @param type: type of the reference + */ + def void addEdge(EObject source, EObject target, String type){ + outcomingEdges.get(type).put(source, target); + incomingEdges.get(type).put(target, source); + } + + /** + * calculate the out degree for an object + */ + def int outDegree(EObject o){ + var count = 0; + + for (String type : edgeTypes){ + count += outcomingEdges.get(type).get(o).size(); + } + return count; + } + + /** + * calculate the in degree of an object + */ + def int inDegree(EObject o){ + var count = 0; + + for (String type : edgeTypes){ + count += incomingEdges.get(type).get(o).size(); + } + return count; + } + + /** + * calculate the dimentional degree of a node + */ + def int dimentionalDegree(EObject o, String type){ + return incomingEdges.get(type).get(o).size() + outcomingEdges.get(type).get(o).size(); + } + + /** + * calculate the number of edge types for a given degree. + */ + def int numOfEdgeTypes(EObject o){ + var count = 0; + + for(String type : edgeTypes){ + if(dimentionalDegree(o, type) > 0){ + count++; + } + } + + return count; + } + + def List getAllTypes(){ + return edgeTypes.toList(); + } + + def List getAllNodes(){ + return nodes.toList(); + } +} + diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/PartialInterpretationGraph.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/PartialInterpretationGraph.xtend new file mode 100644 index 00000000..074a75da --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/PartialInterpretationGraph.xtend @@ -0,0 +1,73 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph + +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BinaryElementRelationLink +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.BooleanElementImpl +import java.util.ArrayList +import java.util.List + +class PartialInterpretationGraph extends Graph{ + var lastStateId=""; + + new(PartialInterpretation partial, List metrics, String name){ + partial.problem.relations.forEach[ + this.statistic.addType(it.name); + ] + // add all elements + val elements = getElements(partial); + for(element : elements){ + statistic.addNode(element) + } + + for(relationInterpretation : partial.partialrelationinterpretation) { + val type = relationInterpretation.interpretationOf.name + + for(edge : relationInterpretation.relationlinks.filter(BinaryElementRelationLink)){ + statistic.addEdge(edge.param1, edge.param2, type); + } + } + + this.name = name; + this.metrics = metrics; + } + + /** + * Set basic information for the output + */ + override setBasicInformation(ArrayList> output){ + val metaInfo = new ArrayList(); + metaInfo.add(META_MODEL_HEADER); + metaInfo.add(this.metaModel); + + val edgeInfo = new ArrayList(); + edgeInfo.add(NUM_EDGE_TYPE_HEADER); + edgeInfo.add(this.statistic.allTypes.size()+""); + + val nodeInfo = new ArrayList(); + nodeInfo.add(NUM_NODE_HEADER); + nodeInfo.add(this.statistic.allNodes.size()+""); + + val stateInfo = new ArrayList(); + stateInfo.add(STATE_ID_HEADER); + stateInfo.add(this.name); + + output.add(metaInfo); + output.add(edgeInfo); + output.add(nodeInfo); + output.add(stateInfo); + } + + private def getElements(PartialInterpretation partial){ + return partial.newElements.filter[!(it instanceof BooleanElementImpl)] + partial.problem.elements; + } + + override getStatistic() { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override getName() { + return name; + } + +} \ No newline at end of file diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/GraphReader.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/GraphReader.xtend new file mode 100644 index 00000000..56bf95a3 --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/GraphReader.xtend @@ -0,0 +1,81 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.input + +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.EMFGraph +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric +import java.io.File +import java.io.FileNotFoundException +import java.util.ArrayList +import java.util.List +import org.eclipse.emf.common.util.URI +import org.eclipse.emf.ecore.EObject +import org.eclipse.emf.ecore.EPackage +import org.eclipse.emf.ecore.EReference +import org.eclipse.emf.ecore.resource.Resource +import org.eclipse.emf.ecore.resource.ResourceSet +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl +import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl + +class GraphReader{ + val ResourceSet resSet = new ResourceSetImpl(); + val referenceTypes = new ArrayList(); + + new(EPackage metaModel) { + Resource.Factory.Registry.INSTANCE.extensionToFactoryMap.put("*",new XMIResourceFactoryImpl) + + //find all reference types in the meta model + metaModel.eAllContents.forEach[ + if(it instanceof EReference){ + referenceTypes.add(it.name); + } + ] + } + + def List readModels(String path){ + val dir = new File(path); + if(!dir.isDirectory){ + throw new Exception("expecting a directory"); + } + + val graphs = new ArrayList(); + + val metrics = new ArrayList(); + metrics.add(new OutDegreeMetric()); + metrics.add(new NodeActivityMetric()); + metrics.add(new MultiplexParticipationCoefficientMetric()); + + //check all files in the directory with xmi + for(String name : dir.list.filter[it| it.endsWith(".xmi")]){ + val file = new File(name); + val roots = readModel(EObject, path, file.name); + //add a list of metrics + val g = new EMFGraph(); + for(root : roots){ + g.init(root, metrics, name.replaceFirst(".xmi", ""), referenceTypes); + } + + graphs.add(g); + } + + return graphs; + } + + def List readModel(Class type, String path, String name) { + try { + val resource = resSet.getResource(getURI(path, name),true); + if(resource === null) throw new FileNotFoundException(getURI(path, name).toString) + else { + return resource.contents as List + } + } catch(Exception e) { + e.printStackTrace(); + throw new FileNotFoundException(getURI(path, name).toString + "reason: " + e.message) + } + } + + def static getURI(String path, String name) { + URI.createFileURI(path + "/" + name) + } +} \ No newline at end of file diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/PartialInterpretationReader.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/PartialInterpretationReader.xtend new file mode 100644 index 00000000..dbaf36b2 --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/PartialInterpretationReader.xtend @@ -0,0 +1,7 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.input + +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation + +class PartialInterpretationReader { + +} \ No newline at end of file diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/Metric.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/Metric.xtend new file mode 100644 index 00000000..ea52009a --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/Metric.xtend @@ -0,0 +1,7 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics + +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic + +abstract class Metric { + abstract def String[][] evaluate(GraphStatistic g); +} \ No newline at end of file diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/MultiplexParticipationCoefficientMetric.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/MultiplexParticipationCoefficientMetric.xtend new file mode 100644 index 00000000..7bd48754 --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/MultiplexParticipationCoefficientMetric.xtend @@ -0,0 +1,65 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics + +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic +import java.text.DecimalFormat +import java.util.HashMap + +class MultiplexParticipationCoefficientMetric extends Metric { + static val countName = "MPCCount"; + static val valueName = "MPCValue"; + + + override evaluate(GraphStatistic g) { + //because the precision issue of double, we translate double values into String to be the key + val formatter = new DecimalFormat("#0.00000"); + + //get number of different types + val typeCounts = g.allTypes.size; + val map = new HashMap(); + //calculate the metric distribution + g.allNodes.forEach[n| + val edgeCounts = g.outDegree(n) + g.inDegree(n); + + var coef = 0.0; + + for(type : g.allTypes){ + val degree = g.dimentionalDegree(n, type) as double; + coef += Math.pow(degree / edgeCounts, 2); + } + coef = 1 - coef; + coef = coef * typeCounts / (typeCounts-1); + + //Consider the case that either typeCounts-1 or the edgeCounts could be 0 in some situation + //in this case the metric should be evaluated to 0 + if(typeCounts == 1){ + println("bad"); + } + + if(Double.isNaN(coef)){ + coef = 0; + } + + //format number to String + val value = formatter.format(coef); + if(!map.containsKey(value)){ + map.put(value, 1); + }else{ + map.put(value, map.get(value) + 1); + } + + ] + + //convert it into a 2 dimentional array + val String[][] datas = newArrayOfSize(2, map.size+1); + datas.get(0).set(0, valueName); + datas.get(1).set(0, countName) + var count = 1; + for(entry : map.entrySet.sortBy[it.key]){ + datas.get(0).set(count, entry.key+""); + datas.get(1).set(count, entry.value+""); + count++; + } + + return datas; + } +} \ No newline at end of file diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/NodeActivityMetric.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/NodeActivityMetric.xtend new file mode 100644 index 00000000..297bdd14 --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/NodeActivityMetric.xtend @@ -0,0 +1,37 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics + +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic +import java.util.HashMap + +class NodeActivityMetric extends Metric { + static val countName = "NACount"; + static val valueName = "NAValue"; + + override evaluate(GraphStatistic g) { + val map = new HashMap(); + + //calculate the metric distribution + g.allNodes.forEach[ + val value = g.numOfEdgeTypes(it); + if(!map.containsKey(value)){ + map.put(value, 1); + }else{ + map.put(value, map.get(value) + 1); + } + ] + + //convert it into a 2 dimentional array + val String[][] datas = newArrayOfSize(2, map.size+1); + datas.get(0).set(0, valueName); + datas.get(1).set(0, countName) + + var count = 1; + for(entry : map.entrySet.sortBy[it.key]){ + datas.get(0).set(count, entry.key+""); + datas.get(1).set(count, entry.value+""); + count++; + } + + return datas; + } +} \ No newline at end of file diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/OutDegreeMetric.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/OutDegreeMetric.xtend new file mode 100644 index 00000000..1ba6c8c7 --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/OutDegreeMetric.xtend @@ -0,0 +1,38 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics + +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic +import java.util.HashMap + +class OutDegreeMetric extends Metric { + static val countName = "OutDegreeCount"; + static val valueName = "OutDegreeValue"; + + override evaluate(GraphStatistic g) { + val map = new HashMap(); + + //calculate the metric distribution + g.allNodes.forEach[ + val value = g.outDegree(it); + if(!map.containsKey(value)){ + map.put(value, 1); + }else{ + map.put(value, map.get(value) + 1); + } + ] + + //convert it into a 2 dimentional array + val String[][] datas = newArrayOfSize(2, map.size+1); + datas.get(0).set(0, valueName); + datas.get(1).set(0, countName) + var count = 1; + for(entry : map.entrySet.sortBy[it.key]){ + datas.get(0).set(count, entry.key+""); + datas.get(1).set(count, entry.value+""); + count++; + } + + return datas; + } + + +} \ No newline at end of file diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/output/CsvFileWriter.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/output/CsvFileWriter.xtend new file mode 100644 index 00000000..1dd204a0 --- /dev/null +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/output/CsvFileWriter.xtend @@ -0,0 +1,37 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.output; + +import java.io.File +import java.io.FileNotFoundException +import java.io.PrintWriter +import java.util.ArrayList +import java.util.List + +class CsvFileWriter { + def static void write(ArrayList> datas, String uri) { + if(datas.size() <= 0) { + return; + } + + //println("Output csv for " + uri); + try { + val PrintWriter writer = new PrintWriter(new File(uri)); + val output = new StringBuilder; + for(List datarow : datas){ + for(var i = 0; i < datarow.size() - 1; i++){ + output.append(datarow.get(i) + ','); + } + + if(datarow.size > 1){ + output.append(datarow.get(datarow.size() - 1)); + output.append('\n'); + } + } + + writer.write(output.toString()); + writer.close(); + //println("Output csv finished"); + }catch(FileNotFoundException e) { + e.printStackTrace(); + } + } +} -- cgit v1.2.3-54-g00ecf