Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions specifications/deli/deli.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
SPECIFICATION Spec

CONSTANT
Processes = {p1, p2, p3}
Null = null

INVARIANT TypeOK
INVARIANT ValidStates
INVARIANT MutualExclusion

PROPERTY EventuallyIdle
99 changes: 99 additions & 0 deletions specifications/deli/deli.tla
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
-------------------------------- MODULE deli --------------------------------
(***************************************************************************)
(* A specification of a deli ordering system with a ticket-queue model. *)
(* Customers arrive (TakeOrder), get assigned to a worker who prepares *)
(* their order (PrepareOrder), then the order is served (Serve), and the *)
(* system returns to Idle (ReturnToIdle) to process the next customer. *)
(***************************************************************************)

EXTENDS Naturals, Sequences

CONSTANTS Processes, Null
Comment thread
EricSpencer00 marked this conversation as resolved.
Outdated

VARIABLES ticket, worker, customer, state, orderQueue

(***************************************************************************)
(* State variables: *)
(* - ticket: increasing counter issued to arriving customers *)
(* - worker: the current worker serving an order, or Null if idle *)
(* - customer: the current customer being served, or Null if idle *)
(* - state: the system's current phase: *)
(* (Idle | TakingOrder | PreparingOrder | Serving) *)
(* - orderQueue: sequence of customers waiting to be served *)
(***************************************************************************)

TypeOK ==
/\ ticket \in Nat
/\ worker \in Processes \cup {Null}
/\ customer \in Processes \cup {Null}
/\ state \in {"Idle", "TakingOrder", "PreparingOrder", "Serving"}
/\ orderQueue \in Seq(Processes)

Init ==
/\ ticket = 0
/\ worker = Null
/\ customer = Null
/\ state = "Idle"
/\ orderQueue = <<>>

(* Customer arrives, gets a ticket number, and joins the queue *)
TakeOrder ==
/\ state = "Idle"
/\ \E c \in Processes :
/\ ticket' = ticket + 1
/\ orderQueue' = Append(orderQueue, c)
/\ state' = "TakingOrder"
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ticket is incremented in TakeOrder, but the ticket value is never associated with a particular customer/order (the queue stores only c). This makes the "ticket-queue" aspect described in the header/comment misleading and leaves ticket effectively unused beyond counting arrivals. Consider either incorporating the ticket into orderQueue (e.g., enqueue a record/pair) or removing ticket and updating the description accordingly.

Copilot uses AI. Check for mistakes.
/\ UNCHANGED <<worker, customer>>

(* The next customer from the queue is called and a worker is assigned *)
PrepareOrder ==
/\ state = "TakingOrder"
/\ Len(orderQueue) > 0
Comment thread
EricSpencer00 marked this conversation as resolved.
Outdated
/\ LET c == Head(orderQueue) IN
/\ \E w \in Processes :
/\ customer' = c
/\ worker' = w
/\ orderQueue' = Tail(orderQueue)
/\ state' = "PreparingOrder"
/\ UNCHANGED ticket

(* The assigned worker serves the current customer *)
Serve ==
/\ state = "PreparingOrder"
/\ state' = "Serving"
/\ UNCHANGED <<ticket, worker, customer, orderQueue>>

(* Customer is served, worker and customer reset, ready for the next order *)
ReturnToIdle ==
/\ state = "Serving"
/\ state' = "Idle"
/\ worker' = Null
/\ customer' = Null
/\ UNCHANGED <<ticket, orderQueue>>

Next ==
TakeOrder \/ PrepareOrder \/ Serve \/ ReturnToIdle

(* Safety: System stays in one of the allowed states *)
ValidStates ==
state \in {"Idle", "TakingOrder", "PreparingOrder", "Serving"}

(* Safety: At most one customer is being served at any given time *)
MutualExclusion ==
(state = "Idle") => (customer = Null /\ worker = Null)
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MutualExclusion doesn't match its comment/name: it only asserts that when state = "Idle" then customer and worker are Null. This doesn't express mutual exclusion (and with a single customer variable, exclusivity is otherwise trivially satisfied). Consider either renaming the predicate/comment to reflect what it checks, or strengthening it to capture the intended safety property (e.g., relating state to whether customer/worker are Null).

Suggested change
(* Safety: At most one customer is being served at any given time *)
MutualExclusion ==
(state = "Idle") => (customer = Null /\ worker = Null)
(* Safety: The system is idle iff there is no active customer or worker *)
MutualExclusion ==
(state = "Idle") <=> (customer = Null /\ worker = Null)

Copilot uses AI. Check for mistakes.
Comment thread
EricSpencer00 marked this conversation as resolved.
Outdated

(* Liveness: The system eventually returns to Idle (progress) *)
EventuallyIdle ==
<> (state = "Idle")
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EventuallyIdle == <> (state = "Idle") is vacuously true because Init already sets state = "Idle", so the liveness property doesn't actually check that the system returns to idle after taking an order. If the intent is progress, consider a stronger temporal property (e.g., []<>(state = "Idle") or a leads-to property from non-idle states) and add fairness assumptions as needed.

Suggested change
(* Liveness: The system eventually returns to Idle (progress) *)
EventuallyIdle ==
<> (state = "Idle")
(* Liveness: The system returns to Idle infinitely often (progress) *)
EventuallyIdle ==
[]<> (state = "Idle")

Copilot uses AI. Check for mistakes.

Spec ==
Init /\ [][Next]_<<ticket, worker, customer, state, orderQueue>>

(* Theorems *)
THEOREM Spec => []TypeOK
THEOREM Spec => []ValidStates
THEOREM Spec => []MutualExclusion
THEOREM Spec => EventuallyIdle

=============================================================================

21 changes: 21 additions & 0 deletions specifications/deli/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"sources": [],
"authors": [
"Eric Spencer"
],
"tags": [],
"modules": [
{
"path": "specifications/deli/deli.tla",
"features": [],
"models": [
{
"path": "specifications/deli/deli.cfg",
"runtime": "00:00:05",
"mode": "exhaustive search",
"result": "success"
}
]
}
]
}
Loading