aboutsummaryrefslogtreecommitdiffstats
path: root/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app
diff options
context:
space:
mode:
authorLibravatar 20001LastOrder <boqi.chen@mail.mcgill.ca>2020-11-03 22:52:26 -0500
committerLibravatar 20001LastOrder <boqi.chen@mail.mcgill.ca>2020-11-03 22:52:26 -0500
commit945f487a08b643392a5d5918c631640b9a0e4605 (patch)
treeb537c456e395950ce98daaabb9468c7c17d5a72b /Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app
parentFix numeric-solver-at-end (diff)
downloadVIATRA-Generator-945f487a08b643392a5d5918c631640b9a0e4605.tar.gz
VIATRA-Generator-945f487a08b643392a5d5918c631640b9a0e4605.tar.zst
VIATRA-Generator-945f487a08b643392a5d5918c631640b9a0e4605.zip
add realistic solver
Diffstat (limited to 'Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app')
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/Domain.xtend7
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/Main.xtend96
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/PartialInterpretationMetric.xtend85
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/PartialInterpretationMetricDistance.xtend216
4 files changed, 404 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..c8fd435b
--- /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,7 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app
2
3enum Domain{
4 Yakindumm,
5 Ecore,
6 Github
7} \ No newline at end of file
diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/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..dfde6593
--- /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,96 @@
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 ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.validation.ViolationCheck
7import hu.bme.mit.inf.dslreasoner.domains.yakindu.sgraph.yakindumm.impl.YakindummPackageImpl
8import java.io.File
9import java.util.ArrayList
10import org.eclipse.emf.ecore.EPackage
11import org.eclipse.emf.ecore.EcorePackage
12import org.eclipse.viatra.query.runtime.rete.matcher.ReteEngine
13import org.eclipse.emf.ecore.impl.EcorePackageImpl
14import org.eclipse.emf.ecore.EReference
15
16//import yakindumm2.impl.Yakindumm2PackageImpl
17
18class Main {
19 var static Domain d = Domain.Yakindumm;
20 val static String suffix = '.xmi'
21 val static String OUTPUT_FOLDER = "Inputs/measurement2/yakindu/Alloy/";
22 val static String INPUT_FOLDER = "outputs/measurement2/yakindu/Alloy/";
23 val static int NUM_RUNS = 1;
24
25 static class RWInformation{
26 public var String inputFolder;
27 public var String outputFolder;
28 public var int numRuns;
29
30 new(String inputFolder, String outputFolder, int numRuns){
31 this.inputFolder = inputFolder;
32 this.outputFolder = outputFolder;
33 this.numRuns = numRuns;
34 }
35 }
36
37 def static void main(String[] args){
38 //init model
39 var EPackage metamodel;
40 //init viatra engine for the violation checker
41 ReteEngine.getClass();
42
43 if(d == Domain.Yakindumm){
44 YakindummPackageImpl.eINSTANCE.eClass;
45 metamodel = YakindummPackageImpl.eINSTANCE;
46 }else if (d == Domain.Ecore){
47 EcorePackage.eINSTANCE.eClass;
48 metamodel = EcorePackageImpl.eINSTANCE;
49 }else if (d == Domain.Github){
50 //TODO: Initialize Github Package
51 }
52
53
54 println("Start Reading Models...");
55 var reader = new GraphReader(metamodel, suffix);
56
57 val models = new RWInformation(OUTPUT_FOLDER, INPUT_FOLDER, NUM_RUNS);
58 calculateAllModels(models.inputFolder, models.outputFolder,models.numRuns, reader);
59 println("finished");
60 }
61
62 static def calculateAllModels(String inputFolder, String outputFolder, int numRuns, GraphReader reader){
63 (new File(outputFolder)).mkdir();
64 for(var i = 1; i <= numRuns; i++){
65 val models = new ArrayList<EMFGraph>();
66 models.addAll(reader.readModels(inputFolder + "run" + i));
67 for(model : models){
68 calculateAndOutputMetrics(model, YakindummPackageImpl.eNAME, outputFolder+model.name+"_run_"+i+".csv");
69 }
70 }
71 println("output results Ended for: " + outputFolder);
72
73
74 }
75
76 static def calculateAndOutputMetrics(EMFGraph model, String metaModel, String fileName){
77 //println("evaluating for " + model.name);
78 model.metaModel = metaModel;
79
80 //remove eGenericType for Ecore domain
81 if(d == Domain.Ecore){
82 var refsToRemove = EcorePackageImpl.eINSTANCE.eAllContents.filter(EReference).filter[
83 it.name.equals('eGenericType') || it.name.equals('eGenericSuperTypes') || it.name.equals('eFactoryInstance')||
84 it.name.equals('eGenericExceptions') || it.name.equals('references') || it.name.equals('contents');
85 ];
86 refsToRemove.forEach[model.removeReference(it)];
87 }
88
89 var outputs = model.evaluateAllMetrics();
90 var violations = ViolationCheck.calculateViolationCounts(model.root, d);
91 println(violations);
92 var violationsOutput = newArrayList('violations', violations+'');
93 outputs.add(violationsOutput);
94 CsvFileWriter.write(outputs, fileName);
95 }
96} \ 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..5e62b586
--- /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,85 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance.JSDistance
4import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance.KSDistance
5import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.PartialInterpretationGraph
6import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.CsvFileWriter
7import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric
8import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric
9import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric
10import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric
11import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
12import java.io.File
13import java.io.FileNotFoundException
14import java.io.PrintWriter
15import java.util.ArrayList
16import java.util.List
17import org.eclipse.emf.ecore.util.EcoreUtil
18import org.eclipse.viatra.dse.api.Solution
19
20class PartialInterpretationMetric {
21 var static KSDistance ks;
22 var static JSDistance js;
23
24 def static void initPaths(){
25 new File("debug/metric/").mkdir();
26 new File("debug/metric/trajectories/").mkdir();
27 }
28
29 // calculate the metrics for a state
30 def static void calculateMetric(PartialInterpretation partial, String path, String currentStateId, Integer counter){
31 val metrics = new ArrayList<Metric>();
32 metrics.add(new OutDegreeMetric());
33 metrics.add(new NodeActivityMetric());
34 metrics.add(new MultiplexParticipationCoefficientMetric());
35
36 //make dir since the folder can be none existing
37 new File(path).mkdir();
38 val filename = path + "/state_"+currentStateId+"-"+counter+".csv";
39 val metricCalculator = new PartialInterpretationGraph(partial, metrics, currentStateId);
40
41 CsvFileWriter.write(metricCalculator.evaluateAllMetrics(), filename);
42 }
43
44 def static void outputTrajectories(PartialInterpretation empty, List<Solution> solutions){
45 for(solution : solutions){
46
47 //need to copy the empty solution because the transition directly worked on the graph
48 val emptySolutionCopy = EcoreUtil.copy(empty)
49 val trajectory = solution.shortestTrajectory;
50 trajectory.model = emptySolutionCopy
51
52 // state codes that will record the trajectory
53 val stateCodes = newArrayList()
54 var counter = 0
55
56 //transform and record the state codes for each state
57 while(trajectory.doNextTransformation){
58 //println(trajectory.stateCoder.createStateCode)
59 val stateId = trajectory.stateCoder.createStateCode.toString
60 val interpretation = trajectory.getModel();
61 println(stateId)
62 //calculate metrics of current state
63 calculateMetric(interpretation as PartialInterpretation, "debug/metric/output", stateId, counter)
64 stateCodes.add(stateId)
65 counter++
66 }
67
68
69 //output the trajectory
70 try{
71 new File("debug/metric/trajectories/").mkdir();
72 val path = "debug/metric/trajectories/trajectory"+trajectory.stateCoder.createStateCode.toString+".csv"
73 val PrintWriter writer = new PrintWriter(new File(path))
74 val output = new StringBuilder
75 for(stateCode : stateCodes){
76 output.append(stateCode+'\n')
77 }
78 writer.write(output.toString())
79 writer.close()
80 }catch(FileNotFoundException e) {
81 e.printStackTrace()
82 }
83 }
84 }
85} \ 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/PartialInterpretationMetricDistance.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/PartialInterpretationMetricDistance.xtend
new file mode 100644
index 00000000..697b2639
--- /dev/null
+++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/PartialInterpretationMetricDistance.xtend
@@ -0,0 +1,216 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance.EuclideanDistance
4import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance.JSDistance
5import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance.KSDistance
6import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance.StateData
7import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.PartialInterpretationGraph
8import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.RepMetricsReader
9import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric
10import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MetricSampleGroup
11import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric
12import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric
13import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeTypeMetric
14import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric
15import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.predictor.LinearModel
16import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
17import java.util.ArrayList
18import java.util.HashMap
19import java.util.List
20import java.util.Map
21import org.apache.commons.math3.stat.regression.OLSMultipleLinearRegression
22import org.eclipse.xtend.lib.annotations.Accessors
23import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.EdgeTypeMetric
24
25class PartialInterpretationMetricDistance {
26
27 var KSDistance ks;
28 var JSDistance js;
29 var EuclideanDistance ed;
30 var Map<Object, StateData> stateAndHistory;
31 var OLSMultipleLinearRegression regression;
32 List<StateData> samples;
33 var MetricSampleGroup g;
34 @Accessors(PUBLIC_GETTER)
35 var LinearModel linearModel;
36
37
38 new(Domain d){
39 var metrics = RepMetricsReader.read(d);
40 this.g = metrics;
41 ks = new KSDistance(g);
42 js = new JSDistance(g);
43 ed = new EuclideanDistance(g);
44 regression = new OLSMultipleLinearRegression();
45 regression.noIntercept = false;
46 stateAndHistory = new HashMap<Object, StateData>();
47 samples = new ArrayList<StateData>();
48 linearModel = new LinearModel(0.01);
49 }
50
51 def MetricDistanceGroup calculateMetricDistanceKS(PartialInterpretation partial){
52 val metrics = new ArrayList<Metric>();
53 metrics.add(new OutDegreeMetric());
54 metrics.add(new NodeActivityMetric());
55 metrics.add(new MultiplexParticipationCoefficientMetric());
56 metrics.add(new NodeTypeMetric());
57 val metricCalculator = new PartialInterpretationGraph(partial, metrics, null);
58 var metricSamples = metricCalculator.evaluateAllMetricsToSamples();
59
60 var mpc = ks.mpcDistance(metricSamples.mpcSamples);
61 var na = ks.naDistance(metricSamples.naSamples);
62 var outDegree = ks.outDegreeDistance(metricSamples.outDegreeSamples);
63 var nodeType = ks.nodeTypeDistance(metricSamples.nodeTypeSamples);
64 //var typedOutDegree = ks.typedOutDegreeDistance(metricSamples.typedOutDegreeSamples);
65 var distance = new MetricDistanceGroup(mpc, na, outDegree, nodeType);
66 distance.nodeTypeInfo = metricSamples.nodeTypeSamples;
67 return distance;
68 }
69
70 def MetricDistanceGroup calculateMetricEuclidean(PartialInterpretation partial){
71 val metrics = new ArrayList<Metric>();
72 metrics.add(new OutDegreeMetric());
73 metrics.add(new NodeActivityMetric());
74 metrics.add(new MultiplexParticipationCoefficientMetric());
75
76 val metricCalculator = new PartialInterpretationGraph(partial, metrics, null);
77 var metricSamples = metricCalculator.evaluateAllMetricsToSamples();
78
79 var mpc = ed.mpcDistance(metricSamples.mpcSamples);
80 var na = ed.naDistance(metricSamples.naSamples);
81 var outDegree = ed.outDegreeDistance(metricSamples.outDegreeSamples);
82
83 return new MetricDistanceGroup(mpc, na, outDegree);
84 }
85
86 def MetricDistanceGroup calculateMetricDistance(PartialInterpretation partial){
87 val metrics = new ArrayList<Metric>();
88 metrics.add(new OutDegreeMetric());
89 metrics.add(new NodeActivityMetric());
90 metrics.add(new MultiplexParticipationCoefficientMetric());
91
92 val metricCalculator = new PartialInterpretationGraph(partial, metrics, null);
93 var metricSamples = metricCalculator.evaluateAllMetricsToSamples();
94
95 var mpc = js.mpcDistance(metricSamples.mpcSamples);
96 var na = js.naDistance(metricSamples.naSamples);
97 var outDegree = js.outDegreeDistance(metricSamples.outDegreeSamples);
98
99 return new MetricDistanceGroup(mpc, na, outDegree);
100 }
101
102 def resetRegression(Object state){
103 samples.clear();
104
105 if(stateAndHistory.containsKey(state)){
106 var data = stateAndHistory.get(state);
107
108 var curState = state;
109
110 samples.add(data);
111
112 while(stateAndHistory.containsKey(data.lastState) && data.lastState != curState){
113 curState = data.lastState;
114 data = stateAndHistory.get(data.lastState);
115 samples.add(data);
116 }
117
118 if(samples.size == 0){
119 println('state: ' + state);
120 println('last state: ' + data.lastState);
121 }
122 }
123 println("trajectory sample size:" + samples.size)
124 }
125
126 def feedData(Object state, double[] features, double value, Object lastState){
127 var data = new StateData(features, value, lastState);
128 stateAndHistory.put(state, data);
129 samples.add(data);
130 }
131
132 def getPredictionForNextDataSample(double[] features, double value, double[] featuresToPredict){
133 if(samples.size <= 4){
134 println('OK');
135 }
136 var data = new StateData(features, value, null);
137 samples.add(data);
138
139 // create training set from current data
140 var double[][] xSamples = samples.map[it.features];
141 var double[] ySamples = samples.map[it.value];
142
143
144 regression.newSampleData(ySamples, xSamples);
145 var prediction = predict(featuresToPredict);
146
147 //remove the last element just added
148 samples.remove(samples.size - 1);
149 return prediction;
150 }
151
152 def private predict(double[] featuresToPredict){
153 var parameters = regression.estimateRegressionParameters();
154 // the regression will add an initial column for 1's, the first parameter is constant term
155 var result = parameters.get(0);
156 for(var i = 0; i < featuresToPredict.length; i++){
157 result += parameters.get(i+1) * featuresToPredict.get(i);
158 }
159 return result;
160 }
161
162 def double[] calculateFeature(int step, int violations){
163 var features = newDoubleArrayOfSize(2);
164 //constant term
165 features.set(0, 1); //a
166 features.set(0, Math.sqrt(step) + 30) // b
167 features.set(1, 1.0 / (step + 30) );// c
168
169
170// features.set(2, violations);
171// features.set(3, Math.pow(violations, 2));
172
173 return features;
174 }
175}
176
177class MetricDistanceGroup{
178 var double mpcDistance;
179 var double naDistance;
180 var double outDegreeDistance;
181 var double nodeTypeDistance;
182 protected var HashMap<String, Double> nodeTypeInfo;
183
184 new(double mpcDistance, double naDistance, double outDegreeDistance, double nodeTypeDistance){
185 this.mpcDistance = mpcDistance;
186 this.naDistance = naDistance;
187 this.outDegreeDistance = outDegreeDistance;
188 this.nodeTypeDistance = nodeTypeDistance;
189 }
190
191 new(double mpcDistance, double naDistance, double outDegreeDistance){
192 this.mpcDistance = mpcDistance;
193 this.naDistance = naDistance;
194 this.outDegreeDistance = outDegreeDistance;
195 }
196
197 def double getNodeTypeDistance(){
198 return this.nodeTypeDistance;
199 }
200
201 def double getMPCDistance(){
202 return this.mpcDistance
203 }
204
205 def double getNADistance(){
206 return this.naDistance
207 }
208
209 def double getOutDegreeDistance(){
210 return this.outDegreeDistance
211 }
212
213 def double getNodeTypePercentage(String typeName){
214 return nodeTypeInfo.getOrDefault(typeName, 0.0);
215 }
216} \ No newline at end of file