和许多程序员一样,我在大学里学过Prolog,但只是很少.我知道Prolog和Datalog密切相关,但Datalog更简单吗?另外,我相信我读到Datalog不依赖于逻辑子句的排序,但我不确定为什么这是优点.据说CLIPS完全不同,但对我来说理解太微妙了.有人可以提供其他语言的一般语言亮点吗?
随着时间的推移,似乎越来越像函数式编程对其他编程语言产生更多影响.我们在我的AI课程中开始使用Prolog,似乎有一些东西可以使非AI领域的编程变得更容易.我的问题是:为什么逻辑编程没有以同样的方式被捕获?
在本主题中,似乎达成了一个普遍的共识,即逻辑编程很有用,但必须这样证明.它有没有被认为有用的原因?
更新:也许我应该更清楚一点.我不是在问Prolog.我可以理解为什么在大多数真实世界的应用程序中选择Prolog不是一个好主意.
为了举一个我正在讨论的内容的例子,请考虑Python中的列表推导/ map/filter.这些明显受功能语言的影响.为什么像Python这样的语言还没有从逻辑编程语言中学到这些东西,比如它们有函数式语言?
是否可以在Prolog中使用惰性列表?类似于以下内容:
ones([1 | Y]) :- ones(Y).
Run Code Online (Sandbox Code Playgroud)
虽然这显然不起作用.
我只与Prolog合作了几天.我理解一些事情,但这真让我感到困惑.
我想要编写一个带有列表并将其展平的函数.
?- flatten([a,[b,c],[[d],[],[e]]],Xs).
Xs = [a,b,c,d,e]. % expected result
Run Code Online (Sandbox Code Playgroud)
该函数取出列表的内部结构.
这是我到目前为止:
flatten2([],[]).
flatten2([Atom|ListTail],[Atom|RetList]) :-
atom(Atom), flatten2(ListTail,RetList).
flatten2([List|ListTail],RetList) :-
flatten2(List,RetList).
Run Code Online (Sandbox Code Playgroud)
现在,这在我打电话时起作用:
?- flatten2([a,[b,c],[[d],[],[e]]], R).
R = [a,b,c,d,e]. % works as expected!
Run Code Online (Sandbox Code Playgroud)
但是当我打电话来查看我输入的列表是否已经展平时,将返回false而不是true:
?- flatten2([a,[b,c],[[d],[],[e]]], [a,b,c,d,e]).
false. % BAD result!
Run Code Online (Sandbox Code Playgroud)
为什么一方面工作,另一方面又不工作?我觉得我错过了很简单的事情.
鉴于word/1,
word(W) :-
abs(ABs),
ABs = W.
abs([]).
abs([AB|ABs]) :-
abs(ABs),
ab(AB).
ab(a).
ab(b).
?- word(W).
W = []
; W = [a]
; W = [b]
; W = [a,a]
; W = [b,a]
; W = [a,b]
; W = [b,b]
; W = [a,a,a]
; W = [b,a,a]
; W = [a,b,a]
; W = [b,b,a]
; W = [a,a,b]
; W = [b,a,b]
; W = [a,b,b]
; W = [b,b,b]
; W = …Run Code Online (Sandbox Code Playgroud) N-Queens问题:
这个问题表明,给定一个大小为N乘N的国际象棋棋盘,找到不同的排列,其中N个皇后可以放在棋盘上而没有任何一个相互威胁.
我的问题是:
程序可以在合理的时间内计算出答案的N的最大值是多少?或者到目前为止我们看到的最大N是多少?
这是我在CLPFD(Prolog)中的程序:
generate([],_).
generate([H|T],N) :-
H in 1..N ,
generate(T,N).
lenlist(L,N) :-
lenlist(L,0,N).
lenlist([],N,N).
lenlist([_|T],P,N) :-
P1 is P+1,
lenlist(T,P1,N).
queens(N,L) :-
generate(L,N),lenlist(L,N),
safe(L),
!,
labeling([ffc],L).
notattack(X,Xs) :-
notattack(X,Xs,1).
notattack(X,[],N).
notattack(X,[Y|Ys],N) :-
X #\= Y,
X #\= Y - N,
X #\= Y + N,
N1 is N + 1,
notattack(X,Ys,N1).
safe([]).
safe([F|T]) :-
notattack(F,T),
safe(T).
Run Code Online (Sandbox Code Playgroud)
这个程序运行得很好,但是它花费的时间不断增加N.这是一个示例执行:
?- queens(4,L).
L = [2, 4, 1, 3] ;
L = [3, 1, 4, 2] ;
No
Run Code Online (Sandbox Code Playgroud)
这意味着您将4个皇后放置在第1列的第2行,第2列的第4行,第3行的第1行和第4行的第3行(在4乘4的棋盘中)
现在让我们看看这个程序是如何执行的(计算第一个排列所花费的时间):
对于N …
我知道在Prolog中你可以做类似的事情
someFunction(List) :-
someOtherFunction(X, List)
doSomethingWith(X)
% and so on
Run Code Online (Sandbox Code Playgroud)
这不会迭代List中的每个元素; 相反,它将分支到不同的"机器" (通过使用多个线程,在单个线程上回溯,创建并行Universe或者你是什么),并为每个可能的X值执行单独的执行,导致someOtherFunction(X, List)返回true!
(我不知道它是如何做到的,但这对问题并不重要)
我的问题是: 还有哪些其他非决定性编程语言? 似乎非确定性是在具有不可变变量的语言中实现多线程的简单化和最合乎逻辑的方式,但我以前从未见过这样做 - 为什么这种技术不再流行?
multithreading functional-programming prolog non-deterministic
我想计算自定义谓词为真的次数.例如,我有以下代码:
is_man(john).
is_man(alex).
?:-is_man(X).
Run Code Online (Sandbox Code Playgroud)
X将返回john,然后如果我按分号,它也将返回alex,然后返回false.
我想建立像:
count(is_man(X), Count).
Run Code Online (Sandbox Code Playgroud)
而这回归
Count = 2
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?
在CLP(FD)中,我们经常需要声明:"这是整数和有限域变量的列表(有时:严格地)升序/降序."
是否有任何CLP(FD)系统为此任务提供通用(参数化)内置约束?
SWI-Prolog提供了一个名为的约束chain/2,类似于我正在寻找的约束.但是,名称稍微过于具体,不能包含约束可以描述的所有关系(例如:#<不是部分顺序,但是可以接受chain/2,导致序列 - 作为一组整数 - 不再计算为链中定义的链数学顺序理论).因此,该名称并未完全描述约束实际实现的内容.
请给所述最一般相对于通常的二进制CLP(FD)约束定义-或包含至少一个合适的子集#<,#>,#=<和#>=- 包括根据代数结构的约束定义适当的名称.强加的条件是约束描述了在文献中具有正确名称的实际数学结构.
首先,请考虑使用SICStus Prolog或SWI:
:- use_module(library(clpfd)).
connex(Relation_2, List) :-
connex_relation(Relation_2),
connex_(List, Relation_2).
connex_relation(#=).
connex_relation(#<).
connex_relation(#=<).
connex_relation(#>).
connex_relation(#>=).
connex_([], _).
connex_([L|Ls], Relation_2) :-
foldl(adjacent(Relation_2), Ls, L, _).
adjacent(Relation_2, X, Prev, X) :- call(Relation_2, Prev, X).
Run Code Online (Sandbox Code Playgroud)
示例案例:
?- connex(#<, [A,B,C]).
A#=<B+-1,
B#=<C+-1.
?- connex(#=, [A,B,C]).
A = B, B = C,
C in inf..sup. …Run Code Online (Sandbox Code Playgroud) 我正在尝试定义一个谓词adjacent(X, Y, Zs),如果X和Y在列表中相邻,则该谓词为真.我的代码目前是这样的:
adjacent(_, _, []).
adjacent(X, Y, [X, Y|Tail]) :-
adjacent(X,Y, Tail).
Run Code Online (Sandbox Code Playgroud)
它适用于基本情况adjacent(c, d, [a, b, c, d, e]),但由于基本情况,每个其他情况也返回true,我坚持这一点.
另一个问题是,如果X不等于列表头部的第一部分,那么它会跳过X和Y并转到下一个'X'; 例如,如果c不等于a,则它跳过a和b两者并检查c是否等于c.例如,当列表是这时,这是有问题的
[a, c, d, e]
Run Code Online (Sandbox Code Playgroud)
因为它最终永远不会检查c(我相信).
我很遗憾如何协调这两个问题,并将我对逻辑的理解转化为代码需要发生的事情.
编辑:感谢Christian Hujer的回答,我的基本情况错误已得到纠正,所以现在我只是坚持第二个问题.