Jump to content

The Principia Machina/TPC-PY/tpc yardstick.py: Difference between revisions

From The Invariance Itself
m 1 revision imported
m 1 revision imported
 
(One intermediate revision by the same user not shown)
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[
  atom order, of weight * atom, weights read from TMS CONSTANTS as doubles.
  rid]["U_C"])) from the field table (0.2.0);  NEG:t = -t;  WSUM = the sum,
  Every value is a double; -0.0 is written as 0.0.
  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 terms await the record field schema (C-16)"
   "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 becomes the only mechanical C2 line for
assumption count. The harness confirms those claims on the suite as a
FIELD terms once C-16 lands. A pass on a finite suite is evidence, not
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 "FIELD:" in base:
     for a in (base[5:].split(";") if base.startswith("WSUM:") else [base]):
         raise _Refusal("FIELD terms await the record field schema (C-16)")
        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:

Latest revision as of 02:11, 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])]