TOMK / src /python /tom_world03 /transitions.py
c0mbatduckzz's picture
Publish WQK 0.6 formal specification, use cases and verified release (part 2)
767a051 verified
Raw History Blame Contribute Delete
4.33 kB
"""Deterministic simultaneous-event transition merge and conflict rejection."""
from __future__ import annotations
from collections import defaultdict
from typing import Any, Mapping
from .canonical import attach_hash
from .model import IntervalWorld, Relation, TransitionOp
from .rational import Q
class TransitionConflict(ValueError):
pass
def _qrecord_map(state: Mapping[str, Q]) -> dict[str, dict[str, int]]:
return {name: value.to_record() for name, value in sorted(state.items())}
def merge_transition_ops(relations: list[Relation]) -> tuple[list[dict[str, Any]], dict[str, tuple[str, Q]]]:
grouped: dict[str, list[tuple[Relation, TransitionOp]]] = defaultdict(list)
for relation in relations:
for operation in relation.transition:
grouped[operation.field].append((relation, operation))
merged: dict[str, tuple[str, Q]] = {}
audit: list[dict[str, Any]] = []
for field in sorted(grouped):
items = grouped[field]
modes = {operation.mode for _, operation in items}
if len(modes) != 1:
raise TransitionConflict(
f"simultaneous transition conflict on {field}: mixed modes {sorted(modes)}"
)
mode = next(iter(modes))
values = [operation.value for _, operation in items]
if mode == "set":
if any(value != values[0] for value in values[1:]):
raise TransitionConflict(f"simultaneous set conflict on {field}")
value = values[0]
elif mode == "add":
value = sum(values, Q(0))
elif mode == "xor":
accumulator = 0
for item in values:
accumulator ^= item.as_integer()
value = Q(accumulator)
else: # pragma: no cover - validated upstream.
raise AssertionError(mode)
merged[field] = (mode, value)
audit.append({
"field": field,
"mode": mode,
"merged_value": value.to_record(),
"contributors": [
{
"relation_id": relation.id,
"event_id": relation.event_id,
"priority": relation.priority,
"value": operation.value.to_record(),
}
for relation, operation in items
],
})
return audit, merged
def apply_event_set(world: IntervalWorld, event_set: Mapping[str, Any]) -> dict[str, Any]:
if event_set.get("schema") != "TOM-NEXT-EVENT-SET-0.3" or event_set.get("status") != "accepted":
raise ValueError("apply_event_set requires an accepted TOM-NEXT-EVENT-SET-0.3 certificate")
event_time = Q.from_value(event_set["event_time"])
by_id = {relation.id: relation for relation in world.relations}
relation_ids = [str(value) for value in event_set.get("relation_order", [])]
try:
relations = [by_id[ident] for ident in relation_ids]
except KeyError as exc:
raise ValueError(f"event set references unknown relation {exc.args[0]}") from exc
pre_state = world.trajectory.state_at(event_time)
audit, merged = merge_transition_ops(relations)
post_state = dict(pre_state)
for field, (mode, value) in merged.items():
current = post_state.get(field, Q(0))
if mode == "set":
post_state[field] = value
elif mode == "add":
post_state[field] = current + value
elif mode == "xor":
post_state[field] = Q(current.as_integer() ^ value.as_integer())
else: # pragma: no cover
raise AssertionError(mode)
return attach_hash({
"schema": "TOM-SIMULTANEOUS-TRANSITION-0.3",
"world_hash": world.content_hash,
"event_set_hash": event_set.get("content_hash"),
"event_time": event_time.to_record(),
"event_order": list(event_set.get("event_order", [])),
"merge_policy": {
"set": "all simultaneous values must be equal",
"add": "exact rational sum",
"xor": "integer xor",
"mixed_modes": "reject",
"application_basis": "all operations read the common pre-event state",
},
"pre_state": _qrecord_map(pre_state),
"merged_operations": audit,
"post_state": _qrecord_map(post_state),
})