Як обчислити найменшу мережу, яка з'єднує всі точки за допомогою PostGIS?


13

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

Створена топологія дорожньої мережі та таблиця точок містить стовпчик, що містить найближчий відрізок дороги.

Тоді я б хотів створити підмножину дорожньої мережі, яка являє собою найменшу мережу, яка з'єднує всі точки, використовуючи щось на кшталт дерева мінімального прольоту. Дорожня мережа непряма, а витрати - це просто довжина маршруту.

Я можу це зробити в QGIS / Grass, використовуючи сімейство модулів v.net, але в ідеалі я хотів би зберегти цей останній крок і в SQL.

Я переглянув нову функцію постгіс 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 подорожній продавець ?
симплексіо

1
Спасибі. Я насправді не боюся. Продавець, який подорожує, передбачає лінійний шлях від a до b до c тощо. Мені хочеться - це мінімальна мережа, яка ефективно пов'язує кожну точку, щоб будь-яка точка могла почати подорож до будь-якої іншої точки, знаючи, що немає зайвих шляхів, щоб загубитися. В інших платформах це зазвичай робиться за допомогою функції мінімального 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;

Я думаю, що це не дуже ефективно.


Дуже ціную це - дякую. Це дало мені нові кути дослідження, про які я не думав. Цей код знайде найближчих непоєднаних сусідів із таблиці пунктів. Додатковим ускладненням, яке я маю, є те, що точки в моєму випадку з'єднуються уздовж мережі рядків рядків, але мені цікаво, чи можу я замінити запит ST_Distance на відстань дороги pgRouting, хоча це було б значно повільніше, ніж запит непорушеної точки.
Адріан

2

@ Адріан, я дуже не знайомий з результатами 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 (шлях) так що в підсумковому маршруті 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 використовує лише ті крайові ідентифікатори для вирішення запиту оптимізації шляху .... можливо.


Дякую - це дуже допомагає і моя перша нова ведуча. Я зараз на це дивлюсь. Я просто намагаюся розробити, як генерувати мінімальний ідентифікатор зупинки та масив. У мене є таблиця необхідних ідентифікаторів, але 'SELECT min (id) FROM node_table' та 'SELECT ARRAY [id] FROM node_table' створюють синтаксичні помилки, коли вставляються у ваш код, але працюють як вільно стоячий код (моє погане розуміння впевнено)
Адріан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.