วิธีคำนวณเครือข่ายที่เล็กที่สุดที่เชื่อมต่อทุกจุดด้วย PostGIS


13

ฉันมีชุดสคริปต์ postgis ที่สร้างสองตาราง - หนึ่งในชุดของคะแนนและชุดที่สองของถนนที่ล้อมรอบพวกเขา ข้อมูลทั้งหมดอยู่ในการฉายภาพเดียวกันและผลลัพธ์ทั้งสองจะถูกเก็บไว้ใน postgres 9.2 ตารางที่มี postgis 2.1

โทโพโลยี pgrouting ของเครือข่ายถนนถูกสร้างขึ้นและตารางคะแนนมีคอลัมน์ที่มีส่วนถนนที่ใกล้ที่สุด

ฉันต้องการสร้างส่วนย่อยของเครือข่ายถนนซึ่งเป็นเครือข่ายที่เล็กที่สุดที่เชื่อมต่อทุกจุดโดยใช้บางอย่างเช่นแผนผังทอดข้ามขั้นต่ำ เครือข่ายถนนไม่ได้ถูกบอกทิศทางและค่าใช้จ่ายเป็นเพียงความยาวเส้นทาง

ฉันสามารถทำสิ่งนี้ได้ใน QGIS / Grass โดยใช้โมดูลตระกูล v.net แต่ในอุดมคติฉันก็อยากจะรักษาขั้นตอนสุดท้ายนี้ไว้ใน 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 the v.net.spanningtree และ v.net.steiner คาดหวังว่าจะได้รับชุดของจุดและเส้นในฐานะเครือข่ายที่รวมกัน

ไม่มีใครมีคำแนะนำสำหรับวิธีการทำเช่นนี้ใน PostGIS


ฉันไม่แน่ใจว่าฉันเข้าใจคำถาม แต่ docs.pgrouting.org/2.0/en/src/tsp/doc/index.html#pgr-tspอัลกอริทึมผู้ขายที่เดินทางช่วยคุณได้อย่างไร
simplexio

1
ขอบคุณ ฉันไม่กลัวจริงๆ พนักงานขายที่เดินทางถือว่าการเดินทางจาก a ถึง b ถึง c และอื่น ๆ ในแบบเชิงเส้น สิ่งที่ฉันต้องการคือเครือข่ายขั้นต่ำที่เชื่อมโยงทุกจุดเข้าด้วยกันอย่างมีประสิทธิภาพเช่นที่จุดใดสามารถเริ่มต้นการเดินทางไปยังจุดอื่น ๆ ในความรู้ที่ไม่มีเส้นทางฟุ่มเฟือยใด ๆ ที่จะหายไป ในแพลตฟอร์มอื่น ๆ สิ่งนี้มักจะทำด้วยฟังก์ชัน Spanning Tree ขั้นต่ำต้นไม้ Steiner ( 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;

ฉันคิดว่ามันไม่ได้มีประสิทธิภาพมาก


ขอบคุณสิ่งนี้จริงๆ - ขอบคุณ สิ่งนี้ทำให้ฉันมีมุมมองใหม่ในการสำรวจที่ฉันไม่เคยนึกถึง รหัสนี้จะค้นหาเพื่อนบ้านที่ไม่ได้เชื่อมต่อที่ใกล้ที่สุดจากตารางคะแนน ความซับซ้อนที่เพิ่มเข้ามาคือจุดในกรณีของฉันเชื่อมต่อกันด้วยเครือข่ายของ linestrings แต่ฉันสงสัยว่าฉันสามารถแทนที่แบบสอบถาม ST_Distance ด้วยระยะทางถนน pgRouting แม้ว่ามันจะช้ากว่าแบบสอบถามจุดที่ไม่ระบุ
เอเดรียน

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 หยุดขั้นต่ำและอาร์เรย์ ฉันมีตารางรหัสที่ต้องการ แต่ 'SELECT min (id) จาก node_table' และ 'SELECT ARRAY [id] FROM node_table' ก่อให้เกิดข้อผิดพลาดทางไวยากรณ์เมื่อใส่ลงในรหัสของคุณ แต่ทำงานเป็นรหัสยืน (ความเข้าใจที่แย่ของฉันฉัน แน่นอน)
Adrian
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.