We now define nat.le using (nat.ble : nat -> nat -> bool) function.
We will add builtin support for reducing `nat.ble` efficiently when the arguments are the to be added nat literals.
In Lean4, we will not generate non dependent recursors for inductive
predicates. The main goal is to make the shape of the automatically
generated recursors more uniform. The non uniform representation is
leftover from Lean2. In Lean2, we wanted to support different kernels
with different features. For example: we could create proof relevant
kernels, no impredicative universe, etc.
Recall that, in a kernel with an impredicative Prop and no proof
irrelevance, inductive predicates without dependent elimination are
weaker that inductive predicates with dependent elimination.
When proof irrelevance is enabled, we can generate the dependent
recursor from the non dependent one. Actually, the module drec.cpp
generates the dependent recursor.
Now, we only support one kind of kernel, and it doesn't make sense
anymore to generate non dependent recursors for inductive predicates.
This would only produce an unnecessary asymmetry on the inductive
datatype module.
Remark: we had to create non dependent recursors to help the elaborator.
This can be avoid if we improve the elaborator. I will do that in the
new elaborator implemented in Lean.
Remark: equation lemmas are broken for definitions that pattern match on
nested inductive datatypes. The problem is the super messy
`prove_eq_rec_invertible_aux` function. This function will not be needed
after I finish the new inductive datatype support in the kernel.
cc @kha
Most efficient hash functions use uint32/uint64 and produce values
that do not fit in out small nat representation. Thus, GMP big numbers
would have to be created.
Before this commit, given `x n : nat` the expression
```
to_bool (n <= x)
```
where `n` is a numeral <= 1024 was being elaborated as
```
@decidable.to_bool (@has_le.le.{0} nat nat.has_le n x) (nat.decidable_lt n' x)
```
where `n'` denotes the numeral `n-1`
Example:
```
to_bool (800 <= x)
```
was elaborated as
```
@decidable.to_bool (@has_le.le.{0} nat nat.has_le 800 x) (nat.decidable_lt 799 x)
```
Reason: `nat.lt` and `nat.le` were reducible. The module `type_context`
has support for solving "offset constraints" for small numerals.
These constraints include:
- `succ ?x =?= n` ===> `?x := n - 1`
For elaborating `to_bool (800 <= x)`, we need to synthesize
```
decidable (@has_le.le.{0} nat nat.has_le 800 x)
```
using type class resolution.
The instance `nat.decidable_lt` is tried before `nat.decidable_le`. For
this instance, we need to solve the unification problem.
```
decidable (@has_lt.lt.{0} nat nat.has_lt ?n ?x) =?= decidable (@has_le.le.{0} nat nat.has_le 800 x)
```
which reduces to:
```
nat.less_than_or_equal (succ ?n) ?x =?= nat.less_than_or_equal 800 x
```
because `nat.le` and `nat.lt` are marked as `[reducible]`.
This constraint reduces to
```
succ ?n =?= 800
```
which is solved using the offset constraint support as
```
?n := 799
```
The kernel does not have support for offset constraints, and may take
a considerable amount of time to check that `succ 799` is definitionally
equal to `800`. This is particularly expensive when trust level 0 is
used.
It was taking almost 1 minute to execute the leanchecker test before
this commit because we add the new predicates for checking which
characters can be used in a Lean identifier.
This commit fixes the problem by removing the annotation `[reducible]`
from `nat.lt` and `nat.le`. This performance issue may be triggered
by any reducible instance that may create offset constraints during
type class resolution.
cc @kha
We use the same approach used to define rbtree:
1- Structure with minimal number of invariants, AND
2- well_formed inductive predicate
We can use the well_formed predicate to prove auxiliary invariants later.
Example: the keys stored in every bucket have the correct hash code.
This implementation does not depend on the tactic framework,
and it is not a mess like the one in mathlib.
All theorems are proved without using the tactic framework.
Thus, we can define `fin/uint32/uint64` types and their operations
before we define the tactic framework.
With the current elaboration scheme, out_params and coercions do not mix well,
as evidenced by the following example by @digama:
```
variables {α : Type*} [group α]
def gpow : α → ℤ → α := sorry
instance group.has_pow : has_pow α ℤ := ⟨gpow⟩
example (a : α) : a ^ 0 = 1 := sorry -- failed to synth ⊢ has_pow α ℕ
example (a : α) : a ^ (0:ℕ) = 1 := sorry -- ok, coerces
example (a : α) : a ^ (0:ℤ) = 1 := sorry -- ok
```
The issue is that
* we first try to solve `has_pow ?α ?β`, which is postponed
* then infer `?α = nat` from `a`
* then at some point call `elaborator::synthesize()` and default `β` to `nat`
* then try to solve `has_pow nat nat`, which fails at `int =?= nat`
for ordered_cancel_comm_monoid. The change to partial_order, with a derived lt relation, makes the lt axioms of ordered groups derivable with no additional assumptions.
To make the equation compiler more convenient to use, we will add a
couple of preprocessing steps.
This commit adds the first one of them. In this step, we use
type inference to refine pattern variables, and we relax the
restrictions on inaccessible annotations.
We will also add a preprocessing step that implements the "complete
transition" step before we execute the elim_match step.
@digama0 I moved bitvec back to the main repo, and many nat lemmas.
I want these lemmas here for now. I will need some of them for future
decision procedures.