aboutsummaryrefslogtreecommitdiffstats
path: root/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse
diff options
context:
space:
mode:
authorLibravatar 20001LastOrder <boqi.chen@mail.mcgill.ca>2019-06-13 15:29:33 -0400
committerLibravatar 20001LastOrder <boqi.chen@mail.mcgill.ca>2019-06-13 15:29:33 -0400
commitd40cfffcbb0a36140fe6b1e7d95d4254358863e7 (patch)
treef8d658ee489b2a7c87be33361a7cce2a67b640f8 /Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse
parentMerge branch 'master' into Realistic-Generation-SURE (diff)
downloadVIATRA-Generator-d40cfffcbb0a36140fe6b1e7d95d4254358863e7.tar.gz
VIATRA-Generator-d40cfffcbb0a36140fe6b1e7d95d4254358863e7.tar.zst
VIATRA-Generator-d40cfffcbb0a36140fe6b1e7d95d4254358863e7.zip
Hill climbing for realistic graphs with consistency feature
Diffstat (limited to 'Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse')
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/Main.xtend2
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/PartialInterpretationMetric.xtend27
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/distance/JSDistance.xtend95
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/distance/KSDistance.xtend2
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/io/CsvFileWriter.xtend2
5 files changed, 121 insertions, 7 deletions
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
index cf871ead..1745bc35 100644
--- 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
@@ -35,7 +35,7 @@ class Main {
35 35
36 //human input has different package declaration 36 //human input has different package declaration
37// reader = new GraphReader(Yakindumm2PackageImpl.eINSTANCE); 37// reader = new GraphReader(Yakindumm2PackageImpl.eINSTANCE);
38 val human = new RWInformation("inputs/Random/", "outputs/", 1); 38 val human = new RWInformation("inputs/Fake_Random_Random/", "outputs/", 1);
39 calculateAllModels(human.inputFolder, human.outputFolder,human.numRuns, reader); 39 calculateAllModels(human.inputFolder, human.outputFolder,human.numRuns, reader);
40 40
41 41
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
index cdd06027..71fa5fed 100644
--- 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
@@ -1,5 +1,6 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app 1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app
2 2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance.JSDistance
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance.KSDistance 4import 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.graph.PartialInterpretationGraph
5import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.CsvFileWriter 6import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.CsvFileWriter
@@ -17,13 +18,14 @@ import org.eclipse.emf.ecore.util.EcoreUtil
17import org.eclipse.viatra.dse.api.Solution 18import org.eclipse.viatra.dse.api.Solution
18 19
19class PartialInterpretationMetric { 20class PartialInterpretationMetric {
20 var static state = 0;
21 var static KSDistance ks; 21 var static KSDistance ks;
22 var static JSDistance js;
22 23
23 def static void initPaths(){ 24 def static void initPaths(){
24 new File("debug/metric/").mkdir(); 25 new File("debug/metric/").mkdir();
25 new File("debug/metric/trajectories/").mkdir(); 26 new File("debug/metric/trajectories/").mkdir();
26 ks = new KSDistance(Domain.Yakinduum); 27 ks = new KSDistance(Domain.Yakinduum);
28 js = new JSDistance(Domain.Yakinduum);
27 } 29 }
28 30
29 def static MetricDistanceGroup calculateMetricDistance(PartialInterpretation partial){ 31 def static MetricDistanceGroup calculateMetricDistance(PartialInterpretation partial){
@@ -35,6 +37,22 @@ class PartialInterpretationMetric {
35 val metricCalculator = new PartialInterpretationGraph(partial, metrics, null); 37 val metricCalculator = new PartialInterpretationGraph(partial, metrics, null);
36 var metricSamples = metricCalculator.evaluateAllMetricsToSamples(); 38 var metricSamples = metricCalculator.evaluateAllMetricsToSamples();
37 39
40 var mpc = js.mpcDistance(metricSamples.mpcSamples);
41 var na = js.naDistance(metricSamples.naSamples);
42 var outDegree = js.outDegreeDistance(metricSamples.outDegreeSamples);
43
44 return new MetricDistanceGroup(mpc, na, outDegree);
45 }
46
47 def static MetricDistanceGroup calculateMetricDistanceKS(PartialInterpretation partial){
48 val metrics = new ArrayList<Metric>();
49 metrics.add(new OutDegreeMetric());
50 metrics.add(new NodeActivityMetric());
51 metrics.add(new MultiplexParticipationCoefficientMetric());
52
53 val metricCalculator = new PartialInterpretationGraph(partial, metrics, null);
54 var metricSamples = metricCalculator.evaluateAllMetricsToSamples();
55
38 var mpc = ks.mpcDistance(metricSamples.mpcSamples); 56 var mpc = ks.mpcDistance(metricSamples.mpcSamples);
39 var na = ks.naDistance(metricSamples.naSamples); 57 var na = ks.naDistance(metricSamples.naSamples);
40 var outDegree = ks.outDegreeDistance(metricSamples.outDegreeSamples); 58 var outDegree = ks.outDegreeDistance(metricSamples.outDegreeSamples);
@@ -52,7 +70,6 @@ class PartialInterpretationMetric {
52 //make dir since the folder can be none existing 70 //make dir since the folder can be none existing
53 new File(path).mkdir(); 71 new File(path).mkdir();
54 val filename = path + "/state_"+currentStateId+"-"+counter+".csv"; 72 val filename = path + "/state_"+currentStateId+"-"+counter+".csv";
55 state++;
56 val metricCalculator = new PartialInterpretationGraph(partial, metrics, currentStateId); 73 val metricCalculator = new PartialInterpretationGraph(partial, metrics, currentStateId);
57 74
58 CsvFileWriter.write(metricCalculator.evaluateAllMetrics(), filename); 75 CsvFileWriter.write(metricCalculator.evaluateAllMetrics(), filename);
@@ -60,20 +77,22 @@ class PartialInterpretationMetric {
60 77
61 def static void outputTrajectories(PartialInterpretation empty, List<Solution> solutions){ 78 def static void outputTrajectories(PartialInterpretation empty, List<Solution> solutions){
62 for(solution : solutions){ 79 for(solution : solutions){
80
63 //need to copy the empty solution because the transition directly worked on the graph 81 //need to copy the empty solution because the transition directly worked on the graph
64 val emptySolutionCopy = EcoreUtil.copy(empty) 82 val emptySolutionCopy = EcoreUtil.copy(empty)
65 val trajectory = solution.shortestTrajectory; 83 val trajectory = solution.shortestTrajectory;
66 trajectory.modelWithEditingDomain = emptySolutionCopy 84 trajectory.model = emptySolutionCopy
67 85
68 // state codes that will record the trajectory 86 // state codes that will record the trajectory
69 val stateCodes = newArrayList() 87 val stateCodes = newArrayList()
70
71 var counter = 0 88 var counter = 0
89
72 //transform and record the state codes for each state 90 //transform and record the state codes for each state
73 while(trajectory.doNextTransformation){ 91 while(trajectory.doNextTransformation){
74 //println(trajectory.stateCoder.createStateCode) 92 //println(trajectory.stateCoder.createStateCode)
75 val stateId = trajectory.stateCoder.createStateCode.toString 93 val stateId = trajectory.stateCoder.createStateCode.toString
76 val interpretation = trajectory.getModel(); 94 val interpretation = trajectory.getModel();
95 println(stateId)
77 //calculate metrics of current state 96 //calculate metrics of current state
78 calculateMetric(interpretation as PartialInterpretation, "debug/metric/output", stateId, counter) 97 calculateMetric(interpretation as PartialInterpretation, "debug/metric/output", stateId, counter)
79 stateCodes.add(stateId) 98 stateCodes.add(stateId)
diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/distance/JSDistance.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/distance/JSDistance.xtend
new file mode 100644
index 00000000..ced9eadb
--- /dev/null
+++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/distance/JSDistance.xtend
@@ -0,0 +1,95 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app.Domain
4import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.RepMetricsReader
5import com.google.common.collect.Sets
6import java.text.DecimalFormat
7import java.util.HashMap
8import java.util.List
9
10class JSDistance {
11 var HashMap<String, Double> mpcPMF;
12 var HashMap<String, Double> naPMF;
13 var HashMap<String, Double> outDegreePMF;
14 var DecimalFormat formatter;
15
16 new(Domain d){
17 var metrics = RepMetricsReader.read(d);
18 var mpcSamples = metrics.mpcSamples;
19 var naSamples = metrics.naSamples.stream.mapToDouble([it]).toArray();
20 var outDegreeSamples = metrics.outDegreeSamples.stream.mapToDouble([it]).toArray();
21
22 //needs to format the number to string avoid precision issue
23 formatter = new DecimalFormat("#0.00000");
24
25 mpcPMF = pmfFromSamples(mpcSamples, formatter);
26 naPMF = pmfFromSamples(naSamples, formatter);
27 outDegreePMF = pmfFromSamples(outDegreeSamples, formatter);
28 }
29
30 def private pmfFromSamples(double[] samples, DecimalFormat formatter){
31 var length = samples.length;
32 var pmfMap = new HashMap<String, Double>();
33
34 for(sample : samples){
35 pmfMap.put(formatter.format(sample), pmfMap.getOrDefault(formatter.format(sample), 0.0) + 1.0 / length);
36 }
37
38 return pmfMap;
39 }
40
41 def private combinePMF(HashMap<String, Double> pmf1, HashMap<String, Double> pmf2){
42 var pmfMap = new HashMap<String, Double>();
43
44 var union = Sets.union(pmf1.keySet(), pmf2.keySet());
45
46 for(key : union){
47 // corresponding to M in JS distance
48 var value = 1.0/2 * (pmf1.getOrDefault(key, 0.0) + pmf2.getOrDefault(key, 0.0));
49 pmfMap.put(key, value);
50 }
51 return pmfMap;
52 }
53
54 def private jsDivergence(HashMap<String, Double> p, HashMap<String, Double> q){
55 val m = combinePMF(q, p);
56 var distance = 1.0/2 * klDivergence(p, m) + 1.0/2 * klDivergence(q, m);
57 return distance;
58 }
59
60 def klDivergence(HashMap<String, Double> p, HashMap<String, Double> q){
61 var distance = 0.0;
62 for(key : q.keySet()){
63 //need to convert log e to log 2
64 if(p.containsKey(key)){
65 distance -= p.get(key) * Math.log(q.get(key) / p.get(key)) / Math.log(2);
66 }
67 }
68 return distance;
69 }
70
71 def double mpcDistance(List<Double> samples){
72 // map list to array
73 var map = pmfFromSamples(samples.stream().mapToDouble([it]).toArray(), formatter);
74 //if the size of array is smaller than 2, ks distance cannot be performed, simply return 1
75 if(map.size < 2) return 1;
76 return jsDivergence(map, mpcPMF);
77 }
78
79 def double naDistance(List<Double> samples){
80 // map list to array
81 var map = pmfFromSamples(samples.stream().mapToDouble([it]).toArray(), formatter);
82
83 //if the size of array is smaller than 2, ks distance cannot be performed, simply return 1
84 if(map.size < 2) return 1;
85 return jsDivergence(map, naPMF);
86 }
87
88 def double outDegreeDistance(List<Double> samples){
89 // map list to array
90 var map = pmfFromSamples(samples.stream().mapToDouble([it]).toArray(), formatter);
91 //if the size of array is smaller than 2, ks distance cannot be performed, simply return 1
92 if(map.size < 2) return 1;
93 return jsDivergence(map, outDegreePMF);
94 }
95} \ 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
index 1fb21529..58e0a8a3 100644
--- 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
@@ -1,9 +1,9 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance 1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance
2 2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app.Domain 3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app.Domain
4import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.RepMetricsReader
4import java.util.List 5import java.util.List
5import org.apache.commons.math3.stat.inference.KolmogorovSmirnovTest 6import org.apache.commons.math3.stat.inference.KolmogorovSmirnovTest
6import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.RepMetricsReader
7 7
8class KSDistance { 8class KSDistance {
9 var static ksTester = new KolmogorovSmirnovTest(); 9 var static ksTester = new KolmogorovSmirnovTest();
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
index bed356e9..01e3940b 100644
--- 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
@@ -21,7 +21,7 @@ class CsvFileWriter {
21 output.append(datarow.get(i) + ','); 21 output.append(datarow.get(i) + ',');
22 } 22 }
23 23
24 if(datarow.size > 1){ 24 if(datarow.size >= 1){
25 output.append(datarow.get(datarow.size() - 1)); 25 output.append(datarow.get(datarow.size() - 1));
26 output.append('\n'); 26 output.append('\n');
27 } 27 }