We assume the abstract definitions from earlier:
-
Types
$\mathcal{T}$ , with inheritance. -
Objects
$\mathcal{O}$ , instantiated from Types via$\tau:\mathcal{O}\to\mathcal{T}$ . -
Fields
$f(o)$ , instantiated at Objects from Type-defined FieldDefinitions. -
Flattened Field Definitions from inheritance, explicitly precomputed:
- Input-side:
$F_T^{in}$ , Output-side:$F_T^{out}$
- Input-side:
-
Relations between Types, realized as sets of object references.
-
A field update can propagate:
- Immediately (direct propagation), or
- Queued (deferred, asynchronous processing).
-
The queuing mechanism ensures:
- Updates occur in correct temporal and priority-based order.
- Updates can be grouped into discrete processing phases.
- Support for delaying updates to subsequent processing "rounds".
Define a Queue
Each event
- An Object
$o \in \mathcal{O}$ . - A Field
$f$ at object$o$ . - A numeric update value
$\Delta \in \mathbb{R}$ . - A processing phase
$p$ . - A discrete round number
$r \in \mathbb{N}$ . - A priority
$s \in \mathbb{R}$ (e.g., absolute update magnitude). - A timestamp
$t \in \mathbb{N}$ (discrete temporal ordering).
We thus formally define an event as a tuple:
Events in the Queue
Ordered by priority:
- Lowest round
$r$ first (lower rounds processed before higher rounds). - Then lowest processing phase
$p$ rank. - Then highest priority
$s$ first (larger magnitude updates processed first, hence negative sign). - Finally, earliest timestamp
$t$ .
Formally, given two events
(Lexicographic order.)
Define operations on queue
-
Add Event:
$Q \leftarrow Q \cup {e}$ -
Remove Minimum Event (highest priority):
-
$e_{\min}$ is minimal in$Q$ according to above ordering. - Remove from queue:
$Q \leftarrow Q \setminus {e_{\min}}$
-
-
Process Queue: Repeatedly remove and handle events until empty or timeout.
Given an initial field update at object
PropagateUpdateQueued(object o, field f, update Δ, phase p, round_increment):
T ← τ(o)
if |Δ| ≤ tolerance(f):
return
current_round ← current queue processing round
event_round ← current_round + (1 if round_increment else 0)
s ← |Δ| // priority based on absolute update magnitude
t ← next available timestamp
Add event (o, f, Δ, p, event_round, s, t) into Q
To process events in the queue:
ProcessQueue(Q):
while Q is not empty:
e ← remove minimal event from Q according to (r,p,-s,t)
(o, f, Δ, p, r, s, t) ← e
ApplyFieldUpdate(o, f, Δ)
Applying field update
ApplyFieldUpdate(o, f, Δ):
current_value ← f(o)
updated_value ← current_value + Δ
f(o) ← updated_value
// propagate to downstream fields using flattened outputs
Outputs ← F_{τ(o)}^{out}[f]
for each (f_target, relation r', T_target, queued, phase', round_inc) in Outputs:
related_objects ← r'(o)
for related_object in related_objects:
Δ' ← EvaluateFunction(F_{τ(related_object)}^{in}[f_target], related_object, Δ)
if queued:
PropagateUpdateQueued(related_object, f_target, Δ', phase', round_inc)
else:
if |Δ'| > tolerance(f_target):
ApplyFieldUpdate(related_object, f_target, Δ')
-
Each output connection now explicitly carries flags:
- queued (bool): whether propagation is queued or immediate.
- phase': phase for queued propagation.
- round_inc: if true, event is placed in next round.
The evaluation of input-side field function remains abstract as:
EvaluateFunction(InputDefinition, object o, incoming_update Δ):
InputDefinition = (φ, {(f_i, r_i, T_i)})
input_values = {}
for each (f_i, r_i, T_i):
related_objs = r_i(o)
input_values[f_i] ← {f_i(o') for o' in related_objs}
return φ(input_values, Δ)
| Component | Abstract Mathematical Definition |
|---|---|
| Queue |
Set of events |
| Event Processing | Remove minimal event, update fields, propagate updates |
| Queued/Immediate Propagation | Decided per output field definition, explicit flags |
| Rounds & Phases | Explicitly part of events, control processing order |
| Tolerance check | Determines if propagation continues |