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.profileClassificationResult.reportsolvscout.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)
| Field | Value | Notes |
|---|---|---|
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.
- 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.pyRun 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 →