Compare commits

...

5 Commits

Author SHA1 Message Date
Leonardo de Moura
38730111c4 chore: move to run 2025-04-01 14:53:06 -07:00
Leonardo de Moura
fce2eeff6e chore: update 2025-04-01 14:52:27 -07:00
Leonardo de Moura
21f00ae347 test: Bool diseq propagation 2025-04-01 14:51:45 -07:00
Leonardo de Moura
81429d504f feat: propagate Bool diseq 2025-04-01 14:50:54 -07:00
Leonardo de Moura
511ab9eea5 feat: helper lemmas 2025-04-01 14:50:19 -07:00
5 changed files with 51 additions and 29 deletions

View File

@@ -113,6 +113,9 @@ theorem Bool.not_eq_of_eq_false {a : Bool} (h : a = false) : (!a) = true := by s
theorem Bool.eq_false_of_not_eq_true {a : Bool} (h : (!a) = true) : a = false := by simp_all
theorem Bool.eq_true_of_not_eq_false {a : Bool} (h : (!a) = false) : a = true := by simp_all
theorem Bool.eq_false_of_not_eq_true' {a : Bool} (h : ¬ a = true) : a = false := by simp_all
theorem Bool.eq_true_of_not_eq_false' {a : Bool} (h : ¬ a = false) : a = true := by simp_all
theorem Bool.false_of_not_eq_self {a : Bool} (h : (!a) = a) : False := by
by_cases a <;> simp_all

View File

@@ -119,15 +119,25 @@ builtin_grind_propagator propagateNotDown ↓Not := fun e => do
else if ( isEqv e a) then
closeGoal <| mkApp2 (mkConst ``Grind.false_of_not_eq_self) a ( mkEqProof e a)
def propagateBoolDiseq (a : Expr) : GoalM Unit := do
if let some h mkDiseqProof? a ( getBoolFalseExpr) then
pushEqBoolTrue a <| mkApp2 (mkConst ``Grind.Bool.eq_true_of_not_eq_false') a h
if let some h mkDiseqProof? a ( getBoolTrueExpr) then
pushEqBoolFalse a <| mkApp2 (mkConst ``Grind.Bool.eq_false_of_not_eq_true') a h
/-- Propagates `Eq` upwards -/
builtin_grind_propagator propagateEqUp Eq := fun e => do
let_expr Eq _ a b := e | return ()
let_expr Eq α a b := e | return ()
if ( isEqTrue a) then
pushEq e b <| mkApp3 (mkConst ``Grind.eq_eq_of_eq_true_left) a b ( mkEqTrueProof a)
else if ( isEqTrue b) then
pushEq e a <| mkApp3 (mkConst ``Grind.eq_eq_of_eq_true_right) a b ( mkEqTrueProof b)
else if ( isEqv a b) then
pushEqTrue e <| mkEqTrueCore e ( mkEqProof a b)
if α.isConstOf ``Bool then
if ( isEqFalse e) then
propagateBoolDiseq a
propagateBoolDiseq b
let aRoot getRootENode a
let bRoot getRootENode b
if aRoot.ctor && bRoot.ctor && aRoot.self.getAppFn != bRoot.self.getAppFn then
@@ -146,6 +156,9 @@ builtin_grind_propagator propagateEqDown ↓Eq := fun e => do
pushEq a b <| mkOfEqTrueCore e ( mkEqTrueProof e)
else if ( isEqFalse e) then
let_expr Eq α lhs rhs := e | return ()
if α.isConstOf ``Bool then
propagateBoolDiseq lhs
propagateBoolDiseq rhs
propagateCutsatDiseq lhs rhs
let thms getExtTheorems α
if !thms.isEmpty then

View File

@@ -1,28 +0,0 @@
open List Nat
attribute [grind] List.getElem_cons_zero
attribute [grind] List.filter_nil List.filter_cons
attribute [grind] List.any_nil List.any_cons
@[simp] theorem any_filter {l : List α} {p q : α Bool} :
(filter p l).any q = l.any fun a => p a && q a := by
induction l <;> grind
-- Fails at:
-- [grind] Goal diagnostics ▼
-- [facts] Asserted facts ▼
-- [prop] (filter p tail).any q = tail.any fun a => p a && q a
-- [prop] ¬(filter p (head :: tail)).any q = (head :: tail).any fun a => p a && q a
-- [prop] filter p (head :: tail) = if p head = true then head :: filter p tail else filter p tail
-- [prop] ((head :: tail).any fun a => p a && q a) = (p head && q head || tail.any fun a => p a && q a)
-- [prop] ¬p head = true
-- [eqc] False propositions ▼
-- [prop] (filter p (head :: tail)).any q = (head :: tail).any fun a => p a && q a
-- [prop] p head = true
-- [eqc] Equivalence classes ▼
-- [] {(head :: tail).any fun a => p a && q a, p head && q head || tail.any fun a => p a && q a}
-- [] {filter p (head :: tail), filter p tail, if p head = true then head :: filter p tail else filter p tail}
-- [] {(filter p tail).any q, (filter p (head :: tail)).any q, tail.any fun a => p a && q a}
-- Despite knowing that `p head = false`, grind doesn't see that
-- `p head && q head || tail.any fun a => p a && q a = tail.any fun a => p a && q a`,
-- which should finish the problem.

View File

@@ -0,0 +1,25 @@
set_option grind.warning false
example (f : Bool Nat) : (x = y q) ¬ q y = false f x = 0 f true = 0 := by
grind (splits := 0)
example (f : Bool Nat) : (x = false q) ¬ q f x = 0 f true = 0 := by
grind (splits := 0)
example (f : Bool Nat) : (y = x q) ¬ q y = false f x = 0 f true = 0 := by
grind (splits := 0)
example (f : Bool Nat) : (x = true q) ¬ q f x = 0 f false = 0 := by
grind (splits := 0)
example (f : Bool Nat) : (true = x q) ¬ q f x = 0 f false = 0 := by
grind (splits := 0)
example (f : Bool Nat) : (false = x q) ¬ q f x = 0 f true = 0 := by
grind (splits := 0)
example (f : Bool Nat) : (x = false q) ¬ q f x = 0 f true = 0 := by
grind (splits := 0)
example (f : Bool Nat) : (y = x q) ¬ q y = true f x = 0 f false = 0 := by
grind (splits := 0)

View File

@@ -0,0 +1,9 @@
reset_grind_attrs%
open List Nat
attribute [grind] List.filter_nil List.filter_cons
attribute [grind] List.any_nil List.any_cons
@[simp] theorem any_filter {l : List α} {p q : α Bool} :
(filter p l).any q = l.any fun a => p a && q a := by
induction l <;> grind