Java Code Examples for kodkod.instance.Bounds#relations()

The following examples show how to use kodkod.instance.Bounds#relations() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: Translator.java    From org.alloytools.alloy with Apache License 2.0 6 votes vote down vote up
/**
 * Checks that the given {@code inc} bounds are incremental with respect to the
 * given {@code translation}.
 *
 * @requires translation.bounds.universe = inc.universe && no inc.intBound && no
 *           (translation.bounds.relations & inc.relations)
 * @requires all s: translation.symmetries | some p:
 *           {@link SymmetryDetector#partition(Bounds) partition}(inc) |
 *           s.elements in p.elements
 * @throws IllegalArgumentException any of the preconditions are violated
 */
public static void checkIncrementalBounds(Bounds inc, Translation.Incremental translation) {
    final Bounds base = translation.bounds();
    if (!base.universe().equals(inc.universe()))
        incBoundErr(inc.universe(), "universe", "equal to", base.universe());
    if (!inc.intBounds().isEmpty())
        incBoundErr(inc.intBounds(), "intBound", "empty, with integer bounds fully specified by", base.intBounds());
    if (inc.relations().isEmpty())
        return;
    final Set<Relation> baseRels = base.relations();
    for (Relation r : inc.relations()) {
        if (baseRels.contains(r)) {
            incBoundErr(inc.relations(), "relations", "disjoint from", baseRels);
        }
    }
    final Set<IntSet> symmetries = translation.symmetries();
    final Set<IntSet> incSymmetries = SymmetryDetector.partition(inc);
    EQUIV_CHECK: for (IntSet part : symmetries) {
        for (IntSet incPart : incSymmetries) {
            if (incPart.containsAll(part))
                continue EQUIV_CHECK;
        }
        incBoundErr(incSymmetries, "partition", "coarser than", symmetries);
    }
}
 
Example 2
Source File: Proc.java    From org.alloytools.alloy with Apache License 2.0 6 votes vote down vote up
public static Bounds union(Bounds b1, Bounds b2) {
    if (b1 == null)
        return b2;
    if (b2 == null)
        return b1;
    if (b1 == b2)
        return b1;
    if (b1.relations().containsAll(b2.relations()))
        return b1;
    if (b2.relations().containsAll(b1.relations()))
        return b2;
    Bounds ans = b1.clone();
    Set<Relation> diff = new HashSet<Relation>(b2.relations());
    // diff.removeAll(bounds.relations());
    for (Relation r : diff)
        ans.bound(r, b2.lowerBound(r), b2.upperBound(r));
    return ans;
}
 
Example 3
Source File: Translator.java    From kodkod with MIT License 6 votes vote down vote up
/**
 * Checks that the given {@code inc} bounds are incremental with respect to the given {@code translation}.
 * @requires translation.bounds.universe = inc.universe && no inc.intBound && no (translation.bounds.relations & inc.relations)
 * @requires all s: translation.symmetries |  
 * 				some p: {@link SymmetryDetector#partition(Bounds) partition}(inc) | 
 * 				   s.elements in p.elements
 * @throws IllegalArgumentException any of the preconditions are violated
 */
public static void checkIncrementalBounds(Bounds inc, Translation.Incremental translation) {
	final Bounds base = translation.bounds();
	if (!base.universe().equals(inc.universe()))
		incBoundErr(inc.universe(), "universe", "equal to", base.universe());
	if (!inc.intBounds().isEmpty()) 
		incBoundErr(inc.intBounds(), "intBound", "empty, with integer bounds fully specified by", base.intBounds());
	if (inc.relations().isEmpty()) return;
	final Set<Relation> baseRels = base.relations();
	for(Relation r : inc.relations()) { 
		if (baseRels.contains(r)) {
			incBoundErr(inc.relations(), "relations", "disjoint from", baseRels);
		}  
		}
	final Set<IntSet> symmetries = translation.symmetries();
	final Set<IntSet> incSymmetries = SymmetryDetector.partition(inc);
	EQUIV_CHECK : for(IntSet part : symmetries) {
		for(IntSet incPart : incSymmetries) {
			if (incPart.containsAll(part))
				continue EQUIV_CHECK;
		}
		incBoundErr(incSymmetries, "partition", "coarser than", symmetries);
	}
}
 
Example 4
Source File: SymmetryDetector.java    From kodkod with MIT License 6 votes vote down vote up
/**
 * Returns an array that contains unique non-empty tuplesets in the given bounds, 
 * sorted in the order of increasing size.
 * @return unique non-empty tuplesets in the given bounds, 
 * sorted in the order of increasing size.
 */
private static TupleSet[] sort(Bounds bounds) { 
	final List<TupleSet> sets = new ArrayList<TupleSet>(bounds.relations().size());
	for(Relation r : bounds.relations()) { 
		final TupleSet lower = bounds.lowerBound(r);
		final TupleSet upper = bounds.upperBound(r);
		if (!lower.isEmpty() && lower.size()<upper.size()) { sets.add(lower); }
		if (!upper.isEmpty()) {	sets.add(upper); }
	}
	final TupleSet[] sorted = sets.toArray(new TupleSet[sets.size()]);
	Arrays.sort(sorted, new Comparator<TupleSet>(){
		public int compare(TupleSet o1, TupleSet o2) {
			return o1.size() - o2.size();
		}
	});
	return sorted;
}
 
Example 5
Source File: SymmetryDetector.java    From org.alloytools.alloy with Apache License 2.0 5 votes vote down vote up
/**
 * Returns an array that contains unique non-empty tuplesets in the given
 * bounds, sorted in the order of increasing size.
 *
 * @return unique non-empty tuplesets in the given bounds, sorted in the order
 *         of increasing size.
 */
private TupleSet[] sort(Bounds bounds) {
    final List<TupleSet> sets = new ArrayList<TupleSet>(bounds.relations().size());
    for (Relation r : bounds.relations()) {
        if (r.isAtom() && ignoreAllAtomRelsExcept != null && !ignoreAllAtomRelsExcept.contains(r))
            continue;
        if (ignoreRels != null && ignoreRels.contains(r))
            continue;
        final TupleSet lower = bounds.lowerBound(r);
        final TupleSet upper = bounds.upperBound(r);
        if (!lower.isEmpty() && lower.size() < upper.size()) {
            sets.add(lower);
        }
        if (!upper.isEmpty()) {
            sets.add(upper);
        }
    }
    final TupleSet[] sorted = sets.toArray(new TupleSet[sets.size()]);
    Arrays.sort(sorted, new Comparator<TupleSet>() {

        @Override
        public int compare(TupleSet o1, TupleSet o2) {
            return o1.size() - o2.size();
        }
    });
    return sorted;
}
 
Example 6
Source File: Translator.java    From kodkod with MIT License 5 votes vote down vote up
/** 
 * @requires checkIncrementalBounds(bounds, transl)
 * @requires checkIncrementalOptions(transl.options) 
 * @requires transl.trivial()
 * @requires transl.cnf.solve()
 * @return see {@link #translateIncremental(Formula, Bounds, Options)}
 **/
private static Translation.Incremental translateIncrementalTrivial(Formula formula, Bounds bounds, Translation.Incremental transl) {
	if (!transl.cnf().solve()) 
		throw new IllegalArgumentException("Expected a satisfiable translation, given " + transl);
	
	transl.cnf().free(); // release the old empty solver since we are going to re-translate
	
	final Options tOptions = transl.options();
	final Bounds tBounds = transl.bounds();
	
	// add new relation bindings to the translation bounds.  since the given bounds induce
	// a coarser set of symmetries on the universe than transl.symmetries, adding their (disjoint) bindings to tBounds 
	// will not change the symmetries of tBounds.  note that the symmetries of tBounds refine transl.symmetries, and they
	// may be strictly finer if some of the symmetries in transl.symmetries were broken via SymmetryBreaker.breakMatrixSymmetries(...) 
	// during the generation of transl.  in particular, any symmetries absent from tBounds are precisely those that were broken based
	// on the total ordering and acyclic predicates in transl.originalFormula.
	for(Relation r : bounds.relations()) {
		tBounds.bound(r, bounds.lowerBound(r), bounds.upperBound(r));
	}
	
	// re-translate the given formula with respect to tBounds.  note that we don't have to re-translate 
	// the conjunction of transl.formula and formula since transl.formula is guaranteed to evaluate to 
	// TRUE with respect to tBounds (since no bindings that were originally in tBounds were changed by the above loop).
	final Translation.Incremental updated = translateIncremental(formula, tBounds, tOptions);
	
	// we can't return the updated translation as is, since we have to make sure that updated.symmetries is set to
	// transl.symmetries rather than the potentially finer set of symmetries induced by tBounds. note that 
	// the updated translation currently has updated.originalBounds = tBounds, while updated.bounds is a copy of 
	// tBounds with possibly additional skolem relations, as well as new bounds for some relations in formula.*components 
	// due to symmetry breaking.
	return new Translation.Incremental(updated.bounds(), tOptions, transl.symmetries(), updated.interpreter(), updated.incrementer());
}
 
Example 7
Source File: SolutionIterator.java    From org.alloytools.alloy with Apache License 2.0 4 votes vote down vote up
/**
 * Returns the trivial solution corresponding to the trivial translation stored
 * in {@code this.translation}, and if {@code this.translation.cnf.solve()} is
 * true, sets {@code this.translation} to a new translation that eliminates the
 * current trivial solution from the set of possible solutions. The latter has
 * the effect of forcing either the translator or the solver to come up with the
 * next solution or return UNSAT. If {@code this.translation.cnf.solve()} is
 * false, sets {@code this.translation} to null.
 *
 * @requires this.translation != null
 * @ensures this.translation is modified to eliminate the current trivial
 *          solution from the set of possible solutions
 * @return current solution
 */
private Solution nextTrivialSolution() {
    final Translation.Whole transl = this.translation;

    final Solution sol = Solver.trivial(transl, translTime); // this also
                                                            // frees up
                                                            // solver
                                                            // resources,
                                                            // if unsat

    if (sol.instance() == null) {
        translation = null; // unsat, no more solutions
    } else {
        trivial++;

        final Bounds bounds = transl.bounds();
        final Bounds newBounds = bounds.clone();
        final List<Formula> changes = new ArrayList<Formula>();

        for (Relation r : bounds.relations()) {
            final TupleSet lower = bounds.lowerBound(r);

            if (lower != bounds.upperBound(r)) { // r may change
                if (lower.isEmpty()) {
                    changes.add(r.some());
                } else {
                    final Relation rmodel = Relation.nary(r.name() + "_" + trivial, r.arity());
                    newBounds.boundExactly(rmodel, lower);
                    changes.add(r.eq(rmodel).not());
                }
            }
        }

        // nothing can change => there can be no more solutions (besides the
        // current trivial one).
        // note that transl.formula simplifies to the constant true with
        // respect to
        // transl.bounds, and that newBounds is a superset of transl.bounds.
        // as a result, finding the next instance, if any, for
        // transl.formula.and(Formula.or(changes))
        // with respect to newBounds is equivalent to finding the next
        // instance of Formula.or(changes) alone.
        final Formula formula = changes.isEmpty() ? Formula.FALSE : Formula.or(changes);

        final long startTransl = System.currentTimeMillis();
        translation = Translator.translate(formula, newBounds, transl.options());
        translTime += System.currentTimeMillis() - startTransl;
    }
    return sol;
}
 
Example 8
Source File: Translator.java    From org.alloytools.alloy with Apache License 2.0 4 votes vote down vote up
/**
 * @requires checkIncrementalBounds(bounds, transl)
 * @requires checkIncrementalOptions(transl.options)
 * @requires transl.trivial()
 * @requires transl.cnf.solve()
 * @return see {@link #translateIncremental(Formula, Bounds, Options)}
 **/
private static Translation.Incremental translateIncrementalTrivial(Formula formula, Bounds bounds, Translation.Incremental transl) {
    if (!transl.cnf().solve())
        throw new IllegalArgumentException("Expected a satisfiable translation, given " + transl);

    transl.cnf().free(); // release the old empty solver since we are going
                        // to re-translate

    final Options tOptions = transl.options();
    final Bounds tBounds = transl.bounds();

    // add new relation bindings to the translation bounds. since the given
    // bounds induce
    // a coarser set of symmetries on the universe than transl.symmetries,
    // adding their (disjoint) bindings to tBounds
    // will not change the symmetries of tBounds. note that the ymmetries of
    // tBounds refine transl.symmetries, and they
    // may be strictly finer if some of the symmetries in transl.symmetries
    // were broken via SymmetryBreaker.breakMatrixSymmetries(...)
    // during the generation of transl. in particular, any symmetries absent
    // from tBounds are precisely those that were broken based
    // on the total ordering and acyclic predicates in
    // transl.originalFormula.
    for (Relation r : bounds.relations()) {
        tBounds.bound(r, bounds.lowerBound(r), bounds.upperBound(r));
    }

    // re-translate the given formula with respect to tBounds. note that we
    // don't have to re-translate
    // the conjunction of transl.formula and formula since transl.formula is
    // guaranteed to evaluate to
    // TRUE with respect to tBounds (since no bindings that were originally
    // in tBounds were changed by the above loop).
    final Translation.Incremental updated = translateIncremental(formula, tBounds, tOptions);

    // we can't return the updated translation as is, since we have to make
    // sure that updated.symmetries is set to
    // transl.symmetries rather than the potentially finer set of symmetries
    // induced by tBounds. note that
    // the updated translation currently has updated.originalBounds =
    // tBounds, while updated.bounds is a copy of
    // tBounds with possibly additional skolem relations, as well as new
    // bounds for some relations in formula.*components
    // due to symmetry breaking.
    return new Translation.Incremental(updated.bounds(), tOptions, transl.symmetries(), updated.interpreter(), updated.incrementer());
}
 
Example 9
Source File: Translator.java    From org.alloytools.alloy with Apache License 2.0 4 votes vote down vote up
/**
 * @requires checkIncrementalBounds(bounds, transl)
 * @requires checkIncrementalOptions(transl.options)
 * @requires !transl.trivial()
 * @return see {@link #translateIncremental(Formula, Bounds, Options)}
 **/
private static Translation.Incremental translateIncrementalNonTrivial(Formula formula, Bounds bounds, Translation.Incremental transl) {

    final Options tOptions = transl.options();
    final Bounds tBounds = transl.bounds();

    // save the set of relations bound in the pre-state
    final Set<Relation> oldRelations = new LinkedHashSet<Relation>(tBounds.relations());

    // add new relation bindings to the translation bounds. note that
    // skolemization (below) may also cause extra relations to be added.
    for (Relation r : bounds.relations()) {
        tBounds.bound(r, bounds.lowerBound(r), bounds.upperBound(r));
    }
    final AnnotatedNode<Formula> annotated = (transl.options().skolemDepth() < 0) ? annotate(formula) : skolemize(annotate(formula), tBounds, tOptions);

    // extend the interpreter with variable allocations for new relations,
    // either from given bounds
    // or those introduced by skolemization
    final LeafInterpreter interpreter = transl.interpreter();
    interpreter.extend(setDifference(tBounds.relations(), oldRelations), tBounds.lowerBounds(), tBounds.upperBounds());

    final BooleanValue circuit = FOL2BoolTranslator.translate(annotated, interpreter);

    if (circuit == BooleanConstant.FALSE) {
        // release the old solver and state, and return a fresh trivially
        // false incremental translation.
        transl.incrementer().solver().free();
        return new Translation.Incremental(tBounds, tOptions, transl.symmetries(), LeafInterpreter.empty(tBounds.universe(), tOptions), Bool2CNFTranslator.translateIncremental(BooleanConstant.FALSE, tOptions.solver()));
    } else if (circuit == BooleanConstant.TRUE) {
        // must add any newly allocated primary variables to the solver for
        // interpretation to work correctly
        final int maxVar = interpreter.factory().maxVariable();
        final int cnfVar = transl.cnf().numberOfVariables();
        if (maxVar > cnfVar) {
            transl.cnf().addVariables(maxVar - cnfVar);
        }
    } else {
        // circuit is a formula; add its CNF representation to
        // transl.incrementer.solver()
        Bool2CNFTranslator.translateIncremental((BooleanFormula) circuit, interpreter.factory().maxVariable(), transl.incrementer());
    }

    return transl;
}
 
Example 10
Source File: Solver.java    From kodkod with MIT License 4 votes vote down vote up
/**
 * Returns the trivial solution corresponding to the trivial translation stored in {@code this.translation},
 * and if {@code this.translation.cnf.solve()} is true, sets {@code this.translation} to a new translation 
 * that eliminates the current trivial solution from the set of possible solutions.  The latter has the effect 
 * of forcing either the translator or the solver to come up with the next solution or return UNSAT.
 * If {@code this.translation.cnf.solve()} is false, sets {@code this.translation} to null.
 * @requires this.translation != null
 * @ensures this.translation is modified to eliminate the current trivial solution from the set of possible solutions
 * @return current solution
 */
private Solution nextTrivialSolution() {
	final Translation.Whole transl = this.translation;
	
	final Solution sol = trivial(transl, translTime); // this also frees up solver resources, if unsat
	
	if (sol.instance()==null) {
		translation = null; // unsat, no more solutions
	} else {
		trivial++;
		
		final Bounds bounds = transl.bounds();
		final Bounds newBounds = bounds.clone();
		final List<Formula> changes = new ArrayList<Formula>();

		for(Relation r : bounds.relations()) {
			final TupleSet lower = bounds.lowerBound(r); 
			
			if (lower != bounds.upperBound(r)) { // r may change
				if (lower.isEmpty()) { 
					changes.add(r.some());
				} else {
					final Relation rmodel = Relation.nary(r.name()+"_"+trivial, r.arity());
					newBounds.boundExactly(rmodel, lower);	
					changes.add(r.eq(rmodel).not());
				}
			}
		}
		
		// nothing can change => there can be no more solutions (besides the current trivial one).
		// note that transl.formula simplifies to the constant true with respect to 
		// transl.bounds, and that newBounds is a superset of transl.bounds.
		// as a result, finding the next instance, if any, for transl.formula.and(Formula.or(changes)) 
		// with respect to newBounds is equivalent to finding the next instance of Formula.or(changes) alone.
		final Formula formula = changes.isEmpty() ? Formula.FALSE : Formula.or(changes);
		
		final long startTransl = System.currentTimeMillis();
		translation = Translator.translate(formula, newBounds, transl.options());
		translTime += System.currentTimeMillis() - startTransl;
	} 
	return sol;
}
 
Example 11
Source File: Translator.java    From kodkod with MIT License 4 votes vote down vote up
/** 
 * @requires checkIncrementalBounds(bounds, transl)
 * @requires checkIncrementalOptions(transl.options) 
 * @requires !transl.trivial()
 * @return see {@link #translateIncremental(Formula, Bounds, Options)}
 **/
private static Translation.Incremental translateIncrementalNonTrivial(Formula formula, Bounds bounds, Translation.Incremental transl) {
	
	final Options tOptions = transl.options();
	final Bounds tBounds = transl.bounds();
	
	// save the set of relations bound in the pre-state
	final Set<Relation> oldRelations = new LinkedHashSet<Relation>(tBounds.relations());
	
	// add new relation bindings to the translation bounds.  note that skolemization (below) may also cause extra relations to be added.
	for(Relation r : bounds.relations()) {
		tBounds.bound(r, bounds.lowerBound(r), bounds.upperBound(r));
	}
	final AnnotatedNode<Formula> annotated = 
		(transl.options().skolemDepth() < 0) ? annotate(formula) : skolemize(annotate(formula), tBounds, tOptions);
	
	// extend the interpreter with variable allocations for new relations, either from given bounds
	// or those introduced by skolemization
	final LeafInterpreter interpreter = transl.interpreter();
	interpreter.extend(setDifference(tBounds.relations(), oldRelations), tBounds.lowerBounds(), tBounds.upperBounds());
	
	final BooleanValue circuit = FOL2BoolTranslator.translate(annotated, interpreter); 

	if (circuit==BooleanConstant.FALSE) {
		// release the old solver and state, and return a fresh trivially false incremental translation.
		transl.incrementer().solver().free();
		return new Translation.Incremental(tBounds, tOptions, transl.symmetries(), 
				LeafInterpreter.empty(tBounds.universe(), tOptions), 
				Bool2CNFTranslator.translateIncremental(BooleanConstant.FALSE, tOptions.solver()));			
	} else if (circuit==BooleanConstant.TRUE) {
		// must add any newly allocated primary variables to the solver for interpretation to work correctly 
		final int maxVar = interpreter.factory().maxVariable();
		final int cnfVar = transl.cnf().numberOfVariables();
		if (maxVar > cnfVar) {
			transl.cnf().addVariables(maxVar-cnfVar);
		}
	} else {
		// circuit is a formula; add its CNF representation to transl.incrementer.solver()			
		Bool2CNFTranslator.translateIncremental((BooleanFormula) circuit, interpreter.factory().maxVariable(), transl.incrementer());			
	}  
	
	return transl;
}