add instances for Equivalence, Op, and Predicate#46
add instances for Equivalence, Op, and Predicate#46subttle wants to merge 1 commit intodmwit:masterfrom
Conversation
|
Oh I need to add a conditional import for |
|
LGTM, up to Travis complaints I guess. |
| , universe-base >=1.1 && <1.1.2 | ||
|
|
||
| if impl(ghc >=8.6.1) | ||
| build-depends: base >=4.12 && <4.13 |
There was a problem hiding this comment.
This is not right.
See https://oleg.fi/gists/posts/2019-06-03-compat-packages.html#s:3
| instance (Finite a, Ord a) | ||
| => Finite (Equivalence a) | ||
| where cardinality = retag (bell <$> (cardinality :: Tagged a Natural)) | ||
| where -- Compute the Bell number for the given cardinality. |
There was a problem hiding this comment.
what is Bell number, add a reference
There was a problem hiding this comment.
I like the wolfram.com definition.
| where -- Compute the Bell number for the given cardinality. | |
| where -- Compute the Bell number for the given cardinality. | |
| -- The Bell number is the "number of ways a set of n elements can be partitioned into nonempty subsets" | |
| -- http://mathworld.wolfram.com/BellNumber.html |
Do you think it is also worth stating somewhere the relation between equivalences and partitions? E.g.:
https://proofwiki.org/wiki/Fundamental_Theorem_on_Equivalence_Relations
https://proofwiki.org/wiki/Relation_Induced_by_Partition_is_Equivalence
Wikipedia says it nicely as:
"there is a natural bijection between the set of all possible equivalence relations on X and the set of all partitions of X"
And it is that bijection which enables the Bell number to compute the cardinality.
If you would like that in the comment, perhaps this is better:
| where -- Compute the Bell number for the given cardinality. | |
| where -- Compute the Bell number for the given cardinality. | |
| -- The Bell number is the "number of ways a set of n elements can | |
| -- be partitioned into nonempty subsets" | |
| -- http://mathworld.wolfram.com/BellNumber.html | |
| -- | |
| -- https://en.wikipedia.org/wiki/Equivalence_relation#Fundamental_theorem_of_equivalence_relations | |
| -- The Fundamental Theorem on Equivalence Relations says, a natural | |
| -- bijection between the set of all possible equivalence relations | |
| -- on X and the set of all partitions of X, and said bijection | |
| -- enables the Bell number to be used for computing the `cardinality`. |
Not sure if someone would like to state that (or something similar) more elegantly, but I think that provides good information to anyone who reads the code and wants to know why bell is used in computing the cardinality.
| where universe = map tabulate universe | ||
| instance (Finite a, Ord a) | ||
| => Universe (Equivalence a) | ||
| where universe = [Equivalence ((==) `on` (`M.lookup` m)) | m <- partitions universeF] |
There was a problem hiding this comment.
This implementation needs a commentary.
I have hard time convincing myself it's correct, thus I'd error on the fact, that it's probably wrong in some corner case. Help me.
There was a problem hiding this comment.
Some commentary:
Here's how we enumerate all the equivalence relations for a set X. First we choose an arbitrary element of X. Call it x. Then the equivalence relation can be described in two parts:
- The equivalence class of x, that is, the set of elements which is equivalent to x. (This is required to contain x.)
- The equivalence relation on all the elements not equivalent to x, which we compute recursively in the same way.
For each piece, we simply nondeterministically choose from among all possibilities. To efficiently track equivalence classes, we choose a fresh number to identify each class, and make a Map from elements of X to the identity of their class.
These ideas should shine through pretty clear in the code once you have them in mind:
-- choose an arbitrary element x of the set X, and set xs = X \ {x}
go n (x : xs) = do
-- choose a subset eq of xs to be equivalent to x, and set notEq = xs \ eq
(eq, notEq) <- partitionA (const [False, True]) xs
-- recursively cook up an equivalence relation on the leftovers, bumping the class identifier up by one
rest <- go (n + 1) notEq
-- map x and all the elements of eq to the current class identifier
pure $ M.fromList [(x', n) | x' <- x : eq] `M.union` rest
It is okay to use the boring old list monad instead of our fancy helpers because everything involved here is finite.
There was a problem hiding this comment.
These comments should be in a implementation.
What's the guarantee that [Equivalence a] doesn't contain same elements, i.e its' cardinality is correct. Still have to think too hard.
A test for 3/4/5 element sets would be 👍, (it turns out that Bell number is a count of partitions of a set)
Also if partitionA works so that it returns empty eq, will the first element of universe :: [Equivalence a] be Equivalence (==). If so, it could be checked as well.
Maybe there should be a big warning on this instance, as Bell numbers grow relatively fast/.
There was a problem hiding this comment.
These comments should be in a implementation.
No objection.
What's the guarantee that
[Equivalence a]doesn't contain same elements
The usual (strong) inductive one: the call to partitionA doesn't return any duplicate equivalence classes for x, and by induction there are no duplicate equivalence relations in rest. I think this one is not even worth writing down.
There was a problem hiding this comment.
See https://github.com/dmwit/universe/pull/47/files, adding such doctest would convince me (and readers of documentation) that this works. Using something like Three to demonstrate various Equivalence would be IMHO neat thing!
|
I merged |
|
Nice! Thank you for that. I can certainly do it, I just won't be able to get to it right away, unfortunately. Realistically I could maybe have it done by next weekend. I realize of course it's not a big task, I just have a lot of work at the moment. No worries about having the conflict. :) |
|
Thank you for your patience, it is much appreciated :) A small update, I worked on this a bit today and finally have a reference for the topic: I am curious to try a new approach which would reuse code from the P.S.: There are some more fascicles from Knuth which may be of use here too: |
|
@subttle any progress? |
|
Yes, I had a few mindblowingly busy months at work but I actually have a weekend to work on this coming up and I have a great idea of how I want to implement it :D |
|
Update: I haven't been able to implement it yet but my experimenting has been very rewarding. I was thinking about the bitstring representation for any given
Here each line represents a partitioning whose union makes up a whole. For example, And then all of the lines together make up all possible partitions. meaning we could also of course think of Now I will just think out loud to myself (I'm not asking anyone questions in particular, I'm just sharing my current thought process). where I can just fix different parts at a time. I will try to make more time this week (hopefully in the next few days) to finish up here, but if not I will continue to update! Thanks for your patience! I don't know what to make of these slides yet, but it might be useful for me: |
PR for #44
Please let me know if you would like anything done differently, I will gladly make changes. Thank you for considering this PR.