@@ -8,6 +8,7 @@ using Ipopt
88using DataInterpolations
99using CasADi
1010using Pyomo
11+ using Test
1112
1213import DiffEqBase: solve
1314const M = ModelingToolkit
@@ -18,8 +19,6 @@ const ENABLE_CASADI = VERSION >= v"1.11"
1819 # Test solving without anything attached.
1920 @parameters α= 1.5 β= 1.0 γ= 3.0 δ= 1.0
2021 @variables x (.. ) y (.. )
21- t = M. t_nounits
22- D = M. D_nounits
2322
2423 eqs = [D (x (t)) ~ α * x (t) - β * x (t) * y (t),
2524 D (y (t)) ~ - γ * y (t) + δ * x (t) * y (t)]
418417 @test psol. sol. u[end ] ≈ [π, 0 , 0 , 0 ]
419418end
420419
421- @testset " Parameter estimation - JuMP" begin
420+ @testset " Parameter defaults usage" begin
421+ # Test that parameter defaults are used when not explicitly provided in op
422+ @parameters α= 1.5 β= 1.0 γ= 3.0 δ= 1.0
423+ @variables x (t) y (t)
424+
425+ eqs = [D (x) ~ α * x - β * x * y
426+ D (y) ~ - γ * y + δ * x * y]
427+
428+ sys = mtkcompile (System (eqs, t, name= :sys ))
429+ tspan = (0.0 , 1.0 )
430+ u0map = [x => 4.0 , y => 2.0 ]
431+
432+ # Only provide initial conditions, rely on parameter defaults
433+ jprob = JuMPDynamicOptProblem (sys, u0map, tspan, dt = 0.01 )
434+ jsol = solve (jprob, JuMPCollocation (Ipopt. Optimizer, constructRK4 ()))
435+
436+ # Compare with ODEProblem that also uses defaults
437+ oprob = ODEProblem (sys, u0map, tspan)
438+ osol = solve (oprob, SimpleRK4 (), dt = 0.01 )
439+
440+ @test jsol. sol. u ≈ osol. u
441+
442+ iprob = InfiniteOptDynamicOptProblem (sys, u0map, tspan, dt = 0.01 )
443+ isol = solve (iprob, InfiniteOptCollocation (Ipopt. Optimizer, InfiniteOpt. OrthogonalCollocation (3 )))
444+ @test isol. sol. u ≈ osol. u rtol= 1e-4
445+
446+ if ENABLE_CASADI
447+ cprob = CasADiDynamicOptProblem (sys, u0map, tspan, dt = 0.01 )
448+ csol = solve (cprob, CasADiCollocation (" ipopt" , constructRK4 ()))
449+ @test csol. sol. u ≈ osol. u
450+ end
451+
452+ pprob = PyomoDynamicOptProblem (sys, u0map, tspan, dt = 0.01 )
453+ psol = solve (pprob, PyomoCollocation (" ipopt" , BackwardEuler ()))
454+
455+ @test psol. sol. u ≈ osol. u rtol= 1e-2
456+ end
457+
458+ @testset " Parameter estimation" begin
422459 @parameters α = 1.5 β = 1.0 [tunable= false ] γ = 3.0 δ = 1.0
423460 @variables x (t) y (t)
424461
@@ -428,22 +465,72 @@ end
428465 @mtkcompile sys0 = System (eqs, t)
429466 tspan = (0.0 , 1.0 )
430467 u0map = [x => 4.0 , y => 2.0 ]
431- parammap = [α => 1.8 , β => 1.0 , γ => 6.5 , δ => 1.0 ]
468+ parammap = [α => 2.5 , β => 1.0 , γ => 3.0 , δ => 1.8 ]
432469
433470 oprob = ODEProblem (sys0, [u0map; parammap], tspan)
434471 osol = solve (oprob, Tsit5 ())
435472 ts = range (tspan... , length= 51 )
436473 data = osol (ts, idxs= x). u
437474
438- costs = [EvalAt (t)(x)- data[i] for (i, t) in enumerate (ts)]
439- consolidate (u, sub) = sum (abs2 .(u) )
475+ costs = [abs2 ( EvalAt (t)(x)- data[i]) for (i, t) in enumerate (ts)]
476+ consolidate (u, sub) = sum (u )
440477
441478 @mtkcompile sys = System (eqs, t; costs, consolidate)
442479
443- sys′ = subset_tunables (sys, [γ , α])
480+ sys′ = subset_tunables (sys, [δ , α])
444481 jprob = JuMPDynamicOptProblem (sys′, u0map, tspan; dt= 1 / 50 , tune_parameters= true )
445482 jsol = solve (jprob, JuMPCollocation (Ipopt. Optimizer, constructTsitouras5 ()))
446483
447- @test jsol. sol. ps[γ] ≈ 6.5 rtol= 1e-4
448- @test jsol. sol. ps[α] ≈ 1.8 rtol= 1e-4
484+ @test jsol. sol. ps[δ] ≈ 1.8 rtol= 1e-4
485+ @test jsol. sol. ps[α] ≈ 2.5 rtol= 1e-4
486+
487+ # test with different time stepping
488+
489+ jprob = JuMPDynamicOptProblem (sys′, u0map, tspan; dt= 1 / 120 , tune_parameters= true )
490+ jsol = solve (jprob, JuMPCollocation (Ipopt. Optimizer, constructTsitouras5 ()))
491+
492+ @test jsol. sol. ps[δ] ≈ 1.8 rtol= 1e-4 broken= true
493+ @test jsol. sol. ps[α] ≈ 2.5 rtol= 1e-4 broken= true
494+
495+ iprob = InfiniteOptDynamicOptProblem (sys′, u0map, tspan, dt = 1 / 50 , tune_parameters= true )
496+ isol = solve (iprob, InfiniteOptCollocation (Ipopt. Optimizer, InfiniteOpt. OrthogonalCollocation (3 )))
497+
498+ @test isol. sol. ps[δ] ≈ 1.8 rtol= 1e-3
499+ @test isol. sol. ps[α] ≈ 2.5 rtol= 1e-3
500+
501+ # test with different time stepping
502+
503+ iprob = InfiniteOptDynamicOptProblem (sys′, u0map, tspan, dt = 1 / 120 , tune_parameters= true )
504+ isol = solve (iprob, InfiniteOptCollocation (Ipopt. Optimizer, InfiniteOpt. OrthogonalCollocation (3 )))
505+
506+ @test isol. sol. ps[δ] ≈ 1.8 rtol= 1e-3
507+ @test isol. sol. ps[α] ≈ 2.5 rtol= 1e-3
508+
509+ if ENABLE_CASADI
510+ cprob = CasADiDynamicOptProblem (sys′, u0map, tspan; dt = 1 / 50 , tune_parameters= true )
511+ csol = solve (cprob, CasADiCollocation (" ipopt" , constructRK4 ()))
512+ @test csol. sol. ps[δ] ≈ 1.8 rtol= 1e-4
513+ @test csol. sol. ps[α] ≈ 2.5 rtol= 1e-4
514+
515+ # test with different time stepping
516+
517+ cprob = CasADiDynamicOptProblem (sys′, u0map, tspan; dt = 1 / 120 , tune_parameters= true )
518+ csol = solve (cprob, CasADiCollocation (" ipopt" , constructRK4 ()))
519+ @test csol. sol. ps[δ] ≈ 1.8 rtol= 1e-4 broken= false
520+ @test csol. sol. ps[α] ≈ 2.5 rtol= 1e-4 broken= true
521+ end
522+
523+ pprob = PyomoDynamicOptProblem (sys′, u0map, tspan, dt = 1 / 50 , tune_parameters= true )
524+ psol = solve (pprob, PyomoCollocation (" ipopt" , LagrangeLegendre (4 )))
525+
526+ @test psol. sol. ps[δ] ≈ 1.8 rtol= 1e-4
527+ @test psol. sol. ps[α] ≈ 2.5 rtol= 1e-4
528+
529+ # test with different time stepping
530+
531+ # pprob = PyomoDynamicOptProblem(sys′, u0map, tspan, dt = 1/120, tune_parameters=true)
532+ # psol = solve(pprob, PyomoCollocation("ipopt", LagrangeLegendre(4)))
533+
534+ # @test psol.sol.ps[δ] ≈ 1.8 rtol=1e-4
535+ # @test psol.sol.ps[α] ≈ 2.5 rtol=1e-4
449536end
0 commit comments