This PR adjusts the experimental module system to not export the bodies
of `def`s unless opted out by the new attribute `@[expose]` on the `def`
or on a surrounding `section`.
---------
Co-authored-by: Markus Himmel <markus@lean-fro.org>
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.
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
```
This PR adds the instances `Grind.CommRing (Fin n)` and `Grind.IsCharP
(Fin n) n`. New tests:
```lean
example (x y z : Fin 13) :
(x + y + z) ^ 2 = x ^ 2 + y ^ 2 + z ^ 2 + 2 * (x * y + y * z + z * x) := by
grind +ring
example (x y : Fin 17) : (x + y) ^ 3 = x ^ 3 + y ^ 3 + 3 * x * y * (x + y) := by
grind +ring
example (x y : Fin 19) : (x - y) * (x ^ 2 + x * y + y ^ 2) = x ^ 3 - y ^ 3 := by
grind +ring
```
---------
Co-authored-by: Kim Morrison <kim@tqft.net>
This PR adds lemmas about the length and use of `[]?` on results of
`List.intersperse`.
This was suggested by @TwoFX as discussed in
https://github.com/TwoFX/human-eval-lean/pull/164#discussion_r2074101914.
I am unsure about the correct naming of `intersperse_getElem?_even` and
`intersperse_getElem?_odd`.
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.
This PR shows that negating a bitvector created from a natural number
equals creating a bitvector from the the negative of that number (as an
integer).
```lean
theorem neg_ofNat_eq_ofInt_neg {w : Nat} (x : Nat) :
- BitVec.ofNat w x = BitVec.ofInt w (- x) := by
apply BitVec.eq_of_toInt_eq
simp [BitVec.toInt_neg, BitVec.toInt_ofNat]
```
---------
Co-authored-by: Luisa Cicolini <48860705+luisacicolini@users.noreply.github.com>
This PR makes `#guard_msgs` to treat `trace` messages separate from
`info`, `warning` and `error`. It also introduce the ability to say
`#guard_msgs (pass info`, like `(drop info)` so far, and also adds
`(check info)` as the explicit form of `(info)`, for completeness.
Fixes#8266
This PR fixes unintended inlining of `ToJson`, `FromJson`, and `Repr`
instances, which was causing exponential compilation times in `deriving`
clauses for large structures.
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.
This PR adds unconditional lemmas for
`HashMap.getElem?_insertMany_list`, alongside the existing ones that
have quite strong preconditions. Also for TreeMap (and
dependent/extensional variants).
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.
This PR adds simp/grind lemmas about `List`/`Array`/`Vector.contains`.
In the presence of `LawfulBEq` these effectively already held, via
simplifying `contains` to `mem`, but now these also fire without
`LawfulBEq`.
This PR adds simprocs to simplify appends of non-overlapping Bitvector
adds. We add a simproc instead of just a `simp` lemma to ensure that we
correctly rewrite bitvector appends. Since bitvector appends lead to
computation at the bitvector width level, it seems to be more stable to
write a simproc.
As I write this, I realize that I can maybe write the `simp` lemma using
`no_index` to recover the same behaviour, so I'll try that too.
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.
This PR is a follow up to #8055 and implements a Selector for
`Std.Channel` in order to allow
multiplexing using channels.
There is one subtlety to the implementation: Suppose we are in a
situation where we run `select` in a loop on two channels. One of the
channels is always quiet while the other has data available occasionally
(however not always as this would trigger the `tryFn` fast path and hide
the issue). In this situation the select receivers that are enqueued on
the silent channel would usually just remain there indefinitely as
nothing ever happens, causing a memleak. To avoid this we want to make a
channel select clean up after itself, even if it fails.
In an imperative programming language we could implement the receive
queue as a doubly linked list and simply make each receive select
maintain a pointer to its element in the queue and then remove itself in
`O(1)` upon failure. As that is not possible in Lean trivially we
decided to go for another approach for now: simply filter the queue for
selects that have failed in `unregisterFn`. While this approach is
`O(n)` we expect the amount of receivers enqueued on a channel to not be
terribly large and thus this to be a reasonably fast operation compared
to the remaining overhead. If it ever ends up becoming an issue, we
could switch to an approach that uses a `TreeMap` with numbered
receivers instead at a certain wait queue size and go to `O(log(n))`.
This PR fixes a mistake in documented time complexity of List.merge.
The running time would only be `O(min |l| |r|)` in the very specific
best case where all the elements in the shorter list are less than all
the elements in the longer list. The worst-case (and average-case) time
complexity is `O(|l| + |r|)`.
Also update the variables in the time complexity to match the names of
the parameters.
This PR adds optimized division functions for `Int` and `Nat` when the
arguments are known to be divisible (such as when normalizing
rationals). These are backed by the gmp functions `mpz_divexact` and
`mpz_divexact_ui`. See also leanprover-community/batteries#1202.
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`.
This PR changes the predicate for `Option.guard` to be `p : α → Bool`
instead of `p : α → Prop`. This brings it in line with other comparable
functions like `Option.filter`.
This PR adds an initial set of `@[grind]` annotations for
`List`/`Array`/`Vector`, enough to set up some regression tests using
`grind` in proofs about `List`. More annotations to follow.
This PR generalises `List.eraseDups` to allow for an arbitrary
comparison relation. Further, it proves `eraseDups_append : (as ++
bs).eraseDups = as.eraseDups ++ (bs.removeAll as).eraseDups`.
This PR adds `List.findRev?` and `List.findSomeRev?`, for parity with
the existing Array API, and simp lemmas converting these into existing
operations.