相关疑难解决方法(0)

将谓词应用于列表元素的Prolog映射过程

如何编写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)

prolog meta-predicate map-function

35
推荐指数
1
解决办法
2万
查看次数

自反传递闭包的定义

许多谓词基本上使用某种形式的传递闭包,只是发现终止也必须得到解决.为什么不一次解决这个问题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)

是否存在此定义不能用于实现传递闭包的情况?


为什么dif/2?

详细回答@ 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 transitive-closure prolog-toplevel meta-predicate

22
推荐指数
1
解决办法
2976
查看次数

在 Prolog 中查找图中两个节点之间的最短路径

我想在 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)

谢谢。

graph-theory prolog shortest-path

5
推荐指数
1
解决办法
7423
查看次数

在prolog中,为什么不添加"edge(X,Y): - edge(Y,X)".单独工作将有向图定义转换为无向图

我正在学习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

prolog transitive-closure failure-slice

5
推荐指数
2
解决办法
223
查看次数

如何让 Prolog 解释超出真实陈述的结果

我有以下事实和规则:

  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

5
推荐指数
1
解决办法
332
查看次数

处理复杂的序言循环

我正在使用 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)作为子目标,则失败并回溯。

是否可以使用元解释器来做到这一点?

prolog prolog-metainterpreter

5
推荐指数
1
解决办法
106
查看次数

查找图中节点之间的路径及其长度

我正在尝试解决这个问题,我已经阅读了这个答案,但我的问题是无限循环,即使我使用了访问节点列表。

让我们看看我的两次尝试:

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

5
推荐指数
1
解决办法
2766
查看次数

将 SWI-Prolog 代码构建到模块中,用于多个算法和数据集的单元测试

我最后一个问题下方的评论中详细说明讨论:我正在寻找有关构建 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)

现在假设我有大量的数据集,以及graphpath模块的多个替代实现(具有相同的接口,即导出的谓词)。对于(小)举例的目的,让我们假设我们文件中的数据文件data1.pldata2.pl,帮手谓语模块path1.plpath2.pl和算法模块 …

unit-testing module prolog composition swi-prolog

5
推荐指数
1
解决办法
499
查看次数

如何从无限集中找到最短长度列表(Prolog)

我有一个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)

prolog shortest-path iterative-deepening

3
推荐指数
1
解决办法
695
查看次数

无法理解为什么prolog无限循环

来自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)被称为?

谢谢.

recursion prolog transitive-closure

3
推荐指数
1
解决办法
94
查看次数

编写Prolog谓词以向另一个谓词提供默认参数

我正在学习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)

但是我无法获得默认参数.

prolog optional-parameters default-parameters

1
推荐指数
1
解决办法
1047
查看次数

试图解决Prolog中的跳钉拼图

九洞有8个钉子.开始时,左边的四个红色钉子和右边的四个蓝色钉子,以及它们之间的一个空洞.谜题是将所有红色向右移动,将蓝色钉向左移动(在另一个相反方向).这些是合法的举措:

  1. 钉子可能只向前移动(红色可能向右移动而蓝色向左移动).
  2. 栓钉可向前移动一步到打开位置.
  3. 如果超出它的位置是打开的,那么一个挂钩可能会跳过一个相反颜色的挂钩.

这是我写的,但它不起作用

% 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 eight-peg-puzzle

0
推荐指数
1
解决办法
1148
查看次数