This PR implements model-based theory combination for types `A` which
implement the `ToInt` interface. Examples:
```lean
example {C : Type} (h : Fin 4 → C) (x : Fin 4)
: 3 ≤ x → x ≤ 3 → h x = h (-1) := by
grind
example {C : Type} (h : UInt8 → C) (x y z w : UInt8)
: y + 1 + w ≤ x + w → x + w ≤ z → z ≤ y + w + 1 → h (x + w) = h (y + w + 1) := by
grind
example {C : Type} (h : Fin 8 → C) (x y w r : Fin 8)
: y + 1 + w ≤ r → r ≤ y + w + x → x = 1 → h r = h (y + w + 1) := by
grind
```
This PR removes `grind →` annotations that fire too often, unhelpfully.
It would be nice for `grind` to instantiate these lemmas, but only if
they already see `xs ++ ys` and `#[]` in the same equivalence class, not
just as soon as it sees `xs ++ ys`.
In the meantime, let's see what is using these.
This PR introduces limited functionality frontends `cutsat` and
`grobner` for `grind`. We disable theorem instantiation (and case
splitting for `grobner`), and turn off all other solvers. Both still
allow `grind` configuration options, so for example one can use `cutsat
+ring` (or `grobner +cutsat`) to solve problems that require both.
For `cutsat`, it is helpful to instantiate a limited set of theorems
(e.g. `Nat.max_def`). Currently this isn't supported, but we intend to
add this later.
This PR fixes the `grind` canonicalizer for `OfNat.ofNat` applications.
Example:
```lean
example {C : Type} (h : Fin 2 → C) :
-- `0` in the first `OfNat.ofNat` is not a raw literal
h (@OfNat.ofNat (Fin (1 + 1)) 0 Fin.instOfNat) = h 0 := by
grind
```
This PR changes the string interpolation procedure to omit redundant
empty parts. For example `s!"{1}{2}"` previously elaborated to `toString
"" ++ toString 1 ++ toString "" ++ toString 2 ++ toString ""` and now
elaborates to `toString 1 ++ toString 2`.
This PR adds missing `grind` normalization rules for `natCast` and
`intCast` Examples:
```
open Lean.Grind
variable (R : Type) (a b : R)
section CommSemiring
variable [CommSemiring R]
example (m n : Nat) : (m + n) • a = m • a + n • a := by grind
example (m n : Nat) : (m * n) • a = m • (n • a) := by grind
end CommSemiring
section CommRing
variable [CommRing R]
example (m n : Nat) : (m + n) • a = m • a + n • a := by grind
example (m n : Nat) : (m * n) • a = m • (n • a) := by grind
example (m n : Int) : (m * n) • (a * b) = (m • a) * (n • b) := by grind
end CommRing
```
This PR makes `IO.RealWorld` opaque. It also adds a new compiler -only
`lcRealWorld` constant to represent this type within the compiler. By
default, an opaque type definition is treated like `lcAny`, whereas we
want a more efficient representation. At the moment, this isn't a big
difference, but in the future we would like to completely erase
`IO.RealWorld` at runtime.
This PR changes the implementation of a function `unfoldPredRel` used in
(co)inductive predicate machinery, that unfolds pointwise order on
predicates to quantifications and implications. Previous implementation
relied on `withDeclsDND` that could not deal with types which depend on
each other. This caused the following example to fail:
```lean4
inductive infSeq_functor1.{u} {α : Type u} (r : α → α → Prop) (call : {α : Type u} → (r : α → α → Prop) → α → Prop) : α → Prop where
| step : r a b → infSeq_functor1 r call b → infSeq_functor1 r call a
def infSeq1 (r : α → α → Prop) : α → Prop := infSeq_functor1 r (infSeq1)
coinductive_fixpoint monotonicity by sorry
#check infSeq1.coinduct
```
Closes#10234.
This test involves re-running the compiler on decls that have already
been compiled, which can cause all sorts of issues. I just hit these
issues on a PR, so it's time to retire this test like others that hit
the same issues.
The proof of the instWPMonad instance relies on the equality of any two
terms of type `IO.RealWorld`, which is only a side effect of the current
transparent definition. Ignoring the questions around the utility of
proving things about programs in `IO`, the semantic validity of this
instance in the intended model of the IO monad is also unclear.
I tried a few things to axiomatize this instance so it could be put into
the test file to preserve the one test section that relies on it, but I
was unsuccessful; everything I attempted caused errors.
This PR moves `String.utf8EncodeChar` to the prelude to prepare for the
imminent redefinition of `String`.
The definition in the prelude uses modulo and division operations on
natural numbers. In `String.Extra`, a `csimp` lemma is provided, showing
that the new definition is equal to the previous one (which is now
called `utf8EncodeCharFast`) which uses bitwise operations on `UInt8`.
This PR implements diagnostic information for the `grind ac` module. It
now displays the basis, normalized disequalities, and additional
properties detected for each associative operator.
This PR improves the counterexamples produced by `grind linarith` for
`NatModule`s. `grind` now hides occurrences of the auxiliary function
`Grind.IntModule.OfNatModule.toQ`.
This PR implements `NatModule` normalization when the `AddRightCancel`
instance is not available. Note that in this case, the embedding into
`IntModule` is not injective. Therefore, we use a custom normalizer,
similar to the `CommSemiring` normalizer used in the `grind ring`
module. Example:
```lean
open Lean Grind
example [NatModule α] (a b c : α)
: 2•a + 2•(b + 2•c) + 3•a = 4•a + c + 2•b + 3•c + a := by
grind
```
This PR changes the implementation of the linear `DecidableEq`
implementation to use `match decEq` rather than `if h : ` to compare the
constructor tags. Otherwise, the “smart unfolding” machinery will not
let `rfl` decide that different constructors are different.
This PR adds support for `NatModule` equalities and inequalities in
`grind linarith`. Examples:
```lean
open Lean Grind Std
example [NatModule α] [LE α] [LT α]
[LawfulOrderLT α] [IsLinearOrder α] [OrderedAdd α]
(x y : α) : x ≤ y → 2 • x + y ≤ 3 • y := by
grind
example [NatModule α] [AddRightCancel α] [LE α] [LT α]
[LawfulOrderLT α] [IsLinearOrder α] [OrderedAdd α]
(a b c d : α) : a ≤ b → a ≥ c + d → d ≤ 0 → d ≥ 0 → b = c → a = b := by
grind
```
This PR changes the naming of the internal functions in deriving
instances like BEq to use accessible names. This is necessary to
reasonably easily prove things about these functions. For example after
`deriving BEq` for a type `T`, the implementation of `instBEqT` is in
`instBEqT.beq`.
This PR adds a new option `maxErrors` that limits the number of errors
printed from a single `lean` run, defaulting to 100. Processing is
aborted when the limit is reached, but this is tracked only on a
per-command level.
Smaller values can be useful when making changes that break a lot of
files and would otherwise scroll the actual root failures out of the
terminal view.
This PR implements the infrastructure for supporting `NatModule` in
`grind linarith` and uses it to handle disequalities. Another PR will
add support for equalities and inequalities. Example:
```lean
open Lean Grind
variable (M : Type) [NatModule M] [AddRightCancel M]
example (x y : M) : 2 • x + 3 • y + x = 3 • (x + y) := by
grind
```
This PR fixes a panic in `grind ring` exposed by #10242. `grind ring`
should not assume that all normalizations have been applied, because
some subterms cannot be rewritten by `simp` due to typing constraints.
Moreover, `grind` uses `preprocessLight` in a few places, and it skips
the simplifier/normalizer.
Closes#10242
This PR fixes a bug in the `LinearOrderPackage.ofOrd` factory. If there
is a `LawfulEqOrd` instance available, it should automatically use it
instead of requiring the user to provide the `eq_of_compare` argument to
the factory. The PR also solves a hygiene-related problem making the
factories fail when `Std` is not open.
This PR adds some test cases for `grind` working with `Fin`. There are
many still failing tests in `tests/lean/grind/grind_fin.lean` which I'm
intending to triage and work on.
This PR fixes the E-matching procedure for theorems that contain
universe parameters not referenced by any regular parameter. This kind
of theorem seldom happens in practice, but we do have instances in the
standard library. Example:
```
@[simp, grind =] theorem Std.Do.SPred.down_pure {φ : Prop} : (⌜φ⌝ : SPred []).down = φ := rfl
```
closes#10233
This PR fixes a missing case in the `grind` canonicalizer. Some types
may include terms or propositions that are internalized later in the
`grind` state.
closes#10232
This PR adds `MonoBind` for more monad transformers. This allows using
`partial_fixpoint` for more complicated monads based on `Option` and
`EIO`. Example:
```lean-4
abbrev M := ReaderT String (StateT String.Pos Option)
def parseAll (x : M α) : M (List α) := do
if (← read).atEnd (← get) then
return []
let val ← x
let list ← parseAll x
return val :: list
partial_fixpoint
```
This PR introduces an alternative construction for `DecidableEq`
instances that avoids the quadratic overhead of the default
construction.
The usual construction uses a `match` statement that looks at each pair
of constructors, and thus is necessarily quadratic in size. For
inductive data type with dozens of constructors or more, this quickly
becomes slow to process.
The new construction first compares the constructor tags (using the
`.ctorIdx` introduced in #9951), and handles the case of a differing
constructor tag quickly. If the constructor tags match, it uses the
per-constructor-eliminators (#9952) to create a linear-size instance. It
does so by creating a custom “matcher” for a parallel match on the data
types and the `h : x1.ctorIdx = x2.ctorIdx` assumption; this behaves
(and delaborates) like a normal `match` statement, but is implemented in
a bespoke way. This same-constructor-matcher will be useful for
implementing other instances as well.
The new construction produces less efficient code at the moment, so we
use it only for inductive types with 10 or more constructors by default.
The option `deriving.decEq.linear_construction_threshold` can be used to
adjust the threshold; set it to 0 to always use the new construction.
This PR implements equality propagation from the new AC module into the
`grind` core. Examples:
```lean
example {α β : Sort u} (f : α → β) (op : α → α → α) [Std.Associative op] [Std.Commutative op]
(a b c d : α) : op a (op b b) = op d c → f (op (op b a) (op b c)) = f (op c (op d c)) := by
grind only
example (a b c : Nat) : min a (max b (max c 0)) = min (max c b) a := by
grind -cutsat only
example {α β : Sort u} (bar : α → β) (op : α → α → α) [Std.Associative op] [Std.IdempotentOp op]
(a b c d e f x y w : α) :
op d (op x c) = op a b →
op e (op f (op y w)) = op (op d a) (op b c) →
bar (op d (op x c)) = bar (op e (op f (op y w))) := by
grind only
```
This PR adds the extra critical pairs to ensure the `grind ac` procedure
is complete when the operator is associative and idempotent, but not
commutative. Example:
```lean
example {α : Sort u} (op : α → α → α) [Std.Associative op] [Std.IdempotentOp op] (a b c d e f x y w : α)
: op d (op x c) = op a b →
op e (op f (op y w)) = op a (op b c) →
op d (op x c) = op e (op f (op y w)) := by
grind only
example {α : Sort u} (op : α → α → α) [Std.Associative op] [Std.IdempotentOp op] (a b c d e f x y w : α)
: op a (op d x) = op b c →
op e (op f (op y w)) = op a (op b c) →
op a (op d x) = op e (op f (op y w)) := by
grind only
```
This PR adds the extra critical pairs to ensure the `grind ac` procedure
is complete when the operator is AC and idempotent. Example:
```lean
example {α : Sort u} (op : α → α → α) [Std.Associative op] [Std.Commutative op] [Std.IdempotentOp op]
(a b c d : α) : op a (op b b) = op d c → op (op b a) (op b c) = op c (op d c) := by
grind only
```
This PR adds superposition for associative (but non-commutative)
operators in `grind ac`. Examples:
```lean
example {α} (op : α → α → α) [Std.Associative op] (a b c d : α)
: op a b = c →
op b a = d →
op (op c a) (op b c) = op (op a d) (op d b) := by
grind
example {α} (a b c d : List α)
: a ++ b = c →
b ++ a = d →
c ++ a ++ b ++ c = a ++ d ++ d ++ b := by
grind only
```
This PR adds superposition for associative and commutative operators in
`grind ac`. Examples:
```lean
example (a b c d e f g h : Nat) :
max a b = max c d → max b e = max d f → max b g = max d h →
max (max f d) (max c g) = max (max e (max d (max b (max c e)))) h := by
grind -cutsat only
example {α} (op : α → α → α) [Std.Associative op] [Std.Commutative op] (a b c d : α)
: op a b = op b c → op c c = op d c →
op (op d a) (op b d) = op (op a a) (op b d) := by
grind only
```
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#1672Closes#10004
This PR implements the proof terms for the new `grind ac` module.
Examples:
```lean
example {α : Sort u} (op : α → α → α) [Std.Associative op] (a b c d : α)
: op a (op b b) = op c d → op c (op d c) = op (op a b) (op b c) := by
grind only
example {α : Sort u} (op : α → α → α) [Std.Associative op] [Std.Commutative op] (a b c d : α)
: op a (op b b) = op d c → op (op b a) (op b c) = op c (op d c) := by
grind only
example {α : Sort u} (op : α → α → α) [Std.Associative op] [Std.Commutative op]
(one : α) [Std.LawfulIdentity op one] (a b c d : α)
: op a (op (op b one) b) = op d c → op (op b a) (op (op b one) c) = op (op c one) (op d c) := by
grind only
```
The `grind ac` module is not complete yet, we still need to implement
critical pair computation and fix the support for idempotent operators.
This PR fixes `grind` instance normalization procedure.
Some modules in grind use builtin instances defined directly in core
(e.g., `cutsat`), while others synthesize them using `synthInstance`
(e.g., `ring`). This inconsistency is problematic, as it may introduce
mismatches and result in two different representations for the same
term. This PR fixes the issue.
This PR modifies macros, which implement non-atomic definitions and
```$cmd1 in $cmd2``` syntax. These macros involve implicit scopes,
introduced through ```section``` and ```namespace``` commands. Since
sections or namespaces are designed to delimit local attributes, this
has led to unintuitive behaviour when applying local attributes to
definitions appearing in the above-mentioned contexts. This has been
causing the following examples to fail:
```lean4
axiom A : Prop
namespace ex1
open Nat in
@[local simp] axiom a : A ↔ True
example : A := by simp
end ex1
namespace ex2
@[local simp] axiom Foo.a : A ↔ True
example : A := by simp
end ex2
```
This PR adds an internal-only piece of syntax,
```InternalSyntax.end_local_scope```, that influences the
```ScopedEnvExtension.addLocalEntry``` used in implementing local
attributes, to avoid delimiting local entries in the current scope. This
command is used in the above-mentioned macros.
Closes [#9445](https://github.com/leanprover/lean4/issues/9445).
---------
Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
This PR changes the construction of a `CompleteLattice` instance on
predicates (maps intro `Prop`) inside of
`coinductive_fixpoint`/`inductive_fixpoint` machinery.
Consider a following endomap on predicates of the type ` α → Prop`:
```lean4
def DefFunctor (r : α → α → Prop) (infSeq : α → Prop) : α → Prop :=
λ x : α => ∃ y, r x y ∧ infSeq y
```
The following eta-reduced expression failed to elaborate:
```lean4
def def1 (r : α → α → Prop) : α → Prop := DefFunctor r (def1 r)
coinductive_fixpoint monotonicity sorry
```
At the same time, eta-expanded variant would elaborate correctly:
```lean4
def def2 (r : α → α → Prop) : α → Prop := fun x => DefFunctor r (def2 r) x
coinductive_fixpoint monotonicity sorry
```
This PR fixes the above issue, by changing the way how `CompleteLattice`
instance on the space of predicates is constructed, to allow for the
eta-reduced case, as outlined above.
This PR reviews the expected-to-fail-right-now tests for `grind`, moving
some (now passing) tests to the main test suite, updating some tests,
and adding some tests about normalisation of exponents.