lean4-htt/tests/lean/run/mutual_termination_by_errors.lean
Wojciech Rozowski 96fcc94acb
feat: add support for lattice-theoretic (co)inductive predicates (#8097)
This PR adds support for inductive and coinductive predicates defined
using lattice theoretic structures on `Prop`. These are syntactically
defined using `greatest_fixpoint` or `least_fixpoint` termination
clauses for recursive `Prop`-valued functions. The functionality relies
on `partial_fixpoint` machinery and requires function definitions to be
monotone. For non-mutually recursive predicates, an appropriate
(co)induction proof principle (given by Park induction) is generated.

Summary of changes:
- `Interal.Order.Basic` now contains `CompleteLattice` class, as well as
version of Knaster-Tarski fixpoint theorem (with an associated Park
induction principle) for the internal use for defining (co)inductive
predicates. `Prop` is shown to have two complete lattice structures (one
given by implication order for defining inductive predicates, and one
given by reverse implication for defining coinductive predicates).
Additionally, proofs that lattices are closed under products and
function spaces are included.
- Partial fixpoint's `EqnInfo` now additionally carries an information
whether something is defined as a lattice-theoretic fixpoint or via
CCPOs.
- When constructing a (co)inductive predicate,`PartialFixpoint/Main`
builds an appropriate lattice structure on the type of the predicate
using product lattice, function space lattice and an appropriate lattice
instance on `Prop`.
- `PartialFixpoint/Eqns` is modified to be able to perform rewrite under
lattice-theoretic fixpoint construction
- `PartialFixpoint/Induction`contains a case split for handling of the
(co)inductive predicates. In the case of lattice-theoretic fixpoints, it
appropriately desugars the Park induction principle.
2025-04-30 15:48:58 +00:00

216 lines
5.2 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

namespace Test
/--
error: incomplete set of termination hints:
This function is mutually recursive with Test.f, Test.h and Test.i, which do not have a termination hint.
The present clause is ignored.
-/
#guard_msgs in
mutual
def f : Nat → ααα
| 0, a, b => a
| n+1, a, b => g n a b |>.1
def g : Nat → αα → (α × α)
| 0, a, b => (a, b)
| n+1, a, b => (h n a b, a)
termination_by n _ _ => n -- Error
def h : Nat → ααα
| 0, a, b => b
| n+1, a, b => i n a b
def i : Nat → ααα
| 0, a, b => b
| n+1, a, b => f n a b
end
end Test
namespace Test2
/--
error: Incompatible termination hint; this function is mutually recursive with Test2.f, which is marked as `termination_by structural` so this one also needs to be marked `structural`.
-/
#guard_msgs in
mutual
def f : Nat → ααα
| 0, a, b => a
| n+1, a, b => g n a b |>.1
termination_by structural n _ _ => n
def g : Nat → αα → (α × α)
| 0, a, b => (a, b)
| n+1, a, b => (h n a b, a)
termination_by n _ _ => n -- Error
def h : Nat → ααα
| 0, a, b => b
| n+1, a, b => f n a b
termination_by n _ _ => n
end
end Test2
namespace Test3
/--
error: Incompatible termination hint; this function is mutually recursive with Test3.f, which is not marked as `structural` so this one cannot be `structural` either.
-/
#guard_msgs in
mutual
def f : Nat → ααα
| 0, a, b => a
| n+1, a, b => g n a b |>.1
termination_by n _ _ => n
def g : Nat → αα → (α × α)
| 0, a, b => (a, b)
| n+1, a, b => (h n a b, a)
termination_by structural n _ _ => n -- Error
def h : Nat → ααα
| 0, a, b => b
| n+1, a, b => f n a b
termination_by structural n _ _ => n
end
end Test3
namespace Test4
/--
error: Incompatible termination hint; this function is mutually recursive with Test4.f, which is not marked as `structural` so this one cannot be `structural` either.
-/
#guard_msgs in
mutual
def f : Nat → ααα
| 0, a, b => a
| n+1, a, b => g n a b |>.1
termination_by n _ _ => n
def g : Nat → αα → (α × α)
| 0, a, b => (a, b)
| n+1, a, b => (h n a b, a)
termination_by n _ _ => n
def h : Nat → ααα
| 0, a, b => b
| n+1, a, b => f n a b
termination_by structural n _ _ => n -- Error
end
end Test4
namespace Test5
/--
error: Incompatible termination hint; this function is marked as structurally recursive, so no explicit termination proof is needed.
-/
#guard_msgs in
mutual
def f : Nat → ααα
| 0, a, b => a
| n+1, a, b => g n a b |>.1
termination_by structural n _ _ => n
def g : Nat → αα → (α × α)
| 0, a, b => (a, b)
| n+1, a, b => (h n a b, a)
termination_by structural n _ _ => n
decreasing_by sorry -- Error
def h : Nat → ααα
| 0, a, b => b
| n+1, a, b => f n a b
termination_by structural n _ _ => n
end
end Test5
namespace Test6
/--
error: Incompatible termination hint; this function is mutually recursive with Test6.f, which is marked as `partial_fixpoint` so this one also needs to be marked `partial_fixpoint`.
-/
#guard_msgs in
mutual
def f (x : Nat) : Prop :=
g (x + 1)
partial_fixpoint
def g (x : Nat) : Prop := f (x + 1)
least_fixpoint
end
end Test6
namespace Test7
/--
error: Incompatible termination hint; this function is mutually recursive with Test7.f, which is marked as `greatest_fixpoint` so this one also needs to be marked `least_fixpoint` or `greatest_fixpoint`.
-/
#guard_msgs in
mutual
def f (x : Nat) : Prop :=
g (x + 1)
greatest_fixpoint
def g (x : Nat) : Prop :=
f (x + 1)
partial_fixpoint
end
end Test7
namespace Test8
/--
error: Incompatible termination hint; this function is mutually recursive with Test8.f, which is not also marked as `partial_fixpoint`, so this one cannot be either.
-/
#guard_msgs in
mutual
def f (x : Nat) : Prop :=
g (x + 1)
termination_by?
def g (x : Nat) : Prop :=
f (x + 1)
partial_fixpoint
end
end Test8
namespace Test9
/--
error: Incompatible termination hint; this function is mutually recursive with Test9.f, which is not also marked as `least_fixpoint` or `greatest_fixpoint`, so this one cannot be either.
-/
#guard_msgs in
mutual
def f (x : Nat) : Prop :=
g (x + 1)
termination_by?
def g (x : Nat) : Prop :=
f (x + 1)
least_fixpoint
end
end Test9
namespace Test10
/--
error: Incompatible termination hint; this function is mutually recursive with Test10.f, which is marked as `greatest_fixpoint` so this one also needs to be marked `least_fixpoint` or `greatest_fixpoint`.
-/
#guard_msgs in
mutual
def f (x : Nat) : Prop :=
g (x + 1)
greatest_fixpoint
def g (x : Nat) : Prop :=
f (x + 1)
termination_by?
end
end Test10
namespace Test11
/--
error: Incompatible termination hint; this function is mutually recursive with Test11.f, which is marked as `partial_fixpoint` so this one also needs to be marked `partial_fixpoint`.
-/
#guard_msgs in
mutual
def f (x : Nat) : Prop :=
g (x +1)
partial_fixpoint
def g (x : Nat) : Prop :=
f (x + 1)
end
end Test11