aboutsummaryrefslogtreecommitdiffstats
path: root/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph
diff options
context:
space:
mode:
Diffstat (limited to 'Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph')
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/EMFGraph.xtend124
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/Graph.xtend71
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/GraphStatistic.xtend194
-rw-r--r--Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/PartialInterpretationGraph.xtend134
4 files changed, 523 insertions, 0 deletions
diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/EMFGraph.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/EMFGraph.xtend
new file mode 100644
index 00000000..8fa29fe6
--- /dev/null
+++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/EMFGraph.xtend
@@ -0,0 +1,124 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric
4import java.util.ArrayList
5import java.util.HashSet
6import java.util.List
7import org.eclipse.emf.common.util.EList
8import org.eclipse.emf.ecore.EObject
9import org.eclipse.emf.ecore.EReference
10import org.eclipse.xtend.lib.annotations.Accessors
11
12class EMFGraph extends Graph{
13 @Accessors(PUBLIC_GETTER)
14 var EObject root;
15
16 def void init (EObject root, List<Metric> metrics, String name, List<EReference> referenceTypes){
17 val otherContents = root.eAllContents.toList();
18 this.root = root;
19 otherContents.add(root);
20 init(otherContents, metrics, name, referenceTypes);
21 }
22
23 /**
24 * init the graph with all nodes and reference types in the meta model
25 * @param objects: objects in the instance model (exclude root)
26 * @param metrics: metrics to be evaluated
27 * @param name: name of the instance model
28 * @param ReferenceTypes: reference types defined in the meta model
29 */
30 def void init(List<EObject> objects, List<Metric> metrics, String name, List<EReference> referenceTypes){
31 objects.forEach[it|
32 // TODO: Maybe want to consider all the super types as well
33 var types = new HashSet();
34 types.add(it.eClass.name);
35 statistic.addNodeWithAllTypes(it, types);
36 ]
37
38 referenceTypes.forEach[it|
39 // Only consider the edges that are not derived to preserve the statistical property
40 if(!it.derived){
41 statistic.addEdgeType(it.name);
42 }
43 ];
44
45 objects.forEach[source|
46 source.eClass.EAllReferences.forEach[r|
47 //many references
48 if(r.isMany){
49 source.getNeighbours(r).forEach[target|
50 addEdge(source, target, r);
51 ]
52 }else{
53 //single references
54 val target = source.eGet(r) as EObject;
55 addEdge(source, target, r);
56 }
57 ]
58 ]
59
60 this.metrics = metrics;
61 this.name = name;
62 }
63
64 def void removeReference(EReference r){
65 if (statistic.containsEdgeType(r.name)){
66 statistic.removeReference(r.name, r.containment);
67 }
68 }
69
70 /**
71 * Set basic information for the output
72 */
73 override setBasicInformation(ArrayList<ArrayList<String>> output){
74 val metaInfo = new ArrayList<String>();
75 metaInfo.add(META_MODEL_HEADER);
76 metaInfo.add(this.metaModel);
77
78 val edgeInfo = new ArrayList<String>();
79 edgeInfo.add(NUM_EDGE_TYPE_HEADER);
80 edgeInfo.add(this.statistic.allTypes.size()+"");
81
82 val nodeInfo = new ArrayList<String>();
83 nodeInfo.add(NUM_NODE_HEADER);
84 nodeInfo.add(this.statistic.allNodes.size()+"");
85
86 val stateInfo = new ArrayList<String>();
87 stateInfo.add(STATE_ID_HEADER);
88 stateInfo.add(this.name);
89
90
91 output.add(metaInfo);
92 output.add(edgeInfo);
93 output.add(nodeInfo);
94 output.add(stateInfo);
95 }
96
97 def EList<EObject> getNeighbours(EObject o, EReference r){
98 return (o.eGet(r, true) as EList<EObject>);
99 }
100
101 def addEdge(EObject source, EObject target, EReference r){
102 //Only add the edge if the reference is not derived to preserve the statistical property
103 if(target !== null && r !== null && !r.derived){
104 statistic.addEdge(source, target, r.name);
105 }
106 }
107
108 override GraphStatistic getStatistic(){
109 return this.statistic;
110 }
111
112 override String getName(){
113 return this.name;
114 }
115
116 def void setMetaModel(String model){
117 this.metaModel = model;
118 }
119
120 def String getMetaModel(){
121 return this.metaModel;
122 }
123
124} \ No newline at end of file
diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/Graph.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/Graph.xtend
new file mode 100644
index 00000000..6b400b0d
--- /dev/null
+++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/Graph.xtend
@@ -0,0 +1,71 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric
4import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MetricSampleGroup
5import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.MultiplexParticipationCoefficientMetric
6import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeActivityMetric
7import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.OutDegreeMetric
8import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.TypedOutDegree
9import java.util.ArrayList
10import java.util.HashMap
11import java.util.List
12import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.NodeTypeMetric
13import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.EdgeTypeMetric
14
15abstract class Graph {
16
17 protected static val String META_MODEL_HEADER = "Meta Mode"
18 protected static val String NUM_NODE_HEADER = "Number Of Nodes";
19 protected static val String NUM_EDGE_TYPE_HEADER = "Number of Edge types";
20 protected static val String STATE_ID_HEADER = "State Id";
21
22 protected val statistic = new GraphStatistic();
23 protected var List<Metric> metrics;
24 protected var String name = "";
25 protected var String metaModel = "";
26
27 /**
28 * evaluate all metrics for this model
29 * return the result as a two dimentional list
30 */
31 def ArrayList<ArrayList<String>> evaluateAllMetrics(){
32 val result = new ArrayList<ArrayList<String>>();
33 setBasicInformation(result);
34
35 for(metric : this.metrics){
36 val datas = metric.evaluate(this.statistic);
37 for(row : datas){
38 result.add(new ArrayList<String>(row));
39 }
40 }
41 return result;
42 }
43
44 def MetricSampleGroup evaluateAllMetricsToSamples(){
45 var sample = new MetricSampleGroup();
46
47 for(metric : this.metrics){
48 if(metric instanceof MultiplexParticipationCoefficientMetric){
49 sample.mpcSamples = metric.evaluateSamples(this.statistic) as ArrayList<Double>;
50 }else if(metric instanceof NodeActivityMetric){
51 sample.naSamples = metric.evaluateSamples(this.statistic) as ArrayList<Double>;
52 }else if(metric instanceof OutDegreeMetric){
53 sample.outDegreeSamples = metric.evaluateSamples(this.statistic) as ArrayList<Double>;
54 }else if(metric instanceof TypedOutDegree){
55 sample.typedOutDegreeSamples = metric.evaluateSamples(this.statistic) as HashMap<String, List<Integer>>;
56 }else if(metric instanceof NodeTypeMetric){
57 sample.nodeTypeSamples = metric.evaluateSamples(this.statistic) as HashMap<String, Double>;
58 }else if (metric instanceof EdgeTypeMetric){
59 sample.edgeTypeSamples = metric.evaluateSamples(this.statistic) as HashMap<String, Double>;
60 }
61 }
62
63 return sample;
64 }
65
66 def void setBasicInformation(ArrayList<ArrayList<String>> result);
67
68 def GraphStatistic getStatistic();
69
70 def String getName();
71} \ No newline at end of file
diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/GraphStatistic.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/GraphStatistic.xtend
new file mode 100644
index 00000000..31788bb2
--- /dev/null
+++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/GraphStatistic.xtend
@@ -0,0 +1,194 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph
2
3import com.google.common.collect.ArrayListMultimap
4import com.google.common.collect.Multimap
5import java.util.HashMap
6import java.util.HashSet
7import java.util.List
8import java.util.Map
9import java.util.Set
10import org.eclipse.emf.ecore.EObject
11import org.eclipse.emf.ecore.EReference
12
13class GraphStatistic {
14 val incomingEdges = new HashMap<String, Multimap<EObject, EObject>>;
15 val outgoingEdges = new HashMap<String, Multimap<EObject, EObject>>;
16
17 val edgeTypes = new HashSet<String>();
18 val nodeToType = new HashMap<EObject, Set<String>>();
19
20 /**
21 * Add an edge type to to the graph
22 * @param type: type to add
23 */
24 def void addEdgeType(String type){
25 if(edgeTypes.contains(type)){
26 return;
27 }
28
29 edgeTypes.add(type);
30 incomingEdges.put(type, ArrayListMultimap.create());
31 outgoingEdges.put(type, ArrayListMultimap.create());
32 }
33
34 /**
35 * Add a node to the graph with one type in its type hierarchy
36 * @param node: node to add
37 */
38 def void addNodeWithType(EObject n, String Type){
39 var types = nodeToType.getOrDefault(n, new HashSet<String>());
40 types.add(Type);
41 nodeToType.put(n, types);
42 }
43
44 def boolean containsNode(EObject o){
45 return nodeToType.containsKey(o);
46 }
47
48 def Set<String> getTypesForNode(EObject o){
49 return nodeToType.getOrDefault(o, new HashSet<String>());
50 }
51
52 def void overwriteCurrentType(EObject o, String type){
53 var typeSet = nodeToType.getOrDefault(o, new HashSet<String>());
54
55 // clear current types
56 typeSet.clear();
57 typeSet.add(type);
58 nodeToType.put(o, typeSet);
59 }
60
61 /**
62 * Add a node to the graph with all types in its type hierarchy
63 */
64 def void addNodeWithAllTypes(EObject n, Set<String> types){
65 nodeToType.put(n, types);
66 }
67
68 /**
69 * Add an edge to the graph
70 * @param source: source node
71 * @param target: target node
72 * @param type: type of the reference
73 */
74 def void addEdge(EObject source, EObject target, String type){
75 outgoingEdges.get(type).put(source, target);
76 incomingEdges.get(type).put(target, source);
77 }
78
79 /**
80 * check if this graph contains a specific edge type
81 */
82 def boolean containsEdgeType(String typeName){
83 if(outgoingEdges.containsKey(typeName) && incomingEdges.containsKey(typeName)){
84 return true;
85 }
86 return false;
87 }
88
89 /**
90 * remove references from the statistics, potentially remove the nodes associated with it
91 * @Param name: name of the reference
92 * @Param isContainment: if true then the corresponding nodes on the incoming side will also be removed
93 */
94 def removeReference(String name, boolean isContainment){
95 if(!edgeTypes.contains(name)){
96 return;
97 }
98
99 edgeTypes.remove(name);
100 var incomingSet = incomingEdges.remove(name);
101 outgoingEdges.remove(name);
102
103 // if the reference is not a containment, then removing the reference is enough
104 if(!isContainment){
105 return;
106 }
107
108 // else remove all corresponding nodes
109 val nodesToRemove = incomingSet.keySet();
110
111 //remove nodes from node sets
112 nodesToRemove.forEach[nodeToType.remove(it)];
113
114 val removeForMultimap = [Multimap<EObject, EObject> refMap|
115 nodesToRemove.forEach[refMap.removeAll(it)];
116 var values = refMap.values()
117 //remove the values from the list is equavalent to remove it in the multimap
118 values.removeAll(nodesToRemove);
119 return;
120 ];
121
122 //remove nodes from all other references on incomingEdges
123 incomingEdges.values.forEach(removeForMultimap);
124 outgoingEdges.values.forEach(removeForMultimap);
125 }
126
127 /**
128 * calculate the out degree for an object
129 */
130 def int outDegree(EObject o){
131 var count = 0;
132
133 for (String type : edgeTypes){
134 count += outgoingEdges.get(type).get(o).size();
135 }
136 return count;
137 }
138
139 /**
140 * calculate the in degree of an object
141 */
142 def int inDegree(EObject o){
143 var count = 0;
144
145 for (String type : edgeTypes){
146 count += incomingEdges.get(type).get(o).size();
147 }
148 return count;
149 }
150
151 /**
152 * calculate the dimentional degree of a node
153 */
154 def int dimentionalDegree(EObject o, String type){
155 return incomingEdges.get(type).get(o).size() + outgoingEdges.get(type).get(o).size();
156 }
157
158 /**
159 * calculate the number of edge types for a given node.
160 */
161 def int numOfEdgeTypes(EObject o){
162 var count = 0;
163
164 for(String type : edgeTypes){
165 if(dimentionalDegree(o, type) > 0){
166 count++;
167 }
168 }
169
170 return count;
171 }
172
173 def List<String> getAllTypes(){
174 return edgeTypes.toList();
175 }
176
177 def Map<EObject, Set<String>> getNodeToTypesMap(){
178 return nodeToType;
179 }
180
181 def List<EObject> getAllNodes(){
182 return nodeToType.keySet().toList();
183 }
184
185 def HashMap<String, Multimap<EObject, EObject>> getOutgoingEdges(){
186 return outgoingEdges;
187 }
188
189 def HashMap<String, Multimap<EObject, EObject>> incomingEdges(){
190 return incomingEdges;
191 }
192
193}
194
diff --git a/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/PartialInterpretationGraph.xtend b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/PartialInterpretationGraph.xtend
new file mode 100644
index 00000000..a2934eb9
--- /dev/null
+++ b/Metrics/Metrics-Calculation/ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator/src/ca/mcgill/ecse/dslreasoner/realistic/metrics/calculator/graph/PartialInterpretationGraph.xtend
@@ -0,0 +1,134 @@
1package ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.graph
2
3import ca.mcgill.ecse.dslreasoner.realistic.metrics.calculator.metrics.Metric
4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration
5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type
6import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDefinition
7import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BinaryElementRelationLink
8import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
9import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.PartialComplexTypeInterpretationImpl
10import java.util.ArrayList
11import java.util.List
12
13class PartialInterpretationGraph extends Graph{
14 val typeToExclude = "undefinedpart";
15 val classSuffix = " class";
16
17 /**
18 * Define a new PartialInterpretationGraph by parse every element from a PartialInterpretation
19 */
20 new(PartialInterpretation partial, List<Metric> metrics, String name){
21 //the edge types are defined in terms of RelationDeclaration
22 partial.problem.relations.filter(RelationDeclaration).forEach[
23 //only need the name of the reference type (remove everything with and after "reference")
24 var n = it.name.split(" ").get(0);
25 this.statistic.addEdgeType(n);
26 ]
27 // add all elements
28 val typeInterpretations = getTypes(partial);
29 for(type : typeInterpretations){
30 //Only consider the most concrete class
31 if(isConcreteType(type.interpretationOf)){
32 var typeName = type.interpretationOf.name.replace(classSuffix, '');
33 for(node : type.elements){
34 if(!this.statistic.containsNode(node)){
35 this.statistic.addNodeWithType(node, typeName);
36 }else{
37 // if the current type of the node is a super type of the type to check,
38 // substitute the current type with the new type
39 var currentType = statistic.getTypesForNode(node).get(0);
40 if(isSuperType(currentType, type.interpretationOf)){
41 statistic.overwriteCurrentType(node, typeName);
42 }
43 }
44 }
45 }
46 }
47
48 for(relationInterpretation : partial.partialrelationinterpretation) {
49 //only need the name of the reference type (remove everything with and after "reference")
50 val type = relationInterpretation.interpretationOf.name.split(" ").get(0);
51 for(edge : relationInterpretation.relationlinks.filter(BinaryElementRelationLink)){
52 statistic.addEdge(edge.param1, edge.param2, type);
53 }
54 }
55
56 this.name = name;
57 this.metrics = metrics;
58 }
59
60 /**
61 * recursively check if a type is the super type of another
62 */
63 def boolean isSuperType(String typeName, Type subtypeToCheck){
64 var superTypes = subtypeToCheck.supertypes;
65 if(superTypes.size == 0){
66 return false;
67 }else if(subtypeToCheck.supertypes.map[it.name.replace(classSuffix, '')].contains(typeName)){
68 return true;
69 }else{
70 for(superType : superTypes){
71 if(isSuperType(typeName, superType)){
72 return true;
73 }
74 }
75 return false;
76 }
77 }
78
79 /**
80 * Check if a Type object is the class that we want to consider
81 * A type object is to be considered if it satisfy one of the following:
82 * 1. if it is not abstract
83 * 2. if it is abstract but has a subclass of type TypeDefinition (This means the generation is
84 * started with nodes in this type)
85 */
86 def boolean isConcreteType(Type t){
87 if(!t.isAbstract || t.subtypes.findFirst[it instanceof TypeDefinition] !== null){
88 return true;
89 }
90 return false;
91 }
92
93 /**
94 * Set basic information for the output
95 */
96 override setBasicInformation(ArrayList<ArrayList<String>> output){
97 val metaInfo = new ArrayList<String>();
98 metaInfo.add(META_MODEL_HEADER);
99 metaInfo.add(this.metaModel);
100
101 val edgeInfo = new ArrayList<String>();
102 edgeInfo.add(NUM_EDGE_TYPE_HEADER);
103 edgeInfo.add(this.statistic.allTypes.size()+"");
104
105 val nodeInfo = new ArrayList<String>();
106 nodeInfo.add(NUM_NODE_HEADER);
107 nodeInfo.add(this.statistic.allNodes.size()+"");
108
109 val stateInfo = new ArrayList<String>();
110 stateInfo.add(STATE_ID_HEADER);
111 stateInfo.add(this.name);
112
113 output.add(metaInfo);
114 output.add(edgeInfo);
115 output.add(nodeInfo);
116 output.add(stateInfo);
117 }
118
119 private def getTypes(PartialInterpretation partial){
120 //only the complex type interpretations are the ones defined in meta model
121 //do not care about undefined types as it will be included in the class type
122 return partial.partialtypeinterpratation.filter(PartialComplexTypeInterpretationImpl)
123 .filter[!it.interpretationOf.name.toLowerCase.contains(typeToExclude)];
124 }
125
126 override getStatistic() {
127 throw new UnsupportedOperationException("TODO: auto-generated method stub")
128 }
129
130 override getName() {
131 return name;
132 }
133
134} \ No newline at end of file