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;
 }
  /**
   * 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 #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;
 }