*相同边缘*问题的有效解决方案

问题描述 投票:0回答:1
二叉树的

边缘是由它的叶子组成的序列,从 左到右。 相同的边缘问题 [Hewitt & Patterson, 1970] 包括确定两个二叉树是否具有相同的边缘。 例如,下面的前两棵树具有相同的边缘,但是 最后两个没有:

% . . . % / \ / \ / \ % . 3 1 . 1 . % / \ / \ / \ % 1 2 2 3 -2 3 example(1, fork(fork(leaf(1), leaf(2)), leaf(3))). example(2, fork(leaf(1), fork(leaf(2), leaf(3)))). example(3, fork(leaf(1), fork(leaf(-2), leaf(3)))).
一个简单的解决方案是将一棵树的叶子收集到一个列表中,然后
然后将它们与另一棵树的叶子进行比较。

/* * SIMPLE SOLUTION */ sf_1(T1, T2) :- walk(T1, [], Xs), walk(T2, [], Xs). walk(leaf(X), A, [X|A]). walk(fork(L, R), A0, Xs) :- walk(R, A0, A1), walk(L, A1, Xs).
虽然简单,但这个解决方案被认为不优雅:首先,因为
当第一棵树非常大时,这可能是不切实际的;以及,第二,
因为当树的前几棵树不同时,效率非常低
树叶。因此,更好的解决方案是尽快停止比较
当发现第一个差异时,没有完全生成列表
包含第一棵树的边缘。

/* * SUPPOSEDLY BETTER SOLUTION */ sf_2(T1, T2) :- step([T1], [T2]). step([], []). step([T1|S1], [T2|S2]) :- next(T1, S1, X, R1), next(T2, S2, X, R2), step(R1, R2). next(leaf(X), S, X, S). next(fork(L, R), S0, X, S) :- next(L, [R|S0], X, S).
为了比较这两种解决方案的性能,我实现了一些谓词来运行自动化实验(通过使用 SWI-prolog,版本 9.0.4):

/* * EMPIRICAL COMPARISON */ comp(Case) :- format('fsize sf-1 sf-2\n'), forall( between(1, 10, I), ( N is 100000 * I, tree(1, N, A), ( Case = true % trees with same fringes -> tree(1, N, B) ; M is random(N//10), % trees with different fringes flip(A, M, B) ), time(10, sf_1(A, B), T1), time(10, sf_2(A, B), T2), format('~0e ~2f ~2f\n', [N, T1, T2]) ) ). time(N, G, T) :- garbage_collect, S is cputime, forall(between(1, N, _), ignore(call(G))), T is (cputime - S) / N. /* * RANDOM TREE GENERATION AND MODIFICATION */ tree(X1, Xn, leaf(X1)) :- X1 = Xn, !. tree(X1, Xn, fork(L, R)) :- X1 < Xn, random(X1, Xn, Xi), Xj is Xi + 1, tree(X1, Xi, L), tree(Xj, Xn, R). flip(leaf(X), Y, leaf(Z)) :- ( X = Y -> Z is -X ; Z is X ). flip(fork(L0, R0), X, fork(L, R)) :- flip(L0, X, L), flip(R0, X, R).
经验结果表明,当树木

不具有相同的边缘时,第二个解决方案实际上比第一个解决方案更快

?- comp(false). fsize sf-1 sf-2 1e+05 0.01 0.00 2e+05 0.03 0.00 3e+05 0.05 0.00 4e+05 0.07 0.01 5e+05 0.09 0.01 6e+05 0.11 0.00 7e+05 0.12 0.01 8e+05 0.14 0.01 9e+05 0.17 0.00 1e+06 0.18 0.00 true.
但是,当树木

确实具有相同的边缘时,第二个解决方案比第一个解决方案稍微

?- comp(true). fsize sf-1 sf-2 1e+05 0.02 0.03 2e+05 0.04 0.05 3e+05 0.06 0.08 4e+05 0.08 0.11 5e+05 0.10 0.12 6e+05 0.12 0.14 7e+05 0.12 0.16 8e+05 0.14 0.18 9e+05 0.17 0.19 1e+06 0.18 0.22 true.

问题:当边缘清晰时,是否有可能实现一个比简单解决方案更快(通过常数因子,不一定是渐近更快)的解决方案(在Prolog中),并且不是当条纹相同时,速度会变慢?怎么办?

performance prolog binary-tree generator
1个回答
0
投票

sf_3(T1, T2) :- stepping(T1, [T2],[]). next(X, [T2|T2s0],T2s) :- t_next(T2, X, T2s0,T2s). t_next(leaf(X), X, T2s,T2s). t_next(fork(L, R), X, T2s0,T2s) :- t_next(L, X, [R|T2s0],T2s). % [R|_] could be eliminated for R a leaf/1. stepping(leaf(X), T2s0,T22):- next(X, T2s0,T2s). stepping(fork(L, R), T2s0,T2s) :- stepping(L, T2s0,T2s1), stepping(R, T2s1,T2s).

	
© www.soinside.com 2019 - 2024. All rights reserved.