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 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= 18. permitted(P,S+1) :- permitted(P,S),step(S),S17, 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.