Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potential Unsoundness in Prelude.bpl #4400

Open
yizhou7 opened this issue Aug 8, 2023 · 10 comments
Open

Potential Unsoundness in Prelude.bpl #4400

yizhou7 opened this issue Aug 8, 2023 · 10 comments
Assignees
Labels
during 3: execution of incorrect program An bug in the verifier that allows Dafny to run a program that does not correctly implement its spec introduced: pre-2009 kind: bug Crashes, unsoundness, incorrect output, etc. If possible, add a `part:` label logic An inconsistency in Dafny's logic (e.g. in the Boogie prelude) priority: not yet Will reconsider working on this when we're looking for work

Comments

@yizhou7
Copy link
Contributor

yizhou7 commented Aug 8, 2023

I naively took Prelude.bpl and added this to the end (otherwise boogie would not emit an SMT file).

procedure should_not_prove()
  ensures false;
{
}

I then ran boogie (version 3.0.0) to log the generated SMT query (dotnet version 6.0.412):

dotnet tool run boogie DafnyPrelude.bpl /proverLog:DafnyPrelude.smt2

I ran this with vampire (version 4.8), it reported that a refutation (unsat):

% Refutation found. Thanks to Tanya!
% SZS status Unsatisfiable for DafnyPrelude
% SZS output start Proof for DafnyPrelude
113. ! [X1 : 'T@Box()',X0 : 'Array'('T@Box()',$int)] : $sum($select(X0,X1),1) = $select('MultiSet#UnionOne_12626'(X0,X1),X1) [input]
122. ! [X2 : 'T@Box()',X1 : 'T@Box()',X0 : 'Array'('T@Box()',$int)] : ($less(0,$select('MultiSet#UnionOne_12626'(X0,X1),X2)) <=> (X1 = X2 | $less(0,$select(X0,X2)))) [input]
412. $sum(X0,X1) = $sum(X1,X0) [theory axiom 138]
416. 0 = $sum(X0,$uminus(X0)) [theory axiom 143]
445. $select($store(X3,X0,X2),X0) = X2 [theory axiom 177]
590. ! [X0 : 'T@Box()',X1 : 'T@Box()',X2 : 'Array'('T@Box()',$int)] : ($less(0,$select('MultiSet#UnionOne_12626'(X2,X1),X0)) <=> (X0 = X1 | $less(0,$select(X2,X0)))) [rectify 122]
595. ! [X0 : 'T@Box()',X1 : 'Array'('T@Box()',$int)] : $sum($select(X1,X0),1) = $select('MultiSet#UnionOne_12626'(X1,X0),X0) [rectify 113]
995. ! [X0 : 'T@Box()',X1 : 'T@Box()',X2 : 'Array'('T@Box()',$int)] : (($less(0,$select('MultiSet#UnionOne_12626'(X2,X1),X0)) | (X0 != X1 & ~$less(0,$select(X2,X0)))) & ((X0 = X1 | $less(0,$select(X2,X0))) | ~$less(0,$select('MultiSet#UnionOne_12626'(X2,X1),X0)))) [nnf transformation 590]
996. ! [X0 : 'T@Box()',X1 : 'T@Box()',X2 : 'Array'('T@Box()',$int)] : (($less(0,$select('MultiSet#UnionOne_12626'(X2,X1),X0)) | (X0 != X1 & ~$less(0,$select(X2,X0)))) & (X0 = X1 | $less(0,$select(X2,X0)) | ~$less(0,$select('MultiSet#UnionOne_12626'(X2,X1),X0)))) [flattening 995]
1410. $less(0,$select('MultiSet#UnionOne_12626'(X2,X1),X0)) | X0 != X1 [cnf transformation 996]
1420. $sum($select(X1,X0),1) = $select('MultiSet#UnionOne_12626'(X1,X0),X0) [cnf transformation 595]
1743. $less(0,$select('MultiSet#UnionOne_12626'(X2,X1),X1)) [equality resolution 1410]
1811. $select('MultiSet#UnionOne_12626'(X1,X0),X0) = $sum(1,$select(X1,X0)) [forward demodulation 1420,412]
1812. $less(0,$sum(1,$select(X2,X1))) [backward demodulation 1743,1811]
2253. $less(0,$sum(1,X5)) [superposition 1812,445]
2258. $less(0,0) [superposition 2253,416]
2261. $false [evaluation 2258]

From the proof, it seems like these two axioms from Prelude.bpl are causing the problem:

// pure containment axiom (in the original multiset or is the added element)
axiom (forall<T> a: MultiSet T, x: T, o: T :: { MultiSet#UnionOne(a,x)[o] }
  0 < MultiSet#UnionOne(a,x)[o] <==> o == x || 0 < a[o]);
// union-ing increases count by one
axiom (forall<T> a: MultiSet T, x: T :: { MultiSet#UnionOne(a, x) }
  MultiSet#UnionOne(a, x)[x] == a[x] + 1);

I removed the two conflicting asserts from the SMT file, a new refutation was found. In fact there seemed to be 4 disjoint sets of conflicting asserts. That is, I repeated the following until vampire was not able to immediately find a refutation, and 4 disjoint sets of asserts were reported:

  • remove all conflicting asserts in one refutation
  • vampire finds a new refutation
@yizhou7
Copy link
Contributor Author

yizhou7 commented Aug 8, 2023

I am not quite sure how Dafny uses Prelude.bpl in the VCG, but if I write this in a Dafny file:

lemma foo()
	ensures false;
{
}

Using dafny (version 4.2.0):

./dafny/dafny test.dfy /compile:0 /proverLog:test.smt2

Of course this does not verify using z3, since it is not an FOL ATP.

test.dfy(3,0): Error: a postcondition could not be proved on this return path
test.dfy(2,9): Related location: this is the postcondition that could not be proved

Dafny program verifier finished with 0 verified, 1 error

But If I run this with vampire, it finds a refutation:

2. (((((((((((((((((((((((((((((((((0 = '$generated@@11'('$generated@@8') & 1 = '$generated@@11'('$generated@@12')) & 2 = '$generated@@11'('$generated@@13')) & ! [X87 : $o] : ('$generated@@2'('$generated@@14'(X87)) = X87)) & ! [X86 : 'T@U()'] : ('$generated@@8' = type(X86) => '$generated@@14'('$generated@@2'(X86)) = X86)) & ! [X85 : $o] : '$generated@@8' = type('$generated@@14'(X85))) & ! [X84 : $int] : '$generated@@1'('$generated@@15'(X84)) = X84) & ! [X83 : 'T@U()'] : ('$generated@@12' = type(X83) => '$generated@@15'('$generated@@1'(X83)) = X83)) & ! [X82 : $int] : '$generated@@12' = type('$generated@@15'(X82))) & ! [X81 : $real] : '$generated@@17'('$generated@@16'(X81)) = X81) & ! [X80 : 'T@U()'] : ('$generated@@13' = type(X80) => '$generated@@16'('$generated@@17'(X80)) = X80)) & ! [X79 : $real] : '$generated@@13' = type('$generated@@16'(X79))) & ! [X78 : 'T@T()',X77 : 'T@T()'] : 3 = '$generated@@11'('$generated@@5'(X77,X78))) & ! [X76 : 'T@T()',X75 : 'T@T()'] : '$generated@@18'('$generated@@5'(X75,X76)) = X75) & ! [X73 : 'T@T()',X74 : 'T@T()'] : '$generated@@19'('$generated@@5'(X73,X74)) = X74) & ! [X72 : 'T@U()',X71 : 'T@U()'] : $let(sLF9: 'T@T()', sLF9 := '$generated@@19'(type(X71)), sLF9 = type('$generated@@10'(X71,X72)))) & ! [X70 : 'T@U()',X68 : 'T@U()',X69 : 'T@U()'] : $let(sLF7: 'T@T()', sLF7 := type(X70), $let(sLF8: 'T@T()', sLF8 := type(X69), '$generated@@5'(sLF8,sLF7) = type('$generated@@20'(X68,X69,X70))))) & ! [X67 : 'T@U()',X65 : 'T@U()',X66 : 'T@U()'] : $let(sLF6: 'T@T()', sLF6 := '$generated@@19'(type(X65)), sLF6 = type(X67) => '$generated@@10'('$generated@@20'(X65,X66,X67),X66) = X67)) & (! [X62 : 'T@U()',X61 : 'T@U()',X64 : 'T@U()',X63 : 'T@U()'] : (X63 = X64 | '$generated@@10'(X62,X64) = '$generated@@10'('$generated@@20'(X62,X63,X61),X64)) & ! [X59 : 'T@U()',X57 : 'T@U()',X60 : 'T@U()',X58 : 'T@U()'] : ($true | '$generated@@10'(X58,X60) = '$generated@@10'('$generated@@20'(X58,X59,X57),X60)))) & ! [X56 : 'T@T()'] : 4 = '$generated@@11'('$generated@@7'(X56))) & ! [X55 : 'T@T()'] : '$generated@@3'('$generated@@7'(X55)) = X55) & ! [X53 : 'T@U()',X54 : 'T@U()'] : $let(sLF5: 'T@T()', sLF5 := '$generated@@3'(type(X54)), sLF5 = type('$generated@@9'(X53,X54)))) & 5 = '$generated@@11'('$generated@@6')) & ! [X50 : 'T@U()',X52 : 'T@U()',X51 : 'T@U()'] : '$generated@@6' = type('$generated@@21'(X50,X51,X52))) & ! [X49 : 'T@U()',X47 : 'T@U()',X48 : 'T@U()'] : $let(sLF4: 'T@T()', sLF4 := '$generated@@3'(type(X48)), sLF4 = type(X49) => '$generated@@9'('$generated@@21'(X47,X48,X49),X48) = X49)) & (! [X46 : 'T@U()',X45 : 'T@U()',X44 : 'T@U()',X43 : 'T@U()'] : (X45 = X46 | '$generated@@9'(X44,X46) = '$generated@@9'('$generated@@21'(X44,X45,X43),X46)) & ! [X41 : 'T@U()',X42 : 'T@U()',X40 : 'T@U()',X39 : 'T@U()'] : ($true | '$generated@@9'(X40,X42) = '$generated@@9'('$generated@@21'(X40,X41,X39),X42)))) & 6 = '$generated@@11'('$generated@@4')) & ! [X37 : 'T@T()',X38 : 'T@T()'] : 7 = '$generated@@11'('$generated@@22'(X37,X38))) & ! [X35 : 'T@T()',X36 : 'T@T()'] : '$generated@@23'('$generated@@22'(X35,X36)) = X35) & ! [X34 : 'T@T()',X33 : 'T@T()'] : '$generated@@24'('$generated@@22'(X33,X34)) = X34) & ! [X30 : 'T@U()',X31 : 'T@U()',X32 : 'T@U()'] : $let(sLF3: 'T@T()', sLF3 := '$generated@@24'(type(X30)), sLF3 = type('$generated'(X30,X31,X32)))) & ! [X26 : 'T@U()',X29 : 'T@U()',X28 : 'T@U()',X27 : 'T@U()'] : $let(sLF1: 'T@T()', sLF1 := type(X29), $let(sLF2: 'T@T()', sLF2 := type(X27), '$generated@@22'(sLF2,sLF1) = type('$generated@@25'(X26,X27,X28,X29))))) & ! [X25 : 'T@U()',X24 : 'T@U()',X23 : 'T@U()',X22 : 'T@U()'] : $let(sLF0: 'T@T()', sLF0 := '$generated@@24'(type(X22)), sLF0 = type(X25) => '$generated'('$generated@@25'(X22,X23,X24,X25),X23,X24) = X25)) & ((! [X18 : 'T@U()',X19 : 'T@U()',X16 : 'T@U()',X17 : 'T@U()',X20 : 'T@U()',X21 : 'T@U()'] : (X18 = X20 | '$generated'(X17,X20,X21) = '$generated'('$generated@@25'(X17,X18,X19,X16),X20,X21)) & ! [X13 : 'T@U()',X12 : 'T@U()',X15 : 'T@U()',X14 : 'T@U()',X10 : 'T@U()',X11 : 'T@U()'] : (X13 = X15 | '$generated'(X11,X14,X15) = '$generated'('$generated@@25'(X11,X12,X13,X10),X14,X15))) & ! [X5 : 'T@U()',X4 : 'T@U()',X7 : 'T@U()',X6 : 'T@U()',X9 : 'T@U()',X8 : 'T@U()'] : ($true | '$generated'(X5,X8,X9) = '$generated'('$generated@@25'(X5,X6,X7,X4),X8,X9)))) & ! [X1 : 'T@U()',X0 : 'T@U()',X3 : $o,X2 : 'T@U()'] : '$generated@@22'('$generated@@4','$generated@@8') = type('$generated@@0'(X0,X1,X2,X3)) [input]
7. ! [X0 : 'T@U()'] : $let(sLF12: 'T@T()', sLF12 := type(X0), '$generated@@136'(sLF12,'$generated@@135'(X0)) = X0) [input]
9. (('$generated@@22'('$generated@@4','$generated@@8') = type('$generated@@144') & '$generated@@4' = type('$generated@@145')) & '$generated@@5'('$generated@@4','$generated@@6') = type('$generated@@146')) & '$generated@@7'('$generated@@8') = type('$generated@@147') [input]
12. ! [X0 : 'T@U()'] : $let(sLF12: 'T@T()', sLF12 := type(X0), '$generated@@136'(sLF12,'$generated@@135'(X0)) = X0) [theory normalization 7]
15. (((((((((((((0 = '$generated@@11'('$generated@@8') & 1 = '$generated@@11'('$generated@@12')) & 2 = '$generated@@11'('$generated@@13')) & ! [X87 : $o] : ('$generated@@2'('$generated@@14'(X87)) = X87)) & ! [X86 : 'T@U()'] : ('$generated@@8' = type(X86) => '$generated@@14'('$generated@@2'(X86)) = X86)) & ! [X85 : $o] : '$generated@@8' = type('$generated@@14'(X85))) & ! [X84 : $int] : '$generated@@1'('$generated@@15'(X84)) = X84) & ! [X83 : 'T@U()'] : ('$generated@@12' = type(X83) => '$generated@@15'('$generated@@1'(X83)) = X83)) & ! [X82 : $int] : '$generated@@12' = type('$generated@@15'(X82))) & ! [X81 : $real] : '$generated@@17'('$generated@@16'(X81)) = X81) & ! [X80 : 'T@U()'] : ('$generated@@13' = type(X80) => '$generated@@16'('$generated@@17'(X80)) = X80)) & ! [X79 : $real] : '$generated@@13' = type('$generated@@16'(X79))) & ! [X78 : 'T@T()',X77 : 'T@T()'] : 3 = '$generated@@11'('$generated@@5'(X77,X78))) & ! [X76 : 'T@T()',X75 : 'T@T()'] : '$generated@@18'('$generated@@5'(X75,X76)) = X75) & ! [X73 : 'T@T()',X74 : 'T@T()'] : '$generated@@19'('$generated@@5'(X73,X74)) = X74 & ! [X72 : 'T@U()',X71 : 'T@U()'] : $let(sLF9: 'T@T()', sLF9 := '$generated@@19'(type(X71)), sLF9 = type('$generated@@10'(X71,X72))) & ! [X70 : 'T@U()',X68 : 'T@U()',X69 : 'T@U()'] : $let(sLF7: 'T@T()', sLF7 := type(X70), $let(sLF8: 'T@T()', sLF8 := type(X69), '$generated@@5'(sLF8,sLF7) = type('$generated@@20'(X68,X69,X70)))) & ! [X67 : 'T@U()',X65 : 'T@U()',X66 : 'T@U()'] : $let(sLF6: 'T@T()', sLF6 := '$generated@@19'(type(X65)), sLF6 = type(X67) => '$generated@@10'('$generated@@20'(X65,X66,X67),X66) = X67) & ! [X62 : 'T@U()',X61 : 'T@U()',X64 : 'T@U()',X63 : 'T@U()'] : (X63 = X64 | '$generated@@10'(X62,X64) = '$generated@@10'('$generated@@20'(X62,X63,X61),X64)) & ! [X59 : 'T@U()',X57 : 'T@U()',X60 : 'T@U()',X58 : 'T@U()'] : ($true | '$generated@@10'(X58,X60) = '$generated@@10'('$generated@@20'(X58,X59,X57),X60)) & ! [X56 : 'T@T()'] : 4 = '$generated@@11'('$generated@@7'(X56)) & ! [X55 : 'T@T()'] : '$generated@@3'('$generated@@7'(X55)) = X55 & ! [X53 : 'T@U()',X54 : 'T@U()'] : $let(sLF5: 'T@T()', sLF5 := '$generated@@3'(type(X54)), sLF5 = type('$generated@@9'(X53,X54))) & 5 = '$generated@@11'('$generated@@6') & ! [X50 : 'T@U()',X52 : 'T@U()',X51 : 'T@U()'] : '$generated@@6' = type('$generated@@21'(X50,X51,X52)) & ! [X49 : 'T@U()',X47 : 'T@U()',X48 : 'T@U()'] : $let(sLF4: 'T@T()', sLF4 := '$generated@@3'(type(X48)), sLF4 = type(X49) => '$generated@@9'('$generated@@21'(X47,X48,X49),X48) = X49) & ! [X46 : 'T@U()',X45 : 'T@U()',X44 : 'T@U()',X43 : 'T@U()'] : (X45 = X46 | '$generated@@9'(X44,X46) = '$generated@@9'('$generated@@21'(X44,X45,X43),X46)) & ! [X41 : 'T@U()',X42 : 'T@U()',X40 : 'T@U()',X39 : 'T@U()'] : ($true | '$generated@@9'(X40,X42) = '$generated@@9'('$generated@@21'(X40,X41,X39),X42)) & 6 = '$generated@@11'('$generated@@4') & ! [X37 : 'T@T()',X38 : 'T@T()'] : 7 = '$generated@@11'('$generated@@22'(X37,X38)) & ! [X35 : 'T@T()',X36 : 'T@T()'] : '$generated@@23'('$generated@@22'(X35,X36)) = X35 & ! [X34 : 'T@T()',X33 : 'T@T()'] : '$generated@@24'('$generated@@22'(X33,X34)) = X34 & ! [X30 : 'T@U()',X31 : 'T@U()',X32 : 'T@U()'] : $let(sLF3: 'T@T()', sLF3 := '$generated@@24'(type(X30)), sLF3 = type('$generated'(X30,X31,X32))) & ! [X26 : 'T@U()',X29 : 'T@U()',X28 : 'T@U()',X27 : 'T@U()'] : $let(sLF1: 'T@T()', sLF1 := type(X29), $let(sLF2: 'T@T()', sLF2 := type(X27), '$generated@@22'(sLF2,sLF1) = type('$generated@@25'(X26,X27,X28,X29)))) & ! [X25 : 'T@U()',X24 : 'T@U()',X23 : 'T@U()',X22 : 'T@U()'] : $let(sLF0: 'T@T()', sLF0 := '$generated@@24'(type(X22)), sLF0 = type(X25) => '$generated'('$generated@@25'(X22,X23,X24,X25),X23,X24) = X25) & (! [X18 : 'T@U()',X19 : 'T@U()',X16 : 'T@U()',X17 : 'T@U()',X20 : 'T@U()',X21 : 'T@U()'] : (X18 = X20 | '$generated'(X17,X20,X21) = '$generated'('$generated@@25'(X17,X18,X19,X16),X20,X21)) & ! [X13 : 'T@U()',X12 : 'T@U()',X15 : 'T@U()',X14 : 'T@U()',X10 : 'T@U()',X11 : 'T@U()'] : (X13 = X15 | '$generated'(X11,X14,X15) = '$generated'('$generated@@25'(X11,X12,X13,X10),X14,X15))) & ! [X5 : 'T@U()',X4 : 'T@U()',X7 : 'T@U()',X6 : 'T@U()',X9 : 'T@U()',X8 : 'T@U()'] : ($true | '$generated'(X5,X8,X9) = '$generated'('$generated@@25'(X5,X6,X7,X4),X8,X9)) & ! [X1 : 'T@U()',X0 : 'T@U()',X3 : $o,X2 : 'T@U()'] : '$generated@@22'('$generated@@4','$generated@@8') = type('$generated@@0'(X0,X1,X2,X3)) [theory normalization 2]
34. ! [X0 : 'T@U()'] : $let(sLF12: 'T@T()', sLF12 := type(X0), '$generated@@136'(sLF12,'$generated@@135'(X0)) = X0) [rectify 12]
35. ! [X0 : 'T@U()'] : type(X0) = lG15(X0) [fool $let elimination 34]
43. (((((((((((((0 = '$generated@@11'('$generated@@8') & 1 = '$generated@@11'('$generated@@12')) & 2 = '$generated@@11'('$generated@@13')) & ! [X0 : $o] : ('$generated@@2'('$generated@@14'(X0)) = X0)) & ! [X1 : 'T@U()'] : ('$generated@@8' = type(X1) => '$generated@@14'('$generated@@2'(X1)) = X1)) & ! [X2 : $o] : '$generated@@8' = type('$generated@@14'(X2))) & ! [X3 : $int] : '$generated@@1'('$generated@@15'(X3)) = X3) & ! [X4 : 'T@U()'] : ('$generated@@12' = type(X4) => '$generated@@15'('$generated@@1'(X4)) = X4)) & ! [X5 : $int] : '$generated@@12' = type('$generated@@15'(X5))) & ! [X6 : $real] : '$generated@@17'('$generated@@16'(X6)) = X6) & ! [X7 : 'T@U()'] : ('$generated@@13' = type(X7) => '$generated@@16'('$generated@@17'(X7)) = X7)) & ! [X8 : $real] : '$generated@@13' = type('$generated@@16'(X8))) & ! [X9 : 'T@T()',X10 : 'T@T()'] : 3 = '$generated@@11'('$generated@@5'(X10,X9))) & ! [X11 : 'T@T()',X12 : 'T@T()'] : '$generated@@18'('$generated@@5'(X12,X11)) = X12) & ! [X13 : 'T@T()',X14 : 'T@T()'] : '$generated@@19'('$generated@@5'(X13,X14)) = X14 & ! [X15 : 'T@U()',X16 : 'T@U()'] : $let(sLF9: 'T@T()', sLF9 := '$generated@@19'(type(X16)), sLF9 = type('$generated@@10'(X16,X15))) & ! [X17 : 'T@U()',X18 : 'T@U()',X19 : 'T@U()'] : $let(sLF7: 'T@T()', sLF7 := type(X17), $let(sLF8: 'T@T()', sLF8 := type(X19), '$generated@@5'(sLF8,sLF7) = type('$generated@@20'(X18,X19,X17)))) & ! [X20 : 'T@U()',X21 : 'T@U()',X22 : 'T@U()'] : $let(sLF6: 'T@T()', sLF6 := '$generated@@19'(type(X21)), sLF6 = type(X20) => '$generated@@10'('$generated@@20'(X21,X22,X20),X22) = X20) & ! [X23 : 'T@U()',X24 : 'T@U()',X25 : 'T@U()',X26 : 'T@U()'] : (X25 = X26 | '$generated@@10'(X23,X25) = '$generated@@10'('$generated@@20'(X23,X26,X24),X25)) & ! [X27 : 'T@U()',X28 : 'T@U()',X29 : 'T@U()',X30 : 'T@U()'] : ($true | '$generated@@10'(X30,X29) = '$generated@@10'('$generated@@20'(X30,X27,X28),X29)) & ! [X31 : 'T@T()'] : 4 = '$generated@@11'('$generated@@7'(X31)) & ! [X32 : 'T@T()'] : '$generated@@3'('$generated@@7'(X32)) = X32 & ! [X33 : 'T@U()',X34 : 'T@U()'] : $let(sLF5: 'T@T()', sLF5 := '$generated@@3'(type(X34)), sLF5 = type('$generated@@9'(X33,X34))) & 5 = '$generated@@11'('$generated@@6') & ! [X35 : 'T@U()',X36 : 'T@U()',X37 : 'T@U()'] : '$generated@@6' = type('$generated@@21'(X35,X37,X36)) & ! [X38 : 'T@U()',X39 : 'T@U()',X40 : 'T@U()'] : $let(sLF4: 'T@T()', sLF4 := '$generated@@3'(type(X40)), sLF4 = type(X38) => '$generated@@9'('$generated@@21'(X39,X40,X38),X40) = X38) & ! [X41 : 'T@U()',X42 : 'T@U()',X43 : 'T@U()',X44 : 'T@U()'] : (X41 = X42 | '$generated@@9'(X43,X41) = '$generated@@9'('$generated@@21'(X43,X42,X44),X41)) & ! [X45 : 'T@U()',X46 : 'T@U()',X47 : 'T@U()',X48 : 'T@U()'] : ($true | '$generated@@9'(X47,X46) = '$generated@@9'('$generated@@21'(X47,X45,X48),X46)) & 6 = '$generated@@11'('$generated@@4') & ! [X49 : 'T@T()',X50 : 'T@T()'] : 7 = '$generated@@11'('$generated@@22'(X49,X50)) & ! [X51 : 'T@T()',X52 : 'T@T()'] : '$generated@@23'('$generated@@22'(X51,X52)) = X51 & ! [X53 : 'T@T()',X54 : 'T@T()'] : '$generated@@24'('$generated@@22'(X54,X53)) = X53 & ! [X55 : 'T@U()',X56 : 'T@U()',X57 : 'T@U()'] : $let(sLF3: 'T@T()', sLF3 := '$generated@@24'(type(X55)), sLF3 = type('$generated'(X55,X56,X57))) & ! [X58 : 'T@U()',X59 : 'T@U()',X60 : 'T@U()',X61 : 'T@U()'] : $let(sLF1: 'T@T()', sLF1 := type(X59), $let(sLF2: 'T@T()', sLF2 := type(X61), '$generated@@22'(sLF2,sLF1) = type('$generated@@25'(X58,X61,X60,X59)))) & ! [X62 : 'T@U()',X63 : 'T@U()',X64 : 'T@U()',X65 : 'T@U()'] : $let(sLF0: 'T@T()', sLF0 := '$generated@@24'(type(X65)), sLF0 = type(X62) => '$generated'('$generated@@25'(X65,X64,X63,X62),X64,X63) = X62) & (! [X66 : 'T@U()',X67 : 'T@U()',X68 : 'T@U()',X69 : 'T@U()',X70 : 'T@U()',X71 : 'T@U()'] : (X66 = X70 | '$generated'(X69,X70,X71) = '$generated'('$generated@@25'(X69,X66,X67,X68),X70,X71)) & ! [X72 : 'T@U()',X73 : 'T@U()',X74 : 'T@U()',X75 : 'T@U()',X76 : 'T@U()',X77 : 'T@U()'] : (X72 = X74 | '$generated'(X77,X75,X74) = '$generated'('$generated@@25'(X77,X73,X72,X76),X75,X74))) & ! [X78 : 'T@U()',X79 : 'T@U()',X80 : 'T@U()',X81 : 'T@U()',X82 : 'T@U()',X83 : 'T@U()'] : ($true | '$generated'(X78,X83,X82) = '$generated'('$generated@@25'(X78,X81,X80,X79),X83,X82)) & ! [X84 : 'T@U()',X85 : 'T@U()',X86 : $o,X87 : 'T@U()'] : '$generated@@22'('$generated@@4','$generated@@8') = type('$generated@@0'(X85,X84,X87,X86)) [rectify 15]
45. ! [X59 : 'T@U()'] : type(X59) = lG19(X59) [fool $let elimination 43]
46. ! [X61 : 'T@U()'] : type(X61) = lG20(X61) [fool $let elimination 43]
47. ! [X55 : 'T@U()'] : '$generated@@24'(type(X55)) = lG21(X55) [fool $let elimination 43]
52. ! [X19 : 'T@U()'] : type(X19) = lG26(X19) [fool $let elimination 43]
53. ! [X16 : 'T@U()'] : '$generated@@19'(type(X16)) = lG27(X16) [fool $let elimination 43]
55. (((((((((((((0 = '$generated@@11'('$generated@@8') & 1 = '$generated@@11'('$generated@@12')) & 2 = '$generated@@11'('$generated@@13')) & ! [X0 : $o] : ('$generated@@2'('$generated@@14'(X0)) <=> ($true = X0))) & ! [X1 : 'T@U()'] : ('$generated@@8' = type(X1) => '$generated@@14'(bG28(X1)) = X1)) & ! [X2 : $o] : '$generated@@8' = type('$generated@@14'(X2))) & ! [X3 : $int] : '$generated@@1'('$generated@@15'(X3)) = X3) & ! [X4 : 'T@U()'] : ('$generated@@12' = type(X4) => '$generated@@15'('$generated@@1'(X4)) = X4)) & ! [X5 : $int] : '$generated@@12' = type('$generated@@15'(X5))) & ! [X6 : $real] : '$generated@@17'('$generated@@16'(X6)) = X6) & ! [X7 : 'T@U()'] : ('$generated@@13' = type(X7) => '$generated@@16'('$generated@@17'(X7)) = X7)) & ! [X8 : $real] : '$generated@@13' = type('$generated@@16'(X8))) & ! [X9 : 'T@T()',X10 : 'T@T()'] : 3 = '$generated@@11'('$generated@@5'(X10,X9))) & ! [X11 : 'T@T()',X12 : 'T@T()'] : '$generated@@18'('$generated@@5'(X12,X11)) = X12) & ! [X13 : 'T@T()',X14 : 'T@T()'] : '$generated@@19'('$generated@@5'(X13,X14)) = X14 & ! [X15 : 'T@U()',X16 : 'T@U()'] : type('$generated@@10'(X16,X15)) = lG27(X16) & ! [X17 : 'T@U()',X18 : 'T@U()',X19 : 'T@U()'] : type('$generated@@20'(X18,X19,X17)) = '$generated@@5'(lG26(X19),lG25(X17)) & ! [X20 : 'T@U()',X21 : 'T@U()',X22 : 'T@U()'] : (type(X20) = lG24(X21) => '$generated@@10'('$generated@@20'(X21,X22,X20),X22) = X20) & ! [X23 : 'T@U()',X24 : 'T@U()',X25 : 'T@U()',X26 : 'T@U()'] : (X25 = X26 | '$generated@@10'(X23,X25) = '$generated@@10'('$generated@@20'(X23,X26,X24),X25)) & ! [X27 : 'T@U()',X28 : 'T@U()',X29 : 'T@U()',X30 : 'T@U()'] : ($true | '$generated@@10'(X30,X29) = '$generated@@10'('$generated@@20'(X30,X27,X28),X29)) & ! [X31 : 'T@T()'] : 4 = '$generated@@11'('$generated@@7'(X31)) & ! [X32 : 'T@T()'] : '$generated@@3'('$generated@@7'(X32)) = X32 & ! [X33 : 'T@U()',X34 : 'T@U()'] : type('$generated@@9'(X33,X34)) = lG23(X34) & 5 = '$generated@@11'('$generated@@6') & ! [X35 : 'T@U()',X36 : 'T@U()',X37 : 'T@U()'] : '$generated@@6' = type('$generated@@21'(X35,X37,X36)) & ! [X38 : 'T@U()',X39 : 'T@U()',X40 : 'T@U()'] : (type(X38) = lG22(X40) => '$generated@@9'('$generated@@21'(X39,X40,X38),X40) = X38) & ! [X41 : 'T@U()',X42 : 'T@U()',X43 : 'T@U()',X44 : 'T@U()'] : (X41 = X42 | '$generated@@9'(X43,X41) = '$generated@@9'('$generated@@21'(X43,X42,X44),X41)) & ! [X45 : 'T@U()',X46 : 'T@U()',X47 : 'T@U()',X48 : 'T@U()'] : ($true | '$generated@@9'(X47,X46) = '$generated@@9'('$generated@@21'(X47,X45,X48),X46)) & 6 = '$generated@@11'('$generated@@4') & ! [X49 : 'T@T()',X50 : 'T@T()'] : 7 = '$generated@@11'('$generated@@22'(X49,X50)) & ! [X51 : 'T@T()',X52 : 'T@T()'] : '$generated@@23'('$generated@@22'(X51,X52)) = X51 & ! [X53 : 'T@T()',X54 : 'T@T()'] : '$generated@@24'('$generated@@22'(X54,X53)) = X53 & ! [X55 : 'T@U()',X56 : 'T@U()',X57 : 'T@U()'] : type('$generated'(X55,X56,X57)) = lG21(X55) & ! [X58 : 'T@U()',X59 : 'T@U()',X60 : 'T@U()',X61 : 'T@U()'] : type('$generated@@25'(X58,X61,X60,X59)) = '$generated@@22'(lG20(X61),lG19(X59)) & ! [X62 : 'T@U()',X63 : 'T@U()',X64 : 'T@U()',X65 : 'T@U()'] : (type(X62) = lG18(X65) => '$generated'('$generated@@25'(X65,X64,X63,X62),X64,X63) = X62) & (! [X66 : 'T@U()',X67 : 'T@U()',X68 : 'T@U()',X69 : 'T@U()',X70 : 'T@U()',X71 : 'T@U()'] : (X66 = X70 | '$generated'(X69,X70,X71) = '$generated'('$generated@@25'(X69,X66,X67,X68),X70,X71)) & ! [X72 : 'T@U()',X73 : 'T@U()',X74 : 'T@U()',X75 : 'T@U()',X76 : 'T@U()',X77 : 'T@U()'] : (X72 = X74 | '$generated'(X77,X75,X74) = '$generated'('$generated@@25'(X77,X73,X72,X76),X75,X74))) & ! [X78 : 'T@U()',X79 : 'T@U()',X80 : 'T@U()',X81 : 'T@U()',X82 : 'T@U()',X83 : 'T@U()'] : ($true | '$generated'(X78,X83,X82) = '$generated'('$generated@@25'(X78,X81,X80,X79),X83,X82)) & ! [X84 : 'T@U()',X85 : 'T@U()',X86 : $o,X87 : 'T@U()'] : '$generated@@22'('$generated@@4','$generated@@8') = type('$generated@@0'(X85,X84,X87,X86)) [fool elimination 43]
58. ! [X0 : 'T@U()'] : '$generated@@19'(type(X0)) = lG27(X0) [rectify 53]
59. ! [X0 : 'T@U()'] : type(X0) = lG26(X0) [rectify 52]
64. ! [X0 : 'T@U()'] : '$generated@@24'(type(X0)) = lG21(X0) [rectify 47]
65. ! [X0 : 'T@U()'] : type(X0) = lG20(X0) [rectify 46]
66. ! [X0 : 'T@U()'] : type(X0) = lG19(X0) [rectify 45]
69. '$generated@@22'('$generated@@4','$generated@@8') = type('$generated@@144') & '$generated@@4' = type('$generated@@145') & '$generated@@5'('$generated@@4','$generated@@6') = type('$generated@@146') & '$generated@@7'('$generated@@8') = type('$generated@@147') [flattening 9]
73. (((((((((((((0 = '$generated@@11'('$generated@@8') & 1 = '$generated@@11'('$generated@@12')) & 2 = '$generated@@11'('$generated@@13')) & ! [X0 : $o] : ('$generated@@2'('$generated@@14'(X0)) <=> ($true = X0))) & ! [X1 : 'T@U()'] : ('$generated@@8' = type(X1) => '$generated@@14'(bG28(X1)) = X1)) & ! [X2 : $o] : '$generated@@8' = type('$generated@@14'(X2))) & ! [X3 : $int] : '$generated@@1'('$generated@@15'(X3)) = X3) & ! [X4 : 'T@U()'] : ('$generated@@12' = type(X4) => '$generated@@15'('$generated@@1'(X4)) = X4)) & ! [X5 : $int] : '$generated@@12' = type('$generated@@15'(X5))) & ! [X6 : $real] : '$generated@@17'('$generated@@16'(X6)) = X6) & ! [X7 : 'T@U()'] : ('$generated@@13' = type(X7) => '$generated@@16'('$generated@@17'(X7)) = X7)) & ! [X8 : $real] : '$generated@@13' = type('$generated@@16'(X8))) & ! [X9 : 'T@T()',X10 : 'T@T()'] : 3 = '$generated@@11'('$generated@@5'(X10,X9))) & ! [X11 : 'T@T()',X12 : 'T@T()'] : '$generated@@18'('$generated@@5'(X12,X11)) = X12) & ! [X13 : 'T@T()',X14 : 'T@T()'] : '$generated@@19'('$generated@@5'(X13,X14)) = X14 & ! [X15 : 'T@U()',X16 : 'T@U()'] : type('$generated@@10'(X16,X15)) = lG27(X16) & ! [X17 : 'T@U()',X18 : 'T@U()',X19 : 'T@U()'] : type('$generated@@20'(X18,X19,X17)) = '$generated@@5'(lG26(X19),lG25(X17)) & ! [X20 : 'T@U()',X21 : 'T@U()',X22 : 'T@U()'] : (type(X20) = lG24(X21) => '$generated@@10'('$generated@@20'(X21,X22,X20),X22) = X20) & ! [X23 : 'T@U()',X24 : 'T@U()',X25 : 'T@U()',X26 : 'T@U()'] : (X25 = X26 | '$generated@@10'(X23,X25) = '$generated@@10'('$generated@@20'(X23,X26,X24),X25)) & ! [X31 : 'T@T()'] : 4 = '$generated@@11'('$generated@@7'(X31)) & ! [X32 : 'T@T()'] : '$generated@@3'('$generated@@7'(X32)) = X32 & ! [X33 : 'T@U()',X34 : 'T@U()'] : type('$generated@@9'(X33,X34)) = lG23(X34) & 5 = '$generated@@11'('$generated@@6') & ! [X35 : 'T@U()',X36 : 'T@U()',X37 : 'T@U()'] : '$generated@@6' = type('$generated@@21'(X35,X37,X36)) & ! [X38 : 'T@U()',X39 : 'T@U()',X40 : 'T@U()'] : (type(X38) = lG22(X40) => '$generated@@9'('$generated@@21'(X39,X40,X38),X40) = X38) & ! [X41 : 'T@U()',X42 : 'T@U()',X43 : 'T@U()',X44 : 'T@U()'] : (X41 = X42 | '$generated@@9'(X43,X41) = '$generated@@9'('$generated@@21'(X43,X42,X44),X41)) & 6 = '$generated@@11'('$generated@@4') & ! [X49 : 'T@T()',X50 : 'T@T()'] : 7 = '$generated@@11'('$generated@@22'(X49,X50)) & ! [X51 : 'T@T()',X52 : 'T@T()'] : '$generated@@23'('$generated@@22'(X51,X52)) = X51 & ! [X53 : 'T@T()',X54 : 'T@T()'] : '$generated@@24'('$generated@@22'(X54,X53)) = X53 & ! [X55 : 'T@U()',X56 : 'T@U()',X57 : 'T@U()'] : type('$generated'(X55,X56,X57)) = lG21(X55) & ! [X58 : 'T@U()',X59 : 'T@U()',X60 : 'T@U()',X61 : 'T@U()'] : type('$generated@@25'(X58,X61,X60,X59)) = '$generated@@22'(lG20(X61),lG19(X59)) & ! [X62 : 'T@U()',X63 : 'T@U()',X64 : 'T@U()',X65 : 'T@U()'] : (type(X62) = lG18(X65) => '$generated'('$generated@@25'(X65,X64,X63,X62),X64,X63) = X62) & (! [X66 : 'T@U()',X67 : 'T@U()',X68 : 'T@U()',X69 : 'T@U()',X70 : 'T@U()',X71 : 'T@U()'] : (X66 = X70 | '$generated'(X69,X70,X71) = '$generated'('$generated@@25'(X69,X66,X67,X68),X70,X71)) & ! [X72 : 'T@U()',X73 : 'T@U()',X74 : 'T@U()',X75 : 'T@U()',X76 : 'T@U()',X77 : 'T@U()'] : (X72 = X74 | '$generated'(X77,X75,X74) = '$generated'('$generated@@25'(X77,X73,X72,X76),X75,X74))) & ! [X84 : 'T@U()',X85 : 'T@U()',X86 : $o,X87 : 'T@U()'] : '$generated@@22'('$generated@@4','$generated@@8') = type('$generated@@0'(X85,X84,X87,X86)) [true and false elimination 55]
74. 0 = '$generated@@11'('$generated@@8') & 1 = '$generated@@11'('$generated@@12') & 2 = '$generated@@11'('$generated@@13') & ! [X0 : $o] : ('$generated@@2'('$generated@@14'(X0)) <=> ($true = X0)) & ! [X1 : 'T@U()'] : ('$generated@@8' = type(X1) => '$generated@@14'(bG28(X1)) = X1) & ! [X2 : $o] : '$generated@@8' = type('$generated@@14'(X2)) & ! [X3 : $int] : '$generated@@1'('$generated@@15'(X3)) = X3 & ! [X4 : 'T@U()'] : ('$generated@@12' = type(X4) => '$generated@@15'('$generated@@1'(X4)) = X4) & ! [X5 : $int] : '$generated@@12' = type('$generated@@15'(X5)) & ! [X6 : $real] : '$generated@@17'('$generated@@16'(X6)) = X6 & ! [X7 : 'T@U()'] : ('$generated@@13' = type(X7) => '$generated@@16'('$generated@@17'(X7)) = X7) & ! [X8 : $real] : '$generated@@13' = type('$generated@@16'(X8)) & ! [X9 : 'T@T()',X10 : 'T@T()'] : 3 = '$generated@@11'('$generated@@5'(X10,X9)) & ! [X11 : 'T@T()',X12 : 'T@T()'] : '$generated@@18'('$generated@@5'(X12,X11)) = X12 & ! [X13 : 'T@T()',X14 : 'T@T()'] : '$generated@@19'('$generated@@5'(X13,X14)) = X14 & ! [X15 : 'T@U()',X16 : 'T@U()'] : type('$generated@@10'(X16,X15)) = lG27(X16) & ! [X17 : 'T@U()',X18 : 'T@U()',X19 : 'T@U()'] : type('$generated@@20'(X18,X19,X17)) = '$generated@@5'(lG26(X19),lG25(X17)) & ! [X20 : 'T@U()',X21 : 'T@U()',X22 : 'T@U()'] : (type(X20) = lG24(X21) => '$generated@@10'('$generated@@20'(X21,X22,X20),X22) = X20) & ! [X23 : 'T@U()',X24 : 'T@U()',X25 : 'T@U()',X26 : 'T@U()'] : (X25 = X26 | '$generated@@10'(X23,X25) = '$generated@@10'('$generated@@20'(X23,X26,X24),X25)) & ! [X31 : 'T@T()'] : 4 = '$generated@@11'('$generated@@7'(X31)) & ! [X32 : 'T@T()'] : '$generated@@3'('$generated@@7'(X32)) = X32 & ! [X33 : 'T@U()',X34 : 'T@U()'] : type('$generated@@9'(X33,X34)) = lG23(X34) & 5 = '$generated@@11'('$generated@@6') & ! [X35 : 'T@U()',X36 : 'T@U()',X37 : 'T@U()'] : '$generated@@6' = type('$generated@@21'(X35,X37,X36)) & ! [X38 : 'T@U()',X39 : 'T@U()',X40 : 'T@U()'] : (type(X38) = lG22(X40) => '$generated@@9'('$generated@@21'(X39,X40,X38),X40) = X38) & ! [X41 : 'T@U()',X42 : 'T@U()',X43 : 'T@U()',X44 : 'T@U()'] : (X41 = X42 | '$generated@@9'(X43,X41) = '$generated@@9'('$generated@@21'(X43,X42,X44),X41)) & 6 = '$generated@@11'('$generated@@4') & ! [X49 : 'T@T()',X50 : 'T@T()'] : 7 = '$generated@@11'('$generated@@22'(X49,X50)) & ! [X51 : 'T@T()',X52 : 'T@T()'] : '$generated@@23'('$generated@@22'(X51,X52)) = X51 & ! [X53 : 'T@T()',X54 : 'T@T()'] : '$generated@@24'('$generated@@22'(X54,X53)) = X53 & ! [X55 : 'T@U()',X56 : 'T@U()',X57 : 'T@U()'] : type('$generated'(X55,X56,X57)) = lG21(X55) & ! [X58 : 'T@U()',X59 : 'T@U()',X60 : 'T@U()',X61 : 'T@U()'] : type('$generated@@25'(X58,X61,X60,X59)) = '$generated@@22'(lG20(X61),lG19(X59)) & ! [X62 : 'T@U()',X63 : 'T@U()',X64 : 'T@U()',X65 : 'T@U()'] : (type(X62) = lG18(X65) => '$generated'('$generated@@25'(X65,X64,X63,X62),X64,X63) = X62) & ! [X66 : 'T@U()',X67 : 'T@U()',X68 : 'T@U()',X69 : 'T@U()',X70 : 'T@U()',X71 : 'T@U()'] : (X66 = X70 | '$generated'(X69,X70,X71) = '$generated'('$generated@@25'(X69,X66,X67,X68),X70,X71)) & ! [X72 : 'T@U()',X73 : 'T@U()',X74 : 'T@U()',X75 : 'T@U()',X76 : 'T@U()',X77 : 'T@U()'] : (X72 = X74 | '$generated'(X77,X75,X74) = '$generated'('$generated@@25'(X77,X73,X72,X76),X75,X74)) & ! [X84 : 'T@U()',X85 : 'T@U()',X86 : $o,X87 : 'T@U()'] : '$generated@@22'('$generated@@4','$generated@@8') = type('$generated@@0'(X85,X84,X87,X86)) [flattening 73]
87. 0 = '$generated@@11'('$generated@@8') & 1 = '$generated@@11'('$generated@@12') & 2 = '$generated@@11'('$generated@@13') & ! [X0 : $o] : ('$generated@@2'('$generated@@14'(X0)) <=> ($true = X0)) & ! [X1 : 'T@U()'] : ('$generated@@14'(bG28(X1)) = X1 | '$generated@@8' != type(X1)) & ! [X2 : $o] : '$generated@@8' = type('$generated@@14'(X2)) & ! [X3 : $int] : '$generated@@1'('$generated@@15'(X3)) = X3 & ! [X4 : 'T@U()'] : ('$generated@@15'('$generated@@1'(X4)) = X4 | '$generated@@12' != type(X4)) & ! [X5 : $int] : '$generated@@12' = type('$generated@@15'(X5)) & ! [X6 : $real] : '$generated@@17'('$generated@@16'(X6)) = X6 & ! [X7 : 'T@U()'] : ('$generated@@16'('$generated@@17'(X7)) = X7 | '$generated@@13' != type(X7)) & ! [X8 : $real] : '$generated@@13' = type('$generated@@16'(X8)) & ! [X9 : 'T@T()',X10 : 'T@T()'] : 3 = '$generated@@11'('$generated@@5'(X10,X9)) & ! [X11 : 'T@T()',X12 : 'T@T()'] : '$generated@@18'('$generated@@5'(X12,X11)) = X12 & ! [X13 : 'T@T()',X14 : 'T@T()'] : '$generated@@19'('$generated@@5'(X13,X14)) = X14 & ! [X15 : 'T@U()',X16 : 'T@U()'] : type('$generated@@10'(X16,X15)) = lG27(X16) & ! [X17 : 'T@U()',X18 : 'T@U()',X19 : 'T@U()'] : type('$generated@@20'(X18,X19,X17)) = '$generated@@5'(lG26(X19),lG25(X17)) & ! [X20 : 'T@U()',X21 : 'T@U()',X22 : 'T@U()'] : ('$generated@@10'('$generated@@20'(X21,X22,X20),X22) = X20 | type(X20) != lG24(X21)) & ! [X23 : 'T@U()',X24 : 'T@U()',X25 : 'T@U()',X26 : 'T@U()'] : (X25 = X26 | '$generated@@10'(X23,X25) = '$generated@@10'('$generated@@20'(X23,X26,X24),X25)) & ! [X31 : 'T@T()'] : 4 = '$generated@@11'('$generated@@7'(X31)) & ! [X32 : 'T@T()'] : '$generated@@3'('$generated@@7'(X32)) = X32 & ! [X33 : 'T@U()',X34 : 'T@U()'] : type('$generated@@9'(X33,X34)) = lG23(X34) & 5 = '$generated@@11'('$generated@@6') & ! [X35 : 'T@U()',X36 : 'T@U()',X37 : 'T@U()'] : '$generated@@6' = type('$generated@@21'(X35,X37,X36)) & ! [X38 : 'T@U()',X39 : 'T@U()',X40 : 'T@U()'] : ('$generated@@9'('$generated@@21'(X39,X40,X38),X40) = X38 | type(X38) != lG22(X40)) & ! [X41 : 'T@U()',X42 : 'T@U()',X43 : 'T@U()',X44 : 'T@U()'] : (X41 = X42 | '$generated@@9'(X43,X41) = '$generated@@9'('$generated@@21'(X43,X42,X44),X41)) & 6 = '$generated@@11'('$generated@@4') & ! [X49 : 'T@T()',X50 : 'T@T()'] : 7 = '$generated@@11'('$generated@@22'(X49,X50)) & ! [X51 : 'T@T()',X52 : 'T@T()'] : '$generated@@23'('$generated@@22'(X51,X52)) = X51 & ! [X53 : 'T@T()',X54 : 'T@T()'] : '$generated@@24'('$generated@@22'(X54,X53)) = X53 & ! [X55 : 'T@U()',X56 : 'T@U()',X57 : 'T@U()'] : type('$generated'(X55,X56,X57)) = lG21(X55) & ! [X58 : 'T@U()',X59 : 'T@U()',X60 : 'T@U()',X61 : 'T@U()'] : type('$generated@@25'(X58,X61,X60,X59)) = '$generated@@22'(lG20(X61),lG19(X59)) & ! [X62 : 'T@U()',X63 : 'T@U()',X64 : 'T@U()',X65 : 'T@U()'] : ('$generated'('$generated@@25'(X65,X64,X63,X62),X64,X63) = X62 | type(X62) != lG18(X65)) & ! [X66 : 'T@U()',X67 : 'T@U()',X68 : 'T@U()',X69 : 'T@U()',X70 : 'T@U()',X71 : 'T@U()'] : (X66 = X70 | '$generated'(X69,X70,X71) = '$generated'('$generated@@25'(X69,X66,X67,X68),X70,X71)) & ! [X72 : 'T@U()',X73 : 'T@U()',X74 : 'T@U()',X75 : 'T@U()',X76 : 'T@U()',X77 : 'T@U()'] : (X72 = X74 | '$generated'(X77,X75,X74) = '$generated'('$generated@@25'(X77,X73,X72,X76),X75,X74)) & ! [X84 : 'T@U()',X85 : 'T@U()',X86 : $o,X87 : 'T@U()'] : '$generated@@22'('$generated@@4','$generated@@8') = type('$generated@@0'(X85,X84,X87,X86)) [ennf transformation 74]
91. 0 = '$generated@@11'('$generated@@8') & 1 = '$generated@@11'('$generated@@12') & 2 = '$generated@@11'('$generated@@13') & ! [X0 : $o] : (('$generated@@2'('$generated@@14'(X0)) | ($true != X0)) & (($true = X0) | ~'$generated@@2'('$generated@@14'(X0)))) & ! [X1 : 'T@U()'] : ('$generated@@14'(bG28(X1)) = X1 | '$generated@@8' != type(X1)) & ! [X2 : $o] : '$generated@@8' = type('$generated@@14'(X2)) & ! [X3 : $int] : '$generated@@1'('$generated@@15'(X3)) = X3 & ! [X4 : 'T@U()'] : ('$generated@@15'('$generated@@1'(X4)) = X4 | '$generated@@12' != type(X4)) & ! [X5 : $int] : '$generated@@12' = type('$generated@@15'(X5)) & ! [X6 : $real] : '$generated@@17'('$generated@@16'(X6)) = X6 & ! [X7 : 'T@U()'] : ('$generated@@16'('$generated@@17'(X7)) = X7 | '$generated@@13' != type(X7)) & ! [X8 : $real] : '$generated@@13' = type('$generated@@16'(X8)) & ! [X9 : 'T@T()',X10 : 'T@T()'] : 3 = '$generated@@11'('$generated@@5'(X10,X9)) & ! [X11 : 'T@T()',X12 : 'T@T()'] : '$generated@@18'('$generated@@5'(X12,X11)) = X12 & ! [X13 : 'T@T()',X14 : 'T@T()'] : '$generated@@19'('$generated@@5'(X13,X14)) = X14 & ! [X15 : 'T@U()',X16 : 'T@U()'] : type('$generated@@10'(X16,X15)) = lG27(X16) & ! [X17 : 'T@U()',X18 : 'T@U()',X19 : 'T@U()'] : type('$generated@@20'(X18,X19,X17)) = '$generated@@5'(lG26(X19),lG25(X17)) & ! [X20 : 'T@U()',X21 : 'T@U()',X22 : 'T@U()'] : ('$generated@@10'('$generated@@20'(X21,X22,X20),X22) = X20 | type(X20) != lG24(X21)) & ! [X23 : 'T@U()',X24 : 'T@U()',X25 : 'T@U()',X26 : 'T@U()'] : (X25 = X26 | '$generated@@10'(X23,X25) = '$generated@@10'('$generated@@20'(X23,X26,X24),X25)) & ! [X31 : 'T@T()'] : 4 = '$generated@@11'('$generated@@7'(X31)) & ! [X32 : 'T@T()'] : '$generated@@3'('$generated@@7'(X32)) = X32 & ! [X33 : 'T@U()',X34 : 'T@U()'] : type('$generated@@9'(X33,X34)) = lG23(X34) & 5 = '$generated@@11'('$generated@@6') & ! [X35 : 'T@U()',X36 : 'T@U()',X37 : 'T@U()'] : '$generated@@6' = type('$generated@@21'(X35,X37,X36)) & ! [X38 : 'T@U()',X39 : 'T@U()',X40 : 'T@U()'] : ('$generated@@9'('$generated@@21'(X39,X40,X38),X40) = X38 | type(X38) != lG22(X40)) & ! [X41 : 'T@U()',X42 : 'T@U()',X43 : 'T@U()',X44 : 'T@U()'] : (X41 = X42 | '$generated@@9'(X43,X41) = '$generated@@9'('$generated@@21'(X43,X42,X44),X41)) & 6 = '$generated@@11'('$generated@@4') & ! [X49 : 'T@T()',X50 : 'T@T()'] : 7 = '$generated@@11'('$generated@@22'(X49,X50)) & ! [X51 : 'T@T()',X52 : 'T@T()'] : '$generated@@23'('$generated@@22'(X51,X52)) = X51 & ! [X53 : 'T@T()',X54 : 'T@T()'] : '$generated@@24'('$generated@@22'(X54,X53)) = X53 & ! [X55 : 'T@U()',X56 : 'T@U()',X57 : 'T@U()'] : type('$generated'(X55,X56,X57)) = lG21(X55) & ! [X58 : 'T@U()',X59 : 'T@U()',X60 : 'T@U()',X61 : 'T@U()'] : type('$generated@@25'(X58,X61,X60,X59)) = '$generated@@22'(lG20(X61),lG19(X59)) & ! [X62 : 'T@U()',X63 : 'T@U()',X64 : 'T@U()',X65 : 'T@U()'] : ('$generated'('$generated@@25'(X65,X64,X63,X62),X64,X63) = X62 | type(X62) != lG18(X65)) & ! [X66 : 'T@U()',X67 : 'T@U()',X68 : 'T@U()',X69 : 'T@U()',X70 : 'T@U()',X71 : 'T@U()'] : (X66 = X70 | '$generated'(X69,X70,X71) = '$generated'('$generated@@25'(X69,X66,X67,X68),X70,X71)) & ! [X72 : 'T@U()',X73 : 'T@U()',X74 : 'T@U()',X75 : 'T@U()',X76 : 'T@U()',X77 : 'T@U()'] : (X72 = X74 | '$generated'(X77,X75,X74) = '$generated'('$generated@@25'(X77,X73,X72,X76),X75,X74)) & ! [X84 : 'T@U()',X85 : 'T@U()',X86 : $o,X87 : 'T@U()'] : '$generated@@22'('$generated@@4','$generated@@8') = type('$generated@@0'(X85,X84,X87,X86)) [nnf transformation 87]
92. 0 = '$generated@@11'('$generated@@8') & 1 = '$generated@@11'('$generated@@12') & 2 = '$generated@@11'('$generated@@13') & ! [X0 : $o] : (('$generated@@2'('$generated@@14'(X0)) | ($true != X0)) & (($true = X0) | ~'$generated@@2'('$generated@@14'(X0)))) & ! [X1 : 'T@U()'] : ('$generated@@14'(bG28(X1)) = X1 | '$generated@@8' != type(X1)) & ! [X2 : $o] : '$generated@@8' = type('$generated@@14'(X2)) & ! [X3 : $int] : '$generated@@1'('$generated@@15'(X3)) = X3 & ! [X4 : 'T@U()'] : ('$generated@@15'('$generated@@1'(X4)) = X4 | '$generated@@12' != type(X4)) & ! [X5 : $int] : '$generated@@12' = type('$generated@@15'(X5)) & ! [X6 : $real] : '$generated@@17'('$generated@@16'(X6)) = X6 & ! [X7 : 'T@U()'] : ('$generated@@16'('$generated@@17'(X7)) = X7 | '$generated@@13' != type(X7)) & ! [X8 : $real] : '$generated@@13' = type('$generated@@16'(X8)) & ! [X9 : 'T@T()',X10 : 'T@T()'] : 3 = '$generated@@11'('$generated@@5'(X10,X9)) & ! [X11 : 'T@T()',X12 : 'T@T()'] : '$generated@@18'('$generated@@5'(X12,X11)) = X12 & ! [X13 : 'T@T()',X14 : 'T@T()'] : '$generated@@19'('$generated@@5'(X13,X14)) = X14 & ! [X15 : 'T@U()',X16 : 'T@U()'] : type('$generated@@10'(X16,X15)) = lG27(X16) & ! [X17 : 'T@U()',X18 : 'T@U()',X19 : 'T@U()'] : type('$generated@@20'(X18,X19,X17)) = '$generated@@5'(lG26(X19),lG25(X17)) & ! [X20 : 'T@U()',X21 : 'T@U()',X22 : 'T@U()'] : ('$generated@@10'('$generated@@20'(X21,X22,X20),X22) = X20 | type(X20) != lG24(X21)) & ! [X23 : 'T@U()',X24 : 'T@U()',X25 : 'T@U()',X26 : 'T@U()'] : (X25 = X26 | '$generated@@10'(X23,X25) = '$generated@@10'('$generated@@20'(X23,X26,X24),X25)) & ! [X27 : 'T@T()'] : 4 = '$generated@@11'('$generated@@7'(X27)) & ! [X28 : 'T@T()'] : '$generated@@3'('$generated@@7'(X28)) = X28 & ! [X29 : 'T@U()',X30 : 'T@U()'] : type('$generated@@9'(X29,X30)) = lG23(X30) & 5 = '$generated@@11'('$generated@@6') & ! [X31 : 'T@U()',X32 : 'T@U()',X33 : 'T@U()'] : '$generated@@6' = type('$generated@@21'(X31,X33,X32)) & ! [X34 : 'T@U()',X35 : 'T@U()',X36 : 'T@U()'] : ('$generated@@9'('$generated@@21'(X35,X36,X34),X36) = X34 | type(X34) != lG22(X36)) & ! [X37 : 'T@U()',X38 : 'T@U()',X39 : 'T@U()',X40 : 'T@U()'] : (X37 = X38 | '$generated@@9'(X39,X37) = '$generated@@9'('$generated@@21'(X39,X38,X40),X37)) & 6 = '$generated@@11'('$generated@@4') & ! [X41 : 'T@T()',X42 : 'T@T()'] : 7 = '$generated@@11'('$generated@@22'(X41,X42)) & ! [X43 : 'T@T()',X44 : 'T@T()'] : '$generated@@23'('$generated@@22'(X43,X44)) = X43 & ! [X45 : 'T@T()',X46 : 'T@T()'] : '$generated@@24'('$generated@@22'(X46,X45)) = X45 & ! [X47 : 'T@U()',X48 : 'T@U()',X49 : 'T@U()'] : type('$generated'(X47,X48,X49)) = lG21(X47) & ! [X50 : 'T@U()',X51 : 'T@U()',X52 : 'T@U()',X53 : 'T@U()'] : type('$generated@@25'(X50,X53,X52,X51)) = '$generated@@22'(lG20(X53),lG19(X51)) & ! [X54 : 'T@U()',X55 : 'T@U()',X56 : 'T@U()',X57 : 'T@U()'] : ('$generated'('$generated@@25'(X57,X56,X55,X54),X56,X55) = X54 | type(X54) != lG18(X57)) & ! [X58 : 'T@U()',X59 : 'T@U()',X60 : 'T@U()',X61 : 'T@U()',X62 : 'T@U()',X63 : 'T@U()'] : (X58 = X62 | '$generated'(X61,X62,X63) = '$generated'('$generated@@25'(X61,X58,X59,X60),X62,X63)) & ! [X64 : 'T@U()',X65 : 'T@U()',X66 : 'T@U()',X67 : 'T@U()',X68 : 'T@U()',X69 : 'T@U()'] : (X64 = X66 | '$generated'(X69,X67,X66) = '$generated'('$generated@@25'(X69,X65,X64,X68),X67,X66)) & ! [X70 : 'T@U()',X71 : 'T@U()',X72 : $o,X73 : 'T@U()'] : '$generated@@22'('$generated@@4','$generated@@8') = type('$generated@@0'(X71,X70,X73,X72)) [rectify 91]
95. '$generated@@19'(type(X0)) = lG27(X0) [cnf transformation 58]
96. type(X0) = lG26(X0) [cnf transformation 59]
101. '$generated@@24'(type(X0)) = lG21(X0) [cnf transformation 64]
102. type(X0) = lG20(X0) [cnf transformation 65]
103. type(X0) = lG19(X0) [cnf transformation 66]
107. type(X0) = lG15(X0) [cnf transformation 35]
117. '$generated@@5'('$generated@@4','$generated@@6') = type('$generated@@146') [cnf transformation 69]
118. '$generated@@4' = type('$generated@@145') [cnf transformation 69]
119. '$generated@@22'('$generated@@4','$generated@@8') = type('$generated@@144') [cnf transformation 69]
131. '$generated@@22'('$generated@@4','$generated@@8') = type('$generated@@0'(X71,X70,X73,X72)) [cnf transformation 92]
132. '$generated'(X69,X67,X66) = '$generated'('$generated@@25'(X69,X65,X64,X68),X67,X66) | X64 = X66 [cnf transformation 92]
135. type('$generated@@25'(X50,X53,X52,X51)) = '$generated@@22'(lG20(X53),lG19(X51)) [cnf transformation 92]
136. type('$generated'(X47,X48,X49)) = lG21(X47) [cnf transformation 92]
137. '$generated@@24'('$generated@@22'(X46,X45)) = X45 [cnf transformation 92]
139. 7 = '$generated@@11'('$generated@@22'(X41,X42)) [cnf transformation 92]
151. type('$generated@@10'(X16,X15)) = lG27(X16) [cnf transformation 92]
152. '$generated@@19'('$generated@@5'(X13,X14)) = X14 [cnf transformation 92]
154. 3 = '$generated@@11'('$generated@@5'(X10,X9)) [cnf transformation 92]
161. '$generated@@8' = type('$generated@@14'(X2)) [cnf transformation 92]
170. lG21(X0) = '$generated@@24'(lG26(X0)) [definition unfolding 101,96]
175. lG27(X0) = '$generated@@19'(lG26(X0)) [definition unfolding 95,96]
177. lG26(X0) = lG20(X0) [definition unfolding 102,96]
178. lG26(X0) = lG19(X0) [definition unfolding 103,96]
180. lG15(X0) = lG26(X0) [definition unfolding 107,96]
181. '$generated@@22'('$generated@@4','$generated@@8') = lG26('$generated@@144') [definition unfolding 119,96]
182. '$generated@@4' = lG26('$generated@@145') [definition unfolding 118,96]
183. '$generated@@5'('$generated@@4','$generated@@6') = lG26('$generated@@146') [definition unfolding 117,96]
192. '$generated@@8' = lG26('$generated@@14'(X2)) [definition unfolding 161,96]
197. lG26('$generated@@10'(X16,X15)) = '$generated@@19'(lG26(X16)) [definition unfolding 151,96,175]
203. lG26('$generated'(X47,X48,X49)) = '$generated@@24'(lG26(X47)) [definition unfolding 136,96,170]
204. '$generated@@22'(lG20(X53),lG19(X51)) = lG26('$generated@@25'(X50,X53,X52,X51)) [definition unfolding 135,96]
206. '$generated@@22'('$generated@@4','$generated@@8') = lG26('$generated@@0'(X71,X70,X73,X72)) [definition unfolding 131,96]
213. lG20(X0) = lG19(X0) [backward demodulation 177,178]
216. lG15(X0) = lG19(X0) [backward demodulation 178,180]
219. lG15(X0) = lG20(X0) [backward demodulation 213,216]
255. '$generated@@22'('$generated@@4','$generated@@8') = lG15('$generated@@144') [forward demodulation 181,180]
256. '$generated@@5'('$generated@@4','$generated@@6') = lG15('$generated@@146') [forward demodulation 183,180]
285. lG26('$generated@@10'(X16,X15)) = '$generated@@19'(lG15(X16)) [forward demodulation 197,180]
293. lG26('$generated'(X47,X48,X49)) = '$generated@@24'(lG15(X47)) [forward demodulation 203,180]
294. lG26('$generated@@25'(X50,X53,X52,X51)) = '$generated@@22'(lG20(X53),lG15(X51)) [forward demodulation 204,216]
295. lG26('$generated@@25'(X50,X53,X52,X51)) = '$generated@@22'(lG15(X53),lG15(X51)) [forward demodulation 294,219]
298. lG26('$generated@@0'(X71,X70,X73,X72)) = lG15('$generated@@144') [forward demodulation 206,255]
300. '$generated@@4' = lG15('$generated@@145') [superposition 180,182]
306. '$generated@@8' = lG15('$generated@@14'(X1)) [superposition 192,180]
318. 7 = '$generated@@11'(lG15('$generated@@144')) [superposition 139,255]
321. 3 = '$generated@@11'(lG15('$generated@@146')) [superposition 154,256]
323. '$generated@@6' = '$generated@@19'(lG15('$generated@@146')) [superposition 152,256]
580. lG15('$generated@@25'(X4,X5,X6,X7)) = '$generated@@22'(lG15(X5),lG15(X7)) [superposition 295,180]
644. '$generated@@24'(lG15('$generated@@25'(X0,X1,X2,X3))) = lG26('$generated'(X0,X4,X5)) | X2 = X5 [superposition 293,132]
645. '$generated@@24'(lG15(X0)) = '$generated@@24'(lG15('$generated@@25'(X0,X1,X2,X3))) | X2 = X5 [forward demodulation 644,293]
646. '$generated@@24'(lG15(X0)) = '$generated@@24'('$generated@@22'(lG15(X1),lG15(X3))) | X2 = X5 [forward demodulation 645,580]
648. 32 <=> ! [X2 : 'T@U()',X5 : 'T@U()'] : X2 = X5 [avatar definition]
649. X2 = X5 <- (32) [avatar component clause 648]
651. 33 <=> ! [X0 : 'T@U()',X1 : 'T@U()',X3 : 'T@U()'] : '$generated@@24'(lG15(X0)) = '$generated@@24'('$generated@@22'(lG15(X1),lG15(X3))) [avatar definition]
652. '$generated@@24'(lG15(X0)) = '$generated@@24'('$generated@@22'(lG15(X1),lG15(X3))) <- (33) [avatar component clause 651]
653. 32 | 33 [avatar split clause 646,651,648]
657. lG26(X16) = lG15('$generated@@144') <- (32) [superposition 298,649]
668. '$generated@@8' = lG15(X42) <- (32) [superposition 306,649]
752. 3 = '$generated@@11'(lG15(X115)) <- (32) [superposition 321,649]
759. lG15('$generated@@144') = '$generated@@19'(lG15(X16)) <- (32) [backward demodulation 285,657]
855. lG15('$generated@@144') = '$generated@@19'('$generated@@8') <- (32) [backward demodulation 759,668]
884. 7 = '$generated@@11'('$generated@@8') <- (32) [backward demodulation 318,668]
891. '$generated@@6' = '$generated@@19'('$generated@@8') <- (32) [backward demodulation 323,668]
908. '$generated@@8' = '$generated@@19'('$generated@@8') <- (32) [forward demodulation 855,668]
942. '$generated@@8' = '$generated@@6' <- (32) [backward demodulation 908,891]
953. '$generated@@6' = lG15(X42) <- (32) [backward demodulation 668,942]
959. 7 = '$generated@@11'('$generated@@6') <- (32) [backward demodulation 884,942]
1026. '$generated@@11'('$generated@@6') = 3 <- (32) [forward demodulation 752,953]
1027. 7 = 3 <- (32) [forward demodulation 1026,959]
1028. $false <- (32) [evaluation 1027]
1029. ~32 [avatar contradiction clause 1028]
1655. '$generated@@24'(lG15(X40)) = '$generated@@24'('$generated@@22'(lG15(X41),'$generated@@4')) <- (33) [superposition 652,300]
1658. lG15(X5) = '$generated@@24'(lG15(X6)) <- (33) [superposition 652,137]
1901. '$generated@@4' = '$generated@@24'(lG15(X40)) <- (33) [forward demodulation 1655,137]
1966. '$generated@@4' = lG15(X5) <- (33) [forward demodulation 1658,1901]
2109. 7 = '$generated@@11'('$generated@@4') <- (33) [backward demodulation 318,1966]
2116. '$generated@@11'('$generated@@4') = 3 <- (33) [backward demodulation 321,1966]
2309. 7 = 3 <- (33) [forward demodulation 2116,2109]
2310. $false <- (33) [evaluation 2309]
2311. ~33 [avatar contradiction clause 2310]
2318. $false [avatar sat refutation 653,1029,2311]

Looks like the symbol names are scrambled, and the axioms are only selectively included in a deeply nested and. But a refutation can still be found.

@atomb atomb added logic An inconsistency in Dafny's logic (e.g. in the Boogie prelude) kind: bug Crashes, unsoundness, incorrect output, etc. If possible, add a `part:` label labels Aug 8, 2023
@atomb
Copy link
Member

atomb commented Aug 8, 2023

Thank you for investigating and reporting this! For completeness, would you be able to list the entire set of axioms that you removed?

@yizhou7
Copy link
Contributor Author

yizhou7 commented Aug 9, 2023

Yes sir. I added :named attributes to assertions in the SMT file. Using vampire with --output_mode ucore then would produce the conflicting sets. The following is produced by this script:

iteration  0
axiom (forall<T> a: MultiSet T, x: T :: { MultiSet#UnionOne(a, x) }
  MultiSet#UnionOne(a, x)[x] == a[x] + 1);
axiom (forall<T> a: MultiSet T, x: T, o: T :: { MultiSet#UnionOne(a,x)[o] }
  0 < MultiSet#UnionOne(a,x)[o] <==> o == x || 0 < a[o]);

iteration  1
axiom (forall<U, V> a: [U]bool, b: [U]V, t: Ty ::
  { IMap#Domain(IMap#Glue(a, b, t)) }
  IMap#Domain(IMap#Glue(a, b, t)) == a);
axiom (forall<U, V> a: [U]bool, b: [U]V, t: Ty ::
  { IMap#Elements(IMap#Glue(a, b, t)) }
  IMap#Elements(IMap#Glue(a, b, t)) == b);
axiom (forall n:int :: { ORD#FromNat(n) }
  0 <= n ==> ORD#IsNat(ORD#FromNat(n)) && ORD#Offset(ORD#FromNat(n)) == n);
axiom (forall<U, V> m: IMap U V ::
  { IMap#Domain(m) }
  m == IMap#Empty() <==> IMap#Domain(m) == ISet#Empty());
axiom (forall<U, V> m: Map U V, u: U, u': U, v: V ::
  { Map#Domain(Map#Build(m, u, v))[u'] } { Map#Elements(Map#Build(m, u, v))[u'] }
  (u' == u ==> Map#Domain(Map#Build(m, u, v))[u'] &&
               Map#Elements(Map#Build(m, u, v))[u'] == v) &&
  (u' != u ==> Map#Domain(Map#Build(m, u, v))[u'] == Map#Domain(m)[u'] &&
               Map#Elements(Map#Build(m, u, v))[u'] == Map#Elements(m)[u']));
  axiom (forall n: int ::
    { char#FromInt(n) }
    char#IsChar(n) ==> char#ToInt(char#FromInt(n)) == n);
  axiom (forall ch: char ::
    { char#ToInt(ch) }
    char#FromInt(char#ToInt(ch)) == ch &&
    char#IsChar(char#ToInt(ch)));

iteration  2
axiom (forall<U, V> a: [U]bool, b: [U]V, t: Ty ::
  { Map#Domain(Map#Glue(a, b, t)) }
  Map#Domain(Map#Glue(a, b, t)) == a);
axiom (forall<U, V> a: [U]bool, b: [U]V, t: Ty ::
  { Map#Elements(Map#Glue(a, b, t)) }
  Map#Elements(Map#Glue(a, b, t)) == b);
  m == Map#Empty() || (exists k: U :: Map#Domain(m)[k]));
function {:identity} Lit<T>(x: T): T { x } uses {
  axiom (forall<T> x: T :: { $Box(Lit(x)) } $Box(Lit(x)) == Lit($Box(x)) );
function {:identity} Lit<T>(x: T): T { x } uses {
  axiom (forall<T> x: T :: { $Box(Lit(x)) } $Box(Lit(x)) == Lit($Box(x)) );
axiom (forall<T> v : T, t : Ty ::
    { $IsBox($Box(v), t) }
    ( $IsBox($Box(v), t) <==> $Is(v,t) ));
  axiom (forall<T> x : T :: { $Box(x) } $Unbox($Box(x)) == x);
axiom (forall<U, V> m: IMap U V, u: U, u': U, v: V ::
  { IMap#Domain(IMap#Build(m, u, v))[u'] } { IMap#Elements(IMap#Build(m, u, v))[u'] }
  (u' == u ==> IMap#Domain(IMap#Build(m, u, v))[u'] &&
               IMap#Elements(IMap#Build(m, u, v))[u'] == v) &&
  (u' != u ==> IMap#Domain(IMap#Build(m, u, v))[u'] == IMap#Domain(m)[u'] &&
               IMap#Elements(IMap#Build(m, u, v))[u'] == IMap#Elements(m)[u']));
axiom (forall<T> o: T :: { ISet#Empty()[o] } !ISet#Empty()[o]);
axiom (forall bx : Box ::
    { $IsBox(bx, TBool) }
    ( $IsBox(bx, TBool) ==> $Box($Unbox(bx) : bool) == bx && $Is($Unbox(bx) : bool, TBool)));
  axiom (forall<T> x: T :: { $Box(Lit(x)) } $Box(Lit(x)) == Lit($Box(x)) );
    axiom(forall v : bool :: { $Is(v,TBool) } $Is(v,TBool));

iteration  3
axiom (forall<T> a, b: MultiSet T ::
  { MultiSet#Card(MultiSet#Difference(a, b)) }
  MultiSet#Card(MultiSet#Difference(a, b)) + MultiSet#Card(MultiSet#Difference(b, a))
  + 2 * MultiSet#Card(MultiSet#Intersection(a, b))
    == MultiSet#Card(MultiSet#Union(a, b)) &&
  MultiSet#Card(MultiSet#Difference(a, b)) == MultiSet#Card(a) - MultiSet#Card(MultiSet#Intersection(a, b)));
axiom (forall a: int :: { Math#clip(a) } 0 <= a ==> Math#clip(a) == a);
  (MultiSet#Card(s) != 0 ==> (exists x: T :: 0 < s[x])));
axiom (forall<T> a: MultiSet T, b: MultiSet T :: { MultiSet#Card(MultiSet#Union(a,b)) }
  MultiSet#Card(MultiSet#Union(a,b)) == MultiSet#Card(a) + MultiSet#Card(b));
axiom (forall<T> o: T :: { MultiSet#Empty()[o] } MultiSet#Empty()[o] == 0);
axiom (forall<T> s: MultiSet T :: { MultiSet#Card(s) } 0 <= MultiSet#Card(s));
axiom (forall<T> a: MultiSet T, b: MultiSet T, o: T :: { MultiSet#Intersection(a,b)[o] }
  MultiSet#Intersection(a,b)[o] == Math#min(a[o],  b[o]));
axiom (forall<T> r: T :: { Set#Card(Set#Singleton(r)) } Set#Card(Set#Singleton(r)) == 1);
axiom (forall<T> s: Set T :: { MultiSet#Card(MultiSet#FromSet(s)) }
  MultiSet#Card(MultiSet#FromSet(s)) == Set#Card(s));
axiom (forall a: int, b: int :: { Math#min(a, b) } b <= a <==> Math#min(a, b) == b);
axiom (forall a: int :: { Math#clip(a) } a < 0  ==> Math#clip(a) == 0);

I think it is possible that these sets are not minimized. I did not attempt to perform deeper manual inspection other than the first one.

@zafer-esen
Copy link
Collaborator

I was looking at the refutation and noticed the following, maybe it would provide some context.

The multiset is encoded as an array from Box to int. Given some multiset a, and index i, $select(a, i) returns the Box value at i in a. In the prelude the notation a[i] is equivalent. I assume $less is < with its regular interpretation. Consider the following line in the refutation.

1743. $less(0,$select('MultiSet#UnionOne_12626'(X2,X1),X1)) [equality resolution 1410]

which eventually becomes a contradiction

2258. $less(0,0) [superposition 2253,416]

i.e., $select('MultiSet#UnionOne_12626'(X2,X1),X1) = 0.

From the prelude

// union-ing increases count by one
axiom (forall<T> a: MultiSet T, x: T :: { MultiSet#UnionOne(a, x) }
  MultiSet#UnionOne(a, x)[x] == a[x] + 1);

This implies $select('MultiSet#UnionOne_12626'(X2,X1),X1) = $select(X2, X1) + 1

Combining with the refutation above, we end up with $select(X2, X1) = -1. As I understand this cannot happen in a good multiset, which is guaranteed by this axiom in DafnyPrelude.bpl (unless the multiset is built from a sequence, which has a separate axiom):

axiom (forall v: MultiSet Box, t0: Ty :: { $Is(v, TMultiSet(t0)) }
  $Is(v, TMultiSet(t0)) ==> $IsGoodMultiSet(v));

I do not see why this axiom is not doing its job though, maybe related to polymorphism + boxes?

Btw it might be interesting to see what happens with the other encodings. Dafny does not currently use the monomorphic encoding (which Boogie uses by default). Could you perhaps try the following?

dotnet tool run boogie DafnyPrelude.bpl /typeEncoding:a /proverLog:DafnyPrelude.smt2
dotnet tool run boogie DafnyPrelude.bpl /typeEncoding:p /proverLog:DafnyPrelude.smt2

I believe this experiment would not work directly from Dafny due to pruning, and there is currently no way to disable pruning through an option in Dafny. Printing a Boogie file and using Boogie on that should work though! In Boogie pruning is off by default.

@yizhou7
Copy link
Contributor Author

yizhou7 commented Aug 9, 2023

Interesting, vampire wasn't able to find a refutation (in 60 seconds) if the predicates option for type encoding was used.

vampire reports one set for the arguments option. The first two asserts don't have corresponding axioms in the prelude. I am not familiar with Boogie encoding, I am guessing that these are axioms Boogie introduced for the type encoding, and map respectively?

(assert (! (and (and (and (and (and (and (and (and (= (Ctor boolType) 0) (= (Ctor intType) 1)) (= (Ctor realType) 2)) (forall ((arg0 Bool)) (! (= (U_2_bool (bool_2_U arg0)) arg0) :qid |typeInv:U_2_bool| :pattern ((bool_2_U arg0))))) (forall ((x T@U)) (! (= (bool_2_U (U_2_bool x)) x) :qid |cast:U_2_bool| :pattern ((U_2_bool x))))) (forall ((arg0@@0 Int)) (! (= (U_2_int (int_2_U arg0@@0)) arg0@@0) :qid |typeInv:U_2_int| :pattern ((int_2_U arg0@@0))))) (forall ((x@@0 T@U)) (! (= (int_2_U (U_2_int x@@0)) x@@0) :qid |cast:U_2_int| :pattern ((U_2_int x@@0))))) (forall ((arg0@@1 Real)) (! (= (U_2_real (real_2_U arg0@@1)) arg0@@1) :qid |typeInv:U_2_real| :pattern ((real_2_U arg0@@1))))) (forall ((x@@1 T@U)) (! (= (real_2_U (U_2_real x@@1)) x@@1) :qid |cast:U_2_real| :pattern ((U_2_real x@@1))))) :named unsat-cores-dump-name-226))
(assert (! (and (forall ((t0 T@T) (t1 T@T) (val T@U) (m T@U) (x0 T@U)) (! (= (MapType0Select t0 t1 (MapType0Store t0 t1 m x0 val) x0) val) :qid |mapAx0:MapType0Select| :weight 0)) (forall ((u0 T@T) (u1 T@T) (val@@0 T@U) (m@@0 T@U) (x0@@0 T@U) (y0 T@U)) (! (or (= x0@@0 y0) (= (MapType0Select u0 u1 (MapType0Store u0 u1 m@@0 x0@@0 val@@0) y0) (MapType0Select u0 u1 m@@0 y0))) :qid |mapAx1:MapType0Select:0| :weight 0))) :named unsat-cores-dump-name-228))

The remaining two asserts correspond to the same two axioms reported above.

axiom (forall<T> a: MultiSet T, x: T :: { MultiSet#UnionOne(a, x) }
  MultiSet#UnionOne(a, x)[x] == a[x] + 1);
axiom (forall<T> a: MultiSet T, x: T, o: T :: { MultiSet#UnionOne(a,x)[o] }
  0 < MultiSet#UnionOne(a,x)[o] <==> o == x || 0 < a[o]);

If I remove all four, vampire wasn't able to find more. However the first one seems quite fundamental to the encoding?

@jtristan jtristan self-assigned this Sep 15, 2023
@RustanLeino
Copy link
Collaborator

Thanks for finding this bug, @yizhou7! Here is a different example that lets you prove false: add the following procedure to DafnyPrelude.bpl:

procedure False()
  ensures false;
{
  var bx: Box;
  var s: MultiSet Box;
  var u: MultiSet Box;

  bx := $Box(0);
  s := MultiSet#Singleton(bx);

  s := s[bx := -10];
  u := MultiSet#UnionOne(s, bx);
  assert u[bx] == -9; // by "union-ing increases count by one" axiom
  assert 0 <= u[bx]; // by "pure containment axiom" axiom

  assert false;
}

The multiset axioms seem to be missing some kind of $IsGoodMultiset antecedents.

@zafer-esen
Copy link
Collaborator

zafer-esen commented Sep 15, 2023

For the example above that @RustanLeino gave, changing the containment axiom as follows fixes this, but I suspect this is not the only issue (and probably not a good fix):

// pure containment axiom (in the original multiset or is the added element)
axiom (forall<T> a: MultiSet T, x: T, o: T :: { MultiSet#UnionOne(a,x)[o] }
  0 < MultiSet#UnionOne(a,x)[o] <==> (o == x && 0 <= a[o]) || 0 < a[o]);

(Added 0 <= a[o] to the lhs of the disjunct.)

@keyboardDrummer keyboardDrummer added the during 3: execution of incorrect program An bug in the verifier that allows Dafny to run a program that does not correctly implement its spec label Feb 7, 2024
@keyboardDrummer keyboardDrummer added the priority: not yet Will reconsider working on this when we're looking for work label Feb 21, 2024
@atomb atomb self-assigned this Mar 4, 2024
@atomb
Copy link
Member

atomb commented Mar 21, 2024

The following stripped down version of the prelude is kind of like iterations 1 and 2 above, and verifies (proving false) with Vampire.

type Ty;

type Box;

// Note: making this an abstract type gets rid of the contradiction
type ORDINAL = Box;  // :| There are more big ordinals than boxes

function ORD#IsNat(ORDINAL): bool;
function ORD#Offset(ORDINAL): int;
function ORD#FromNat(int): ORDINAL;

axiom (forall n:int :: { ORD#FromNat(n) }
  0 <= n ==> /*ORD#IsNat(ORD#FromNat(n)) &&*/ ORD#Offset(ORD#FromNat(n)) == n);

type Set = [Box]bool;
function Set#Card(Set): int;

type Map;

function Map#Domain(Map) : Set;
function Map#Elements(Map) : [Box]Box;
function Map#Card(Map) : int;
function Map#Empty(): Map;
function Map#Values(Map) : Set;
function Map#Glue([Box]bool, [Box]Box, Ty): Map;
function Map#Build(Map, Box, Box): Map;

axiom (forall m: Map ::
  { Map#Domain(m) }
  m == Map#Empty() || (exists k: Box :: Map#Domain(m)[k]));

axiom (forall u: Box ::
        { Map#Domain(Map#Empty(): Map)[u] }
        !Map#Domain(Map#Empty(): Map)[u]);

axiom (forall a: [Box]bool, b: [Box]Box, t: Ty ::
  { Map#Domain(Map#Glue(a, b, t)) }
  Map#Domain(Map#Glue(a, b, t)) == a);

axiom (forall a: [Box]bool, b: [Box]Box, t: Ty ::
  { Map#Elements(Map#Glue(a, b, t)) }
  Map#Elements(Map#Glue(a, b, t)) == b);

// Contradiction goes away by commenting out the first conjunct, but not the second.
axiom (forall m: Map, u: Box, u': Box, v: Box ::
  { Map#Domain(Map#Build(m, u, v))[u'] }
  { Map#Elements(Map#Build(m, u, v))[u'] }
  (u' == u ==> Map#Domain(Map#Build(m, u, v))[u'] &&
               Map#Elements(Map#Build(m, u, v))[u'] == v) &&
  (u' != u ==> Map#Domain(Map#Build(m, u, v))[u'] == Map#Domain(m)[u'] &&
               Map#Elements(Map#Build(m, u, v))[u'] == Map#Elements(m)[u']));

axiom (forall m: Map, u: Box, v: Box :: { Map#Card(Map#Build(m, u, v)) }
  Map#Domain(m)[u] ==> Map#Card(Map#Build(m, u, v)) == Map#Card(m));

axiom (forall m: Map, u: Box, v: Box :: { Map#Card(Map#Build(m, u, v)) }
  !Map#Domain(m)[u] ==> Map#Card(Map#Build(m, u, v)) == Map#Card(m) + 1);

procedure ProveFalse()
  ensures false;
{
}

A very interesting thing I observed. however, is that removing the = Box from the type declaration for ORDINAL makes Vampire unable to find a proof (at least in the time I waited, and it can find one in a small fraction of a second with the = Box in place).

The comment after it shows that someone was already skeptical about it. :)

I'm going to see whether anything fails with the definition for ORDINAL removed.

@MikaelMayer
Copy link
Member

Is it the minimal file already, i.e. if you remove any other declarations, will it stop managing proving false?

@atomb
Copy link
Member

atomb commented Mar 22, 2024

Is it the minimal file already, i.e. if you remove any other declarations, will it stop managing proving false?

Yes, unless I'm misremembering.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
during 3: execution of incorrect program An bug in the verifier that allows Dafny to run a program that does not correctly implement its spec introduced: pre-2009 kind: bug Crashes, unsoundness, incorrect output, etc. If possible, add a `part:` label logic An inconsistency in Dafny's logic (e.g. in the Boogie prelude) priority: not yet Will reconsider working on this when we're looking for work
Projects
None yet
Development

No branches or pull requests

7 participants