This PR implements basic model-based theory combination in `grind`.
`grind` can now solve examples such as
```lean
example (f : Int → Int) (x : Int)
: 0 ≤ x → x ≠ 0 → x ≤ 1 → f x = 2 → f 1 = 2 := by
grind
```
This PR improves the counterexamples produced by the cutsat procedure,
and adds proper support for `Nat`. Before this PR, the assignment for an
natural variable `x` would be represented as `NatCast.natCast x`.
This PR fixes the support for nonlinear `Nat` terms in cutsat. For
example, cutsat was failing in the following example
```lean
example (i j k l : Nat) : i / j + k + l - k = i / j + l := by grind
```
because we were not adding the fact that `i / j` is non negative when we
inject the `Nat` expression into `Int`.
This PR ensures that we use the same ordering to normalize linear `Int`
terms and relations. This change affects `simp +arith` and `grind`
normalizer.
This consistency is important in the cutsat procedure. We want to avoid
a situation where the cutsat state contains both "atoms":
- `「(NatCast.natCast x + NatCast.natCast y) % 8」`
- `「(NatCast.natCast y + NatCast.natCast x) % 8」`
This was happening because we were using different orderings for
(nested) terms and relations (`=`, `<=`).
This PR fixes the procedure for putting new facts into the `grind`
"to-do" list. It ensures the new facts are preprocessed. This PR also
removes some of the clutter in the `Nat.sub` support.
This PR ensures that `grind` can be used as a more powerful
`contradiction` tactic, sparing the user from having to type `exfalso;
grind` or `intros; exfalso; grind`.
This PR prefers using `∅` instead of `.empty` functions. We may later
rename `.empty` functions to avoid the naming clash with
`EmptyCollection`, and to better express semantics of functions which
take an optional capacity argument.
This PR allows the use of `dsimp` during preprocessing of well-founded
definitions. This fixes regressions when using `if-then-else` without
giving a name to the condition, but where the condition is needed for
the termination proof, in cases where that subexpression is reachable
only by dsimp, but not by simp (e.g. inside a dependent let)
Also fixes some preprocessing lemmas to not be bad simp lemmas (with
lambdas on the LHS, due to dot notation and unfortunate argument order)
This fixes#7408.
This PR makes the docstrings in the `Char` namespace follow the
documentation conventions.
---------
Co-authored-by: Markus Himmel <markus@himmel-villmar.de>
This PR fixes an issue in the `grind` tactic when case splitting on
if-then-else expressions.
It adds a new marker gadget that prevents `grind` for re-normalizing the
condition `c` of an if-then-else
expression. Without this marker, the negated condition `¬c` might be
rewritten into
an alternative form `c'`, which `grind` may not recognize as equivalent
to `¬c`.
As a result, `grind` could fail to propagate that `if c then a else b`
simplifies to `b`
in the `¬c` branch.
This PR implements the last missing case for the cutsat procedure and
fixes a bug. During model construction, we may encounter a bounded
interval containing integer solutions that satisfy the divisibility
constraint but fail to satisfy known disequalities.
This PR ensures cutsat does not have to perform case analysis in the
univariate polynomial case. That it, it can close a goal whenever there
is no solution for a divisibility constraint in an interval. Example of
theorem that is now proved in a single step by cutsat:
```lean
example (x : Int) : 100 ≤ x → x ≤ 10000 → 20000 ∣ 3*x → False := by
grind
```
This PR implements cooper conflict resolution in the cutsat procedure.
It also fixes several bugs in the proof term construction. We still need
to add more tests, but we can already solve the following example that
`omega` fails to solve:
```lean
example (x y : Int) :
27 ≤ 11*x + 13*y →
11*x + 13*y ≤ 45 →
-10 ≤ 7*x - 9*y →
7*x - 9*y ≤ 4 → False := by
grind
```
This PR extends the notion of “fixed parameter” of a recursive function
also to parameters that come after varying function. The main benefit is
that we get nicer induction principles.
Before the definition
```lean
def app (as : List α) (bs : List α) : List α :=
match as with
| [] => bs
| a::as => a :: app as bs
```
produced
```lean
app.induct.{u_1} {α : Type u_1} (motive : List α → List α → Prop) (case1 : ∀ (bs : List α), motive [] bs)
(case2 : ∀ (bs : List α) (a : α) (as : List α), motive as bs → motive (a :: as) bs) (as bs : List α) : motive as bs
```
and now you get
```lean
app.induct.{u_1} {α : Type u_1} (motive : List α → Prop) (case1 : motive [])
(case2 : ∀ (a : α) (as : List α), motive as → motive (a :: as)) (as : List α) : motive as
```
because `bs` is fixed throughout the recursion (and can completely be
dropped from the principle).
This is a breaking change when such an induction principle is used
explicitly. Using `fun_induction` makes proof tactics robust against
this change.
The rules for when a parameter is fixed are now:
1. A parameter is fixed if it is reducibly defq to the the corresponding
argument in each recursive call, so we have to look at each such call.
2. With mutual recursion, it is not clear a-priori which arguments of
another function correspond to the parameter. This requires an analysis
with some graph algorithms to determine.
3. A parameter can only be fixed if all parameters occurring in its type
are fixed as well.
This dependency graph on parameters can be different for the different
functions in a recursive group, even leading to cycles.
4. For structural recursion, we kinda want to know the fixed parameters
before investigating which argument to actually recurs on. But once we
have that we may find that we fixed an index of the recursive
parameter’s type, and these cannot be fixed. So we have to un-fix them
5. … and all other fixed parameters that have dependencies on them.
Lean tries to identify the largest set of parameters that satisfies
these criteria.
Note that in a definition like
```lean
def app : List α → List α → List α
| [], bs => bs
| a::as, bs => a :: app as bs
```
the `bs` is not considered fixes, as it goes through the matcher
machinery.
Fixes#7027Fixes#2113