Skip to content

Commit 5afa0fb

Browse files
Oren Bassikclaude
andcommitted
fix: per-interpolator error handling to prevent HC crashes from losing results
Wrap per-interpolator body in try/catch so an InexactError(NaN) in one interpolator (e.g. S3SE) doesn't crash the entire estimation, preserving results from other interpolators. Also add per-point try/catch in solve_with_hc_parameterized so a single bad shooting point doesn't kill the whole interpolator pass. Includes resolve_states try/catch fallback and fhdn(5) fix. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 87cbf74 commit 5afa0fb

3 files changed

Lines changed: 55 additions & 15 deletions

File tree

src/core/homotopy_continuation.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,7 @@ function solve_with_hc_parameterized(poly_system, solve_vars, data_vars, param_v
917917
initial_solution_count = 0
918918

919919
for (i, current_params) in enumerate(param_values_list)
920+
try
920921
if i == 1 || isnothing(prev_all_solutions) || isempty(prev_all_solutions)
921922
# Fresh solve at first point - get ALL solutions
922923
if debug
@@ -989,6 +990,20 @@ function solve_with_hc_parameterized(poly_system, solve_vars, data_vars, param_v
989990
# Track ALL solutions to next point (real + complex)
990991
prev_all_solutions = all_solutions
991992
prev_params = current_params
993+
994+
catch e
995+
@error "[HC-PARAM] Point $i failed" exception=(e, catch_backtrace())
996+
println(stderr, "[HC-CRASH] Point $i threw $(typeof(e)): $e")
997+
println(stderr, "[HC-CRASH] current_params = $current_params")
998+
if any(isnan, current_params) || any(isinf, current_params)
999+
println(stderr, "[HC-CRASH] WARNING: current_params contains NaN/Inf!")
1000+
end
1001+
# Push empty results for this point
1002+
push!(all_real_results, Vector{Vector{Float64}}())
1003+
# Reset tracking so next point does a fresh solve
1004+
prev_all_solutions = nothing
1005+
prev_params = nothing
1006+
end
9921007
end
9931008

9941009
return all_real_results

src/core/optimized_multishot_estimation.jl

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,8 @@ function optimized_multishot_parameter_estimation(PEP::ParameterEstimationProble
12551255
interp_solutions = []
12561256
interp_time_indices = Int[]
12571257

1258+
try # Catch errors in individual interpolators so one crash doesn't lose all results
1259+
12581260
if use_param_homotopy
12591261
# ============================================================================
12601262
# PARAMETER HOMOTOPY PATH
@@ -1541,6 +1543,20 @@ function optimized_multishot_parameter_estimation(PEP::ParameterEstimationProble
15411543
end
15421544
end # end if use_param_homotopy
15431545

1546+
catch e
1547+
@error "Interpolator $interp_sym failed" exception=(e, catch_backtrace())
1548+
println(stderr, "[HC-CRASH] Interpolator $interp_sym threw $(typeof(e)): $e")
1549+
if @isdefined(param_values_list) && isa(param_values_list, AbstractVector)
1550+
println(stderr, "[HC-CRASH] param_values_list had $(length(param_values_list)) points")
1551+
for (pi, pv) in enumerate(param_values_list)
1552+
if any(isnan, pv) || any(isinf, pv)
1553+
println(stderr, "[HC-CRASH] Point $pi: contains NaN/Inf: $pv")
1554+
end
1555+
end
1556+
end
1557+
# interp_solutions is empty, so accumulation below appends nothing
1558+
end # end try/catch for interpolator
1559+
15441560
# Accumulate this pass's solutions into the global pool
15451561
append!(all_solutions, interp_solutions)
15461562
append!(solution_time_indices, interp_time_indices)
@@ -1650,20 +1666,29 @@ function optimized_multishot_parameter_estimation(PEP::ParameterEstimationProble
16501666
known_param_dict = OrderedDict{Any, Float64}(k => Float64(v) for (k, v) in params_dict)
16511667

16521668
# Algebraic re-solve at t=0 with fixed parameters
1653-
state_solutions, state_vars = resolve_states_with_fixed_params(
1654-
PEP.model.system,
1655-
PEP.measured_quantities,
1656-
PEP.data_sample,
1657-
good_deriv_level,
1658-
good_udict,
1659-
good_varlist,
1660-
good_DD,
1661-
known_param_dict,
1662-
interpolants;
1663-
si_template = si_template,
1664-
time_index = 1,
1665-
diagnostics = opts.diagnostics,
1666-
)
1669+
state_solutions = Vector{Vector{Float64}}()
1670+
state_vars = Any[]
1671+
try
1672+
state_solutions, state_vars = resolve_states_with_fixed_params(
1673+
PEP.model.system,
1674+
PEP.measured_quantities,
1675+
PEP.data_sample,
1676+
good_deriv_level,
1677+
good_udict,
1678+
good_varlist,
1679+
good_DD,
1680+
known_param_dict,
1681+
interpolants;
1682+
si_template = si_template,
1683+
time_index = 1,
1684+
diagnostics = opts.diagnostics,
1685+
)
1686+
catch e
1687+
@warn "[RESOLVE] Algebraic re-solve failed for parameter set" exception = (e, catch_backtrace())
1688+
if !opts.nooutput
1689+
println(" Algebraic re-solve failed ($(typeof(e))), falling back to data-derived ICs")
1690+
end
1691+
end
16671692

16681693
if !isempty(state_solutions)
16691694
# Build ParameterEstimationResult for each algebraic state solution

src/types/estimation_options.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ function get_interpolator_function(method::InterpolatorMethod, custom::Union{Not
344344
elseif method == InterpolatorAAADOld
345345
return aaad_old_reliable
346346
elseif method == InterpolatorFHD
347-
return fhd5 # Default to degree 5 FHD
347+
return fhdn(5) # Default to degree 5 FHD
348348
elseif method == InterpolatorAGP
349349
return agp_gpr
350350
elseif method == InterpolatorAGPRobust

0 commit comments

Comments
 (0)