Using Leo II to prove Theorems in Frobenius Algebras - z3

Using the ATP Leo II with the TPTP thf language it is possible to prove many theorems in Frobenius algebras and open-closed cobordisms. I an using the following code
thf(alpha_decl,type,(alpha: $aaxa > $axaa)).
thf(invalpha_decl,type,(invalpha: $axaa > $aaxa )).
thf(mu_decl,type,(mu: $aa > $a )).
thf(eta_decl,type,(eta: $i > $a )).
thf(muid_decl,type,(muid: $aaxa > $aa )).
thf(idmu_decl,type,(idmu: $axaa > $aa )).
thf(etaid_decl,type,(etaid: $ja > $aa )).
thf(ideta_decl,type,(ideta: $ai > $aa )).
thf(lamb_decl,type,(lamb: $ja > $a )).
thf(rho_decl,type,(rho: $ai > $a )).
thf(delta_decl,type,(delta: $a > $aa )).
thf(deltaid_decl,type,(deltaid: $aa > $aaxa )).
thf(iddelta_decl,type,(iddelta: $aa > $axaa )).
thf(epsilon_decl,type,(epsilon: $a > $i )).
thf(invlamb_decl,type,(invlamb: $a > $ja )).
thf(invrho_decl,type,(invrho: $a > $ai )).
thf(epsilonid_decl,type,(epsilonid: $aa > $ja )).
thf(idepsilon_decl,type,(idepsilon: $aa > $ai )).
thf(id_decl,type,(id: $a > $a )).
thf(beta1_decl,type,( beta1: $a > $ai )).
thf(beta2_decl,type,(beta2: $a > $ja )).
thf(invbeta1_decl,type,(invbeta1: $ai > $a )).
thf(invbeta2_decl,type,(invbeta2: $ja > $a )).
thf(axio1,axiom,(! [X: $ja] :
( (lamb # X) = (mu # (etaid # X ) ) ) )).
thf(axio2,axiom,(! [X: $ai] :
( (rho # X) = (mu # (ideta # X ) ) ) )).
thf(axio3,axiom,(! [X: $aaxa] :
( (mu # (idmu # (alpha # X)) ) = (mu # (muid # X) ) ) )).
thf(axio4,axiom,(! [X: $a] :
( (iddelta # (delta # X) ) = (alpha # (deltaid # (delta # X)) ) ) )).
thf(axio5,axiom,(! [X: $a] :
( (epsilonid # (delta # X) ) = (invlamb # X ) ) )).
thf(axio6,axiom,(! [X: $a] :
( (idepsilon # (delta # X) ) = (invrho # X ) ) )).
thf(axio7,axiom,(! [X: $aa] :
( (muid # (invalpha # (iddelta # X)) ) = (delta # (mu # X)) ) )).
thf(axio8,axiom,(! [X: $aa] :
( (idmu # (alpha # (deltaid # X)) ) = (delta # (mu # X)) ) )).
thf(axio9,axiom,(! [X: $a] :
( (mu # (ideta # (beta1 # X)) ) = (id # X) ) )).
thf(axio10,axiom,(! [X: $a] :
( (mu # (etaid # (beta2 # X)) ) = (id # X) ) )).
thf(axio11,axiom,(! [X: $a] :
( (invbeta1 # (idepsilon # (delta # X)) ) = (id # X) ) )).
thf(axio12,axiom,(! [X: $a] :
( (invbeta2 # (epsilonid # (delta # X)) ) = (id # X) ) )).
thf(axio13,axiom,(! [X: $a] :
( (id # (id # X) ) = (id # X) ) )).
thf(axio14,axiom,(! [X: $a] :
( (delta # (id # X) ) = (delta # X) ) )).
For example it is possible to prove that
using the previous code with the following sentences
thf(conj,conjecture,(! [X: $ja] :
( (idepsilon # (idmu # (alpha # (deltaid # (etaid # X))) ) ) =
(idepsilon # (delta # (mu # (etaid # X))))
) )).
thf(conj2,conjecture,(! [X: $a] :
( (invbeta1 # (idepsilon # (delta # (mu # (etaid # (beta2 # X)))) ) ) =
(id # X)
) )).
thf(conj3,conjecture,(! [X: $ai] :
( (epsilonid # (muid # (invalpha # (iddelta # (ideta # X))) ) ) =
(epsilonid # (delta # (mu # (ideta # X))))
) )).
thf(conj4,conjecture,(! [X: $a] :
( (invbeta2 # (epsilonid # (delta # (mu # (ideta # (beta1 # X)))) ) ) =
(id # X)
) )).
and the output that Leo II generates is
% END OF SYSTEM OUTPUT
% RESULT: SOT_RS_aB8 - LEO-II---1.6.2 says Theorem - CPU = 0.05 WC = 0.17
% OUTPUT: SOT_RS_aB8 - LEO-II---1.6.2 says CNFRefutation - CPU = 0.05 WC = 0.17
My questions is: How to extract a proof for humans from the output of Leo II using sledgehammer?
Please take a look at Frobenius algebras with Z3

Related

Multiset proof verification in dafny

I'm trying to prove a little lemma for a larger proof, the lemma definition is below:
lemma LoopLemma(a: seq<int>, b: seq<int>, c: seq<int>, k:int, i:int, j:int)
requires 0 <= i < |a| && 0<= j < |b| && 0 <= k < |c| && i +j ==k && |a| + |b| == |c|
requires Sorted(c[..k]) && Sorted(b) && Sorted(a)
requires multiset(c[..k]) == multiset(a[..i]+b[..j])
ensures Sorted(c[..k]+[b[j]]) && Sorted(c[..k]+[a[i]])
{
assert multiset(c[..k]) == multiset(a[..i]+b[..j]);
var q:=a[..i]+b[..j];
var c1 := c[..k];
assert Sorted(c1);
assert multiset(c1) == multiset(q);
assert |q| == i + j;
assert |c1| == k == i + j;
calc {
multiset(c1) == multiset(q);
==
forall l :: l in multiset(c1) ==> l in multiset(q);
== {assert forall l :: l in multiset(q) ==> exists r :: 0 <= r <|q| && l == q[r]; assert forall l :: l in multiset(c1) ==> exists r :: 0 <= r <|c1| && l == c1[r];}
forall l :: 0<=l <|c1| ==> exists r :: 0 <= r < |q| && q[r] == c1[l];
}
}
I get "the calculation step between the previous line and this line might not hold" for the last step, and I don't understand why.
All I'm saying there is that if the multisets of two sequences are equal, for any entry in the first sequence exists an entry in the second sequence with the same value.
I tried some simpler examples (where I define the sequences explicitly) and it worked. Maybe I don't understand something about multisets?
Any suggestions will help.
Additional hint that needed here is every element in sequence is in multiset i.e forall i :: 0 <= i < |c[..k]| ==> c[..k][i] in multiset(c[..k]) (hint in forward direction of reasoning). Following snippet verifies.
predicate Sorted(a: seq<int>)
{
if |a| <= 1 then true else (a[0] <= a[1]) && Sorted(a[1..])
}
lemma LoopLemma(a: seq<int>, b: seq<int>, c: seq<int>, k: int, i: int, j: int)
requires 0 <= i < |a| && 0 <= j < |b| && 0 <= k < |c| && i + j == k && |a| + |b| == |c|
requires Sorted(c[..k]) && Sorted(a) && Sorted(b)
requires multiset(c[..k]) == multiset(a[..i] + b[..j])
{
var s := a[..i] + b[..j];
calc {
multiset(c[..k]) == multiset(s);
forall e :: e in multiset(c[..k]) ==> e in multiset(s);
{
assert forall e :: e in multiset(c[..k]) ==>
exists r :: 0 <= r < |s| && s[r] == e;
// assert forall e :: e in multiset(c[..k]) ==>
// exists r :: 0 <= r < |c[..k]| && c[..k][r] == e;
assert forall i :: 0 <= i < |c[..k]| ==> c[..k][i] in multiset(c[..k]);
}
forall i :: 0 <= i < |c[..k]| ==> exists r :: 0 <= r < |s| && s[r] == c[..k][i];
}
}

Finding counterexamples for a "Horn" solver object

I'm trying to learn how to write code for giving a counterexample to a horn clause and it's guessed interpretation. In the below code, let I be the uninterpreted function (it's a trivial loop invariant). The first 3 s.add() add the condition requirements for I(x), and the fourth one is a guess candidate for I. I try to use the s.prove directive to get a counterexample to my guessed candidate for I. I seem to be getting a huge error log on running this code, could anyone tell me what's wrong?
s = SolverFor("HORN")
I = Function('I', IntSort(), BoolSort())
x, x2 = Ints('x x2')
s.set("produce-proofs", True)
s.add( ForAll( [x] ,Implies( x == 0 , I(x))) )
s.add( ForAll( [x, x2] , Implies ( And( I(x), x2 == x + 1 , x < 5) , I(x2) ) ) )
s.add( ForAll( [x] ,Implies( And( I(x), Not(x < 5) ) , x == 5 ) ) )
s.add( ForAll( [x], And( Implies( I(x) , (x == 2) ), Implies( (x == 2) , I(x) ) ) ) ) #Adding guessed invariant here!
assert unsat == s.check()
print(s.proof())
You've a couple of mistakes in the script; perhaps this dates back from a while ago with a different version of z3? In any case, the following goes through with z3 version 4.8.14:
from z3 import *
s = SolverFor("HORN")
I = Function('I', IntSort(), BoolSort())
x, x2 = Ints('x x2')
s.set("proof", True)
s.add( ForAll( [x] ,Implies( x == 0 , I(x))) )
s.add( ForAll( [x, x2] , Implies ( And( I(x), x2 == x + 1 , x < 5) , I(x2) ) ) )
s.add( ForAll( [x] ,Implies( And( I(x), Not(x < 5) ) , x == 5 ) ) )
s.add( ForAll( [x], And( Implies( I(x) , (x == 2) ), Implies( (x == 2) , I(x) ) ) ) ) #Adding guessed invariant here!
print(s.check())
Unfortunately it prints:
unknown
This means the solver wasn't able to determine if the input is satisfiable or not; it gave up and said unknown. An earlier version of the solver might've been able to solve this successfully, providing an unsatisfiability proof, or a model should it be satisfiable.
I recommend tracking down where you got this example from and find out which version of z3 they were using. Going back to that version might help you make progress. Or, if you think the problem should be solvable as is, you can file a bug report at https://github.com/Z3Prover/z3/issues

Does Gforth optimize proper tail calls?

I have the following (somewhat inefficient) code:
\ RNG support
VARIABLE seed
: rand ( -- random )
seed #
DUP 13 LSHIFT XOR
DUP 17 RSHIFT XOR
DUP 5 LSHIFT XOR
DUP seed ! ;
\ Checker for number of set bits
: clear-lsb ( u -- u )
DUP 1- AND ;
: under++ ( u x -- u++ x )
SWAP 1+ SWAP ;
: ones-rec ( c u -- c u | c )
?DUP ( c 0 | c u u )
0<> IF EXIT ( c | c u )
THEN under++ clear-lsb RECURSE ;
: ones-rec ( c u -- c u | c )
?DUP IF
under++ clear-lsb
RECURSE
THEN ;
: ones ( u -- n )
0 SWAP ones-rec ;
\ Makes a random number with n set bits
: rand-n-bits ( n -- random )
rand ( n random )
OVER SWAP ( n n random )
ones ( n n bits )
= ( n f )
IF EXIT
THEN RECURSE ;
By my understanding, both the RECURSEs in rand-n-bits and ones-rec should be proper tail calls. However, when I ask Gforth to do 10 rand-n-bits, I overflow the return stack. Does Gforth not optimize proper tail calls, or am I simply not doing this correctly?

What are some basic modulo arithmetic rules?

Let a = 10^18 and b = 10 ^ 18. c = 1 to 100000
I want to find ( a + b ) % c or ( a * b ) % c
I need to prevent integer overflow. How can I do so?
(x * y) % k = ((x % k) * (y % k)) % k
(x + y) % k = ((x % k) + (y % k)) % k
(x - y) % k = ((((x % k + k) % k) - ((y % k + k) % k)) % k + k) % k
I need compute (9173501*9173502*9173504)%9173503 in C#;

How can i assign (assert) values to functions in Z3py?

I would like to kindly ask , How can I convert the following Z3 constraints into Z3py (Python API).
(declare-datatypes () ((S a b c d e f g)))
(declare-fun fun1 ( S ) Bool)
(declare-fun fun2 ( S S ) Bool)
(assert (forall ((x S)) (= (fun1 x)
(or
(= x a)
(= x b)
(= x c)
(= x d)
(= x e)
(= x f)
(= x g)
))))
(assert (forall ((y1 S) (y2 S)) (= (fun2 y1 y2)
(or
(and (= y1 a) (= y2 b))
(and (= y1 c) (= y2 d))
(and (= y2 e) (= y2 f))
))))
You can encode it in the following way:
from z3 import *
S, (a, b, c, d, e, f, g) = EnumSort('S', ['a', 'b', 'c', 'd', 'e', 'f', 'g'])
fun1 = Function('fun1', S, BoolSort())
fun2 = Function('fun2', S, S, BoolSort())
s = Solver()
x = Const('x', S)
s.add(ForAll([x], fun1(x) == Or(x == a, x == b, x == c, x == d, x == e, x == f, x == g, x == e)))
y1, y2 = Consts('y1 y2', S)
s.add(ForAll([y1, y2], fun2(y1, y2) == Or(And(y1 == a, y2 == b), And(y1 == c, y2 == d), And(y1 == e, y2 == f))))
print(s.check())
print(s.model())
Note that fun1 and fun2 are essentially macros. So, we can avoid the quantifiers and define them as:
def fun1(x):
return Or(x == a, x == b, x == c, x == d, x == e, x == f, x == g, x == e)
def fun2(y1, y2):
return Or(And(y1 == a, y2 == b), And(y1 == c, y2 == d), And(y1 == e, y2 == f))

Resources