将不平等合并为一个

时间:2014-11-10 15:41:08

标签: algorithm math data-structures graph graph-algorithm

假设我被赋予了n个不等式,如下所示:

输入:

示例:n = 4

f4 > f2 > f3
f4 > f1 > f3
f4 > f2 > f1
f2 > f1 > f3

输出:

我必须将这些不等式合并以产生1个不等式,使得上述不等式保持正确。对于上面的例子:

f4 > f2 > f1 > f3

作为答案,可能存在多种不平等;我需要任何一个正确的。它也确定存在给定输入的解决方案;也就是说,我们可以假设输入始终有效。

关于如何制定算法来实现这一点的任何想法?

我一直认为可以使用有向图,但我不确定。

实现上述算法的任何想法? n的值可能非常大。

4 个答案:

答案 0 :(得分:2)

此解决方案提取所有两项不等式并执行符合它们的排序:

Python 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ineq = """f4 > f2 > f3
f4 > f1 > f3
f4 > f2 > f1
f2 > f1 > f3"""
>>> print(ineq)
f4 > f2 > f3
f4 > f1 > f3
f4 > f2 > f1
f2 > f1 > f3
>>> greater_thans, all_f = set(), set()
>>> for line in ineq.split('\n'):
    tokens = line.strip().split()[::2]
    for n, t1 in enumerate(tokens[:-1]):
        for t2 in tokens[n+1:]:
            greater_thans.add((t1, t2))
            all_f.add(t1)
        all_f.add(t2)


>>> sorted(all_f, cmp=lambda t1, t2: 0 if t1==t2 else (1 if (t1, t2) not in greater_thans else -1))
['f4', 'f2', 'f1', 'f3']
>>> 

comp.lang.python上有点人员指出,如果原始关系集不包含每个小于关系,那么排序可能会失败,所以我需要添加一个函数{{ 1}}:

expand_transitive_relations

<强>输出:

from __future__ import print_function
from itertools import permutations


def extract_relations(ineq):
    "Turns lines of lists of relations separated by '>' into set of tuples of (x,y) pairs where x > y"
    greater_thans, all_f = set(), set()
    for line in ineq.split('\n'):
        tokens = line.strip().split()[::2]
        for n, t1 in enumerate(tokens[:-1]):
            for t2 in tokens[n+1:]:
                greater_thans.add((t1, t2))
                all_f.add(t1)
            all_f.add(t2)
    expanded = expand_transitive_ralations(greater_thans, all_f)
    return sorted(all_f, cmp=lambda t1, t2: 0 if t1==t2 else 
                                            (1 if (t1, t2) not in expanded else -1))

def expand_transitive_ralations(greater_thans, all_f):
    "if x > y and y > z then x > z"
    start_len = len(greater_thans)
    while True:
        for x, y, z in permutations(all_f, 3):
            if (x, y) in greater_thans and (y, z) in greater_thans:
                greater_thans.add((x, z))
        new_len = len(greater_thans)
        if start_len == new_len:
            break
        else:
            start_len = new_len
    return greater_thans

if __name__ == '__main__':
    for ineq in (
            """\
            f4 > f2 > f3
            f4 > f1 > f3
            f4 > f2 > f1
            f2 > f1 > f3\
            """,
            """\
            f4 > f2 > f3 
            f4 > f1 > f3 
            f4 > f2 > f1 
            f2 > f1 > f3 
            f3 > f5\
            """,
            """\
            f2 > f3 
            f3 > f1\
            """):
        print(ineq)
        print('  Becomes:', ' > '.join(extract_relations(ineq)), '\n')

答案 1 :(得分:1)

您可以制作有向图,其中顶点将被赋予变量,边将在更大和更小之间(连接v1 --> v2表示v1 > v2)。例如:

f4 > f2 > f3
f4 > f1 > f3
f4 > f2 > f1
f2 > f1 > f3

表示边缘从f4f2 & f1,从f2f3 & f1以及从f1f3f3没有传出边缘。

现在您只需sort topologically图表了。注意,如果你有一个循环没有解决方案! f4 -> f2 -> f1 -> f4表示f4 > f2 > f1 > f4

答案 2 :(得分:0)

您可以在表示这些不等式的有向图上使用拓扑排序。它可以使用深度优先搜索在O(N + M)时间内完成(其中N是变量的数量,M是不等式的数量)。

答案 3 :(得分:0)

可行的方法是制作有向图G,其中边u到v表示u> u。 v(当然,每个不等式对应于G中的边),寻找没有入边的顶点w,然后尝试从w开始找到具有n个顶点的非循环路径。但这只是直觉;这可能是错误的,对我来说,Tacet和用户2040251的拓扑排序提案没有明显的相似之处。

修改 看起来我的建议也涉及拓扑排序,但也许我们的建议之间的细节有所不同?