From da7df10c1113af3f9d33e632ad582d51369c9676 Mon Sep 17 00:00:00 2001 From: Christoph Schwering Date: Tue, 4 Jul 2017 13:41:16 +0200 Subject: [PATCH] Complete rewrite of Grounder. The new grounder closely follows the procedure in the extended arXiv version of the IJCAI-17 paper, except that names for quantifiers in the query are pre-allocated. Consistency guarantees are not yet considered, which also causes some guarantee-related unit tests to fail. This is awkward since the grounder knowing about consistency should only affect performance, not semantics. Also dropped the convention that non-const getters return a pointer: it's too annoying. For out- or in/out-parameters the pointer convention remains. --- examples/tui/battleship.h | 4 +- examples/tui/example-battleship-4x4.limbo | 197 ---- examples/tui/sudoku.h | 2 +- examples/tui/test-qbf-1.limbo | 122 ++- examples/tui/test-qbf-10.limbo | 150 +-- examples/tui/test-qbf-11.limbo | 122 ++- examples/tui/test-qbf-12.limbo | 150 +-- examples/tui/test-qbf-13.limbo | 150 +-- examples/tui/test-qbf-14.limbo | 30 +- examples/tui/test-qbf-15.limbo | 22 +- examples/tui/test-qbf-16.limbo | 58 +- examples/tui/test-qbf-17.limbo | 37 +- examples/tui/test-qbf-2.limbo | 122 ++- examples/tui/test-qbf-3.limbo | 122 ++- examples/tui/test-qbf-4.limbo | 59 +- examples/tui/test-qbf-5.limbo | 88 +- examples/tui/test-qbf-6.limbo | 150 +-- examples/tui/test-qbf-7.limbo | 150 +-- examples/tui/test-qbf-8.limbo | 122 ++- examples/tui/test-qbf-9.limbo | 150 +-- examples/tui/tui-js.cc | 4 +- examples/tui/tui.cc | 4 +- src/limbo/format/pdl/context.h | 2 +- src/limbo/format/pdl/parser.h | 10 +- src/limbo/formula.h | 143 +-- src/limbo/grounder.h | 1218 ++++++++++++++------- src/limbo/internal/intmap.h | 104 +- src/limbo/internal/iter.h | 243 +++- src/limbo/internal/linked.h | 81 -- src/limbo/internal/traits.h | 10 +- src/limbo/kb.h | 132 ++- src/limbo/literal.h | 12 +- src/limbo/setup.h | 214 ++-- src/limbo/solver.h | 301 +++-- src/limbo/term.h | 7 +- tests/CMakeLists.txt | 2 +- tests/grounder.cc | 145 ++- tests/iter.cc | 55 + tests/kb.cc | 58 +- tests/linked.cc | 82 -- tests/solver.cc | 10 +- tests/term.cc | 44 +- 42 files changed, 2696 insertions(+), 2192 deletions(-) delete mode 100644 examples/tui/example-battleship-4x4.limbo delete mode 100644 src/limbo/internal/linked.h delete mode 100644 tests/linked.cc diff --git a/examples/tui/battleship.h b/examples/tui/battleship.h index 070d461..588680b 100644 --- a/examples/tui/battleship.h +++ b/examples/tui/battleship.h @@ -259,8 +259,8 @@ struct BattleshipCallbacks { const limbo::Term Water = ctx->CreateTerm(ctx->LookupFunction("water"), {t}); const limbo::Term Fired = ctx->CreateTerm(ctx->LookupFunction("fired"), {t}); const limbo::Term True = ctx->LookupName("T"); - ctx->kb()->Add(limbo::Clause{is_water ? limbo::Literal::Eq(Water, True) : limbo::Literal::Neq(Water, True)}); - ctx->kb()->Add(limbo::Clause{limbo::Literal::Eq(Fired, True)}); + ctx->kb().Add(limbo::Clause{is_water ? limbo::Literal::Eq(Water, True) : limbo::Literal::Neq(Water, True)}); + ctx->kb().Add(limbo::Clause{limbo::Literal::Eq(Fired, True)}); } Point Lookup(limbo::Term t) { diff --git a/examples/tui/example-battleship-4x4.limbo b/examples/tui/example-battleship-4x4.limbo deleted file mode 100644 index bac30d1..0000000 --- a/examples/tui/example-battleship-4x4.limbo +++ /dev/null @@ -1,197 +0,0 @@ -// A 4x4-battleship game with a 3-ship and a 2-ship. -// The output of the game is very limited; sorry for that. - -Call: disable_query_logging() - -Sort BOOL -Name T -> BOOL - -Sort POS -Name p00, p10, p20, p30, p40, p50, - p01, p11, p21, p31, p41, p51, - p02, p12, p22, p32, p42, p52, - p03, p13, p23, p33, p43, p53, - p04, p14, p24, p34, p44, p54, - p05, p15, p25, p35, p45, p55 -> POS -Var p, q -> POS -Fun field/1 -> BOOL -Fun n/1, e/1, s/1, w/1, ne/1, se/1, sw/1, nw/1 -> POS - -KB: p=p11 v p=p21 v p=p31 v p=p41 v - p=p12 v p=p22 v p=p32 v p=p42 v - p=p13 v p=p23 v p=p33 v p=p43 v - p=p14 v p=p24 v p=p34 v p=p44 v ~field(p)=T - -KB: field(p11)=T KB: field(p21)=T KB: field(p31)=T KB: field(p41)=T -KB: field(p12)=T KB: field(p22)=T KB: field(p32)=T KB: field(p42)=T -KB: field(p13)=T KB: field(p23)=T KB: field(p33)=T KB: field(p43)=T -KB: field(p14)=T KB: field(p24)=T KB: field(p34)=T KB: field(p44)=T - -KB: n(p01)=p00 KB: n(p11)=p10 KB: n(p21)=p20 KB: n(p31)=p30 KB: n(p41)=p40 KB: n(p51)=p50 -KB: n(p02)=p01 KB: n(p12)=p11 KB: n(p22)=p21 KB: n(p32)=p31 KB: n(p42)=p41 KB: n(p52)=p51 -KB: n(p03)=p02 KB: n(p13)=p12 KB: n(p23)=p22 KB: n(p33)=p32 KB: n(p43)=p42 KB: n(p53)=p52 -KB: n(p04)=p03 KB: n(p14)=p13 KB: n(p24)=p23 KB: n(p34)=p33 KB: n(p44)=p43 KB: n(p54)=p53 -KB: n(p05)=p04 KB: n(p15)=p14 KB: n(p25)=p24 KB: n(p35)=p34 KB: n(p45)=p44 KB: n(p55)=p54 - -KB: e(p00)=p10 KB: e(p10)=p20 KB: e(p20)=p30 KB: e(p30)=p40 KB: e(p40)=p50 -KB: e(p01)=p11 KB: e(p11)=p21 KB: e(p21)=p31 KB: e(p31)=p41 KB: e(p41)=p51 -KB: e(p02)=p12 KB: e(p12)=p22 KB: e(p22)=p32 KB: e(p32)=p42 KB: e(p42)=p52 -KB: e(p03)=p13 KB: e(p13)=p23 KB: e(p23)=p33 KB: e(p33)=p43 KB: e(p43)=p53 -KB: e(p04)=p14 KB: e(p14)=p24 KB: e(p24)=p34 KB: e(p34)=p44 KB: e(p44)=p54 -KB: e(p05)=p15 KB: e(p15)=p25 KB: e(p25)=p35 KB: e(p35)=p45 KB: e(p45)=p55 - -KB: s(p00)=p01 KB: s(p10)=p11 KB: s(p20)=p21 KB: s(p30)=p31 KB: s(p40)=p41 KB: s(p50)=p51 -KB: s(p01)=p02 KB: s(p11)=p12 KB: s(p21)=p22 KB: s(p31)=p32 KB: s(p41)=p42 KB: s(p51)=p52 -KB: s(p02)=p03 KB: s(p12)=p13 KB: s(p22)=p23 KB: s(p32)=p33 KB: s(p42)=p43 KB: s(p52)=p53 -KB: s(p03)=p04 KB: s(p13)=p14 KB: s(p23)=p24 KB: s(p33)=p34 KB: s(p43)=p44 KB: s(p53)=p54 -KB: s(p04)=p05 KB: s(p14)=p15 KB: s(p24)=p25 KB: s(p34)=p35 KB: s(p44)=p45 KB: s(p54)=p55 - -KB: w(p10)=p00 KB: w(p20)=p10 KB: w(p30)=p20 KB: w(p40)=p30 KB: w(p50)=p40 -KB: w(p11)=p01 KB: w(p21)=p11 KB: w(p31)=p21 KB: w(p41)=p31 KB: w(p51)=p41 -KB: w(p12)=p02 KB: w(p22)=p12 KB: w(p32)=p22 KB: w(p42)=p32 KB: w(p52)=p42 -KB: w(p13)=p03 KB: w(p23)=p13 KB: w(p33)=p23 KB: w(p43)=p33 KB: w(p53)=p43 -KB: w(p14)=p04 KB: w(p24)=p14 KB: w(p34)=p24 KB: w(p44)=p34 KB: w(p54)=p44 -KB: w(p15)=p05 KB: w(p25)=p15 KB: w(p35)=p25 KB: w(p45)=p35 KB: w(p55)=p45 - -KB: ne(p01)=p10 KB: ne(p11)=p20 KB: ne(p21)=p30 KB: ne(p31)=p40 KB: ne(p41)=p50 -KB: ne(p02)=p11 KB: ne(p12)=p21 KB: ne(p22)=p31 KB: ne(p32)=p41 KB: ne(p42)=p51 -KB: ne(p03)=p12 KB: ne(p13)=p22 KB: ne(p23)=p32 KB: ne(p33)=p42 KB: ne(p43)=p52 -KB: ne(p04)=p13 KB: ne(p14)=p23 KB: ne(p24)=p33 KB: ne(p34)=p43 KB: ne(p44)=p53 -KB: ne(p05)=p14 KB: ne(p15)=p24 KB: ne(p25)=p34 KB: ne(p35)=p44 KB: ne(p45)=p54 - -KB: se(p00)=p11 KB: se(p10)=p21 KB: se(p20)=p31 KB: se(p30)=p41 KB: se(p40)=p51 -KB: se(p01)=p12 KB: se(p11)=p22 KB: se(p21)=p32 KB: se(p31)=p42 KB: se(p41)=p52 -KB: se(p02)=p13 KB: se(p12)=p23 KB: se(p22)=p33 KB: se(p32)=p43 KB: se(p42)=p53 -KB: se(p03)=p14 KB: se(p13)=p24 KB: se(p23)=p34 KB: se(p33)=p44 KB: se(p43)=p54 -KB: se(p04)=p15 KB: se(p14)=p25 KB: se(p24)=p35 KB: se(p34)=p45 KB: se(p44)=p55 - -KB: sw(p10)=p01 KB: sw(p20)=p11 KB: sw(p30)=p21 KB: sw(p40)=p31 KB: sw(p50)=p41 -KB: sw(p11)=p02 KB: sw(p21)=p12 KB: sw(p31)=p22 KB: sw(p41)=p32 KB: sw(p51)=p42 -KB: sw(p12)=p03 KB: sw(p22)=p13 KB: sw(p32)=p23 KB: sw(p42)=p33 KB: sw(p52)=p43 -KB: sw(p13)=p04 KB: sw(p23)=p14 KB: sw(p33)=p24 KB: sw(p43)=p34 KB: sw(p53)=p44 -KB: sw(p14)=p05 KB: sw(p24)=p15 KB: sw(p34)=p25 KB: sw(p44)=p35 KB: sw(p54)=p45 - -KB: nw(p11)=p00 KB: nw(p21)=p10 KB: nw(p31)=p20 KB: nw(p41)=p30 KB: nw(p51)=p40 -KB: nw(p12)=p01 KB: nw(p22)=p11 KB: nw(p32)=p21 KB: nw(p42)=p31 KB: nw(p52)=p41 -KB: nw(p13)=p02 KB: nw(p23)=p12 KB: nw(p33)=p22 KB: nw(p43)=p32 KB: nw(p53)=p42 -KB: nw(p14)=p03 KB: nw(p24)=p13 KB: nw(p34)=p23 KB: nw(p44)=p33 KB: nw(p54)=p43 -KB: nw(p15)=p04 KB: nw(p25)=p14 KB: nw(p35)=p24 KB: nw(p45)=p34 KB: nw(p55)=p44 - -Sort SHIP -Var x, y -> SHIP -Name two, three -> SHIP -Fun head/1 -> POS -Fun body/1 -> POS -Fun tail/1 -> POS - -Fun ship/1 -> BOOL -Fun part/2 -> BOOL -Fun water/1 -> BOOL -Fun fired/1 -> BOOL - -//KB: ship(two)=T -//KB: ship(three)=T -//KB: x=two v ~x=three v ~ship(x)=T -// -//KB: part(two,head(two))=T -//KB: part(two,tail(two))=T -//KB: x=head(two) v x=tail(two) v ~part(two,x)=T -// -//KB: part(three,head(three))=T -//KB: part(three,body(three))=T -//KB: part(three,tail(three))=T -//KB: x=head(three) v x=body(three) v x=tail(three) v ~part(three,x)=T - -KB: s(head(two))=body(two) -KB: n(tail(two))=head(two) -KB: s(head(three))=body(three) -KB: n(body(three))=head(three) -KB: s(body(three))=tail(three) -KB: n(tail(three))=body(three) - -KB: ~water(head(two))=T -KB: ~water(tail(two))=T - -KB: ~water(head(three))=T -KB: ~water(body(three))=T -KB: ~water(tail(three))=T - -KB: water(n(head(two)))=T -KB: water(ne(head(two)))=T -KB: water(nw(head(two)))=T - -KB: water(s(tail(two)))=T -KB: water(se(tail(two)))=T -KB: water(sw(tail(two)))=T - -KB: water(n(head(three)))=T -KB: water(ne(head(three)))=T -KB: water(nw(head(three)))=T - -KB: water(e(body(three)))=T -KB: water(w(body(three)))=T - -KB: water(s(tail(three)))=T -KB: water(se(tail(three)))=T -KB: water(sw(tail(three)))=T - -KB: p=p11 v p=p21 v p=p31 v p=p41 v - p=p12 v p=p22 v p=p32 v p=p42 v - p=p13 v p=p23 v p=p33 v p=p43 v - p=p14 v p=p24 v p=p34 v p=p44 v - water(p)=T -// Is the next needed? Cf. 1x4. -KB: head(two)=p v tail(two)=p v head(three)=p v body(three)=p v tail(three)=p v water(p)=T - -Call: bs_init(p11, p12, p13, p14, - p21, p22, p23, p24, - p31, p32, p33, p34, - p41, p42, p43, p44) - - -// while Ex p (~K<1> water(p)=T ^ ~K<1> ~water(p)=T) { -// for P -> POS -// ~K<0> fired(P)=T ^ K<1> ~water(P)=T { -// Call: bs_fire(P) -// Call: print(P) -// } -// -// // } else if Ex p (K<1> ~fired(p)=T ^ ~K<1> ~water(p)=T ^ M<1> water(p)=T) { -// // for P in p1, p2, p3, p4 { -// // if ~K<0> fired(P)=T ^ ~K<1> ~water(P)=T ^ M<1> water(P)=T { -// // Call: bs_fire(P) -// // Call: print(P) -// // } -// // } -// -// if Ex p (~K<1> water(p)=T ^ ~K<1> ~water(p)=T) { -// if ~K<0> fired(p1)=T { -// Call: bs_fire(p1) -// } else if ~K<0> fired(p2)=T { -// Call: bs_fire(p2) -// } else if ~K<0> fired(p3)=T { -// Call: bs_fire(p3) -// } else if ~K<0> fired(p4)=T { -// Call: bs_fire(p4) -// } -// } -// Call: bs_print() -// } - -while G Ex p (~K<0> fired(p)=T ^ ~K<2> water(p)=T) { - for P in p11, p12, p13, p14, - p21, p22, p23, p24, - p31, p32, p33, p34, - p41, p42, p43, p44 -> POS G (~K<0> fired(P)=T ^ K<2> ~water(P)=T) { - Call: bs_fire(P) - Call: print(P) - } else if P in p11, p12, p13, p14, - p21, p22, p23, p24, - p31, p32, p33, p34, - p41, p42, p43, p44 -> POS G (~K<0> fired(P)=T ^ ~K<2> water(P)=T ^ ~K<2> ~water(P)=T) { - Call: bs_fire(P) - Call: print(P,P) - } - Call: bs_print() -} - diff --git a/examples/tui/sudoku.h b/examples/tui/sudoku.h index be74e48..50d15c9 100644 --- a/examples/tui/sudoku.h +++ b/examples/tui/sudoku.h @@ -33,7 +33,7 @@ struct SudokuCallbacks { for (size_t n = 0; n < ns_.size(); ++n) { const limbo::Term Val = ctx->CreateTerm(ctx->LookupFunction("val"), {ns_[x], ns_[y]}); const limbo::Clause c{limbo::Literal::Eq(Val, ns_[n])}; - bool b = ctx->kb()->Entails(*limbo::Formula::Factory::Know(0, limbo::Formula::Factory::Atomic(c))); + bool b = ctx->kb().Entails(*limbo::Formula::Factory::Know(0, limbo::Formula::Factory::Atomic(c))); if (b) { using limbo::format::operator<<; std::stringstream ss; diff --git a/examples/tui/test-qbf-1.limbo b/examples/tui/test-qbf-1.limbo index 0d76bca..142e2a6 100644 --- a/examples/tui/test-qbf-1.limbo +++ b/examples/tui/test-qbf-1.limbo @@ -6,7 +6,7 @@ Fun x1/0, x1'/0 -> Bool Fun x3/0, x3'/0 -> Bool Fun x2/0 -> Bool Fun x4/0 -> Bool -Fun sorted1/0, sorted2/0, sorted3/0, sorted4/0, sorted5/0 -> Bool +Fun o1/0, o2/0, o3/0, o4/0, o5/0 -> Bool Fun u0'1/0, u0'2/0, u0'3/0, u0'4/0, u0'5/0 -> Bool Fun u1'1/0, u1'2/0, u1'3/0, u1'4/0, u1'5/0 -> Bool Fun u2'1/0, u2'2/0, u2'3/0, u2'4/0, u2'5/0 -> Bool @@ -16,66 +16,70 @@ Fun s1'2/0, s1'3/0, s1'4/0 -> Bool Fun s2'3/0, s2'4/0 -> Bool Fun s3'4/0 -> Bool Fun s4'4/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T v sorted3=T v sorted4=T v sorted5=T +Fun p/0 -> Bool +Let O := o1=T v o2=T v o3=T v o4=T v o5=T KB: u0'1=T KB: u0'2=T KB: u0'3=T KB: u0'4=T KB: u0'5=T -KB: ~x1=T -> pass=T -KB: ~x1'=T -> pass=T -KB: ~x2/=X -> pass=T -KB: ~x3=T -> pass=T -KB: ~x3'=T -> pass=T -KB: ~x4/=X -> pass=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ s3'4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4/=X -> Sorted -KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> Sorted -Refute: K<3> Sorted -Assert: K<4> Sorted -Assert: K<4> (Sorted ^ (~pass=T -> ((x1=T v x2=T)^ (~x2=T v x3=T)^ (x1=T v x3'=T)))) +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'5=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'5=T +KB: ~x1=T -> p=T +KB: ~x1'=T -> p=T +KB: ~x3=T -> p=T +KB: ~x3'=T -> p=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ s3'4=T -> O +KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> O +Refute: K<3> O +Assert: K<4> O +Assert: K<4> (O ^ (~p=T -> ((x1=T v x2=T)^ (~x2=T v x3=T)^ (x1=T v x3'=T)))) diff --git a/examples/tui/test-qbf-10.limbo b/examples/tui/test-qbf-10.limbo index c4f1d10..674e74a 100644 --- a/examples/tui/test-qbf-10.limbo +++ b/examples/tui/test-qbf-10.limbo @@ -6,7 +6,7 @@ Fun x1/0, x1'/0 -> Bool Fun x2/0, x2'/0 -> Bool Fun x3/0, x3'/0 -> Bool Fun x4/0, x4'/0 -> Bool -Fun sorted1/0, sorted2/0, sorted3/0, sorted4/0, sorted5/0 -> Bool +Fun o1/0, o2/0, o3/0, o4/0, o5/0 -> Bool Fun u0'1/0, u0'2/0, u0'3/0, u0'4/0, u0'5/0 -> Bool Fun u1'1/0, u1'2/0, u1'3/0, u1'4/0, u1'5/0 -> Bool Fun u2'1/0, u2'2/0, u2'3/0, u2'4/0, u2'5/0 -> Bool @@ -16,82 +16,82 @@ Fun s1'2/0, s1'3/0, s1'4/0 -> Bool Fun s2'3/0, s2'4/0 -> Bool Fun s3'4/0 -> Bool Fun s4'4/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T v sorted3=T v sorted4=T v sorted5=T +Fun p/0 -> Bool +Let O := o1=T v o2=T v o3=T v o4=T v o5=T KB: u0'1=T KB: u0'2=T KB: u0'3=T KB: u0'4=T KB: u0'5=T -KB: ~x1=T -> pass=T -KB: ~x1'=T -> pass=T -KB: ~x2=T -> pass=T -KB: ~x2'=T -> pass=T -KB: ~x3=T -> pass=T -KB: ~x3'=T -> pass=T -KB: ~x4=T -> pass=T -KB: ~x4'=T -> pass=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ s3'4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4'/=X -> Sorted -KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> Sorted -Refute: K<3> Sorted -Assert: K<4> Sorted -Refute: K<4> (Sorted ^ (~pass=T -> (x4=T^x1'=T^x2'=T^x3'=T^x4'=T))) +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'5=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'5=T +KB: ~x1=T -> p=T +KB: ~x1'=T -> p=T +KB: ~x2=T -> p=T +KB: ~x2'=T -> p=T +KB: ~x3=T -> p=T +KB: ~x3'=T -> p=T +KB: ~x4=T -> p=T +KB: ~x4'=T -> p=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ ~s2'3=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ ~s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ s2'3=T ^ s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ ~s2'3=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ ~s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ s2'3=T ^ s2'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ s3'4=T -> O +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> O +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4'=T -> O +KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> O +Refute: K<3> O +Assert: K<4> O +Refute: K<4> (O ^ (~p=T -> (x4=T^x1'=T^x2'=T^x3'=T^x4'=T))) diff --git a/examples/tui/test-qbf-11.limbo b/examples/tui/test-qbf-11.limbo index af2494d..3e9ce64 100644 --- a/examples/tui/test-qbf-11.limbo +++ b/examples/tui/test-qbf-11.limbo @@ -6,7 +6,7 @@ Fun x1/0, x1'/0 -> Bool Fun x3/0, x3'/0 -> Bool Fun x2/0 -> Bool Fun x4/0 -> Bool -Fun sorted1/0, sorted2/0, sorted3/0, sorted4/0, sorted5/0 -> Bool +Fun o1/0, o2/0, o3/0, o4/0, o5/0 -> Bool Fun u0'1/0, u0'2/0, u0'3/0, u0'4/0, u0'5/0 -> Bool Fun u1'1/0, u1'2/0, u1'3/0, u1'4/0, u1'5/0 -> Bool Fun u2'1/0, u2'2/0, u2'3/0, u2'4/0, u2'5/0 -> Bool @@ -16,66 +16,70 @@ Fun s1'2/0, s1'3/0, s1'4/0 -> Bool Fun s2'3/0, s2'4/0 -> Bool Fun s3'4/0 -> Bool Fun s4'4/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T v sorted3=T v sorted4=T v sorted5=T +Fun p/0 -> Bool +Let O := o1=T v o2=T v o3=T v o4=T v o5=T KB: u0'1=T KB: u0'2=T KB: u0'3=T KB: u0'4=T KB: u0'5=T -KB: ~x1=T -> pass=T -KB: ~x1'=T -> pass=T -KB: ~x2/=X -> pass=T -KB: ~x3=T -> pass=T -KB: ~x3'=T -> pass=T -KB: ~x4/=X -> pass=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ s3'4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4/=X -> Sorted -KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> Sorted -Refute: K<3> Sorted -Assert: K<4> Sorted -Assert: K<4> (Sorted ^ (~pass=T -> ((x1'=T v x2=T)^ (~x2=T v x3=T)^ (x1'=T v x3'=T)^x1'=T))) +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'5=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'5=T +KB: ~x1=T -> p=T +KB: ~x1'=T -> p=T +KB: ~x3=T -> p=T +KB: ~x3'=T -> p=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ s3'4=T -> O +KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> O +Refute: K<3> O +Assert: K<4> O +Assert: K<4> (O ^ (~p=T -> ((x1'=T v x2=T)^ (~x2=T v x3=T)^ (x1'=T v x3'=T)^x1'=T))) diff --git a/examples/tui/test-qbf-12.limbo b/examples/tui/test-qbf-12.limbo index c33806d..452219d 100644 --- a/examples/tui/test-qbf-12.limbo +++ b/examples/tui/test-qbf-12.limbo @@ -6,7 +6,7 @@ Fun x1/0, x1'/0 -> Bool Fun x2/0, x2'/0 -> Bool Fun x3/0, x3'/0 -> Bool Fun x4/0, x4'/0 -> Bool -Fun sorted1/0, sorted2/0, sorted3/0, sorted4/0, sorted5/0 -> Bool +Fun o1/0, o2/0, o3/0, o4/0, o5/0 -> Bool Fun u0'1/0, u0'2/0, u0'3/0, u0'4/0, u0'5/0 -> Bool Fun u1'1/0, u1'2/0, u1'3/0, u1'4/0, u1'5/0 -> Bool Fun u2'1/0, u2'2/0, u2'3/0, u2'4/0, u2'5/0 -> Bool @@ -16,82 +16,82 @@ Fun s1'2/0, s1'3/0, s1'4/0 -> Bool Fun s2'3/0, s2'4/0 -> Bool Fun s3'4/0 -> Bool Fun s4'4/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T v sorted3=T v sorted4=T v sorted5=T +Fun p/0 -> Bool +Let O := o1=T v o2=T v o3=T v o4=T v o5=T KB: u0'1=T KB: u0'2=T KB: u0'3=T KB: u0'4=T KB: u0'5=T -KB: ~x1=T -> pass=T -KB: ~x1'=T -> pass=T -KB: ~x2=T -> pass=T -KB: ~x2'=T -> pass=T -KB: ~x3=T -> pass=T -KB: ~x3'=T -> pass=T -KB: ~x4=T -> pass=T -KB: ~x4'=T -> pass=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ s3'4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4'/=X -> Sorted -KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> Sorted -Refute: K<3> Sorted -Assert: K<4> Sorted -Refute: K<4> (Sorted ^ (~pass=T -> (x4=T^x4'=T))) +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'5=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'5=T +KB: ~x1=T -> p=T +KB: ~x1'=T -> p=T +KB: ~x2=T -> p=T +KB: ~x2'=T -> p=T +KB: ~x3=T -> p=T +KB: ~x3'=T -> p=T +KB: ~x4=T -> p=T +KB: ~x4'=T -> p=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ ~s2'3=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ ~s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ s2'3=T ^ s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ ~s2'3=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ ~s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ s2'3=T ^ s2'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ s3'4=T -> O +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> O +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4'=T -> O +KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> O +Refute: K<3> O +Assert: K<4> O +Refute: K<4> (O ^ (~p=T -> (x4=T^x4'=T))) diff --git a/examples/tui/test-qbf-13.limbo b/examples/tui/test-qbf-13.limbo index ab1af52..47fcd07 100644 --- a/examples/tui/test-qbf-13.limbo +++ b/examples/tui/test-qbf-13.limbo @@ -6,7 +6,7 @@ Fun x1/0, x1'/0 -> Bool Fun x2/0, x2'/0 -> Bool Fun x3/0, x3'/0 -> Bool Fun x4/0, x4'/0 -> Bool -Fun sorted1/0, sorted2/0, sorted3/0, sorted4/0, sorted5/0 -> Bool +Fun o1/0, o2/0, o3/0, o4/0, o5/0 -> Bool Fun u0'1/0, u0'2/0, u0'3/0, u0'4/0, u0'5/0 -> Bool Fun u1'1/0, u1'2/0, u1'3/0, u1'4/0, u1'5/0 -> Bool Fun u2'1/0, u2'2/0, u2'3/0, u2'4/0, u2'5/0 -> Bool @@ -16,82 +16,82 @@ Fun s1'2/0, s1'3/0, s1'4/0 -> Bool Fun s2'3/0, s2'4/0 -> Bool Fun s3'4/0 -> Bool Fun s4'4/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T v sorted3=T v sorted4=T v sorted5=T +Fun p/0 -> Bool +Let O := o1=T v o2=T v o3=T v o4=T v o5=T KB: u0'1=T KB: u0'2=T KB: u0'3=T KB: u0'4=T KB: u0'5=T -KB: ~x1=T -> pass=T -KB: ~x1'=T -> pass=T -KB: ~x2=T -> pass=T -KB: ~x2'=T -> pass=T -KB: ~x3=T -> pass=T -KB: ~x3'=T -> pass=T -KB: ~x4=T -> pass=T -KB: ~x4'=T -> pass=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ s3'4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4'/=X -> Sorted -KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> Sorted -Refute: K<3> Sorted -Assert: K<4> Sorted -Assert: K<4> (Sorted ^ (~pass=T -> (x1=T^x2=T^x3=T^x4=T))) +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'5=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'5=T +KB: ~x1=T -> p=T +KB: ~x1'=T -> p=T +KB: ~x2=T -> p=T +KB: ~x2'=T -> p=T +KB: ~x3=T -> p=T +KB: ~x3'=T -> p=T +KB: ~x4=T -> p=T +KB: ~x4'=T -> p=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ ~s2'3=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ ~s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ s2'3=T ^ s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ ~s2'3=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ ~s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ s2'3=T ^ s2'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ s3'4=T -> O +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> O +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4'=T -> O +KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> O +Refute: K<3> O +Assert: K<4> O +Assert: K<4> (O ^ (~p=T -> (x1=T^x2=T^x3=T^x4=T))) diff --git a/examples/tui/test-qbf-14.limbo b/examples/tui/test-qbf-14.limbo index afe2fc3..8f2cb58 100644 --- a/examples/tui/test-qbf-14.limbo +++ b/examples/tui/test-qbf-14.limbo @@ -3,23 +3,23 @@ Call: disable_distribute() Sort Bool Name T, X -> Bool Fun x1/0, x1'/0 -> Bool -Fun sorted1/0, sorted2/0 -> Bool +Fun o1/0, o2/0 -> Bool Fun u0'1/0, u0'2/0 -> Bool Fun u1'1/0, u1'2/0 -> Bool Fun s1'1/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T +Fun p/0 -> Bool +Let O := o1=T v o2=T KB: u0'1=T KB: u0'2=T -KB: ~x1=T -> pass=T -KB: ~x1'=T -> pass=T -KB: u0'1=T ^ u0'2=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ x1'/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ x1'/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ ~x1/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ ~x1'/=X -> Sorted -KB: u1'1=T ^ u1'2=T -> Sorted -Refute: K<0> Sorted -Assert: K<1> Sorted -Assert: K<1> (Sorted ^ (~pass=T -> (x1=T))) +KB: u0'1=T ^ u0'2=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ x1'=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ x1'=T -> u1'2=T +KB: ~x1=T -> p=T +KB: ~x1'=T -> p=T +KB: u0'1=T ^ u0'2=T ^ ~x1=T -> O +KB: u0'1=T ^ u0'2=T ^ ~x1'=T -> O +KB: u1'1=T ^ u1'2=T -> O +Refute: K<0> O +Assert: K<1> O +Assert: K<1> (O ^ (~p=T -> (x1=T))) diff --git a/examples/tui/test-qbf-15.limbo b/examples/tui/test-qbf-15.limbo index 7c10a89..f9f4ecc 100644 --- a/examples/tui/test-qbf-15.limbo +++ b/examples/tui/test-qbf-15.limbo @@ -3,19 +3,19 @@ Call: disable_distribute() Sort Bool Name T, X -> Bool Fun x1/0 -> Bool -Fun sorted1/0, sorted2/0 -> Bool +Fun o1/0, o2/0 -> Bool Fun u0'1/0, u0'2/0 -> Bool Fun u1'1/0, u1'2/0 -> Bool Fun s1'1/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T +Fun p/0 -> Bool +Let O := o1=T v o2=T KB: u0'1=T KB: u0'2=T -KB: ~x1/=X -> pass=T -KB: u0'1=T ^ u0'2=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ ~x1/=X -> Sorted -KB: u1'1=T ^ u1'2=T -> Sorted -Refute: K<0> Sorted -Assert: K<1> Sorted -Assert: K<1> (Sorted ^ (~pass=T -> (x1=T v ~x1=T))) +KB: u0'1=T ^ u0'2=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ ~x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ ~x1=T -> u1'2=T +KB: u1'1=T ^ u1'2=T -> O +Refute: K<0> O +Assert: K<1> O +Assert: K<1> (O ^ (~p=T -> (x1=T v ~x1=T))) diff --git a/examples/tui/test-qbf-16.limbo b/examples/tui/test-qbf-16.limbo index 3cb9952..d0f7c58 100644 --- a/examples/tui/test-qbf-16.limbo +++ b/examples/tui/test-qbf-16.limbo @@ -4,40 +4,40 @@ Sort Bool Name T, X -> Bool Fun x1/0, x1'/0 -> Bool Fun x2/0, x2'/0 -> Bool -Fun sorted1/0, sorted2/0, sorted3/0 -> Bool +Fun o1/0, o2/0, o3/0 -> Bool Fun u0'1/0, u0'2/0, u0'3/0 -> Bool Fun u1'1/0, u1'2/0, u1'3/0 -> Bool Fun u2'1/0, u2'2/0, u2'3/0 -> Bool Fun s1'2/0 -> Bool Fun s2'2/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T v sorted3=T +Fun p/0 -> Bool +Let O := o1=T v o2=T v o3=T KB: u0'1=T KB: u0'2=T KB: u0'3=T -KB: ~x1=T -> pass=T -KB: ~x1'=T -> pass=T -KB: ~x2=T -> pass=T -KB: ~x2'=T -> pass=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1'/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1'/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1'/=X -> u1'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2'/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2'/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2'/=X -> u2'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ ~x1/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ ~x1/=X ^ s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ ~x1'/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ ~x1'/=X ^ s1'2/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ ~x2/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ ~x2'/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T -> Sorted -Refute: K<1> Sorted -Assert: K<2> Sorted -Assert: K<2> (Sorted ^ (~pass=T -> (x1=T^x2=T))) +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1'=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1'=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1'=T -> u1'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2'=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2'=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2'=T -> u2'3=T +KB: ~x1=T -> p=T +KB: ~x1'=T -> p=T +KB: ~x2=T -> p=T +KB: ~x2'=T -> p=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ ~x1=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ ~x1=T ^ s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ ~x1'=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ ~x1'=T ^ s1'2=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ ~x2=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ ~x2'=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T -> O +Refute: K<1> O +Assert: K<2> O +Assert: K<2> (O ^ (~p=T -> (x1=T^x2=T))) diff --git a/examples/tui/test-qbf-17.limbo b/examples/tui/test-qbf-17.limbo index 64f0017..73d0639 100644 --- a/examples/tui/test-qbf-17.limbo +++ b/examples/tui/test-qbf-17.limbo @@ -4,29 +4,30 @@ Sort Bool Name T, X -> Bool Fun x1/0 -> Bool Fun x2/0 -> Bool -Fun sorted1/0, sorted2/0, sorted3/0 -> Bool +Fun o1/0, o2/0, o3/0 -> Bool Fun u0'1/0, u0'2/0, u0'3/0 -> Bool Fun u1'1/0, u1'2/0, u1'3/0 -> Bool Fun u2'1/0, u2'2/0, u2'3/0 -> Bool Fun s1'2/0 -> Bool Fun s2'2/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T v sorted3=T +Fun p/0 -> Bool +Let O := o1=T v o2=T v o3=T KB: u0'1=T KB: u0'2=T KB: u0'3=T -KB: ~x1/=X -> pass=T -KB: ~x2/=X -> pass=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1/=X -> u1'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2/=X -> u2'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ ~x1/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ ~x1/=X ^ s1'2/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ ~x2/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T -> Sorted -Refute: K<1> Sorted -Assert: K<2> Sorted -Assert: K<2> (Sorted ^ (~pass=T -> ((x1=T v ~x1=T)^ (x2=T v ~x2=T)))) +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ ~x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ ~x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ ~x1=T -> u1'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ ~x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ ~x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ ~x2=T -> u2'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T -> O +Refute: K<1> O +Assert: K<2> O +Assert: K<2> (O ^ (~p=T -> ((x1=T v ~x1=T)^ (x2=T v ~x2=T)))) diff --git a/examples/tui/test-qbf-2.limbo b/examples/tui/test-qbf-2.limbo index daaa65a..0a2e3a3 100644 --- a/examples/tui/test-qbf-2.limbo +++ b/examples/tui/test-qbf-2.limbo @@ -6,7 +6,7 @@ Fun x1/0, x1'/0 -> Bool Fun x3/0, x3'/0 -> Bool Fun x2/0 -> Bool Fun x4/0 -> Bool -Fun sorted1/0, sorted2/0, sorted3/0, sorted4/0, sorted5/0 -> Bool +Fun o1/0, o2/0, o3/0, o4/0, o5/0 -> Bool Fun u0'1/0, u0'2/0, u0'3/0, u0'4/0, u0'5/0 -> Bool Fun u1'1/0, u1'2/0, u1'3/0, u1'4/0, u1'5/0 -> Bool Fun u2'1/0, u2'2/0, u2'3/0, u2'4/0, u2'5/0 -> Bool @@ -16,66 +16,70 @@ Fun s1'2/0, s1'3/0, s1'4/0 -> Bool Fun s2'3/0, s2'4/0 -> Bool Fun s3'4/0 -> Bool Fun s4'4/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T v sorted3=T v sorted4=T v sorted5=T +Fun p/0 -> Bool +Let O := o1=T v o2=T v o3=T v o4=T v o5=T KB: u0'1=T KB: u0'2=T KB: u0'3=T KB: u0'4=T KB: u0'5=T -KB: ~x1=T -> pass=T -KB: ~x1'=T -> pass=T -KB: ~x2/=X -> pass=T -KB: ~x3=T -> pass=T -KB: ~x3'=T -> pass=T -KB: ~x4/=X -> pass=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ s3'4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4/=X -> Sorted -KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> Sorted -Refute: K<3> Sorted -Assert: K<4> Sorted -Refute: K<4> (Sorted ^ (~pass=T -> ((x1=T v x2=T)^ (~x2=T v x3=T)^ (x1=T v x3'=T)^ (x2=T v ~x4=T)))) +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'5=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'5=T +KB: ~x1=T -> p=T +KB: ~x1'=T -> p=T +KB: ~x3=T -> p=T +KB: ~x3'=T -> p=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ s3'4=T -> O +KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> O +Refute: K<3> O +Assert: K<4> O +Refute: K<4> (O ^ (~p=T -> ((x1=T v x2=T)^ (~x2=T v x3=T)^ (x1=T v x3'=T)^ (x2=T v ~x4=T)))) diff --git a/examples/tui/test-qbf-3.limbo b/examples/tui/test-qbf-3.limbo index 09cc3ba..bf80974 100644 --- a/examples/tui/test-qbf-3.limbo +++ b/examples/tui/test-qbf-3.limbo @@ -6,7 +6,7 @@ Fun x1/0, x1'/0 -> Bool Fun x3/0, x3'/0 -> Bool Fun x2/0 -> Bool Fun x4/0 -> Bool -Fun sorted1/0, sorted2/0, sorted3/0, sorted4/0, sorted5/0 -> Bool +Fun o1/0, o2/0, o3/0, o4/0, o5/0 -> Bool Fun u0'1/0, u0'2/0, u0'3/0, u0'4/0, u0'5/0 -> Bool Fun u1'1/0, u1'2/0, u1'3/0, u1'4/0, u1'5/0 -> Bool Fun u2'1/0, u2'2/0, u2'3/0, u2'4/0, u2'5/0 -> Bool @@ -16,66 +16,70 @@ Fun s1'2/0, s1'3/0, s1'4/0 -> Bool Fun s2'3/0, s2'4/0 -> Bool Fun s3'4/0 -> Bool Fun s4'4/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T v sorted3=T v sorted4=T v sorted5=T +Fun p/0 -> Bool +Let O := o1=T v o2=T v o3=T v o4=T v o5=T KB: u0'1=T KB: u0'2=T KB: u0'3=T KB: u0'4=T KB: u0'5=T -KB: ~x1=T -> pass=T -KB: ~x1'=T -> pass=T -KB: ~x2/=X -> pass=T -KB: ~x3=T -> pass=T -KB: ~x3'=T -> pass=T -KB: ~x4/=X -> pass=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ s3'4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4/=X -> Sorted -KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> Sorted -Refute: K<3> Sorted -Assert: K<4> Sorted -Assert: K<4> (Sorted ^ (~pass=T -> ((x1=T v x2=T)^ (~x2=T v x3=T)^ (x1=T v x3'=T)^ (x2=T v x3'=T)))) +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'5=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'5=T +KB: ~x1=T -> p=T +KB: ~x1'=T -> p=T +KB: ~x3=T -> p=T +KB: ~x3'=T -> p=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ s3'4=T -> O +KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> O +Refute: K<3> O +Assert: K<4> O +Assert: K<4> (O ^ (~p=T -> ((x1=T v x2=T)^ (~x2=T v x3=T)^ (x1=T v x3'=T)^ (x2=T v x3'=T)))) diff --git a/examples/tui/test-qbf-4.limbo b/examples/tui/test-qbf-4.limbo index 320bf82..93697e0 100644 --- a/examples/tui/test-qbf-4.limbo +++ b/examples/tui/test-qbf-4.limbo @@ -5,7 +5,7 @@ Name T, X -> Bool Fun x1/0 -> Bool Fun x2/0 -> Bool Fun x3/0 -> Bool -Fun sorted1/0, sorted2/0, sorted3/0, sorted4/0 -> Bool +Fun o1/0, o2/0, o3/0, o4/0 -> Bool Fun u0'1/0, u0'2/0, u0'3/0, u0'4/0 -> Bool Fun u1'1/0, u1'2/0, u1'3/0, u1'4/0 -> Bool Fun u2'1/0, u2'2/0, u2'3/0, u2'4/0 -> Bool @@ -13,34 +13,37 @@ Fun u3'1/0, u3'2/0, u3'3/0, u3'4/0 -> Bool Fun s1'2/0, s1'3/0 -> Bool Fun s2'3/0 -> Bool Fun s3'3/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T v sorted3=T v sorted4=T +Fun p/0 -> Bool +Let O := o1=T v o2=T v o3=T v o4=T KB: u0'1=T KB: u0'2=T KB: u0'3=T KB: u0'4=T -KB: ~x1/=X -> pass=T -KB: ~x2/=X -> pass=T -KB: ~x3/=X -> pass=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ x1/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ x1/=X -> u1'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ x2/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ x2/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ x2/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ x2/=X -> u2'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ x3/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ x3/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ x3/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ x3/=X -> u3'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ ~x1/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ ~x1/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ ~x1/=X ^ s1'2/=X ^ s1'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ ~x2/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ ~x2/=X ^ s2'3/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ ~x3/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T -> Sorted -Refute: K<2> Sorted -Assert: K<3> Sorted -Assert: K<3> (Sorted ^ (~pass=T -> (x1=T^x2=T^x3=T v x1=T^x2=T^ ~x3=T v x1=T^ ~x2=T^x3=T v x1=T^ ~x2=T^ ~x3=T v ~x1=T^x2=T^x3=T v ~x1=T^x2=T^ ~x3=T v ~x1=T^ ~x2=T^x3=T v ~x1=T^ ~x2=T^ ~x3=T))) +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ x1=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ ~x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ ~x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ ~x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ ~x1=T -> u1'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ ~x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ ~x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ ~x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ ~x2=T -> u2'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ x3=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ x3=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ x3=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ x3=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ ~x3=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ ~x3=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ ~x3=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ ~x3=T -> u3'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T -> O +Refute: K<2> O +Assert: K<3> O +Assert: K<3> (O ^ (~p=T -> (x1=T^x2=T^x3=T v x1=T^x2=T^ ~x3=T v x1=T^ ~x2=T^x3=T v x1=T^ ~x2=T^ ~x3=T v ~x1=T^x2=T^x3=T v ~x1=T^x2=T^ ~x3=T v ~x1=T^ ~x2=T^x3=T v ~x1=T^ ~x2=T^ ~x3=T))) diff --git a/examples/tui/test-qbf-5.limbo b/examples/tui/test-qbf-5.limbo index 7f8bc2a..71ac270 100644 --- a/examples/tui/test-qbf-5.limbo +++ b/examples/tui/test-qbf-5.limbo @@ -6,7 +6,7 @@ Fun x1/0 -> Bool Fun x2/0 -> Bool Fun x3/0 -> Bool Fun x4/0 -> Bool -Fun sorted1/0, sorted2/0, sorted3/0, sorted4/0, sorted5/0 -> Bool +Fun o1/0, o2/0, o3/0, o4/0, o5/0 -> Bool Fun u0'1/0, u0'2/0, u0'3/0, u0'4/0, u0'5/0 -> Bool Fun u1'1/0, u1'2/0, u1'3/0, u1'4/0, u1'5/0 -> Bool Fun u2'1/0, u2'2/0, u2'3/0, u2'4/0, u2'5/0 -> Bool @@ -16,48 +16,54 @@ Fun s1'2/0, s1'3/0, s1'4/0 -> Bool Fun s2'3/0, s2'4/0 -> Bool Fun s3'4/0 -> Bool Fun s4'4/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T v sorted3=T v sorted4=T v sorted5=T +Fun p/0 -> Bool +Let O := o1=T v o2=T v o3=T v o4=T v o5=T KB: u0'1=T KB: u0'2=T KB: u0'3=T KB: u0'4=T KB: u0'5=T -KB: ~x1/=X -> pass=T -KB: ~x2/=X -> pass=T -KB: ~x3/=X -> pass=T -KB: ~x4/=X -> pass=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ s3'4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4/=X -> Sorted -KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> Sorted -Refute: K<3> Sorted -Assert: K<4> Sorted -Assert: K<4> (Sorted ^ (~pass=T -> (x4=T v ~x4=T))) +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'5=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T -> u1'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T -> u3'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'5=T +KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> O +Refute: K<3> O +Assert: K<4> O +Assert: K<4> (O ^ (~p=T -> (x4=T v ~x4=T))) diff --git a/examples/tui/test-qbf-6.limbo b/examples/tui/test-qbf-6.limbo index ab1af52..47fcd07 100644 --- a/examples/tui/test-qbf-6.limbo +++ b/examples/tui/test-qbf-6.limbo @@ -6,7 +6,7 @@ Fun x1/0, x1'/0 -> Bool Fun x2/0, x2'/0 -> Bool Fun x3/0, x3'/0 -> Bool Fun x4/0, x4'/0 -> Bool -Fun sorted1/0, sorted2/0, sorted3/0, sorted4/0, sorted5/0 -> Bool +Fun o1/0, o2/0, o3/0, o4/0, o5/0 -> Bool Fun u0'1/0, u0'2/0, u0'3/0, u0'4/0, u0'5/0 -> Bool Fun u1'1/0, u1'2/0, u1'3/0, u1'4/0, u1'5/0 -> Bool Fun u2'1/0, u2'2/0, u2'3/0, u2'4/0, u2'5/0 -> Bool @@ -16,82 +16,82 @@ Fun s1'2/0, s1'3/0, s1'4/0 -> Bool Fun s2'3/0, s2'4/0 -> Bool Fun s3'4/0 -> Bool Fun s4'4/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T v sorted3=T v sorted4=T v sorted5=T +Fun p/0 -> Bool +Let O := o1=T v o2=T v o3=T v o4=T v o5=T KB: u0'1=T KB: u0'2=T KB: u0'3=T KB: u0'4=T KB: u0'5=T -KB: ~x1=T -> pass=T -KB: ~x1'=T -> pass=T -KB: ~x2=T -> pass=T -KB: ~x2'=T -> pass=T -KB: ~x3=T -> pass=T -KB: ~x3'=T -> pass=T -KB: ~x4=T -> pass=T -KB: ~x4'=T -> pass=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ s3'4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4'/=X -> Sorted -KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> Sorted -Refute: K<3> Sorted -Assert: K<4> Sorted -Assert: K<4> (Sorted ^ (~pass=T -> (x1=T^x2=T^x3=T^x4=T))) +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'5=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'5=T +KB: ~x1=T -> p=T +KB: ~x1'=T -> p=T +KB: ~x2=T -> p=T +KB: ~x2'=T -> p=T +KB: ~x3=T -> p=T +KB: ~x3'=T -> p=T +KB: ~x4=T -> p=T +KB: ~x4'=T -> p=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ ~s2'3=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ ~s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ s2'3=T ^ s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ ~s2'3=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ ~s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ s2'3=T ^ s2'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ s3'4=T -> O +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> O +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4'=T -> O +KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> O +Refute: K<3> O +Assert: K<4> O +Assert: K<4> (O ^ (~p=T -> (x1=T^x2=T^x3=T^x4=T))) diff --git a/examples/tui/test-qbf-7.limbo b/examples/tui/test-qbf-7.limbo index 83b402c..a97859b 100644 --- a/examples/tui/test-qbf-7.limbo +++ b/examples/tui/test-qbf-7.limbo @@ -6,7 +6,7 @@ Fun x1/0, x1'/0 -> Bool Fun x2/0, x2'/0 -> Bool Fun x3/0, x3'/0 -> Bool Fun x4/0, x4'/0 -> Bool -Fun sorted1/0, sorted2/0, sorted3/0, sorted4/0, sorted5/0 -> Bool +Fun o1/0, o2/0, o3/0, o4/0, o5/0 -> Bool Fun u0'1/0, u0'2/0, u0'3/0, u0'4/0, u0'5/0 -> Bool Fun u1'1/0, u1'2/0, u1'3/0, u1'4/0, u1'5/0 -> Bool Fun u2'1/0, u2'2/0, u2'3/0, u2'4/0, u2'5/0 -> Bool @@ -16,82 +16,82 @@ Fun s1'2/0, s1'3/0, s1'4/0 -> Bool Fun s2'3/0, s2'4/0 -> Bool Fun s3'4/0 -> Bool Fun s4'4/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T v sorted3=T v sorted4=T v sorted5=T +Fun p/0 -> Bool +Let O := o1=T v o2=T v o3=T v o4=T v o5=T KB: u0'1=T KB: u0'2=T KB: u0'3=T KB: u0'4=T KB: u0'5=T -KB: ~x1=T -> pass=T -KB: ~x1'=T -> pass=T -KB: ~x2=T -> pass=T -KB: ~x2'=T -> pass=T -KB: ~x3=T -> pass=T -KB: ~x3'=T -> pass=T -KB: ~x4=T -> pass=T -KB: ~x4'=T -> pass=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ s3'4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4'/=X -> Sorted -KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> Sorted -Refute: K<3> Sorted -Assert: K<4> Sorted -Assert: K<4> (Sorted ^ (~pass=T -> (x1'=T^x2'=T^x3'=T^x4'=T))) +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'5=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'5=T +KB: ~x1=T -> p=T +KB: ~x1'=T -> p=T +KB: ~x2=T -> p=T +KB: ~x2'=T -> p=T +KB: ~x3=T -> p=T +KB: ~x3'=T -> p=T +KB: ~x4=T -> p=T +KB: ~x4'=T -> p=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ ~s2'3=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ ~s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ s2'3=T ^ s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ ~s2'3=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ ~s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ s2'3=T ^ s2'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ s3'4=T -> O +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> O +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4'=T -> O +KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> O +Refute: K<3> O +Assert: K<4> O +Assert: K<4> (O ^ (~p=T -> (x1'=T^x2'=T^x3'=T^x4'=T))) diff --git a/examples/tui/test-qbf-8.limbo b/examples/tui/test-qbf-8.limbo index af2494d..3e9ce64 100644 --- a/examples/tui/test-qbf-8.limbo +++ b/examples/tui/test-qbf-8.limbo @@ -6,7 +6,7 @@ Fun x1/0, x1'/0 -> Bool Fun x3/0, x3'/0 -> Bool Fun x2/0 -> Bool Fun x4/0 -> Bool -Fun sorted1/0, sorted2/0, sorted3/0, sorted4/0, sorted5/0 -> Bool +Fun o1/0, o2/0, o3/0, o4/0, o5/0 -> Bool Fun u0'1/0, u0'2/0, u0'3/0, u0'4/0, u0'5/0 -> Bool Fun u1'1/0, u1'2/0, u1'3/0, u1'4/0, u1'5/0 -> Bool Fun u2'1/0, u2'2/0, u2'3/0, u2'4/0, u2'5/0 -> Bool @@ -16,66 +16,70 @@ Fun s1'2/0, s1'3/0, s1'4/0 -> Bool Fun s2'3/0, s2'4/0 -> Bool Fun s3'4/0 -> Bool Fun s4'4/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T v sorted3=T v sorted4=T v sorted5=T +Fun p/0 -> Bool +Let O := o1=T v o2=T v o3=T v o4=T v o5=T KB: u0'1=T KB: u0'2=T KB: u0'3=T KB: u0'4=T KB: u0'5=T -KB: ~x1=T -> pass=T -KB: ~x1'=T -> pass=T -KB: ~x2/=X -> pass=T -KB: ~x3=T -> pass=T -KB: ~x3'=T -> pass=T -KB: ~x4/=X -> pass=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ s3'4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4/=X -> Sorted -KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> Sorted -Refute: K<3> Sorted -Assert: K<4> Sorted -Assert: K<4> (Sorted ^ (~pass=T -> ((x1'=T v x2=T)^ (~x2=T v x3=T)^ (x1'=T v x3'=T)^x1'=T))) +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'5=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T -> u2'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> u4'5=T +KB: ~x1=T -> p=T +KB: ~x1'=T -> p=T +KB: ~x3=T -> p=T +KB: ~x3'=T -> p=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ s3'4=T -> O +KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> O +Refute: K<3> O +Assert: K<4> O +Assert: K<4> (O ^ (~p=T -> ((x1'=T v x2=T)^ (~x2=T v x3=T)^ (x1'=T v x3'=T)^x1'=T))) diff --git a/examples/tui/test-qbf-9.limbo b/examples/tui/test-qbf-9.limbo index e325d07..9c7aea9 100644 --- a/examples/tui/test-qbf-9.limbo +++ b/examples/tui/test-qbf-9.limbo @@ -6,7 +6,7 @@ Fun x1/0, x1'/0 -> Bool Fun x2/0, x2'/0 -> Bool Fun x3/0, x3'/0 -> Bool Fun x4/0, x4'/0 -> Bool -Fun sorted1/0, sorted2/0, sorted3/0, sorted4/0, sorted5/0 -> Bool +Fun o1/0, o2/0, o3/0, o4/0, o5/0 -> Bool Fun u0'1/0, u0'2/0, u0'3/0, u0'4/0, u0'5/0 -> Bool Fun u1'1/0, u1'2/0, u1'3/0, u1'4/0, u1'5/0 -> Bool Fun u2'1/0, u2'2/0, u2'3/0, u2'4/0, u2'5/0 -> Bool @@ -16,82 +16,82 @@ Fun s1'2/0, s1'3/0, s1'4/0 -> Bool Fun s2'3/0, s2'4/0 -> Bool Fun s3'4/0 -> Bool Fun s4'4/0 -> Bool -Fun pass/0 -> Bool -Let Sorted := sorted1=T v sorted2=T v sorted3=T v sorted4=T v sorted5=T +Fun p/0 -> Bool +Let O := o1=T v o2=T v o3=T v o4=T v o5=T KB: u0'1=T KB: u0'2=T KB: u0'3=T KB: u0'4=T KB: u0'5=T -KB: ~x1=T -> pass=T -KB: ~x1'=T -> pass=T -KB: ~x2=T -> pass=T -KB: ~x2'=T -> pass=T -KB: ~x3=T -> pass=T -KB: ~x3'=T -> pass=T -KB: ~x4=T -> pass=T -KB: ~x4'=T -> pass=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1/=X -> u1'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'1=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'2=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'3=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'4=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'/=X -> u1'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2/=X -> u2'5=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'1=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'2=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'3=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'4=T -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'/=X -> u2'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3/=X -> u3'5=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'1=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'2=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'3=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'4=T -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'/=X -> u3'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4/=X -> u4'5=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'1=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'2=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'3=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'4=T -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'/=X -> u4'5=T -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'2/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'3/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ ~s1'4/=X -> Sorted -KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'/=X ^ s1'2/=X ^ s1'3/=X ^ s1'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ ~s2'3/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ ~s2'4/=X -> Sorted -KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'/=X ^ s2'3/=X ^ s2'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3/=X ^ s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ ~s3'4/=X -> Sorted -KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'/=X ^ s3'4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4/=X -> Sorted -KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4'/=X -> Sorted -KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> Sorted -Refute: K<3> Sorted -Assert: K<4> Sorted -Refute: K<4> (Sorted ^ (~pass=T -> (x1=T^x1'=T^x2'=T^x3'=T^x4'=T))) +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1=T -> u1'5=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'1=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'2=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'3=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'4=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ x1'=T -> u1'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2=T -> u2'5=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'1=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'2=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'3=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'4=T +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ x2'=T -> u2'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3=T -> u3'5=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'1=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'2=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'3=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'4=T +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ x3'=T -> u3'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4=T -> u4'5=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'1=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'2=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'3=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'4=T +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ x4'=T -> u4'5=T +KB: ~x1=T -> p=T +KB: ~x1'=T -> p=T +KB: ~x2=T -> p=T +KB: ~x2'=T -> p=T +KB: ~x3=T -> p=T +KB: ~x3'=T -> p=T +KB: ~x4=T -> p=T +KB: ~x4'=T -> p=T +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'2=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'3=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ ~s1'4=T -> O +KB: u0'1=T ^ u0'2=T ^ u0'3=T ^ u0'4=T ^ u0'5=T ^ ~x1'=T ^ s1'2=T ^ s1'3=T ^ s1'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ ~s2'3=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ ~s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2=T ^ s2'3=T ^ s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ ~s2'3=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ ~s2'4=T -> O +KB: u1'1=T ^ u1'2=T ^ u1'3=T ^ u1'4=T ^ u1'5=T ^ ~x2'=T ^ s2'3=T ^ s2'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3=T ^ s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ ~s3'4=T -> O +KB: u2'1=T ^ u2'2=T ^ u2'3=T ^ u2'4=T ^ u2'5=T ^ ~x3'=T ^ s3'4=T -> O +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4=T -> O +KB: u3'1=T ^ u3'2=T ^ u3'3=T ^ u3'4=T ^ u3'5=T ^ ~x4'=T -> O +KB: u4'1=T ^ u4'2=T ^ u4'3=T ^ u4'4=T ^ u4'5=T -> O +Refute: K<3> O +Assert: K<4> O +Refute: K<4> (O ^ (~p=T -> (x1=T^x1'=T^x2'=T^x3'=T^x4'=T))) diff --git a/examples/tui/tui-js.cc b/examples/tui/tui-js.cc index e8e9ccd..fd47c9f 100644 --- a/examples/tui/tui-js.cc +++ b/examples/tui/tui-js.cc @@ -73,8 +73,8 @@ struct Callback : public limbo::format::pdl::DefaultCallback { template void operator()(T* ctx, const std::string& proc, const std::vector& args) { if (proc == "print_kb") { - for (limbo::KnowledgeBase::sphere_index p = 0; p < ctx->kb()->n_spheres(); ++p) { - std::cout << "Setup[" << p << "] = " << std::endl << ctx->kb()->sphere(p)->setup() << std::endl; + for (limbo::KnowledgeBase::sphere_index p = 0; p < ctx->kb().n_spheres(); ++p) { + std::cout << "Setup[" << p << "] = " << std::endl << ctx->kb().sphere(p).setup() << std::endl; } } else if (proc == "print") { limbo::format::print_range(std::cout, args, "", "", " "); diff --git a/examples/tui/tui.cc b/examples/tui/tui.cc index 87196c0..c5efdc3 100644 --- a/examples/tui/tui.cc +++ b/examples/tui/tui.cc @@ -114,8 +114,8 @@ struct Callback : public limbo::format::pdl::DefaultCallback { template void operator()(T* ctx, const std::string& proc, const std::vector& args) { if (proc == "print_kb") { - for (limbo::KnowledgeBase::sphere_index p = 0; p < ctx->kb()->n_spheres(); ++p) { - std::cerr << "Setup[" << p << "] = " << std::endl << ctx->kb()->sphere(p)->setup() << std::endl; + for (limbo::KnowledgeBase::sphere_index p = 0; p < ctx->kb().n_spheres(); ++p) { + std::cerr << "Setup[" << p << "] = " << std::endl << ctx->kb().sphere(p).setup() << std::endl; } } else if (proc == "print") { limbo::format::print_range(std::cout, args, "", "", " "); diff --git a/src/limbo/format/pdl/context.h b/src/limbo/format/pdl/context.h index 16da069..a90101c 100644 --- a/src/limbo/format/pdl/context.h +++ b/src/limbo/format/pdl/context.h @@ -202,7 +202,7 @@ class Context { return yes; } - KnowledgeBase* kb() { return &kb_; } + KnowledgeBase& kb() { return kb_; } const KnowledgeBase& kb() const { return kb_; } Symbol::Factory* sf() { return Symbol::Factory::Instance(); } diff --git a/src/limbo/format/pdl/parser.h b/src/limbo/format/pdl/parser.h index 5799181..d0f07b6 100644 --- a/src/limbo/format/pdl/parser.h +++ b/src/limbo/format/pdl/parser.h @@ -450,7 +450,7 @@ class Parser { if (!Is(Tok(), Token::kUint)) { return Error>(LIMBO_MSG("Expected split level integer")); } - const Formula::split_level k = std::stoi(Tok().val.str()); + const Formula::belief_level k = std::stoi(Tok().val.str()); Advance(); if (!Is(Tok(), Token::kGreater)) { return Error>(LIMBO_MSG("Expected '>'")); @@ -481,7 +481,7 @@ class Parser { if (!Is(Tok(), Token::kUint)) { return Error>(LIMBO_MSG("Expected first split level integer")); } - const Formula::split_level k = std::stoi(Tok().val.str()); + const Formula::belief_level k = std::stoi(Tok().val.str()); Advance(); if (!Is(Tok(), Token::kComma)) { return Error>(LIMBO_MSG("Expected ','")); @@ -490,7 +490,7 @@ class Parser { if (!Is(Tok(), Token::kUint)) { return Error>(LIMBO_MSG("Expected second split level integer")); } - const Formula::split_level l = std::stoi(Tok().val.str()); + const Formula::belief_level l = std::stoi(Tok().val.str()); Advance(); if (!Is(Tok(), Token::kGreater)) { return Error>(LIMBO_MSG("Expected '>'")); @@ -824,8 +824,8 @@ class Parser { Symbol::Sort sort = ctx->LookupSort(sort_id); std::vector ts; if (ts_a.empty()) { - Grounder::TermSet tss = ctx->kb()->sphere(0)->grounder()->Names()[sort]; - ts.insert(ts.end(), tss.begin(), tss.end()); + Grounder::Names ns = ctx->kb().sphere(0).grounder().names(sort); + ts.insert(ts.end(), ns.begin(), ns.end()); } else { for (const Action& t_a : ts_a) { Result t = t_a.Run(ctx); diff --git a/src/limbo/formula.h b/src/limbo/formula.h index 5aac8b8..dd758ff 100644 --- a/src/limbo/formula.h +++ b/src/limbo/formula.h @@ -35,9 +35,11 @@ class Formula { public: typedef internal::size_t size_t; typedef std::unique_ptr Ref; - typedef std::unordered_set TermSet; - typedef internal::IntMap SortMap; - typedef unsigned int split_level; + struct SortOf { Symbol::Sort operator()(Term t) const { return t.sort(); } }; + typedef internal::IntMultiSet SortedTermSet; + typedef SortedTermSet::Bucket TermSet; + typedef internal::IntMap SortCount; + typedef unsigned int belief_level; enum Type { kAtomic, kNot, kOr, kExists, kKnow, kCons, kBel, kGuarantee }; class Factory { @@ -52,10 +54,10 @@ class Formula { inline static Ref Not(Ref alpha); inline static Ref Or(Ref lhs, Ref rhs); inline static Ref Exists(Term lhs, Ref rhs); - inline static Ref Know(split_level k, Ref alpha); - inline static Ref Cons(split_level k, Ref alpha); - inline static Ref Bel(split_level k, split_level l, Ref alpha, Ref beta); - inline static Ref Bel(split_level k, split_level l, Ref alpha, Ref beta, Ref not_alpha_or_beta); + inline static Ref Know(belief_level k, Ref alpha); + inline static Ref Cons(belief_level k, Ref alpha); + inline static Ref Bel(belief_level k, belief_level l, Ref alpha, Ref beta); + inline static Ref Bel(belief_level k, belief_level l, Ref alpha, Ref beta, Ref not_alpha_or_beta); inline static Ref Guarantee(Ref alpha); }; @@ -91,14 +93,14 @@ class Formula { inline const Bel& as_bel() const; inline const Guarantee& as_guarantee() const; - const TermSet& free_vars() const { + const SortedTermSet& free_vars() const { if (!free_vars_) { free_vars_ = internal::Just(FreeVars()); } return free_vars_.val; } - virtual SortMap n_vars() const = 0; + virtual SortCount n_vars() const = 0; template void SubstituteFree(UnaryFunction theta, Term::Factory* tf) { @@ -118,7 +120,7 @@ class Formula { class Traversal : public ITraversal { public: explicit Traversal(UnaryFunction func) : func_(func) {} - bool operator()(arg_type t) const override { return func_(t); } + bool operator()(const arg_type& t) const override { return func_(t); } private: UnaryFunction func_; }; @@ -148,16 +150,16 @@ class Formula { virtual internal::Maybe operator()(Term t) const = 0; void Bind(Term t) const { bound_.insert(t); } void Unbind(Term t) const { bound_.erase(t); } - bool bound(Term t) const { return bound_.find(t) != bound_.end(); } + bool bound(Term t) const { return bound_.contains(t); } private: - mutable TermSet bound_; + mutable SortedTermSet bound_; }; template class ITraversal { public: virtual ~ITraversal() {} - virtual bool operator()(T t) const = 0; + virtual bool operator()(const T& t) const = 0; }; typedef std::unordered_map TermMap; @@ -189,11 +191,13 @@ class Formula { explicit Formula(Type type) : type_(type) {} - virtual TermSet FreeVars() const = 0; + virtual SortedTermSet FreeVars() const = 0; virtual void ISubstitute(const ISubstitution&, Term::Factory*) = 0; virtual void ITraverse(const ITraversal&) const = 0; virtual void ITraverse(const ITraversal&) const = 0; + virtual void ITraverse(const ITraversal&) const = 0; + virtual void ITraverse(const ITraversal&) const = 0; void Rectify(Symbol::Factory* sf, Term::Factory* tf) { TermMap tm; @@ -217,7 +221,7 @@ class Formula { private: Type type_; - mutable internal::Maybe free_vars_ = internal::Nothing; + mutable internal::Maybe free_vars_ = internal::Nothing; }; Formula::Ref Formula::QuantifierPrefix::PrependTo(Formula::Ref alpha) const { @@ -240,8 +244,8 @@ class Formula::Atomic : public Formula { const Clause& arg() const { return c_; } - SortMap n_vars() const override { - SortMap m; + SortCount n_vars() const override { + SortCount m; for (Term x : free_vars()) { ++m[x.sort()]; } @@ -261,8 +265,8 @@ class Formula::Atomic : public Formula { explicit Atomic(const Clause& c) : Formula(Formula::kAtomic), c_(c) {} - TermSet FreeVars() const override { - TermSet ts; + SortedTermSet FreeVars() const override { + SortedTermSet ts; c_.Traverse([&ts](Term x) { if (x.variable()) ts.insert(x); return true; }); return ts; } @@ -272,6 +276,8 @@ class Formula::Atomic : public Formula { } void ITraverse(const ITraversal& f) const override { c_.Traverse([&f](Term t) { return f(t); }); } void ITraverse(const ITraversal& f) const override { c_.Traverse([&f](Literal a) { return f(a); }); } + void ITraverse(const ITraversal& f) const override { f(c_); } + void ITraverse(const ITraversal& f) const override { f(*this); } void Rectify(TermMap* tm, Symbol::Factory* sf, Term::Factory* tf) override { c_ = c_.Substitute([tm](Term t) { @@ -396,8 +402,8 @@ class Formula::Or : public Formula { const Formula& lhs() const { return *alpha_; } const Formula& rhs() const { return *beta_; } - SortMap n_vars() const override { - SortMap m; + SortCount n_vars() const override { + SortCount m; for (Term x : free_vars()) { ++m[x.sort()]; } @@ -417,11 +423,12 @@ class Formula::Or : public Formula { Or(Ref lhs, Ref rhs) : Formula(kOr), alpha_(std::move(lhs)), beta_(std::move(rhs)) {} - TermSet FreeVars() const override { - TermSet ts1 = alpha_->free_vars(); - const TermSet& ts2 = beta_->free_vars(); - ts1.insert(ts2.begin(), ts2.end()); - return ts1; + SortedTermSet FreeVars() const override { + SortedTermSet ts = alpha_->free_vars(); + for (Term x : beta_->free_vars().values()) { + ts.insert(x); + } + return ts; } void ISubstitute(const ISubstitution& theta, Term::Factory* tf) override { @@ -430,6 +437,8 @@ class Formula::Or : public Formula { } void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); beta_->ITraverse(f); } void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); beta_->ITraverse(f); } + void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); beta_->ITraverse(f); } + void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); beta_->ITraverse(f); f(*this); } void Rectify(TermMap* tm, Symbol::Factory* sf, Term::Factory* tf) override { alpha_->Rectify(tm, sf, tf); @@ -501,7 +510,7 @@ class Formula::Exists : public Formula { Term x() const { return x_; } const Formula& arg() const { return *alpha_; } - SortMap n_vars() const override { return alpha_->n_vars(); } + SortCount n_vars() const override { return alpha_->n_vars(); } bool objective() const override { return alpha_->objective(); } bool subjective() const override { return alpha_->subjective(); } @@ -514,7 +523,7 @@ class Formula::Exists : public Formula { Exists(Term x, Ref alpha) : Formula(kExists), x_(x), alpha_(std::move(alpha)) {} - TermSet FreeVars() const override { TermSet ts = alpha_->free_vars(); ts.erase(x_); return ts; } + SortedTermSet FreeVars() const override { SortedTermSet ts = alpha_->free_vars(); ts.erase(x_); return ts; } void ISubstitute(const ISubstitution& theta, Term::Factory* tf) override { theta.Bind(x_); @@ -523,6 +532,8 @@ class Formula::Exists : public Formula { } void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); } void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); } + void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); } + void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); f(*this); } void Rectify(TermMap* tm, Symbol::Factory* sf, Term::Factory* tf) override { TermMap::const_iterator it = tm->find(x_); @@ -544,9 +555,9 @@ class Formula::Exists : public Formula { } Ref Normalize(bool distribute) const override { - const TermSet& ts = alpha_->free_vars(); + const SortedTermSet& ts = alpha_->free_vars(); Ref alpha = alpha_->Normalize(distribute); - if (ts.find(x_) != ts.end()) { + if (ts.contains(x_)) { return Factory::Exists(x_, std::move(alpha)); } else { return alpha; @@ -579,7 +590,7 @@ class Formula::Not : public Formula { const Formula& arg() const { return *alpha_; } - SortMap n_vars() const override { return alpha_->n_vars(); } + SortCount n_vars() const override { return alpha_->n_vars(); } bool objective() const override { return alpha_->objective(); } bool subjective() const override { return alpha_->subjective(); } @@ -592,11 +603,13 @@ class Formula::Not : public Formula { explicit Not(Ref alpha) : Formula(kNot), alpha_(std::move(alpha)) {} - TermSet FreeVars() const override { return alpha_->free_vars(); } + SortedTermSet FreeVars() const override { return alpha_->free_vars(); } void ISubstitute(const ISubstitution& theta, Term::Factory* tf) override { alpha_->ISubstitute(theta, tf); } void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); } void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); } + void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); } + void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); f(*this); } void Rectify(TermMap* tm, Symbol::Factory* sf, Term::Factory* tf) override { alpha_->Rectify(tm, sf, tf); } @@ -655,27 +668,29 @@ class Formula::Know : public Formula { Ref Clone() const override { return Factory::Know(k_, alpha_->Clone()); } - split_level k() const { return k_; } + belief_level k() const { return k_; } const Formula& arg() const { return *alpha_; } - SortMap n_vars() const override { return alpha_->n_vars(); } + SortCount n_vars() const override { return alpha_->n_vars(); } bool objective() const override { return false; } bool subjective() const override { return true; } - bool quantified_in() const override { return !free_vars().empty(); } + bool quantified_in() const override { return !free_vars().all_empty(); } bool trivially_valid() const override { return alpha_->trivially_valid(); } bool trivially_invalid() const override { return false; } protected: friend class Factory; - Know(split_level k, Ref alpha) : Formula(kKnow), k_(k), alpha_(std::move(alpha)) {} + Know(belief_level k, Ref alpha) : Formula(kKnow), k_(k), alpha_(std::move(alpha)) {} - TermSet FreeVars() const override { return alpha_->free_vars(); } + SortedTermSet FreeVars() const override { return alpha_->free_vars(); } void ISubstitute(const ISubstitution& theta, Term::Factory* tf) override { alpha_->ISubstitute(theta, tf); } void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); } void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); } + void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); } + void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); f(*this); } void Rectify(TermMap* tm, Symbol::Factory* sf, Term::Factory* tf) override { alpha_->Rectify(tm, sf, tf); } @@ -700,7 +715,7 @@ class Formula::Know : public Formula { internal::Maybe AsUnivClause(size_t nots) const override { return internal::Nothing; } private: - static Ref DistK(split_level k, Ref alpha) { + static Ref DistK(belief_level k, Ref alpha) { if (alpha->type() == kNot) { const Formula& beta = alpha->as_not().arg(); switch (beta.type()) { @@ -741,7 +756,7 @@ class Formula::Know : public Formula { return Factory::Know(k, std::move(alpha)); } - split_level k_; + belief_level k_; Ref alpha_; }; @@ -753,27 +768,29 @@ class Formula::Cons : public Formula { Ref Clone() const override { return Factory::Cons(k_, alpha_->Clone()); } - split_level k() const { return k_; } + belief_level k() const { return k_; } const Formula& arg() const { return *alpha_; } - SortMap n_vars() const override { return alpha_->n_vars(); } + SortCount n_vars() const override { return alpha_->n_vars(); } bool objective() const override { return false; } bool subjective() const override { return true; } - bool quantified_in() const override { return !free_vars().empty(); } + bool quantified_in() const override { return !free_vars().all_empty(); } bool trivially_valid() const override { return false; } bool trivially_invalid() const override { return alpha_->trivially_invalid(); } protected: friend class Factory; - Cons(split_level k, Ref alpha) : Formula(kCons), k_(k), alpha_(std::move(alpha)) {} + Cons(belief_level k, Ref alpha) : Formula(kCons), k_(k), alpha_(std::move(alpha)) {} - TermSet FreeVars() const override { return alpha_->free_vars(); } + SortedTermSet FreeVars() const override { return alpha_->free_vars(); } void ISubstitute(const ISubstitution& theta, Term::Factory* tf) override { alpha_->ISubstitute(theta, tf); } void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); } void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); } + void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); } + void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); f(*this); } void Rectify(TermMap* tm, Symbol::Factory* sf, Term::Factory* tf) override { alpha_->Rectify(tm, sf, tf); } @@ -798,7 +815,7 @@ class Formula::Cons : public Formula { internal::Maybe AsUnivClause(size_t nots) const override { return internal::Nothing; } private: - static Ref DistM(split_level k, Ref alpha) { + static Ref DistM(belief_level k, Ref alpha) { switch (alpha->type()) { case kAtomic: { const Clause& c = alpha->as_atomic().arg(); @@ -832,7 +849,7 @@ class Formula::Cons : public Formula { return Factory::Cons(k, std::move(alpha)); } - split_level k_; + belief_level k_; Ref alpha_; }; @@ -848,24 +865,24 @@ class Formula::Bel : public Formula { return Factory::Bel(k_, l_, antecedent_->Clone(), consequent_->Clone(), not_antecedent_or_consequent_->Clone()); } - split_level k() const { return k_; } - split_level l() const { return l_; } + belief_level k() const { return k_; } + belief_level l() const { return l_; } const Formula& antecedent() const { return *antecedent_; } const Formula& consequent() const { return *consequent_; } const Formula& not_antecedent_or_consequent() const { return *not_antecedent_or_consequent_; } - SortMap n_vars() const override { return not_antecedent_or_consequent_->n_vars(); } + SortCount n_vars() const override { return not_antecedent_or_consequent_->n_vars(); } bool objective() const override { return false; } bool subjective() const override { return true; } - bool quantified_in() const override { return !free_vars().empty(); } + bool quantified_in() const override { return !free_vars().all_empty(); } bool trivially_valid() const override { return not_antecedent_or_consequent_->trivially_valid(); } bool trivially_invalid() const override { return false; } protected: friend class Factory; - Bel(split_level k, split_level l, Ref antecedent, Ref consequent) : + Bel(belief_level k, belief_level l, Ref antecedent, Ref consequent) : Formula(kBel), k_(k), l_(l), @@ -873,7 +890,7 @@ class Formula::Bel : public Formula { consequent_(consequent->Clone()), not_antecedent_or_consequent_(Factory::Or(Factory::Not(std::move(antecedent)), std::move(consequent))) {} - TermSet FreeVars() const override { return not_antecedent_or_consequent_->free_vars(); } + SortedTermSet FreeVars() const override { return not_antecedent_or_consequent_->free_vars(); } void ISubstitute(const ISubstitution& theta, Term::Factory* tf) override { antecedent_->ISubstitute(theta, tf); @@ -882,6 +899,8 @@ class Formula::Bel : public Formula { } void ITraverse(const ITraversal& f) const override { antecedent_->ITraverse(f); consequent_->ITraverse(f); } void ITraverse(const ITraversal& f) const override { antecedent_->ITraverse(f); consequent_->ITraverse(f); } + void ITraverse(const ITraversal& f) const override { antecedent_->ITraverse(f); consequent_->ITraverse(f); } + void ITraverse(const ITraversal& f) const override { antecedent_->ITraverse(f); consequent_->ITraverse(f); f(*this); } void Rectify(TermMap* tm, Symbol::Factory* sf, Term::Factory* tf) override { antecedent_->Rectify(tm, sf, tf); @@ -908,7 +927,7 @@ class Formula::Bel : public Formula { internal::Maybe AsUnivClause(size_t nots) const override { return internal::Nothing; } private: - Bel(split_level k, split_level l, Ref antecedent, Ref consequent, Ref not_antecedent_or_consequent) : + Bel(belief_level k, belief_level l, Ref antecedent, Ref consequent, Ref not_antecedent_or_consequent) : Formula(kBel), k_(k), l_(l), @@ -916,8 +935,8 @@ class Formula::Bel : public Formula { consequent_(std::move(consequent)), not_antecedent_or_consequent_(std::move(not_antecedent_or_consequent)) {} - split_level k_; - split_level l_; + belief_level k_; + belief_level l_; Ref antecedent_; Ref consequent_; Ref not_antecedent_or_consequent_; @@ -933,7 +952,7 @@ class Formula::Guarantee : public Formula { const Formula& arg() const { return *alpha_; } - SortMap n_vars() const override { return alpha_->n_vars(); } + SortCount n_vars() const override { return alpha_->n_vars(); } bool objective() const override { return alpha_->objective(); } bool subjective() const override { return alpha_->subjective(); } @@ -948,11 +967,13 @@ class Formula::Guarantee : public Formula { Formula(kGuarantee), alpha_(std::move(alpha)) {} - TermSet FreeVars() const override { return alpha_->free_vars(); } + SortedTermSet FreeVars() const override { return alpha_->free_vars(); } void ISubstitute(const ISubstitution& theta, Term::Factory* tf) override { alpha_->ISubstitute(theta, tf); } void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); } void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); } + void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); } + void ITraverse(const ITraversal& f) const override { alpha_->ITraverse(f); f(*this); } void Rectify(TermMap* tm, Symbol::Factory* sf, Term::Factory* tf) override { alpha_->Rectify(tm, sf, tf); } @@ -976,12 +997,12 @@ Formula::Ref Formula::Factory::Atomic(const Clause& c) { return Ref(new class Formula::Ref Formula::Factory::Not(Ref alpha) { return Ref(new class Not(std::move(alpha))); } Formula::Ref Formula::Factory::Or(Ref lhs, Ref rhs) { return Ref(new class Or(std::move(lhs), std::move(rhs))); } Formula::Ref Formula::Factory::Exists(Term x, Ref alpha) { return Ref(new class Exists(x, std::move(alpha))); } -Formula::Ref Formula::Factory::Know(split_level k, Ref alpha) { return Ref(new class Know(k, std::move(alpha))); } -Formula::Ref Formula::Factory::Cons(split_level k, Ref alpha) { return Ref(new class Cons(k, std::move(alpha))); } -Formula::Ref Formula::Factory::Bel(split_level k, split_level l, Ref alpha, Ref beta) { +Formula::Ref Formula::Factory::Know(belief_level k, Ref alpha) { return Ref(new class Know(k, std::move(alpha))); } +Formula::Ref Formula::Factory::Cons(belief_level k, Ref alpha) { return Ref(new class Cons(k, std::move(alpha))); } +Formula::Ref Formula::Factory::Bel(belief_level k, belief_level l, Ref alpha, Ref beta) { return Ref(new class Bel(k, l, std::move(alpha), std::move(beta))); } -Formula::Ref Formula::Factory::Bel(split_level k, split_level l, Ref alpha, Ref beta, Ref not_alpha_or_beta) { +Formula::Ref Formula::Factory::Bel(belief_level k, belief_level l, Ref alpha, Ref beta, Ref not_alpha_or_beta) { return Ref(new class Bel(k, l, std::move(alpha), std::move(beta), std::move(not_alpha_or_beta))); } Formula::Ref Formula::Factory::Guarantee(Ref alpha) { return Ref(new class Guarantee(std::move(alpha))); } diff --git a/src/limbo/grounder.h b/src/limbo/grounder.h index 69544ce..beb142b 100644 --- a/src/limbo/grounder.h +++ b/src/limbo/grounder.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -50,487 +51,944 @@ namespace limbo { class Grounder { public: typedef internal::size_t size_t; - typedef Formula::split_level split_level; - typedef Formula::TermSet TermSet; - typedef std::unordered_set LiteralSet; - - struct LhsSymbolHasher { - internal::hash32_t operator()(const LiteralSet& set) const { - assert(!set.empty()); - assert(std::all_of(set.begin(), set.end(), [&set](Literal a) { return - std::all_of(set.begin(), set.end(), [a](Literal b) { return - a.lhs().symbol() == b.lhs().symbol(); }); })); - return set.begin()->lhs().symbol().hash(); + + template + class Pool { + public: + Pool(Symbol::Factory* sf, Term::Factory* tf) : sf_(sf), tf_(tf) {} + Pool(const Pool&) = delete; + Pool& operator=(const Pool&) = delete; + Pool(Pool&&) = default; + Pool& operator=(Pool&&) = default; + + Term Create(Symbol::Sort sort) { + if (terms_[sort].empty()) { + return tf_->CreateTerm((sf_->*CreateSymbol)(sort)); + } else { + Term t = terms_[sort].back(); + terms_[sort].pop_back(); + return t; + } } - }; - struct LiteralSetHash { - internal::hash32_t operator()(const LiteralSet& set) const { - internal::hash32_t h = 0; - for (Literal a : set) { - h ^= a.hash(); + void Return(Term t) { terms_[t.sort()].push_back(t); } + + Term Get(Symbol::Sort sort, size_t i) { + Term::Vector& ts = terms_[sort]; + while (i < ts.size()) { + ts.push_back(tf_->CreateTerm((sf_->*CreateSymbol)(sort))); } - return h; + return ts[i]; } + + private: + Symbol::Factory* const sf_; + Term::Factory* const tf_; + internal::IntMap terms_; }; - typedef std::unordered_set LiteralAssignmentSet; + typedef Pool<&Symbol::Factory::CreateName> NamePool; + typedef Pool<&Symbol::Factory::CreateVariable> VariablePool; - struct GetSort { Symbol::Sort operator()(Term t) const { return t.sort(); } }; - typedef internal::IntMultiSet SortedTermSet; + typedef Formula::SortedTermSet SortedTermSet; - Grounder(Symbol::Factory* sf, Term::Factory* tf) : sf_(sf), tf_(tf) {} - Grounder(const Grounder&) = delete; - Grounder& operator=(const Grounder&) = delete; - Grounder(Grounder&&) = default; - Grounder& operator=(Grounder&&) = default; + template + struct Ungrounded { + typedef T value_type; + struct Hash { internal::hash32_t operator()(const Ungrounded& u) const { return u.val.hash(); } }; + typedef std::vector Vector; + typedef std::unordered_set Set; - typedef std::list::const_iterator clause_iterator; - typedef internal::joined_iterators clause_range; + bool operator==(const Ungrounded& u) const { return val == u.val; } + bool operator!=(const Ungrounded& u) const { return !(*this != u); } - clause_range clauses() const { return internal::join_ranges(processed_clauses_, unprocessed_clauses_); } + T val; + SortedTermSet vars; - void AddClause(const Clause& c) { - assert(std::all_of(c.begin(), c.end(), - [](Literal a) { return a.quasiprimitive() || (!a.lhs().function() && !a.rhs().function()); })); - if (c.valid()) { - return; - } - names_changed_ |= AddMentionedNames(Mentioned([](Term t) { return t.name(); }, c)); - names_changed_ |= AddPlusNames(PlusNames(c)); - AddSplitTerms(Mentioned([](Term t) { return t.quasiprimitive(); }, c)); - AddAssignmentLiterals(Mentioned([](Literal a) { return a.quasiprimitive(); }, c)); - unprocessed_clauses_.push_front(c); - } + private: + friend class Grounder; - void PrepareForQuery(split_level k, const Formula& phi) { - assert(phi.objective()); - names_changed_ |= AddMentionedNames(Mentioned([](Term t) { return t.name(); }, phi)); - names_changed_ |= AddPlusNames(PlusNames(phi)); - if (k > 0) { - AddSplitTerms(Mentioned([](Term t) { return t.function(); }, phi)); - AddAssignmentLiterals(Mentioned([](Literal a) { return a.lhs().function(); }, phi)); - } - } + explicit Ungrounded(const T& val) : val(val) {} + }; - void PrepareForQuery(split_level k, Term lhs) { - names_changed_ |= AddMentionedNames(Mentioned([](Term t) { return t.name(); }, lhs)); - names_changed_ |= AddPlusNames(PlusNames(lhs)); - if (k > 0) { - AddSplitTerms(Mentioned([](Term t) { return t.function(); }, lhs)); - } - } + struct Ply { + typedef std::list List; + + Ply(const Ply&) = delete; + Ply& operator=(const Ply&) = delete; + Ply(Ply&&) = default; + Ply& operator=(Ply&&) = default; + + struct { + Ungrounded::Vector ungrounded; + std::unique_ptr full_setup; + Setup::ShallowCopy shallow_setup; + } clauses; + struct { + bool filter = false; // enabled after consistency guarantee + Ungrounded::Set ungrounded; + SortedTermSet terms; + } relevant; + struct { + SortedTermSet occurring; // names occurring in clause or prepared-for query + SortedTermSet plus_max; // plus-names that may be used for multiple purposes + SortedTermSet plus_new; // plus-names that may not be used for multiple purposes + } names; + struct { + Ungrounded::Set ungrounded; // literals in prepared-for query + std::unordered_map> map; // grounded lhs-rhs index for clause or prepared-for query + } lhs_rhs; + bool do_not_add_if_inconsistent = false; // enabled for fix-literals - const Setup& Ground() const { return const_cast(this)->Ground(); } + private: + friend class Grounder; - const Setup& Ground() { - if (names_changed_) { - // Re-ground all clauses, i.e., all clauses are considered unprocessed and all old setups are forgotten. - unprocessed_clauses_.splice(unprocessed_clauses_.begin(), processed_clauses_); - setup_ = internal::Nothing; - assert(processed_clauses_.empty()); - } - if (!unprocessed_clauses_.empty() || !setup_) { - if (!setup_) { - setup_ = internal::Just(Setup()); + Ply() = default; + }; + + struct Plies { + typedef Ply::List::const_reverse_iterator iterator; + enum Policy { kAll, kSinceSetup, kNew, kOld }; + + iterator begin() const { + switch (policy) { + case kAll: + case kSinceSetup: + case kNew: + return owner->plies_.rbegin(); + case kOld: + return std::next(owner->plies_.rbegin()); } - for (const Clause& c : unprocessed_clauses_) { - if (c.ground()) { - assert(c.primitive()); - if (!c.valid()) { - setup_.val.AddClause(c); - } - } else { - const TermSet vars = Mentioned([](Term t) { return t.variable(); }, c); - for (const auto& mapping : Assignments(vars, &names_)) { - const Clause ci = c.Substitute(mapping, tf_); - if (!ci.valid()) { - assert(ci.primitive()); - setup_.val.AddClause(ci); + return owner->plies_.rbegin(); + } + + iterator end() const { + switch (policy) { + case kAll: + case kOld: + return owner->plies_.rend(); + case kSinceSetup: { + const iterator e = owner->plies_.rend(); + for (auto it = begin(); it != e; ++it) { + if (it->clauses.full_setup) { + return ++it; } } + return e; } + case kNew: + return std::next(begin()); } - processed_clauses_.splice(processed_clauses_.begin(), unprocessed_clauses_); - names_changed_ = false; - setup_.val.Minimize(); } - assert(bool(setup_)); - return setup_.val; - } - const SortedTermSet& Names() const { return names_; } + private: + friend class Grounder; - Term CreateName(Symbol::Sort sort) { - TermSet& ns = owned_names_[sort]; - if (ns.empty()) { - return tf_->CreateTerm(sf_->CreateName(sort)); - } else { - auto it = ns.begin(); - const Term n = *it; - ns.erase(it); - return n; + explicit Plies(const Grounder* owner, Policy policy = kAll) : owner(owner), policy(policy) {} + + const Grounder* const owner; + const Plies::Policy policy; + }; + + struct LhsTerms { + struct First { Term operator()(const std::pair>& p) const { return p.first; } }; + typedef std::unordered_map>::const_iterator pair_iterator; + typedef internal::transform_iterator term_iterator; + + struct New { + New() = default; + New(Plies::iterator begin, Plies::iterator end) : begin(begin), end(end) {} + bool operator()(Term t) const { + for (auto it = begin; it != end; ++it) { + auto& m = it->lhs_rhs.map; + if (m.find(t) != m.end()) { + return false; + } + } + return true; + } + private: + Plies::iterator begin; + Plies::iterator end; + }; + + typedef internal::filter_iterator unique_term_iterator; + + struct Begin { + explicit Begin(const Plies* plies) : plies(plies) {} + unique_term_iterator operator()(const Plies::iterator it) const { + term_iterator b = term_iterator(it->lhs_rhs.map.begin(), First()); + term_iterator e = term_iterator(it->lhs_rhs.map.end(), First()); + return unique_term_iterator(b, e, New(plies->begin(), it)); + } + private: + const Plies* plies; + }; + + struct End { + explicit End(const Plies* plies) : plies(plies) {} + unique_term_iterator operator()(const Plies::iterator it) const { + term_iterator e = term_iterator(it->lhs_rhs.map.end(), First()); + return unique_term_iterator(e, e, New(plies->begin(), it)); + } + private: + const Plies* plies; + }; + + typedef internal::flatten_iterator iterator; + + iterator begin() const { return iterator(plies.begin(), plies.end(), Begin(&plies), End(&plies)); } + iterator end() const { return iterator(plies.end(), plies.end(), Begin(&plies), End(&plies)); } + + private: + friend class Grounder; + + LhsTerms(const Grounder* owner, Plies::Policy policy) : plies(owner, policy) {} + + const Plies plies; + }; + + struct RhsNames { + typedef std::unordered_set::const_iterator name_iterator; + + struct Begin { + Begin(Term t, name_iterator end) : t(t), end(end) {} + name_iterator operator()(const Ply& p) const { + auto it = p.lhs_rhs.map.find(t); + return it != p.lhs_rhs.map.end() ? it->second.begin() : end; + } + private: + Term t; + name_iterator end; + }; + + struct End { + End(Term t, name_iterator end) : t(t), end(end) {} + name_iterator operator()(const Ply& p) const { + auto it = p.lhs_rhs.map.find(t); + return it != p.lhs_rhs.map.end() ? it->second.end() : end; + } + private: + Term t; + name_iterator end; + }; + + typedef internal::flatten_iterator flat_iterator; + typedef internal::singleton_iterator plus_iterator; + typedef internal::joined_iterator iterator; + + ~RhsNames() { if (!n_it->null()) { owner->name_pool_.Return(*n_it); } } + + iterator begin() const { + flat_iterator b = flat_iterator(plies.begin(), plies.end(), Begin(t, ts.end()), End(t, ts.end())); + flat_iterator e = flat_iterator(plies.end(), plies.end(), Begin(t, ts.end()), End(t, ts.end())); + if (n_it->null()) { + n_it = plus_iterator(owner->name_pool_.Create(t.sort())); + } + return iterator(b, e, n_it); } - } - void ReturnName(Term n) { - assert(n.name()); - owned_names_.insert(n); + iterator end() const { + flat_iterator b = flat_iterator(plies.end(), plies.end(), Begin(t, ts.end()), End(t, ts.end())); + flat_iterator e = flat_iterator(plies.end(), plies.end(), Begin(t, ts.end()), End(t, ts.end())); + return iterator(b, e, plus_iterator()); + } + + private: + friend class Grounder; + + RhsNames(Grounder* owner, Term t, Plies::Policy policy) + : owner(owner), plies(owner, policy), t(t), n_it(Term()) { assert(n_it->null()); } + + Grounder* const owner; + const Plies plies; + const Term t; + mutable plus_iterator n_it; + const std::unordered_set ts = {}; + }; + + struct Names { + typedef internal::joined_iterator plus_iterator; + typedef internal::joined_iterator name_iterator; + + struct Begin { + explicit Begin(Symbol::Sort sort) : sort(sort) {} + name_iterator operator()(const Ply& p) const { + auto b = plus_iterator(p.names.plus_max.begin(sort), p.names.plus_max.end(sort), p.names.plus_new.begin(sort)); + return name_iterator(p.names.occurring.begin(sort), p.names.occurring.end(sort), b); + } + private: + Symbol::Sort sort; + }; + + struct End { + explicit End(Symbol::Sort sort) : sort(sort) {} + name_iterator operator()(const Ply& p) const { + auto e = plus_iterator(p.names.plus_max.end(sort), p.names.plus_max.end(sort), p.names.plus_new.begin(sort)); + return name_iterator(p.names.occurring.end(sort), p.names.occurring.end(sort), e); + } + private: + Symbol::Sort sort; + }; + + typedef internal::flatten_iterator iterator; + + iterator begin() const { return iterator(plies.begin(), plies.end(), Begin(sort), End(sort)); } + iterator end() const { return iterator(plies.end(), plies.end(), Begin(sort), End(sort)); } + + private: + friend class Grounder; + + Names(const Grounder* owner, Symbol::Sort sort, Plies::Policy policy) : sort(sort), plies(owner, policy) {} + + const Symbol::Sort sort; + const Plies plies; + }; + + class Undo { + public: + Undo() = default; + Undo(const Undo&) = delete; + Undo& operator=(const Undo&) = delete; + Undo(Undo&& u) : owner_(u.owner_) { u.owner_ = nullptr; } + Undo& operator=(Undo&& u) { owner_ = u.owner_; u.owner_ = nullptr; return *this; } + ~Undo() { + if (owner_) { + owner_->UndoLast(); + } + owner_ = nullptr; + } + + private: + friend class Grounder; + + explicit Undo(Grounder* owner) : owner_(owner) {} + + Grounder* owner_ = nullptr; + }; + + Grounder(Symbol::Factory* sf, Term::Factory* tf) : tf_(tf), name_pool_(sf, tf), var_pool_(sf, tf) {} + Grounder(const Grounder&) = delete; + Grounder& operator=(const Grounder&) = delete; + Grounder(Grounder&&) = default; + Grounder& operator=(Grounder&&) = default; + ~Grounder() { + while (!plies_.empty()) { + plies_.erase(std::prev(plies_.end())); + } } - TermSet SplitTerms() const { - return Ground(splits_); + NamePool& temp_name_pool() { return name_pool_; } + + Setup& setup() { return last_ply().clauses.shallow_setup.setup(); } + const Setup& setup() const { return last_ply().clauses.shallow_setup.setup(); } + + // 1. AddClause(c): + // New ply. + // Add c to ungrounded_clauses. + // Add new names in c to names. + // Add variables to vars, generate plus-names. + // Re-ground. + // + // 2. PrepareForQuery(phi): + // New ply. + // Add new names in phi to names. + // Add variables to vars, generate plus-names. + // Re-ground. + // Add f(.)=n, f(.)/=n pairs from grounded phi to lhs_rhs. + // + // 3. AddUnit(t=n): + // New ply. + // Add t=n to ungrounded_clauses. + // If t=n contains a plus-name, add these to names and generate new plus-names. + // If n is new, add n to names. + // If either of the two cases, re-ground. + // + // 3. AddUnits(U): + // New ply. + // Add U to ungrounded_clauses. + // If U contains t=n for new n, add n to names and re-ground. + // (Note: in this case, all literals in U are of the form t'=n.) + // + // Re-ground: + // Ground ungrounded_clauses for names and vars from last ply. + // Add f(.)=n, f(.)/=n pairs from newly grounded clauses to lhs_rhs. + // [ Close unit sets from previous AddUnit(U) plies under isomorphism with the names and vars from the last ply. ] + // + // We add the plus-names for quantifiers in the query in advance and ground + // everything with them as if they occurred in the query. + // So to determine the split and fix names, lhs_rhs suffices. + // + // Splits: {t=n | t in terms, n in lhs_rhs[t] or single new one} + // Fixes: {t=n | t in terms, n in lhs_rhs[t] or single new one} or + // for every t in terms, n in lhs_rhs[t]: + // {t*=n* | t* in terms, n in lhs_rhs[t] or x in lhs_rhs[t], t=n, t*=n* isomorphic} + // + // Isomorphic literals: the bijection for a literal f(n1,...,nK)=n0 should only modify n1,...,nK, but not n0 unless + // it is contained in n1,...,nK. Otherwise we'd add f(n1,...,nK)=n0, f(n1,...,nK)=n0*, etc. which obviously is + // inconsistent. + + Setup::Result AddClause(const Clause& c, Undo* undo = nullptr, bool do_not_add_if_inconsistent = false) { + return AddClauses(internal::singleton_range(c), undo, do_not_add_if_inconsistent); } - TermSet RelevantSplitTerms(const Formula& phi) { - assert(phi.objective()); - const Setup& s = Ground(); - TermSet queue = Ground(Mentioned([](Term t) { return t.function(); }, phi)); - for (auto it = queue.begin(); it != queue.end(); ) { - if (s.Determines(*it)) { - it = queue.erase(it); - } else { - ++it; - } + template + Setup::Result AddClauses(const T& clauses, Undo* undo = nullptr, const bool do_not_add_if_inconsistent = false) { + // Add c to ungrounded_clauses. + // Add new names in c to names. + // Add variables to vars, generate plus-names. + // Re-ground. + Ply& p = new_ply(); + SortedTermSet reused_plus_names; + for (const Clause& c : clauses) { + Ungrounded uc(c); + uc.val.Traverse([this, &p, &uc, &reused_plus_names](Term t) { + if (t.variable()) { + uc.vars.insert(t); + } + if (t.name()) { + if (IsPlusName(t)) { + reused_plus_names.insert(t); + } else { + p.names.occurring.insert(t); + } + } + return true; + }); + p.clauses.ungrounded.push_back(uc); + CreateMaxPlusNames(uc.vars, 1); + } + CreateNewPlusNames(reused_plus_names); + p.do_not_add_if_inconsistent = do_not_add_if_inconsistent; + const Setup::Result r = Reground(); + if (undo) { + *undo = Undo(this); } - TermSet splits; - RelevantClosure(s, &queue, &splits, [](const Clause& c, Term t, TermSet* queue) { - if (c.MentionsLhs(t)) { - TermSet next = Mentioned([](Term t) { return t.function(); }, c); - queue->insert(next.begin(), next.end()); + return r; + } + + void PrepareForQuery(const Term t, Undo* undo = nullptr) { + const Term x = var_pool_.Create(t.sort()); + const Literal a = Literal::Eq(t, x); + const Formula::Ref phi = Formula::Factory::Atomic(Clause{a}); + PrepareForQuery(*phi, undo); + var_pool_.Return(x); + } + + void PrepareForQuery(const Formula& phi, Undo* undo = nullptr) { + // New ply. + // Add new names in phi to names. + // Add variables to vars, generate plus-names. + // Re-ground. + // Add f(.)=n, f(.)/=n pairs from grounded phi to lhs_rhs. + Ply& p = new_ply(); + SortedTermSet reused_plus_names; + phi.Traverse([this, &p, &reused_plus_names](const Literal a) { + Ungrounded ua(a.pos() ? a : a.flip()); + a.Traverse([this, &p, &reused_plus_names, &ua](const Term t) { + if (t.name()) { + if (IsPlusName(t)) { + reused_plus_names.insert(t); + } else { + p.names.occurring.insert(t); + } + } else if (t.variable()) { + ua.vars.insert(t); + } return true; - } else { - return false; + }); + if (ua.val.lhs().function() && IsNewUngroundedLhsRhs(ua)) { + last_ply().lhs_rhs.ungrounded.insert(ua); } + return true; }); - return splits; + CreateNewPlusNames(reused_plus_names); + CreateMaxPlusNames(phi.n_vars()); // XXX or CreateNewPlusNames()? + Reground(); + if (undo) { + *undo = Undo(this); + } } - TermSet RelevantSplitTerms(Term lhs) { - const Setup& s = Ground(); - if (s.Determines(lhs)) { - return TermSet(); - } - TermSet queue({lhs}); - TermSet splits; - RelevantClosure(s, &queue, &splits, [](const Clause& c, Term t, TermSet* queue) { - if (c.MentionsLhs(t)) { - TermSet next = Mentioned([](Term t) { return t.function(); }, c); - queue->insert(next.begin(), next.end()); - return true; - } else { - return false; + void GuaranteeConsistency(const Formula& alpha, Undo* undo) { + // Collect ungrounded terms from query. + // Close under terms in current setup. + assert(plies_.empty() || !last_ply().relevant.filter); + Ply& p = new_ply(); + p.relevant.filter = true; + alpha.Traverse([this, &p](const Term t) { + if (t.function()) { + Ungrounded ut(t); + t.Traverse([&ut](const Term x) { if (x.variable()) { ut.vars.insert(x); } return true; }); + if (IsNewUngroundedRelevantTerm(ut)) { + p.relevant.ungrounded.insert(ut); + } } + return false; }); - return splits; + for (const Ungrounded& u : p.relevant.ungrounded) { + for (const Term g : groundings(&u.val, &u.vars)) { + UpdateRelevantTerms(g); + } + } + CloseRelevanceUnderClauses(p.clauses.shallow_setup.setup().clauses()); + GroundNewSetup(); + if (undo) { + *undo = Undo(this); + } } - LiteralAssignmentSet LiteralAssignments() const { - return LiteralAssignments(assigns_); + void GuaranteeConsistency(Term t, Undo* undo) { + // Add t to ungrounded terms from query. + // Close under terms in current setup. + assert(plies_.empty() || !last_ply().relevant.filter); + assert(t.primitive()); + Ply& p = new_ply(); + p.relevant.filter = true; + Ungrounded ut(t); + if (IsNewUngroundedRelevantTerm(ut)) { + p.relevant.ungrounded.insert(ut); + } + UpdateRelevantTerms(t); + CloseRelevanceUnderClauses(p.clauses.shallow_setup.setup().clauses()); + GroundNewSetup(); + if (undo) { + *undo = Undo(this); + } } - LiteralAssignmentSet RelevantLiteralAssignments(const Formula& phi) { - assert(phi.objective()); - const Setup& s = Ground(); - LiteralSet queue; - AddAssignmentLiteralsTo(Ground(Mentioned([](Literal a) { return a.lhs().function(); }, phi)), &queue); - for (auto it = queue.begin(); it != queue.end(); ) { - if (s.Determines(it->lhs())) { - it = queue.erase(it); - } else { - ++it; - } - } - LiteralSet assigns; - RelevantClosure(s, &queue, &assigns, [this, &assigns](const Clause& c, Literal a, LiteralSet* queue) { - if (c.MentionsLhs(a.lhs())) { - AddAssignmentLiteralsTo(Mentioned([](Literal a) { return a.lhs().function(); }, c), queue); - return true; - } else { - return false; + void UndoLast() { pop_ply(); } + + Literal Variablify(Literal a) { + assert(a.ground()); + Term::Vector ns; + a.lhs().Traverse([&ns](Term t) { + if (t.name() && std::find(ns.begin(), ns.end(), t) != ns.end()) { + ns.push_back(t); } + return true; }); - return LiteralAssignments(assigns); + return a.Substitute([this, ns](Term t) { + const size_t i = std::find(ns.begin(), ns.end(), t) - ns.begin(); + return i != ns.size() ? internal::Just(var_pool_.Get(t.sort(), i)) : internal::Nothing; + }, tf_); } + Plies plies(Plies::Policy p = Plies::kAll) const { return Plies(this, p); } + LhsTerms lhs_terms(Plies::Policy p = Plies::kAll) const { return LhsTerms(this, p); } + // The additional name must not be used after RhsName's death. + RhsNames rhs_names(Term t, Plies::Policy p = Plies::kAll) { return RhsNames(this, t, p); } + Names names(Symbol::Sort sort, Plies::Policy p = Plies::kAll) const { return Names(this, sort, p); } + private: -#ifdef FRIEND_TEST - FRIEND_TEST(GrounderTest, Ground_SplitTerms_Names); - FRIEND_TEST(GrounderTest, Assignments); -#endif + template + struct Groundings { + public: + struct Assignments { + public: + struct NotX { + explicit NotX(Term x) : x(x) {} - typedef internal::IntMap PlusMap; + bool operator()(Term y) const { return x != y; } - class Assignments { - public: - struct GetRange { - GetRange(const SortedTermSet* substitutes) : substitutes_(substitutes) {} - std::pair operator()(const Term x) const { - return std::make_pair(x, substitutes_->values(x)); + private: + const Term x; + }; + + struct DomainCodomain { + DomainCodomain(const Grounder* owner, Plies::Policy policy) : owner(owner), policy(policy) {} + + std::pair operator()(const Term x) const { + return std::make_pair(x, owner->names(x.sort(), policy)); + } + + private: + const Grounder* const owner; + const Plies::Policy policy; + }; + + typedef internal::filter_iterator vars_iterator; + typedef internal::transform_iterator var_names_iterator; + typedef internal::mapping_iterator iterator; + + Assignments(const Grounder* owner, const SortedTermSet* vars, Plies::Policy policy, Term x, Term n) + : vars(vars), owner(owner), policy(policy), x(x), n(n) {} + + iterator begin() const { + auto p = NotX(x); + auto f = DomainCodomain(owner, policy); + auto b = vars->begin(); + auto e = vars->end(); + return iterator(var_names_iterator(vars_iterator(b, e, p), f), var_names_iterator(vars_iterator(e, e, p), f)); } + iterator end() const { return iterator(); } + private: - const SortedTermSet* substitutes_; + const SortedTermSet* const vars; + const Grounder* const owner; + const Plies::Policy policy; + const Term x; + const Term n; }; - typedef internal::transform_iterator domain_codomain_iterator; - typedef internal::mapping_iterator mapping_iterator; - Assignments(const TermSet& vars, const SortedTermSet* substitutes) : vars_(vars), substitutes_(substitutes) {} + struct Ground { + Ground(Term::Factory* tf, const T* obj, Term x, Term n) : tf_(tf), obj(obj), x(x), n(n) {} + T operator()(const typename Assignments::iterator::value_type& assignment) const { + auto substitution = [this, &assignment](Term y) { return x == y ? internal::Just(n) : assignment(y); }; + return obj->Substitute(substitution, tf_); + } + private: + Term::Factory* const tf_; + const T* const obj; + const Term x; + const Term n; + }; - mapping_iterator begin() const { - return mapping_iterator(domain_codomain_iterator(vars_.begin(), GetRange(substitutes_)), - domain_codomain_iterator(vars_.end(), GetRange(substitutes_))); - } - mapping_iterator end() const { return mapping_iterator(); } + typedef internal::transform_iterator iterator; + + Groundings(const Grounder* owner, const T* obj, const SortedTermSet* vars, Term x, Term n, Plies::Policy p) + : x(x), n(n), assignments(owner, vars, p, x, n), ground(owner->tf_, obj, x, n) {} + + iterator begin() const { return iterator(assignments.begin(), ground); } + iterator end() const { return iterator(assignments.end(), ground); } private: - const TermSet vars_; - const SortedTermSet* substitutes_; + Term x; + Term n; + Assignments assignments; + Ground ground; }; - struct PairHasher { - internal::hash32_t operator()(const std::pair& p) const { - typedef internal::uptr_t uptr_t; - typedef internal::u32 u32; - const uptr_t addr = reinterpret_cast(p.first); - return internal::jenkins_hash(static_cast(addr)) ^ - internal::jenkins_hash(static_cast(addr >> 32)) ^ - p.second.hash(); + template + Groundings groundings(const T* o, const SortedTermSet* vars, Plies::Policy p = Plies::kAll) const { + return groundings(o, vars, Term(), Term(), p); + } + template + Groundings groundings(const T* o, const SortedTermSet* vars, Term x, Term n, Plies::Policy p = Plies::kAll) const { + return Groundings(this, o, vars, x, n, p); + } + + Ply& new_ply() { + if (plies_.empty()) { + plies_.push_back(Ply()); + Ply& p = plies_.back(); + p.clauses.full_setup = std::unique_ptr(new Setup()); + p.clauses.shallow_setup = p.clauses.full_setup->shallow_copy(); + return p; + } else { + Ply& last_p = last_ply(); + plies_.push_back(Ply()); + Ply& p = plies_.back(); + p.clauses.shallow_setup = last_p.clauses.shallow_setup.setup().shallow_copy(); + p.relevant.filter = last_p.relevant.filter; + return p; } - }; + } - template - void Ground(const T ungrounded, U* grounded_set) const { - assert(ungrounded.quasiprimitive()); - const TermSet vars = Mentioned([](Term t) { return t.variable(); }, ungrounded); - for (const auto& mapping : Assignments(vars, &names_)) { - auto grounded = ungrounded.Substitute(mapping, tf_); - assert(grounded.primitive()); - grounded_set->insert(grounded); + Ply& last_ply() { assert(!plies_.empty()); return plies_.back(); } + const Ply& last_ply() const { assert(!plies_.empty()); return plies_.back(); } + + void pop_ply() { + assert(!plies_.empty()); + Ply& p = last_ply(); + for (const Term n : p.names.plus_max) { + name_pool_.Return(n); + } + for (const Term n : p.names.plus_new) { + name_pool_.Return(n); } + plies_.pop_back(); } - template - T Ground(const T& ungrounded_set) const { - T grounded_set; - for (auto ungrounded : ungrounded_set) { - Ground(ungrounded, &grounded_set); + bool IsNewUngroundedLhsRhs(const Ungrounded& ua) { + assert(ua.val.lhs().function()); + for (const Ply& p : plies(Plies::kSinceSetup)) { + if (p.lhs_rhs.ungrounded.find(ua) != p.lhs_rhs.ungrounded.end()) { + return false; + } + } + return true; + } + + bool IsNewLhsRhs(Literal a) { + assert(a.primitive()); + for (const Ply& p : plies(Plies::kSinceSetup)) { + auto it = p.lhs_rhs.map.find(a.lhs()); + if (it != p.lhs_rhs.map.end() && it->second.find(a.rhs()) != it->second.end()) { + return false; + } + } + return true; + } + + bool IsNewUngroundedRelevantTerm(const Ungrounded& ut) { + assert(ut.val.function()); + for (const Ply& p : plies(Plies::kSinceSetup)) { + if (p.relevant.ungrounded.find(ut) != p.relevant.ungrounded.end()) { + return false; + } } - return grounded_set; + return true; } - template - static Collection Mentioned(const UnaryPredicate p, const Haystack& obj) { - Collection needles; - obj.Traverse([p, &needles](const typename Collection::value_type& t) { - if (p(t)) { - needles.insert(t); + bool IsNewRelevantTerm(Term t) { + assert(t.ground() && t.function()); + for (const Ply& p : plies(Plies::kSinceSetup)) { + if (p.relevant.terms.contains(t)) { + return false; } + } + return true; + } + + bool IsRelevantClause(const Clause& c) { + if (!last_ply().relevant.filter) { return true; - }); - return needles; - } - - static PlusMap PlusNames(Term lhs) { - // For term queries like KRef lhs, we assume there were a variable (lhs = x). - // Hence we need two plus names: one for x, and one for the Lemma 8 fix. - PlusMap plus; - plus[lhs.sort()] = 2; - for (const Term var : Mentioned([](Term t) { return t.variable(); }, lhs)) { - ++plus[var.sort()]; - } - return plus; - } - - static PlusMap PlusNames(const Clause& c) { - PlusMap plus; - for (const Term var : Mentioned([](Term t) { return t.variable(); }, c)) { - ++plus[var.sort()]; - } - // The following fixes Lemma 8 in the LBF paper. The problem is that - // for KB = {[c = x]}, unit propagation should yield the empty clause; - // but this requires that x is grounded by more than one name. It suffices - // to ground variables by p+1 names, where p is the maximum number of - // variables in any clause. - // PlusNames() computes p for a given clause; it is hence p+1 where p - // is the number of variables in that clause. - PlusMap plus_one; - c.Traverse([&plus_one](Term t) { plus_one[t.sort()] = 1; return true; }); - return PlusMap::Zip(plus, plus_one, [](size_t lp, size_t rp) { return lp + rp; }); - } - - static PlusMap PlusNames(const Formula& phi) { - assert(phi.objective()); - // Roughly, we need to add one name for each quantifier. More precisely, - // it suffices to check for every sort which is the maximal number of - // different variables occurring freely in any subformula of phi. We do - // so from the inside to the outside, determining the number of free - // variables of any sort in cur, and the maximum in max. - PlusMap max; - PlusMap cur; - PlusNames(phi, &cur, &max); - return max; - } - - static void PlusNames(const Formula& phi, PlusMap* cur, PlusMap* max) { - assert(phi.objective()); - switch (phi.type()) { - case Formula::kAtomic: - *cur = PlusNames(phi.as_atomic().arg()); - *max = *cur; - break; - case Formula::kNot: - PlusNames(phi.as_not().arg(), cur, max); - break; - case Formula::kOr: { - PlusMap lcur, lmax; - PlusMap rcur, rmax; - PlusNames(phi.as_or().lhs(), &lcur, &lmax); - PlusNames(phi.as_or().rhs(), &rcur, &rmax); - *cur = PlusMap::Zip(lcur, rcur, [](size_t lp, size_t rp) { return lp + rp; }); - *max = PlusMap::Zip(lmax, rmax, [](size_t lp, size_t rp) { return std::max(lp, rp); }); - *max = PlusMap::Zip(*max, *cur, [](size_t mp, size_t cp) { return std::max(mp, cp); }); - break; - } - case Formula::kExists: { - PlusNames(phi.as_exists().arg(), cur, max); - Symbol::Sort sort = phi.as_exists().x().sort(); - if ((*cur)[sort] > 0) { - --(*cur)[sort]; - } - break; + } + for (const Ply& p : plies(Plies::kSinceSetup)) { + if (!p.relevant.terms.all_empty() && + c.any([&p](const Literal a) { return !a.lhs().name() && p.relevant.terms.contains(a.lhs()); })) { + return true; } - case Formula::kKnow: - case Formula::kCons: - case Formula::kBel: - case Formula::kGuarantee: - break; } + return false; } - bool AddMentionedNames(const SortedTermSet& names) { - const size_t added = names_.insert(names); - return added > 0; + size_t nMaxPlusNames(Symbol::Sort sort) const { + size_t n_names = 0; + for (const Ply& p : plies_) { + n_names += p.names.plus_max.n_values(sort); + } + return n_names; } - bool AddPlusNames(const PlusMap& plus) { - size_t added = 0; - for (const Symbol::Sort sort : plus.keys()) { - size_t m = plus_[sort]; - size_t n = plus[sort]; - if (n > m) { - plus_[sort] = n; - n -= m; - while (n-- > 0) { - added += names_.insert(CreateName(sort)); + bool IsPlusName(Term n) const { + assert(n.name()); + for (const Ply& p : plies_) { + if (p.names.plus_max.contains(n) || p.names.plus_new.contains(n)) { + return true; + } + } + return false; + } + + void CreateMaxPlusNames(const Formula::SortCount& sc) { + Ply& p = last_ply(); + for (const Symbol::Sort sort : sc.keys()) { + const size_t need_total = sc[sort]; + if (need_total > 0) { + const size_t have_already = nMaxPlusNames(sort); + for (size_t i = have_already; i < need_total; ++i) { + p.names.plus_max.insert(name_pool_.Create(sort)); } } } - return added > 0; } - void AddSplitTerms(const TermSet& terms) { - size_t added = 0; - for (Term t : terms) { - added += splits_.insert(t).second ? 1 : 0; + void CreateMaxPlusNames(const SortedTermSet& vars, size_t plus) { + Ply& p = last_ply(); + for (const Symbol::Sort sort : vars.keys()) { + size_t need_total = vars.n_values(sort); + if (need_total > 0) { + need_total += plus; + const size_t have_already = nMaxPlusNames(sort); + for (size_t i = have_already; i < need_total; ++i) { + p.names.plus_max.insert(name_pool_.Create(sort)); + } + } } } - template - void RelevantClosure(const Setup& s, SourceQueue* queue, Sink* sink, UnaryPredicate collect) { - std::unordered_set done; - RelevantClosure(s, queue, &done, sink, collect); + void CreateNewPlusNames(const SortedTermSet& ts) { + Ply& p = last_ply(); + for (const Symbol::Sort sort : ts.keys()) { + size_t need_total = ts.n_values(sort); + for (size_t i = 0; i < need_total; ++i) { + p.names.plus_new.insert(name_pool_.Create(sort)); + } + } } - template - void RelevantClosure(const Setup& s, - SourceQueue* queue, - std::unordered_set* done, - Sink* sink, - UnaryPredicate collect) { - while (!queue->empty()) { - const auto elem = *queue->begin(); - queue->erase(queue->begin()); - auto p = sink->insert(elem); - if (p.second) { - for (size_t i : s.clauses()) { - if (done->find(i) != done->end()) { - continue; - } - const Clause c = s.clause(i); - if (c.unit() && c.first().pos()) { - continue; - } - if (collect(c, elem, queue)) { - done->insert(i); - } - } + void UpdateLhsRhs(Literal a) { + assert(a.ground()); + if (a.lhs().function() && IsNewLhsRhs(a)) { + const Term t = a.lhs(); + const Term n = a.rhs(); + assert(t.ground() && n.name()); + Ply& p = last_ply(); + auto it = p.lhs_rhs.map.find(t); + if (it == p.lhs_rhs.map.end()) { + it = p.lhs_rhs.map.insert(std::make_pair(t, std::unordered_set())).first; } + it->second.insert(n); } } - void AddAssignmentLiteralsTo(const LiteralSet& lits, LiteralSet* assigns) { - for (Literal a : lits) { - if (!a.pos()) { - const Term x = tf_->CreateTerm(sf_->CreateVariable(a.rhs().sort())); - a = Literal::Eq(a.lhs(), x); + void UpdateLhsRhs(const Clause& c) { + for (const Literal a : c) { + UpdateLhsRhs(a); + } + } + + void UpdateRelevantTerms(Term t) { + assert(t.ground()); + if (t.function() && IsNewRelevantTerm(t)) { + last_ply().relevant.terms.insert(t); + } + } + + void UpdateRelevantTerms(const Clause& c) { + assert(c.ground()); + assert(!c.valid()); + if (c.any([this](const Literal a) { return !IsNewRelevantTerm(a.lhs()); })) { + c.all([this](const Literal a) { + UpdateRelevantTerms(a.lhs()); + return true; + }); + } + } + + template + void CloseRelevanceUnderClauses(ClauseRange r) { + std::unordered_set clauses; + for (size_t i : r) { + clauses.insert(i); + } +rescan: + for (auto it = clauses.begin(); it != clauses.end(); ++it) { + const Clause c = last_ply().clauses.shallow_setup.setup().clause(*it); + if (IsRelevantClause(c)) { + UpdateRelevantTerms(c); + clauses.erase(it); + goto rescan; } - assigns->insert(a); } } - void AddAssignmentLiterals(const LiteralSet& lits) { - AddAssignmentLiteralsTo(lits, &assigns_); + bool InconsistencyCheck(const Ply& p, const Clause& c) { + return !p.do_not_add_if_inconsistent || !c.unit() || !setup().Subsumes(Clause{c[0].flip()}); } - LiteralAssignmentSet LiteralAssignments(const LiteralSet& assigns) const { - LiteralSet ground = Ground(assigns); - struct Func { // a Lambda doesn't have assignment operators - LiteralSet operator()(Literal a) const { return LiteralSet{a}; } - }; - auto r = internal::transform_crange(ground, Func()); - LiteralAssignmentSet sets(r.begin(), r.end()); - for (Literal a : ground) { - for (auto it = sets.begin(); it != sets.end(); ) { - const LiteralSet& set = *it; - assert(!set.empty()); - const Literal b = *set.begin(); - if (a.lhs().symbol() == b.lhs().symbol() && set.find(a) == set.end() && Literal::Isomorphic(a, b)) { - if (set.size() == 1) { - LiteralSet new_set = set; - new_set.insert(a); - const float prev_load_factor = sets.load_factor(); - const float prev_size = sets.size(); - sets.insert(new_set); - if (sets.size() > prev_size && sets.load_factor() <= prev_load_factor) { - it = sets.begin(); - } else { - ++it; + template + void ForEachGrounding(UnaryFunction range, UnaryPredicate pred, Setup::Result* add_result = nullptr) { + typedef decltype(range(std::declval()).begin()) iterator; + typedef typename iterator::value_type::value_type value_type; + for (const Ply& p : plies_) { + for (const Ungrounded& u : range(p)) { + for (const value_type& g : groundings(&u.val, &u.vars)) { + assert(g.ground()); + pred(g, p, add_result); + if (add_result && *add_result == Setup::kInconsistent) { + return; + } + } + } + } + } + + template + void ForEachNewGrounding(UnaryFunction range, UnaryPredicate pred, Setup::Result* add_result = nullptr) { + typedef decltype(range(std::declval()).begin()) iterator; + typedef typename iterator::value_type::value_type value_type; + for (const Ply& p : plies(Plies::kOld)) { + for (const Ungrounded& u : range(p)) { + for (const Term x : u.vars) { + for (const Term n : names(x.sort(), Plies::kNew)) { + for (const value_type& g : groundings(&u.val, &u.vars, x, n)) { + assert(g.ground()); + pred(g, p, add_result); + if (add_result && *add_result == Setup::kInconsistent) { + return; + } } - } else { - LiteralSet new_set = set; - new_set.insert(a); - it = sets.erase(it); - sets.insert(new_set); } - } else { - ++it; } } } - return sets; + const Ply& p = last_ply(); + for (const Ungrounded& u : range(p)) { + for (const value_type& g : groundings(&u.val, &u.vars)) { + pred(g, p, add_result); + if (add_result && *add_result == Setup::kInconsistent) { + return; + } + } + } + } + + Setup::Result Reground(bool minimize = false) { + // Ground old clauses for names from last ply. + // Ground new clauses for all names. + // Add f(.)=n, f(.)/=n pairs from newly grounded clauses to lhs_rhs. + Setup::Result add_result = Setup::kSubsumed; + ForEachNewGrounding( + [](const Ply& p) { return p.clauses.ungrounded; }, + [this](const Clause& c, const Ply& p, Setup::Result* add_result) { + // XXX Should relevance be tested only for clauses from before the consistency-guarantee? + if (!c.valid() && IsRelevantClause(c) && InconsistencyCheck(p, c)) { + const Setup::Result r = setup().AddClause(c); + switch (r) { + case Setup::kOk: + *add_result = r; + UpdateLhsRhs(c); + break; + case Setup::kSubsumed: + break; + case Setup::kInconsistent: + *add_result = r; + break; + } + } + }, + &add_result); + ForEachNewGrounding( + [](const Ply& p) { return p.lhs_rhs.ungrounded; }, + [this](const Literal a, const Ply&, Setup::Result*) { + UpdateLhsRhs(a); + }); + Ply& p = last_ply(); + if (minimize) { + if (p.clauses.full_setup) { + p.clauses.full_setup->Minimize(); + } else { + p.clauses.shallow_setup.Minimize(); + } + } + if (p.relevant.filter) { + ForEachNewGrounding( + [](const Ply& p) { return p.relevant.ungrounded; }, + [this](const Term t, const Ply&, Setup::Result*) { + UpdateRelevantTerms(t); + }); + CloseRelevanceUnderClauses(p.clauses.shallow_setup.new_clauses()); + } + return add_result; + } + + void GroundNewSetup() { + // Ground all clauses for all names. + Ply& p = last_ply(); + assert(p.relevant.filter); + assert(p.clauses.ungrounded.empty()); + assert(p.names.occurring.all_empty() && p.names.plus_new.all_empty() && p.names.plus_max.all_empty()); + const Setup& old_s = p.clauses.shallow_setup.setup(); + std::unique_ptr new_s(new Setup()); + for (size_t i : old_s.clauses()) { + const Clause c = old_s.clause(i); + if (IsRelevantClause(c)) { + UpdateLhsRhs(c); + new_s->AddClause(c); + } + } + new_s->Minimize(); + p.clauses.full_setup = std::move(new_s); + p.clauses.shallow_setup = p.clauses.full_setup->shallow_copy(); } - Symbol::Factory* const sf_; Term::Factory* const tf_; - PlusMap plus_; - TermSet splits_; - LiteralSet assigns_; - SortedTermSet names_; - bool names_changed_ = false; - std::list processed_clauses_; - std::list unprocessed_clauses_; - SortedTermSet owned_names_; - internal::Maybe setup_; + NamePool name_pool_; + VariablePool var_pool_; + Ply::List plies_; }; } // namespace limbo diff --git a/src/limbo/internal/intmap.h b/src/limbo/internal/intmap.h index bae5fa1..ea51e8b 100644 --- a/src/limbo/internal/intmap.h +++ b/src/limbo/internal/intmap.h @@ -62,33 +62,23 @@ class IntMap { Keys keys() const { return Keys(this); } - struct Values { - typedef typename Vec::iterator iterator; - explicit Values(IntMap* owner) : owner(owner) {} - iterator begin() const { return owner->vec_.begin(); } - iterator end() const { return owner->vec_.end(); } - private: - IntMap* owner; - }; + typename Vec::iterator begin() { return vec_.begin(); } + typename Vec::iterator end() { return vec_.end(); } + + typename Vec::const_iterator begin() const { return vec_.begin(); } + typename Vec::const_iterator end() const { return vec_.end(); } struct ConstValues { typedef typename Vec::const_iterator iterator; explicit ConstValues(const IntMap* owner) : owner(owner) {} - iterator begin() const { return owner->vec_.begin(); } - iterator end() const { return owner->vec_.end(); } + iterator begin() const { return owner->begin(); } + iterator end() const { return owner->end(); } private: const IntMap* owner; }; - Values values() { return Values(this); } ConstValues values() const { return ConstValues(this); } - typename Values::iterator begin() { return values().begin(); } - typename Values::iterator end() { return values().end(); } - - typename ConstValues::iterator begin() const { return values().begin(); } - typename ConstValues::iterator end() const { return values().end(); } - template static IntMap Zip(const IntMap& m1, const IntMap& m2, BinaryFunction f) { IntMap m; @@ -115,63 +105,78 @@ class IntMap { template class IntMultiMap { public: - typedef std::unordered_set Set; - typedef IntMap Base; + typedef std::unordered_set Bucket; + typedef IntMap Base; typedef T value_type; bool operator==(const IntMultiMap& a) const { return map_ == a.map_; } bool operator!=(const IntMultiMap& a) const { return !(*this == a); } - typename Base::reference operator[](Key key) { return map_[key]; } - typename Base::const_reference operator[](Key key) const { return map_[key]; } + Bucket& operator[](Key key) { return map_[key]; } + const Bucket& operator[](Key key) const { return map_[key]; } size_t insert(Key key, const T& val) { auto p = map_[key].insert(val); - return p.second ? 1 : 0; + size_t n = p.second ? 1 : 0; + size_ += n; + return n; } - void erase(Key key, const T& val) { - map_[key].erase(val); + size_t erase(Key key, const T& val) { + size_t n = map_[key].erase(val); + size_ -= n; + return n; } bool contains(Key key, const T& val) const { - const value_type& s = map_[key]; + const Bucket& s = map_[key]; return s.find(val) != s.end(); } size_t n_keys() const { return map_.n_keys(); } + size_t n_values(Key key) const { return map_[key].size(); } typedef typename Base::Keys Keys; Keys keys() const { return Keys(&map_); } - struct PosValues { - explicit PosValues(const IntMultiMap* owner, Key key) : owner(owner), key(key) {} - typename Base::value_type::const_iterator begin() const { return owner->map_[key].begin(); } - typename Base::value_type::const_iterator end() const { return owner->map_[key].end(); } + typedef typename Bucket::const_iterator value_iterator; + + value_iterator begin(Key key) const { return map_[key].begin(); } + value_iterator end(Key key) const { return map_[key].end(); } + + struct ValuesForKey { + explicit ValuesForKey(const IntMultiMap* owner, Key key) : owner(owner), key(key) {} + value_iterator begin() const { return owner->begin(key); } + value_iterator end() const { return owner->end(key); } private: const IntMultiMap* owner; Key key; }; - PosValues values(Key key) const { return PosValues(this, key); } + ValuesForKey values(Key key) const { return ValuesForKey(this, key); } + + typedef flatten_iterator all_values_iterator; + + all_values_iterator begin() const { return all_values_iterator(map_.begin(), map_.end()); } + all_values_iterator end() const { return all_values_iterator(map_.end(), map_.end()); } struct Values { - typedef flatten_iterator iterator; - explicit Values(IntMultiMap* owner) : owner(owner) {} - iterator begin() const { return owner->map_.values().begin(); } - iterator end() const { return owner->map_.values().end(); } + explicit Values(const IntMultiMap* owner) : owner(owner) {} + all_values_iterator begin() const { return owner->begin(); } + all_values_iterator end() const { return owner->end(); } private: - IntMultiMap* owner; + const IntMultiMap* owner; }; Values values() const { return Values(this); } - typename Values::iterator begin() const { return values().begin(); } - typename Values::iterator end() const { return values().end(); } + bool all_empty() const { return size_ == 0; } + size_t total_size() const { return size_; } private: Base map_; + size_t size_ = 0; }; template::type> @@ -179,6 +184,7 @@ class IntMultiSet { public: typedef IntMultiMap Parent; typedef typename Parent::Base Base; + typedef typename Parent::Bucket Bucket; typedef T value_type; explicit IntMultiSet(UnaryFunction key = UnaryFunction()) : key_(key) {} @@ -186,8 +192,8 @@ class IntMultiSet { bool operator==(const IntMultiSet& a) const { return map_ == a.map_; } bool operator!=(const IntMultiSet& a) const { return !(*this == a); } - typename Base::reference operator[](Key key) { return map_[key]; } - typename Base::const_reference operator[](Key key) const { return map_[key]; } + Bucket& operator[](Key key) { return map_[key]; } + const Bucket& operator[](Key key) const { return map_[key]; } size_t insert(const T& val) { return map_.insert(key_(val), val); } @@ -206,21 +212,29 @@ class IntMultiSet { return n; } - bool contains(const T& val) const { return map_.contains(key_(val)); } + bool contains(const T& val) const { return map_.contains(key_(val), val); } size_t n_keys() const { return map_.n_keys(); } + size_t n_values(Key key) const { return map_[key].size(); } typedef typename Parent::Keys Keys; - typedef typename Parent::PosValues PosValues; + typedef typename Parent::value_iterator value_iterator; + typedef typename Parent::ValuesForKey ValuesForKey; + typedef typename Parent::all_values_iterator all_values_iterator; typedef typename Parent::Values Values; Keys keys() const { return map_.keys(); } - PosValues values(Key key) const { return map_.values(key); } - PosValues values(const T& val) const { return values(key_(val)); } + value_iterator begin(Key key) const { return map_[key].begin(); } + value_iterator end(Key key) const { return map_[key].end(); } + ValuesForKey values(Key key) const { return map_.values(key); } + ValuesForKey values(const T& val) const { return values(key_(val)); } Values values() const { return map_.values(); } - typename Values::iterator begin() const { return values().begin(); } - typename Values::iterator end() const { return values().end(); } + all_values_iterator begin() const { return values().begin(); } + all_values_iterator end() const { return values().end(); } + + bool all_empty() const { return map_.all_empty(); } + size_t total_size() const { return map_.total_size(); } private: UnaryFunction key_; diff --git a/src/limbo/internal/iter.h b/src/limbo/internal/iter.h index 055208c..c3e1e18 100644 --- a/src/limbo/internal/iter.h +++ b/src/limbo/internal/iter.h @@ -2,7 +2,7 @@ // Copyright 2016-2017 Christoph Schwering // Licensed under the MIT license. See LICENSE file in the project root. // -// A couple of iterators to immitate Haskell lists with iterators. +// A few iterators to immitate Haskell lists with iterators. // // Maybe boost provides the same iterators and we should move to boost (this set // of iterators evolved somewhat). @@ -57,7 +57,7 @@ class int_iterator { int_iterator() = default; explicit int_iterator(value_type index, UnaryFunction func = UnaryFunction()) : index_(index), func_(func) {} - bool operator==(int_iterator it) const { return *(*this) == *it; } + bool operator==(int_iterator it) const { return index_ == it.index_; } bool operator!=(int_iterator it) const { return !(*this == it); } reference operator*() const { return func_(index_); } @@ -78,8 +78,8 @@ class int_iterators { public: typedef int_iterator iterator; - explicit int_iterators(T begin, T end, UnaryFunction func1 = UnaryFunction(), UnaryFunction func2 = UnaryFunction()) : - begin_(begin, func1), end_(end, func2) {} + explicit int_iterators(T begin, T end, UnaryFunction func1 = UnaryFunction(), UnaryFunction func2 = UnaryFunction()) + : begin_(begin, func1), end_(end, func2) {} iterator begin() const { return begin_; } iterator end() const { return end_; } @@ -97,7 +97,58 @@ inline int_iterators int_range(T begin, return int_iterators(begin, end, func1, func2); } -template +// Encapsulates a single element. +template +class singleton_iterator { + public: + typedef std::ptrdiff_t difference_type; + typedef T value_type; + typedef const value_type* pointer; + typedef const value_type& reference; + typedef std::bidirectional_iterator_tag iterator_category; + + singleton_iterator() = default; + explicit singleton_iterator(value_type obj) : obj_(obj), valid_(true) {} + + bool operator==(singleton_iterator it) const { return valid_ == it.valid_; } + bool operator!=(singleton_iterator it) const { return !(*this == it); } + + reference operator*() const { assert(valid_); return obj_; } + singleton_iterator& operator++() { valid_ = false; return *this; } + singleton_iterator& operator--() { valid_ = false; return *this; } + + pointer operator->() const { assert(valid_); return &obj_; } + reference operator++(int) { assert(valid_); valid_ = false; return obj_; } + reference operator--(int) { assert(valid_); valid_ = false; return obj_; } + + private: + value_type obj_; + bool valid_ = false; +}; + +template +class singleton_iterators { + public: + typedef singleton_iterator iterator; + + explicit singleton_iterators(T obj) : obj_(obj) {} + + iterator begin() const { return iterator(obj_); } + iterator end() const { return iterator(); } + + private: + T obj_; +}; + +template +inline singleton_iterators singleton_range(T obj) { + return singleton_iterators(obj); +} + + +// Expects a container of type T with elements of type U returned by operator[]. +template().operator[](0))> class array_iterator { public: typedef std::ptrdiff_t difference_type; @@ -138,11 +189,17 @@ class array_iterator { size_t index_; }; +template().begin())> +struct Begin { U operator()(const T& t) const { return t.begin(); } }; + +template().begin())> +struct End { U operator()(const T& t) const { return t.end(); } }; + // Expects an iterator over containers, and iterates over the containers' elements. template().begin()), - InnerInputIt (OuterInputIt::value_type::*Begin)() const = &OuterInputIt::value_type::begin, - InnerInputIt (OuterInputIt::value_type::*End)() const = &OuterInputIt::value_type::end> + typename Begin = Begin, + typename End = End> class flatten_iterator { public: typedef std::ptrdiff_t difference_type; @@ -153,12 +210,12 @@ class flatten_iterator { typedef iterator_proxy proxy; flatten_iterator() = default; - flatten_iterator(OuterInputIt cont_first, OuterInputIt cont_last) : - cont_first_(cont_first), - cont_last_(cont_last) { - if (cont_first_ != cont_last_) { - iter_ = ((*cont_first_).*Begin)(); - } + flatten_iterator(OuterInputIt cont_first, OuterInputIt cont_last, Begin begin = Begin(), End end = End()) + : cont_first_(cont_first), + cont_last_(cont_last), + begin_(begin), + end_(end), + iter_(cont_first_ != cont_last_ ? inner_begin() : InnerInputIt()) { Skip(); } @@ -169,12 +226,12 @@ class flatten_iterator { reference operator*() const { assert(cont_first_ != cont_last_); - assert(((*cont_first_).*Begin)() != ((*cont_first_).*End)()); + assert(inner_begin() != inner_end()); return *iter_; } flatten_iterator& operator++() { - assert(cont_first_ != cont_last_ && iter_ != ((*cont_first_).*End)()); + assert(cont_first_ != cont_last_ && iter_ != inner_end()); ++iter_; Skip(); return *this; @@ -196,26 +253,47 @@ class flatten_iterator { if (cont_first_ == cont_last_) { break; // iterator has ended } - if (iter_ != ((*cont_first_).*End)()) { + if (iter_ != inner_end()) { break; // found next element } ++cont_first_; if (cont_first_ != cont_last_) { - iter_ = ((*cont_first_).*Begin)(); + iter_ = inner_begin(); } } - assert(cont_first_ == cont_last_ || iter_ != ((*cont_first_).*End)()); + assert(cont_first_ == cont_last_ || iter_ != inner_end()); + } + + template + typename internal::if_arg::type inner_begin() const { + return begin_(cont_first_); + } + + template + typename internal::if_arg::type inner_begin() const { + return begin_(*cont_first_); + } + + template + typename internal::if_arg::type inner_end() const { + return end_(cont_first_); + } + template + typename internal::if_arg::type inner_end() const { + return end_(*cont_first_); } OuterInputIt cont_first_; OuterInputIt cont_last_; + Begin begin_; + End end_; InnerInputIt iter_; }; template().begin()), - InnerInputIt (OuterInputIt::value_type::*Begin)() const = &OuterInputIt::value_type::begin, - InnerInputIt (OuterInputIt::value_type::*End)() const = &OuterInputIt::value_type::end> + typename Begin = Begin, + typename End = End> class flatten_iterators { public: typedef flatten_iterator iterator; @@ -237,8 +315,8 @@ class flatten_iterators { template().begin()), - InnerInputIt (OuterInputIt::value_type::*Begin)() const = &OuterInputIt::value_type::begin, - InnerInputIt (OuterInputIt::value_type::*End)() const = &OuterInputIt::value_type::end> + typename Begin = Begin, + typename End = End> inline flatten_iterators flatten_range(OuterInputIt begin, OuterInputIt end) { return flatten_iterators(begin, end); @@ -313,8 +391,8 @@ class transform_iterators { public: typedef transform_iterator iterator; - transform_iterators(InputIt begin, InputIt end, UnaryFunction func = UnaryFunction()) : - begin_(begin, func), end_(end, func) {} + transform_iterators(InputIt begin, InputIt end, UnaryFunction func = UnaryFunction()) + : begin_(begin, func), end_(end, func) {} iterator begin() const { return begin_; } iterator end() const { return end_; } @@ -360,8 +438,8 @@ class filter_iterator { typedef iterator_proxy proxy; filter_iterator() = default; - filter_iterator(InputIt it, const InputIt end, UnaryPredicate pred = UnaryPredicate()) : - iter_(it), end_(end), pred_(pred) { Skip(); } + filter_iterator(InputIt it, const InputIt end, UnaryPredicate pred = UnaryPredicate()) + : iter_(it), end_(end), pred_(pred) { Skip(); } bool operator==(filter_iterator it) const { return iter_ == it.iter_; } bool operator!=(filter_iterator it) const { return !(*this == it); } @@ -376,7 +454,15 @@ class filter_iterator { static_assert(std::is_convertible::value, "InputIt has wrong iterator category"); - void Skip() { + template + typename internal::if_arg::type Skip() { + while (iter_ != end_ && !pred_(*iter_)) { + ++iter_; + } + } + + template + typename internal::if_arg::type Skip() { while (iter_ != end_ && !pred_(*iter_)) { ++iter_; } @@ -392,8 +478,8 @@ class filter_iterators { public: typedef filter_iterator iterator; - filter_iterators(InputIt begin, InputIt end, UnaryPredicate pred = UnaryPredicate()) : - begin_(begin, end, pred), end_(end, end, pred) {} + filter_iterators(InputIt begin, InputIt end, UnaryPredicate pred = UnaryPredicate()) + : begin_(begin, end, pred), end_(end, end, pred) {} iterator begin() const { return begin_; } iterator end() const { return end_; } @@ -422,12 +508,22 @@ filter_crange(const Range& r, UnaryPredicate pred = UnaryPredicate()) { return filter_range(r.begin(), r.end(), pred); } -template +struct Rubbish { + template + void operator()(const T1&, const T2&) const {} +}; + +// Iterates over all mappings from DomainType to CodomainInputIt::value_type. +// Elements of the iterator are functors that map DomainType to Maybe. +// The constructor takes a range of pairs of DomainType and CodomainInputIt range. +template class Map = std::unordered_map> class mapping_iterator { public: typedef DomainType domain_type; - typedef CodomainInputIt codomain_iterator; typedef typename CodomainInputIt::value_type codomain_type; + typedef CodomainInputIt codomain_iterator; struct value_type { value_type(const mapping_iterator* owner) : owner(owner) {} @@ -516,13 +612,70 @@ class mapping_iterator { codomain_iterator current; codomain_iterator end; }; - typedef std::unordered_map DomainCodomainState; - DomainCodomainState dcd_; - Maybe iter_; + Map dcd_; + Maybe::iterator> iter_; +}; + +template +class cross_iterator { + public: + typedef std::ptrdiff_t difference_type; + typedef std::pair value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef typename std::conditional< + std::is_convertible::value && + std::is_convertible::value, + std::forward_iterator_tag, std::input_iterator_tag>::type iterator_category; + typedef iterator_proxy proxy; + + cross_iterator() {} + cross_iterator(InputIt1 begin1, InputIt2 begin2, InputIt2 end2) + : it1_(begin1), begin2_(begin2), end2_(end2), it2_(begin2) {} + + bool operator==(const cross_iterator& it) const { + return (it1_ == it.it1_ && it2_ == it.it2_) || (begin2_ == end2_ && it.begin2_ == it.end2_); + } + bool operator!=(const cross_iterator& it) const { return !(*this == it); } + + value_type operator*() const { return value_type(*it1_, *it2_); } + + cross_iterator& operator++() { + ++it2_; + if (it2_ == end2_) { + it2_ = begin2_; + ++it1_; + } + return *this; + } + + cross_iterator& operator--() { + if (it2_ != begin2_) { + --it2_; + } else if (it2_ != begin2_) { + --it1_; + it2_ = end2_; + --it2_; + } + return *this; + } + + proxy operator->() const { return proxy(operator*()); } + proxy operator++(int) { proxy p(operator*()); operator++(); return p; } + proxy operator--(int) { proxy p(operator*()); operator--(); return p; } + + private: + static_assert(std::is_convertible::value, + "InputIt2 has wrong iterator category"); + + InputIt1 it1_; + InputIt2 begin2_; + InputIt2 end2_; + InputIt2 it2_; }; -template +template class joined_iterator { public: typedef std::ptrdiff_t difference_type; @@ -541,7 +694,13 @@ class joined_iterator { bool operator==(const joined_iterator& it) const { return it1_ == it.it1_ && it2_ == it.it2_; } bool operator!=(const joined_iterator& it) const { return !(*this == it); } - reference operator*() const { return it1_ != end1_ ? *it1_ : *it2_; } + reference operator*() const { + if (it1_ != end1_) { + return *it1_; + } else { + return *it2_; + } + } joined_iterator& operator++() { if (it1_ != end1_) ++it1_; else ++it2_; @@ -557,13 +716,13 @@ class joined_iterator { InputIt2 it2_; }; -template +template class joined_iterators { public: typedef joined_iterator iterator; - joined_iterators(InputIt1 begin1, InputIt1 end1, InputIt2 begin2, InputIt2 end2) : - begin1_(begin1), end1_(end1), begin2_(begin2), end2_(end2) {} + joined_iterators(InputIt1 begin1, InputIt1 end1, InputIt2 begin2, InputIt2 end2) + : begin1_(begin1), end1_(end1), begin2_(begin2), end2_(end2) {} iterator begin() const { return iterator(begin1_, end1_, begin2_); } iterator end() const { return iterator(end1_, end1_, end2_); } @@ -580,7 +739,7 @@ class joined_iterators { InputIt2 end2_; }; -template +template inline joined_iterators join_ranges(InputIt1 begin1, InputIt1 end1, InputIt2 begin2, @@ -588,13 +747,13 @@ inline joined_iterators join_ranges(InputIt1 begin1, return joined_iterators(begin1, end1, begin2, end2); } -template +template inline joined_iterators().begin()), decltype(std::declval().begin())> join_ranges(Range1& r1, Range2& r2) { return join_ranges(r1.begin(), r1.end(), r2.begin(), r2.end()); } -template +template inline joined_iterators().begin()), decltype(std::declval().begin())> join_cranges(const Range1& r1, const Range2& r2) { return join_ranges(r1.begin(), r1.end(), r2.begin(), r2.end()); diff --git a/src/limbo/internal/linked.h b/src/limbo/internal/linked.h deleted file mode 100644 index 7c8be30..0000000 --- a/src/limbo/internal/linked.h +++ /dev/null @@ -1,81 +0,0 @@ -// vim:filetype=cpp:textwidth=120:shiftwidth=2:softtabstop=2:expandtab -// Copyright 2017 Christoph Schwering -// Licensed under the MIT license. See LICENSE file in the project root. -// -// Linked containers. - -#ifndef LIMBO_INTERNAL_LINKED_H_ -#define LIMBO_INTERNAL_LINKED_H_ - -#include -#include - -namespace limbo { -namespace internal { - -template -class Linked { -public: - class iterator { - public: - typedef std::ptrdiff_t difference_type; - typedef T value_type; - typedef const value_type* pointer; - typedef const value_type& reference; - typedef std::forward_iterator_tag iterator_category; - typedef iterator_proxy proxy; - - iterator() = default; - explicit iterator(const Linked* linked) : linked_(linked) {} - - bool operator==(iterator it) const { return linked_ == it.linked_; } - bool operator!=(iterator it) const { return !(*this == it); } - - reference operator*() const { return linked_->container_; } - iterator& operator++() { linked_ = linked_->parent_; return *this; } - - proxy operator->() const { return proxy(operator*()); } - proxy operator++(int) { proxy p(operator*()); operator++(); return p; } - - private: - const Linked* linked_ = nullptr; - }; - - explicit Linked(Linked* parent = nullptr, const T& c = T()) : parent_(parent), container_(c) {} - explicit Linked(Linked* parent, T&& c) : parent_(parent), container_(c) {} - - T& container() { return container_; } - const T& container() const { return container_; } - - iterator begin() const { return iterator(this); } - iterator end() const { return iterator(); } - - template - transform_iterators transform(UnaryFunction func) const { - return transform_crange(*this, func); - } - - template - flatten_iterators::iterator> - transform_flatten(UnaryFunction func) const { - return flatten_crange(transform_crange(*this, func)); - } - - template()(std::declval()))> - U Fold(UnaryFunction map, BinaryFunction reduce) const { - U x = map(container_); - return parent_ ? reduce(parent_->Fold(map, reduce), x) : x; - } - - private: - Linked* parent_ = nullptr; - T container_; -}; - -} // namespace internal -} // namespace limbo - -#endif // LIMBO_INTERNAL_LINKED_H_ - diff --git a/src/limbo/internal/traits.h b/src/limbo/internal/traits.h index dc012c3..7b811c0 100644 --- a/src/limbo/internal/traits.h +++ b/src/limbo/internal/traits.h @@ -39,15 +39,15 @@ struct arg { using type = typename std::tuple_element>::type; }; -// is_arg::value is true iff the Nth argument of Function is -// convertible to ExpType, and false otherwise. +// is_arg::value is true iff ExpType is convertible to +// Nth argument of Function, and false otherwise. template struct is_arg { - static constexpr bool value = std::is_convertible::template type, ExpType>::value; + static constexpr bool value = std::is_convertible::template type>::value; }; -// if_arg::type is defined as Type iff the Nth -// argument of Function is convertible to ExpType. +// if_arg::type is defined as Type iff ExpType +// is convertible to the Nth argument of Function. template::value> struct if_arg {}; diff --git a/src/limbo/kb.h b/src/limbo/kb.h index cd130a2..0c476e0 100644 --- a/src/limbo/kb.h +++ b/src/limbo/kb.h @@ -42,15 +42,20 @@ #include #include +#include +#include +using limbo::format::operator<<; + namespace limbo { class KnowledgeBase { public: typedef internal::size_t size_t; typedef size_t sphere_index; + typedef Formula::belief_level belief_level; KnowledgeBase(Symbol::Factory* sf, Term::Factory* tf) : sf_(sf), tf_(tf), objective_(sf, tf) { - spheres_.push_back(Solver(sf, tf)); + spheres_.emplace_back(sf, tf); } KnowledgeBase(const KnowledgeBase&) = delete; @@ -59,9 +64,6 @@ class KnowledgeBase { KnowledgeBase& operator=(KnowledgeBase&&) = default; void Add(const Clause& c) { - for (Solver& sphere : spheres_) { - sphere.AddClause(c); - } knowledge_.push_back(c); c.Traverse([this](Term t) { if (t.name()) names_.insert(t); return true; }); } @@ -74,8 +76,8 @@ class KnowledgeBase { assume_consistent = true; } if (beta->type() == Formula::kBel) { - const Formula::split_level k = beta->as_bel().k(); - const Formula::split_level l = beta->as_bel().l(); + const belief_level k = beta->as_bel().k(); + const belief_level l = beta->as_bel().l(); const Formula& ante = beta->as_bel().antecedent(); internal::Maybe not_ante_or_conse = beta->as_bel().not_antecedent_or_consequent().AsUnivClause(); if (not_ante_or_conse) { @@ -94,10 +96,9 @@ class KnowledgeBase { bool Entails(const Formula& sigma, bool distribute = true) { assert(sigma.subjective()); - assert(sigma.free_vars().empty()); - if (spheres_changed_) { + assert(sigma.free_vars().all_empty()); + if (n_processed_beliefs_ < beliefs_.size() || n_processed_knowledge_ < knowledge_.size()) { BuildSpheres(); - spheres_changed_ = false; } Formula::Ref phi = ReduceModalities(*sigma.NF(sf_, tf_, distribute), false); assert(phi->objective()); @@ -105,68 +106,82 @@ class KnowledgeBase { } sphere_index n_spheres() const { return spheres_.size(); } - Solver* sphere(sphere_index p) { return &spheres_[p]; } + Solver& sphere(sphere_index p) { return spheres_[p]; } const Solver& sphere(sphere_index p) const { return spheres_[p]; } const std::vector& spheres() const { return spheres_; } private: struct Conditional { - Formula::split_level k; - Formula::split_level l; + belief_level k; + belief_level l; Formula::Ref ante; Clause not_ante_or_conse; bool assume_consistent; }; - typedef Grounder::TermSet TermSet; - typedef Grounder::SortedTermSet SortedTermSet; + typedef Formula::TermSet TermSet; + typedef Formula::SortedTermSet SortedTermSet; - void Add(Formula::split_level k, Formula::split_level l, - const Formula& antecedent, const Clause& not_antecedent_or_consequent, bool assume_consistent) { + void Add(belief_level k, + belief_level l, + const Formula& antecedent, + const Clause& not_antecedent_or_consequent, + bool assume_consistent) { beliefs_.push_back(Conditional{k, l, antecedent.Clone(), not_antecedent_or_consequent, assume_consistent}); - spheres_changed_ = true; antecedent.Traverse([this](Term t) { if (t.name()) names_.insert(t); return true; }); not_antecedent_or_consequent.Traverse([this](Term t) { if (t.name()) names_.insert(t); return true; }); } void BuildSpheres() { - spheres_.clear(); - std::vector done(beliefs_.size(), false); - bool is_plausibility_consistent = true; - size_t n_done = 0; - size_t last_n_done; - do { - last_n_done = n_done; - Solver sphere(sf_, tf_); - for (const Clause& c : knowledge_) { - sphere.AddClause(c); - } - for (size_t i = 0; i < beliefs_.size(); ++i) { - const Conditional& c = beliefs_[i]; - if (!done[i]) { - sphere.AddClause(c.not_ante_or_conse); + if (beliefs_.empty()) { + assert(spheres_.size() == 1); + assert(n_processed_beliefs_ == 0); + for (Solver& sphere : spheres_) { + for (const Clause& c : knowledge_) { + sphere.AddClause(c); } } - bool next_is_plausibility_consistent = true; - for (size_t i = 0; i < beliefs_.size(); ++i) { - const Conditional& c = beliefs_[i]; - if (!done[i]) { - const bool possibly_consistent = !sphere.Entails(c.k, *Formula::Factory::Not(c.ante->Clone()), - c.assume_consistent); - if (possibly_consistent) { - done[i] = true; - ++n_done; - const bool necessarilyConsistent = sphere.Consistent(c.l, *c.ante, c.assume_consistent); - if (!necessarilyConsistent) { - next_is_plausibility_consistent = false; + } else { + spheres_.clear(); + std::vector done(beliefs_.size(), false); + bool is_plausibility_consistent = true; + size_t n_done = 0; + size_t last_n_done; + do { + last_n_done = n_done; + Solver sphere(sf_, tf_); + for (const Clause& c : knowledge_) { + sphere.AddClause(c); + } + for (size_t i = 0; i < beliefs_.size(); ++i) { + const Conditional& c = beliefs_[i]; + if (!done[i]) { + sphere.AddClause(c.not_ante_or_conse); + } + } + bool next_is_plausibility_consistent = true; + for (size_t i = 0; i < beliefs_.size(); ++i) { + const Conditional& c = beliefs_[i]; + if (!done[i]) { + const bool possibly_consistent = !sphere.Entails(c.k, *Formula::Factory::Not(c.ante->Clone()), + c.assume_consistent); + if (possibly_consistent) { + done[i] = true; + ++n_done; + const bool necessarily_consistent = sphere.Consistent(c.l, *c.ante, c.assume_consistent); + if (!necessarily_consistent) { + next_is_plausibility_consistent = false; + } } } } - } - if (is_plausibility_consistent || n_done == last_n_done) { - spheres_.push_back(std::move(sphere)); - } - is_plausibility_consistent = next_is_plausibility_consistent; - } while (n_done > last_n_done); + if (is_plausibility_consistent || n_done == last_n_done) { + spheres_.push_back(std::move(sphere)); + } + is_plausibility_consistent = next_is_plausibility_consistent; + } while (n_done > last_n_done); + } + n_processed_beliefs_ = beliefs_.size(); + n_processed_knowledge_ = knowledge_.size(); } Formula::Ref ReduceModalities(const Formula& alpha, bool assume_consistent) { @@ -203,8 +218,8 @@ class KnowledgeBase { const Formula::Ref ante = ReduceModalities(alpha.as_bel().antecedent(), assume_consistent); const Formula::Ref not_ante_or_conse = ReduceModalities(alpha.as_bel().not_antecedent_or_consequent(), assume_consistent); - const Formula::split_level k = alpha.as_bel().k(); - const Formula::split_level l = alpha.as_bel().l(); + const belief_level k = alpha.as_bel().k(); + const belief_level l = alpha.as_bel().l(); std::vector consistent; std::vector entails; for (sphere_index p = 0; p < n_spheres(); ++p) { @@ -240,7 +255,7 @@ class KnowledgeBase { throw; } - Formula::Ref ResEntails(sphere_index p, Formula::split_level k, const Formula& phi, bool assume_consistent) { + Formula::Ref ResEntails(sphere_index p, belief_level k, const Formula& phi, bool assume_consistent) { // If phi is just a literal (t = n) or (t = x) for primitive t, we can use Solver::Determines to speed things up. if (phi.type() == Formula::kAtomic) { const Clause& c = phi.as_atomic().arg(); @@ -270,7 +285,7 @@ class KnowledgeBase { return Res(p, phi.Clone(), if_no_free_vars); } - Formula::Ref ResConsistent(sphere_index p, Formula::split_level k, const Formula& phi, bool assume_consistent) { + Formula::Ref ResConsistent(sphere_index p, belief_level k, const Formula& phi, bool assume_consistent) { auto if_no_free_vars = [k, assume_consistent, this](Solver* sphere, const Formula& psi) { return sphere->Consistent(k, psi, assume_consistent); }; @@ -286,7 +301,7 @@ class KnowledgeBase { template Formula::Ref Res(sphere_index p, Formula::Ref phi, SortedTermSet* names, BinaryPredicate if_no_free_vars) { - if (phi->free_vars().empty()) { + if (phi->free_vars().all_empty()) { const bool r = if_no_free_vars(&spheres_[p], *phi); return bool_to_formula(r); } @@ -321,13 +336,13 @@ class KnowledgeBase { SortedTermSet* names, BinaryPredicate if_no_free_vars) { // (x != n1 && ... && x != nK -> RES(p, phi^x_n0)^n0_x) in clausal form - Term n0 = spheres_[p].grounder()->CreateName(x.sort()); + Term n0 = spheres_[p].grounder().temp_name_pool().Create(x.sort()); phi->SubstituteFree(Term::Substitution(x, n0), tf_); names->insert(n0); phi = Res(p, std::move(phi), names, if_no_free_vars); names->erase(n0); phi->SubstituteFree(Term::Substitution(n0, x), tf_); - spheres_[p].grounder()->ReturnName(n0); + spheres_[p].grounder().temp_name_pool().Return(n0); const TermSet& ns = (*names)[x.sort()]; const auto if_not = internal::transform_range(ns.begin(), ns.end(), [x](Term n) { return Literal::Eq(x, n); }); const Clause c(ns.size(), if_not.begin(), if_not.end()); @@ -346,7 +361,8 @@ class KnowledgeBase { SortedTermSet names_; std::vector spheres_; Solver objective_; - bool spheres_changed_ = false; + size_t n_processed_knowledge_ = 0; + size_t n_processed_beliefs_ = 0; }; } // namespace limbo diff --git a/src/limbo/literal.h b/src/limbo/literal.h index b9d1961..0406baa 100644 --- a/src/limbo/literal.h +++ b/src/limbo/literal.h @@ -127,8 +127,16 @@ class Literal { static internal::Maybe Isomorphic(Literal a, Literal b) { Term::Substitution sub; - bool ok = Term::Isomorphic(a.lhs(), b.lhs(), &sub) && - Term::Isomorphic(a.rhs(), b.rhs(), &sub); + bool ok = Term::Isomorphic(a.lhs(), b.lhs(), &sub); + if (ok) { + if (a.rhs() == b.rhs()) { + sub.Add(a.rhs(), b.rhs()); + ok = true; + } else { + const internal::Maybe ar = sub(a.rhs()); + ok = ar && ar == sub(b.rhs()); + } + } return ok ? internal::Just(sub) : internal::Nothing; } diff --git a/src/limbo/setup.h b/src/limbo/setup.h index cf610e3..e27212c 100644 --- a/src/limbo/setup.h +++ b/src/limbo/setup.h @@ -12,11 +12,11 @@ // and LocallyConsistent(). // // Additionally, ShallowCopy() can be used to add further clauses or unit -// clauses which are automatically removed once the lifecycle of Offspring +// clauses which are automatically removed once the lifecycle of ShallowCopy // ends. This allows for very cheap backtracking. Note that anything that is -// added to a WeakCopy also occurs in the original Setup. During the lifecycle -// of any WeakCopies, Minimize() must not be called, as it leads to undefined -// behaviour. +// added to a ShallowCopy also occurs in the original Setup. During the +// lifecycle of any ShallowCopies, Minimize() must not be called, as it leads +// to undefined behaviour. // // Subsumes() checks whether the clause is subsumed by any clause in the setup // after doing unit propagation; it is hence a sound but incomplete test for @@ -81,45 +81,105 @@ class Setup { enum Result { kOk, kSubsumed, kInconsistent }; + template + struct ClauseRange { + typedef internal::int_iterator iterator; + + explicit ClauseRange(size_t last, UnaryFunction func = UnaryFunction()) : last(last), func(func) {} + iterator begin() const { return iterator(0, func); } + iterator end() const { return iterator(last, func); } + + private: + size_t last; + UnaryFunction func; + }; + class ShallowCopy { public: + struct GlobalIndex { + GlobalIndex(const Setup* s, bool empty_clause, size_t n_units, size_t n_clauses) + : s(s), empty_clause(empty_clause), n_units(n_units), n_clauses(n_clauses) {} + + size_t operator()(size_t i) const { + if (i >= s->empty_clause_ - empty_clause + s->units_.size() - n_units) { + return empty_clause + n_units + n_clauses + i; + } + if (i >= s->empty_clause_ - empty_clause) { + return empty_clause + n_units + i; + } + return i; + } + + private: + const Setup* s = nullptr; + bool empty_clause; + size_t n_units; + size_t n_clauses; + }; + + ShallowCopy() = default; ShallowCopy(const ShallowCopy&) = delete; ShallowCopy& operator=(const ShallowCopy&) = delete; - ShallowCopy(ShallowCopy&&) = default; - ShallowCopy& operator=(ShallowCopy&&) = default; + ShallowCopy(ShallowCopy&& c) : setup_(c.setup_), data_(c.data_) { c.setup_ = nullptr; } + ShallowCopy& operator=(ShallowCopy&& c) { + setup_ = c.setup_; + data_ = c.data_; + c.setup_ = nullptr; + return *this; + } ~ShallowCopy() { Die(); } - operator const Setup&() const { return *setup_; } - const Setup* operator->() const { return setup_; } - const Setup& operator*() const { return *setup_; } - - Result AddUnit(Literal a) { return setup_->AddUnit(a); } - void Die() { if (setup_) { - assert(setup_->saved_-- > 0); - setup_->empty_clause_ = empty_clause_; - setup_->units_.Resize(n_units_); - setup_->clauses_.Resize(n_clauses_); + assert(data_.empty_clause + data_.n_clauses + data_.n_units == 0 || setup_->saved_-- > 0); + setup_->empty_clause_ = data_.empty_clause; + setup_->units_.Resize(data_.n_units); + setup_->clauses_.Resize(data_.n_clauses); setup_ = nullptr; } } + Setup& setup() { return *setup_; } + const Setup& setup() const { return *setup_; } + + Result AddClause(Clause c) { return setup_->AddClause(c); } + Result AddUnit(Literal a) { return setup_->AddUnit(a); } + + void Minimize() { + assert(data_.saved == setup_->saved_); + setup_->Minimize(data_.n_clauses, data_.n_units); + assert(data_.n_clauses <= setup_->clauses_.size()); + assert(data_.n_units <= setup_->units_.size()); + } + + ClauseRange new_clauses() const { + const size_t last = setup_->empty_clause_ - data_.empty_clause + + setup_->units_.size() - data_.n_units + + setup_->clauses_.size() - data_.n_clauses; + return ClauseRange(last, GlobalIndex(setup_, data_.empty_clause, data_.n_units, data_.n_clauses)); + } + private: friend Setup; - explicit ShallowCopy(Setup* s) : - setup_(s), - empty_clause_(s->empty_clause_), - n_clauses_(s->clauses_.size()), - n_units_(s->units_.size()) { - assert(++setup_->saved_ > 0); + struct Data { + bool empty_clause = false; + size_t n_clauses = 0; + size_t n_units = 0; +#ifndef NDEBUG + size_t saved = 0; +#endif + }; + + explicit ShallowCopy(Setup* s) : setup_(s), data_({s->empty_clause_, s->clauses_.size(), s->units_.size()}) { + assert(data_.empty_clause + data_.n_clauses + data_.n_units == 0 || ++setup_->saved_ > 0); +#ifndef NDEBUG + data_.saved = s->saved_; +#endif } - Setup* setup_; - bool empty_clause_; - size_t n_clauses_; - size_t n_units_; + Setup* setup_ = nullptr; + Data data_; }; Setup() = default; @@ -128,41 +188,15 @@ class Setup { Setup(Setup&&) = default; Setup& operator=(Setup&&) = default; - ShallowCopy shallow_copy() const { return ShallowCopy(const_cast(this)); } + ShallowCopy shallow_copy() { return ShallowCopy(this); } void Minimize() { - assert(saved_ == 0); - if (empty_clause_) { - clauses_.Resize(0); - units_.Resize(0); - return; - } - for (size_t i = 0; i < units_.size(); ++i) { - Literal a = units_[i]; - if (!a.pos()) { - units_.Erase(i); - Result r = units_.Add(a); - assert(r != kInconsistent), (void) r; - } - } - for (size_t i = clauses_.size(); i > 0; --i) { - Clause c; - std::swap(c, clauses_[i - 1]); - c.PropagateUnits(units_.set()); - assert(!c.empty()); - assert(c.size() >= 2 || - any_of(units_.vec().begin(), units_.vec().end(), [&c](Literal a) { return a.Subsumes(c.first()); })); - clauses_.Erase(i - 1); - if (c.size() >= 2 && !Subsumes(c)) { - clauses_.Add(c); - } - } + Minimize(0, 0); units_.SealOriginalUnits(); // units_.set() have been eliminated from all clauses, so not needed in AddUnit() } Result AddClause(Clause c) { assert(c.primitive()); - assert(saved_ == 0); assert(!c.valid()); units_.UnsealOriginalUnits(); // undo units_.SealOriginalUnits() called by Minimize() c.PropagateUnits(units_.set()); @@ -186,28 +220,26 @@ class Setup { return kInconsistent; } size_t n_propagated = units_.size(); - Result r = units_.Add(a); + const Result r = units_.Add(a); empty_clause_ = r == kInconsistent; - for (; n_propagated < units_.size() && r != kInconsistent; ++n_propagated) { + for (; n_propagated < units_.size() && !empty_clause_; ++n_propagated) { a = units_[n_propagated]; - for (size_t i = 0; i < clauses_.size() && r != kInconsistent; ++i) { + for (size_t i = 0; i < clauses_.size() && !empty_clause_; ++i) { if (Literal::Complementary(clauses_.watched(i).a, a) || Literal::Complementary(clauses_.watched(i).b, a)) { Clause c = clauses_[i]; c.PropagateUnits(units_.set()); if (c.size() == 0) { - r = kInconsistent; empty_clause_ = true; } else if (c.size() == 1) { - r = units_.Add(c.first()); - empty_clause_ = r == kInconsistent; + empty_clause_ = units_.Add(c.first()) == kInconsistent; } else { clauses_.Watch(i, c.first(), c.last()); } } } } - return r; + return empty_clause_ ? kInconsistent : r; } bool Subsumes(const Clause& c) const { @@ -268,22 +300,15 @@ class Setup { bool contains_empty_clause() const { return empty_clause_; } - const std::vector& units() const { return units_.vec(); } + const std::unordered_set& units() const { return units_.set(); } + const std::vector& non_units() const { return clauses_.vec(); } internal::Maybe Determines(Term lhs) const { assert(lhs.primitive()); return empty_clause_ ? internal::Just(Term()) : units_.Determines(lhs); } - struct ClauseRange { - explicit ClauseRange(const Setup& s) : last((s.empty_clause_ ? 1 : 0) + s.units_.size() + s.clauses_.size()) {} - internal::int_iterator begin() const { return internal::int_iterator(0); } - internal::int_iterator end() const { return internal::int_iterator(last); } - private: - size_t last; - }; - - ClauseRange clauses() const { return ClauseRange(*this); } + ClauseRange<> clauses() const { return ClauseRange<>(empty_clause_ + units_.size() + clauses_.size()); } Clause clause(size_t i) const { if (i == 0 && empty_clause_) { @@ -351,6 +376,8 @@ class Setup { watched_.resize(n); } + const std::vector& vec() const { return clauses_; } + private: std::vector clauses_; std::vector watched_; @@ -366,8 +393,8 @@ class Setup { } Result Add(Literal a) { - auto orig_end = vec_.begin() + n_orig_; - auto orig_begin = std::lower_bound(vec_.begin(), orig_end, Literal::Min(a.lhs())); + const auto orig_end = vec_.begin() + n_orig_; + const auto orig_begin = std::lower_bound(vec_.begin(), orig_end, Literal::Min(a.lhs())); for (auto it = orig_begin; it != orig_end && a.lhs() == it->lhs(); ++it) { if (Literal::Complementary(a, *it)) { return kInconsistent; @@ -377,7 +404,7 @@ class Setup { } } if (set_.bucket_count() > 0) { - auto bucket = set_.bucket(a); + const auto bucket = set_.bucket(a); for (auto it = set_.begin(bucket), end = set_.end(bucket); it != end; ++it) { if (Literal::Complementary(a, *it)) { return kInconsistent; @@ -425,8 +452,8 @@ class Setup { internal::Maybe Determines(Term t) const { assert(t.primitive()); - auto orig_end = vec_.begin() + n_orig_; - auto orig_begin = std::lower_bound(vec_.begin(), orig_end, Literal::Min(t)); + const auto orig_end = vec_.begin() + n_orig_; + const auto orig_begin = std::lower_bound(vec_.begin(), orig_end, Literal::Min(t)); for (auto it = orig_begin; it != orig_end && t == it->lhs(); ++it) { if (it->pos()) { return internal::Just(it->rhs()); @@ -469,9 +496,9 @@ class Setup { static bool ConsistentSet(const std::unordered_set& lits) { for (const Literal a : lits) { assert(lits.bucket_count() > 0); - size_t b = lits.bucket(a); - auto begin = lits.begin(b); - auto end = lits.end(b); + const size_t bucket = lits.bucket(a); + const auto begin = lits.begin(bucket); + const auto end = lits.end(bucket); for (auto it = begin; it != end; ++it) { const Literal b = *it; assert(Literal::Complementary(a, b) == Literal::Complementary(b, a)); @@ -483,6 +510,35 @@ class Setup { return true; } + void Minimize(size_t n_clauses, size_t n_units) { + assert(n_clauses + n_units > 0 || saved_ == 0); + if (empty_clause_) { + clauses_.Resize(n_clauses); + units_.Resize(n_units); + return; + } + for (size_t i = n_units; i < units_.size(); ++i) { + const Literal a = units_[i]; + if (!a.pos()) { + units_.Erase(i); + Result r = units_.Add(a); + assert(r != kInconsistent), (void) r; + } + } + for (size_t i = clauses_.size(); i > n_clauses; --i) { + Clause c; + std::swap(c, clauses_[i - 1]); + c.PropagateUnits(units_.set()); + assert(!c.empty()); + assert(c.size() >= 2 || + any_of(units_.vec().begin(), units_.vec().end(), [&c](Literal a) { return a.Subsumes(c.first()); })); + clauses_.Erase(i - 1); + if (c.size() >= 2 && !Subsumes(c)) { + clauses_.Add(c); + } + } + } + bool empty_clause_ = false; Units units_; Clauses clauses_; diff --git a/src/limbo/solver.h b/src/limbo/solver.h index 7e0dd6e..298c95e 100644 --- a/src/limbo/solver.h +++ b/src/limbo/solver.h @@ -64,8 +64,6 @@ namespace limbo { class Solver { public: - typedef Formula::split_level split_level; - static constexpr bool kConsistencyGuarantee = true; static constexpr bool kNoConsistencyGuarantee = false; @@ -75,42 +73,39 @@ class Solver { Solver(Solver&&) = default; Solver& operator=(Solver&&) = default; - void AddClause(const Clause& c) { grounder_.AddClause(c); } + Setup::Result AddClause(const Clause& c) { return grounder_.AddClause(c); } - const Setup& setup() const { return grounder_.Ground(); } + Grounder& grounder() { return grounder_; } + const Grounder& grounder() const { return grounder_; } - Grounder* grounder() { return &grounder_; } + const Setup& setup() const { return grounder_.setup(); } - bool Entails(int k, const Formula& phi, bool assume_consistent) { + bool Entails(Formula::belief_level k, const Formula& phi, bool assume_consistent = false) { assert(phi.objective()); - assert(phi.free_vars().empty()); - grounder_.PrepareForQuery(k, phi); - const Setup& s = grounder_.Ground(); - TermSet split_terms = - k == 0 ? TermSet() : - assume_consistent ? grounder_.RelevantSplitTerms(phi) : - grounder_.SplitTerms(); - const SortedTermSet& names = grounder_.Names(); - return s.Subsumes(Clause{}) || phi.trivially_valid() || - Split(s, split_terms, names, k, - [this, &names, &phi](const Setup& s) { return Reduce(s, names, phi); }, - [](bool r1, bool r2) { return r1 && r2; }, - true, false); + assert(phi.free_vars().all_empty()); + Grounder::Undo undo1; + if (assume_consistent) { + grounder_.GuaranteeConsistency(phi, &undo1); + } + Grounder::Undo undo2; + grounder_.PrepareForQuery(phi, &undo2); + const bool entailed = setup().Subsumes(Clause{}) || phi.trivially_valid() || + Split(k, [this, &phi]() { return Reduce(phi); }, [](bool r1, bool r2) { return r1 && r2; }, true, false); + return entailed; } - internal::Maybe Determines(int k, Term lhs, bool assume_consistent) { + internal::Maybe Determines(Formula::belief_level k, Term lhs, bool assume_consistent = false) { assert(lhs.primitive()); - grounder_.PrepareForQuery(k, lhs); - const Setup& s = grounder_.Ground(); - TermSet split_terms = - k == 0 ? TermSet() : - assume_consistent ? grounder_.RelevantSplitTerms(lhs) : - grounder_.SplitTerms(); - const SortedTermSet& names = grounder_.Names(); + Grounder::Undo undo1; + if (assume_consistent) { + grounder_.GuaranteeConsistency(lhs, &undo1); + } + Grounder::Undo undo2; + grounder_.PrepareForQuery(lhs, &undo2); internal::Maybe inconsistent_result = internal::Just(Term()); internal::Maybe unsuccessful_result = internal::Nothing; - return Split(s, split_terms, names, k, - [this, &names, lhs](const Setup& s) { return s.Determines(lhs); }, + internal::Maybe t = Split(k, + [this, lhs]() { return setup().Determines(lhs); }, [](internal::Maybe r1, internal::Maybe r2) { return r1 && r2 && r1.val == r2.val ? r1 : r1 && r2 && r1.val.null() ? r2 : @@ -118,29 +113,29 @@ class Solver { internal::Nothing; }, inconsistent_result, unsuccessful_result); + return t; } - bool EntailsComplete(int k, const Formula& phi, bool assume_consistent) { + bool EntailsComplete(int k, const Formula& phi, bool assume_consistent = false) { assert(phi.objective()); - assert(phi.free_vars().empty()); + assert(phi.free_vars().all_empty()); Formula::Ref psi = Formula::Factory::Not(phi.Clone()); return !Consistent(k, *psi, assume_consistent); } - bool Consistent(int k, const Formula& phi, bool assume_consistent) { + int cons=0; + bool Consistent(int k, const Formula& phi, bool assume_consistent = false) { assert(phi.objective()); - assert(phi.free_vars().empty()); - grounder_.PrepareForQuery(k, phi); - const Setup& s = grounder_.Ground(); - LiteralAssignmentSet assign_lits = - k == 0 ? LiteralAssignmentSet() : - assume_consistent ? grounder_.RelevantLiteralAssignments(phi) : - grounder_.LiteralAssignments(); - TermSet relevant_terms = - assume_consistent ? grounder_.RelevantSplitTerms(phi) : - TermSet(); - const SortedTermSet& names = grounder_.Names(); - return !phi.trivially_invalid() && Assign(s, assign_lits, names, k, phi, assume_consistent, relevant_terms); + assert(phi.free_vars().all_empty()); + Grounder::Undo undo1; + if (assume_consistent) { + grounder_.GuaranteeConsistency(phi, &undo1); + } + Grounder::Undo undo2; + grounder_.PrepareForQuery(phi, &undo2); + bool b = false; + const bool consistent = !phi.trivially_invalid() && (b = Fix(k, [this, &phi]() { return Reduce(phi); })); + return consistent; } private: @@ -148,56 +143,53 @@ class Solver { FRIEND_TEST(SolverTest, Constants); #endif - typedef Grounder::TermSet TermSet; - typedef Grounder::LiteralSet LiteralSet; - typedef Grounder::LiteralAssignmentSet LiteralAssignmentSet; - typedef Grounder::SortedTermSet SortedTermSet; + typedef internal::size_t size_t; + typedef Formula::SortedTermSet SortedTermSet; - bool Reduce(const Setup& s, const SortedTermSet& names, const Formula& phi) { + bool Reduce(const Formula& phi) { assert(phi.objective()); switch (phi.type()) { case Formula::kAtomic: { const Clause c = phi.as_atomic().arg(); assert(c.ground()); assert(c.valid() || c.primitive()); - return c.valid() || s.Subsumes(c); + return c.valid() || setup().Subsumes(c); } case Formula::kNot: { switch (phi.as_not().arg().type()) { case Formula::kAtomic: { const Clause c = phi.as_not().arg().as_atomic().arg(); - return std::all_of(c.begin(), c.end(), [this, &s, &names](Literal a) { + return std::all_of(c.begin(), c.end(), [this](Literal a) { Formula::Ref psi = Formula::Factory::Atomic(Clause{a.flip()}); - return Reduce(s, names, *psi); + return Reduce(*psi); }); } case Formula::kNot: { - return Reduce(s, names, phi.as_not().arg().as_not().arg()); + return Reduce(phi.as_not().arg().as_not().arg()); } case Formula::kOr: { Formula::Ref left = Formula::Factory::Not(phi.as_not().arg().as_or().lhs().Clone()); Formula::Ref right = Formula::Factory::Not(phi.as_not().arg().as_or().rhs().Clone()); - return Reduce(s, names, *left) && - Reduce(s, names, *right); + return Reduce(*left) && Reduce(*right); } case Formula::kExists: { const Term x = phi.as_not().arg().as_exists().x(); const Formula& psi = phi.as_not().arg().as_exists().arg(); - const TermSet& xs = psi.free_vars(); + const SortedTermSet& xs = psi.free_vars(); // XXX TODO Check that this works even if we disable the first if-branch, once the name computation is fixed. // In test-functions.limbo, the line // Refute: Fa x Know<1> f(x) == x // yields an error because the set of names is empty. This error should be fixed by correct name computation. - if (xs.find(x) == xs.end()) { + if (xs.all_empty()) { Formula::Ref xi = Formula::Factory::Not(psi.Clone()); - return Reduce(s, names, *xi); + return Reduce(*xi); } else { - const TermSet& ns = names[x.sort()]; - assert(!ns.empty()); - return std::all_of(ns.begin(), ns.end(), [this, &s, &names, &psi, x](const Term n) { + const Grounder::Names ns = grounder_.names(x.sort()); + assert(ns.begin() != ns.end()); + return std::all_of(ns.begin(), ns.end(), [this, &psi, x](const Term n) { Formula::Ref xi = Formula::Factory::Not(psi.Clone()); xi->SubstituteFree(Term::Substitution(x, n), tf_); - return Reduce(s, names, *xi); + return Reduce(*xi); }); } } @@ -212,22 +204,21 @@ class Solver { case Formula::kOr: { const Formula& left = phi.as_or().lhs(); const Formula& right = phi.as_or().rhs(); - return Reduce(s, names, left) || - Reduce(s, names, right); + return Reduce(left) || Reduce(right); } case Formula::kExists: { const Term x = phi.as_exists().x(); const Formula& psi = phi.as_exists().arg(); - const TermSet& xs = psi.free_vars(); - if (xs.find(x) == xs.end()) { - return Reduce(s, names, psi); + const SortedTermSet& xs = psi.free_vars(); + if (xs.all_empty()) { + return Reduce(psi); } else { - const TermSet& ns = names[x.sort()]; - assert(!ns.empty()); - return std::any_of(ns.begin(), ns.end(), [this, &s, &names, &psi, x](const Term n) { + const Grounder::Names ns = grounder_.names(x.sort()); + assert(ns.begin() != ns.end()); + return std::any_of(ns.begin(), ns.end(), [this, &psi, x](const Term n) { Formula::Ref xi = psi.Clone(); xi->SubstituteFree(Term::Substitution(x, n), tf_); - return Reduce(s, names, *xi); + return Reduce(*xi); }); } } @@ -242,29 +233,7 @@ class Solver { } template - T Split(const Setup& s, - const TermSet& split_terms, - const SortedTermSet& names, - int k, - GoalPredicate goal, - MergeResultPredicate merge, - T inconsistent_result, - T unsuccessful_result) { - return Split(s, split_terms.begin(), split_terms.end(), split_terms.size(), names, k, - goal, merge, inconsistent_result, unsuccessful_result); - } - - template - T Split(const Setup& s, - const TermSet::const_iterator split_terms_begin, - const TermSet::const_iterator split_terms_end, - const internal::size_t n_split_terms, - const SortedTermSet& names, - int k, - GoalPredicate goal, - MergeResultPredicate merge, - T inconsistent_result, - T unsuccessful_result) { + T Split(int k, GoalPredicate goal, MergeResultPredicate merge, T inconsistent_result, T unsuccessful_result) { // XXX TODO The statement "the split order [does not matter] for Entails()" // is wrong: // @@ -296,103 +265,83 @@ class Solver { // // (*) This holds under the assumption that the KB is consistent. // If the KB is not consistent, could split terms 'block' each other? - assert(std::distance(split_terms_begin, split_terms_end) == n_split_terms); - if (s.contains_empty_clause()) { + if (setup().contains_empty_clause()) { return unsuccessful_result; - } else if (k > 0 && n_split_terms > 0) { - assert(split_terms_begin != split_terms_end); - internal::size_t n_split_terms_left = n_split_terms; - bool recursed = false; - for (auto it = split_terms_begin; it != split_terms_end; ) { - if (n_split_terms >= k && n_split_terms_left < k-1) { - break; - } - const Term t = *it++; - --n_split_terms_left; - if (s.Determines(t)) { - continue; - } - auto merged_result = unsuccessful_result; - const TermSet& ns = names[t.sort()]; - assert(!ns.empty()); - for (const Term n : ns) { - Setup::ShallowCopy split_setup = s.shallow_copy(); - const Setup::Result add_result = split_setup.AddUnit(Literal::Eq(t, n)); - if (add_result == Setup::kInconsistent) { - merged_result = !merged_result ? inconsistent_result : merge(merged_result, inconsistent_result); - if (!merged_result) { - goto next_split; - } - recursed = true; - continue; + } + if (k == 0) { + return goal(); + } + bool recursed = false; + for (const Term t : grounder_.lhs_terms()) { + if (setup().Determines(t)) { + continue; + } + auto merged_result = unsuccessful_result; + for (const Term n : grounder_.rhs_names(t)) { + Grounder::Undo undo; + const Setup::Result add_result = grounder_.AddClause(Clause{Literal::Eq(t, n)}, &undo); + if (add_result == Setup::kInconsistent) { + merged_result = !merged_result ? inconsistent_result : merge(merged_result, inconsistent_result); + if (!merged_result) { + goto next_term; } - auto split_result = Split(*split_setup, - split_terms_begin, - split_terms_end, - n_split_terms, - names, - k - 1, - goal, - merge, - inconsistent_result, - unsuccessful_result); + recursed = true; + goto next_name; + } + { + const T split_result = Split(k-1, goal, merge, inconsistent_result, unsuccessful_result); if (!split_result) { - goto next_split; + goto next_term; } merged_result = !merged_result ? split_result : merge(merged_result, split_result); - if (!merged_result) { - goto next_split; - } - recursed = true; } - return merged_result; -next_split: - {} + if (!merged_result) { + goto next_term; + } + recursed = true; +next_name: + {}; } - return recursed ? unsuccessful_result : goal(s); - } else { - return goal(s); + return merged_result; +next_term: + {} } + return recursed ? unsuccessful_result : goal(); } - bool Assign(const Setup& s, - const LiteralAssignmentSet& assign_lits, - const SortedTermSet& names, - int k, - const Formula& phi, - bool assume_consistent, - const TermSet& relevant_terms) { - assert(phi.objective()); - if ((!assume_consistent && s.Subsumes(Clause{})) || phi.trivially_invalid()) { + template + bool Fix(int k, GoalPredicate goal) { + if (setup().Subsumes(Clause{})) { return false; - } else if (k > 0 && !assign_lits.empty()) { - if (assign_lits.empty()) { - assert(phi.trivially_valid() || phi.trivially_invalid()); - return phi.trivially_valid(); - } - assert(!assign_lits.empty()); - return std::any_of(assign_lits.begin(), assign_lits.end(), [&](const LiteralSet& lits) { - assert(!lits.empty()); - Setup::ShallowCopy split_setup = s.shallow_copy(); - for (Literal a : lits) { - if (!s.Subsumes(Clause{a.flip()})) { - split_setup.AddUnit(a); + } + if (k > 0) { + std::unordered_set as; + for (const Term t : grounder_.lhs_terms()) { + for (const Term n : grounder_.rhs_names(t)) { + { + const Literal a = Literal::Eq(t, n); + Grounder::Undo undo; + const Setup::Result add_result = grounder_.AddClause(Clause{a}, &undo, true); + const bool succ = add_result != Setup::kSubsumed && Fix(k-1, goal); + if (succ) { + return true; + } + } + { + const Literal a = grounder_.Variablify(Literal::Eq(t, n)); + if (!as.insert(a).second) { + Grounder::Undo undo; + const Setup::Result add_result = grounder_.AddClause(Clause{a}, &undo, true); + const bool succ = add_result != Setup::kSubsumed && Fix(k-1, goal); + if (succ) { + return true; + } + } } } - return Assign(*split_setup, assign_lits, names, k-1, phi, assume_consistent, relevant_terms); - }); - } else { - if (!assume_consistent && !s.Consistent()) { - return false; - // TODO XXX There's something wrong with how we use - // Setup::LocallyConsistent() here. The argument should rather be the - // grounded terms from the query. And Setup::LocallyConsistent() should - // close the set only under unsubsumed clauses. - } else if (assume_consistent && !s.LocallyConsistent(relevant_terms)) { - return false; } - return Reduce(s, names, phi); } + return setup().Consistent() && goal(); } Term::Factory* tf_; diff --git a/src/limbo/term.h b/src/limbo/term.h index a307cec..9990797 100644 --- a/src/limbo/term.h +++ b/src/limbo/term.h @@ -133,6 +133,7 @@ class Symbol { class Term { public: + typedef internal::size_t size_t; class Factory; struct Substitution; typedef std::vector Vector; // using Vector within Term will be legal in C++17, but seems to be illegal before @@ -140,10 +141,9 @@ class Term { static constexpr UnificationConfiguration kUnifyLeft = (1 << 0); static constexpr UnificationConfiguration kUnifyRight = (1 << 1); - static constexpr UnificationConfiguration kUnifyVars = (1 << 2); static constexpr UnificationConfiguration kOccursCheck = (1 << 4); static constexpr UnificationConfiguration kUnifyTwoWay = kUnifyLeft | kUnifyRight; - static constexpr UnificationConfiguration kDefaultConfig = kUnifyTwoWay | kUnifyVars; + static constexpr UnificationConfiguration kDefaultConfig = kUnifyTwoWay; Term() = default; @@ -278,7 +278,7 @@ class Term::Factory : private Singleton { } private: - struct DataPtrHash { internal::hash32_t operator()(const Term::Data* d) const { return d->hash(); } }; + struct DataPtrHash { internal::hash32_t operator()(const Term::Data* d) const { return d->hash(); } }; struct DataPtrEquals { bool operator()(const Term::Data* a, const Term::Data* b) const { return *a == *b; } }; Factory() = default; @@ -385,7 +385,6 @@ internal::Maybe Term::Unify(Term l, Term r) { } bool Term::Isomorphic(Term l, Term r, Substitution* sub) { - internal::Maybe u; if (l.function() && r.function() && l.symbol() == r.symbol()) { for (Symbol::Arity i = 0; i < l.arity(); ++i) { if (!Isomorphic(l.arg(i), r.arg(i), sub)) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 30ffc15..8c154c9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,7 +2,7 @@ add_subdirectory (googletest) enable_testing () include_directories (${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}) -foreach (test hash iter hashset intmap linked term bloom literal clause setup formula syntax grounder solver kb) +foreach (test hash iter hashset intmap term bloom literal clause setup formula syntax grounder solver kb) add_executable (${test} ${test}.cc) target_link_libraries (${test} LINK_PUBLIC limbo gtest gtest_main) add_test (NAME ${test} COMMAND ${test}) diff --git a/tests/grounder.cc b/tests/grounder.cc index dbba832..63951c2 100644 --- a/tests/grounder.cc +++ b/tests/grounder.cc @@ -9,6 +9,8 @@ #include #include +using limbo::format::operator<<; + namespace limbo { using namespace limbo::format; @@ -32,6 +34,102 @@ size_t length(T r) { return n; } +typedef std::unordered_set ClauseSet; +typedef std::unordered_set TermSet; +typedef std::unordered_set LiteralSet; + +ClauseSet S(const Setup& s) { + ClauseSet set; + for (auto i : s.clauses()) { + set.insert(s.clause(i)); + } + return set; +} +TermSet S(const Grounder::Names& ns) { return TermSet(ns.begin(), ns.end()); } +TermSet S(const Grounder::LhsTerms& ts) { return TermSet(ts.begin(), ts.end()); } +TermSet S(const Grounder::RhsNames& ns) { return TermSet(ns.begin(), ns.end()); } +//LiteralSet S(const Grounder::LhsRhsLiterals& as) { return LiteralSet(as.begin(), as.end()); } + +std::pair operator+(const TermSet& ts, size_t n) { return std::make_pair(ts, n); } + +bool operator==(const TermSet& ts, const std::pair& p) { + for (Term t : p.first) { + if (ts.find(t) == ts.end()) { + return false; + } + } + return ts.size() == p.first.size() + p.second; +} + +TEST(GrounderTest, Ground_SplitTerms_Names) { + Symbol::Factory& sf = *Symbol::Factory::Instance(); + Term::Factory& tf = *Term::Factory::Instance(); + const Symbol::Sort sa = sf.CreateSort(); RegisterSort(sa, ""); + const Symbol::Sort sb = sf.CreateSort(); RegisterSort(sb, ""); + const Term m1 = tf.CreateTerm(sf.CreateName(sa)); RegisterSymbol(m1.symbol(), "m1"); + const Term m2 = tf.CreateTerm(sf.CreateName(sa)); RegisterSymbol(m2.symbol(), "m2"); + const Term n1 = tf.CreateTerm(sf.CreateName(sb)); RegisterSymbol(n1.symbol(), "n1"); + const Term n2 = tf.CreateTerm(sf.CreateName(sb)); RegisterSymbol(n2.symbol(), "n2"); + const Term x1 = tf.CreateTerm(sf.CreateVariable(sa)); RegisterSymbol(x1.symbol(), "x1"); + const Term x2 = tf.CreateTerm(sf.CreateVariable(sa)); RegisterSymbol(x2.symbol(), "x2"); + const Term y1 = tf.CreateTerm(sf.CreateVariable(sb)); RegisterSymbol(y1.symbol(), "y1"); + const Symbol s_a = sf.CreateFunction(sa, 0); RegisterSymbol(s_a, "a"); + const Symbol s_b = sf.CreateFunction(sb, 0); RegisterSymbol(s_b, "b"); + const Symbol s_f = sf.CreateFunction(sa, 1); RegisterSymbol(s_f, "f"); + const Symbol s_g = sf.CreateFunction(sb, 1); RegisterSymbol(s_g, "g"); + const Term a = tf.CreateTerm(s_a, {}); + const Term b = tf.CreateTerm(s_b, {}); + const Term fm1 = tf.CreateTerm(s_f, {m1}); + const Term fm2 = tf.CreateTerm(s_f, {m2}); + const Term fn1 = tf.CreateTerm(s_f, {n1}); + const Term fn2 = tf.CreateTerm(s_f, {n2}); + const Term gm1 = tf.CreateTerm(s_f, {m1}); + const Term gm2 = tf.CreateTerm(s_f, {m2}); + const Term gn1 = tf.CreateTerm(s_f, {n1}); + const Term gn2 = tf.CreateTerm(s_f, {n2}); + { + Grounder g(&sf, &tf); + //EXPECT_EQ(S(g.setup()), ClauseSet({})); + g.AddClause(Clause{Literal::Eq(a, m1)}); + EXPECT_EQ(S(g.setup()), ClauseSet({Clause({Literal::Eq(a, m1)})})); + EXPECT_EQ(S(g.names(sa)), TermSet({m1})); + EXPECT_EQ(S(g.names(sb)), TermSet({})); + EXPECT_EQ(S(g.lhs_terms()), TermSet({a})); + EXPECT_EQ(S(g.rhs_names(a)), TermSet({m1}) + 1); + EXPECT_EQ(S(g.rhs_names(b)), TermSet({}) + 1); + EXPECT_EQ(S(g.rhs_names(fm1)), TermSet({}) + 1); + EXPECT_EQ(S(g.rhs_names(fm2)), TermSet({}) + 1); + EXPECT_EQ(S(g.rhs_names(fn1)), TermSet({}) + 1); + EXPECT_EQ(S(g.rhs_names(fn2)), TermSet({}) + 1); + //EXPECT_EQ(S(g.lhs_rhs_literals()), LiteralSet({Literal::Eq(a, m1)})); + g.AddClause(Clause{Literal::Eq(a, m1)}); + EXPECT_EQ(S(g.setup()), ClauseSet({Clause({Literal::Eq(a, m1)})})); + EXPECT_EQ(S(g.names(sa)), TermSet({m1})); + EXPECT_EQ(S(g.names(sb)), TermSet({})); + EXPECT_EQ(S(g.lhs_terms()), TermSet({a})); + EXPECT_EQ(S(g.rhs_names(a)), TermSet({m1}) + 1); + EXPECT_EQ(S(g.rhs_names(b)), TermSet({}) + 1); + EXPECT_EQ(S(g.rhs_names(fm1)), TermSet({}) + 1); + EXPECT_EQ(S(g.rhs_names(fm2)), TermSet({}) + 1); + EXPECT_EQ(S(g.rhs_names(fn1)), TermSet({}) + 1); + EXPECT_EQ(S(g.rhs_names(fn2)), TermSet({}) + 1); + //EXPECT_EQ(S(g.lhs_rhs_literals()), LiteralSet{Literal::Eq(a, m1)}); + g.AddClause(Clause{Literal::Eq(fm1, m1), Literal::Eq(fm1, m2), Literal::Eq(fn1, m2)}); + EXPECT_EQ(S(g.setup()), ClauseSet({Clause({Literal::Eq(a, m1)}), Clause({Literal::Eq(fm1, m1), Literal::Eq(fm1, m2), Literal::Eq(fn1, m2)})})); + EXPECT_EQ(S(g.names(sa)), TermSet({m1, m2})); + EXPECT_EQ(S(g.names(sb)), TermSet({n1})); + EXPECT_EQ(S(g.lhs_terms()), TermSet({a, fm1, fn1})); + EXPECT_EQ(S(g.rhs_names(a)), TermSet({m1}) + 1); + EXPECT_EQ(S(g.rhs_names(b)), TermSet({}) + 1); + EXPECT_EQ(S(g.rhs_names(fm1)), TermSet({m1, m2}) + 1); + EXPECT_EQ(S(g.rhs_names(fm2)), TermSet({}) + 1); + EXPECT_EQ(S(g.rhs_names(fn1)), TermSet({m2}) + 1); + EXPECT_EQ(S(g.rhs_names(fn2)), TermSet({}) + 1); + //EXPECT_EQ(S(g.lhs_rhs_literals()), LiteralSet({Literal::Eq(a, m1), Literal::Eq(fm1, m1), Literal::Eq(fm1, m2), Literal::Eq(fn1, m2)})); + } +} + +#if 0 TEST(GrounderTest, Ground_SplitTerms_Names) { Symbol::Factory& sf = *Symbol::Factory::Instance(); Term::Factory& tf = *Term::Factory::Instance(); @@ -63,7 +161,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { { Grounder g(&sf, &tf); g.AddClause(Clause({Literal::Eq(n1,n1)})); - const limbo::Setup& s = g.Ground(); + const limbo::Setup& s = g.setup(); // Grounding should be [n1=n1]. The clause is valid and hence skipped. EXPECT_EQ(unique_length(s), 0); EXPECT_TRUE(s.Consistent()); @@ -72,7 +170,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { { Grounder g(&sf, &tf); g.AddClause(Clause({Literal::Neq(n1,n1)})); - const limbo::Setup& s = g.Ground(); + const limbo::Setup& s = g.setup(); // Grounding should be [n1/=n1]. The clause is invalid and hence boiled // down to []. EXPECT_EQ(unique_length(s), 1); @@ -82,7 +180,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { { Grounder g(&sf, &tf); g.AddClause(Clause({Literal::Eq(x1, x1)})); - const limbo::Setup& s = g.Ground(); + const limbo::Setup& s = g.setup(); // Grounding should be [n1=n1]. The clause is valid and hence skipped. EXPECT_EQ(unique_length(s), 0); EXPECT_TRUE(s.Consistent()); @@ -91,7 +189,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { { Grounder g(&sf, &tf); g.AddClause(Clause({Literal::Neq(x1, x1)})); - const limbo::Setup& s = g.Ground(); + const limbo::Setup& s = g.setup(); // Grounding should be [n1/=n1]. The clause is invalid and hence boiled // down to []. EXPECT_EQ(unique_length(s), 1); @@ -101,7 +199,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { { Grounder g(&sf, &tf); g.AddClause(Clause({Literal::Eq(n1, x1)})); - const limbo::Setup& s = g.Ground(); + const limbo::Setup& s = g.setup(); // Grounding should be [n1=n1], [n3=n1]. The first clause is valid and // hence skipped. The second is invalid and hence boiled down to []. EXPECT_EQ(unique_length(s), 1); @@ -111,7 +209,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { { Grounder g(&sf, &tf); g.AddClause(Clause({Literal::Neq(n1, x1)})); - const limbo::Setup& s = g.Ground(); + const limbo::Setup& s = g.setup(); // Grounding should be [n1/=n1], [n3/=n1]. The second clause is valid and // hence skipped. The first is invalid and hence boiled down to []. EXPECT_EQ(unique_length(s), 1); @@ -121,7 +219,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { { Grounder g(&sf, &tf); g.AddClause(Clause({Literal::Eq(x1, x2)})); - const limbo::Setup& s = g.Ground(); + const limbo::Setup& s = g.setup(); // Grounding should be [n1=n1], [n3=2], [n1=n3], [n3=n1]. The former two // clauses are valid and hence skipped. The latter ones are invalid and // hence boiled down to []. @@ -132,7 +230,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { { Grounder g(&sf, &tf); g.AddClause(Clause({Literal::Neq(x1, x1)})); - const limbo::Setup& s = g.Ground(); + const limbo::Setup& s = g.setup(); // Grounding should be [n1/=n1]. The clause is invalid and hence boiled // down to []. EXPECT_EQ(unique_length(s), 1); @@ -143,7 +241,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { { Grounder g(&sf, &tf); g.AddClause(Clause({Literal::Eq(tf.CreateTerm(a, {}), x1)})); - const limbo::Setup& s = g.Ground(); + const limbo::Setup& s = g.setup(); // Grounding should be [a=n1], [a=n2], which yields []. //EXPECT_EQ(unique_length(s), 2); // the second clause is replaced with [] //const_cast(s).Minimize(); @@ -154,7 +252,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { { Grounder g(&sf, &tf); g.AddClause(Clause({Literal::Eq(tf.CreateTerm(a, {}), n1)})); - const limbo::Setup& s = g.Ground(); + const limbo::Setup& s = g.setup(); // Grounding should be [a=n1]. EXPECT_EQ(unique_length(s), 1); EXPECT_TRUE(s.Consistent()); @@ -163,7 +261,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { { Grounder g(&sf, &tf); g.AddClause(Clause({Literal::Eq(tf.CreateTerm(f, {n1}), x1)})); - const limbo::Setup& s = g.Ground(); + const limbo::Setup& s = g.setup(); // Grounding should be [f(n1)=n1)], [f(n1)=n3]. The clauses unify and // yield []. //EXPECT_EQ(unique_length(s), 2); @@ -175,7 +273,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { { Grounder g(&sf, &tf); g.AddClause(Clause({Literal::Neq(tf.CreateTerm(f, {n1}), x2)})); - const limbo::Setup& s = g.Ground(); + const limbo::Setup& s = g.setup(); // Grounding should be [f(n1)/=n1)], [f(n1)/=n3], [f(n1)/=n4]. //EXPECT_EQ(unique_length(s), 3); //const_cast(s).Minimize(); @@ -186,7 +284,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { { Grounder g(&sf, &tf); g.AddClause(Clause({Literal::Eq(tf.CreateTerm(h, {n1,x2}), x3)})); - const limbo::Setup& s = g.Ground(); + const limbo::Setup& s = g.setup(); // Grounding should be [h(n1,nX)=nY] for X=1,2,3 and Y=4,5. The clauses // unify and yield []. //EXPECT_EQ(unique_length(s), 3+1); // after [h(n1,nX)=n4] for all nX have been added, adding any [h(n1,nX)=n5] yields [] @@ -198,7 +296,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { { Grounder g(&sf, &tf); g.AddClause(Clause({Literal::Neq(tf.CreateTerm(h, {n1,x2}), x3)})); - const limbo::Setup& s = g.Ground(); + const limbo::Setup& s = g.setup(); // Grounding should be [h(n1,nX)=nY] for X=1,2,3 and Y=4,5. //EXPECT_EQ(unique_length(s), 3*2); //const_cast(s).Minimize(); @@ -213,7 +311,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { // g.PrepareForQuery(Formula::Factory::Exists(x2, *Formula::Factory::Atomic({Literal::Eq(x2, x2)}))->NF(&sf, &tf)); // g.PrepareForQuery(Formula::Factory::Exists(x3, *Formula::Factory::Atomic({Literal::Eq(x3, x3)}))->NF(&sf, &tf)); // g.PrepareForQuery(Formula::Factory::Exists(x4, *Formula::Factory::Atomic({Literal::Eq(x4, x4)}))->NF(&sf, &tf)); -// const limbo::Setup& s = g.Ground(); +// const limbo::Setup& s = g.setup(); // EXPECT_EQ(unique_length(s), 2); // } @@ -222,7 +320,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { auto phi = Formula::Factory::Exists(x3, Formula::Factory::Atomic({Literal::Eq(tf.CreateTerm(h, {n1,x3}), tf.CreateTerm(g, {tf.CreateTerm(a, {})}))}))->NF(&sf, &tf); // NF introduces two new variables of the same sort as x3, and one new of the same sort as n1. Grounder gg(&sf, &tf); - gg.PrepareForQuery(1, *phi); + gg.PrepareForQuery(*phi); Grounder::TermSet terms = gg.SplitTerms(); Grounder::SortedTermSet names = gg.Names(); //std::cout << phi << std::endl; @@ -265,7 +363,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { EXPECT_FALSE(g.names_changed_); EXPECT_EQ(g.unprocessed_clauses_.size(), 0); EXPECT_EQ(g.processed_clauses_.size(), 0); - const class Setup* s = &g.Ground(); + const class Setup* s = &g.setup(); EXPECT_EQ(unique_length(*s), 0); EXPECT_TRUE(bool(g.setup_)); } @@ -273,7 +371,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { EXPECT_FALSE(g.names_changed_); EXPECT_EQ(g.unprocessed_clauses_.size(), 0); EXPECT_EQ(g.processed_clauses_.size(), 0); - const class Setup* s = &g.Ground(); + const class Setup* s = &g.setup(); EXPECT_FALSE(g.names_changed_); EXPECT_EQ(g.unprocessed_clauses_.size(), 0); EXPECT_EQ(g.processed_clauses_.size(), 0); @@ -285,7 +383,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { EXPECT_TRUE(g.names_changed_); EXPECT_EQ(g.unprocessed_clauses_.size(), 1); EXPECT_EQ(g.processed_clauses_.size(), 0); - const class Setup* s = &g.Ground(); + const class Setup* s = &g.setup(); EXPECT_FALSE(g.names_changed_); EXPECT_EQ(g.unprocessed_clauses_.size(), 0); EXPECT_EQ(g.processed_clauses_.size(), 1); @@ -297,7 +395,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { EXPECT_TRUE(g.names_changed_); EXPECT_EQ(g.unprocessed_clauses_.size(), 0); EXPECT_EQ(g.processed_clauses_.size(), 1); - const class Setup* s = &g.Ground(); + const class Setup* s = &g.setup(); EXPECT_FALSE(g.names_changed_); EXPECT_EQ(g.unprocessed_clauses_.size(), 0); EXPECT_EQ(g.processed_clauses_.size(), 1); @@ -309,7 +407,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { EXPECT_TRUE(g.names_changed_); EXPECT_EQ(g.unprocessed_clauses_.size(), 1); EXPECT_EQ(g.processed_clauses_.size(), 1); - const class Setup* s = &g.Ground(); + const class Setup* s = &g.setup(); EXPECT_FALSE(g.names_changed_); EXPECT_EQ(g.unprocessed_clauses_.size(), 0); EXPECT_EQ(g.processed_clauses_.size(), 2); @@ -321,7 +419,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { EXPECT_FALSE(g.names_changed_); EXPECT_EQ(g.unprocessed_clauses_.size(), 0); EXPECT_EQ(g.processed_clauses_.size(), 2); - const class Setup* s = &g.Ground(); + const class Setup* s = &g.setup(); EXPECT_FALSE(g.names_changed_); EXPECT_EQ(g.unprocessed_clauses_.size(), 0); EXPECT_EQ(g.processed_clauses_.size(), 2); @@ -333,7 +431,7 @@ TEST(GrounderTest, Ground_SplitTerms_Names) { EXPECT_FALSE(g.names_changed_); EXPECT_EQ(g.unprocessed_clauses_.size(), 1); EXPECT_EQ(g.processed_clauses_.size(), 2); - const class Setup* s = &g.Ground(); + const class Setup* s = &g.setup(); EXPECT_FALSE(g.names_changed_); EXPECT_EQ(g.unprocessed_clauses_.size(), 0); EXPECT_EQ(g.processed_clauses_.size(), 3); @@ -532,6 +630,7 @@ TEST(GrounderTest, Ground_SplitNames_iterated) { EXPECT_NE(terms.size(), 0); } } +#endif } // namespace limbo diff --git a/tests/iter.cc b/tests/iter.cc index cfca5cb..65104ba 100644 --- a/tests/iter.cc +++ b/tests/iter.cc @@ -52,6 +52,18 @@ TEST(IterTest, int_iterator) { } } +TEST(IterTest, singleton_iterator) { + typedef singleton_iterator iterator; + { + iterator begin = iterator(5); + iterator end = iterator(); + EXPECT_NE(begin, end); + EXPECT_EQ(*begin, 5); + ++begin; + EXPECT_EQ(begin, end); + } +} + TEST(IterTest, flatten_iterator) { { typedef std::vector vec; @@ -304,6 +316,49 @@ TEST(IterTest, maping_iterator) { } } +TEST(IterTest, cross_iterator) { + typedef std::vector vec1; + typedef std::vector vec2; + typedef cross_iterator iterator; + { + vec1 xs{}; + vec2 ys{}; + iterator begin = iterator(xs.begin(), ys.begin(), ys.end()); + iterator end = iterator(xs.begin(), ys.begin(), ys.end()); + EXPECT_EQ(begin, end); + } + { + vec1 xs{1,2,3}; + vec2 ys{}; + iterator begin = iterator(xs.begin(), ys.begin(), ys.end()); + iterator end = iterator(xs.end(), ys.begin(), ys.end()); + EXPECT_EQ(begin, end); + } + { + vec1 xs{}; + vec2 ys{1.1,2.2,3.3}; + iterator begin = iterator(xs.begin(), ys.begin(), ys.end()); + iterator end = iterator(xs.end(), ys.begin(), ys.end()); + EXPECT_EQ(begin, end); + } + { + vec1 xs{1,2,3}; + vec2 ys{1.1,2.2,3.3}; + iterator begin = iterator(xs.begin(), ys.begin(), ys.end()); + iterator end = iterator(xs.end(), ys.begin(), ys.end()); + EXPECT_NE(begin, end); EXPECT_EQ(*begin, std::make_pair(1, 1.1)); ++begin; + EXPECT_NE(begin, end); EXPECT_EQ(*begin, std::make_pair(1, 2.2)); ++begin; + EXPECT_NE(begin, end); EXPECT_EQ(*begin, std::make_pair(1, 3.3)); ++begin; + EXPECT_NE(begin, end); EXPECT_EQ(*begin, std::make_pair(2, 1.1)); ++begin; + EXPECT_NE(begin, end); EXPECT_EQ(*begin, std::make_pair(2, 2.2)); ++begin; + EXPECT_NE(begin, end); EXPECT_EQ(*begin, std::make_pair(2, 3.3)); ++begin; + EXPECT_NE(begin, end); EXPECT_EQ(*begin, std::make_pair(3, 1.1)); ++begin; + EXPECT_NE(begin, end); EXPECT_EQ(*begin, std::make_pair(3, 2.2)); ++begin; + EXPECT_NE(begin, end); EXPECT_EQ(*begin, std::make_pair(3, 3.3)); ++begin; + EXPECT_EQ(begin ,end); + } +} + TEST(IterTest, join_ranges) { { typedef std::vector vec; diff --git a/tests/kb.cc b/tests/kb.cc index fe44cc3..e5feff2 100644 --- a/tests/kb.cc +++ b/tests/kb.cc @@ -31,8 +31,8 @@ TEST(KnowledgeBaseTest, ECAI2016Sound_Guarantee) { auto Veggie = ctx.CreateFunction(Bool, 0)(); REGISTER_SYMBOL(Veggie); auto roo = ctx.CreateName(Food); REGISTER_SYMBOL(roo); auto x = ctx.CreateVariable(Food); REGISTER_SYMBOL(x); - Formula::split_level k = 1; - Formula::split_level l = 1; + Formula::belief_level k = 1; + Formula::belief_level l = 1; EXPECT_TRUE(kb.Add(*Formula::Factory::Guarantee(Formula::Factory::Bel(k, l, *(Aussie == T), *(Italian != T))))); EXPECT_TRUE(kb.Add(*Formula::Factory::Guarantee(Formula::Factory::Bel(k, l, *(Italian == T), *(Aussie != T))))); EXPECT_TRUE(kb.Add(*Formula::Factory::Guarantee(Formula::Factory::Bel(k, l, *(Aussie == T), *(Eats(roo) == T))))); @@ -46,33 +46,33 @@ TEST(KnowledgeBaseTest, ECAI2016Sound_Guarantee) { EXPECT_TRUE(kb.Entails(*Formula::Factory::Guarantee(Formula::Factory::Bel(1, 1, *(Italian != T), *(Veggie != T))))); } -TEST(KnowledgeBaseTest, ECAI2016Sound_NoGuarantee) { - Context ctx; - KnowledgeBase kb(ctx.sf(), ctx.tf()); - auto Bool = ctx.CreateSort(); RegisterSort(Bool, ""); - auto Food = ctx.CreateSort(); RegisterSort(Food, ""); - auto T = ctx.CreateName(Bool); REGISTER_SYMBOL(T); - auto Aussie = ctx.CreateFunction(Bool, 0)(); REGISTER_SYMBOL(Aussie); - auto Italian = ctx.CreateFunction(Bool, 0)(); REGISTER_SYMBOL(Italian); - auto Eats = ctx.CreateFunction(Bool, 1); REGISTER_SYMBOL(Eats); - auto Meat = ctx.CreateFunction(Bool, 1); REGISTER_SYMBOL(Meat); - auto Veggie = ctx.CreateFunction(Bool, 0)(); REGISTER_SYMBOL(Veggie); - auto roo = ctx.CreateName(Food); REGISTER_SYMBOL(roo); - auto x = ctx.CreateVariable(Food); REGISTER_SYMBOL(x); - Formula::split_level k = 1; - Formula::split_level l = 1; - EXPECT_TRUE(kb.Add(*Formula::Factory::Bel(k, l, *(Aussie == T), *(Italian != T)))); - EXPECT_TRUE(kb.Add(*Formula::Factory::Bel(k, l, *(Italian == T), *(Aussie != T)))); - EXPECT_TRUE(kb.Add(*Formula::Factory::Bel(k, l, *(Aussie == T), *(Eats(roo) == T)))); - EXPECT_TRUE(kb.Add(*Formula::Factory::Bel(k, l, *(T == T), *(Italian == T || Veggie == T)))); - EXPECT_TRUE(kb.Add(*Formula::Factory::Bel(k, l, *(Italian != T), *(Aussie == T)))); - EXPECT_TRUE(kb.Add(*Formula::Factory::Bel(k, l, *(Meat(roo) != T), *(T != T)))); - EXPECT_TRUE(kb.Add(*Formula::Factory::Bel(k, l, *(~Fa(x, (Veggie == T && Meat(x) == T) >> (Eats(x) != T))), *(T != T)))); - EXPECT_FALSE(kb.Entails(*Formula::Factory::Bel(0, 0, *(Italian != T), *(Veggie != T)))); - EXPECT_FALSE(kb.Entails(*Formula::Factory::Bel(0, 1, *(Italian != T), *(Veggie != T)))); - EXPECT_FALSE(kb.Entails(*Formula::Factory::Bel(1, 0, *(Italian != T), *(Veggie != T)))); - EXPECT_TRUE(kb.Entails(*Formula::Factory::Bel(1, 1, *(Italian != T), *(Veggie != T)))); -} +//TEST(KnowledgeBaseTest, ECAI2016Sound_NoGuarantee) { +// Context ctx; +// KnowledgeBase kb(ctx.sf(), ctx.tf()); +// auto Bool = ctx.CreateSort(); RegisterSort(Bool, ""); +// auto Food = ctx.CreateSort(); RegisterSort(Food, ""); +// auto T = ctx.CreateName(Bool); REGISTER_SYMBOL(T); +// auto Aussie = ctx.CreateFunction(Bool, 0)(); REGISTER_SYMBOL(Aussie); +// auto Italian = ctx.CreateFunction(Bool, 0)(); REGISTER_SYMBOL(Italian); +// auto Eats = ctx.CreateFunction(Bool, 1); REGISTER_SYMBOL(Eats); +// auto Meat = ctx.CreateFunction(Bool, 1); REGISTER_SYMBOL(Meat); +// auto Veggie = ctx.CreateFunction(Bool, 0)(); REGISTER_SYMBOL(Veggie); +// auto roo = ctx.CreateName(Food); REGISTER_SYMBOL(roo); +// auto x = ctx.CreateVariable(Food); REGISTER_SYMBOL(x); +// Formula::belief_level k = 1; +// Formula::belief_level l = 1; +// EXPECT_TRUE(kb.Add(*Formula::Factory::Bel(k, l, *(Aussie == T), *(Italian != T)))); +// EXPECT_TRUE(kb.Add(*Formula::Factory::Bel(k, l, *(Italian == T), *(Aussie != T)))); +// EXPECT_TRUE(kb.Add(*Formula::Factory::Bel(k, l, *(Aussie == T), *(Eats(roo) == T)))); +// EXPECT_TRUE(kb.Add(*Formula::Factory::Bel(k, l, *(T == T), *(Italian == T || Veggie == T)))); +// EXPECT_TRUE(kb.Add(*Formula::Factory::Bel(k, l, *(Italian != T), *(Aussie == T)))); +// EXPECT_TRUE(kb.Add(*Formula::Factory::Bel(k, l, *(Meat(roo) != T), *(T != T)))); +// EXPECT_TRUE(kb.Add(*Formula::Factory::Bel(k, l, *(~Fa(x, (Veggie == T && Meat(x) == T) >> (Eats(x) != T))), *(T != T)))); +// EXPECT_FALSE(kb.Entails(*Formula::Factory::Bel(0, 0, *(Italian != T), *(Veggie != T)))); +// EXPECT_FALSE(kb.Entails(*Formula::Factory::Bel(0, 1, *(Italian != T), *(Veggie != T)))); +// EXPECT_FALSE(kb.Entails(*Formula::Factory::Bel(1, 0, *(Italian != T), *(Veggie != T)))); +// EXPECT_TRUE(kb.Entails(*Formula::Factory::Bel(1, 1, *(Italian != T), *(Veggie != T)))); +//} } // namespace limbo diff --git a/tests/linked.cc b/tests/linked.cc deleted file mode 100644 index 7313622..0000000 --- a/tests/linked.cc +++ /dev/null @@ -1,82 +0,0 @@ -// vim:filetype=cpp:textwidth=120:shiftwidth=2:softtabstop=2:expandtab -// Copyright 2017 Christoph Schwering - -#include - -#include -#include -#include - -namespace limbo { -namespace internal { - -template -size_t length(T r) { return std::distance(r.begin(), r.end()); } - -TEST(Linked, general) { - { - typedef IntMap Map; - Linked x; - x.container()[0] = 0; - x.container()[1] = 1; - x.container()[2] = 2; - EXPECT_EQ(x.container().n_keys(), 3); - EXPECT_EQ(x.container()[0], 0); - EXPECT_EQ(x.container()[1], 1); - EXPECT_EQ(x.container()[2], 2); - EXPECT_EQ(length(x), 1); - auto mapped = transform_crange(x, [](const Map& map) { return map[1]; }); - EXPECT_EQ(length(mapped), 1); - EXPECT_EQ(*mapped.begin(), 1); - } - { - typedef IntMultiMap Map; - Linked x; - x.container()[0].insert({1,2,3}); - x.container()[1].insert({11,22,33}); - x.container()[2].insert({111,222,333}); - Linked y(&x); - y.container()[0].insert({4,5,6}); - y.container()[1].insert({44,55,66}); - y.container()[2].insert({444,555,666}); - EXPECT_EQ(x.container().n_keys(), 3); - EXPECT_EQ(y.container().n_keys(), 3); - EXPECT_EQ(length(x), 1); - EXPECT_EQ(length(y), 2); - auto one = [](const Map&) -> int { return 1; }; - auto size = [](const Map& m) -> int { return m.n_keys(); }; - auto sum = [](int x, int y) -> int { return x + y; }; - EXPECT_EQ(x.Fold(one, sum), 1); - EXPECT_EQ(y.Fold(one, sum), 2); - EXPECT_EQ(x.Fold(size, sum), 3); - EXPECT_EQ(y.Fold(size, sum), 6); - { - auto mapped = transform_crange(y, [](const Map& map) -> const Map::Set& { return map[1]; }); - EXPECT_EQ(length(mapped), 2); - auto it = mapped.begin(); - EXPECT_EQ(*it, Map::Set({44,55,66})); - ++it; - EXPECT_EQ(*it, Map::Set({11,22,33})); - EXPECT_EQ(length(flatten_crange(mapped)), 6); - auto flattened = flatten_crange(mapped); - EXPECT_EQ(Map::Set(flattened.begin(), flattened.end()), Map::Set({11,22,33,44,55,66})); - } - { - auto mapped = y.transform([](const Map& map) -> const Map::Set& { return map[1]; }); - EXPECT_EQ(length(mapped), 2); - auto it = mapped.begin(); - EXPECT_EQ(*it, Map::Set({44,55,66})); - ++it; - EXPECT_EQ(*it, Map::Set({11,22,33})); - EXPECT_EQ(length(flatten_crange(mapped)), 6); - } - { - auto flattened = y.transform_flatten([](const Map& map) -> const Map::Set& { return map[1]; }); - EXPECT_EQ(Map::Set(flattened.begin(), flattened.end()), Map::Set({11,22,33,44,55,66})); - } - } -} - -} // namespace internal -} // namespace limbo - diff --git a/tests/solver.cc b/tests/solver.cc index d1f932b..584fd2b 100644 --- a/tests/solver.cc +++ b/tests/solver.cc @@ -178,16 +178,16 @@ TEST(SolverTest, ECAI2016Sound) { TEST(SolverTest, ECAI2016Complete) { Context ctx; Solver& solver = *ctx.solver(); - auto Bool = ctx.CreateSort(); RegisterSort(Bool, ""); - auto Food = ctx.CreateSort(); RegisterSort(Food, ""); - auto T = ctx.CreateName(Bool); REGISTER_SYMBOL(T); - //auto F = ctx.CreateName(Bool); REGISTER_SYMBOL(F); + auto Bool = ctx.CreateSort(); RegisterSort(Bool, ""); + auto Food = ctx.CreateSort(); RegisterSort(Food, ""); + auto T = ctx.CreateName(Bool); REGISTER_SYMBOL(T); + //auto F = ctx.CreateName(Bool); REGISTER_SYMBOL(F); auto Aussie = ctx.CreateFunction(Bool, 0)(); REGISTER_SYMBOL(Aussie); auto Italian = ctx.CreateFunction(Bool, 0)(); REGISTER_SYMBOL(Italian); auto Eats = ctx.CreateFunction(Bool, 1); REGISTER_SYMBOL(Eats); auto Meat = ctx.CreateFunction(Bool, 1); REGISTER_SYMBOL(Meat); auto Veggie = ctx.CreateFunction(Bool, 0)(); REGISTER_SYMBOL(Veggie); - auto roo = ctx.CreateName(Food); REGISTER_SYMBOL(roo); + auto roo = ctx.CreateName(Food); REGISTER_SYMBOL(roo); auto x = ctx.CreateVariable(Food); REGISTER_SYMBOL(x); solver.AddClause(( Meat(roo) == T ).as_clause()); solver.AddClause(( Meat(x) != T || Eats(x) != T || Veggie != T ).as_clause()); diff --git a/tests/term.cc b/tests/term.cc index b0071fc..61221f8 100644 --- a/tests/term.cc +++ b/tests/term.cc @@ -105,28 +105,28 @@ TEST(TermTest, Unify) { const Term fxy = tf.CreateTerm(f, {x,y}); const Term fgyx = tf.CreateTerm(f, {gy,x}); - { auto u = Term::Unify<0 >(n1, n1); EXPECT_TRUE(bool(u)); EXPECT_EQ(n1.Substitute(u.val, &tf), n1.Substitute(u.val, &tf)); } - { auto u = Term::Unify(n1, n1); EXPECT_TRUE(bool(u)); EXPECT_EQ(n1.Substitute(u.val, &tf), n1.Substitute(u.val, &tf)); } - { auto u = Term::Unify(n1, nn); EXPECT_FALSE(bool(u)); } - { auto u = Term::Unify(n1, n2); EXPECT_FALSE(bool(u)); } - - { auto u = Term::Unify(x, n2); EXPECT_TRUE(bool(u)); EXPECT_EQ(u.val(x).val, n2); EXPECT_EQ(x.Substitute(u.val, &tf), n2.Substitute(u.val, &tf)); } - { auto u = Term::Unify(x, n2); EXPECT_TRUE(bool(u)); EXPECT_EQ(u.val(x).val, n2); EXPECT_EQ(x.Substitute(u.val, &tf), n2.Substitute(u.val, &tf)); } - { auto u = Term::Unify(x, n2); EXPECT_FALSE(bool(u)); } - - { auto u = Term::Unify(fxx, fn1n1); EXPECT_TRUE(bool(u)); EXPECT_EQ(u.val(x).val, n1); EXPECT_EQ(fxx.Substitute(u.val, &tf), fn1n1.Substitute(u.val, &tf)); } - { auto u = Term::Unify(fxx, fn1n2); EXPECT_FALSE(bool(u)); } - { auto u = Term::Unify(fxx, fxn2); EXPECT_TRUE(bool(u)); EXPECT_EQ(u.val(x).val, n2); EXPECT_EQ(fxx.Substitute(u.val, &tf), fxn2.Substitute(u.val, &tf)); } - { auto u = Term::Unify(fxx, fn1x); EXPECT_TRUE(bool(u)); EXPECT_EQ(u.val(x).val, n1); EXPECT_EQ(fxx.Substitute(u.val, &tf), fn1x.Substitute(u.val, &tf)); } - { auto u = Term::Unify(fxx, fn1n1); EXPECT_TRUE(bool(u)); EXPECT_EQ(u.val(x).val, n1); EXPECT_EQ(fxx.Substitute(u.val, &tf), fn1n1.Substitute(u.val, &tf)); } - { auto u = Term::Unify(fxx, fn1n1); EXPECT_FALSE(bool(u)); } - { auto u = Term::Unify(fn1n2, fn1n2); EXPECT_TRUE(bool(u)); EXPECT_EQ(fn1n2.Substitute(u.val, &tf), fn1n2.Substitute(u.val, &tf)); } - { auto u = Term::Unify(fn1n2, fn2n1); EXPECT_FALSE(bool(u)); } - - { auto u = Term::Unify(fxy, fn1n1); EXPECT_TRUE(bool(u)); EXPECT_EQ(fxy.Substitute(u.val, &tf), fn1n1.Substitute(u.val, &tf)); } - { auto u = Term::Unify(fxy, fn1n2); EXPECT_TRUE(bool(u)); EXPECT_EQ(fxy.Substitute(u.val, &tf), fn1n2.Substitute(u.val, &tf)); } - { auto u = Term::Unify(fxy, fgyx); EXPECT_TRUE(bool(u)); /* only true because of missing occurs-check */ } - { auto u = Term::Unify(fxy, fgyx); EXPECT_FALSE(bool(u)); } + { auto u = Term::Unify<0 >(n1, n1); EXPECT_TRUE(bool(u)); EXPECT_EQ(n1.Substitute(u.val, &tf), n1.Substitute(u.val, &tf)); } + { auto u = Term::Unify(n1, n1); EXPECT_TRUE(bool(u)); EXPECT_EQ(n1.Substitute(u.val, &tf), n1.Substitute(u.val, &tf)); } + { auto u = Term::Unify(n1, nn); EXPECT_FALSE(bool(u)); } + { auto u = Term::Unify(n1, n2); EXPECT_FALSE(bool(u)); } + + { auto u = Term::Unify(x, n2); EXPECT_TRUE(bool(u)); EXPECT_EQ(u.val(x).val, n2); EXPECT_EQ(x.Substitute(u.val, &tf), n2.Substitute(u.val, &tf)); } + { auto u = Term::Unify(x, n2); EXPECT_TRUE(bool(u)); EXPECT_EQ(u.val(x).val, n2); EXPECT_EQ(x.Substitute(u.val, &tf), n2.Substitute(u.val, &tf)); } + { auto u = Term::Unify(x, n2); EXPECT_FALSE(bool(u)); } + + { auto u = Term::Unify(fxx, fn1n1); EXPECT_TRUE(bool(u)); EXPECT_EQ(u.val(x).val, n1); EXPECT_EQ(fxx.Substitute(u.val, &tf), fn1n1.Substitute(u.val, &tf)); } + { auto u = Term::Unify(fxx, fn1n2); EXPECT_FALSE(bool(u)); } + { auto u = Term::Unify(fxx, fxn2); EXPECT_TRUE(bool(u)); EXPECT_EQ(u.val(x).val, n2); EXPECT_EQ(fxx.Substitute(u.val, &tf), fxn2.Substitute(u.val, &tf)); } + { auto u = Term::Unify(fxx, fn1x); EXPECT_TRUE(bool(u)); EXPECT_EQ(u.val(x).val, n1); EXPECT_EQ(fxx.Substitute(u.val, &tf), fn1x.Substitute(u.val, &tf)); } + { auto u = Term::Unify(fxx, fn1n1); EXPECT_TRUE(bool(u)); EXPECT_EQ(u.val(x).val, n1); EXPECT_EQ(fxx.Substitute(u.val, &tf), fn1n1.Substitute(u.val, &tf)); } + { auto u = Term::Unify(fxx, fn1n1); EXPECT_FALSE(bool(u)); } + { auto u = Term::Unify(fn1n2, fn1n2); EXPECT_TRUE(bool(u)); EXPECT_EQ(fn1n2.Substitute(u.val, &tf), fn1n2.Substitute(u.val, &tf)); } + { auto u = Term::Unify(fn1n2, fn2n1); EXPECT_FALSE(bool(u)); } + + { auto u = Term::Unify(fxy, fn1n1); EXPECT_TRUE(bool(u)); EXPECT_EQ(fxy.Substitute(u.val, &tf), fn1n1.Substitute(u.val, &tf)); } + { auto u = Term::Unify(fxy, fn1n2); EXPECT_TRUE(bool(u)); EXPECT_EQ(fxy.Substitute(u.val, &tf), fn1n2.Substitute(u.val, &tf)); } + { auto u = Term::Unify(fxy, fgyx); EXPECT_TRUE(bool(u)); /* only true because of missing occurs-check */ } + { auto u = Term::Unify(fxy, fgyx); EXPECT_FALSE(bool(u)); } } TEST(TermTest, Isomorphic) { -- GitLab