如何比较由两个值组成的元素? (帕累托最优)

时间:2017-07-04 09:25:23

标签: python-3.x

我是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']。

在我的模型中,我尝试比较两个不同门的成本,如果两个门的成本都高于另一个门的成本,则拆除门,但它不能给我我想要的输出。

我知道我的功能可能太简单了,无法解决这个问题,但我不知道如何解决这个问题。有人知道如何解决这个问题吗?我已经在互联网上看了几个网站,但似乎没有什么能真正解决我的问题。

非常感谢您的帮助!

2 个答案:

答案 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)

请注意双重比较(>>=)和(>=>)。仅使用{>>),D1D2

之间没有区别

生成样本

在这里,我使用一个集合,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取决于子集检查和比较的相对性能。