abstract sig Formula {
-- Trick: formulas carry which instances
-- make them true.
eval: set Instance
}
sig Var extends Formula {} {
eval = {i: Instance | this in i.val}
}
sig Not extends Formula {
child: Formula
} {
eval = Instance - child.@eval
}
/*
fact notEval {
all n: Not |
n.eval = Instance - n.child.eval
}*/
sig And extends Formula {
left, right: Formula
} {
eval = left.@eval & right.@eval
}
sig Or extends Formula {
left, right: Formula
} {
eval = left.@eval + right.@eval
}
fun subformulas[f: Formula]: set Formula {
f.^(child + (And <: left) + (Or <: left)
+ (And <: right) + (Or <: right))
}
fact acyclic {
all f: Formula | {
f not in subformulas[f]
}
}
run {#Var > 2} for 5 Formula, 4 Instance, 4 int
-- Syntax
-----------------------------------------
-- Semantics
sig Instance {
val: set Var
}
-- Sadly, this won't work in Alloy.
-- We get no recursion!
/*
fun eval[f: Formula, i: Instance]: Bool {
if f in Var => f in i.val
if f in Not => not eval[f.child, i]
if f in And => ...
}
*/