// Service discovery: Complex goals and postconditions
//                    (defined by rules, alternative outcomes, etc.)
// Also illustrates a different representation for input

%% A taxonomy of cities; europe means European Cities, france - French cities
germany::europe.
austria::europe.
france::europe.
tyrol::austria.
innsbruck:tyrol.
lienz:tyrol.
vienna:austria.
bonn:germany.
frankfurt:germany.
paris:france.
nancy:france.

%% Available services
%% Example: If input object is of the form
%%      ${objid[from->someplace,to->someotherplace]}
%% then return train ticket as before. If the input is
%%      ${objid[local->somecity]}
%% then return tourist pass for that city
%%
%% Confession: rule reification is not currently supported in Flora-2, but
%%             is easy to add. It is not a technical problem for this approach
serv1[
   precondition(_Input) -> ${(
	                      _Input ~ ${Req[from->From,to->To]},
			      Req:request, From:germany, To:austria
			      ;
                              _Input ~ ${Req[local->City]},
			      Req:request, City:tyrol
			     )},
   postcondition(_Input)-> [${_Input},
	                    ${(
			        (ticket(Req)[start->From,destination->To] :-
					    Req:request[from->From, to->To]),
                                (pass(Req)[location->City] :-
					    Req:request[local->City])
                               )}]
].
serv2[
   precondition(_Input) -> ${
                              _Input ~ ${Req[from->From,to->to]},
			      Req:request, From:france, To:austria
			    },
   postcondition(_Input)-> [${_Input},
	                    ${
                               (ticket(Req)[start->From,destination->To] :-
	                                    Req:request[from->From, to->To])
			     }]
].
serv3[
   precondition(_Input) -> ${
                              _Input ~ ${Req[local->City]},
			      Req:request, City:france
			    },
   postcondition(_Input)-> [${_Input},
	                    ${
                                (pass(Req)[location->City] :-
					    Req:request[local->City])
                             }]
].

%% What we want
goal[
   desire-> ${_Ticket[start->bonn, destination->innsbruck]}
/*
   %% complex goals are also fine
   desire-> ${_Pass[location->_X:france; location->_X:tyrol]}
   desire-> ${_Ticket[start->bonn, (destination->innsbruck
                                    ; destination->lienz)]}
   desire-> ${_Ticket[start->bonn, (destination->vienna
                                    ; (destination->_X:tyrol,
                                        not destination->lienz)
                                   )]}
*/
].

%% Discovery query
?-  gensym('req',NewReqId)@prolog(gensym),
	Serv[precondition(${NewReqId[local->paris]})->_Precond,
	     postcondition(${NewReqId[local->paris]}) -> _Post],
	goal[desire->_Desire],
	_Precond,
	_Post = [_Input,_PCondRules],
	insert{_Input},          % hypothetically assert input request
        insertrule{_PCondRules}, % hypothetically assert postcondition
	_Desire,
        write('\n\nService ')@prolog(), write(Serv)@prolog(),
	writeln(' matches!')@prolog(),
	delete{_Post}.