I have a equivalence relation R on a set A. How can I build equivalence classes on A? It's something like groupBy do, but between all the elements, not only neighbors.
For example, equal is equivalence relation (it is reflexive, symmetric and transitive binary relation):
type Sometuple = (Int, Int, Int)
equal :: Sometuple -> Sometuple -> Bool
equal (_, x, _) (_, y, _) = x == y
It is actually a predicate that connect 2 Sometuple elements.
λ> equal (1,2,3) (1,2,2)
True
So, how can I build all equivalence classes on [Sometuple] based on equal predicate? Something like that:
equivalenceClasses :: (Sometuple -> Sometuple -> Bool) -> [Sometuple] -> [[Sometuple]]
λ> equivalenceClasses equal [(1,2,3), (2,1,4), (0,3,2), (9,2,1), (5,3,1), (1,3,1)]
[[(1,2,3),(9,2,1)],[(2,1,4)],[(0,3,2),(5,3,1),(1,3,2)]]
An equivalence relation is a relationship on a set, generally denoted by “∼”, that is reflexive, symmetric, and transitive for everything in the set. 1. (Reflexivity) a ∼ a, 2. (Symmetry) if a ∼ b then b ∼ a, 3. (Transitivity) if a ∼ b and b ∼ c then a ∼ c.
Equivalence relations are often used to group together objects that are similar, or “equiv- alent”, in some sense. Example: The relation “is equal to”, denoted “=”, is an equivalence relation on the set of real numbers since for any x, y, z ∈ R: 1. (Reflexivity) x = x, 2.
Hence, only two possible relation are there which are equivalence.
To prove an equivalence relation, you must show reflexivity, symmetry, and transitivity, so using our example above, we can say: Reflexivity: Since a – a = 0 and 0 is an integer, this shows that (a, a) is in the relation; thus, proving R is reflexive. Symmetry: If a – b is an integer, then b – a is also an integer.
If you can define a compatible ordering relation, you can use
equivalenceClasses equal comp = groupBy equal . sortBy comp
which would give you O(n*log n) complexity. Without that, I don't see any way to get better complexity than O(n^2), basically
splitOffFirstGroup :: (a -> a -> Bool) -> [a] -> ([a],[a])
splitOffFirstGroup equal xs@(x:_) = partition (equal x) xs
splitOffFirstGroup _ [] = ([],[])
equivalenceClasses _ [] = []
equivalenceClasses equal xs = let (fg,rst) = splitOffFirstGroup equal xs
in fg : equivalenceClasses equal rst
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With