Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions solve.eigs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,14 @@ define pagerank(m, maxit) as:
return [r, it]

# ---- demo ----
# zeros returns a numeric buffer since EigenScript#1093. Materialize only
# for display so both list and buffer-backed solvers print their components.
define display_vector(v) as:
local components is []
for i in range of (len of v):
append of [components, v[i]]
return components

print of "=== iterative solvers: the predicate as a loop condition ==="
print of "every loop runs until `report of change` is settled and HOLDs — the observer,"
print of "not a magnitude tolerance, decides when to stop. (iters include the hold)"
Expand All @@ -210,9 +218,9 @@ A is [[4.0, -1.0, 0.0], [-1.0, 4.0, -1.0], [0.0, -1.0, 4.0]]
bb is [3.0, 2.0, 3.0]
rj is jacobi of [A, bb, 500]
rg is gauss_seidel of [A, bb, 500]
print of f"Jacobi Ax=b -> {rj[0]}"
print of f"Jacobi Ax=b -> {display_vector of rj[0]}"
print of f" {rj[1]} iters"
print of f"Gauss-Seidel Ax=b -> {rg[0]}"
print of f"Gauss-Seidel Ax=b -> {display_vector of rg[0]}"
print of f" {rg[1]} iters (fresh values -> fewer than Jacobi)"
print of ""

Expand All @@ -224,6 +232,6 @@ print of ""
# 3-node graph 0->{1,2}, 1->{2}, 2->{0}; column-stochastic. True stationary [0.4,0.2,0.4].
G is [[0.0, 0.0, 1.0], [0.5, 0.0, 0.0], [0.5, 1.0, 0.0]]
rr is pagerank of [G, 500]
print of f"PageRank stationary distribution -> {rr[0]} ({rr[1]} iters)"
print of f"PageRank stationary distribution -> {display_vector of rr[0]} ({rr[1]} iters)"
print of ""
print of "DONE"
29 changes: 29 additions & 0 deletions tests/check_solver_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env python3
"""Check the three numeric vectors printed by the standalone solver demo."""
import ast
import math
import re
import sys

output = sys.stdin.read()
# A @ [1, 1, 1] = b; G @ [0.4, 0.2, 0.4] = [0.4, 0.2, 0.4], sum = 1.
for label, expected in (
("Jacobi", (1.0, 1.0, 1.0)),
("Gauss-Seidel", (1.0, 1.0, 1.0)),
("PageRank", (0.4, 0.2, 0.4)),
):
rows = re.findall(r"^" + re.escape(label) + r"\s+[^\n]*?-> (\[[^\n]*?\])(?:\s|$)", output, re.M)
try:
if len(rows) != 1:
raise ValueError("expected one printed numeric vector")
values = ast.literal_eval(rows[0])
if len(values) != 3 or any(
type(value) not in (int, float)
or not math.isfinite(value)
or not math.isclose(value, want, rel_tol=0.0, abs_tol=0.0001)
for value, want in zip(values, expected)
):
raise ValueError(f"incorrect components: {values!r}")
except (ValueError, SyntaxError, TypeError) as error:
sys.exit(f"FAIL: {label}: {error}")
print(f"PASS: {label} prints all three converged components")
7 changes: 3 additions & 4 deletions tests/test_lab.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ SOUT=$("$EIGS" solve.eigs 2>&1)
echo "$SOUT"
echo "$SOUT" | grep -q "DONE" || { echo "FAIL: solve.eigs did not finish"; exit 1; }
echo "$SOUT" | grep -q "dominant eigenvalue -> 2" || { echo "FAIL: power iteration eigenvalue wrong"; exit 1; }
# PageRank true stationary is [0.4, 0.2, 0.4]
echo "$SOUT" | grep -qE "0\.3999|0\.4000" || { echo "FAIL: PageRank did not reach the stationary distribution"; exit 1; }
# both linear solves reach ~[1,1,1]
echo "$SOUT" | grep -q "0.9999" || { echo "FAIL: Jacobi/Gauss-Seidel did not converge to the solution"; exit 1; }
# Check every component on its own named row; a number printed by another
# solver must not mask a missing distribution or an incorrect component.
printf '%s\n' "$SOUT" | python3 tests/check_solver_output.py
echo "PASS: solvers converge via the predicate-driven loop (settled + hold)"
Loading