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