%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Descriptions of the physical world. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % The 3 London's city regions are represented by 3 rectangular % blocks in a gridworld, in which each location is represented % by a term loc(X, Y), where X and Y are the coordinates. % % Please see accompanied documentation for a more detailed diagram. % % y % ^ % | |---------|---------| % | | | | % | | NW | NE | % | | | | % | |---------|---------| % | | | % | | S | % | | | % | |---------| % --------------------------------> x % % For each region, we will assume (for now) that there are: % - 1 Base % - 1 Hospital % - 10 cars, all initially parked at the base % % What can be a coordinate value coordVal(1). coordVal(2). coordVal(3). coordVal(4). coordVal(5). coordVal(6). coordVal(7). coordVal(8). coordVal(9). coordVal(10). coordVal(11). coordVal(12). coordVal(13). coordVal(14). coordVal(15). coordVal(16). coordVal(17). coordVal(18). coordVal(19). coordVal(20). /* ---------- */ % region(Name, ID, BottomLeft, TopRight) region(nw, 1, loc(1, 11), loc(10, 20)). region(ne, 2, loc(11, 11), loc(20, 20)). region(s, 3, loc(6, 1), loc(15, 10)). range(allRegions, [nw, ne, s]). regionRange(all, allRegions). /* ---------- */ % base(Name, ID, Region, Loc) base(b1, 1, nw, loc( 7, 14)). base(b2, 2, ne, loc(14, 14)). base(b3, 3, s, loc(12, 7)). range(nwBases, [b1]). range(neBases, [b2]). range(sBases, [b3]). range(allBases, [b1, b2, b3]). baseRange(nw, nwBases). baseRange(ne, neBases). baseRange(s, sBases). baseRange(all, allBases). /* ---------- */ % hospital(Name, ID, Region, Loc) hospital(h1, 1, nw, loc( 4, 17)). hospital(h2, 2, ne, loc(17, 17)). hospital(h3, 3, s, loc( 9, 4)). range(nwHosps, [h1]). range(neHosps, [h2]). range(sHosps, [h3]). range(allHosps, [h1, h2, h3]). hospRange(nw, nwHosps). hospRange(ne, neHosps). hospRange(s, sHosps). hospRange(all, allHosps). /* ---------- */ % car(Name, ID, Region) car(c1, 1, nw). car(c11, 11, ne). car(c21, 21, s). car(c2, 2, nw). car(c12, 12, ne). car(c22, 22, s). car(c3, 3, nw). car(c13, 13, ne). car(c23, 23, s). car(c4, 4, nw). car(c14, 14, ne). car(c24, 24, s). car(c5, 5, nw). car(c15, 15, ne). car(c25, 25, s). car(c6, 6, nw). car(c16, 16, ne). car(c26, 26, s). car(c7, 7, nw). car(c17, 17, ne). car(c27, 27, s). car(c8, 8, nw). car(c18, 18, ne). car(c28, 28, s). car(c9, 9, nw). car(c19, 19, ne). car(c29, 29, s). car(c10, 10, nw). car(c20, 20, ne). car(c30, 30, s). % range(Name, List). range(nwCars, [c1, c2, c3, c4, c5, c6, c7, c8, c9, c10]). range(neCars, [c11, c12, c13, c14, c15, c16, c17, c18, c19, c20]). range(sCars, [c21, c22, c23, c24, c25, c26, c27, c28, c29, c30]). range(allCars, [c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30]). % carRange(Region, RangeName). carRange(nw, nwCars). carRange(ne, neCars). carRange(s, sCars). carRange(all, allCars). /* ----------------------------------------- */ % % If a car is on the move, its location changes and therefore becomes unknown. % However, we assume that within this initial grace period, its location is % considered unchanged and therefore its location is considered known. % validPeriod(60). % % The average amount of time it takes to travel one road block: % - Inside and outside the home region % - With and without the emergency siren % avgTimePerBlockEmergHome(80). % Home region, with emergency siren on avgTimePerBlockEmergForeign(120). % Foreign region, with emergency siren on avgTimePerBlockNormHome(160). % Home region, without emergency siren avgTimePerBlockNormForeign(240). % Foreign region, without emergency siren % % The percentage at which patients need to be carried to the hospital % (after on-site diagnosis is done) % hospitalizeRate(0.8). % % The rate at which emergency requests arrive % :- dynamic(requestRate/1). requestRate(100). % 1 request every 60 secs % % The rate at which communication would fail, given the car is not at the base % commFailRate(0.15). % % The average amount of time it takes to perform onsite diagnosis % diagTime(240). % 4 minutes % % The average amount of time it takes to unload the patient % unloadTime(120). % 2 minutes % % Tired crew work more slowly. We assume that if we mobilize a car that is % ready but still on the road, its crew will not be happy, because they have % not been able to rest properly after their last assignment. Therefore, it % will take them more time than normal to complete the next assignment. We % will call this extra time the "Tiredness Lag Time" % tirednessLagTime(120). crewRecoveryTime(200). /* ----------------------------------------- */ % % Reward Constants % Please see accompanied documentation for explaination % rOntime(100). % 100 points for getting there on time rLate(0). % 0 points for getting there late %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Actions Descriptions % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Agent actions % agentAction(wait(T)). agentAction(mobilize(Car, Loc, T)). deterministic(wait(T), S). nondetActions(mobilize(Car, Loc, T), S, [mobilizeS(Car, Loc, T), mobilizeF(Car, Loc, T)]). prob(mobilizeS(Car, L, T), P, S):- carLocation(Car, Loc, T, S), ( base(_, _, _, Loc) -> P is 1; (commFailRate(Rate), P is 1 - Rate) ). prob(mobilizeF(Car, L, T), P, S):- carLocation(Car, Loc, T, S), ( base(_, _, _, Loc) -> P is 0; (commFailRate(Rate), P is Rate) ). senseCondition(mobilizeS(Car, Loc, T), (isACar(Car) & -ready(Car) & -commLost(Car))). senseCondition(mobilizeF(Car, Loc, T), (isACar(Car) & (ready(Car) v commLost(Car)))). differentiatingSeq(mobilize(Car, Loc, T), askStatus(Car, Status, T)). % % Sensing actions % senseAction(askPosition(Car, L, T)). agentAction(askPosition(Car, L, T)). deterministic(askPosition(Car, L, T)). senseAction(askStatus(Car, Status, T)). deterministic(askStatus(Car, Status, T)). % % Exogenous Actions % exoAction(reportArrival(Car, Loc, T)). exoAction(reportReady(Car, Loc, T)). exoAction(reportLocation(Car, Loc, T)). exoAction(request(Loc, T)). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Precondition and Successor State Axioms % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% poss(wait(T), S). poss(mobilizeS(Car, Loc, T), S):- ready(Car, S), carLocKnown(Car, T, S). poss(mobilizeF(Car, Loc, T), S):- ready(Car, S), carLocKnown(Car, T, S). poss(askPosition(Car, L, T), S). poss(askStatus(Car, Status, T), S). /* ----------------------------------------- */ % % ready(Name, Situation). % ready(Car, s0):- isACar(Car). ready(Car, do(A, S)):- A = reportReady(Car, L, T); A = askStatus(Car, ready, T); not A = mobilizeS(Car, L, T), not A = askStatus(Car, busy, T), not A = askStatus(Car, unknown, T), ready(Car, S). % % The location of a car C is known in the situation S if % it has not moved away from its last reported position. % % carLocKnown(Car, s0):- isACar(Car). % carLocKnown(Car, do(A, S)):- % A = reportReady(Car, L, _), base(_, _, _, L); % A = reportReady(Car, L, T), validPeriod(P), start(S, T1), T1 - T =< P; % A = askPosition(Car, L, T), not L = unclear, validPeriod(P), start(S, T1), T1 - T =< P; % A = mobilizeS(Car, _, T), validPeriod(P), start(S, T1), T1 - T =< P; % not (A = mobilizeS(Car, _, T), validPeriod(P), start(S, T1), T1 - T > P), % carLocKnown(Car, S). carLocKnown(Car, Time, s0):- isACar(Car), start(s0, T), Time >= T. carLocKnown(Car, Time, do(A, S)):- A = reportReady(Car, L, T), base(_, _, _, L), Time >= T ; A = reportReady(Car, L, T), validPeriod(P), Time =< T + P, Time >= T ; A = askPosition(Car, L, T), base(_, _, _, L), Time >= T ; A = askPosition(Car, L, T), not L = unclear, validPeriod(P), Time =< T + P, T >= T; not (A = mobilizeS(Car, _, T), validPeriod(P), Time > T + P), carLocKnown(Car, Time, S). % % Initially, all cars are at their home base % carLocation(Car, Loc, Time, s0):- isACar(Car), homeBase(Car, Base), locOf(Base, Loc), start(s0, T), Time >= T. carLocation(Car, Loc, Time, do(A, S)):- A = reportReady(Car, Loc, T), base(_, _, _, Loc), Time >= T ; A = reportReady(Car, Loc, T), validPeriod(P), Time =< T + P, Time >= T ; A = askPosition(Car, Loc, T), base(_, _, _, Loc), Time >= T ; A = askPosition(Car, Loc, T), not Loc = unclear, validPeriod(P), Time =< T + P, T >= T; not (A = mobilizeS(Car, _, T), validPeriod(P), Time > T + P), carLocation(Car, Loc, Time, S). % % Communication with a given car is said to be lost if: % - We tried to ask for its location, and % - The reply was unclear, and % - The car has not get back (ie, reportReady or reportArrival) % to us since then. % commLost(Car, do(A, S)):- A = askPosition(Car, unclear, T); A = askStatus(Car, unknown, T); A = mobilizeF(Car, Loc, T); not A = reportReady(Car, _, _), not A = reportArrival(Car, _, _), commLost(Car, S). requestPending(L, do(A, S)):- A = request(L, _); not A = mobilizeS(_, L, _), requestPending(L, S). atBase(Car, s0):- isACar(Car). atBase(Car, do(A, S)):- A = reportReady(Car, Loc, _), homeBase(Car, Base), locOf(Base, Loc); A = askPosition(Car, Loc, _), homeBase(Car, Base), locOf(Base, Loc); not A = mobilizeS(Car, _, _), atBase(Car, S). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Utility Predicates % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% time(mobilizeS(_, _, T), T). time(mobilizeF(_, _, T), T). time(wait(T), T). time(askPosition(_, _, T), T). time(askStatus(_, _, T), T). time(reportArrival(_, _, T), T). time(reportReady(_, _, T), T). time(request(_, T), T). restoreSitArg(requestPending(L), S, requestPending(L, S)). restoreSitArg(ready(C), S, ready(C, S)). restoreSitArg(carLocKnown(C, T), S, carLocKnown(C, T, S)). restoreSitArg(carLocation(C, L, T), S, carLocation(C, L, T, S)). restoreSitArg(commLost(C), S, commLost(C, S)). restoreSitArg(someCarReady, S, someCarReady(S)). restoreSitArg(atBase(Car), S, atBase(Car, S)). /* ----------------------------------------- */ consecTripCount(_, 0, s0). consecTripCount(Car, 0, do(A, S)):- A = reportReady(Car, Loc, _), homeBase(Car, Base), locOf(Base, Loc). consecTripCount(Car, N, do(A, S)):- A = mobilizeS(Car, Loc, _), consecTripCount(Car, N1, S), N is N1 + 1. consecTripCount(Car, N, do(A, S)):- not (A = reportReady(Car, Loc, _), homeBase(Car, Base), locOf(Base, Loc)), not A = mobilizeS(Car, _, _), consecTripCount(Car, N, S). % Manhattan distance between two points distance(loc(X1, Y1), loc(X2, Y2), D):- Y3 is Y2 - Y1, abs(Y3, Y4), X3 is X2 - X1, abs(X3, X4), D is X4 + Y4. validXCoord(Region, X):- region(Region, _, loc(X1, Y1), loc(X2, Y2)), coordVal(X), X >= X1, X =< X2. validYCoord(Region, Y):- region(Region, _, loc(X1, Y1), loc(X2, Y2)), coordVal(Y), Y >= Y1, Y =< Y2. % The isA relation isARegion(Reg):- region(Reg, _, _, _). isAHospital(Hosp):- hospital(Hosp, _, _, _). isABase(Base):- base(Base, _, _, _). isACar(Car):- car(Car, _, _). % Reg is the home region of Car homeRegion(Car, Reg):- car(Car, _, Reg). % Base is the home base of Car homeBase(Car, Base):- car(Car, _, Reg), base(Base, _, Reg, _). % Whether or not sth belong to the region Reg in(Base, Reg):- base(Base, _, Reg, _). in(Hosp, Reg):- hospital(Hosp, _, Reg, _). in(Loc, Reg):- region(Reg, _, loc(X1, Y1), loc(X2, Y2)), Loc = loc(X, Y), X1 =< X, X =< X2, Y1 =< Y, Y =< Y2. % Whether two things is in the same region inSameRegion(A, B):- car(A, _, Reg), base(B, _, Reg, _); car(B, _, Reg), base(A, _, Reg, _); car(A, _, Reg), hospital(B, _, Reg, _); car(B, _, Reg), hospital(A, _, Reg, _); base(A, _, Reg, _), hospital(B, _, Reg, _); base(B, _, Reg, _), hospital(A, _, Reg, _). % Location of a base or a hosp locOf(Base, Loc):- base(Base, _, _, Loc). locOf(Hosp, Loc):- hospital(Hosp, _, _, Loc). /* Note that in the interpreter we defined that range([],[]). range([H | T],[H | T]). Consequently, even if a range has no individual name, but is a list of elements, the following implementation works. */ aCarFromTheRange(Car, RangeName, OtherCars) :- range(RangeName, [Car | OtherCars]). nonEmptyRange( RangeName ) :- range(RangeName, List), List = [Head | Tail]. firstCarInList([H|T], H, T). nonEmptyList(List):- not (List = []). /* ------------------------------- */ listOfRegions(RList):- regionRange(all, RName), range(RName, List), buildListOfRegions(List, RList). buildListOfRegions([], []). buildListOfRegions([H|T], RList):- buildListOfRegions(T, RList1), region(H, I, loc(X1, Y1), loc(X2, Y2)), RList = [[I, X1, Y1, X2, Y2] | RList1]. listOfBases(BList) :- baseRange(all, RName), range(RName, List), buildListOfBases(List, BList). buildListOfBases([], []). buildListOfBases([H|T], BList):- buildListOfBases(T, BList1), base(H, I, _, loc(X, Y)), BList = [[I, X, Y] | BList1]. listOfHosps(HList) :- hospRange(all, RName), range(RName, List), buildListOfHosps(List, HList). buildListOfHosps([], []). buildListOfHosps([H|T], HList):- buildListOfHosps(T, HList1), hospital(H, I, _, loc(X, Y)), HList = [[I, X, Y] | HList1]. listOfCars(CList):- carRange(all, RName), range(RName, List), buildListOfCars(List, CList). buildListOfCars([], []). buildListOfCars([H|T], CList):- buildListOfCars(T, CList1), car(H, I, _), homeBase(H, Base), base(Base, _, _, loc(X, Y)), CList = [[I, X, Y] | CList1].