Prolog 序言时间重叠

Prolog 序言时间重叠,prolog,Prolog,假设我有这个知识库: free(ann,slot(time(8,0),time(9,0))). free(ann,slot(time(10,0),time(11,0))). free(bob,slot(time(7,0),time(8,30))). free(bob,slot(time(10,0),time(11,0))). free(carla,slot(time(8,0),time(9,0))). free(carla,slot(time(10,0),time(10,15))). 因此

假设我有这个知识库:

free(ann,slot(time(8,0),time(9,0))).
free(ann,slot(time(10,0),time(11,0))).

free(bob,slot(time(7,0),time(8,30))).
free(bob,slot(time(10,0),time(11,0))).

free(carla,slot(time(8,0),time(9,0))).
free(carla,slot(time(10,0),time(10,15))).
因此,经过大量的努力,我成功地编写了一些东西,用以下代码打印出在特定时段内第一个可用的人:

meetone(Person, slot(time(BeginHour, BeginMinute), time(EndHour, EndMinute)))
:- free(Person, slot(time(BH, BM), time(EH, EM))),
   BH*60 + BM =< EndHour*60 + EndMinute,
   EH*60 + EM >= BeginHour*60 + BeginMinute.

main :- (meetone(Person,slot(time(7,15),time(7,20))); halt),
       write(Person),
       nl,
       halt.

:- initialization(main).
这里有一些模糊的伪代码,我认为可能会实现我所寻找的,但我没有足够的经验让它工作

  • 从第一人称的空闲位置开始
  • 递归遍历列表中的其他人,找到重叠的时间
  • 可以使用类似于meetone的东西验证插槽是否重叠;在此验证之后,可以使用两个插槽开始时间的最大值和两个结束时间的最小值来查找准确的重叠周期
  • 打印插槽的最终列表

  • 最终输出将显示8:00-8:30和10:00-10:15的插槽。如果能帮上忙,我们将不胜感激。

    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).
    
    现在来谈谈你的主要问题:

    假设我想找出知识库中每个人的共同时间段

    我将开始编写一个通用的\u时间段/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).
    
    定义了这个之后,所有的commons都可以通过

    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.
    
    ?- main.
    ann: (8:0<8:30)
    ann: (10:0<10:15)
    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)
        )).
    
    免费(安,08:00<09:00)。 免费(安,10:00<11:00)。 免费(鲍勃,07:00<08:30)。 免费(鲍勃,10:00<11:00)。 免费(卡拉,08:00<09:00)。 免费(卡拉,10:00<10:15)。 meetone(个人,插槽):-免费(个人,插槽),包含(插槽,插槽)。 包含(Slot1、Slot2):- 时间点(Slot1、B1、E1), 时间点(时差2、B2、E2), B1==B2。 时间点(BH:BMB是BH*60+BM, E是EH*60+EM ;BH是B//60, BM为地板(B模块60), 呃是E//60, EM为楼层(E模块60) ). %公共_时隙(S、S、S)。 公共_时隙(S1、S2、S):- 时间点(S1、B1、E1), 时间点(S2、B2、E2), B是最大值(B1,B2), E是最小值(E1,E2), B 这就产生了

    ?- 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.
    
    ?- main.
    ann: (8:0<8:30)
    ann: (10:0<10:15)
    true.
    
    ?-main。
    
    ann:(8:0您的伪代码是正确的。您应该从编写第3步的谓词开始:
    overlap(S1,S2,句点)
    是的。事实上,我首先用Java编写了一个解决方案,以确保唯一的障碍是语言不熟悉。经过数小时的尝试,我似乎无法做到这一点,原本是一个有趣的项目却变成了一件非常令人沮丧的事。我无法用Prolog思考,我缺乏Prolog调试技能,理解流控制等的取消使得这一点非常具有挑战性。根据我的经验,与命令式语言相比,Prolog中最大的障碍是感觉函数(参数输入,返回值输出)和谓词(绑定输入,统一绑定输出)之间的区别。这就是为什么我建议您尝试使用一个较小的构建块,它的工作方式不同。在您的情况下,
    重叠
    将使用绑定插槽S1和S2调用,当它们重叠时会成功,重叠时段将绑定到进程中的时段。事实并非如此!您可以使用
    (=这是我在博伊西州立大学的一名学生:他违反了学校的学术诚信政策。请不要帮助他。我正在努力将他/她从我们的课程中开除。谢谢。--JimApologies的不明确性;最终结果应该只显示时间段8-8:30和10:00-10:15,这三个时间段都是可用。(这是常用的交叉口吗?)但是这看起来很有帮助,如果我现在有点不知所措的话。我会在我闭上眼睛后更详细地看它。谢谢!+1,但是在我看来,
    -
    会比
    更可读,这没有多大意义,特别是因为
    8<9
    。所以
    免费(安,8:00-9:00)
    对我来说似乎更好。@mat:谢谢,我将实现您的注释,但是-的优先级错误,可能需要父项。我将切换到或使用一个新的中缀运算符
    -->
    。太棒了。使用GNU Prolog 1.4.4,我似乎得到了以下错误:未捕获异常:错误(type_error(float,0),(is)/2)知道在哪里/为什么会发生这种情况吗?