}
}
/** Helper method that translates the formula "r in (a ?->? b)" into a Kodkod formula. */
private Formula isInBinary(Expression r, ExprBinary ab) throws Err {
final Expression a=cset(ab.left), b=cset(ab.right);
Decls d=null, d2=null;
Formula ans1, ans2;
// "R in A ->op B" means for each tuple a in A, there are "op" tuples in r that begins with a.
Expression atuple=null, ar=r;
for(int i=a.arity(); i>0; i--) {
Variable v=Variable.unary("");
if (a.arity()==1) d=v.oneOf(a); else if (d==null) d=v.oneOf(Relation.UNIV); else d=v.oneOf(Relation.UNIV).and(d);
ar=v.join(ar);
if (atuple==null) atuple=v; else atuple=atuple.product(v);
}
ans1=isIn(ar, ab.right);
switch(ab.op) {
case ISSEQ_ARROW_LONE:
case ANY_ARROW_LONE: case SOME_ARROW_LONE: case ONE_ARROW_LONE: case LONE_ARROW_LONE: ans1=ar.lone().and(ans1); break;
case ANY_ARROW_ONE: case SOME_ARROW_ONE: case ONE_ARROW_ONE: case LONE_ARROW_ONE: ans1=ar.one().and(ans1); break;
case ANY_ARROW_SOME: case SOME_ARROW_SOME: case ONE_ARROW_SOME: case LONE_ARROW_SOME: ans1=ar.some().and(ans1); break;
}
if (a.arity()>1) { Formula tmp=isIn(atuple, ab.left); if (tmp!=Formula.TRUE) ans1=tmp.implies(ans1); }
ans1=ans1.forAll(d);
// "R in A op-> B" means for each tuple b in B, there are "op" tuples in r that end with b.
Expression btuple=null, rb=r;
for(int i=b.arity(); i>0; i--) {
Variable v=Variable.unary("");
if (b.arity()==1) d2=v.oneOf(b); else if (d2==null) d2=v.oneOf(Relation.UNIV); else d2=v.oneOf(Relation.UNIV).and(d2);
rb=rb.join(v);
if (btuple==null) btuple=v; else btuple=v.product(btuple);
}
ans2=isIn(rb, ab.left);
switch(ab.op) {
case LONE_ARROW_ANY: case LONE_ARROW_SOME: case LONE_ARROW_ONE: case LONE_ARROW_LONE: ans2=rb.lone().and(ans2); break;
case ONE_ARROW_ANY: case ONE_ARROW_SOME: case ONE_ARROW_ONE: case ONE_ARROW_LONE: ans2=rb.one().and(ans2); break;
case SOME_ARROW_ANY: case SOME_ARROW_SOME: case SOME_ARROW_ONE: case SOME_ARROW_LONE: ans2=rb.some().and(ans2); break;
}
if (b.arity()>1) { Formula tmp=isIn(btuple, ab.right); if (tmp!=Formula.TRUE) ans2=tmp.implies(ans2); }
ans2=ans2.forAll(d2);
// Now, put everything together
Formula ans=r.in(a.product(b)).and(ans1).and(ans2);
if (ab.op==ExprBinary.Op.ISSEQ_ARROW_LONE) {
Expression rr=r;
while(rr.arity()>1) rr=rr.join(Relation.UNIV);
ans=rr.difference(rr.join(A4Solution.KK_NEXT)).in(A4Solution.KK_ZERO).and(ans);
}
return ans;
}