【问题标题】:How to generate Permutation Linear Extension using Python如何使用 Python 生成排列线性扩展
【发布时间】:2021-04-07 12:45:07
【问题描述】:

我想重现来自this paper 的实验。作者说他们使用了线性扩展,MathWorld对线性扩展的定义是:

偏序集 P 的线性扩展是 P 的元素 p_1, p_2, ... 的置换,使得 p_i((1,2),(3,4))的线性扩展是1234、1324、1342、3124、3142和3412,它们都有1 2 之前和 3 之前 4。

根据线性扩展的定义,我发现python代码是这样的

import itertools

groups = [(1,2),(3,4)]
groupdxs = [i for i, group in enumerate(groups) for j in range(len(group))]
old_combo = ()
for dx_combo in itertools.permutations(groupdxs):
    if dx_combo <= old_combo: # as simple filter
        continue
    old_combo = dx_combo
    iters = [iter(group) for group in groups]
    print([next(iters[i]) for i in dx_combo])

根据线性扩展的定义,结果完全一样: 结果如下:

[1, 2, 3, 4]
[1, 3, 2, 4]
[1, 3, 4, 2]
[3, 1, 2, 4]
[3, 1, 4, 2]
[3, 4, 1, 2]

但是,我不知道如何根据论文实现这一点:

  1. 论文中的线性扩展是按降序排列的,高分在前。
  2. 看来论文中的线性扩展是基于字典而不是元组。

假设我有一个 Pandas 数据框 df:

import pandas as pd
data = [['a1', '10-11'], ['a2', '3-8'], ['a3', '4-6'],['a4','1-2'], ['a5','5-10']] 
df = pd.DataFrame(data, columns = ['A', 'B']) 
df 

df:

     A   B
0   a1  10-11
1   a2  3-8
2   a3  4-6
3   a4  1-2
4   a5  5-10

我的问题是如何根据论文从df 生成所有排列?论文中的线性扩展示例如下图所示:

预期的结果是这样的:

[a1, a5, a3, a2, a4]
[a1, a2, a5, a3, a4] 
.
.
.

【问题讨论】:

    标签: python list permutation


    【解决方案1】:

    您可以通过使用递归生成器函数来镜像图形的遍历以产生所需的结果:

    纸质数据输出:

    data = [['a1', '9'], ['a2', '5-8'], ['a3', '7'],['a4','0-10'], ['a5','4']]  
    r = {a:list(map(int, b.split('-'))) for a, b in data}
    vals = [(a, [[j, a] for j in range(b, b+1 if not x else x[0]+1)][::-1]) for a, (b, *x) in r.items()]
    def get_combos(vals, c = []):
       v = [(i, [a, b]) for i, (a, b) in enumerate(vals) if a not in c]
       start = [a for i, (a, b) in v if all(b[0][0] > min([x for x, _ in k]) 
                for l, (j, k) in v if l != i)]
       if c:
          start = sorted(start, key=lambda x:r[x][-1], reverse=True)
       if not start:
          yield c
       else:
          yield from [i for b in start for i in get_combos(vals, c=c+[b])]
    
    print(list(get_combos(vals)))
    

    结果:

    [['a1', 'a4', 'a2', 'a3', 'a5'], ['a1', 'a4', 'a3', 'a2', 'a5'], ['a1', 'a2', 'a4', 'a3', 'a5'], ['a1', 'a2', 'a3', 'a4', 'a5'], ['a1', 'a2', 'a3', 'a5', 'a4'], ['a1', 'a3', 'a4', 'a2', 'a5'], ['a1', 'a3', 'a2', 'a4', 'a5'], ['a1', 'a3', 'a2', 'a5', 'a4'], ['a4', 'a1', 'a2', 'a3', 'a5'], ['a4', 'a1', 'a3', 'a2', 'a5']]
    

    数据输出:

    data = [['a1', '10-11'], ['a2', '3-8'], ['a3', '4-6'],['a4','1-2'], ['a5','5-10']] 
    r = {a:list(map(int, b.split('-'))) for a, b in data}
    vals = [(a, [[j, a] for j in range(b, b+1 if not x else x[0]+1)][::-1]) for a, (b, *x) in r.items()]
    print(list(get_combos(vals)))
    

    结果:

    [['a1', 'a5', 'a2', 'a3', 'a4'], ['a1', 'a5', 'a3', 'a2', 'a4'], ['a1', 'a2', 'a5', 'a3', 'a4'], ['a1', 'a2', 'a3', 'a5', 'a4'], ['a1', 'a3', 'a5', 'a2', 'a4'], ['a1', 'a3', 'a2', 'a5', 'a4']]
    

    【讨论】:

    • 谢谢@Ajax1234 我赞成你的回答,我不知道为什么有人给你反对票,也许他们只是按错了按钮。还是谢谢你:)
    • @rischan 很高兴为您提供帮助!
    • 嗨@Ajax1234 等一下,如果愤怒中的值是浮动的怎么办?我收到此错误,“浮点”对象不能解释为整数。
    • @rischan 你可以使用int进行四舍五入:range(int(b), int(b+1 if not x else x[0]+1))
    猜你喜欢
    • 2011-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-12
    • 1970-01-01
    • 1970-01-01
    • 2019-10-01
    • 2011-04-24
    相关资源
    最近更新 更多