Private API
This page lists non-exported (internal) symbols of CTModelsPlots, CTModelsJSON, CTModels.Solutions, CTModels.Components, CTModels.Init, CTModels.Models, CTModels.Display, CTModelsJLD, CTModels.PlotCase, CTModels.Building, CTModelsMakie, CTModels.Serialization.
From CTModelsPlots
_plot [Function]
CTModelsPlots._plot Function
_plot(
sol::CTModels.Solutions.Solution,
description::Symbol...;
size,
color,
kwargs...
) -> AnyInternal implementation of Plots.plot(::CTModels.Solution).
Builds the figure with CTModels.PlotCase.build_figure and renders it via CTBase.Plotting (Plots backend).
_plot! [Function]
CTModelsPlots._plot! Function
_plot!(
p::Plots.Plot,
sol::CTModels.Solutions.Solution,
description::Symbol...;
color,
kwargs...
) -> Plots.PlotInternal implementation of Plots.plot!(::Plots.Plot, ::CTModels.Solution).
Builds the figure with CTModels.PlotCase.build_figure and overlays it onto the existing plot p via CTBase.Plotting (Plots backend).
From CTModelsJSON
_MATRIX_FIELDS [Constant]
CTModelsJSON._MATRIX_FIELDS Constant
Solution fields that are always serialized as Matrix{Float64} and must be converted to Vector{Vector} for JSON.
_OPTIONAL_MATRIX_FIELDS [Constant]
CTModelsJSON._OPTIONAL_MATRIX_FIELDS Constant
Solution fields that may be present (non-empty duals) and require the same Matrix → Vector{Vector} conversion.
_SWITCHING_MATRIX_FIELDS [Constant]
CTModelsJSON._SWITCHING_MATRIX_FIELDS Constant
Switching limits (present when the solution holds a switching structure), converted like the other matrices.
_apply_over_grid [Function]
CTModelsJSON._apply_over_grid Function
Apply a function over a grid (broadcast), or return nothing if input is nothing.
_convert_matrices_for_json! [Function]
CTModelsJSON._convert_matrices_for_json! Function
Convert Matrix fields to Vector{Vector} for JSON export.
JSON writes a Matrix{Float64} as a flat 1D array, losing the 2D structure. This function converts all matrix fields to Vector{Vector} format to preserve dimensions.
_deserialize_infos [Function]
CTModelsJSON._deserialize_infos Function
Convert Dict{String,Any} back to Dict{Symbol,Any} after JSON deserialization. Uses symbol_keys metadata to restore Symbol types where they were originally present.
_deserialize_value [Function]
CTModelsJSON._deserialize_value Function
Deserialize a single value from JSON format. Uses symbol_keys to restore Symbol types at the correct paths.
_json_rows_to_matrix [Function]
CTModelsJSON._json_rows_to_matrix Function
Convert the rows of a JSON switching-limit field back to a Matrix{Float64} with n rows (one per switching time); 0 × 0 when there is no switching time.
_json_to_matrix [Function]
CTModelsJSON._json_to_matrix Function
Convert a JSON field (Vector{Vector} via stack) to Matrix{Float64}.
JSON exports matrices as Vector{Vector}. After stack(blob[field]; dims=1), we get either a Matrix (multi-D) or Vector (1D). This normalizes to Matrix.
Arguments
blob_field: JSON array field (Vector of Vectors)
Returns
Matrix{Float64}: (n_time_points, n_dim)
_json_to_optional_matrix [Function]
CTModelsJSON._json_to_optional_matrix Function
Convert an optional JSON field to Matrix{Float64} or nothing.
Arguments
blob_field: JSON array field or nothing
Returns
Matrix{Float64}ornothing
_serialize_infos [Function]
CTModelsJSON._serialize_infos Function
Convert Dict{Symbol,Any} to Dict{String,Any} for JSON serialization. Only serializes JSON-compatible types (numbers, strings, bools, arrays, dicts). Returns a tuple: (serialized_dict, symbol_keys) where symbol_keys tracks which values were Symbols.
_serialize_value [Function]
CTModelsJSON._serialize_value Function
Serialize a single value to JSON-compatible format. Returns a tuple: (serialized_value, symbol_paths) where symbol_paths tracks Symbol locations.
From CTModels.Solutions
BoxDualDiff [Struct]
CTModels.Solutions.BoxDualDiff Type
BoxDualDiff{DL,DU,I,C} <: FunctionCallable struct computing the dual of a box constraint from the multipliers of its lower and upper bounds: f(t) = cl .* lb(t)[idx] .+ cu .* ub(t)[idx].
I = Int gives a scalar; I = Vector{Int} gives a vector, with one coefficient per component in cl and cu. The coefficients follow the sign convention of the ecosystem (ct-conventions SGN2, SGN3), see CTModels.Solutions.dual: (1, 0) for a component with a lower bound only (the dual is zL ≥ 0), (0, 1) for an upper bound only (zU ≥ 0), (-1, 1) for two finite bounds or a fixed component (the signed zU − zL). The three-argument constructor gives (1, -1), the net lb(t)[idx] − ub(t)[idx].
Replaces anonymous closures t -> duals_lb(t)[i] - duals_ub(t)[i] (and the vector variant) produced by dual(sol, model, label) for state and control box constraints.
DualSlice [Struct]
CTModels.Solutions.DualSlice Type
DualSlice{D,I} <: FunctionCallable struct extracting a slice of a time-dependent dual vector: f(t) = duals(t)[idx].
I = Int gives a scalar; I = Vector{Int} gives a vector. The scalar/vector distinction is encoded in the type parameter so the call method is fully specialised (no runtime branch).
Replaces anonymous closures t -> duals(t)[indices[1]] and t -> duals(t)[indices] produced by dual(sol, model, label).
SERIALIZATION_FORMAT_VERSION [Constant]
CTModels.Solutions.SERIALIZATION_FORMAT_VERSION Constant
Version of the serialized solution format, stored under the "format_version" key.
Files written before the key existed (no "format_version", no "model_signature") are still readable, with a reduced compatibility check against the model.
Version history:
1: model signature, for the compatibility check at import time.2: optional switching structure ("switching_times","phase_labels"and the"switching_<component>_<side>"limits), written only for a solution that holds one; files without these keys are read with anCTModels.Solutions.EmptySwitchingModel.
_JumpInterpolant [Struct]
CTModels.Solutions._JumpInterpolant Type
struct _JumpInterpolant{F}Interpolant of sampled data that keeps the jumps at the switching times.
Around a switching time τ, a plain interpolant of the grid values would join the last point before τ to the first point after it, smearing the jump. This one interpolates between the last grid point before τ and the left limit at τ, then between the right limit at τ and the first grid point after it. With constant = true (piecewise-constant control), it returns the right limit until the next grid point. Elsewhere it returns the base interpolant. At τ it returns the left limit (left continuity).
Fields
base::F: the interpolant of the grid values (returns a vector).grid::Vector{Float64}: the grid of the data.times::Vector{Float64}: the switching times.left::Matrix{Float64},right::Matrix{Float64}: the limits, one row per switching time.constant::Bool: piecewise-constant interpolation.
_SWITCHING_LIMIT_KEYS [Constant]
CTModels.Solutions._SWITCHING_LIMIT_KEYS Constant
Keys of the serialized switching limits, as (key, component, side) with side = 1 for the left limit and 2 for the right limit.
_as_vector [Function]
CTModels.Solutions._as_vector Function
_as_vector(v::Real) -> Vector{Float64}Normalize a time-independent solution field to a Vector{Float64} (or nothing) for serialization.
Several solution fields follow the "1-D is a scalar" convention: Components.variable(sol) and, for variable_dimension(ocp) == 1, Solutions.variable_constraints_lb_dual(sol) / ub_dual(sol). Unlike state/control/costate, these fields are time-independent and are not run through _discretize_function, so without this normalization a scalar (or nothing) would leak into the serialized data untouched.
_box_dual [Function]
CTModels.Solutions._box_dual Function
_box_dual(
duals_lb,
duals_ub,
cp,
idxs::Vector{Int64}
) -> Union{CTModels.Solutions.BoxDualDiff{_A, _B, Vector{Int64}, Vector{Float64}} where {_A, _B}, CTModels.Solutions.BoxDualDiff{_A, _B, Int64, Float64} where {_A, _B}}The dual of the state or control box components idxs, as a function of time (a CTModels.Solutions.BoxDualDiff with the coefficients of CTModels.Solutions._box_dual_coefficients): a scalar for one component.
_box_dual_coefficients [Function]
CTModels.Solutions._box_dual_coefficients Function
_box_dual_coefficients(
cp,
idxs::Vector{Int64}
) -> Tuple{Vector{Float64}, Vector{Float64}}Coefficients (cl, cu) of the lower- and upper-bound multipliers in the dual of each box component idxs (ct-conventions SGN2, SGN3): (1, 0) for a component with a finite lower bound only (the dual is zL ≥ 0), (0, 1) for a finite upper bound only (zU ≥ 0), (-1, 1) for two finite bounds or a fixed component (the signed zU − zL). The bounds of a component are those of all its declarations in the box tuple cp (effective bounds: the largest lower and the smallest upper bound).
_check_limit_component [Function]
CTModels.Solutions._check_limit_component Function
_check_limit_component(component::Symbol)Check that component is a component with switching limits: :state, :costate, :control or :path_dual.
Throws
CTBase.Exceptions.IncorrectArgument: if it is not.
_check_switching [Function]
CTModels.Solutions._check_switching Function
_check_switching(
_::CTModels.Solutions.EmptySwitchingModel,
T,
dim_x,
dim_u,
dim_p
)Check that a switching model is consistent with a solution: its switching times lie strictly inside the time span of the state grid T, and its stored limits have one column per component (dim_x for the state and costate, dim_u for the control, dim_p for the duals of the path constraints) or none (limits not known).
Throws
CTBase.Exceptions.IncorrectArgument: if a switching time is outside(first(T), last(T)), or a matrix of limits has a wrong number of columns.
_checked_limits [Function]
CTModels.Solutions._checked_limits Function
_checked_limits(
lr,
n::Integer,
name::String
) -> Tuple{Any, Any}Check a (left, right) pair of limits for n switching times and convert it to NTuple{2,Matrix{Float64}}.
Throws
CTBase.Exceptions.IncorrectArgument: if a matrix does not havenrows, or the two matrices differ in size.
_deserialize_switching [Function]
CTModels.Solutions._deserialize_switching Function
_deserialize_switching(
data
) -> Union{CTModels.Solutions.EmptySwitchingModel, CTModels.Solutions.SwitchingModel}Rebuild the switching model from serialized data: an CTModels.Solutions.EmptySwitchingModel when the data holds no "switching_times" (e.g. a file written by an older version), a CTModels.Solutions.SwitchingModel otherwise. The limits are matrices with one row per switching time; limits missing from the data (the duals, in a file written by an older version) are not known.
_discretize_all_components [Function]
CTModels.Solutions._discretize_all_components Function
_discretize_all_components(
sol::CTModels.Solutions.Solution,
T_state::Vector{Float64},
T_control::Vector{Float64},
T_costate::Vector{Float64},
T_path::Vector{Float64},
dim_x::Int64,
dim_u::Int64
) -> Dict{String, Any}Discretize all solution components on their respective time grids for serialization.
This internal helper function extracts the common discretization logic shared by both UnifiedTimeGridModel and MultipleTimeGridModel serialization. It evaluates all trajectory functions on their associated time grids and assembles them into a dictionary.
Grid-Component Association
Each component is discretized on its semantically correct time grid:
State trajectory →
T_stategridControl trajectory →
T_controlgridCostate trajectory →
T_costategridPath constraint duals →
T_pathgridState box constraint duals (lb/ub) →
T_stategridControl box constraint duals (lb/ub) →
T_controlgridBoundary/variable duals → Time-independent (vectors, not discretized)
Arguments
sol::Solution: Solution object containing trajectory functionsT_state::Vector{Float64}: Time grid for state discretizationT_control::Vector{Float64}: Time grid for control discretizationT_costate::Vector{Float64}: Time grid for costate discretizationT_path::Vector{Float64}: Time grid for path constraint dual discretizationdim_x::Int: State dimension (for validation)dim_u::Int: Control dimension (for validation)
Returns
Dict{String, Any}: Dictionary with all discretized components (grids not included)
Notes
This function does NOT include time grid data in the returned dictionary. The calling function (_serialize_solution for UnifiedTimeGridModel or MultipleTimeGridModel) is responsible for adding the appropriate grid keys.
See also: CTModels.Solutions._serialize_solution, CTModels.Solutions._discretize_function, CTModels.Solutions._discretize_dual
_discretize_dual [Function]
CTModels.Solutions._discretize_dual Function
_discretize_dual(
dual_func::Union{Nothing, Function},
T
) -> Union{Nothing, Matrix{Float64}}
_discretize_dual(
dual_func::Union{Nothing, Function},
T,
dim::Int64
) -> Union{Nothing, Matrix{Float64}}Discretize a dual function, returning nothing if the input is nothing.
Arguments
dual_func::Union{Function,Nothing}: Dual function ornothing.T: Time grid.dim::Int: Dimension (auto-detected if -1).
Returns
Matrix{Float64}ifdual_funcis a function.nothingifdual_funcisnothing.
See also: CTModels.Solutions._discretize_function.
_discretize_function [Function]
CTModels.Solutions._discretize_function Function
_discretize_function(
f::Function,
T::AbstractVector
) -> Matrix{Float64}
_discretize_function(
f::Function,
T::AbstractVector,
dim::Int64
) -> Matrix{Float64}Discretize a function on a time grid.
Evaluates f at each point in T and collects the results into a matrix. If dim is -1, the output dimension is auto-detected from the first evaluation of f.
Arguments
f::Function: Function to discretize (can return a scalar or a vector).T::AbstractVector: Time grid.dim::Int: Expected dimension of the result. If -1, auto-detected from first evaluation.
Returns
Matrix{Float64}: n×dim matrix where n = length(T).
Examples
# Scalar function
f_scalar = t -> 2.0 * t
result = _discretize_function(f_scalar, [0.0, 0.5, 1.0], 1)
# result = [0.0; 1.0; 2.0]
# Vector function
f_vec = t -> [t, 2*t]
result = _discretize_function(f_vec, [0.0, 0.5, 1.0], 2)
# result = [0.0 0.0; 0.5 1.0; 1.0 2.0]
# Auto-detect dimension
result = _discretize_function(f_vec, [0.0, 0.5, 1.0])
# result = [0.0 0.0; 0.5 1.0; 1.0 2.0]See also: CTModels.Solutions._discretize_dual.
_discretize_function(
f::Function,
T::CTModels.Solutions.UnifiedTimeGridModel
) -> Matrix{Float64}
_discretize_function(
f::Function,
T::CTModels.Solutions.UnifiedTimeGridModel,
dim::Int64
) -> Matrix{Float64}Discretize a function on a TimeGridModel by extracting the underlying time grid.
See also: CTModels.Solutions._discretize_function.
_dual_dimension [Function]
CTModels.Solutions._dual_dimension Function
_dual_dimension(
_::Nothing,
_::CTModels.Solutions.Solution
) -> Int64Return the dimension of a dual value, evaluating at initial time.
Arguments
dual::Union{Nothing, Function}: The dual function or nothing.sol::Solution: The optimal control solution.
Returns
Dimension: The dual dimension (0 if dual is nothing).
See also: CTModels.Solutions.dim_dual_state_constraints_box, CTModels.Solutions.dim_dual_control_constraints_box.
_ensure_dual [Function]
CTModels.Solutions._ensure_dual Function
_ensure_dual(
sol::CTModels.Solutions.Solution,
duals,
label::Symbol,
kind::String
)Throw a CTBase.Exceptions.PreconditionError when the solution holds no dual for the kind constraints (duals === nothing), although it holds others: the label label exists in the model, but its dual was not computed. A flow solution, for instance, carries the duals of the path constraints only. The suggestion is the note infos(sol)[:missing_duals] left by the producer of the solution, when there is one (see CTModels.Solutions._missing_duals_note).
_extend_grid_to_match [Function]
CTModels.Solutions._extend_grid_to_match Function
_extend_grid_to_match(
T_target::Vector{Float64},
T_reference::Vector{Float64},
component_name::String
) -> Vector{Float64}Extend a target time grid to match a reference grid if the target is a strict prefix.
This function checks if T_target is missing only the last element of T_reference (i.e., T_target == T_reference[1:end-1]). If so, it returns T_reference to enable grid unification. Otherwise, it returns T_target unchanged.
Arguments
T_target::Vector{Float64}: Time grid to potentially extendT_reference::Vector{Float64}: Reference time grid (typically the longest grid)component_name::String: Name of the component for logging purposes
Returns
Vector{Float64}: Extended grid if extension condition met, otherwise originalT_target
Notes
Extension condition:
length(T_target) == length(T_reference) - 1ANDT_target == T_reference[1:end-1]Emits
@infolog when extension is performed for transparencyDoes not modify trajectory data matrices (interpolation handles this via
T[1:N])
See also: CTModels.Solutions._validate_and_fix_time_grid, CTModels.Solutions.build_solution
_interpolate_from_data [Function]
CTModels.Solutions._interpolate_from_data Function
_interpolate_from_data(data, T, dim, type_param; allow_nothing=false,
constant_if_two_points=false, expected_dim=nothing,
interpolation=:linear)Internal helper to create an interpolated function from discrete data.
Arguments
data: Matrix{Float64}, Function, or Nothing (if allow_nothing=true)T: Time grid vectordim: Dimension to extract from matrix (nothing = take full matrix)type_param: Type parameter for dispatch (Matrix, Function, or Nothing)allow_nothing: If false, throws IncorrectArgument when data is nothingconstant_if_two_points: If true and length(T)==2, return constant functionexpected_dim: If provided, validates matrix dimension matches (via @ensure)interpolation: Interpolation type (:linearor:constant)
Returns
- Interpolated function (or nothing if data=nothing and allow_nothing=true)
Throws
IncorrectArgument: If data is nothing and allow_nothing=falseAssertionError: If expected_dim provided and doesn't match (via @ensure)
Notes
This is a low-level helper. Use build_interpolated_function for the complete workflow.
See also: CTModels.Solutions.build_interpolated_function, CTModels.Solutions._wrap_scalar_and_deepcopy.
_is_constraint_label [Function]
CTModels.Solutions._is_constraint_label Function
_is_constraint_label(
model::CTModels.Models.Model,
label::Symbol
) -> BoolWhether label is a constraint of model: a path or boundary constraint, or an alias of a state, control or variable box.
_limit [Function]
CTModels.Solutions._limit Function
_limit(
sol::CTModels.Solutions.Solution,
component::Symbol,
i::Integer,
side::Int64
) -> AnyShared implementation of CTModels.Solutions.left_limit (side = 1) and CTModels.Solutions.right_limit (side = 2).
_missing_duals_note [Function]
CTModels.Solutions._missing_duals_note Function
_missing_duals_note(
sol::CTModels.Solutions.Solution,
default::AbstractString
) -> StringThe explanation of the missing duals of sol: the note infos(sol)[:missing_duals] left by the producer of the solution (e.g. CTFlows, which knows why a dual could not be rebuilt and how to get it), or default when there is none.
_no_limits [Function]
CTModels.Solutions._no_limits Function
_no_limits(
n::Integer
) -> Tuple{Matrix{Float64}, Matrix{Float64}}Default (left, right) limits: two matrices with n rows and no column (limits not known).
_phase_sequence [Function]
CTModels.Solutions._phase_sequence Function
_phase_sequence(
labels::AbstractVector{<:AbstractString}
) -> StringReturn the sequence of phase labels as written by the displays, e.g. "bang → · → singular": the labels joined by arrows, a phase with no label written · so that every phase keeps its place between the switching times.
_serialize_solution [Function]
CTModels.Solutions._serialize_solution Function
_serialize_solution(
sol::CTModels.Solutions.Solution
) -> Dict{String, Any}Serialize a solution into discrete data for export to persistent storage (JLD2, JSON, etc.).
This function converts a Solution object (which may contain interpolated functions) into a fully discrete, serializable representation. All trajectory functions are evaluated on their respective time grids and stored as matrices. The serialization format automatically adapts based on whether the solution uses unified or multiple time grids.
Serialization Formats
The function produces two different formats depending on the solution's time grid model:
Unified Time Grid Format (Legacy)
When all grids are identical (UnifiedTimeGridModel), produces:
Dict(
"time_grid" => T, # Single grid for all components
"state" => Matrix, # Discretized on T
"control" => Matrix, # Discretized on T
"costate" => Matrix, # Discretized on T
"path_constraints_dual" => Matrix, # Discretized on T
# ... other fields
)Multiple Time Grids Format
When grids differ (MultipleTimeGridModel), produces:
Dict(
"time_grid_state" => T_state, # State-specific grid
"time_grid_control" => T_control, # Control-specific grid
"time_grid_costate" => T_costate, # Costate-specific grid
"time_grid_path" => T_path, # Path constraints grid
"state" => Matrix, # Discretized on T_state
"control" => Matrix, # Discretized on T_control
"costate" => Matrix, # Discretized on T_costate
"path_constraints_dual" => Matrix, # Discretized on T_path
# ... other fields
)Arguments
sol::Solution: Solution object to serialize (may contain functions or matrices)
Returns
Dict{String, Any}: Complete serializable dictionary containing:Time grids: Either single
"time_grid"or four separate gridsTrajectories:
"state","control","costate"asMatrix{Float64}Variable:
"variable"asVector{Float64}(time-independent)Objective:
"objective"asFloat64Dual variables: All constraint duals (can be
nothingif not present)"path_constraints_dual": Path constraint duals on path grid"state_constraints_lb_dual","state_constraints_ub_dual": State box duals on state grid"control_constraints_lb_dual","control_constraints_ub_dual": Control box duals on control grid"boundary_constraints_dual": Boundary duals (time-independent vector)"variable_constraints_lb_dual","variable_constraints_ub_dual": Variable duals (vectors)
Solver info:
"iterations","message","status","successful","constraints_violation","infos". The optional fields"iterations","message","status"and"constraints_violation"arenothingwhen unset (Core.NotProvided)Compatibility check:
"format_version"and"model_signature"(seeCTModels.Models._model_signature), used at import time to check the file against the model
Discretization Behavior
Function trajectories: Evaluated at each point of their associated time grid
Matrix trajectories: Copied as-is (already discrete)
Nothing duals: Preserved as
nothingin the dictionaryGrid association: Each component is discretized on its correct grid:
State and state box duals →
T_stateControl and control box duals →
T_controlCostate →
T_costatePath constraint duals →
T_path
Example
using CTModels
# Solve OCP with multiple grids
sol = solve(ocp, strategy=MyStrategy())
# Serialize to dictionary
data = _serialize_solution(sol)
# Check format
if haskey(data, "time_grid_state")
# Multiple grids format
println("State grid: ", length(data["time_grid_state"]), " points")
println("Control grid: ", length(data["time_grid_control"]), " points")
println("Costate grid: ", length(data["time_grid_costate"]), " points")
else
# Unified grid format
println("Unified grid: ", length(data["time_grid"]), " points")
end
# Export to file (handled by extensions)
export_ocp_solution(sol; filename="solution", format=:JLD)
# Reconstruct from data
sol_reconstructed = _reconstruct_solution_from_data(ocp, data)Notes
Backward Compatibility
The serialization format is designed for backward compatibility:
Old files with single
"time_grid"can be read (costate defaults to state grid)New files with four grids are forward-compatible with updated readers
The
_reconstruct_solution_from_datafunction handles both formats automatically
Memory Efficiency
When all grids are identical, the unified format avoids storing redundant grid data, reducing file size and memory usage.
Round-Trip Guarantee
The serialized data is fully compatible with build_solution for exact reconstruction:
data = _serialize_solution(sol)
sol_new = build_solution(ocp, data["time_grid_state"], ...; objective=data["objective"], ...)See also: CTModels.Solutions.build_solution, CTModels.Serialization._reconstruct_solution_from_data, CTModels.Serialization.export_ocp_solution, CTModels.Serialization.import_ocp_solution
_serialize_solution(
_::CTModels.Solutions.UnifiedTimeGridModel,
sol::CTModels.Solutions.Solution,
dim_x::Int64,
dim_u::Int64
) -> Dict{String, Any}Serialize solution with unified time grid (legacy single-grid format).
This method handles solutions where all components share the same time grid. It produces the legacy format with a single "time_grid" key, which is backward-compatible with older versions of the package.
Format Produced
Dict(
"time_grid" => T, # Single unified grid
"state" => Matrix, # All components discretized on T
"control" => Matrix,
"costate" => Matrix,
# ... all other fields
)Arguments
::UnifiedTimeGridModel: Time grid model type (dispatch parameter)sol::Solution: Solution to serializedim_x::Int: State dimensiondim_u::Int: Control dimension
Returns
Dict{String, Any}: Serialized data with single time grid
Notes
This format is used when build_solution is called with identical grids for all components, or when using the legacy single-grid signature. It ensures backward compatibility with files created before the multi-grid feature was introduced.
See also: CTModels.Solutions._serialize_solution
_serialize_solution(
_::CTModels.Solutions.MultipleTimeGridModel,
sol::CTModels.Solutions.Solution,
dim_x::Int64,
dim_u::Int64
) -> Dict{String, Any}Serialize solution with multiple independent time grids (modern format).
This method handles solutions where different components use different time grids. It produces the modern format with four separate grid keys (time_grid_state, time_grid_control, time_grid_costate, time_grid_path), preserving the independent discretizations.
Format Produced
Dict(
"time_grid_state" => T_state, # State-specific grid
"time_grid_control" => T_control, # Control-specific grid
"time_grid_costate" => T_costate, # Costate-specific grid
"time_grid_path" => T_path, # Path constraints grid
"state" => Matrix, # Discretized on T_state
"control" => Matrix, # Discretized on T_control
"costate" => Matrix, # Discretized on T_costate
"path_constraints_dual" => Matrix, # Discretized on T_path
# ... all other fields
)Arguments
::MultipleTimeGridModel: Time grid model type (dispatch parameter)sol::Solution: Solution to serializedim_x::Int: State dimensiondim_u::Int: Control dimension
Returns
Dict{String, Any}: Serialized data with four independent time grids
Notes
This format is used when build_solution is called with different grids for different components. It allows numerical schemes to use optimal discretizations for each component (e.g., finer grid for state, coarser for control, custom for costate).
The reconstruction function _reconstruct_solution_from_data detects this format by checking for the presence of "time_grid_state" key and handles it appropriately.
See also: CTModels.Solutions._serialize_solution, CTModels.Solutions.build_solution
_serialize_switching! [Function]
CTModels.Solutions._serialize_switching! Function
_serialize_switching!(
data::Dict{String, Any},
_::CTModels.Solutions.EmptySwitchingModel
) -> Dict{String, Any}Add the switching structure of a solution to its serialized data: nothing for an CTModels.Solutions.EmptySwitchingModel; the switching times, the phase labels and the six matrices of limits for a CTModels.Solutions.SwitchingModel.
_stored_limits [Function]
CTModels.Solutions._stored_limits Function
_stored_limits(
m::CTModels.Solutions.SwitchingModel
) -> StringReturn the components whose limits a switching model stores, e.g. "state, costate", or "none".
_switching_limit_key [Function]
CTModels.Solutions._switching_limit_key Function
_switching_limit_key(
component::Symbol,
side::Int64
) -> StringReturn the key of the serialized side limit (1 left, 2 right) of component, e.g. "switching_state_left".
_throw_label_not_found [Function]
CTModels.Solutions._throw_label_not_found Function
_throw_label_not_found(label::Symbol)Throw the CTBase.Exceptions.IncorrectArgument of an unknown constraint label.
_throw_repeated_time [Function]
CTModels.Solutions._throw_repeated_time Function
_throw_repeated_time(t::Float64, component_name::String)Throw the error of a time grid with a repeated time.
Throws
CTBase.Exceptions.IncorrectArgument: always.
_unset_to_nothing [Function]
CTModels.Solutions._unset_to_nothing Function
_unset_to_nothing(x) -> AnyReturn nothing for an unset optional field (Core.NotProvided), and x otherwise.
An unset field is written as nothing (null in JSON), whatever the format.
_validate_and_fix_time_grid [Function]
CTModels.Solutions._validate_and_fix_time_grid Function
_validate_and_fix_time_grid(
T::Vector{Float64},
component_name::String
) -> Vector{Float64}Validate and fix a time grid by ensuring it is strictly increasing.
Arguments
T::Vector{Float64}: Time grid to validatecomponent_name::String: Name of the component for error messages
Returns
Vector{Float64}: Validated and potentially reordered time grid
Throws
CTBase.Exceptions.IncorrectArgument: If the grid holds a repeated time. A trajectory takes one value at each time; a jump at a switching time is stored in the switching model instead (seeCTModels.Solutions.SwitchingModel).
Notes
If the grid is not increasing, it is reordered and a warning is emitted.
_with_jumps [Function]
CTModels.Solutions._with_jumps Function
_with_jumps(
base,
grid::Vector{Float64},
sw::CTModels.Solutions.AbstractSwitchingModel,
component::Symbol;
constant
) -> AnyWrap the interpolant base of sampled data on grid so that it keeps the jumps of component stored in the switching model sw. Returned unchanged when sw holds no switching time, or no limit of component.
_wrap_scalar_and_deepcopy [Function]
CTModels.Solutions._wrap_scalar_and_deepcopy Function
_wrap_scalar_and_deepcopy(func, dim)Internal helper to wrap a function with scalar extraction and deepcopy, returning a CTModels.Components.CoercedTrajectory.
Arguments
func: Function or callable to wrap (or nothing)dim: Dimension of output (1 = scalar extraction viaonly, otherwiseidentity)
Returns
Components.CoercedTrajectory(deepcopy(func), coerce)wherecoerceisonly(dim==1) oridentity(otherwise)nothingif func is nothing
Notes
deepcopy is applied to func before storing it in the struct. This is essential for closures supplied by the user: Julia closures capture variable REFERENCES, not values, so without deepcopy, modifying external variables after solution creation would affect the solution.
Example:
param_x = 1.0
X_func = t -> [param_x * t]
sol = build_solution(...)
param_x = 999.0
# Without deepcopy: sol.state(0.5) would return [499.5] (uses new param_x)
# With deepcopy: sol.state(0.5) returns [0.5] (uses original param_x value)See also: CTModels.Solutions._interpolate_from_data, CTModels.Solutions.build_interpolated_function.
build_interpolated_function [Function]
CTModels.Solutions.build_interpolated_function Function
build_interpolated_function(data, T, dim, type_param; allow_nothing=false,
constant_if_two_points=false, expected_dim=nothing,
interpolation=:linear)Unified function to build an interpolated function with deepcopy and scalar wrapping.
This is the main entry point that combines interpolation and wrapping in one call.
Arguments
data: Matrix{Float64}, Function, or Nothing (if allow_nothing=true)T: Time grid vectordim: Dimension to extract (nothing = take full matrix)type_param: Type parameter for dispatchallow_nothing: Allow data=nothing (for optional duals)constant_if_two_points: Return constant function if length(T)==2 (for costate)expected_dim: Validate matrix has this dimension (for robustness)interpolation: Interpolation type (:linearor:constant)jumps:nothing, or(switching, component)to keep the jumps ofcomponentstored in the switching model when the data is a matrix (seeCTModels.Solutions._JumpInterpolant); function data is left as is.
Returns
Wrapped interpolated function ready for use in Solution
nothing if data=nothing and allow_nothing=true
Throws
IncorrectArgument: If data is nothing and allow_nothing=falseAssertionError: If expected_dim doesn't match actual dimension
Examples
# State interpolation (required, with validation)
fx = build_interpolated_function(X, T, dim_x, TX; expected_dim=dim_x)
# Control with piecewise-constant interpolation
fu = build_interpolated_function(U, T, dim_u, TU; expected_dim=dim_u, interpolation=:constant)
# Costate with special 2-point handling
fp = build_interpolated_function(P, T, dim_x, TP;
constant_if_two_points=true, expected_dim=dim_x)
# Optional dual (can be nothing)
fscbd = build_interpolated_function(state_constraints_lb_dual, T, dim_x,
Union{Matrix{Float64},Nothing};
allow_nothing=true)See also: CTModels.Solutions._interpolate_from_data, CTModels.Solutions._wrap_scalar_and_deepcopy.
dual_model [Function]
CTModels.Solutions.dual_model Function
dual_model(
sol::CTModels.Solutions.Solution{<:CTModels.Solutions.AbstractTimeGridModel, <:CTModels.Components.AbstractTimesModel, <:CTModels.Components.AbstractStateModel, <:CTModels.Components.AbstractControlModel, <:CTModels.Components.AbstractVariableModel, <:CTModels.Models.AbstractModel, <:Function, <:Real, DM<:CTModels.Solutions.AbstractDualModel}
) -> CTModels.Solutions.AbstractDualModelReturn the dual model containing all constraint multipliers.
limits [Function]
CTModels.Solutions.limits Function
limits(
m::CTModels.Solutions.SwitchingModel,
component::Symbol
) -> Tuple{Matrix{Float64}, Matrix{Float64}}Return the (left, right) matrices of limits of component (:state, :costate, :control or :path_dual), one row per switching time.
Throws
CTBase.Exceptions.IncorrectArgument: ifcomponentis not one of these.
limits(
_::CTModels.Solutions.EmptySwitchingModel,
component::Symbol
) -> Tuple{Matrix{Float64}, Matrix{Float64}}Return the (left, right) limits of component: none for an CTModels.Solutions.EmptySwitchingModel (two 0 × 0 matrices).
From CTModels.Components
CoercedTrajectory [Struct]
CTModels.Components.CoercedTrajectory Type
CoercedTrajectory{F,C} <: FunctionA callable struct decorating a time function inner with a coercion coerce: f(t) = coerce(inner(t)).
Replaces anonymous closures t -> func(t)[1] (coerce = only, scalar extraction) and t -> func(t) (coerce = identity, pass-through). Since C is a concrete singleton type (typeof(only) or typeof(identity)), the call method is fully specialised — no type instability.
Satisfies <: Function so it can be stored in containers parameterised by F <: Function (e.g. StateModelSolution{TS<:Function}).
Examples
f = CoercedTrajectory(t -> [2t], only)
f(0.5) # returns 1.0 (scalar extraction, validates length == 1)
g = CoercedTrajectory(t -> [t, 2t], identity)
g(0.5) # returns [0.5, 1.0]ConstantInTime [Struct]
CTModels.Components.ConstantInTime Type
ConstantInTime{V} <: FunctionA callable struct representing a constant function of time: f(t) = value for all t.
Replaces anonymous closures t -> value to gain named type, type stability, value capture (no deepcopy needed), and testability.
Satisfies <: Function so it can be stored in containers parameterised by F <: Function (e.g. InitialGuess{X<:Function, U<:Function, V}).
Examples
f = ConstantInTime(1.0)
f(0.5) # returns 1.0
g = ConstantInTime([1.0, 2.0])
g(3.7) # returns [1.0, 2.0]From CTModels.Init
MergedTrajectory [Struct]
CTModels.Init.MergedTrajectory Type
struct MergedTrajectory{F, C<:(AbstractDict{Int64, <:Function})} <: FunctionCallable struct merging a block-level trajectory base with sparse component-level overrides comps: f(t) evaluates base(t), normalises to a vector, applies each component override, and returns a scalar (dim == 1) or a vector.
base::F is a concrete type parameter, replacing the former base_fun::Function abstract capture. comps::C stores the Dict{Int,Function} override map.
Component index bounds are validated at construction, not at call time, so the call method stays allocation-free beyond what base and the component functions allocate.
Replaces the anonymous closure t -> begin … end (57 lines) produced inside CTModels.Init._build_block_with_components in builders.jl.
Fields
base::F: Block-level trajectory function.comps::C: Component-level override map (Dict{Int,Function}).dim::Int: Total dimension.role::Symbol: Component role (:stateor:control).
Examples
using CTModels: Init
base = t -> [0.0, 0.0]
comps = Dict{Int,Function}(2 => t -> sin(t))
f = MergedTrajectory(base, comps, 2, :state)
f(0.5) # returns [0.0, sin(0.5)]_build_block_with_components [Function]
CTModels.Init._build_block_with_components Function
_build_block_with_components(
ocp::CTModels.Models.AbstractModel,
role::Symbol,
block_data,
comp_data::Dict{Int64, Any}
) -> AnyBuild an initialisation function combining block-level and component-level data.
Arguments
ocp::CTModels.Models.AbstractModel: The optimal control problem.role::Symbol: The component role (:stateor:control).block_data: Block-level initialisation data.comp_data::Dict{Int,Any}: Component-level initialisation data indexed by component.
Returns
Function: A combined initialisation function that merges block and component data.
Throws
CTBase.Exceptions.IncorrectArgument: If dimensions are incompatible or component indices are out of bounds.
See also: CTModels.Init.MergedTrajectory, CTModels.Init.initial_state, CTModels.Init.initial_control
_build_component_function [Function]
CTModels.Init._build_component_function Function
_build_component_function(data) -> FunctionBuild a component-level initialisation function from data.
Arguments
data: The component data (time-dependent tuple or time-independent data).
Returns
Function: A component initialisation function.
See also: CTModels.Init._build_component_function_without_time, CTModels.Init._build_component_function_with_time
_build_component_function_with_time [Function]
CTModels.Init._build_component_function_with_time Function
_build_component_function_with_time(
data,
time::AbstractVector
) -> FunctionBuild a component function from data with an associated time grid.
Arguments
data: The component data (function, scalar, or vector).time::AbstractVector: The time grid for interpolation.
Returns
Function: A component initialisation function with time interpolation.
Throws
CTBase.Exceptions.IncorrectArgument: If the data type is unsupported or time-grid mismatch occurs.
See also: CTModels.Components.ConstantInTime, CTBase.Interpolation.ctinterpolate
_build_component_function_without_time [Function]
CTModels.Init._build_component_function_without_time Function
_build_component_function_without_time(data) -> FunctionBuild a component function from time-independent data (scalar, vector, or function).
Arguments
data: The time-independent data (function, scalar, or vector).
Returns
Function: A component initialisation function.
Throws
CTBase.Exceptions.IncorrectArgument: If the data type is unsupported or vector length is invalid.
See also: CTModels.Components.ConstantInTime
_build_time_dependent_init [Function]
CTModels.Init._build_time_dependent_init Function
_build_time_dependent_init(
ocp::CTModels.Models.AbstractModel,
role::Symbol,
data,
time::AbstractVector
) -> Union{Nothing, Function}Build a time-dependent initialisation function from data and a time grid.
Arguments
ocp::CTModels.Models.AbstractModel: The optimal control problem.role::Symbol: The component role (:stateor:control).data: The data to interpolate (function, vector, or vector-of-vectors).time::AbstractVector: The time grid.
Returns
Function: An interpolated initialisation functiont -> value(t).
Throws
CTBase.Exceptions.IncorrectArgument: If data type is unsupported or dimensions/time-grid mismatch occurs.
See also: CTBase.Interpolation.ctinterpolate, CTModels.Init.initial_state, CTModels.Init.initial_control
_coerce_base [Function]
CTModels.Init._coerce_base Function
_coerce_base(
v::AbstractVector,
dim::Int64,
role::Symbol
) -> AnyValidate and collect the base trajectory output for a component with dim > 1.
Throws if v is not an AbstractVector of the expected length, or if v is a scalar.
Arguments
v: raw output of the base trajectory function.dim::Int: expected component dimension.role::Symbol: component role (e.g.:state,:control) used in the error message.
Returns
Vector: a freshly collected copy ofv.
Throws
CTBase.Exceptions.IncorrectArgument: ifvis a scalar or has incorrect length.
See also: CTModels.Init._wrap_1d
_format_init_data_for_grid [Function]
CTModels.Init._format_init_data_for_grid Function
_format_init_data_for_grid(data) -> AnyConvert matrix data to vector-of-vectors format for time-grid interpolation.
Arguments
data: The data to format (matrix or other format).
Returns
Union{AbstractVector, Any}: The formatted data as vector-of-vectors, or the original data.
_format_time_grid [Function]
CTModels.Init._format_time_grid Function
_format_time_grid(time_data) -> AnyNormalise time grid data to a vector format.
Arguments
time_data: The time grid data (vector, array, ornothing).
Returns
Union{Nothing, AbstractVector}: The normalised time grid as a vector, ornothing.
Throws
Exceptions.IncorrectArgument: If the time grid type is invalid.
_initial_guess_from_namedtuple [Function]
CTModels.Init._initial_guess_from_namedtuple Function
_initial_guess_from_namedtuple(
ocp::CTModels.Models.AbstractModel,
init_data::NamedTuple
) -> CTModels.Init.InitialGuessBuild an initial guess from a NamedTuple.
Arguments
ocp::Models.AbstractModel: The optimal control problem.init_data::NamedTuple: The initial guess data with named fields.
Returns
InitialGuess: An initial guess constructed from the NamedTuple.
Throws
Exceptions.IncorrectArgument: If keys are invalid, dimensions mismatch, or specifications are duplicated.
_initial_guess_from_preinit [Function]
CTModels.Init._initial_guess_from_preinit Function
_initial_guess_from_preinit(
ocp::CTModels.Models.AbstractModel,
pre::CTModels.Init.PreInitialGuess
) -> CTModels.Init.InitialGuessBuild an initial guess from a pre-initialisation object.
Arguments
ocp::Models.AbstractModel: The optimal control problem.pre::PreInitialGuess: The pre-initialisation container.
Returns
InitialGuess: An initial guess constructed from the pre-initialisation data.
_initial_guess_from_solution [Function]
CTModels.Init._initial_guess_from_solution Function
_initial_guess_from_solution(
ocp::CTModels.Models.AbstractModel,
sol::CTModels.Solutions.AbstractSolution
) -> Union{CTModels.Init.InitialGuess{X, U, V} where {X<:Function, U<:Function, V<:Real}, CTModels.Init.InitialGuess{X, U, V} where {X<:Function, U<:Function, V<:(AbstractVector{<:Real})}}Build an initial guess from a previous solution (warm start).
Arguments
ocp::Models.AbstractModel: The optimal control problem.sol::Solutions.AbstractSolution: The previous solution.
Returns
InitialGuess: An initial guess constructed from the solution.
Throws
Exceptions.IncorrectArgument: If dimensions do not match between the problem and solution.
_normalize_scalar_components [Function]
CTModels.Init._normalize_scalar_components Function
_normalize_scalar_components(
_::CTModels.Models.AbstractModel,
init::CTModels.Init.AbstractInitialGuess
) -> CTModels.Init.InitialGuessNormalise the one-dimensional components of a validated initial guess to scalars.
Arguments
ocp::Models.AbstractModel: The optimal control problem.init::AbstractInitialGuess: The validated initial guess.
Returns
AbstractInitialGuess:inititself when nothing needs converting, otherwise a newInitialGuesswhose one-dimensional components are scalars.
_scalar_trajectory [Function]
CTModels.Init._scalar_trajectory Function
_scalar_trajectory(f::Function, dim::Int64) -> FunctionReturn a trajectory that yields a scalar when the component is one-dimensional.
A validated one-dimensional trajectory returns either a scalar or a length-1 vector. The second case is wrapped so that it returns the scalar, following the rule that a one-dimensional state or control is a Number. Trajectories of any other dimension, and trajectories that already return a scalar, are returned unchanged.
Arguments
f::Function: The validated trajectoryt -> x(t).dim::Int: The dimension of the component.
Returns
Function: The trajectory, or a scalar-returning wrapper around it.
See also: CTModels.Components.CoercedTrajectory.
_scalar_value [Function]
CTModels.Init._scalar_value Function
_scalar_value(v, dim::Int64) -> AnyReturn the variable as a scalar when it is one-dimensional.
Arguments
v: The validated variable value (scalar or vector).dim::Int: The variable dimension.
Returns
- The scalar
only(v)whendim == 1andvis a vector,votherwise.
_validate_initial_guess [Function]
CTModels.Init._validate_initial_guess Function
_validate_initial_guess(
ocp::CTModels.Models.AbstractModel,
init::CTModels.Init.InitialGuess
) -> CTModels.Init.InitialGuessInternal validation of an InitialGuess.
Arguments
ocp::Models.AbstractModel: The optimal control problem.init::InitialGuess: The initial guess to validate.
Returns
InitialGuess: The validated initial guess.
Throws
Exceptions.IncorrectArgument: If dimensions or types are incompatible.
_wrap_1d [Function]
CTModels.Init._wrap_1d Function
_wrap_1d(v::AbstractVector) -> AnyNormalise a scalar or vector base value to a Vector of length 1 for dim-1 components.
Dispatched overloads replace isa AbstractVector runtime checks with static dispatch, letting the compiler specialise on the return type of the base trajectory.
Arguments
v: raw output of a base trajectory function for a 1-dimensional component.
Returns
Vector: a length-1 vector containing or wrappingv.
See also: CTModels.Init._coerce_base
From CTModels.Models
BoxProjection [Struct]
CTModels.Models.BoxProjection Type
BoxProjection{Slot,CIDX} <: FunctionCallable struct projecting a box constraint onto selected components.
Slot ∈ (:state, :control, :variable) selects which argument is projected; CIDX = Int gives a scalar, CIDX = Vector{Int} gives a vector. Both the slot and the scalar/vector distinction are encoded in type parameters so the call method is fully specialised (no runtime branch).
Replaces three anonymous closures in constraint(model, label):
(_, x, _, _) -> x[cidxs](state box)(_, _, u, _) -> u[cidxs](control box)(_, _, v) -> v[cidxs](variable box, arity 3)
SubBoundaryConstraint [Struct]
CTModels.Models.SubBoundaryConstraint Type
SubBoundaryConstraint{CP,I} <: FunctionIn-place callable struct extracting a sub-vector of a nonlinear boundary constraint: evaluates the full boundary constraint vector then copies r .= r_[indices].
I = Int or I = Vector{Int}. Intended to be wrapped by Core.to_out_of_place.
Replaces the anonymous in-place closure produced inside constraint(model, label): fc! = (r, x0, xf, v) -> begin r_ = zeros(...); cp[2](r_, x0, xf, v); r .= r_[indices] end.
SubPathConstraint [Struct]
CTModels.Models.SubPathConstraint Type
SubPathConstraint{CP,I} <: FunctionIn-place callable struct extracting a sub-vector of a nonlinear path constraint: evaluates the full path constraint vector then copies r .= r_[indices].
I = Int or I = Vector{Int}. Intended to be wrapped by Core.to_out_of_place.
Replaces the anonymous in-place closure produced inside constraint(model, label): fc! = (r, t, x, u, v) -> begin r_ = zeros(...); cp[2](r_, t, x, u, v); r .= r_[indices] end.
_control_dependence [Function]
CTModels.Models._control_dependence Function
_control_dependence(
_::CTModels.Components.EmptyControlModel
) -> Type{CTBase.Traits.ControlFree}Resolve the control-dependence trait value from the control model type.
Returns Traits.ControlFree when the model carries no control input (CTModels.Components.EmptyControlModel), and Traits.WithControl otherwise.
Arguments
model: anCTModels.Components.AbstractControlModelinstance.
Returns
- trait value:
Traits.ControlFreeorTraits.WithControl.
See also: CTModels.Models._variable_dependence
_label_strings [Function]
CTModels.Models._label_strings Function
_label_strings(labels) -> Vector{String}Normalize constraint labels to strings, mapping the unique labels generated for unnamed constraints (gensym(:unnamed), which differ from one model instance to another) to the empty string.
Arguments
labels: Collection of constraint labels.
Returns
Vector{String}: The normalized labels.
_model_signature [Function]
CTModels.Models._model_signature Function
_model_signature(
ocp::CTModels.Models.Model
) -> Dict{String, Any}Return a plain-data description of the structure of a model, used to check, at import time, that a serialized solution is compatible with the model it is rebuilt against.
The signature only contains values that can be stored as is in JLD2 and JSON files (integers, booleans, strings, vectors of strings, floats or nothing). It never contains functions: dynamics, costs and constraint functions are not compared.
Arguments
ocp::Model: The optimal control problem.
Returns
Dict{String,Any}: The signature, with the keys:dimensions:
dim_x,dim_u,dim_v,dim_path_nl,dim_boundary_nl,dim_state_box,dim_control_box,dim_variable_box;names:
state_name,state_components,control_name,control_components,variable_name,variable_components,time_name,initial_time_name,final_time_name;constraint labels:
labels_path_nl,labels_boundary_nl,labels_state_box,labels_control_box,labels_variable_box(unnamed constraints have an empty label);objective:
criterion,has_mayer,has_lagrange;times:
fixed_initial_time,fixed_final_time,initial_time,final_time(the value isnothingwhen the time is free).
See also: CTModels.Serialization._validate_solution_against_model.
_variable_dependence [Function]
CTModels.Models._variable_dependence Function
_variable_dependence(
_::CTModels.Components.EmptyVariableModel
) -> Type{CTBase.Traits.Fixed}Resolve the variable-dependence trait value from the variable model type.
Returns Traits.Fixed when the model carries no optimisation variable (CTModels.Components.EmptyVariableModel), and Traits.NonFixed otherwise.
Arguments
model: anCTModels.Components.AbstractVariableModelinstance.
Returns
- trait value:
Traits.FixedorTraits.NonFixed.
See also: CTModels.Models._control_dependence
From CTModels.Display
__print [Function]
CTModels.Display.__print Function
__print(e::Expr, io::IO, l::Int64)Print an expression with indentation.
Arguments
e::Expr: The expression to print.io::IO: The output stream.l::Int: The indentation level (number of spaces).
Returns
Nothing: Prints toioand returns nothing.
__print_mathematical_definition [Function]
CTModels.Display.__print_mathematical_definition Function
__print_mathematical_definition(
io::IO,
some_printing::Bool,
x_dim::Int64,
u_dim::Int64,
v_dim::Int64,
t_name::String,
t0_name::String,
tf_name::String,
x_name::String,
u_name::String,
v_name::String,
xi_names::Vector{String},
ui_names::Vector{String},
vi_names::Vector{String},
is_variable_dependent::Bool,
is_time_dependent::Bool,
is_control_free_ocp::Bool,
has_a_lagrange_cost::Bool,
has_a_mayer_cost::Bool,
dim_path_cons_nl::Int64,
dim_boundary_cons_nl::Int64,
dim_state_cons_box::Int64,
dim_control_cons_box::Int64,
dim_variable_cons_box::Int64
) -> BoolPrint the mathematical definition of an optimal control problem.
Displays the problem in standard mathematical notation with objective, dynamics, and constraints.
When u_dim == 0 (no control input), all control-dependent parts of the output are suppressed:
The objective is rendered as
J(x, v)instead ofJ(x, u, v).Dynamics arguments omit the control:
f(t, x, v)instead off(t, x, u, v).The "where" clause lists only
x(andvif variable-dependent).Box constraints on control are not listed.
Arguments
io::IO: The output stream.some_printing::Bool: Whether content has already been printed.x_dim::Int: State dimension.u_dim::Int: Control dimension.v_dim::Int: Variable dimension.t_name::String: Time variable name.t0_name::String: Initial time name.tf_name::String: Final time name.x_name::String: State variable name.u_name::String: Control variable name.v_name::String: Variable name.xi_names::Vector{String}: State component names.ui_names::Vector{String}: Control component names.vi_names::Vector{String}: Variable component names.is_variable_dependent::Bool: Whether the problem depends on variables.is_time_dependent::Bool: Whether the problem is non-autonomous.is_control_free_ocp::Bool: Whether the problem has no control input.has_a_lagrange_cost::Bool: Whether the problem has a Lagrange cost.has_a_mayer_cost::Bool: Whether the problem has a Mayer cost.dim_path_cons_nl::Int: Dimension of nonlinear path constraints.dim_boundary_cons_nl::Int: Dimension of nonlinear boundary constraints.dim_state_cons_box::Int: Dimension of state box constraints.dim_control_cons_box::Int: Dimension of control box constraints.dim_variable_cons_box::Int: Dimension of variable box constraints.
Returns
Bool:trueif something was printed.
See also: CTModels.Display._print_abstract_definition.
_compact_fields [Function]
CTModels.Display._compact_fields Function
Remove palette callbacks from fields used by compact displays.
_component_name [Function]
CTModels.Display._component_name Function
Return the concrete display name for a component model.
_display_value [Function]
CTModels.Display._display_value Function
_display_value(io::IO, value) -> AbstractStringRender a nested display value while preserving the colour context of io.
_dual_presence [Function]
CTModels.Display._dual_presence Function
Return whether an optional dual value is present.
_grid_summary [Function]
CTModels.Display._grid_summary Function
Summarize a time grid by its size and endpoint values.
_print_abstract_definition [Function]
CTModels.Display._print_abstract_definition Function
_print_abstract_definition(
_::IO,
_::CTModels.Components.EmptyDefinition
) -> BoolPrint a CTModels.Components.EmptyDefinition: no output is produced.
Returns
Bool:falseto indicate that nothing was printed.
_print_abstract_definition(
io::IO,
d::CTModels.Components.Definition
) -> BoolPrint a CTModels.Components.Definition under an "Abstract definition:" header.
Block expressions are unfolded line-by-line; other expression heads are printed as a single indented entry.
Arguments
io::IO: The output stream.d::Definition: The symbolic definition to display.
Returns
Bool:trueto indicate that output was produced.
See also: CTModels.Display.__print.
_show_compact [Function]
CTModels.Display._show_compact Function
_show_compact(io::IO, type_name; fields, fmt)Print a compact one-line representation with palette-styled fields.
_show_detail [Function]
CTModels.Display._show_detail Function
_show_detail(io::IO, type_name; fields, fmt)Print a detailed tree representation with palette-styled fields.
_show_objective [Function]
CTModels.Display._show_objective Function
_show_objective(io::IO, model, fields; detailed)Render an objective model without expanding its callable fields.
_show_solution_space [Function]
CTModels.Display._show_solution_space Function
Render a solution state, control, or variable component.
_show_space [Function]
CTModels.Display._show_space Function
Render a state, control, or variable model in compact or detailed form.
_solution_space_fields [Function]
CTModels.Display._solution_space_fields Function
Collect display fields for a component model carrying a trajectory or value.
_space_fields [Function]
CTModels.Display._space_fields Function
Collect accessor-backed fields for a state, control, or variable model.
_styled_fields [Function]
CTModels.Display._styled_fields Function
Apply the selected palette role to each display field.
format_codes [Function]
CTModels.Display.format_codes Function
format_codes(
io::IO
) -> @NamedTuple{name::String, type::String, value::String, keyword::String, count::String, label::String, emphasis::String, muted::String, error::String, warning::String, success::String, reset::String, bold::String, dim::String}Return the active CTBase palette codes for io.
print_field [Function]
CTModels.Display.print_field Function
print_field(io::IO, label, value; last, fmt, value_style)Print one labelled tree field using semantic palette roles.
print_fields [Function]
CTModels.Display.print_fields Function
print_fields(io::IO, fields; fmt)Print a sequence of labelled fields and mark the final field with └─.
print_header [Function]
CTModels.Display.print_header Function
print_header(io::IO, name; fmt)Print a palette-styled type header without a trailing newline.
From CTModels.PlotCase
_BOUND_STYLE [Constant]
CTModels.PlotCase._BOUND_STYLE Constant
Default style for box-bound and path-bound horizontal reference lines.
_BUILD_KEYS [Constant]
CTModels.PlotCase._BUILD_KEYS Constant
Keyword-argument names consumed by build_figure; every other keyword a user passes to plot(sol; …) is forwarded to the rendering backend.
_TIME_STYLE [Constant]
CTModels.PlotCase._TIME_STYLE Constant
Default style for initial/final time vertical reference lines.
__control_layout [Function]
CTModels.PlotCase.__control_layout Function
__control_layout() -> SymbolReturn the default control representation (:components).
__description [Function]
CTModels.PlotCase.__description Function
__description() -> NTuple{12, Symbol}Return the default description tuple used when the user gives none.
Aliases are included so that clean collapses them to the canonical set.
__phase_labels [Function]
CTModels.PlotCase.__phase_labels Function
__phase_labels() -> SymbolReturn the default placement of the phase labels (:control).
__plot_jumps [Function]
CTModels.PlotCase.__plot_jumps Function
__plot_jumps() -> SymbolReturn the default drawing of a jump at a switching time (:segment, a vertical segment from the left to the right limit).
__plot_label_suffix [Function]
CTModels.PlotCase.__plot_label_suffix Function
__plot_label_suffix() -> StringReturn the default suffix appended to plot labels (empty string).
__plot_layout [Function]
CTModels.PlotCase.__plot_layout Function
__plot_layout() -> SymbolReturn the default plot layout (:split).
__plot_style [Function]
CTModels.PlotCase.__plot_style Function
__plot_style() -> @NamedTuple{}Return the default plotting style (empty NamedTuple).
__time_normalization [Function]
CTModels.PlotCase.__time_normalization Function
__time_normalization() -> SymbolReturn the default time-axis normalization (:default).
_as_value [Function]
CTModels.PlotCase._as_value Function
_as_value(row::AbstractVector) -> AnyReturn a sampled row as the value of a trajectory: a scalar for one component (the "1-D is a scalar" convention), the vector otherwise.
_assemble_group [Function]
CTModels.PlotCase._assemble_group Function
_assemble_group(
cells::AbstractVector{<:CTBase.Plotting.AbstractLayoutNode}
) -> AnyAssemble group cells horizontally (:group layout).
Exactly four cells (state, costate, control, control-norm) fold into a 2×2 grid.
_assemble_split [Function]
CTModels.PlotCase._assemble_split Function
_assemble_split(
;
state,
costate,
control,
path,
dual
) -> Union{Nothing, CTBase.Plotting.AbstractLayoutNode}Assemble stacked columns (:split layout).
The layout is (state | costate) over control over (path | dual). Returns nothing when there is nothing to draw.
_base_style [Function]
CTModels.PlotCase._base_style Function
_base_style(style::NamedTuple) -> NamedTupleReturn the default per-series style, merged with any user-supplied group style.
_box_hlines [Function]
CTModels.PlotCase._box_hlines Function
_box_hlines(
box,
ncomp::Int64,
style::NamedTuple
) -> Vector{Vector{CTBase.Plotting.HLine}}Build per-component horizontal bound lines from a box constraint tuple.
For a panel with ncomp components, hlines[i] holds the lines for component i.
_build_root [Function]
CTModels.PlotCase._build_root Function
_build_root(
sol,
description::Symbol...;
layout,
control,
time,
state_style,
costate_style,
control_style,
path_style,
dual_style,
time_style,
state_bounds_style,
control_bounds_style,
path_bounds_style,
switching_style,
phase_labels,
phase_labels_style,
jumps
)Build the CTBase.Plotting layout tree for a CTModels solution.
Returns nothing if there is nothing to draw. Decorations (bounds, initial/final time lines) are added according to the user-supplied style keywords.
_check_jumps [Function]
CTModels.PlotCase._check_jumps Function
_check_jumps(jumps::Symbol)Check the drawing of the jumps: :segment or :none.
Throws
CTBase.Exceptions.IncorrectArgument: for any other value.
_check_phase_labels [Function]
CTModels.PlotCase._check_phase_labels Function
_check_phase_labels(phase_labels::Symbol)Check the placement of the phase labels: :control, :all or :none.
Throws
CTBase.Exceptions.IncorrectArgument: for any other value.
_control_panels [Function]
CTModels.PlotCase._control_panels Function
_control_panels(
sol,
control::Symbol,
style::NamedTuple,
layout::Symbol;
connect
) -> Vector{CTBase.Plotting.Panel}Build one or more CTBase.Plotting.Panel objects for the control trajectory.
control = :components: one panel with a curve per control component.control = :norm: one panel with the Euclidean norm of the control.control = :all: both panels (in:group) or a single panel with components and norm (in:split).
Returns
Vector{Plotting.Panel}: The panels to be assembled into the layout.
_costate_panel [Function]
CTModels.PlotCase._costate_panel Function
_costate_panel(
sol,
style::NamedTuple;
layout,
state_shown,
connect
)Build a CTBase.Plotting.Panel for the costate trajectory.
Labels depend on layout and whether the state panel is shown alongside.
_dual_panel [Function]
CTModels.PlotCase._dual_panel Function
_dual_panel(
sol,
model,
style::NamedTuple;
path_shown,
connect
)Build a CTBase.Plotting.Panel for the dual variables of the path constraints. At a switching time whose dual limits are known, the jump is drawn as for the state (see CTModels.PlotCase._spliced_samples).
_pair [Function]
CTModels.PlotCase._pair Function
_pair(a, b) -> AnyPair two layout columns side by side, tolerating a missing one.
If both are present, returns a Plotting.Paired; otherwise returns the non-nothing one.
_path_hlines [Function]
CTModels.PlotCase._path_hlines Function
_path_hlines(model, style::NamedTuple) -> AnyBuild bound lines for nonlinear path constraints.
Each of the nc components carries lower and upper bound lines.
_path_panel [Function]
CTModels.PlotCase._path_panel Function
_path_panel(
sol,
model,
style::NamedTuple;
connect
) -> CTBase.Plotting.PanelBuild a CTBase.Plotting.Panel for the nonlinear path constraints.
_phase_annotations [Function]
CTModels.PlotCase._phase_annotations Function
_phase_annotations(
sol,
time::Symbol,
style::NamedTuple
) -> Vector{CTBase.Plotting.Annotation}Build the phase labels of sol as texts centred on each phase, with CTBase.Plotting.phase_annotations over the state time grid. A phase with an empty label gets no text; a solution with no label gets none.
_phase_label_group [Function]
CTModels.PlotCase._phase_label_group Function
_phase_label_group(
phase_labels::Symbol;
state,
costate,
control,
path,
dual
)Return the group that receives the phase labels: :all for phase_labels = :all; for :control, the control group when it is drawn, otherwise the first drawn group, in the order of the figure (:state, :costate, :path, :dual), or :none when no group is drawn. The keywords tell which groups are drawn.
_rownorm [Function]
CTModels.PlotCase._rownorm Function
_rownorm(row) -> AnyReturn the Euclidean norm of a matrix row.
_sample [Function]
CTModels.PlotCase._sample Function
_sample(f, T) -> AnySample a callable f over grid T into an (n_times, n_components) matrix.
Uniform for scalar and vector-valued f.
_spliced_samples [Function]
CTModels.PlotCase._spliced_samples Function
_spliced_samples(
sol,
T::AbstractVector,
M::AbstractMatrix,
component::Symbol;
connect
) -> Tuple{Any, Any}Insert the left and right limits of component (:state, :costate, :control or :path_dual) at the switching times of sol into the samples (T, M) of that component, with CTBase.Plotting.splice_jumps: a jump is drawn as a vertical segment. The samples are returned unchanged when the solution has no switching time or the limits of component are not known. With connect = false, the curve is broken between the two limits instead of drawing the vertical segment.
Returns
(T, M): the time grid (with each switching time twice) and the matrix of samples.
_state_panel [Function]
CTModels.PlotCase._state_panel Function
_state_panel(
sol,
style::NamedTuple;
connect
) -> CTBase.Plotting.PanelBuild a CTBase.Plotting.Panel for the state trajectory.
_switching_style [Function]
CTModels.PlotCase._switching_style Function
_switching_style(
time_style,
switching_style::NamedTuple
) -> NamedTupleStyle of the switching-time lines. By default they look like the initial/final time lines: the base time style, merged with the user time_style when it is a NamedTuple; a user switching_style merges on top.
_switching_vlines [Function]
CTModels.PlotCase._switching_vlines Function
_switching_vlines(
sol,
time::Symbol,
style::NamedTuple
) -> Vector{CTBase.Plotting.VLine}Build the vertical lines at the switching times of sol, shared by every cell, with CTBase.Plotting.switching_vlines over the state time grid. Empty when the solution has no switching time.
_time_name [Function]
CTModels.PlotCase._time_name Function
_time_name(sol, time::Symbol) -> StringReturn the time-axis label, with the historical "(normalized)" suffix when time is rescaled.
_time_vlines [Function]
CTModels.PlotCase._time_vlines Function
_time_vlines(
sol,
model,
time::Symbol,
style::NamedTuple
) -> Vector{CTBase.Plotting.VLine}Build initial/final time vertical lines shared by every cell.
Positions are [0, 1] under time normalisation, otherwise read from the model (variable-dependent for free time).
build_figure [Function]
CTModels.PlotCase.build_figure Function
build_figure(
sol::CTModels.Solutions.Solution,
description::Symbol...;
layout,
control,
time,
state_style,
costate_style,
control_style,
path_style,
dual_style,
time_style,
state_bounds_style,
control_bounds_style,
path_bounds_style,
switching_style,
phase_labels,
phase_labels_style,
jumps,
size
) -> Union{Nothing, CTBase.Plotting.Figure}Build the CTBase.Plotting.Figure for a CTModels sol (or nothing if there is nothing to draw). Backend-agnostic entry point of the case layer: it resolves the description, gates the groups, builds the panels and decorations, assembles the layout template and wraps it in a Figure. The CTModelsPlots / CTModelsMakie extensions render the result with a concrete backend.
Keyword arguments
layout::Symbol = :split::split(one subplot per component) or:group.control::Symbol = :components::components,:normor:all.time::Symbol = :default::defaultor:normalize/:normalise.size: figure size;nothingdefers to the engine heuristic.the
*_style/*_bounds_style/time_stylekeywords: aNamedTupleof attributes or:noneto hide the group / decoration.switching_style = NamedTuple(): style of the vertical lines at the switching times (seeCTModels.Solutions.switching_times); by default they look like the initial/final time lines (time_styleincluded);:nonehides them.phase_labels::Symbol = :control: where to write the phase labels (seeCTModels.Solutions.phase_labels)::control(the control cell, or the first drawn group when the control is not drawn),:all(every group) or:none.phase_labels_style::NamedTuple = NamedTuple(): style of the phase labels (color,fontsize,halign,valign).jumps::Symbol = :segment: how a jump at a switching time is drawn::segment, a vertical segment from the left to the right limit (it makes the jumps easy to see and to compare with a smoothed jump, e.g. from a direct method), or:none, the curve is broken between the two limits (no segment suggests values the trajectory does not take).
Throws
CTBase.Exceptions.IncorrectArgument: for an invalidlayout,control,time,phase_labelsorjumps.
clean [Function]
CTModels.PlotCase.clean Function
clean(description) -> TupleCollapse plural/alias forms to canonical singular symbols and drop duplicates.
For example, (:states, :controls, :cons, :duals) becomes (:state, :control, :path, :dual).
Arguments
description: A tuple of symbols from the caller.
Returns
Tuple{Symbol...}: Cleaned, unique, canonical symbols.
do_decorate [Function]
CTModels.PlotCase.do_decorate Function
do_decorate(
;
model,
time_style,
state_bounds_style,
control_bounds_style,
path_bounds_style
)Decide which decorations to draw (bounds lines and initial/final time lines).
Each decoration needs a non-:none style and a model to read the bounds/times from.
Returns
NTuple{4, Bool}: flags for(time, state_bounds, control_bounds, path_bounds).
do_plot [Function]
CTModels.PlotCase.do_plot Function
do_plot(
sol::CTModels.Solutions.AbstractSolution,
description::Symbol...;
state_style,
control_style,
costate_style,
path_style,
dual_style
)Decide which signal groups to draw for the given solution and description.
A group is drawn when it is requested, its style is not :none, and it actually exists in the solution:
control needs
control_dimension(sol) > 0,path needs
dim_path_constraints_nl(ocp) > 0,dual needs
path_constraints_dual(sol)to be present.
Returns
NTuple{5, Bool}: flags for(state, costate, control, path, dual).
split_plot_kwargs [Function]
CTModels.PlotCase.split_plot_kwargs Function
split_plot_kwargs(kwargs) -> Tuple{NamedTuple, NamedTuple}Split the user keyword arguments of plot(sol; …) into the pair (build, render): build holds the _BUILD_KEYS consumed by build_figure, render holds everything else (forwarded to the CTBase.Plotting backend).
From CTModels.Building
CompositeConstraint [Struct]
CTModels.Building.CompositeConstraint Type
struct CompositeConstraint{Sig, CS} <: FunctionIn-place callable struct concatenating n nonlinear constraints into a single composite constraint. Sig = :path selects the call method (val, t, x, u, v); Sig = :boundary selects (val, x0, xf, v). Both the signature and the concrete tuple type CS are encoded in type parameters, so each call method is fully specialised with no runtime branch.
Storing n, dims, and funs as fields (Pattern 7) eliminates the capture-by-reference fragility present in the previous make_boundary_cons_nl closure (where constraints_number and constraints_dimensions were outside the let block).
Replaces the anonymous closures path_cons_nl! and boundary_cons_nl! produced inside CTModels.Building.build in build.jl.
Fields
n::Int: Number of individual constraints.dims::Vector{Int}: Dimension of each individual constraint.funs::CS: Concrete tuple of the N constraint functions.
Examples
using CTModels: Building
f1!(r, t, x, u, v) = (r[1] = x[1] + u[1])
f2!(r, t, x, u, v) = (r[1] = x[2])
fc = CompositeConstraint{:path}(2, [1, 1], (f1!, f2!))
val = zeros(2)
fc(val, 0.0, [1.0, 2.0], [3.0], nothing)
# val == [4.0, 2.0]__build_dynamics_from_parts [Function]
CTModels.Building.__build_dynamics_from_parts Function
__build_dynamics_from_parts(
parts::Vector{<:Tuple{var"#s48", var"#s47"} where {var"#s48"<:(AbstractRange{<:Int64}), var"#s47"<:Function}}
) -> CTModels.Building.var"#dyn!#__build_dynamics_from_parts##0"{Vector{var"#s46"}} where var"#s46"<:(Tuple{var"#s45", var"#s44"} where {var"#s45"<:(AbstractRange{<:Int64}), var"#s44"<:Function})Build a single combined in-place dynamics function from ordered partial parts.
Used internally by CTModels.Building.build after all partial dynamics calls have been collected. Each part function updates its assigned slice of the output vector via a @view, avoiding copies.
Arguments
parts::Vector{<:Tuple{<:AbstractRange{<:Int},<:Function}}: Ordered vector of(range, f!)pairs; eachf!(r, t, x, u, v)fillsr=view(val, range).
Returns
Function: Combineddyn!(val, t, x, u, v)that applies all parts in order.
__collect_used_names [Function]
CTModels.Building.__collect_used_names Function
__collect_used_names(
ocp::CTModels.Building.PreModel
) -> Vector{String}Collect all names already used in the PreModel across all components.
Returns a vector containing:
Time name (if set)
State name and components (if set)
Control name and components (if set)
Variable name and components (if set and non-empty)
Example
julia> using CTModels
julia> ocp = CTModels.PreModel(); CTModels.state!(ocp, 2, "x", ["x₁", "x₂"]); CTModels.control!(ocp, 1, "u");
julia> CTModels.Building.__collect_used_names(ocp)
4-element Vector{String}:
"x"
"x₁"
"x₂"
"u"See also: CTModels.Building.__has_name_conflict, CTModels.Building.__validate_name_uniqueness.
__constraint! [Function]
CTModels.Building.__constraint! Function
__constraint!(
ocp_constraints::OrderedCollections.OrderedDict{Symbol, Tuple{Symbol, Union{Function, OrdinalRange{<:Int64}}, AbstractVector{<:Real}, AbstractVector{<:Real}}},
type::Symbol,
n::Int64,
m::Int64,
q::Int64;
rg,
f,
lb,
ub,
label,
codim_f
)Add a constraint to a dictionary of constraints.
Arguments
ocp_constraints: The dictionary of constraints to which the constraint will be added.type: The type of the constraint. It can be:state,:control,:variable,:boundary, or:path.n: The dimension of the state.m: The dimension of the control.q: The dimension of the variable.rg: The range of the constraint. It can be an integer or a range of integers.f: The function that defines the constraint. It must return a vector of the same dimension as the constraint.lb: The lower bound of the constraint. It can be a number or a vector.ub: The upper bound of the constraint. It can be a number or a vector.label: The label of the constraint. It must be unique in the dictionary of constraints.
Requirements
The constraint must not be set before.
The lower bound
lband the upper boundubcannot be bothnothing.The lower bound
lband the upper boundubmust have the same length, if both provided.
If rg and f are not provided then,
typemust be:state,:control, or:variable.lbandubmust be of dimensionn,m, orqrespectively, when provided.
If rg is provided, then:
fmust not be provided.typemust be:state,:control, or:variable.rgmust be a range of integers, and must be contained in1:n,1:m, or1:qrespectively.
If f is provided, then:
rgmust not be provided.typemust be:boundaryor:path.fmust be a function that returns a vector of the same dimension as the constraint.lbandubmust be of the same dimension as the output off, when provided.
Example
julia> using CTModels
julia> ocp_constraints = CTModels.Components.ConstraintsDictType()
julia> CTModels.Building.__constraint!(ocp_constraints, :state, 3, 2, 1; rg=1:2, lb=[-1.0, -1.0], ub=[1.0, 1.0], label=:x_box);__constraint_label [Function]
CTModels.Building.__constraint_label Function
__constraint_label() -> SymbolReturn a unique label for a constraint using gensym with prefix :unnamed.
Returns
Symbol: A unique constraint label.
__constraints [Function]
CTModels.Building.__constraints Function
__constraints()Return the default value for the constraints.
Returns
Nothing
__control_components [Function]
CTModels.Building.__control_components Function
__control_components(
m::Int64,
name::String
) -> Vector{String}Return the default component names for a control variable of dimension m.
Arguments
m::Dimension: The control dimension.name::String: The base name for components.
Returns
Vector{String}: Component names (single element for m=1, subscripted for m>1).
__control_interpolation [Function]
CTModels.Building.__control_interpolation Function
__control_interpolation() -> SymbolReturn the default control interpolation type.
Returns
Symbol: The interpolation type (:constantfor piecewise constant,:linearfor piecewise linear).
__control_name [Function]
CTModels.Building.__control_name Function
__control_name() -> StringReturn the default name of the control variable.
Returns
String: The default control name ("u").
__criterion_type [Function]
CTModels.Building.__criterion_type Function
__criterion_type() -> SymbolReturn the default optimization criterion type.
Returns
Symbol: The criterion type (:minfor minimization).
__filename_export_import [Function]
CTModels.Building.__filename_export_import Function
__filename_export_import() -> StringReturn the default filename (without extension) for exporting and importing solutions.
Returns
String: The default filename ("solution").
__format [Function]
CTModels.Building.__format Function
__format() -> SymbolReturn the default format of the file to be used for export and import.
Returns
Symbol: The format symbol (:JLD).
__has_name_conflict [Function]
CTModels.Building.__has_name_conflict Function
__has_name_conflict(
ocp::CTModels.Building.PreModel,
new_name::String
) -> Bool
__has_name_conflict(
ocp::CTModels.Building.PreModel,
new_name::String,
exclude_component::Symbol
) -> BoolCheck if a name conflicts with existing names in the PreModel.
Arguments
ocp::PreModel: The model to check againstnew_name::String: The new name to checkexclude_component::Symbol: Component type to exclude from check (:state,:control,:variable,:time,:none)
The exclude_component parameter allows checking for conflicts while updating a component, excluding the component's own current names from the check.
Returns
Bool:trueif conflict exists,falseotherwise
Example
julia> using CTModels
julia> ocp = CTModels.PreModel(); CTModels.state!(ocp, 2, "x", ["x₁", "x₂"]);
julia> CTModels.Building.__has_name_conflict(ocp, "x", :none)
true
julia> CTModels.Building.__has_name_conflict(ocp, "y", :none)
falseSee also: CTModels.Building.__collect_used_names, CTModels.Building.__validate_name_uniqueness.
__is_autonomous_set [Function]
CTModels.Building.__is_autonomous_set Function
__is_autonomous_set(ocp::CTModels.Building.PreModel) -> BoolReturn true if the autonomous flag has been set in the PreModel.
Returns
Bool
__is_consistent [Function]
CTModels.Building.__is_consistent Function
__is_consistent(ocp::CTModels.Building.PreModel) -> BoolReturn true if all the required fields are set in the PreModel.
Arguments
ocp::PreModel: The pre-model to check.
Returns
Bool
__is_control_empty [Function]
CTModels.Building.__is_control_empty Function
__is_control_empty(c) -> BoolReturn true if c is an EmptyControlModel.
Returns
Bool
__is_control_empty(ocp::CTModels.Building.PreModel) -> BoolReturn true if the control field of the PreModel is an EmptyControlModel.
Returns
Bool
__is_definition_empty [Function]
CTModels.Building.__is_definition_empty Function
__is_definition_empty(d) -> BoolReturn true if d is an CTModels.Components.EmptyDefinition.
Returns
Bool
__is_definition_empty(
ocp::CTModels.Building.PreModel
) -> BoolReturn true if the definition field of the PreModel is an CTModels.Components.EmptyDefinition.
Returns
Bool
__is_dynamics_complete [Function]
CTModels.Building.__is_dynamics_complete Function
__is_dynamics_complete(
ocp::CTModels.Building.PreModel
) -> BoolReturn true if dynamics cover all state components in the PreModel.
For component-wise dynamics, checks that all state indices are covered.
Arguments
ocp::PreModel: The pre-model to check.
Returns
Bool
__is_dynamics_set [Function]
CTModels.Building.__is_dynamics_set Function
__is_dynamics_set(ocp::CTModels.Building.PreModel) -> BoolReturn true if dynamics have been set in the PreModel.
Returns
Bool
__is_empty [Function]
CTModels.Building.__is_empty Function
__is_empty(ocp::CTModels.Building.PreModel) -> BoolReturn true if nothing has been set.
Arguments
ocp::PreModel: The pre-model to check.
Returns
Bool
__is_objective_set [Function]
CTModels.Building.__is_objective_set Function
__is_objective_set(ocp::CTModels.Building.PreModel) -> BoolReturn true if objective has been set in the PreModel.
Returns
Bool
__is_set [Function]
CTModels.Building.__is_set Function
__is_set(x) -> BoolReturn true if x is not nothing.
Returns
Bool
__is_state_set [Function]
CTModels.Building.__is_state_set Function
__is_state_set(ocp::CTModels.Building.PreModel) -> BoolReturn true if state has been set in the PreModel.
Returns
Bool
__is_times_set [Function]
CTModels.Building.__is_times_set Function
__is_times_set(ocp::CTModels.Building.PreModel) -> BoolReturn true if times have been set in the PreModel.
Returns
Bool
__is_variable_empty [Function]
CTModels.Building.__is_variable_empty Function
__is_variable_empty(v) -> BoolReturn true if v is an EmptyVariableModel.
Returns
Bool
__is_variable_empty(ocp::CTModels.Building.PreModel) -> BoolReturn true if the variable field of the PreModel is an EmptyVariableModel.
Returns
Bool
__state_components [Function]
CTModels.Building.__state_components Function
__state_components(n::Int64, name::String) -> Vector{String}Return the default component names for a state variable of dimension n.
Arguments
n::Dimension: The state dimension.name::String: The base name for components.
Returns
Vector{String}: Component names (single element for n=1, subscripted for n>1).
__state_name [Function]
CTModels.Building.__state_name Function
__state_name() -> StringReturn the default name of the state variable.
Returns
String: The default state name ("x").
__time_grid_default_component [Function]
CTModels.Building.__time_grid_default_component Function
__time_grid_default_component() -> SymbolReturn the default component for time grid access in multiple time grid solutions.
Returns
Symbol: The default component (:state).
__time_name [Function]
CTModels.Building.__time_name Function
__time_name() -> StringReturn the default name of the time variable.
Returns
String: The default time name ("t").
__validate_name_uniqueness [Function]
CTModels.Building.__validate_name_uniqueness Function
__validate_name_uniqueness(
ocp::CTModels.Building.PreModel,
name::String,
components::Vector{String},
component_type::Symbol
)Validate that a name and its components don't conflict with existing names.
Performs comprehensive validation:
Name is not empty
Components are not empty
Name not in components (internal conflict)
No duplicates in components
No conflicts with existing names in other components (global uniqueness)
Arguments
ocp::PreModel: The model to validate againstname::String: The component namecomponents::Vector{String}: The component namescomponent_type::Symbol: Type of component (:state,:control,:variable,:time)
Throws
Exceptions.IncorrectArgument: If any validation fails
Example
julia> using CTModels
julia> ocp = CTModels.PreModel(); CTModels.state!(ocp, 2, "x", ["x₁", "x₂"]);
julia> CTModels.Building.__validate_name_uniqueness(ocp, "y", ["u"], :control) # "y" is unique: succeedsSee also: CTModels.Building.__has_name_conflict, CTModels.Building.__collect_used_names.
__variable_components [Function]
CTModels.Building.__variable_components Function
__variable_components(
q::Int64,
name::String
) -> Vector{String}Return the default component names for a variable of dimension q.
Arguments
q::Dimension: The variable dimension.name::String: The base name for components.
Returns
Vector{String}: Component names (empty for q=0, single element for q=1, subscripted for q>1).
__variable_name [Function]
CTModels.Building.__variable_name Function
__variable_name(q::Int64) -> StringReturn the default name for optimization variables.
Arguments
q::Dimension: The variable dimension.
Returns
String: The variable name ("v"for q>0, empty string for q=0).
_dedup_box_constraints! [Function]
CTModels.Building._dedup_box_constraints! Function
_dedup_box_constraints!(
inds::Vector{Int64},
lbs::Array{T<:Real, 1},
ubs::Array{T<:Real, 1},
labels::Vector{Symbol},
aliases::Vector{Vector{Symbol}},
kind::String
)Deduplicate box-constraint declarations by component, applying the intersection of all declared bounds for each repeated component. Produces an aliases vector recording every label that targeted each component.
After this function returns, the vectors satisfy the invariant:
allunique(inds)— each component appears at most once.lbs[k]=maxof all declared lower bounds for componentinds[k].ubs[k]=minof all declared upper bounds for componentinds[k].labels[k]= the first label that declared componentinds[k](stable order).aliases[k]= all distinct labels that declared componentinds[k], in first-seen order (always starts withlabels[k]).Vectors are sorted by
inds.
A @warn is emitted once for each duplicated component, listing all contributing labels. If the intersection is empty (i.e. max(lbs_k) > min(ubs_k)), an CTBase.Exceptions.IncorrectArgument is thrown.
Arguments
inds,lbs,ubs,labels: in-place flat vectors produced by successive calls toCTModels.Building.append_box_constraints!.aliases: in-place emptyVector{Vector{Symbol}}to be populated with the per-component list of all declaring labels.kind::String: human-readable descriptor (e.g. "state", "control", "variable") used in diagnostic messages.
Throws
CTBase.Exceptions.IncorrectArgumentif the intersection of declared bounds is empty for some component.
Returns
Nothing
as_range [Function]
CTModels.Building.as_range Function
as_range(::Nothing) -> NothingReturn nothing unchanged.
Returns
Nothing
as_range(r::Int) -> UnitRange{Int}Convert a scalar integer to a single-element range r:r.
Arguments
r::Int: An integer index.
Returns
UnitRange{Int}: A range containing onlyr.
Example
julia> as_range(3)
3:3as_range(r::OrdinalRange{Int}) -> OrdinalRange{Int}Return an ordinal range unchanged.
Arguments
r::OrdinalRange{Int}: A range of integers.
Returns
OrdinalRange{Int}: The input range unchanged.
Example
julia> as_range(1:5)
1:5as_vector [Function]
CTModels.Building.as_vector Function
as_vector(::Nothing) -> NothingReturn nothing unchanged.
Returns
Nothing
as_vector(x::T) -> Vector{T} where {T<:ctNumber}Wrap a scalar number into a single-element vector.
Arguments
x::T: A scalar number.
Returns
Vector{T}: A single-element vector containingx.
Example
julia> as_vector(1.0)
1-element Vector{Float64}:
1.0as_vector(x::AbstractVector{T}) -> AbstractVector{T} where {T<:ctNumber}Return a vector unchanged.
Arguments
x::AbstractVector{T}: A vector of numbers.
Returns
AbstractVector{T}: The input vector unchanged.
Example
julia> as_vector([1.0, 2.0, 3.0])
3-element Vector{Float64}:
1.0
2.0
3.0From CTModelsMakie
_plot [Function]
CTModelsMakie._plot Function
_plot(
sol::CTModels.Solutions.Solution,
description::Symbol...;
size,
color,
kwargs...
) -> Makie.FigureInternal implementation of Makie.plot(::CTModels.Solution).
Builds the figure with CTModels.PlotCase.build_figure and renders it via CTBase.Plotting (Makie backend).
_plot! [Function]
CTModelsMakie._plot! Function
_plot!(
f::Makie.Figure,
sol::CTModels.Solutions.Solution,
description::Symbol...;
color,
kwargs...
) -> Makie.FigureInternal implementation of Makie.plot!(::Makie.Figure, ::CTModels.Solution).
Builds the figure with CTModels.PlotCase.build_figure and overlays it onto f via CTBase.Plotting (Makie backend); an empty f is filled as if by plot.
From CTModels.Serialization
_check_data_dimensions! [Function]
CTModels.Serialization._check_data_dimensions! Function
_check_data_dimensions!(errors, ocp, data)Compare what can be deduced from the arrays of the file (dimensions of the trajectories and of the duals, number of samples) with the model. Works on files of any age.
Arguments
errors: Vector of differences, modified in place.ocp: The model.data: Dictionary containing the imported solution data.
Returns
Nothing
_check_signature! [Function]
CTModels.Serialization._check_signature! Function
_check_signature!(errors, warnings, ocp, sig)Compare the model signature stored in the file with the signature of the model. Only used for files exported with a model signature.
Differences that can make the solution unusable (dimensions, number and labels of the constraints, fixed versus free times) are recorded in errors; the others (names, objective, values of fixed times) in warnings.
Arguments
errors: Vector of differences, modified in place.warnings: Vector of differences, modified in place.ocp: The model.sig: The signature stored in the file.
Returns
Nothing
_data_time_grids [Function]
CTModels.Serialization._data_time_grids Function
_data_time_grids(data) -> AnyTime grids stored in the data, as a vector of (component, grid) pairs.
Arguments
data: Dictionary containing the imported solution data.
Returns
Vector{Tuple{Symbol,Vector{Float64}}}: The grid of each of:state,:control,:costateand:path(all equal to"time_grid"in the unified format); empty if the data has no time grid.
_ensure_extension [Function]
CTModels.Serialization._ensure_extension Function
_ensure_extension(filename::String, ext::String) -> StringReturn filename with ext appended, unless filename already ends with ext (case-insensitively).
Arguments
filename::String: base filename, with or withoutext.ext::String: extension to ensure, including the leading dot (e.g.".json").
Returns
String:filenameunchanged if it already ends withext;filename * extotherwise.
Example
julia> using CTModels: Serialization
julia> Serialization._ensure_extension("solution", ".json")
"solution.json"
julia> Serialization._ensure_extension("solution.json", ".json")
"solution.json"_extract_optional_vector [Function]
CTModels.Serialization._extract_optional_vector Function
_extract_optional_vector(x) -> AnyNothing-safe wrapper around CTModels.Serialization._extract_time_vector.
Used to normalize the "variable_constraints_lb_dual"/"ub_dual" fields, which are nullable (unlike the time grids and "variable", which are always present).
See also: CTModels.Serialization._reconstruct_solution_from_data.
_extract_time_vector [Function]
CTModels.Serialization._extract_time_vector Function
_extract_time_vector(time_data) -> AnyExtract time vector from various data formats.
Arguments
time_data: Time data in various formats (Vector, Matrix, scalar, etc.)
Returns
Vector{Float64}: Time vector
Notes
Handles Vector{Float64}, Matrix{Float64} (single column) and scalar
RealformatsUsed by JSON and JLD2 importers to normalize time grid data, and to normalize the
"variable"field, which is serialized as a scalar whenvariable_dimension(ocp) == 1(per the "1-D is a scalar" convention, seeCTModels.Components.variable)
See also: CTModels.Serialization._reconstruct_solution_from_data.
_format_difference [Function]
CTModels.Serialization._format_difference Function
_format_difference(d, side::Int64) -> StringFormat one side of a recorded difference (what, file_value, model_value) as "what = value": side = 1 for the file, side = 2 for the model.
_ncols [Function]
CTModels.Serialization._ncols Function
_ncols(_::Nothing)Number of columns of a stored matrix, or nothing when the entry is absent.
_nlength [Function]
CTModels.Serialization._nlength Function
_nlength(_::Nothing)Number of points of a stored time grid, or nothing when the entry is absent.
_nrows [Function]
CTModels.Serialization._nrows Function
_nrows(_::Nothing)Number of rows of a stored array, or nothing when the entry is absent.
_optional [Function]
CTModels.Serialization._optional Function
_optional(data, key::String, _::Type{T}) -> AnyRead the optional solver field key of data as a T, or Core.NotProvided if it is unset.
A field is unset when its key is missing or when its value is nothing (null in JSON), Core.NotProvided, or the string "NotProvided" (written by older versions).
Throws
CTBase.Exceptions.ParsingError: if the value cannot be converted toT.
_reconstruct_solution_from_data [Function]
CTModels.Serialization._reconstruct_solution_from_data Function
_reconstruct_solution_from_data(
ocp,
data;
infos
) -> CTModels.Solutions.Solution{TimeGridModelType, TimesModelType, StateModelType, ControlModelType, VariableModelType, ModelType, CostateModelType, Float64, DualModelType, CTModels.Solutions.SolverInfos{Any, Dict{Symbol, Any}}, SwitchingModelType} where {TimeGridModelType<:Union{CTModels.Solutions.MultipleTimeGridModel, CTModels.Solutions.UnifiedTimeGridModel{Vector{Float64}}}, TimesModelType<:CTModels.Components.TimesModel, StateModelType<:(CTModels.Components.StateModelSolution{TS} where TS<:CTModels.Components.CoercedTrajectory), ControlModelType<:(CTModels.Components.ControlModelSolution{TS} where TS<:CTModels.Components.CoercedTrajectory), VariableModelType<:Union{CTModels.Components.VariableModelSolution{Vector{Float64}}, CTModels.Components.VariableModelSolution{Float64}}, ModelType<:(CTModels.Models.Model{<:CTBase.Traits.TimeDependence, T} where T<:CTModels.Components.TimesModel), CostateModelType<:CTModels.Components.CoercedTrajectory, DualModelType<:Union{CTModels.Solutions.EmptyDualModel, CTModels.Solutions.DualModel{PC_Dual, BC_Dual, SC_LB_Dual, SC_UB_Dual, CC_LB_Dual, CC_UB_Dual, VC_LB_Dual, VC_UB_Dual} where {PC_Dual<:Union{Nothing, CTModels.Components.CoercedTrajectory}, BC_Dual<:Union{Nothing, Vector{Float64}}, SC_LB_Dual<:Union{Nothing, CTModels.Components.CoercedTrajectory}, SC_UB_Dual<:Union{Nothing, CTModels.Components.CoercedTrajectory}, CC_LB_Dual<:Union{Nothing, CTModels.Components.CoercedTrajectory}, CC_UB_Dual<:Union{Nothing, CTModels.Components.CoercedTrajectory}, VC_LB_Dual<:Union{Nothing, Float64, Vector{Float64}}, VC_UB_Dual<:Union{Nothing, Float64, Vector{Float64}}}}, SwitchingModelType<:Union{CTModels.Solutions.EmptySwitchingModel, CTModels.Solutions.SwitchingModel}}Reconstruct a solution from imported data, detecting the format (single vs multiple time grids).
Duals and control_interpolation are read from data. Only infos is accepted as a keyword argument because its deserialization is format-specific (JSON restores Symbol types).
Arguments
ocp: The optimal control problem modeldata: Dictionary containing the imported solution data, including all dual fields andcontrol_interpolation
Keyword Arguments
infos: Solver information dictionary (Dict{Symbol,Any}). Passed explicitly because JSON deserialization must restoreSymboltypes before calling this helper.
Returns
Solution: Reconstructed solution with appropriate time grid model
Notes
If
time_grid_statekey exists, assumes multiple time grid formatOtherwise, uses the current unified format (single
time_gridkey)The switching structure is rebuilt when the data holds it (
"switching_times"), so the trajectories keep their jumps (seeCTModels.Solutions.build_solution)
Example
julia> sol = _reconstruct_solution_from_data(ocp, data; infos=infos)See also: CTModels.Serialization._extract_time_vector.
_record_difference! [Function]
CTModels.Serialization._record_difference! Function
_record_difference!(
list,
what::String,
file_value,
model_value
)Record a difference (what, file_value, model_value) in list, unless file_value is nothing (unknown) or equal to model_value, or what is already recorded.
Arguments
list: Vector of differences, modified in place.what::String: Description of the compared quantity.file_value: Value found in the file (nothingif it cannot be known).model_value: Value found in the model.
Returns
Nothing
_validate_solution_against_model [Function]
CTModels.Serialization._validate_solution_against_model Function
_validate_solution_against_model(ocp, data)Check that imported solution data is compatible with the model it is going to be rebuilt against, before calling build_solution.
The check is performed in two stages:
from the arrays of the file only (dimensions of the trajectories and of the duals, number of samples versus time grids, fixed times versus the first and last grid points): works for files of any age;
from the model signature stored in the file (see
CTModels.Models._model_signature), if present: also catches differences that the arrays cannot show (absent duals, constraint labels, names, fixed versus free times).
Arguments
ocp: The model the solution is rebuilt against.data: Dictionary containing the imported solution data.
Returns
Nothing
Throws
CTBase.Exceptions.IncorrectArgument: if the file cannot belong to a solution ofocp(dimensions, number or labels of constraints, fixed versus free times, corrupted arrays). All differences are reported in the same error.
Notes
Differences which cannot make the solution unusable (names of the components, criterion, cost type, values of fixed times) only produce a warning. A file without model signature produces an informational message.
See also: CTModels.Serialization._reconstruct_solution_from_data.