Product documentation — installation, licensing, and integration guides.
SolvScout / SolvTune
Examples
04 Compare arms

Journey 04 — Compare arms

Use compare() to get a four-objective corpus lookup table without running solvers locally. Understand corpus_match and source='corpus' rows.

Prerequisites: Journey 03 — you know recommend() objectives. Scenario: A corpus-backed work-precision table (no local solve)

Key APIs

  • solvscout.compare(rhs, y0, t_span)
  • Comparison.sections
  • Comparison.corpus_match
  • RunResult.source

Concepts to internalize

  • No local solve — compare() classifies, then looks up benchmark medians. nfev/wall_s are corpus statistics, not this call's cost.
  • Four sections — one per objective (precision, balanced, survival, efficiency), each with a recommended arm.
  • corpus_match — 'exact' or 'class proxy'; tells you how literally the table applies.
  • Printed table — compare() also renders a human-readable table to stdout.

Important code

The guided tour script wraps this pattern. Copy the production shape into your pipeline:

import solvscout as scout
 
# Robertson stiff chemistry
rhs = lambda t, y: [
    -0.04*y[0] + 1e4*y[1]*y[2],
    0.04*y[0] - 1e4*y[1]*y[2] - 3e7*y[1]**2,
    3e7*y[1]**2,
]
comparison = scout.compare(rhs, [1, 0, 0], (0, 100))
 
print(comparison.recommended, comparison.corpus_match)
for section in comparison.sections:
    print(section.objective, section.recommended)
    for row in section.results:
        print(row.arm, row.survived, row.nfev, row.source)  # source='corpus'

Act-by-act walkthrough

Act 1 — What compare() does

compare(rhs, y0, t_span) classifies the problem, then looks up all four SolvTune objectives (precision, balanced, survival, efficiency) from the benchmark corpus. It does NOT run solvers here - it prints the table and returns a Comparison. There is no objective= argument.

FieldValueNotes
problemstiffness S2, relaxation, dim 3
sigmaclean
evidencecorpus match: exact
accuracy'scaled err' = deterministic error vs a 1e-12 reference.
envelope3 arm(s) do not survive here: RK45, DOP853, RK23.

precision

FieldValueNotes
recommendedSolvSRK (confidence: high)
whySolvSRK - precision pick: 12.6 sig-digits, 100% survival, 106,041 fevals. +2.1 digits over Radau.
pastecfg = solvsrk.config(mode='acmode', rtol=1e-12, atol=1e-12, ek_dt=0.0001, ek_max_steps=0, timeout_s=60)
strongestSolvSRK (0.288s)
fastestLSODA (0.005s)
most efficientRadau (eff=0.31, within tol)

balanced

FieldValueNotes
recommendedSolvSRK (confidence: high)
whySolvSRK - balanced pick: 12.6 sig-digits, 100% survival, 106,041 fevals.
pastecfg = solvsrk.config(mode='acmode', rtol=1e-12, atol=1e-12, ek_dt=0.0001, ek_max_steps=0, timeout_s=60)
strongestSolvSRK (0.288s)
fastestLSODA (0.005s)
most efficientRadau (eff=0.31, within tol)

survival

FieldValueNotes
recommendedSolvSRK (confidence: high)
whySolvSRK - survival pick: 12.6 sig-digits, 100% survival, 106,041 fevals.
pastecfg = solvsrk.config(mode='acmode', rtol=1e-12, atol=1e-12, ek_dt=0.0001, ek_max_steps=0, timeout_s=60)
strongestSolvSRK (0.288s)
fastestLSODA (0.005s)
most efficientRadau (eff=0.31, within tol)

efficiency

FieldValueNotes
recommendedLSODA (confidence: high)
whyLSODA - efficiency pick: 7.4 sig-digits, 100% survival, 1,022 fevals. ~1x fewer fevals than BDF.
pastecfg = solvsrk.config(mode='acmode', rtol=1e-12, atol=1e-12, ek_dt=0.0001, ek_max_steps=0, timeout_s=60)
strongestSolvSRK (0.288s)
fastestLSODA (0.005s)
most efficientRadau (eff=0.31, within tol)
sourcebenchmark corpus
notetable lookup only — not a live run on your problem

Act 2 — The returned object

Comparison.sections has one payload per objective; each has a recommended field arm and a copy-paste solvsrk.config(...) line. corpus_match is 'exact' or 'class proxy' — never a benchmark slug.

FieldValueNotes
recommendedsolvsrk
recommended_confidencehigh
corpus_matchexact
n_sections4
n_rows7

Act 3 — Per-arm rows

Each RunResult carries status, survived, error (tol units), nfev and wall_s. source='corpus' confirms these are looked-up medians, not a live run.

precision-ranked corpus rows (7 steps)

FieldValueNotes
statuscorpus
survivedTrue
error0.0555
nfev106041
wall_s0.2876
sourcecorpus
statuscorpus
survivedTrue
error0.0892
nfev2503
wall_s0.0495
sourcecorpus
statuscorpus
survivedTrue
error0.1766
nfev1382
wall_s0.0394
sourcecorpus
statuscorpus
survivedTrue
error0.1817
nfev1022
wall_s0.0051
sourcecorpus
statuscorpus
survivedFalse
error-
nfev-
wall_s-
sourcecorpus
statuscorpus
survivedFalse
error-
nfev-
wall_s-
sourcecorpus
statuscorpus
survivedFalse
error-
nfev-
wall_s-
sourcecorpuscompare() is corpus lookup only. For live integration use solvsrk.run_profile or solvsrk.run.
problemrobertson

Guided tour output

Verified console capture from 04_compare_arms.py:

A corpus-backed work-precision table (no local solve)

-- Act 1 - What compare() does --
  -> compare(rhs, y0, t_span) classifies the problem, then looks up all four SolvTune objectives (precision, balanced, survival, efficiency) from the benchmark corpus. It does NOT run solvers here - it prints the table and returns a Comparison. There is no objective= argument.
  problem: stiffness S2, relaxation, dim 3
  sigma: clean
  evidence: corpus match: exact
  accuracy: 'scaled err' = deterministic error vs a 1e-12 reference.
  envelope: 3 arm(s) do not survive here: RK45, DOP853, RK23.
  _section: precision
  recommended: SolvSRK  (confidence: high)
  why: SolvSRK - precision pick: 12.6 sig-digits, 100% survival, 106,041 fevals. +2.1 digits over Radau.
  paste: cfg = solvsrk.config(mode='acmode', rtol=1e-12, atol=1e-12, ek_dt=0.0001, ek_max_steps=0, timeout_s=60)
  strongest: SolvSRK  (0.288s)
  fastest: LSODA  (0.005s)
  most efficient: Radau  (eff=0.31, within tol)
  _section: balanced
  recommended: SolvSRK  (confidence: high)
  why: SolvSRK - balanced pick: 12.6 sig-digits, 100% survival, 106,041 fevals.
  paste: cfg = solvsrk.config(mode='acmode', rtol=1e-12, atol=1e-12, ek_dt=0.0001, ek_max_steps=0, timeout_s=60)
  strongest: SolvSRK  (0.288s)
  fastest: LSODA  (0.005s)
  most efficient: Radau  (eff=0.31, within tol)
  _section: survival
  recommended: SolvSRK  (confidence: high)
  why: SolvSRK - survival pick: 12.6 sig-digits, 100% survival, 106,041 fevals.
  paste: cfg = solvsrk.config(mode='acmode', rtol=1e-12, atol=1e-12, ek_dt=0.0001, ek_max_steps=0, timeout_s=60)
  strongest: SolvSRK  (0.288s)
  fastest: LSODA  (0.005s)
  most efficient: Radau  (eff=0.31, within tol)
  _section: efficiency
  recommended: LSODA  (confidence: high)
  why: LSODA - efficiency pick: 7.4 sig-digits, 100% survival, 1,022 fevals. ~1x fewer fevals than BDF.
  paste: cfg = solvsrk.config(mode='acmode', rtol=1e-12, atol=1e-12, ek_dt=0.0001, ek_max_steps=0, timeout_s=60)
  strongest: SolvSRK  (0.288s)
  fastest: LSODA  (0.005s)
  most efficient: Radau  (eff=0.31, within tol)
  source: benchmark corpus
  note: table lookup only — not a live run on your problem

-- Act 2 - The returned object --
  -> Comparison.sections has one payload per objective; each has a recommended field arm and a copy-paste solvsrk.config(...) line. corpus_match is 'exact' or 'class proxy' — never a benchmark slug.
  recommended: solvsrk
  recommended_confidence: high
  corpus_match: exact
  n_sections: 4
  n_rows: 7

-- Act 3 - Per-arm rows --
  -> Each RunResult carries status, survived, error (tol units), nfev and wall_s. source='corpus' confirms these are looked-up medians, not a live run.
  _section: precision-ranked corpus rows (7 steps)
  status: corpus
  survived: True
  error: 0.0555
  nfev: 106041
  wall_s: 0.2876
  source: corpus
  status: corpus
  survived: True
  error: 0.0892
  nfev: 2503
  wall_s: 0.0495
  source: corpus
  status: corpus
  survived: True
  error: 0.1766
  nfev: 1382
  wall_s: 0.0394
  source: corpus
  status: corpus
  survived: True
  error: 0.1817
  nfev: 1022
  wall_s: 0.0051
  source: corpus
  status: corpus
  survived: False
  error: -
  nfev: -
  wall_s: -
  source: corpus
  status: corpus
  survived: False
  error: -
  nfev: -
  wall_s: -
  source: corpus
  status: corpus
  survived: False
  error: -
  nfev: -
  wall_s: -
  source: corpus
  -> compare() is corpus lookup only. For live integration use solvsrk.run_profile or solvsrk.run.
  problem: robertson

-- Run complete --
  next_journey: 05_product_profile.py
  recommended: solvsrk

Run it

cd python
# Guided tour — narrated scenario walkthrough (recommended first run):
python examples/journeys/04_compare_arms.py
 
# Production one-liner — same API call you ship:
python -c "import solvscout as s; rhs=lambda t,y:(lambda x,z,w:[-z-w,x+0.2*z,0.2+w*(x-5.7)])(*y); c=s.compare(rhs,[1,1,1],(0,100)); print(c.recommended, c.corpus_match)"

What comes next

Journey 05 mints a portable SolvSRK profile token with recommend_product().

Navigation

← Journey 03 — Recommend a solver · Journey 05 — Product profile token →