有边缘,增加边缘重量和复杂性

时间:2014-04-09 23:41:28

标签: python igraph

我想执行一些边缘操作:有边缘并增加边缘权重。

我试过了:

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

然而,当进程添加新的边缘权重时,这不起作用。 E.g:

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

另外,我想要一些更高效或更优雅的东西。例如,在库IGRAPH中执行此操作的操作/函数在计算上更有效吗?

3 个答案:

答案 0 :(得分:3)

好的,你应该知道一些事情,以了解为什么增加操作不起作用。

首先,g.es.select()返回EdgeSeq个对象,即边缘序列。在您的情况下,如果边存在,则返回长度为1的边序列,否则返回长度为零的边序列:

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

其次,在['weight']上使用EdgeSeq操作会返回列表,其中包含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]

最简单的解决方案是从Edge获取单个EdgeSeq对象并对其进行修改,因为在['weight']上使用Edge操作会将权重返回为单个元素,您可以使用+=运算符以简洁的方式增加并写回边缘:

>>> 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的边缘属性时,如果g[source, target]source连接,target只是1,否则为零。所以,你也可以这样做:

g = Nexus.get('karate')
g.es["weight"] = 1       # to ensure that existing edges have weight=1
g[0,1] += 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]

答案 2 :(得分: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