Как рассчитать наименьшую сеть, которая соединяет все точки, используя PostGIS?

13

У меня есть набор сценариев postgis, которые генерируют две таблицы - одну из набора точек и вторую группу дорог, которые их окружают. Все данные находятся в одной проекции, и оба вывода хранятся в таблицах postgres 9.2 с postgis 2.1

Была создана топология pgrouting сети дорог, и в таблице точек есть столбец, содержащий ближайший сегмент дороги.

Затем я хотел бы создать подмножество дорожной сети, которая представляет собой наименьшую сеть, которая соединяет все точки, используя что-то вроде минимального связующего дерева. Дорожная сеть является ненаправленной, а затраты - это просто длина маршрута.

Я могу сделать это в QGIS / Grass, используя семейство модулей v.net, но в идеале я бы хотел сохранить этот последний шаг и в SQL.

Я посмотрел на новую функцию postgis apspWarshall, но не знаю, как можно побудить его сосредоточиться на соединении точек, а не на всей сети.

Это короткий сценарий, который я собрал, пытаясь создать структуру, чтобы решить эту проблему, но я не вижу, где можно сфокусировать функцию, чтобы начать с подмножества ребер.

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 Traveling Sales Person алгоритм?
симплексио
1
Благодарю. Боюсь, на самом деле это не так. Командующий коммивояжер предполагает путешествие от a до b к c и т. Д. Линейным образом. То, что я хочу, - это минимальная сеть, которая эффективно связывает каждую точку, так что любая точка может начать путешествие в любую другую точку в знании, что нет никаких лишних путей, которые можно потерять. На других платформах это обычно делается с помощью функции Minimum Spanning Tree, Steiner Tree ( en.wikipedia.org/wiki/Steiner_tree_problem ) или аналогичной. Если хотите, TSP отлично подходит для логистической компании, но я хочу спланировать дороги, которые они будут использовать.
Адриан

Ответы:

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;

Я думаю, что это не очень эффективно.

youseeus
источник
Действительно ценю это - спасибо. Это дало мне новые возможности для исследования, о которых я даже не думал. Этот код найдет ближайших неподключенных соседей из таблицы точек. Дополнительное осложнение, которое у меня есть, заключается в том, что точки в моем случае связаны между собой сетью линейных линий, но мне интересно, смогу ли я заменить запрос ST_Distance расстоянием дороги pgRouting, хотя это будет значительно медленнее, чем запрос точки без маршрута.
Адриан
2

@ Adrian, я действительно не знаком с результатами pgrouting, однако документация очень подробная. Мой ответ основан на двухступенчатой ​​функции, которая будет очень неэффективна в 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 (путь). так что в конечном маршруте фельдмаршала используется только подмножество дорог :

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 использует только эти идентификаторы ребер для решения запроса оптимизации пути .... возможно.

JasonInVegas
источник
Спасибо - это очень полезно и мое первое новое руководство. Я смотрю на это сейчас. Я просто пытаюсь понять, как создать минимальный идентификатор остановки и массив. У меня есть таблица с необходимыми идентификаторами, но «SELECT min (id) FROM node_table» и «SELECT ARRAY [id] FROM node_table» выдают синтаксические ошибки при вставке в ваш код, но работают как автономный код (мое плохое понимание, что я конечно)
Адриан