我是Python的新手,我想要执行某种帕累托最优。这有点难以解释,所以我希望我的问题能够清楚地理解。
我有以下模型,其中包含5个门的列表(列表:'门'),每个门包含两个成本(以字典“成本”显示):[行程距离,延迟]。我想比较每扇门的成本和另一扇门的成本。但是,没有主导成本。这意味着我需要一个门列表,其中包含两种成本的最佳解决方案(最小化成本)。
doors = ['D1', 'D2', 'D3', 'D4', 'D5']
# cost: [travel distance, delay]
cost = {
'D1': [150, 0],
'D2': [160, 0],
'D3': [170, 1],
'D4': [140, 2],
'D5': [150, 0]
}
def test(doors):
for s in doors:
for d in doors:
if s != d:
if cost[s][0] < cost[d][0] and cost[s][1] < cost[d][1]:
doors.remove(d)
return doors
print(test(doors))
例如:D1,D2,D5的延迟成本均为0.如果我只想以最小的延迟成本寻找门,那么所有三扇门都可以。但是,D2的行程距离为160,大于150.因此,您永远不会选择D2(与D1和D5相比),因为它包含相同的延迟值和更差的行程距离值。所以我们希望D2从列表中删除。
对于行驶距离成本,您将选择D4,因为它具有最低行驶距离:140。虽然它具有最高延迟,但由于行驶距离较短,因此没有门优于D4。
所以最终我想要一个带有门的列表,其中一个成本最低,其他成本的最佳值。 基于此,我想得到以下输出:
best_doors = ['D1','D4','D5']。
在我的模型中,我尝试比较两个不同门的成本,如果两个门的成本都高于另一个门的成本,则拆除门,但它不能给我我想要的输出。
我知道我的功能可能太简单了,无法解决这个问题,但我不知道如何解决这个问题。有人知道如何解决这个问题吗?我已经在互联网上看了几个网站,但似乎没有什么能真正解决我的问题。
非常感谢您的帮助!
答案 0 :(得分:0)
我知道这可能无法完全回答你的问题,但我希望它会引导你走向正确的方向,因为这不是一个(太)微不足道的问题(这太长了,不能发表评论)。
解决这个问题的一种方法是给每个成本一个重量&#34;即决定是否选择特定的门有多大作用。
通常通过提出适当描述每项费用的重量的公式来完成。
在下面的示例中,我使用了一个公式,给出距离权重为1,delay
权重为5。
cost = {
'D1': [150, 0],
'D2': [160, 0],
'D3': [170, 1],
'D4': [140, 2],
'D5': [150, 0]
}
def cost_function(x):
# x here is a tuple of the form (door_name, [travel distance, delay])
return x[1][0] + x[1][1] * 5
print(sorted(cost.items(), key=cost_function))
# [('D1', [150, 0]), ('D4', [140, 2]), ('D5', [150, 0]),
# ('D2', [160, 0]), ('D3', [170, 1])]
此成本函数可达到您想要的特定顺序。
答案 1 :(得分:0)
最简单的方法是制作Door
课程
class Door():
def __init__(self, name, distance, delay):
self.name = name
self.distance = distance
self.delay = delay
def __gt__(self, other):
return (self.distance > other.distance and self.delay >= other.delay) or \
(self.distance >= other.distance and self.delay > other.delay)
def __repr__(self):
return 'Door(name=%s, distance=%i, delay=%i'% (self.name, self.distance, self.delay)
请注意双重比较(>
,>=
)和(>=
,>
)。仅使用{>
,>
),D1
和D2
在这里,我使用一个集合,dict
也可以轻微改编
doors_orig = set()
for d, c in cost.items():
doors_orig.add(Door(d, *c))
doors_orig
{Door(name=D4, distance=140, delay=2,
Door(name=D1, distance=150, delay=0,
Door(name=D5, distance=150, delay=0,
Door(name=D2, distance=160, delay=0,
Door(name=D3, distance=170, delay=1}
然后您可以使用itertools.permutations
生成所有可能的组合。检查该组合是否仍然是可能的最佳门的子集并进行比较。丢弃它绝对更大。
doors_perm = doors_orig.copy()
comb = itertools.permutations(doors_perm, 2)
for d1, d2 in comb:
if {d1, d2} <= doors_perm and (d1 > d2):
doors_perm.discard(d1)
doors_perm
{Door(name=D4, distance=140, delay=2,
Door(name=D1, distance=150, delay=0,
Door(name=D5, distance=150, delay=0}
是否需要{d1, d2} <= doors_perm
取决于子集检查和比较的相对性能。