def loop (x : Nat) : Unit := loop (x + 1) partial_fixpoint /-- info: loop.fixpoint_induct (motive : (Nat → Unit) → Prop) (adm : Lean.Order.admissible motive) (h : ∀ (loop : Nat → Unit), motive loop → motive fun x => loop (x + 1)) : motive loop -/ #guard_msgs in #check loop.fixpoint_induct /-- error: Unknown constant `loop.partial_correctness` -/ #guard_msgs in #check loop.partial_correctness def find (P : Nat → Bool) (x : Nat) : Option Nat := if P x then some x else find P (x +1) partial_fixpoint /-- info: find.fixpoint_induct (P : Nat → Bool) (motive : (Nat → Option Nat) → Prop) (adm : Lean.Order.admissible motive) (h : ∀ (find : Nat → Option Nat), motive find → motive fun x => if P x = true then some x else find (x + 1)) : motive (find P) -/ #guard_msgs in #check find.fixpoint_induct /-- info: find.partial_correctness (P : Nat → Bool) (motive : Nat → Nat → Prop) (h : ∀ (find : Nat → Option Nat), (∀ (x r : Nat), find x = some r → motive x r) → ∀ (x r : Nat), (if P x = true then some x else find (x + 1)) = some r → motive x r) (x r✝ : Nat) : find P x = some r✝ → motive x r✝ -/ #guard_msgs in #check find.partial_correctness def fib (n : Nat) := go 0 0 1 where go i fip fi := if i = n then fi else go (i + 1) fi (fi + fip) partial_fixpoint /-- info: fib.go.fixpoint_induct (n : Nat) (motive : (Nat → Nat → Nat → Nat) → Prop) (adm : Lean.Order.admissible motive) (h : ∀ (go : Nat → Nat → Nat → Nat), motive go → motive fun i fip fi => if i = n then fi else go (i + 1) fi (fi + fip)) : motive (fib.go n) -/ #guard_msgs in #check fib.go.fixpoint_induct local instance (b : Bool) [Nonempty α] [Nonempty β] : Nonempty (cond b α β) := by cases b <;> assumption local instance (b : Bool) [Nonempty α] [Nonempty β] : Nonempty (if b then α else β) := by split <;> assumption mutual def dependent2''a (m n : Nat) (b : Bool) : if b then Nat else Bool := if _ : b then dependent2''a m (n + 1) b else dependent2''b m m (n + m) b partial_fixpoint def dependent2''b (m k n : Nat) (b : Bool) : if b then Nat else Bool := if b then dependent2''b m k n b else dependent2''c m (.last _) (n + m) b partial_fixpoint def dependent2''c (m : Nat) (i : Fin (m+1)) (n : Nat) (b : Bool) : if b then Nat else Bool := if b then dependent2''c m i n b else dependent2''a m i b partial_fixpoint end /-- info: dependent2''a.mutual_fixpoint_induct (m : Nat) (b : Bool) (motive_1 : (Nat → if b = true then Nat else Bool) → Prop) (motive_2 : (Nat → Nat → if b = true then Nat else Bool) → Prop) (motive_3 : (Fin (m + 1) → Nat → if b = true then Nat else Bool) → Prop) (adm_1 : Lean.Order.admissible motive_1) (adm_2 : Lean.Order.admissible motive_2) (adm_3 : Lean.Order.admissible motive_3) (h_1 : ∀ (dependent2''a : Nat → if b = true then Nat else Bool) (dependent2''b : Nat → Nat → if b = true then Nat else Bool), motive_1 dependent2''a → motive_2 dependent2''b → motive_1 fun n => if x : b = true then dependent2''a (n + 1) else dependent2''b m (n + m)) (h_2 : ∀ (dependent2''b : Nat → Nat → if b = true then Nat else Bool) (dependent2''c : Fin (m + 1) → Nat → if b = true then Nat else Bool), motive_2 dependent2''b → motive_3 dependent2''c → motive_2 fun k n => if b = true then dependent2''b k n else dependent2''c (Fin.last m) (n + m)) (h_3 : ∀ (dependent2''a : Nat → if b = true then Nat else Bool) (dependent2''c : Fin (m + 1) → Nat → if b = true then Nat else Bool), motive_1 dependent2''a → motive_3 dependent2''c → motive_3 fun i n => if b = true then dependent2''c i n else dependent2''a ↑i) : (motive_1 fun n => dependent2''a m n b) ∧ (motive_2 fun k n => dependent2''b m k n b) ∧ motive_3 fun i n => dependent2''c m i n b -/ #guard_msgs in #check dependent2''a.mutual_fixpoint_induct mutual def dependent3''a (m n : Nat) (b : Bool) : Option (if b then Nat else Bool) := if _ : b then dependent3''a m (n + 1) b else dependent3''b m m (n + m) b partial_fixpoint def dependent3''b (m k n : Nat) (b : Bool) : Option (if b then Nat else Bool) := if b then dependent3''b m k n b else dependent3''c m (.last _) (n + m) b partial_fixpoint def dependent3''c (m : Nat) (i : Fin (m+1)) (n : Nat) (b : Bool) : Option (if b then Nat else Bool) := if b then dependent3''c m i n b else dependent3''a m i b partial_fixpoint end /-- info: dependent3''a.mutual_partial_correctness (m : Nat) (b : Bool) (motive_1 : Nat → (if b = true then Nat else Bool) → Prop) (motive_2 : Nat → Nat → (if b = true then Nat else Bool) → Prop) (motive_3 : Fin (m + 1) → Nat → (if b = true then Nat else Bool) → Prop) (h_1 : ∀ (dependent3''a : Nat → Option (if b = true then Nat else Bool)) (dependent3''b : Nat → Nat → Option (if b = true then Nat else Bool)), (∀ (n : Nat) (r : if b = true then Nat else Bool), dependent3''a n = some r → motive_1 n r) → (∀ (k n : Nat) (r : if b = true then Nat else Bool), dependent3''b k n = some r → motive_2 k n r) → ∀ (n : Nat) (r : if b = true then Nat else Bool), (if x : b = true then dependent3''a (n + 1) else dependent3''b m (n + m)) = some r → motive_1 n r) (h_2 : ∀ (dependent3''b : Nat → Nat → Option (if b = true then Nat else Bool)) (dependent3''c : Fin (m + 1) → Nat → Option (if b = true then Nat else Bool)), (∀ (k n : Nat) (r : if b = true then Nat else Bool), dependent3''b k n = some r → motive_2 k n r) → (∀ (i : Fin (m + 1)) (n : Nat) (r : if b = true then Nat else Bool), dependent3''c i n = some r → motive_3 i n r) → ∀ (k n : Nat) (r : if b = true then Nat else Bool), (if b = true then dependent3''b k n else dependent3''c (Fin.last m) (n + m)) = some r → motive_2 k n r) (h_3 : ∀ (dependent3''a : Nat → Option (if b = true then Nat else Bool)) (dependent3''c : Fin (m + 1) → Nat → Option (if b = true then Nat else Bool)), (∀ (n : Nat) (r : if b = true then Nat else Bool), dependent3''a n = some r → motive_1 n r) → (∀ (i : Fin (m + 1)) (n : Nat) (r : if b = true then Nat else Bool), dependent3''c i n = some r → motive_3 i n r) → ∀ (i : Fin (m + 1)) (n : Nat) (r : if b = true then Nat else Bool), (if b = true then dependent3''c i n else dependent3''a ↑i) = some r → motive_3 i n r) : (∀ (n : Nat) (r : if b = true then Nat else Bool), dependent3''a m n b = some r → motive_1 n r) ∧ (∀ (k n : Nat) (r : if b = true then Nat else Bool), dependent3''b m k n b = some r → motive_2 k n r) ∧ ∀ (i : Fin (m + 1)) (n : Nat) (r : if b = true then Nat else Bool), dependent3''c m i n b = some r → motive_3 i n r -/ #guard_msgs in #check dependent3''a.mutual_partial_correctness -- The following example appears in the manual; having it here alerts us early of breakage def List.findIndex (xs : List α) (p : α → Bool) : Option Nat := match xs with | [] => none | x::ys => if p x then some 0 else (· + 1) <$> List.findIndex ys p partial_fixpoint /-- info: List.findIndex.partial_correctness.{u_1} {α : Type u_1} (p : α → Bool) (motive : List α → Nat → Prop) (h : ∀ (findIndex : List α → Option Nat), (∀ (xs : List α) (r : Nat), findIndex xs = some r → motive xs r) → ∀ (xs : List α) (r : Nat), (match xs with | [] => none | x :: ys => if p x = true then some 0 else (fun x => x + 1) <$> findIndex ys) = some r → motive xs r) (xs : List α) (r✝ : Nat) : xs.findIndex p = some r✝ → motive xs r✝ -/ #guard_msgs in #check List.findIndex.partial_correctness theorem List.findIndex_implies_pred (xs : List α) (p : α → Bool) : xs.findIndex p = some i → xs[i]?.any p := by apply List.findIndex.partial_correctness (motive := fun xs i => xs[i]?.any p) intro findIndex ih xs r hsome split at hsome next => contradiction next x ys => split at hsome next => have : r = 0 := by simp_all simp_all next => simp only [Option.map_eq_map, Option.map_eq_some_iff] at hsome obtain ⟨r', hr, rfl⟩ := hsome specialize ih _ _ hr simpa mutual def f (n : Nat) : Option Nat := g (n + 1) partial_fixpoint def g (n : Nat) : Option Nat := if n = 0 then .none else f (n + 1) partial_fixpoint end /-- info: f.mutual_partial_correctness (motive_1 motive_2 : Nat → Nat → Prop) (h_1 : ∀ (g : Nat → Option Nat), (∀ (n r : Nat), g n = some r → motive_2 n r) → ∀ (n r : Nat), g (n + 1) = some r → motive_1 n r) (h_2 : ∀ (f : Nat → Option Nat), (∀ (n r : Nat), f n = some r → motive_1 n r) → ∀ (n r : Nat), (if n = 0 then none else f (n + 1)) = some r → motive_2 n r) : (∀ (n r : Nat), f n = some r → motive_1 n r) ∧ ∀ (n r : Nat), g n = some r → motive_2 n r -/ #guard_msgs in #check f.mutual_partial_correctness /-- info: f.partial_correctness (motive_1 motive_2 : Nat → Nat → Prop) (h_1 : ∀ (g : Nat → Option Nat), (∀ (n r : Nat), g n = some r → motive_2 n r) → ∀ (n r : Nat), g (n + 1) = some r → motive_1 n r) (h_2 : ∀ (f : Nat → Option Nat), (∀ (n r : Nat), f n = some r → motive_1 n r) → ∀ (n r : Nat), (if n = 0 then none else f (n + 1)) = some r → motive_2 n r) (n r✝ : Nat) : f n = some r✝ → motive_1 n r✝ -/ #guard_msgs in #check f.partial_correctness