Zulip Chat Archive

Stream: mathlib4

Topic: Algebra.BigOperators.Finprod mathlib4#1766


Lukas Miaskiwskyi (Jan 22 2023 at 16:27):

Link to PR: mathlib4#1766

Running into strange issues right at the start of the file:

noncomputable irreducible_def finsum {M α} [AddCommMonoid M] (f : α  M) : M :=
  if h : (support (f  PLift.down)).Finite then  i in h.toFinset, f i.down else 0
#align finsum finsum

Throws the error failed to compile definition, consider marking it as 'noncomputable' because it depends on 'Classical.propDecidable', and it does not have executable code. What I find the weirdest is that the error throws the red squiggles onto the docstring of the function.

Replacing irreducible_def with def and adding an @[irreducible] attribute seems to work, but irreducible_def seems to do more than the attribute, so that's probably not an ideal fix.

Reid Barton (Jan 22 2023 at 21:19):

irreducible_def is just a command someone wrote (I think Gabriel), it probably doesn't interact with noncomputable properly yet.

Lukas Miaskiwskyi (Jan 23 2023 at 11:05):

Also a notational question: The statements of many theorems in this file contain expressions like ∏ᶠ i ∈ s, f i and (∏ᶠ (i) (_h : i = a), f i) which I would like to port to lean4 notation syntax. The product in the BigOperators.Basic does not allow for such expressions currently, so I don't have that to guide me, and we probably don't want to refactor all the theorem statements at this point.

How would we like the lean4 syntax to be set up for this? For the first one, the macro_rules case

macro_rules (kind := bigfinprod)
(∏ᶠ $x:ident  $s:ident, $p) => `(finprod fun $x => (finprod (α := $x  $s) (fun _ => $p)))

seems to reproduce the lean3 behavior, but I don't know if that's good design.

The second one I'm trying to match with

syntax (name := bigfinprod_condition) "∏ᶠ (" extBinder ") (" extBinder "), " term:67 : term
macro_rules (kind := bigfinprod_condition)
  | `(∏ᶠ ($x:ident) ($u:ident), $p) => `(finprod fun $x => (finprod (α := $u) (fun _ => $p)))

But that throws a strange expected ')' error at (α := $u) . Could be that I do not yet fully understand the syntax here.

Lukas Miaskiwskyi (Jan 23 2023 at 11:07):

cc @Johan Commelin since he mentioned porting the notation to how BigOperators.Basic does it

Eric Wieser (Jan 23 2023 at 11:16):

You should be able to build the notation in the same way as the supᵢ notation

Ruben Van de Velde (Jan 23 2023 at 11:46):

I thought we shouldn't have supr anymore

Eric Wieser (Jan 23 2023 at 11:49):

Whoops, I removed the stray r

Lukas Miaskiwskyi (Jan 23 2023 at 13:32):

Thanks for the suggestion, Eric, that sent me on a painful journey of understanding the syntax. What seems to reproduce all the lean3-style notation in this file is:

syntax (name := bigfinprod) "∏ᶠ " extBinders ", " term:67 : term
macro_rules (kind := bigfinprod)
  | `(∏ᶠ $x:ident, $p) => `(finprod (fun $x:ident  $p))
  | `(∏ᶠ $x:ident : $t, $p) => `(finprod (fun $x:ident : $t  $p))
  | `(∏ᶠ $x:ident $b:binderPred, $p) =>
    `(finprod fun $x => (finprod (α := satisfies_binder_pred% $x $b) (fun _ => $p)))

  | `(∏ᶠ ($x:ident) ($h:ident : $t), $p) =>
      `(finprod fun ($x) => finprod (α := $t) (fun $h => $p))
  | `(∏ᶠ ($x:ident : $_) ($h:ident : $t), $p) =>
      `(finprod fun ($x) => finprod (α := $t) (fun $h => $p))

  | `(∏ᶠ ($x:ident) ($y:ident), $p) =>
      `(finprod fun $x => (finprod fun $y => $p))
  | `(∏ᶠ ($x:ident) ($y:ident) ($h:ident : $t), $p) =>
      `(finprod fun $x => (finprod fun $y => (finprod (α := $t) fun $h => $p)))

  | `(∏ᶠ ($x:ident) ($y:ident) ($z:ident), $p) =>
      `(finprod fun $x => (finprod fun $y => (finprod fun $z => $p)))
  | `(∏ᶠ ($x:ident) ($y:ident) ($z:ident) ($h:ident : $t), $p) =>
      `(finprod fun $x => (finprod fun $y => (finprod fun $z => (finprod (α := $t) fun $h => $p))))

And similar for finsum. But that's of course extremely fickle, since now the notation breaks if the user gives a typehint at an unconsidered place. And of course it would be nice to allow arbitrarily many arguments to take the product over, rather than just three. Any easy fixes?

Eric Wieser (Jan 23 2023 at 16:19):

What did we do here for docs4#supᵢ?

Eric Wieser (Jan 23 2023 at 16:20):

Why do we need anything different to what we had here?

notation3 "∏ᶠ "(...)", "r:(scoped f => finprod f) => r

Lukas Miaskiwskyi (Jan 23 2023 at 16:34):

In the PR, Johan mentioned that using the macro_rules approach allows you to set operator precedence properly, which I suppose notation3doesn't. But other than that, the file works fine without it. And the macro_rules approach in supᵢ does not include iterated applications. Chris & Johan agreed to fix the notation at a later time, so it is now merged anyway.

Rob Lewis (Feb 22 2023 at 14:40):

A question here, since I'll (hopefullly) be using finsum in class soon: right now it seems that the pretty printer doesn't use finsum/prod notation at all. For example,

import Mathlib.Algebra.BigOperators.Finprod

example :  n : , (∑ᶠ k  n, k) = n*(n+1)/2 := by
  -- ⊢ ∀ (n : ℕ), (finsum fun k => finsum fun h => k) = n * (n + 1) / 2

Is there any way I can coax this to display like the input, or is it impossible for now? Unfortunately I can't show students something like finsum fun k => finsum fun h => k :sad:

Patrick Massot (Feb 22 2023 at 14:50):

Hi Rob! It's nice to see you here. You need a unexpander for finsum.

Patrick Massot (Feb 22 2023 at 14:51):

I'll try to see if I can write that by imitating other examples.

Rob Lewis (Feb 22 2023 at 14:54):

Good to be here :smile: Every week I tell myself the chaos of the semester will die down and I'll have more time to spend here, next week...

Rob Lewis (Feb 22 2023 at 14:55):

Thanks! (And I can try myself if you could point me to other examples?)

David Renshaw (Feb 22 2023 at 14:59):

Here's one example: https://github.com/leanprover-community/mathlib4/blob/88c789ef511f8bf32a7d30ae403e29857748c079/Mathlib/Init/Set.lean#L78-L82

David Renshaw (Feb 22 2023 at 15:01):

Another thing that's possible is using delab: https://github.com/dwrensha/lean4-maze/blob/b7b36525dbf48989d09cd89c79703b55343af124/Maze.lean#L160

I don't have a good understanding of when Unexpander or delab is more appropriate.

Rob Lewis (Feb 22 2023 at 15:35):

Awesome, thanks David. Unsurprisingly a little tricker than I was hoping! I'm struggling to even parse what pattern I need to unexpand...

Rob Lewis (Feb 24 2023 at 15:18):

I need to give in and admit I'm stumped here -- this is about as far as I got, going off an existsi example, which isn't right.

import Mathlib.Algebra.BigOperators.Finprod

@[app_unexpander finsum] def unexpandFinsum : Lean.PrettyPrinter.Unexpander
  | `($(_) fun $_:ident  finsum fun $h:ident  $p) => `(∑ᶠ $h:ident, $p)
  | _                                               => throw ()

example : (∑ᶠ x  2, x)= 4 := by
  sorry

Maybe this does need a delab? Somehow we need to access the type of h? But I'm copying things without really understanding here.

Alexander Bentkamp (Feb 27 2023 at 14:00):

Yes, I think a delab is necessary since the unexpander can only access the information that is already present in the syntax, and the type of h is not in the syntax. Here is what I came up with so far for Finset.sum:

import Mathlib.Algebra.BigOperators.Basic

open Lean PrettyPrinter Delaborator SubExpr

namespace BigOperators

example :   i : Fin n, ((i : ) + 1) = 4 := by
  sorry

@[local delab app.Finset.sum]
def delabFinsetSum : Delab := do
  guard $ ( getExpr).getAppNumArgs == 5
  guard $ (( getExpr).getArg! 3).isAppOf' ``Finset.univ
  guard $ (( getExpr).getArg! 4).isLambda
  withNaryArg 4 do
    let α  withBindingDomain delab
    withBindingBodyUnusedName fun n => do
      let n : TSyntax `ident := n
      let b  delab
      `( $n:ident : $α, $b)

example :  i : Fin n, ((i : ) + 1) = 4 := by
  sorry

Last updated: Dec 20 2023 at 11:08 UTC