簡體   English   中英

是否可以在圖論中為節點添加權重/概率(使用networkx)

[英]Is it possible to add a weight/probability to a node in graph theory(using networkx)

我正在使用networkx(用於python的庫來處理圖形)。 我基本上有各種邊緣的節點,但想看看如果它使用連接最多的節點,路徑會是什么樣子。

我可以使用此命令查看連接數:

len(G.edges(CurrentNode))

我可以獲得邊數,但我不知道如何將其應用於列表作為路徑。 例如,我可以將此數字添加為屬性,但我不認為在查找路徑時會考慮屬性,並且因為我在連接邊緣后添加此數字,所以我無法將權重添加到邊緣本身。 另一個問題是得分越高我想要跟隨的路徑越多但是我認為它遵循最低加權邊緣。

我想知道其他人根據節點的某些特征采取什么方法來尋找路徑? 如果有人知道如何為networkx做這件事,太好了! 但我認為networkx有很多功能,所以如果我能得到理論或一般方法,我相信我能找到一種方法在python中做到這一點。

更新:對不起我可能會解釋錯了。 我知道我可以向節點添加屬性,但我不確定如何根據這些屬性做出路徑決策。 所以在我的情況下,基於某些條件,我在節點之間添加邊緣。 每組節點代表不同的一天(day1data ..,day2data ..,day3data ..),所以我只在某些規則匹配時才將第一天的幾個節點連接到第二天的節點。 一旦我連接了邊緣,我希望在選擇路徑時考慮那些邊緣。 所以我在當前每個節點添加了一個屬性'weight',它基本上是連接該節點的邊的總數。 我的問題是,權重屬性不用於任何路徑決策,因為它是我創建並標記自己的屬性(我可以創建一個名為'abc'='hello world'的標簽,它會將該屬性應用於節點)。 如何在創建路徑時考慮這個權重(邊緣已經創建,所以我不認為我可以返回並重新創建它們)?

您當然可以在NetworkX中為邊緣添加權重。 實際上,您可以為邊設置任意數據,因為它基本上是一個dict

In [30]: import networkx as nx

In [31]: G = nx.Graph()

In [32]: G.add_edge(1, 2, weight=3, type="green")

In [33]: G[1][2]
Out[33]: {'type': 'green', 'weight': 3}

In [34]: G[1][2]["weight"]
Out[34]: 3

此外,您可以在添加邊之后更改邊(或節點)的參數。

In [35]: G[1][2]["weight"] = 5

In [36]: del G[1][2]["type"]

In [37]: G[1][2]["color"] = "green"

In [38]: G[1][2]
Out[38]: {'color': 'green', 'weight': 5}

當然,您可以根據權重(或權重參數中指定的任何其他屬性)計算路徑。

In [39]: G.add_edge(1, 3, weight=1)

In [40]: G.add_edge(2, 3, weight=2)

In [41]: G.edges()
Out[41]: [(1, 2), (1, 3), (2, 3)]

In [42]: nx.shortest_path(G, source=1, target=2, weight="weight")
Out[42]: [1, 3, 2]

對於您的情況,決定邊權重可能會很棘手。 請記住,加權最短路徑通常使用Djikstra算法計算,並且它有利於較小的權重。 它還需要正重量。 一種可能的解決方案是將權重1/max(k_i,k_j)分配給邊(i,j) ,其中k_ik_j是節點ij的度。

在轉移概率上計算最短路徑的正確方法是將邊權重變換為表示驚人的:即概率的負對數。 這導致權重為正,並且任何給定的最短路徑然后被解釋為最小化意外。 由於Dijkstra的算法總結了權重,它在日志空間中這樣做,這意味着它實際上是乘以概率。 為了恢復觀察任何給定最短路徑的聯合概率,那么,你只需采取負面意外的指數。

考慮自制attribute的唯一方法是在框架中編輯文件。

您要查找的文件是networkx/algorithms/shortest_paths/weighted.py

在這里會有一個get_weight function的lambda聲明,如下所示:

if G.is_multigraph():
    get_weight = lambda u, v, data: min(
        eattr.get(weight, 1) for eattr in data.values())
else:
    get_weight = lambda u, v, data: data.get(weight, 1)

我想給我的node一定的重量,所以我修改它像這樣:

if G.is_multigraph():
    get_weight = lambda u, v, data: min(
        eattr.get(weight, 1) for eattr in data.values())
else:
    get_weight = lambda u, v, data: (data.get(weight,0) + nx.get_node_attributes(G, "node_weight").get(v,0)) 

我將默認邊權重設置為0: data: data.get(weight,0)並添加了我自己的屬性“node_weight”的值(默認為0)。

data: (data.get(weight,0) + nx.get_node_attributes(G, "node_weight").get(v,0))

v是圖中下一個可到達的node

現在,您可以在創建圖表后設置attribute

nx.set_node_attributes(G, "node_weight", {1:3.5, 2:56})

來自NetworkX教程

>>> G.add_edge(1, 2, weight=4.7 )
>>> G.add_edges_from([(3,4),(4,5)], color='red')
>>> G.add_edges_from([(1,2,{'color':'blue'}), (2,3,{'weight':8})])
>>> G[1][2]['weight'] = 4.7
>>> G.edge[1][2]['weight'] = 4

看起來事后可以添加權重。

暫無
暫無

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

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