Example #1
0
 /** If ex is a simple combination of Relations, then return that combination, else return null. */
 private Expression sim(Expr ex) {
   while (ex instanceof ExprUnary) {
     ExprUnary u = (ExprUnary) ex;
     if (u.op != ExprUnary.Op.NOOP && u.op != ExprUnary.Op.EXACTLYOF) break;
     ex = u.sub;
   }
   if (ex instanceof ExprBinary) {
     ExprBinary b = (ExprBinary) ex;
     if (b.op == ExprBinary.Op.ARROW || b.op == ExprBinary.Op.PLUS || b.op == ExprBinary.Op.JOIN) {
       Expression left = sim(b.left);
       if (left == null) return null;
       Expression right = sim(b.right);
       if (right == null) return null;
       if (b.op == ExprBinary.Op.ARROW) return left.product(right);
       if (b.op == ExprBinary.Op.PLUS) return left.union(right);
       else return left.join(right);
     }
   }
   if (ex instanceof ExprConstant) {
     switch (((ExprConstant) ex).op) {
       case EMPTYNESS:
         return Expression.NONE;
     }
   }
   if (ex == Sig.NONE) return Expression.NONE;
   if (ex == Sig.SIGINT) return Expression.INTS;
   if (ex instanceof Sig) return sol.a2k((Sig) ex);
   if (ex instanceof Field) return sol.a2k((Field) ex);
   return null;
 }
Example #2
0
 /** Allocate relations for SubsetSig top-down. */
 private Expression allocateSubsetSig(SubsetSig sig) throws Err {
   // We must not visit the same SubsetSig more than once, so if we've been here already, then
   // return the old value right away
   Expression sum = sol.a2k(sig);
   if (sum != null && sum != Expression.NONE) return sum;
   // Recursively form the union of all parent expressions
   TupleSet ts = factory.noneOf(1);
   for (Sig parent : sig.parents) {
     Expression p =
         (parent instanceof PrimSig) ? sol.a2k(parent) : allocateSubsetSig((SubsetSig) parent);
     ts.addAll(sol.query(true, p, false));
     if (sum == null) sum = p;
     else sum = sum.union(p);
   }
   // If subset is exact, then just use the "sum" as is
   if (sig.exact) {
     sol.addSig(sig, sum);
     return sum;
   }
   // Allocate a relation for this subset sig, then bound it
   rep.bound("Sig " + sig + " in " + ts + "\n");
   Relation r = sol.addRel(sig.label, null, ts);
   sol.addSig(sig, r);
   // Add a constraint that it is INDEED a subset of the union of its parents
   sol.addFormula(r.in(sum), sig.isSubset);
   return r;
 }
Example #3
0
 /**
  * Returns the conjecture proposition_2_14_1.
  *
  * @return proposition_2_14_1
  */
 public final Formula proposition2141() {
   // all c1, c2: curve, p: point |
   //  p->c1->c2 in meet && c1->c2 in sum.open =>
   //  all q: point - p | c1 + c2 !in q.incident
   final Variable c1 = Variable.unary("C1");
   final Variable c2 = Variable.unary("C2");
   final Variable p = Variable.unary("P");
   final Variable q = Variable.unary("Q");
   final Expression e0 = c1.product(c2);
   final Formula f0 = p.product(e0).in(meet).and(e0.in(sum.join(open)));
   final Formula f1 = c1.union(c2).in(q.join(incident)).not().forAll(q.oneOf(point.difference(p)));
   return f0.implies(f1).forAll(c1.oneOf(curve).and(c2.oneOf(curve)).and(p.oneOf(point)));
 }
Example #4
0
 /**
  * Returns the conjecture theorem_3_8_5.
  *
  * @return theorem_3_8_5
  */
 public final Formula theorem385() {
   // all c: curve, p, q, r: point |
   //  c->p->q->r in between =>
   //    incident.c - q in q.(p.(c.between)) + ((c.between).r).q
   final Variable c = Variable.unary("C");
   final Variable p = Variable.unary("P");
   final Variable q = Variable.unary("Q");
   final Variable r = Variable.unary("R");
   final Formula f0 = c.product(p).product(q).product(r).in(between);
   final Expression e0 = q.join(p.join(c.join(between)));
   final Expression e1 = c.join(between).join(r).join(q);
   final Formula f1 = incident.join(c).difference(q).in(e0.union(e1));
   return f0.implies(f1)
       .forAll(p.oneOf(point).and(q.oneOf(point)).and(r.oneOf(point)).and(c.oneOf(curve)));
 }
Example #5
0
 /** Allocate relations for nonbuiltin PrimSigs bottom-up. */
 private Expression allocatePrimSig(PrimSig sig) throws Err {
   // Recursively allocate all children expressions, and form the union of them
   Expression sum = null;
   for (PrimSig child : sig.children()) {
     Expression childexpr = allocatePrimSig(child);
     if (sum == null) {
       sum = childexpr;
       continue;
     }
     // subsigs are disjoint
     sol.addFormula(sum.intersection(childexpr).no(), child.isSubsig);
     sum = sum.union(childexpr);
   }
   TupleSet lower = lb.get(sig).clone(), upper = ub.get(sig).clone();
   if (sum == null) {
     // If sig doesn't have children, then sig should make a fresh relation for itself
     sum = sol.addRel(sig.label, lower, upper);
   } else if (sig.isAbstract == null) {
     // If sig has children, and sig is not abstract, then create a new relation to act as the
     // remainder.
     for (PrimSig child : sig.children()) {
       // Remove atoms that are KNOWN to be in a subsig;
       // it's okay to mistakenly leave some atoms in, since we will never solve for the
       // "remainder" relation directly;
       // instead, we union the remainder with the children, then solve for the combined solution.
       // (Thus, the more we can remove, the more efficient it gets, but it is not crucial for
       // correctness)
       TupleSet childTS = sol.query(false, sol.a2k(child), false);
       lower.removeAll(childTS);
       upper.removeAll(childTS);
     }
     sum = sum.union(sol.addRel(sig.label + " remainder", lower, upper));
   }
   sol.addSig(sig, sum);
   return sum;
 }
  /**
   * Returns a relational encoding of the problem.
   *
   * @return a relational encoding of the problem.
   */
  public Formula rules() {
    final List<Formula> rules = new ArrayList<Formula>();

    rules.add(x.function(queen, num));
    rules.add(y.function(queen, num));

    final Variable i = Variable.unary("n");
    final Variable q1 = Variable.unary("q1"), q2 = Variable.unary("q2");

    // at most one queen in each row: all i: num | lone x.i

    rules.add(x.join(i).lone().forAll(i.oneOf(num)));

    // at most one queen in each column: all i: num | lone y.i
    rules.add(y.join(i).lone().forAll(i.oneOf(num)));

    // no queen in a blocked position:  all q: Queen | q.x->q.y !in blocked
    rules.add(q1.join(x).product(q1.join(y)).intersection(blocked).no().forAll(q1.oneOf(queen)));

    // at most one queen on each diagonal
    //		all q1: Queen, q2: Queen - q1 |
    //		let xu = prevs[q2.x] + prevs[q1.x],
    //		     xi =  prevs[q2.x] & prevs[q1.x],
    //                yu = prevs[q2.y] + prevs[q1.y],
    //                yi = prevs[q2.y] & prevs[q1.y] |
    //		#(xu - xi) != #(yu - yi)
    final Expression ordClosure = ord.closure();
    final Expression q2xPrevs = ordClosure.join(q2.join(x)), q1xPrevs = ordClosure.join(q1.join(x));
    final Expression q2yPrevs = ordClosure.join(q2.join(y)), q1yPrevs = ordClosure.join(q1.join(y));

    final IntExpression xDiff =
        (q2xPrevs.union(q1xPrevs)).difference(q2xPrevs.intersection(q1xPrevs)).count();
    final IntExpression yDiff =
        (q2yPrevs.union(q1yPrevs)).difference(q2yPrevs.intersection(q1yPrevs)).count();

    rules.add(xDiff.eq(yDiff).not().forAll(q1.oneOf(queen).and(q2.oneOf(queen.difference(q1)))));

    return Formula.and(rules);
  }
Example #7
0
 /**
  * Helper method that returns the constraint that the sig has exactly "n" elements, or at most "n"
  * elements
  */
 private Formula size(Sig sig, int n, boolean exact) {
   Expression a = sol.a2k(sig);
   if (n <= 0) return a.no();
   if (n == 1) return exact ? a.one() : a.lone();
   Formula f = exact ? Formula.TRUE : null;
   Decls d = null;
   Expression sum = null;
   while (n > 0) {
     n--;
     Variable v = Variable.unary("");
     kodkod.ast.Decl dd = v.oneOf(a);
     if (d == null) d = dd;
     else d = dd.and(d);
     if (sum == null) sum = v;
     else {
       if (f != null) f = v.intersection(sum).no().and(f);
       sum = v.union(sum);
     }
   }
   if (f != null) return sum.eq(a).and(f).forSome(d);
   else return a.no().or(sum.eq(a).forSome(d));
 }
Example #8
0
 /**
  * Computes the bounds for sigs/fields, then construct a BoundsComputer object that you can query.
  */
 private BoundsComputer(A4Reporter rep, A4Solution sol, ScopeComputer sc, Iterable<Sig> sigs)
     throws Err {
   this.sc = sc;
   this.factory = sol.getFactory();
   this.rep = rep;
   this.sol = sol;
   // Figure out the sig bounds
   final Universe universe = factory.universe();
   final int atomN = universe.size();
   final List<Tuple> atoms = new ArrayList<Tuple>(atomN);
   for (int i = atomN - 1; i >= 0; i--) atoms.add(factory.tuple(universe.atom(i)));
   for (Sig s : sigs) if (!s.builtin && s.isTopLevel()) computeLowerBound(atoms, (PrimSig) s);
   for (Sig s : sigs) if (!s.builtin && s.isTopLevel()) computeUpperBound((PrimSig) s);
   // Bound the sigs
   for (Sig s : sigs) if (!s.builtin && s.isTopLevel()) allocatePrimSig((PrimSig) s);
   for (Sig s : sigs) if (s instanceof SubsetSig) allocateSubsetSig((SubsetSig) s);
   // Bound the fields
   again:
   for (Sig s : sigs) {
     while (s.isOne != null
         && s.getFieldDecls().size() == 2
         && s.getFields().size() == 2
         && s.getFacts().size() == 1) {
       // Let's check whether this is a total ordering on an enum...
       Expr fact = s.getFacts().get(0).deNOP(),
           b1 = s.getFieldDecls().get(0).expr.deNOP(),
           b2 = s.getFieldDecls().get(1).expr.deNOP(),
           b3;
       if (!(fact instanceof ExprList)
           || !(b1 instanceof ExprUnary)
           || !(b2 instanceof ExprBinary)) break;
       ExprList list = (ExprList) fact;
       if (list.op != ExprList.Op.TOTALORDER || list.args.size() != 3) break;
       if (((ExprUnary) b1).op != ExprUnary.Op.SETOF) break;
       else b1 = ((ExprUnary) b1).sub.deNOP();
       if (((ExprBinary) b2).op != ExprBinary.Op.ARROW) break;
       else {
         b3 = ((ExprBinary) b2).right.deNOP();
         b2 = ((ExprBinary) b2).left.deNOP();
       }
       if (!(b1 instanceof PrimSig) || b1 != b2 || b1 != b3) break;
       PrimSig sub = (PrimSig) b1;
       Field f1 = s.getFields().get(0), f2 = s.getFields().get(1);
       if (sub.isEnum == null
           || !list.args.get(0).isSame(sub)
           || !list.args.get(1).isSame(s.join(f1))
           || !list.args.get(2).isSame(s.join(f2))) break;
       // Now, we've confirmed it is a total ordering on an enum. Let's pre-bind the relations
       TupleSet me = sol.query(true, sol.a2k(s), false),
           firstTS = factory.noneOf(2),
           lastTS = null,
           nextTS = factory.noneOf(3);
       if (me.size() != 1 || me.arity() != 1) break;
       int n = sub.children().size();
       for (PrimSig c : sub.children()) {
         TupleSet TS = sol.query(true, sol.a2k(c), false);
         if (TS.size() != 1 || TS.arity() != 1) {
           firstTS = factory.noneOf(2);
           nextTS = factory.noneOf(3);
           break;
         }
         if (lastTS == null) {
           firstTS = me.product(TS);
           lastTS = TS;
           continue;
         }
         nextTS.addAll(me.product(lastTS).product(TS));
         lastTS = TS;
       }
       if (firstTS.size() != (n > 0 ? 1 : 0) || nextTS.size() != n - 1) break;
       sol.addField(f1, sol.addRel(s.label + "." + f1.label, firstTS, firstTS));
       sol.addField(f2, sol.addRel(s.label + "." + f2.label, nextTS, nextTS));
       rep.bound("Field " + s.label + "." + f1.label + " == " + firstTS + "\n");
       rep.bound("Field " + s.label + "." + f2.label + " == " + nextTS + "\n");
       continue again;
     }
     for (Field f : s.getFields()) {
       boolean isOne = s.isOne != null;
       if (isOne && f.decl().expr.mult() == ExprUnary.Op.EXACTLYOF) {
         Expression sim = sim(f.decl().expr);
         if (sim != null) {
           rep.bound("Field " + s.label + "." + f.label + " defined to be " + sim + "\n");
           sol.addField(f, sol.a2k(s).product(sim));
           continue;
         }
       }
       Type t = isOne ? Sig.UNIV.type().join(f.type()) : f.type();
       TupleSet ub = factory.noneOf(t.arity());
       for (List<PrimSig> p : t.fold()) {
         TupleSet upper = null;
         for (PrimSig b : p) {
           TupleSet tmp = sol.query(true, sol.a2k(b), false);
           if (upper == null) upper = tmp;
           else upper = upper.product(tmp);
         }
         ub.addAll(upper);
       }
       Relation r = sol.addRel(s.label + "." + f.label, null, ub);
       sol.addField(f, isOne ? sol.a2k(s).product(r) : r);
     }
   }
   // Add any additional SIZE constraints
   for (Sig s : sigs)
     if (!s.builtin) {
       Expression exp = sol.a2k(s);
       TupleSet upper = sol.query(true, exp, false), lower = sol.query(false, exp, false);
       final int n = sc.sig2scope(s);
       if (s.isOne != null && (lower.size() != 1 || upper.size() != 1)) {
         rep.bound("Sig " + s + " in " + upper + " with size==1\n");
         sol.addFormula(exp.one(), s.isOne);
         continue;
       }
       if (s.isSome != null && lower.size() < 1) sol.addFormula(exp.some(), s.isSome);
       if (s.isLone != null && upper.size() > 1) sol.addFormula(exp.lone(), s.isLone);
       if (n < 0) continue; // This means no scope was specified
       if (lower.size() == n && upper.size() == n && sc.isExact(s)) {
         rep.bound("Sig " + s + " == " + upper + "\n");
       } else if (sc.isExact(s)) {
         rep.bound("Sig " + s + " in " + upper + " with size==" + n + "\n");
         sol.addFormula(size(s, n, true), Pos.UNKNOWN);
       } else if (upper.size() <= n) {
         rep.bound("Sig " + s + " in " + upper + "\n");
       } else {
         rep.bound("Sig " + s + " in " + upper + " with size<=" + n + "\n");
         sol.addFormula(size(s, n, false), Pos.UNKNOWN);
       }
     }
 }
  public static void main(String[] args) throws Exception {

    Relation x0 = Relation.unary("Int/min");
    Relation x1 = Relation.unary("Int/zero");
    Relation x2 = Relation.unary("Int/max");
    Relation x3 = Relation.nary("Int/next", 2);
    Relation x4 = Relation.unary("seq/Int");
    Relation x5 = Relation.unary("String");
    Relation x6 = Relation.unary("this/A");
    Relation x7 = Relation.unary("this/Relation");
    Relation x8 = Relation.nary("this/Relation.r", 4);

    List<String> atomlist =
        Arrays.asList(
            "-1",
            "-2",
            "-3",
            "-4",
            "-5",
            "-6",
            "-7",
            "-8",
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6",
            "7",
            "A$0",
            "A$1",
            "A$2",
            "Relation$0",
            "unused0",
            "unused1");

    Universe universe = new Universe(atomlist);
    TupleFactory factory = universe.factory();
    Bounds bounds = new Bounds(universe);

    TupleSet x0_upper = factory.noneOf(1);
    x0_upper.add(factory.tuple("-8"));
    bounds.boundExactly(x0, x0_upper);

    TupleSet x1_upper = factory.noneOf(1);
    x1_upper.add(factory.tuple("0"));
    bounds.boundExactly(x1, x1_upper);

    TupleSet x2_upper = factory.noneOf(1);
    x2_upper.add(factory.tuple("7"));
    bounds.boundExactly(x2, x2_upper);

    TupleSet x3_upper = factory.noneOf(2);
    x3_upper.add(factory.tuple("-8").product(factory.tuple("-7")));
    x3_upper.add(factory.tuple("-7").product(factory.tuple("-6")));
    x3_upper.add(factory.tuple("-6").product(factory.tuple("-5")));
    x3_upper.add(factory.tuple("-5").product(factory.tuple("-4")));
    x3_upper.add(factory.tuple("-4").product(factory.tuple("-3")));
    x3_upper.add(factory.tuple("-3").product(factory.tuple("-2")));
    x3_upper.add(factory.tuple("-2").product(factory.tuple("-1")));
    x3_upper.add(factory.tuple("-1").product(factory.tuple("0")));
    x3_upper.add(factory.tuple("0").product(factory.tuple("1")));
    x3_upper.add(factory.tuple("1").product(factory.tuple("2")));
    x3_upper.add(factory.tuple("2").product(factory.tuple("3")));
    x3_upper.add(factory.tuple("3").product(factory.tuple("4")));
    x3_upper.add(factory.tuple("4").product(factory.tuple("5")));
    x3_upper.add(factory.tuple("5").product(factory.tuple("6")));
    x3_upper.add(factory.tuple("6").product(factory.tuple("7")));
    bounds.boundExactly(x3, x3_upper);

    TupleSet x4_upper = factory.noneOf(1);
    x4_upper.add(factory.tuple("0"));
    x4_upper.add(factory.tuple("1"));
    x4_upper.add(factory.tuple("2"));
    bounds.boundExactly(x4, x4_upper);

    TupleSet x5_upper = factory.noneOf(1);
    bounds.boundExactly(x5, x5_upper);

    TupleSet x6_upper = factory.noneOf(1);
    x6_upper.add(factory.tuple("A$0"));
    x6_upper.add(factory.tuple("A$1"));
    x6_upper.add(factory.tuple("A$2"));
    bounds.boundExactly(x6, x6_upper);

    TupleSet x7_upper = factory.noneOf(1);
    x7_upper.add(factory.tuple("unused0"));
    x7_upper.add(factory.tuple("unused1"));
    x7_upper.add(factory.tuple("Relation$0"));
    bounds.bound(x7, x7_upper);

    TupleSet x8_upper = factory.noneOf(4);
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("unused1")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1"))
            .product(factory.tuple("A$2")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$0")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$1")));
    x8_upper.add(
        factory
            .tuple("Relation$0")
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2"))
            .product(factory.tuple("A$2")));
    bounds.bound(x8, x8_upper);

    bounds.boundExactly(-8, factory.range(factory.tuple("-8"), factory.tuple("-8")));
    bounds.boundExactly(-7, factory.range(factory.tuple("-7"), factory.tuple("-7")));
    bounds.boundExactly(-6, factory.range(factory.tuple("-6"), factory.tuple("-6")));
    bounds.boundExactly(-5, factory.range(factory.tuple("-5"), factory.tuple("-5")));
    bounds.boundExactly(-4, factory.range(factory.tuple("-4"), factory.tuple("-4")));
    bounds.boundExactly(-3, factory.range(factory.tuple("-3"), factory.tuple("-3")));
    bounds.boundExactly(-2, factory.range(factory.tuple("-2"), factory.tuple("-2")));
    bounds.boundExactly(-1, factory.range(factory.tuple("-1"), factory.tuple("-1")));
    bounds.boundExactly(0, factory.range(factory.tuple("0"), factory.tuple("0")));
    bounds.boundExactly(1, factory.range(factory.tuple("1"), factory.tuple("1")));
    bounds.boundExactly(2, factory.range(factory.tuple("2"), factory.tuple("2")));
    bounds.boundExactly(3, factory.range(factory.tuple("3"), factory.tuple("3")));
    bounds.boundExactly(4, factory.range(factory.tuple("4"), factory.tuple("4")));
    bounds.boundExactly(5, factory.range(factory.tuple("5"), factory.tuple("5")));
    bounds.boundExactly(6, factory.range(factory.tuple("6"), factory.tuple("6")));
    bounds.boundExactly(7, factory.range(factory.tuple("7"), factory.tuple("7")));

    Variable x12 = Variable.unary("this");
    Decls x11 = x12.oneOf(x7);
    Expression x16 = x12.join(x8);
    Expression x18 = x6.product(x6);
    Expression x17 = x6.product(x18);
    Formula x15 = x16.in(x17);
    Variable x21 = Variable.unary("x21");
    Decls x20 = x21.oneOf(x6);
    Expression x25 = x21.join(x16);
    Expression x26 = x6.product(x6);
    Formula x24 = x25.in(x26);
    Variable x29 = Variable.unary("x29");
    Decls x28 = x29.oneOf(x6);
    Expression x32 = x29.join(x25);
    Formula x31 = x32.one();
    Formula x33 = x32.in(x6);
    Formula x30 = x31.and(x33);
    Formula x27 = x30.forAll(x28);
    Formula x23 = x24.and(x27);
    Variable x36 = Variable.unary("x36");
    Decls x35 = x36.oneOf(x6);
    Expression x38 = x25.join(x36);
    Formula x37 = x38.in(x6);
    Formula x34 = x37.forAll(x35);
    Formula x22 = x23.and(x34);
    Formula x19 = x22.forAll(x20);
    Formula x14 = x15.and(x19);
    Variable x42 = Variable.unary("x42");
    Decls x41 = x42.oneOf(Expression.UNIV);
    Variable x45 = Variable.unary("x45");
    Decls x44 = x45.oneOf(Expression.UNIV);
    Decls x40 = x41.and(x44);
    Expression x50 = x42.product(x45);
    Expression x51 = x6.product(x6);
    Formula x49 = x50.in(x51);
    Variable x54 = Variable.unary("x54");
    Decls x53 = x54.oneOf(x6);
    Expression x57 = x54.join(x50);
    Formula x56 = x57.one();
    Formula x58 = x57.in(x6);
    Formula x55 = x56.and(x58);
    Formula x52 = x55.forAll(x53);
    Formula x48 = x49.and(x52);
    Variable x61 = Variable.unary("x61");
    Decls x60 = x61.oneOf(x6);
    Expression x63 = x50.join(x61);
    Formula x62 = x63.in(x6);
    Formula x59 = x62.forAll(x60);
    Formula x47 = x48.and(x59);
    Expression x66 = x16.join(x45);
    Expression x65 = x66.join(x42);
    Formula x64 = x65.in(x6);
    Formula x46 = x47.implies(x64);
    Formula x39 = x46.forAll(x40);
    Formula x13 = x14.and(x39);
    Formula x10 = x13.forAll(x11);
    Expression x70 = x8.join(Expression.UNIV);
    Expression x69 = x70.join(Expression.UNIV);
    Expression x68 = x69.join(Expression.UNIV);
    Formula x67 = x68.in(x7);
    Formula x71 = x0.eq(x0);
    Formula x72 = x1.eq(x1);
    Formula x73 = x2.eq(x2);
    Formula x74 = x3.eq(x3);
    Formula x75 = x4.eq(x4);
    Formula x76 = x5.eq(x5);
    Formula x77 = x6.eq(x6);
    Formula x78 = x7.eq(x7);
    Formula x79 = x8.eq(x8);
    Formula x9 =
        Formula.compose(FormulaOperator.AND, x10, x67, x71, x72, x73, x74, x75, x76, x77, x78, x79);

    Solver solver = new Solver();
    solver.options().setSolver(SATFactory.DefaultSAT4J);
    solver.options().setBitwidth(4);
    solver.options().setFlatten(false);
    solver.options().setIntEncoding(Options.IntEncoding.TWOSCOMPLEMENT);
    solver.options().setSymmetryBreaking(20);
    solver.options().setSkolemDepth(0);

    System.out.println(PrettyPrinter.print(x9, 0));
    System.out.println(bounds);

    System.out.println("Solving...");
    System.out.flush();
    Solution sol = solver.solve(x9, bounds);
    System.out.println(sol.toString());

    Instance inst = sol.instance();
    Evaluator ev = new Evaluator(inst);

    System.out.println("Universe: " + ev.evaluate(Expression.UNIV));
    Formula xx = x46.forAll(x40).forAll(x11);
    System.out.println(PrettyPrinter.print(xx, 2));
    System.out.println(ev.evaluate(xx));

    System.out.println(PrettyPrinter.print(x46, 4));

    //        Variable r = Variable.unary("this");
    //        Variable u1 = Variable.unary("u1");
    //        Variable u2 = Variable.unary("u2");
    //
    //        Formula ff =
    // u1.product(u2).in(x6.product(x6)).forAll(u1.oneOf(Expression.UNIV).and(u2.oneOf(Expression.UNIV))).forAll(r.oneOf(x7));
    //        System.out.println(PrettyPrinter.print(ff, 0));
    //        System.out.println(ev.evaluate(ff));

  }
  public static void main(String[] args) throws Exception {

    Relation x0 = Relation.unary("Int/min");
    Relation x1 = Relation.unary("Int/zero");
    Relation x2 = Relation.unary("Int/max");
    Relation x3 = Relation.nary("Int/next", 2);
    Relation x4 = Relation.unary("seq/Int");
    Relation x5 = Relation.unary("String");
    Relation x6 = Relation.unary("this/Test");
    Relation x7 = Relation.nary("this/Test.weight", 2);
    Relation x8 = Relation.nary("this/Test.x", 2);
    Relation x9 = Relation.nary("this/Test.y", 2);

    List<String> atomlist =
        Arrays.asList(
            "-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "0", "1", "2", "3", "4", "5", "6", "7",
            "Test$0", "Test$1", "Test$2");

    Universe universe = new Universe(atomlist);
    TupleFactory factory = universe.factory();
    Bounds bounds = new Bounds(universe);

    TupleSet x0_upper = factory.noneOf(1);
    x0_upper.add(factory.tuple("-8"));
    bounds.boundExactly(x0, x0_upper);

    TupleSet x1_upper = factory.noneOf(1);
    x1_upper.add(factory.tuple("0"));
    bounds.boundExactly(x1, x1_upper);

    TupleSet x2_upper = factory.noneOf(1);
    x2_upper.add(factory.tuple("7"));
    bounds.boundExactly(x2, x2_upper);

    TupleSet x3_upper = factory.noneOf(2);
    x3_upper.add(factory.tuple("-8").product(factory.tuple("-7")));
    x3_upper.add(factory.tuple("-7").product(factory.tuple("-6")));
    x3_upper.add(factory.tuple("-6").product(factory.tuple("-5")));
    x3_upper.add(factory.tuple("-5").product(factory.tuple("-4")));
    x3_upper.add(factory.tuple("-4").product(factory.tuple("-3")));
    x3_upper.add(factory.tuple("-3").product(factory.tuple("-2")));
    x3_upper.add(factory.tuple("-2").product(factory.tuple("-1")));
    x3_upper.add(factory.tuple("-1").product(factory.tuple("0")));
    x3_upper.add(factory.tuple("0").product(factory.tuple("1")));
    x3_upper.add(factory.tuple("1").product(factory.tuple("2")));
    x3_upper.add(factory.tuple("2").product(factory.tuple("3")));
    x3_upper.add(factory.tuple("3").product(factory.tuple("4")));
    x3_upper.add(factory.tuple("4").product(factory.tuple("5")));
    x3_upper.add(factory.tuple("5").product(factory.tuple("6")));
    x3_upper.add(factory.tuple("6").product(factory.tuple("7")));
    bounds.boundExactly(x3, x3_upper);

    TupleSet x4_upper = factory.noneOf(1);
    x4_upper.add(factory.tuple("0"));
    x4_upper.add(factory.tuple("1"));
    x4_upper.add(factory.tuple("2"));
    x4_upper.add(factory.tuple("3"));
    bounds.boundExactly(x4, x4_upper);

    TupleSet x5_upper = factory.noneOf(1);
    bounds.boundExactly(x5, x5_upper);

    TupleSet x6_upper = factory.noneOf(1);
    x6_upper.add(factory.tuple("Test$0"));
    x6_upper.add(factory.tuple("Test$1"));
    x6_upper.add(factory.tuple("Test$2"));
    bounds.boundExactly(x6, x6_upper);

    TupleSet x7_upper = factory.noneOf(2);
    x7_upper.add(factory.tuple("Test$0").product(factory.tuple("-8")));
    x7_upper.add(factory.tuple("Test$0").product(factory.tuple("-7")));
    x7_upper.add(factory.tuple("Test$0").product(factory.tuple("-6")));
    x7_upper.add(factory.tuple("Test$0").product(factory.tuple("-5")));
    x7_upper.add(factory.tuple("Test$0").product(factory.tuple("-4")));
    x7_upper.add(factory.tuple("Test$0").product(factory.tuple("-3")));
    x7_upper.add(factory.tuple("Test$0").product(factory.tuple("-2")));
    x7_upper.add(factory.tuple("Test$0").product(factory.tuple("-1")));
    x7_upper.add(factory.tuple("Test$0").product(factory.tuple("0")));
    x7_upper.add(factory.tuple("Test$0").product(factory.tuple("1")));
    x7_upper.add(factory.tuple("Test$0").product(factory.tuple("2")));
    x7_upper.add(factory.tuple("Test$0").product(factory.tuple("3")));
    x7_upper.add(factory.tuple("Test$0").product(factory.tuple("4")));
    x7_upper.add(factory.tuple("Test$0").product(factory.tuple("5")));
    x7_upper.add(factory.tuple("Test$0").product(factory.tuple("6")));
    x7_upper.add(factory.tuple("Test$0").product(factory.tuple("7")));
    x7_upper.add(factory.tuple("Test$1").product(factory.tuple("-8")));
    x7_upper.add(factory.tuple("Test$1").product(factory.tuple("-7")));
    x7_upper.add(factory.tuple("Test$1").product(factory.tuple("-6")));
    x7_upper.add(factory.tuple("Test$1").product(factory.tuple("-5")));
    x7_upper.add(factory.tuple("Test$1").product(factory.tuple("-4")));
    x7_upper.add(factory.tuple("Test$1").product(factory.tuple("-3")));
    x7_upper.add(factory.tuple("Test$1").product(factory.tuple("-2")));
    x7_upper.add(factory.tuple("Test$1").product(factory.tuple("-1")));
    x7_upper.add(factory.tuple("Test$1").product(factory.tuple("0")));
    x7_upper.add(factory.tuple("Test$1").product(factory.tuple("1")));
    x7_upper.add(factory.tuple("Test$1").product(factory.tuple("2")));
    x7_upper.add(factory.tuple("Test$1").product(factory.tuple("3")));
    x7_upper.add(factory.tuple("Test$1").product(factory.tuple("4")));
    x7_upper.add(factory.tuple("Test$1").product(factory.tuple("5")));
    x7_upper.add(factory.tuple("Test$1").product(factory.tuple("6")));
    x7_upper.add(factory.tuple("Test$1").product(factory.tuple("7")));
    x7_upper.add(factory.tuple("Test$2").product(factory.tuple("-8")));
    x7_upper.add(factory.tuple("Test$2").product(factory.tuple("-7")));
    x7_upper.add(factory.tuple("Test$2").product(factory.tuple("-6")));
    x7_upper.add(factory.tuple("Test$2").product(factory.tuple("-5")));
    x7_upper.add(factory.tuple("Test$2").product(factory.tuple("-4")));
    x7_upper.add(factory.tuple("Test$2").product(factory.tuple("-3")));
    x7_upper.add(factory.tuple("Test$2").product(factory.tuple("-2")));
    x7_upper.add(factory.tuple("Test$2").product(factory.tuple("-1")));
    x7_upper.add(factory.tuple("Test$2").product(factory.tuple("0")));
    x7_upper.add(factory.tuple("Test$2").product(factory.tuple("1")));
    x7_upper.add(factory.tuple("Test$2").product(factory.tuple("2")));
    x7_upper.add(factory.tuple("Test$2").product(factory.tuple("3")));
    x7_upper.add(factory.tuple("Test$2").product(factory.tuple("4")));
    x7_upper.add(factory.tuple("Test$2").product(factory.tuple("5")));
    x7_upper.add(factory.tuple("Test$2").product(factory.tuple("6")));
    x7_upper.add(factory.tuple("Test$2").product(factory.tuple("7")));
    bounds.bound(x7, x7_upper);

    TupleSet x8_upper = factory.noneOf(2);
    x8_upper.add(factory.tuple("Test$0").product(factory.tuple("-8")));
    x8_upper.add(factory.tuple("Test$0").product(factory.tuple("-7")));
    x8_upper.add(factory.tuple("Test$0").product(factory.tuple("-6")));
    x8_upper.add(factory.tuple("Test$0").product(factory.tuple("-5")));
    x8_upper.add(factory.tuple("Test$0").product(factory.tuple("-4")));
    x8_upper.add(factory.tuple("Test$0").product(factory.tuple("-3")));
    x8_upper.add(factory.tuple("Test$0").product(factory.tuple("-2")));
    x8_upper.add(factory.tuple("Test$0").product(factory.tuple("-1")));
    x8_upper.add(factory.tuple("Test$0").product(factory.tuple("0")));
    x8_upper.add(factory.tuple("Test$0").product(factory.tuple("1")));
    x8_upper.add(factory.tuple("Test$0").product(factory.tuple("2")));
    x8_upper.add(factory.tuple("Test$0").product(factory.tuple("3")));
    x8_upper.add(factory.tuple("Test$0").product(factory.tuple("4")));
    x8_upper.add(factory.tuple("Test$0").product(factory.tuple("5")));
    x8_upper.add(factory.tuple("Test$0").product(factory.tuple("6")));
    x8_upper.add(factory.tuple("Test$0").product(factory.tuple("7")));
    x8_upper.add(factory.tuple("Test$1").product(factory.tuple("-8")));
    x8_upper.add(factory.tuple("Test$1").product(factory.tuple("-7")));
    x8_upper.add(factory.tuple("Test$1").product(factory.tuple("-6")));
    x8_upper.add(factory.tuple("Test$1").product(factory.tuple("-5")));
    x8_upper.add(factory.tuple("Test$1").product(factory.tuple("-4")));
    x8_upper.add(factory.tuple("Test$1").product(factory.tuple("-3")));
    x8_upper.add(factory.tuple("Test$1").product(factory.tuple("-2")));
    x8_upper.add(factory.tuple("Test$1").product(factory.tuple("-1")));
    x8_upper.add(factory.tuple("Test$1").product(factory.tuple("0")));
    x8_upper.add(factory.tuple("Test$1").product(factory.tuple("1")));
    x8_upper.add(factory.tuple("Test$1").product(factory.tuple("2")));
    x8_upper.add(factory.tuple("Test$1").product(factory.tuple("3")));
    x8_upper.add(factory.tuple("Test$1").product(factory.tuple("4")));
    x8_upper.add(factory.tuple("Test$1").product(factory.tuple("5")));
    x8_upper.add(factory.tuple("Test$1").product(factory.tuple("6")));
    x8_upper.add(factory.tuple("Test$1").product(factory.tuple("7")));
    x8_upper.add(factory.tuple("Test$2").product(factory.tuple("-8")));
    x8_upper.add(factory.tuple("Test$2").product(factory.tuple("-7")));
    x8_upper.add(factory.tuple("Test$2").product(factory.tuple("-6")));
    x8_upper.add(factory.tuple("Test$2").product(factory.tuple("-5")));
    x8_upper.add(factory.tuple("Test$2").product(factory.tuple("-4")));
    x8_upper.add(factory.tuple("Test$2").product(factory.tuple("-3")));
    x8_upper.add(factory.tuple("Test$2").product(factory.tuple("-2")));
    x8_upper.add(factory.tuple("Test$2").product(factory.tuple("-1")));
    x8_upper.add(factory.tuple("Test$2").product(factory.tuple("0")));
    x8_upper.add(factory.tuple("Test$2").product(factory.tuple("1")));
    x8_upper.add(factory.tuple("Test$2").product(factory.tuple("2")));
    x8_upper.add(factory.tuple("Test$2").product(factory.tuple("3")));
    x8_upper.add(factory.tuple("Test$2").product(factory.tuple("4")));
    x8_upper.add(factory.tuple("Test$2").product(factory.tuple("5")));
    x8_upper.add(factory.tuple("Test$2").product(factory.tuple("6")));
    x8_upper.add(factory.tuple("Test$2").product(factory.tuple("7")));
    bounds.bound(x8, x8_upper);

    TupleSet x9_upper = factory.noneOf(2);
    x9_upper.add(factory.tuple("Test$0").product(factory.tuple("-8")));
    x9_upper.add(factory.tuple("Test$0").product(factory.tuple("-7")));
    x9_upper.add(factory.tuple("Test$0").product(factory.tuple("-6")));
    x9_upper.add(factory.tuple("Test$0").product(factory.tuple("-5")));
    x9_upper.add(factory.tuple("Test$0").product(factory.tuple("-4")));
    x9_upper.add(factory.tuple("Test$0").product(factory.tuple("-3")));
    x9_upper.add(factory.tuple("Test$0").product(factory.tuple("-2")));
    x9_upper.add(factory.tuple("Test$0").product(factory.tuple("-1")));
    x9_upper.add(factory.tuple("Test$0").product(factory.tuple("0")));
    x9_upper.add(factory.tuple("Test$0").product(factory.tuple("1")));
    x9_upper.add(factory.tuple("Test$0").product(factory.tuple("2")));
    x9_upper.add(factory.tuple("Test$0").product(factory.tuple("3")));
    x9_upper.add(factory.tuple("Test$0").product(factory.tuple("4")));
    x9_upper.add(factory.tuple("Test$0").product(factory.tuple("5")));
    x9_upper.add(factory.tuple("Test$0").product(factory.tuple("6")));
    x9_upper.add(factory.tuple("Test$0").product(factory.tuple("7")));
    x9_upper.add(factory.tuple("Test$1").product(factory.tuple("-8")));
    x9_upper.add(factory.tuple("Test$1").product(factory.tuple("-7")));
    x9_upper.add(factory.tuple("Test$1").product(factory.tuple("-6")));
    x9_upper.add(factory.tuple("Test$1").product(factory.tuple("-5")));
    x9_upper.add(factory.tuple("Test$1").product(factory.tuple("-4")));
    x9_upper.add(factory.tuple("Test$1").product(factory.tuple("-3")));
    x9_upper.add(factory.tuple("Test$1").product(factory.tuple("-2")));
    x9_upper.add(factory.tuple("Test$1").product(factory.tuple("-1")));
    x9_upper.add(factory.tuple("Test$1").product(factory.tuple("0")));
    x9_upper.add(factory.tuple("Test$1").product(factory.tuple("1")));
    x9_upper.add(factory.tuple("Test$1").product(factory.tuple("2")));
    x9_upper.add(factory.tuple("Test$1").product(factory.tuple("3")));
    x9_upper.add(factory.tuple("Test$1").product(factory.tuple("4")));
    x9_upper.add(factory.tuple("Test$1").product(factory.tuple("5")));
    x9_upper.add(factory.tuple("Test$1").product(factory.tuple("6")));
    x9_upper.add(factory.tuple("Test$1").product(factory.tuple("7")));
    x9_upper.add(factory.tuple("Test$2").product(factory.tuple("-8")));
    x9_upper.add(factory.tuple("Test$2").product(factory.tuple("-7")));
    x9_upper.add(factory.tuple("Test$2").product(factory.tuple("-6")));
    x9_upper.add(factory.tuple("Test$2").product(factory.tuple("-5")));
    x9_upper.add(factory.tuple("Test$2").product(factory.tuple("-4")));
    x9_upper.add(factory.tuple("Test$2").product(factory.tuple("-3")));
    x9_upper.add(factory.tuple("Test$2").product(factory.tuple("-2")));
    x9_upper.add(factory.tuple("Test$2").product(factory.tuple("-1")));
    x9_upper.add(factory.tuple("Test$2").product(factory.tuple("0")));
    x9_upper.add(factory.tuple("Test$2").product(factory.tuple("1")));
    x9_upper.add(factory.tuple("Test$2").product(factory.tuple("2")));
    x9_upper.add(factory.tuple("Test$2").product(factory.tuple("3")));
    x9_upper.add(factory.tuple("Test$2").product(factory.tuple("4")));
    x9_upper.add(factory.tuple("Test$2").product(factory.tuple("5")));
    x9_upper.add(factory.tuple("Test$2").product(factory.tuple("6")));
    x9_upper.add(factory.tuple("Test$2").product(factory.tuple("7")));
    bounds.bound(x9, x9_upper);

    bounds.boundExactly(-8, factory.range(factory.tuple("-8"), factory.tuple("-8")));
    bounds.boundExactly(-7, factory.range(factory.tuple("-7"), factory.tuple("-7")));
    bounds.boundExactly(-6, factory.range(factory.tuple("-6"), factory.tuple("-6")));
    bounds.boundExactly(-5, factory.range(factory.tuple("-5"), factory.tuple("-5")));
    bounds.boundExactly(-4, factory.range(factory.tuple("-4"), factory.tuple("-4")));
    bounds.boundExactly(-3, factory.range(factory.tuple("-3"), factory.tuple("-3")));
    bounds.boundExactly(-2, factory.range(factory.tuple("-2"), factory.tuple("-2")));
    bounds.boundExactly(-1, factory.range(factory.tuple("-1"), factory.tuple("-1")));
    bounds.boundExactly(0, factory.range(factory.tuple("0"), factory.tuple("0")));
    bounds.boundExactly(1, factory.range(factory.tuple("1"), factory.tuple("1")));
    bounds.boundExactly(2, factory.range(factory.tuple("2"), factory.tuple("2")));
    bounds.boundExactly(3, factory.range(factory.tuple("3"), factory.tuple("3")));
    bounds.boundExactly(4, factory.range(factory.tuple("4"), factory.tuple("4")));
    bounds.boundExactly(5, factory.range(factory.tuple("5"), factory.tuple("5")));
    bounds.boundExactly(6, factory.range(factory.tuple("6"), factory.tuple("6")));
    bounds.boundExactly(7, factory.range(factory.tuple("7"), factory.tuple("7")));

    Variable x13 = Variable.unary("this");
    Decls x12 = x13.oneOf(x6);
    Expression x16 = x13.join(x7);
    Formula x15 = x16.one();
    Formula x17 = x16.in(Expression.INTS);
    Formula x14 = x15.and(x17);
    Formula x11 = x14.forAll(x12);
    Expression x20 = x7.join(Expression.UNIV);
    Formula x19 = x20.in(x6);
    Variable x24 = Variable.unary("this");
    Decls x23 = x24.oneOf(x6);
    Expression x27 = x24.join(x8);
    Formula x26 = x27.lone();
    Formula x28 = x27.in(Expression.INTS);
    Formula x25 = x26.and(x28);
    Formula x22 = x25.forAll(x23);
    Expression x30 = x8.join(Expression.UNIV);
    Formula x29 = x30.in(x6);
    Variable x33 = Variable.unary("this");
    Decls x32 = x33.oneOf(x6);
    Expression x36 = x33.join(x9);
    Formula x35 = x36.one();
    Formula x37 = x36.in(Expression.INTS);
    Formula x34 = x35.and(x37);
    Formula x31 = x34.forAll(x32);
    Expression x39 = x9.join(Expression.UNIV);
    Formula x38 = x39.in(x6);
    Variable x42 = Variable.unary("this");
    Decls x41 = x42.oneOf(x6);
    Expression x44 = x42.join(x7);
    Expression x48 = x42.join(x8);
    IntExpression x47 = x48.sum();
    Expression x50 = x42.join(x9);
    IntExpression x49 = x50.sum();
    IntExpression x46 = x47.plus(x49);
    Expression x45 = x46.toExpression();
    Formula x43 = x44.eq(x45);
    Formula x40 = x43.forAll(x41);
    Formula x51 = x0.eq(x0);
    Formula x52 = x1.eq(x1);
    Formula x53 = x2.eq(x2);
    Formula x54 = x3.eq(x3);
    Formula x55 = x4.eq(x4);
    Formula x56 = x5.eq(x5);
    Formula x57 = x6.eq(x6);
    Formula x58 = x7.eq(x7);
    Formula x59 = x8.eq(x8);
    Formula x60 = x9.eq(x9);
    IntExprReduction ier = new IntExprReduction();
    Formula[] formulas =
        ier.reduceIntExpressions(
            x11, x19, x22, x29, x31, x38, x40, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60);
    Formula newFormula = Formula.compose(FormulaOperator.AND, formulas);
    ier.solve(newFormula, bounds, factory, universe, 32);
  }