グラフをノードとエッジのセットとして記述したレコードがあります。
data MyGraph a = MyGraph {
nodes :: Set a,
edges :: Set (a,a),
components :: UnionFindM a -- ?
}
emptyGraph = MyGraph{
nodes = empty, edges = empty,
components = emptyUnionFind singleton union --?
}
addEdge g (a,b) = g{
edges = (a,b) `insert` (edges g),
components = (components g) >>= (equate a b) -- ?
}
エッジを削除することはないので、接続されたコンポーネントをマップしたいので、union-find 構造 (エッジを追加するときに簡単に更新できます) を使用して接続されたコンポーネントを追跡したいと思います。それらもセットのセットとして保管してください。そしてもちろん、ノードのコンポーネントを取得したいと考えています。
等価ライブラリを見つけました。これを選択したのは、 union-findとpersistent-equivalenceを使用してセットを作成する方法がわからず、値の範囲を知る必要があるためです。
これでリレーションを作成し、以下を使用してセットのセットを返すことができます:
import Control.Monad(liftM)
import Data.Equivalence.Monad
import Data.Set(singleton, union, fromList)
f = runEquivM singleton union $ do
equate "foo" "bar"
equate "bar" "baz"
(liftM fromList) $ mapM classDesc ["foo","bar","baz","one","two"]
>>> f
fromList [fromList ["bar","baz","foo"],fromList ["one"],fromList ["two"]]
ただし、使用fromList
は非常に単純です。内部データ構造からすべての等価クラスを直接取得できるはずです。
さらに重要なことは、データ構造に同値関係を格納するにはどうすればよいかということです。