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哦,到目前为止