Zulip Chat Archive

Stream: general

Topic: nlinarith: if at first you don't succeed...


Eric Wieser (Nov 14 2022 at 23:59):

There are no unicode tricks here, the examples contain exactly the same text

import tactic.linarith
import data.rat.basic

variables (x y : )

example
  (hx : x * x + x * x + y = 0) (hy : y * y + x * y + y = 0) :
  (y - x) * 2 = (x - y) * y :=
begin
  nlinarith, -- fails
end
example
  (hx : x * x + x * x + y = 0) (hy : y * y + x * y + y = 0) :
  (y - x) * 2 = (x - y) * y :=
begin
  nlinarith, -- works
end

What's going on?

Scott Morrison (Nov 15 2022 at 00:04):

Haha, I get the opposite failures. :-)

Mario Carneiro (Nov 15 2022 at 00:05):

I also replicated Eric's result

Scott Morrison (Nov 15 2022 at 00:05):

It works with my fix.

Scott Morrison (Nov 15 2022 at 00:06):

#17307

Scott Morrison (Nov 15 2022 at 00:06):

So you discovered the same bug in linarith I discovered while porting.

Eric Wieser (Nov 15 2022 at 00:06):

Isn't your bug at least deterministic?

Scott Morrison (Nov 15 2022 at 00:06):

The appearance of the bug is sensitive to ordering of variables used.

Scott Morrison (Nov 15 2022 at 00:06):

And apparently that is not deterministic??

Eric Wieser (Nov 15 2022 at 00:06):

Is this "ordering" in the sense of "some random hash of some garbage-named metavariables"?

Mario Carneiro (Nov 15 2022 at 00:07):

It might be due to the names of fvars?

Mario Carneiro (Nov 15 2022 at 00:07):

this is weird, I agree

Eric Wieser (Nov 15 2022 at 00:07):

I think it's deterministic with lean --make within a single process

Eric Wieser (Nov 15 2022 at 00:07):

And just not with the lean server

Mario Carneiro (Nov 15 2022 at 00:07):

variable ordering should not be nondeterministic

Eric Wieser (Nov 15 2022 at 00:08):

If your variables are named _mfresh.123 or whatever, are they guaranteed to be the same every time you run the tactic?

Eric Wieser (Nov 15 2022 at 00:08):

Or are those counters global within a module?

Mario Carneiro (Nov 15 2022 at 00:08):

they are a global counter

Eric Wieser (Nov 15 2022 at 00:08):

Then I bet if you put your variables in a name_set and iterate them, the iteration order is non-deterministic (as a function of human-visible state)

Mario Carneiro (Nov 15 2022 at 00:08):

but I would have expected linarith to name its variables in the order they occur in the hypothesis list

Mario Carneiro (Nov 15 2022 at 00:13):

Note that the one-liner test case I made for bug #17307 depends on the traversal order to get variables numbered in the right way

Mario Carneiro (Nov 15 2022 at 00:20):

Found it:

do s  ls.mfoldr (λ h s', infer_type h >>= find_squares s') mk_rb_set,
   new_es  s.mfold ([] : list expr) $ λ e, is_sq new_es,
     ((do p  mk_app (if is_sq then ``sq_nonneg else ``mul_self_nonneg) [e],
       return $ p::new_es) <|> return new_es),

that's a monadic fold over an rb_set (expr ×ₗ bool)

Mario Carneiro (Nov 15 2022 at 00:22):

and expr.lt of course depends on the ordering of those unique names

Eric Wieser (Nov 15 2022 at 00:22):

Damn, beat me to it

Eric Wieser (Nov 15 2022 at 00:23):

I guess using list.dedup instead of mk_rb_set would solve the problem?

Mario Carneiro (Nov 15 2022 at 00:24):

yes

Mario Carneiro (Nov 15 2022 at 00:24):

what's more, that is usually better because we want to use defeq up to reducible or something like that

Eric Wieser (Nov 15 2022 at 00:24):

Surely list.dedup won't do that either?

Mario Carneiro (Nov 15 2022 at 00:25):

well I mean the algorithm

Eric Wieser (Nov 15 2022 at 00:26):

RIght, so just manually iterate and insert if none of the existing items match; which is unfortunately O(n^2), but I guess n is small

Mario Carneiro (Nov 15 2022 at 00:26):

the dedup is usually done manually, using logic like this

Mario Carneiro (Nov 15 2022 at 00:26):

yeah, nothing that can be done about that

Eric Wieser (Nov 15 2022 at 00:31):

find_squares looks like it needs a similar fix

Eric Wieser (Nov 15 2022 at 00:31):

Either that, or we should canonize the order after doing all the initial deduplicating

Mario Carneiro (Nov 15 2022 at 00:34):

the comment says something about the inputs having been canonized, not sure when that happens but it seems like it should have also numbered the atoms

Mario Carneiro (Nov 15 2022 at 00:36):

assuming we aren't doing any big changes to this code, I guess find_squares should accumulate two list exprs (or I guess list (expr * unit) to pass to find_defeq)

Eric Wieser (Nov 15 2022 at 10:20):

Do you plan to make the patch, @Mario Carneiro?

Mario Carneiro (Nov 15 2022 at 10:21):

no, unless you are having trouble

Eric Wieser (Nov 15 2022 at 10:25):

Do you think it's worth making at all, or is there little point with Scott's patch on the horizon?

Mario Carneiro (Nov 15 2022 at 10:30):

I think it is best not to have nondeterministic tactics. Scott's fix is an independent issue

Eric Wieser (Nov 15 2022 at 10:37):

In theory it ought to be externally deterministic irrespective of the order, right? I suppose we can't use a quot.lift in meta code to prove that...


Last updated: Dec 20 2023 at 11:08 UTC