518 lines
34 KiB
Python
518 lines
34 KiB
Python
#!/usr/bin/env python3
|
|
"""Audit saved reduced-surface algebra; a reduced gate is not a full solve.
|
|
|
|
No FEM action, preparation, or physical quadrature is independently repeated.
|
|
The dual residual restriction is checked against the physical basis and saved
|
|
normalization, rather than assumed to be the state injection's transpose.
|
|
"""
|
|
import argparse
|
|
import json
|
|
import math
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
from audit_shape_field_weak import (Audit, EPS, RTOL, checked_einsum as einsum,
|
|
digest, finite, integer, layout, near, norm,
|
|
np, rows, table, vector, vector_near)
|
|
from analyze_shape_surface_modes import harmonics
|
|
|
|
P = "reduced_surface_"
|
|
MAPS = ("basis_physical", "state_basis", "residual_basis", "state_transform", "residual_transform")
|
|
VECTORS = ("base", "physical_base", "residual", "direction", "physical_direction", "action", "defect",
|
|
"state_factors", "residual_factors", "reduced_residual", "reduced_direction", "reduced_action",
|
|
"reduced_defect", "excluded_residual", "excluded_defect", "restored_residual", "restored_action")
|
|
ALPHAS = (1., .25, .0625, 1 / 1024)
|
|
|
|
|
|
def matrix(path):
|
|
with Path(path).open() as stream:
|
|
dimensions = [int(x) for x in stream.readline().split()]
|
|
values = np.loadtxt(stream, ndmin=1)
|
|
if len(dimensions) != 2 or min(dimensions) <= 0 or values.ndim != 1 or values.size != math.prod(dimensions) or not np.isfinite(values).all():
|
|
raise ValueError(f"Invalid finite row-major matrix: {path}")
|
|
return values.reshape(dimensions)
|
|
|
|
|
|
def close_array(audit, label, actual, expected, scale=0.):
|
|
audit.check(label, vector_near(np.asarray(actual).ravel(), np.asarray(expected).ravel(), scale))
|
|
|
|
|
|
class Coordinates:
|
|
def __init__(self, summary, maps):
|
|
self.n = integer(summary["full_size"])
|
|
self.s = integer(summary["shape_size"])
|
|
self.k = integer(summary["mode_count"])
|
|
self.vo = integer(summary["shape_value_offset"])
|
|
self.ro = integer(summary["shape_residual_offset"])
|
|
self.identity = summary["identity_control"] == 1
|
|
self.maps = maps
|
|
if not (0 < self.k <= self.s <= self.n and 0 <= self.vo <= self.n - self.s and 0 <= self.ro <= self.n - self.s):
|
|
raise ValueError("Invalid coordinate dimensions")
|
|
|
|
def restrict(self, values, residual=True):
|
|
if self.identity:
|
|
return values.copy()
|
|
offset = self.ro if residual else self.vo
|
|
basis = self.maps["residual_basis" if residual else "state_basis"]
|
|
middle = einsum("ij,i->j", basis, values[offset:offset + self.s])
|
|
return np.concatenate((values[:offset], middle, values[offset + self.s:]))
|
|
|
|
def inject(self, values, residual=False):
|
|
if self.identity:
|
|
return values.copy()
|
|
offset = self.ro if residual else self.vo
|
|
basis = self.maps["residual_basis" if residual else "state_basis"]
|
|
middle = einsum("ij,j->i", basis, values[offset:offset + self.k])
|
|
return np.concatenate((values[:offset], middle, values[offset + self.k:]))
|
|
|
|
def excluded(self, values):
|
|
return values - self.inject(self.restrict(values), residual=True)
|
|
|
|
def validate(self, factors, residual_factors, audit):
|
|
if self.identity:
|
|
audit.check("identity:full_mode_count", self.k == self.s)
|
|
return
|
|
b, px, qf, tx, tf = (self.maps[k] for k in MAPS)
|
|
audit.check("maps:dimensions", b.shape == px.shape == qf.shape == (self.s, self.k) and tx.shape == tf.shape == (self.k, self.k))
|
|
sx = factors[self.vo:self.vo + self.s]
|
|
rf = residual_factors[self.ro:self.ro + self.s]
|
|
close_array(audit, "maps:state_QR", sx[:, None] * b, einsum("ij,jk->ik", px, tx))
|
|
close_array(audit, "maps:dual_QR", b / rf[:, None], einsum("ij,jk->ik", qf, tf))
|
|
for name, basis, transform in (("state", px, tx), ("residual", qf, tf)):
|
|
close_array(audit, "maps:" + name + "_orthonormal", einsum("ij,ik->jk", basis, basis), np.eye(self.k))
|
|
close_array(audit, "maps:" + name + "_triangular", np.tril(transform, -1), np.zeros((self.k, self.k)), norm(transform.ravel()))
|
|
audit.check("maps:" + name + "_nonsingular", np.all(np.abs(np.diag(transform)) > 64 * EPS * max(norm(transform.ravel()), 1e-300)))
|
|
|
|
|
|
def basis_package(folder, coords, physical_base, required, audit):
|
|
first = folder / (P + "basis_raw.txt")
|
|
if not first.exists():
|
|
raise ValueError("Missing physical harmonic basis package")
|
|
def get(name):
|
|
path = folder / (P + name + ".txt")
|
|
required.add(path.name)
|
|
return matrix(path)
|
|
raw, gram, orthogram, transform, samples = (get(k) for k in
|
|
("basis_raw", "gram_raw", "gram_orthonormal", "coefficient_transform", "basis_samples_raw"))
|
|
weights_path = folder / (P + "basis_weights.txt")
|
|
required.add(weights_path.name)
|
|
weights = vector(weights_path)
|
|
audit.check("basis:positive_quadrature", len(weights) == len(samples) and np.all(weights > 0))
|
|
close_array(audit, "basis:quadrature_gram", gram, einsum("ni,n,nj->ij", samples, weights, samples))
|
|
close_array(audit, "basis:physical_from_raw", coords.maps["basis_physical"], einsum("ij,jk->ik", raw, transform))
|
|
actual = einsum("ij,ik,kl->jl", transform, gram, transform)
|
|
close_array(audit, "basis:transformed_gram", orthogram, actual)
|
|
close_array(audit, "basis:mass_orthonormal", actual, np.eye(coords.k))
|
|
node_path, mode_path, meta_path = (folder / (P + n + ".csv") for n in ("basis_nodes", "basis_modes", "basis_metadata"))
|
|
required.update(p.name for p in (node_path, mode_path, meta_path))
|
|
nodes, modes = rows(node_path), rows(mode_path)
|
|
audit.check("basis:node_indices", [integer(r["parameter"]) for r in nodes] == list(range(coords.s)))
|
|
node_base = np.array([finite(r["base_parameter"]) for r in nodes])
|
|
reference_radius = np.array([finite(r["reference_radius"]) for r in nodes])
|
|
physical_radius = np.array([finite(r["physical_radius"]) for r in nodes])
|
|
close_array(audit, "basis:frozen_base_parameters", node_base, physical_base[coords.vo:coords.vo + coords.s])
|
|
close_array(audit, "basis:physical_radius", physical_radius, reference_radius + node_base)
|
|
audit.check("basis:positive_radii", np.all(reference_radius > 0) and np.all(physical_radius > 0))
|
|
points = np.array([[finite(r["unit_radial_" + axis]) for axis in "xyz"] for r in nodes])
|
|
lengths = np.sqrt(einsum("ij,ij->i", points, points))
|
|
close_array(audit, "basis:unit_directions", lengths, np.ones(coords.s))
|
|
maximum_degree = max(integer(r["degree"]) for r in modes)
|
|
expected, labels = harmonics(points / lengths[:, None], maximum_degree)
|
|
audit.check("basis:mode_indices", [integer(r["column"]) for r in modes] == list(range(coords.k)))
|
|
audit.check("basis:mode_order", [(integer(r["degree"]), integer(r["m"])) for r in modes] == [(l["degree"], l["m"]) for l in labels])
|
|
close_array(audit, "basis:independent_harmonics", raw, expected)
|
|
text_keys = {"metric_scope", "scalar_finite_element_collection", "displacement_finite_element_collection"}
|
|
metadata = {k: r["value"] if k in text_keys else finite(r["value"])
|
|
for k, r in table(meta_path, lambda r: r["metric"]).items()}
|
|
for key, value in {"maximum_degree": maximum_degree, "modes": coords.k, "surface_parameters": coords.s,
|
|
"quadrature": 14, "surface_quadrature_points": len(weights), "accepted_buffers_unchanged": 1,
|
|
"prepared_state_unchanged": 1, "normalization_factors_unchanged": 1,
|
|
"vector_displacement_metric_claimed": 0, "base_projection_performed": 0,
|
|
"trial_preparations": 0, "radial_trace_validation_actions": 1}.items():
|
|
audit.check("basis:metadata:" + key, metadata[key] == value)
|
|
audit.check("basis:metric_scope", metadata["metric_scope"] == "scalar_radial_amplitude_FE_trace_mass_on_current_physical_surface")
|
|
audit.check("basis:reported_error_bounds", 0 <= metadata["maximum_gram_orthogonality_error"] <= 1e-10 and
|
|
0 <= metadata["maximum_sample_reconstruction_error"] <= 1e-10 and 0 <= metadata["adjoint_relative_error"] <= 1e-12)
|
|
for j, row in enumerate(modes):
|
|
pivot, relative = finite(row["pivot_norm"]), finite(row["relative_pivot"])
|
|
audit.check(f"basis:independent_mode:{j}", pivot > 0 and relative > metadata["rank_relative_pivot_threshold"] > 0)
|
|
audit.close(f"basis:pivot_transform:{j}", pivot * transform[j, j], 1.)
|
|
audit.close(f"basis:relative_pivot:{j}", relative, pivot / math.sqrt(gram[j, j]))
|
|
audit.close("basis:surface_area", metadata["physical_surface_area"], math.fsum(weights))
|
|
return {"status": "nodal_basis_and_saved_quadrature_gram_checked", "metadata": metadata,
|
|
"scope": "Saved FE trace samples and weights are checked algebraically; physical quadrature is not rerun."}
|
|
|
|
|
|
def provenance(folder, required, audit):
|
|
run_path = folder.parent / (folder.name + "_run.json")
|
|
source_path = folder.parent / "provenance.json"
|
|
if not run_path.exists() and not source_path.exists():
|
|
return {"status": "unavailable", "bound": False}
|
|
if not run_path.exists() or not source_path.exists():
|
|
raise ValueError("Incomplete campaign provenance")
|
|
run, source = json.loads(run_path.read_text()), json.loads(source_path.read_text())
|
|
audit.check("provenance:required_hashes", required <= set(run["output_hashes"]))
|
|
for name, expected in run["output_hashes"].items():
|
|
audit.check("provenance:output:" + name, digest(folder / name) == expected)
|
|
for name, expected in run.get("input_state_hashes", {}).items():
|
|
audit.check("provenance:input:" + name, digest(name) == expected)
|
|
command = run.get("command", run.get("cmd"))
|
|
if command is None:
|
|
raise ValueError("Missing recorded command")
|
|
case = next(c for c in source["cases"] if c["id"] == folder.name)
|
|
expected = [str(folder.parent / "plateau_diagnostic"), *case["arguments"], "--mesh", source["mesh"], "--output", str(folder)]
|
|
audit.check("provenance:command", command == expected)
|
|
audit.check("provenance:binary", digest(command[0]) == source["binary_sha256"])
|
|
audit.check("provenance:mesh", digest(source["mesh"]) == source["mesh_sha256"])
|
|
if "--probe-state" in command:
|
|
path = Path(command[command.index("--probe-state") + 1])
|
|
if not path.is_absolute():
|
|
path = Path(source["source"]) / path
|
|
audit.check("provenance:base_input_bound", str(path.resolve()) in run.get("input_state_hashes", {}))
|
|
close_array(audit, "provenance:physical_base_input", vector(path), vector(folder / (P + "physical_base.txt")))
|
|
audit.check("provenance:successful_probe_exit", run["exit_code"] == 0)
|
|
return {"status": "runner_hashes_checked", "bound": True, "source_commit": source["commit"],
|
|
"run_sha256": digest(run_path), "provenance_sha256": digest(source_path)}
|
|
|
|
|
|
def inspect(folder):
|
|
folder = Path(folder).resolve()
|
|
audit, required, observations = Audit(), set(), {}
|
|
try:
|
|
def get(name):
|
|
path = folder / (P + name + ".txt")
|
|
required.add(path.name)
|
|
return vector(path)
|
|
summary_path = folder / (P + "summary.csv")
|
|
trials_path = folder / (P + "trials.csv")
|
|
layout_path = folder / (P + "layout.csv")
|
|
required.update(p.name for p in (summary_path, trials_path, layout_path))
|
|
summary = {k: finite(r["value"]) for k, r in table(summary_path, lambda r: r["metric"]).items()}
|
|
audit.check("identity:boolean", summary["identity_control"] in (0, 1))
|
|
maps = {}
|
|
for name in MAPS:
|
|
path = folder / (P + name + ".txt")
|
|
if summary["identity_control"]:
|
|
audit.check("identity:matrix_absent:" + name, not path.exists())
|
|
else:
|
|
required.add(path.name)
|
|
maps[name] = matrix(path)
|
|
coordinates = Coordinates(summary, maps)
|
|
n, s, k, vo, ro = coordinates.n, coordinates.s, coordinates.k, coordinates.vo, coordinates.ro
|
|
degree = integer(summary["maximum_degree"])
|
|
audit.check("prescribed_basis_size", (degree == 0 and k == s) if coordinates.identity else (degree in (2, 4, 6, 8) and k == (degree + 1) ** 2))
|
|
audit.check("reduced_size", summary["reduced_size"] == n - s + k)
|
|
audit.check("schema_version", summary["schema_version"] == 1)
|
|
audit.check("reported_algebra_selfcheck", summary["algebra_self_check_passed"] == 1)
|
|
blocks = layout(layout_path, n)
|
|
audit.check("layout:value_shape", ("surface_deformation", vo, s) in blocks["value"])
|
|
audit.check("layout:residual_shape", ("surface_shape_balance", ro, s) in blocks["residual"])
|
|
data = {name: get(name) for name in VECTORS}
|
|
for name, values in data.items():
|
|
audit.check("size:" + name, len(values) == (n - s + k if name.startswith("reduced_") else n))
|
|
sx, rf = data["state_factors"], data["residual_factors"]
|
|
audit.check("normalization:positive", np.all(sx > 0) and np.all(rf > 0))
|
|
coordinates.validate(sx, rf, audit)
|
|
for key, value in {"accepted_buffers_bitwise_identical": 1, "normalization_factors_bitwise_identical": 1,
|
|
"direction_buffers_bitwise_identical": 1, "restored_residual_error": 0,
|
|
"restored_action_error": 0, "probe_exception": 0, "accepted_commits": 0}.items():
|
|
audit.check("invariant:" + key, summary[key] == value)
|
|
audit.check("restoration:residual_exact", np.array_equal(data["residual"], data["restored_residual"]))
|
|
audit.check("restoration:action_exact", np.array_equal(data["action"], data["restored_action"]))
|
|
close_array(audit, "normalization:base", data["physical_base"], data["base"] / sx)
|
|
close_array(audit, "normalization:direction", data["physical_direction"], data["direction"] / sx)
|
|
close_array(audit, "injection:direction", data["direction"], coordinates.inject(data["reduced_direction"]))
|
|
for name in ("residual", "action", "defect"):
|
|
# Forming R(F+Jp) and RF+RJp rounds differently when F and Jp
|
|
# cancel. The allowance must scale with the operands, not only
|
|
# with the potentially zero defect being checked.
|
|
scale = norm(data["residual"]) + norm(data["action"]) if name == "defect" else 0.
|
|
close_array(audit, "restriction:" + name, data["reduced_" + name], coordinates.restrict(data[name]), scale)
|
|
close_array(audit, "defect:full", data["defect"], data["residual"] + data["action"], norm(data["residual"]) + norm(data["action"]))
|
|
close_array(audit, "defect:reduced", data["reduced_defect"], data["reduced_residual"] + data["reduced_action"],
|
|
norm(data["reduced_residual"]) + norm(data["reduced_action"]))
|
|
for name in ("residual", "defect"):
|
|
excluded = coordinates.excluded(data[name])
|
|
close_array(audit, "excluded:" + name, data["excluded_" + name], excluded, norm(data[name]))
|
|
audit.close("pythagoras:" + name, norm(data[name]) ** 2,
|
|
norm(data["reduced_" + name]) ** 2 + norm(excluded) ** 2, norm(data[name]) ** 2)
|
|
eta = summary["linear_relative_tolerance"]
|
|
absolute = summary["linear_absolute_tolerance"]
|
|
audit.check("linear:controls", 0 < eta < 1 and absolute >= 0 and integer(summary["linear_maximum_iterations"]) > 0)
|
|
gates, slopes = {}, {}
|
|
for label, prefix in (("full", ""), ("reduced", "reduced_")):
|
|
fn, dn = norm(data[prefix + "residual"]), norm(data[prefix + "defect"])
|
|
audit.check(label + ":nonzero_rhs", fn > 0)
|
|
passed = dn <= max(absolute, eta * fn)
|
|
audit.check(label + ":reported_gate", summary[label + "_verified_gate"] in (0, 1) and bool(summary[label + "_verified_gate"]) == passed)
|
|
audit.close(label + ":relative_defect", summary[label + "_relative_defect"], dn / fn)
|
|
gates[label] = {"verified_gate": passed, "residual_norm": fn, "defect_norm": dn, "relative_defect": dn / fn}
|
|
slopes[label] = float(einsum("i,i->", data[prefix + "residual"], data[prefix + "action"]))
|
|
audit.close(label + ":reported_norm", summary[label + "_base_norm"], fn)
|
|
audit.close(label + ":reported_slope", summary[label + "_merit_slope"], slopes[label], fn * norm(data[prefix + "action"]))
|
|
audit.close("reported_direction_norm", summary["direction_norm"], norm(data["direction"]))
|
|
audit.close("reported_excluded_base", summary["excluded_base_norm"], norm(data["excluded_residual"]), norm(data["residual"]))
|
|
audit.close("linear:reported_true_norm", summary["linear_reported_true_norm"], norm(data["reduced_defect"]), norm(data["reduced_residual"]))
|
|
audit.check("linear:iteration_budget", 0 <= integer(summary["linear_iterations"]) <= integer(summary["linear_maximum_iterations"]))
|
|
trials = rows(trials_path)
|
|
audit.check("trial:complete_grid", len(trials) == len(ALPHAS))
|
|
trial_observations = []
|
|
for index, row in enumerate(trials):
|
|
alpha = finite(row["alpha"])
|
|
audit.check(f"trial:{index}:alpha", index < len(ALPHAS) and alpha == ALPHAS[index])
|
|
audit.check(f"trial:{index}:sample", integer(row["sample"]) == index)
|
|
prepared = integer(row["prepared"])
|
|
audit.check(f"trial:{index}:prepared_flag", prepared in (0, 1))
|
|
result = {"sample": index, "alpha": alpha, "prepared": bool(prepared), "reason": integer(row["reason"]), "stage": integer(row["stage"])}
|
|
candidate_path = folder / (P + f"candidate_a{index}.txt")
|
|
if prepared or candidate_path.exists():
|
|
candidate = get(f"candidate_a{index}")
|
|
close_array(audit, f"trial:{index}:candidate", candidate, data["base"] + alpha * data["direction"])
|
|
if prepared:
|
|
audit.check(f"trial:{index}:prepared_status", result["reason"] == result["stage"] == -1)
|
|
physical_candidate = get(f"physical_candidate_a{index}")
|
|
close_array(audit, f"trial:{index}:physical_candidate", physical_candidate, candidate / sx)
|
|
full, reduced = get(f"residual_a{index}"), get(f"reduced_residual_a{index}")
|
|
close_array(audit, f"trial:{index}:restriction", reduced, coordinates.restrict(full))
|
|
excluded = coordinates.excluded(full)
|
|
full_norm, reduced_norm, excluded_norm = norm(full), norm(reduced), norm(excluded)
|
|
remainder = full - data["residual"] - alpha * data["action"]
|
|
reduced_remainder = reduced - data["reduced_residual"] - alpha * data["reduced_action"]
|
|
for label, actual in (("full_norm", full_norm), ("reduced_norm", reduced_norm), ("excluded_shape_norm", excluded_norm),
|
|
("full_remainder_norm", norm(remainder)), ("reduced_remainder_norm", norm(reduced_remainder))):
|
|
audit.close(f"trial:{index}:" + label, finite(row[label]), actual, norm(data["residual"]))
|
|
audit.close(f"trial:{index}:pythagoras", full_norm ** 2, reduced_norm ** 2 + excluded_norm ** 2, full_norm ** 2)
|
|
for label, actual in (("full", full_norm), ("reduced", reduced_norm)):
|
|
accepted = actual <= (1 - 1e-4 * alpha) * gates[label]["residual_norm"]
|
|
audit.check(f"trial:{index}:" + label + "_accept", integer(row[label + "_merit_pass"]) in (0, 1) and bool(integer(row[label + "_merit_pass"])) == accepted)
|
|
result[label + "_merit_pass"] = accepted
|
|
result.update(full_norm=full_norm, reduced_norm=reduced_norm, excluded_shape_norm=excluded_norm,
|
|
full_remainder_norm=norm(remainder), reduced_remainder_norm=norm(reduced_remainder))
|
|
else:
|
|
audit.check(f"trial:{index}:failure_status", result["reason"] >= 0 and result["stage"] >= 0)
|
|
for name in (f"residual_a{index}", f"reduced_residual_a{index}"):
|
|
audit.check(f"trial:{index}:unavailable:" + name, not (folder / (P + name + ".txt")).exists())
|
|
for label in ("full_norm", "reduced_norm", "excluded_shape_norm", "full_remainder_norm", "reduced_remainder_norm"):
|
|
audit.check(f"trial:{index}:unavailable:" + label, math.isnan(float(row[label])))
|
|
audit.check(f"trial:{index}:failure_not_accepted", integer(row["full_merit_pass"]) == integer(row["reduced_merit_pass"]) == 0)
|
|
trial_observations.append(result)
|
|
package = basis_package(folder, coordinates, data["physical_base"], required, audit) if not coordinates.identity else {"status": "identity_control"}
|
|
if not coordinates.identity:
|
|
audit.check("basis:degree_matches_summary", package["metadata"]["maximum_degree"] == degree)
|
|
binding = provenance(folder, required, audit)
|
|
observations = {"summary": summary, "linear": gates, "merit_directional_derivatives": slopes,
|
|
"classification": "full_and_reduced_gates_pass" if gates["full"]["verified_gate"] and gates["reduced"]["verified_gate"] else
|
|
"reduced_gate_only_not_full_Newton" if gates["reduced"]["verified_gate"] else "finite_reduced_solve_failed_gate",
|
|
"base_excluded_shape_norm": norm(data["excluded_residual"]), "trials": trial_observations,
|
|
"basis": package, "provenance": binding}
|
|
except (ValueError, OSError, KeyError, TypeError, IndexError, StopIteration, np.linalg.LinAlgError) as error:
|
|
audit.check("complete_readable_consistent_artifacts:" + str(error), False)
|
|
return {"directory": str(folder), "artifact_pass": not audit.failures, "checks_count": audit.count,
|
|
"failures": audit.failures, "required_artifacts": sorted(required), "observations": observations if not audit.failures else {}}
|
|
|
|
|
|
def self_test():
|
|
count = 0
|
|
def checked(condition):
|
|
nonlocal count
|
|
assert condition
|
|
count += 1
|
|
# Deliberately different value/residual factors and shape offsets catch the
|
|
# tempting but invalid reuse of the state basis as a residual test basis.
|
|
b = np.array([[1., .4], [1., -.1], [1., -.3]])
|
|
sx = np.array([2., 3., 5., 7., 11., 13., 17.])
|
|
rf = np.array([.2, .3, .7, 1.1, 1.3, 1.7, 1.9])
|
|
summary = dict(full_size=7, shape_size=3, mode_count=2, shape_value_offset=1, shape_residual_offset=3, identity_control=0)
|
|
px, tx = np.linalg.qr(sx[1:4, None] * b)
|
|
qf, tf = np.linalg.qr(b / rf[3:6, None])
|
|
maps = dict(zip(MAPS, (b, px, qf, tx, tf)))
|
|
c = Coordinates(summary, maps)
|
|
a = Audit(); c.validate(sx, rf, a); checked(not a.failures)
|
|
z = np.arange(1., 7.)
|
|
f = np.arange(-3., 4.)
|
|
checked(vector_near(c.restrict(c.inject(z), False), z))
|
|
checked(vector_near(c.restrict(c.inject(z, True)), z))
|
|
checked(near(norm(f) ** 2, norm(c.restrict(f)) ** 2 + norm(c.excluded(f)) ** 2))
|
|
physical_dual = einsum("ij,i->j", b, f[3:6] / rf[3:6])
|
|
checked(vector_near(einsum("ji,j->i", tf, c.restrict(f)[3:5]), physical_dual))
|
|
bad = Coordinates(summary, {**maps, "residual_basis": px})
|
|
a = Audit(); bad.validate(sx, rf, a); checked("maps:dual_QR" in a.failures)
|
|
a = Audit(); c.validate(sx, rf[::-1], a); checked(bool(a.failures))
|
|
checked(norm(c.restrict(c.excluded(f))) < 1e-14)
|
|
# Full-rank bases may rotate the coordinates. Verify the recovered full
|
|
# direction, not equality of the rotated coefficient arrays.
|
|
bfull = np.array([[1., .4, .2], [1., -.1, .7], [1., -.3, -.6]])
|
|
px, tx = np.linalg.qr(sx[1:4, None] * bfull)
|
|
qf, tf = np.linalg.qr(bfull / rf[3:6, None])
|
|
full = Coordinates({**summary, "mode_count": 3}, dict(zip(MAPS, (bfull, px, qf, tx, tf))))
|
|
op = np.diag(np.arange(2., 9.)) + .03 * np.ones((7, 7))
|
|
columns = []
|
|
for i in range(7):
|
|
columns.append(full.restrict(einsum("ij,j->i", op, full.inject(np.eye(7)[:, i]))))
|
|
reduced_op = np.column_stack(columns)
|
|
result = full.inject(np.linalg.solve(reduced_op, -full.restrict(f)))
|
|
checked(vector_near(result, np.linalg.solve(op, -f)))
|
|
identity = Coordinates({**summary, "mode_count": 3, "identity_control": 1}, {})
|
|
checked(np.array_equal(identity.inject(f), f) and np.array_equal(identity.restrict(f), f))
|
|
checked(np.array_equal(identity.excluded(f), np.zeros(7)))
|
|
# A reduced zero defect can coexist with a substantial discarded full one.
|
|
discarded = c.excluded(f)
|
|
checked(norm(discarded) > .1 and norm(c.restrict(discarded)) < 1e-14)
|
|
import csv
|
|
import tempfile
|
|
def fixture(folder, identity=False):
|
|
folder.mkdir()
|
|
def save(name, array):
|
|
array = np.asarray(array)
|
|
with (folder / (P + name + ".txt")).open("w") as stream:
|
|
stream.write((f"{len(array)}" if array.ndim == 1 else f"{array.shape[0]} {array.shape[1]}") + "\n")
|
|
np.savetxt(stream, array.ravel(), fmt="%.17g")
|
|
def csv_save(name, columns, records):
|
|
with (folder / (P + name + ".csv")).open("w", newline="") as stream:
|
|
writer = csv.writer(stream); writer.writerow(columns); writer.writerows(records)
|
|
n, s, k, vo, ro = 18, 12, 9, 1, 4
|
|
points = []
|
|
for i in range(s):
|
|
z = 1 - 2 * (i + .5) / s
|
|
phi = i * math.pi * (3 - math.sqrt(5))
|
|
points.append((math.sqrt(1 - z * z) * math.cos(phi), math.sqrt(1 - z * z) * math.sin(phi), z))
|
|
points = np.asarray(points)
|
|
raw, modes = harmonics(points, 2)
|
|
weights = np.ones(s)
|
|
gram = einsum("ni,n,nj->ij", raw, weights, raw)
|
|
transform = np.linalg.inv(np.linalg.cholesky(gram).T)
|
|
b = einsum("ij,jk->ik", raw, transform)
|
|
sx, rf = np.linspace(1., 3., n), np.linspace(.4, 2., n)
|
|
px, tx = np.linalg.qr(sx[vo:vo + s, None] * b)
|
|
qf, tf = np.linalg.qr(b / rf[ro:ro + s, None])
|
|
maps = dict(zip(MAPS, (b, px, qf, tx, tf)))
|
|
summary = dict(schema_version=1, full_size=n, shape_size=s, mode_count=s if identity else k,
|
|
shape_value_offset=vo, shape_residual_offset=ro, identity_control=int(identity),
|
|
maximum_degree=0 if identity else 2, reduced_size=n if identity else n - s + k,
|
|
linear_relative_tolerance=.03, linear_absolute_tolerance=0., linear_maximum_iterations=200,
|
|
linear_restart=160, linear_status=0, linear_iterations=7, linear_seconds=.01,
|
|
algebra_self_check_passed=1, accepted_commits=0, accepted_buffers_bitwise_identical=1,
|
|
normalization_factors_bitwise_identical=1, direction_buffers_bitwise_identical=1,
|
|
restored_residual_error=0, restored_action_error=0, preparations=8, probe_exception=0)
|
|
c = Coordinates(summary, {} if identity else maps)
|
|
reduced_direction = np.sin(np.arange(summary["reduced_size"]) + 1.)
|
|
direction = c.inject(reduced_direction)
|
|
action = direction.copy()
|
|
residual = -action + c.excluded(np.cos(np.arange(n)))
|
|
base = np.linspace(.1, .3, n)
|
|
data = dict(base=base, physical_base=base / sx, residual=residual, direction=direction,
|
|
physical_direction=direction / sx, action=action, defect=residual + action,
|
|
state_factors=sx, residual_factors=rf, reduced_direction=reduced_direction,
|
|
restored_residual=residual, restored_action=action)
|
|
for name in ("residual", "action", "defect"):
|
|
data["reduced_" + name] = c.restrict(data[name])
|
|
for name in ("residual", "defect"):
|
|
data["excluded_" + name] = c.excluded(data[name])
|
|
for label, prefix in (("full", ""), ("reduced", "reduced_")):
|
|
fn, dn = norm(data[prefix + "residual"]), norm(data[prefix + "defect"])
|
|
summary[label + "_base_norm"] = fn
|
|
summary[label + "_relative_defect"] = dn / fn
|
|
summary[label + "_verified_gate"] = int(dn <= .03 * fn)
|
|
summary[label + "_merit_slope"] = float(einsum("i,i->", data[prefix + "residual"], data[prefix + "action"]))
|
|
summary["linear_reported_true_norm"] = norm(data["reduced_defect"])
|
|
summary["direction_norm"] = norm(direction)
|
|
summary["excluded_base_norm"] = norm(data["excluded_residual"])
|
|
for name, values in data.items():
|
|
save(name, values)
|
|
csv_save("summary", ["metric", "value"], summary.items())
|
|
csv_save("layout", ["kind", "block", "offset", "size"],
|
|
[("value", "density", 0, vo), ("value", "surface_deformation", vo, s), ("value", "tail", vo + s, n - vo - s),
|
|
("residual", "head", 0, ro), ("residual", "surface_shape_balance", ro, s), ("residual", "tail", ro + s, n - ro - s)])
|
|
trials = []
|
|
for index, alpha in enumerate(ALPHAS):
|
|
save(f"candidate_a{index}", base + alpha * direction)
|
|
if index == 0:
|
|
trials.append((index, alpha, 0, 0, 0, "nan", "nan", "nan", 0, 0, "nan", "nan"))
|
|
continue
|
|
f = residual + alpha * action + .025 * alpha ** 2 * residual
|
|
fr = c.restrict(f)
|
|
remainder = f - residual - alpha * action
|
|
save(f"physical_candidate_a{index}", (base + alpha * direction) / sx)
|
|
save(f"residual_a{index}", f); save(f"reduced_residual_a{index}", fr)
|
|
trials.append((index, alpha, 1, -1, -1, norm(f), norm(fr), norm(c.excluded(f)),
|
|
int(norm(f) <= (1 - 1e-4 * alpha) * norm(residual)),
|
|
int(norm(fr) <= (1 - 1e-4 * alpha) * norm(data["reduced_residual"])),
|
|
norm(remainder), norm(c.restrict(remainder))))
|
|
csv_save("trials", ["sample", "alpha", "prepared", "reason", "stage", "full_norm", "reduced_norm", "excluded_shape_norm",
|
|
"full_merit_pass", "reduced_merit_pass", "full_remainder_norm", "reduced_remainder_norm"], trials)
|
|
if not identity:
|
|
for name, values in maps.items():
|
|
save(name, values)
|
|
for name, values in {"basis_raw": raw, "gram_raw": gram, "coefficient_transform": transform,
|
|
"gram_orthonormal": einsum("ij,ik,kl->jl", transform, gram, transform),
|
|
"basis_samples_raw": raw, "basis_weights": weights}.items():
|
|
save(name, values)
|
|
csv_save("basis_nodes", ["parameter", "unit_radial_x", "unit_radial_y", "unit_radial_z", "reference_radius", "physical_radius", "base_parameter"],
|
|
[(i, *point, 1., 1 + data["physical_base"][vo + i], data["physical_base"][vo + i]) for i, point in enumerate(points)])
|
|
csv_save("basis_modes", ["column", "degree", "m", "pivot_norm", "relative_pivot"],
|
|
[(i, m["degree"], m["m"], 1 / transform[i, i], 1 / (transform[i, i] * math.sqrt(gram[i, i]))) for i, m in enumerate(modes)])
|
|
metadata = dict(maximum_degree=2, modes=k, surface_parameters=s, quadrature=14, surface_quadrature_points=s,
|
|
physical_surface_area=s, accepted_buffers_unchanged=1, prepared_state_unchanged=1, normalization_factors_unchanged=1,
|
|
vector_displacement_metric_claimed=0, base_projection_performed=0, trial_preparations=0,
|
|
radial_trace_validation_actions=1, metric_scope="scalar_radial_amplitude_FE_trace_mass_on_current_physical_surface",
|
|
maximum_gram_orthogonality_error=1e-15, maximum_sample_reconstruction_error=0.,
|
|
adjoint_relative_error=0., rank_relative_pivot_threshold=1e-12)
|
|
csv_save("basis_metadata", ["metric", "value"], metadata.items())
|
|
return save
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
folder = Path(tmp) / "reduced"
|
|
save = fixture(folder)
|
|
result = inspect(folder)
|
|
assert result["artifact_pass"], result["failures"]
|
|
checked(result["artifact_pass"])
|
|
checked(result["observations"]["classification"] == "reduced_gate_only_not_full_Newton")
|
|
for name in ("residual_basis", "candidate_a1", "excluded_residual", "gram_raw", "state_factors"):
|
|
path = folder / (P + name + ".txt")
|
|
original = path.read_bytes()
|
|
values = matrix(path) if name in ("residual_basis", "gram_raw") else vector(path)
|
|
values.flat[0] += .02
|
|
save(name, values)
|
|
checked(not inspect(folder)["artifact_pass"])
|
|
path.write_bytes(original)
|
|
summary_path = folder / (P + "summary.csv")
|
|
original = summary_path.read_text()
|
|
summary_path.write_text(original.replace("full_verified_gate,0", "full_verified_gate,1"))
|
|
checked(not inspect(folder)["artifact_pass"])
|
|
summary_path.write_text(original)
|
|
save("residual_a0", np.ones(18))
|
|
checked(not inspect(folder)["artifact_pass"])
|
|
(folder / (P + "residual_a0.txt")).unlink()
|
|
identity_folder = Path(tmp) / "identity"
|
|
fixture(identity_folder, True)
|
|
result = inspect(identity_folder)
|
|
checked(result["artifact_pass"] and result["observations"]["classification"] == "full_and_reduced_gates_pass")
|
|
print(f"{count} tiny algebra, end-to-end artifact and corruption checks passed")
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("directories", nargs="*")
|
|
parser.add_argument("--output", type=Path)
|
|
parser.add_argument("--self-test", action="store_true")
|
|
args = parser.parse_args()
|
|
if args.self_test:
|
|
self_test()
|
|
return 0
|
|
if not args.directories or args.output is None:
|
|
parser.error("Provide probe directories and a fresh output JSON")
|
|
output = args.output.resolve()
|
|
if output.exists() or any(output.is_relative_to(Path(d).resolve()) for d in args.directories):
|
|
parser.error("Use a fresh output outside immutable probe directories")
|
|
cases = [inspect(d) for d in args.directories]
|
|
result = {"schema_version": 1, "passed": all(c["artifact_pass"] for c in cases), "checker_sha256": digest(__file__),
|
|
"tolerances": {"relative": RTOL, "cancellation_epsilon_multiplier": 2048}, "cases": cases,
|
|
"scope": "Independent saved-vector and map algebra only. Reduced success does not certify the unrestricted equations, FEM evaluation, or physical validity."}
|
|
output.parent.mkdir(parents=True, exist_ok=True)
|
|
output.write_text(json.dumps(result, indent=2, allow_nan=False) + "\n")
|
|
print(f"{'PASS' if result['passed'] else 'FAIL'}: {len(cases)} cases; {output}")
|
|
return 0 if result["passed"] else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|