Prologue.

Say I have this knowledge base:

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))).

So, after many efforts, I managed to write what prints the first person who has accessibility for a specific slot with the following code:

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).

Prints bob, expected result.

Here, where it gets complicated (at least for me). Let's say I want to find out all the time intervals that everyone has in the Knowledge Base. The following code demonstrates how I ultimately want to call it:

people([ann,bob,carla]).

meet :- ???

main :- (setof(Slot,meet(Slot),Slots); halt),
        write(Slots),
        nl,
        halt.

:- initialization(main).

Here is some vague pseudo-code that I think can fulfill what I am looking for, but I am not experienced enough to make it work.

  • Start with free first person slots.
  • Recursively move the rest of the list of people, find overlapping times.
  • , meetone; .
  • .

8:00 8:30 10:00 - 10:15. .

+4
1

Prolog , , imho, . , :

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).

, : /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.

, /3 "". common_timeslot/3, .

, , "" . , forall/2, setof/3, , , Prolog.

+1

All Articles