Skip to content

Commit b837698

Browse files
merkstemaxkurze1
authored andcommitted
Fix evaluation order of labels instead repetitive recursion
1 parent 5fa10d0 commit b837698

2 files changed

Lines changed: 65 additions & 44 deletions

File tree

prism/src/parser/ast/LabelList.java

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,12 @@
2626

2727
package parser.ast;
2828

29-
import parser.State;
3029
import parser.visitor.ASTVisitor;
3130
import prism.PrismLangException;
3231
import prism.PrismUtils;
3332

3433
import java.util.ArrayList;
35-
import java.util.HashMap;
3634
import java.util.List;
37-
import java.util.Map;
3835
import java.util.Vector;
3936

4037
// class to store list of labels
@@ -67,7 +64,23 @@ public LabelList()
6764
*/
6865
public void findCycles() throws PrismLangException
6966
{
70-
// Create boolean matrix of dependencies
67+
boolean[][] matrix = getLabelDependencies();
68+
// Check for and report dependencies
69+
int firstCycle = PrismUtils.findCycle(matrix);
70+
if (firstCycle != -1) {
71+
String s = "Cyclic dependency in definition of label \"" + names.get(firstCycle) + "\"";
72+
throw new PrismLangException(s, labels.get(firstCycle));
73+
}
74+
}
75+
76+
/**
77+
* Create a boolean matrix of dependencies between labels.
78+
*
79+
* @return a matrix m such that label i depends on label j iff m[i][j]
80+
* @throws PrismLangException
81+
*/
82+
public boolean[][] getLabelDependencies() throws PrismLangException
83+
{
7184
// (matrix[i][j] is true if label i contains label j)
7285
int n = size();
7386
int j;
@@ -81,12 +94,7 @@ public void findCycles() throws PrismLangException
8194
}
8295
}
8396
}
84-
// Check for and report dependencies
85-
int firstCycle = PrismUtils.findCycle(matrix);
86-
if (firstCycle != -1) {
87-
String s = "Cyclic dependency in definition of label \"" + names.get(firstCycle) + "\"";
88-
throw new PrismLangException(s, labels.get(firstCycle));
89-
}
97+
return matrix;
9098
}
9199

92100
// Set methods

prism/src/simulator/LabelEvaluator.java

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
package simulator;
22

33

4+
import common.iterable.IterableArray;
5+
import common.iterable.Range;
6+
import common.iterable.Reducible;
47
import parser.State;
58
import parser.ast.Expression;
69
import parser.ast.LabelList;
710
import prism.PrismException;
811
import prism.PrismLangException;
12+
import prism.PrismUtils;
913

10-
import java.util.BitSet;
11-
import java.util.HashMap;
12-
import java.util.List;
13-
import java.util.Map;
14+
import java.util.*;
15+
import java.util.function.Predicate;
1416

1517
/**
1618
* This class will evaluate labels. Therefore, it's wrapped around a {@link LabelList}.
@@ -23,13 +25,47 @@ public class LabelEvaluator
2325
Map<State, BitSet> stateValues = new HashMap<>();
2426
/** The labelList that will be evaluated */
2527
LabelList labelList;
28+
int[] evaluationOrder;
2629

2730
/**
2831
* Creates new object that will evaluate and cache the given {@link LabelList}.
2932
*/
30-
public LabelEvaluator(LabelList labelList)
33+
public LabelEvaluator(LabelList labelList) throws PrismLangException
3134
{
3235
this.labelList = labelList;
36+
this.evaluationOrder = fixEvaluationOrder(labelList);
37+
}
38+
39+
/**
40+
* Fix an order on the labels such that l1 < l2 if l2 depends on l1
41+
* @param labels
42+
* @return an int array of the label indices in ascending order
43+
* @throws PrismLangException In case a label depencies could not be computed.
44+
*/
45+
private int[] fixEvaluationOrder(LabelList labels) throws PrismLangException
46+
{
47+
boolean[][] deps = labels.getLabelDependencies();
48+
assert PrismUtils.findCycle(deps) == -1 : "label dependencies must not contain a cylce";
49+
50+
int numLabels = labels.size();
51+
Integer[] order = new Range(numLabels).collect(new Integer[numLabels]);
52+
Arrays.sort(order, new Comparator<Integer>()
53+
{
54+
@Override
55+
public int compare(Integer row, Integer col)
56+
{
57+
int i = row;
58+
int j = col;
59+
if (deps[i][j]) { // i depends on j
60+
return +1;
61+
}
62+
if (deps[j][i]) { // j depends on i
63+
return -1;
64+
}
65+
return Integer.compare(i, j);
66+
}
67+
});
68+
return Reducible.unboxInt(new IterableArray.Of<>(order)).collect(new int[numLabels]);
3369
}
3470

3571
/**
@@ -60,7 +96,7 @@ public Map<String, Boolean> getLabelValues(State state) throws PrismLangExceptio
6096
labelValueMap.put(labelList.getLabelName(i), value.get(i));
6197
}
6298
return labelValueMap;
63-
}
99+
}
64100

65101
/**
66102
* This method provides all values of a certain label. They will be ordered by the given statesList. <br>
@@ -112,36 +148,13 @@ private BitSet evaluateState(State state) throws PrismLangException
112148
int numLabels = labelList.size();
113149
Map<String, Boolean> labelValues = new HashMap<>(numLabels);
114150
BitSet values = new BitSet();
115-
for (int labelIndex = numLabels; labelIndex >= 0; labelIndex--) {
116-
boolean labelValue = evaluateLabel(labelList.getLabelName(labelIndex), labelValues, state);
117-
values.set(labelIndex, labelValue);
151+
for (int i : evaluationOrder) {
152+
Expression label = labelList.getLabel(i);
153+
boolean labelValue = label.evaluateBoolean(null, labelValues, state);
154+
labelValues.put(labelList.getLabelName(i), labelValue);
155+
values.set(i, labelValue);
118156
}
119157
stateValues.put(state, values);
120158
return values;
121159
}
122-
123-
/**
124-
* Helper function to recursively evaluate label values. The value will be stored inside the given map.
125-
*
126-
* @param name The name of the label.
127-
* @param labelValues The already known values of all labels.
128-
*/
129-
private boolean evaluateLabel(String name, Map<String, Boolean> labelValues, State state) throws PrismLangException
130-
{
131-
// check if value is already known
132-
if (labelValues.containsKey(name)) {
133-
return labelValues.get(name);
134-
}
135-
// get expression
136-
Expression label = labelList.getLabel(labelList.getLabelIndex(name));
137-
// check if all the (other) label dependencies are evaluated
138-
for (String dependency : label.getAllLabels()){
139-
// evaluate other label first
140-
evaluateLabel(dependency, labelValues, state);
141-
}
142-
// all dependencies are fulfilled
143-
boolean labelValue = label.evaluateBoolean(null, labelValues, state);
144-
labelValues.put(name, labelValue);
145-
return labelValue;
146-
}
147160
}

0 commit comments

Comments
 (0)