Skip to content

Commit dca5028

Browse files
committed
Merge branch 'simulator' into v2.1
2 parents f73c3ce + 16be7ec commit dca5028

File tree

3 files changed

+158
-47
lines changed

3 files changed

+158
-47
lines changed

org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4viz/VizGUI.java

+151-47
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@
4646
import java.lang.reflect.Method;
4747
import java.util.ArrayList;
4848
import java.util.HashMap;
49-
import java.util.HashSet;
5049
import java.util.LinkedHashMap;
5150
import java.util.List;
5251
import java.util.Map;
5352
import java.util.Set;
53+
import java.util.StringJoiner;
5454
import java.util.prefs.Preferences;
5555

5656
import javax.swing.Box;
@@ -85,17 +85,13 @@
8585
import edu.mit.csail.sdg.alloy4.Util;
8686
import edu.mit.csail.sdg.alloy4.Version;
8787
import edu.mit.csail.sdg.alloy4graph.GraphViewer;
88-
import kodkod.ast.Decls;
89-
import kodkod.ast.Expression;
90-
import kodkod.ast.Formula;
91-
import kodkod.ast.Node;
92-
import kodkod.ast.QuantifiedFormula;
93-
import kodkod.ast.Relation;
94-
import kodkod.ast.Variable;
95-
import kodkod.ast.visitor.AbstractReplacer;
96-
import kodkod.instance.PardinusBounds;
97-
import kodkod.instance.TemporalInstance;
98-
import kodkod.util.nodes.PrettyPrinter;
88+
import edu.mit.csail.sdg.ast.Expr;
89+
import edu.mit.csail.sdg.ast.ExprConstant;
90+
import edu.mit.csail.sdg.ast.ExprVar;
91+
import edu.mit.csail.sdg.ast.Sig;
92+
import edu.mit.csail.sdg.translator.A4Solution;
93+
import edu.mit.csail.sdg.translator.A4Tuple;
94+
import edu.mit.csail.sdg.translator.A4TupleSet;
9995

10096
/**
10197
* GUI main window for the visualizer.
@@ -141,7 +137,10 @@ public final class VizGUI implements ComponentListener {
141137
private final JButton projectionButton, openSettingsButton, closeSettingsButton, magicLayout,
142138
loadSettingsButton, saveSettingsButton, saveAsSettingsButton, resetSettingsButton, updateSettingsButton,
143139
openEvaluatorButton, closeEvaluatorButton, enumerateButton, vizButton, treeButton,
144-
txtButton, tableButton, leftNavButton, rightNavButton, cnfgButton, forkButton, initButton/* , dotButton, xmlButton */; // [HASLab]
140+
txtButton, tableButton, leftNavButton, rightNavButton, cnfgButton, forkButton, initButton, pathButton/*
141+
* , dotButton,
142+
* xmlButton
143+
*/; // [HASLab]
145144

146145
/**
147146
* This list must contain all the display mode buttons (that is, vizButton,
@@ -158,15 +157,19 @@ public final class VizGUI implements ComponentListener {
158157
/** The "show next" menu item. */
159158
private final JMenuItem enumerateMenu;
160159

161-
/** The "fork next" menu item. */
160+
/** The "fresh config" menu item. */
162161
// [HASLab]
163162
private final JMenuItem cnfgMenu;
164163

164+
/** The "fresh path" menu item. */
165+
// [HASLab]
166+
private final JMenuItem pathMenu;
167+
165168
/** The "fork next" menu item. */
166169
// [HASLab]
167170
private final JMenuItem forkMenu;
168171

169-
/** The "fork next" menu item. */
172+
/** The "fork init" menu item. */
170173
// [HASLab]
171174
private final JMenuItem initMenu;
172175

@@ -183,6 +186,9 @@ public final class VizGUI implements ComponentListener {
183186
*/
184187
private int settingsOpen = 0;
185188

189+
// [HASLab]
190+
private boolean seg_iteration = false;
191+
186192
/**
187193
* The current states and visualization settings; null if none is loaded.
188194
*/
@@ -645,6 +651,7 @@ else if (height < 100)
645651
JMenu instanceMenu = menu(mb, "&Instance", null);
646652
enumerateMenu = menuItem(instanceMenu, "Show Next Solution", 'N', 'N', doNext());
647653
cnfgMenu = menuItem(instanceMenu, "Show Fresh Configuration", 'C', 'C', doConfig()); // [HASLab]
654+
pathMenu = menuItem(instanceMenu, "Show Fresh Path", 'P', 'P', doPath()); // [HASLab]
648655
initMenu = menuItem(instanceMenu, "Show Fresh Initial State", 'I', 'I', doInit()); // [HASLab]
649656
forkMenu = menuItem(instanceMenu, "Show Different Post-state", 'F', 'F', doFork()); // [HASLab]
650657
leftNavMenu = menuItem(instanceMenu, "Show Previous State", KeyEvent.VK_LEFT, KeyEvent.VK_LEFT, leftNavListener); // [HASLab]
@@ -701,6 +708,7 @@ public void actionPerformed(ActionEvent e) {
701708
toolbar.add(closeEvaluatorButton = OurUtil.button("Close Evaluator", "Close the evaluator", "images/24_settings_close2.gif", doCloseEvalPanel()));
702709
toolbar.add(enumerateButton = OurUtil.button("Next", "Show a fresh solution", "images/24_history.gif", doNext()));
703710
toolbar.add(cnfgButton = OurUtil.button("Fresh Config", "Show a fresh configuration", "images/24_history.gif", doConfig())); // [HASLab]
711+
toolbar.add(pathButton = OurUtil.button("Fresh Path", "Show a fresh path", "images/24_history.gif", doPath())); // [HASLab]
704712
toolbar.add(initButton = OurUtil.button("Fresh Init", "Show a fresh initial state", "images/24_history.gif", doInit())); // [HASLab]
705713
toolbar.add(forkButton = OurUtil.button("Fork", "Show a different post-state", "images/24_history.gif", doFork())); // [HASLab]
706714
toolbar.add(leftNavButton = OurUtil.button(new String(Character.toChars(0x2190)), "Show the previous state", "images/24_history.gif", leftNavListener));
@@ -876,6 +884,10 @@ private void updateDisplay() {
876884
initMenu.setEnabled(!isMeta && settingsOpen == 0 && enumerator != null); // [HASLab]
877885
initMenu.setVisible(isTrace); // [HASLab]
878886
initButton.setVisible(!isMeta && settingsOpen == 0 && enumerator != null && isTrace); // [HASLab]
887+
pathMenu.setEnabled(!isMeta && settingsOpen == 0 && enumerator != null && !seg_iteration); // [HASLab]
888+
pathMenu.setVisible(isTrace); // [HASLab]
889+
pathButton.setVisible(!isMeta && settingsOpen == 0 && enumerator != null && isTrace); // [HASLab]
890+
pathButton.setEnabled(!seg_iteration); // [HASLab]
879891
cnfgMenu.setEnabled(!isMeta && settingsOpen == 0 && enumerator != null); // [HASLab]
880892
cnfgMenu.setVisible(isTrace); // [HASLab]
881893
cnfgButton.setVisible(!isMeta && settingsOpen == 0 && enumerator != null && isTrace); // [HASLab]
@@ -1127,6 +1139,8 @@ public void loadXML(final String fileName, boolean forcefully, int state) {
11271139
current = state; // [HASLab]
11281140
final String xmlFileName = Util.canon(fileName);
11291141
File f = new File(xmlFileName);
1142+
if (!forcefully)
1143+
seg_iteration = false;
11301144
if (forcefully || !xmlFileName.equals(this.xmlFileName)) {
11311145
for (int i = 0; i < statepanes; i++) { // [HASLab]
11321146
try {
@@ -1443,46 +1457,107 @@ private Runner doExportXml() {
14431457
}
14441458

14451459
// [HASLab]
1446-
// reuses the Pardinus instance to formula translation, so needs some tweaks to the Alloy level
1460+
// ad hoc implementation since alloy lacks a proper pretty printer
1461+
// also, prints conjunctions as lists, which can't be parsed
14471462
private Runner doExportLTL() {
14481463
if (wrap)
14491464
return wrapMe();
14501465
if (myStates.isEmpty())
14511466
return null;
1452-
TemporalInstance inst = (TemporalInstance) myStates.get(myStates.size() - 1).getOriginalInstance().originalA4.debugExtractKInstance();
1453-
Formula rels = Formula.TRUE;
1454-
for (Relation r : inst.state(0).relations())
1455-
if (!(r.toString().startsWith("Int/") || r.toString().startsWith("seq/") || r.isAtom()))
1456-
rels = rels.and(r.eq(r));
1457-
Formula form = null;
1458-
Map<Object,Expression> reifs = new HashMap<Object,Expression>();
1459-
form = inst.formulate(reifs, rels, true, new PardinusBounds(inst.state(0).universe()), false);
1460-
Expression unvs = Expression.UNIV;
1461-
for (int i = 1; i < inst.prefixLength(); i++)
1462-
unvs = Expression.UNIV.union(unvs.prime());
1463-
Decls decs = null;
1464-
for (Expression rs : reifs.values()) {
1465-
if (decs == null)
1466-
decs = ((Variable) rs).oneOf(unvs);
1467-
else
1468-
decs = decs.and(((Variable) rs).oneOf(unvs));
1469-
}
1470-
form = ((QuantifiedFormula) form).formula().forSome(decs);
1471-
// [HASLab] normalize variable names
1472-
AbstractReplacer repls = new AbstractReplacer(new HashSet<Node>()) {
14731467

1474-
@Override
1475-
public Expression visit(Variable v) {
1476-
final Expression ret = lookup(v);
1477-
if (ret != null)
1478-
return ret;
1479-
String n = v.name().replace("$", "");
1480-
return cache(v, Variable.nary(n, v.arity()));
1468+
Map<String,ExprVar> reifs = new HashMap<String,ExprVar>();
1469+
A4Solution inst = myStates.get(myStates.size() - 1).getOriginalInstance().originalA4;
1470+
1471+
StringJoiner config = new StringJoiner(" and ");
1472+
for (Sig s : inst.getAllReachableSigs()) {
1473+
if (s.isPrivate != null || s.isVariable != null || s.equals(Sig.UNIV) || s.equals(Sig.NONE))
1474+
continue;
1475+
A4TupleSet ts = inst.eval(s);
1476+
Expr tupleset = null;
1477+
for (A4Tuple t : ts) {
1478+
Expr tuple = null;
1479+
for (int ai = 0; ai < t.arity(); ai++) {
1480+
Expr atom;
1481+
if (t.atom(ai).matches("-?\\d+")) {
1482+
atom = ExprConstant.makeNUMBER(Integer.valueOf(t.atom(ai)));
1483+
} else {
1484+
atom = reifs.computeIfAbsent("_" + t.atom(ai).replace("$", "").replace("/", "_"), k -> ExprVar.make(null, k));
1485+
}
1486+
tuple = tuple == null ? atom : tuple.product(tuple);
1487+
}
1488+
tupleset = tupleset == null ? tuple : tupleset.plus(tuple);
14811489
}
1490+
if (tupleset == null) {
1491+
tupleset = ExprConstant.EMPTYNESS;
1492+
for (int ai = 0; ai < ts.arity() - 1; ai++)
1493+
tupleset = tupleset.product(ExprConstant.EMPTYNESS);
1494+
}
1495+
config.add(s.equal(tupleset).toString());
1496+
}
14821497

1483-
};
1484-
form = form.accept(repls);
1485-
OurDialog.showtext("Text Viewer", PrettyPrinter.print(form, 4).replaceAll("Int\\[(-?\\d*)\\]", "$1").replaceFirst("some", "some disj"));
1498+
List<String> states = new ArrayList<String>();
1499+
for (int i = 0; i < inst.getTraceLength(); i++) {
1500+
StringJoiner state = new StringJoiner(" and ");
1501+
for (Sig s : inst.getAllReachableSigs()) {
1502+
if (s.isPrivate != null || (s.isVariable == null && !s.equals(Sig.UNIV)))
1503+
continue;
1504+
A4TupleSet ts = inst.eval(s, i);
1505+
Expr tupleset = null;
1506+
for (A4Tuple t : ts) {
1507+
Expr tuple = null;
1508+
for (int ai = 0; ai < t.arity(); ai++) {
1509+
Expr atom;
1510+
if (t.atom(ai).matches("-?\\d+")) {
1511+
atom = ExprConstant.makeNUMBER(Integer.valueOf(t.atom(ai)));
1512+
} else {
1513+
atom = reifs.computeIfAbsent("_" + t.atom(ai).replace("$", "").replace("/", "_"), k -> ExprVar.make(null, k));
1514+
}
1515+
tuple = tuple == null ? atom : tuple.product(tuple);
1516+
}
1517+
tupleset = tupleset == null ? tuple : tupleset.plus(tuple);
1518+
}
1519+
if (tupleset == null) {
1520+
tupleset = ExprConstant.EMPTYNESS;
1521+
for (int ai = 0; ai < ts.arity() - 1; ai++)
1522+
tupleset = tupleset.product(ExprConstant.EMPTYNESS);
1523+
}
1524+
state.add(s.equal(tupleset).toString());
1525+
}
1526+
states.add(state.toString());
1527+
}
1528+
StringBuilder sb = new StringBuilder();
1529+
sb.append("some disj ");
1530+
StringJoiner sj = new StringJoiner(",");
1531+
for (ExprVar v : reifs.values())
1532+
sj.add(v.toString());
1533+
sb.append(sj.toString());
1534+
sb.append(" : ");
1535+
Expr unvs = Sig.UNIV;
1536+
for (int i = 0; i < inst.getTraceLength() - 1; i++)
1537+
unvs = Sig.UNIV.plus(unvs.prime());
1538+
sb.append(unvs.toString());
1539+
sb.append(" {\n ");
1540+
sb.append(config.toString());
1541+
sb.append("\n\n ");
1542+
StringJoiner statesj = new StringJoiner(";\n ");
1543+
for (String s : states)
1544+
statesj.add(s);
1545+
sb.append(statesj.toString());
1546+
sb.append("\n\n ");
1547+
for (int i = 0; i < inst.getLoopState(); i++)
1548+
sb.append("after ");
1549+
sb.append(" {\n");
1550+
for (int i = inst.getLoopState(); i < inst.getTraceLength(); i++) {
1551+
StringBuilder sa = new StringBuilder("");
1552+
for (int j = inst.getLoopState(); j < inst.getTraceLength(); j++)
1553+
sa.append("after ");
1554+
sa.append("(");
1555+
sa.append(states.get(i));
1556+
sa.append(")");
1557+
sb.append(" (" + states.get(i) + ") implies " + sa.toString() + "\n");
1558+
}
1559+
sb.append(" }\n}\n");
1560+
OurDialog.showtext("Text Viewer", sb.toString());
14861561
return null;
14871562
}
14881563

@@ -1619,6 +1694,7 @@ private Runner doConfig() {
16191694
OurDialog.alert("Cannot display the next solution since the analysis engine is not loaded with the visualizer.");
16201695
} else {
16211696
try {
1697+
seg_iteration = false;
16221698
enumerator.compute(new String[] {
16231699
xmlFileName, -1 + ""
16241700
});
@@ -1629,6 +1705,32 @@ private Runner doConfig() {
16291705
return null;
16301706
}
16311707

1708+
/**
1709+
* This method attempts to derive the next satisfying instance.
1710+
*/
1711+
// [HASLab]
1712+
private Runner doPath() {
1713+
if (wrap)
1714+
return wrapMe();
1715+
if (settingsOpen != 0)
1716+
return null;
1717+
if (xmlFileName.length() == 0) {
1718+
OurDialog.alert("Cannot display the next solution since no instance is currently loaded.");
1719+
} else if (enumerator == null) {
1720+
OurDialog.alert("Cannot display the next solution since the analysis engine is not loaded with the visualizer.");
1721+
} else {
1722+
try {
1723+
seg_iteration = false;
1724+
enumerator.compute(new String[] {
1725+
xmlFileName, -2 + ""
1726+
});
1727+
} catch (Throwable ex) {
1728+
OurDialog.alert(ex.getMessage());
1729+
}
1730+
}
1731+
return null;
1732+
}
1733+
16321734
/** This method attempts to derive the next satisfying instance. */
16331735
// [HASLab] simulator
16341736
private Runner doFork() {
@@ -1642,6 +1744,7 @@ private Runner doFork() {
16421744
OurDialog.alert("Cannot display the next solution since the analysis engine is not loaded with the visualizer.");
16431745
} else {
16441746
try {
1747+
seg_iteration = true;
16451748
enumerator.compute(new String[] {
16461749
xmlFileName, current + 1 + ""
16471750
});
@@ -1665,6 +1768,7 @@ private Runner doInit() {
16651768
OurDialog.alert("Cannot display the next solution since the analysis engine is not loaded with the visualizer.");
16661769
} else {
16671770
try {
1771+
seg_iteration = true;
16681772
enumerator.compute(new String[] {
16691773
xmlFileName, 0 + ""
16701774
});

org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/ExprUnary.java

+5
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ public void toString(StringBuilder out, int indent) {
101101
sub.toString(out, -1);
102102
out.append(']');
103103
return;
104+
case PRIME : // [HASLab]
105+
out.append('(');
106+
sub.toString(out, -1);
107+
out.append(")'");
108+
return;
104109
case NOOP :
105110
break;
106111
default :

org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/A4Solution.java

+2
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,8 @@ private A4Solution(A4Solution old, int state) throws Err {
484484
try { // [HASLab] better reporting of unsupported iteration
485485
if (state == -1) // [HASLab] simulator, this is a next config
486486
inst = old.kEnumerator.nextC().instance();
487+
else if (state == -2) // [HASLab] simulator, this is a next path
488+
inst = old.kEnumerator.nextP().instance();
487489
else if (state >= 0) { // [HASLab] simulator, this is a fork
488490
Set<Relation> rels = ((TemporalInstance) old.eval.instance()).state(0).relations().stream().filter(r -> r.isVariable()).collect(Collectors.toSet());
489491
inst = old.kEnumerator.nextS(state, 1, rels).instance();

0 commit comments

Comments
 (0)