0 prolog
在Prolog中,我如何制定一条规则来检查一个人的网络中有多少人,然后查询分离程度?
例如,如果在 Facebook 中我的名字是 John;我有一个朋友汤姆,汤姆有一个朋友露西,露西有一个朋友本,本有一个朋友乔什,乔什有一个朋友南希。
我想在 Prolog 中创建一条规则来测试我的网络中有多少人,并告诉 Prolog 返回达到给定分离度的名称。
例如,如果我查询类似的内容;
?- mynetwork(josh,2).
Run Code Online (Sandbox Code Playgroud)
Prolog 应该返回
或者
欢迎来到普罗格!
首先你需要一些事实:
friend(john, tom).
friend(tom, lucy).
friend(lucy, ben).
...
Run Code Online (Sandbox Code Playgroud)
为简单起见,让我们考虑一下友谊定向的情况:我可以加你为好友,但这并不意味着你也加我为好友。
如果我加你为好友,我们就可以说我们是 1 级好友。那看起来像这样:
network(Person, 1, Friend) :- friend(Person, Friend).
Run Code Online (Sandbox Code Playgroud)
现在归纳的情况是我们通过朋友找到了朋友。看起来像这样:
network(Person, N1, FoaF) :-
N1 > 1,
N0 is N1-1,
network(Person, N0, Friend),
network(Friend, 1, FoaF).
Run Code Online (Sandbox Code Playgroud)
使用is/2you 可以确定谓词将表现不良。例如,如果您省略> 1约束,您将能够提出问题并得到 N 答案,而如果您包含该约束,则无法得到答案。但您也会收到有关超出本地堆栈的错误。因此,如果您有能力,请clpfd立即引入:
:- use_module(library(clpfd)).
network(Person, 1, Friend) :- friend(Person, Friend).
network(Person, N1, FoaF) :-
N1 #> 0,
N0 #= N1-1,
network(Person, N0, Friend),
network(Friend, 1, FoaF).
Run Code Online (Sandbox Code Playgroud)
这应该适用于您想要尝试的所有输入情况,尽管它仍然无法知道您何时超出友谊级别。
?- network(john, N, X).
N = 1,
X = tom ;
N = 2,
X = lucy ;
N = 3,
X = ben ;
^CAction (h for help) ? abort
% Execution Aborted
?- network(john, 3, X).
X = ben ;
false.
?- network(john, 2, X).
X = lucy ;
false.
Run Code Online (Sandbox Code Playgroud)
编辑让我不按顺序回答你的问题。
打印语句在哪里?
根据设计,我没有使用过。到目前为止,我们只是使用 Prolog REPL(读取-求值-打印循环)来执行 I/O。这是使用 Prolog 的自然方式。如果您费尽心思将执行 I/O 和用户表示的谓词与与含义相关的谓词分开,那么您以后会省去很多心痛。这只是模型视图分离的一个小型应用。您还可以受益于将副作用隔离在它们自己的谓词中。只要程序的纯逻辑部分是独立的,您就始终能够使用它进行构建和组合。
您将如何打印给定数量的人员。例如,如果您输入 network(john, 3, X)。那么它应该打印出最多 N=3 X=ben
我倾向于调用这个谓词show_network/2来代替并保持分离。您可以使用故障驱动循环以廉价的方式完成此操作,如下所示:
show_network(Person, Max) :-
between(1, Max, N),
network(Person, N, Friend),
format('~w is friends with ~w\n', [Person, Friend]),
fail.
show_network(_, _).
Run Code Online (Sandbox Code Playgroud)
这将像这样工作:
?- show_network(john, 3).
john is friends with tom.
john is friends with lucy.
john is friends with ben.
true.
Run Code Online (Sandbox Code Playgroud)
还有其他方法,例如,您可以使用forall/2:
show_network(Person, Max) :-
forall(
(between(1, Max, N), network(Person, N, Friend)),
format('~w is friends with ~w\n', [Person, Friend])).
Run Code Online (Sandbox Code Playgroud)
故障驱动循环与该循环之间的关系应该非常清楚。您还可以手动获取列表,然后使用maplist/2以下命令处理它:
show_network(Person, Max) :-
findall(friend(Person,Friend),
(between(1, Max, N), network(Person, N, Friend)),
Friends),
maplist(show_friend, Friends).
show_friend(friend(Person, Friend)) :-
format('~w is friends with ~w\n', [Person, Friend]).
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
331 次 |
| 最近记录: |