Skip to content

Commit

Permalink
perf: improve kernel reduction of List.sublists (leanprover-communi…
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-wieser authored Oct 20, 2023
1 parent 727fa6a commit 0b07a6e
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 0 deletions.
10 changes: 10 additions & 0 deletions Std/Data/List/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -889,10 +889,20 @@ sublists [1, 2, 3] = [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
```
-/
def sublists (l : List α) : List (List α) :=
l.foldr (fun a acc => acc.bind fun x => [x, a :: x]) [[]]

/-- A version of `List.sublists` that has faster runtime performance but worse kernel performance -/
def sublistsFast (l : List α) : List (List α) :=
let f a arr := arr.foldl (init := Array.mkEmpty (arr.size * 2))
fun r l => (r.push l).push (a :: l)
(l.foldr f #[[]]).toList

-- The fact that this transformation is safe is proved in mathlib4 as `sublists_eq_sublistsFast`.
-- Using a `csimp` lemma here is impractical as we are missing a lot of lemmas about lists.
-- TODO(std4#307): upstream the necessary results about `sublists` and put the `csimp` lemma in
-- `Std/Data/List/Lemmas.lean`.
attribute [implemented_by sublistsFast] sublists

section Forall₂

variable {r : α → β → Prop} {p : γ → δ → Prop}
Expand Down
10 changes: 10 additions & 0 deletions test/list_sublists.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Std.Data.List.Basic

-- this times out with `sublistsFast`
set_option maxRecDepth 561 in
example : [1, 2, 3].sublists.sublists.length = 256 := rfl

-- TODO(std4#307): until we have the `csimp` lemma in std, this is a sanity check that these two
-- are equal.
example : ([] : List Nat).sublists = [].sublistsFast := rfl
example : [1, 2, 3].sublists = [1, 2, 3].sublistsFast := rfl

0 comments on commit 0b07a6e

Please sign in to comment.