/** * Returns all facts in the model. * * @return the facts. */ public final Formula facts() { // sig File extends Object {} { some d: Dir | this in d.entries.contents } final Variable file = Variable.unary("this"); final Variable d = Variable.unary("d"); final Formula f0 = file.in(d.join(entries).join(contents)).forSome(d.oneOf(Dir)).forAll(file.oneOf(File)); // sig Dir extends Object { // entries: set DirEntry, // parent: lone Dir // } { // parent = this.~@contents.~@entries // all e1, e2 : entries | e1.name = e2.name => e1 = e2 // this !in this.^@parent // this != Root => Root in this.^@parent // } final Variable dir = Variable.unary("this"); final Variable e1 = Variable.unary("e1"), e2 = Variable.unary("e2"); final Formula f1 = (dir.join(parent)).eq(dir.join(contents.transpose()).join(entries.transpose())); final Expression e0 = dir.join(entries); final Formula f2 = e1.join(name).eq(e2.join(name)).implies(e1.eq(e2)).forAll(e1.oneOf(e0).and(e2.oneOf(e0))); final Formula f3 = dir.in(dir.join(parent.closure())).not(); final Formula f4 = dir.eq(Root).not().implies(Root.in(dir.join(parent.closure()))); final Formula f5 = f1.and(f2).and(f3).and(f4).forAll(dir.oneOf(Dir)); // one sig Root extends Dir {} { no parent } final Formula f6 = Root.join(parent).no(); // sig DirEntry { // name: Name, // contents: Object // } { one this.~entries } final Variable entry = Variable.unary("this"); final Formula f7 = entry.join(entries.transpose()).one().forAll(entry.oneOf(DirEntry)); // fact OneParent { // // all directories besides root xhave one parent // all d: Dir - Root | one d.parent // } final Formula f8 = d.join(parent).one().forAll(d.oneOf(Dir.difference(Root))); return f0.and(f5).and(f6).and(f7).and(f8); }
/** * 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); }