The Principia Machina/TPC-PY/tpc yardstick.py: Difference between revisions
Appearance
m 1 revision imported |
TPC-PY source tpc_yardstick.py (0.2.0), SHA-256 61bc436a04c9a7a6; conformed TPS 0.4.0; PROPOSED, not declared (TPC-PY 0.2.0) |
||
| Line 23: | Line 23: | ||
TERMS, on a synthetic record (TPS 4.5.2 fields): | TERMS, on a synthetic record (TPS 4.5.2 fields): | ||
SR1 = 1 if the record fails SR1, else 0; A = a(r) (SR4, tpc_strike); | SR1 = 1 if the record fails SR1, else 0; A = a(r) (SR4, tpc_strike); | ||
S = s(r), the record's steps; NEG:t = -t; WSUM = the sum, in canonical | S = s(r), the record's steps; FIELD:U_C = float(canon_decimal(fields[ | ||
rid]["U_C"])) from the field table (0.2.0); NEG:t = -t; WSUM = the sum, | |||
in canonical atom order, of weight * atom, weights read from TMS | |||
CONSTANTS as doubles. Every value is a double; -0.0 is written as 0.0. | |||
THE FIELD TABLE (0.2.0; tpm_record_functions 0.2.0 section 10, D195 (f) | |||
at Option 1, RD-RS-35): {rid: {"U_C": canonical decimal}}, built by the | |||
caller with tpc_record field_values (an L record "0"); an argument of | |||
yardstick_key and suite["fields"] for the checks and the harness; absent | |||
when no FIELD term is used. It holds U_C alone. A record r+ that SR9 C2 | |||
builds from r carries r's row (FIELD is independent of the assumption | |||
count): the key reads a record's row from a copy of the records in which | |||
each row is placed on its record, under the key "fields". | |||
REFUSED, as ["REFUSED", reason], never raised: | REFUSED, as ["REFUSED", reason], never raised: | ||
"TMS is not well-formed" (tms_well_formed first) | "TMS is not well-formed" (tms_well_formed first) | ||
"no yardstick named <name>" | "no yardstick named <name>" | ||
"FIELD | "FIELD <ident> is not in the field table" (any FIELD but U_C) | ||
"FIELD U_C has no value for <rid>" (no row, or no canonical | |||
decimal U_C in it) | |||
"weight <c> is not a finite double" | "weight <c> is not a finite double" | ||
"a yardstick value is not finite" | "a yardstick value is not finite" | ||
| Line 36: | Line 48: | ||
WHAT A PASS MEANS. On a well-formed, FIELD-free yardstick the grammar | WHAT A PASS MEANS. On a well-formed, FIELD-free yardstick the grammar | ||
already guarantees C1 (SR1 first) and C4 (fixed resolution), and static C2 | already guarantees C1 (SR1 first) and C4 (fixed resolution), and static C2 | ||
decides C2 for SR1, A and S exactly. The harness confirms those claims on | decides C2 for SR1, A and S exactly, FIELD being independent of the | ||
the suite as a regression test; it | assumption count. The harness confirms those claims on the suite as a | ||
FIELD terms | regression test; it is the only mechanical C2 line for FIELD terms. A pass on a finite suite is evidence, not | ||
proof (TPS 4.5.2). | proof (TPS 4.5.2). | ||
""" | """ | ||
| Line 48: | Line 60: | ||
import tpc_zone as Z | import tpc_zone as Z | ||
TPC_YARDSTICK_VERSION = "0.1.0 | TPC_YARDSTICK_VERSION = "0.2.0" # increment 12 (S95: one MINOR bump over the declared 0.1.0): FIELD:U_C by the field table; 0.1.1 C-MS-5 | ||
| Line 61: | Line 73: | ||
neg = c.startswith("NEG:") | neg = c.startswith("NEG:") | ||
base = c[4:] if neg else c | base = c[4:] if neg else c | ||
if " | for a in (base[5:].split(";") if base.startswith("WSUM:") else [base]): | ||
raise _Refusal("FIELD | a = a.split("*", 1)[1] if base.startswith("WSUM:") else a | ||
if a.startswith("FIELD:") and a != "FIELD:U_C": | |||
raise _Refusal(Z._show("FIELD " + a[6:] + " is not in the field table")) | |||
if base.startswith("WSUM:"): | if base.startswith("WSUM:"): | ||
parts = [] | parts = [] | ||
| Line 81: | Line 95: | ||
if atom == "A": | if atom == "A": | ||
return float(S.a_of_r(rid, records, tfk)) | return float(S.a_of_r(rid, records, tfk)) | ||
if atom == "FIELD:U_C": | |||
row = r.get("fields") | |||
v = row.get("U_C") if type(row) is dict else None | |||
if type(v) is not str or Z.canon_decimal(v) != v: | |||
raise _Refusal(Z._show("FIELD U_C has no value for " + rid)) | |||
return float(v) | |||
return float(r["steps"]) # "S" | return float(r["steps"]) # "S" | ||
| Line 121: | Line 141: | ||
def yardstick_key(tms, name, rid, records, tfk_assumptions=()): | def _placed(records, fields): | ||
"""["OK", [values]] for one record, or ["REFUSED", reason].""" | """A copy of the records with each field-table row placed on its record | ||
under "fields" (none when the table has no row for it).""" | |||
out = {} | |||
for rid, r in records.items(): | |||
c = dict(r) | |||
c.pop("fields", None) | |||
if type(fields) is dict and rid in fields: | |||
c["fields"] = fields[rid] | |||
out[rid] = c | |||
return out | |||
def yardstick_key(tms, name, rid, records, tfk_assumptions=(), fields=None): | |||
"""["OK", [values]] for one record, or ["REFUSED", reason]. fields: the | |||
field table (0.2.0), None when no FIELD term is used.""" | |||
try: | try: | ||
key, _, _ = _build(tms, name) | key, _, _ = _build(tms, name) | ||
return ["OK", list(key(rid, records, list(tfk_assumptions)))] | return ["OK", list(key(rid, _placed(records, fields), list(tfk_assumptions)))] | ||
except _Refusal as e: | except _Refusal as e: | ||
return ["REFUSED", str(e)] | return ["REFUSED", str(e)] | ||
| Line 132: | Line 166: | ||
def yardstick_checks(tms, name, suite): | def yardstick_checks(tms, name, suite): | ||
"""["OK", C1, C2, C4] with each check's full result from tpc_sr9 (the | """["OK", C1, C2, C4] with each check's full result from tpc_sr9 (the | ||
witnesses CAC's refusal names), or ["REFUSED", reason].""" | witnesses CAC's refusal names), or ["REFUSED", reason]. suite["fields"] | ||
is the field table (0.2.0), absent when no FIELD term is used.""" | |||
try: | try: | ||
entry = _build(tms, name) | entry = _build(tms, name) | ||
suite = dict(suite, records=_placed(suite["records"], suite.get("fields"))) | |||
return ["OK", C.sr9_c1(entry, suite), C.sr9_c2(entry, suite), C.sr9_c4(entry, suite)] | return ["OK", C.sr9_c1(entry, suite), C.sr9_c2(entry, suite), C.sr9_c4(entry, suite)] | ||
except _Refusal as e: | except _Refusal as e: | ||
Revision as of 02:10, 30 September 2026
# -*- coding: utf-8 -*-
"""
TPC-PY --- the yardstick evaluator (TPC step 2, increment 5)
============================================================
Compiles a yardstick declared in a UWC's TMS (the closed grammar of
D100.1; tpm_zone_schemas 0.2.0 section 4) into the SR9 executable-entry
interface, and runs SR9 C1, C2, C4 on the synthetic record suite. This is
the second line behind the static checks tms_well_formed makes at entry:
TPS 4.5 row 17, MECHANICAL when the entry is executable. Standard library
only; Python 3.7+; Windows/Linux.
WHAT IT BUILDS, from one named yardstick of a well-formed TMS:
key(rid, records, tfk) the KEY evaluated on the record, lexicographic,
lower is closer; a record whose DOMAIN equals a
LIMITING DOMAIN (after text normalization) is
keyed by that limiting KEY instead;
resolve FIXED to the framework: SR7 for an L-M pair, SR5
on the key otherwise (D100.1: a yardstick orders,
it never resolves);
limiting the declared LIMITING DOMAINs, where SR9 C2
exempts a lowered key.
TERMS, on a synthetic record (TPS 4.5.2 fields):
SR1 = 1 if the record fails SR1, else 0; A = a(r) (SR4, tpc_strike);
S = s(r), the record's steps; FIELD:U_C = float(canon_decimal(fields[
rid]["U_C"])) from the field table (0.2.0); NEG:t = -t; WSUM = the sum,
in canonical atom order, of weight * atom, weights read from TMS
CONSTANTS as doubles. Every value is a double; -0.0 is written as 0.0.
THE FIELD TABLE (0.2.0; tpm_record_functions 0.2.0 section 10, D195 (f)
at Option 1, RD-RS-35): {rid: {"U_C": canonical decimal}}, built by the
caller with tpc_record field_values (an L record "0"); an argument of
yardstick_key and suite["fields"] for the checks and the harness; absent
when no FIELD term is used. It holds U_C alone. A record r+ that SR9 C2
builds from r carries r's row (FIELD is independent of the assumption
count): the key reads a record's row from a copy of the records in which
each row is placed on its record, under the key "fields".
REFUSED, as ["REFUSED", reason], never raised:
"TMS is not well-formed" (tms_well_formed first)
"no yardstick named <name>"
"FIELD <ident> is not in the field table" (any FIELD but U_C)
"FIELD U_C has no value for <rid>" (no row, or no canonical
decimal U_C in it)
"weight <c> is not a finite double"
"a yardstick value is not finite"
WHAT A PASS MEANS. On a well-formed, FIELD-free yardstick the grammar
already guarantees C1 (SR1 first) and C4 (fixed resolution), and static C2
decides C2 for SR1, A and S exactly, FIELD being independent of the
assumption count. The harness confirms those claims on the suite as a
regression test; it is the only mechanical C2 line for FIELD terms. A pass on a finite suite is evidence, not
proof (TPS 4.5.2).
"""
import math
import tpc_sr9 as C
import tpc_strike as S
import tpc_zone as Z
TPC_YARDSTICK_VERSION = "0.2.0" # increment 12 (S95: one MINOR bump over the declared 0.1.0): FIELD:U_C by the field table; 0.1.1 C-MS-5
class _Refusal(Exception):
pass
def _compile_term(t, weights):
"""A canonical term -> (neg, base, parts): parts is the canonical WSUM
list of (weight, atom), or None for a bare atom."""
c = Z.canonical_term(Z._text(t))
neg = c.startswith("NEG:")
base = c[4:] if neg else c
for a in (base[5:].split(";") if base.startswith("WSUM:") else [base]):
a = a.split("*", 1)[1] if base.startswith("WSUM:") else a
if a.startswith("FIELD:") and a != "FIELD:U_C":
raise _Refusal(Z._show("FIELD " + a[6:] + " is not in the field table"))
if base.startswith("WSUM:"):
parts = []
for wt in base[5:].split(";"):
name, atom = wt.split("*", 1)
w = float(Z.canon_decimal(weights[name]))
if not math.isfinite(w):
raise _Refusal("weight " + name + " is not a finite double")
parts.append((w, atom))
return neg, "WSUM", parts
return neg, base, None
def _atom(atom, rid, records, tfk):
r = records[rid]
if atom == "SR1":
return 1.0 if r["sr1_fail"] else 0.0
if atom == "A":
return float(S.a_of_r(rid, records, tfk))
if atom == "FIELD:U_C":
row = r.get("fields")
v = row.get("U_C") if type(row) is dict else None
if type(v) is not str or Z.canon_decimal(v) != v:
raise _Refusal(Z._show("FIELD U_C has no value for " + rid))
return float(v)
return float(r["steps"]) # "S"
def _value(term, rid, records, tfk):
neg, base, parts = term
if parts is None:
v = _atom(base, rid, records, tfk)
else:
v = 0.0
for w, atom in parts:
v = v + w * _atom(atom, rid, records, tfk)
if neg:
v = -v
v = v + 0.0 # -0.0 -> 0.0
if not math.isfinite(v):
raise _Refusal("a yardstick value is not finite")
return v
def _build(tms, name):
"""The SR9 entry tuple for one named yardstick, or a _Refusal."""
if not Z.tms_well_formed(tms)[0]:
raise _Refusal("TMS is not well-formed")
ys = [y for y in tms.get("YARDSTICKS", []) if y.get("NAME") == name]
if not ys:
raise _Refusal(Z._show("no yardstick named " + name))
y = ys[0]
weights = dict((c["NAME"], c["VALUE"]) for c in tms.get("CONSTANTS", []))
main = [_compile_term(t, weights) for t in y["KEY"]]
lim = {}
for le in y["LIMITING"]:
lim[Z._text(le["DOMAIN"])] = [_compile_term(t, weights) for t in le["KEY"]]
def key(rid, records, tfk):
terms = lim.get(Z._text(records[rid]["domain"]), main)
return tuple(_value(t, rid, records, tfk) for t in terms)
return (key, C._resolve_regime_aware(key), sorted(lim))
def _placed(records, fields):
"""A copy of the records with each field-table row placed on its record
under "fields" (none when the table has no row for it)."""
out = {}
for rid, r in records.items():
c = dict(r)
c.pop("fields", None)
if type(fields) is dict and rid in fields:
c["fields"] = fields[rid]
out[rid] = c
return out
def yardstick_key(tms, name, rid, records, tfk_assumptions=(), fields=None):
"""["OK", [values]] for one record, or ["REFUSED", reason]. fields: the
field table (0.2.0), None when no FIELD term is used."""
try:
key, _, _ = _build(tms, name)
return ["OK", list(key(rid, _placed(records, fields), list(tfk_assumptions)))]
except _Refusal as e:
return ["REFUSED", str(e)]
def yardstick_checks(tms, name, suite):
"""["OK", C1, C2, C4] with each check's full result from tpc_sr9 (the
witnesses CAC's refusal names), or ["REFUSED", reason]. suite["fields"]
is the field table (0.2.0), absent when no FIELD term is used."""
try:
entry = _build(tms, name)
suite = dict(suite, records=_placed(suite["records"], suite.get("fields")))
return ["OK", C.sr9_c1(entry, suite), C.sr9_c2(entry, suite), C.sr9_c4(entry, suite)]
except _Refusal as e:
return ["REFUSED", str(e)]
def yardstick_harness(tms, name, suite):
"""["OK", C1 pass, C2 pass, C4 pass, total violations] for the CAC
gate, or ["REFUSED", reason]."""
r = yardstick_checks(tms, name, suite)
if r[0] != "OK":
return r
c1, c2, c4 = r[1], r[2], r[3]
return ["OK", c1[0], c2[0], c4[0], len(c1[1]) + len(c2[1]) + len(c4[1])]