aboutsummaryrefslogtreecommitdiffstats
path: root/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca
diff options
context:
space:
mode:
Diffstat (limited to 'Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca')
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/Domain.xtend5
-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.xtend124
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/distance/KSDistance.xtend47
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/EMFGraph.xtend106
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/Graph.xtend61
-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.xtend77
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/io/CsvFileWriter.xtend37
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/io/GraphReader.xtend81
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/io/RepMetricsReader.xtend79
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/Metric.xtend8
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/MetricSampleGroup.xtend9
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/MultiplexParticipationCoefficientMetric.xtend80
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/NodeActivityMetric.xtend49
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/OutDegreeMetric.xtend49
16 files changed, 991 insertions, 0 deletions
diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/Domain.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/Domain.xtend
new file mode 100644
index 00000000..8351e96b
--- /dev/null
+++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/Domain.xtend
@@ -0,0 +1,5 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app
2
3enum Domain{
4 Yakinduum
5} \ 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/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..cf871ead
--- /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.io.CsvFileWriter
5import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.GraphReader
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/Random/", "outputs/", 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..cdd06027
--- /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,124 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance.KSDistance
4import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.PartialInterpretationGraph
5import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.CsvFileWriter
6import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric
7import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric
8import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric
9import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric
10import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
11import java.io.File
12import java.io.FileNotFoundException
13import java.io.PrintWriter
14import java.util.ArrayList
15import java.util.List
16import org.eclipse.emf.ecore.util.EcoreUtil
17import org.eclipse.viatra.dse.api.Solution
18
19class PartialInterpretationMetric {
20 var static state = 0;
21 var static KSDistance ks;
22
23 def static void initPaths(){
24 new File("debug/metric/").mkdir();
25 new File("debug/metric/trajectories/").mkdir();
26 ks = new KSDistance(Domain.Yakinduum);
27 }
28
29 def static MetricDistanceGroup calculateMetricDistance(PartialInterpretation partial){
30 val metrics = new ArrayList<Metric>();
31 metrics.add(new OutDegreeMetric());
32 metrics.add(new NodeActivityMetric());
33 metrics.add(new MultiplexParticipationCoefficientMetric());
34
35 val metricCalculator = new PartialInterpretationGraph(partial, metrics, null);
36 var metricSamples = metricCalculator.evaluateAllMetricsToSamples();
37
38 var mpc = ks.mpcDistance(metricSamples.mpcSamples);
39 var na = ks.naDistance(metricSamples.naSamples);
40 var outDegree = ks.outDegreeDistance(metricSamples.outDegreeSamples);
41
42 return new MetricDistanceGroup(mpc, na, outDegree);
43 }
44
45 // calculate the metrics for a state
46 def static void calculateMetric(PartialInterpretation partial, String path, String currentStateId, Integer counter){
47 val metrics = new ArrayList<Metric>();
48 metrics.add(new OutDegreeMetric());
49 metrics.add(new NodeActivityMetric());
50 metrics.add(new MultiplexParticipationCoefficientMetric());
51
52 //make dir since the folder can be none existing
53 new File(path).mkdir();
54 val filename = path + "/state_"+currentStateId+"-"+counter+".csv";
55 state++;
56 val metricCalculator = new PartialInterpretationGraph(partial, metrics, currentStateId);
57
58 CsvFileWriter.write(metricCalculator.evaluateAllMetrics(), filename);
59 }
60
61 def static void outputTrajectories(PartialInterpretation empty, List<Solution> solutions){
62 for(solution : solutions){
63 //need to copy the empty solution because the transition directly worked on the graph
64 val emptySolutionCopy = EcoreUtil.copy(empty)
65 val trajectory = solution.shortestTrajectory;
66 trajectory.modelWithEditingDomain = emptySolutionCopy
67
68 // state codes that will record the trajectory
69 val stateCodes = newArrayList()
70
71 var counter = 0
72 //transform and record the state codes for each state
73 while(trajectory.doNextTransformation){
74 //println(trajectory.stateCoder.createStateCode)
75 val stateId = trajectory.stateCoder.createStateCode.toString
76 val interpretation = trajectory.getModel();
77 //calculate metrics of current state
78 calculateMetric(interpretation as PartialInterpretation, "debug/metric/output", stateId, counter)
79 stateCodes.add(stateId)
80 counter++
81 }
82
83
84 //output the trajectory
85 try{
86 new File("debug/metric/trajectories/").mkdir();
87 val path = "debug/metric/trajectories/trajectory"+trajectory.stateCoder.createStateCode.toString+".csv"
88 val PrintWriter writer = new PrintWriter(new File(path))
89 val output = new StringBuilder
90 for(stateCode : stateCodes){
91 output.append(stateCode+'\n')
92 }
93 writer.write(output.toString())
94 writer.close()
95 }catch(FileNotFoundException e) {
96 e.printStackTrace()
97 }
98 }
99 }
100}
101
102class MetricDistanceGroup{
103 var double mpcDistance;
104 var double naDistance;
105 var double outDegreeDistance;
106
107 new(double mpcDistance, double naDistance, double outDegreeDistance){
108 this.mpcDistance = mpcDistance;
109 this.naDistance = naDistance;
110 this.outDegreeDistance = outDegreeDistance;
111 }
112
113 def double getMPCDistance(){
114 return this.mpcDistance
115 }
116
117 def double getNADistance(){
118 return this.naDistance
119 }
120
121 def double getOutDegreeDistance(){
122 return this.outDegreeDistance
123 }
124} \ 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/distance/KSDistance.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/distance/KSDistance.xtend
new file mode 100644
index 00000000..1fb21529
--- /dev/null
+++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/distance/KSDistance.xtend
@@ -0,0 +1,47 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app.Domain
4import java.util.List
5import org.apache.commons.math3.stat.inference.KolmogorovSmirnovTest
6import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.RepMetricsReader
7
8class KSDistance {
9 var static ksTester = new KolmogorovSmirnovTest();
10 var double[] mpcSamples;
11 var double[] naSamples;
12 var double[] outDegreeSamples;
13
14 new(Domain d){
15 var metrics = RepMetricsReader.read(d);
16 mpcSamples = metrics.mpcSamples;
17 naSamples = metrics.naSamples.stream.mapToDouble([it]).toArray();
18 outDegreeSamples = metrics.outDegreeSamples.stream.mapToDouble([it]).toArray();
19 }
20
21 def double mpcDistance(List<Double> samples){
22 // map list to array
23 var arr = samples.stream.mapToDouble([it]).toArray();
24
25 //if the size of array is smaller than 2, ks distance cannot be performed, simply return 1
26 if(arr.size < 2) return 1;
27 return ksTester.kolmogorovSmirnovStatistic(mpcSamples, arr);
28 }
29
30 def double naDistance(List<Double> samples){
31 // map list to array
32 var arr = samples.stream.mapToDouble([it]).toArray();
33
34 //if the size of array is smaller than 2, ks distance cannot be performed, simply return 1
35 if(arr.size < 2) return 1;
36 return ksTester.kolmogorovSmirnovStatistic(naSamples as double[], arr);
37 }
38
39 def double outDegreeDistance(List<Double> samples){
40 // map list to array
41 var arr = samples.stream.mapToDouble([it]).toArray();
42
43 //if the size of array is smaller than 2, ks distance cannot be performed, simply return 1
44 if(arr.size < 2) return 1;
45 return ksTester.kolmogorovSmirnovStatistic(outDegreeSamples, arr);
46 }
47} \ 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..5c161f4b
--- /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,106 @@
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 def void init (EObject root, List<Metric> metrics, String name, List<String> referenceTypes){
12 val otherContents = root.eAllContents.toList();
13 otherContents.add(root);
14 init(otherContents, metrics, name, referenceTypes);
15 }
16
17 /**
18 * init the graph with all nodes and reference types in the meta model
19 * @param objects: objects in the instance model (exclude root)
20 * @param metrics: metrics to be evaluated
21 * @param name: name of the instance model
22 * @param ReferenceTypes: reference types defined in the meta model
23 */
24 def void init(List<EObject> objects, List<Metric> metrics, String name, List<String> referenceTypes){
25 objects.forEach[it|
26 statistic.addNode(it);
27 ]
28
29 referenceTypes.forEach[it|
30 statistic.addType(it);
31 ];
32
33 objects.forEach[source|
34 source.eClass.EAllReferences.forEach[r|
35 //add the type first (if it is not added already)
36 //many references
37 if(r.isMany){
38 source.getNeighbours(r).forEach[target|
39 addEdge(source, target, r);
40 ]
41 }else{
42 //single references
43 val target = source.eGet(r) as EObject;
44 addEdge(source, target, r);
45 }
46 ]
47 ]
48
49 this.metrics = metrics;
50 this.name = name;
51 }
52
53 /**
54 * Set basic information for the output
55 */
56 override setBasicInformation(ArrayList<ArrayList<String>> output){
57 val metaInfo = new ArrayList<String>();
58 metaInfo.add(META_MODEL_HEADER);
59 metaInfo.add(this.metaModel);
60
61 val edgeInfo = new ArrayList<String>();
62 edgeInfo.add(NUM_EDGE_TYPE_HEADER);
63 edgeInfo.add(this.statistic.allTypes.size()+"");
64
65 val nodeInfo = new ArrayList<String>();
66 nodeInfo.add(NUM_NODE_HEADER);
67 nodeInfo.add(this.statistic.allNodes.size()+"");
68
69 val stateInfo = new ArrayList<String>();
70 stateInfo.add(STATE_ID_HEADER);
71 stateInfo.add(this.name);
72
73
74 output.add(metaInfo);
75 output.add(edgeInfo);
76 output.add(nodeInfo);
77 output.add(stateInfo);
78 }
79
80 def EList<EObject> getNeighbours(EObject o, EReference r){
81 return (o.eGet(r, true) as EList<EObject>);
82 }
83
84 def addEdge(EObject source, EObject target, EReference r){
85 if(target !== null && r !== null){
86 statistic.addEdge(source, target, r.name);
87 }
88 }
89
90 override GraphStatistic getStatistic(){
91 return this.statistic;
92 }
93
94 override String getName(){
95 return this.name;
96 }
97
98 def void setMetaModel(String model){
99 this.metaModel = model;
100 }
101
102 def String getMetaModel(){
103 return this.metaModel;
104 }
105
106} \ 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..cf4aedba
--- /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,61 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric
4import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MetricSampleGroup
5import java.util.ArrayList
6import java.util.List
7import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric
8import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric
9import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric
10
11abstract class Graph {
12
13 protected static val String META_MODEL_HEADER = "Meta Mode"
14 protected static val String NUM_NODE_HEADER = "Number Of Nodes";
15 protected static val String NUM_EDGE_TYPE_HEADER = "Number of Edge types";
16 protected static val String STATE_ID_HEADER = "State Id";
17
18 protected val statistic = new GraphStatistic();
19 protected var List<Metric> metrics;
20 protected var String name = "";
21 protected var String metaModel = "";
22
23 /**
24 * evaluate all metrics for this model
25 * return the result as a two dimentional list
26 */
27 def ArrayList<ArrayList<String>> evaluateAllMetrics(){
28 val result = new ArrayList<ArrayList<String>>();
29 setBasicInformation(result);
30
31 for(metric : this.metrics){
32 val datas = metric.evaluate(this.statistic);
33 for(row : datas){
34 result.add(new ArrayList<String>(row));
35 }
36 }
37 return result;
38 }
39
40 def MetricSampleGroup evaluateAllMetricsToSamples(){
41 var sample = new MetricSampleGroup();
42
43 for(metric : this.metrics){
44 if(metric instanceof MultiplexParticipationCoefficientMetric){
45 sample.mpcSamples = metric.evaluateSamples(this.statistic);
46 }else if(metric instanceof NodeActivityMetric){
47 sample.naSamples = metric.evaluateSamples(this.statistic);
48 }else if(metric instanceof OutDegreeMetric){
49 sample.outDegreeSamples = metric.evaluateSamples(this.statistic);
50 }
51 }
52
53 return sample;
54 }
55
56 def void setBasicInformation(ArrayList<ArrayList<String>> result);
57
58 def GraphStatistic getStatistic();
59
60 def String getName();
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/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..14337ab0
--- /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,77 @@
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.logic.model.logiclanguage.RelationDeclaration
5import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BinaryElementRelationLink
6import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
7import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.BooleanElementImpl
8import java.util.ArrayList
9import java.util.List
10
11class PartialInterpretationGraph extends Graph{
12
13 /**
14 * Define a new PartialInterpretationGraph by parse every element from a PartialInterpretation
15 */
16 new(PartialInterpretation partial, List<Metric> metrics, String name){
17 //the edge types are defined in terms of RelationDeclaration
18 partial.problem.relations.filter(RelationDeclaration).forEach[
19 this.statistic.addType(it.name);
20 ]
21 // add all elements
22 val elements = getElements(partial);
23 for(element : elements){
24 statistic.addNode(element)
25 }
26
27 for(relationInterpretation : partial.partialrelationinterpretation) {
28 val type = relationInterpretation.interpretationOf.name
29
30 for(edge : relationInterpretation.relationlinks.filter(BinaryElementRelationLink)){
31 statistic.addEdge(edge.param1, edge.param2, type);
32 }
33 }
34
35 this.name = name;
36 this.metrics = metrics;
37 }
38
39 /**
40 * Set basic information for the output
41 */
42 override setBasicInformation(ArrayList<ArrayList<String>> output){
43 val metaInfo = new ArrayList<String>();
44 metaInfo.add(META_MODEL_HEADER);
45 metaInfo.add(this.metaModel);
46
47 val edgeInfo = new ArrayList<String>();
48 edgeInfo.add(NUM_EDGE_TYPE_HEADER);
49 edgeInfo.add(this.statistic.allTypes.size()+"");
50
51 val nodeInfo = new ArrayList<String>();
52 nodeInfo.add(NUM_NODE_HEADER);
53 nodeInfo.add(this.statistic.allNodes.size()+"");
54
55 val stateInfo = new ArrayList<String>();
56 stateInfo.add(STATE_ID_HEADER);
57 stateInfo.add(this.name);
58
59 output.add(metaInfo);
60 output.add(edgeInfo);
61 output.add(nodeInfo);
62 output.add(stateInfo);
63 }
64
65 private def getElements(PartialInterpretation partial){
66 return partial.newElements.filter[!(it instanceof BooleanElementImpl)] + partial.problem.elements;
67 }
68
69 override getStatistic() {
70 throw new UnsupportedOperationException("TODO: auto-generated method stub")
71 }
72
73 override getName() {
74 return name;
75 }
76
77} \ 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/io/CsvFileWriter.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/io/CsvFileWriter.xtend
new file mode 100644
index 00000000..bed356e9
--- /dev/null
+++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/io/CsvFileWriter.xtend
@@ -0,0 +1,37 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io;
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}
diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/io/GraphReader.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/io/GraphReader.xtend
new file mode 100644
index 00000000..fc56e142
--- /dev/null
+++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/io/GraphReader.xtend
@@ -0,0 +1,81 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io;
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/io/RepMetricsReader.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/io/RepMetricsReader.xtend
new file mode 100644
index 00000000..867ddd1a
--- /dev/null
+++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/io/RepMetricsReader.xtend
@@ -0,0 +1,79 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app.Domain
4import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric
5import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric
6import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric
7import java.io.File
8import java.util.List
9import java.util.Scanner
10import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MetricSampleGroup
11
12/**
13 * Read the sample of the distribution of a metric provided the csv file of the metric
14 */
15class RepMetricsReader {
16 static def read(Domain d){
17 var domainRepPath = CsvDataName.REP_PATH + d.name + '/';
18 var rep = new MetricSampleGroup()
19 rep.mpcSamples = readFile(domainRepPath + CsvDataName.MPC_REP, MultiplexParticipationCoefficientMetric.valueName,
20 MultiplexParticipationCoefficientMetric.countName).map[Double.parseDouble(it)];
21 rep.naSamples = readFile(domainRepPath+CsvDataName.NA_REP, NodeActivityMetric.valueName, NodeActivityMetric.countName
22 ).map[Double.parseDouble(it)];
23 rep.outDegreeSamples = readFile(domainRepPath+CsvDataName.OUT_D_REP, OutDegreeMetric.valueName, OutDegreeMetric.countName
24 ).map[Double.parseDouble(it)];
25 return rep;
26 }
27
28 /**
29 * read metric data and parse it to samples
30 */
31 private static def List<String> readFile(String filename, String valueDataName, String countDataName){
32 var s = new Scanner(new File(filename));
33 val counts = newArrayList();
34 val values = newArrayList();
35 //read data from csv
36 while(s.hasNext()){
37 var data = s.nextLine().split(',');
38
39 if(data.size >= 1){
40 if(data.get(0).equals(countDataName)){
41 //add all data with parsing them as integers
42 counts.addAll(data.subList(1, data.size()).map[Integer.parseInt(it)]);
43 }else if(data.get(0).equals(valueDataName)){
44 //add all data without parsing (there can be either double or string, to be parsed later)
45 values.addAll(data.subList(1, data.size()));
46 }
47 }
48 }
49
50 return createSamples(counts, values);
51 }
52
53 // create samples from values and counts
54 private static def List<String> createSamples(List<Integer> counts, List<String> values){
55 val samples = newArrayList();
56
57 if(counts.size() != values.size()){
58 throw new RuntimeException("counts and values should have the same size!");
59 }
60
61 for(var i = 0; i < counts.size(); i++){
62 for(var j = 0; j < counts.get(i); j++){
63 samples.add(values.get(i));
64 }
65 }
66
67 return samples;
68 }
69
70
71}
72
73class CsvDataName{
74 public static val REP_PATH = 'data/';
75 public static val MPC_REP = 'mpc_rep.csv';
76 public static val NA_REP = 'na_rep.csv';
77 public static val OUT_D_REP = 'out_d_rep.csv';
78}
79
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..38ef72f2
--- /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,8 @@
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 abstract def double[] evaluateSamples(GraphStatistic g);
8} \ 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/MetricSampleGroup.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/MetricSampleGroup.xtend
new file mode 100644
index 00000000..8cd3daee
--- /dev/null
+++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/MetricSampleGroup.xtend
@@ -0,0 +1,9 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics
2
3import java.util.List
4
5class MetricSampleGroup{
6 public var List<Double> mpcSamples;
7 public var List<Double> naSamples;
8 public var List<Double> outDegreeSamples;
9} \ 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..d9c88bb4
--- /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,80 @@
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.ArrayList
6import java.util.HashMap
7import org.eclipse.emf.ecore.EObject
8
9class MultiplexParticipationCoefficientMetric extends Metric {
10 public static val countName = "MPCCount";
11 public static val valueName = "MPCValue";
12
13
14 override evaluate(GraphStatistic g) {
15 //because the precision issue of double, we translate double values into String to be the key
16 val formatter = new DecimalFormat("#0.00000");
17
18 //get number of different types
19 val typeCounts = g.allTypes.size;
20 val map = new HashMap<String, Integer>();
21 //calculate the metric distribution
22 g.allNodes.forEach[n|
23 var coef = calculateMPC(n, g, typeCounts);
24
25 //format number to String
26 val value = formatter.format(coef);
27 if(!map.containsKey(value)){
28 map.put(value, 1);
29 }else{
30 map.put(value, map.get(value) + 1);
31 }
32
33 ]
34
35 //convert it into a 2 dimentional array
36 val String[][] datas = newArrayOfSize(2, map.size+1);
37 datas.get(0).set(0, valueName);
38 datas.get(1).set(0, countName)
39 var count = 1;
40 for(entry : map.entrySet.sortBy[it.key]){
41 datas.get(0).set(count, entry.key+"");
42 datas.get(1).set(count, entry.value+"");
43 count++;
44 }
45
46 return datas;
47 }
48
49 override evaluateSamples(GraphStatistic g){
50 val samples = new ArrayList<Double>();
51 val typeCounts = g.allTypes.size;
52 //calculate the metric distribution
53 g.allNodes.forEach[
54 samples.add(calculateMPC(it, g, typeCounts));
55 ]
56
57 return samples;
58 }
59
60 def double calculateMPC(EObject n, GraphStatistic g, int typeCounts){
61 val edgeCounts = g.outDegree(n) + g.inDegree(n);
62
63 var coef = 0.0;
64
65 for(type : g.allTypes){
66 val degree = g.dimentionalDegree(n, type) as double;
67 coef += Math.pow(degree / edgeCounts, 2);
68 }
69 coef = 1 - coef;
70 coef = coef * typeCounts / (typeCounts-1);
71
72 //Consider the case that either typeCounts-1 or the edgeCounts could be 0 in some situation
73 //in this case the metric should be evaluated to 0
74 if(Double.isNaN(coef)){
75 coef = 0;
76 }
77
78 return coef;
79 }
80} \ 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..fbf06c47
--- /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,49 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic
4import java.util.ArrayList
5import java.util.HashMap
6
7class NodeActivityMetric extends Metric {
8 public static val countName = "NACount";
9 public static val valueName = "NAValue";
10
11 override evaluate(GraphStatistic g) {
12 val map = new HashMap<Integer, Integer>();
13
14 //calculate the metric distribution
15 g.allNodes.forEach[
16 val value = g.numOfEdgeTypes(it);
17 if(!map.containsKey(value)){
18 map.put(value, 1);
19 }else{
20 map.put(value, map.get(value) + 1);
21 }
22 ]
23
24 //convert it into a 2 dimentional array
25 val String[][] datas = newArrayOfSize(2, map.size+1);
26 datas.get(0).set(0, valueName);
27 datas.get(1).set(0, countName)
28
29 var count = 1;
30 for(entry : map.entrySet.sortBy[it.key]){
31 datas.get(0).set(count, entry.key+"");
32 datas.get(1).set(count, entry.value+"");
33 count++;
34 }
35
36 return datas;
37 }
38
39 override evaluateSamples(GraphStatistic g){
40 val samples = new ArrayList<Double>();
41
42 //calculate the metric distribution
43 g.allNodes.forEach[
44 samples.add(g.numOfEdgeTypes(it) as double);
45 ]
46
47 return samples;
48 }
49} \ 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..55046b14
--- /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,49 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic
4import java.util.ArrayList
5import java.util.HashMap
6
7class OutDegreeMetric extends Metric {
8 public static val countName = "OutDegreeCount";
9 public static val valueName = "OutDegreeValue";
10
11 override evaluate(GraphStatistic g) {
12 val map = new HashMap<Integer, Integer>();
13
14 //calculate the metric distribution
15 g.allNodes.forEach[
16 val value = g.outDegree(it);
17 if(!map.containsKey(value)){
18 map.put(value, 1);
19 }else{
20 map.put(value, map.get(value) + 1);
21 }
22 ]
23
24 //convert it into a 2 dimentional array
25 val String[][] datas = newArrayOfSize(2, map.size+1);
26 datas.get(0).set(0, valueName);
27 datas.get(1).set(0, countName)
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
38 override evaluateSamples(GraphStatistic g){
39 val samples = new ArrayList<Double>();
40
41 //calculate the metric distribution
42 g.allNodes.forEach[
43 samples.add(g.outDegree(it) as double);
44 ]
45
46 return samples;
47 }
48
49} \ No newline at end of file