繁体   English   中英

在纯 Prolog 中通过 CLP(FD) 反转 function

[英]Inverting a function via CLP(FD) in pure Prolog

让我们来看看这个 function:

function gcd(a, b)
   while a ≠ b
     if a > b
        a := a − b
     else
        b := b − a
   return a 

我们如何在纯 Prolog 中编码 gcd/3,以便它可以反转。 例如,Prolog 谓词应该计算 gcd(2,3)=1。 但是如果我们要问什么是 a, b 使得 gcd(a,b)=1,我们也会得到相同的 Prolog 谓词:

/* one while iteration */
2, 1
1, 2 
/* two while iterations */
3, 1
2, 3
3, 2
1, 3 
/* Etc... */

Prolog 似乎特别适合,因为它可以枚举解决方案。

此解决方案使用参数来跟踪循环的当前层:

gcd(A, B, G):-
  gcd(_, A, B, G).

gcd(Tier, A, B, G):-
  Tier1 #= Tier - 1,
  Tier1 #>= 0,
  zcompare(Order, A, B),
  gcd(Order, Tier1, A, B, G).
  
gcd(=, 0, G, G, G).
gcd(>, Tier, A, B, G):-
  A1 #= A - B,
  gcd(Tier, A1, B, G).
gcd(<, Tier, A, B, G):-
  B1 #= B - A,
  gcd(Tier, A, B1, G).

因此,当您想获得分层枚举时,我会写:

?- between(1,3,Tier), gcd(Tier, A,B,1), write(B/A), nl, fail; true.
1/1
1/2
2/1
1/3
2/3
3/2
3/1
true.

我首先尝试将 GCD function 字面翻译成 Prolog 代码。 第一个条款适用于 a ≠ b 为假的情况,这意味着我们可以终止 function。 否则我们递归到这两种情况:

euclid(A,A,A).
euclid(A,B,R) :- A #< B, C #= B-A, euclid(A,C,R).
euclid(A,B,R) :- A #> B, C #= A-B, euclid(C,B,R).

我们可以测试,似乎工作正常,除了它有选择点。 但是选择点是我们必须为使用 CLP(FD) 和编程纯 Prolog 而不削减所付出的代价:

?- euclid(17,13,X).
X = 1 ;
No

但是使用 euclid/3 进行枚举并不是很令人满意,
结果只是 GCD function 的一个执行分支:

?- euclid(A,B,1).
A = 1,
B = 1 ;
A = 1,
B = 2 ;
A = 1,
B = 3 ;
A = 1,
B = 4 ;

现在我们可以执行以下操作,并用二进制数对通过 GCD function 的路径 P 进行编码。 当我们终止时,路径将是 P=1。 否则,我们使用 P 的低位来编码 GCD 的剩余两个子句中的哪一个被选择:

euclid(A,A,1,A).
euclid(A,B,P,R) :- A #< B, C #= B-A, P #= 2*Q, Q #> 0, euclid(A,C,Q,R).
euclid(A,B,P,R) :- A #> B, C #= A-B, P #= 2*Q+1, Q #> 0, euclid(C,B,Q,R).

生成的 Prolog 谓词确实是双向的:

?- euclid(17,13,P,X).
P = 241,
X = 1 ;
No
?- euclid(A,B,241,1).
A = 17,
B = 13 ;
No

我们也可以用它来任意枚举,虽然只能用
between/3 的帮助可能不是最有效的,但它很有效:

?- between(1,7,P), euclid(A,B,P,1), write(B/A), nl, fail; true.
1/1
2/1
1/2
3/1
2/3
3/2
1/3
Yes

编辑 04.02.2021:
哦,有趣的是,这也有效。 但结果的顺序不同:

?- P #< 8, euclid(A,B,P,1), write(B/A), nl, fail; true.
1/1
2/1
3/1
3/2
1/2
2/3
1/3
true.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM