For Ben and Nil,
If you wish to ponder this some more, here is a short atomese <--> ASP
syntax conversion guide. Some ruminations about performance below.
So: English: "every sweep boat is a boat"
written in ASP: boat(BOAT) :- sweep_boat(BOAT).
written in Atomese:
Implication
Evaluation
Predicate "sweep_boat"
List
Variable BOAT
Evaluation
Predicate "boat"
List
Variable BOAT
Clearly Atomese is verbose.
Here's another:
% A boat is available if its not in use by any crew.
available(RACE, BOAT) :- racenum(RACE), crew(CREW), boat(BOAT),
not inuse(RACE, CREW, BOAT).
The first three clauses are "typechecking": the variable CREW must be of
type "crew", etc.
The last clause is a non-trivial constraint.
Implication
And
Evaluation
Predicate "racenum"
List
Variable RACE
Evaluation
Predicate "crew"
List
Variable CREW
Evaluation
Predicate "boat"
List
Variable BOAT
Not
Evaluation
Predicate "inuse"
List
Variable RACE
Variable CREW
Variable BOAT
Evaluation
Predicate "available"
List
Variable RACE
Variable BOAT
I'm totally unclear on the performance profile for atomese. So, for
example: one could use the pattern matcher only, and implement naive
forward chaining. The statement "eight(sophie)" declares a fact without
any variables: "sophie" is an "eight", and since "sweep_boat(BOAT) :-
eight(BOAT)" then one run of the pattern matcher will generate the fact
that "sophie" is a "sweep_boat", and a second pass will generate the fact
that "sophie" is a "boat". Turning the crank in this way will eventually
generate every possible fact that can be deduced.
This naive approach pollutes the atomspace with lots and lots of redundant
facts. In this particular case, its manageable: although a combinatorial
explosion is possible in principle, its absent in practice (there are just
barely enough boats for everyone, and sometimes not enough - the problem is
sometimes not satisfiable)
The forward chainer is supposed to avoid this pollution. I'm somewhat
unclear on how its actually implemented. I'm also unclear on the backward
chainer.
The ASP solver treats the assertions as a graph: In my infamous,
unfinished, unliked "sheaf" paper, the expression "available(RACE, BOAT) :-
racenum(RACE), crew(CREW), boat(BOAT), not inuse(RACE, CREW, BOAT)." would
be a "seed" (jigsaw-puzzle piece) having three connectors - BOAT, CREW and
RACE, and the task is to connect together all such "puzzle pieces" to find
the answer. The ASP solvers do this by pruning all trivial, unidirectional
connections (e.g. "sophie" is a "sweep_boat" is trivial, since there are no
conflicts that prevent the deduction of this fact). After pruning all
deductions that are not conflicting, what is left is some tight knot of
conflicting deductions, which the ASP solver examines exhaustively,
exploring every possible case. Then for each possible solution, the
trivial connections are reattached, and the result is reported to the
user. Bingo.
To the best of my knowledge, this is not how the backward chainer works.
One problem with PLN and probabilistic rules is that *every* possibility
needs to be explored, since the truth values are not crisp T/F. By
contrast, ASP assumes crisp T/F making the problem much much simpler.
(both airplane scheduling, and boat scheduling are crisp T/F).
Nil and I very briefly discussed the possibility of using ASP as a
probabilistic solver for PLN. That is, we would randomly assign T/F values
to atoms, run ASP on them, see what it deduces, and then increment the
count on the corresponding atom. After running this enough times, a
probability distribution becomes clear. Again, this is one of the points
of the "sheaf" paper. A different point is that neural nets also take
these structures, but use a different algo to arrive at a likely
probability distribution. I have yet to finish writing that part of the
paper. It raises the interesting possibility of implementing PLN as a
neural net.
--linas
p.s. I forgot to post the oar solver. Here it is:
%
% regatta team oar scheduling
%
% The problem of scheduling equipment for a regatta is a constraint
% problem -- two crews cannot use the same boat at the same time,
% and, indeed, there must be enough time between crews to rig the boat,
% launch it, warm up, race, and return to the dock, before the next
% crew can use it. Because this is a classic constraint problem,
% implementing this via answer-set programming seems like the easiest,
% most direct way to accomplish this.
%
% Initial version: Linas Vepstas April 2012
%
% Copyright (c) 2012 Linas Vepstas
% The GNU GPLv3 applies.
%
% Two fundamental oar classes; we need this for consistent reservations.
oars(OARS, sweep, COUNT) :- sweep_oars(OARS, COUNT).
oars(OARS, scull, COUNT) :- scull_oars(OARS, COUNT).
oar_type(OARS, TYPE) :- oars(OARS, TYPE, COUNT).
% Enumerate all possible pairs of oars, given the declaration,
% and the count of how many pairs there are.
oarpair(OARS, TYPE, PAIR) :- oars(OARS, TYPE, COUNT), PAIR=1..COUNT.
% The number of oars needed, for a given boat type.
oarpairs_needed(BOAT, sweep, 4) :- eight(BOAT).
oarpairs_needed(BOAT, sweep, 2) :- fourplus(BOAT).
oarpairs_needed(BOAT, sweep, 2) :- fourminus(BOAT).
oarpairs_needed(BOAT, sweep, 1) :- pair(BOAT).
oarpairs_needed(BOAT, scull, 4) :- quad(BOAT).
oarpairs_needed(BOAT, scull, 2) :- double(BOAT).
oarpairs_needed(BOAT, scull, 1) :- single(BOAT).
% ----------------------
% Preference indication.
% choice must be a number, 1 to 4.
oar_choice(CHOICE) :- CHOICE=1..4.
%%% ========================================================== %%%
%% The actual scheduling algorithm.
%% DO NOT MODIFY ANYTHING BELOW THIS LINE!
%% (Unless you really, really know what you're doing, and
%% you probably don't.) Just write me with questions, requests.
%%% ========================================================== %%%
% ----------------------
% oarset logic
%
% The total possible number of matchings of sets of oars to boats.
% The division is done so that out of a set of 4 pairs of oars, a
% quad gets just one set, a double gets set 1 or 2, while singles
% get set 1,2,3 or 4. By contrast, if there are only three pairs of
% oars, then the quads get zero, while doubles and singles can still
% get a set.
oarsets_possible(BOAT, OARS, NSETS) :-
oarpairs_needed(BOAT, TYPE, COUNT),
oars(OARS, TYPE, SETCOUNT),
NSETS = SETCOUNT/COUNT,
NSETS != 0.
% The total universe of oar-set assignments. Any boat will only ever
% get one set of oars. Out of a set of 4 pairs of oars, a quad will
% get the whole set, a double can get set 1 or set 2, while singles
% can get one and only one of the sets 1,2,3 or 4.
% crew and racenum are "free variables", so an orset is generated for
% every possible crew+race combination.
1 { set_universe(RACE, CREW, BOAT, OARS, SET) :
SET=1..NSETS :
oars(OARS, TYPE, COUNT) :
oarsets_possible(BOAT, OARS, NSETS)
} 1 :-
crew(CREW), racenum(RACE).
% Out of a list of desired oars, choose only one set of oars.
oarset_request(RACE, CREW, OARS, SET) :-
oar_prefer(RACE, CREW, OARS, CHOICE),
set_universe(RACE, CREW, BOAT, OARS, SET).
% Two different crews cannot make a request for the same oarset
% for the same race.
:- oarset_request(RACE, CREW, OARS, SET),
oarset_request(RACE, OTHER_CREW, OARS, SET),
CREW != OTHER_CREW.
% ----------------------
% Every boat reservation must have an oar reservation.
% If a crew did not express an oar choice, make a request for them,
% ask for something, anything.
expressed_oar_pref(RACE, CREW) :- oar_prefer(RACE, CREW, OARS, CHOICE).
auto_oar_req(RACE, CREW) :-
got_a_boat(RACE, CREW),
not expressed_oar_pref(RACE, CREW).
oarset_request(RACE, CREW, OARS, SET) :-
auto_oar_req(RACE, CREW),
set_universe(RACE, CREW, BOAT, OARS, SET).
% ----------------------
% Convert oarset requests into oarpair requests. Basically, just take
% the oarset, and multiply by the number of oarpairs needed for a given
% boat class. This is the magic where sets of oars can be split up
% between doubles, singles.
% Note also: a request is not made unless a boat is reserved.
oarpair_request(RACE, CREW, OARS, TYPE, PAIR) :-
reserve(RACE, CREW, BOAT),
oarset_request(RACE, CREW, OARS, SET),
oarpairs_needed(BOAT, TYPE, COUNT),
N = 1..COUNT,
PAIR = N + (SET-1)* COUNT.
% ----------------------
% The core reservation/inuse logic. Vaguely resembles that used for the
% boats, but has more arguments.
% Oars are available if not in use by any crew.
oarpair_available(RACE, OARS, TYPE, PAIR) :-
racenum(RACE), crew(CREW),
oarpair(OARS, TYPE, PAIR),
not oarpair_inuse(RACE, CREW, OARS, TYPE, PAIR).
% Reserve oar pairs if they are requested and available.
oarpair_reserve(RACE, CREW, OARS, TYPE, PAIR) :-
oarpair_available(RACE, OARS, TYPE, PAIR),
oarpair_request(RACE, CREW, OARS, TYPE, PAIR).
% If oarpair is reserved, then it will be in use at least CENTER races
% beforehand. That is, the crew needs CENTER-1 races to launch and
% warmup before the race.
oarpair_inuse(ONWATER, CREW, OARS, TYPE, PAIR) :-
oarpair_reserve(RACE, CREW, OARS, TYPE, PAIR),
heat(SCH, RACE),
SCHMN = SCH - N,
heat(SCHMN, ONWATER),
N = 1..CENTER-1,
center(CENTER).
% Oars are on the water for race immediately after, too.
oarpair_inuse(ONWATER, CREW, OARS, TYPE, PAIR) :-
oarpair_reserve(RACE, CREW, OARS, TYPE, PAIR),
heat(SCH, RACE),
heat(SCH+1, ONWATER).
% Cannot reserve oars that are in use.
:- oarpair_reserve(RACE, CREW, OARS, TYPE, PAIR),
oarpair_inuse(RACE, OTHER_CREW, OARS, TYPE, PAIR),
racenum(RACE), crew(CREW), crew(OTHER_CREW), oarpair(OARS, TYPE, PAIR).
% Cannot request oars if they're in use.
% This rule isn't needed right now, comment it out.
% :- oar_request(RACE, CREW, OARS), oar_inuse(RACE, OTHER_CREW, OARS, PAIR).
% Two different crews cannot reserve same oars for the same race.
% I think this may be a redundant constraint, not sure. I think an
% earlier constraint on oarpair_request by different crews already
% guarantees this.
:- oarpair_reserve(RACE, CREW, OARS, TYPE, PAIR),
oarpair_reserve(RACE, OTHER_CREW, OARS, TYPE, PAIR),
CREW != OTHER_CREW,
racenum(RACE), crew(CREW), crew(OTHER_CREW), oarpair(OARS, TYPE, PAIR).
% ---------------------------------
% Second guess everything. The above should be enough, I think, to
% properly reserve oars. But, just in case ...
% After a bit of experimentation, it seems that this improves
% performance: the solver can find a solution faster, with this code
% in place.
% Make sure that quads and eights get four pairs of oars, and not less.
% Start by counting how many oarparis we actually got.
got_four_oarpairs(RACE, CREW, OARS, TYPE) :-
oarpair_reserve(RACE, CREW, OARS, TYPE, PA),
oarpair_reserve(RACE, CREW, OARS, TYPE, PB),
oarpair_reserve(RACE, CREW, OARS, TYPE, PC),
oarpair_reserve(RACE, CREW, OARS, TYPE, PD),
PA != PB, PA != PC, PA != PD,
PB != PC, PB != PD, PC != PD.
% Doubles, fours need only two pairs of oars.
got_two_oarpairs(RACE, CREW, OARS, TYPE) :-
oarpair_reserve(RACE, CREW, OARS, TYPE, PA),
oarpair_reserve(RACE, CREW, OARS, TYPE, PB),
PA != PB.
% We got enough oar pairs if ... etc, depending on boat type.
got_enough_oarpairs(RACE, CREW, OARS, TYPE) :-
got_four_oarpairs(RACE, CREW, OARS, TYPE),
oarpairs_needed(BOAT, TYPE, 4),
reserve(RACE, CREW, BOAT).
got_enough_oarpairs(RACE, CREW, OARS, TYPE) :-
got_two_oarpairs(RACE, CREW, OARS, TYPE),
oarpairs_needed(BOAT, TYPE, 2),
reserve(RACE, CREW, BOAT).
got_enough_oarpairs(RACE, CREW, OARS, TYPE) :-
oarpair_reserve(RACE, CREW, OARS, TYPE, PAIR),
oarpairs_needed(BOAT, TYPE, 1),
reserve(RACE, CREW, BOAT).
% Whoops, this is true if we got something, but did NOT get enough.
not_got_enough_oarpairs(RACE, CREW, OARS, TYPE) :-
not got_enough_oarpairs(RACE, CREW, OARS, TYPE),
oarpair_reserve(RACE, CREW, OARS, TYPE, PAIR).
% Double-negative: must get enough.
:- not_got_enough_oarpairs(RACE, CREW, OARS, TYPE).
% --------------------
% minimize oar reservation conflicts.
% A crew has a reservation if it has one or more oar pairs.
oar_reserve(RACE, CREW, OARS, TYPE) :-
oarpair_reserve(RACE, CREW, OARS, TYPE, PAIR).
% A crew got oars if it has a reservation.
got_oars(RACE, CREW) :- oar_reserve(RACE, CREW, OARS, TYPE).
% We sure want every oar request to be granted. Must flag any crews
% that got boats, but we can't find them oarpair.
% This flag must be highly visible.
oar_reservation_failure(RACE, CREW) :- got_a_boat(RACE, CREW),
not got_oars(RACE, CREW).
% The above rules do allow a situation where some crews can't get
% oars. Thus, we have to maximize for number of reservations
% granted. This must be at the highest priority, higher than the
% hot-seat avoidance priority.
#minimize [oar_reservation_failure(RACE, CREW)
: oar_reserve_priority(ORP)
: racenum(RACE)
: crew(CREW) @ORP ].
% We're going to try to honour everyone's top preferences.
% So CHOICE=1 is first choice, CHOICE=2 is second choice, etc.
% XXX disabled right now, enable later.
% #minimize [oar_request(RACE, CREW, OARS)
% : oar_choice_priority(OCP)
% : oar_prefer(RACE, CREW, OARS, CHOICE) = CHOICE@OCP ].
% ----------------------
% Hotseat notifications and minimization.
% Basically, we try to find assignments with the fewest hot-seats.
% True if oars will be hotseated at the dock.
% XXX M should be M=0..HOTS but this spews cpu time right now
% and is borken. fixme later.
oar_hotseat(RACE, OARS) :-
oarpair_reserve(RACE, CREW, OARS, TYPE, PAIR),
oarpair_reserve(OTHER_RACE, OTHER_CREW, OARS, TYPE, PAIR),
heat(SCH, RACE),
heat(SCH-CENTER-M, OTHER_RACE),
center(CENTER),
M=1..HOTS, hotseat_warn(HOTS).
% True if crew should hurry back because oarpair are needed.
% Currently, not used for anything, except as a printout for the
% convenience of the crews.
oar_hurry_back(RACE, CREW, OARS) :-
oarpair_reserve(RACE, CREW, OARS, TYPE, PAIR),
oarpair_reserve(OTHER_RACE, OTHER_CREW, OARS, TYPE, PAIR),
heat(SCH, RACE),
heat(SCH+CENTER+M, OTHER_RACE),
center(CENTER),
M=1..HOTS, hotseat_warn(HOTS).
% Minimize the number of oars that are hot-seated.
#minimize [oar_hotseat(RACE, OARS) @OHP : oar_hotseat_priority(OHP)].
% ----------------------
% Equipment list. Stuff to take to the venue.
take_oars_to_venue(OARS, TYPE) :- oar_reserve(RACE, CREW, OARS, TYPE).
% XXX Caution: enabling this can chew up huge amounts of CPU time!
% #minimize [take_oars_to_venue(OARS, TYPE)
% : num_oars_priority(NOP) @NOP ].
% ----------------------
% Look for a typo in the name of the oarpair, crew or race.
% Typos can screw everything up, so flag these.
% fixme, use some kind of aggregate.
% bad_oar_count(OARS) :- oars(OARS,TYPE,COUNT), not COUNT=1..8.
oarname(OARS) :- oars(OARS, TYPE, COUNT).
bad_oar_name(OARS) :- oar_prefer(RACE,CREW,OARS,CH), not oarname(OARS).
bad_crew_name(CREW) :- oar_prefer(RACE,CREW,OARS,CH), not crew(CREW).
bad_race_num(RACE) :- oar_prefer(RACE,CREW,OARS,CH), not racenum(RACE).
bad_oar_name(OARS) :- oar_prefer(RACE,CREW,OARS,CHOICE), not oarname(OARS).
bad_crew_name(CREW) :- oar_prefer(RACE,CREW,OARS,CHOICE), not crew(CREW).
bad_race_num(RACE) :- oar_prefer(RACE,CREW,OARS,CHOICE), not racenum(RACE).
bad_oar_preference(CHOICE) :- oar_prefer(RACE,CREW,OARS,CHOICE), not
choice(CHOICE).
#show oar_reservation_failure/2.
#show bad_oar_count/1.
#show bad_oar_name/1.
#show bad_oar_preference/1.
% #show got_four_oarpairs/4.
% #show got_enough_oarpairs/4.
% #show not_got_enough_oarpairs/4.
#show oar_reserve/4.
#show oar_hotseat/2.
#show oar_hurry_back/3.
#show take_oars_to_venue/2.
% #show oar_request/3.
% #show oarpair_inuse/5.
% #show oarpair_available/4.
% #show oarpairs_needed/3.
% #show set_universe/5.
% #show oarsets_possible/3.
% #show oarset_request/4.
% #show oarpair_request/5.
% #show oarpair_reserve/5.
On Tue, Jan 2, 2018 at 1:49 PM, Linas Vepstas <[email protected]>
wrote:
> Hi Ramin,
>
> For this kind of problem, I would strongly encourage using answer-set
> programming. It looks like prolog (but isn't), it uses modern SAT-solving
> technology to get tremendous speed. The Univ Potsdam solver is maybe the
> best one. It's excellent for solving constraint satisfaction problems.
>
> Here's an example: instead of airplanes, its boats and oars. The
> constraints are:
> -- a race every 4 minutes
> -- boat must be back in time to unload, reload, and get to starting line
> viz 12 minutes
> -- boat (and oars) obviously cannot be used by someone else while on the
> water
> -- boats are 1x, 2x, 2+, 2-, 4x, 4+, 4-, 8+ (these are different kinds of
> boats)
> -- oars must be a matched set, appropriate for that boat style.
> -- boats are constrained by the race that they are in.
> -- certain crews insist on using certain equipment, and have priority
> -- certain crews can select only a subset (e.g. mens crews cannot use the
> lightweight boats)
>
> It turns out that the problem is not too hard, until you throw the oars
> into the mix, and then it gets a lot harder.
>
> Here's the solver (it works):
>
> %
> % regatta team equipment scheduling
> %
> % The problem of scheduling equipment for a regatta is a constraint
> % problem -- two crews cannot use the same boat at the same time,
> % and, indeed, there must be enough time between crews to rig the boat,
> % launch it, warm up, race, and return to the dock, before the next
> % crew can use it. Because this is a classic constraint problem,
> % implementing this via answer-set programming seems like the easiest,
> % most direct way to accomplish this.
> %
> % Initial version: Linas Vepstas April 2012
> %
> % Copyright (c) 2012 Linas Vepstas
> % The GNU GPLv3 applies.
> %
>
> % -- List of fundamental boat classes. We must distinguish sweeps
> % from sculls, and quads, doubles, singles, etc. in order to be
> % able to count the number of oars needed, for oar reservations.
> % That's why these are the "fundamental" types.
> boat(BOAT) :- sweep_boat(BOAT).
> boat(BOAT) :- scull_boat(BOAT).
>
> sweep_boat(BOAT) :- eight(BOAT).
> sweep_boat(BOAT) :- fourplus(BOAT).
> sweep_boat(BOAT) :- fourminus(BOAT).
> sweep_boat(BOAT) :- pair(BOAT).
>
> scull_boat(BOAT) :- quad(BOAT).
> scull_boat(BOAT) :- double(BOAT).
> scull_boat(BOAT) :- single(BOAT).
>
> %%% ========================================================== %%%
> %% The actual scheduling algorithm. Short and simple, huh?
> %% DO NOT MODIFY ANYTHING BELOW THIS LINE!
> %% (Unless you really, really know what you're doing, and
> %% you probably don't.) Just write me with questions, requests.
> %%% ========================================================== %%%
>
> % Some priority assignments:
> boat_reserve_priority(12). % top priority
> oar_reserve_priority(11). % 2nd highest priority
> boat_hotseat_priority(10). % 3rd priority
> oar_hotseat_priority(9). % 4th priority
> boat_choice_priority(8).
> oar_choice_priority(7).
> num_boats_priority(6).
> num_oars_priority(5).
>
> % Below follows the core available/request/reserve logic.
>
> % A boat is available if its not in use by any crew.
> available(RACE, BOAT) :- racenum(RACE), crew(CREW), boat(BOAT),
> not inuse(RACE, CREW, BOAT).
>
> % Reserve the boat if it is requested and available.
> reserve(RACE, CREW, BOAT) :- racenum(RACE), crew(CREW), boat(BOAT),
> request(RACE, CREW, BOAT),
> available(RACE, BOAT).
>
> % If a boat is reserved, then it will be in use at least CENTER races
> % beforehand. That is, the crew needs CENTER-1 races to launch and
> % warmup before the race.
> inuse(ONWATER, CREW, BOAT) :- reserve(RACE, CREW, BOAT),
> heat(SCH, RACE),
> SCHMN = SCH - N,
> heat(SCHMN, ONWATER),
> N = 1..CENTER-1,
> center(CENTER).
>
> % Its on the water for the next race, too.
> inuse(ONWATER, CREW, BOAT) :- reserve(RACE, CREW, BOAT),
> heat(SCH, RACE),
> heat(SCH+1, ONWATER).
>
> % Cannot reserve a boat that is in use.
> :- reserve(RACE, CREW, BOAT), inuse(RACE, OTHER_CREW, BOAT),
> racenum(RACE), crew(CREW), crew(OTHER_CREW), boat(BOAT).
>
> % Cannot request a boat if its in use.
> % This rule isn't needed right now, comment it out.
> % :- request(RACE, CREW, BOAT), inuse(RACE, OTHER_CREW, BOAT).
>
> % Two different crews cannot reserve same boat for the same race.
> :- reserve(RACE, CREW, BOAT), reserve(RACE, OTHER_CREW, BOAT),
> CREW != OTHER_CREW,
> racenum(RACE), crew(CREW), crew(OTHER_CREW), boat(BOAT).
>
> % ----------------------
> % Preference indication.
>
> % choice must be a number, 1 to 4.
> choice(CHOICE) :- CHOICE=1..4.
>
> % The total universe of all possible boat assignments, to a given
> % crew and race. In this universe, only one boat is ever assigned.
> 1 { boat_universe(RACE, CREW, BOAT) : boat(BOAT) } 1 :-
> crew(CREW), racenum(RACE).
>
> % Out of a list of desired boats, choose only one boat.
> request(RACE, CREW, BOAT) :- prefer(RACE, CREW, BOAT, CHOICE),
> boat_universe(RACE, CREW, BOAT).
>
> % A crew wants to race in a race if they've expressed a boat preference.
> % or if they've requested a specific boat.
> want_to_race(RACE, CREW) :- prefer(RACE, CREW, BOAT, CHOICE).
> want_to_race(RACE, CREW) :- request(RACE, CREW, BOAT).
>
> % A crew got a boat if it has a reservation.
> got_a_boat(RACE, CREW) :- reserve(RACE, CREW, BOAT).
>
> % We sure want every boat request to be granted. Must flag any crews
> % that want to race a race, but we can't find them a boat.
> % This flag must be highly visible.
> boat_reservation_failure(RACE, CREW) :- want_to_race(RACE, CREW),
> not got_a_boat(RACE, CREW).
>
> % The above rules do allow a situation where some crews can't get
> % a boat. Thus, we have to maximize for number of reservations
> % granted. This must be at the highest priority, higher than the
> % hot-seat avoidance priority.
> #minimize [boat_reservation_failure(RACE, CREW)
> : boat_reserve_priority(BRP)
> : racenum(RACE)
> : crew(CREW) @BRP ].
>
> % We're going to try to honour everyone's top preferences.
> % So CHOICE=1 is first choice, CHOICE=2 is second choice, etc.
> #minimize [request(RACE, CREW, BOAT)
> : boat_choice_priority(BCP)
> : prefer(RACE, CREW, BOAT, CHOICE) = CHOICE@BCP ].
>
> % ----------------------
> % Hotseat notifications and minimization.
> % Basically, we try to find assignments with the fewest hot-seats.
>
> % True if boat will be hotseated at the dock.
> hotseat(RACE, BOAT) :- reserve(RACE, CREW, BOAT),
> reserve(OTHER_RACE, OTHER_CREW, BOAT),
> heat(SCH, RACE),
> heat(SCH-CENTER-M, OTHER_RACE),
> center(CENTER),
> M=0..HOTS, hotseat_warn(HOTS).
>
> % True if crew should hurry back because boat is needed.
> % Currently, not used for anything, except as a printout for the
> % convenience of the crews.
> hurry_back(RACE, CREW, BOAT) :-
> reserve(RACE, CREW, BOAT),
> reserve(OTHER_RACE, OTHER_CREW, BOAT),
> heat(SCH, RACE),
> heat(SCH+CENTER+M, OTHER_RACE),
> center(CENTER),
> M=0..HOTS, hotseat_warn(HOTS).
>
> % Minimize the number of boats that are hot-seated.
> % The @10 just means that minimizing the number of hot-seats is
> % top priority -- higher priority than honoring desired boats.
> #minimize [hotseat(RACE, BOAT) @BHP : boat_hotseat_priority(BHP)].
>
>
> % ----------------------
> % Equipment list. Stuff to take to the venue.
> take_to_venue(BOAT) :- reserve(RACE, CREW, BOAT).
>
> % This seems to make things run a bit slower... and yeilds nothing
> % noteworthy, since specific boats are being aasked for in almost
> % all cases, and so te below can't cut down on anything.
> % It seems to add 5% or so tot toal run time ...
> #minimize [take_to_venue(BOAT)
> : num_boats_priority(NBP) @NBP ].
>
> % ----------------------
> % Look for a typo in the name of the boat, crew or race.
> % Typos can screw everything up, so flag these.
> bad_boat_name(BOAT) :- request(RACE,CREW,BOAT), not boat(BOAT).
> bad_crew_name(CREW) :- request(RACE,CREW,BOAT), not crew(CREW).
> bad_race_num(RACE) :- request(RACE,CREW,BOAT), not racenum(RACE).
>
> bad_boat_name(BOAT) :- prefer(RACE,CREW,BOAT,CHOICE), not boat(BOAT).
> bad_crew_name(CREW) :- prefer(RACE,CREW,BOAT,CHOICE), not crew(CREW).
> bad_race_num(RACE) :- prefer(RACE,CREW,BOAT,CHOICE), not racenum(RACE).
> bad_preference(CHOICE) :- prefer(RACE,CREW,BOAT,CHOICE), not
> choice(CHOICE).
>
> #hide.
> #show boat_reservation_failure/2.
> #show bad_boat_name/1.
> #show bad_crew_name/1.
> #show bad_race_num/1.
> #show bad_preference/1.
> #show reserve/3.
> #show hotseat/2.
> #show hurry_back/3.
> #show take_to_venue/1.
> % #show request/2.
> % #show inuse/2.
> % #show available/2.
>
>
>
> On Mon, Jan 1, 2018 at 7:02 AM, Ramin Barati <[email protected]> wrote:
>
>> Hi Ben, Linas, etc
>>
>> I am trying to solve a resource allocation problem; assigning planes to
>> flights.
>>
>> Here is the domain definition in PDDL:
>>
>> ------------------------------------------------------------
>> -------------------------
>> (define (domain flight-plan)
>> (:requirements :strips :typing :action-costs)
>> (:types
>> location localable leg - object
>> airport - location
>> register - localable
>> )
>> (:predicates
>> (at ?o - localable ?l - location)
>> (assigned ?l - leg)
>> (assigned-to ?l - leg ?r - register)
>> (source ?l - leg ?a - airport)
>> (destination ?l - leg ?a - airport)
>> )
>> (:functions
>> (start ?l - leg) - number
>> (duration ?l - leg ?r - register) - number
>> (pax ?l - leg) - number
>> (capacity ?r - register) - number
>> (assignement-cost ?l - leg ?r - register) - number
>> (timeline ?r - register) - number
>> (total-cost) - number
>> )
>> (:action asgn
>> :parameters (?l - leg ?r - register ?src ?dest - airport)
>> :precondition (and
>> (> (start ?l) (timeline ?r))
>> (source ?l ?src)
>> (destination ?l ?dest)
>> (at ?r ?src)
>> (not (assigned ?l))
>> (> (capacity ?r) (pax ?l))
>> )
>> :effect (and
>> (decrease (timeline ?r) (timeline ?r))
>> (increase (timeline ?r) (+ (start ?l) (duration ?l ?r)))
>> (not (at ?r ?src))
>> (at ?r ?dest)
>> (assigned ?l)
>> (assigned-to ?l ?r)
>> (increase (total-cost) (assignement-cost ?l ?r))
>> )
>> )
>> (:action shift-left-sixty
>> :parameters (?l - leg)
>> :precondition (and
>> (not (assigned ?l))
>> (> (start ?l) 60)
>> )
>> :effect (and
>> (decrease (start ?l) 60)
>> )
>> )
>> (:action shift-right-sixty
>> :parameters (?l - leg)
>> :precondition (and
>> (not (assigned ?l))
>> (< (start ?l) 1380)
>> )
>> :effect (and
>> (increase (start ?l) 60)
>> )
>> )
>> )
>> ------------------------------------------------------------
>> -------------------------
>>
>> and here is a sample problem:
>>
>> ------------------------------------------------------------
>> -------------------------
>> (define (problem assignment)
>> (:domain flight-plan)
>> (:objects
>> THR-SRY SRY-THR THR-ISF ISF-THR - leg
>> MOC JHH MNT - register
>> thr sry isf - airport
>> )
>> (:init
>> (= (total-cost) 0)
>> (at MOC thr)
>> (at JHH thr)
>> (at MNT thr)
>> (= (capacity MOC) 100)
>> (= (timeline MOC) 0)
>> (= (capacity JHH) 200)
>> (= (timeline JHH) 0)
>> (= (capacity MNT) 280)
>> (= (timeline MNT) 0)
>> (source THR-SRY thr)
>> (destination THR-SRY sry)
>> (= (start THR-SRY) 600)
>> (= (pax THR-SRY) 90)
>> (source SRY-THR sry)
>> (destination SRY-THR thr)
>> (= (start SRY-THR) 720)
>> (= (pax SRY-THR) 150)
>> (source THR-ISF thr)
>> (destination THR-ISF isf)
>> (= (start THR-ISF) 720)
>> (= (pax THR-ISF) 220)
>> (source ISF-THR isf)
>> (destination ISF-THR thr)
>> (= (start ISF-THR) 900)
>> (= (pax ISF-THR) 190)
>> (= (assignement-cost THR-SRY MOC) 1)
>> (= (assignement-cost SRY-THR MOC) 1)
>> (= (assignement-cost THR-ISF MOC) 1)
>> (= (assignement-cost ISF-THR MOC) 1)
>> (= (assignement-cost THR-SRY JHH) 1)
>> (= (assignement-cost SRY-THR JHH) 1)
>> (= (assignement-cost THR-ISF JHH) 1)
>> (= (assignement-cost ISF-THR JHH) 1)
>> (= (assignement-cost THR-SRY MNT) 1)
>> (= (assignement-cost SRY-THR MNT) 1)
>> (= (assignement-cost THR-ISF MNT) 1)
>> (= (assignement-cost ISF-THR MNT) 1)
>> (= (duration THR-SRY MOC) 180)
>> (= (duration SRY-THR MOC) 180)
>> (= (duration THR-ISF MOC) 120)
>> (= (duration ISF-THR MOC) 120)
>> (= (duration THR-SRY JHH) 180)
>> (= (duration SRY-THR JHH) 180)
>> (= (duration THR-ISF JHH) 120)
>> (= (duration ISF-THR JHH) 120)
>> (= (duration THR-SRY MNT) 180)
>> (= (duration SRY-THR MNT) 180)
>> (= (duration THR-ISF MNT) 120)
>> (= (duration ISF-THR MNT) 120)
>> )
>> (:goal (and
>> (at MOC thr)
>> (at JHH thr)
>> (at MNT thr)
>> (assigned THR-SRY)
>> (assigned SRY-THR)
>> (assigned THR-ISF)
>> (assigned ISF-THR)
>> ))
>> (:metric minimize (total-cost))
>> )
>> ------------------------------------------------------------
>> -------------------------
>>
>> Is it possible to use OpenCog planner and Atomese to solve this problem?
>>
>> Regards,
>> Ramin
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "opencog" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> To post to this group, send email to [email protected].
>> Visit this group at https://groups.google.com/group/opencog.
>> To view this discussion on the web visit https://groups.google.com/d/ms
>> gid/opencog/CAHmauB6Wh6DEJcF_2KoCSD%2BapWaeJtkKSPCT7%
>> 2Bd5K96c_tuRnA%40mail.gmail.com
>> <https://groups.google.com/d/msgid/opencog/CAHmauB6Wh6DEJcF_2KoCSD%2BapWaeJtkKSPCT7%2Bd5K96c_tuRnA%40mail.gmail.com?utm_medium=email&utm_source=footer>
>> .
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
>
> --
> *"The problem is not that artificial intelligence will get too smart and
> take over the world," computer scientist Pedro Domingos writes, "the
> problem is that it's too stupid and already has." *
>
--
*"The problem is not that artificial intelligence will get too smart and
take over the world," computer scientist Pedro Domingos writes, "the
problem is that it's too stupid and already has." *
--
You received this message because you are subscribed to the Google Groups
"opencog" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/opencog.
To view this discussion on the web visit
https://groups.google.com/d/msgid/opencog/CAHrUA35arLRE%3DThdj4P-aUb7k83LmnxqWo0bETZ7dHQjHFWV8g%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.