私はここ数日これで遊んでいます。
最初に、各ノードにエッジへの参照のセットを保持させ、各エッジにノードへの参照のセットを保持させてみました。ある種の操作では、それらを互いに等しく設定します(dosync... (ref-set...))
。1つのノードを変更するには大量の更新が必要であり、グラフの印刷には少し注意が必要だったため、これは気に入らなかった。私はオーバーライドする必要がありましたprint-method
replがオーバーフローをスタックしないようにマルチメソッド。また、既存のノードにエッジを追加したいときはいつでも、最初にグラフから実際のノードを抽出してから、あらゆる種類のエッジの更新を実行し、全員が最新バージョンを保持していることを確認する必要がありました。他のものの。また、物事が参照されていたため、何かが他の何かに接続されているかどうかを判断することは、線形時間の操作であり、エレガントではないように見えました。この方法で有用なアルゴリズムを実際に実行するのは難しいと判断するまで、私はそれほど遠くまでは行きませんでした。
次に、他の場所で参照されているマトリックスのバリエーションである別のアプローチを試しました。グラフはclojureマップであり、キーはノード(ノードへの参照ではない)であり、値はキーが隣接ノードであり、各キーの単一の値がそのノードへのエッジである別のマップであり、次のいずれかで表されます。エッジの強度を示す数値、または他の場所で定義したエッジ構造。
このように見えます1->2, 1->3, 2->5, 5->2
(def graph {node-1 {node-2 edge12, node-3 edge13},
node-2 {node-5 edge25},
node-3 nil ;;no edge leaves from node 3
node-5 {node-2 edge52}) ;; nodes 2 and 5 have an undirected edge
ノード1のネイバーにアクセスするには、(keys (graph node-1))
他の場所で定義されている関数にアクセスするか呼び出します。または、からエッジを取得する(neighbors graph node-1)
と言うこともできます。((graph node-1) node-2)
1->2
いくつかの利点:
- グラフ内のノードと隣接ノードの一定時間のルックアップ、または存在しない場合はnilを返します。
- シンプルで柔軟なエッジ定義。マップ内のノードエントリにネイバーを追加すると、有向エッジが暗黙的に存在し、その値(または詳細情報の構造)が明示的に提供されるか、nilになります。
- 何かをするために既存のノードを検索する必要はありません。不変なので、グラフに追加する前に一度定義すれば、状況が変わったときに最新バージョンを取得するために追跡する必要はありません。グラフの接続が変更された場合は、ノード/エッジ自体ではなく、グラフの構造を変更します。
- これは、マトリックス表現の最良の機能(グラフトポロジは、ノードとエッジでエンコードされていないグラフマップ自体にあり、一定時間のルックアップ、および非変化ノードとエッジ)と隣接リスト(各ノードは「隣接ノードのリスト。正規のスパース行列のような「空白」がないため、スペース効率が良い)。
- ノード間に複数のエッジを設定できます。すでに正確に存在するエッジを誤って定義した場合は、マップ構造が重複していないことを確認します。
- ノードとエッジのIDはclojureによって保持されます。インデックススキームや共通の参照ポイントを考え出す必要はありません。マップのキーと値はそれらが表すものであり、他の場所でのルックアップや参照ではありません。ノード構造はすべてnilにすることができ、一意である限り、グラフで表すことができます。
私が目にする唯一の大きな欠点は、特定の操作(追加、削除、アルゴリズム)について、開始ノードを渡すことができないことです。グラフマップ全体と開始ノードを渡す必要があります。これは、全体を単純にするために支払うのにおそらく公正な価格です。もう1つの小さな欠点(またはそうでない場合もあります)は、無向エッジの場合、各方向のエッジを定義する必要があることです。エッジの値が方向ごとに異なる場合があり、このスキームではそれが可能になるため、これは実際には問題ありません。
ここで私が見る他の唯一のことは、エッジがマップ内のキーと値のペアの存在に暗黙的に存在するため、ハイパーエッジ(つまり、3つ以上のノードを接続するもの)を定義できないことです。私が遭遇したほとんどのグラフアルゴリズム(すべて?)は2つのノードを接続するエッジのみを処理するため、これは必ずしも大したことではないと思います。