diff --git a/ext/CTModelsJSON.jl b/ext/CTModelsJSON.jl index 5a4cab62..5e0bef26 100644 --- a/ext/CTModelsJSON.jl +++ b/ext/CTModelsJSON.jl @@ -342,8 +342,11 @@ function CTModels.import_ocp_solution( "control_constraints_ub_dual" => control_constraints_ub_dual, "variable_constraints_lb_dual" => variable_constraints_lb_dual, "variable_constraints_ub_dual" => variable_constraints_ub_dual, - "control_interpolation" => - get(blob, "control_interpolation", string(CTModels.Building.__control_interpolation())), + "control_interpolation" => get( + blob, + "control_interpolation", + string(CTModels.Building.__control_interpolation()), + ), ) # Add time grid data (format detection handled by helper) diff --git a/src/Building/constraint_composers.jl b/src/Building/constraint_composers.jl index ef5d0b9c..b5f6b5f3 100644 --- a/src/Building/constraint_composers.jl +++ b/src/Building/constraint_composers.jl @@ -42,8 +42,9 @@ struct CompositeConstraint{Sig,CS} <: Function funs::CS # concrete tuple of the N functions end -CompositeConstraint{Sig}(n, dims, funs) where {Sig} = - CompositeConstraint{Sig,typeof(funs)}(n, copy(dims), funs) +function CompositeConstraint{Sig}(n, dims, funs) where {Sig} + return CompositeConstraint{Sig,typeof(funs)}(n, copy(dims), funs) +end """ $(TYPEDSIGNATURES) @@ -102,7 +103,7 @@ $(TYPEDSIGNATURES) Compact string representation of [`CTModels.Building.CompositeConstraint`](@ref). """ function Base.show(io::IO, f::CompositeConstraint{Sig,CS}) where {Sig,CS} - print(io, "CompositeConstraint{:", Sig, "}(n=", f.n, ", dims=", f.dims, ")") + return print(io, "CompositeConstraint{:", Sig, "}(n=", f.n, ", dims=", f.dims, ")") end """ @@ -116,5 +117,5 @@ function Base.show( print(io, "CompositeConstraint") print(io, "\n sig: :", Sig) print(io, "\n n: ", f.n) - print(io, "\n dims: ", f.dims) + return print(io, "\n dims: ", f.dims) end diff --git a/src/Components/accessors.jl b/src/Components/accessors.jl index a8f53e8f..f3599f46 100644 --- a/src/Components/accessors.jl +++ b/src/Components/accessors.jl @@ -441,7 +441,9 @@ Return an empty block expression for an [`CTModels.Components.EmptyDefinition`]( See also: [`CTModels.Components.expression`](@ref). """ -expression(::EmptyDefinition)::Expr = :(begin end) +expression(::EmptyDefinition)::Expr = :( + begin end +) """ $(TYPEDSIGNATURES) diff --git a/src/Components/constraints_accessors.jl b/src/Components/constraints_accessors.jl index 9484001e..c85a6d17 100644 --- a/src/Components/constraints_accessors.jl +++ b/src/Components/constraints_accessors.jl @@ -31,7 +31,7 @@ Get the nonlinear path constraints from the model. See also: [`CTModels.Components.boundary_constraints_nl`](@ref), [`CTModels.Components.dim_path_constraints_nl`](@ref). """ function path_constraints_nl( - model::ConstraintsModel{TP,<:Tuple,<:Tuple,<:Tuple,<:Tuple}, + model::ConstraintsModel{TP,<:Tuple,<:Tuple,<:Tuple,<:Tuple} ) where {TP} return model.path_nl end @@ -47,7 +47,7 @@ Get the nonlinear boundary constraints from the model. See also: [`CTModels.Components.path_constraints_nl`](@ref), [`CTModels.Components.dim_boundary_constraints_nl`](@ref). """ function boundary_constraints_nl( - model::ConstraintsModel{<:Tuple,TB,<:Tuple,<:Tuple,<:Tuple}, + model::ConstraintsModel{<:Tuple,TB,<:Tuple,<:Tuple,<:Tuple} ) where {TB} return model.boundary_nl end @@ -63,7 +63,7 @@ Get the state box constraints from the model. See also: [`CTModels.Components.control_constraints_box`](@ref), [`CTModels.Components.dim_state_constraints_box`](@ref). """ function state_constraints_box( - model::ConstraintsModel{<:Tuple,<:Tuple,TS,<:Tuple,<:Tuple}, + model::ConstraintsModel{<:Tuple,<:Tuple,TS,<:Tuple,<:Tuple} ) where {TS} return model.state_box end @@ -79,7 +79,7 @@ Get the control box constraints from the model. See also: [`CTModels.Components.state_constraints_box`](@ref), [`CTModels.Components.dim_control_constraints_box`](@ref). """ function control_constraints_box( - model::ConstraintsModel{<:Tuple,<:Tuple,<:Tuple,TC,<:Tuple}, + model::ConstraintsModel{<:Tuple,<:Tuple,<:Tuple,TC,<:Tuple} ) where {TC} return model.control_box end @@ -95,7 +95,7 @@ Get the variable box constraints from the model. See also: [`CTModels.Components.state_constraints_box`](@ref), [`CTModels.Components.dim_variable_constraints_box`](@ref). """ function variable_constraints_box( - model::ConstraintsModel{<:Tuple,<:Tuple,<:Tuple,<:Tuple,TV}, + model::ConstraintsModel{<:Tuple,<:Tuple,<:Tuple,<:Tuple,TV} ) where {TV} return model.variable_box end diff --git a/src/Components/functors.jl b/src/Components/functors.jl index 33d98d8b..b85cfb81 100644 --- a/src/Components/functors.jl +++ b/src/Components/functors.jl @@ -30,13 +30,13 @@ end (f::ConstantInTime)(::Real) = f.value function Base.show(io::IO, f::ConstantInTime) - print(io, "ConstantInTime(", f.value, ")") + return print(io, "ConstantInTime(", f.value, ")") end function Base.show(io::IO, ::MIME"text/plain", f::ConstantInTime{V}) where {V} print(io, "ConstantInTime") print(io, "\n value: ", f.value) - print(io, "\n type: ", V) + return print(io, "\n type: ", V) end # ------------------------------------------------------------------------------ @@ -75,11 +75,11 @@ end (f::CoercedTrajectory)(t) = f.coerce(f.inner(t)) function Base.show(io::IO, f::CoercedTrajectory) - print(io, "CoercedTrajectory(", nameof(f.coerce), ")") + return print(io, "CoercedTrajectory(", nameof(f.coerce), ")") end function Base.show(io::IO, ::MIME"text/plain", f::CoercedTrajectory{F,C}) where {F,C} print(io, "CoercedTrajectory") print(io, "\n inner: ", nameof(typeof(f.inner))) - print(io, "\n coerce: ", nameof(f.coerce)) + return print(io, "\n coerce: ", nameof(f.coerce)) end diff --git a/src/Display/Display.jl b/src/Display/Display.jl index 768b683c..57d2a56c 100644 --- a/src/Display/Display.jl +++ b/src/Display/Display.jl @@ -61,7 +61,9 @@ include(joinpath(@__DIR__, "solution.jl")) # ----------------------------- # RecipesBase.plot stub - to be extended by CTModelsPlots extension -function RecipesBase.plot(sol::Solutions.AbstractSolution, description::Symbol...; kwargs...) +function RecipesBase.plot( + sol::Solutions.AbstractSolution, description::Symbol...; kwargs... +) throw(Exceptions.ExtensionError(:Plots; message="to plot solutions")) end diff --git a/src/Display/solution.jl b/src/Display/solution.jl index 772a584c..7879ef63 100644 --- a/src/Display/solution.jl +++ b/src/Display/solution.jl @@ -46,8 +46,12 @@ function Base.show(io::IO, ::MIME"text/plain", sol::Solutions.Solution) end if Solutions.dim_dual_variable_constraints_box(sol) > 0 && Components.dim_variable_constraints_box(Solutions.model(sol)) > 0 - println(io, " │ Var dual (lb) : ", Solutions.variable_constraints_lb_dual(sol)) - println(io, " └─ Var dual (ub) : ", Solutions.variable_constraints_ub_dual(sol)) + println( + io, " │ Var dual (lb) : ", Solutions.variable_constraints_lb_dual(sol) + ) + println( + io, " └─ Var dual (ub) : ", Solutions.variable_constraints_ub_dual(sol) + ) end end diff --git a/src/Init/init_functors.jl b/src/Init/init_functors.jl index 41ff5c43..1bd0bebf 100644 --- a/src/Init/init_functors.jl +++ b/src/Init/init_functors.jl @@ -177,7 +177,16 @@ $(TYPEDSIGNATURES) Compact string representation of [`CTModels.Init.MergedTrajectory`](@ref). """ function Base.show(io::IO, f::MergedTrajectory{F,C}) where {F,C} - print(io, "MergedTrajectory(dim=", f.dim, ", role=:", f.role, ", ncomps=", length(f.comps), ")") + return print( + io, + "MergedTrajectory(dim=", + f.dim, + ", role=:", + f.role, + ", ncomps=", + length(f.comps), + ")", + ) end """ @@ -189,5 +198,5 @@ function Base.show(io::IO, ::MIME"text/plain", f::MergedTrajectory{F,C}) where { print(io, "MergedTrajectory") print(io, "\n role: :", f.role) print(io, "\n dim: ", f.dim) - print(io, "\n ncomps: ", length(f.comps)) + return print(io, "\n ncomps: ", length(f.comps)) end diff --git a/src/Init/validation.jl b/src/Init/validation.jl index 53df567b..3674ed27 100644 --- a/src/Init/validation.jl +++ b/src/Init/validation.jl @@ -156,7 +156,9 @@ Build an initial guess from a previous solution (warm start). # Throws - `Exceptions.IncorrectArgument`: If dimensions do not match between the problem and solution. """ -function _initial_guess_from_solution(ocp::Models.AbstractModel, sol::Solutions.AbstractSolution) +function _initial_guess_from_solution( + ocp::Models.AbstractModel, sol::Solutions.AbstractSolution +) # Basic dimensional consistency checks if Models.state_dimension(ocp) != Models.state_dimension(sol.model) throw( diff --git a/src/Models/constraint_functors.jl b/src/Models/constraint_functors.jl index 7aa5e350..f3713170 100644 --- a/src/Models/constraint_functors.jl +++ b/src/Models/constraint_functors.jl @@ -27,13 +27,13 @@ function (f::SubPathConstraint)(r, t, x, u, v) end function Base.show(io::IO, f::SubPathConstraint) - print(io, "SubPathConstraint(n=", f.n, ", indices=", f.indices, ")") + return print(io, "SubPathConstraint(n=", f.n, ", indices=", f.indices, ")") end function Base.show(io::IO, ::MIME"text/plain", f::SubPathConstraint{CP,I}) where {CP,I} print(io, "SubPathConstraint") print(io, "\n n: ", f.n) - print(io, "\n indices: ", f.indices) + return print(io, "\n indices: ", f.indices) end # ------------------------------------------------------------------------------ @@ -63,13 +63,13 @@ function (f::SubBoundaryConstraint)(r, x0, xf, v) end function Base.show(io::IO, f::SubBoundaryConstraint) - print(io, "SubBoundaryConstraint(n=", f.n, ", indices=", f.indices, ")") + return print(io, "SubBoundaryConstraint(n=", f.n, ", indices=", f.indices, ")") end function Base.show(io::IO, ::MIME"text/plain", f::SubBoundaryConstraint{CP,I}) where {CP,I} print(io, "SubBoundaryConstraint") print(io, "\n n: ", f.n) - print(io, "\n indices: ", f.indices) + return print(io, "\n indices: ", f.indices) end # ------------------------------------------------------------------------------ @@ -95,16 +95,18 @@ end BoxProjection{Slot}(cidx) where {Slot} = BoxProjection{Slot,typeof(cidx)}(cidx) -(f::BoxProjection{:state})(_, x, _, _) = x[f.cidx] +(f::BoxProjection{:state})(_, x, _, _) = x[f.cidx] (f::BoxProjection{:control})(_, _, u, _) = u[f.cidx] -(f::BoxProjection{:variable})(_, _, v) = v[f.cidx] +(f::BoxProjection{:variable})(_, _, v) = v[f.cidx] function Base.show(io::IO, f::BoxProjection{Slot,CIDX}) where {Slot,CIDX} - print(io, "BoxProjection{:", Slot, "}(", f.cidx, ")") + return print(io, "BoxProjection{:", Slot, "}(", f.cidx, ")") end -function Base.show(io::IO, ::MIME"text/plain", f::BoxProjection{Slot,CIDX}) where {Slot,CIDX} +function Base.show( + io::IO, ::MIME"text/plain", f::BoxProjection{Slot,CIDX} +) where {Slot,CIDX} print(io, "BoxProjection") print(io, "\n slot: :", Slot) - print(io, "\n cidx: ", f.cidx) + return print(io, "\n cidx: ", f.cidx) end diff --git a/src/Models/model.jl b/src/Models/model.jl index bb387515..d6d49aa3 100644 --- a/src/Models/model.jl +++ b/src/Models/model.jl @@ -1322,8 +1322,9 @@ Return the nonlinear path constraints. See also: [`CTModels.Models.constraints`](@ref), [`CTModels.Components.boundary_constraints_nl`](@ref). """ -Components.path_constraints_nl(ocp::Model) = - Components.path_constraints_nl(constraints(ocp)) +function Components.path_constraints_nl(ocp::Model) + return Components.path_constraints_nl(constraints(ocp)) +end """ $(TYPEDSIGNATURES) @@ -1338,8 +1339,9 @@ Return the nonlinear boundary constraints. See also: [`CTModels.Models.constraints`](@ref), [`CTModels.Components.path_constraints_nl`](@ref). """ -Components.boundary_constraints_nl(ocp::Model) = - Components.boundary_constraints_nl(constraints(ocp)) +function Components.boundary_constraints_nl(ocp::Model) + return Components.boundary_constraints_nl(constraints(ocp)) +end """ $(TYPEDSIGNATURES) @@ -1354,8 +1356,9 @@ Return the box constraints on state. See also: [`CTModels.Models.constraints`](@ref), [`CTModels.Components.control_constraints_box`](@ref). """ -Components.state_constraints_box(ocp::Model) = - Components.state_constraints_box(constraints(ocp)) +function Components.state_constraints_box(ocp::Model) + return Components.state_constraints_box(constraints(ocp)) +end """ $(TYPEDSIGNATURES) @@ -1370,8 +1373,9 @@ Return the box constraints on control. See also: [`CTModels.Models.constraints`](@ref), [`CTModels.Components.state_constraints_box`](@ref). """ -Components.control_constraints_box(ocp::Model) = - Components.control_constraints_box(constraints(ocp)) +function Components.control_constraints_box(ocp::Model) + return Components.control_constraints_box(constraints(ocp)) +end """ $(TYPEDSIGNATURES) @@ -1386,8 +1390,9 @@ Return the box constraints on variable. See also: [`CTModels.Models.constraints`](@ref), [`CTModels.Components.state_constraints_box`](@ref). """ -Components.variable_constraints_box(ocp::Model) = - Components.variable_constraints_box(constraints(ocp)) +function Components.variable_constraints_box(ocp::Model) + return Components.variable_constraints_box(constraints(ocp)) +end """ $(TYPEDSIGNATURES) diff --git a/src/Solutions/dual_functors.jl b/src/Solutions/dual_functors.jl index 2801e41d..a361ce9d 100644 --- a/src/Solutions/dual_functors.jl +++ b/src/Solutions/dual_functors.jl @@ -23,13 +23,13 @@ end (f::DualSlice)(t) = f.duals(t)[f.idx] function Base.show(io::IO, f::DualSlice) - print(io, "DualSlice(", nameof(typeof(f.duals)), ", ", f.idx, ")") + return print(io, "DualSlice(", nameof(typeof(f.duals)), ", ", f.idx, ")") end function Base.show(io::IO, ::MIME"text/plain", f::DualSlice{D,I}) where {D,I} print(io, "DualSlice") print(io, "\n duals: ", nameof(typeof(f.duals))) - print(io, "\n idx: ", f.idx) + return print(io, "\n idx: ", f.idx) end # ------------------------------------------------------------------------------ @@ -55,12 +55,21 @@ end (f::BoxDualDiff)(t) = f.lb(t)[f.idx] - f.ub(t)[f.idx] function Base.show(io::IO, f::BoxDualDiff) - print(io, "BoxDualDiff(", nameof(typeof(f.lb)), ", ", nameof(typeof(f.ub)), ", ", f.idx, ")") + return print( + io, + "BoxDualDiff(", + nameof(typeof(f.lb)), + ", ", + nameof(typeof(f.ub)), + ", ", + f.idx, + ")", + ) end function Base.show(io::IO, ::MIME"text/plain", f::BoxDualDiff{DL,DU,I}) where {DL,DU,I} print(io, "BoxDualDiff") print(io, "\n lb: ", nameof(typeof(f.lb))) print(io, "\n ub: ", nameof(typeof(f.ub))) - print(io, "\n idx: ", f.idx) + return print(io, "\n idx: ", f.idx) end diff --git a/test/suite/building/test_constraints.jl b/test/suite/building/test_constraints.jl index ab671098..55f32b33 100644 --- a/test/suite/building/test_constraints.jl +++ b/test/suite/building/test_constraints.jl @@ -10,10 +10,10 @@ const VERBOSE = isdefined(Main, :TestData) ? Main.TestData.VERBOSE : true const SHOWTIMING = isdefined(Main, :TestData) ? Main.TestData.SHOWTIMING : true # Module-level stubs for CompositeConstraint tests (world-age safe) -_path_stub1!(r, _, x, u, _) = (r[1] = x[1] + u[1]) -_path_stub2!(r, t, x, _, _) = (r[1] = x[2]; r[2] = t) -_boundary_stub1!(r, x0, _, _) = (r[1] = x0[1]) -_boundary_stub2!(r, _, xf, _) = (r[1] = xf[1]) +_path_stub1!(r, _, x, u, _) = (r[1] = x[1] + u[1]) +_path_stub2!(r, t, x, _, _) = (r[1]=x[2]; r[2]=t) +_boundary_stub1!(r, x0, _, _) = (r[1] = x0[1]) +_boundary_stub2!(r, _, xf, _) = (r[1] = xf[1]) # Top-level helper (module-level to avoid world-age issues) """ @@ -456,7 +456,9 @@ function test_constraints() end Test.@testset "CompositeConstraint{:boundary} — two functions" begin - f = Building.CompositeConstraint{:boundary}(2, [1, 1], (_boundary_stub1!, _boundary_stub2!)) + f = Building.CompositeConstraint{:boundary}( + 2, [1, 1], (_boundary_stub1!, _boundary_stub2!) + ) val = zeros(2) f(val, [2.0], [5.0], nothing) Test.@test f isa Function @@ -469,7 +471,9 @@ function test_constraints() Test.@testset "CompositeConstraint{:boundary} — concrete fields (no capture-by-ref bug)" begin dims_orig = [1, 1] - f = Building.CompositeConstraint{:boundary}(2, dims_orig, (_boundary_stub1!, _boundary_stub2!)) + f = Building.CompositeConstraint{:boundary}( + 2, dims_orig, (_boundary_stub1!, _boundary_stub2!) + ) dims_orig[1] = 99 # mutate the original after construction val = zeros(2) f(val, [2.0], [5.0], nothing) diff --git a/test/suite/building/test_control_zero.jl b/test/suite/building/test_control_zero.jl index b899894d..d41eb4e4 100644 --- a/test/suite/building/test_control_zero.jl +++ b/test/suite/building/test_control_zero.jl @@ -502,7 +502,9 @@ function test_control_zero() mktempdir() do dir filename = joinpath(dir, "sol_zero_ctrl") Serialization.export_ocp_solution(sol; format=:JSON, filename=filename) - sol2 = Serialization.import_ocp_solution(model; format=:JSON, filename=filename) + sol2 = Serialization.import_ocp_solution( + model; format=:JSON, filename=filename + ) Test.@test Models.control_dimension(sol2) == 0 Test.@test Models.state_dimension(sol2) == 2 @@ -556,7 +558,9 @@ function test_control_zero() mktempdir() do dir filename = joinpath(dir, "sol_zero_ctrl") Serialization.export_ocp_solution(sol; format=:JLD, filename=filename) - sol2 = Serialization.import_ocp_solution(model; format=:JLD, filename=filename) + sol2 = Serialization.import_ocp_solution( + model; format=:JLD, filename=filename + ) Test.@test Models.control_dimension(sol2) == 0 Test.@test Models.state_dimension(sol2) == 2 diff --git a/test/suite/building/test_dedup.jl b/test/suite/building/test_dedup.jl index fd046fe8..8af52569 100644 --- a/test/suite/building/test_dedup.jl +++ b/test/suite/building/test_dedup.jl @@ -5,7 +5,7 @@ import CTBase.Exceptions: Exceptions import CTModels.Components: Components import CTModels.Building: Building -const VERBOSE = isdefined(Main, :TestData) ? Main.TestData.VERBOSE : true +const VERBOSE = isdefined(Main, :TestData) ? Main.TestData.VERBOSE : true const SHOWTIMING = isdefined(Main, :TestData) ? Main.TestData.SHOWTIMING : true function test_dedup() @@ -16,11 +16,11 @@ function test_dedup() # ==================================================================== Test.@testset "empty inds → aliases cleared" begin - inds = Int[] - lbs = Float64[] - ubs = Float64[] + inds = Int[] + lbs = Float64[] + ubs = Float64[] labels = Symbol[] - aliases = Vector{Symbol}[[ :existing]] # non-empty going in + aliases = Vector{Symbol}[[:existing]] # non-empty going in Building._dedup_box_constraints!(inds, lbs, ubs, labels, aliases, "state") @@ -29,9 +29,9 @@ function test_dedup() end Test.@testset "single declaration → no warning, no dedup" begin - inds = [2] - lbs = [0.0] - ubs = [1.0] + inds = [2] + lbs = [0.0] + ubs = [1.0] labels = [:a] aliases = Vector{Symbol}[] @@ -49,9 +49,9 @@ function test_dedup() Test.@testset "duplicates → intersection bounds + @warn" begin # Component 1 declared by :a (lb=0,ub=2) and :b (lb=1,ub=3) # Effective: lb=max(0,1)=1, ub=min(2,3)=2 - inds = [1, 1] - lbs = [0.0, 1.0] - ubs = [2.0, 3.0] + inds = [1, 1] + lbs = [0.0, 1.0] + ubs = [2.0, 3.0] labels = [:a, :b] aliases = Vector{Symbol}[] @@ -68,24 +68,26 @@ function test_dedup() Test.@testset "empty intersection → IncorrectArgument" begin # Component 1: lb=5, ub=3 after intersection → infeasible - inds = [1, 1] - lbs = [5.0, 0.0] - ubs = [10.0, 3.0] + inds = [1, 1] + lbs = [5.0, 0.0] + ubs = [10.0, 3.0] labels = [:x, :y] aliases = Vector{Symbol}[] Test.@test_throws Exceptions.IncorrectArgument begin redirect_stderr(devnull) do - Building._dedup_box_constraints!(inds, lbs, ubs, labels, aliases, "state") + return Building._dedup_box_constraints!( + inds, lbs, ubs, labels, aliases, "state" + ) end end end Test.@testset "sorting by component index" begin # Declare component 3 first, then 1 → result must be sorted [1, 3] - inds = [3, 1] - lbs = [0.0, -1.0] - ubs = [4.0, 2.0] + inds = [3, 1] + lbs = [0.0, -1.0] + ubs = [4.0, 2.0] labels = [:c3, :c1] aliases = Vector{Symbol}[] @@ -101,9 +103,9 @@ function test_dedup() Test.@testset "multiple components, one duplicated" begin # Component 1: declared once by :a # Component 2: declared by :b (lb=0,ub=1) and :c (lb=0.5,ub=2) → intersection lb=0.5,ub=1 - inds = [1, 2, 2] - lbs = [-1.0, 0.0, 0.5] - ubs = [ 1.0, 1.0, 2.0] + inds = [1, 2, 2] + lbs = [-1.0, 0.0, 0.5] + ubs = [1.0, 1.0, 2.0] labels = [:a, :b, :c] aliases = Vector{Symbol}[] @@ -113,7 +115,7 @@ function test_dedup() Test.@test inds == [1, 2] Test.@test lbs ≈ [-1.0, 0.5] - Test.@test ubs ≈ [ 1.0, 1.0] + Test.@test ubs ≈ [1.0, 1.0] Test.@test aliases[1] == [:a] Test.@test aliases[2] == [:b, :c] end @@ -130,7 +132,6 @@ function test_dedup() Test.@test_throws Exceptions.IncorrectArgument Building.build(constraints) end - end end diff --git a/test/suite/building/test_name_validation.jl b/test/suite/building/test_name_validation.jl index 3413da61..df6cc3b3 100644 --- a/test/suite/building/test_name_validation.jl +++ b/test/suite/building/test_name_validation.jl @@ -119,9 +119,7 @@ function test_name_validation() # Name == component (single component) - should PASS ocp = Building.PreModel() - Test.@test_nowarn Building.__validate_name_uniqueness( - ocp, "x", ["x"], :state - ) + Test.@test_nowarn Building.__validate_name_uniqueness(ocp, "x", ["x"], :state) # Duplicate components ocp = Building.PreModel() diff --git a/test/suite/components/test_components.jl b/test/suite/components/test_components.jl index 8b726b50..6e6a156f 100644 --- a/test/suite/components/test_components.jl +++ b/test/suite/components/test_components.jl @@ -90,16 +90,16 @@ function test_components() Test.@testset "ConstantInTime" begin f_scalar = Components.ConstantInTime(1.0) - Test.@test f_scalar(0.0) == 1.0 - Test.@test f_scalar(0.5) == 1.0 + Test.@test f_scalar(0.0) == 1.0 + Test.@test f_scalar(0.5) == 1.0 Test.@test f_scalar(42.0) == 1.0 f_vec = Components.ConstantInTime([1.0, 2.0]) - Test.@test f_vec(0.0) == [1.0, 2.0] + Test.@test f_vec(0.0) == [1.0, 2.0] Test.@test f_vec(99.9) == [1.0, 2.0] Test.@test f_scalar isa Function - Test.@test f_vec isa Function + Test.@test f_vec isa Function Test.@test contains(repr(f_scalar), "ConstantInTime") Test.@test contains(repr(MIME("text/plain"), f_scalar), "ConstantInTime") @@ -132,12 +132,12 @@ function test_components() end Test.@testset "objective and constraints models" begin - mayer_f = (x0, xf, _v) -> x0[1] + xf[1] + mayer_f = (x0, xf, _v) -> x0[1] + xf[1] lagrange_f = (_t, _x, u, _v) -> u[1]^2 - mayer = Components.MayerObjectiveModel(mayer_f, :min) + mayer = Components.MayerObjectiveModel(mayer_f, :min) lagrange = Components.LagrangeObjectiveModel(lagrange_f, :max) - bolza = Components.BolzaObjectiveModel(mayer_f, lagrange_f, :min) + bolza = Components.BolzaObjectiveModel(mayer_f, lagrange_f, :min) Test.@test Components.criterion(mayer) == :min Test.@test Components.criterion(lagrange) == :max diff --git a/test/suite/components/test_contracts.jl b/test/suite/components/test_contracts.jl index 9f3f2ac9..218ec8b5 100644 --- a/test/suite/components/test_contracts.jl +++ b/test/suite/components/test_contracts.jl @@ -83,9 +83,7 @@ function test_contracts() # Contract — all concrete subtypes also satisfy the contract Test.@test check_state_contract(Components.StateModel("y", ["y1"])) xf = t -> [sin(t)] - Test.@test check_state_contract( - Components.StateModelSolution("x", ["x1"], xf) - ) + Test.@test check_state_contract(Components.StateModelSolution("x", ["x1"], xf)) end # ==================================================================== @@ -167,9 +165,7 @@ function test_contracts() Test.@test_throws Exceptions.PreconditionError Components.initial_time( fm, [0.0] ) - Test.@test_throws Exceptions.PreconditionError Components.final_time( - fm, [1.0] - ) + Test.@test_throws Exceptions.PreconditionError Components.final_time(fm, [1.0]) end end end diff --git a/test/suite/components/test_model_types.jl b/test/suite/components/test_model_types.jl index 4dc929f9..9d2d6382 100644 --- a/test/suite/components/test_model_types.jl +++ b/test/suite/components/test_model_types.jl @@ -23,7 +23,9 @@ function test_model_types() Test.@testset "__is_* predicates on Model" begin times = Components.TimesModel( - Components.FixedTimeModel(0.0, "t₀"), Components.FixedTimeModel(1.0, "t_f"), "t" + Components.FixedTimeModel(0.0, "t₀"), + Components.FixedTimeModel(1.0, "t_f"), + "t", ) state = Components.StateModel("x", ["x"]) control = Components.ControlModel("u", ["u"]) @@ -78,7 +80,9 @@ function test_model_types() Test.@test Building.__is_definition_empty(ocp) times = Components.TimesModel( - Components.FixedTimeModel(0.0, "t₀"), Components.FixedTimeModel(1.0, "t_f"), "t" + Components.FixedTimeModel(0.0, "t₀"), + Components.FixedTimeModel(1.0, "t_f"), + "t", ) state = Components.StateModel("x", ["x"]) control = Components.ControlModel("u", ["u"]) @@ -125,7 +129,9 @@ function test_model_types() Test.@test !can_build(empty_ocp) times = Components.TimesModel( - Components.FixedTimeModel(0.0, "t₀"), Components.FixedTimeModel(1.0, "t_f"), "t" + Components.FixedTimeModel(0.0, "t₀"), + Components.FixedTimeModel(1.0, "t_f"), + "t", ) state = Components.StateModel("x", ["x"]) control = Components.ControlModel("u", ["u"]) diff --git a/test/suite/init/test_initial_guess_api.jl b/test/suite/init/test_initial_guess_api.jl index b476c5fb..87abdf01 100644 --- a/test/suite/init/test_initial_guess_api.jl +++ b/test/suite/init/test_initial_guess_api.jl @@ -198,9 +198,7 @@ function test_initial_guess_api() ocp = DummyOCP1DNoVar() # Unsupported type should throw - Test.@test_throws Exceptions.IncorrectArgument Init.build_initial_guess( - ocp, 42 - ) + Test.@test_throws Exceptions.IncorrectArgument Init.build_initial_guess(ocp, 42) Test.@test_throws Exceptions.IncorrectArgument Init.build_initial_guess( ocp, "invalid" ) diff --git a/test/suite/init/test_initial_guess_control.jl b/test/suite/init/test_initial_guess_control.jl index 8cd7593d..cf220fb6 100644 --- a/test/suite/init/test_initial_guess_control.jl +++ b/test/suite/init/test_initial_guess_control.jl @@ -46,9 +46,7 @@ function test_initial_guess_control() Test.@test result(0.0) == 0.5 ocp_2d = DummyOCP2D() - Test.@test_throws Exceptions.IncorrectArgument Init.initial_control( - ocp_2d, 0.5 - ) + Test.@test_throws Exceptions.IncorrectArgument Init.initial_control(ocp_2d, 0.5) end Test.@testset "initial_control with Vector" begin diff --git a/test/suite/init/test_initial_guess_state.jl b/test/suite/init/test_initial_guess_state.jl index d379f2b7..abbce38b 100644 --- a/test/suite/init/test_initial_guess_state.jl +++ b/test/suite/init/test_initial_guess_state.jl @@ -47,9 +47,7 @@ function test_initial_guess_state() Test.@test result(0.0) == 0.5 ocp_2d = DummyOCP2DState() - Test.@test_throws Exceptions.IncorrectArgument Init.initial_state( - ocp_2d, 0.5 - ) + Test.@test_throws Exceptions.IncorrectArgument Init.initial_state(ocp_2d, 0.5) end Test.@testset "initial_state with Vector" begin @@ -59,9 +57,7 @@ function test_initial_guess_state() Test.@test result isa Function Test.@test result(0.0) == [0.0, 1.0] - Test.@test_throws Exceptions.IncorrectArgument Init.initial_state( - ocp, [0.0] - ) + Test.@test_throws Exceptions.IncorrectArgument Init.initial_state(ocp, [0.0]) end Test.@testset "initial_state with Nothing" begin diff --git a/test/suite/init/test_initial_guess_validation.jl b/test/suite/init/test_initial_guess_validation.jl index 87607046..2d103b8d 100644 --- a/test/suite/init/test_initial_guess_validation.jl +++ b/test/suite/init/test_initial_guess_validation.jl @@ -129,11 +129,7 @@ function test_initial_guess_validation() Test.@testset "dimension validation - incorrect variable dimension" begin ocp = DummyOCP1DVar() - init_bad = Init.InitialGuess( - t -> 0.1, - t -> 0.1, - [0.1, 0.2], - ) + init_bad = Init.InitialGuess(t -> 0.1, t -> 0.1, [0.1, 0.2]) Test.@test_throws Exceptions.IncorrectArgument Init.validate_initial_guess( ocp, init_bad diff --git a/test/suite/init/test_initial_guess_variable.jl b/test/suite/init/test_initial_guess_variable.jl index f23b6670..d6eee8b0 100644 --- a/test/suite/init/test_initial_guess_variable.jl +++ b/test/suite/init/test_initial_guess_variable.jl @@ -56,9 +56,7 @@ function test_initial_guess_variable() result = Init.initial_variable(ocp, [0.0, 1.0]) Test.@test result == [0.0, 1.0] - Test.@test_throws Exceptions.IncorrectArgument Init.initial_variable( - ocp, [0.0] - ) + Test.@test_throws Exceptions.IncorrectArgument Init.initial_variable(ocp, [0.0]) end Test.@testset "initial_variable with Nothing" begin diff --git a/test/suite/integration/test_ocp.jl b/test/suite/integration/test_ocp.jl index 27d6b676..276ec925 100644 --- a/test/suite/integration/test_ocp.jl +++ b/test/suite/integration/test_ocp.jl @@ -65,9 +65,7 @@ function test_ocp() pre_constraints, :path, n, m, q; f=f_path_a, lb=[0, 1], ub=[1, 2] ) f_path_b(r, t, x, u, v) = r .= x[1] + u[1] + v[1] + t - Building.__constraint!( - pre_constraints, :path, n, m, q; f=f_path_b, lb=[3], ub=[3] - ) + Building.__constraint!(pre_constraints, :path, n, m, q; f=f_path_b, lb=[3], ub=[3]) # boundary constraint f_boundary_a(r, x0, xf, v) = r .= x0 .+ v .* (xf .- x0) @@ -88,20 +86,14 @@ function test_ocp() # state box Building.__constraint!(pre_constraints, :state, n, m, q; lb=[0, 1], ub=[1, 2]) - Building.__constraint!( - pre_constraints, :state, n, m, q; rg=2:2, lb=[1], ub=[1.5] - ) + Building.__constraint!(pre_constraints, :state, n, m, q; rg=2:2, lb=[1], ub=[1.5]) # control box Building.__constraint!(pre_constraints, :control, n, m, q; lb=[0, 1], ub=[1, 2]) - Building.__constraint!( - pre_constraints, :control, n, m, q; rg=2:2, lb=[1], ub=[1.5] - ) + Building.__constraint!(pre_constraints, :control, n, m, q; rg=2:2, lb=[1], ub=[1.5]) # variable box - Building.__constraint!( - pre_constraints, :variable, n, m, q; lb=[0, 1], ub=[1, 2] - ) + Building.__constraint!(pre_constraints, :variable, n, m, q; lb=[0, 1], ub=[1, 2]) Building.__constraint!( pre_constraints, :variable, n, m, q; rg=2:2, lb=[1], ub=[1.5] ) @@ -252,7 +244,9 @@ function test_ocp() # -------------------------------------------------------------------------- # # ocp with fixed times times = Components.TimesModel( - Components.FixedTimeModel(0.0, "t₀"), Components.FixedTimeModel(10.0, "t_f"), "t" + Components.FixedTimeModel(0.0, "t₀"), + Components.FixedTimeModel(10.0, "t_f"), + "t", ) ocp = Models.Model{Components.NonAutonomous}( times, diff --git a/test/suite/meta/test_CTModels.jl b/test/suite/meta/test_CTModels.jl index 6bf06823..a0a3a9cb 100644 --- a/test/suite/meta/test_CTModels.jl +++ b/test/suite/meta/test_CTModels.jl @@ -60,8 +60,13 @@ function test_CTModels() # Type aliases for sym in [ - :Dimension, :ctNumber, :Time, :ctVector, :Times, - :TimesDisc, :ConstraintsDictType, + :Dimension, + :ctNumber, + :Time, + :ctVector, + :Times, + :TimesDisc, + :ConstraintsDictType, ] Test.@test sym in exported end @@ -78,24 +83,31 @@ function test_CTModels() # Control for sym in [ - :AbstractControlModel, :ControlModel, - :ControlModelSolution, :EmptyControlModel, + :AbstractControlModel, + :ControlModel, + :ControlModelSolution, + :EmptyControlModel, ] Test.@test sym in exported end # Variable for sym in [ - :AbstractVariableModel, :VariableModel, - :VariableModelSolution, :EmptyVariableModel, + :AbstractVariableModel, + :VariableModel, + :VariableModelSolution, + :EmptyVariableModel, ] Test.@test sym in exported end # Time models for sym in [ - :AbstractTimeModel, :FixedTimeModel, :FreeTimeModel, - :AbstractTimesModel, :TimesModel, + :AbstractTimeModel, + :FixedTimeModel, + :FreeTimeModel, + :AbstractTimesModel, + :TimesModel, ] Test.@test sym in exported end @@ -103,7 +115,9 @@ function test_CTModels() # Objective for sym in [ :AbstractObjectiveModel, - :MayerObjectiveModel, :LagrangeObjectiveModel, :BolzaObjectiveModel, + :MayerObjectiveModel, + :LagrangeObjectiveModel, + :BolzaObjectiveModel, ] Test.@test sym in exported end @@ -125,32 +139,50 @@ function test_CTModels() # Time model accessors for sym in [ - :index, :initial, :final, - :time_name, :initial_time_name, :final_time_name, - :initial_time, :final_time, - :has_fixed_initial_time, :has_free_initial_time, - :has_fixed_final_time, :has_free_final_time, - :is_initial_time_fixed, :is_initial_time_free, - :is_final_time_fixed, :is_final_time_free, + :index, + :initial, + :final, + :time_name, + :initial_time_name, + :final_time_name, + :initial_time, + :final_time, + :has_fixed_initial_time, + :has_free_initial_time, + :has_fixed_final_time, + :has_free_final_time, + :is_initial_time_fixed, + :is_initial_time_free, + :is_final_time_fixed, + :is_final_time_free, ] Test.@test sym in exported end # Objective accessors for sym in [ - :criterion, :mayer, :lagrange, - :has_mayer_cost, :has_lagrange_cost, - :is_mayer_cost_defined, :is_lagrange_cost_defined, + :criterion, + :mayer, + :lagrange, + :has_mayer_cost, + :has_lagrange_cost, + :is_mayer_cost_defined, + :is_lagrange_cost_defined, ] Test.@test sym in exported end # Constraints accessors for sym in [ - :path_constraints_nl, :boundary_constraints_nl, - :state_constraints_box, :control_constraints_box, :variable_constraints_box, - :dim_path_constraints_nl, :dim_boundary_constraints_nl, - :dim_state_constraints_box, :dim_control_constraints_box, + :path_constraints_nl, + :boundary_constraints_nl, + :state_constraints_box, + :control_constraints_box, + :variable_constraints_box, + :dim_path_constraints_nl, + :dim_boundary_constraints_nl, + :dim_state_constraints_box, + :dim_control_constraints_box, :dim_variable_constraints_box, ] Test.@test sym in exported diff --git a/test/suite/models/test_build_examodel.jl b/test/suite/models/test_build_examodel.jl index 3cef35a7..4222799e 100644 --- a/test/suite/models/test_build_examodel.jl +++ b/test/suite/models/test_build_examodel.jl @@ -36,9 +36,7 @@ function test_build_examodel() model = Building.build(ocp) # Attempting to get build_examodel should throw PreconditionError - Test.@test_throws Exceptions.PreconditionError Models.get_build_examodel( - model - ) + Test.@test_throws Exceptions.PreconditionError Models.get_build_examodel(model) # Verify the error message contains the key information try diff --git a/test/suite/models/test_model.jl b/test/suite/models/test_model.jl index d10213ec..ca001f7a 100644 --- a/test/suite/models/test_model.jl +++ b/test/suite/models/test_model.jl @@ -122,14 +122,32 @@ function test_model() # warnings are emitted; redirect_stderr(devnull) suppresses them from # the test output. model = Test.@test_logs( - (:warn, r"Multiple bound declarations for state component 1 \(labels: state, state_scalar\)"), - (:warn, r"Multiple bound declarations for state component 2 \(labels: state, state_scalar_2\)"), - (:warn, r"Multiple bound declarations for control component 1 \(labels: control, control_scalar\)"), - (:warn, r"Multiple bound declarations for control component 2 \(labels: control, control_scalar_2\)"), - (:warn, r"Multiple bound declarations for variable component 1 \(labels: variable, variable_scalar\)"), - (:warn, r"Multiple bound declarations for variable component 2 \(labels: variable, variable_scalar_2\)"), + ( + :warn, + r"Multiple bound declarations for state component 1 \(labels: state, state_scalar\)", + ), + ( + :warn, + r"Multiple bound declarations for state component 2 \(labels: state, state_scalar_2\)", + ), + ( + :warn, + r"Multiple bound declarations for control component 1 \(labels: control, control_scalar\)", + ), + ( + :warn, + r"Multiple bound declarations for control component 2 \(labels: control, control_scalar_2\)", + ), + ( + :warn, + r"Multiple bound declarations for variable component 1 \(labels: variable, variable_scalar\)", + ), + ( + :warn, + r"Multiple bound declarations for variable component 2 \(labels: variable, variable_scalar_2\)", + ), redirect_stderr(devnull) do - Building.build(pre_ocp) + return Building.build(pre_ocp) end ) @@ -146,12 +164,15 @@ function test_model() # test the functions Test.@test Models.constraint(model, :path)[2](t, x, u, v) == x .+ u .+ v .+ t - Test.@test Models.constraint(model, :boundary)[2](x0, xf, v) == x0 .+ v .* (xf .- x0) + Test.@test Models.constraint(model, :boundary)[2](x0, xf, v) == + x0 .+ v .* (xf .- x0) Test.@test Models.constraint(model, :state)[2](t, x, u, v) == x Test.@test Models.constraint(model, :control)[2](t, x, u, v) == u Test.@test Models.constraint(model, :variable)[2](x0, xf, v) == v - Test.@test Models.constraint(model, :path_scalar)[2](t, x, u, v) == x[1] + u[1] + v[1] + t - Test.@test Models.constraint(model, :boundary_scalar)[2](x0, xf, v) == x0[1] + v[1] * (xf[1] - x0[1]) + Test.@test Models.constraint(model, :path_scalar)[2](t, x, u, v) == + x[1] + u[1] + v[1] + t + Test.@test Models.constraint(model, :boundary_scalar)[2](x0, xf, v) == + x0[1] + v[1] * (xf[1] - x0[1]) Test.@test Models.constraint(model, :state_scalar)[2](t, x, u, v) == x[1] Test.@test Models.constraint(model, :control_scalar)[2](t, x, u, v) == u[1] Test.@test Models.constraint(model, :variable_scalar)[2](x0, xf, v) == v[1] @@ -213,7 +234,7 @@ function test_model() # print the premodel (captured, no terminal output) redirect_stderr(devnull) do io = IOBuffer() - show(io, MIME"text/plain"(), pre_ocp) + return show(io, MIME"text/plain"(), pre_ocp) end # -------------------------------------------------------------------------- # @@ -230,7 +251,7 @@ function test_model() Building.time_dependence!(pre_ocp; autonomous=false) io = IOBuffer() redirect_stderr(devnull) do - show(io, MIME"text/plain"(), pre_ocp) + return show(io, MIME"text/plain"(), pre_ocp) end # @@ -245,7 +266,7 @@ function test_model() Building.time_dependence!(pre_ocp; autonomous=true) io = IOBuffer() redirect_stderr(devnull) do - show(io, MIME"text/plain"(), pre_ocp) + return show(io, MIME"text/plain"(), pre_ocp) end # ==================================================================== @@ -428,7 +449,9 @@ function test_model() Building.time_dependence!(pre; autonomous=false) m = Building.build(pre) - Test.@test_throws Exceptions.IncorrectArgument Models.constraint(m, :nonexistent) + Test.@test_throws Exceptions.IncorrectArgument Models.constraint( + m, :nonexistent + ) end # ==================================================================== @@ -486,7 +509,6 @@ function test_model() end Test.@testset "BoxProjection, SubPathConstraint, SubBoundaryConstraint" verbose=VERBOSE showtiming=SHOWTIMING begin - Test.@testset "BoxProjection{:state} — scalar" begin f = Models.BoxProjection{:state}(2) Test.@test f isa Function @@ -518,7 +540,7 @@ function test_model() Test.@testset "SubPathConstraint" begin # stub cp tuple: (lb, fun!, ub, labels, aliases) # fun!(r, t, x, u, v) fills r with [t, x[1], u[1]] - _cp_fun!(r, t, x, u, _) = (r[1] = t; r[2] = x[1]; r[3] = u[1]) + _cp_fun!(r, t, x, u, _) = (r[1]=t; r[2]=x[1]; r[3]=u[1]) cp = ([0.0, 0.0, 0.0], _cp_fun!, [1.0, 1.0, 1.0], [:a, :b, :c], []) f = Models.SubPathConstraint(cp, 3, [2, 3]) r = zeros(2) @@ -530,7 +552,7 @@ function test_model() end Test.@testset "SubBoundaryConstraint" begin - _cp_fun!(r, x0, xf, _) = (r[1] = x0[1]; r[2] = xf[1]) + _cp_fun!(r, x0, xf, _) = (r[1]=x0[1]; r[2]=xf[1]) cp = ([0.0, 0.0], _cp_fun!, [1.0, 1.0], [:a, :b], []) f = Models.SubBoundaryConstraint(cp, 2, [2]) r = zeros(1) diff --git a/test/suite/serialization/test_export_import.jl b/test/suite/serialization/test_export_import.jl index 6da4f720..b85eaec9 100644 --- a/test/suite/serialization/test_export_import.jl +++ b/test/suite/serialization/test_export_import.jl @@ -279,7 +279,9 @@ function test_export_import() Test.@testset "JSON round-trip: TestProblems.solution_example (function)" begin ocp, sol = TestProblems.solution_example(; fun=true) - Serialization.export_ocp_solution(sol; filename="solution_test_fun", format=:JSON) + Serialization.export_ocp_solution( + sol; filename="solution_test_fun", format=:JSON + ) sol_reloaded = Serialization.import_ocp_solution( ocp; filename="solution_test_fun", format=:JSON ) @@ -463,7 +465,9 @@ function test_export_import() Test.@testset "JSON import: all fields reconstructed" begin ocp, sol = TestProblems.solution_example_dual() - Serialization.export_ocp_solution(sol; filename="solution_import_test", format=:JSON) + Serialization.export_ocp_solution( + sol; filename="solution_import_test", format=:JSON + ) sol_reloaded = Serialization.import_ocp_solution( ocp; filename="solution_import_test", format=:JSON ) @@ -483,8 +487,7 @@ function test_export_import() 1e-10 # Metadata: dimensions, names, components and time labels - Test.@test Models.state_dimension(sol_reloaded) == - Models.state_dimension(sol) + Test.@test Models.state_dimension(sol_reloaded) == Models.state_dimension(sol) Test.@test Models.control_dimension(sol_reloaded) == Models.control_dimension(sol) Test.@test Models.variable_dimension(sol_reloaded) == @@ -494,8 +497,7 @@ function test_export_import() Test.@test Models.control_name(sol_reloaded) == Models.control_name(sol) Test.@test Models.variable_name(sol_reloaded) == Models.variable_name(sol) - Test.@test Models.state_components(sol_reloaded) == - Models.state_components(sol) + Test.@test Models.state_components(sol_reloaded) == Models.state_components(sol) Test.@test Models.control_components(sol_reloaded) == Models.control_components(sol) Test.@test Models.variable_components(sol_reloaded) == @@ -633,7 +635,9 @@ function test_export_import() # TestProblems.solution_example has no duals ocp, sol = TestProblems.solution_example() - Serialization.export_ocp_solution(sol; filename="solution_no_duals", format=:JSON) + Serialization.export_ocp_solution( + sol; filename="solution_no_duals", format=:JSON + ) # Read raw JSON json_string = read("solution_no_duals.json", String) @@ -706,7 +710,9 @@ function test_export_import() Test.@test Solutions.infos(sol)[:tolerance] == 1e-6 # Export and import - Serialization.export_ocp_solution(sol; filename="solution_with_infos", format=:JSON) + Serialization.export_ocp_solution( + sol; filename="solution_with_infos", format=:JSON + ) sol_reloaded = Serialization.import_ocp_solution( ocp; filename="solution_with_infos", format=:JSON ) @@ -740,13 +746,17 @@ function test_export_import() ocp, sol0 = TestProblems.solution_example_dual() # First cycle: sol0 → export → import → sol1 - Serialization.export_ocp_solution(sol0; filename="idempotence_json_1", format=:JSON) + Serialization.export_ocp_solution( + sol0; filename="idempotence_json_1", format=:JSON + ) sol1 = Serialization.import_ocp_solution( ocp; filename="idempotence_json_1", format=:JSON ) # Second cycle: sol1 → export → import → sol2 - Serialization.export_ocp_solution(sol1; filename="idempotence_json_2", format=:JSON) + Serialization.export_ocp_solution( + sol1; filename="idempotence_json_2", format=:JSON + ) sol2 = Serialization.import_ocp_solution( ocp; filename="idempotence_json_2", format=:JSON ) @@ -763,19 +773,25 @@ function test_export_import() ocp, sol0 = TestProblems.solution_example_dual() # First cycle - Serialization.export_ocp_solution(sol0; filename="idempotence_json_t1", format=:JSON) + Serialization.export_ocp_solution( + sol0; filename="idempotence_json_t1", format=:JSON + ) sol1 = Serialization.import_ocp_solution( ocp; filename="idempotence_json_t1", format=:JSON ) # Second cycle - Serialization.export_ocp_solution(sol1; filename="idempotence_json_t2", format=:JSON) + Serialization.export_ocp_solution( + sol1; filename="idempotence_json_t2", format=:JSON + ) sol2 = Serialization.import_ocp_solution( ocp; filename="idempotence_json_t2", format=:JSON ) # Third cycle - Serialization.export_ocp_solution(sol2; filename="idempotence_json_t3", format=:JSON) + Serialization.export_ocp_solution( + sol2; filename="idempotence_json_t3", format=:JSON + ) sol3 = Serialization.import_ocp_solution( ocp; filename="idempotence_json_t3", format=:JSON ) @@ -894,13 +910,17 @@ function test_export_import() ocp, sol0 = TestProblems.solution_example_dual() # First cycle: sol0 → export → import → sol1 - Serialization.export_ocp_solution(sol0; filename="idempotence_jld_1", format=:JLD) + Serialization.export_ocp_solution( + sol0; filename="idempotence_jld_1", format=:JLD + ) sol1 = Serialization.import_ocp_solution( ocp; filename="idempotence_jld_1", format=:JLD ) # Second cycle: sol1 → export → import → sol2 - Serialization.export_ocp_solution(sol1; filename="idempotence_jld_2", format=:JLD) + Serialization.export_ocp_solution( + sol1; filename="idempotence_jld_2", format=:JLD + ) sol2 = Serialization.import_ocp_solution( ocp; filename="idempotence_jld_2", format=:JLD ) @@ -917,19 +937,25 @@ function test_export_import() ocp, sol0 = TestProblems.solution_example_dual() # First cycle - Serialization.export_ocp_solution(sol0; filename="idempotence_jld_t1", format=:JLD) + Serialization.export_ocp_solution( + sol0; filename="idempotence_jld_t1", format=:JLD + ) sol1 = Serialization.import_ocp_solution( ocp; filename="idempotence_jld_t1", format=:JLD ) # Second cycle - Serialization.export_ocp_solution(sol1; filename="idempotence_jld_t2", format=:JLD) + Serialization.export_ocp_solution( + sol1; filename="idempotence_jld_t2", format=:JLD + ) sol2 = Serialization.import_ocp_solution( ocp; filename="idempotence_jld_t2", format=:JLD ) # Third cycle - Serialization.export_ocp_solution(sol2; filename="idempotence_jld_t3", format=:JLD) + Serialization.export_ocp_solution( + sol2; filename="idempotence_jld_t3", format=:JLD + ) sol3 = Serialization.import_ocp_solution( ocp; filename="idempotence_jld_t3", format=:JLD ) @@ -978,7 +1004,9 @@ function test_export_import() ocp, sol = TestProblems.solution_example() # Export to JSON - Serialization.export_ocp_solution(sol; filename="stack_investigation", format=:JSON) + Serialization.export_ocp_solution( + sol; filename="stack_investigation", format=:JSON + ) # Read and observe what stack() returns json_string = read("stack_investigation.json", String) @@ -1217,7 +1245,9 @@ function test_export_import() ) # Export to JSON (will not include control_interpolation field) - Serialization.export_ocp_solution(sol_old; filename="test_old_format", format=:JSON) + Serialization.export_ocp_solution( + sol_old; filename="test_old_format", format=:JSON + ) # Manually remove control_interpolation from JSON to simulate old format json_string = read("test_old_format.json", String) @@ -1284,7 +1314,9 @@ function test_export_import() ) # Export to JLD2 - Serialization.export_ocp_solution(sol_linear; filename="test_mixed_jld", format=:JLD) + Serialization.export_ocp_solution( + sol_linear; filename="test_mixed_jld", format=:JLD + ) sol_jld_reloaded = Serialization.import_ocp_solution( ocp; filename="test_mixed_jld", format=:JLD ) diff --git a/test/suite/serialization/test_multi_grids.jl b/test/suite/serialization/test_multi_grids.jl index 311f2144..984c0e8d 100644 --- a/test/suite/serialization/test_multi_grids.jl +++ b/test/suite/serialization/test_multi_grids.jl @@ -159,7 +159,9 @@ function test_multi_grids() ) # Export - Serialization.export_ocp_solution(sol_multi; filename="multi_grid_test", format=:JLD) + Serialization.export_ocp_solution( + sol_multi; filename="multi_grid_test", format=:JLD + ) # Import sol_reloaded = Serialization.import_ocp_solution( @@ -185,8 +187,7 @@ function test_multi_grids() Test.@test Models.state(sol_reloaded)(t) ≈ Models.state(sol_multi)(t) atol=1e-8 end for t in T_control - Test.@test Models.control(sol_reloaded)(t) ≈ - Models.control(sol_multi)(t) atol=1e-8 + Test.@test Models.control(sol_reloaded)(t) ≈ Models.control(sol_multi)(t) atol=1e-8 end remove_if_exists("multi_grid_test.jld2") @@ -584,7 +585,8 @@ function test_multi_grids() Test.@test Solutions.time_grid(sol_reconstructed, :control) ≈ T_control Test.@test Solutions.time_grid(sol_reconstructed, :costate) ≈ T_costate Test.@test Solutions.time_grid(sol_reconstructed, :dual) ≈ T_path - Test.@test Solutions.objective(sol_reconstructed) ≈ Solutions.objective(sol_orig) + Test.@test Solutions.objective(sol_reconstructed) ≈ + Solutions.objective(sol_orig) end # ==================================================================== @@ -698,7 +700,7 @@ function test_multi_grids() end end open("compat_tgd_legacy.json", "w") do f - JSON3.write(f, legacy_data) + return JSON3.write(f, legacy_data) end # Import from legacy file — should transparently map time_grid_dual @@ -710,8 +712,10 @@ function test_multi_grids() Test.@test Solutions.time_grid_model(sol_reimported) isa Solutions.MultipleTimeGridModel Test.@test Solutions.time_grid(sol_reimported, :state) ≈ T_state atol = 1e-10 - Test.@test Solutions.time_grid(sol_reimported, :control) ≈ T_control atol = 1e-10 - Test.@test Solutions.time_grid(sol_reimported, :costate) ≈ T_costate atol = 1e-10 + Test.@test Solutions.time_grid(sol_reimported, :control) ≈ T_control atol = + 1e-10 + Test.@test Solutions.time_grid(sol_reimported, :costate) ≈ T_costate atol = + 1e-10 Test.@test Solutions.time_grid(sol_reimported, :dual) ≈ T_path atol = 1e-10 Test.@test Solutions.objective(sol_reimported) ≈ Solutions.objective(sol_unified) atol = 1e-8 diff --git a/test/suite/solutions/test_dual_model.jl b/test/suite/solutions/test_dual_model.jl index bbacd3c9..e1c1a8b5 100644 --- a/test/suite/solutions/test_dual_model.jl +++ b/test/suite/solutions/test_dual_model.jl @@ -283,12 +283,13 @@ function test_dual_model() ub = zeros(3, 1) sol = _make_solution(m; state_dim=1, state_lb=lb, state_ub=ub) - Test.@test_throws Exceptions.IncorrectArgument Solutions.dual(sol, m, :nonexistent) + Test.@test_throws Exceptions.IncorrectArgument Solutions.dual( + sol, m, :nonexistent + ) end end Test.@testset "DualSlice and BoxDualDiff" verbose=VERBOSE showtiming=SHOWTIMING begin - Test.@testset "DualSlice — scalar index" begin duals_fn = t -> [10.0 * t, 20.0 * t, 30.0 * t] f = Solutions.DualSlice(duals_fn, 2) diff --git a/test/suite/solutions/test_grid_extension.jl b/test/suite/solutions/test_grid_extension.jl index 55304fa7..1b1d80ad 100644 --- a/test/suite/solutions/test_grid_extension.jl +++ b/test/suite/solutions/test_grid_extension.jl @@ -65,8 +65,12 @@ function test_grid_extension() g -> !isnothing(g), [T_state, T_control, T_costate, T_path] ) T_ref = non_nothing_grids[argmax(map(length, non_nothing_grids))] - T_control_extended = Solutions._extend_grid_to_match(T_control, T_ref, "control") - T_costate_extended = Solutions._extend_grid_to_match(T_costate, T_ref, "costate") + T_control_extended = Solutions._extend_grid_to_match( + T_control, T_ref, "control" + ) + T_costate_extended = Solutions._extend_grid_to_match( + T_costate, T_ref, "costate" + ) # After extension, all grids should be identical Test.@test T_control_extended == T_ref diff --git a/test/suite/solutions/test_interpolation_helpers.jl b/test/suite/solutions/test_interpolation_helpers.jl index 625d70d7..640aeb9e 100644 --- a/test/suite/solutions/test_interpolation_helpers.jl +++ b/test/suite/solutions/test_interpolation_helpers.jl @@ -38,7 +38,9 @@ function test_interpolation_helpers() Test.@testset "_interpolate_from_data: nothing handling" begin # Test allow_nothing=true - result = Solutions._interpolate_from_data(nothing, T, 2, Nothing; allow_nothing=true) + result = Solutions._interpolate_from_data( + nothing, T, 2, Nothing; allow_nothing=true + ) Test.@test isnothing(result) # Test allow_nothing=false (should throw) @@ -69,7 +71,9 @@ function test_interpolation_helpers() Test.@testset "_interpolate_from_data: dimension validation" begin # Valid: matrix has exactly `expected_dim` columns (strict check) - func = Solutions._interpolate_from_data(X_2d, T, 2, Matrix{Float64}; expected_dim=2) + func = Solutions._interpolate_from_data( + X_2d, T, 2, Matrix{Float64}; expected_dim=2 + ) Test.@test !isnothing(func) # Invalid: matrix has 2 columns but expected_dim=1 (strict mismatch) diff --git a/test/suite/solutions/test_solution_multi_grids.jl b/test/suite/solutions/test_solution_multi_grids.jl index 4e91a5a3..7ee9b888 100644 --- a/test/suite/solutions/test_solution_multi_grids.jl +++ b/test/suite/solutions/test_solution_multi_grids.jl @@ -195,7 +195,8 @@ function test_solution_multi_grids() successful=true, ) - Test.@test Solutions.time_grid_model(sol) isa Solutions.MultipleTimeGridModel + Test.@test Solutions.time_grid_model(sol) isa + Solutions.MultipleTimeGridModel Test.@test Solutions.time_grid(sol, :state) == T_state Test.@test Solutions.time_grid(sol, :control) == T_control Test.@test Solutions.time_grid(sol, :costate) == T_costate @@ -233,7 +234,8 @@ function test_solution_multi_grids() successful=true, ) - Test.@test Solutions.time_grid_model(sol) isa Solutions.MultipleTimeGridModel + Test.@test Solutions.time_grid_model(sol) isa + Solutions.MultipleTimeGridModel Test.@test Solutions.time_grid(sol, :state) == T_state Test.@test Solutions.time_grid(sol, :control) == T_control Test.@test Solutions.time_grid(sol, :costate) == T_costate diff --git a/test/suite/solutions/test_solution_types.jl b/test/suite/solutions/test_solution_types.jl index c097a3ed..34f0f129 100644 --- a/test/suite/solutions/test_solution_types.jl +++ b/test/suite/solutions/test_solution_types.jl @@ -60,7 +60,9 @@ function test_solution_types() Test.@testset "Solution structure and empty time grid" begin times = Components.TimesModel( - Components.FixedTimeModel(0.0, "t₀"), Components.FixedTimeModel(1.0, "t_f"), "t" + Components.FixedTimeModel(0.0, "t₀"), + Components.FixedTimeModel(1.0, "t_f"), + "t", ) state = Components.StateModel("x", ["x"]) control = Components.ControlModel("u", ["u"]) @@ -159,7 +161,9 @@ function test_solution_types() Test.@testset "fake Solution summary" begin times = Components.TimesModel( - Components.FixedTimeModel(0.0, "t₀"), Components.FixedTimeModel(1.0, "t_f"), "t" + Components.FixedTimeModel(0.0, "t₀"), + Components.FixedTimeModel(1.0, "t_f"), + "t", ) state = Components.StateModel("x", ["x"]) control = Components.ControlModel("u", ["u"])