Commit graph

2362 commits

Author SHA1 Message Date
Kim Morrison
8154aaa1b3
feat: preparation for semirings and noncommutative rings in grind (#8343)
This PR splits `Lean.Grind.CommRing` into 4 typeclasses, for semirings
and noncommutative rings. This does not yet change the behaviour of
`grind`, which expects to find all 4 typeclasses. Later we will make
some generalizations.
2025-05-15 11:25:57 +00:00
Leonardo de Moura
06ef738aec
fix: etaStruct and preprocessing issues in grind (#8344)
This PR fixes term normalization issues in `grind`, and the new option
`grind +etaStruct`.
2025-05-15 03:32:10 +00:00
Leonardo de Moura
fad3e0ef5e
fix: propagateCtor (#8341)
This PR fixes the `propagateCtor` constraint propagator used in `grind`.
2025-05-15 00:32:25 +00:00
JovanGerb
0a32ba371a
perf: store dsimp cache in a simp call (#7428)
This PR adds a `dsimp` cache to `simp`. Previously each `dsimp` call
from `simp` started with a fresh cache.

For example, when simplifying `a * b` for `a b : A`, the type `A` is now
only visited once by `dsimp`, instead of at least 3 times.
[
Mathlib
bench](https://github.com/leanprover-community/mathlib4/pull/22812#issuecomment-2712043349):
```
Metric                 Change
=============================
instructions            -8.1%
task-clock              -7.4%
simp                   -45.6%
instantiate metavars   -11.7%
share common exprs      -8.2%
```

[#lean4 > Enormous speedup from `dsimp` caching in
`simp`](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Enormous.20speedup.20from.20.60dsimp.60.20caching.20in.20.60simp.60)

---------

Co-authored-by: Kim Morrison <kim@tqft.net>
2025-05-14 22:21:06 +00:00
JovanGerb
f699e18212
perf: dsimp shouldn't visit proofs (#6973)
This PR stops `dsimp` from visiting proof terms, which should make
`simp` and `dsimp` more efficient.
In this attempt I have `dsimp` leave the proofs in place as-is, instead
of simplifying the proof type.

Closes #6960
2025-05-14 22:09:25 +00:00
jrr6
995fa4766b
fix: reduce ambiguity of "final" in application type mismatch message (#8322)
This PR refines the new wording of the "application type mismatch" error
message to avoid ambiguity in references to the "final" argument in a
subexpression that may be followed by additional arguments.

It does so by replacing "final" with "last," rephrasing the message so
that this adjective modifies the argument itself rather than the word
"argument," and only displaying this wording when two arguments could be
confused (determined by expression equality).

These changes were motivated by a report that in cases where a function
application `f a b c` fails to elaborate because `b` is incorrectly
typed, the existing error message's reference to `b` being the "final"
argument in the application `f a b` may create confusion because it is
not the final argument in the full application expression.
2025-05-14 16:12:10 +00:00
euprunin
88078930a9
chore: fix spelling mistakes (#8324)
Co-authored-by: euprunin <euprunin@users.noreply.github.com>
2025-05-14 06:52:16 +00:00
Leonardo de Moura
6ca31baa55
feat: structure extensionality in grind (#8330)
This PR improves support for structure extensionality in `grind`. It now
uses eta expansion for structures instead of the extensionality theorems
generated by `[ext]`. Examples:

```lean
opaque f (a : Nat) : Nat × Bool

attribute [grind ext] Prod Subtype

example (a b : Nat) : (f a).1 = (f b).1 → (f a).2 = (f b).2 → f a = f b := by
  grind

def g (a : Nat) : { x : Nat // x > 1 } :=
  ⟨a + 2, by grind⟩

example (a b : Nat) : (g a).1 = (g b).1 → g a = g b := by
  grind

@[grind ext] structure S where
  x : Nat
  y : Int

example (x y : S) : x.1 = y.1 → x.2 = y.2 → x = y := by
  grind
```
2025-05-14 02:43:52 +00:00
Joachim Breitner
e575736cae
feat: fun_induction to unfold function application in the goal (#8104)
This PR makes `fun_induction` and `fun_cases` (try to) unfold the
function application of interest in the goal. The old behavior can be
enabled with `set_option tactic.fun_induction.unfolding false`. For
`fun_cases` this does not work yet when the function’s result type
depends on one of the arguments, see issue #8296.
2025-05-13 09:37:39 +00:00
Leonardo de Moura
1aa16f1e3c
fix: missing foldProjs (#8303)
This PR fixes missing occurrences of `foldProjs` in `grind`.
2025-05-12 18:32:57 +00:00
Joachim Breitner
c55bf5172d
feat: unfolding induction theorems to unfold bif (#8301)
This PR unfolds functions in the unfolding induction principle properly
when they use `bif` (a.k.a. `Bool.cond`).
2025-05-12 16:00:30 +00:00
Leonardo de Moura
3f75f08e1d
feat: abstract metavars in grind preprocessor (#8299)
This PR implements a missing preprocessing step in `grind`: abstract
metavariables in the goal
2025-05-12 14:53:54 +00:00
Markus Himmel
eda467e066
fix: typo in application type mismatch error message (#8290)
This PR fixes a typo that was introduced recently.
2025-05-12 13:35:29 +00:00
Joachim Breitner
33aaabaed7
fix: FunInd: rewrite matches more reliably in .induct_unfolding (#8277)
This PR improves the generation of `.induct_unfolding` by rewriting
`match` statements more reliably, using the new “congruence equations”
introduced in #8284. Fixes #8195.
2025-05-11 15:26:28 +00:00
Joachim Breitner
dc1a70fa43
feat: congruence equations for matchers (#8284)
This PR adds a new variant of equations for matchers, namely “congruence
equations” that generalize the normal matcher equations. They have
unrestricted left-hand-sides, extra equality assumptions relating the
discriminiants with the patterns and thus prove heterogenous equalities.
In that sense they combine congruence with rewriting. They can be used
to rewrite matcher applications where, due to dependencies, `simp` would
fail to rewrite the discriminants, and will be used when producing the
unfolding induction theorems.
2025-05-11 13:04:59 +00:00
Joachim Breitner
ca73223d4c
fix: left-over free variables in splitter (#8285)
This PR fixes “declaration has free variables” errors when generating a
splitter for a match statement with named patterns. Fixes #8274.
2025-05-11 13:04:45 +00:00
Sebastian Ullrich
1f85fd2db8
fix: rfl theorem tracking in the module system (#8215)
We need to track rfl status in both the private and public scope once
defs may become irreducible in the latter.
2025-05-11 07:57:19 +00:00
Leonardo de Moura
e681855428
feat: improve procedure for proving auxiliary type casting equalities in grind (#8281)
This PR improves the module used to prove auxiliary type cast equalities
in `grind`.
2025-05-11 04:15:41 +00:00
Leonardo de Moura
9096eb168d
fix: arrow congruence in grind (#8280)
This PR the support for arrows in the congruence closure procedure used
in `grind`.
2025-05-11 03:18:18 +00:00
Leonardo de Moura
ddf5512c9a
feat: add support for implies_congr in grind (#8275)
This PR ensures the congruence closure in `grind` and find non-dependent
arrow congruences. That is, it can apply the `implies_congr` theorem.
2025-05-10 12:09:45 +00:00
Rob23oba
5df7770977
feat: consider universes and projections in addPPExplicitToExposeDiff (#8271)
This PR changes `addPPExplicitToExposeDiff` to show universe differences
and to visit into projections, e.g.:
```
error: tactic 'rfl' failed, the left-hand side
  (Test.mk (∀ (x : PUnit.{1}), True)).1
is not definitionally equal to the right-hand side
  (Test.mk (∀ (x : PUnit.{2}), True)).1
```
for
```lean
inductive Test where
  | mk (x : Prop)

example : (Test.mk (∀ _ : PUnit.{1}, True)).1 = (Test.mk (∀ _ : PUnit.{2}, True)).1 := by
  rfl
```
2025-05-09 15:07:50 +00:00
Kim Morrison
33afaa061e
feat: improve 'apply' unification error message (#8261)
This PR adjusts the error message when `apply` fails to unify. It is
clearer about distinguishing the term being applied and the goal, as
well as distinguishing the "conclusion" of the given term and the term
itself.

---------

Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
2025-05-08 16:00:42 +00:00
Markus Himmel
1db53b39c4
chore: improve application type mismatch error message (#8264)
This PR rewords the `application type mismatch` error message by more
specifically mentioning that the problem is with the final argument.
This is useful when the same argument is passed to the function multiple
times.

We decided against using a wording which specifically mentions the
"function expression", because users who are not used to currying might
not think of the `f a` in `f a b` as a function.
2025-05-08 15:34:40 +00:00
jrr6
836d7b703a
feat: add labeled subcomponents and helper functions for error messages (#8225)
This PR adds additional infrastructure for error message formatting.
Specifically, it adds convenience formatters for hints and notes,
including the ability to attach code actions to hint messages using a
"Try This"-like widget, along with several convenience formatters for
message data.

---------

Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
2025-05-07 21:15:27 +00:00
Joachim Breitner
edcad9a14b
chore: post-stage0 fixes for #8171 (#8250) 2025-05-06 17:10:45 +00:00
Joachim Breitner
898eec78cd
feat: FunInd: omit cases proved by contradiction (#8171)
This PR omits cases from functional induction/cases principles that are
implemented `by contradiction` (or, more generally, `False.elim`,
`absurd` or `noConfusion). Breaking change in the sense that there are
fewer goals to prove after using functional induction.

Fixes #8103.
2025-05-06 09:07:33 +00:00
Leonardo de Moura
ef603cf37d
fix: simplifyBasis (#8226)
This PR fixes the `simplifyBasis` procedure in the commutative ring
procedure in `grind`.
2025-05-05 02:35:52 +00:00
Leonardo de Moura
8cc4505bb1
feat: diagnostics for comm ring procedure in grind (#8224)
This PR adds diagnostic information for the commutative ring procedure
in `grind`.
2025-05-04 22:55:40 +00:00
Leonardo de Moura
14d647f219
fix: nondeterminism in grind (#8209)
This PR fixes a nondeterminism issue in the `grind` tactic. It was a bug
in the model-based theory combination module.
2025-05-02 20:01:38 +00:00
Leonardo de Moura
d26d7973ad
fix: theory propagation in grind (#8198)
This PR fixes an issue in the theory propagation used in `grind`. When
two equivalence classes are merged, the core may need to push additional
equalities or disequalities down to the satellite theory solvers (e.g.,
`cutsat`, `comm ring`, etc). Some solvers (e.g. `cutsat`) assume that
all of the core’s invariants hold before they receive those facts.
Propagating immediately therefore risks violating a solver’s
pre-conditions midway through the merge. To decouple the merge operation
from propagation and to keep the core solver-agnostic, this PR adds the
helper type `PendingTheoryPropagation`.
2025-05-02 02:19:56 +00:00
Leonardo de Moura
1143b4766c
chore: remove dead code (#8197) 2025-05-02 01:33:41 +00:00
Leonardo de Moura
af4c693030
feat: improve E-matching pattern inference in grind (#8196)
This PR improves the E-matching pattern inference procedure in `grind`.
Consider the following theorem:
```lean
@[grind →]
theorem eq_empty_of_append_eq_empty {xs ys : Array α} (h : xs ++ ys = #[]) : xs = #[] ∧ ys = #[] :=
  append_eq_empty_iff.mp h
```
Before this PR, `grind` inferred the following pattern:
```lean
@HAppend.hAppend _ _ _ _ #2 #1
```
Note that this pattern would match any `++` application, even if it had
nothing to do with arrays. With this PR, the inferred pattern becomes:
```lean
@HAppend.hAppend (Array #3) (Array _) (Array _) _ #2 #1
```
With the new pattern, the theorem will not be considered by `grind` for
goals that do not involve `Array`s.
2025-05-01 23:48:32 +00:00
Leonardo de Moura
ae5fe802ce
feat: stepwise proof terms for the commutative ring procedure in grind (#8189)
This PR implements **stepwise proof terms** in the commutative ring
procedure used by `grind`. These terms serve as an alternative
representation to the traditional Nullstellensatz certificates, aiming
to address the **exponential worst-case complexity** often associated
with certificate construction.

While various compression techniques for Nullstellensatz certificates
exist, they are not implemented in our procedure. Moreover, many of
these techniques rely on additional properties not available in
arbitrary commutative rings. In contrast, the stepwise proof terms
encode the **actual derivation** used during simplification, offering
significantly better scalability in practice.
Here is a motivating example:
```lean
example {α} [CommRing α] [IsCharP α 0] (d t c : α) (d_inv PSO3_inv : α)
  (Δ40 : d^2 * (d + t - d * t - 2) * (d + t + d * t) = 0)
  (Δ41 : -d^4 * (d + t - d * t - 2) *
         (2 * d + 2 * d * t - 4 * d * t^2 + 2 * d * t^4 + 2 * d^2 * t^4 - c * (d + t + d * t)) = 0)
  (_ : d * d_inv = 1)
  (_ : (d + t - d * t - 2) * PSO3_inv = 1) :
  t^2 = t + 1 := by grind +ring
```
In this case, the Nullstellensatz certificate generated by our procedure
contains **over 20,000 terms**, which overwhelms the Lean kernel during
verification. @kim-em also computed certificates using Mathematica with
various variable orderings, producing results between **500 and 2,000
terms**: still quite large.

By switching to stepwise derivations:
- `grind` completes the goal in **under 10 ms**
- The Lean kernel checks the resulting proof term in **under 1 second**

This change dramatically improves both the performance and robustness of
`grind` for nontrivial algebraic goals.
2025-04-30 18:45:29 +00:00
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
Joachim Breitner
d16862fd33
feat: induction: allow complex arguments to motive in conclusion of eliminator (#8096)
This PR lets `induction` accept eliminator where the motive application
in the conclusion has complex arguments; these are abstracted over using
`kabstract` if possible. This feature will go well with unfolding
induction principles (#8088).
2025-04-30 08:56:17 +00:00
Leonardo de Moura
a1989c2387
feat: infrastructure for creating stepwise proof terms in the commutative ring procedure in grind (#8170)
This PR adds the infrastructure for creating stepwise proof terms in the
commutative procedure used in `grind`.
2025-04-30 05:01:02 +00:00
Leonardo de Moura
0eb9671787
fix: proof term for Nullstellensatz certificate (#8168)
This PR fixes a bug when constructing the proof term for a
Nullstellensatz certificate produced by the new commutative ring
procedure in `grind`. The kernel was rejecting the proof term.
2025-04-30 01:03:57 +00:00
Leonardo de Moura
e0230d8377
perf: improve heuristics for commutative ring procedure in grind (#8167)
This PR improves the heuristics used to compute the basis and simplify
polynomials in the commutative procedure used in `grind`.
2025-04-29 22:35:36 +00:00
Kim Morrison
febf6c10f0
fix: update Grind.CommRing to avoid constructing non-defeq NatCast instance (#8161)
This PR changes `Lean.Grind.CommRing` to inline the `NatCast` instance
(i.e. to be provided by the user) rather than constructing one from the
existing data. Without this change we can't construct instances in
Mathlib that `grind` can use.
2025-04-29 16:50:54 +00:00
Joachim Breitner
3d1d8fc1de
feat: unfolding functional induction principles (#8088)
This PR adds the “unfolding” variant of the functional induction and
functional cases principles, under the name `foo.induct_unfolding` resp.
`foo.fun_cases_unfolding`. These theorems combine induction over the
structure of a recursive function with the unfolding of that function,
and should be more reliable, easier to use and more efficient than just
case-splitting and then rewriting with equational theorems.

For example  instead of
```
ackermann.induct
  (motive : Nat → Nat → Prop)
  (case1 : ∀ (m : Nat), motive 0 m)
  (case2 : ∀ (n : Nat), motive n 1 → motive (Nat.succ n) 0)
  (case3 : ∀ (n m : Nat), motive (n + 1) m → motive n (ackermann (n + 1) m) → motive (Nat.succ n) (Nat.succ m))
  (x x : Nat) : motive x x
```
one gets
```
ackermann.fun_cases_unfolding
  (motive : Nat → Nat → Nat → Prop)
  (case1 : ∀ (m : Nat), motive 0 m (m + 1))
  (case2 : ∀ (n : Nat), motive n.succ 0 (ackermann n 1))
  (case3 : ∀ (n m : Nat), motive n.succ m.succ (ackermann n (ackermann (n + 1) m)))
  (x✝ x✝¹ : Nat) : motive x✝ x✝¹ (ackermann x✝ x✝¹)
```
2025-04-29 16:43:06 +00:00
Leonardo de Moura
245ed056a3
fix: grind +splitImp, arrow propagator, missing normalization rule (#8158)
This PR fixes the `grind +splitImp` and the arrow propagator. Given `p :
Prop`, the propagator was incorrectly assuming `A` was always a
proposition in an arrow `A -> p`. This PR also adds a missing
normalization rule to `grind`.
2025-04-28 22:59:43 +00:00
Sebastian Ullrich
eb559d58a8
refactor: introduce VisibilityMap in Lean.Environment, use it to split base in preparation for private import (#8145) 2025-04-28 10:17:18 +00:00
Leonardo de Moura
2ba021ecc2
fix: equality propagation and simplification in the comm ring procedure (#8137)
This PR improves equality propagation (also known as theory combination)
and polynomial simplification for rings that do not implement the
`NoZeroNatDivisors` class. With these fixes, `grind` can now solve:
```lean
example [CommRing α] (a b c : α) (f : α → Nat)
  : a + b + c = 3 →
    a^2 + b^2 + c^2 = 5 →
    a^3 + b^3 + c^3 = 7 →
    f (a^4 + b^4) + f (9 - c^4) ≠ 1 := by
  grind +ring
```
This example uses the commutative ring procedure, the linear integer
arithmetic solver, and congruence closure.
For rings that implement `NoZeroNatDivisors`, a polynomial is now also
divided by the greatest common divisor (gcd) of its coefficients when it
is inserted into the basis.
2025-04-28 00:55:18 +00:00
Leonardo de Moura
b77e9edd44
feat: add checkInvariants to CommRing (#8135)
This PR implements the sanity check function `CommRing.checkInvariants`.
2025-04-27 21:43:10 +00:00
Leonardo de Moura
9a5d961c5e
fix: grind.debug true when using grind +ring (#8134)
This PR ensures that `set_option grind.debug true` works properly when
using `grind +ring`. It also adds the helper functions `mkPropEq` and
`mkExpectedPropHint`.
2025-04-27 20:28:08 +00:00
Leonardo de Moura
d73557321b
feat: add grind (ringSteps := <num>) (#8131)
This PR adds a configuration option that controls the maximum number of
steps the commutative-ring procedure in `grind` performs.
2025-04-27 17:46:02 +00:00
Leonardo de Moura
26138a5362
feat: equality propagation for comm ring procedure in grind (#8128)
This PR implements equality propagation in the new commutative ring
procedure in `grind`. The idea is to propagate implied equalities back
to the `grind` core module that does congruence closure. In the
following example, the equalities: `x^2*y = 1` and `x*y^2 - y = 0` imply
that `y*x` is equal to `y*x*y`, which implies by congruence that `f
(y*x) = f (y*x*y)`.
```lean
example [CommRing α] (x y : α) (f : α → Nat) : x^2*y = 1 → x*y^2 - y = 0 → f (y*x) = f (y*x*y) := by
  grind +ring
```
2025-04-27 15:05:56 +00:00
Leonardo de Moura
c3a1669398
feat: process comm ring module todo-queue in grind (#8126)
This PR implements the main loop of the new commutative ring procedure
in `grind`. In the main loop, for each polynomial `p` in the todo queue,
the procedure:
- Simplifies it using the current basis.
- Computes critical pairs with polynomials already in the basis and adds
them to the queue.

After the queue is empty, the disequalities are re-simplified using the
new basis. `grind` can now solve examples such as:
```lean
example [CommRing α] (x y : α) : x*y*x = 1 → x*y*y = y → y = 1 := by
  grind +ring

example [CommRing α] (x y : α) : x^2*y = 1 → x*y^2 = y → y*x = 1 := by
  grind +ring

example (x y : BitVec 16) : x^2*y = 1 → x*y^2 = y → y*x = 1 := by
  grind +ring
```
2025-04-27 01:04:45 +00:00
Leonardo de Moura
d64ae32965
feat: generate Nullstellensatz proof terms in grind (#8122)
This PR implements the generation of compact proof terms for
Nullstellensatz certificates in the new commutative ring procedure in
`grind`. Some examples:
```lean
example [CommRing α] (x y : α) : x = 1 → y = 2 → 2*x + y = 4 := by
  grind +ring

example [CommRing α] [IsCharP α 7] (x y : α) : 3*x = 1 → 3*y = 2 → x + y = 1 := by
  grind +ring

example [CommRing α] [NoZeroNatDivisors α] (x y : α) : 3*x = 1 → 3*y = 2 → x + y = 1 := by
  grind +ring

example (x y z : BitVec 8) : z = y → (x + 1)*(x - 1)*y + y = z*x^2 + 1 → False := by
  grind +ring
```
2025-04-26 22:52:00 +00:00
Sebastian Ullrich
87dccb9d1b
fix: restore what simp theorems are recorded as rfl (#8114)
#8090 accidentally affected `dsimp` applications even outside the module
system, restore previous extension data.
2025-04-26 16:09:20 +00:00