from __future__ import annotations
import argparse
import json
import math
import sys
import time
from pathlib import Path
from typing import Any, Dict, List
def _json_safe(value: Any) -> Any:
if isinstance(value, float):
if math.isnan(value):
return "NaN"
if math.isinf(value):
return "Infinity" if value > 0.0 else "-Infinity"
return value
if isinstance(value, list):
return [_json_safe(v) for v in value]
if isinstance(value, dict):
return {k: _json_safe(v) for k, v in value.items()}
return value
def _coerce_maybe_nan_f64(value: Any) -> float:
if isinstance(value, str):
key = value.strip().lower()
if key == "nan":
return float("nan")
if key in ("infinity", "inf", "+infinity", "+inf"):
return float("inf")
if key in ("-infinity", "-inf"):
return float("-inf")
return float(value)
return float(value)
def _matrix_from_spec(spec: Dict[str, Any], sparse: Any, np: Any) -> Any:
shape = tuple(spec["shape"])
row = np.asarray(spec["row"], dtype=np.int64)
col = np.asarray(spec["col"], dtype=np.int64)
data = np.asarray([_coerce_maybe_nan_f64(v) for v in spec["data"]], dtype=np.float64)
coo = sparse.coo_array((data, (row, col)), shape=shape)
fmt = spec.get("format", "coo")
if fmt == "coo":
return coo
if fmt == "csr":
return coo.tocsr()
if fmt == "csc":
return coo.tocsc()
raise ValueError(f"unsupported sparse fixture format: {fmt}")
def _matrix_result(matrix: Any) -> Dict[str, Any]:
coo = matrix.tocoo()
return {
"format": getattr(matrix, "format", None),
"shape": [int(coo.shape[0]), int(coo.shape[1])],
"row": [int(v) for v in coo.row.tolist()],
"col": [int(v) for v in coo.col.tolist()],
"data": [float(v) for v in coo.data.tolist()],
}
def _find_result(matrix: Any, sparse: Any) -> Dict[str, Any]:
row, col, data = sparse.find(matrix)
return {
"row": [int(v) for v in row.tolist()],
"col": [int(v) for v in col.tolist()],
"data": [float(v) for v in data.tolist()],
}
def _csr_components_result(matrix: Any) -> Dict[str, Any]:
csr = matrix if getattr(matrix, "format", None) == "csr" else matrix.tocsr()
return {
"shape": [int(csr.shape[0]), int(csr.shape[1])],
"data": [float(v) for v in csr.data.tolist()],
"indices": [int(v) for v in csr.indices.tolist()],
"indptr": [int(v) for v in csr.indptr.tolist()],
"has_sorted_indices": bool(csr.has_sorted_indices),
"has_canonical_format": bool(csr.has_canonical_format),
}
def _run_case(case: Dict[str, Any], sparse: Any, np: Any) -> Dict[str, Any]:
case_id = case["case_id"]
operation = case["operation"]
try:
if operation == "find":
matrix = _matrix_from_spec(case["matrix"], sparse, np)
return {
"case_id": case_id,
"status": "ok",
"result_kind": "find_triplets",
"result": _find_result(matrix, sparse),
"error": None,
}
if operation == "tril":
matrix = _matrix_from_spec(case["matrix"], sparse, np)
result = sparse.tril(matrix, k=int(case.get("k", 0)))
return {
"case_id": case_id,
"status": "ok",
"result_kind": "matrix_triplets",
"result": _matrix_result(result),
"error": None,
}
if operation == "triu":
matrix = _matrix_from_spec(case["matrix"], sparse, np)
result = sparse.triu(matrix, k=int(case.get("k", 0)))
return {
"case_id": case_id,
"status": "ok",
"result_kind": "matrix_triplets",
"result": _matrix_result(result),
"error": None,
}
if operation == "tocsc":
matrix = _matrix_from_spec(case["matrix"], sparse, np)
result = matrix.tocsc()
return {
"case_id": case_id,
"status": "ok",
"result_kind": "matrix_triplets",
"result": _matrix_result(result),
"error": None,
}
if operation == "vstack":
blocks = [_matrix_from_spec(block, sparse, np) for block in case["blocks"]]
result = sparse.vstack(blocks, format=case.get("format"))
return {
"case_id": case_id,
"status": "ok",
"result_kind": "matrix_triplets",
"result": _matrix_result(result),
"error": None,
}
if operation == "hstack":
blocks = [_matrix_from_spec(block, sparse, np) for block in case["blocks"]]
result = sparse.hstack(blocks, format=case.get("format"))
return {
"case_id": case_id,
"status": "ok",
"result_kind": "matrix_triplets",
"result": _matrix_result(result),
"error": None,
}
if operation == "csr_matmul":
lhs = _matrix_from_spec(case["blocks"][0], sparse, np)
rhs = _matrix_from_spec(case["blocks"][1], sparse, np)
result = lhs @ rhs
return {
"case_id": case_id,
"status": "ok",
"result_kind": "csr_components",
"result": _csr_components_result(result),
"error": None,
}
if operation in {"eigsh", "eigs", "svds"}:
from scipy.sparse import coo_matrix
from scipy.sparse.linalg import eigs, eigsh, svds
rows = int(case["rows"])
cols = int(case["cols"])
data = [_coerce_maybe_nan_f64(v) for v in case.get("data", [])]
row_indices = [int(v) for v in case.get("row_indices", [])]
col_indices = [int(v) for v in case.get("col_indices", [])]
mat = coo_matrix(
(data, (row_indices, col_indices)), shape=(rows, cols)
).tocsr()
k = int(case.get("k", 1))
if operation == "eigsh":
values = eigsh(mat, k=k, return_eigenvectors=False)
values = sorted([float(v) for v in values], key=lambda v: abs(v), reverse=True)
elif operation == "eigs":
ev = eigs(mat, k=k, return_eigenvectors=False)
values = sorted([float(v.real) for v in ev], key=lambda v: abs(v), reverse=True)
else: u, s, vt = svds(mat, k=k)
values = sorted([float(v) for v in s], key=lambda v: abs(v), reverse=True)
return {
"case_id": case_id,
"status": "ok",
"result_kind": "eigenvalues_abs_sorted",
"result": {"values": values},
"error": None,
}
if operation in {"spmv", "spsolve", "add", "scale", "format_roundtrip"}:
rows = int(case["rows"])
cols = int(case["cols"])
data = [_coerce_maybe_nan_f64(v) for v in case.get("data", [])]
row_indices = [int(v) for v in case.get("row_indices", [])]
col_indices = [int(v) for v in case.get("col_indices", [])]
fmt = str(case.get("format", "csr")).lower()
coo = sparse.coo_matrix(
(data, (row_indices, col_indices)),
shape=(rows, cols),
)
if fmt == "csr":
mat = coo.tocsr()
elif fmt == "csc":
mat = coo.tocsc()
elif fmt == "coo":
mat = coo
elif fmt == "dok":
mat = coo.todok()
elif fmt == "lil":
mat = coo.tolil()
else:
mat = coo.tocsr()
if operation == "spmv":
rhs = np.asarray([_coerce_maybe_nan_f64(v) for v in case.get("rhs", [])])
y = mat @ rhs
return {
"case_id": case_id,
"status": "ok",
"result_kind": "vector",
"result": {"values": [float(v) for v in y.tolist()]},
"error": None,
}
if operation == "spsolve":
rhs = np.asarray([_coerce_maybe_nan_f64(v) for v in case.get("rhs", [])])
from scipy.sparse import linalg as splinalg
x = splinalg.spsolve(mat.tocsr(), rhs)
return {
"case_id": case_id,
"status": "ok",
"result_kind": "vector",
"result": {"values": [float(v) for v in np.atleast_1d(x).tolist()]},
"error": None,
}
if operation == "scale":
scalar = _coerce_maybe_nan_f64(case.get("scalar", 1.0))
scaled = (mat.tocoo() * scalar).tocoo()
return {
"case_id": case_id,
"status": "ok",
"result_kind": "matrix_triplets",
"result": _matrix_result(scaled),
"error": None,
}
if operation == "add":
rhs_raw = case.get("rhs")
if rhs_raw is None or (hasattr(rhs_raw, "__len__") and len(rhs_raw) == 0):
rhs_mat = mat.tocsr()
else:
rhs_data = [_coerce_maybe_nan_f64(v) for v in rhs_raw]
rhs_mat = sparse.coo_matrix(
(rhs_data, (row_indices, col_indices)),
shape=(rows, cols),
).tocsr()
result = (mat.tocsr() + rhs_mat).tocoo()
return {
"case_id": case_id,
"status": "ok",
"result_kind": "matrix_triplets",
"result": _matrix_result(result),
"error": None,
}
if operation == "format_roundtrip":
result = mat.tocsr().tocoo().tocsc().tocoo()
return {
"case_id": case_id,
"status": "ok",
"result_kind": "matrix_triplets",
"result": _matrix_result(result),
"error": None,
}
return {
"case_id": case_id,
"status": "error",
"result_kind": "unsupported_operation",
"result": {},
"error": f"unsupported operation: {operation}",
}
except (
ArithmeticError,
OverflowError,
TypeError,
ValueError,
KeyError,
IndexError,
RuntimeError,
) as exc:
return {
"case_id": case_id,
"status": "error",
"result_kind": "exception",
"result": {},
"error": f"{type(exc).__name__}: {exc}",
}
def main() -> int:
parser = argparse.ArgumentParser(description="Capture SciPy sparse helper oracle outputs")
parser.add_argument("--fixture", required=True, help="Input fixture JSON path")
parser.add_argument("--output", required=True, help="Output oracle capture JSON path")
parser.add_argument("--oracle-root", required=False, default="", help="Optional path to legacy scipy reference tree")
args = parser.parse_args()
fixture_path = Path(args.fixture)
output_path = Path(args.output)
try:
import numpy as np
from scipy import sparse
except ModuleNotFoundError as exc:
print(str(exc), file=sys.stderr)
return 2
try:
fixture = json.loads(fixture_path.read_text(encoding="utf-8"))
except json.JSONDecodeError as exc:
print(f"Invalid JSON in fixture: {exc}", file=sys.stderr)
return 1
case_outputs: List[Dict[str, Any]] = []
for case in fixture.get("cases", []):
case_outputs.append(_run_case(case, sparse=sparse, np=np))
payload = {
"packet_id": fixture.get("packet_id", "unknown"),
"family": fixture.get("family", "unknown"),
"generated_unix_ms": int(time.time() * 1000),
"runtime": {
"python_version": sys.version.split()[0],
"numpy_version": getattr(np, "__version__", "unknown"),
"scipy_version": getattr(sys.modules.get("scipy"), "__version__", "unknown"),
},
"case_outputs": case_outputs,
}
output_path.parent.mkdir(parents=True, exist_ok=True)
output_path.write_text(
json.dumps(_json_safe(payload), allow_nan=False, indent=2, sort_keys=True),
encoding="utf-8",
)
return 0
if __name__ == "__main__":
raise SystemExit(main())