Skip to content

[Merged by Bors] - feat: define List.offDiag#33812

Closed
urkud wants to merge 11 commits intoleanprover-community:masterfrom
urkud:YK-offDiag
Closed

[Merged by Bors] - feat: define List.offDiag#33812
urkud wants to merge 11 commits intoleanprover-community:masterfrom
urkud:YK-offDiag

Conversation

@urkud
Copy link
Copy Markdown
Member

@urkud urkud commented Jan 10, 2026

Use it to drop decidability assumption in Finset.offDiag. Also redefine Finset.diag.


Built on top of #12632, reopened from a fork.

Open in Gitpod

@github-actions github-actions bot added the merge-conflict The PR has a merge conflict with master, and needs manual merging. (this label is managed by a bot) label Jan 10, 2026
@urkud urkud changed the base branch from YK-offDiag to master January 10, 2026 03:09
@github-actions github-actions bot removed the merge-conflict The PR has a merge conflict with master, and needs manual merging. (this label is managed by a bot) label Jan 10, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Jan 10, 2026

PR summary 6f741b69cb

Import changes for modified files

Dependency changes

File Base Count Head Count Change
Mathlib.Data.List.Nodup 232 226 -6 (-2.59%)
Mathlib.Data.Finset.Prod 405 407 +2 (+0.49%)
Mathlib.Algebra.BigOperators.Group.Finset.Basic 417 419 +2 (+0.48%)
Mathlib.Data.Fintype.Prod 429 431 +2 (+0.47%)
Mathlib.Data.Finite.Prod 441 443 +2 (+0.45%)
Mathlib.Data.Finset.Sym 488 490 +2 (+0.41%)
Mathlib.Topology.MetricSpace.Infsep 962 964 +2 (+0.21%)
Import changes for all files
Files Import difference
There are 4814 files with changed transitive imports taking up over 217233 characters: this is too many to display!
You can run scripts/import_trans_difference.sh all locally to see the whole output.

Declarations diff

+ Nodup.mem_offDiag
+ Nodup.of_offDiag
+ Nodup.offDiag
+ Perm.offDiag
+ Sublist.flatMap_right
+ count_offDiag_eq_mul_sub_ite
+ length_offDiag
+ length_offDiag'
+ map_prodMap_offDiag
+ mem_offDiag_iff_getElem
+ nodup_offDiag
+ offDiag_cons_perm
+ offDiag_nil
+ toFinset_offDiag
++- offDiag
++- offDiag_singleton

You can run this locally as follows
## summary with just the declaration names:
./scripts/declarations_diff.sh <optional_commit>

## more verbose report:
./scripts/declarations_diff.sh long <optional_commit>

The doc-module for script/declarations_diff.sh contains some details about this script.


No changes to technical debt.

You can run this locally as

./scripts/technical-debt-metrics.sh pr_summary
  • The relative value is the weighted sum of the differences with weight given by the inverse of the current value of the statistic.
  • The absolute value is the relative value divided by the total sum of the inverses of the current values (i.e. the weighted average of the differences).

@urkud urkud requested a review from eric-wieser January 10, 2026 08:04
@urkud urkud added the t-data Data (lists, quotients, numbers, etc) label Jan 10, 2026
@eric-wieser
Copy link
Copy Markdown
Member

eric-wieser commented Jan 10, 2026

What do you think of this pseudo code definition? Is it faster?

def offDiag :=
  (aux l).flatten
where aux : List α → List (List (α × α))
| [] := []
| (x :: xs) := xs.map (fun y => (x, y)) ::
  zipWith (fun x' l => (x', x) :: l) xs (aux xs)

@urkud
Copy link
Copy Markdown
Member Author

urkud commented Jan 10, 2026

@eric-wieser Try this:

namespace List

variable {α : Type _}

def offDiag (l : List α) : List (α × α) :=
  l.zipIdx.flatMap fun (x, n) ↦ map (Prod.mk x) <| l.eraseIdx n

def offDiag₂ (l : List α) : List (α × α) :=
  aux l |>.flatten
  where aux : List α → List (List (α × α))
  | [] => []
  | x :: xs => map (x, ·) xs :: zipWith (fun y l ↦ (y, x) :: l) xs (aux xs)

def offDiag₃ : List α → List (α × α)
  | [] => []
  | x :: xs => map (x, ·) xs ++ map (·, x) xs ++ offDiag₃ xs

def offDiag₃TR (l : List α) : List (α × α) :=
  loop [] l
  where loop : List (α × α) → List α → List (α × α)
  | l, [] => l
  | l, x :: xs => loop (map (x, ·) xs ++ map (·, x) xs ++ l) xs

#time #eval (List.range 5000).offDiag.length
#time #eval (List.range 5000).offDiag₂.length
#time #eval (List.range 5000).offDiag₃.length
#time #eval (List.range 5000).offDiag₃TR.length

I'm getting (rounded) 2100ms, 4900ms, 2200ms, 2000ms on my desktop.

@urkud
Copy link
Copy Markdown
Member Author

urkud commented Jan 12, 2026

@eric-wieser What do you want to do about this PR? Do you want me to change the definition? If yes, then which one do you prefer?

@eric-wieser
Copy link
Copy Markdown
Member

Apologies, I missed your ping. Thanks for the comparison, I think those results make it clear that your definition is the right one. Would you mind adding that to the PR description?

def offDiag :=
(s ×ˢ s).filter fun a : α × α => a.fst ≠ a.snd
def offDiag : Finset (α × α) :=
.mk (Quotient.map List.offDiag (fun _ _ ↦ List.Perm.offDiag) s.1) <| by
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's tempting to extract this to a Multiset.offDiag; do you think it's ok to do this without writing API for it? Otherwise perhaps lets just leave a TODO.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to add a TODO.


@[simp]
theorem diag_union_offDiag : s.diag ∪ s.offDiag = s ×ˢ s := by
theorem diag_union_offDiag [DecidableEq (α × α)] : s.diag ∪ s.offDiag = s ×ˢ s := by
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This generalization makes me feel a little uneasy; certainly it feels a little out of scope for the PR. Would you mind changing back to [DecidableEq α] throughout for now, and then making a separate PR with the [DecidableEq (α × α)] generalization?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

Copy link
Copy Markdown
Member

@eric-wieser eric-wieser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise looks great, thanks!

bors d+

@mathlib-bors
Copy link
Copy Markdown
Contributor

mathlib-bors bot commented Jan 12, 2026

✌️ urkud can now approve this pull request. To approve and merge a pull request, simply reply with bors r+. More detailed instructions are available here.

@ghost ghost added the delegated This pull request has been delegated to the PR author (or occasionally another non-maintainer). label Jan 12, 2026
@urkud urkud added the auto-merge-after-CI Please do not add manually. Requests for a bot to merge automatically once CI is done. label Jan 13, 2026
@ghost
Copy link
Copy Markdown

ghost commented Jan 13, 2026

As this PR is labelled auto-merge-after-CI, we are now sending it to bors:

bors merge

@ghost ghost added the ready-to-merge This PR has been sent to bors. label Jan 13, 2026
mathlib-bors bot pushed a commit that referenced this pull request Jan 13, 2026
Use it to drop decidability assumption in `Finset.offDiag`. Also redefine `Finset.diag`.
@mathlib-bors
Copy link
Copy Markdown
Contributor

mathlib-bors bot commented Jan 13, 2026

Build failed (retrying...):

mathlib-bors bot pushed a commit that referenced this pull request Jan 13, 2026
Use it to drop decidability assumption in `Finset.offDiag`. Also redefine `Finset.diag`.
@mathlib-bors
Copy link
Copy Markdown
Contributor

mathlib-bors bot commented Jan 13, 2026

Timed out.

@bryangingechen
Copy link
Copy Markdown
Contributor

bors r+

mathlib-bors bot pushed a commit that referenced this pull request Jan 13, 2026
Use it to drop decidability assumption in `Finset.offDiag`. Also redefine `Finset.diag`.
@mathlib-bors
Copy link
Copy Markdown
Contributor

mathlib-bors bot commented Jan 13, 2026

Build failed (retrying...):

mathlib-bors bot pushed a commit that referenced this pull request Jan 13, 2026
Use it to drop decidability assumption in `Finset.offDiag`. Also redefine `Finset.diag`.
@mathlib-bors
Copy link
Copy Markdown
Contributor

mathlib-bors bot commented Jan 13, 2026

Pull request successfully merged into master.

Build succeeded:

@mathlib-bors mathlib-bors bot changed the title feat: define List.offDiag [Merged by Bors] - feat: define List.offDiag Jan 13, 2026
@mathlib-bors mathlib-bors bot closed this Jan 13, 2026
@urkud urkud deleted the YK-offDiag branch January 14, 2026 04:39
eliasjudin pushed a commit to eliasjudin/mathlib4 that referenced this pull request Jan 18, 2026
Use it to drop decidability assumption in `Finset.offDiag`. Also redefine `Finset.diag`.
Ruben-VandeVelde added a commit to Ruben-VandeVelde/mathlib4 that referenced this pull request Jan 19, 2026
This proves that the new definition of Finset.diag (from leanprover-community#33812) is equivalent to the old one.
mathlib-bors bot pushed a commit that referenced this pull request Jan 19, 2026
This proves that the new definition of Finset.diag (from #33812) is equivalent to the old one.
goliath-klein pushed a commit to PrParadoxy/mathlib4 that referenced this pull request Jan 24, 2026
Use it to drop decidability assumption in `Finset.offDiag`. Also redefine `Finset.diag`.
goliath-klein pushed a commit to PrParadoxy/mathlib4 that referenced this pull request Jan 24, 2026
This proves that the new definition of Finset.diag (from leanprover-community#33812) is equivalent to the old one.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto-merge-after-CI Please do not add manually. Requests for a bot to merge automatically once CI is done. delegated This pull request has been delegated to the PR author (or occasionally another non-maintainer). ready-to-merge This PR has been sent to bors. t-data Data (lists, quotients, numbers, etc)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants