在Prolog中,我如何制定一个规则来检查一个人网络中有多少人进入,然后查询其分离程度?
例如,如果在Facebook,我的名字是约翰;我有一个朋友汤姆,汤姆有一个朋友露西,露西有一个朋友本,本有一个朋友约什,约什有一个朋友南希。
我想在Prolog中创建一个规则来测试我的网络中有多少人,并告诉Prolog将名称返回到给定的分离度。
e.g。如果我查询类似的东西;
?- mynetwork(josh,2).
Prolog应该返回
或
答案 0 :(得分:4)
欢迎来到Prolog!
首先,你需要一些事实:
friend(john, tom).
friend(tom, lucy).
friend(lucy, ben).
...
为简单起见,让我们考虑友情关系的情况:我可以和你交朋友,但这并不意味着你和我交往。
如果我和你结识,我们就说我们是1级的朋友。这看起来像这样:
network(Person, 1, Friend) :- friend(Person, Friend).
现在,归纳案例是我们通过朋友找到朋友的案例。这看起来像这样:
network(Person, N1, FoaF) :-
N1 > 1,
N0 is N1-1,
network(Person, N0, Friend),
network(Friend, 1, FoaF).
使用is/2
可以确定谓词不正常。例如,如果省略> 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).
这应该适用于你想要尝试的所有输入案例,尽管它仍然无法知道你何时超出友谊水平。
?- 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.
修改让我不按顺序回答您的问题。
打印声明在哪里?
按照设计,我没有使用过。在此之前,我们只是使用Prolog REPL(读取 - 评估 - 打印循环)来完成I / O.这是与Prolog合作的自然方式。如果您遇到一些麻烦,将I / O和用户表示的谓词与关注意义的谓词分开,那么您以后会为自己省去很多心痛。这只是模型视图分离的小型应用。您还可以将副作用隔离在自己的谓词中。只要程序的纯逻辑部分是自包含的,您就可以随时构建和编写它。
您如何打印给定数量的人。例如如果你输入网络(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(_, _).
这样可以这样工作:
?- show_network(john, 3).
john is friends with tom.
john is friends with lucy.
john is friends with ben.
true.
还有其他方法,例如,您可以使用forall/2
:
show_network(Person, Max) :-
forall(
(between(1, Max, N), network(Person, N, Friend)),
format('~w is friends with ~w\n', [Person, Friend])).
故障驱动循环与那个循环之间的关系应该非常明确。您也可以手动获取列表,然后使用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]).