【问题标题】:Automatic results showing?自动显示结果?
【发布时间】:2014-01-23 16:03:25
【问题描述】:

如何让 SWI-Prolog 解释器自动执行分号? 由于回溯,我有很多结果(大约 300 个),我不想为所有结果推送分号。

我不想要所有解决方案的列表,我只想不按分号或空格,这样我就可以让程序在后台打印回溯的解决方案。

【问题讨论】:

  • 我相信您的 prolog 解释器的 prolog 手册描述了您在“解决方案提示”中的各种选项。
  • 没有重复。我不想列出解决方案。我只想要一个自动分号。

标签: prolog backtracking prolog-toplevel


【解决方案1】:

您可以手动发出解决方案(例如使用write/1format/2),并使用false 强制回溯以查看所有解决方案。例如:

?- solution(S), writeln(S), false.

此外,例如在 SWI-Prolog 中,您可以简单地按 SPACE 而不是 ; 以获得更多解决方案。

【讨论】:

  • 在这种情况下使用 ISO Prolog 内置控件构造 fail/0 会更清楚一些(尽管 false/0 最近也被 ISO 标准化了)。
  • 我不确定如何实现这一点。这就是我得到的agrupacion_compatible_de_asignaturas(C,P) :- findall(A, lista_de_clase(C,A,_), J), setof(T, (subseq0(J,T), not(T=[]), not(grupo_incompatible(T))), Y), subseq0(Y,P), flatten(P,U), is_set(U), permutation(U,J).
  • 我现在明白了。这不是理想的解决方案,但它很好地解决了问题。
  • @Javier:作为一个习惯问题:请使用writeq/1 写出一般的 Prolog 术语。不要使用 write 或 writeln。他们混淆了一些术语。
  • @Javier:总是在必须引用某些内容时。想想T = 'a b'
【解决方案2】:

@repeat 不确定这是否符合您的标准,但您不能开发元解释器吗?我不确定是否有办法加载 mi,以便所有顶级查询都通过它?

比如:

mi1(true).
mi1((A,B)) :-
 mi1(A),
 mi1(B).
mi1(Goal) :-
 Goal \= true,
 Goal \= (_,_),
 Goal =..List,
 maplist(newvar,List,NewList),
 Goal2 =..NewList,
 clause(Goal2, Body),
 List=[_,T],!,
 findnsols(5,I,(Goal =..[_,I],Goal),T),
 mi1(Body).

newvar(V,V2):-
 var(V).
newvar(V,V):-
 nonvar(V).

%test predicates.
natnum1(0).
natnum1(s(X)) :-
 natnum1(X).

 w(w1).
 w(w2).
 w(w3).
 w(w4).
 w(w5).
 w(w6).
 w(w7).
 w(w8).

查询:

?- mi1(w(X)).
X = [w1, w2, w3, w4, w5] ;
X = [w6, w7, w8] ;
false.

?- mi1(natnum1(X)).
X = [0, s(0), s(s(0)), s(s(s(0))), s(s(s(s(0))))] ;
X = [s(s(s(s(s(0))))), s(s(s(s(s(s(0)))))), s(s(s(s(s(s(s(...))))))), s(s(s(s(s(s(...)))))), s(s(s(s(s(...)))))] ;
X = [s(s(s(s(s(s(s(s(s(...))))))))), s(s(s(s(s(s(s(s(...)))))))), s(s(s(s(s(s(s(...))))))), s(s(s(s(s(s(...)))))), s(s(s(s(s(...)))))] ;
X = [s(s(s(s(s(s(s(s(s(...))))))))), s(s(s(s(s(s(s(s(...)))))))), s(s(s(s(s(s(s(...))))))), s(s(s(s(s(s(...)))))), s(s(s(s(s(...)))))] 
...

仅显示基本思想..这仅适用于 1 arg 谓词..

【讨论】:

  • swi prolog 中必须有一个设置,因为在 swish 中你可以做下 10 个解决方案等swish.swi-prolog.org/p/so1.swinb
  • 狡猾!我希望一些prolog-toplevel 已经具备所需的一切,所以我只需要设置正确的标志。 swish 有类似的东西(但我需要将默认行为更改为“无论何时运行查询,都会搜索并呈现至少 5-10 个答案”)。当然,谷普至少做了 20 年是对的……
  • 如果为 ?-natnum(X)。 X 被绑定到 [0, s(0), s(s(0)), s(s(s(0))), s(s(s(s(0))))],那么你会怎么做想发生在像 natnum(X),natnum(Y), something(X,Y,Z) 这样的查询上。
  • 如何获得GUPU的副本?我以前没听说过。
  • 在大多数 Prolog 系统中,标准的 clause/2 谓词只能与 动态 谓词一起使用...
【解决方案3】:

这是我认为很好的另一种方式:

:- op(1200, xfx, all).
:- op(1200, xfx, s5).
:- op(1200, xfx, s10).

all(F,X):-
 F =.. [_|T],
 findall(T, F,X).

s5(F,X):-
 F =.. [_|T],
 findnsols(5,T,F,X).

s10(F,X):-
 F =.. [_|T],
 findnsols(10,T,F,X).

p(1).
p(2).
p(3).
p(4).
p(5).
p(6).
p(7).

nat(0).
nat(s(X)) :- nat(X).
nat_nat_sum(0,X,X).
nat_nat_sum(s(X),Y,s(Z)) :- nat_nat_sum(X,Y,Z).

问:

 ?- nat(X),nat(Y),nat_nat_sum(X,Y,Z) s5 Sols.
 Sols = [[nat(0),  (nat(0), nat_nat_sum(0, 0, 0))], [nat(0),  (nat(s(0)), nat_nat_sum(0, s(0), s(0)))], [nat(0),  (nat(s(s(0))), nat_nat_sum(0, s(s(0)), s(s(0))))], [nat(0),  (nat(s(s(...))), nat_nat_sum(0, s(s(...)), s(s(...))))], [nat(0),  (nat(s(...)), nat_nat_sum(0, s(...), s(...)))]] ;
 Sols = [[nat(0),  (nat(s(s(s(s(s(...)))))), nat_nat_sum(0, s(s(s(s(s(...))))), s(s(s(s(s(...)))))))], [nat(0),  (nat(s(s(s(s(...))))), nat_nat_sum(0, s(s(s(s(...)))), s(s(s(s(...))))))], [nat(0),  (nat(s(s(s(...)))), nat_nat_sum(0, s(s(s(...))), s(s(s(...)))))], [nat(0),  (nat(s(s(...))), nat_nat_sum(0, s(s(...)), s(s(...))))], [nat(0),  (nat(s(...)), nat_nat_sum(0, s(...), s(...)))]] ;
Sols = [[nat(0),  (nat(s(s(s(s(s(...)))))), nat_nat_sum(0, s(s(s(s(s(...))))), s(s(s(s(s(...)))))))], [nat(0),  (nat(s(s(s(s(...))))), nat_nat_sum(0, s(s(s(s(...)))), s(s(s(s(...))))))], [nat(0),  (nat(s(s(s(...)))), nat_nat_sum(0, s(s(s(...))), s(s(s(...)))))], [nat(0),  (nat(s(s(...))), nat_nat_sum(0, s(s(...)), s(s(...))))], [nat(0),  (nat(s(...)), nat_nat_sum(0, s(...), s(...)))]] .

 ?- p(X) s5 Sols.
 Sols = [[1], [2], [3], [4], [5]] ;
 Sols = [[6], [7]].

优点是您可以在查询末尾添加所需的答案数。然后,您将获得该长度的列表作为答案,因此它们不仅被写入控制台,还可以用于进一步的查询。

【讨论】:

    【解决方案4】:

    一种可能的解决方案,使用在某些具有不同名称的 Prolog 系统上发现的讨厌的全局谓词,此处针对 SWI-Prolog 进行了说明。

    chunks_of_size(Size, Goal) :-
        Size1 is Size + 1,
        nb_setval('$chunk_size', Size1),
        nb_setval('$chunk_count', Size),
        call((Goal,chunks)).
    
    chunks :-
        nb_getval('$chunk_count', N),
        N > 0,
        M is N - 1,
        nb_setval('$chunk_count', M),
        nl,
        fail.
    chunks :-
        nb_getval('$chunk_count', 0),
        nb_getval('$chunk_size', Size),
        nb_setval('$chunk_count', Size),
        write('-----'),
        chunks.
    

    使用示例:

    ?- chunks_of_size(3, (between(1, 12, N), write(N))).
    1
    2
    3
    -----
    4
    5
    6
    -----
    7
    8
    9
    -----
    10
    11
    12
    -----
    false.
    

    如果您想在每组解决方案后停止用户交互,请将chunks/0 谓词的第二个子句替换为:

    chunks :-
        nb_getval('$chunk_count', 0),
        nb_getval('$chunk_size', Size),
        nb_setval('$chunk_count', Size),
        (   write('-----')
        ;   chunks
        ).
    

    通过此更改,您现在将获得:

    ?- chunks_of_size(3, (between(1, 12, N), write(N))).
    1
    2
    3
    -----
    N = 3 ;
    
    4
    5
    6
    -----
    N = 6 ;
    
    7
    8
    9
    -----
    N = 9 ;
    
    10
    11
    12
    -----
    N = 12 ;
    
    false.
    

    【讨论】:

    • s(X)。将讨厌的东西变成一种向善的力量绝对是“好事™”!
    • 可以使用nb_setarg 来消除“全局变量”的气味吗?
    • @repeat 也许吧。但它仍然会发臭:-)
    猜你喜欢
    • 1970-01-01
    • 2013-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多