Product documentation — installation, licensing, and integration guides.
SolvScout / SolvTune
Examples
02 Classify an RHS

Journey 02 — Classify an RHS

How classify() turns an RHS callback into a ProblemProfile + FeatureReport, and why you classify once and reuse the profile for recommend/compare/product.

Prerequisites: Journey 01 — import and license work. Scenario: From dynamics to a ProblemProfile + FeatureReport

Key APIs

  • solvscout.classify()
  • ClassificationResult.profile
  • ClassificationResult.report
  • solvscout.classify_from_data(t, y)

Concepts to internalize

  • Stiffness class (S0–S4) — how separated the timescales are. Robertson lands stiff; Rössler does not.
  • dynamics_type — attractor vs limit cycle vs decay; helps the corpus matcher.
  • FeatureReport — raw measurements (stiffness_max, confidence). Profile is the serializable summary.
  • classify_from_data — same routing when you have (t, y) arrays but no RHS source.

Important code

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

import solvscout as scout
 
# Rössler — chaotic, non-stiff in the Robertson sense
rossler_rhs = lambda t, y: (
    lambda x, z, w: [-z - w, x + 0.2 * z, 0.2 + w * (x - 5.7)]
)(*y)
res = scout.classify(rossler_rhs, [1, 1, 1], (0, 100))
 
p, r = res.profile, res.report
print(p.stiffness, p.dynamics_type, p.challenge_axis)
print(r.stiffness_max, r.stiffness_confidence)
 
# Alternative when you only have logged trajectories:
# scout.classify_from_data(t_array, y_array)

Act-by-act walkthrough

Act 1 — How classification works

classify() probes the RHS: it estimates the Jacobian spectrum, runs short probe integrations, and detects dynamics type and challenge axis - no hand-labelling required. It returns .profile (the summary) and .report (raw measurements).

Act 2 — Two contrasting systems

Rössler is a chaotic attractor; Robertson is the classic stiff chemistry benchmark spanning many timescales. Watch the stiffness class and dynamics_type differ.

classify() (2 steps)

FieldValueNotes
stiffnessS1
dynamics_typechaotic
challenge_axismixed_stiffness
dim3
stiffness_max704.517
stiffness_confidencelow
stiffnessS2
dynamics_typerelaxation
challenge_axisstandard
dim3
stiffness_max439416.171
stiffness_confidencemedium

Act 3 — What you got

The ProblemProfile is a compact, serializable description. Everything downstream (recommend, compare, recommend_product) consumes it - you classify once and reuse the profile.

  • classify_from_data(t_array, y_array) does the same from a recorded trajectory when you have no RHS.

Guided tour output

Verified console capture from 02_classify_rhs.py:

From dynamics to a ProblemProfile + FeatureReport

-- Act 1 - How classification works --
  -> classify() probes the RHS: it estimates the Jacobian spectrum, runs short probe integrations, and detects dynamics type and challenge axis - no hand-labelling required. It returns .profile (the summary) and .report (raw measurements).

-- Act 2 - Two contrasting systems --
  -> Rössler is a chaotic attractor; Robertson is the classic stiff chemistry benchmark spanning many timescales. Watch the stiffness class and dynamics_type differ.
  _section: classify() (2 steps)
  stiffness: S1
  dynamics_type: chaotic
  challenge_axis: mixed_stiffness
  dim: 3
  stiffness_max: 704.517
  stiffness_confidence: low
  stiffness: S2
  dynamics_type: relaxation
  challenge_axis: standard
  dim: 3
  stiffness_max: 439416.171
  stiffness_confidence: medium

-- Act 3 - What you got --
  -> The ProblemProfile is a compact, serializable description. Everything downstream (recommend, compare, recommend_product) consumes it - you classify once and reuse the profile.
  log: classify_from_data(t_array, y_array) does the same from a recorded trajectory when you have no RHS.

-- Run complete --
  next_journey: 03_recommend.py

Run it

cd python
# Guided tour — narrated scenario walkthrough (recommended first run):
python examples/journeys/02_classify_rhs.py
 
# Production one-liner — same API call you ship:
python -c "import solvscout as s; print(s.classify(lambda t,y:[-y[0]],[1.0],(0.0,1.0)).profile.stiffness)"

What comes next

Journey 03 feeds the profile into recommend() under multiple objectives.

Navigation

← Journey 01 — First contact · Journey 03 — Recommend a solver →