/* prolog server */

:- use_module(library(sockets)).
:- use_module(library(lists)).
:- reconsult('report.pl').

start_server(Port, QueueLength) :-
        nl,write('Common Process Assistant (CPA) version 1.0'),nl,
        write('  Listening on port 6792...'),nl,
        socket('AF_INET', Socket),
        socket_bind(Socket, 'AF_INET'(localhost, Port)),
        socket_listen(Socket, QueueLength),
        loop(Socket).

loop(Socket) :-
        socket_accept(Socket, Client, Stream),
        on_exception(RE, get_request(Stream, Request),
		     h1(Stream,Client,RE)),
        on_exception(PE, process(Request, Stream, Client),
	h1(Stream, Client, PE)),
        loop(Socket).

get_request(Stream, Request):-
        read(Stream, Request).

process(bye, Stream, _Client) :-
        close(Stream).
process(Request, Stream, Client) :-
        on_exception(E, user:application_handle(Request,Stream,Result), 
	h2(Stream, no, E)),
        return(Stream,Result),
        on_exception(RE, get_request(Stream, Request1),
		     h1(Stream,Client,RE)),
        on_exception(PE, process(Request1, Stream, Client),
	h1(Stream, Client, PE)).

return(Stream,Result) :-
        nonvar(Result), !,
        format(Stream, "~w~nend~n", [Result]),
        flush_output(Stream).
return(_, _).

h1(Stream, C, E) :-
        format(Stream, "error~n",[]),
        format(user_output, "Client: ~w~nError: ~w",[C, E]).

h2(Stream, Ack, E) :-
        format(Stream, "~w~n",[Ack]),
        format(user_output, "Application Error: ~w~n",[E]).

% add_node/2 

application_handle(add_node(Key),_,Output) :- 
	%write('Running add_node...'), nl,
	add_node(Key,Output).
add_node(Key,Output) :- 
	assert(node(Key)),
	Output ='Ok'.

% add_before/2

application_handle(add_before(Point1,Point2),_,Output) :- 
	%write('Running add_before...'), nl,
	add_before(Point1,Point2,Output).
add_before(Point1,Point2,Output) :- 
	assert(before_pts(Point1,Point2)),
	Output ='Ok'.

% add_equal/2 

application_handle(add_equal(Point1,Point2),_,Output) :- 
	%write('Running add_equal...'), nl,
	add_equal(Point1, Point2,Output).
add_equal(Point1,Point2,Output) :- 
	assert(equal_pts(Point1,Point2)),
	Output ='Ok'.

% check_process/2 - adder example
%application_handle(check_process(List),_,Output) :- 
%	write('Running check_process2...'), nl,
%	check_process(List,Output).
%check_process(List,Output) :- 
%	list_adder(List, Result),
%	L1 = "The sum is: ",
%	name(Result,L2),
%	append(L1,L2,L3),
%	name(Output,L3).

% check_process/1 
application_handle(check_process,Stream,Output) :- 
	write('Running check_process1...'), nl,
	check_process(Stream,Output).
check_process(Stream,Output) :- 

        assert(problem_noted([null,null,null])),
        assert(node(zzz)),
        assert(before_pts(xxx,zzz)),
        assert(equal_pts(yyy,zzz)),

	%there is a problem if prolog can prove an abnormal relationship
	setof((A,B),ab(A,B,Stream),_),
        %clean up the database
        abolish(node),
        abolish(before_pts),
        abolish(equal_pts),
        abolish(problem_noted),
	Output ='Analysis Complete!'.
check_process(_,Output) :- 
	Output ='Analysis Complete! No errors.'.

% misc util

list_adder([],0).
list_adder([X|Rest],Z) :-
	list_adder(Rest,Z1),
	Z is X + Z1.

% Temporal Reasoner

before_pt(A,B) :- before_pts(A,B).
equal_pt(A,B) :- equal_pts(A,B).

equal_pt(Tp,Tp).
before_pt(begin_point(A),end_point(A)) :- node(A).
%before_pt(Tp1,Tp3) :-  \+Tp1=Tp2, \+Tp1=Tp3, \+Tp2=Tp3, 
%	before_pt(Tp1,Tp2), before_pt(Tp2,Tp3).

% translate timepoint theory to allen interval relationships
before_a(A,B) :- node(A), node(B), \+A=B, 
	before_pt(end_point(A), begin_point(B)).
after_a(B,A) :- before_a(A,B).
meets_a(A,B) :- node(A), node(B), \+A=B,
	equal_pt(end_point(A), begin_point(B)).
met_by_a(B,A) :- meets_a(A,B).
overlaps_a(A,B) :- node(A), node(B), \+A=B,
	before_pt(begin_point(A), begin_point(B)),
	before_pt(begin_point(B), end_point(A)).
overlapped_by_a(B,A) :- overlaps_a(A,B).
starts_a(A,B) :- node(A), node(B), \+A=B,
	equal_pt(begin_point(A), begin_point(B)),
	before_pt(end_point(A),end_point(B)).
started_by_a(B,A) :- starts_a(A,B).
during_a(A,B) :- node(A), node(B), \+A=B,
	before_pt(begin_point(B), begin_point(A)),
	before_pt(end_point(A), end_point(B)).
contains_a(B,A) :- during_a(A,B).
finishes_a(A,B) :- node(A), node(B), \+A=B,
	before_pt(begin_point(B), begin_point(A)),
	equal_pt(end_point(A), end_point(B)).
finished_by_a(B,A) :- finishes_a(A,B).
equal_a(A,B) :- node(A), node(B), \+A=B,
	equal_pt(begin_point(A), begin_point(B)),
	equal_pt(end_point(A), end_point(B)).

% encoding of Allen's transitivity table, p17 Reason. about Plans
/* equal_a(A,A).
equal_a(A,C) :- node(A), node(B), node(C), 
	\+A=B, \+A=C, \+B=C, equal_a(A,B), equal_a(B,C).
before_a(A,C) :- node(A), node(B), node(C), 
	\+A=B, \+A=C, \+B=C, before_a(A,B), before_a(B,C).
before_a(A,C) :- node(A), node(B), node(C), 
	\+A=B, \+A=C, \+B=C, before_a(A,B), contains_a(B,C).
before_a(A,C) :- node(A), node(B), node(C), 
	\+A=B, \+A=C, \+B=C, before_a(A,B), overlaps_a(B,C).
before_a(A,C) :- node(A), node(B), node(C), 
	\+A=B, \+A=C, \+B=C, before_a(A,B), meets_a(B,C).
before_a(A,C) :- node(A), node(B), node(C), 
	\+A=B, \+A=C, \+B=C, before_a(A,B), starts_a(B,C).
before_a(A,C) :- node(A), node(B), node(C), 
	\+A=B, \+A=C, \+B=C, before_a(A,B), started_by_a(B,C).
before_a(A,C) :- node(A), node(B), node(C), 
	\+A=B, \+A=C, \+B=C, before_a(A,B), finished_by_a(B,C). 
*/
% table of inverse relationships
/* b  = before
   bi = after
   d  = during
   di = contains 
   o  = overlaps
   oi = overlapped_by
   m  = meets
   mi = met-by
   s  = starts
   si = started-by
   f  = finishes
   fi = finished-by
   e  = equals
*/

inv(b_a(A,B),O) :- 
	after_c(A,B,O); during_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); overlapped_by_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(bi_a(A,B),O) :- 
	before_c(A,B,O); during_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); overlapped_by_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(bomds_a(A,B),O) :- 
	after_c(A,B,O); contains_c(A,B,O);
	overlapped_by_c(A,B,O);
	met_by_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(bioimidf_a(A,B),O) :- 
	before_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); meets_c(A,B,O);
	starts_c(A,B,O); started_by_c(A,B,O);
	finished_by_c(A,B,O); equal_c(A,B,O).
inv(boimidf_a(A,B),O) :- 
	after_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); meets_c(A,B,O);
	starts_c(A,B,O); started_by_c(A,B,O);
	finished_by_c(A,B,O); equal_c(A,B,O). 
inv(d_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); overlapped_by_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(bomdifi_a(A,B),O) :- 
	after_c(A,B,O); during_c(A,B,O);
	overlapped_by_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); equal_c(A,B,O).
inv(bioidimisi_a(A,B),O) :- 
	before_c(A,B,O); during_c(A,B,O);
	overlaps_c(A,B,O); meets_c(A,B,O);
	starts_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(ooiddie_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O);
	meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O).
inv(di_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); during_c(A,B,O);
	overlaps_c(A,B,O); overlapped_by_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(oidifi_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); during(A,B);
	overlaps_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); equal_c(A,B,O).
inv(oidisi_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); during_c(A,B,O);
	overlaps_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(odifi_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); during_c(A,B,O);
	overlapped_by_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); equal_c(A,B,O).
inv(ods_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); contains_c(A,B,O);
	overlapped_by_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(bom_a(A,B),O) :- 
	after_c(A,B,O); during_c(A,B,O); contains_c(A,B,O);
	overlapped_by_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(o_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); during_c(A,B,O); contains_c(A,B,O);
	overlapped_by_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(dso_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); contains_c(A,B,O);
	overlapped_by_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(oidf_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finished_by_c(A,B,O); equal_c(A,B,O).
inv(bioimi_a(A,B),O) :- 
	after_c(A,B,O); during_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); meets_c(A,B,O);
	starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(oi_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); during_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(ffie_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); during_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); overlapped_by_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O).
inv(m_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); during_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); overlapped_by_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(bioi_a(A,B),O) :- 
	before_c(A,B,O); during_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(ssie_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); during_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); overlapped_by_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); 
	finishes_c(A,B,O); finished_by_c(A,B,O).
inv(mi_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); during_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); overlapped_by_c(A,B,O); meets_c(A,B,O);
	starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(mib_a(A,B),O) :- 
	after_c(A,B,O); during_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); overlapped_by_c(A,B,O); meets_c(A,B,O);
	starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(df_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); overlapped_by_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finished_by_c(A,B,O); equal_c(A,B,O).
inv(si_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); during_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); overlapped_by_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O); equal_c(A,B,O).
inv(f_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); during_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); overlapped_by_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finished_by_c(A,B,O); equal_c(A,B,O).
inv(e_a(A,B),O) :- 
	before_c(A,B,O); after_c(A,B,O); during_c(A,B,O); contains_c(A,B,O);
	overlaps_c(A,B,O); overlapped_by_c(A,B,O); meets_c(A,B,O);
	met_by_c(A,B,O); starts_c(A,B,O); started_by_c(A,B,O);
	finishes_c(A,B,O); finished_by_c(A,B,O).

%blank template of all 13 relations.
%inv(_a(A,B)) :-
%	before_a(A,B); after_a(A,B); during_a(A,B); contains_a(A,B);
%	overlaps_a(A,B); overlapped_by_a(A,B); meets_a(A,B);
%	met_by_a(A,B); starts_a(A,B); started_by_a(A,B);
%	finishes_a(A,B); finished_by_a(A,B); equal_a(A,B).

% abnormal relationships, only report error once for any 3-tuple

ab(A,C,Output) :- 
	node(A), node(B), \+A=B, node(C), \+A=C, \+B=C, 
	\+already_flagged(A,B,C), ab(A,B,C,Output).

already_flagged(A,B,C) :- permutation([A,B,C],D),problem_entry(E),D=E.
problem_entry(A) :- problem_noted(A).

%row1
ab(A,B,C,O) :- before_a(A,B), before_a(B,C), inv(b_a(A,C),O), 
	     explain(b_a,A,'before',B,'before',C,O).
ab(A,B,C,O) :- before_a(A,B), during_a(B,C), inv(bomds_a(A,C),O),
	     explain(bomds_a,A,'before',B,'during',C,O).
ab(A,B,C,O) :- before_a(A,B), contains_a(B,C), inv(b_a(A,C),O), 
	     explain(b_a,A,'before',B,'contains',C,O).
ab(A,B,C,O) :- before_a(A,B), overlaps_a(B,C), inv(b_a(A,C),O), 
	     explain(b_a,A,'before',B,'overlaps',C,O).
ab(A,B,C,O) :- before_a(A,B), overlapped_by_a(B,C), inv(bomds_a(A,C),O),
	     explain(bomds_a,A,'before',B,'overlapped by',C,O).
ab(A,B,C,O) :- before_a(A,B), meets_a(B,C), inv(b_a(A,C),O),
	     explain(b_a,A,'before',B,'meets',C,O).
ab(A,B,C,O) :- before_a(A,B), met_by_a(B,C), inv(bomds_a(A,C),O),
	     explain(bomds_a,A,'before',B,'met by',C,O).
ab(A,B,C,O) :- before_a(A,B), starts_a(B,C), inv(b_a(A,C),O),
	     explain(b_a,A,'before',B,'starts',C,O).
ab(A,B,C,O) :- before_a(A,B), started_by_a(B,C), inv(b_a(A,C),O),
	     explain(b_a,A,'before',B,'started by',C,O).
ab(A,B,C,O) :- before_a(A,B), finishes_a(B,C), inv(bomds_a(A,C),O),
	     explain(bomds_a,A,'before',B,'finishes',C,O).
ab(A,B,C,O) :- before_a(A,B), finished_by_a(B,C), inv(b_a(A,C),O),
	     explain(b_a,A,'before',B,'finished by',C,O).

%row2
ab(A,B,C,O) :- after_a(A,B), after_a(B,C), inv(bi_a(A,C),O),
	     explain(bi_a,A,'after',B,'after',C,O).
ab(A,B,C,O) :- after_a(A,B), during_a(B,C), inv(bioimidf_a(A,C),O),
	     explain(bioimidf_a,A,'after',B,'during',C,O).
ab(A,B,C,O) :- after_a(A,B), contains_a(B,C), inv(bi_a(A,C),O),
	     explain(bi_a,A,'after',B,'contains',C,O).
ab(A,B,C,O) :- after_a(A,B), overlaps_a(B,C), inv(bioimidf_a(A,C),O),
	     explain(bioimidf_a,A,'after',B,'overlaps',C,O).
ab(A,B,C,O) :- after_a(A,B), overlapped_by_a(B,C), inv(bi_a(A,C),O),
	     explain(bi_a,A,'after',B,'overlapped by',C,O).
ab(A,B,C,O) :- after_a(A,B), meets_a(B,C), inv(bioimidf_a(A,C),O),
	     explain(bioimidf_a,A,'after',B,'meets',C,O).
ab(A,B,C,O) :- after_a(A,B), met_by_a(B,C), inv(bi_a(A,C),O),
	     explain(bi_a,A,'after',B,'met by',C,O).
ab(A,B,C,O) :- after_a(A,B), starts_a(B,C), inv(boimidf_a(A,C),O),
	     explain(boimidf_a,A,'after',B,'starts',C,O).
ab(A,B,C,O) :- after_a(A,B), started_by_a(B,C), inv(bi_a(A,C),O),
	     explain(bi_a,A,'after',B,'started by',C,O).
ab(A,B,C,O) :- after_a(A,B), finishes_a(B,C), inv(bi_a(A,C),O),
	     explain(bi_a,A,'after',B,'finishes',C,O).
ab(A,B,C,O) :- after_a(A,B), finished_by_a(B,C), inv(bi_a(A,C),O),
	     explain(bi_a,A,'after',B,'finished by',C,O).
%row3
ab(A,B,C,O) :- during_a(A,B), before_a(B,C), inv(b_a(A,C),O), 
	     explain(b_a,A,'during',B,'before',C,O).
ab(A,B,C,O) :- during_a(A,B), after_a(B,C), inv(bi_a(A,C),O),
             explain(bi_a,A,'during',B,'after',C,O).
ab(A,B,C,O) :- during_a(A,B), during_a(B,C), inv(d_a(A,C),O),
             explain(d_a,A,'during',B,'during',C,O).
ab(A,B,C,O) :- during_a(A,B), overlaps_a(B,C), inv(bomds_a(A,C),O),
             explain(bomds_a,A,'during',B,'overlaps',C,O).
ab(A,B,C,O) :- during_a(A,B), overlapped_by_a(B,C), inv(bioimidf_a(A,C),O),
             explain(bioimidf_a,A,'during',B,'overlapped by',C,O).
ab(A,B,C,O) :- during_a(A,B), meets_a(B,C), inv(b_a(A,C),O),
             explain(b_a,A,'during',B,'meets',C,O).
ab(A,B,C,O) :- during_a(A,B), met_by_a(B,C), inv(bi_a(A,C),O),
             explain(bi_a,A,'during',B,'met by',C,O).
ab(A,B,C,O) :- during_a(A,B), starts_a(B,C), inv(d_a(A,C),O),
             explain(d_a,A,'during',B,'starts',C,O).
ab(A,B,C,O) :- during_a(A,B), started_by_a(B,C), inv(bioimidf_a(A,C),O),
             explain(bioimidf_a,A,'during',B,'started by',C,O).
ab(A,B,C,O) :- during_a(A,B), finishes_a(B,C), inv(d_a(A,C),O),
             explain(d_a,A,'during',B,'finishes',C,O).
ab(A,B,C,O) :- during_a(A,B), finished_by_a(B,C), inv(bomds_a(A,C),O),
             explain(bomds_a,A,'during',B,'finished by',C,O).

%row4
ab(A,B,C,O) :- contains_a(A,B), before_a(B,C), inv(bomdifi_a(A,C),O),
             explain(bomdifi_a,A,'contains',B,'before',C,O).
ab(A,B,C,O) :- contains_a(A,B), after_a(B,C), inv(bioidimisi_a(A,C),O),
             explain(bioidimisi_a,A,'contains',B,'after',C,O).
ab(A,B,C,O) :- contains_a(A,B), contains_a(B,C), inv(ooiddie_a(A,C),O),
             explain(ooiddie_a,A,'contains',B,'contains',C,O).
ab(A,B,C,O) :- contains_a(A,B), during_a(B,C), inv(di_a(A,C),O),
             explain(di_a,A,'contains',B,'during',C,O).
ab(A,B,C,O) :- contains_a(A,B), overlaps_a(B,C), inv(oidifi_a(A,C),O),
             explain(oidifi_a,A,'contains',B,'overlaps',C,O).
ab(A,B,C,O) :- contains_a(A,B), overlapped_by_a(B,C), inv(oidisi_a(A,C),O),
             explain(oidisi_a,A,'contains',B,'overlapped by',C,O).
ab(A,B,C,O) :- contains_a(A,B), meets_a(B,C), inv(odifi_a(A,C),O),
             explain(oidifi_a,A,'contains',B,'meets',C,O).
ab(A,B,C,O) :- contains_a(A,B), met_by_a(B,C), inv(oidisi_a(A,C),O),
             explain(oidisi_a,A,'contains',B,'met by',C,O).
ab(A,B,C,O) :- contains_a(A,B), starts_a(B,C), inv(odifi_a(A,C),O),
             explain(odifi_a,A,'contains',B,'starts',C,O).
ab(A,B,C,O) :- contains_a(A,B), started_by_a(B,C), inv(di_a(A,C),O),
             explain(di_a,A,'contains',B,'started by',C,O).
ab(A,B,C,O) :- contains_a(A,B), finishes_a(B,C), inv(oidisi_a(A,C),O),
             explain(oidisi_a,A,'contains',B,'finishes',C,O).
ab(A,B,C,O) :- contains_a(A,B), finished_by_a(B,C), inv(di_a(A,C),O),
             explain(di_a,A,'contains',B,'finished by',C,O).

%row5
ab(A,B,C,O) :- overlaps_a(A,B), before_a(B,C), inv(b_a(A,C),O),
             explain(b_a,A,'overlaps',B,'before',C,O).
ab(A,B,C,O) :- overlaps_a(A,B), after_a(B,C), inv(bioidimisi_a(A,C),O),
             explain(bioidimisi_a,A,'overlaps',B,'after',C,O).
ab(A,B,C,O) :- overlaps_a(A,B), contains_a(B,C), inv(ods_a(A,C),O),
             explain(ods_a,A,'overlaps',B,'contains',C,O).
ab(A,B,C,O) :- overlaps_a(A,B), during_a(B,C), inv(bomdifi_a(A,C),O),
             explain(bomdifi_a,A,'overlaps',B,'during',C,O).
ab(A,B,C,O) :- overlaps_a(A,B), overlaps_a(B,C), inv(bom_a(A,C),O),
             explain(bom_a,A,'overlaps',B,'overlaps',C,O).
ab(A,B,C,O) :- overlaps_a(A,B), overlapped_by_a(B,C), inv(ooiddie_a(A,C),O),
             explain(ooiddie_a,A,'overlaps',B,'overlapped by',C,O).
ab(A,B,C,O) :- overlaps_a(A,B), meets_a(B,C), inv(b_a(A,C),O),
             explain(b_a,A,'overlaps',B,'meets',C,O).
ab(A,B,C,O) :- overlaps_a(A,B), met_by_a(B,C), inv(oidisi_a(A,C),O),
             explain(oidisi_a,A,'overlaps',B,'met by',C,O).
ab(A,B,C,O) :- overlaps_a(A,B), starts_a(B,C), inv(o_a(A,C),O),
             explain(o_a,A,'overlaps',B,'starts',C,O).
ab(A,B,C,O) :- overlaps_a(A,B), started_by_a(B,C), inv(odifi_a(A,C),O),
             explain(odifi_a,A,'overlaps',B,'started by',C,O).
ab(A,B,C,O) :- overlaps_a(A,B), finishes_a(B,C), inv(dso_a(A,C),O),
             explain(dso_a,A,'overlaps',B,'finishes',C,O).
ab(A,B,C,O) :- overlaps_a(A,B), finished_by_a(B,C), inv(bom_a(A,C),O),
             explain(bom_a,A,'overlaps',B,'finished by',C,O).
%row6
ab(A,B,C,O) :- overlapped_by_a(A,B), before_a(B,C), inv(bomdifi_a(A,C),O),
             explain(bomdifi_a,A,'overlapped by',B,'before',C,O).
ab(A,B,C,O) :- overlapped_by_a(A,B), after_a(B,C), inv(bi_a(A,C),O),
             explain(bi_a,A,'overlapped by',B,'after',C,O).
ab(A,B,C,O) :- overlapped_by_a(A,B), contains_a(B,C), inv(oidf_a(A,C),O),
             explain(oidf_a,A,'overlapped by',B,'contains',C,O).
ab(A,B,C,O) :- overlapped_by_a(A,B), during_a(B,C), inv(bioidimisi_a(A,C),O),
             explain(bioidimisi_a,A,'overlapped by',B,'during',C,O).
ab(A,B,C,O) :- overlapped_by_a(A,B), overlaps_a(B,C), inv(ooiddie_a(A,C),O),
             explain(ooiddie_a,A,'overlapped by',B,'overlaps',C,O).
ab(A,B,C,O) :- overlapped_by_a(A,B), overlapped_by_a(B,C), inv(bioimi_a(A,C),O),
             explain(bioimi_a,A,'overlapped by',B,'overlapped by',C,O).
ab(A,B,C,O) :- overlapped_by_a(A,B), meets_a(B,C), inv(odifi_a(A,C),O),
             explain(odifi_a,A,'overlapped by',B,'meets',C,O).
ab(A,B,C,O) :- overlapped_by_a(A,B), met_by_a(B,C), inv(bi_a(A,C),O),
             explain(bi_a,A,'overlapped by',B,'met by',C,O).
ab(A,B,C,O) :- overlapped_by_a(A,B), starts_a(B,C), inv(oidf_a(A,C),O),
             explain(oidf_a,A,'overlapped by',B,'starts',C,O).
ab(A,B,C,O) :- overlapped_by_a(A,B), started_by_a(B,C), inv(bioimi_a(A,C),O),
             explain(bioimi_a,A,'overlapped by',B,'started by',C,O).
ab(A,B,C,O) :- overlapped_by_a(A,B), finishes_a(B,C), inv(oi_a(A,C),O),
             explain(oi_a,A,'overlapped by',B,'finishes',C,O).
ab(A,B,C,O) :- overlapped_by_a(A,B), finished_by_a(B,C), inv(oidisi_a(A,C),O),
             explain(oidisi_a,A,'overlapped by',B,'finished by',C,O).

%row7
ab(A,B,C,O) :- meets_a(A,B), before_a(B,C), inv(b_a(A,C),O),
             explain(b_a,A,'meets',B,'before',C,O).
ab(A,B,C,O) :- meets_a(A,B), after_a(B,C), inv(bioidimisi_a(A,C),O),
             explain(bioidimisi_a,A,'meets',B,'after',C,O).
ab(A,B,C,O) :- meets_a(A,B), contains_a(B,C), inv(ods_a(A,C),O),
             explain(ods_a,A,'meets',B,'contains',C,O).
ab(A,B,C,O) :- meets_a(A,B), during_a(B,C), inv(b_a(A,C),O),
             explain(b_a,A,'meets',B,'during',C,O).
ab(A,B,C,O) :- meets_a(A,B), overlaps_a(B,C), inv(b_a(A,C),O),
             explain(b_a,A,'meets',B,'overlaps',C,O).
ab(A,B,C,O) :- meets_a(A,B), overlapped_by_a(B,C), inv(ods_a(A,C),O),
             explain(ods_a,A,'meets',B,'overlapped by',C,O).
ab(A,B,C,O) :- meets_a(A,B), meets_a(B,C), inv(b_a(A,C),O),
             explain(b_a,A,'meets',B,'meets',C,O).
ab(A,B,C,O) :- meets_a(A,B), met_by_a(B,C), inv(ffie_a(A,C),O),
             explain(ffie_a,A,'meets',B,'met by',C,O).
ab(A,B,C,O) :- meets_a(A,B), starts_a(B,C), inv(m_a(A,C),O),
             explain(m_a,A,'meets',B,'starts',C,O).
ab(A,B,C,O) :- meets_a(A,B), started_by_a(B,C), inv(m_a(A,C),O),
             explain(m_a,A,'meets',B,'started by',C,O).
ab(A,B,C,O) :- meets_a(A,B), finishes_a(B,C), inv(dso_a(A,C),O),
             explain(dso_a,A,'meets',B,'finishes',C,O).
ab(A,B,C,O) :- meets_a(A,B), finished_by_a(B,C), inv(b_a(A,C),O),
             explain(b_a,A,'meets',B,'finished by',C,O).
%row8
ab(A,B,C,O) :- met_by_a(A,B), before_a(B,C), inv(bomdifi_a(A,C),O),
             explain(bomdifi_a,A,'met by',B,'before',C,O).
ab(A,B,C,O) :- met_by_a(A,B), after_a(B,C), inv(bi_a(A,C),O),
             explain(bi_a,A,'met by',B,'after',C,O).
ab(A,B,C,O) :- met_by_a(A,B), contains_a(B,C), inv(oidf_a(A,C),O),
             explain(oidf_a,A,'met by',B,'contains',C,O).
ab(A,B,C,O) :- met_by_a(A,B), during_a(B,C), inv(bi_a(A,C),O),
             explain(bi_a,A,'met by',B,'during',C,O).
ab(A,B,C,O) :- met_by_a(A,B), overlaps_a(B,C), inv(oidf_a(A,C),O),
             explain(oidf_a,A,'met by',B,'overlaps',C,O).
ab(A,B,C,O) :- met_by_a(A,B), overlapped_by_a(B,C), inv(bioi_a(A,C),O),
             explain(bioi_a,A,'met by',B,'overlapped by',C,O).
ab(A,B,C,O) :- met_by_a(A,B), meets_a(B,C), inv(ssie(A,C),O),
             explain(ssie_a,A,'met by',B,'meets',C,O).
ab(A,B,C,O) :- met_by_a(A,B), met_by_a(B,C), inv(bi_a(A,C),O),
             explain(bi_a,A,'met by',B,'met by',C,O).
ab(A,B,C,O) :- met_by_a(A,B), starts_a(B,C), inv(oidf_a(A,C),O),
             explain(oidf_a,A,'met by',B,'starts',C,O).
ab(A,B,C,O) :- met_by_a(A,B), started_by_a(B,C), inv(bi_a(A,C),O),
             explain(bi_a,A,'met by',B,'started by',C,O).
ab(A,B,C,O) :- met_by_a(A,B), finishes_a(B,C), inv(mi_a(A,C),O),
             explain(mi_a,A,'met by',B,'finishes',C,O).
ab(A,B,C,O) :- met_by_a(A,B), finished_by_a(B,C), inv(mib_a(A,C),O),
             explain(mib_a,A,'met by',B,'finished by',C,O).

ab(A,B,C,O) :- equal_a(A,B), equal_a(B,C), inv(e_a(A,C),O),
             explain(e_a,A,'equal',B,'equal',C,O).

%%%%%%%%%%%%%%%%%%%%% Sample Problem Instance Data

%node(acta).
%node(actb).
%node(actc).
%node(actd).
%node(acte).
%node(actf).
%% a is before b
%before_pt(end_point(acta),begin_point(actb)).
%% b is during c
%before_pt(begin_point(actc),begin_point(actb)).
%before_pt(end_point(actb),end_point(actc)).
%%broken: a is after c
%%before_pt(end_point(actc),begin_point(acta)).
%%ok: c is after a
%before_pt(end_point(acta),begin_point(actc)).

%% legal trans. d is before e, d is before a.
%before_pt(end_point(actd),begin_point(acte)).
%before_pt(end_point(actd),begin_point(acta)).
%before_pt(end_point(acte),begin_point(actf)).
%% oops, error! d cannot be after f
%before_pt(end_point(actf),begin_point(actd)).

% go!
:- start_server(6792,1024).
