aboutsummaryrefslogtreecommitdiffstats
path: root/Metrics
diff options
context:
space:
mode:
authorLibravatar 20001LastOrder <boqi.chen@mail.mcgill.ca>2019-05-27 15:50:05 -0400
committerLibravatar 20001LastOrder <boqi.chen@mail.mcgill.ca>2019-05-27 15:50:05 -0400
commit6b751d1c3cf6294f589364acc1b8fe0f2d113bf4 (patch)
tree5fb0859d6bfd716a3fc8115203b7784662d67948 /Metrics
parentadd metrics data plot tool (diff)
downloadVIATRA-Generator-6b751d1c3cf6294f589364acc1b8fe0f2d113bf4.tar.gz
VIATRA-Generator-6b751d1c3cf6294f589364acc1b8fe0f2d113bf4.tar.zst
VIATRA-Generator-6b751d1c3cf6294f589364acc1b8fe0f2d113bf4.zip
add project for metric calculator
Diffstat (limited to 'Metrics')
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.classpath8
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.gitignore5
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.project34
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/Inputs/.gitignore4
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/META-INF/MANIFEST.MF18
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/build.properties4
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/Main.xtend72
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/PartialInterpretationMetric.xtend61
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/EMFGraph.xtend101
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/Graph.xtend41
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/GraphStatistic.xtend107
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/PartialInterpretationGraph.xtend73
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/GraphReader.xtend81
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/PartialInterpretationReader.xtend7
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/Metric.xtend7
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/MultiplexParticipationCoefficientMetric.xtend65
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/NodeActivityMetric.xtend37
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/OutDegreeMetric.xtend38
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/output/CsvFileWriter.xtend37
20 files changed, 807 insertions, 0 deletions
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 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<classpath>
3 <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
4 <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
5 <classpathentry kind="src" path="src"/>
6 <classpathentry kind="src" path="xtend-gen"/>
7 <classpathentry kind="output" path="bin"/>
8</classpath>
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 @@
1/bin/
2bin/
3testInput/
4testOutput/
5xtend-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 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<projectDescription>
3 <name>ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator</name>
4 <comment></comment>
5 <projects>
6 </projects>
7 <buildSpec>
8 <buildCommand>
9 <name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
10 <arguments>
11 </arguments>
12 </buildCommand>
13 <buildCommand>
14 <name>org.eclipse.jdt.core.javabuilder</name>
15 <arguments>
16 </arguments>
17 </buildCommand>
18 <buildCommand>
19 <name>org.eclipse.pde.ManifestBuilder</name>
20 <arguments>
21 </arguments>
22 </buildCommand>
23 <buildCommand>
24 <name>org.eclipse.pde.SchemaBuilder</name>
25 <arguments>
26 </arguments>
27 </buildCommand>
28 </buildSpec>
29 <natures>
30 <nature>org.eclipse.pde.PluginNature</nature>
31 <nature>org.eclipse.jdt.core.javanature</nature>
32 <nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
33 </natures>
34</projectDescription>
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 @@
1eclipse.preferences.version=1
2org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
4org.eclipse.jdt.core.compiler.compliance=1.8
5org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
6org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
7org.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 @@
1# ignore everything in this folder except for this folder it self
2
3*
4!.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 @@
1Manifest-Version: 1.0
2Bundle-ManifestVersion: 2
3Bundle-Name: Graph_metrics_calculation
4Bundle-SymbolicName: ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator
5Bundle-Version: 1.0.0.qualifier
6Automatic-Module-Name: graph_metrics_calculation
7Bundle-RequiredExecutionEnvironment: JavaSE-1.8
8Require-Bundle: com.google.guava,
9 org.eclipse.xtext.xbase.lib,
10 org.eclipse.xtend.lib,
11 org.eclipse.xtend.lib.macro,
12 org.eclipse.emf.ecore;bundle-version="2.17.0",
13 org.eclipse.emf.ecore.xmi;bundle-version="2.15.0",
14 hu.bme.mit.inf.dslreasoner.viatra2logic;bundle-version="1.0.0",
15 hu.bme.mit.inf.dslreasoner.domains.yakindu.sgraph;bundle-version="1.0.0",
16 hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage;bundle-version="1.0.0",
17 org.eclipse.viatra.dse;bundle-version="0.21.2"
18Export-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 @@
1source.. = src/
2output.. = bin/
3bin.includes = META-INF/,\
4 .
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 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.EMFGraph
4import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.input.GraphReader
5import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.output.CsvFileWriter
6import hu.bme.mit.inf.dslreasoner.domains.yakindu.sgraph.yakindumm.impl.YakindummPackageImpl
7import java.util.ArrayList
8
9//import yakindumm2.impl.Yakindumm2PackageImpl
10
11class Main {
12 static class RWInformation{
13 public var String inputFolder;
14 public var String outputFolder;
15 public var int numRuns;
16
17 new(String inputFolder, String outputFolder, int numRuns){
18 this.inputFolder = inputFolder;
19 this.outputFolder = outputFolder;
20 this.numRuns = numRuns;
21 }
22 }
23
24 def static void main(String[] args){
25 //init model
26 YakindummPackageImpl.eINSTANCE.eClass;
27// Yakindumm2PackageImpl.eINSTANCE.eClass;
28 val infos = initData();
29
30 println("Start Reading Models...");
31 var reader = new GraphReader(YakindummPackageImpl.eINSTANCE);
32 for(info : infos){
33 calculateAllModels(info.inputFolder, info.outputFolder,info.numRuns, reader);
34 }
35
36 //human input has different package declaration
37// reader = new GraphReader(Yakindumm2PackageImpl.eINSTANCE);
38 val human = new RWInformation("inputs/humanInput/", "../plot/statistics/humanOutput/", 1);
39 calculateAllModels(human.inputFolder, human.outputFolder,human.numRuns, reader);
40
41
42 println("finished");
43 }
44
45 static def initData(){
46 val infos = new ArrayList<RWInformation>();
47 infos.add(new RWInformation("inputs/alloyInput/models/", "../plot/statistics/alloyOutput/", 20));
48 infos.add(new RWInformation("inputs/randomInput/models/", "../plot/statistics/randomOutput/", 20));
49 infos.add(new RWInformation("inputs/viatraInput30/", "../plot/statistics/viatraOutput30/", 20));
50 infos.add(new RWInformation("inputs/viatraInput100/", "../plot/statistics/viatraOutput100/", 10));
51 return infos;
52 }
53
54 static def calculateAllModels(String inputFolder, String outputFolder, int numRuns, GraphReader reader){
55 for(var i = 1; i <= numRuns; i++){
56 val models = new ArrayList<EMFGraph>();
57 models.addAll(reader.readModels(inputFolder + "run" + i));
58 for(model : models){
59 calculateAndOutputMetrics(model, YakindummPackageImpl.eNAME, outputFolder+model.name+"_run_"+i+".csv");
60 }
61 }
62 println("output results Ended for: " + outputFolder);
63
64
65 }
66
67 static def calculateAndOutputMetrics(EMFGraph model, String metaModel, String fileName){
68 //println("evaluating for " + model.name);
69 model.metaModel = metaModel;
70 CsvFileWriter.write(model.evaluateAllMetrics(), fileName);
71 }
72} \ 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 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.PartialInterpretationGraph
4import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric
5import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric
6import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric
7import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric
8import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.output.CsvFileWriter
9import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
10import java.io.File
11import java.io.FileNotFoundException
12import java.io.PrintWriter
13import java.util.ArrayList
14import java.util.List
15import org.eclipse.emf.ecore.util.EcoreUtil
16import org.eclipse.viatra.dse.api.Solution
17
18class PartialInterpretationMetric {
19 var static state = 0;
20 def static void calculateMetric(PartialInterpretation partial, String path, int id, String currentStateId){
21 val metrics = new ArrayList<Metric>();
22 metrics.add(new OutDegreeMetric());
23 metrics.add(new NodeActivityMetric());
24 metrics.add(new MultiplexParticipationCoefficientMetric());
25
26 new File(path).mkdir();
27 val filename = path + "/state_"+state+".csv";
28 state++;
29 val metricCalculator = new PartialInterpretationGraph(partial, metrics, currentStateId);
30
31 CsvFileWriter.write(metricCalculator.evaluateAllMetrics(), filename);
32 }
33
34 def static void outputTrajectories(PartialInterpretation empty, List<Solution> solutions){
35
36 for(solution : solutions){
37 val emptySolutionCopy = EcoreUtil.copy(empty)
38 val trajectory = solution.shortestTrajectory;
39 trajectory.modelWithEditingDomain = emptySolutionCopy
40 val stateCodes = newArrayList()
41
42 while(trajectory.doNextTransformation){
43 println(trajectory.stateCoder.createStateCode)
44 stateCodes.add(trajectory.stateCoder.createStateCode.toString)
45 }
46
47 try{
48 val path = "debug/metric/trajectories/trajectory"+trajectory.stateCoder.createStateCode.toString+".csv"
49 val PrintWriter writer = new PrintWriter(new File(path))
50 val output = new StringBuilder
51 for(stateCode : stateCodes){
52 output.append(stateCode+'\n')
53 }
54 writer.write(output.toString())
55 writer.close()
56 }catch(FileNotFoundException e) {
57 e.printStackTrace()
58 }
59 }
60 }
61} \ 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 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric
4import java.util.ArrayList
5import java.util.List
6import org.eclipse.emf.common.util.EList
7import org.eclipse.emf.ecore.EObject
8import org.eclipse.emf.ecore.EReference
9
10class EMFGraph extends Graph{
11
12 def void init (EObject root, List<Metric> metrics, String name, List<String> referenceTypes){
13 val otherContents = root.eAllContents.toList();
14 otherContents.add(root);
15 init(otherContents, metrics, name, referenceTypes);
16 }
17
18 /**
19 * init the graph with all nodes and reference types in the meta model
20 * @param objects: objects in the instance model (exclude root)
21 * @param metrics: metrics to be evaluated
22 * @param name: name of the instance model
23 * @param ReferenceTypes: reference types defined in the meta model
24 */
25 def void init(List<EObject> objects, List<Metric> metrics, String name, List<String> referenceTypes){
26 objects.forEach[it|
27 statistic.addNode(it);
28 ]
29
30 referenceTypes.forEach[it|
31 statistic.addType(it);
32 ];
33
34 objects.forEach[source|
35 source.eClass.EAllReferences.forEach[r|
36 //add the type first (if it is not added already)
37 //many references
38 if(r.isMany){
39 source.getNeighbours(r).forEach[target|
40 addEdge(source, target, r);
41 ]
42 }else{
43 //single references
44 val target = source.eGet(r) as EObject;
45 addEdge(source, target, r);
46 }
47 ]
48 ]
49
50 this.metrics = metrics;
51 this.name = name;
52 }
53
54 /**
55 * Set basic information for the output
56 */
57 override setBasicInformation(ArrayList<ArrayList<String>> output){
58 val metaInfo = new ArrayList<String>();
59 metaInfo.add(META_MODEL_HEADER);
60 metaInfo.add(this.metaModel);
61
62 val edgeInfo = new ArrayList<String>();
63 edgeInfo.add(NUM_EDGE_TYPE_HEADER);
64 edgeInfo.add(this.statistic.allTypes.size()+"");
65
66 val nodeInfo = new ArrayList<String>();
67 nodeInfo.add(NUM_NODE_HEADER);
68 nodeInfo.add(this.statistic.allNodes.size()+"");
69
70 output.add(metaInfo);
71 output.add(edgeInfo);
72 output.add(nodeInfo);
73 }
74
75 def EList<EObject> getNeighbours(EObject o, EReference r){
76 return (o.eGet(r, true) as EList<EObject>);
77 }
78
79 def addEdge(EObject source, EObject target, EReference r){
80 if(target !== null && r !== null){
81 statistic.addEdge(source, target, r.name);
82 }
83 }
84
85 override GraphStatistic getStatistic(){
86 return this.statistic;
87 }
88
89 override String getName(){
90 return this.name;
91 }
92
93 def void setMetaModel(String model){
94 this.metaModel = model;
95 }
96
97 def String getMetaModel(){
98 return this.metaModel;
99 }
100
101} \ 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 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric
4import java.util.ArrayList
5import java.util.List
6
7abstract class Graph {
8
9 protected static val String META_MODEL_HEADER = "Meta Mode"
10 protected static val String NUM_NODE_HEADER = "Number Of Nodes";
11 protected static val String NUM_EDGE_TYPE_HEADER = "Number of Edge types";
12 protected static val String STATE_ID_HEADER = "State Id";
13
14 protected val statistic = new GraphStatistic();
15 protected var List<Metric> metrics;
16 protected var String name = "";
17 protected var String metaModel = "";
18
19 /**
20 * evaluate all metrics for this model
21 * return the result as a two dimentional list
22 */
23 def ArrayList<ArrayList<String>> evaluateAllMetrics(){
24 val result = new ArrayList<ArrayList<String>>();
25 setBasicInformation(result);
26
27 for(metric : this.metrics){
28 val datas = metric.evaluate(this.statistic);
29 for(row : datas){
30 result.add(new ArrayList<String>(row));
31 }
32 }
33 return result;
34 }
35
36 def void setBasicInformation(ArrayList<ArrayList<String>> result);
37
38 def GraphStatistic getStatistic();
39
40 def String getName();
41} \ 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 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph
2
3import com.google.common.collect.ArrayListMultimap
4import com.google.common.collect.Multimap
5import java.util.HashMap
6import java.util.HashSet
7import java.util.List
8import org.eclipse.emf.ecore.EObject
9
10class GraphStatistic {
11 val incomingEdges = new HashMap<String, Multimap<EObject, EObject>>;
12 val outcomingEdges = new HashMap<String, Multimap<EObject, EObject>>;
13
14 val edgeTypes = new HashSet<String>();
15 val nodes = new HashSet<EObject>();
16
17 /**
18 * Add an edge type to to the graph
19 * @param type: type to add
20 */
21 def void addType(String type){
22 if(edgeTypes.contains(type)){
23 return;
24 }
25 edgeTypes.add(type);
26 incomingEdges.put(type, ArrayListMultimap.create());
27 outcomingEdges.put(type, ArrayListMultimap.create());
28 }
29
30 /**
31 * Add a node to he graph
32 * @param node: node to add
33 */
34 def void addNode(EObject n){
35 if(nodes.contains(n)){
36 return;
37 }
38
39 nodes.add(n);
40 }
41
42 /**
43 * Add an edge to the graph
44 * @param source: source node
45 * @param target: target node
46 * @param type: type of the reference
47 */
48 def void addEdge(EObject source, EObject target, String type){
49 outcomingEdges.get(type).put(source, target);
50 incomingEdges.get(type).put(target, source);
51 }
52
53 /**
54 * calculate the out degree for an object
55 */
56 def int outDegree(EObject o){
57 var count = 0;
58
59 for (String type : edgeTypes){
60 count += outcomingEdges.get(type).get(o).size();
61 }
62 return count;
63 }
64
65 /**
66 * calculate the in degree of an object
67 */
68 def int inDegree(EObject o){
69 var count = 0;
70
71 for (String type : edgeTypes){
72 count += incomingEdges.get(type).get(o).size();
73 }
74 return count;
75 }
76
77 /**
78 * calculate the dimentional degree of a node
79 */
80 def int dimentionalDegree(EObject o, String type){
81 return incomingEdges.get(type).get(o).size() + outcomingEdges.get(type).get(o).size();
82 }
83
84 /**
85 * calculate the number of edge types for a given degree.
86 */
87 def int numOfEdgeTypes(EObject o){
88 var count = 0;
89
90 for(String type : edgeTypes){
91 if(dimentionalDegree(o, type) > 0){
92 count++;
93 }
94 }
95
96 return count;
97 }
98
99 def List<String> getAllTypes(){
100 return edgeTypes.toList();
101 }
102
103 def List<EObject> getAllNodes(){
104 return nodes.toList();
105 }
106}
107
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 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric
4import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BinaryElementRelationLink
5import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
6import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.BooleanElementImpl
7import java.util.ArrayList
8import java.util.List
9
10class PartialInterpretationGraph extends Graph{
11 var lastStateId="";
12
13 new(PartialInterpretation partial, List<Metric> metrics, String name){
14 partial.problem.relations.forEach[
15 this.statistic.addType(it.name);
16 ]
17 // add all elements
18 val elements = getElements(partial);
19 for(element : elements){
20 statistic.addNode(element)
21 }
22
23 for(relationInterpretation : partial.partialrelationinterpretation) {
24 val type = relationInterpretation.interpretationOf.name
25
26 for(edge : relationInterpretation.relationlinks.filter(BinaryElementRelationLink)){
27 statistic.addEdge(edge.param1, edge.param2, type);
28 }
29 }
30
31 this.name = name;
32 this.metrics = metrics;
33 }
34
35 /**
36 * Set basic information for the output
37 */
38 override setBasicInformation(ArrayList<ArrayList<String>> output){
39 val metaInfo = new ArrayList<String>();
40 metaInfo.add(META_MODEL_HEADER);
41 metaInfo.add(this.metaModel);
42
43 val edgeInfo = new ArrayList<String>();
44 edgeInfo.add(NUM_EDGE_TYPE_HEADER);
45 edgeInfo.add(this.statistic.allTypes.size()+"");
46
47 val nodeInfo = new ArrayList<String>();
48 nodeInfo.add(NUM_NODE_HEADER);
49 nodeInfo.add(this.statistic.allNodes.size()+"");
50
51 val stateInfo = new ArrayList<String>();
52 stateInfo.add(STATE_ID_HEADER);
53 stateInfo.add(this.name);
54
55 output.add(metaInfo);
56 output.add(edgeInfo);
57 output.add(nodeInfo);
58 output.add(stateInfo);
59 }
60
61 private def getElements(PartialInterpretation partial){
62 return partial.newElements.filter[!(it instanceof BooleanElementImpl)] + partial.problem.elements;
63 }
64
65 override getStatistic() {
66 throw new UnsupportedOperationException("TODO: auto-generated method stub")
67 }
68
69 override getName() {
70 return name;
71 }
72
73} \ 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 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.input
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.EMFGraph
4import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric
5import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric
6import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric
7import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric
8import java.io.File
9import java.io.FileNotFoundException
10import java.util.ArrayList
11import java.util.List
12import org.eclipse.emf.common.util.URI
13import org.eclipse.emf.ecore.EObject
14import org.eclipse.emf.ecore.EPackage
15import org.eclipse.emf.ecore.EReference
16import org.eclipse.emf.ecore.resource.Resource
17import org.eclipse.emf.ecore.resource.ResourceSet
18import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl
19import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl
20
21class GraphReader{
22 val ResourceSet resSet = new ResourceSetImpl();
23 val referenceTypes = new ArrayList<String>();
24
25 new(EPackage metaModel) {
26 Resource.Factory.Registry.INSTANCE.extensionToFactoryMap.put("*",new XMIResourceFactoryImpl)
27
28 //find all reference types in the meta model
29 metaModel.eAllContents.forEach[
30 if(it instanceof EReference){
31 referenceTypes.add(it.name);
32 }
33 ]
34 }
35
36 def List<EMFGraph> readModels(String path){
37 val dir = new File(path);
38 if(!dir.isDirectory){
39 throw new Exception("expecting a directory");
40 }
41
42 val graphs = new ArrayList<EMFGraph>();
43
44 val metrics = new ArrayList<Metric>();
45 metrics.add(new OutDegreeMetric());
46 metrics.add(new NodeActivityMetric());
47 metrics.add(new MultiplexParticipationCoefficientMetric());
48
49 //check all files in the directory with xmi
50 for(String name : dir.list.filter[it| it.endsWith(".xmi")]){
51 val file = new File(name);
52 val roots = readModel(EObject, path, file.name);
53 //add a list of metrics
54 val g = new EMFGraph();
55 for(root : roots){
56 g.init(root, metrics, name.replaceFirst(".xmi", ""), referenceTypes);
57 }
58
59 graphs.add(g);
60 }
61
62 return graphs;
63 }
64
65 def <RootType extends EObject> List<RootType> readModel(Class<RootType> type, String path, String name) {
66 try {
67 val resource = resSet.getResource(getURI(path, name),true);
68 if(resource === null) throw new FileNotFoundException(getURI(path, name).toString)
69 else {
70 return resource.contents as List<RootType>
71 }
72 } catch(Exception e) {
73 e.printStackTrace();
74 throw new FileNotFoundException(getURI(path, name).toString + "reason: " + e.message)
75 }
76 }
77
78 def static getURI(String path, String name) {
79 URI.createFileURI(path + "/" + name)
80 }
81} \ 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 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.input
2
3import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
4
5class PartialInterpretationReader {
6
7} \ 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 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic
4
5abstract class Metric {
6 abstract def String[][] evaluate(GraphStatistic g);
7} \ 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 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic
4import java.text.DecimalFormat
5import java.util.HashMap
6
7class MultiplexParticipationCoefficientMetric extends Metric {
8 static val countName = "MPCCount";
9 static val valueName = "MPCValue";
10
11
12 override evaluate(GraphStatistic g) {
13 //because the precision issue of double, we translate double values into String to be the key
14 val formatter = new DecimalFormat("#0.00000");
15
16 //get number of different types
17 val typeCounts = g.allTypes.size;
18 val map = new HashMap<String, Integer>();
19 //calculate the metric distribution
20 g.allNodes.forEach[n|
21 val edgeCounts = g.outDegree(n) + g.inDegree(n);
22
23 var coef = 0.0;
24
25 for(type : g.allTypes){
26 val degree = g.dimentionalDegree(n, type) as double;
27 coef += Math.pow(degree / edgeCounts, 2);
28 }
29 coef = 1 - coef;
30 coef = coef * typeCounts / (typeCounts-1);
31
32 //Consider the case that either typeCounts-1 or the edgeCounts could be 0 in some situation
33 //in this case the metric should be evaluated to 0
34 if(typeCounts == 1){
35 println("bad");
36 }
37
38 if(Double.isNaN(coef)){
39 coef = 0;
40 }
41
42 //format number to String
43 val value = formatter.format(coef);
44 if(!map.containsKey(value)){
45 map.put(value, 1);
46 }else{
47 map.put(value, map.get(value) + 1);
48 }
49
50 ]
51
52 //convert it into a 2 dimentional array
53 val String[][] datas = newArrayOfSize(2, map.size+1);
54 datas.get(0).set(0, valueName);
55 datas.get(1).set(0, countName)
56 var count = 1;
57 for(entry : map.entrySet.sortBy[it.key]){
58 datas.get(0).set(count, entry.key+"");
59 datas.get(1).set(count, entry.value+"");
60 count++;
61 }
62
63 return datas;
64 }
65} \ 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 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic
4import java.util.HashMap
5
6class NodeActivityMetric extends Metric {
7 static val countName = "NACount";
8 static val valueName = "NAValue";
9
10 override evaluate(GraphStatistic g) {
11 val map = new HashMap<Integer, Integer>();
12
13 //calculate the metric distribution
14 g.allNodes.forEach[
15 val value = g.numOfEdgeTypes(it);
16 if(!map.containsKey(value)){
17 map.put(value, 1);
18 }else{
19 map.put(value, map.get(value) + 1);
20 }
21 ]
22
23 //convert it into a 2 dimentional array
24 val String[][] datas = newArrayOfSize(2, map.size+1);
25 datas.get(0).set(0, valueName);
26 datas.get(1).set(0, countName)
27
28 var count = 1;
29 for(entry : map.entrySet.sortBy[it.key]){
30 datas.get(0).set(count, entry.key+"");
31 datas.get(1).set(count, entry.value+"");
32 count++;
33 }
34
35 return datas;
36 }
37} \ 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 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic
4import java.util.HashMap
5
6class OutDegreeMetric extends Metric {
7 static val countName = "OutDegreeCount";
8 static val valueName = "OutDegreeValue";
9
10 override evaluate(GraphStatistic g) {
11 val map = new HashMap<Integer, Integer>();
12
13 //calculate the metric distribution
14 g.allNodes.forEach[
15 val value = g.outDegree(it);
16 if(!map.containsKey(value)){
17 map.put(value, 1);
18 }else{
19 map.put(value, map.get(value) + 1);
20 }
21 ]
22
23 //convert it into a 2 dimentional array
24 val String[][] datas = newArrayOfSize(2, map.size+1);
25 datas.get(0).set(0, valueName);
26 datas.get(1).set(0, countName)
27 var count = 1;
28 for(entry : map.entrySet.sortBy[it.key]){
29 datas.get(0).set(count, entry.key+"");
30 datas.get(1).set(count, entry.value+"");
31 count++;
32 }
33
34 return datas;
35 }
36
37
38} \ 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 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.output;
2
3import java.io.File
4import java.io.FileNotFoundException
5import java.io.PrintWriter
6import java.util.ArrayList
7import java.util.List
8
9class CsvFileWriter {
10 def static void write(ArrayList<ArrayList<String>> datas, String uri) {
11 if(datas.size() <= 0) {
12 return;
13 }
14
15 //println("Output csv for " + uri);
16 try {
17 val PrintWriter writer = new PrintWriter(new File(uri));
18 val output = new StringBuilder;
19 for(List<String> datarow : datas){
20 for(var i = 0; i < datarow.size() - 1; i++){
21 output.append(datarow.get(i) + ',');
22 }
23
24 if(datarow.size > 1){
25 output.append(datarow.get(datarow.size() - 1));
26 output.append('\n');
27 }
28 }
29
30 writer.write(output.toString());
31 writer.close();
32 //println("Output csv finished");
33 }catch(FileNotFoundException e) {
34 e.printStackTrace();
35 }
36 }
37}