Commit graph

13 commits

Author SHA1 Message Date
Rob23oba
5b9567b144
fix: complete overhaul of structural recursion on inductives predicates (#9995)
This PR almost completely rewrites the inductive predicate recursion
algorithm; in particular `IndPredBelow` to function more consistently.
Historically, the `brecOn` generation through `IndPredBelow` has been
very error-prone -- this should be fixed now since the new algorithm is
very direct and doesn't rely on tactics or meta-variables at all.
Additionally, the new structural recursion procedure for inductive
predicates shares more code with regular structural recursion and thus
allows for mutual and nested recursion in the same way it was possible
with regular structural recursion. For example, the following works now:
```lean-4
mutual

inductive Even : Nat → Prop where
  | zero : Even 0
  | succ (h : Odd n) : Even n.succ

inductive Odd : Nat → Prop where
  | succ (h : Even n) : Odd n.succ

end

mutual

theorem Even.exists (h : Even n) : ∃ a, n = 2 * a :=
  match h with
  | .zero => ⟨0, rfl⟩
  | .succ h =>
    have ⟨a, ha⟩ := h.exists
    ⟨a + 1, congrArg Nat.succ ha⟩
termination_by structural h

theorem Odd.exists (h : Odd n) : ∃ a, n = 2 * a + 1 :=
  match h with
  | .succ h =>
    have ⟨a, ha⟩ := h.exists
    ⟨a, congrArg Nat.succ ha⟩
termination_by structural h

end
```

Closes #1672
Closes #10004
2025-09-01 08:17:58 +00:00
Wojciech Rozowski
7f17970551
feat: generate (co)induction proof principles for mutually (co)inductive predicates (#9358)
This PR adds support for generating lattice-theoretic (co)induction
proof principles for predicates defined via `mutual` blocks using
`inductive_fixpoint`/`coinductive_fixpoint` constructs.

### Key Changes
- The order on product lattices (used to define fixpoints of mutual
blocks) is unfolded.
- Hypotheses in generated principles are curried.
- Conclusions are projected to focus only on the predicate of interest
(rather than being a conjunction of conclusions for all functions
defined in the `mutual` block.

### Example
Given:
```lean4
mutual
    def f : Prop :=
      g
    coinductive_fixpoint

    def g : Prop :=
      f
    coinductive_fixpoint
  end
```
The system now generates these coinduction principles:
```lean4
f.coinduct (pred_1 pred_2 : Prop) (hyp_1 : pred_1 → pred_2) (hyp_2 : pred_2 → pred_1) : pred_1 → f
```
and 
```lean4
g.coinduct (pred_1 pred_2 : Prop) (hyp_1 : pred_1 → pred_2) (hyp_2 : pred_2 → pred_1) : pred_2 → g
```

---------

Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
2025-07-30 11:18:41 +00:00
Sebastian Ullrich
ff1d3138bf
refactor: module-ize Lean (#9330) 2025-07-25 12:02:51 +00:00
Rob23oba
e148871087
chore: fix spelling errors (#9175)
(Almost) only typos in constant names and doc-strings were considered;
grammar was not considered. Also, along others,
`mkDefinitionValInferrringUnsafe` has been fixed :-)
2025-07-24 23:35:32 +00:00
Joachim Breitner
ec13bb963f
fix: PProdN.reduceProjs to also look for projection functions (#9464)
This PR makes `PProdN.reduceProjs` also look for projection functions.
Previously, all redexes were created by the functions in `PProdN`, which
used primitive projections. But with `mkAdmProj` the projection
functions creep in via the types of the `admissible_pprod_fst` theorem.
So let's just reduce both of them.

Fixes #9462.
2025-07-22 09:22:50 +00:00
Paul Reichert
98e4b2882f
refactor: migrate to new ranges (#8841)
This PR migrates usages of `Std.Range` to the new polymorphic ranges.

This PR unfortunately increases the transitive imports for
frequently-used parts of `Init` because the ranges now rely on iterators
in order to provide their functionality for types other than `Nat`.
However, iteration over ranges in compiled code is as efficient as
before in the examples I checked. This is because of a special
`IteratorLoop` implementation provided in the PR for this purpose.

There were two issues that were uncovered during migration:

* In `IndPredBelow.lean`, migrating the last remaining range causes
`compilerTest1.lean` to break. I have minimized the issue and came to
the conclusion it's a compiler bug. Therefore, I have not replaced said
old range usage yet (see #9186).
* In `BRecOn.lean`, we are publicly importing the ranges. Making this
import private should theoretically work, but there seems to be a
problem with the module system, causing the build to panic later in
`Init.Data.Grind.Poly` (see #9185).
* In `FuzzyMatching.lean`, inlining fails with the new ranges, which
would have led to significant slowdown. Therefore, I have not migrated
this file either.
2025-07-07 12:41:53 +00:00
euprunin
2ea675369f
chore: fix spelling mistakes (#7328)
Co-authored-by: euprunin <euprunin@users.noreply.github.com>
2025-04-07 01:15:48 +00:00
Joachim Breitner
7b813d4f5d
feat: partial_fixpoint: partial functions with equations (#6355)
This PR adds the ability to define possibly non-terminating functions
and still be able to reason about them equationally, as long as they are
tail-recursive or monadic.

Typical uses of this feature are
```lean4
def ack : (n m : Nat) → Option Nat
  | 0,   y   => some (y+1)
  | x+1, 0   => ack x 1
  | x+1, y+1 => do ack x (← ack (x+1) y)
partial_fixpiont

def whileSome (f : α → Option α) (x : α) : α :=
  match f x with
  | none => x
  | some x' => whileSome f x'
partial_fixpiont

def computeLfp {α : Type u} [DecidableEq α] (f : α → α) (x : α) : α :=
  let next := f x
  if x ≠ next then
    computeLfp f next
  else
    x
partial_fixpiont

noncomputable def geom : Distr Nat := do
  let head ← coin
  if head then
    return 0
  else
    let n ← geom
    return (n + 1)
partial_fixpiont
```

This PR contains

* The necessary fragment of domain theory, up to (a variant of)
Knaster–Tarski theorem (merged as
https://github.com/leanprover/lean4/pull/6477)
* A tactic to solve monotonicity goals compositionally (a bit like
mathlib’s `fun_prop`) (merged as
https://github.com/leanprover/lean4/pull/6506)
* An attribute to extend that tactic (merged as
https://github.com/leanprover/lean4/pull/6506)
* A “derecursifier” that uses that machinery to define recursive
function, including support for dependent functions and mutual
recursion.
* Fixed-point induction principles (technical, tedious to use)
* For `Option`-valued functions: Partial correctness induction theorems
that hide all the domain theory

This is heavily inspired by [Isabelle’s `partial_function`
command](https://isabelle.in.tum.de/doc/codegen.pdf).
2025-01-21 09:54:30 +00:00
Kim Morrison
218601009b
chore: rename Array.back to back! (#5897) 2024-10-31 09:18:18 +00:00
Joachim Breitner
60096e7d15
refactor: more idiomatic syntax for if h: (#5567)
https://github.com/leanprover/lean4/pull/5552 introduced a fair number
of `if h:`, but the slightly preferred style is `if h :`, with a space,
so here goes a quick `sed`.
2024-10-01 15:23:54 +00:00
TomasPuverle
ddec5336e5
chore: switch obvious cases of array "bang"[]! indexing to rely on hypothesis (#5552)
Update certain uses of `arr[i]!` to use the "provably correct" version
`arr[i]`, in order to use "best practices".

Some motivation and discussion on
[Zulip](https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Lean.20compiler.2Felaborator.20development.20question/near/472934715)
2024-10-01 11:12:22 +00:00
euprunin
1b4ee185e8
chore: fix spelling mistakes in src/Lean/Meta/ (#5436)
---
This is the final set of fixes of this kind. Thanks for your patience!

Co-authored-by: euprunin <euprunin@users.noreply.github.com>
2024-09-23 23:09:14 +00:00
Joachim Breitner
3a4d2cded3
refactor: Introduce PProdN module (#4807)
code to create nested `PProd`s, and project out, and related functions
were scattered in variuos places. This unifies them in
`Lean.Meta.PProdN`.

It also consistently avoids the terminal `True` or `PUnit`, for slightly
easier to read constructions.
2024-07-22 11:56:50 +00:00