-
Notifications
You must be signed in to change notification settings - Fork 108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: OrderedAssocList #556
base: main
Are you sure you want to change the base?
Conversation
I'm assuming this is useful for kernel execution efficiency. Is that the case? Could you test performance against RBMap? |
No, actually, there's no need to run any of this in the kernel. I want this because I think it will be easier to write the theorems about algebraic operations on finitely supported functions |
Co-authored-by: Mario Carneiro <di.gama@gmail.com>
In that case I'm a bit dubious of adding a new data structure like this to std, since it has neither good kernel performance nor good runtime performance, and we already have other ways to write finitely supported functions for proving purposes. |
Hmm, okay. I will see how proofs go on top of |
Currently |
What are you trying to do more specifically? Why do you need proofs in this case? If this is an
Wikipedia describes a better algorithm for RBMap merge with complexity |
This is very slightly inaccurate (because of subsequent laziness taking some shortcuts), but the functions and theorems I need on the representation of coefficients are given in https://github.com/leanprover/std4/blob/main/Std/Tactic/Omega/Coeffs/IntList.lean Currently all these functions are implemented on As you can see the intention is that I should be able to swap out any representation satisfying that API. This is not particularly urgent, as right now now one is actually calling |
So why not just use |
Because then the merge operation (which is actually run, not just proved about) is |
I mean, you can still implement a |
That's what this PR does! |
Is it? I would expect it to just be a simple predicate, e.g. theorem orderedMerge_ordered : Ordered l1 -> Ordered l2 -> Ordered (l1.orderedMerge l2) := ... Actually it might not even be |
I've started refactoring, and agree this is better. Thanks for talking me around. :-) |
I think all my concerns have been addressed. Just one additional remark: the design of |
This is still WIP, I will probably eventually remove the bundled However, I am not intending to use |
I've cleaned this up. I decided to keep the bundled structure because the whole point is the nice extensionality lemma available there. |
Mathlib CI status (docs):
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only made it part way but I don't know when I will come back to it :/
The predicate that the keys of an `AssocList` are | ||
in strictly increasing order according to the comparator `cmp`. | ||
-/ | ||
def keysOrdered (cmp : α → α → Ordering) : AssocList α β → Prop |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make Bool
valued. It's nicely tail recursive too!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm skeptical. What is the pay-off? It's kind of annoying to adapt to this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, it's a major refactor. My concern is that the decision procedure for the current version is not necessarily as efficient. Can we have both? Also, keysOrdered
should be KeysOrdered
if it's a proposition.
Have you considered using ltHeadKey?
here to save some cases?
def KeysOrdered (cmp : α → α → Ordering) : AssocList α β → Prop
| .nil => True
| .cons a _ t => ltHeadKey? cmp a t ∧ KeysOrdered cmp t
/-- | ||
The condition that an element is less than the first key of an `AssocList`, or that list is empty. | ||
-/ | ||
abbrev ltHeadKey? (cmp : α → α → Ordering) (a : α) (t : AssocList α β) : Prop := |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes more sense as Bool
valued. Something about the ?
makes me unhappy here but it's hard to think of a more accurate alternative.
| .cons _ _ .nil => True | ||
| .cons a _ (.cons x y t) => cmp a x = .lt ∧ keysOrdered cmp (.cons x y t) | ||
|
||
instance instKeysOrderedDecidablePred : DecidablePred (keysOrdered cmp : AssocList α β → Prop) := by |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't be necessary if keysOrdered
returns Bool
.
Ordered wrapper around
AssocList
, and basic functionsfind?
,insert?
,filterMapVal
, andmerge
. An extensionality lemma(∀ a, l₁.find? a = l₂.find? a) → l₁ = l₂
.I will later use this to implement sparse coefficients in
omega
.