                 Romeo and Juliet: Solutions

************************************************
*** SOLUTION 1, in the language of PAL
*** By Pedro Cabalar (cabalar@fi.udc.es)
************************************************

constants
  n = 3;
options
  not concurrent;
sets
  person={romeo,juliet};  

fluents
   current_year : [2001,2003];
   
   /* Some data for each person */
            sex : person -> {male,female};
         status : person -> {single,married};
            age : person -> [15,20];
     has_permis : person -> boolean;
  parents_agree : person -> boolean;
      may_marry : person -> boolean;
        
actions
  marry: person x person -> event;
  ask_permis : person -> event;
  wait_a_year;

vars
  P,Q : person;     
  
rules
  age(P):=prev(age(P))+1 if wait_a_year;
  current_year:=prev(current_year)+1 if wait_a_year;

  status(P):=married if marry(P,Q);
  status(Q):=married if marry(P,Q);
  false if marry(P,Q) and not (prev(may_marry(P)) and prev(may_marry(Q)));
  /* in Netherlands, they have deleted the rule below... */
  false if marry(P,Q) and not (sex(P)=male and sex(Q)=female);
  
  may_marry(P):= status(P)=single and (age(P)>=18 or has_permis(P));
  
  has_permis(P) if ask_permis(P) and parents_agree(P);
  
  /*---- some control rules -----*/
  /* do not ask for permission if not needed */
  false if ask_permis(P) and (prev(may_marry(P)) or prev(status(P))=married);  

  /* Romeo and Juliet want to marry as soon as possible :-) */
  false if wait_a_year and prev(may_marry(romeo)) and prev(may_marry(juliet));
  
initially
  current_year:=2001,
  
  sex(romeo):=male,
  status(romeo):=single,
  age(romeo):=17,
  not has_permis(romeo),
  not may_marry(romeo),
  parents_agree(romeo),
  
  sex(juliet):=female,
  status(juliet):=single,
  age(juliet):=16,
  not has_permis(juliet),
  not may_marry(juliet),
  parents_agree(juliet);

/* Trying with n=1, n=2 leads to no solution */
query
  ...{n} status(romeo)=married and status(juliet)=married ?

************************************************
*** SOLUTION 2, in the language of Smodels
*** By Paolo Ferraris (otto@cs.utexas.edu)
************************************************

% to be executed with: lparse <juliet | smodel

action(getMarried).
action(askJohnson).
action(askRobinson).
action(wait).

status(fiances).
status(married).

permission(notAsked).
permission(asked).

age(16..19).
adult(18..19).

canGetMarried(AGE1,PERM1) :- permission(PERM1), adult(AGE1).
canGetMarried(AGE1,asked) :- age(AGE1).


state(17,16,notAsked,notAsked,fiances).

%       +-------------- age of Romeo
%       |  +----------- age of Juliet
%       |  |  +-------- permission asked to Robinson
%       |  |  |  +----- permission asked to Johnson
%       |  |  |  |  +-- status(fiances/married)
%       v  v  v  v  v
% state(A1,A2,P1,P2,S)

%    +--------------- action done
%    |       +------- same fields of "state"
%    |       |
%    v /-----------\
% do(P,A1,S2,P1,P2,S)


% only one action and only if they are not married
1 [do(ACT,AGE1,AGE2,PERM1,PERM2,fiances): action(ACT)] 1:-
   state(AGE1,AGE2,PERM1,PERM2,fiances), age(AGE1), age(AGE2),
   permission(PERM1), permission(PERM2).

% you don't need to wait if both can get married?
:- do(wait,AGE1,AGE2,PERM1,PERM2,STAT),
   age(AGE1), age(AGE2), permission(PERM1), permission(PERM2),
   status(STAT), canGetMarried(AGE1,PERM1), canGetMarried(AGE2,PERM2).

% both of them must be able to get married to get married
:- [canGetMarried(AGE1,PERM1), canGetMarried(AGE2,PERM2)] 1,
   do(getMarried,AGE1,AGE2,PERM1,PERM2,STAT), age(AGE1), age(AGE2),
   permission(PERM1), permission(PERM2), status(STAT).

% if they are already legally allowed to get married they don't have
% to ask permission to parents
:- do(askJohnson,AGE1,AGE2,PERM1,PERM2,STAT), age(AGE1), age(AGE2),
   permission(PERM1), permission(PERM2), status(STAT),
   canGetMarried(AGE2,PERM2).
:- do(askRobinson,AGE1,AGE2,PERM1,PERM2,STAT), age(AGE1), age(AGE2),
   permission(PERM1), permission(PERM2), status(STAT),
   canGetMarried(AGE1,PERM1).

% effect of actions
state(AGE1,AGE2,PERM1,PERM2,STAT) :-
   do(wait,AGE1-1,AGE2-1,PERM1,PERM2,STAT), age(AGE1), age(AGE2),
   permission(PERM1), permission(PERM2), status(STAT).

state(AGE1,AGE2,PERM1,PERM2,married) :-
   do(getMarried,AGE1,AGE2,PERM1,PERM2,STAT), age(AGE1), age(AGE2),
   permission(PERM1), permission(PERM2), status(STAT).

state(AGE1,AGE2,asked,PERM2,STAT) :-
   do(askRobinson,AGE1,AGE2,PERM1,PERM2,STAT), age(AGE1), age(AGE2),
   permission(PERM1), permission(PERM2), status(STAT).

state(AGE1,AGE2,PERM1,asked,STAT) :-
   do(askJohnson,AGE1,AGE2,PERM1,PERM2,STAT), age(AGE1), age(AGE2),
   permission(PERM1), permission(PERM2), status(STAT).

% goal condition: they want to get married
:- [state(AGE1,AGE2,PERM1,PERM2,married): age(AGE1): age(AGE2):
   permission(PERM1): permission(PERM2)] 0.

compute all {}.

hide.
show state(AGE1,AGE2,PERM1,PERM2,STAT),
     do(askJohnson,AGE1,AGE2,PERM1,PERM2,STAT).

************************************************
*** SOLUTION 3, in the language of Smodels
*** By Semra Dogandag (semra@ceng.metu.edu.tr)
************************************************

% Romeo and Juliet

 person(romeo).
 person(juliet).

% They will get married now, 1 year later  or 2 years later
 time(0..2).

% To represent the ages
 number(16..19).

 age(romeo,17,0).   % Age of Romeo is 17 at time 0(now)
 age(juliet,16,0).

 hide.
 show ask_parent(_).
 show get_married(_,_,_).
 
% Compute possible solutions
 {ask_parent(X)} :- person(X).

1{get_married(X,Y,T) : time(T)}1 :- person(X), person(Y), lt(X,Y).

 age(X,A1,T) :- age(X,A,0), assign(A1,A+T),time(T), person(X),
		number(A), number(A1), T>0.

 has_parent_consent(X) :- ask_parent(X), person(X).

% They should have their parents consent if their age is less than 18 
 :- get_married(X,Y,T), 
    age(X, Z, T), Z<18, not has_parent_consent(X), person(X), person(Y), neq(X,Y).
 :- get_married(X,Y,T), 
    age(Y, Z, T), Z<18, not has_parent_consent(Y), person(X), person(Y), neq(X,Y).

% If the age is at least 18 they don't need to ask the parents
 :- get_married(X,Y,T), 
    age(X, Z, T), Z>=18, ask_parent(X), person(X), person(Y), neq(X,Y).
 :- get_married(X,Y,T), 
    age(Y, Z, T), Z>=18, ask_parent(Y), person(X), person(Y), neq(X,Y).

 compute all{}.

************************************************
*** SOLUTION 4, in the language of Smodels
*** By Guray Alsac (guray@asu.edu)
************************************************

%	The program implements a simple planner derived from the
% action language A augmented with static causal laws and
% executability conditions.
%	The basic insight into solving the problem was that the
% fluent for age "statically causes" the fluent for marriageable
% to be true, allowing Romeo and Juliet to continue with their
% wedding plans if they wait for 2 years.
%	A domain description for this problem in the language A
% might be something like the following:
%
% INITIALLY -marriageable(romeo)
% INITIALLY -marriageable(juliet)
% INITIALLY age(romeo, 17)
% INITIALLY age(juliet, 16)
%
% getConsent(P)			CAUSES marriageable(P)
% waitAYear			CAUSES age(P, +1)
%
% age(P, 18) 	STATICALLY CAUSES marriageable(P)
%
%
%	What follows is the encoding of a planner for this domain
% description.



% ACTIONS
% -------
action(getConsent(P)) :-		person(P).
action(waitAYear).


% FLUENTS
% -------
fluent(marriageable(P)) :-		person(P).
fluent(marriageable(P)) :-		person(P).
fluent(age(P, X)) :-			person(P), agePoint(X).

% CAUSE AND EFFECT RULES
% ----------------------
holds(marriageable(P), T + 1) :-
	occurs(getConsent(P), T),
	timePoint(T),
	person(P).
ab(marriageable(P), getConsent(P), T) :-
	timePoint(T),
	person(P),
	occurs(getConsent(P), T).

holds(age(P, X + 1), T + 1) :-
	occurs(waitAYear, T),
	holds(age(P, X), T),
	timePoint(T),
	agePoint(X),
	person(P).
ab(age(P, X), waitAYear, T) :-
	timePoint(T),
	agePoint(X),
	person(P),
	occurs(waitAYear, T).

% INITIAL CONDIITONS
% ------------------
not_holds(marriageable(romeo), 1).
not_holds(marriageable(juliet), 1).
holds(age(romeo, 17), 1).
holds(age(juliet, 16), 1).


% INERTIA RULES
% -------------
holds(F, T + 1) :-
	occurs(A, T),
	holds(F, T),
	not ab(F, A, T),
	fluent(F),
	timePoint(T),
	action(A).
not_holds(F, T + 1) :-
	occurs(A, T),
	not_holds(F, T),
	not ab(F, A, T),
	fluent(F),
	timePoint(T),
	action(A).

% STATIC CAUSAL LAWS
% ------------------

% You are marriageable at 18 years of age:

holds(marriageable(P), T) :-
	holds(age(P, X), T),
	X >= 18,
	timePoint(T),
	agePoint(X),
	person(P).


% LENGTH OF PLAN
% --------------
const length = 2.

% ENUMERATION OF ALL POSSIBLE PLANS
% ---------------------------------
not_occurs(A, T) :-
	occurs(B, T),
	A != B,
	action(A),
	action(B),
	timePoint(T).
occurs(A, T) :-
	T <= length,
	not not_occurs(A, T),
	action(A),
	timePoint(T).

% GOAL
% ----
:- not holds(marriageable(romeo), length + 1).
:- not holds(marriageable(juliet), length + 1).

% MISC
% ----

person(romeo).	% Romeo
person(juliet).	% Juliet

timePoint(1..3).
agePoint(16..19).

%hide occurs(X,X).
hide holds(X,X).
hide not_occurs(X,X).
hide not_holds(X,X).
hide ab(X,X,X).
hide fluent(X).
hide action(X).
hide timePoint(X).
hide agePoint(X).
hide person(X).

************************************************
*** SOLUTION 5, in the language of CCalc
*** By Joohyung Lee (appsmurf@cs.utexas.edu)
************************************************

:- macros
  maxstep -> 2.

:- sorts
  person;
  age.

:- objects
  romeo, juliet            :: person;
  16..19                   :: age.

:- variables
  Ag                       :: age;
  P                        :: person;
  A                        :: action.

:- constants
  age(person)              :: inertialFluent(age);
  allowedToMarry(person)   :: fluent;
  getMarried               :: fluent;
  asked(person)            :: fluent;
  wait                     :: action;
  askPermission(person)    :: action.


% increase the age of a person
wait causes age(P)=Ag+1 if age(P)=Ag where Ag<19.

% the person is eligible for marriage if age>=18
caused allowedToMarry(P) if age(P)=Ag && Ag>=18.

%   or, if he/she gets parental consent
askPermission(P) causes allowedToMarry(P).

default -allowedToMarry(P).

% no concurrency between waiting and asking permission
caused false after wait && askPermission(P).

% romeo and juliet get married if they are allowed to marry
caused getMarried if allowedToMarry(romeo) && allowedToMarry(juliet).

default -getMarried.

% once married...
caused getMarried after getMarried.

% keeps track of the fact that a permission is asked:

default -asked(P).
askPermission(P) causes asked(P).
caused asked(P) after asked(P).

% - avoid asking repeatedly
nonexecutable askPermission(P) if asked(P).

% get married after asking permission
% - avoid unnecessary asking before marriage
caused false if -getMarried after askPermission(P).

% if old enough to marry, don't need to ask permission
nonexecutable askPermission(P) if age(P) eq Ag && Ag >= 18.

% an action should be executed at each step
caused false after [/\A | -A].


:- query
anyHistory;
constraint 0:
  [/\P | -asked(P)],
  [/\P | -allowedToMarry(P)],
  -getMarried,
  age(romeo) = 17,
  age(juliet) = 16;
constraint maxstep:
  getMarried.

************************************************
*** SOLUTION 6, in the language of Smodels
*** By Esra Erdem (esra@cs.utexas.edu)
************************************************

const maxYear = 2.

const maxStep = 10.
step(0..maxStep).       % denotes the order of actions

person(romeo;juliet).
age(16..20).

age_of(romeo,17,0).
age_of(juliet,16,0).

{get_married(S):step(S):S<maxStep}.
married(S+1) :- get_married(S),step(S),S<maxStep.
married(S+1) :- married(S), step(S), S<maxStep.
:- get_married(S), step(S), not permitted(P,S), person(P).

{wait_for_a_year(S):step(S):S<maxStep}maxYear.
age_of(P,A+1,S+1) :- age_of(P,A,S),person(P),age(A), step(S), S<maxStep,
wait_for_a_year(S).
age_of(P,A,S+1) :- age_of(P,A,S),person(P),age(A), step(S), S<maxStep, not
wait_for_a_year(S).

{ask_for_permission(P,S)} :- step(S), S<maxStep, person(P), not permitted(P,S).
permitted(P,S+1) :- person(P),ask_for_permission(P,S),step(S),S<maxStep.
permitted(P,S) :- age_of(P,A,S), person(P), step(S), age(A), A >= 18.
permitted(P,S+1) :- permitted(P,S),step(S),S<maxStep,person(P).

goal(S) :- married(S), step(S).
goal(S+1) :- goal(S), step(S), S<maxStep.
goal :- goal(S),step(S).
:- not goal.

% no actions after the goal is reached
:- 1{get_married(S), wait_for_a_year(S), ask_for_permission(P,S):person(P)}, step(S), goal(S).

% limited concurrency
:- 2{wait_for_a_year(S), get_married(S), ask_for_permission(P,S)}, person(P), step(S).

% no waiting
:- 1{get_married(S+1), wait_for_a_year(S+1), ask_for_permission(P,S+1):person(P)},
step(S), not get_married(S), not wait_for_a_year(S), not ask_for_permission(romeo,S), not ask_for_permission(juliet,S).

hide.
show wait_for_a_year(S).
show ask_for_permission(P,S).
show get_married(S).

************************************************
*** SOLUTION 7, in the language of Smodels
*** By Michael Gelfond (mgelfond@cs.ttu.edu)
************************************************

year(1..3).
person(j).
person(r).
age(16..19).
time(0..2).

age(j,Y,A) :- year(Y), A = 15+Y. 

age(r,Y,A) :- year(Y), A = 16+Y. 

1{get_married(Y) : year(Y)}1.

{get_perm(P,Y) : year(Y)}1 :- person(P).

:- age(A),year(Y),person(P),
   age(P,Y,A), A>17, get_perm(P,Y).


:- year(Y1),year(Y2),person(P),
   get_married(Y1),get_perm(P,Y2),Y2>Y1.


:- year(Y), person(P),age(A),
   get_married(Y),
   age(P,Y,A),
   A > 17,
   has_perm(P,Y).


has_perm(P,Y2) :- year(Y1),year(Y2),person(P),
                  get_perm(P,Y1),
                  Y1 <= Y2.

% A person P with age less than 18 cannot get married
% without having permission.
:- year(Y), person(P),age(A),
   get_married(Y), age(P,Y,A), A < 18, not has_perm(P,Y).
   

% To order the occurence of actions in a year.

1{o(get_married(Y),T) : time(T)}1 :- year(Y), 
                                     get_married(Y).

1{o(get_perm(P,Y),T) : time(T) }1 :- year(Y),person(P),
                                     get_perm(P,Y).

:- o(get_married(Y),T2),o(get_perm(P,Y),T1), T1 >= T2, 
   year(Y), person(P), time(T1),time(T2). 
   

:- no_action_occ(Y,T), action_occ(Y,T+1), year(Y), time(T).

action_occ(Y,T) :- o(get_married(Y),T), year(Y), time(T).
		   
action_occ(Y,T) :- o(get_perm(P,Y),T), time(T), 
		   person(P), year(Y).
		 
no_action_occ(Y,T) :- not action_occ(Y,T), year(Y), time(T).
	
hide.
show o(A,B).
		      
************************************************
*** SOLUTION 8, in the language of Smodels
*** By Veena Mellarkod (mellarko@cs.ttu.edu)
************************************************

person(romeo).
person(juliet).
plan_to_marry(romeo,juliet).

age(16..19).
time(0..2).
              
parents(robinsons,romeo).
parents(johnsons,juliet).

age(romeo,17,0).
age(juliet,16,0).

age(X,A+1,T+1) :- person(X), time(T),
		  age(X,A,T), age(A).
		       
1{ get_married(X,Y,T) : time(T)}1 :- plan_to_marry(X,Y).

get_married(X,T) :- get_married(X,Y,T), person(X),
                    person(Y), time(T).
                    
get_married(Y,T) :- get_married(X,Y,T), person(X),
                    person(Y), time(T).
                   
ask(X,Y) :- parents(Y,X), get_married(X,T), age(A),
            age(X,A,T), A < 18, time(T).


% print            
to_marry(now) :- get_married(romeo,juliet,0).
to_marry(yearlater) :- get_married(romeo,juliet,1).
to_marry(twoyearslater) :- get_married(romeo,juliet,2).
            
            
hide.
show to_marry(X).
show ask(X,Y).  

************************************************
*** SOLUTION 9, in the language of Smodels
*** By Yulia Babovich (yuliya@cs.utexas.edu)
************************************************

age(16..19).
step(1..4).
human(romeo).
human(juliet).
human_age(romeo,17,1).
human_age(juliet,16,1).

% can ask or not ask permission at step S
0{ask_permission(S)}1:-human_age(romeo,A1,S),human_age(juliet,A2,S),
A1+A2<36,age(A1),age(A2), step(S), not get_married(S1),
S1<=S, step(S1).

%cannot ask permission twice
:-ask_permission(S),ask_permission(S1),step(S),step(S1),S!=S1.

%year may pass or not
0{one_year_pass(S)}1:-step(S), not ask_permission(S1), S>=S1, step(S1).

%year may not pass after they have got married
:- one_year_pass(S), get_married(S1), S>=S1, step(S),step(S1) .

%human_age stay the same if year did not pass
human_age(H,A,S):-human_age(H,A,S-1),age(A),human(H),
	not one_year_pass(S-1),step(S).

%human age changes if year has passed
human_age(H,A,S):-human_age(H,A-1,S-1),one_year_pass(S-1),step(S),age(A),human(H).

%cannot pass year and ask permission at the same step
:- ask_permission(S), one_year_pass(S), step(S).

%cannot pass year and get married at the same step
:- get_married(S), one_year_pass(S), step(S).

%may get married or may not at step S if permission is asked and
% sum of ages is less than 36
0{get_married(S)}1:- human_age(romeo,A1,S-1),human_age(juliet,A2,S-1),
A1+A2<36, ask_permission(S-1), age(A1),age(A2),step(S).

%may get married or may not at step S if they are grown up
0{get_married(S)}1:- human_age(romeo,A1,S-1),human_age(juliet,A2,S-1),
	 A1+A2>36,age(A1),age(A2),step(S).

%canoot get married twice
:-get_married(S),get_married(S1),S!=S1, step(S),step(S1).


married:-get_married(S),step(S).

done:-married.
:-not done.


compute all {married}.
hide.
show married.
show get_married(S).
show ask_permission(S).
show one_year_pass(S).

************************************************
*** SOLUTION 10, in the language of CCalc
*** By Jonathan Campbell (campbell@cs.utexas.edu)
************************************************

:- macros
   minAge -> 16;
   maxAge -> 20;
   maxYear -> 2;
   planLen -> 6.

:- sorts
   yearInt;
   ageInt;
   person.

:- variables
   P,P2,P3 :: person;
   A, A2:: ageInt;
   Y :: yearInt;
   AC :: action.

:- constants
   minAge..maxAge :: ageInt;
   0..maxYear :: yearInt;
   romeo,juliet :: person;
   askPermission(person) :: action;
   marry(person,person) :: action;
   waitAYear :: action;
   currentYear :: inertialFluent(yearInt);
   permitted(person) :: inertialFluent;
   age(person) :: inertialFluent(ageInt);
   married(person,person) :: inertialFluent;
   actionTaken :: defaultFalseFluent.

% waiting a year causes the current year and each person's age to increase by
% one
waitAYear causes age(P) eq A+1 if age(P) eq A && A < maxAge.
waitAYear causes currentYear eq Y+1 if currentYear eq Y && Y < maxYear.
nonexecutable waitAYear if currentYear eq maxYear.

% if a person asks her parents for permission to marry, permission will be
% granted.
askPermission(P) causes permitted(P).
caused permitted(P) if age(P) eq A && A >= 18.
nonexecutable askPermission(P) if permitted(P).

% marriage causes two people to be married to each other (not surprisingly).
% The 'marry' action requires its arguments to be ordered, so that each couple
% has exactly one corresponding marry action.
marry(P,P2) causes married(P,P2).
nonexecutable marry(P,P2) if -(P @< P2).
caused married(P,P2) if married(P2,P) && (P2 @< P).

% two people can't marry unless they both have permission
nonexecutable marry(P,P2) if (-permitted(P) ++ -permitted(P2)) && -(P=P2).

% a person who's already married can't remarry her spouse
nonexecutable marry(P,P2) if married(P,P2) && -(P=P2).

% marriage is always symmetric and irreflexive
never married(P,P2) && -married(P2,P) && -(P=P2).
never married(P,P).

% a person can never be married to two different people.
never married(P,P2) && married(P,P3) && -(P=P2) && -(P=P3) && -(P2=P3).

% waiting can't be performed concurrently with another action, since waiting is
% by definition not doing anything
nonexecutable waitAYear && askPermission(P).
nonexecutable waitAYear && marry(P,P2).

% The following two rules give each plan of length M a unique extension to
% length N > M.  They ensure that the plan includes a sequence of actions
% (without any steps in which no action is taken), followed by a sequence in
% which no actions are taken.
AC causes actionTaken.
caused -actionTaken after -actionTaken.

:- set(number_of_interpretations,all).

:- plan
   facts::
      0: currentYear eq 0,
      0: age(romeo) eq 17,
      0: age(juliet) eq 16,
      0: -permitted(romeo),
      0: -permitted(juliet),
      0: -married(juliet,romeo);
   goal::
      planLen: married(juliet,romeo),
      planLen: currentYear eq maxYear.
