Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Christian Müller
NIWO
Commits
71ff4192
Commit
71ff4192
authored
Nov 16, 2017
by
Christian Müller
Browse files
fix, better simplifier
parent
64d2a9a9
Changes
8
Hide whitespace changes
Inline
Side-by-side
build.sbt
View file @
71ff4192
...
...
@@ -10,7 +10,7 @@ libraryDependencies ++= Seq(
"com.typesafe.scala-logging"
%%
"scala-logging"
%
"3.5.0"
,
"ch.qos.logback"
%
"logback-classic"
%
"1.1.7"
,
"org.scalactic"
%%
"scalactic"
%
"3.0.4"
,
"org.scalatest"
%%
"scalatest"
%
"3.0.4"
%
"test"
,
"org.scalatest"
%%
"scalatest"
%
"3.0.4"
,
"org.scala-graph"
%%
"graph-core"
%
"1.12.1"
,
"org.scala-graph"
%%
"graph-dot"
%
"1.12.1"
,
"org.scala-lang.modules"
%%
"scala-parser-combinators"
%
"1.0.5"
...
...
src/main/scala/de/tum/workflows/MainInvariants.scala
View file @
71ff4192
...
...
@@ -57,7 +57,7 @@ object MainInvariants extends App with LazyLogging {
}
clear
()
generateExample
(
"nonomitting/conference"
)
//
generateExample("tests/
declasstest
")
//
generateExample("nonomitting/conference")
generateExample
(
"tests/
loopexampleNoOracle
"
)
// generateAllExamples()
}
\ No newline at end of file
src/main/scala/de/tum/workflows/foltl/FOLTLTermFunctions.scala
View file @
71ff4192
...
...
@@ -50,8 +50,22 @@ object FormulaFunctions extends LazyLogging {
case
And
(
t
,
False
)
=>
False
case
And
(
True
,
t
)
=>
t
case
And
(
t
,
True
)
=>
t
case
Implies
(
False
,
t
)
=>
True
case
Implies
(
True
,
t
)
=>
t
// left-trees
case
And
(
And
(
t1
,
t2
),
t3
)
=>
And
(
t1
,
And
(
t2
,
t3
))
case
Or
(
Or
(
t1
,
t2
),
t3
)
=>
Or
(
t1
,
Or
(
t2
,
t3
))
// case Or(t1, Neg(t2)) if t1 == t2 => True
// equal things in tree
case
And
(
t1
,
t2
)
if
t1
==
t2
=>
t1
case
Or
(
t1
,
t2
)
if
t1
==
t2
=>
t1
case
And
(
t1
,
And
(
t2
,
t3
))
if
(
t1
==
t2
)
=>
And
(
t1
,
t3
)
case
And
(
t1
,
And
(
t2
,
t3
))
if
(
t1
==
t3
)
=>
And
(
t1
,
t2
)
case
Or
(
t1
,
Or
(
t2
,
t3
))
if
(
t1
==
t2
)
=>
Or
(
t1
,
t3
)
case
Or
(
t1
,
Or
(
t2
,
t3
))
if
(
t1
==
t3
)
=>
Or
(
t1
,
t2
)
// case Or(t1, Neg(t2)) if t1 == t2 => True
// Equivalence
case
Eq
(
t1
,
t2
)
if
t1
==
t2
=>
True
...
...
@@ -64,6 +78,12 @@ object FormulaFunctions extends LazyLogging {
case
Quantifier
(
_
,
xs
,
t
)
if
xs
.
isEmpty
=>
t
case
Quantifier
(
_
,
_
,
True
)
=>
True
case
Quantifier
(
_
,
_
,
False
)
=>
False
// Quantifiers binding same things
case
And
(
Forall
(
vars1
,
t1
),
Forall
(
vars2
,
t2
))
if
(
vars1
==
vars2
)
=>
Forall
(
vars1
,
And
(
t1
,
t2
))
case
Or
(
Forall
(
vars1
,
t1
),
Forall
(
vars2
,
t2
))
if
(
vars1
==
vars2
)
=>
Forall
(
vars1
,
Or
(
t1
,
t2
))
case
And
(
Exists
(
vars1
,
t1
),
Exists
(
vars2
,
t2
))
if
(
vars1
==
vars2
)
=>
Exists
(
vars1
,
And
(
t1
,
t2
))
case
Or
(
Exists
(
vars1
,
t1
),
Exists
(
vars2
,
t2
))
if
(
vars1
==
vars2
)
=>
Exists
(
vars1
,
Or
(
t1
,
t2
))
// Gobble up equal quantifiers
case
Forall
(
vars1
,
Forall
(
vars2
,
f
))
=>
Forall
(
vars1
++
vars2
,
f
)
...
...
@@ -84,13 +104,13 @@ object FormulaFunctions extends LazyLogging {
if
(
t
==
t1
)
t1
else
simplify
(
t1
)
}
def
eliminateImplication
(
f
:
Formula
)
:
Formula
=
{
def
eliminateImplication
(
f
:
Formula
)
:
Formula
=
{
f
everywhere
{
case
Implies
(
f1
,
f2
)
=>
Or
(
Neg
(
eliminateImplication
(
f1
)),
eliminateImplication
(
f2
))
}
}
def
eliminateEq
(
f
:
Formula
)
:
Formula
=
{
def
eliminateEq
(
f
:
Formula
)
:
Formula
=
{
f
everywhere
{
case
Eq
(
f1
,
f2
)
=>
{
val
e1
=
eliminateEq
(
f1
)
...
...
@@ -148,25 +168,25 @@ object FormulaFunctions extends LazyLogging {
case
x
=>
List
.
empty
}
}
def
hasSubFormula
(
coll
:
PartialFunction
[
Formula
,
Boolean
],
t
:
Formula
)
=
{
def
or
(
bs
:
Boolean*
)
=
{
bs
.
exists
(
identity
)
}
def
or
(
bs
:
Boolean*
)
=
{
bs
.
exists
(
identity
)
}
collect
(
or
)(
coll
,
t
)
}
// def hasSubFormula(check: (Formula => Boolean), t: Formula): Boolean = {
// if (check(t)) {
// true
// } else {
// t match {
// // Extractors
// case Quantifier(make, ps, t) => hasSubFormula(check, t)
// case UnOp(make, t) => hasSubFormula(check, t)
// case BinOp(make, t1, t2) => hasSubFormula(check, t1) || hasSubFormula(check, t2)
// case x => false
// }
// }
// }
// def hasSubFormula(check: (Formula => Boolean), t: Formula): Boolean = {
// if (check(t)) {
// true
// } else {
// t match {
// // Extractors
// case Quantifier(make, ps, t) => hasSubFormula(check, t)
// case UnOp(make, t) => hasSubFormula(check, t)
// case BinOp(make, t1, t2) => hasSubFormula(check, t1) || hasSubFormula(check, t2)
// case x => false
// }
// }
// }
def
assumeEmpty
(
t
:
Formula
,
name
:
String
)
=
{
t
.
everywhere
({
...
...
@@ -186,8 +206,8 @@ object FormulaFunctions extends LazyLogging {
case
Fun
(
f
,
None
,
xs
)
=>
Fun
(
f
,
Some
(
name
),
xs
)
})
}
def
annotateOverwrite
(
t
:
Formula
,
Name1
:
String
,
name
:
String
)
=
{
def
annotateOverwrite
(
t
:
Formula
,
Name1
:
String
,
name
:
String
)
=
{
t
.
everywhere
({
case
Fun
(
f
,
Some
(
Name1
),
xs
)
=>
Fun
(
f
,
Some
(
name
),
xs
)
})
...
...
@@ -265,9 +285,9 @@ object FormulaFunctions extends LazyLogging {
val
q1
=
collectQuantifiersSub
(
f1
)
val
q2
=
collectQuantifiersSub
(
f2
)
// Merge while trying to stay in BS, if possible
// Merge while trying to stay in BS, if possible
// TODO: could be improved to minimize quantifier alternations)
// TODO: merge universals with same type by renaming
// TODO: merge universals with same type by renaming
val
ex1
=
q1
.
takeWhile
(
_
.
_1
)
val
rest1
=
q1
.
drop
(
ex1
.
size
)
...
...
@@ -294,7 +314,7 @@ object FormulaFunctions extends LazyLogging {
// logger.info(s"Formula binds variables more than once - renaming bindings: ${f.pretty}")
FormulaFunctions
.
fixBinding
(
f
,
Set
()).
_1
}
else
f
val
noeq
=
eliminateEq
(
bound
)
eliminateImplication
(
noeq
).
simplify
()
}
...
...
@@ -365,47 +385,47 @@ object FormulaFunctions extends LazyLogging {
// normalized is now Quantifiers, then only And/Or with Negation inside
toCNFSub
(
normalized
)
}
/**
* Resolves a universally quantified predicate
* Blows up the formula linearly due to CNF
*/
def
eliminatePredicate
(
f
:
Formula
,
name
:
String
)
=
{
def
listFunsWithName
(
f
:
Formula
,
name
:
String
)
=
{
def
eliminatePredicate
(
f
:
Formula
,
name
:
String
)
=
{
def
listFunsWithName
(
f
:
Formula
,
name
:
String
)
=
{
f
.
collect
({
case
Fun
(
n
,
ind
,
vars
)
if
n
==
name
=>
List
((
Some
(
Fun
(
n
,
ind
,
vars
)),
None
))
case
Fun
(
n
,
ind
,
vars
)
if
n
==
name
=>
List
((
Some
(
Fun
(
n
,
ind
,
vars
)),
None
))
case
Neg
(
Fun
(
n
,
ind
,
vars
))
if
n
==
name
=>
List
((
None
,
Some
(
Neg
(
Fun
(
n
,
ind
,
vars
)))))
})
}
val
norm
=
f
.
toCNF
()
val
removed
=
norm
.
everywhere
({
// find top-level ORs in CNF
case
inner
:
Or
=>
{
case
inner
:
Or
=>
{
val
list
=
listFunsWithName
(
inner
,
name
)
val
positives
=
list
.
map
(
_
.
_1
).
flatten
val
negatives
=
list
.
map
(
_
.
_2
).
flatten
val
isSuperFluous
=
positives
.
exists
{
f1
=>
val
isSuperFluous
=
positives
.
exists
{
f1
=>
negatives
.
exists
{
f2
=>
Neg
(
f1
)
==
f2
}
}
if
(
isSuperFluous
)
{
// Remove clause
True
}
else
{
// Remove predicate both in positive and negative
inner
.
everywhere
({
inner
.
everywhere
({
case
Neg
(
Fun
(
n
,
ind
,
vars
))
if
n
==
name
=>
False
case
Fun
(
n
,
ind
,
vars
)
if
n
==
name
=>
False
case
Fun
(
n
,
ind
,
vars
)
if
n
==
name
=>
False
})
}
}
})
removed
.
simplify
()
}
}
\ No newline at end of file
src/main/scala/de/tum/workflows/ltl/LTL.scala
View file @
71ff4192
...
...
@@ -83,6 +83,9 @@ object LTL extends LazyLogging {
}
t
.
everywhere
({
case
Exists
(
tup
,
term
)
=>
{
Exists
(
tup
,
eliminateUniversals
(
term
,
agents
++
tup
))
}
case
Forall
(
tup
,
term
)
=>
{
instantiate
(
tup
,
term
,
universe
)
}
...
...
@@ -122,14 +125,21 @@ object LTL extends LazyLogging {
}
/**
* Instantiates
inner E
xistentials in AE formulae.
*
Does not change quantifier structure, but returns
formula in NegNF
* Instantiates
e
xistentials in AE formulae.
*
Resulting
formula
is
in NegNF
*/
def
instantiateInnerExistentials
(
f
:
Formula
)
=
{
val
neg
=
Neg
(
f
).
toNegNf
()
def
instantiateExistentials
(
f
:
Formula
)
=
{
val
neg
=
Neg
(
f
).
toNegNf
().
simplify
()
// Check fragment
if
(!
neg
.
isBS
())
{
logger
.
error
(
"Trying to instantiate Existentials for wrong fragment"
)
logger
.
error
(
s
"Formula was $f"
)
}
val
res
=
instantiateUniversals
(
neg
)
Neg
(
res
).
toNegNf
()
// val (agents, inner) = LTL.eliminateExistentials(nf)
// val existbound = Exists(agents, inner)
val
res
=
LTL
.
eliminateUniversals
(
neg
,
List
())
Neg
(
res
).
simplify
()
}
}
\ No newline at end of file
src/main/scala/de/tum/workflows/toz3/InvariantChecker.scala
View file @
71ff4192
...
...
@@ -33,16 +33,12 @@ object InvariantChecker extends LazyLogging {
// val s = ctx.mkSolver(t)
val
s
=
ctx
.
mkSolver
()
// Make QFree - will work for any A* or A*E* formula
val
tocheck
=
Neg
(
f
).
simplify
()
if
(!
tocheck
.
isBS
())
{
logger
.
error
(
s
"Not in BS: ${tocheck.pretty}"
)
}
val
univfree
=
LTL
.
instantiateUniversals
(
tocheck
)
// Can only check universal things
val
neg
=
Neg
(
f
).
simplify
()
// univfree is now in E*, so can be solved as SAT Problem
val
stripped
=
FormulaFunctions
.
stripQuantifiers
(
univfree
)
val
stripped
=
FormulaFunctions
.
stripQuantifiers
(
neg
)
// val prefix = FormulaFunctions.collectQuantifiersSub(univfree)
val
satform
=
LTL
.
eliminatePredicates
(
stripped
)
...
...
@@ -122,9 +118,16 @@ object InvariantChecker extends LazyLogging {
// check if relabelled invariant still satisfiable
// never relabel initial node
if
(!
isfirst
)
{
val
newinv
=
And
(
labels
(
next
.
_1
),
Preconditions
.
weakestPrecondition
(
post
,
next
))
val
(
status2
,
solver2
)
=
checkOnZ3
(
Implies
(
newinv
,
False
))
val
newinv
=
And
(
labels
(
next
.
_1
),
Preconditions
.
weakestPrecondition
(
post
,
next
)).
simplify
()
// Abstract away inner existentials
val
universalinv
=
LTL
.
instantiateExistentials
(
newinv
).
simplify
()
// TODO: Abstract away auxilliaries
val
(
status2
,
solver2
)
=
checkOnZ3
(
Implies
(
universalinv
,
False
))
// FIXME breaks if universalinv is used
val
newlabels
=
labels
.
updated
(
next
.
_1
,
newinv
)
val
invalidated
=
proven
.
filter
(
_
.
_2
==
next
.
_1
)
...
...
@@ -146,8 +149,8 @@ object InvariantChecker extends LazyLogging {
}
}
// create labelling
val
labels
=
(
for
(
n
<-
graph
.
nodes
)
yield
{
n
->
inv
})
toMap
// create labelling
- FIXME: maybe use inv only for last
val
labels
=
(
for
(
n
<-
graph
.
nodes
)
yield
{
n
->
inv
})
.
toMap
val
(
result
,
afterlabels
,
proven
)
=
checkInvariantRec
(
labels
,
Set
())
val
dot
=
Encoding
.
toDot
(
graph
)(
afterlabels
.
map
(
t
=>
(
t
.
_1
,
t
.
_2
.
pretty
())),
proven
)
...
...
src/test/scala/de/tum/workflows/ltl/tests/FOLTLTest.scala
View file @
71ff4192
...
...
@@ -27,6 +27,11 @@ class FOLTLTest extends FlatSpec {
)
}
"Simplification"
should
"simplify equal things"
in
{
val
t
=
Forall
(
"x"
,
Fun
(
"S"
,
"x"
))
And
(
t
,
t
).
simplify
()
should
be
(
t
)
}
"Parallel rename"
should
"work on simple functions"
in
{
val
f
=
And
(
"a"
,
Fun
(
"f"
,
List
(
"b"
,
"a"
)))
...
...
src/test/scala/de/tum/workflows/ltl/tests/LTLTests.scala
View file @
71ff4192
...
...
@@ -22,7 +22,7 @@ class LTLSpec extends FlatSpec {
LTL
.
eliminateUniversals
(
f
,
List
(
"a"
))
should
be
(
Globally
(
Fun
(
"f"
,
List
(
"a"
,
"a"
))))
val
f2
=
Exists
(
"x"
,
Forall
(
List
(
"y"
),
Fun
(
"f"
,
List
(
"x"
,
"y"
))))
LTL
.
eliminateUniversals
(
f2
,
List
(
"a"
))
should
be
(
Exists
(
"x"
,
Fun
(
"f"
,
List
(
"x"
,
"
a
"
))))
LTL
.
eliminateUniversals
(
f2
,
List
())
should
be
(
Exists
(
"x"
,
Fun
(
"f"
,
List
(
"x"
,
"
x
"
))))
val
f3
=
Forall
(
List
(
"x"
,
"y"
),
Fun
(
"f"
,
List
(
"x"
,
"y"
)))
val
r
=
"""
...
...
@@ -69,7 +69,7 @@ class LTLSpec extends FlatSpec {
"Existential Elimination"
should
"work in AE formulae"
in
{
val
f
=
Forall
(
List
(
"x"
,
"y"
),
Exists
(
"z"
,
Fun
(
"f"
,
List
(
"x"
,
"z"
))))
LTL
.
instantiate
Inner
Existentials
(
f
)
should
be
(
LTL
.
instantiateExistentials
(
f
)
should
be
(
Forall
(
List
(
"x"
,
"y"
),
Or
(
Fun
(
"f"
,
List
(
"x"
,
"x"
)),
Fun
(
"f"
,
List
(
"x"
,
"y"
))))
)
}
...
...
src/test/scala/de/tum/workflows/ltl/tests/Z3Test.scala
View file @
71ff4192
...
...
@@ -202,7 +202,7 @@ class Z3Test extends FlatSpec with LazyLogging with BeforeAndAfterEach {
check
(
s
,
Status
.
SATISFIABLE
)
}
it
should
"check tests/fixedarity5 (nonomitting, stubborn) as LTL prop"
i
n
{
it
should
"check tests/fixedarity5 (nonomitting, stubborn) as LTL prop"
i
gnore
{
val
s
=
checkNonOmittingWF
(
ExampleWorkflows
.
parseExample
(
"tests/fixedarity5"
).
get
)
check
(
s
,
Status
.
SATISFIABLE
)
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment