Package kodkod.engine

Source Code of kodkod.engine.ResolutionBasedProof

package kodkod.engine;

import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import kodkod.ast.Formula;
import kodkod.ast.Node;
import kodkod.ast.Variable;
import kodkod.ast.visitor.AbstractVoidVisitor;
import kodkod.engine.fol2sat.RecordFilter;
import kodkod.engine.fol2sat.TranslationLog;
import kodkod.engine.fol2sat.TranslationRecord;
import kodkod.engine.satlab.ReductionStrategy;
import kodkod.engine.satlab.ResolutionTrace;
import kodkod.engine.satlab.SATProver;
import kodkod.engine.ucore.StrategyUtils;
import kodkod.instance.TupleSet;
import kodkod.util.collections.IdentityHashSet;
import kodkod.util.ints.IntSet;
import kodkod.util.ints.IntTreeSet;

/**
* A proof of unsatisfiability based on a {@linkplain ResolutionTrace resolution trace} produced
* by a {@linkplain SATProver SATProver}.
*
* @author Emina Torlak
*/
final class ResolutionBasedProof extends Proof {
  private SATProver solver;
  private RecordFilter coreFilter;
  private Map<Formula,Node> coreRoots;
 
  /**
   * Constructs a new ResolutionRefutation that will extract the
   * unsatisfiable core for log.formula from the given solver. 
   * @requires solver.solve() has been called and it returned false.
   * @requires log.formula is the formula whose translation
   * resulted in the given SATProver
   * @effects this.formula' = log.formula
   */
  ResolutionBasedProof(SATProver solver, TranslationLog log) {
    super(log);
    this.solver = solver;
    this.coreFilter = null;
    this.coreRoots = null;
  }
 
  /**
   * Returns the connected core based on the given set of
   * core variables. 
   * @requires coreVar = StrategyUtils.coreVars(solver.proof());
   * @return let formulas = (this.log.records[int] & literal.{i: int | abs(i) in coreVars}).formula |
   *       connected = {f: formulas  | some s: set coreNodes | f + this.log.formula in s and (s - this.log.formula).~components in s }
   */
  private Set<Formula>  connectedCore(final IntSet coreVars) {
    final Set<Formula> coreNodes = new IdentityHashSet<Formula>();
    final RecordFilter filter = new RecordFilter() {
      public boolean accept(Node node, Formula translated, int literal, Map<Variable,TupleSet> env) {
        return coreVars.contains(StrictMath.abs(literal));
      }
    };
    for(Iterator<TranslationRecord> itr = log().replay(filter); itr.hasNext(); ) {
      coreNodes.add(itr.next().translated());
    }
    final Set<Formula> connected = new IdentityHashSet<Formula>();
    final AbstractVoidVisitor traverser = new AbstractVoidVisitor() {
      final Set<Node> visited = new IdentityHashSet<Node>();
      /**
       * Returns true if the given node has been visited before or if
       * it is not contained in this.nodes set.  Otherwise adds
       * the node to the connected set and returns false.
       * @effects this.visited' = this.visited + n
       * @effects n !in this.visited && n in coreNodes =>
       *  connected' = connected + n else connected' = connected
       * @return n in visited || n !in coreNodes
       */
      protected boolean visited(Node n) {
        if (visited.add(n) && coreNodes.contains(n)) {
          connected.add((Formula)n);
          return false;
        }
        return true;
      }
    };
    for(Formula root: log().roots()) {
      root.accept(traverser);
    }
    return connected;
  }
 
  /**
   * {@inheritDoc}
   * @see kodkod.engine.Proof#core()
   */
  public final Iterator<TranslationRecord> core() {
    if (coreFilter == null) {
      coreFilter = new RecordFilter() {
        final IntSet coreVariables = StrategyUtils.coreVars(solver.proof());
        final Set<Formula> coreNodes = connectedCore(coreVariables);
        public boolean accept(Node node, Formula translated, int literal, Map<Variable,TupleSet> env) {
          return coreNodes.contains(translated) && coreVariables.contains(StrictMath.abs(literal));
        }
      };
    }
    return log().replay(coreFilter);
  }
 
  /**
   * {@inheritDoc}
   * @see kodkod.engine.Proof#highLevelCore()
   */
  public final Map<Formula, Node> highLevelCore() {
    if (coreRoots == null) {
      final RecordFilter unitFilter = new RecordFilter() {
        final IntSet coreUnits = StrategyUtils.coreUnits(solver.proof());
        final Set<Formula> roots = log().roots();
        public boolean accept(Node node, Formula translated, int literal, Map<Variable, TupleSet> env) {
          return roots.contains(translated) && coreUnits.contains(Math.abs(literal));
        }
       
      };
      coreRoots = new LinkedHashMap<Formula, Node>();
      final IntSet seenUnits = new IntTreeSet();
      for(Iterator<TranslationRecord> itr = log().replay(unitFilter); itr.hasNext(); ) {
        // it is possible that two top-level formulas have identical meaning,
        // and are represented with the same core unit; in that case, we want only
        // one of them in the core.
        final TranslationRecord rec = itr.next();
        if (seenUnits.add(rec.literal())) {
          coreRoots.put(rec.translated(), rec.node());
       
      }
      coreRoots = Collections.unmodifiableMap(coreRoots);
    }
    return coreRoots;
  }
 
  /**
   * {@inheritDoc}
   * @see kodkod.engine.Proof#minimize(kodkod.engine.satlab.ReductionStrategy)
   */
  public void minimize(ReductionStrategy strategy) {
    solver.reduce(strategy);
    coreFilter = null;
    coreRoots = null;
  }
}
TOP

Related Classes of kodkod.engine.ResolutionBasedProof

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.