Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve scalar_eq_nf #303

Open
sonmarcho opened this issue Aug 20, 2024 · 0 comments
Open

Improve scalar_eq_nf #303

sonmarcho opened this issue Aug 20, 2024 · 0 comments

Comments

@sonmarcho
Copy link
Member

sonmarcho commented Aug 20, 2024

We today have the scalar_eq_nf tactic to reason about some non-linear arithmetic goals, typically of the shape:

c_0 * a_0 ^ n_0 ... + c_n * a_n ^ n_n = ...

(see the proofs about the big num functions in the tutorial)

Issue 1: properly normalize equalities

Under the hood, scalar_eq_nf calls ring_nf, the tactic to normalize semiring expressions, but it does slightly more because of the following problem. If we have an equality whose both sides are simplified to the same expression thanks to ring_nf, then ring_nf simplifies the equality to true. However, if they are not equal, ring_nf simply normalizes the two sides. For instance, if the goal is:

a + a + 3 * b + c + d = a + 2 * b + 2 * c + d

then ring_nf simplifies it to:

2 * a + 3 * b + c + d = a + 2 * b + 2 * c + d

What we would rather have (especially for big expressions) is (we count the coefficients on each side and eliminate terms whenever possible):

a + b = c

For this reason, scalar_eq_nf first applies the rewriting: a = b <-> a - b = 0 so that we actually get:

a + b - c = 0

This is far better than the default behavior of ring_nf but still not exactly what we want, and can be confusing at times.

Issue 2: boost the simplification

Because scalar_eq_nf (and also scalar_nf) simply call ring_nf they inherit its limitations, meaning it can not simplify expressions which often appear and that the user expects to get simplified.
For instance, if we write (where n is a natural number): 2 ^ n = 2 * 2 ^ (n - 1) then it will not simplify.
As a result, we have to do this kind of manipulations:

have : 2 ^ (i * 32) = (2 ^ ((i - 1) * 32) * 4294967296 : Int) := by

Doing this is not completely trivial, because we have to prove that n = (n - 1) + 1 typically by using scalar_tac (note that this equality is not true if n = 0, because then n - 1 = 0 - we are working with natural numbers), then do exactly the rewriting we want (on the 2 ^ n expression, but not the other ones). Also, identifying for which n we need to do that is not trivial (let's say the goal is: 2 ^ n + 4 ^ m = 2 * 2 ^ (n - 1) + 8 ^ (k - 1), we should do something with n but not with k - we'll have to prove that 4 ^ m = 8 ^(k - 1) by other means). But I believe this kind of issues will be recurrent enough to be worth investigating.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant