簡體   English   中英

如何找到限制與源的距離的最短路徑?

[英]How to find shortest path limiting the distance from source?

幾天前我開始學習 Neo4j。

我正在使用它來尋找最佳路徑並進行一些分析。

邏輯是一個人 (id, name) 可以通過一些街道 (id, name) 去餐廳 (id, name)。 它們之間的聯系是有代價的。 PS:所有街道之間都有聯系。 例如:

(Person {id: 1})-[CONNECTION {cost:10}]->(Street {id: 1})
(Person {id: 1})-[CONNECTION {cost:11}]->(Street {id: 2})
(Street {id: 1})-[CONNECTION {cost:4}]->(Street {id: 2})
(Street {id: 2})-[CONNECTION {cost:11}]->(Restaurant {id: 1})
(Street {id: 2})-[CONNECTION {cost:7}]->(Restaurant {id: 2})

...

我正在使用 Dijkstra 為特定人員找到所有餐廳的最佳路徑。 但問題是我無法設置最大深度,我想限制最多 3 條街道。 我怎么能那樣做?

CALL gds.graph.project(
  'Person-Street-Restaurant',    
  ['Person', 'Street' 'Restaurant'],   
  'CONNECTION',
  {
    relationshipProperties: 'cost'
  }
)

MATCH (source:Person{id:1})
CALL gds.allShortestPaths.dijkstra.stream('Person-Street-Restaurant', {
    sourceNode: source,
    relationshipWeightProperty: 'cost'
})
YIELD sourceNode, targetNode, totalCost, nodeIds
WHERE 'Restaurant' IN LABELS(gds.util.asNode(targetNode))
RETURN
    gds.util.asNode(sourceNode).name AS sourceNodeName,
    gds.util.asNode(targetNode).name AS targetNodeName,
    totalCost,
    [nodeId IN nodeIds | gds.util.asNode(nodeId).name] AS nodeNames,
    SIZE(nodeIds) AS hops
ORDER BY totalCost

圖片示例

最佳路徑是:P->S#3->S#4->S#5->R,總成本7。但如果我限制為2條街道,應該是P->S#1->S# 2->R,總成本 10。 PS:在這個例子中很簡單,因為我們的連接較少,但在實際情況下,我們有很多,所有街道之間都有連接。

簡單的:

如果您的圖庫有訪問者

  • 訪問者檢查與源的距離,如果太遠則停止搜索。

如果您願意使用 Neo4J 的替代品,InfiniteGraph 有更好的方法來執行加權圖查詢。 InfiniteGraph 提供了一個權重計算器運算符,您可以定義並在查詢中使用該運算符。 您可以基於普通節點和邊謂詞約束查詢,並且可以設置路徑的最大長度。

鑒於您的圖表,我將按如下方式定義架構:

UPDATE SCHEMA {
    CREATE CLASS Person {
        name : String,
        id   : Integer,
        location: REFERENCE { REFERENCED Intersection }
                  
    },
    CREATE CLASS Intersection {
        streets : List { REFERENCE { REFERENCED Street }}
    },
    CREATE CLASS Street {
        cost :  Integer,
        intersections: List { REFERENCE { REFERENCED Intersection }},
        business: List { REFERENCE { REFERENCED Business }}
    },
    CREATE CLASS Business {
        name :  String
    }
}

您可以按如下方式定義重量計算器:

CREATE WEIGHT CALCULATOR routeCost {
    minimum: 0,
    default: 0,
    edges: {
        ()-[s:Street]->()   : s.cost
    }
};

接下來,您可以編寫查詢以查找兩個節點之間成本最低的路線:

MATCH m = LIGHTEST routeCost (
            (:Person {id == 1})-[1..20]->(:Restaurant {name == "H"})
          )
          RETURN m;

如果您只想查找總權重小於某個值的路徑,可以添加 MAX WEIGHT 子句:

MATCH m = LIGHTEST routeCost (
            MAX WEIGHT 13.0 routeCost (
              (:Person {id == 1})-[1..20]->(:Restaurant {name == "H"})
            )
          )
          RETURN m;

在您的情況下,您只需將 [1..20] 修改為 [1..3] 即可限制您想要允許的街道數量。

此外,由於您已經對邊緣的成本進行了編碼,因此權重計算器中的邊緣權重函數將簡單地返回 s.cost 而沒有乘數。

InfiniteGraph 支持 20、30 或更多度的非常深的路徑查詢,而且速度非常快。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM