【问题标题】:Creating list of values with according to condition in python根据python中的条件创建值列表
【发布时间】:2021-02-22 13:25:21
【问题描述】:

我需要根据字典规定的优先关系创建一份工作列表。

 dict_preced = {(1, 2): 0,  (1, 3): 0,  (2, 1): 1,  (2, 3): 0,  (3, 1): 1,  (3, 2): 0}

 Where (j1, j2) == 1 means that j1 requires j2, 0 otherwise.

假设我已经有了起始列表:j_seq = [3, 2, 1],我需要创建一个 new_list,其中 j_seq 中的所有值都将遵循优先关系,这意味着在所需的作业之前没有作业正在执行。 (即作业 3 和作业 2 不能在作业 1 之前执行)。

因此,有许多候选列表(即new_list = [1, 2, 3]new_list = [1, 3, 2])。 如何创建始终尊重这些优先关系的new_list 样本?

当每个值都需要尊重给定条件而不依赖于其他值时,我发现了许多列表理解示例。但是我没有找到任何例子,其中陈述的条件涉及同一个列表的两个值。

编辑:我不需要得到所有关于优先约束的排列,一个就足够了。

【问题讨论】:

  • 在您给出的示例中,3 需要 2,2 需要 3。在这种情况下,您认为关系的偏好是什么?

标签: python list dictionary


【解决方案1】:

一种解决方案是枚举j_seq 的所有排列,然后根据您的优先字典查找每对组合,以识别无效且可能被丢弃的排列。

例如:

import itertools

dict_preced = {(1, 2): 0,  (1, 3): 0,  (2, 1): 1,  (2, 3): 0,  (3, 1): 1,  (3, 2): 0}
j_seq = [3, 2, 1]
valid = []

for perm in itertools.permutations(j_seq):
    print('Permutation:', perm)
    for perm_pair in itertools.combinations(perm, 2):
        precedence = dict_preced.get(perm_pair, 0)
        print('\tCombination:', perm_pair, '=>', precedence)
        if precedence == 1:
            print('\tDecision: exclude', perm)
            break
    else:
        print('\tDecision: include', perm)
        valid.append(perm)

print('Result:', valid)

结果是:[(1, 3, 2), (1, 2, 3)]

完整的输出(包括调试日志)是:

Permutation: (3, 2, 1)
        Combination: (3, 2) => 0
        Combination: (3, 1) => 1
        Decision: exclude (3, 2, 1)
Permutation: (3, 1, 2)
        Combination: (3, 1) => 1
        Decision: exclude (3, 1, 2)
Permutation: (2, 3, 1)
        Combination: (2, 3) => 0
        Combination: (2, 1) => 1
        Decision: exclude (2, 3, 1)
Permutation: (2, 1, 3)
        Combination: (2, 1) => 1
        Decision: exclude (2, 1, 3)
Permutation: (1, 3, 2)
        Combination: (1, 3) => 0
        Combination: (1, 2) => 0
        Combination: (3, 2) => 0
        Decision: include (1, 3, 2)
Permutation: (1, 2, 3)
        Combination: (1, 2) => 0
        Combination: (1, 3) => 0
        Combination: (2, 3) => 0
        Decision: include (1, 2, 3)
Result: [(1, 3, 2), (1, 2, 3)]

【讨论】:

  • 嘿,@jarmod 非常感谢您的帮助!它可以根据小示例的需要工作。问题是我正在使用 len 大约为 20 的列表。因此排列将我引向数十万个列表。在我的电脑上处理它是不可能的
  • 在我的例子中不需要计算所有排列,因为我只需要得到一个尊重所有优先约束的列表。如果您有想法在没有所有排列的情况下获得它,请告诉我。我很抱歉之前没有解释这一点
  • itertools 函数是 afaik 的生成器,因此非常高效。当您找到第一个有效排列时,简单地终止搜索就足够了吗?也许将这段代码变成一个函数,而不是 valid.append(perm) 来累积所有有效的排列,只需返回使用 return perm 找到的第一个?
  • 我试过了,但还是很耗时。我正在尝试直接在给定的 j_seq 上调整优先级,但效果不佳。我试图这样做: for p in test_list: i1 = test_list.index(p) for el in test_list[i1:]: i2 = test_list.index(el) if dict_preced.get((el, p)) == 1: test_list.remove(p) test_list.insert(i2+1, p) 但它并不总是按需要工作。你知道如何纠正它吗?
  • 您是否有特定的测试用例数据可以添加到您的问题以及您当前的代码中,并解释问题是什么(如果太慢,它有多慢?如果失败,如何它失败了吗?)
【解决方案2】:

我正在回答我自己的问题,因为我找到了解决这个问题的方法。

当使用短列表时,@jarmod 提出的方法可以很方便。但是,当考虑长列表时,使用他的方法变得不切实际,因为排列的数量增加到 10^18。

对于那些可以从 IBM CPLEX(或其他约束规划求解器)访问 CP 优化器的人,一种可能的替代方法是使用约束传播方法来获取一些有效序列列表(尊重优先约束)。

在我的例子中,我通过 docplex 模块调用了 CP 优化器。 你可以在这里查看脚本:https://github.com/campioni1/CPO_Docplex_precedence_constraints

如果您遇到任何困难,请告诉我,

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多