Python 一种高效的成对计算算法

Python 一种高效的成对计算算法,python,algorithm,data-structures,Python,Algorithm,Data Structures,我有一个代理列表a={a1,a2,a3,…,an},其中每个代理可以与零个或多个其他代理配对。例如,对于n=6,我可以: a1: a2, a3, a5 a2: a1, a3, a4 a3: a1, a2. a5 a4: a2 a5: a1, a3 a6: 每一对都相互作用,每一个代理都会从这种作用中获得一个值(例如,他们可以玩游戏,但这里可以抽象出相互作用的细节)我感兴趣的是基于给定的成对结构计算和存储这些交互的结果,如上文所述 显然,一个简单的算法是遍历每个代理,然后逐个计算与每个交互伙伴的

我有一个代理列表
a={a1,a2,a3,…,an}
,其中每个代理可以与零个或多个其他代理配对。例如,对于
n=6
,我可以:

a1: a2, a3, a5
a2: a1, a3, a4
a3: a1, a2. a5
a4: a2
a5: a1, a3
a6:
每一对都相互作用,每一个代理都会从这种作用中获得一个值(例如,他们可以玩游戏,但这里可以抽象出相互作用的细节)我感兴趣的是基于给定的成对结构计算和存储这些交互的结果,如上文所述

显然,一个简单的算法是遍历每个代理,然后逐个计算与每个交互伙伴的成对交互但是,很明显,这种方法会重复一些(或可能是许多)计算。使用上述示例:

当我们完成代理
a1
时,我们已经获得了
(a1,a2)
(a1,a3)
、和
(a1,a5)
,因此当我们为代理
a2
a3
a5
进行计算时,这些对之间的后续计算变得多余

一种改进的算法是在两个维度(即沿着代理本身和它们各自的伙伴)上按升序对输入结构进行排序,如上例所示,这样对于每个代理(例如
a3
),我们只需要计算该代理之间的交互(
a3
)而那些比他“高”的(
a5
),因为我们知道他和“低”合伙人之间的互动(
(a1,a3)
(a2,a3)
)已经被计算出来了

我想知道是否有不同的更好的算法来解决这个问题?我所说的更好,是指在时间和空间上更高效的计算。

为了营救

>>> from itertools import combinations
>>> agents=['a1','a2','a3','a4','a5']
>>> list(combinations(agents, 2))
[('a1', 'a2'), ('a1', 'a3'), ('a1', 'a4'), ('a1', 'a5'), 
 ('a2', 'a3'), ('a2', 'a4'), ('a2', 'a5'),
 ('a3', 'a4'), ('a3', 'a5'),
 ('a4', 'a5')]
>>> 
营救

>>> from itertools import combinations
>>> agents=['a1','a2','a3','a4','a5']
>>> list(combinations(agents, 2))
[('a1', 'a2'), ('a1', 'a3'), ('a1', 'a4'), ('a1', 'a5'), 
 ('a2', 'a3'), ('a2', 'a4'), ('a2', 'a5'),
 ('a3', 'a4'), ('a3', 'a5'),
 ('a4', 'a5')]
>>> 

就我所知,你为什么不考虑二维矩阵呢?在第一阶段,如果两个代理可以相互协作,只需将相交单元设置为1即可。
在第二阶段,只需围绕矩阵设置一个循环,并仅计算具有互连的代理之间的一些值(即,单元等于1)。而不是1,而是一个实际值。所以在这种情况下,你不需要做多余的计算。唯一多余的部分是在矩阵中填充两次计算值。

据我理解你的问题,为什么不考虑二维矩阵?在第一阶段,如果两个代理可以相互协作,只需将相交单元设置为1即可。
在第二阶段,只需围绕矩阵设置一个循环,并仅计算具有互连的代理之间的一些值(即,单元等于1)。而不是1,而是一个实际值。所以在这种情况下,你不需要做多余的计算。唯一的冗余部分是在矩阵中填充两次计算值。

您可以将代理ID与以下内容进行比较:

agents = {
    'a1': ['a2', 'a3', 'a5'],
    'a2': ['a1', 'a3', 'a4'],
    'a3': ['a1', 'a2', 'a5'],
    'a4': ['a2'],
    'a5': ['a1', 'a3'],
    'a6': []
}

interactions = []
for agent, connections in agents.iteritems():
    interactions.extend((agent, connection) for connection in connections if agent < connection)

print interactions
# [('a1', 'a2'), ('a1', 'a3'), ('a1', 'a5'), ('a3', 'a5'), ('a2', 'a3'), ('a2', 'a4')]
代理={
‘a1’:[‘a2’、‘a3’、‘a5’],
‘a2’:[‘a1’、‘a3’、‘a4’],
'a3':['a1','a2','a5'],
“a4”:[“a2”],
“a5”:[a1”,“a3'],
‘a6’:[]
}
交互作用=[]
对于代理,代理中的连接。iteritems()
交互。如果代理<连接,则为连接中的连接扩展((代理,连接)
打印交互
#[('a1','a2'),('a1','a3'),('a1','a5'),('a3','a5'),('a2','a3'),('a2','a4')]

您可以将代理ID与以下内容进行比较:

agents = {
    'a1': ['a2', 'a3', 'a5'],
    'a2': ['a1', 'a3', 'a4'],
    'a3': ['a1', 'a2', 'a5'],
    'a4': ['a2'],
    'a5': ['a1', 'a3'],
    'a6': []
}

interactions = []
for agent, connections in agents.iteritems():
    interactions.extend((agent, connection) for connection in connections if agent < connection)

print interactions
# [('a1', 'a2'), ('a1', 'a3'), ('a1', 'a5'), ('a3', 'a5'), ('a2', 'a3'), ('a2', 'a4')]
代理={
‘a1’:[‘a2’、‘a3’、‘a5’],
‘a2’:[‘a1’、‘a3’、‘a4’],
'a3':['a1','a2','a5'],
“a4”:[“a2”],
“a5”:[a1”,“a3'],
‘a6’:[]
}
交互作用=[]
对于代理,代理中的连接。iteritems()
交互。如果代理<连接,则为连接中的连接扩展((代理,连接)
打印交互
#[('a1','a2'),('a1','a3'),('a1','a5'),('a3','a5'),('a2','a3'),('a2','a4')]

是的,这会尝试将每一对添加到集合中两次,但我觉得这可能比有条件的更有效。是否有人想尝试确定备选方案的时间

agents = {
    'a1': ['a2', 'a3', 'a5'],
    'a2': ['a1', 'a3', 'a4'],
    'a3': ['a1', 'a2', 'a5'],
    'a4': ['a2'],
    'a5': ['a1', 'a3'],
    'a6': []
}
pairs = {(k,v) for k in agents for v in agents[k]}
这仍然是O(n),所以就效率而言,比任何涉及排序的东西都好

您可能会通过使用

pairs = {(k,v) for k,vs in agents.iteritems() for v in vs}

是的,这会尝试将每一对添加到集合中两次,但我觉得这可能比有条件的更有效。是否有人想尝试确定备选方案的时间

agents = {
    'a1': ['a2', 'a3', 'a5'],
    'a2': ['a1', 'a3', 'a4'],
    'a3': ['a1', 'a2', 'a5'],
    'a4': ['a2'],
    'a5': ['a1', 'a3'],
    'a6': []
}
pairs = {(k,v) for k in agents for v in agents[k]}
这仍然是O(n),所以就效率而言,比任何涉及排序的东西都好

您可能会通过使用

pairs = {(k,v) for k,vs in agents.iteritems() for v in vs}

根据@gnibbler的回答,我得出以下结论:

agents = {
    'a1': ['a2', 'a3', 'a5'],
    'a2': ['a1', 'a3', 'a4'],
    'a3': ['a1', 'a2', 'a5'],
    'a4': ['a2'],
    'a5': ['a1', 'a3'],
    'a6': []
}

pairs = {tuple(sorted((k,v))) for k in agents for v in agents[k]}

仍然需要排序,但仅限于一对。

根据@gnibbler的回答,我得出以下结论:

agents = {
    'a1': ['a2', 'a3', 'a5'],
    'a2': ['a1', 'a3', 'a4'],
    'a3': ['a1', 'a2', 'a5'],
    'a4': ['a2'],
    'a5': ['a1', 'a3'],
    'a6': []
}

pairs = {tuple(sorted((k,v))) for k in agents for v in agents[k]}

仍然需要排序,但仅限于一对。

他不想生成所有可能的对。他需要将他的结构转换为非重复的对列表。这就是上面所做的-将结构
代理转换为非重复的对列表。@NickCraigWood,据我所知,初始结构是这样的:
a={“a1”:[“a2”,“a3”,“a5”],“a2”:[“a1”,“a3”,“a4”],“a3”:[“a1”,“a2”,“a5”]、“a4”:[“a2”]、“a5”:[“a1”、“a3”]、“a6”:[]}
@NickCraig-Wood,成对交互结构输入可以是任意的。我想你提供的例子是一个特例。我认为你对问题意图的理解是正确的,但我也认为,
组合
将提供所有可能的成对交互的最有效计算,这似乎是be OP想要什么。我会把这个答案留一会儿,以防万一其他人同意,否则我会删除它!他不想生成所有可能的对。他需要将他的结构转换为非重复的对列表。这就是上面所做的-将结构
代理
转换为非重复的对列表。@NickCraigW哦,到目前为止