Diagnostics

SolverDiagnostics captures structured data about solver behavior. It is available at result.diagnostics and printed to stderr when print_level >= 5.

Diagnostic block format

--- ripopt diagnostics ---
status: Optimal
iterations: 8
wall_time: 0.001s
final_mu: 4.14e-9
final_primal_inf: 5.55e-17
final_dual_inf: 1.04e-12
final_compl: 7.75e-9
restoration_count: 0
nlp_restoration_count: 0
mu_mode_switches: 2
filter_rejects: 0
watchdog_activations: 0
soc_corrections: 0
--- end diagnostics ---

Fields

FieldMeaning
statusFinal solve status
iterationsTotal IPM iterations
wall_time_secsTotal wall-clock time
final_muBarrier parameter at termination
final_primal_infConstraint violation at termination
final_dual_infDual infeasibility (stationarity error) at termination
final_complComplementarity error at termination
restoration_countGauss-Newton restoration entries
nlp_restoration_countFull NLP restoration entries (heavier)
mu_mode_switchesBarrier mode transitions (Free ↔ Fixed)
filter_rejectsLine search failures (backtracking exhausted)
watchdog_activationsWatchdog triggered by consecutive short steps
soc_correctionsSecond-order corrections accepted
fallback_usedWhich fallback succeeded, if any (lbfgs_hessian, augmented_lagrangian, sqp, slack)

Interpreting the diagnostics

Healthy solve (HS071-like): 0 restorations, 0 filter rejects, 2–4 mu mode switches, final_mu near 1e-9, final_primal_inf and final_dual_inf both below tol.

Struggling solve: Many filter rejects, multiple restorations, final_mu stuck above 1e-4, or a fallback was used.

Pattern → cause → fix

PatternLikely causeOptions to try
filter_rejects > 5Line search fighting constraintsIncrease mu_init, reduce kappa
restoration_count > 3Repeated feasibility recoverySet enable_slack_fallback: true, increase mu_init
mu_mode_switches > 10Free/Fixed cyclingSet mu_strategy_adaptive: false
final_mu stuck > 1e-4Barrier parameter not decreasingIncrease max_iter, reduce mu_linear_decrease_factor
fallback_used: Some(...)Primary IPM failedCheck which fallback; consider changing Hessian strategy
soc_corrections > 0Nonlinear constraints causing step rejectionNormal; increase max_soc if filter rejects are also high
watchdog_activations > 0Tiny steps detectedTry hessian_approximation_lbfgs: true

Example: healthy solve (HS071)

#![allow(unused)]
fn main() {
let result = ripopt::solve(&Hs071, &SolverOptions::default());
let d = &result.diagnostics;
assert_eq!(d.filter_rejects, 0);
assert_eq!(d.restoration_count, 0);
assert!(d.final_mu < 1e-8);
// iterations ≈ 8
}

Example: struggling solve — reading and reacting

#![allow(unused)]
fn main() {
let r1 = ripopt::solve(&problem, &opts);

if r1.status != SolveStatus::Optimal {
    let d = &r1.diagnostics;
    let mut opts2 = opts.clone();

    if d.filter_rejects > 5 {
        opts2.mu_init = 1.0;
        opts2.kappa = 3.0;
    }
    if d.restoration_count > 3 {
        opts2.enable_slack_fallback = true;
    }
    if d.final_mu > 1e-4 {
        opts2.mu_strategy_adaptive = false;
    }
    if d.mu_mode_switches > 10 {
        opts2.hessian_approximation_lbfgs = true;
    }

    let r2 = ripopt::solve(&problem, &opts2);
}
}

Using diagnostics with Claude Code

Claude Code can read the --- ripopt diagnostics --- block from stderr and automatically adjust solver options:

claude -p "
  Run: cargo run --example debug_tp374 2>&1
  Parse the diagnostics block.
  If not Optimal:
    - High filter_rejects → increase mu_init, decrease kappa
    - High restoration_count → try enable_slack_fallback
    - mu stuck high → try mu_strategy_adaptive: false
    - Large multipliers → try hessian_approximation_lbfgs: true
  Adjust options, re-run, compare. Up to 3 attempts.
"

The Rust code is a pure reporter. All intelligence — pattern matching, strategy selection — lives in Claude's reasoning.