Zulip Chat Archive

Stream: new members

Topic: Problems with MvPolynomial evaluation


Sarah Azevedo Pereira (Nov 05 2024 at 11:38):

Hi everyone! I’m working with multivariable polynomials in Lean, using the MvPolynomial type, and I created a function that takes a string and converts it into a polynomial. However, when I try to evaluate the result, it doesn’t simplify as expected.
Here is an example:

import Mathlib

open MvPolynomial

noncomputable def str_poly (s : String) : MvPolynomial (Fin 2)  :=
  let vars := s.splitOn "+"
  if vars.length == 2 then
    X 0 + X 1
  else
    C 0

#reduce str_poly "a+b"  -- Expected to see something like `X 0 + X 1`
#reduce str_poly "a+b+c" -- Expected to see `C 0`

When I run #reduce, Lean returns a more complex output with support and other internal details of the polynomial structure... Here's a sample of the output I get:

{
  support :=
    Decidable.rec
      (fun h 
        {
          val :=
            Quot.mk List.Perm
              [{ support := { val := Quot.mk List.Perm [], nodup :=  }, toFun := fun x  Nat.zero,
                  mem_support_toFun :=  }],
          nodup :=  })
      (fun h  { val := Quot.mk List.Perm [], nodup :=  }) ...

Does anyone know how to make Lean simplify the expression so that #reduce only shows the simplified polynomial (X 0 + X 1 or C 0) instead of this full internal structure? I feel like I might be missing a configuration needed to get the reduced form.

Daniel Weber (Nov 05 2024 at 15:39):

The problem is that #reduce also reduces X and C, as well as addition

Sarah Azevedo Pereira (Nov 13 2024 at 22:04):

Well, I thought that comparing the output using #reduce ((str_poly "a+b") == X 0 + X 1) would work out and return true. However, the output is something like Decidable.rec (...)
An alternative way would be: example : Eq (str_poly "a+b") (X 0 + X 1) := by decide, but it gave the following error:

tactic 'decide' failed for proposition
  str_poly "a+b" = X 0 + X 1
since its 'Decidable' instance
  (str_poly "a+b").decidableEqMvPolynomial (X 0 + X 1)
did not reduce to 'isTrue' or 'isFalse'.

After unfolding the instances 'decidable_of_decidable_of_iff', 'decidable_of_iff', 'instDecidableAnd', 'instDecidableEqBool', 'instDecidableEqList', 'instDecidableEqNat', 'instDecidableEqString', 'Bool.decEq', 'Finset.decidableEq', 'Finsupp.instDecidableEq', 'List.hasDecEq', 'Multiset.decidableEq', 'decidableEqMvPolynomial', 'Nat.decEq' and 'String.decEq', reduction got stuck at the 'Decidable' instance
   
    (Quot.lift
        (Quot.indep fun a =>
          (fun a =>
              Quot.recOnSubsingleton (X 0 + X 1).support.val fun a_1 =>
                (fun x x_1 => decidable_of_iff' (x  x_1) ) a a_1)
            a)
         (str_poly "a+b").support.val).snd

Hint: Reduction got stuck on '▸' (Eq.rec), which suggests that one of the 'Decidable' instances is defined using tactics such as 'rw' or 'simp'. To avoid tactics, make use of functions such as 'inferInstanceAs' or 'decidable_of_decidable_of_iff' to alter a proposition.

The error message suggests trying alternatives like inferInstanceAs or decidable_of_decidable_of_iff, but I’m not sure how to apply these here.

Has anyone had this kind of issue with polynomials or have ideas on how to test the function? I'd appreciate any insights

Kevin Buzzard (Nov 13 2024 at 22:07):

The issue is that much of Lean (and in particular, polynomials) is (intentionally) noncomputable (to make proving easier). I think the philosophy in mathlib is that you're supposed to test your definitions by proving theorems about them, rather than checking examples! You might be better off writing a decidable version of polynomials which is optimised to your needs.

Kevin Buzzard (Nov 13 2024 at 22:11):

The issue seems to be with String.splitOn rather than polynomials:

example : str_poly "a+b" = X 0 + X 1 := by
  have foo : ("a+b".splitOn "+").length = 2 := by
    -- I need a computer scientist to do this because I don't
    -- know the API for `String.splitOn`
    sorry
  simp_all [str_poly]

Tomaz Mascarenhas (Nov 13 2024 at 22:14):

shouldn't it be possible to prove foo just by reducing both sides?

Tomaz Mascarenhas (Nov 13 2024 at 22:14):

or is splitOn noncomputable too? :face_with_monocle:

Sarah Azevedo Pereira (Nov 13 2024 at 22:15):

Kevin Buzzard said:

The issue seems to be with String.splitOn rather than polynomials:

example : str_poly "a+b" = X 0 + X 1 := by
  have foo : ("a+b".splitOn "+").length = 2 := by
    -- I need a computer scientist to do this because I don't
    -- know the API for `String.splitOn`
    sorry
  simp_all [str_poly]

Well, that's weird, because when I do this: #reduce ("a+b".splitOn "+").length == 2 it returns true

Kevin Buzzard (Nov 13 2024 at 22:15):

It's not noncomputable, it's just CS gobble-de-gook and I can't find any API for it.

Kevin Buzzard (Nov 13 2024 at 22:16):

Sarah Azevedo Pereira said:

Well, that's weird, because when I do this: #reduce ("a+b".splitOn "+").length == 2 it returns true

That's surprising because rfl doesn't close the goal. But all this is way beyond my comfort zone, I have no idea what #reduce does.

Tomaz Mascarenhas (Nov 13 2024 at 22:17):

Kevin Buzzard said:

The issue is that much of Lean (and in particular, polynomials) is (intentionally) noncomputable (to make proving easier). I think the philosophy in mathlib is that you're supposed to test your definitions by proving theorems about them, rather than checking examples! You might be better off writing a decidable version of polynomials which is optimised to your needs.

Also, I am a bit confused about how can we have DecidableEq for polynomials if they are noncomputable

Kevin Buzzard (Nov 13 2024 at 22:19):

I should shut up and we should wait until someone who knows what they're talking about comes along.

Eric Wieser (Nov 13 2024 at 22:21):

Also, I am a bit confused about how can we have DecidableEq for polynomials if they are noncomputable

DecidableEq and noncomputable are somewhat independent

Kevin Buzzard (Nov 13 2024 at 22:21):

Oh that didn't take long

Eric Wieser (Nov 13 2024 at 22:22):

But you can computably decide whether the polynomial 0 is equal to itself

Eric Wieser (Nov 13 2024 at 22:23):

DecidableEq just says "I have a function that tells you if x = y given x and y". If x or y are noncomputable (as all polynomials except 0 are for stupid reasons), then calling f x y is going to be noncomputable even if f is computable.

Eric Wieser (Nov 13 2024 at 22:23):

#reduce is something different again, and is not what is meant in lean when people talk about computability.

Sarah Azevedo Pereira (Nov 13 2024 at 22:31):

Kevin Buzzard said:

The issue is that much of Lean (and in particular, polynomials) is (intentionally) noncomputable (to make proving easier). I think the philosophy in mathlib is that you're supposed to test your definitions by proving theorems about them, rather than checking examples! You might be better off writing a decidable version of polynomials which is optimised to your needs.

Well, at first i tried to do that, but for this project I’ll need mathlib to help prove certain theorems about the polynomials as well, so I guess defining them another way wouldn't be the best solution

Tomaz Mascarenhas (Nov 13 2024 at 22:36):

Eric Wieser said:

DecidableEq just says "I have a function that tells you if x = y given x and y". If x or y are noncomputable (as all polynomials except 0 are for stupid reasons), then calling f x y is going to be noncomputable even if f is computable.

So there is no hope to test the function str_poly?

Daniel Weber (Nov 14 2024 at 04:52):

Kevin Buzzard said:

The issue seems to be with String.splitOn rather than polynomials:

example : str_poly "a+b" = X 0 + X 1 := by
  have foo : ("a+b".splitOn "+").length = 2 := by
    -- I need a computer scientist to do this because I don't
    -- know the API for `String.splitOn`
    sorry
  simp_all [str_poly]

with_unfolding_all rfl works here, as String.splitOn is irreducible

Kevin Buzzard (Nov 14 2024 at 08:23):

Oh nice!


Last updated: May 02 2025 at 03:31 UTC