content: /* 
   * Kodkod -- Copyright (c) 2005-2012, Emina Torlak
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */
  package kodkod.examples.bmc;
  
  import kodkod.ast.Expression;
  import kodkod.ast.Formula;
  import kodkod.ast.Relation;
  import kodkod.engine.Solution;
  import kodkod.engine.Solver;
  import kodkod.engine.satlab.SATFactory;
  import kodkod.examples.bmc.ListViz.State;
  import kodkod.instance.Bounds;
  import kodkod.instance.Instance;
  import kodkod.instance.TupleFactory;
  
  /**
   * Data structure repair demo.
   * 
   * @author Emina Torlak
   */
  public class ListRepair extends ListEncoding {
  	final Relation next3, head0;
  	
  	ListRepair() {
  		
  		next3 = Relation.binary("next3");						// next3 = free variable
  		head0 = Relation.binary("head0");						// head0 = free variable
  	}
  
  	Expression next3() { return next3; }
  	Expression head0() { return head0; }
  	
  	Formula repairSpec() {
  		return Formula.and(pre(), post());
  	}
  	
  	Bounds repairBounds(int size) { 
  		final Bounds b = bounds(size);
  		final ListCheck checker = new ListCheck();
  		final Instance cex = checker.check(size).instance();
  		assert cex != null;
  		final TupleFactory t = b.universe().factory();
  		b.bound(next3, b.upperBound(next));
  		b.bound(head0, b.upperBound(head));
  		b.boundExactly(next, copyFrom(t, cex.tuples(checker.next)));
  		b.boundExactly(head, copyFrom(t, cex.tuples(checker.head)));
  		b.boundExactly(data, copyFrom(t, cex.tuples(checker.data)));
  		b.boundExactly(thisList, copyFrom(t, cex.tuples(checker.thisList)));
  		return b;
  	}
  	
  	Solution repair(int size) {
  		final Solver solver = new Solver();
  		solver.options().setSolver(SATFactory.DEFAULT);
  		return solver.solve(repairSpec(), repairBounds(size));
  	}
  	
  	private void showRepair(int size) {
  		final Solution sol = repair(size);
  		System.out.println("************ REPAIR REVERSE FOR " + size + " NODES ************");
  		System.out.println(sol.outcome());
  		System.out.println();
  		System.out.println(sol.stats());
  		System.out.println();
  		ListViz.printInstance(this, sol.instance());
  		ListViz.printStateGraph("repair-pre", this, sol.instance(), State.PRE);
  		ListViz.printStateGraph("repair-post", this, sol.instance(), State.POST);
  
  	}
  	
  	public static void main(String[] args) {
  		ListRepair enc = new ListRepair();
  		//ListViz.printEncoding(enc);
  		enc.showRepair(3);
  	}
  	
  }
  