Skip to content
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

Add MergeableMap (an implementation of the union-find algorithm) #236

Open
julianhyde opened this issue Jan 11, 2025 · 3 comments
Open

Add MergeableMap (an implementation of the union-find algorithm) #236

julianhyde opened this issue Jan 11, 2025 · 3 comments

Comments

@julianhyde
Copy link
Collaborator

Add interface MergeableMap, an implementation of the union-find algorithm using the disjoint set data structure.

A MergeableMap<K, V> is a Map<K, V> with an additional operation:

  • V merge(K k1, K k2) that declares that two keys are in the same equivalence class

We provide an implementation, class MergeableHashMap<K, V>, based on a hash map.

If you just want to build equivalence classes, you can create a MergeableMap with a Void value.

julianhyde added a commit to julianhyde/morel that referenced this issue Jan 12, 2025
@julianhyde
Copy link
Collaborator Author

Similar to JGraphT's UnionFind.

@julianhyde
Copy link
Collaborator Author

@julianhyde
Copy link
Collaborator Author

julianhyde commented Jan 13, 2025

As of julianhyde@fd1527d the put(K key, V value) method (inherited from Map<K, V>) is a bit awkward. If key is new, or is a singleton equivalence class, it works as you would expect. But if key is part of a larger equivalence class, value will replace the value for the whole equivalence class. That doesn't seem right if value has been carefully constructed by aggregating the values of all keys in the equivalence class. It's not even possible to re-compute the value, because the per-key values have been lost.

For similar reasons, we don't allow remove(key). We would have to re-compute the sum for the whole equivalence class.

Maybe the solution is for MergeableMap<K, V> to become MergeableMap<K, V, S> where S is the summed value for an equivalence set. We remember the values of each individual key, and V get(K) and put(K, V)work on these values.Map.Entry<K, S> find(K)` returns the representative key and summed value for an equivalence set.

put(K, V) and remove(K) would be expensive because we have to scan the whole map, to find all the members of the equivalence class, to compute its sum from scratch. We could make them cheaper by adding a Function<S, V, S> subtractor as inverse for Function<S, V, S> combiner.

Of course if you don't have values, you can use MergeableMap<K, Dummy, Dummy> where

enum Dummy {
  INSTANCE;

  Dummy add(Dummy d) { return this; )
  Dummy subtract(Dummy d) { return this; }
}

is a singleton.

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

No branches or pull requests

1 participant