Help us shape the future of Go! Take the 2026 Go Developer Survey

conformance

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 20, 2026 License: BSD-3-Clause Imports: 19 Imported by: 0

Documentation

Overview

Package conformance compares this module with SciPy. A Generator runs the cases in both implementations through a live oracle session and records SciPy's answers as a Fixture (JSON, committed under testdata/); Verify re-runs the Go side from the fixture alone, so the regression tests need neither Python nor network.

Index

Constants

View Source
const CorpusBase = "https://math.nist.gov/pub/MatrixMarket2/Harwell-Boeing/"

CorpusBase is where the matrices come from. They carry no stated licence, so they are never copied into this repository: they are downloaded into a cache directory outside every work tree and checked against pinned SHA-256 sums.

View Source
const LiveMaxIter = 900

LiveMaxIter bounds the iterations of a live (report-only) run.

Variables

View Source
var (
	SuiteSolve = []string{"lap2d:30:30", "lap3d:12:12:12", "cd2d:30:30:2", "rnd:1000:6:1:1", "rnd:1000:6:0:2"}
	SuiteOrder = []string{"lap2d:30:30+scr:1", "lap3d:12:12:12+scr:2", "cd2d:30:30:1+scr:3", "rnd:1000:3:1:4", "rnd:1000:3:0:5"}
)

SuiteSolve and SuiteOrder name the matrices of the committed suite.

View Source
var Corpus = []CorpusEntry{
	{"bcsstruc1", "bcsstk01"}, {"bcsstruc1", "bcsstk04"}, {"bcsstruc1", "bcsstk05"},
	{"lanpro", "nos1"}, {"lanpro", "nos2"}, {"lanpro", "nos3"}, {"lanpro", "nos5"}, {"lanpro", "nos6"}, {"lanpro", "nos7"},
	{"chemwest", "west0067"}, {"chemwest", "west0479"},
	{"sherman", "sherman1"}, {"sherman", "sherman4"}, {"pores", "pores_3"},
	{"oilgen", "orsirr_1"}, {"oilgen", "orsreg_1"},
}

Corpus is the small named set (n <= 5000) used by the live comparison.

View Source
var CorpusSums = map[string]string{
	"bcsstk01": "567560f75b952d9c14c0d193ded5d80370d7ca26fe49f9e67deee55f22e55699",
	"bcsstk04": "11aa7f961f13eb47752e7f7dddaa5ffb3213c0158ef8bb1f30cae59088771694",
	"bcsstk05": "f69d081ee645980a230909473991f5d5edfd3ee1c1637c5dceb3b7a174705eb3",
	"nos1":     "22887f6f2e5d5f45cd93d4ed34e87f4ed34a10e9fe10f7b37e7b467b5ccb6e00",
	"nos2":     "2e64095a3df034ddb4739695c3f37f63a084f8b27c239dcc562a5080255e97ab",
	"nos3":     "83337fac6e0785af7043ba216cb54795b98bcab4903375f14ef23d2fc05e1def",
	"nos5":     "1317ee84c28a6380793e22ec6e70ceb75b1b5a74cb3765da7200b00e22615f16",
	"nos6":     "474a46ccf889db2ffe466e6b46d0d1b1684b80c360aaba05fc34e3c8fada2095",
	"nos7":     "c0a58a31b26cfef06aa4830940244dbc6dd28730afdd40c7246a0d511eb1c6ed",
	"west0067": "228c55ac4746e8be7bb7f7e03e590d7066cdfe9ba9c06616dd19c04104ff6adb",
	"west0479": "aa32caf765f8236338e4899ca8434fad56d524020b60a329671223e6c5d68027",
	"sherman1": "36f6d76bbfec3c4465070e92171b05ed74fda5beb4a5a0910b2237ff6de6c2fd",
	"sherman4": "6ed0608d81db3f2cb66a5f779086e2ae0856a2d5c13c682bd893e3492bdcdb97",
	"pores_3":  "254509c62d170c2cb28ed5868e899e969263bd83b2122047fb0d33836395543b",
	"orsirr_1": "402189c444c35acbd3b49eed2099ada90814b8795ea845260be5008ad43f406c",
	"orsreg_1": "56d2e8897d8a5f906b8065409fe501eecff49a39e7d5f2ee40abb12b97bb1dd7",
}

CorpusSums pins the SHA-256 of each corpus file (the .mtx.gz as served by math.nist.gov on 2026-10-17).

View Source
var OrderBounds = struct{ RCMBandwidth, RCMProfile, AMDChol, AMDLU, COLAMDLU float64 }{
	RCMBandwidth: 1.25, RCMProfile: 1.25, AMDChol: 1.15, AMDLU: 1.15, COLAMDLU: 1.2,
}

OrderBounds are the quality ratios Verify enforces (Go over reference).

Functions

func CorpusDir

func CorpusDir(getenv func(string) string, userCache func() (string, error)) (string, error)

CorpusDir returns the cache directory (GO_SPARSE_CORPUS overrides it) and refuses a directory inside a git work tree.

func DefaultSolveCases

func DefaultSolveCases(matrices []Named) []struct {
	Name string
	Case SolveCase
}

DefaultSolveCases is the committed suite: every solver on matrices of the right kind with each applicable preconditioner.

func Document

func Document(f *Fixture, live *LiveReport) string

Document renders docs/verification.md from the committed fixture (re-run on the Go side) and, when live is not nil, the corpus comparison.

func Fetch

func Fetch(dir string, get func(string) ([]byte, error), entries []CorpusEntry, sums map[string]string) (paths []string, unpinned map[string]string, err error)

Fetch makes sure every entry is in dir (as <name>.mtx.gz) and returns the paths. A file already present is reused; a downloaded or present file whose SHA-256 is pinned in sums must match it. unpinned lists the entries that had no pinned sum, with the sum observed, for the maintainer to pin.

func HTTPGet

func HTTPGet(url string) ([]byte, error)

HTTPGet fetches a URL with a timeout. (Not built for android and ios, where importing net/http pulls in cgo and the corpus download is meaningless.)

func IterTolerance

func IterTolerance(solver string, sciIters int) int

IterTolerance is the allowed difference in iteration counts between Go and SciPy for the same case: floating-point summation order differs, which moves a Krylov method by an iteration or two (more for BiCGSTAB, whose convergence is erratic).

func LSMRTable

func LSMRTable(rows []LSMRRow) string

LSMRTable renders lsmr rows.

func LSQRMatrix

func LSQRMatrix(m, n, perRow int, seed uint64) *sparse.CSR[float64]

LSQRMatrix builds a full-column-rank m x n least-squares matrix with about perRow random entries per row plus a strengthened diagonal block.

func LSQRTable

func LSQRTable(rows []LSQRRow) string

LSQRTable renders least-squares rows.

func OrderTable

func OrderTable(rows []OrderRow) string

OrderTable renders ordering rows: Go next to SciPy / SuiteSparse.

func PermHash

func PermHash(p []int) string

PermHash is a short checksum of a permutation, used to detect that an ordering changed since the fixture was generated.

func RHS

func RHS(n int) []float64

RHS is the deterministic right-hand side used for matrix a.

func RunGo

func RunGo(n Named, c SolveCase) (info, iters int, res float64, err error)

RunGo executes the Go side of a case.

func SaveFixture

func SaveFixture(path string, f *Fixture) error

SaveFixture writes f as indented JSON.

func SolveTable

func SolveTable(rows []SolveRow) string

SolveTable renders solver rows as a Markdown table.

Types

type CorpusEntry

type CorpusEntry struct{ Set, Name string }

CorpusEntry names a matrix of the NIST Matrix Market Harwell-Boeing set.

type Fixture

type Fixture struct {
	SciPy  string     `json:"scipy"`
	NumPy  string     `json:"numpy"`
	Solves []SolveFix `json:"solves"`
	LSQR   []LSQRFix  `json:"lsqr"`
	LSMR   []LSMRFix  `json:"lsmr"`
	Orders []OrderFix `json:"orders"`
}

Fixture is the committed oracle record.

func GenerateAll

func GenerateAll(s *scipy.Session) (*Fixture, error)

GenerateAll runs the whole suite against the oracle.

func LoadFixture

func LoadFixture(path string) (*Fixture, error)

LoadFixture reads a fixture file.

type LSMRFix

type LSMRFix struct {
	LSQRCase
	Sci scipy.LSMRResponse `json:"scipy"`
}

LSMRFix is an LSQRCase (the matrices are shared) with SciPy's lsmr answer.

func GenerateLSMR

func GenerateLSMR(s *scipy.Session) ([]LSMRFix, error)

GenerateLSMR runs the least-squares cases through scipy lsmr with maxiter 5n.

type LSMRRow

type LSMRRow struct {
	LSMRFix
	GoIstop, GoItn int
	GoNormR        float64
	MaxXDiff       float64
}

LSMRRow compares the two implementations on one case.

func VerifyLSMR

func VerifyLSMR(fixes []LSMRFix) ([]LSMRRow, []string)

VerifyLSMR checks stopping reason, iteration count (within 3), solution and residual norm (1e-6 relative) against the fixtures.

type LSQRCase

type LSQRCase struct {
	Matrix string  `json:"matrix"` // "m:n:perRow:seed"
	Damp   float64 `json:"damp"`
	ATol   float64 `json:"atol"`
	BTol   float64 `json:"btol"`
}

LSQRCase is one lsqr run.

func DefaultLSQRCases

func DefaultLSQRCases() []LSQRCase

DefaultLSQRCases is the committed least-squares suite.

type LSQRFix

type LSQRFix struct {
	LSQRCase
	Sci scipy.LSQRResponse `json:"scipy"`
}

LSQRFix is an LSQRCase with SciPy's answer.

func GenerateLSQR

func GenerateLSQR(s *scipy.Session) ([]LSQRFix, error)

GenerateLSQR runs the cases against the oracle.

type LSQRRow

type LSQRRow struct {
	LSQRFix
	GoIstop, GoItn int
	GoR1Norm       float64
	MaxXDiff       float64 // max |x_go - x_scipy| / max(1, |x_scipy|)
}

LSQRRow compares the two implementations on one case.

func VerifyLSQR

func VerifyLSQR(fixes []LSQRFix) ([]LSQRRow, []string)

VerifyLSQR runs the Go side and checks it against the fixtures: same stopping reason, iteration count within 3, solution and residual norm equal to 1e-6 relative.

type LiveReport

type LiveReport struct {
	Notes  []string
	Solves []SolveRow
	Orders []OrderRow
}

LiveReport holds a report-only comparison on matrices whose behaviour is not enforced (ill-conditioned corpus matrices converge erratically, so iteration counts are listed, not asserted).

func RunLive

func RunLive(s *scipy.Session, matrices []Named) LiveReport

RunLive compares Go and the oracle matrix by matrix, skipping (with a note) any case that cannot be set up, such as an IC(0) breakdown or a singular matrix for SuperLU.

type Named

type Named struct {
	Name string
	A    *sparse.CSR[float64]
	SPD  bool
}

Named is a matrix and the name it is reported under.

func Build

func Build(name string) (Named, error)

Build constructs a gallery matrix from its name: lap1d:n, lap2d:nx:ny, lap3d:nx:ny:nz, cd2d:nx:ny:peclet, rnd:n:perRow:sym:seed, each optionally followed by "+scr:seed" (symmetric random permutation).

func LoadCorpus

func LoadCorpus(paths []string) ([]Named, error)

LoadCorpus reads the files; symmetric files are treated as SPD candidates.

func Suite

func Suite(names []string) ([]Named, error)

Suite builds the named matrices.

type OrderFix

type OrderFix struct {
	Matrix string `json:"matrix"`
	N      int    `json:"n"`
	NNZ    int    `json:"nnz"`
	// RCM: bandwidth and profile after SciPy's reverse_cuthill_mckee.
	SciRCMBandwidth int `json:"sci_rcm_bandwidth"`
	SciRCMProfile   int `json:"sci_rcm_profile"`
	// AMD (symmetric matrices): Cholesky nnz under SuiteSparse AMD's
	// permutation and nnz(L+U) of SuperLU's minimum degree on A+Aᵀ.
	SuiteSparseAMDChol int    `json:"suitesparse_amd_chol,omitempty"`
	SuperLUMMDLU       int    `json:"superlu_mmd_lu,omitempty"`
	GoAMDHash          string `json:"go_amd_hash,omitempty"`
	GoAMDLU            int    `json:"go_amd_lu,omitempty"`
	// COLAMD: nnz(L+U) of SuperLU's COLAMD and of SuperLU on our ordering.
	SciCOLAMDLU  int    `json:"sci_colamd_lu"`
	NaturalLU    int    `json:"natural_lu"`
	GoCOLAMDHash string `json:"go_colamd_hash"`
	GoCOLAMDLU   int    `json:"go_colamd_lu"`
	GoRCMHash    string `json:"go_rcm_hash"`
}

OrderFix records the ordering comparison for one matrix.

func GenerateOrders

func GenerateOrders(s *scipy.Session, matrices []Named) ([]OrderFix, error)

GenerateOrders runs the ordering comparison on the oracle.

type OrderRow

type OrderRow struct {
	OrderFix
	GoRCMBandwidth, GoRCMProfile int
	GoAMDChol                    int
}

OrderRow is the Go-side measurement next to the recorded oracle values.

func VerifyOrders

func VerifyOrders(matrices []Named, fixes []OrderFix) ([]OrderRow, []string)

VerifyOrders re-runs the Go orderings and checks them against the fixture.

type PrecondSpec

type PrecondSpec string

PrecondSpec names a preconditioner: none, jacobi, ssor, ic0, ilu0, ilut.

type SolveCase

type SolveCase struct {
	Matrix  string  `json:"matrix"`
	Solver  string  `json:"solver"`
	Precond string  `json:"precond"`
	RTol    float64 `json:"rtol"`
	Restart int     `json:"restart,omitempty"`
	MaxIter int     `json:"maxiter,omitempty"` // 0: the solver default
}

SolveCase is one solver run on one matrix.

type SolveFix

type SolveFix struct {
	SolveCase
	Sci scipy.SolveResponse `json:"scipy"`
}

SolveFix is a SolveCase with SciPy's answer.

func Generate

func Generate(s *scipy.Session, matrices []Named) ([]SolveFix, error)

Generate runs the cases against the oracle.

type SolveRow

type SolveRow struct {
	SolveFix
	GoInfo, GoIters int
	GoRes           float64
}

SolveRow compares the two implementations on one case.

func Verify

func Verify(matrices []Named, fixes []SolveFix) ([]SolveRow, []string)

Verify runs the Go side of every fixture and returns the comparison rows and the list of violations.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL