生成Farry序列的Prolog程序
设n为正整数,n阶Farey序列为[0,1]区间内所有分母小于或等于n的所有有理数递增排列所构成的序列。记0=0/1,1=1/1,Fn为n阶Farey序列,则1~7阶的Farey序列为:
{0/1,1/1}
{0/1,1/2,1/1}
{0/1,1/3,1/2,2/3,1/1}
{0/1,1/4,1/3,1/2,2/3,3/4,1/1}
{0/1,1/5,1/4,1/3,2/5,1/2,3/5,2/3,3/4,4/5,1/1}
{0/1,1/6,1/5,1/4,1/3,2/5,1/2,3/5,2/3,3/4,4/5,5/6,1/1}
{0/1,1/7,1/6,1/5,1/4,2/7,1/3,2/5,3/7,1/2,4/7,3/5,2/3,5/7,3/4,4/5,5/6,6/7,1/1}
Farry序列的基本数学性质
关于Farey序列的构造规律,我们有如下定理:
定理
(1)若p1/q1和p2/q2为Fn中相继的两项,则p2q1-p1q2=1且q1+q2>n
(2)若p1/q1, p2/q2 和p3/q3为Fn中相继的3项,则p2/q2=(p1+p3)/(q1+q3)
生成Farry序列的Prolog程序
// 第一个arg表示级数的阶,第二个表为生成的farry级数表
farry_series(1, [fr(0,1), fr(1,1)]).
farry_series(N, Fs):-
N > 1,
farry_series_4(2, N, [fr(0,1), fr(1,1)], Fs).
// 第一个arg值K表示目前已经生成的farry级数的阶,第二个N为目标级数的阶,第三个为K阶Farry级数,是一个部分结果,第四个为目标阶的Farry级数
farry_series_4(K, N, Fs, Fs):-
K > N.
farry_series_4(K, N, Fs0, Fs):-
K <= N,
g(0, K, G),
frlist_merge(Fs0, G, Fs1),
K1 = K + 1,
farry_series_4(K1, N, Fs1, Fs).
// 形成所有分母为N的既约分数,例如N=4时,生成表[1/4,3/4]
g(K, N, []):-K > N, !.
g(K, N, [fr(K, N)|G]):-
gcd(K, N, 1), !, // gcd is a greatest common divisor predicate
K1 = K + 1,
g(K1, N, G).
g(K, N, G):-
K1 = K + 1,
g(K1, N, G).
// merge two fract lists orderly
frlist_merge([], Fs, Fs).
frlist_merge(Fs, [], Fs).
frlist_merge([F1|Fs1], [F2|Fs2], [F1|Fs]):-
fract_ls(F1, F2), !,
frlist_merge(Fs1, [F2|Fs2], Fs).
frlist_merge(Fs1, [F2|Fs2], [F2|Fs]):-
frlist_merge(Fs1, Fs2, Fs).
fract_ls(fr(P1, Q1), fr(P2, Q2)):-
P1*Q2 < P2*Q1.
frlist_print([]):-
write("{}").
frlist_print([F|Fs]):-
frlist_print_first_element(F),
frlist_print_rest_elements(Fs).
frlist_print_first_element(fr(P, Q)):-
write("{", P, "/", Q).
frlist_print_rest_elements([]):-
write("}").
frlist_print_rest_elements([fr(P, Q)|Fs]):-
write(",", P, "/", Q),
frlist_print_rest_elements(Fs).
以下是上述程序的生成结果:
{0/1,1/1}
{0/1,1/2,1/1}
{0/1,1/3,1/2,2/3,1/1}
{0/1,1/4,1/3,1/2,2/3,3/4,1/1}
{0/1,1/5,1/4,1/3,2/5,1/2,3/5,2/3,3/4,4/5,1/1}
{0/1,1/6,1/5,1/4,1/3,2/5,1/2,3/5,2/3,3/4,4/5,5/6,1/1}
{0/1,1/7,1/6,1/5,1/4,2/7,1/3,2/5,3/7,1/2,4/7,3/5,2/3,5/7,3/4,4/5,5/6,6/7,1/1}
{0/1,1/8,1/7,1/6,1/5,1/4,2/7,1/3,3/8,2/5,3/7,1/2,4/7,3/5,5/8,2/3,5/7,3/4,4/5,5/6,6/7,7/8,1/1}
{0/1,1/9,1/8,1/7,1/6,1/5,2/9,1/4,2/7,1/3,3/8,2/5,3/7,4/9,1/2,5/9,4/7,3/5,5/8,2/3,5/7,3/4,7/9,4/5,5/6,6/7,7/8,8/9,1/1}
{0/1,1/10,1/9,1/8,1/7,1/6,1/5,2/9,1/4,2/7,3/10,1/3,3/8,2/5,3/7,4/9,1/2,5/9,4/7,3/5,5/8,2/3,7/10,5/7,3/4,7/9,4/5,5/6,6/7,7/8,8/9,9/10,1/1}