From 98e0479f26ce0bc54016c4fba8e74e3223203b9a Mon Sep 17 00:00:00 2001 From: 20001LastOrder Date: Wed, 5 Jun 2019 11:38:23 -0400 Subject: plotting for metrics during generation --- .../.classpath | 2 + .../realistic/metrics/calculator/app/Domain.xtend | 5 + .../realistic/metrics/calculator/app/Main.xtend | 4 +- .../app/PartialInterpretationMetric.xtend | 45 ++++- .../metrics/calculator/distance/KSDistance.xtend | 47 +++++ .../realistic/metrics/calculator/graph/Graph.xtend | 20 ++ .../metrics/calculator/input/GraphReader.xtend | 81 -------- .../input/PartialInterpretationReader.xtend | 7 - .../metrics/calculator/io/CsvFileWriter.xtend | 37 ++++ .../metrics/calculator/io/GraphReader.xtend | 81 ++++++++ .../metrics/calculator/io/RepMetricsReader.xtend | 79 ++++++++ .../metrics/calculator/metrics/Metric.xtend | 1 + .../calculator/metrics/MetricSampleGroup.xtend | 9 + .../MultiplexParticipationCoefficientMetric.xtend | 59 +++--- .../calculator/metrics/NodeActivityMetric.xtend | 16 +- .../calculator/metrics/OutDegreeMetric.xtend | 15 +- .../metrics/calculator/output/CsvFileWriter.xtend | 37 ---- .../metrics_plot/model comparison/input/.gitignore | 3 + .../output/Human-Viatra (30 nodes)-/MPC.png | Bin 0 -> 99670 bytes .../Human-Viatra (30 nodes)-/Node Activity.png | Bin 0 -> 85981 bytes .../output/Human-Viatra (30 nodes)-/Out Degree.png | Bin 0 -> 78151 bytes .../model comparison/src/plot_ks_stats.py | 98 ++++++++++ .../output/Human-viatraEvolve-/MPC.png | Bin 114616 -> 0 bytes .../output/Human-viatraEvolve-/Node Activity.png | Bin 92967 -> 0 bytes .../output/Human-viatraEvolve-/Out Degree.png | Bin 118164 -> 0 bytes .../src/metrics_distance_with_selector.ipynb | 204 ++++++++++++++++++--- .../metrics_plot/utils/GraphType.py | 29 +++ .../metrics_plot/utils/constants.py | 25 +++ .../metrics_plot/utils/readCSV.py | 169 +++++++++++++++++ 29 files changed, 897 insertions(+), 176 deletions(-) create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/app/Domain.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/distance/KSDistance.xtend delete mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/GraphReader.xtend delete mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/PartialInterpretationReader.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/io/CsvFileWriter.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/io/GraphReader.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/io/RepMetricsReader.xtend create mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/metrics/MetricSampleGroup.xtend delete mode 100644 Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/output/CsvFileWriter.xtend create mode 100644 Metrics/Metrics-Calculation/metrics_plot/model comparison/input/.gitignore create mode 100644 Metrics/Metrics-Calculation/metrics_plot/model comparison/output/Human-Viatra (30 nodes)-/MPC.png create mode 100644 Metrics/Metrics-Calculation/metrics_plot/model comparison/output/Human-Viatra (30 nodes)-/Node Activity.png create mode 100644 Metrics/Metrics-Calculation/metrics_plot/model comparison/output/Human-Viatra (30 nodes)-/Out Degree.png create mode 100644 Metrics/Metrics-Calculation/metrics_plot/model comparison/src/plot_ks_stats.py delete mode 100644 Metrics/Metrics-Calculation/metrics_plot/output/Human-viatraEvolve-/MPC.png delete mode 100644 Metrics/Metrics-Calculation/metrics_plot/output/Human-viatraEvolve-/Node Activity.png delete mode 100644 Metrics/Metrics-Calculation/metrics_plot/output/Human-viatraEvolve-/Out Degree.png create mode 100644 Metrics/Metrics-Calculation/metrics_plot/utils/GraphType.py create mode 100644 Metrics/Metrics-Calculation/metrics_plot/utils/constants.py create mode 100644 Metrics/Metrics-Calculation/metrics_plot/utils/readCSV.py (limited to 'Metrics') diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.classpath b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.classpath index 428337e5..f4f8357b 100644 --- a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.classpath +++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/.classpath @@ -4,5 +4,7 @@ + + 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 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app + +enum Domain{ + Yakinduum +} \ 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 index 15df0dde..cf871ead 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 @@ -1,8 +1,8 @@ package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.EMFGraph -import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.input.GraphReader -import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.output.CsvFileWriter +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.CsvFileWriter +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.GraphReader import hu.bme.mit.inf.dslreasoner.domains.yakindu.sgraph.yakindumm.impl.YakindummPackageImpl import java.util.ArrayList 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 0e505d30..cdd06027 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,11 +1,12 @@ package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance.KSDistance import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.PartialInterpretationGraph +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.CsvFileWriter import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric -import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.output.CsvFileWriter import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation import java.io.File import java.io.FileNotFoundException @@ -17,10 +18,28 @@ import org.eclipse.viatra.dse.api.Solution class PartialInterpretationMetric { var static state = 0; + var static KSDistance ks; def static void initPaths(){ new File("debug/metric/").mkdir(); new File("debug/metric/trajectories/").mkdir(); + ks = new KSDistance(Domain.Yakinduum); + } + + def static MetricDistanceGroup calculateMetricDistance(PartialInterpretation partial){ + val metrics = new ArrayList(); + metrics.add(new OutDegreeMetric()); + metrics.add(new NodeActivityMetric()); + metrics.add(new MultiplexParticipationCoefficientMetric()); + + val metricCalculator = new PartialInterpretationGraph(partial, metrics, null); + var metricSamples = metricCalculator.evaluateAllMetricsToSamples(); + + var mpc = ks.mpcDistance(metricSamples.mpcSamples); + var na = ks.naDistance(metricSamples.naSamples); + var outDegree = ks.outDegreeDistance(metricSamples.outDegreeSamples); + + return new MetricDistanceGroup(mpc, na, outDegree); } // calculate the metrics for a state @@ -78,4 +97,28 @@ class PartialInterpretationMetric { } } } +} + +class MetricDistanceGroup{ + var double mpcDistance; + var double naDistance; + var double outDegreeDistance; + + new(double mpcDistance, double naDistance, double outDegreeDistance){ + this.mpcDistance = mpcDistance; + this.naDistance = naDistance; + this.outDegreeDistance = outDegreeDistance; + } + + def double getMPCDistance(){ + return this.mpcDistance + } + + def double getNADistance(){ + return this.naDistance + } + + def double getOutDegreeDistance(){ + return this.outDegreeDistance + } } \ 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 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.distance + +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app.Domain +import java.util.List +import org.apache.commons.math3.stat.inference.KolmogorovSmirnovTest +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io.RepMetricsReader + +class KSDistance { + var static ksTester = new KolmogorovSmirnovTest(); + var double[] mpcSamples; + var double[] naSamples; + var double[] outDegreeSamples; + + new(Domain d){ + var metrics = RepMetricsReader.read(d); + mpcSamples = metrics.mpcSamples; + naSamples = metrics.naSamples.stream.mapToDouble([it]).toArray(); + outDegreeSamples = metrics.outDegreeSamples.stream.mapToDouble([it]).toArray(); + } + + def double mpcDistance(List samples){ + // map list to array + var arr = samples.stream.mapToDouble([it]).toArray(); + + //if the size of array is smaller than 2, ks distance cannot be performed, simply return 1 + if(arr.size < 2) return 1; + return ksTester.kolmogorovSmirnovStatistic(mpcSamples, arr); + } + + def double naDistance(List samples){ + // map list to array + var arr = samples.stream.mapToDouble([it]).toArray(); + + //if the size of array is smaller than 2, ks distance cannot be performed, simply return 1 + if(arr.size < 2) return 1; + return ksTester.kolmogorovSmirnovStatistic(naSamples as double[], arr); + } + + def double outDegreeDistance(List samples){ + // map list to array + var arr = samples.stream.mapToDouble([it]).toArray(); + + //if the size of array is smaller than 2, ks distance cannot be performed, simply return 1 + if(arr.size < 2) return 1; + return ksTester.kolmogorovSmirnovStatistic(outDegreeSamples, arr); + } +} \ 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 index 6d65367f..cf4aedba 100644 --- 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 @@ -1,8 +1,12 @@ package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MetricSampleGroup import java.util.ArrayList import java.util.List +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric abstract class Graph { @@ -33,6 +37,22 @@ abstract class Graph { return result; } + def MetricSampleGroup evaluateAllMetricsToSamples(){ + var sample = new MetricSampleGroup(); + + for(metric : this.metrics){ + if(metric instanceof MultiplexParticipationCoefficientMetric){ + sample.mpcSamples = metric.evaluateSamples(this.statistic); + }else if(metric instanceof NodeActivityMetric){ + sample.naSamples = metric.evaluateSamples(this.statistic); + }else if(metric instanceof OutDegreeMetric){ + sample.outDegreeSamples = metric.evaluateSamples(this.statistic); + } + } + + return sample; + } + def void setBasicInformation(ArrayList> result); def GraphStatistic getStatistic(); diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/GraphReader.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/GraphReader.xtend deleted file mode 100644 index 56bf95a3..00000000 --- a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/GraphReader.xtend +++ /dev/null @@ -1,81 +0,0 @@ -package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.input - -import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.EMFGraph -import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric -import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric -import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric -import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric -import java.io.File -import java.io.FileNotFoundException -import java.util.ArrayList -import java.util.List -import org.eclipse.emf.common.util.URI -import org.eclipse.emf.ecore.EObject -import org.eclipse.emf.ecore.EPackage -import org.eclipse.emf.ecore.EReference -import org.eclipse.emf.ecore.resource.Resource -import org.eclipse.emf.ecore.resource.ResourceSet -import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl -import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl - -class GraphReader{ - val ResourceSet resSet = new ResourceSetImpl(); - val referenceTypes = new ArrayList(); - - new(EPackage metaModel) { - Resource.Factory.Registry.INSTANCE.extensionToFactoryMap.put("*",new XMIResourceFactoryImpl) - - //find all reference types in the meta model - metaModel.eAllContents.forEach[ - if(it instanceof EReference){ - referenceTypes.add(it.name); - } - ] - } - - def List readModels(String path){ - val dir = new File(path); - if(!dir.isDirectory){ - throw new Exception("expecting a directory"); - } - - val graphs = new ArrayList(); - - val metrics = new ArrayList(); - metrics.add(new OutDegreeMetric()); - metrics.add(new NodeActivityMetric()); - metrics.add(new MultiplexParticipationCoefficientMetric()); - - //check all files in the directory with xmi - for(String name : dir.list.filter[it| it.endsWith(".xmi")]){ - val file = new File(name); - val roots = readModel(EObject, path, file.name); - //add a list of metrics - val g = new EMFGraph(); - for(root : roots){ - g.init(root, metrics, name.replaceFirst(".xmi", ""), referenceTypes); - } - - graphs.add(g); - } - - return graphs; - } - - def List readModel(Class type, String path, String name) { - try { - val resource = resSet.getResource(getURI(path, name),true); - if(resource === null) throw new FileNotFoundException(getURI(path, name).toString) - else { - return resource.contents as List - } - } catch(Exception e) { - e.printStackTrace(); - throw new FileNotFoundException(getURI(path, name).toString + "reason: " + e.message) - } - } - - def static getURI(String path, String name) { - URI.createFileURI(path + "/" + name) - } -} \ 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/input/PartialInterpretationReader.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/PartialInterpretationReader.xtend deleted file mode 100644 index dbaf36b2..00000000 --- a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/input/PartialInterpretationReader.xtend +++ /dev/null @@ -1,7 +0,0 @@ -package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.input - -import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation - -class PartialInterpretationReader { - -} \ 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 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io; + +import java.io.File +import java.io.FileNotFoundException +import java.io.PrintWriter +import java.util.ArrayList +import java.util.List + +class CsvFileWriter { + def static void write(ArrayList> datas, String uri) { + if(datas.size() <= 0) { + return; + } + + //println("Output csv for " + uri); + try { + val PrintWriter writer = new PrintWriter(new File(uri)); + val output = new StringBuilder; + for(List datarow : datas){ + for(var i = 0; i < datarow.size() - 1; i++){ + output.append(datarow.get(i) + ','); + } + + if(datarow.size > 1){ + output.append(datarow.get(datarow.size() - 1)); + output.append('\n'); + } + } + + writer.write(output.toString()); + writer.close(); + //println("Output csv finished"); + }catch(FileNotFoundException e) { + e.printStackTrace(); + } + } +} 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 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io; + +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.EMFGraph +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric +import java.io.File +import java.io.FileNotFoundException +import java.util.ArrayList +import java.util.List +import org.eclipse.emf.common.util.URI +import org.eclipse.emf.ecore.EObject +import org.eclipse.emf.ecore.EPackage +import org.eclipse.emf.ecore.EReference +import org.eclipse.emf.ecore.resource.Resource +import org.eclipse.emf.ecore.resource.ResourceSet +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl +import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl + +class GraphReader{ + val ResourceSet resSet = new ResourceSetImpl(); + val referenceTypes = new ArrayList(); + + new(EPackage metaModel) { + Resource.Factory.Registry.INSTANCE.extensionToFactoryMap.put("*",new XMIResourceFactoryImpl) + + //find all reference types in the meta model + metaModel.eAllContents.forEach[ + if(it instanceof EReference){ + referenceTypes.add(it.name); + } + ] + } + + def List readModels(String path){ + val dir = new File(path); + if(!dir.isDirectory){ + throw new Exception("expecting a directory"); + } + + val graphs = new ArrayList(); + + val metrics = new ArrayList(); + metrics.add(new OutDegreeMetric()); + metrics.add(new NodeActivityMetric()); + metrics.add(new MultiplexParticipationCoefficientMetric()); + + //check all files in the directory with xmi + for(String name : dir.list.filter[it| it.endsWith(".xmi")]){ + val file = new File(name); + val roots = readModel(EObject, path, file.name); + //add a list of metrics + val g = new EMFGraph(); + for(root : roots){ + g.init(root, metrics, name.replaceFirst(".xmi", ""), referenceTypes); + } + + graphs.add(g); + } + + return graphs; + } + + def List readModel(Class type, String path, String name) { + try { + val resource = resSet.getResource(getURI(path, name),true); + if(resource === null) throw new FileNotFoundException(getURI(path, name).toString) + else { + return resource.contents as List + } + } catch(Exception e) { + e.printStackTrace(); + throw new FileNotFoundException(getURI(path, name).toString + "reason: " + e.message) + } + } + + def static getURI(String path, String name) { + URI.createFileURI(path + "/" + name) + } +} \ 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 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.io + +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.app.Domain +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric +import java.io.File +import java.util.List +import java.util.Scanner +import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MetricSampleGroup + +/** + * Read the sample of the distribution of a metric provided the csv file of the metric + */ +class RepMetricsReader { + static def read(Domain d){ + var domainRepPath = CsvDataName.REP_PATH + d.name + '/'; + var rep = new MetricSampleGroup() + rep.mpcSamples = readFile(domainRepPath + CsvDataName.MPC_REP, MultiplexParticipationCoefficientMetric.valueName, + MultiplexParticipationCoefficientMetric.countName).map[Double.parseDouble(it)]; + rep.naSamples = readFile(domainRepPath+CsvDataName.NA_REP, NodeActivityMetric.valueName, NodeActivityMetric.countName + ).map[Double.parseDouble(it)]; + rep.outDegreeSamples = readFile(domainRepPath+CsvDataName.OUT_D_REP, OutDegreeMetric.valueName, OutDegreeMetric.countName + ).map[Double.parseDouble(it)]; + return rep; + } + + /** + * read metric data and parse it to samples + */ + private static def List readFile(String filename, String valueDataName, String countDataName){ + var s = new Scanner(new File(filename)); + val counts = newArrayList(); + val values = newArrayList(); + //read data from csv + while(s.hasNext()){ + var data = s.nextLine().split(','); + + if(data.size >= 1){ + if(data.get(0).equals(countDataName)){ + //add all data with parsing them as integers + counts.addAll(data.subList(1, data.size()).map[Integer.parseInt(it)]); + }else if(data.get(0).equals(valueDataName)){ + //add all data without parsing (there can be either double or string, to be parsed later) + values.addAll(data.subList(1, data.size())); + } + } + } + + return createSamples(counts, values); + } + + // create samples from values and counts + private static def List createSamples(List counts, List values){ + val samples = newArrayList(); + + if(counts.size() != values.size()){ + throw new RuntimeException("counts and values should have the same size!"); + } + + for(var i = 0; i < counts.size(); i++){ + for(var j = 0; j < counts.get(i); j++){ + samples.add(values.get(i)); + } + } + + return samples; + } + + +} + +class CsvDataName{ + public static val REP_PATH = 'data/'; + public static val MPC_REP = 'mpc_rep.csv'; + public static val NA_REP = 'na_rep.csv'; + public static val OUT_D_REP = 'out_d_rep.csv'; +} + 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 index ea52009a..38ef72f2 100644 --- 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 @@ -4,4 +4,5 @@ import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatis abstract class Metric { abstract def String[][] evaluate(GraphStatistic g); + abstract def double[] evaluateSamples(GraphStatistic g); } \ 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 @@ +package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics + +import java.util.List + +class MetricSampleGroup{ + public var List mpcSamples; + public var List naSamples; + public var List outDegreeSamples; +} \ 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 index 7bd48754..d9c88bb4 100644 --- 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 @@ -2,11 +2,13 @@ package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic import java.text.DecimalFormat +import java.util.ArrayList import java.util.HashMap +import org.eclipse.emf.ecore.EObject class MultiplexParticipationCoefficientMetric extends Metric { - static val countName = "MPCCount"; - static val valueName = "MPCValue"; + public static val countName = "MPCCount"; + public static val valueName = "MPCValue"; override evaluate(GraphStatistic g) { @@ -18,26 +20,7 @@ class MultiplexParticipationCoefficientMetric extends Metric { val map = new HashMap(); //calculate the metric distribution g.allNodes.forEach[n| - val edgeCounts = g.outDegree(n) + g.inDegree(n); - - var coef = 0.0; - - for(type : g.allTypes){ - val degree = g.dimentionalDegree(n, type) as double; - coef += Math.pow(degree / edgeCounts, 2); - } - coef = 1 - coef; - coef = coef * typeCounts / (typeCounts-1); - - //Consider the case that either typeCounts-1 or the edgeCounts could be 0 in some situation - //in this case the metric should be evaluated to 0 - if(typeCounts == 1){ - println("bad"); - } - - if(Double.isNaN(coef)){ - coef = 0; - } + var coef = calculateMPC(n, g, typeCounts); //format number to String val value = formatter.format(coef); @@ -62,4 +45,36 @@ class MultiplexParticipationCoefficientMetric extends Metric { return datas; } + + override evaluateSamples(GraphStatistic g){ + val samples = new ArrayList(); + val typeCounts = g.allTypes.size; + //calculate the metric distribution + g.allNodes.forEach[ + samples.add(calculateMPC(it, g, typeCounts)); + ] + + return samples; + } + + def double calculateMPC(EObject n, GraphStatistic g, int typeCounts){ + val edgeCounts = g.outDegree(n) + g.inDegree(n); + + var coef = 0.0; + + for(type : g.allTypes){ + val degree = g.dimentionalDegree(n, type) as double; + coef += Math.pow(degree / edgeCounts, 2); + } + coef = 1 - coef; + coef = coef * typeCounts / (typeCounts-1); + + //Consider the case that either typeCounts-1 or the edgeCounts could be 0 in some situation + //in this case the metric should be evaluated to 0 + if(Double.isNaN(coef)){ + coef = 0; + } + + return coef; + } } \ 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 index 297bdd14..fbf06c47 100644 --- 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 @@ -1,11 +1,12 @@ package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic +import java.util.ArrayList import java.util.HashMap class NodeActivityMetric extends Metric { - static val countName = "NACount"; - static val valueName = "NAValue"; + public static val countName = "NACount"; + public static val valueName = "NAValue"; override evaluate(GraphStatistic g) { val map = new HashMap(); @@ -34,4 +35,15 @@ class NodeActivityMetric extends Metric { return datas; } + + override evaluateSamples(GraphStatistic g){ + val samples = new ArrayList(); + + //calculate the metric distribution + g.allNodes.forEach[ + samples.add(g.numOfEdgeTypes(it) as double); + ] + + return samples; + } } \ 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 index 1ba6c8c7..55046b14 100644 --- 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 @@ -1,11 +1,12 @@ package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph.GraphStatistic +import java.util.ArrayList import java.util.HashMap class OutDegreeMetric extends Metric { - static val countName = "OutDegreeCount"; - static val valueName = "OutDegreeValue"; + public static val countName = "OutDegreeCount"; + public static val valueName = "OutDegreeValue"; override evaluate(GraphStatistic g) { val map = new HashMap(); @@ -34,5 +35,15 @@ class OutDegreeMetric extends Metric { return datas; } + override evaluateSamples(GraphStatistic g){ + val samples = new ArrayList(); + + //calculate the metric distribution + g.allNodes.forEach[ + samples.add(g.outDegree(it) as double); + ] + + return samples; + } } \ 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/output/CsvFileWriter.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/output/CsvFileWriter.xtend deleted file mode 100644 index 1dd204a0..00000000 --- a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/output/CsvFileWriter.xtend +++ /dev/null @@ -1,37 +0,0 @@ -package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.output; - -import java.io.File -import java.io.FileNotFoundException -import java.io.PrintWriter -import java.util.ArrayList -import java.util.List - -class CsvFileWriter { - def static void write(ArrayList> datas, String uri) { - if(datas.size() <= 0) { - return; - } - - //println("Output csv for " + uri); - try { - val PrintWriter writer = new PrintWriter(new File(uri)); - val output = new StringBuilder; - for(List datarow : datas){ - for(var i = 0; i < datarow.size() - 1; i++){ - output.append(datarow.get(i) + ','); - } - - if(datarow.size > 1){ - output.append(datarow.get(datarow.size() - 1)); - output.append('\n'); - } - } - - writer.write(output.toString()); - writer.close(); - //println("Output csv finished"); - }catch(FileNotFoundException e) { - e.printStackTrace(); - } - } -} diff --git a/Metrics/Metrics-Calculation/metrics_plot/model comparison/input/.gitignore b/Metrics/Metrics-Calculation/metrics_plot/model comparison/input/.gitignore new file mode 100644 index 00000000..b3934b01 --- /dev/null +++ b/Metrics/Metrics-Calculation/metrics_plot/model comparison/input/.gitignore @@ -0,0 +1,3 @@ +# ignore everything in this folder +* +!.gitignore \ No newline at end of file diff --git a/Metrics/Metrics-Calculation/metrics_plot/model comparison/output/Human-Viatra (30 nodes)-/MPC.png b/Metrics/Metrics-Calculation/metrics_plot/model comparison/output/Human-Viatra (30 nodes)-/MPC.png new file mode 100644 index 00000000..e660f3da Binary files /dev/null and b/Metrics/Metrics-Calculation/metrics_plot/model comparison/output/Human-Viatra (30 nodes)-/MPC.png differ diff --git a/Metrics/Metrics-Calculation/metrics_plot/model comparison/output/Human-Viatra (30 nodes)-/Node Activity.png b/Metrics/Metrics-Calculation/metrics_plot/model comparison/output/Human-Viatra (30 nodes)-/Node Activity.png new file mode 100644 index 00000000..92047e47 Binary files /dev/null and b/Metrics/Metrics-Calculation/metrics_plot/model comparison/output/Human-Viatra (30 nodes)-/Node Activity.png differ diff --git a/Metrics/Metrics-Calculation/metrics_plot/model comparison/output/Human-Viatra (30 nodes)-/Out Degree.png b/Metrics/Metrics-Calculation/metrics_plot/model comparison/output/Human-Viatra (30 nodes)-/Out Degree.png new file mode 100644 index 00000000..dad7483f Binary files /dev/null and b/Metrics/Metrics-Calculation/metrics_plot/model comparison/output/Human-Viatra (30 nodes)-/Out Degree.png differ diff --git a/Metrics/Metrics-Calculation/metrics_plot/model comparison/src/plot_ks_stats.py b/Metrics/Metrics-Calculation/metrics_plot/model comparison/src/plot_ks_stats.py new file mode 100644 index 00000000..2f39ca93 --- /dev/null +++ b/Metrics/Metrics-Calculation/metrics_plot/model comparison/src/plot_ks_stats.py @@ -0,0 +1,98 @@ +import os, sys +lib_path = os.path.abspath(os.path.join('..', '..', 'utils')) +sys.path.append(lib_path) +import glob +import random +from sklearn.manifold import MDS +import matplotlib.pyplot as plt +from scipy import stats +import numpy as np +from GraphType import GraphCollection + +def main(): + # read models + human = GraphCollection('../input/humanOutput/', 500, 'Human') + viatra30 = GraphCollection('../input/viatraOutput30/', 500, 'Viatra (30 nodes)') + # viatra60 = GraphCollection('../input/viatraOutput60/', 500, 'Viatra (60 nodes)') + # viatra100 = GraphCollection('../input/viatraOutput100/', 500, 'Viatra (100 nodes)') + # random = GraphCollection('../input/randomOutput/', 500, 'Random') + # alloy = GraphCollection('../input/alloyOutput/', 500, 'Alloy (30 nodes)') + + models_to_compare = [human, viatra30] + + # define output folder + outputFolder = '../output/' + + #calculate metrics + metricStat(models_to_compare, 'Node Activity', nodeActivity, 0, outputFolder) + metricStat(models_to_compare, 'Out Degree', outDegree, 1, outputFolder) + metricStat(models_to_compare, 'MPC', mpc, 2, outputFolder) + +def calculateKSMatrix(dists): + dist = [] + + for i in range(len(dists)): + dist = dist + dists[i] + matrix = np.empty((len(dist),len(dist))) + + for i in range(len(dist)): + matrix[i,i] = 0 + for j in range(i+1, len(dist)): + value, p = stats.ks_2samp(dist[i], dist[j]) + matrix[i, j] = value + matrix[j, i] = value + return matrix + + +def calculateMDS(dissimilarities): + embedding = MDS(n_components=2, dissimilarity='precomputed') + trans = embedding.fit_transform(X=dissimilarities) + return trans + +def plot(graphTypes, coords, title='',index = 0, savePath = ''): + half_length = int(coords.shape[0] / len(graphTypes)) + color = ['blue', 'red', 'green', 'yellow'] + plt.figure(index, figsize=(7, 4)) + plt.title(title) + for i in range(len(graphTypes)): + x = (coords[(i*half_length):((i+1)*half_length), 0].tolist()) + y = (coords[(i*half_length):((i+1)*half_length), 1].tolist()) + plt.plot(x, y, color=color[i], marker='o', label = graphTypes[i].name, linestyle='', alpha=0.7) + plt.legend(loc='upper right') + plt.savefig(fname = savePath, dpi=150) + #graph.show() + +def mkdir_p(mypath): + '''Creates a directory. equivalent to using mkdir -p on the command line''' + + from errno import EEXIST + from os import makedirs,path + + try: + makedirs(mypath) + except OSError as exc: # Python >2.5 + if exc.errno == EEXIST and path.isdir(mypath): + pass + else: raise + +def metricStat(graphTypes, metricName, metric, graphIndex, outputFolder): + metrics = [] + for graph in graphTypes: + metrics.append(metric(graph)) + outputFolder = outputFolder + graph.name + '-' + print('calculate' + metricName +' for ' + outputFolder) + mkdir_p(outputFolder) + out_d_coords = calculateMDS(calculateKSMatrix(metrics)) + plot(graphTypes, out_d_coords, metricName, graphIndex,outputFolder + '/'+ metricName+'.png') + +def nodeActivity(graphType): + return graphType.nas + +def outDegree(graphType): + return graphType.out_ds + +def mpc(graphType): + return graphType.mpcs + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/Metrics/Metrics-Calculation/metrics_plot/output/Human-viatraEvolve-/MPC.png b/Metrics/Metrics-Calculation/metrics_plot/output/Human-viatraEvolve-/MPC.png deleted file mode 100644 index d819aad5..00000000 Binary files a/Metrics/Metrics-Calculation/metrics_plot/output/Human-viatraEvolve-/MPC.png and /dev/null differ diff --git a/Metrics/Metrics-Calculation/metrics_plot/output/Human-viatraEvolve-/Node Activity.png b/Metrics/Metrics-Calculation/metrics_plot/output/Human-viatraEvolve-/Node Activity.png deleted file mode 100644 index 4b3b187e..00000000 Binary files a/Metrics/Metrics-Calculation/metrics_plot/output/Human-viatraEvolve-/Node Activity.png and /dev/null differ diff --git a/Metrics/Metrics-Calculation/metrics_plot/output/Human-viatraEvolve-/Out Degree.png b/Metrics/Metrics-Calculation/metrics_plot/output/Human-viatraEvolve-/Out Degree.png deleted file mode 100644 index d8e01f6e..00000000 Binary files a/Metrics/Metrics-Calculation/metrics_plot/output/Human-viatraEvolve-/Out Degree.png and /dev/null differ diff --git a/Metrics/Metrics-Calculation/metrics_plot/src/metrics_distance_with_selector.ipynb b/Metrics/Metrics-Calculation/metrics_plot/src/metrics_distance_with_selector.ipynb index e5868da0..a0b0ad8d 100644 --- a/Metrics/Metrics-Calculation/metrics_plot/src/metrics_distance_with_selector.ipynb +++ b/Metrics/Metrics-Calculation/metrics_plot/src/metrics_distance_with_selector.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -48,7 +48,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -78,7 +78,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -108,7 +108,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -139,7 +139,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -149,7 +149,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -163,7 +163,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -200,7 +200,8 @@ "# Read generated models\n", "viatra_no_con_stats = readStats('../statistics/viatra_nocon_output/', 5000)\n", "viatra_con_stats = readStats('../statistics/viatra_con_output/',5000)\n", - "random_stats = readStats('../statistics/random_output/',5000)" + "random_stats = readStats('../statistics/random_output/',5000)\n", + "con_viatra_stats = readStats('../statistics/controled_viatra/',300)" ] }, { @@ -218,7 +219,8 @@ "source": [ "viatra_no_con_dic = calDistanceDic(viatra_no_con_stats, human_rep)\n", "viatra_con_dic = calDistanceDic(viatra_con_stats, human_rep)\n", - "random_dic = calDistanceDic(random_stats, human_rep)" + "random_dic = calDistanceDic(random_stats, human_rep)\n", + "con_viatra_dic = calDistanceDic(con_viatra_stats, human_rep)" ] }, { @@ -255,7 +257,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "1bdc31418d894783b36cc79c60251f00", + "model_id": "868a437468d24144926f1390cbf2acb8", "version_major": 2, "version_minor": 0 }, @@ -291,7 +293,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "78565a0ec3d740908fcea753387cfc3e", + "model_id": "e8b74fe96a45445f8062468ddf2597bf", "version_major": 2, "version_minor": 0 }, @@ -327,7 +329,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "4392eb19fe1844c4affeb62f9ba9163b", + "model_id": "c6e7e31f454a48169dac12c8aac70eef", "version_major": 2, "version_minor": 0 }, @@ -363,7 +365,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "c667f0f9dcd5494f81d95c64ad900612", + "model_id": "cebc359548f74cc8b7540ecc3876c9ee", "version_major": 2, "version_minor": 0 }, @@ -399,7 +401,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "991d8d2bfc644c82a9b079615900dc4d", + "model_id": "682beae42eef4676b11b6fe23127a44e", "version_major": 2, "version_minor": 0 }, @@ -435,7 +437,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "be65f39c2fae4c84a1d6908f3b70a86e", + "model_id": "6893b8c6e03441f89fc35bf784992ae9", "version_major": 2, "version_minor": 0 }, @@ -471,7 +473,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "1de0db5b5c8d46de958f6b43144dac54", + "model_id": "ff0e1991c69a4d77a40f57225f90295a", "version_major": 2, "version_minor": 0 }, @@ -501,13 +503,13 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "6f8fa855125b4beca603abbf801412ac", + "model_id": "838570f20bed4d8d9c618305984d19ef", "version_major": 2, "version_minor": 0 }, @@ -524,7 +526,7 @@ "" ] }, - "execution_count": 20, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } @@ -537,13 +539,13 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "b4ed2adb29004908a3799bc91bf0662b", + "model_id": "f4825f6257a74bce9dd22aac8a98effa", "version_major": 2, "version_minor": 0 }, @@ -560,7 +562,7 @@ "" ] }, - "execution_count": 23, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -571,6 +573,164 @@ "interact(plot_out_degree, lines=[[]])" ] }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [], + "source": [ + "con_viatra_stats = readStats('../statistics/controled_viatra/',5000)\n", + "con_viatra_dic = calDistanceDic(con_viatra_stats, human_rep)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Trajectories for controlled viatra solver" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [], + "source": [ + "filenames = reader.readmultiplefiles('../statistics/controled_viatra/trajectories/', 25, False)\n", + "trajectories = {}\n", + "for name in filenames:\n", + " trajectories[name] = reader.readTrajectory(name)\n", + "\n", + "w = widgets.SelectMultiple(\n", + " options = trajectories,\n", + " value = [trajectories[filenames[0]]],\n", + " description='Trajectory:',\n", + " disabled=False,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4b60ae3859e343299badf29272f67d21", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(SelectMultiple(description='Trajectory:', index=(0,), options={'../statistics/controled_…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 57, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def plot_out_degree(lines):\n", + " plot(con_viatra_dic, lines, 0, lambda a: a.out_d_distance, colors, 'out_degree')\n", + "interact(plot_out_degree, lines=w)" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "8e7965d793a146d4bbc268554262eb58", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(SelectMultiple(description='Trajectory:', index=(0,), options={'../statistics/controled_…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def plot_na(lines):\n", + " plot(con_viatra_dic, lines, 0, lambda a: a.na_distance, colors, 'Node Activity')\n", + "interact(plot_na, lines=w)" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "55a1209d0b924a39b4729228e81ee3ab", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(SelectMultiple(description='Trajectory:', index=(0,), options={'../statistics/controled_…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def plot_mpc(lines):\n", + " plot(con_viatra_dic, lines, 0, lambda a: a.mpc_distance, colors, 'mpc')\n", + "interact(plot_mpc, lines=w)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, diff --git a/Metrics/Metrics-Calculation/metrics_plot/utils/GraphType.py b/Metrics/Metrics-Calculation/metrics_plot/utils/GraphType.py new file mode 100644 index 00000000..13754e80 --- /dev/null +++ b/Metrics/Metrics-Calculation/metrics_plot/utils/GraphType.py @@ -0,0 +1,29 @@ +import readCSV as reader +import constants +import numpy as np + +# graph stats for a collection of graphs +class GraphCollection: + + # init with path contrain files and number of files to read reader is imported from (readCSV) + def __init__(self, path, number, name, shouldShuffle = True): + self.out_ds = [] + self.nas = [] + self.mpcs = [] + self.name = name + models = reader.readmultiplefiles(path, number, shouldShuffle) + for i in range(len(models)): + contents, out_d, na, mpc = reader.getmetrics(models[i]) + self.out_ds.append(out_d) + self.nas.append(na) + self.mpcs.append(mpc) + print(len(self.out_ds)) + +#Graph stat for one graph +class GraphStat: + # init with teh file name of the stat + def __init__(self, filename): + contents, self.out_d, self.na, self.mpc = reader.getmetrics(filename) + self.num_nodes = np.array(contents[constants.NUMBER_NODES]) + if constants.STATE_ID in contents: + self.id = (contents[constants.STATE_ID])[0] diff --git a/Metrics/Metrics-Calculation/metrics_plot/utils/constants.py b/Metrics/Metrics-Calculation/metrics_plot/utils/constants.py new file mode 100644 index 00000000..58ca7549 --- /dev/null +++ b/Metrics/Metrics-Calculation/metrics_plot/utils/constants.py @@ -0,0 +1,25 @@ +NUMBER_EDGE_TYPES = 'Number of Edge types' + +NUMBER_NODES = 'Number Of Nodes' + +OUT_DEGREE_COUNT = 'OutDegreeCount' + +OUT_DEGREE_VALUE = 'OutDegreeValue' + +NA_COUNT = 'NACount' + +NA_VALUE = 'NAValue' + +MPC_VALUE = 'MPCValue' + +MPC_COUNT = 'MPCCount' + +METAMODEL = 'Meta Mode' + +STATE_ID = 'State Id' + +HUMAN_OUT_D_REP = '../statistics/humanOutput\R_20158_run_1.csv' + +HUMAN_MPC_REP = '../statistics/humanOutput\R_2015246_run_1.csv' + +HUMAN_NA_REP = '../statistics/humanOutput\R_2016176_run_1.csv' diff --git a/Metrics/Metrics-Calculation/metrics_plot/utils/readCSV.py b/Metrics/Metrics-Calculation/metrics_plot/utils/readCSV.py new file mode 100644 index 00000000..e0402519 --- /dev/null +++ b/Metrics/Metrics-Calculation/metrics_plot/utils/readCSV.py @@ -0,0 +1,169 @@ +import numpy as np +import matplotlib.pyplot as plt +from scipy import stats +import glob +import random +import constants + +# +# read csvfile returns outdegree, node activity, mpc +# as matrix with the first row of values and second row of count +# +def readcsvfile(filename): + + contents = {} + with open(filename) as f: + for i, line in enumerate(f): + arr = line.split(',') + # if there is no element in the line, continue + if len(line) < 0: continue + # else check for contents + # if it is MPC then use float + if arr[0] == constants.MPC_VALUE: + contents[constants.MPC_VALUE] = list(map(float, arr[1:])) + # meta models are string + elif(arr[0] == constants.METAMODEL): + contents[constants.METAMODEL] = arr[1:] + # all other contants are integer + else: + contents[arr[0]] = list(map(int, arr[1:])) + f.close() + return contents + +def checkAndReshape(arr): + if len(arr.shape) < 2: + arr = np.reshape(arr, (arr.shape[0],1)) + return arr + +def readTrajectory(filename): + state_codes = [] + with open(filename) as f: + for i, line in enumerate(f): + if(line == ''): continue + state_codes.append(int(line)) + return state_codes +# +# take a matrix as input +# return the sample array +# +def getsample(dataMatrix): + data = [] + value = dataMatrix[0, :] + count = dataMatrix[1, :] + for i, v in enumerate(value): + for x in range(0, int(count[i])): + data.append(v) + return data + +def reproduceSample(values, counts): + arr = np.array([values, counts]) + return getsample(arr) + +# +# take an array of filenames as input +# return the samples of outdegree, na, mpc +# +def getmetrics(filename): + contents = readcsvfile(filename) + outdegree_sample = reproduceSample(contents[constants.OUT_DEGREE_VALUE], contents[constants.OUT_DEGREE_COUNT]) + na_sample = reproduceSample(contents[constants.NA_VALUE], contents[constants.NA_COUNT]) + mpc_sample = reproduceSample(contents[constants.MPC_VALUE], contents[constants.MPC_COUNT]) + return contents,outdegree_sample, na_sample, mpc_sample + +# +# read number of files in the given path RANDOMLY +# +def readmultiplefiles(dirName, maxNumberOfFiles, shouldShuffle = True): + list_of_files = glob.glob(dirName + '*.csv') # create the list of file + if shouldShuffle: + random.shuffle(list_of_files) + #if the number of files is out of bound then just give the whole list + file_names = list_of_files[:maxNumberOfFiles] + # print(file_names) + return file_names + + +def plotlines(x, y, ax): + l1, = ax.plot(x, y) + + +def testgetsamplesfromfiles(): + files = readmultiplefiles('../statistics/viatraOutput/', 2) + for file in files: + getmetrics(file) + +def probability(data): + sum = np.sum(data) + probabilityList = [] + for d in data: + p = d/sum + probabilityList.append(p) + a = np.array(probabilityList) + return a + + +def cumulativeProbability(p): + cdf = np.cumsum(p) + return cdf + + +def plot(): + fig, ax = plt.subplots() + fig, ax1 = plt.subplots() + fig, ax2 = plt.subplots() + fig, ax3 = plt.subplots() + fig, ax4 = plt.subplots() + fig, ax5 = plt.subplots() + list_of_files = readmultiplefiles('../statistics/iatraOutput/') + for file_name in list_of_files: + contents = readcsvfile(file_name) + outdegree = [contents[constants.OUT_DEGREE_VALUE], contents[constants.OUT_DEGREE_COUNT]] + na = [contents[constants.NA_VALUE], contents[constants.NA_COUNT]] + mpc = [contents[constants.MPC_VALUE], contents[constants.MPC_COUNT]] + outV = outdegree[0, :] + outC = outdegree[1, :] + outP = probability(outC) + outCumP = cumulativeProbability(outP) + plotlines(outV, outP, ax) + naV = na[0, :] + naC = na[1, :] + naP = probability(naC) + naCumP = cumulativeProbability(naP) + plotlines(naV, naP, ax1) + mpcV = mpc[0, :] + mpcC = mpc[1, :] + mpcP = probability(mpcC) + mpcCumP = cumulativeProbability(mpcP) + plotlines(mpcV, mpcP, ax2) + plotlines(outV, outCumP, ax3) + plotlines(naV, naCumP, ax4) + plotlines(mpcV, mpcCumP, ax5) + ax.set_xlabel('ourdegree') + ax.set_ylabel('pdf') + ax.grid() + + ax1.set_xlabel('node activity') + ax1.set_ylabel('pdf') + ax1.grid() + + ax2.set_xlabel('multiplex participation coefficient') + ax2.set_ylabel('pdf') + ax2.grid() + + ax3.set_xlabel('ourdegree') + ax3.set_ylabel('cdf') + ax3.grid() + + ax4.set_xlabel('node activity') + ax4.set_ylabel('cdf') + ax4.grid() + + ax5.set_xlabel('multiplex participation coefficient') + ax5.set_ylabel('cdf') + ax5.grid() + + plt.show() + + +# plot() + -- cgit v1.2.3-54-g00ecf