% ========== Constants ==========
#const n = 30.
time(0..n).
% ========== Grid and Entities ==========
totalCols(C) :- C = #count{X : init(object(node, _), value(at, pair(X, _)))}.
totalRows(R) :- R = #count{Y : init(object(node, _), value(at, pair(_, Y)))}.
node(ID) :- init(object(node, ID), value(at, pair(_, _))).
nodeCoordinates(ID, X, Y) :- init(object(node, ID), value(at, pair(X, Y))).
robot(R) :- init(object(robot, R), value(at, pair(_, _))).
location(R, ID, 0) :- init(object(robot, R), value(at, pair(X, Y))), nodeCoordinates(ID, X, Y).
road(ID) :- init(object(highway, ID), value(at, pair(_, _))).
pickupStation(PS, ID) :- init(object(pickingStation, PS), value(at, pair(X, Y))),
nodeCoordinates(ID, X, Y).
rack(SH) :- init(object(shelf, SH), value(at, pair(_, _))).
shelfPosition(SH, ID, 0) :- init(object(shelf, SH), value(at, pair(X, Y))), nodeCoordinates(ID, X,
Y).
product(PID, SH, Q, 0) :- init(object(product, PID), value(on, pair(SH, Q))).
order(OID) :- init(object(order, OID), _).
orderRequirement(OID, PID, Q, 0) :- init(object(order, OID), value(line, pair(PID, Q))).
orderTarget(OID, SID) :- init(object(order, OID), value(pickingStation, PS)), pickupStation(PS,
SID).
% ========== Movement Directions ==========
moveDir(1,0; -1,0; 0,1; 0,-1).
% ========== Action Generation ==========
{ task(R, move(DX,DY), T) : moveDir(DX,DY) } 1 :- robot(R), time(T), T>0.
{ task(R, pickup(SH), T) : rack(SH) } 1 :- robot(R), time(T), T>0.
{ task(R, putdown(SH), T) : rack(SH) } 1 :- robot(R), time(T), T>0.
{ task(R, deliver(OID, PID, Qty), T) :
orderRequirement(OID, PID, Remaining, T),
product(PID, SH, Available, T),
Qty=1..Available
} 1 :- robot(R), time(T), T>0.
% ========== Action Effects ==========
% --- Movement ---
location(R, NewID, T+1) :-
location(R, ID, T),
nodeCoordinates(ID, X, Y),
nodeCoordinates(NewID, X+DX, Y+DY),
task(R, move(DX,DY), T).
% --- Pick up / Put down ---
shelfPosition(SH, R, T+1) :-
task(R, pickup(SH), T),
shelfPosition(SH, ID, T),
location(R, ID, T).
shelfPosition(SH, ID, T+1) :-
task(R, putdown(SH), T),
shelfPosition(SH, R, T),
location(R, ID, T).
% --- Delivery ---
orderRequirement(OID, PID, NewQ, T+1) :-
task(R, deliver(OID, PID, DeliveredQty), T),
orderRequirement(OID, PID, OldQ, T),
NewQ = OldQ - DeliveredQty.
product(PID, SH, NewQty, T+1) :-
task(R, deliver(OID, PID, DeliveredQty), T),
product(PID, SH, OldQty, T),
NewQty = OldQty - DeliveredQty.
% ========== Frame Axioms (Persistence) ==========
location(R, ID, T+1) :- location(R, ID, T), not moved(R, T), T<n.
shelfPosition(SH, ID, T+1) :- shelfPosition(SH, ID, T), not shelfMoved(SH, T), T<n.
shelfPosition(SH, R, T+1) :- shelfPosition(SH, R, T), not shelfMoved(SH, T), T<n.
orderRequirement(OID, PID, Q, T+1) :- orderRequirement(OID, PID, Q, T), not
orderChanged(OID, PID, T), T<n.
product(PID, SH, Q, T+1) :- product(PID, SH, Q, T), not productChanged(PID, SH, T), T<n.
moved(R, T) :- task(R, _, T).
shelfMoved(SH, T) :- task(R, pickup(SH), T); task(R, putdown(SH), T).
orderChanged(OID, PID, T) :- task(R, deliver(OID, PID, _), T).
productChanged(PID, SH, T) :- task(R, deliver(_, PID, _), T), product(PID, SH, _, T).
% ========== Constraints ==========
% --- Movement Out of Bounds ---
:- location(R, ID, T), task(R, move(DX,DY), T), nodeCoordinates(ID, X, Y), X+DX > C,
totalCols(C).
:- location(R, ID, T), task(R, move(DX,DY), T), nodeCoordinates(ID, X, Y), X+DX < 1.
:- location(R, ID, T), task(R, move(DX,DY), T), nodeCoordinates(ID, X, Y), Y+DY > R,
totalRows(R).
:- location(R, ID, T), task(R, move(DX,DY), T), nodeCoordinates(ID, X, Y), Y+DY < 1.
% --- Pickup Constraints ---
:- task(R, pickup(SH), T), not location(R, ID, T), shelfPosition(SH, ID, T).
:- 2 { task(R, pickup(SH), T) : robot(R) }, rack(SH).
% --- Putdown Constraints ---
:- task(R, putdown(SH), T), not shelfPosition(SH, R, T).
:- task(R, putdown(SH), T), location(R, ID, T), road(ID).
% --- Delivery Validations ---
:- task(R, deliver(OID, PID, Qty), T),
orderRequirement(OID, PID, Need, T),
Qty > Need.
:- task(R, deliver(OID, PID, Qty), T),
product(PID, SH, Available, T),
Qty > Available.
:- task(R, deliver(OID, PID, _), T),
orderTarget(OID, SID),
not location(R, SID, T).
% --- No Collisions ---
:- location(R1, ID, T), location(R2, ID, T), R1 != R2.
:- location(R1, ID1, T), location(R2, ID2, T),
location(R1, ID2, T+1), location(R2, ID1, T+1),
R1 != R2.
% --- Goal Completion ---
:- orderRequirement(OID, PID, Q, n), Q != 0.
% ========== Optimization ==========
#minimize { T : task(R, _, T) }.
% ========== Output ==========
#show task/3.
Output for inst1: