Zulip Chat Archive

Stream: general

Topic: nat.pow


Kevin Buzzard (May 05 2020 at 17:39):

Someone just privately asked me how to prove 1 <= 2^k, and applying one_le_pow_of_one_le doesn't work because nat.has_pow is not definitionally monoid.has_pow. We were always told that nothing could be done about this because it was in core. Is this something which can now be changed though? Or would it just break a gazillion things and nobody can be bothered to fix them? The issue I'm concerned about is that the two functions have different conventions about the succ case: nat.pow is b^n*b and monoid.pow is a*a^n :-(

Patrick Massot (May 05 2020 at 17:40):

I think it mostly requires having someone with enough time and energy.

Mario Carneiro (May 05 2020 at 17:43):

there is a theorem to rewrite one in terms of the other

Gabriel Ebner (May 05 2020 at 17:45):

https://github.com/leanprover-community/lean/pull/128#issuecomment-610281436

Reid Barton (Aug 27 2020 at 23:13):

an amusing proof that relies on the current nat.pow, perhaps found by library_search?
https://github.com/leanprover-community/mathlib/blob/master/src/number_theory/primorial.lean#L163-L164

Johan Commelin (Aug 28 2020 at 04:30):

Gabriel Ebner said:

https://github.com/leanprover-community/lean/pull/128#issuecomment-610281436

I replied to this on github, but let me also ask it here. Lean has VM implementations for nat.pow for reasons of efficiency. But does the VM care whether nat.pow is defined as a*a^n or a^n*a?
If I understand things correctly, it doesn't, right?

Mario Carneiro (Aug 28 2020 at 06:00):

It doesn't use either one

Mario Carneiro (Aug 28 2020 at 06:00):

But it does care that the function being called is nat.pow

Mario Carneiro (Aug 28 2020 at 06:01):

if you call another function it won't be automagically replaced with the efficient C++ implementation

Johan Commelin (Aug 28 2020 at 06:01):

Right. Than it is like I expected.

Reid Barton (Aug 28 2020 at 14:40):

I've seen contradictory comments on whether nat.pow actually has special VM support at all. It seems to me that it doesn't:

rwbarton@scw-capybara:~/lean/lean$ git grep '"pow"'
src/library/vm/vm_float.cpp:    DECLARE_VM_BUILTIN(name({"native", "float", "pow"}),   [](vm_obj const & a1, vm_obj const & a2) {return mk_vm_float(std::pow(to_float(a1), to_float(a2)));});
rwbarton@scw-capybara:~/lean/lean$ git grep '"mul"'
src/library/vm/vm_float.cpp:    DECLARE_VM_BUILTIN(name({"native", "float", "mul"}),   [](vm_obj const & a1, vm_obj const & a2) {return mk_vm_float(to_float(a1) * to_float(a2));});
src/library/vm/vm_int.cpp:    DECLARE_VM_BUILTIN(name({"int", "mul"}),              int_mul);
src/library/vm/vm_nat.cpp:    DECLARE_VM_BUILTIN(name({"nat", "mul"}),              nat_mul);

Gabriel Ebner (Aug 28 2020 at 14:43):

You're right, only the bitwise operations have VM support. Feel free to r+ merge master into the nat.pow removal then.

Johan Commelin (Aug 28 2020 at 14:48):

Whut? So we can just remove nat.pow from core?

Johan Commelin (Aug 28 2020 at 14:48):

Wouldn't it actually be better to add VM support?

Reid Barton (Aug 28 2020 at 14:48):

Do you mean Chris's old PR? It didn't build because some of the removed lemmas are used elsewhere in core.
But I'm preparing a new PR that removes everything that depends on nat.pow (including the whole of data.bitvec) with the intention of adding corresponding lemmas about ^ = monoid.pow to mathlib.

Reid Barton (Aug 28 2020 at 14:48):

I wasn't necessarily expecting that to work, but it seems to be working.

Reid Barton (Aug 28 2020 at 14:49):

There's not really that much point in using an optimized nat.pow implementation unless you're calculating 0^n or 1^n for large n.

Reid Barton (Aug 28 2020 at 14:52):

Removing nat.pow completely is preferable to having nat.pow with the old implementation because it means there won't be lemmas about the old nat.pow.

Gabriel Ebner (Aug 28 2020 at 14:54):

I'm pretty sure that you can do better than the naive recursive version though. You can do n32n^{32} in 5 multiplications instead of 31. There is also a dedicated pow function in gmp.

Johan Commelin (Aug 28 2020 at 14:57):

@Gabriel Ebner the naive version uses 32 multiplications, right :grinning_face_with_smiling_eyes: :stuck_out_tongue_wink:

Reid Barton (Aug 29 2020 at 21:44):

The change to Lean has landed, so here's my current progrress on the required mathlib changes. Primarily I still need to finish splitting up algebra.group_power and seeing what lemmas I can reuse in data.nat.lemmas. Later, if there are lemmas in the nat namespace that are exactly specializations of their general group_power counterparts, we can remove them completely.

Question: Is it worth adding a has_pow nat nat instance with the normal priority 1000, to be picked up immediately by instance search? I'm inclined to say it doesn't matter much since there are only a total of 12 instances of has_pow in mathlib, and 2 in core. If we do add it (now or in the future) we need to add back the corresponding parts of norm_num and ring (which I have just commented out for now).

Floris van Doorn (Aug 29 2020 at 22:22):

I think it is not necessary to have a separate instance has_pow nat nat.

Kevin Buzzard (Aug 29 2020 at 22:33):

If the plan is to make it defeq to the monoid pow one then do we need it? If the plan is to make it the other one then...well, this can't be the plan, because the plan is to solve the problem, and this is the problem.

Reid Barton (Aug 29 2020 at 22:33):

There isn't going to be any other one.

Reid Barton (Aug 29 2020 at 22:34):

The only reason to add it would be so that it gets tried earlier in the instance search order


Last updated: Dec 20 2023 at 11:08 UTC