diff options
Diffstat (limited to 'Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic')
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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app | ||
2 | |||
3 | enum 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app | ||
2 | |||
3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.EMFGraph | ||
4 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.CsvFileWriter | ||
5 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.GraphReader | ||
6 | import hu.bme.mit.inf.dslreasoner.domains.yakindu.sgraph.yakindumm.impl.YakindummPackageImpl | ||
7 | import java.util.ArrayList | ||
8 | |||
9 | //import yakindumm2.impl.Yakindumm2PackageImpl | ||
10 | |||
11 | class 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app | ||
2 | |||
3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance.KSDistance | ||
4 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.PartialInterpretationGraph | ||
5 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.CsvFileWriter | ||
6 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric | ||
7 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric | ||
8 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric | ||
9 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric | ||
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
11 | import java.io.File | ||
12 | import java.io.FileNotFoundException | ||
13 | import java.io.PrintWriter | ||
14 | import java.util.ArrayList | ||
15 | import java.util.List | ||
16 | import org.eclipse.emf.ecore.util.EcoreUtil | ||
17 | import org.eclipse.viatra.dse.api.Solution | ||
18 | |||
19 | class 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 | |||
102 | class 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance | ||
2 | |||
3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app.Domain | ||
4 | import java.util.List | ||
5 | import org.apache.commons.math3.stat.inference.KolmogorovSmirnovTest | ||
6 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.RepMetricsReader | ||
7 | |||
8 | class 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph | ||
2 | |||
3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric | ||
4 | import java.util.ArrayList | ||
5 | import java.util.List | ||
6 | import org.eclipse.emf.common.util.EList | ||
7 | import org.eclipse.emf.ecore.EObject | ||
8 | import org.eclipse.emf.ecore.EReference | ||
9 | |||
10 | class 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph | ||
2 | |||
3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric | ||
4 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MetricSampleGroup | ||
5 | import java.util.ArrayList | ||
6 | import java.util.List | ||
7 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric | ||
8 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric | ||
9 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric | ||
10 | |||
11 | abstract 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph | ||
2 | |||
3 | import com.google.common.collect.ArrayListMultimap | ||
4 | import com.google.common.collect.Multimap | ||
5 | import java.util.HashMap | ||
6 | import java.util.HashSet | ||
7 | import java.util.List | ||
8 | import org.eclipse.emf.ecore.EObject | ||
9 | |||
10 | class 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph | ||
2 | |||
3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric | ||
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BinaryElementRelationLink | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.BooleanElementImpl | ||
8 | import java.util.ArrayList | ||
9 | import java.util.List | ||
10 | |||
11 | class 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io; | ||
2 | |||
3 | import java.io.File | ||
4 | import java.io.FileNotFoundException | ||
5 | import java.io.PrintWriter | ||
6 | import java.util.ArrayList | ||
7 | import java.util.List | ||
8 | |||
9 | class 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io; | ||
2 | |||
3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.EMFGraph | ||
4 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric | ||
5 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric | ||
6 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric | ||
7 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric | ||
8 | import java.io.File | ||
9 | import java.io.FileNotFoundException | ||
10 | import java.util.ArrayList | ||
11 | import java.util.List | ||
12 | import org.eclipse.emf.common.util.URI | ||
13 | import org.eclipse.emf.ecore.EObject | ||
14 | import org.eclipse.emf.ecore.EPackage | ||
15 | import org.eclipse.emf.ecore.EReference | ||
16 | import org.eclipse.emf.ecore.resource.Resource | ||
17 | import org.eclipse.emf.ecore.resource.ResourceSet | ||
18 | import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl | ||
19 | import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl | ||
20 | |||
21 | class 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io | ||
2 | |||
3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app.Domain | ||
4 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric | ||
5 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric | ||
6 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric | ||
7 | import java.io.File | ||
8 | import java.util.List | ||
9 | import java.util.Scanner | ||
10 | import 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 | */ | ||
15 | class 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 | |||
73 | class 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics | ||
2 | |||
3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic | ||
4 | |||
5 | abstract 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics | ||
2 | |||
3 | import java.util.List | ||
4 | |||
5 | class 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics | ||
2 | |||
3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic | ||
4 | import java.text.DecimalFormat | ||
5 | import java.util.ArrayList | ||
6 | import java.util.HashMap | ||
7 | import org.eclipse.emf.ecore.EObject | ||
8 | |||
9 | class 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics | ||
2 | |||
3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic | ||
4 | import java.util.ArrayList | ||
5 | import java.util.HashMap | ||
6 | |||
7 | class 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics | ||
2 | |||
3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic | ||
4 | import java.util.ArrayList | ||
5 | import java.util.HashMap | ||
6 | |||
7 | class 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 | ||