Làm cách nào để tính toán mạng nhỏ nhất kết nối tất cả các điểm bằng PostGIS?


13

Tôi có một tập các tập lệnh postgis tạo ra hai bảng - một trong những tập hợp điểm và tập thứ hai là tập hợp các đường bao quanh chúng. Tất cả dữ liệu nằm trong cùng một phép chiếu và cả hai kết quả đầu ra được lưu trữ trong các bảng postgres 9.2 với postgis 2.1

Cấu trúc liên kết của mạng lưới đường đã được tạo và bảng điểm có một cột chứa đoạn đường gần nhất.

Sau đó, tôi muốn tạo một tập hợp con của mạng lưới đại diện cho mạng nhỏ nhất kết nối tất cả các điểm bằng cách sử dụng một cái gì đó giống như một cây bao trùm tối thiểu. Mạng lưới đường bộ không bị ảnh hưởng và chi phí chỉ đơn giản là chiều dài tuyến đường.

Tôi có thể thực hiện điều này trong QGIS / Grass bằng cách sử dụng nhóm mô-đun v.net nhưng lý tưởng nhất là tôi cũng muốn giữ bước cuối cùng này trong SQL.

Tôi đã xem chức năng postgis apspWarshall mới nhưng tôi không biết làm thế nào nó có thể được khuyến khích để tập trung năng lượng của nó vào việc kết nối các điểm chứ không phải toàn bộ mạng.

Đây là kịch bản ngắn mà tôi đã cùng nhau cố gắng tạo ra một khung để giải quyết vấn đề này nhưng tôi không thể thấy nơi nào có thể tập trung chức năng để bắt đầu với một tập hợp con của các cạnh.

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

Trong các bài toán đường dẫn ngắn nhất, hàm yêu cầu bắt đầu và kết thúc nhưng dường như không phải trong tất cả các vấn đề về điểm. Tương tự trong Grass, v.net.spanningtree và v.net.steiner mong đợi một tập hợp các điểm và đường như một mạng kết hợp để hoạt động.

Có ai có một gợi ý cho cách làm điều này trong PostGIS không?


Tôi không chắc là tôi hiểu câu hỏi nhưng liệu docs.pgrouting.org/2.0/en/src/tsp/doc/index.html#pgr-tsp Thuật toán Nhân viên bán hàng du lịch có giúp bạn không?
Simplexio

1
Cảm ơn. Nó không thực sự tôi sợ. Nhân viên bán hàng du lịch giả định một hành trình từ a đến b đến c và cứ thế theo kiểu tuyến tính. Điều tôi muốn là mạng tối thiểu liên kết mọi điểm với nhau một cách hiệu quả sao cho bất kỳ điểm nào cũng có thể bắt đầu một hành trình đến bất kỳ điểm nào khác trong kiến ​​thức rằng không có bất kỳ con đường thừa nào bị lạc. Trong các nền tảng khác, điều này thường được thực hiện với chức năng Cây Spanning tối thiểu, Cây Steiner ( en.wikipedia.org/wiki/Steiner_tree_probols ) hoặc tương tự. Nếu bạn thích, TSP là công cụ tuyệt vời cho công ty hậu cần nhưng tôi muốn lập kế hoạch cho những con đường họ sẽ sử dụng.
Adrian

Câu trả lời:


2

Câu trả lời này không đầy đủ hoặc đã được thử nghiệm, nhưng hãy thử một cái gì đó như thế này:

theo câu hỏi / 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;

Tôi nghĩ rằng điều này là không hiệu quả.


Thực sự đánh giá cao điều này - cảm ơn bạn. Điều này đã cho tôi một số góc độ mới để khám phá mà tôi chưa từng nghĩ đến. Mã này sẽ tìm các hàng xóm không được kết nối gần nhất từ ​​một bảng điểm. Sự phức tạp thêm vào mà tôi có là các điểm trong trường hợp của tôi được kết nối dọc theo một mạng lưới linestrings nhưng tôi tự hỏi liệu tôi có thể thay thế truy vấn ST_Distance bằng khoảng cách đường pgRouting hay không, mặc dù nó sẽ chậm hơn đáng kể so với truy vấn điểm chưa được xử lý.
Adrian

2

@Adrian, tôi thực sự không quen thuộc với các kết quả mở rộng, tuy nhiên tài liệu rất chi tiết. Câu trả lời của tôi dựa trên hàm hai bước, sẽ rất thiếu trong SQL nhưng [có khả năng] tạo ra kết quả. Giải pháp [chưa được kiểm tra] này sẽ KHÔNG tối ưu hóa điểm khởi đầu tốt nhất, nhưng sẽ giảm toàn bộ mạng tuyến xuống chỉ các cạnh kết nối tất cả các điểm dừng, sau đó định tuyến hiệu quả đến tất cả các điểm dừng.

Bước 1 (lựa chọn phụ của tập hợp mạng đường bộ kết nối tất cả các điểm dừng) Điều này sử dụng chức năng định tuyến nhiều đích (đường dẫn K Dijkstr) để trả về một tập hợp các đường dẫn (khi chi phí <> -1) thực sự kết nối tất cả các đường dẫn của bạn dừng lại

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

Vấn đề tôi gặp ở đây là cú pháp để lắp ráp một mảng từ bảng dừng của bạn, vì nó không thực sự được mô tả trong câu hỏi. Tuy nhiên, giả sử rằng cú pháp SQL có thể tập hợp mảng đó và điểm dừng id tối thiểu phải là điểm bắt đầu cho tất cả các đường dẫn K đến các điểm dừng đích còn lại.

Bước 2 (lựa chọn cuối cùng của các đường dẫn tối thiểu dựa trên các đường dẫn mạng con đường con ở trên kết nối tất cả các điểm dừng) Đây thực chất là những gì bạn đã bắt đầu, nhưng tôi đề nghị bạn nên kết nối mạng đường của mình với kết quả ban đầu trên id1 (đường dẫn) sao cho chỉ có tập hợp con đường được sử dụng trong định tuyến Field-Warshal cuối cùng :

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

Vì vậy, tóm lại ... truy vấn định tuyến k_dijkstra_path bên trong làm giảm tổng mạng đường xuống chỉ còn các đường dẫn kết nối tất cả các điểm dừng của bạn, sau đó định tuyến fField_Warshal bên ngoài chỉ sử dụng các id cạnh đó để giải quyết truy vấn tối ưu hóa đường dẫn .... có thể.


Cảm ơn bạn - điều này rất hữu ích và là người dẫn đầu tiên mới của tôi. Tôi đang nhìn nó bây giờ. Tôi chỉ đang cố gắng tìm ra cách tạo id dừng tối thiểu và mảng. Tôi có một bảng gồm các id bắt buộc nhưng 'CHỌN min (id) TỪ node_table' và 'CHỌN ARRAY [id] TỪ node_table' tạo ra lỗi cú pháp khi chèn vào mã của bạn nhưng hoạt động như mã đứng tự do (tôi hiểu kém chắc chắn)
Adrian
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.