Skip to content

feat(Algorithms): comparison sort lower bound via decision-tree induction - #770

Open
SamuelSchlesinger wants to merge 2 commits into
leanprover:mainfrom
SamuelSchlesinger:comparison-sort-lower-bound
Open

feat(Algorithms): comparison sort lower bound via decision-tree induction#770
SamuelSchlesinger wants to merge 2 commits into
leanprover:mainfrom
SamuelSchlesinger:comparison-sort-lower-bound

Conversation

@SamuelSchlesinger

Copy link
Copy Markdown
Collaborator

An attempt to prove the comparison sort lower bound of #685 taking, in my view, a more natural proof approach for this model. The original proof analyzes traces of the computation, while this approach takes direct advantage of the inductive structure of the free monad and essentially does induction on the program. At a high level, #685 formalizes the encoding argument whereas we formalize the decision tree argument. The arithmetic estimate of log_2 n! is adapted from #685.

Claude Fable 5 authored this code under my direction and review.

…tion

A comparison program is a free monad over a single comparison query,
i.e. a binary decision tree. card_image_run_le_two_pow_of_cost_le bounds
its distinct results over a finite comparator family by 2 ^ t whenever
every comparator in the family costs at most t comparisons, by structural
induction: the family splits at the root comparison. A program that sorts
under every hidden permutation order on Fin n therefore takes at least
log2(n!) comparisons in the worst case; (n/2) * log2(n/2) follows as a
corollary.
Address the suggestion that data should not be constructed by pattern
matching on FreeM: run and cost are now the two projections of the
canonical interpretation (FreeM.liftM) of a program into TimeM, so the
monad-morphism lemmas run_bind and cost_bind follow from liftM_bind
rather than bespoke inductions. The unfolding lemmas remain
definitional, and the lower bound proofs are unchanged except that
grind now closes their mechanical leaf goals through the
grind-annotated unfolding lemmas. Drop two unused imports.
Comment on lines +71 to +72
def run (P : FreeM (SortOps α) β) (le : α → α → Bool) : β :=
(P.liftM (sortHandler le)).ret

@eric-wieser eric-wieser Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't think Cslib.Algorithms.run should be about SortOps; this needs a better name.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Alternatively, just drop the run altogether and inline (P.liftM (sortHandler le)).ret below (note that ret has notation)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Large parts of this code verbatim resemble the proof in #685

@Shreyas4991

Copy link
Copy Markdown
Contributor

Large parts of this resemble #685 verbatim. It would be nice to have a diff.
Cc: @eric-wieser

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants