它们存在吗?他们是如何实施的?
所述coroutining SWI-Prolog的(的谓词freeze,when,dif等)具有的功能警卫.它们如何适合首选的Prolog编程风格?
我是很新的逻辑编程(有序言和共)和事实,即它不是纯粹的声明,并要求即使在非常简单的情况下程序上的考虑有点困惑(见本关于使用问题\==或dif).我错过了重要的事吗?
我一直反对这一点,我无法确定攻击它的方法.以下是处理一些季节事实的两种方法.
我想弄清楚的是,是否使用方法1或方法2,以及每种方法的利弊是什么,特别是大量的事实.
methodone因为事实是可用的,所以似乎很浪费,为什么还要建立一个列表(特别是一个大的列表).如果列表足够大,这也必须有内存含义吗?它没有利用Prolog的自然回溯功能.
methodtwo利用回溯来为我做递归,我猜想会有更多的内存效率,但是通常这样做是不是很好的编程习惯呢?这可以说是更难以理解,可能还有其他副作用吗?
我可以看到的一个问题是每次fail调用时,我们都失去了将任何东西传递回调用谓词的能力,例如.如果是的话methodtwo(SeasonResults),因为我们故意不断地破坏谓词.所以methodtwo需要断言事实来存储状态.
大概(?)方法2会更快,因为它没有(大)列表处理吗?
我可以想象,如果我有一个清单,那么methodone将是要走的路......还是总是如此?在任何情况下都可以将列表声明为事实,methodone然后使用方法二处理它们?完全疯了吗?
但话说回来,我读到断言事实是一项非常"昂贵"的业务,所以列表处理可能是要走的路,即使是大型列表?
有什么想法吗?或者有时候使用一个而不是另一个更好,这取决于(什么)情况?例如.对于内存优化,使用方法2,包括断言事实,以及速度使用方法1?
season(spring).
season(summer).
season(autumn).
season(winter).
% Season handling
showseason(Season) :-
atom_length(Season, LenSeason),
write('Season Length is '), write(LenSeason), nl.
% -------------------------------------------------------------
% Method 1 - Findall facts/iterate through the list and process each
%--------------------------------------------------------------
% Iterate manually through a season list
lenseason([]).
lenseason([Season|MoreSeasons]) :-
showseason(Season),
lenseason(MoreSeasons).
% Findall to build a list then iterate until all done
methodone :-
findall(Season, season(Season), …Run Code Online (Sandbox Code Playgroud) 尝试编写一个给出值和列表的过程,它会删除列表中写入的值的所有出现:
delMember(X, [], []) :- !.
delMember(X, [X|Xs], Y) :- !, delMember(X, Xs, Y).
delMember(X, [T|Xs], Y) :- !, delMember(X, Xs, Y2), append([T], Y2, Y).
Run Code Online (Sandbox Code Playgroud)
由于cut此代码无法正确回答如下问题:
delMember(Y, [1,2,3,1,2,3,1,2,3], [1, 2, 1, 2, 1, 2 ]).
Run Code Online (Sandbox Code Playgroud)
如果我删除剪辑:
delMember(X, [], []).
delMember(X, [X|Xs], Y) :- delMember(X, Xs, Y).
delMember(X, [T|Xs], Y) :- delMember(X, Xs, Y2), append([T], Y2, Y).
Run Code Online (Sandbox Code Playgroud)
它在以下查询中失败:
delMember(Y, [1,2,3,1,2,3,1,2,3], [1,2,3,1,2,3,1,2,3]).
Run Code Online (Sandbox Code Playgroud)
(true当正确的答案是时,返回false).
如何使它在两种情况下都能正常工作?
也许我可以X is not T在第三行代码中检查一下,我试过:
delMember(X, [T|Xs], Y) :- …Run Code Online (Sandbox Code Playgroud) 好的我是Prolog的新手,请原谅,如果这是微不足道的,但我似乎无法找到一个合适的优雅答案.我试图在learnprolognow.org,练习2.4(填字游戏)上进行练习.
练习提供了以下事实:
word(astante, a,s,t,a,n,t,e).
word(astoria, a,s,t,o,r,i,a).
word(baratto, b,a,r,a,t,t,o).
word(cobalto, c,o,b,a,l,t,o).
word(pistola, p,i,s,t,o,l,a).
word(statale, s,t,a,t,a,l,e).
Run Code Online (Sandbox Code Playgroud)
我想出解决每个单词的填字游戏位置的解决方案是这样的:
crossword(V1, V2, V3, H1, H2, H3) :-
word(V1, V1a, V1bH1b, V1c, V1dH2b, V1e, V1fH3b, V1g),
word(V2, V2a, V2bH1d, V2c, V2dH2d, V2e, V2fH3d, V2g),
word(V3, V3a, V3bH1f, V3c, V3dH2f, V3e, V3fH3f, V3g),
word(H1, H1a, V1bH1b, H1c, V2bH1d, H1e, V3bH1f, H1g),
word(H2, H2a, V1dH2b, H2c, V2dH2d, H2e, V3dH2f, H2g),
word(H3, H3a, V1fH3b, H3c, V2fH3d, H3e, V3fH3f, H3g).
Run Code Online (Sandbox Code Playgroud)
随着V1a对V1g等为每个单词的字符,并且V1bH1b …
我在理解为什么我的prolog代码根据我的规则的顺序做了一些事情时遇到了一些麻烦.
这是我的数据库:
parent(tom, bob).
parent(tom, liz).
parent(mary, bob).
parent(mary, liz).
male(tom).
male(bob).
female(mary).
female(liz).
Run Code Online (Sandbox Code Playgroud)
以下是规则:
%difference(X, Y) ==> Predicate to check if two people X and Y are not the same person.
difference(X, Y) :- \==(X, Y).
father(X, Y) :- male(X), parent(X, Y), difference(X, Y).
mother(X, Y) :- female(X), parent(X, Y), difference(X, Y).
sibling(X, Y) :-
difference(X, Y),
mother(M, X), mother(M, Y),
father(F, X), father(F, Y).
Run Code Online (Sandbox Code Playgroud)
问题是,当我这样做时,
?- sibling(bob, X).
Run Code Online (Sandbox Code Playgroud)
我明白了
X = bob ;
X = liz ;
false. …Run Code Online (Sandbox Code Playgroud) 围绕dif/2约束存在很多炒作,特别是作为对(\ =)/ 2和(\ ==)/ 2的一些非声明性的拯救.这种非声明性通常被描述为非单调性,并给出了非交际性的例子.
但是,测试涉及dif/2的测试用例是否可交换的方法是什么.以下是我想要做的元解释:
我进行了交换性测试,我想探究两种变体给出相同的结果:
Run Code Online (Sandbox Code Playgroud)?- A, B. -- versus -- ?- B, A.
所以通常你可以用(==)/ 2内置谓词检查单调性,如果它归结为检查交换性.由于此谓词遵循实例化变量.
但是,如果您正在测试产生约束的情况,call_with_residue/2是不够的,您还需要具有相等的约束.这可能很棘手,如下例所示:
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.23)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam
?- dif(f(X,X),f(a(U,g(T)),a(g(Z),U))), X=a(g(Z),U).
X = a(g(Z), U),
dif(f(a(g(Z), U), U, Z, U, T), f(a(U, g(T)), g(Z), T, g(Z), Z)).
?- X=a(g(Z),U), dif(f(X,X),f(a(U,g(T)),a(g(Z),U))).
X = a(g(Z), U),
dif(f(U, T), f(g(Z), Z)).
Run Code Online (Sandbox Code Playgroud)
任何想法如何进行?
免责声明,它是一个陷阱:
我不认可交换性测试作为一种好的测试方法,在这种方法中你可以将好的和坏的谓词与规范分开.因为通常好的和坏的谓词都可能没有交换性问题.
我正在使用交换性测试作为一种工具来找出有关dif/2约束相等的方法.然后,可以在更传统的测试用例中将此等式用作验证点.
我正在使用SICStus Prolog并拥有一系列事实:
student('John Henry', 'Maths').
student('Jim Henry', 'Maths').
student('John Alan', 'Maths').
student('Alan Smith', 'Computing').
student('Gary Henry', 'Maths').
Run Code Online (Sandbox Code Playgroud)
我想得到两个学生的共同主题,两个学生都不同,所以我得到了:
sharedSubject(S1, S2, Sub) :- S1 \== S2, student(S1, Sub), student(S2, Sub).
Run Code Online (Sandbox Code Playgroud)
但是,当我输入:
sharedSubject('John Henry', F, E).
Run Code Online (Sandbox Code Playgroud)
我得到F = 'John Henry'.有人可以指出我出错的地方以及我需要做什么吗?谢谢.
本页上的练习09 http://www.ic.unicamp.br/~meidanis/courses/mc336/2009s2/prolog/problemas/要求创建一个谓词,将重复的元素打包到子列表中.
一个直截了当的解决方案很简单
pack([], []).
pack([H|T], [I|U]) :-
split(H, T, I, P),
pack(P, U).
Run Code Online (Sandbox Code Playgroud)
split split(Head, Tail, HeadGroup, Rest)的定义为
split(A, [], [A], []).
split(A, [B|T], [A], [B|T]) :- A \= B.
split(A, [A|T], [A|U], B) :- split(A, T, U, B).
Run Code Online (Sandbox Code Playgroud)
工作正常,几乎与上述网页上提供的示例解决方案一致.
这个解决方案失败的地方是查询pack(X, [[a], [b, b]])..2个解集之间的对应关系是双射(对于每个A在pack(A, B)有一个且只有一个B),所以必须有一个更好的解决方案.
解决它的一种方法是改变评估的顺序,帮助prolog根据参数的类型选择非无限分支,如下所示
pack([], []).
pack(A, B) :-
( var(A) ->
A = [H|T],
B = [I|U],
pack(P, U),
split(H, T, I, P)
; A = …Run Code Online (Sandbox Code Playgroud) 我需要在列表中找到第一个重复值.
prep(3,[1,3,5,3,5]). 应该是真的.
prep(5,[1,3,5,3,5]). 应该是假的.
我想检查与当前值和先前列表成员的相等性,直到我找到重复,如果它找到一个它将测试与X的相等但我不知道如何在Prolog中做到这一点!
我感谢任何帮助!谢谢
是否存在差异检查?这在这里有效:
Welcome to SWI-Prolog (threaded, 64 bits, version 8.3.7)
?- set_prolog_flag(occurs_check, true).
true.
?- dif(X,f(Y)), X = Y.
X = Y.
Run Code Online (Sandbox Code Playgroud)
但以上是不可行的,因为发生检查是一个全局标志,我得到以下信息:
SWI-Prolog console for thread 3
?- X=f(X).
false.
Run Code Online (Sandbox Code Playgroud)