Skip to content

Commit dc9c8e6

Browse files
orebasclaude
andcommitted
Add diagnostic framework, S3 adaptive/BIC interpolators, and transcendental UQ
Major additions: - Diagnostic framework (diagnostics.jl, svg_plots.jl): oracle Taylor coefficients, polynomial feasibility, Jacobian sensitivity analysis, and HTML report generation - S3 adaptive-tolerance and BIC model-selection interpolator variants - _obs_trfn_ observable transcendental variable support for UQ pipeline - forced_decay() test model for fast transcendental regression testing Key fixes: - GP hyperparameter optimization: replaced Zygote with ForwardDiff (Julia 1.12 compat) - Removed data jitter from GP fitting (was destroying high-order derivatives) - Adaptive Cholesky jitter for numerical stability - SE kernel derivatives: generalized to arbitrary order via Hermite recurrence - HC.jl variable replacement: two-pass longest-first to prevent substring collisions - Skip _trfn_ auxiliary observables in interpolant construction (pure waste) - UQ warnings: negative variance, high condition number, zero-variance data vars Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 6c9bbcb commit dc9c8e6

19 files changed

Lines changed: 6164 additions & 379 deletions

CLAUDE.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# ODEParameterEstimation.jl Guidelines
22

33
## Build/Test Commands
4-
- Activate the project: `julia --project`
5-
- Run tests: `julia --project -e "using Pkg; Pkg.test()"`
6-
- Run specific test: `julia --project test/specific_test.jl`
7-
- Run examples: `julia --project -e "include(\"src/examples/run_examples.jl\")"`
4+
- **Always use `--startup-file=no`** when invoking Julia (Revise.jl causes exit segfaults on Julia 1.12)
5+
- Use global Julia environment (plain `julia`, NOT `julia --project`) for running tests
6+
- Run tests: `julia --startup-file=no -e 'using ODEParameterEstimation; include("test/fast_core.jl")'`
7+
- Run feature regressions: `julia --startup-file=no -e 'using ODEParameterEstimation; include("test/feature_regressions.jl")'`
8+
- Run specific test: `julia --startup-file=no -e 'using ODEParameterEstimation; include("test/specific_test.jl")'`
9+
- Run examples: `julia --startup-file=no -e 'using ODEParameterEstimation; include("src/examples/run_examples.jl")'`
810

911
## Code Style Guidelines
1012
- Imports: Group related packages, with ModelingToolkit, OrdinaryDiffEq first

src/ODEParameterEstimation.jl

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ using TaylorDiff
3434
using NonlinearSolve, Symbolics, ForwardDiff, FiniteDiff, LinearAlgebra
3535
using NLopt, Optim, NLsolve
3636
using SciMLSensitivity
37-
using Zygote
37+
# using Zygote # Disabled: segfaults Julia 1.12 JIT compiler. ForwardDiff is used instead.
3838
using Enzyme
3939
#using OptimizationEnzyme
4040
using SymbolicUtils
@@ -88,6 +88,8 @@ include("core/optimized_multishot_estimation.jl") # New optimized workflow
8888
include("core/derivatives.jl")
8989
include("core/uncertainty_quantification.jl") # UQ via GP derivative covariances and IFT
9090
include("core/sampling.jl")
91+
include("core/svg_plots.jl")
92+
include("core/diagnostics.jl")
9193
include("examples/load_examples.jl")
9294

9395
# Export types
@@ -107,7 +109,7 @@ export unpack_ODE, tag_symbol, create_ordered_ode_system
107109
export add_relative_noise, sample_problem_data, calculate_error_stats
108110
export analyze_estimation_result, print_stats_table, cluster_solutions
109111
export clear_denoms, hmcs, analyze_parameter_estimation_problem, analyze_estimation_result
110-
export aaad, aaad_in_testing, aaad_old_reliable, AAADapprox, GPRapprox, FHDapprox, nth_deriv_at, aaad_gpr_pivot, fhdn
112+
export aaad, aaad_in_testing, aaad_old_reliable, AAADapprox, GPRapprox, FHDapprox, nth_deriv, nth_deriv_at, aaad_gpr_pivot, fhdn
111113
export AGPInterpolator, agp_gpr, agp_gpr_robust, mean_and_var
112114
export calculate_observable_derivatives, create_interpolants, AbstractInterpolator, FourierSeries, solve_with_nlopt, solve_with_nlopt_testing, solve_with_nlopt_quick, solve_with_fast_nlopt
113115
export solve_with_hc_parameterized, convert_to_hc_format_with_params, extract_data_variables_from_DD, evaluate_data_vars_at_point
@@ -121,6 +123,12 @@ export calculate_higher_derivatives, calculate_higher_derivative_terms
121123
# Export transcendental handling
122124
export detect_transcendentals, transform_pep_for_estimation, TranscendentalInfo
123125

126+
# Export diagnostic functions and types
127+
export diagnose, diagnose_model, diagnose_derivative_accuracy, diagnose_polynomial_system, diagnose_sensitivity
128+
export PerfectInterpolant, DiagnosticReport, ComprehensiveDiagnosticReport, DerivativeAccuracyReport, PolynomialFeasibilityReport, SensitivityReport
129+
export EstimationResultsReport, BacksolveUQReport, UncertaintyReport
130+
export build_perfect_interpolants, compute_oracle_taylor_coefficients, compute_observable_taylor_coefficients
131+
124132
# Export UQ (Uncertainty Quantification) functions
125133
export AGPInterpolatorUQ, agp_gpr_uq
126134
export se_kernel_derivative, se_kernel_prior_covariance_matrix, se_kernel_cross_time_covariance_matrix
@@ -131,7 +139,7 @@ export estimate_parameter_uncertainty, print_uncertainty_results
131139
# Export example models
132140
# Simple models
133141
export simple, simple_linear_combination, onesp_cubed, threesp_cubed
134-
export lotka_volterra, vanderpol, brusselator, harmonic, fitzhugh_nagumo
142+
export lotka_volterra, vanderpol, brusselator, harmonic, fitzhugh_nagumo, forced_decay
135143
export seir, treatment, biohydrogenation, repressilator
136144
export crauste, seir, daisy_mamil3, daisy_mamil4, hiv
137145
export substr_test, global_unident_test, sum_test, trivial_unident
@@ -141,11 +149,11 @@ export substr_test, global_unident_test, sum_test, trivial_unident
141149
export EstimationOptions, SystemSolverMethod, InterpolatorMethod, PolishMethod, EstimationFlow
142150
export FlowStandard, FlowDirectOpt
143151
export SolverRS, SolverHC, SolverNLOpt, SolverFastNLOpt, SolverRobust
144-
export InterpolatorAAAD, InterpolatorAAADGPR, InterpolatorAAADOld, InterpolatorFHD, InterpolatorAGP, InterpolatorAGPRobust, InterpolatorAGPRobustRQ, InterpolatorAGPRobustSEpRQ, InterpolatorAGPRobustSExRQ, InterpolatorAGPRobustMatern52, InterpolatorS2AAAMLE, InterpolatorS3SE, InterpolatorS3RQ, InterpolatorS3SEpRQ, InterpolatorS3SExRQ, InterpolatorS3Matern52, InterpolatorCustom
152+
export InterpolatorAAAD, InterpolatorAAADGPR, InterpolatorAAADOld, InterpolatorFHD, InterpolatorAGP, InterpolatorAGPRobust, InterpolatorAGPRobustRQ, InterpolatorAGPRobustSEpRQ, InterpolatorAGPRobustSExRQ, InterpolatorAGPRobustMatern52, InterpolatorAGPUQ, InterpolatorS2AAAMLE, InterpolatorS3SE, InterpolatorS3RQ, InterpolatorS3SEpRQ, InterpolatorS3SExRQ, InterpolatorS3Matern52, InterpolatorS3AdaptSE, InterpolatorS3AdaptRQ, InterpolatorS3AdaptSEpRQ, InterpolatorS3AdaptSExRQ, InterpolatorS3AdaptMatern52, InterpolatorS3BICSE, InterpolatorS3BICRQ, InterpolatorS3BICSEpRQ, InterpolatorS3BICSExRQ, InterpolatorS3BICMatern52, InterpolatorCustom
145153
export PolishNewtonTrust, PolishLevenberg, PolishGaussNewton, PolishBFGS, PolishLBFGS
146154
export get_solver_function, get_interpolator_function, get_polish_optimizer, get_ad_backend
147155
export interpolator_method_to_symbol, resolve_interpolator_list, setup_identifiability, compute_shooting_indices
148-
export is_gp_interpolator, is_matern_interpolator, s3_symbol, s3_refine_gp
156+
export is_gp_interpolator, is_matern_interpolator, s3_symbol, s3_refine_gp, s3_refine_gp_adaptive, s3_refine_gp_bic
149157
export merge_options, validate_options, print_options, get_solver_options_dict
150158
export compatibility_return_code, sync_result_contract!, lineage_summary
151159
export optimized_multishot_parameter_estimation

src/core/analysis_utils.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,12 +407,17 @@ function analyze_parameter_estimation_problem(PEP::ParameterEstimationProblem, o
407407
end
408408
# Use the best solution for UQ
409409
best_solution = first(filter(x -> !isnothing(x.err), sort(solved_res, by = x -> isnothing(x.err) ? Inf : x.err)))
410+
# Map estimation kernel to UQ kernel (UQ only supports :se and :matern52)
411+
_uq_kernel = let k = _gp_kernel_of(opts.interpolator)
412+
(k === :matern52) ? :matern52 : :se
413+
end
410414
uq_result = estimate_parameter_uncertainty(
411415
PEP,
412416
best_solution,
413417
PEP.data_sample;
414418
max_deriv_order = 2,
415419
n_timepoints = min(20, length(PEP.data_sample["t"]) ÷ 5),
420+
kernel_type = _uq_kernel,
416421
)
417422
uq_result = apply_uq_failure_policy(uq_result, opts)
418423
if !opts.nooutput

0 commit comments

Comments
 (0)