2014-04-09 125 views
0

我想執行一些邊緣操作:具有邊緣並增加邊緣權重。具有邊緣,增加邊緣重量和複雜度

我嘗試這樣做:

from igraph import * 
g = Nexus.get("karate") 
if g.es.select(_from=0, _target=1): 
    g.es.select(_from=0, _target=1)['weight'] += 1 
else: 
    g.add_edge(0, 1, weight=1) 

我有問題:運營商增加:

g.es.select(_from=0, _target=1)['weight'] += 1 # not work 

不行的,然而,當流程中添加新邊的權重這個工程。例如: -

g.es.select(_from=0, _target=1)['weight'] = 200000 # this is ok 

另外我想的東西更有效率或優雅。例如,在庫IGRAPH中執行此操作的操作/函數的計算效率更高?

回答

3

好了,還有,你應該知道理解爲什麼增加操作不起作用的幾件事情。

首先,g.es.select()返回EdgeSeq對象,即邊緣序列。在你的情況,如果邊緣存在,則返回長度爲1的邊緣序列,否則返回長度爲零的邊序列:

>>> edges = g.es.select(_from=0, _to=1) 
>>> edges 
<igraph.EdgeSeq at 0x10ce62350> 
>>> len(edges) 
1 

其次,使用上一個EdgeSeq['weight']操作會返回一個列表包含每個邊緣在EdgeSeq重屬性:

>>> edges["weight"] 
[42] 

三,x += 1實質上等同於x = x + 1,所以當你嘗試使用+=增加體重,你試試到追加 1而不是(因爲x是一個列表,請參閱我的第二點),這將無法正常工作,因爲您只能追加另一個列表到列表中。此外,你得到的名單只是一個複製邊緣屬性無論如何,所以修改它不會改變邊緣屬性:

>>> edges["weight"] += 1 
TypeError: 'int' object is not iterable 
>>> edges["weight"] += [1] 
>>> edges["weight"] 
[42] 

最簡單的辦法是從EdgeSeq得到一個Edge對象,然後修改即,由於使用上的Edge['weight']操作將返回重量爲一個單一的元素,你可以使用+=運營商在一個簡潔的方式提高和寫回給力:

>>> edge = edges[0] 
>>> edge 
igraph.Edge(<igraph.Graph object at 0x10d788148>, 0, {'weight': 42}) 
>>> edge["weight"] += 1 
>>> edge 
igraph.Edge(<igraph.Graph object at 0x10d788148>, 0, {'weight': 43}) 

如何在這種情況下,我會避免g.es.select,因爲它會評估g.es中的每條邊,以便找到滿足條件的邊。取而代之的是,我會用g.get_eid()得到邊緣的ID我正在尋找,然後用g.es[edge_id]找到合適的邊緣:

eid = g.get_eid(0, 1, error=False) 
if eid >= 0: 
    g.es[eid]["weight"] += 1 
else: 
    g.add_edge(0, 1, weight=1) 

的另一種方式是認識到的igraph對象可以被視爲鄰接矩陣。當圖形具有名爲weight的邊緣屬性時,調用g[source, target]返回給定源頂點和目標頂點之間邊的權重,這也可用於設置當然權重。當圖形沒有名爲weight的邊緣屬性時,如果連接了sourcetarget,則g[source, target]僅爲1,否則爲零。所以,你也可以這樣做:

g = Nexus.get('karate') 
g.es["weight"] = 1  # to ensure that existing edges have weight=1 
g[0,1] += 1 
1

對於剛剛工作,(既沒有效率也不優雅)

>>> from igraph import * 
>>> g = Nexus.get('karate') 
>>> print g.es.select(_from=0, _target=1)['weight'] # to see the value 
[4.0] 
>>> if g.es.select(_from=0, _target=1): 
...  buff = g.es.select(_from=0, _target=1)['weight'] 
...  buff[0] += 1 
...  g.es.select(_from=0, _target=1)['weight'] = buff 
... else: 
...  g.add_edge(0, 1, weight=1) 
>>> print g.es.select(_from=0, _target=1)['weight'] # to see the value 
[5.0] 
0

我強烈建議networkx爲此。這是相同的代碼。

import networkx as nx 
G = nx.karate_club_graph() 

#you can assign all with a starting weight 
for x,y in G.edges_iter(): 
    G.add_edge(x,y,weight=1) 

# then add more as you come across them. 
for x,y in SomeIterableAffectingTheGraph: 
    G.edge[x][y]['weight']+=1