Commit af9e6806 authored by Christian Müller's avatar Christian Müller

interpolation and stuff

parent aa3504e5
...@@ -198,7 +198,7 @@ object Encoding extends LazyLogging { ...@@ -198,7 +198,7 @@ object Encoding extends LazyLogging {
val MAXINVLENGTH = 1200 val MAXINVLENGTH = 1200
def toDot(g: WorkflowGraph)(labels:Map[Encoding.WorkflowGraph#NodeT, String], edges:Set[g.EdgeT]) = { def toDot(g: WorkflowGraph)(labels:Map[Int, String], edges:Set[g.EdgeT]) = {
val root = DotRootGraph( val root = DotRootGraph(
directed = true, directed = true,
id = Some("Invariant Labelling")) id = Some("Invariant Labelling"))
...@@ -225,7 +225,7 @@ object Encoding extends LazyLogging { ...@@ -225,7 +225,7 @@ object Encoding extends LazyLogging {
} }
} }
def nodeTransformer(innerNode: WorkflowGraph#NodeT): Option[(DotGraph, DotNodeStmt)] = { def nodeTransformer(innerNode: WorkflowGraph#NodeT): Option[(DotGraph, DotNodeStmt)] = {
val str = labels(innerNode) val str = labels(innerNode.value)
val label = if (str.length() > MAXINVLENGTH) str.substring(0, MAXINVLENGTH) + "..." + s"(${str.length()} characters)" else str val label = if (str.length() > MAXINVLENGTH) str.substring(0, MAXINVLENGTH) + "..." + s"(${str.length()} characters)" else str
Some((root, DotNodeStmt(innerNode.toString, List(DotAttr("label", "Node " + innerNode + ":\n" + label))))) Some((root, DotNodeStmt(innerNode.toString, List(DotAttr("label", "Node " + innerNode + ":\n" + label)))))
} }
......
...@@ -57,7 +57,7 @@ object InvariantCLI extends App with LazyLogging { ...@@ -57,7 +57,7 @@ object InvariantCLI extends App with LazyLogging {
def generate(name: String, spec: Spec, properties: InvProperties) { def generate(name: String, spec: Spec, properties: InvProperties) {
logger.info(s"Encoding Spec:\n$spec") logger.info(s"Encoding Spec:\n$spec")
def invariant = InvariantGenerator.invariantNoninterStubbornSingleBS(spec) def invariant = InvariantGenerator.invariantNoninterSingleBS(spec)
Utils.check(name, "", invariant, spec, properties) Utils.check(name, "", invariant, spec, properties)
} }
......
...@@ -4,10 +4,7 @@ import foltl.FOLTL._ ...@@ -4,10 +4,7 @@ import foltl.FOLTL._
import blocks.Workflow._ import blocks.Workflow._
import Implicits._ import Implicits._
import com.typesafe.scalalogging.LazyLogging import com.typesafe.scalalogging.LazyLogging
import de.tum.workflows.ltl.FOTransformers
import de.tum.workflows.Utils._ import de.tum.workflows.Utils._
import de.tum.workflows.foltl.Stubborn
import de.tum.workflows.foltl.Properties
import java.io.PrintWriter import java.io.PrintWriter
import java.io.File import java.io.File
import de.tum.workflows.blocks.Workflow import de.tum.workflows.blocks.Workflow
...@@ -22,7 +19,7 @@ object MainInvariants extends App with LazyLogging { ...@@ -22,7 +19,7 @@ object MainInvariants extends App with LazyLogging {
logger.info(s"Encoding Spec:\n$spec") logger.info(s"Encoding Spec:\n$spec")
def invariant = def invariant =
InvariantGenerator.invariantNoninterStubbornSingleBS _ InvariantGenerator.invariantNoninterSingleBS _
// InvariantGenerator.invariantNoninterStubbornBS _ // InvariantGenerator.invariantNoninterStubbornBS _
// InvariantChecker.invariantNoninterStubborn _ // InvariantChecker.invariantNoninterStubborn _
// InvariantChecker.invariantAllEqual _ // InvariantChecker.invariantAllEqual _
......
...@@ -3,43 +3,87 @@ package de.tum.workflows ...@@ -3,43 +3,87 @@ package de.tum.workflows
import com.microsoft.z3.Status import com.microsoft.z3.Status
import com.typesafe.scalalogging.LazyLogging import com.typesafe.scalalogging.LazyLogging
import de.tum.workflows.Utils._ import de.tum.workflows.Utils._
import de.tum.workflows.blocks.Spec import de.tum.workflows.blocks.{SimpleBlock, Spec}
import de.tum.workflows.foltl.FOLTL._
import de.tum.workflows.foltl.FOTransformers
import de.tum.workflows.synth.Model
import de.tum.workflows.toz3._ import de.tum.workflows.toz3._
// Labelled Edge to Block
import Implicits._
object MainInvariantsInference extends App with LazyLogging { object MainInvariantsInference extends App with LazyLogging {
def generate(name: String, spec: Spec) { def generate(name: String, spec: Spec) {
logger.info(s"Encoding Spec:\n$spec") logger.info(s"Encoding Spec:\n$spec")
def invariant = def invariant =
InvariantGenerator.invariantNoninterStubbornSingleBS _ InvariantGenerator.invariantNoninterSingleBS _
// InvariantGenerator.invariantNoninterStubbornBS _ // InvariantGenerator.invariantNoninterStubbornBS _
// InvariantChecker.invariantNoninterStubborn _ // InvariantChecker.invariantNoninterStubborn _
// InvariantChecker.invariantAllEqual _ // InvariantChecker.invariantAllEqual _
val props = InvProperties(stubborn = false, eliminateAux = false)
val inv = invariant(spec)
val (res, graph, labels, t) = InvariantChecker.checkInvariantFPHeadLabel(spec, inv, props)
logger.info(s"Invariant was ${if (res) "" else "not "}proven (took $t ms)\n")
logger.info(s"Invariant was ${inv}")
val (res, label, t) = InvariantChecker.checkInvariantFPHeadLabel(spec, invariant(spec), InvProperties(stubborn = false, eliminateAux = false))
val msg = s"Invariant was ${if (res) "" else "not "}proven (took $t ms)\n" logger.info(s"Graph: $graph")
val tar = 0
val headlabel = labels(graph.get(tar))
// Invariant not valid // Invariant not valid
if (!res) { if (!res) {
// Try to break headlabel invariant // Try to break headlabel invariant
val (status, solver) = InvariantChecker.checkOnZ3(label) val (status, solver) = Z3QFree.checkUniversal(headlabel)
if (status == Status.SATISFIABLE) { if (status == Status.SATISFIABLE) {
// Broken, found model // Broken, found model
// logger.info(s"Model:\n${Z3.printModel(solver.getModel())}") // logger.info(s"Model:\n${Z3.printModel(solver.getModel())}")
logger.info(s"Initial State Invariant: ${label}") logger.info(s"State Invariant: ${headlabel}")
val model = Z3QFree.modelFacts(solver.getModel()) val z3model = Z3QFree.modelFacts(solver.getModel())
model foreach { f => logger.info(f.toString()) }
// make facts
// filter only workflow rels
// val relfacts = model
logger.info(s"Z3model: $z3model")
// Not constant val facts = for ((f, b) <- z3model) yield {
val tar = 1 if (b == True) {
f
} else {
Neg(f)
}
}
logger.info(s"Model Facts: ${facts}")
val g = Encoding.toGraph(spec.w) val vars = z3model.flatMap(_._1.freeVars()).distinct
val groupedvars = vars.groupBy { _.typ }
// These should only contain Choice and Oracle predicates
val state = Model.emptystate(spec, groupedvars, props)
val model = Model(groupedvars, And.make(facts), state)
// get outgoing edge
// FIXME: Don't just take head
val edge = graph.get(tar).outgoing.head
val newmodel = Model.warp(And.make(facts), edge, spec, props, model)
logger.info(s"Warped Model: ${newmodel.prettyprint}")
val inv = labels(edge.to)
val neginv = Neg(inv).toNegNf.simplify
// Instantiate inv for given universe
val instInv = FOTransformers.instantiateExistentials(neginv, vars.toSet)
val itp = Z3QFree.interpolate(model.stateFormula(), instInv)
logger.info(s"Interpolant is $itp")
} else { } else {
logger.error("Invariant not valid, but also not satisfiable.") logger.error("Invariant not valid, but also not satisfiable.")
...@@ -49,6 +93,7 @@ object MainInvariantsInference extends App with LazyLogging { ...@@ -49,6 +93,7 @@ object MainInvariantsInference extends App with LazyLogging {
} }
def generateExample(name: String) { def generateExample(name: String) {
logger.info(s"Generating $name") logger.info(s"Generating $name")
val spec = ExampleWorkflows.parseExample(name) val spec = ExampleWorkflows.parseExample(name)
......
...@@ -2,7 +2,7 @@ package de.tum.workflows ...@@ -2,7 +2,7 @@ package de.tum.workflows
import foltl.FOLTL._ import foltl.FOLTL._
import com.typesafe.scalalogging.LazyLogging import com.typesafe.scalalogging.LazyLogging
import de.tum.workflows.ltl.FOTransformers import de.tum.workflows.foltl.FOTransformers
import de.tum.workflows.Utils._ import de.tum.workflows.Utils._
import de.tum.workflows.foltl.Properties import de.tum.workflows.foltl.Properties
import de.tum.workflows.blocks.Spec import de.tum.workflows.blocks.Spec
......
package de.tum.workflows package de.tum.workflows
import com.typesafe.scalalogging._ import com.typesafe.scalalogging._
import blocks._ import blocks._
import de.tum.workflows.foltl.FOLTL import de.tum.workflows.foltl.{FOLTL, FOTransformers, FormulaFunctions}
import de.tum.workflows.foltl.FOLTL._ import de.tum.workflows.foltl.FOLTL._
import de.tum.workflows.foltl.FormulaFunctions._
import de.tum.workflows.foltl.FormulaFunctions
import de.tum.workflows.ltl.FOTransformers
import de.tum.workflows.foltl.Properties._ import de.tum.workflows.foltl.Properties._
import de.tum.workflows.toz3.InvProperties import de.tum.workflows.toz3.InvProperties
object Preconditions extends LazyLogging { object Preconditions extends LazyLogging {
def elaborateSteps(b: SimpleBlock, s: Spec) = { private def elaborateSteps(b: SimpleBlock, s: Spec): List[SimpleBlock] = {
val newsteps = (for (stmt <- b.steps if stmt.tuple.head.typ == s.target.params.head.typ) yield { val newsteps = for (stmt <- b.steps if stmt.tuple.head.typ == s.target.params.head.typ) yield {
val fun = Fun(stmt.fun, stmt.tuple) val fun = Fun(stmt.fun, stmt.tuple)
// TODO // TODO
val guard = Neg(Eq(fun.in(T1), fun.in(T2))) val guard = Neg(Eq(fun.in(T1), fun.in(T2)))
ForallBlock(stmt.tuple, List(Add(guard, INFNAME, List(stmt.tuple.head)))) ForallBlock(stmt.tuple, List(Add(guard, INFNAME, List(stmt.tuple.head))))
}) }
b :: newsteps b :: newsteps
} }
// For oracly blocks, remove O from guard and add to ForallMay choice predicate
def elaborateOraclyBlock(b: SimpleBlock, s: Spec) = { def elaborateOraclyBlock(b: SimpleBlock, s: Spec) = {
if (b.isoracly) { if (b.isoracly) {
val stmt = b.steps.head // can only be one val stmt = b.steps.head // can only be one
...@@ -66,14 +63,14 @@ object Preconditions extends LazyLogging { ...@@ -66,14 +63,14 @@ object Preconditions extends LazyLogging {
}) })
} }
def getUpdate(s:Statement, b:SimpleBlock, choice:Option[Fun], isOracly:Boolean, spec:Spec, properties:InvProperties) = { def getUpdate(s:Statement, b:SimpleBlock, choice:Option[Fun], spec:Spec, properties:InvProperties) = {
// val list = List(s.guard) ++ choice.toList // val list = List(s.guard) ++ choice.toList
// val guard = And.make(list) // val guard = And.make(list)
val first = s.tuple.head val first = s.tuple.head
// Trace related substitution for informedness // Trace related substitution for informedness
val con = if (isOracly) { val con = if (b.isoracly) {
val decl = spec.declass.getOrElse(b.pred.get, (List(), False))._2 val decl = spec.declass.getOrElse(b.pred.get, (List(), False))._2
// FIXME: substitutions? // FIXME: substitutions?
// FIXME: decl in T2? // FIXME: decl in T2?
...@@ -110,29 +107,38 @@ object Preconditions extends LazyLogging { ...@@ -110,29 +107,38 @@ object Preconditions extends LazyLogging {
form form
} }
def elaborate(block: SimpleBlock, spec:Spec, properties:InvProperties) = {
val stepOne = if (!properties.stubborn) elaborateSteps(block, spec) else List(block)
stepOne map { b => elaborateOraclyBlock(b, spec) }
}
def weakestPrecondition(post: Formula, outerb: SimpleBlock, spec: Spec, properties: InvProperties) = { def weakestPrecondition(post: Formula, outerb: SimpleBlock, spec: Spec, properties: InvProperties) = {
val steps = elaborate(outerb, spec, properties)
// elaborate only if non-stubborn // elaborate only if non-stubborn
val steps = if (!properties.stubborn) elaborateSteps(outerb, spec) else List(outerb) // val steps = if (!properties.stubborn) elaborateSteps(outerb, spec) else List(outerb)
val precond = steps.foldRight(post)((b, f) => { val precond = steps.foldRight(post)((b, f) => {
val innerb = if (b.isoracly) { // val innerb = if (b.isoracly) {
elaborateOraclyBlock(b, spec) // elaborateOraclyBlock(b, spec)
} else { // } else {
b // b
} // }
val innerprecond = weakestPreconditionSingle(f, innerb, b.isoracly, spec, properties) val innerprecond = weakestPreconditionSingle(f, b, spec, properties)
innerprecond innerprecond
}) })
precond precond
} }
def weakestPreconditionSingle(f: Formula, b: SimpleBlock, isOracly:Boolean, spec: Spec, properties: InvProperties) = { private def weakestPreconditionSingle(f: Formula, b: SimpleBlock, spec: Spec, properties: InvProperties) = {
val choice = b.pred.map(n => Fun(n, b.agents)) val choice = b.pred.map(n => Fun(n, b.agents))
val updates = for (s <- b.steps) yield { val updates = for (s <- b.steps) yield {
s.fun -> (s.tuple, { s.fun -> (s.tuple, {
getUpdate(s, b, choice, isOracly, spec, properties) getUpdate(s, b, choice, spec, properties)
}) })
} }
...@@ -145,7 +151,7 @@ object Preconditions extends LazyLogging { ...@@ -145,7 +151,7 @@ object Preconditions extends LazyLogging {
removed removed
} }
def abstractPrecondition(f: Formula, b: SimpleBlock, s: Spec, properties: InvProperties) = { def abstractedPrecondition(f: Formula, b: SimpleBlock, s: Spec, properties: InvProperties) = {
val precond = weakestPrecondition(f, b, s, properties) val precond = weakestPrecondition(f, b, s, properties)
// Stubborn agents -> remove trace variable from choice predicate // Stubborn agents -> remove trace variable from choice predicate
......
...@@ -70,7 +70,7 @@ object Utils extends LazyLogging { ...@@ -70,7 +70,7 @@ object Utils extends LazyLogging {
val filenames = s"${name}_$model${if (desc.isEmpty()) "" else s"_$desc"}" val filenames = s"${name}_$model${if (desc.isEmpty()) "" else s"_$desc"}"
// do not blow up the formula with auxilliary elimination // do not blow up the formula with auxilliary elimination
val (res, graph, labelling, provens, dot, time, headlabel) = val (res, graph, labelling, provens, dot, time) =
InvariantChecker.checkInvariantFPLabelling(spec, inv, properties) InvariantChecker.checkInvariantFPLabelling(spec, inv, properties)
for ((s, i) <- dot.zipWithIndex) { for ((s, i) <- dot.zipWithIndex) {
Utils.write(s"${filenames}_$i.dot", s) Utils.write(s"${filenames}_$i.dot", s)
...@@ -80,7 +80,7 @@ object Utils extends LazyLogging { ...@@ -80,7 +80,7 @@ object Utils extends LazyLogging {
} }
val labels = (for ((node, inv) <- labelling.last) yield { val labels = (for ((node, inv) <- labelling.last) yield {
s"Node ${node.value}:\n${inv.pretty()}\n" s"Node ${node}:\n${inv.pretty()}\n"
}).mkString("\n") }).mkString("\n")
Utils.write(s"$filenames.invariants", labels) Utils.write(s"$filenames.invariants", labels)
......
...@@ -40,8 +40,8 @@ case class Spec(w: Workflow, declass: Map[String, (List[Var], Formula)], target: ...@@ -40,8 +40,8 @@ case class Spec(w: Workflow, declass: Map[String, (List[Var], Formula)], target:
def saneoraclestmt(stmt:Statement, frees:List[Var]) = { def saneoraclestmt(stmt:Statement, frees:List[Var]) = {
// Oracle only positive // Oracle only positive
val f = stmt.guard.toNegNf() val f = stmt.guard.toNegNf
val noneg = !(f hasSubFormula { val noneg = !(f.hasSubFormula {
case Neg(f:Fun) if f.isOracle() => true case Neg(f:Fun) if f.isOracle() => true
}) })
val allvars = !(f hasSubFormula { val allvars = !(f hasSubFormula {
...@@ -94,10 +94,17 @@ abstract sealed class SimpleBlock extends Block { ...@@ -94,10 +94,17 @@ abstract sealed class SimpleBlock extends Block {
steps.exists(s => agents.exists(a => !s.tuple.contains(a))) steps.exists(s => agents.exists(a => !s.tuple.contains(a)))
} }
def isoracly = { def isoracly: Boolean = {
steps.exists(_.guard.hasSubFormula { // before transformation
case f:Fun => f.isOracle() val before = steps.exists(s => {
s.guard.hasSubFormula {
case f:Fun => f.isOracle()
}
}) })
// after transformation
val after = pred.exists(name => Fun(name, agents).isOracle())
before || after
} }
} }
......
...@@ -7,24 +7,25 @@ import scala.annotation.tailrec ...@@ -7,24 +7,25 @@ import scala.annotation.tailrec
object FOLTL { object FOLTL {
abstract class Formula { abstract class Formula {
def simplify() = FormulaFunctions.simplify(this) def simplify(): Formula = FormulaFunctions.simplify(this)
def freeVars() = FormulaFunctions.freeVars(this) def freeVars(): Set[Var] = FormulaFunctions.freeVars(this)
def everywhere(trans: PartialFunction[Formula, Formula]) = FormulaFunctions.everywhere(trans, this) def everywhere(trans: PartialFunction[Formula, Formula]): Formula = FormulaFunctions.everywhere(trans, this)
def assumeEmpty(name: String) = FormulaFunctions.assumeEmpty(this, name) def assumeEmpty(name: String): Formula = FormulaFunctions.assumeEmpty(this, name)
def assumeEmpty(names: List[String]) = FormulaFunctions.assumeAllEmpty(this, names) def assumeEmpty(names: List[String]): Formula = FormulaFunctions.assumeAllEmpty(this, names)
def in(name: String) = FormulaFunctions.annotate(this, name) def in(name: String): Formula = FormulaFunctions.annotate(this, name)
def in(name: String, ignore: Set[String]) = FormulaFunctions.annotate(this, name, ignore) def in(name: String, ignore: Set[String]): Formula = FormulaFunctions.annotate(this, name, ignore)
def collect[T](coll: PartialFunction[Formula, List[T]]) = FormulaFunctions.collect(coll, this) def collect[T](coll: PartialFunction[Formula, List[T]]):List[T] = FormulaFunctions.collect(coll, this)
def hasSubFormula(coll: PartialFunction[Formula, Boolean]) = FormulaFunctions.hasSubFormula(coll, this) def hasSubFormula(coll: PartialFunction[Formula, Boolean]):Boolean = FormulaFunctions.hasSubFormula(coll, this)
def opsize() = FormulaFunctions.opsize(this) def opsize(): Int = FormulaFunctions.opsize(this)
def toPrenex() = FormulaFunctions.toPrenex(this) def toPrenex: Formula = FormulaFunctions.toPrenex(this)
def toNegNf() = FormulaFunctions.toNegNf(this) def toNegNf: Formula = FormulaFunctions.toNegNf(this)
def toCNF() = FormulaFunctions.toCNF(this) def toCNF: Formula = FormulaFunctions.toCNF(this)
def isBS() = FormulaFunctions.isBS(this) def isBS: Boolean = FormulaFunctions.isBS(this)
def isQFree: Boolean = FormulaFunctions.isQFree(this)
def removeOTQuantifiers() = FormulaFunctions.removeOTQuantifiers(this)
def parallelRename(vars: List[Var], newvars: List[Var]) = FormulaFunctions.parallelRename(this, vars, newvars) def removeOTQuantifiers(): Formula = FormulaFunctions.removeOTQuantifiers(this)
def parallelRename(vars: List[Var], newvars: List[Var]): Formula = FormulaFunctions.parallelRename(this, vars, newvars)
def bracketed(): String = this match { def bracketed(): String = this match {
case _: BinOp => "(" + this + ")" case _: BinOp => "(" + this + ")"
...@@ -111,7 +112,7 @@ object FOLTL { ...@@ -111,7 +112,7 @@ object FOLTL {
} }
trait Quantifier extends Formula { trait Quantifier extends Formula {
def qmake: (List[Var], Formula) => Quantifier def make: (List[Var], Formula) => Formula
def qname: String def qname: String
def vars: List[Var] def vars: List[Var]
def t: Formula def t: Formula
...@@ -123,20 +124,35 @@ object FOLTL { ...@@ -123,20 +124,35 @@ object FOLTL {
} }
object Quantifier { object Quantifier {
def unapply(q: Quantifier) = Some((q.qmake, q.vars, q.t)) def unapply(q: Quantifier) = Some((q.make, q.vars, q.t))
def make(m: (List[Var], Formula) => Quantifier, l:List[Var], f:Formula) = {
if (l.isEmpty) f else m(l, f)
}
}
object Exists {
def make = Quantifier.make(Exists.apply, _:List[Var], _:Formula)
}
object Forall {
def make = Quantifier.make(Forall.apply, _:List[Var], _:Formula)
}
object ForallOtherThan {
def make(l:List[Var], otherthan:List[Var], f:Formula) = {
if (otherthan.isEmpty || l.isEmpty) { Forall.make(l, f) } else {
ForallOtherThan(l, otherthan, f)
}
}
} }
case class Exists(vars: List[Var], t: Formula) extends Quantifier { case class Exists(vars: List[Var], t: Formula) extends Quantifier {
val qname = "∃" val qname = "∃"
val qmake = Exists.apply val make = Quantifier.make(Exists.apply, _, _)
} }
case class Forall(vars: List[Var], t: Formula) extends Quantifier { case class Forall(vars: List[Var], t: Formula) extends Quantifier {
val qname = "∀" val qname = "∀"
val qmake = Forall.apply val make = Quantifier.make(Forall.apply, _, _)
} }
case class ForallOtherThan(vars: List[Var], otherthan: List[Var], t: Formula) extends Quantifier { case class ForallOtherThan(vars: List[Var], otherthan: List[Var], t: Formula) extends Quantifier {
val qname = "∀" val qname = "∀"
val qmake = ForallOtherThan.apply(_: List[Var], otherthan, _: Formula) val make = ForallOtherThan.apply(_: List[Var], otherthan, _: Formula)
override def toString() = { override def toString() = {
s"$qname ${vars.map(_.withType()).mkString(",")} ∉ {${otherthan.map(_.withType()).mkString(",")}}. ${t.bracketed()}" s"$qname ${vars.map(_.withType()).mkString(",")} ∉ {${otherthan.map(_.withType()).mkString(",")}}. ${t.bracketed()}"
} }
......
package de.tum.workflows.ltl package de.tum.workflows.foltl
import com.typesafe.scalalogging.LazyLogging import com.typesafe.scalalogging.LazyLogging
import de.tum.workflows.Utils
import de.tum.workflows.foltl.FOLTL._ import de.tum.workflows.foltl.FOLTL._
import de.tum.workflows.foltl.FOLTL
import de.tum.workflows.foltl.FormulaFunctions
object FOTransformers extends LazyLogging { object FOTransformers extends LazyLogging {
// Computes all possible tuples of size i // Computes all possible tuples of signature types
def comb[T](types:List[String], universe:Map[String, List[T]]):List[List[T]] = { def comb[T](types:List[String], universe:Map[String, List[T]]):List[List[T]] = {
types match { types match {
case List() => List(List()) case List() => List(List())
...@@ -18,7 +14,7 @@ object FOTransformers extends LazyLogging { ...@@ -18,7 +14,7 @@ object FOTransformers extends LazyLogging {
if (!universe.isDefinedAt(t)) { if (!universe.isDefinedAt(t)) {
logger.error(s"No variable for type $t in the universe.") logger.error(s"No variable for type $t in the universe.")
} }
for (a <- universe(t); s <- subres) yield { for (a <- universe(t); s <- subres) yield {
a :: s a :: s
} }
...@@ -50,7 +46,7 @@ object FOTransformers extends LazyLogging { ...@@ -50,7 +46,7 @@ object FOTransformers extends LazyLogging {
case Quantifier(make, vars, inner) => make(vars.filterNot(bound.contains).distinct, elimSub(inner, bound ++ vars)) case Quantifier(make, vars, inner) => make(vars.filterNot(bound.contains).distinct, elimSub(inner, bound ++ vars))
} }
} }
elimSub(f.toNegNf(), Set()) elimSub(f.toNegNf, Set())
} }
def eliminateAuxiliaryPredicate(f:Formula, AUX:String) = { def eliminateAuxiliaryPredicate(f:Formula, AUX:String) = {
...@@ -108,7 +104,8 @@ object FOTransformers extends LazyLogging { ...@@ -108,7 +104,8 @@ object FOTransformers extends LazyLogging {
(agents, res) (agents, res)
} }
// Instantiate all universals in a E*A* formula
def eliminateUniversals(t: Formula, agents: List[Var]):Formula = { def eliminateUniversals(t: Formula, agents: List[Var]):Formula = {
// if (agents.isEmpty) { // if (agents.isEmpty) {
...@@ -165,13 +162,14 @@ object FOTransformers extends LazyLogging { ...@@ -165,13 +162,14 @@ object FOTransformers extends LazyLogging {
* Resulting formula is in E* with all existentials outermost and in NegNF * Resulting formula is in E* with all existentials outermost and in NegNF
*/ */
def instantiateUniversals(f:Formula) = { def instantiateUniversals(f:Formula) = {
// Check fragment // Check fragment
if (!f.isBS()) { if (!f.isBS) {
logger.error("Trying to instantiate Universals for wrong fragment") logger.error("Trying to instantiate Universals for wrong fragment")
logger.error(s"Formula was $f") logger.error(s"Formula was $f")
} }
val nf = f.toNegNf() val nf = f.toNegNf
val (agents, inner) = FOTransformers.eliminateExistentials(nf) val (agents, inner) = FOTransformers.eliminateExistentials(nf)
val existbound = Exists(agents, inner) val existbound = Exists(agents, inner)
val constants = existbound.freeVars() val constants = existbound.freeVars()
...@@ -184,18 +182,39 @@ object FOTransformers extends LazyLogging { ...@@ -184,18 +182,39 @@ object FOTransformers extends LazyLogging {
* Resulting formula is in NegNF * Resulting formula is in NegNF
*/ */
def abstractExistentials(f:Formula) = { def abstractExistentials(f:Formula) = {
val neg = Neg(f).toNegNf().simplify() val neg = Neg(f).toNegNf.simplify
// Check fragment // Check fragment
if (!neg.isBS()) { if (!neg.isBS) {
logger.warn("Trying to instantiate Existentials for wrong fragment -- Termination not guaranteed") logger.warn("Trying to instantiate Existentials for wrong fragment -- Termination not guaranteed")
// logger.error(s"Formula was $f") // logger.error(s"Formula was $f")
} }
val (agents, inner) = FOTransformers.eliminateExistentials(neg) val (agents, inner) = FOTransformers.eliminateExistentials(neg)
val existbound = Exists(agents, inner) val existbound = Exists(agents, inner)
val constants = neg.freeVars() val constants = neg.freeVars
val res = FOTransformers.eliminateUniversals(existbound, constants.toList) val res = FOTransformers.eliminateUniversals(existbound, constants.toList)
Neg(res).simplify()