如何编写map(List, PredName, Result)将谓词应用于PredName(Arg, Res)元素的Prolog过程,并将List结果返回到列表中Result?
例如:
test(N,R) :- R is N*N.
?- map([3,5,-2], test, L).
L = [9,25,4] ;
no
Run Code Online (Sandbox Code Playgroud) 许多谓词基本上使用某种形式的传递闭包,只是发现终止也必须得到解决.为什么不一次解决这个问题closure0/3:
:- meta_predicate closure0(2,?,?).
:- meta_predicate closure(2,?,?).
:- meta_predicate closure0(2,?,?,+). % internal
closure0(R_2, X0,X) :-
closure0(R_2, X0,X, [X0]).
closure(R_2, X0,X) :-
call(R_2, X0,X1),
closure0(R_2, X1,X, [X1,X0]).
closure0(_R_2, X,X, _).
closure0(R_2, X0,X, Xs) :-
call(R_2, X0,X1),
non_member(X1, Xs),
closure0(R_2, X1,X, [X1|Xs]).
non_member(_E, []).
non_member(E, [X|Xs]) :-
dif(E,X),
non_member(E, Xs).
Run Code Online (Sandbox Code Playgroud)
是否存在此定义不能用于实现传递闭包的情况?
详细回答@ WouterBeek的评论:dif/2或者iso_dif/2是理想的,因为它们能够显示或发出潜在问题的信号.但是,在当前的实现中,顶级循环通常会隐藏实际问题.考虑一下closure0(\_^_^true,a,b)本身肯定存在问题的目标.使用以下系统时,实际问题直接不可见.
| ?- closure0(\_^_^true,a,b). % SICStus
yes
?- closure0(\_^_^true,a,b). % SWI
true ;
true ;
true ...
Run Code Online (Sandbox Code Playgroud)
两个顶级循环都没有显示我们真正想要看到的内容:悬空约束.在SICStus中,我们需要一个伪变量来产生一些替换,在SWI中,查询必须被包装call_residue_vars/2.以这种方式,现在显示所有附加约束的变量.
| …Run Code Online (Sandbox Code Playgroud) 我想在 Prolog 中找到两个节点之间的最短路径。我想出了如何找到两个节点之间的所有路径,但不幸的是以下代码陷入了循环:
arc(a,b).
arc(b,a).
arc(b,c).
arc(c,b).
arc(c,d).
arc(d,c).
path(X,Y,[arc(X,Y)]) :-
arc(X,Y).
path(X,Y,[arc(X,Z)|P]) :-
arc(X,Z),
path(Z,Y,P).
Run Code Online (Sandbox Code Playgroud)
运行的代码是:
?- path(a,c,R).
R = [arc(a, b), arc(b, c)] ;
R = [arc(a, b), arc(b, a), arc(a, b), arc(b, c)] ;
R = [arc(a, b), arc(b, a), arc(a, b), arc(b, a), arc(a, b), arc(b, c)]
....
Run Code Online (Sandbox Code Playgroud)
所以,我的问题是:如何获取所有路径而不无限循环?
在一天结束时,我会得到列表的长度并找到最小值。
如果可能的话,请给出 ISO Prolog 的解决方案。
注意:这是更新的代码,我仍然有问题。显然,在检查事实而不是原子时,成员谓词不起作用。
xxx([]).
path(X,Y,[arc(X,Y)]) :-
arc(X,Y).
path(X,Y,[arc(X,Z)|P]) :-
arc(X,Z)
,xxx(L)
,member(arc(X,Z),L)->
!;
(member(arc(Z,X),L)->
!;
(append(L,[arc(X,Z)],R),retract(xxx(_)),assert(xxx(R)),path(Z,Y,P))).
Run Code Online (Sandbox Code Playgroud)
我的成员谓词是:
member(X,[X|T]).
member(X,[H|T]) :- member(X,T).
Run Code Online (Sandbox Code Playgroud)
谢谢。
我正在学习Prolog,我正在复习讲义,所有笔记都说:
给定有向图的以下定义:
path(X, Y) :- edge(X, Y).
path(X, Y) :- edge(X, Z), path(Z, Y).
Run Code Online (Sandbox Code Playgroud)
如果我们想让它成为一个无向图,edge(X, Y) :- edge(Y, X).单独定义
不起作用,我无法弄清楚为什么.如果Y到X有边,则X到Y有一条边.似乎对我有意义.
这些说明并没有真正说明原因,但它确实定义了正确的解决方案:
edge1(X, Y) :- edge(X, Y).
edge1(X, Y) :- edge(Y, X).
Run Code Online (Sandbox Code Playgroud)
我们已经拥有的东西.
谁能解释一下这个,请和谢谢?<3
我有以下事实和规则:
flight(sea,msp).
flight(msp,jfk).
route(A,B) :- flight(A,B).
route(B,A) :- flight(A,B).
route(A,C) :- flight(A,B) , flight(B,C).
Run Code Online (Sandbox Code Playgroud)
当查询route(sea,jfk)我得到结果true但我希望得到的是解释:
sea-->msp-->jfk 这样我不仅可以告诉它它是真的,而且可以告诉它它是如何真实的。
我正在使用 Prolog 在我的一个项目中编码一些相当复杂的规则。有很多递归,包括相互递归。部分规则如下所示:
pred1(X) :- ...
pred1(X) :- someguard(X), pred2(X).
pred2(X) :- ...
pred2(X) :- othercondition(X), pred1(X).
Run Code Online (Sandbox Code Playgroud)
pred1和之间有一个相当明显的无限循环pred2。不幸的是,这些谓词之间的交互非常复杂且难以隔离。我能够通过传递已传递给 的对象列表来消除此实例中的无限循环pred1,但这非常笨拙!事实上,它在很大程度上违背了在这个应用程序中使用 Prolog 的目的。
如何让 Prolog 避免无限循环?例如,如果在证明过程中pred1(foo)尝试将证明pred1(foo)作为子目标,则失败并回溯。
是否可以使用元解释器来做到这一点?
我正在尝试解决这个问题,我已经阅读了这个答案,但我的问题是无限循环,即使我使用了访问节点列表。
让我们看看我的两次尝试:
edge(1,2).
edge(1,4).
edge(1,3).
edge(2,3).
edge(2,5).
edge(3,4).
edge(3,5).
edge(4,5).
% ------ simple path finding in a directed graph
% ----- simple exploration
path0(A,B, Result) :-
path0(A, B, [], Result).
path0(A, B, _, [e(A,B)]):-
edge(A,B).
path0(A, B, Visited, [e(A,X)|Path]):-
edge(A, X), dif(X, B),
\+ member(X, Visited),
path0(X, B, [A|Visited], Path ).
%---- 1. exploration and length
path(A, B, _, [e(A,B)], 1):-
edge(A,B).
path(A, B, Visited, [e(A,X)|Path], Length):-
edge(A, X),
\+ member(X, Visited),
length(Path, L), % ERR: Path refers …Run Code Online (Sandbox Code Playgroud) graph-theory prolog shortest-path non-termination failure-slice
在我最后一个问题下方的评论中详细说明讨论:我正在寻找有关构建 SWI-Prolog 代码的技术或最佳实践的建议,以便能够使用和测试算法及其支持模块的替代、可互换实现。
当前情况可以使用以下虚构的小示例来说明:用户提供一些输入数据 (file data.pl) 并加载具有要应用的算法(file ) 的模块graph.pl。算法模块本身使用来自另一个模块(文件path.pl)的辅助谓词,而后者又需要访问用户提供的数据:
文件“ data.pl”(输入数据集):
:- use_module(graph).
edge(a,b).
edge(b,c).
edge(c,d).
Run Code Online (Sandbox Code Playgroud)
文件“ graph.pl”(算法):
:- module(graph, [reachable/2]).
:- use_module(path).
reachable(X,Y) :-
path(X,Y), !.
reachable(X,Y) :-
path(Y,X), !.
Run Code Online (Sandbox Code Playgroud)
文件“ path.pl”(带有辅助谓词的模块,注意它访问 中的数据user):
:- module(path, [path/2]).
path(X,X).
path(X,Y) :-
user:edge(X,Z),
path(Z,Y).
Run Code Online (Sandbox Code Playgroud)
对于将算法应用于单个输入数据集和算法的单个实现的用例,这完全没问题:
?- [data].
true.
?- reachable(a,a).
true.
?- reachable(a,d).
true.
?- reachable(d,a).
true.
Run Code Online (Sandbox Code Playgroud)
现在假设我有大量的数据集,以及graph和path模块的多个替代实现(具有相同的接口,即导出的谓词)。对于(小)举例的目的,让我们假设我们文件中的数据文件data1.pl,data2.pl,帮手谓语模块path1.pl,path2.pl和算法模块 …
我有一个Prolog函数path(A,B,Path),它产生从A到B的板上的所有有效路径.
此函数的输出如下所示:
?- path(0,2,Path).
Path = [0, 1, 2] ;
Path = [0, 3, 2] ;
Path = [0, 1, 4, 2] ;
Path = [0, 3, 4, 2] ;
Path = [0, 1, 4, 5, 3, 2] ;
Run Code Online (Sandbox Code Playgroud)
等等
它生成一组包含有效路径的无限列表.我只想得到这些路径中最短的路径(无论有多少路径).也就是说,我想要一个函数shortest(A,B,Path),它将在A到B的板上产生最短的有效路径.
我想要的输出是:
?- shortest(0,2,Path).
Path = [0, 1, 2] ;
Path = [0, 3, 2] ;
false.
Run Code Online (Sandbox Code Playgroud)
我一直在玩setofProlog中的函数将所有路径绑定到一个集合,我对它施加了一些长度限制,但我还没有完成它的工作.
到目前为止我的糟糕工作看起来像这样.这绝对是错的,我很感激任何帮助,了解如何setof工作以及如何从这个集合中找到最短的列表.谢谢!
shortest(A,B,MinPath) :-
setof(Path,path(A,B,Path),MinPath),
min(length(Path), length(MinPath)).
Run Code Online (Sandbox Code Playgroud) 来自Bratko的书,人工智能的Prolog编程(第4版) 我们有以下代码不起作用 -
anc4(X,Z):-
anc4(X,Y),
parent(Y,Z).
anc4(X,Z):-
parent(X,Z).
Run Code Online (Sandbox Code Playgroud)
在第55页的图书中,图2.15显示了parent(Y,Z)在堆栈内存不足之前一直保持调用.
我不明白的是,prolog首先对anc4(X,Y)进行recursiv调用,而不是父对象(Y,Z).为什么prolog不会反复到第一行,anc4(X,Y)而是转到第二行?
你能否详细说明为什么这条线parent(Y,Z)被称为?
谢谢.
我正在学习Prolog,我在本教程中学习 了图表.这是我的代码:
path(X, Y, Length, [X,Y], _) :-
connect(X, Y, Length).
path(X, Y, Length, [X|P], V) :-
\+ member(X, V),
connect(X, Z, Length1),
path(Z, Y, Length2, P, [X|V]),
Length is Length1 + Length2.
Run Code Online (Sandbox Code Playgroud)
为了使用它,我打电话
?- path(a, f, Length, Path, []).
Run Code Online (Sandbox Code Playgroud)
但是,我想将其缩短为:
?- path(a, f, Length, Path).
Run Code Online (Sandbox Code Playgroud)
但是我无法获得默认参数.
九洞有8个钉子.开始时,左边的四个红色钉子和右边的四个蓝色钉子,以及它们之间的一个空洞.谜题是将所有红色向右移动,将蓝色钉向左移动(在另一个相反方向).这些是合法的举措:
这是我写的,但它不起作用
% Form of board, b for blue, r for red, o for empty.
% [ [r,r,r,r], [o], [b,b,b,b] ]
% jumps
linjmp([x, x, o | T], [o, o, x | T]).
linjmp([o, x, x | T], [x, o, o | T]).
linjmp([H|T1], [H|T2]) :- linjmp(T1,T2).
% Series of legal boards.
series(From, To, [From, To]) :- jump(From, To).
series(From, To, [From, By | Rest])
:- jump(From, By),
series(By, To, [By | Rest]).
% Print a series …Run Code Online (Sandbox Code Playgroud) prolog ×12
graph-theory ×2
composition ×1
map-function ×1
module ×1
recursion ×1
swi-prolog ×1
unit-testing ×1