diff options
author | 20001LastOrder <boqi.chen@mail.mcgill.ca> | 2019-06-13 15:29:33 -0400 |
---|---|---|
committer | 20001LastOrder <boqi.chen@mail.mcgill.ca> | 2019-06-13 15:29:33 -0400 |
commit | d40cfffcbb0a36140fe6b1e7d95d4254358863e7 (patch) | |
tree | f8d658ee489b2a7c87be33361a7cce2a67b640f8 /Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill | |
parent | Merge branch 'master' into Realistic-Generation-SURE (diff) | |
download | VIATRA-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')
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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app | 1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app |
2 | 2 | ||
3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance.JSDistance | ||
3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance.KSDistance | 4 | 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.graph.PartialInterpretationGraph |
5 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.CsvFileWriter | 6 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.CsvFileWriter |
@@ -17,13 +18,14 @@ import org.eclipse.emf.ecore.util.EcoreUtil | |||
17 | import org.eclipse.viatra.dse.api.Solution | 18 | import org.eclipse.viatra.dse.api.Solution |
18 | 19 | ||
19 | class PartialInterpretationMetric { | 20 | class 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance | ||
2 | |||
3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app.Domain | ||
4 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.RepMetricsReader | ||
5 | import com.google.common.collect.Sets | ||
6 | import java.text.DecimalFormat | ||
7 | import java.util.HashMap | ||
8 | import java.util.List | ||
9 | |||
10 | class 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 @@ | |||
1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance | 1 | package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance |
2 | 2 | ||
3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app.Domain | 3 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app.Domain |
4 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.RepMetricsReader | ||
4 | import java.util.List | 5 | import java.util.List |
5 | import org.apache.commons.math3.stat.inference.KolmogorovSmirnovTest | 6 | import org.apache.commons.math3.stat.inference.KolmogorovSmirnovTest |
6 | import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.RepMetricsReader | ||
7 | 7 | ||
8 | class KSDistance { | 8 | class 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 | } |