Prolog 有一些语法特性,恕我直言,它们确实有助于编写可理解的代码。然后这是您的问题,利用运营商获得可读性:
free(ann, 08:00 > 09:00).
free(ann, 10:00 > 11:00).
free(bob, 07:00 > 08:30).
free(bob, 10:00 > 11:00).
free(carla, 08:00 > 09:00).
free(carla, 10:00 > 10:15).
meetone(Person, Slot) :- free(Person, SlotP), contains(SlotP, Slot).
contains(Slot1, Slot2) :-
timepoints(Slot1, B1, E1),
timepoints(Slot2, B2, E2),
B1 =< E2, E1 >= B2.
timepoints(BH:BM > EH:EM, B, E) :-
B is BH*60 + BM,
E is EH*60 + EM.
main :- setof(Person, meetone(Person, 7:15 > 7:20), Available),
maplist(writeln, Available).
我试图介绍两个实用程序,一种可重用的代码:contains/2 和 timepoints/3。在编写更复杂的逻辑时,拥有这样的片段可能会有所帮助......
运行这段代码,我得到
?- main.
bob
true.
现在来到你的主要问题:
假设我想找出知识库中每个人共有的所有时间段
我将开始编写 common_timeslot/3,解释(计算)预期内容:
common_timeslot(S1, S2, Common) :-
timepoints(S1, B1, E1),
timepoints(S2, B2, E2),
% do you mean intersection by common ?
...
否则,只考虑身份
common_timeslot(S, S, S).
定义了这个之后,所有的公共都可以找到
main :-
setof(Sc/P/Q, Sp^Sq^(
free(P, Sp), free(Q, Sq), Q \= P,
common_timeslot(Sp, Sq, Sc)
), Commons),
maplist(writeln, Commons).
产生
?- main.
(8:0>9:0)/ann/carla
(8:0>9:0)/carla/ann
(10:0>11:0)/ann/bob
(10:0>11:0)/bob/ann
true.
编辑mat 评论的会计,现在我发布整个程序
free(ann, 08:00 < 09:00).
free(ann, 10:00 < 11:00).
free(bob, 07:00 < 08:30).
free(bob, 10:00 < 11:00).
free(carla, 08:00 < 09:00).
free(carla, 10:00 < 10:15).
meetone(Person, Slot) :- free(Person, SlotP), contains(SlotP, Slot).
contains(Slot1, Slot2) :-
timepoints(Slot1, B1, E1),
timepoints(Slot2, B2, E2),
B1 =< E2, E1 >= B2.
timepoints(BH:BM < EH:EM, B, E) :-
( ( var(B), var(E) )
-> B is BH * 60 + BM,
E is EH * 60 + EM
; BH is B // 60,
BM is floor(B mod 60),
EH is E // 60,
EM is floor(E mod 60)
).
% common_timeslot(S, S, S).
common_timeslot(S1,S2,S) :-
timepoints(S1,B1,E1),
timepoints(S2,B2,E2),
B is max(B1,B2),
E is min(E1,E2),
B < E,
timepoints(S,B,E).
% base case: C passed all commonality test
check_common(C, [], C).
% S is the current common, to be checked for availability on person P
check_common(S, [P|Ps], C) :-
free(P, Sp),
common_timeslot(S, Sp, Ct),
check_common(Ct, Ps, C).
main :- setof(P, S^free(P,S), [FirstP|Others]),
forall(free(FirstP, S), (
check_common(S, Others, C),
writeln(FirstP:C)
)).
产生
?- main.
ann: (8:0<8:30)
ann: (10:0<10:15)
true.
主要变化是 timepoints/3 现在是“双向”的。然后我介绍了 common_timeslot/3 正如您在评论中解释的那样。
我想你会明白那些小的句法抽象有助于拥有一个干净的“应用”逻辑。当然,forall /2 或setof /3 是您需要学习的内置函数,以便更熟练地使用 Prolog。