예제 #1
0
  /**
   * {@inheritDoc}
   *
   * @see kodkod.engine.satlab.ReductionStrategy#next(kodkod.engine.satlab.ResolutionTrace)
   */
  public IntSet next(ResolutionTrace trace) {
    if (hits.isEmpty()) return Ints.EMPTY_SET; // tried everything
    final IntSet relevantVars = StrategyUtils.coreTailUnits(trace);

    final long[] byRelevance = sortByRelevance(trace, relevantVars);
    if (DBG) printRelevant(byRelevance);
    for (int i = byRelevance.length - 1; i >= 0; i--) {
      final int var = (int) byRelevance[i];
      if (hits.remove(var) != null) {
        // remove maxVar from the set of relevant variables
        relevantVars.remove(var);
        if (relevantVars.isEmpty()) break; // there was only one root formula left
        // get all axioms and resolvents corresponding to the clauses that
        // form the translations of formulas identified by relevant vars
        final IntSet relevantClauses = clausesFor(trace, relevantVars);
        assert !relevantClauses.isEmpty() && !relevantClauses.contains(trace.size() - 1);

        if (DBG)
          System.out.println("relevant clauses: " + relevantClauses.size() + ", removed " + var);

        return relevantClauses;
      }
    }

    hits.clear();
    return Ints.EMPTY_SET;
  }
예제 #2
0
  /**
   * Minimizes the current core using the trivial strategy that does one of the following: (1) if
   * there is a root that simplified to FALSE, sets the minimal core to that root; or (2) if not,
   * there must be two roots that translated to x and -x, where x is a boolean literal, so we pick
   * those two as the minimal core. The strategy argument is ignored (it can be null).
   *
   * @see Proof#minimize(ReductionStrategy)
   */
  @Override
  public void minimize(ReductionStrategy strategy) {
    final Map<Formula, int[]> rootLits = new LinkedHashMap<Formula, int[]>();
    final Map<Formula, Node> rootNodes = new LinkedHashMap<Formula, Node>();
    final Set<Formula> roots = log().roots();

    for (Iterator<TranslationRecord> itr = core(); itr.hasNext(); ) {
      final TranslationRecord rec = itr.next();
      if (roots.contains(rec.translated())) {
        // simply record the most recent output value for each formula:
        // this is guaranteed to be the final output value for that
        // formula because of the translation log guarantee that the
        // log is replayed in the order of translation:  i.e. a child's
        // output value is always recorded before the parent's
        int[] val = rootLits.get(rec.translated());
        if (val == null) {
          val = new int[1];
          rootLits.put(rec.translated(), val);
        }
        val[0] = rec.literal();
        rootNodes.put(rec.translated(), rec.node());
      }
    }

    final SparseSequence<Formula> lits = new TreeSequence<Formula>();
    for (Map.Entry<Formula, int[]> entry : rootLits.entrySet()) {
      final int lit = entry.getValue()[0];
      if (lit == -Integer.MAX_VALUE) {
        coreRoots = Collections.singletonMap(entry.getKey(), rootNodes.get(entry.getKey()));
        break;
      } else if (lits.containsIndex(-lit)) {
        final Formula f0 = lits.get(-lit);
        final Formula f1 = entry.getKey();
        coreRoots = new LinkedHashMap<Formula, Node>(3);
        coreRoots.put(f0, rootNodes.get(f0));
        coreRoots.put(f1, rootNodes.get(f1));
        coreRoots = Collections.unmodifiableMap(coreRoots);
        break;
      } else {
        lits.put(lit, entry.getKey());
      }
    }

    coreFilter = null;
    assert coreRoots.size() == 1
            && rootLits.get(coreRoots.keySet().iterator().next())[0] == -Integer.MAX_VALUE
        || coreRoots.size() == 2;
  }
예제 #3
0
 /**
  * Returns a deep (modifiable) copy of this Bounds object.
  *
  * @return a deep (modifiable) copy of this Bounds object.
  */
 public Bounds clone() {
   try {
     return new Bounds(
         factory,
         new LinkedHashMap<Relation, TupleSet>(lowers),
         new LinkedHashMap<Relation, TupleSet>(uppers),
         intbounds.clone());
   } catch (CloneNotSupportedException cnse) {
     throw new InternalError(); // should not be reached
   }
 }
예제 #4
0
  /**
   * Returns an array R of longs such that for each i, j in [0..R.length) i < j implies that the
   * formula identified by (int)R[i] in this.hits contributes fewer clauses to the core of the given
   * trace than the formula identified by (int)R[j].
   *
   * @return an array as described above
   */
  private long[] sortByRelevance(ResolutionTrace trace, IntSet relevantVars) {
    hits.indices().retainAll(relevantVars);

    if (hits.get(hits.indices().min()) == null) { // first call, initialize the hits
      for (IntIterator varItr = relevantVars.iterator(); varItr.hasNext(); ) {
        final int var = varItr.next();
        final IntSet varReachable = new IntBitSet(var + 1);
        varReachable.add(var);
        hits.put(var, varReachable);
      }
      for (Iterator<Clause> clauseItr = trace.reverseIterator(trace.axioms());
          clauseItr.hasNext(); ) {
        final Clause clause = clauseItr.next();
        final int maxVar = clause.maxVariable();
        for (IntSet reachableVars : hits.values()) {
          if (reachableVars.contains(maxVar)) {
            for (IntIterator lits = clause.literals(); lits.hasNext(); ) {
              reachableVars.add(StrictMath.abs(lits.next()));
            }
          }
        }
      }
    }

    final long[] counts = new long[hits.size()];

    for (Iterator<Clause> clauseItr = trace.iterator(trace.core()); clauseItr.hasNext(); ) {
      final Clause clause = clauseItr.next();
      final int maxVar = clause.maxVariable();
      int i = 0;
      for (IntSet reachableVars : hits.values()) {
        if (reachableVars.contains(maxVar)) {
          counts[i]++;
        }
        i++;
      }
    }

    int i = 0;
    for (IntIterator varItr = hits.indices().iterator(); varItr.hasNext(); ) {
      final int var = varItr.next();
      counts[i] = (counts[i] << 32) | var;
      i++;
    }

    Arrays.sort(counts);

    return counts;
  }
예제 #5
0
 /**
  * Constructs an ARCE strategy that will use the given translation log to relate the cnf clauses
  * back to the logic constraints from which they were generated.
  *
  * @ensures this.hardnessCutOff' = hardnessCutOff and this.recycleLimit' = recycleLimit and
  *     this.noRecycleRatio' = noRecycleRatio
  */
 public DynamicRCEStrategy(
     final TranslationLog log, double noRecycleRatio, double hardnessCutOff, double recycleLimit) {
   if (noRecycleRatio < 0 || noRecycleRatio > 1)
     throw new IllegalArgumentException("noRecycleRatio must be in [0..1]: " + noRecycleRatio);
   if (hardnessCutOff < 1)
     throw new IllegalArgumentException("hardnessCutOff must be >=1: " + hardnessCutOff);
   if (recycleLimit < 1)
     throw new IllegalArgumentException("recycleLimit must be >=1: " + recycleLimit);
   this.noRecycleRatio = noRecycleRatio;
   this.hardnessCutOff = hardnessCutOff;
   this.recycleLimit = recycleLimit;
   this.hits = new TreeSequence<IntSet>();
   for (IntIterator itr = StrategyUtils.rootVars(log).iterator(); itr.hasNext(); ) {
     hits.put(itr.next(), null);
   }
 }
예제 #6
0
 /**
  * Makes the specified tupleset an exact bound on the relational value that corresponds to the
  * given integer.
  *
  * @requires ibound.arity = 1 && i.bound.size() = 1
  * @ensures this.intBound' = this.intBound' ++ i -> ibound
  * @throws NullPointerException ibound = null
  * @throws IllegalArgumentException ibound.arity != 1 || ibound.size() != 1
  * @throws IllegalArgumentException ibound.universe != this.universe
  */
 public void boundExactly(int i, TupleSet ibound) {
   checkBound(1, ibound);
   if (ibound.size() != 1) throw new IllegalArgumentException("ibound.size != 1: " + ibound);
   intbounds.put(i, ibound.clone().unmodifiableView());
 }
예제 #7
0
 /**
  * Returns the set of tuples representing the given integer. If i is not mapped by this, null is
  * returned.
  *
  * @return this.intBound[i]
  */
 public TupleSet exactBound(int i) {
   return intbounds.get(i);
 }
예제 #8
0
 /**
  * Returns the set of all integers bound by this Bounds. The returned set does not support the add
  * operation. It supports removal iff this is not an unmodifiable Bounds.
  *
  * @return this.intBounds.TupleSet
  */
 public IntSet ints() {
   return intbounds.indices();
 }