ModelDeliberationResultsDiscussion
Too Many Chefs · Levels 1–3 · Xun Sun · 35389338
PAUSED · P
FIT5222 · Assignment 2

Too Many
Chefs

Levels 1–3
Xun Sun 35389338
1Describe the kitchen in PDDL → 2Pick the orders worth cooking → 3Let the simulator choose a plan → 4Hand the steps to the chefs
Model · what matters

What does the kitchen need the model to know?

Level 1 · one chef, cheeseburger from scratch
Tilesstorage · cutboard · pan · counter · delivery
Level 2 · four chefs, floor cut into four
Food crosses only over a counter
Left out on purpose
🚶
Walking

the framework moves chefs; the model keeps only can_reach

⏱
Time

PDDL has no clock; I judge timing by running the plan

Three kinds of things
🧑‍🍳Chefs
who act; every action names one
🍳Tiles
counters, stations, storages, bins, delivery
🍰Items
food, plates, and tools like a bowl

State

what each chef holds · what is on each tile · what is inside each station · which orders are open

Rules

Recipes: food changes only at the right station. Level 3 adds:

🔥 pans burn ① ② orders in turn 🍽 plates run out, come back dirty 🧱 floor cut in half

Goal  (served ?order) for the orders I choose

The planner chooses the actions and their order. Timing is checked by running the plan in the simulator.
Model · the domain

The domain follows straight from that

Types
object location item chef order count food plate tool bowl off its base c0 → c1 → … every action names its chef
Level 3 rules as predicates
🔥Burningburns · safe_station
①②Serve in turnorder_turn · order_next
🍽Plate dispenserdispenser_count
c3 → c2 → c1 → c0
(:action put_in_station
  :parameters (?chef - chef ?food - food
               ?location - location)
  :precondition (and
    (can_reach ?chef ?location)
    (holding ?chef ?food)
    (station_empty ?location)
    (accepts ?location ?food)
    (safe_station ?location))
  :effect (and
    (hand_empty ?chef)
    (in_station ?food ?location)
    (not (holding ?chef ?food))
    (not (station_empty ?location))))

can_reach · the chef can stand next to it; walking is gone

holding · what is in the chef's hand

station_empty · accepts · the recipe structure

safe_station · a Level 3 rule, written as a fact

effects: the food moves from the hand into the station

Plates by state, not by identity

empty_plate · dirty_plate · plated_<dish>

A tile holds one item, so this is enough, and the model stays small.

Actions by group
0
Fetch and carry8

take_from_storage · take_plate · pick_up · place_* · mount_tool · lift_station

Use a station7

put_in_station · pour_into_station · cook · grill_onto_plate · …

Plate up5

add_to_plate · station_to_plate · storage_to_plate · …

Clean up4

wash_plate · bin_food · bin_from_plate · clear_station

Deliver1

deliver

STRIPS + typing
so it runs on Fast Downward 26.2 (Helmert, 2006), the planner on the contest server.
Deliberation · the loop

How the kitchen becomes a plan, then commands

The kitchen

right now

to_pddl

pick the orders, write the kitchen as a problem file, in a few versions

problem files × N

Fast Downward

one plan per version

2 s each

Rollout

run each plan in a copy of the simulator, no screen

from_pddl

share the best plan out between the chefs, turn it into simulator commands

1
2
3
4
planned_orders(env)
score, scored_at = simulate(env, plan)
best: most points, then soonest
tidy → schedule ×6
→ depend
commands → the chefs act in the real kitchen
🔁 Replan when a new order comes in an order expires nothing changed for 30 checks the last one is how I notice the plan is done, or stuck
Deliberation · goal reasoning

Picking the goal, on one real kitchen

🍰
Black forest cake
+50 · due t120
🍔
Cheeseburger
+50 · due t195
no meat
🍰
Black forest cake
+50 · due t195
🍰
Black forest cake
+50 · due t195
🍰
Black forest cake
+50 · due t230
no plate left
🍔
Hamburger
+50 · due t260
no meat
🥩 no meat in any storage 🍒 4 loose cherries only 🍽 3 plates, no dispenser
1

FilterCheck each recipe against the food that is really there. One impossible goal would leave no plan at all.

2

CapEach delivery takes a plate away until the next replan, so plan at most as many orders as plates.

3

ChooseNo dispenser: the plates are the budget for the whole level. most_valuable tries the combinations the food can make together, keeps the one that pays most.

this kitchen
t0plates3served0/3
3rd plate out → kitchen goes quiet → 30 checks → replan: no plates, empty goal
(:objects …  order_0 order_1 order_2 order_end - order)
(:init …
  (order_dish order_0 plated_catalog_food_black_forest_cake)
  (order_turn order_0)  (order_next order_0 order_end)
  (may_serve chef_chef_1_2 order_0)  …)
(:goal (and
  (served order_0)
  (served order_1)
  (served order_2)))
Deliberation · candidates

Steps are not time, so I write the problem several ways

What the planner sees
pan pan 🧑‍🍳
put_in_station · 1 step2 tiles of walking
put_in_station · 1 step9 tiles of walking

To the planner these cost the same.
So I write the kitchen several ways, and let the simulator judge.

Kitchen 3-1 layout, four cakes · first plan
real rollout · points · finished
Plate storage food only near its storage248 · t271
Plate storage food anywhere127 · t198
Each chef keeps to its closest tiles ★ best248 · t216
Most urgent order first, the rest added248 · t226
Closest tiles + build dishes on a counter248 · t228
Urgent first + build dishes on a counter248 · t239
+ 4 random copies with some counters and plates removed (no better plan this time)
rank: most points, then soonestthe real run finished its fourth cake at t216
Fast Downward solves each version in at most 2 s. The simulator run shows how long each plan really takes, and the best one is kept.
Deliberation · execution

One plan step, traced all the way to commands

plan step ▸ (grill_onto_plate chef_chef_1_2 catalog_food_meat loc_1_0 catalog_food_grilled_meat loc_2_0 plated_catalog_food_bun plated_catalog_food_hamburger)
Level 3 · the pan burns · loc_1_0 = pan, loc_2_0 = counter
① Combine at the panput the meat in
② PickUp at the counterexpect a plate holding a bun
③ Combine at the panexpect grilled meat → scoop
t0
If the kitchen doesn't match what a command expects, the command is illegal. The chef waits, nothing changes, and 30 checks later I replan from what is really there.
1
Who does it

Cut the plan into jobs, empty hands to empty hands. Each goes to the chef who can start it soonest. Six ways; the rollout picks.

chef 1chef 2 grill_onto_plate
2
When

An empty pan before someone's turn looks the same as after it. A step that puts something into a place waits for the earlier step there.

chef 2 · scoop from pan chef 1 · meat into pan waits

Action dependency graph, after Hönig et al. (2019)

3The commandsone step becomes three
elif step.name == "grill_onto_plate":
    put = Combine(chef, expected_held_food=meat)
    pick = PickUp(chef, expected_input_name=PLATE_NAME)
    scoop = Combine(chef,
        expected_target_equipment_contents_name=grilled_meat)
    return [put @ pan, pick @ counter, scoop @ pan]
Results

Did it work? Full marks on every hidden level

Level 1
Level 2
Level 3
0 / 637 pts
10 / 10 marks
0 / 1567 pts
15 / 15 marks
0 / 3291 pts
25 / 25 marks
LEVEL 3 MARKS OVER MY SUBMISSIONS 25 21.9 22.5 23.45 24.26 24.73 25.0 3-12 3-1 3-11

The maximum is each order's reward plus its tips, worked out from the rules. Full marks means every available point was collected.

The last 1.5 marks of Level 3 came from fixing three kitchens, marked on the chart.

Discussion · where it broke
3-13-113-12

Three kitchens that held Level 3 back

Kitchen 3-1 layout · four cakes, now with trim
t0served0/4
cake 1 cake 2 cake 3 cake 4 | = due● = served
The first plan Fast Downward finds can contain steps that undo each other. trim removes them before the chefs start.
Symptom

Four cakes. Three went out; the fourth always just missed its deadline.

Cause

The plans were valid, but wasteful. The first plan found did this:

pour_into_station batter → oventake_from_station batter ← ovenpour_into_station batter → ovencook batter → cake
Fix · trim
175→175
served = run(domain, facts, steps)  # orders this plan serves
index = 0
while index < len(steps):
    kept = shorter({index})          # replay without step index
    if kept is not None:             # every order still served?
        steps, index = kept, 0       # keep it out, start again
    else:
        index += 1
Discussion · where it broke
3-13-113-12

Three kitchens that held Level 3 back

Kitchen 3-11 layout · six orders, three plates
plates left3served0
Without a plate dispenser, plates never come back, so I choose the orders before planning.
Symptom

Six orders, three plates, no dispenser. Three went out, then it stopped at 212 of 248.

Cause

The plans were fine, but the goal was not: most-urgent-first used the last cherries on cheaper orders.

most urgent first212
most valuable first248
Fix · most_valuable
212→212
def visit(left, stock, chosen, total):
    if (total, len(chosen)) > best_key: best = chosen   # pays most
    if len(chosen) == plates: return                    # budget spent
    for name in dishes_left_by_deadline:
        trial = dict(stock)
        if _make(name, trial):          # food left after this dish?
            visit(rest, trial, chosen + [name], total + reward)
Discussion · where it broke
3-13-113-12

Three kitchens that held Level 3 back

Kitchen 3-12 layout · bowl in the wrong room
t0served0/4
Carry the bowl of dubious food to the bin
Empty it, put the bowl down
lift_station · pick the empty bowl up as a tool
Hand it over the counter
mount_tool · back on the mixer
The model had no action for picking up an emptied bowl that was off its base. lift_station adds it.
Symptom

Four cakes, none delivered. The planner found no plan.

Cause
bowl + food

a place (station)

→
emptied bowl

still a place

✕
a tool

a thing to carry

Nothing could lift the emptied bowl back onto the mixer, so no goal was reachable.

Fix · one new action
131→131
(:action lift_station
  :parameters (?chef - chef ?tool - tool ?location - location)
  :precondition (and (can_reach ?chef ?location) (hand_empty ?chef)
                     (lifts ?location ?tool)
                     (station_empty ?location))
  :effect (and (holding ?chef ?tool) (counter_empty ?location)
               (not (lifts ?location ?tool)) …))
Discussion · verdict

My verdict, and what I would change

Verdict

The approach worked: plain STRIPS for the kitchen, and simulator rollouts to judge timing.

✓

Full marks on every level, within the time limit.

✓

Each failure came from a gap in my model, not from the planner.

What I would change
1

Make walking the action cost

evidence: candidate scores

The planner counts steps, so a far station looks as good as a near one. I work around it with several problem versions and rollouts; on the 3-1 layout they ranged from 127 to 248 points. With walking distance as the action cost, the planner would prefer nearby work itself.

2

Count scarce food, like plates

evidence: 3-11

Plates already count down through count objects. Cherries could do the same, so the planner itself would refuse to spend the last one.

3

Keep the trim step

evidence: 3-1

It turned valid plans into fast ones: 3-1 went from three cakes to four.

Thank you

Xun Sun 35389338
Sources

Helmert, M. (2006). The Fast Downward planning system. JAIR 26 · Hönig, W., Kiesel, S., Tinka, A., Durham, J. W., Ayanian, N. (2019). Persistent and robust execution of MAPF schedules in warehouses (action dependency graphs). IEEE RA-L · Topcuoglu, H., Hariri, S., Wu, M.-Y. (2002). HEFT list scheduling. IEEE TPDS · Too Many Chefs simulator and kitchen guide, FIT5222, Monash University.