%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% A two rooms, two agents, four blocks, and a table problem. %%%% (inspired from Boutilier Brafman JAIR 14, 2001, 105-136) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% Encoded by DFP, MAY 2009 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Run as :-bmap(7) and observe how the agents uses the table to transport the %%% four blocks. agent(a). agent(b). blk(B) :- numblocks(Max), interval(B,1,Max). room(1). room(2). place(table). place(ground). liftable(X) :- blk(X). liftable(table). object(X) :- blk(X). object(table). object(X) :- agent(X). fluent(holds_something(X),0,L) :- agent(X), numblocks(L). %0=nothing fluent(inroom(X),1,2) :- object(X). fluent(position(B),0,2) :- blk(B). % 0=on_ground 1=on_table 2=in_hand fluent(lifts_table(X),0,1) :- agent(X). %%%%%%%%%%%%%% % THE ACTIONS: %%%%%%%%%%%%%% action([X], walk(From,To)) :- agent(X), room(From), room(To), neq(From,To). action([X], walk(1,2)) :- agent(X). action([X], grab(A)) :- agent(X), liftable(A). action([X], put_on(table,ground)) :- agent(X). action([X], put_on(A,P)) :- agent(X), blk(A), place(P). %%%%%%%%%%%%%% % EXECUTABILITY: %%%%%%%%%%%%%% %An agent can move from room 1 to room 2 only if he is carrying something executable([X], walk(2,1), [inroom(X) eq 2, lifts_table(X) eq 0] ) :- action([X], walk(2,1)), agent(X). executable([X], walk(1,2), [inroom(X) eq 1, holds_something(X) gt 0] ) :- action([X], walk(1,2)), agent(X). executable([X], walk(1,2), [inroom(X) eq 1, lifts_table(X) gt 0, lifts_table(Y) gt 0] ) :- action([X], walk(1,2)), agent(X),agent(Y),neq(X,Y). executable([X], grab(A), [inroom(X) eq inroom(A), position(A) lt 2, holds_something(X) eq 0, lifts_table(X) eq 0]) :- action([X], grab(A)), blk(A). executable([X], grab(table), [inroom(X) eq inroom(table), holds_something(X) eq 0, lifts_table(X) eq 0]) :- action([X], grab(table)). executable([X], put_on(A,table), [inroom(X) eq inroom(A), inroom(table) eq inroom(X), holds_something(X) eq A]) :- action([X], put_on(A,table)), blk(A). executable([X], put_on(A,ground), [inroom(X) eq inroom(A), holds_something(X) eq A]) :- action([X], put_on(A,ground)), blk(A). executable([X], put_on(table,ground), [inroom(X) eq inroom(table), lifts_table(X) eq 1]) :- action([X], put_on(table,ground)). %%%%%%%%%%%%%% % DYNAMIC LAWS: %%%%%%%%%%%%%% causes(inroom(X) eq To, [actocc([X], walk(From,To))]) :- action([X], walk(From,To)). causes(inroom(Obj) eq To, [actocc([X], walk(From,To)), holds_something(X) eq Obj]) :- action([X], walk(From,To)), blk(Obj). %the table is heavy and only two agents can move it: causes(inroom(table) eq To, [actocc([X], walk(From,To)), lifts_table(X) eq 1, actocc([Y], walk(From,To)), lifts_table(Y) eq 1]) :- action([X], walk(From,To)), action([Y], walk(From,To)), neq(X,Y). %if only one agent moves while grabbing the table than the table is released: causes(lifts_table(X) eq 0, [actocc([X], walk(From,To)), lifts_table(X) eq 1, actocc([Y], walk(From,To)) eq 0]) :- action([X], walk(From,To)), action([Y], walk(From,To)), neq(X,Y). causes(lifts_table(X) eq 0, [actocc([X], walk(From,To)), lifts_table(X) eq 1, lifts_table(Y) eq 0]) :- action([X], walk(From,To)), agent(Y), neq(X,Y). causes(inroom(Obj) eq To, [actocc([X], walk(From,To)), lifts_table(X) eq 1, actocc([Y], walk(From,To)), lifts_table(Y) eq 1, position(Obj) eq 1]) :- action([X], walk(From,To)), action([Y], walk(From,To)), neq(X,Y), blk(Obj). causes(holds_something(X) eq Blk, [actocc([X], grab(Blk))]) :- action([X], grab(Blk)), blk(Blk). causes(position(Blk) eq 2, [actocc([X], grab(Blk))]) :- action([X], grab(Blk)), blk(Blk). causes(lifts_table(X) eq 1, [actocc([X], grab(table))]) :- action([X], grab(table)). causes(holds_something(X) eq 0, [actocc([X], put_on(Blk,P))]) :- action([X], put_on(Blk,P)), place(P), blk(Blk). causes(position(Blk) eq 0, [actocc([X], put_on(Blk,ground))]) :- action([X], put_on(Blk,ground)), blk(Blk). causes(position(Blk) eq 1, [actocc([X], put_on(Blk,table))]) :- action([X], put_on(Blk,table)), blk(Blk). causes(lifts_table(X) eq 0, [actocc([X], put_on(table,ground))]) :- action([X], put_on(table,ground)). %if only one agents puts_on the table while the other is grabbing it, %then the blocks fall from the table to the ground causes(position(Blk) eq 0, [rei(actocc([A], put_on(table,ground))) + rei(actocc([B], put_on(table,ground))) eq 1, position(Blk) eq 1]) :- blk(Blk),agent(A),agent(B),neq(A,B). %% If only one grabs the table then the blocks fall down causes(position(Blk) eq 0, [rei(actocc([X], grab(table))) + rei(actocc([Y], grab(table))) eq 1, position(Blk) eq 1]) :- action([X], grab(table)), action([Y], grab(table)), blk(Blk), neq(X,Y). %%% NOTE: With rei(A) + rei(B) eq 1 it run faster than the equivalent (in this case) A neq B %%%%%%%%%%%%%% % STATIC LAWS and CONCURRENCY_CONSTRAINTS: %%%%%%%%%%%%%% % One block cannot be simultaneously grabbed by two agents concurrency_constraint(rei(actocc([X], grab(Blk))) + rei(actocc([Y], grab(Blk))) leq 1) :- action([X], grab(Blk)), action([Y], grab(Blk)), neq(X,Y), blk(Blk). %If agent b grabs a block then also agent a has to grab a block... concurrency_constraint( rei(actocc([b], grab(B1))) + rei(actocc([a], walk(R1,R2))) leq 1) :- action([b], grab(B1)), action([a], walk(R1,R2)), blk(B1), room(R1), room(R2). concurrency_constraint( rei(actocc([b], grab(B1))) + rei(actocc([a], put_on(O2,P2))) leq 1) :- action([b], grab(B1)), action([a], put_on(O2,P2)), blk(B1), object(O2), place(P2). %...with lower index concurrency_constraint( rei(actocc([b], grab(B1))) + rei(actocc([a], grab(B2))) leq 1) :- action([b], grab(B1)), action([a], grab(B2)), blk(B1), blk(B2), B1 =< B2. %symmetry-breaking: blk(B1), blk(B2), B1 inroom(B1)>=inroom(B2) always(inroom(B1) geq inroom(B2)) :- blk(B1), blk(B2), B1 < B2. %%%%%%%%%%%%%% % INITIAL STATE: %%%%%%%%%%%%%% initially(holds_something(X) eq 0) :- agent(X). %0=nothing initially(inroom(X) eq 1) :- object(X). initially(position(B) eq 0) :- blk(B). % 0=on_ground 1=on_table 2=in_hand initially(lifts_table(X) eq 0) :- agent(X). %%%%%%%%%%%%%% % GOAL STATE: %%%%%%%%%%%%%% numblocks(4). goal(inroom(table) eq 2). goal(inroom(X) eq 2) :- blk(X). goal(position(X) eq 0) :- blk(X). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%