Skip to content

Construct explicit second-order AD for optimization BVPs - #573

Draft
ChrisRackauckas-Claude wants to merge 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:agent/fix-mirk-downgrade
Draft

Construct explicit second-order AD for optimization BVPs#573
ChrisRackauckas-Claude wants to merge 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:agent/fix-mirk-downgrade

Conversation

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Member

Ignore this PR until it has been reviewed by @ChrisRackauckas.

Summary

  • construct the sparse optimization AD backend with an explicit SecondOrder dense backend
  • preserve the existing sparsity-detector choices and the special handling for AutoZygote, AutoSymbolics, an existing SecondOrder, and NoAD
  • assert that the two Ipopt regression solves emit no warnings and return successful solutions

Root cause

MIRK optimization problems currently pass a first-order AutoSparse backend to OptimizationFunction. OptimizationBase can synthesize its second-order backend later, but the generic OptimizationCache now checks the original AD type first and correctly warns that an explicit second-order backend was not provided. That warning makes both existing @test_nowarn regression cases fail after OptimizationIpopt moved to the generic cache.

This change constructs the same second-order combinations that OptimizationBase would generate, but does so before the cache is initialized. SecondOrder is imported directly from its public owner, DifferentiationInterface.

The same downgrade also exposed a separate sparse constraint-Jacobian live-parameter failure. That belongs in OptimizationBase and is fixed by SciML/Optimization.jl#1270.

Dependencies

This is the BoundaryValueDiffEq companion to:

The OptimizationBase compatibility floor cannot be raised until those changes have a coordinated registered release; SciML/Optimization.jl#1287 is coordinating the sequential package version.

Validation

On clean current upstream/master, the Julia 1.10 MIRK Core downgrade with OptimizationIpopt 1.3.0 and released OptimizationBase reproduces the regression in MIRK Basic Tests: 197 passed, 2 failed, 1 errored (200 total). The failures are the two captured missing_second_order_ad warnings; the error is the structured-parameter sparse constraint-Jacobian callback.

With this branch plus the exact changes from Optimization PRs #1269 and #1270:

  • official BoundaryValueDiffEqMIRK, GROUP=Core: passed
    • Basic: 205/205 in 87m52.1s
    • NLLS: 72/72 in 38m06.3s
    • Ensemble: 10/10 in 5m19.1s
    • Singular BVP: 8/8 in 2m48.8s
    • VectorOfVector initials: 2/2 in 1m21.1s
    • Dynamic Optimization: 6/6 in 6m40.5s
  • BoundaryValueDiffEqCore, GROUP=Core: 14/14 passed
  • BoundaryValueDiffEqCore, GROUP=QA: 18/18 passed
  • direct NoAD preservation assertion: passed
  • Runic 1.7 over the repository: passed
  • git diff --check: passed

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
@github-actions

Copy link
Copy Markdown
Contributor

Benchmark Results (Julia v1.11)

Time benchmarks
master 77b8fbd... master / 77b8fbd...
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK2() 0.571 ± 0.0063 s 0.591 ± 0.0049 s 0.967 ± 0.013
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK3() 12.2 ± 0.34 ms 12.3 ± 0.23 ms 0.998 ± 0.034
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK4() 2.69 ± 0.07 ms 2.73 ± 0.097 ms 0.985 ± 0.043
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK5() 3.22 ± 0.1 ms 3.2 ± 0.1 ms 1.01 ± 0.045
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK6() 1.56 ± 0.052 ms 1.57 ± 0.062 ms 0.991 ± 0.051
Simple Pendulum/IIP/MultipleShooting(10, Tsit5; grid_coarsening = false) 1.56 ± 0.078 ms 1.53 ± 0.074 ms 1.02 ± 0.071
Simple Pendulum/IIP/MultipleShooting(10, Tsit5; grid_coarsening = true) 3.23 ± 0.16 ms 3.18 ± 0.16 ms 1.02 ± 0.072
Simple Pendulum/IIP/MultipleShooting(100, Tsit5; grid_coarsening = false) 0.0404 ± 0.0036 s 0.0401 ± 0.0037 s 1.01 ± 0.13
Simple Pendulum/IIP/MultipleShooting(100, Tsit5; grid_coarsening = true) 0.0637 ± 0.0016 s 0.0614 ± 0.0016 s 1.04 ± 0.038
Simple Pendulum/IIP/Shooting(Tsit5()) 0.178 ± 0.073 ms 0.184 ± 0.072 ms 0.97 ± 0.55
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK2() 0.736 ± 0.009 s 0.747 ± 0.013 s 0.985 ± 0.021
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK3() 16.4 ± 6.6 ms 16.5 ± 6.4 ms 0.997 ± 0.56
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK4() 3.31 ± 0.22 ms 3.25 ± 0.15 ms 1.02 ± 0.082
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK5() 3.94 ± 0.25 ms 3.93 ± 0.21 ms 1 ± 0.082
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK6() 1.88 ± 0.13 ms 1.87 ± 0.12 ms 1.01 ± 0.096
Simple Pendulum/OOP/MultipleShooting(10, Tsit5; grid_coarsening = false) 3.42 ± 0.54 ms 3.39 ± 0.71 ms 1.01 ± 0.26
Simple Pendulum/OOP/MultipleShooting(10, Tsit5; grid_coarsening = true) 6.7 ± 6.4 ms 6.56 ± 5.6 ms 1.02 ± 1.3
Simple Pendulum/OOP/MultipleShooting(100, Tsit5; grid_coarsening = false) 0.0945 ± 0.0051 s 0.089 ± 0.0068 s 1.06 ± 0.099
Simple Pendulum/OOP/MultipleShooting(100, Tsit5; grid_coarsening = true) 0.141 ± 0.0045 s 0.14 ± 0.0054 s 1.01 ± 0.051
Simple Pendulum/OOP/Shooting(Tsit5()) 0.622 ± 0.065 ms 0.617 ± 0.051 ms 1.01 ± 0.13
time_to_load 7.59 ± 0.12 s 7.58 ± 0.12 s 1 ± 0.022
Memory benchmarks
master 77b8fbd... master / 77b8fbd...
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK2() 0.389 M allocs: 0.0443 GB 0.389 M allocs: 0.0443 GB 1
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK3() 0.0436 M allocs: 4.88 MB 0.0436 M allocs: 4.88 MB 1
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK4() 15.7 k allocs: 1.65 MB 15.7 k allocs: 1.65 MB 1
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK5() 22.1 k allocs: 2.04 MB 22.1 k allocs: 2.04 MB 1
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK6() 12.8 k allocs: 1.05 MB 12.8 k allocs: 1.05 MB 1
Simple Pendulum/IIP/MultipleShooting(10, Tsit5; grid_coarsening = false) 25.5 k allocs: 1.82 MB 25.5 k allocs: 1.82 MB 1
Simple Pendulum/IIP/MultipleShooting(10, Tsit5; grid_coarsening = true) 0.049 M allocs: 3.39 MB 0.049 M allocs: 3.39 MB 1
Simple Pendulum/IIP/MultipleShooting(100, Tsit5; grid_coarsening = false) 0.553 M allocs: 0.0535 GB 0.553 M allocs: 0.0535 GB 1
Simple Pendulum/IIP/MultipleShooting(100, Tsit5; grid_coarsening = true) 0.833 M allocs: 0.0778 GB 0.833 M allocs: 0.0778 GB 1
Simple Pendulum/IIP/Shooting(Tsit5()) 4.64 k allocs: 0.224 MB 4.64 k allocs: 0.224 MB 1
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK2() 0.89 M allocs: 0.984 GB 0.89 M allocs: 0.984 GB 1
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK3() 0.0932 M allocs: 24.8 MB 0.0932 M allocs: 24.8 MB 1
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK4() 0.0324 M allocs: 3.96 MB 0.0324 M allocs: 3.96 MB 1
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK5() 0.045 M allocs: 4.99 MB 0.045 M allocs: 4.99 MB 1
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK6() 25.3 k allocs: 2.17 MB 25.3 k allocs: 2.17 MB 1
Simple Pendulum/OOP/MultipleShooting(10, Tsit5; grid_coarsening = false) 0.142 M allocs: 10.2 MB 0.142 M allocs: 10.2 MB 1
Simple Pendulum/OOP/MultipleShooting(10, Tsit5; grid_coarsening = true) 0.266 M allocs: 18.7 MB 0.266 M allocs: 18.7 MB 1
Simple Pendulum/OOP/MultipleShooting(100, Tsit5; grid_coarsening = false) 2.52 M allocs: 0.279 GB 2.52 M allocs: 0.279 GB 1
Simple Pendulum/OOP/MultipleShooting(100, Tsit5; grid_coarsening = true) 3.82 M allocs: 0.404 GB 3.82 M allocs: 0.404 GB 1
Simple Pendulum/OOP/Shooting(Tsit5()) 0.0373 M allocs: 1.69 MB 0.0373 M allocs: 1.69 MB 1
time_to_load 0.159 k allocs: 11.2 kB 0.159 k allocs: 11.2 kB 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants