PostGISを使用してすべてのポイントを接続する最小のネットワークを計算する方法は?


13

2つのテーブルを生成するpostgisスクリプトのセットがあります-1つはポイントのセット、もう1つはそれらを囲む道路のセットです。すべてのデータは同じプロジェクションにあり、両方の出力はpostgis 2.1でpostgres 9.2テーブルに保存されます

道路ネットワークのトポロジーを作成し、ポイントテーブルに最も近い道路セグメントを含む列があります。

次に、最小全域木などを使用してすべてのポイントを接続する最小のネットワークを表す道路ネットワークのサブセットを生成します。道路ネットワークは無向であり、コストは単にルートの長さです。

モジュールのv.netファミリを使用してQGIS / Grassでこれを行うことができますが、理想的にはSQLでもこの最終ステップを維持したいと思います。

新しいapspWarshall postgis関数を見てきましたが、ネットワーク全体ではなくポイントの接続にエネルギーを集中するように奨励する方法については迷っています。

これは、これを解決するためのフレームワークを作成するために作成した短いスクリプトですが、エッジのサブセットから開始するために関数をフォーカスできる場所がわかりません。

SELECT seq, id1 AS node, id2 AS edge, cost, the_geom
FROM   pgr_apspWarshall('SELECT gid AS id, 
                                source, 
                                target, 
                                st_length(the_geom) AS cost 
                         FROM   road_network
                        ',
                        false, false
                       ) AS tree
JOIN   road_network As roads
ON     tree.id2 = roads.gid

単一パスの最短パスの問題では、関数は開始と終了を要求しますが、明らかにすべてのポイントの問題ではありません。同様に、Grassでは、v.net.spanningtreeとv.net.steinerは、連携するネットワークとして一連のポイントとラインを使用することを想定しています。

PostGISでこれを行う方法についての提案はありますか?


私は質問を理解していると確信していませが、 docs.pgrouting.org / 2.0 / en / src / tsp / doc / index.html#pgr-tsp巡回セールスパーソンアルゴリズムが役立ちますか?
シンキシオ14

1
ありがとう。本当に怖いわけではありません。巡回セールスマンは、aからb、cなどへの直線的な旅を想定しています。私が欲しいのは、すべてのポイントを効率的にリンクし、迷子になる余分なパスがないという知識のあるポイントが他のポイントへの旅を始めることができる最小限のネットワークです。他のプラットフォームでは、これは通常、最小スパニングツリー関数、シュタイナーツリー(en.wikipedia.org/wiki/Steiner_tree_problem)または同様のもので行われます。必要に応じて、TSPは物流会社には最適ですが、使用する道路を計画したいと思います。
エイドリアン14

回答:


2

この答えは完全またはテストされていませんが、次のようなものを試してください。

質問/ 39210によると:

with index_query as (
SELECT
        ,ST_Distance(i.geom, i.b_geom) AS dist
        ,ST_MakeLine(i.geom, i.b_geom) as geom
FROM(
SELECT
        ,a.geom
        ,b.geom AS b_geom
        ,rank() OVER (PARTITION BY a.id ORDER BY ST_Distance(a.centroid_geom, b.the_geom)) AS pos
FROM points a, points b 
WHERE a.id <> b.id) i
WHERE pos = 1
) select ST_Union(geom) from index_query;

これはあまり効率的ではないと思います。


本当に感謝します-ありがとう。これは、私が考えもしなかった新しい探求の角度を与えてくれました。このコードは、ポイントのテーブルから最も近い接続されていない近傍を見つけます。私が持っている追加の複雑さは、私のケースのポイントが線ストリングのネットワークに沿って接続されていることですが、ルーティングされていないポイントクエリよりも大幅に遅くなりますが、ST_DistanceクエリをpgRouting道路距離に置き換えることができるのでしょうか?
エイドリアン

2

@Adrian、私は本当にグラウト注入の結果に不慣れですが、ドキュメントは非常に詳細です。私の答えは2段階の関数に基づいています。この関数はSQLでは非常に非効率ですが、[おそらく]結果を生成します。この[テストされていない]ソリューションは最適な出発点である最適化を行いませんが、ルートネットワーク全体をすべてのストップに接続するエッジのみに削減し、すべてのストップに効率的にルーティングします。

ステップ1(すべてのストップを接続する道路ネットワークサブセットのサブ選択)これは、複数の目的地(K Dijkstrパス)ルーティング機能を使用して、(コスト<> -1の場合)実際にすべてのストップを接続するパスのコレクションを返します停止します。

SELECT id1 as path, st_astext(st_linemerge(st_union(b.the_geom))) as the_geom
FROM pgr_kdijkstraPath(
SELECT id, source, target, cost FROM edge_table’,
min(all_your_stop_ids), [array_of_all_your_stop_ids], false, false
) a,
edge_table b
WHERE a.id3=b.id
GROUP by id1
ORDER by id1

ここで問題になっているのは、ストップテーブルから配列を組み立てる構文です。これは質問で実際に説明されていないためです。ただし、SQL構文がその配列をアセンブルでき、最小IDストップが残りのターゲットストップへのすべてのKパスの開始点であると仮定します。

ステップ2(すべてのストップを接続する上記のサブセット道路ネットワークパスに基づく最小パスの最終選択)これは基本的にあなたが始めたものですが、道路ネットワークをid1(パス)の初期結果に等加することを提案しますそのため、最終的なField-Warshalルーティングでは道路のサブセットのみが使用されます

SELECT seq, id1 AS node, id2 AS edge, cost, the_geom
FROM   pgr_apspWarshall('SELECT R.gid AS id, 
                                R.source, 
                                R.target, 
                                st_length(R.the_geom) AS cost 
             FROM   road_network AS R JOIN
                   (SELECT id1 as path
                     FROM pgr_kdijkstraPath(
                            ’SELECT id, source, target, cost FROM edge_table’,
                            min(all_your_stop_ids), 
                            [array_of_all_your_stop_ids], false, false
                           ) a,
                     edge_table b
                    WHERE a.id3=b.id
                    GROUP by id1
                    ORDER by id1
                        ',
                        false, false
                  ) AS  Just_K_Paths
         on R.id1 = just_K_paths.id1',       /* this join reduces R down to K paths */
         false, false
        ) AS tree
  JOIN   road_network As roads
  ON     tree.id2 = roads.gid

つまり、要約すると...内側のk_dijkstra_pathルーティングクエリは、道路網全体をすべてのストップに接続するパスのみに削減し、外側のfField_WarshalルーティングはそれらのエッジIDのみを使用してパス最適化クエリを解決します。


ありがとう-これは非常に役に立ち、私の最初の新しいリードです。今見ています。最小ストップIDと配列を生成する方法を考えています。必要なIDのテーブルがありますが、 'SELECT min(id)FROM node_table'および 'SELECT ARRAY [id] FROM node_table'は、コードに挿入されたときに構文エラーを生成しますが、独立したコードとして動作します確かに)
エイドリアン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.