简单的Prolog发生器

时间:2012-08-24 12:38:48

标签: prolog generator

我是Prolog的新手,我试图编写简单的生成器,找到低于5的整数。

gen(0).
gen(X):- X<5

当我使用gen(X)运行程序时,它只打印X = 0并提示我输入内容,当我按下输入&#39;? - &#39;再次显示。

如何让他生成从零到五的数字?我正在使用SWI-Prolog。感谢

4 个答案:

答案 0 :(得分:4)

如果您不想使用between/3,可以使用辅助程序gen/3轻松编写您的生成器:

gen(Num):-
  gen(0, 5, Num).

gen(Cur, Top, Cur):- Cur < Top.
gen(Cur, Top, Next):-
  Cur < Top,
  succ(Cur, Cur1),  % or Cur1 is Cur+1
  gen(Cur1, Top, Next).

辅助程序gen/3跟踪生成的当前数字和最高数字,并将第三个参数与当前生成的数字绑定。

gen/3的第一个子句成功,当输入数字低于顶部时,将输出数字与输入数字绑定。

第二个子句递增当前数字,并递归调用自身以在回溯时获得下一个数字。

答案 1 :(得分:3)

用于枚举整数的内置谓词介于(低,高,数字)之间。

使用它你会写gen(X) :- between(0,4,X).

我以这种方式重新实现了

gen(X) :- between_(0, 4, X).

/* between_(I,J,K) is true if K is an integer between I and J inclusive.    */
between_(I,J,I) :- I =< J.
between_(I,J,K) :- I < J, I1 is I+1, between_(I1,J,K).

问题的有趣部分是理解为什么只有一个参数的天真实现永远循环......

gen(0).
gen(X) :- gen(Y), X is Y + 1, X < 5.

?- gen(X).
X = 0 ;
X = 1 ;
X = 2 ;
X = 3 ;
X = 4 ;
^CAction (h for help) ? goals
[374,153] 3<5
[374,152] gen(3)
[374,151] gen(_G1013)
[374,150] gen(_G1013)
[374,149] gen(_G1013)

答案 2 :(得分:2)

好吧,因为gen / 1应该生成从0到5的整数(从技术上讲,如果它是5以下的整数,我们也应该产生负数),你可以这样做:

gen(0).
gen(1).
gen(2).
gen(3).
gen(4).
gen(5).

技术上满足chack的限制xD

对于谓词gen/2,其中第一个参数定义了我们可以执行的最大数量:

gen(N,R):-
    N>0,
    R is N-1.
gen(N,R):-
    N>1,
    NN is N-1,
    gen(NN,R).

但这具有使用第一个参数的优点。避免第一种解决方案的规则的重新定义是,我们应该能够在不改变规则的情况下用其他数字替换每次出现的5,并且程序应该仍然有效;我们还应该补充一点,我们不能使用列表(除非它们只有1个元素)或tupples或基本上任何带有两个变量作为参数的术语以及任何类型的编码(例如2^X * 3*Y) 。灵感来自第一个项目:

gen(X):-
    clause(g(_),_) ->
    g(X) ; (generate(5),!, g(X)).

generate(-1):-
    compile_predicates([g/1]).
generate(N):-
    assert(g(N)),
    NN is N-1,
    generate(NN).

compile_predicates/1只是为了提高速度;请注意,如果我们更改最大数量,我们应该重新启动VM。另一种选择是避免在致电g/1之前编译retract_all(g(_))并添加generate/1。当然,显而易见的问题是它不是纯粹的序言,因为我们依赖于元谓词。

好吧,有了所有这些限制,看起来确实不可能

答案 3 :(得分:-1)

使用内置函数numlist怎么样?

?- numlist(0,4,X).
X = [0, 1, 2, 3, 4].