diff --git a/strategy/cli.py b/strategy/cli.py index a7139d7..0e30549 100644 --- a/strategy/cli.py +++ b/strategy/cli.py @@ -36,8 +36,8 @@ def build_parser() -> argparse.ArgumentParser: help="test-matrix content. 'lowrank' = compressible data " "where the strategy is accurate (default)") p.add_argument("--data-rank", type=int, default=None, - help="rank of generated matrices when --fill lowrank " - "(default n//32)") + help="rank of generated matrices for --fill lowrank / " + "decaying-spectrum (default max(1, n//32))") p.add_argument("--seed", type=int, default=0) p.add_argument("--verify", action="store_true", help="report reconstruction error vs a float64 reference") diff --git a/tests/test_data_rank_decaying_spectrum.py b/tests/test_data_rank_decaying_spectrum.py new file mode 100644 index 0000000..0bd8d65 --- /dev/null +++ b/tests/test_data_rank_decaying_spectrum.py @@ -0,0 +1,37 @@ +"""`--data-rank` controls the rank of BOTH the lowrank and decaying-spectrum +fills (storage.generate uses it for each), and its default is max(1, n//32) -- +not the bare n//32 the CLI help used to claim. These pure-NumPy checks pin that +contract, backing the corrected --data-rank help text. +""" +from __future__ import annotations + +import numpy as np + +from strategy import storage + + +def test_data_rank_sets_decaying_spectrum_rank(): + for r in (2, 8, 20): + m = storage.generate(64, np.float64, False, None, seed=0, + fill="decaying-spectrum", data_rank=r) + assert np.linalg.matrix_rank(m) == r + + +def test_data_rank_sets_lowrank_rank(): + for r in (3, 10): + m = storage.generate(64, np.float64, False, None, seed=0, + fill="lowrank", data_rank=r) + assert np.linalg.matrix_rank(m) == r + + +def test_default_data_rank_is_floored_at_one(): + # n // 32 == 0 for small n, but the default is max(1, n//32), so a + # decaying-spectrum matrix is at least rank 1 (never rank 0 / all-zero). + m = storage.generate(16, np.float64, False, None, seed=0, + fill="decaying-spectrum", data_rank=None) + assert np.linalg.matrix_rank(m) == 1 + + +if __name__ == "__main__": + import pytest + raise SystemExit(pytest.main([__file__, "-q"]))