/** * */ package kodkod.examples.tptp; import static kodkod.ast.Expression.UNIV; import java.util.ArrayList; import java.util.List; import kodkod.ast.Expression; import kodkod.ast.Formula; import kodkod.ast.Relation; import kodkod.ast.Variable; import kodkod.engine.Solution; import kodkod.engine.Solver; import kodkod.engine.satlab.SATFactory; import kodkod.instance.Bounds; import kodkod.instance.TupleFactory; import kodkod.instance.TupleSet; import kodkod.instance.Universe; /** * A KK encoding of NUM374+1.p from http://www.cs.miami.edu/~tptp/ * @author Emina Torlak */ public final class NUM374 { private final Relation sum, product, exponent, n1; /** * Constructs a new instance of NUM374. */ public NUM374() { n1 = Relation.unary("n1"); sum = Relation.ternary("sum"); product = Relation.ternary("product"); exponent = Relation.ternary("exponent"); } /** * Returns op[X][Y]. * @return op[X][Y] */ final Expression apply(Relation op, Expression X, Expression Y) { return Y.join(X.join(op)); } /** * Returns sum[X][Y]. * @return sum[X][Y] */ final Expression sum(Expression X, Expression Y) { return Y.join(X.join(sum)); } /** * Returns product[X][Y]. * @return product[X][Y] */ final Expression product(Expression X, Expression Y) { return Y.join(X.join(product)); } /** * Returns exponent[X][Y]. * @return exponent[X][Y] */ final Expression exponent(Expression X, Expression Y) { return Y.join(X.join(exponent)); } /** * Returns the declarations. * @return declarations. */ public final Formula decls() { final Formula f0 = n1.one(); final Variable x = Variable.unary("X"); final Variable y = Variable.unary("Y"); final Formula f1 = sum(x,y).one().and(product(x,y).one()).and(exponent(x,y).one()); return f0.and(f1.forAll(x.oneOf(UNIV).and(y.oneOf(UNIV)))); } /** * Returns all X, Y: Num | op[X][Y] = op[Y][X] * @return all X, Y: Num | op[X][Y] = op[Y][X] */ final Formula symmetric(Relation op) { // all X, Y: Num | op[X][Y] = op[Y][X] final Variable x = Variable.unary("X"); final Variable y = Variable.unary("Y"); return apply(op, x, y).eq(apply(op, y, x)).forAll(x.oneOf(UNIV).and(y.oneOf(UNIV))); } /** * Returns all X, Y, Z: Num | op[X][op[Y][Z]] = op[op[X][Y]][Z] * @return all X, Y, Z: Num | op[X][op[Y][Z]] = op[op[X][Y]][Z] */ final Formula associative(Relation op) { // all X, Y, Z: Num | op[X][op[Y][Z]] = op[op[X][Y]][Z] final Variable x = Variable.unary("X"); final Variable y = Variable.unary("Y"); final Variable z = Variable.unary("Z"); return apply(op, x, apply(op, y, z)).eq(apply(op, apply(op, x, y), z)). forAll(x.oneOf(UNIV).and(y.oneOf(UNIV)).and(z.oneOf(UNIV))); } /** * Returns the sum_symmetry axiom. * @return sum_symmetry */ public final Formula sumSymmetry() { return symmetric(sum); } /** * Returns the sum_associativity axiom. * @return sum_associativity */ public final Formula sumAssociativity() { return associative(sum); } /** * Returns the product_identity axiom. * @return product_identity */ public final Formula productIdentity() { // ! [X] : product(X,n1) = X final Variable x = Variable.unary("X"); return product(x,n1).eq( x ).forAll(x.oneOf(UNIV)); } /** * Returns the product_symmetry axiom. * @return product_symmetry */ public final Formula productSymmetry() { return symmetric(product); } /** * Returns the product_associativity axiom. * @return product_associativity */ public final Formula productAssociativity() { return associative(product); } /** * Returns the sum_product_distribution axiom. * @return sum_product_distribution */ public final Formula sumProductDistribution() { // ! [X,Y,Z] : product(X,sum(Y,Z)) = sum(product(X,Y),product(X,Z)) )). final Variable x = Variable.unary("X"); final Variable y = Variable.unary("Y"); final Variable z = Variable.unary("Z"); return product(x, sum(y, z)).eq(sum(product(x,y),product(x,z))). forAll(x.oneOf(UNIV).and(y.oneOf(UNIV)).and(z.oneOf(UNIV))); } /** * Returns the exponent_n1 axiom. * @return exponent_n1 */ public final Formula exponentN1() { // ! [X] : exponent(n1,X) = n1 final Variable x = Variable.unary("X"); return exponent(n1,x).eq(n1).forAll(x.oneOf(UNIV)); } /** * Returns the exponent_identity axiom. * @return exponent_identity */ public final Formula exponentIdentity() { // ! [X] : exponent(X,n1) = X final Variable x = Variable.unary("X"); return exponent(x,n1).eq(x).forAll(x.oneOf(UNIV)); } /** * Returns the exponent_sum_product axiom. * @return exponent_sum_product */ public final Formula exponentSumProduct() { // ! [X,Y,Z] : exponent(X,sum(Y,Z)) = product(exponent(X,Y),exponent(X,Z)) final Variable x = Variable.unary("X"); final Variable y = Variable.unary("Y"); final Variable z = Variable.unary("Z"); return exponent(x,sum(y,z)).eq(product(exponent(x,y),exponent(x,z))). forAll(x.oneOf(UNIV).and(y.oneOf(UNIV)).and(z.oneOf(UNIV))); } /** * Returns the exponent_product_distribution axiom. * @return exponent_product_distribution */ public final Formula exponentProductDistribution() { // ! [X,Y,Z] : exponent(product(X,Y),Z) = product(exponent(X,Z),exponent(Y,Z)) final Variable x = Variable.unary("X"); final Variable y = Variable.unary("Y"); final Variable z = Variable.unary("Z"); return exponent(product(x,y),z).eq( product(exponent(x,z),exponent(y,z)) ). forAll(x.oneOf(UNIV).and(y.oneOf(UNIV)).and(z.oneOf(UNIV))); } /** * Returns the exponent_exponent axiom. * @return exponent_exponent */ public final Formula exponentExponent() { // ! [X,Y,Z] : exponent(exponent(X,Y),Z) = exponent(X,product(Y,Z)) final Variable x = Variable.unary("X"); final Variable y = Variable.unary("Y"); final Variable z = Variable.unary("Z"); return exponent(exponent(x,y),z).eq(exponent(x,product(y,z))). forAll(x.oneOf(UNIV).and(y.oneOf(UNIV)).and(z.oneOf(UNIV))); } /** * Returns the conjuction of all axioms. * @return axioms */ public final Formula axioms() { return decls().and(sumSymmetry()).and(sumAssociativity()).and(productIdentity()). and(productSymmetry()).and(productAssociativity()).and(sumProductDistribution()). and(exponentN1()).and(exponentIdentity()).and(exponentSumProduct()). and(exponentProductDistribution()).and(exponentExponent()); } /** * Returns the wilkie conjecture. * @return wilkie */ public final Formula wilkie() { // ! [C,P,Q,R,S,A,B] : // ( ( C = product(A,A) // & P = sum(n1,A) // & Q = sum(P,C) // & R = sum(n1,product(A,C)) // & S = sum(sum(n1,C),product(C,C)) ) // => product(exponent(sum(exponent(P,A),exponent(Q,A)),B),exponent(sum(exponent(R,B),exponent(S,B)),A)) = // product(exponent(sum(exponent(P,B),exponent(Q,B)),A),exponent(sum(exponent(R,A),exponent(S,A)),B)) ) )). 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 Variable s = Variable.unary("S"); final Variable a = Variable.unary("A"); final Variable b = Variable.unary("B"); final Formula f0 = c.eq(product(a,a)); final Formula f1 = p.eq(sum(n1,a)); final Formula f2 = q.eq(sum(p,c)); final Formula f3 = r.eq(sum(n1,product(a,c))); final Formula f4 = s.eq(sum(sum(n1,c),product(c,c))); final Expression e0 = product(exponent(sum(exponent(p,a),exponent(q,a)),b),exponent(sum(exponent(r,b),exponent(s,b)),a)); final Expression e1 = product(exponent(sum(exponent(p,b),exponent(q,b)),a),exponent(sum(exponent(r,a),exponent(s,a)),b)); final Formula f5 = e0.eq(e1); return (f0.and(f1).and(f2).and(f3).and(f4)).implies(f5). forAll(c.oneOf(UNIV).and(p.oneOf(UNIV)).and(q.oneOf(UNIV)). and(r.oneOf(UNIV)).and(s.oneOf(UNIV)).and(a.oneOf(UNIV)).and(b.oneOf(UNIV))); } /** * Returns the conjunction of the axioms and the negation of the hypothesis. * @return axioms() && !wilkie() */ public final Formula checkWilkie() { return axioms().and(wilkie().not()); } /** * Returns the bounds for the given scope. * @return bounds for the given scope */ public final Bounds bounds(int n) { assert n > 0; final List<String> atoms = new ArrayList<String>(n); for(int i = 0; i < n; i++) atoms.add("a"+i); final Universe u = new Universe(atoms); final Bounds b = new Bounds(u); final TupleFactory f = u.factory(); final TupleSet all3 = f.allOf(3); b.bound(sum, all3); b.bound(product, all3); b.bound(exponent, all3); b.bound(n1, f.allOf(1)); return b; } private static void usage() { System.out.println("java examples.tptp.NUM374 [univ size]"); System.exit(1); } /** * Usage: java examples.tptp.NUM374 [univ size] */ public static void main(String[] args) { if (args.length < 1) usage(); try { final int n = Integer.parseInt(args[0]); if (n < 1) usage(); final NUM374 model = new NUM374(); final Solver solver = new Solver(); solver.options().setSolver(SATFactory.MiniSat); solver.options().setSymmetryBreaking(n*n); final Formula f = model.checkWilkie(); final Bounds b = model.bounds(n); System.out.println(f); final Solution sol = solver.solve(f, b); System.out.println(sol); } catch (NumberFormatException nfe) { usage(); } } }