假设我被赋予了n个不等式,如下所示:
输入:
示例:n = 4
f4 > f2 > f3
f4 > f1 > f3
f4 > f2 > f1
f2 > f1 > f3
输出:
我必须将这些不等式合并以产生1个不等式,使得上述不等式保持正确。对于上面的例子:
f4 > f2 > f1 > f3
作为答案,可能存在多种不平等;我需要任何一个正确的。它也确定存在给定输入的解决方案;也就是说,我们可以假设输入始终有效。
关于如何制定算法来实现这一点的任何想法?
我一直认为可以使用有向图,但我不确定。
实现上述算法的任何想法? n的值可能非常大。
答案 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
表示边缘从f4
到f2 & f1
,从f2
到f3 & f1
以及从f1
到f3
。 f3
没有传出边缘。
现在您只需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的拓扑排序提案没有明显的相似之处。
修改强> 看起来我的建议也涉及拓扑排序,但也许我们的建议之间的细节有所不同?