Skip to content

Commit 6e2c7ce

Browse files
author
Nuno Macedo
authored
Merge pull request #43 from haslab/dev
Version 1.2.2
2 parents 892ef18 + d23c002 commit 6e2c7ce

File tree

12 files changed

+307
-109
lines changed

12 files changed

+307
-109
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>pt.uminho.haslab.pardinus</groupId>
66
<artifactId>pardinus</artifactId>
7-
<version>1.2.1</version>
7+
<version>1.2.2</version>
88
<packaging>jar</packaging>
99
<name>pardinus</name>
1010
<profiles>

src/main/java/kodkod/engine/TemporalPardinusSolver.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,10 @@ private Solution nextNonTrivialSolution(int state, int steps, Set<Relation> fix,
563563
private int iteration_stage = 0;
564564

565565
private Solution nextNonTrivialSolutionSAT(int state, int steps, Set<Relation> fix, Set<Relation> change) {
566+
if (change.isEmpty()) {
567+
translation = null;
568+
return Solution.unsatisfiable(new Statistics(0, 0, 0, 0, 0), null);
569+
}
566570

567571
boolean isSat = false;
568572
long solveTime = 0;

src/main/java/kodkod/engine/fol2sat/SymmetryBreaker.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ final BooleanValue generateSBP(LeafInterpreter interpreter, Options options) {
211211
int curIndex = indeces.next();
212212
Iterator<Tuple> times = null;
213213
if (bounds.relations().contains(TemporalTranslator.STATE))
214-
bounds.lowerBound(TemporalTranslator.STATE).iterator();
214+
times = bounds.lowerBound(TemporalTranslator.STATE).iterator();
215215
Tuple time = null;
216216
do {
217217
for(Iterator<RelationParts> rIter = relParts.iterator(); rIter.hasNext() && original.size() < predLength;) {
@@ -239,7 +239,7 @@ final BooleanValue generateSBP(LeafInterpreter interpreter, Options options) {
239239
continue;
240240

241241
boolean zzz = false;
242-
if (times != null) {
242+
if (times != null) {
243243
TupleSet yyy = bounds.lowerBound(TemporalTranslator.STATE);
244244
Tuple xxx = interpreter.universe().factory().tuple(interpreter.universe().factory().tuple(r.arity(), entry.index()).atom(r.arity()-1));
245245
zzz = yyy.contains(xxx);

src/main/java/kodkod/instance/Instance.java

Lines changed: 73 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import kodkod.ast.ConstantExpression;
3535
import kodkod.ast.Expression;
3636
import kodkod.ast.Formula;
37+
import kodkod.ast.IntConstant;
3738
import kodkod.ast.NaryFormula;
3839
import kodkod.ast.Relation;
3940
import kodkod.ast.Variable;
@@ -235,37 +236,76 @@ public Instance clone() {
235236
}
236237
}
237238

239+
238240
/**
239241
* Converts an instance into a formula that exactly identifies it. Requires that
240-
* every relevant atom be reified into a singleton relation, which may be
241-
* re-used between calls. Relevant atoms are determined from the provided formulas.
242+
* every relevant atom be reified into a singleton relation or quantified in a
243+
* some-disj pattern, which may be re-used between calls. Relevant atoms are
244+
* determined from the provided formulas.
242245
*
243-
* Will change <bounds> if not all atoms of the universe are present at <reif>.
246+
* Will change <bounds> if not all atoms of the universe are present at <reif>
247+
* and <someDisj> false.
244248
*
245-
* @assumes reif != null
246-
* @param reif
247-
* the previously reified atoms
248-
* @throws NullPointerException
249-
* reif = null
249+
* @assumes reif != null
250+
* @assumes !someDisj => bounds != null
251+
* @param reif the previously reified atoms, as relations or quantified vars depending on <someDisj>
252+
* @param formula a formula from which the relevant relations are identified
253+
* @param someDisj whether the formula will use atoms reified as relations or a some-disj pattern
254+
* @param bounds the problem's bounds, updated if !someDisj
255+
* @throws NullPointerException reif = null
256+
* @throws NullPointerException !someDisj && bounds == null
257+
* @return the formula representing <this>
258+
*/
259+
public Formula formulate(Map<Object, Expression> reif, Formula formula, boolean someDisj, Bounds bounds) {
260+
return formulate(reif,formula,someDisj,bounds,false);
261+
}
262+
263+
/**
264+
* Converts an instance into a formula that exactly identifies it. Requires that
265+
* every relevant atom be reified into a singleton relation or quantified in a
266+
* some-disj pattern, which may be re-used between calls. Relevant atoms are
267+
* determined from the provided formulas.
268+
*
269+
* Will change <bounds> if not all atoms of the universe are present at <reif>
270+
* and <someDisj> false.
271+
*
272+
* @assumes reif != null
273+
* @assumes !someDisj => bounds != null
274+
* @param reif the previously reified atoms, as relations or quantified vars depending on <someDisj>
275+
* @param formula a formula from which the relevant relations are identified
276+
* @param someDisj whether the formula will use atoms reified as relations or a some-disj pattern
277+
* @param bounds the problem's bounds, updated if !someDisj
278+
* @param localUniv whether to restrict the universe of atoms locally, only relevant if some-disj pattern
279+
* @throws NullPointerException reif = null
280+
* @throws NullPointerException !someDisj && bounds == null
250281
* @return the formula representing <this>
251282
*/
252283
// [HASLab]
253-
public Formula formulate(Bounds bounds, Map<Object, Expression> reif, Formula formula, boolean someDisj) {
254-
284+
public Formula formulate(Map<Object, Expression> reif, Formula formula, boolean someDisj, Bounds bounds, boolean localUniv) {
285+
255286
Set<Relation> relevants = formula.accept(new RelationCollector(new HashSet<>()));
256287
// reify atoms not yet reified
257288
for (int i = 0; i < universe().size(); i++) {
258-
Expression r;
259-
if (reif.keySet().contains(universe().atom(i)))
260-
r = reif.get(universe().atom(i));
261-
else {
262-
r = Relation.atom(universe().atom(i).toString());
263-
reif.put(universe().atom(i), r);
289+
// integers do not need to be quantified
290+
if (!universe().atom(i).toString().matches("-?\\d+")) {
291+
Expression r;
292+
if (reif.keySet().contains(universe().atom(i)))
293+
r = reif.get(universe().atom(i));
294+
else {
295+
if (someDisj) {
296+
r = Variable.unary(universe().atom(i).toString());
297+
} else {
298+
r = Relation.atom(universe().atom(i).toString());
299+
}
300+
reif.put(universe().atom(i), r);
301+
}
302+
if (!someDisj && !bounds.relations.contains(r))
303+
bounds.boundExactly((Relation) r, bounds.universe().factory().setOf(universe().atom(i)));
264304
}
265-
if (r instanceof Relation && !bounds.relations.contains(r))
266-
bounds.boundExactly((Relation) r, bounds.universe().factory().setOf(universe().atom(i)));
267305
}
268306

307+
List<Expression> locals = new ArrayList<Expression>();
308+
269309
// create an equality for every relation
270310
// a = A + ... && r = A -> B + ...
271311
List<Formula> res = new ArrayList<Formula>();
@@ -281,6 +321,7 @@ public Formula formulate(Bounds bounds, Map<Object, Expression> reif, Formula fo
281321
if (it.hasNext()) {
282322
Tuple u = it.next();
283323
Expression r1 = reif.get(u.atom(0));
324+
locals.add(r1);
284325
for (int i = 1; i < u.arity(); i++)
285326
r1 = r1.product(reif.get(u.atom(i)));
286327
r = r1;
@@ -293,12 +334,26 @@ public Formula formulate(Bounds bounds, Map<Object, Expression> reif, Formula fo
293334
while (it.hasNext()) {
294335
Tuple u = it.next();
295336
Expression r1 = reif.get(u.atom(0));
337+
locals.add(r1);
296338
for (int i = 1; i < u.arity(); i++)
297339
r1 = r1.product(reif.get(u.atom(i)));
298340
r = r.union(r1);
299341
}
300342
res.add(rel.eq(r));
301343
}
344+
345+
if (someDisj && localUniv) {
346+
Expression al = null;
347+
for (Expression e : locals)
348+
al = al == null? e : al.union(e);
349+
for (int i = 0; i < universe().size(); i++)
350+
if (universe().atom(i).toString().matches("-?\\d+")) {
351+
Expression intexp = IntConstant.constant(Integer.valueOf(universe().atom(i).toString())).toExpression();
352+
al = al == null ? intexp : al.union(intexp);
353+
}
354+
res.add(al.eq(Expression.UNIV));
355+
}
356+
302357
return NaryFormula.and(res);
303358
}
304359

src/main/java/kodkod/instance/TemporalInstance.java

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import kodkod.ast.Decls;
3636
import kodkod.ast.Expression;
3737
import kodkod.ast.Formula;
38+
import kodkod.ast.IntConstant;
3839
import kodkod.ast.Relation;
3940
import kodkod.ast.Variable;
4041
import kodkod.engine.Evaluator;
@@ -235,16 +236,25 @@ public TemporalInstance(Instance instance, PardinusBounds extbounds) {
235236
* Will change <bounds> if not all atoms of the universe are present at <reif>.
236237
*
237238
* @assumes reif != null
238-
* @param bounds the declaration of the relations
239239
* @param reif the previously reified atoms
240240
* @param formula formula used to identify the relevant relations
241+
* @param bounds the declaration of the relations
241242
* @throws NullPointerException reif = null
242243
* @return the formula representing <this>
243244
*/
244245
// [HASLab]
245246
@Override
246-
public Formula formulate(Bounds bounds, Map<Object, Expression> reif, Formula formula, boolean someDisj) {
247-
return formulate(bounds, reif, formula, -1, null, someDisj);
247+
public Formula formulate(Map<Object, Expression> reif, Formula formula, boolean someDisj, Bounds bounds) {
248+
return formulate(bounds, reif, formula, -1, null, someDisj, true);
249+
}
250+
251+
@Override
252+
public Formula formulate(Map<Object, Expression> reif, Formula formula, boolean someDisj, Bounds bounds, boolean localUniv) {
253+
return formulate(bounds, reif, formula, -1, null, someDisj, localUniv);
254+
}
255+
256+
public Formula formulate(Bounds bounds, Map<Object, Expression> reif, Formula formula, int start, Integer end, boolean someDisj) {
257+
return formulate(bounds, reif, formula, start, end, someDisj, true);
248258
}
249259

250260
/**
@@ -274,7 +284,7 @@ public Formula formulate(Bounds bounds, Map<Object, Expression> reif, Formula fo
274284
* @return the formula representing <this>
275285
*/
276286
// [HASLab]
277-
public Formula formulate(Bounds bounds, Map<Object, Expression> reif, Formula formula, int start, Integer end, boolean someDisj) {
287+
public Formula formulate(Bounds bounds, Map<Object, Expression> reif, Formula formula, int start, Integer end, boolean someDisj, boolean localUniv) {
278288
if (start < -1)
279289
throw new IllegalArgumentException("Segment start must be >= -1.");
280290
if (end != null && end < start)
@@ -283,22 +293,24 @@ public Formula formulate(Bounds bounds, Map<Object, Expression> reif, Formula fo
283293
// reify atoms not yet reified
284294
Universe sta_uni = states.get(0).universe();
285295
for (int i = 0; i < sta_uni.size(); i++) {
286-
Expression r;
287-
if (!reif.keySet().contains(sta_uni.atom(i))) {
288-
if (someDisj) {
289-
r = Variable.unary(sta_uni.atom(i).toString());
296+
// integers do not need to be quantified
297+
if (!sta_uni.atom(i).toString().matches("-?\\d+")) {
298+
Expression r;
299+
if (!reif.keySet().contains(sta_uni.atom(i))) {
300+
if (someDisj) {
301+
r = Variable.unary(sta_uni.atom(i).toString());
302+
} else {
303+
r = Relation.atom(sta_uni.atom(i).toString());
304+
}
305+
reif.put(sta_uni.atom(i), r);
290306
} else {
291-
r = Relation.atom(sta_uni.atom(i).toString());
307+
r = reif.get(sta_uni.atom(i));
292308
}
293-
reif.put(sta_uni.atom(i), r);
294-
} else {
295-
r = reif.get(sta_uni.atom(i));
309+
if (!someDisj && !bounds.relations.contains(r))
310+
bounds.boundExactly((Relation) r, bounds.universe().factory().setOf(sta_uni.atom(i)));
296311
}
297-
if (!someDisj && !bounds.relations.contains((Relation) r))
298-
bounds.boundExactly((Relation) r, bounds.universe().factory().setOf(sta_uni.atom(i)));
299312
}
300313

301-
302314
Set<Relation> staticss = new HashSet<Relation>();
303315
for (Relation r : states.get(0).relations())
304316
if (!r.isVariable())
@@ -318,11 +330,11 @@ public Formula formulate(Bounds bounds, Map<Object, Expression> reif, Formula fo
318330
// TODO: the looping formula should also be offset in this case!
319331
if (j == null)
320332
j = Integer.max(start + (prefixLength() - 1) - loop, prefixLength() - 1);
321-
if (j >= 0) {
333+
if (j != null && j >= 0) {
322334
// the state formulas, start from the end and accumulate afters
323-
res = state(j--).formulate(bounds, reif, slcs.getValue(), someDisj);
335+
res = state(j--).formulate(reif, slcs.getValue(), someDisj, bounds, !localUniv);
324336
for (; j >= Integer.max(0, start); j--)
325-
res = state(j).formulate(bounds, reif, slcs.getValue(), someDisj).and(res.after());
337+
res = state(j).formulate(reif, slcs.getValue(), someDisj, bounds, !localUniv).and(res.after());
326338
// after offset when start > 0
327339
for (; j >= 0; j--)
328340
res = res.after();
@@ -331,7 +343,7 @@ public Formula formulate(Bounds bounds, Map<Object, Expression> reif, Formula fo
331343

332344
// the configuration formula, if start = -1
333345
if (start < 0 && !slcs.getKey().equals(Formula.TRUE)) {
334-
Formula sres = states.get(prefixLength() - 1).formulate(bounds, reif, slcs.getKey(), someDisj);
346+
Formula sres = states.get(prefixLength() - 1).formulate(reif, slcs.getKey(), someDisj, bounds, false);
335347
res = res.equals(Formula.TRUE) ? sres : sres.and(res);
336348
}
337349

@@ -340,14 +352,14 @@ public Formula formulate(Bounds bounds, Map<Object, Expression> reif, Formula fo
340352
// create the looping constraint
341353
// after^loop always (Sloop => after^(end-loop) Sloop && Sloop+1 =>
342354
// after^(end-loop) Sloop+1 && ...)
343-
Formula rei = states.get(loop).formulate(bounds, reif, slcs.getValue(), someDisj);
355+
Formula rei = states.get(loop).formulate(reif, slcs.getValue(), someDisj, bounds, !localUniv);
344356
Formula rei2 = rei;
345357
for (int i = loop; i < prefixLength(); i++)
346358
rei2 = rei2.after();
347359

348360
Formula looping = rei.implies(rei2);
349361
for (int i = loop + 1; i < prefixLength(); i++) {
350-
rei = states.get(i).formulate(bounds, reif, slcs.getValue(), someDisj);
362+
rei = states.get(i).formulate(reif, slcs.getValue(), someDisj, bounds, !localUniv);
351363
rei2 = rei;
352364
for (int k = loop; k < prefixLength(); k++)
353365
rei2 = rei2.after();
@@ -372,7 +384,11 @@ public Formula formulate(Bounds bounds, Map<Object, Expression> reif, Formula fo
372384
decls = decls.and(((Variable) e).oneOf(Expression.UNIV));
373385
}
374386
}
375-
res = (al.eq(Expression.UNIV)).and(res);
387+
for (int i = 0; i < sta_uni.size(); i++)
388+
if (sta_uni.atom(i).toString().matches("-?\\d+"))
389+
al = al.union(IntConstant.constant(Integer.valueOf(sta_uni.atom(i).toString())).toExpression());
390+
if (localUniv)
391+
res = (al.eq(Expression.UNIV)).and(res);
376392
res = res.forSome(decls);
377393
}
378394
}

src/main/java/kodkod/util/nodes/PrettyPrinter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,8 +349,8 @@ public void visit(UnaryTempFormula node) {
349349
* parenthesized if it's an instance of binary expression or an if expression. **/
350350
// [HASLab]
351351
public void visit(TempExpression node) {
352-
keyword(node.op());
353352
visitChild(node.expression(), parenthesize(node.op(), node.expression()));
353+
append(node.op());
354354
}
355355

356356

0 commit comments

Comments
 (0)