Skip to content

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
julia
_plot(
    sol::CTModels.Solutions.Solution,
    description::Symbol...;
    size,
    color,
    kwargs...
)

Internal 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
julia
_plot!(
    p::Plots.Plot,
    sol::CTModels.Solutions.Solution,
    description::Symbol...;
    color,
    kwargs...
) -> Plots.Plot

Internal 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 ​

_DUALS_WITH_UNKNOWN_FIELDS [Constant] ​

CTModelsJSON._DUALS_WITH_UNKNOWN_FIELDS Constant

Dual fields whose unknown entries are NaN (the duals given by label): written as null.

_DUAL_MASK_FIELDS [Constant] ​

CTModelsJSON._DUAL_MASK_FIELDS Constant

The masks of the known rows of the duals, written only when some rows are unknown.

_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_dual_matrix [Function] ​

CTModelsJSON._json_to_optional_dual_matrix Function

Convert an optional JSON dual matrix (rows of numbers, null for an unknown entry) to a Matrix{Float64} with NaN for the unknown entries, or nothing.

_json_to_optional_mask [Function] ​

CTModelsJSON._json_to_optional_mask Function

Convert an optional JSON mask of the known rows to Vector{Bool} or nothing.

_nan_to_null [Function] ​

CTModelsJSON._nan_to_null Function

Replace the NaN entries of a dual (a vector, or the rows of a matrix) by nothing, written as null in JSON; nothing is left as is.

_null_to_nan [Function] ​

CTModelsJSON._null_to_nan Function

Replace the null entries of a dual read from JSON (a vector, or the rows of a matrix) by NaN: the inverse of _nan_to_null.

_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
julia
BoxDualDiff{DL,DU,I,C} <: Function

Callable 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.

BoxDualSplit [Struct] ​

CTModels.Solutions.BoxDualSplit Type
julia
struct BoxDualSplit{S, F} <: Function

One side of the box multipliers of a box label given by its signed dual: f(t) is the lower-bound multiplier zL (S = :lower) or the upper-bound multiplier zU (S = :upper) of each component of the label, split from the signed dual dual(t) with the coefficients (cl, cu) of the components (see CTModels.Solutions._split_lower, CTModels.Solutions._split_upper).

Fields

  • dual::F: The signed dual of the label, t -> value (a scalar for one component).

  • cl::Vector{Float64}, cu::Vector{Float64}: The coefficients of the components.

DualMasks [Struct] ​

CTModels.Solutions.DualMasks Type
julia
struct DualMasks

The masks of the known rows of the duals of a solution, one per kind of constraint.

A mask has one entry per row of the stacked constraint (path, boundary) or per component (state, control, variable box): true when the dual of that row is known. The masks are canonical: nothing when every row of the stored duals of that kind is known, a vector only when some rows are known and others are not. A kind with no known row stores no dual at all (nothing in the CTModels.Solutions.DualModel), with the mask nothing.

Fields

  • path, boundary, state, control, variable: Union{Nothing,Vector{Bool}}.

DualSlice [Struct] ​

CTModels.Solutions.DualSlice Type
julia
DualSlice{D,I} <: Function

Callable 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 an CTModels.Solutions.EmptySwitchingModel.

  • 3: masks of the known rows of the duals ("<kind>_constraints_dual_known" for path, boundary, state, control, variable), written only when some rows are unknown; the unknown entries of the duals are NaN (null in JSON). Limits of the box duals at the switching times ("switching_state_dual_<side>", "switching_control_dual_<side>"). Files without the masks are read with every stored row known.

StackedDuals [Struct] ​

CTModels.Solutions.StackedDuals Type
julia
struct StackedDuals{P<:Tuple} <: Function

The duals given by label, as one function of time on the stacked layout of the model: f(t) is a vector with one entry per row (stacked path constraint) or per component (box multipliers), the rows of a given label filled by its function, and fill in the other rows: NaN for the path duals (the labels not given are unknown), 0 for the box multipliers (a component bounded by no label).

Each part is a pair (rows, g): rows the rows of the label (see CTModels.Models.constraint_rows), g its dual t -> value (a scalar for a one-row label, a vector otherwise).

Fields

  • dim::Int: The number of rows.

  • parts::P: The parts, a tuple of (rows, g) pairs.

  • fill::Float64: The value of the rows covered by no part.

_JumpInterpolant [Struct] ​

CTModels.Solutions._JumpInterpolant Type
julia
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.

_LIMIT_COMPONENTS [Constant] ​

CTModels.Solutions._LIMIT_COMPONENTS Constant

The components of a switching model with (left, right) limits.

_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_limit_matrices [Function] ​

CTModels.Solutions._as_limit_matrices Function
julia
_as_limit_matrices(lr) -> Tuple{Any, Any}

The (left, right) limits of a label as two matrices: a vector (one-row label) becomes a one-column matrix.

Throws

_as_mask [Function] ​

CTModels.Solutions._as_mask Function
julia
_as_mask(::Nothing)

A mask of the known rows read from a file as a Vector{Bool} (nothing: every row known).

_as_vector [Function] ​

CTModels.Solutions._as_vector Function
julia
_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.

See also: CTModels.Solutions._discretize_all_components.

_box_dual [Function] ​

CTModels.Solutions._box_dual Function
julia
_box_dual(
    duals_lb,
    duals_ub,
    cp,
    idxs::Vector{Int64}
) -> Union{CTModels.Solutions.BoxDualDiff{<:Any, <:Any, Vector{Int64}, Vector{Float64}}, CTModels.Solutions.BoxDualDiff{<:Any, <:Any, Int64, Float64}}

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
julia
_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).

_box_known [Function] ​

CTModels.Solutions._box_known Function
julia
_box_known(
    parts::Vector{Pair{Vector{Int64}, Any}},
    cp::Tuple,
    dim::Int64
) -> Tuple{Union{Nothing, Vector{Bool}}, Vector{Int64}}

The canonical mask of the known components of a box given by the parts components => value, and the components left unknown: the bounded components of the box tuple cp whose label is not among the parts. A component bounded by no label is known (its dual is 0).

_by_label_or_keyword [Function] ​

CTModels.Solutions._by_label_or_keyword Function
julia
_by_label_or_keyword(
    placed,
    kind::Symbol,
    keywords::Tuple,
    names::String
)

The duals of the kind kind for the solution: those placed from the labels in placed (see CTModels.Solutions._place_duals) when some label of that kind was given, the keyword values keywords otherwise (every row known), followed by the mask of the known rows.

Throws

_canonical_mask [Function] ​

CTModels.Solutions._canonical_mask Function
julia
_canonical_mask(
    known::Vector{Bool}
) -> Union{Nothing, Vector{Bool}}

The canonical form of a mask of the known rows: nothing when every row is known, the mask itself otherwise. A mask with no known row never reaches this function: a kind of constraint with no known dual is stored as nothing.

_check_limit_component [Function] ​

CTModels.Solutions._check_limit_component Function
julia
_check_limit_component(component::Symbol)

Check that component is a component with switching limits (see CTModels.Solutions._LIMIT_COMPONENTS).

Throws

_check_switching [Function] ​

CTModels.Solutions._check_switching Function
julia
_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

_checked_limits [Function] ​

CTModels.Solutions._checked_limits Function
julia
_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

_checked_static_dual [Function] ​

CTModels.Solutions._checked_static_dual Function
julia
_checked_static_dual(
    label::Symbol,
    kind::Symbol,
    rows::Vector{Int64},
    value
) -> Union{Real, AbstractVector{<:Real}}

Check the dual value given for the label label of a time-independent constraint (kind :boundary or :variable) of rows rows: a Number for a one-row label, a vector with one entry per row otherwise.

_checked_timed_dual [Function] ​

CTModels.Solutions._checked_timed_dual Function
julia
_checked_timed_dual(
    label::Symbol,
    kind::Symbol,
    rows::Vector{Int64},
    value,
    T
)

Check the dual value given for the label label of a time-dependent constraint (kind :path, :state or :control) of rows rows: a Function t -> value (its size is checked at the first time of the grid T), or a matrix with one row per time of T and one column per row of the label (a vector for a one-row label). Returns the value, a vector being turned into a one-column matrix.

_claim_components! [Function] ​

CTModels.Solutions._claim_components! Function
julia
_claim_components!(
    owners::Dict{Tuple{Symbol, Int64}, Symbol},
    kind::Symbol,
    rows::Vector{Int64},
    label::Symbol
)

Record that the box label label gives the dual of the kind components rows, in owners ((kind, component) => label).

Throws

  • CTBase.Exceptions.IncorrectArgument: if a component is already given by another label. Several labels on one component (aliases) share its single multiplier, so it is given by one of them only: two values would leave one silently overwritten.

_deserialize_switching [Function] ​

CTModels.Solutions._deserialize_switching Function
julia
_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
julia
_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_state grid

  • Control trajectory → T_control grid

  • Costate trajectory → T_costate grid

  • Path constraint duals → T_path grid

  • State box constraint duals (lb/ub) → T_state grid

  • Control box constraint duals (lb/ub) → T_control grid

  • Boundary/variable duals → Time-independent (vectors, not discretized)

Arguments

  • sol::Solution: Solution object containing trajectory functions

  • T_state::Vector{Float64}: Time grid for state discretization

  • T_control::Vector{Float64}: Time grid for control discretization

  • T_costate::Vector{Float64}: Time grid for costate discretization

  • T_path::Vector{Float64}: Time grid for path constraint dual discretization

  • dim_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
julia
_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 or nothing.

  • T: Time grid.

  • dim::Int: Dimension (auto-detected if -1).

Returns

  • Matrix{Float64} if dual_func is a function.

  • nothing if dual_func is nothing.

See also: CTModels.Solutions._discretize_function.

_discretize_function [Function] ​

CTModels.Solutions._discretize_function Function
julia
_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

julia
# 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.

julia
_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
julia
_dual_dimension(
    ::Nothing,
    ::CTModels.Solutions.Solution
) -> Int64

Return 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.

_dual_masks [Function] ​

CTModels.Solutions._dual_masks Function
julia
_dual_masks(
    sol::CTModels.Solutions.Solution
) -> CTModels.Solutions.DualMasks

The masks of the known rows of the duals of sol (see CTModels.Solutions.DualMasks); every mask nothing when the solution carries no duals.

_duals_by_label [Function] ​

CTModels.Solutions._duals_by_label Function
julia
_duals_by_label(
    ocp::CTModels.Models.Model,
    path::Union{Nothing, AbstractMatrix{<:Real}},
    boundary::Union{Nothing, AbstractVector{<:Real}},
    path_known::Union{Nothing, AbstractVector{Bool}},
    boundary_known::Union{Nothing, AbstractVector{Bool}}
) -> Dict{Symbol, Any}

The inverse of the placement: the path and boundary duals stored on the stacked layout of ocp (path: a matrix with one column per row, or nothing; boundary: a vector or nothing), with their canonical masks, given back by label, as CTModels.Solutions.build_solution takes them in duals. A label with an unknown row is left out. Used to rebuild a solution read from a file.

_ensure_dual [Function] ​

CTModels.Solutions._ensure_dual Function
julia
_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).

_ensure_dual_size [Function] ​

CTModels.Solutions._ensure_dual_size Function
julia
_ensure_dual_size(
    label::Symbol,
    n::Int64,
    got::Int64,
    what::String
)

Throw an CTBase.Exceptions.IncorrectArgument when the dual given for label has got entries instead of the n rows of the label.

_ensure_known [Function] ​

CTModels.Solutions._ensure_known Function
julia
_ensure_known(
    sol::CTModels.Solutions.Solution,
    known::Union{Nothing, Vector{Bool}},
    rows::Vector{Int64},
    label::Symbol,
    kind::String
)

Throw a CTBase.Exceptions.PreconditionError when some of the rows rows of the kind constraint label are unknown in the mask known (see CTModels.Solutions.DualModel): the duals of this kind were stored, but not the one of label, which was absent from the duals given to CTModels.Solutions.build_solution.

_extend_grid_to_match [Function] ​

CTModels.Solutions._extend_grid_to_match Function
julia
_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 extend

  • T_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 original T_target

Notes

  • Extension condition: length(T_target) == length(T_reference) - 1 AND T_target == T_reference[1:end-1]

  • Emits @info log when extension is performed for transparency

  • Does 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
julia
_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 vector

  • dim: 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 nothing

  • constant_if_two_points: If true and length(T)==2, return constant function

  • expected_dim: If provided, validates matrix dimension matches (via @ensure)

  • interpolation: Interpolation type (:linear or :constant)

Returns

  • Interpolated function (or nothing if data=nothing and allow_nothing=true)

Throws

  • IncorrectArgument: If data is nothing and allow_nothing=false

  • AssertionError: 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.

_interpolate_part [Function] ​

CTModels.Solutions._interpolate_part Function
julia
_interpolate_part(
    value::Matrix{Float64},
    T,
    n::Int64
) -> CTModels.Components.CoercedTrajectory
_interpolate_part(
    value::Matrix{Float64},
    T,
    n::Int64,
    interpolation::Symbol
) -> CTModels.Components.CoercedTrajectory

A matrix part of the duals as a function of time on the grid T, with interpolation (a scalar for one row).

_known_rows [Function] ​

CTModels.Solutions._known_rows Function
julia
_known_rows(
    parts::Vector{<:Pair{<:AbstractVector{Int64}, Any}},
    dim::Int64
) -> Union{Nothing, Vector{Bool}}

The canonical mask of the rows covered by parts among dim rows.

_limit [Function] ​

CTModels.Solutions._limit Function
julia
_limit(
    sol::CTModels.Solutions.Solution,
    component::Symbol,
    i::Integer,
    side::Int64
)

Shared implementation of CTModels.Solutions.left_limit (side = 1) and CTModels.Solutions.right_limit (side = 2).

_limit_matrix [Function] ​

CTModels.Solutions._limit_matrix Function
julia
_limit_matrix(x::AbstractVector{<:Real})

The limits of a label on one side as a matrix: a vector (one-row label) becomes a one-column matrix.

Throws

_missing_duals_note [Function] ​

CTModels.Solutions._missing_duals_note Function
julia
_missing_duals_note(
    sol::CTModels.Solutions.Solution,
    default::AbstractString
) -> String

The 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
julia
_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
julia
_phase_sequence(
    labels::AbstractVector{<:AbstractString}
) -> String

Return 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.

_place_boundary_duals [Function] ​

CTModels.Solutions._place_boundary_duals Function
julia
_place_boundary_duals(
    parts::Vector{<:Pair{<:AbstractVector{Int64}, Any}},
    dim::Int64
) -> Union{Tuple{Nothing, Nothing}, Tuple{Vector{Float64}, Union{Nothing, Vector{Bool}}}}

The boundary duals of the parts rows => value on dim stacked rows (NaN in the unknown rows), with their canonical mask.

_place_box_duals [Function] ​

CTModels.Solutions._place_box_duals Function
julia
_place_box_duals(
    parts::Vector{Pair{Vector{Int64}, Any}},
    cp::Tuple,
    dim::Int64,
    T,
    interpolation::Symbol
) -> Union{Nothing, Tuple{Any, Any, Union{Nothing, Vector{Bool}}}}

The state or control box duals of the parts components => value (the signed duals given by label), on dim components, split into (lb, ub, known): the lower- and upper-bound multipliers and the canonical mask of the known components. A component bounded by no label carries a known 0, as with the box keywords; a bounded component whose label is not given holds NaN.

When every value is a matrix (sampled on T), the multipliers are matrices, interpolated afterwards as the box keywords are. Otherwise each part becomes a function of time (a matrix is interpolated on T with interpolation) and each side is a CTModels.Solutions.StackedDuals of CTModels.Solutions.BoxDualSplit.

_place_dual_limits [Function] ​

CTModels.Solutions._place_dual_limits Function
julia
_place_dual_limits(
    sw::CTModels.Solutions.EmptySwitchingModel,
    ::CTModels.Models.Model
) -> CTModels.Solutions.EmptySwitchingModel

Place the limits of the duals given by label to the switching model sw (its labelled_duals) on the layout of ocp: the limits of a path label go to the columns of its rows in path_dual, those of a state or control box label (signed duals) to the columns of its components in state_dual or control_dual. The columns of a kind with some label given and the others not are NaN; a kind with no label keeps its limits. Returns a switching model with no label left to place.

Throws

  • CTBase.Exceptions.IncorrectArgument: if a label is not a constraint of ocp, is not a path, state box or control box label (a boundary or variable dual does not depend on time), its limits have the wrong number of columns, or the limits of the path duals are given both by label and by path_dual.

_place_duals [Function] ​

CTModels.Solutions._place_duals Function
julia
_place_duals(
    ocp::CTModels.Models.Model,
    duals::AbstractDict{Symbol},
    T_path;
    T_state,
    T_control,
    control_interpolation::Symbol
) -> NamedTuple{(:path, :boundary, :state, :control, :variable), <:Tuple{Tuple{Any, Union{Nothing, Vector{Bool}}}, Union{Tuple{Nothing, Nothing}, Tuple{Vector{Float64}, Union{Nothing, Vector{Bool}}}}, Union{Nothing, Tuple{Any, Any, Union{Nothing, Vector{Bool}}}}, Union{Nothing, Tuple{Any, Any, Union{Nothing, Vector{Bool}}}}, Union{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Union{Nothing, Vector{Bool}}}}}}

Place the duals given by label in duals into the stacked layout of ocp.

Returns a named tuple, one entry per kind of constraint, whose kinds with no label in duals are nothing:

  • path = (duals, known): the path duals (a matrix on the path grid T_path, or a CTModels.Solutions.StackedDuals) and their canonical mask;

  • boundary = (duals, known): a vector and its mask;

  • state, control = (lb, ub, known): the lower- and upper-bound multipliers, by component (matrices on T_state / T_control, or functions of time), and the mask of the known components;

  • variable = (lb, ub, known): vectors and their mask.

The masks are canonical (see CTModels.Solutions._canonical_mask).

Throws

_place_path_duals [Function] ​

CTModels.Solutions._place_path_duals Function
julia
_place_path_duals(
    parts::Vector{Pair{UnitRange{Int64}, Any}},
    dim::Int64,
    T_path
) -> Tuple{Any, Union{Nothing, Vector{Bool}}}

The path duals of the parts rows => value on dim stacked rows, with their canonical mask. When every value is a matrix, they are stacked into one matrix (NaN in the unknown rows), interpolated afterwards as positional path duals are. Otherwise every part becomes a function of time (a matrix is interpolated on T_path) and the parts are combined into a CTModels.Solutions.StackedDuals.

_place_variable_box_duals [Function] ​

CTModels.Solutions._place_variable_box_duals Function
julia
_place_variable_box_duals(
    parts::Vector{Pair{Vector{Int64}, Any}},
    cp::Tuple,
    dim::Int64
) -> Union{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Union{Nothing, Vector{Bool}}}}

The variable box duals of the parts components => value, on dim components, split into (lb, ub, known) vectors (see CTModels.Solutions._place_box_duals).

_rows_known [Function] ​

CTModels.Solutions._rows_known Function
julia
_rows_known(
    known::Union{Nothing, Vector{Bool}},
    rows::Vector{Int64}
) -> Bool

Whether the rows rows are known in the canonical mask known (nothing: every row).

_serialize_solution [Function] ​

CTModels.Solutions._serialize_solution Function
julia
_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:

julia
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:

julia
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 grids

    • Trajectories: "state", "control", "costate" as Matrix{Float64}

    • Variable: "variable" as Vector{Float64} (time-independent)

    • Objective: "objective" as Float64

    • Dual variables: All constraint duals (can be nothing if 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" are nothing when unset (Core.NotProvided)

    • Compatibility check: "format_version" and "model_signature" (see CTModels.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 nothing in the dictionary

  • Grid association: Each component is discretized on its correct grid:

    • State and state box duals → T_state

    • Control and control box duals → T_control

    • Costate → T_costate

    • Path constraint duals → T_path

Example

julia
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_data function 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:

julia
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

julia
_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

julia
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 serialize

  • dim_x::Int: State dimension

  • dim_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

julia
_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

julia
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 serialize

  • dim_x::Int: State dimension

  • dim_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
julia
_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 matrices of limits for a CTModels.Solutions.SwitchingModel.

_split_lower [Function] ​

CTModels.Solutions._split_lower Function
julia
_split_lower(d::Real, cl::Real, cu::Real)

The lower-bound multiplier zL of a box component whose signed dual is d (ct-conventions SGN2/SGN3), from the coefficients (cl, cu) of the component (see CTModels.Solutions._box_dual_coefficients): d for a lower bound only ((1, 0)), 0 for an upper bound only ((0, 1)), max(-d, 0) for two bounds or a fixed component ((-1, 1)). With CTModels.Solutions._split_upper, the inverse of cl * zL + cu * zU: lossless, since at most one side of a component is active.

_split_upper [Function] ​

CTModels.Solutions._split_upper Function
julia
_split_upper(d::Real, cl::Real, cu::Real)

The upper-bound multiplier zU of a box component whose signed dual is d: 0 for a lower bound only, d for an upper bound only, max(d, 0) for two bounds or a fixed component (see CTModels.Solutions._split_lower).

_stored_limits [Function] ​

CTModels.Solutions._stored_limits Function
julia
_stored_limits(
    m::CTModels.Solutions.SwitchingModel
) -> String

Return the components whose limits a switching model stores, e.g. "state, costate", or "none".

_switching_limit_key [Function] ​

CTModels.Solutions._switching_limit_key Function
julia
_switching_limit_key(
    component::Symbol,
    side::Int64
) -> String

Return the key of the serialized side limit (1 left, 2 right) of component, e.g. "switching_state_left".

_switching_model [Function] ​

CTModels.Solutions._switching_model Function
julia
_switching_model(;
    times::AbstractVector{<:Real},
    labels::AbstractVector{<:AbstractString},
    state,
    costate,
    control,
    path_dual,
    state_dual,
    control_dual,
    duals::AbstractDict{Symbol}
)

Build a CTModels.Solutions.SwitchingModel and check its shapes: the keyword constructor without its deprecation warning, used to rebuild a switching model from serialized data, where the stacked limits of the duals are already placed.

_throw_repeated_time [Function] ​

CTModels.Solutions._throw_repeated_time Function
julia
_throw_repeated_time(t::Float64, component_name::String)

Throw the error of a time grid with a repeated time.

Throws

_unset_to_nothing [Function] ​

CTModels.Solutions._unset_to_nothing Function
julia
_unset_to_nothing(x)

Return 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
julia
_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 validate

  • component_name::String: Name of the component for error messages

Returns

  • Vector{Float64}: Validated and potentially reordered time grid

Throws

Notes

If the grid is not increasing, it is reordered and a warning is emitted.

_with_box_masks [Function] ​

CTModels.Solutions._with_box_masks Function
julia
_with_box_masks(
    sol::CTModels.Solutions.Solution,
    state::Union{Nothing, Vector{Bool}},
    control::Union{Nothing, Vector{Bool}},
    variable::Union{Nothing, Vector{Bool}}
) -> CTModels.Solutions.Solution

sol with the masks of the known components of its box duals replaced by state, control and variable (see CTModels.Solutions.DualMasks); the duals and the other masks are unchanged. Used to rebuild a solution read from a file: its box multipliers are passed by component as they were stored (NaN for the unknown components), then their masks are restored, which holds whatever the aliases of the box labels.

_with_jumps [Function] ​

CTModels.Solutions._with_jumps Function
julia
_with_jumps(
    base,
    grid::Vector{Float64},
    sw::CTModels.Solutions.AbstractSwitchingModel,
    component::Symbol;
    constant
)

Wrap 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
julia
_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 via only, otherwise identity)

Returns

  • Components.CoercedTrajectory(deepcopy(func), coerce) where coerce is only (dim==1) or identity (otherwise)

  • nothing if 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:

julia
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
julia
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 vector

  • dim: Dimension to extract (nothing = take full matrix)

  • type_param: Type parameter for dispatch

  • allow_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 (:linear or :constant)

  • jumps: nothing, or (switching, component) to keep the jumps of component stored in the switching model when the data is a matrix (see CTModels.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=false

  • AssertionError: If expected_dim doesn't match actual dimension

Examples

julia
# 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
julia
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}
) where DM<:CTModels.Solutions.AbstractDualModel -> CTModels.Solutions.AbstractDualModel

Return the dual model containing all constraint multipliers.

limits [Function] ​

CTModels.Solutions.limits Function
julia
limits(
    m::CTModels.Solutions.SwitchingModel,
    component::Symbol
) -> Tuple{Matrix{Float64}, Matrix{Float64}}

Return the (left, right) matrices of limits of component (:state, :costate, :control, :path_dual, :state_dual or :control_dual), one row per switching time.

Throws

julia
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
julia
CoercedTrajectory{F,C} <: Function

A 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

julia
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
julia
ConstantInTime{V} <: Function

A 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

julia
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
julia
struct MergedTrajectory{F, P<:Tuple, D} <: Function

Callable 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 (D == 1) or a vector.

base::F is a concrete type parameter, replacing the former base_fun::Function abstract capture. comps::P is a concrete Tuple of (index, f) pairs in index order — the concrete tuple type P carries every override's function type in its parameters, so the @generated call method dispatches each f(t) statically (issue #498; same pattern as CTModels.Building.CompositeDynamics). Iterating a Dict{Int,Function} instead dispatched dynamically and boxed every return value.

The total dimension is the type parameter D (like the N of Array{T,N}): the generated call picks the scalar or vector path statically — for D == 1 no scratch vector is allocated and the return type is fully inferred (issue #501).

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::P: Concrete Tuple of (index::Int, f::Function) override pairs, sorted by index.

  • role::Symbol: Component role (:state or :control).

Type parameters

  • F: concrete type of base.

  • P: concrete tuple type of the override pairs.

  • D::Int: total dimension.

Examples

julia
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
julia
_build_block_with_components(
    ocp::CTModels.Models.AbstractModel,
    role::Symbol,
    block_data,
    comp_data::Dict{Int64, Any}
)

Build an initialisation function combining block-level and component-level data.

Arguments

  • ocp::CTModels.Models.AbstractModel: The optimal control problem.

  • role::Symbol: The component role (:state or :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
julia
_build_component_function(data) -> Function

Build 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
julia
_build_component_function_with_time(
    data,
    time::AbstractVector
) -> Function

Build 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
julia
_build_component_function_without_time(data) -> Function

Build 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
julia
_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 (:state or :control).

  • data: The data to interpolate (function, vector, or vector-of-vectors).

  • time::AbstractVector: The time grid.

Returns

  • Function: An interpolated initialisation function t -> 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
julia
_coerce_base(v::AbstractVector, dim::Int64, role::Symbol)

Validate 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 of v.

Throws

  • CTBase.Exceptions.IncorrectArgument: if v is a scalar or has incorrect length.

See also: CTModels.Init._scalar_base

_component_shape_error [Function] ​

CTModels.Init._component_shape_error Function
julia
_component_shape_error(val, i::Int64, role::Symbol)

Throw CTBase.Exceptions.IncorrectArgument for a component override returning a vector of length other than 1.

Arguments

  • val: raw output of the component override function.

  • i::Int: Component index.

  • role::Symbol: Component role (e.g. :state, :control) used in the error message.

Throws

  • CTBase.Exceptions.IncorrectArgument: always.

_format_init_data_for_grid [Function] ​

CTModels.Init._format_init_data_for_grid Function
julia
_format_init_data_for_grid(data)

Convert 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
julia
_format_time_grid(time_data)

Normalise time grid data to a vector format.

Arguments

  • time_data: The time grid data (vector, array, or nothing).

Returns

  • Union{Nothing, AbstractVector}: The normalised time grid as a vector, or nothing.

Throws

  • Exceptions.IncorrectArgument: If the time grid type is invalid.

_initial_guess_from_namedtuple [Function] ​

CTModels.Init._initial_guess_from_namedtuple Function
julia
_initial_guess_from_namedtuple(
    ocp::CTModels.Models.AbstractModel,
    init_data::NamedTuple
) -> CTModels.Init.InitialGuess

Build 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
julia
_initial_guess_from_preinit(
    ocp::CTModels.Models.AbstractModel,
    pre::CTModels.Init.PreInitialGuess
) -> CTModels.Init.InitialGuess

Build 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
julia
_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.

_merge_scalar [Function] ​

CTModels.Init._merge_scalar Function
julia
_merge_scalar(val::AbstractVector, i::Int64, role::Symbol)

Validate and extract the scalar value of a dim-1 component override.

Dispatched overloads resolve the shape check statically when the override's return type is inferred: a length-1 vector unwraps to only(val), anything longer throws, and a scalar passes through unchanged.

Arguments

  • val: Raw output of the component override function.

  • i::Int: Component index (always 1 for a dim-1 trajectory).

  • role::Symbol: Component role (e.g. :state, :control) used in the error message.

Returns

  • The scalar override value.

Throws

  • CTBase.Exceptions.IncorrectArgument: if val is a vector of length other than 1.

See also: CTModels.Init._scalar_base, CTModels.Init._set_component!

_normalize_scalar_components [Function] ​

CTModels.Init._normalize_scalar_components Function
julia
_normalize_scalar_components(
    ::CTModels.Models.AbstractModel,
    init::CTModels.Init.AbstractInitialGuess
) -> CTModels.Init.AbstractInitialGuess

Normalise 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: init itself when nothing needs converting, otherwise a new InitialGuess whose one-dimensional components are scalars.

_scalar_base [Function] ​

CTModels.Init._scalar_base Function
julia
_scalar_base(v::AbstractVector)

Extract the scalar component value from a dim-1 base trajectory output.

Dispatched overloads replace isa AbstractVector runtime checks with static dispatch: v[1] on a vector base (same BoundsError as the former copy(v)[1] on an empty vector), a scalar base passed through unchanged.

Arguments

  • v: raw output of a base trajectory function for a 1-dimensional component.

Returns

  • The scalar component value.

See also: CTModels.Init._coerce_base, CTModels.Init._merge_scalar

_scalar_trajectory [Function] ​

CTModels.Init._scalar_trajectory Function
julia
_scalar_trajectory(f::Function, dim::Int64) -> Function

Return 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 trajectory t -> 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
julia
_scalar_value(v, dim::Int64)

Return 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) when dim == 1 and v is a vector, v otherwise.

_set_component! [Function] ​

CTModels.Init._set_component! Function
julia
_set_component!(
    vec::AbstractVector,
    i::Int64,
    val::AbstractVector,
    role::Symbol
)

Assign a component override value val to vec[i] after shape validation, and return the vector holding the result.

Dispatched overloads replace isa AbstractVector runtime checks with static dispatch: a length-1 vector unwraps to only(val), anything longer throws, and a scalar assigns directly.

When the type of val fits the element type of vec, vec is filled in place and returned. Otherwise (for instance a Float64 override on an Int base vector) the result is a copy promoted to promote_type(eltype(vec), typeof(val)), instead of failing with an InexactError (issue #505). The branch is resolved statically from the types, so the call stays inferred and allocation-free in the common case.

Arguments

  • vec: Output vector being filled (modified in-place when no promotion is needed).

  • i::Int: Component index.

  • val: Raw output of the component override function.

  • role::Symbol: Component role (e.g. :state, :control) used in the error message.

Returns

  • Vector: vec itself, or its promoted copy; callers must use the returned vector.

Throws

  • CTBase.Exceptions.IncorrectArgument: if val is a vector of length other than 1.

See also: CTModels.Init._scalar_base, CTModels.Init._coerce_base

_validate_initial_guess [Function] ​

CTModels.Init._validate_initial_guess Function
julia
_validate_initial_guess(
    ocp::CTModels.Models.AbstractModel,
    init::CTModels.Init.InitialGuess
) -> CTModels.Init.InitialGuess

Internal 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.

From CTModels.Models ​

BoxProjection [Struct] ​

CTModels.Models.BoxProjection Type
julia
BoxProjection{Slot,CIDX} <: Function

Callable 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
julia
SubBoundaryConstraint{CP,I} <: Function

In-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
julia
SubPathConstraint{CP,I} <: Function

In-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.

_box_components [Function] ​

CTModels.Models._box_components Function
julia
_box_components(cp::Tuple, label::Symbol) -> Vector{Int64}

The components bounded under the label label in the box tuple cp = (lb, ind, ub, labels, aliases).

_control_dependence [Function] ​

CTModels.Models._control_dependence Function
julia
_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

Returns

  • trait value: Traits.ControlFree or Traits.WithControl.

See also: CTModels.Models._variable_dependence

_label_strings [Function] ​

CTModels.Models._label_strings Function
julia
_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
julia
_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 is nothing when the time is free).

See also: CTModels.Serialization._validate_solution_against_model.

_nl_rows [Function] ​

CTModels.Models._nl_rows Function
julia
_nl_rows(cp::Tuple, label::Symbol) -> Vector{Int64}

The rows labelled label in the nonlinear constraint tuple cp = (lb, f!, ub, labels).

_throw_constraint_label_not_found [Function] ​

CTModels.Models._throw_constraint_label_not_found Function
julia
_throw_constraint_label_not_found(label::Symbol)

Throw the CTBase.Exceptions.IncorrectArgument of an unknown constraint label.

_variable_dependence [Function] ​

CTModels.Models._variable_dependence Function
julia
_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

Returns

  • trait value: Traits.Fixed or Traits.NonFixed.

See also: CTModels.Models._control_dependence


From CTModels.Display ​

__print [Function] ​

CTModels.Display.__print Function
julia
__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 to io and returns nothing.

__print_mathematical_definition [Function] ​

CTModels.Display.__print_mathematical_definition Function
julia
__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
) -> Bool

Print 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 of J(x, u, v).

  • Dynamics arguments omit the control: f(t, x, v) instead of f(t, x, u, v).

  • The "where" clause lists only x (and v if 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: true if 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
julia
_display_value(io::IO, value) -> AbstractString

Render 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
julia
_print_abstract_definition(
    ::IO,
    ::CTModels.Components.EmptyDefinition
) -> Bool

Print a CTModels.Components.EmptyDefinition: no output is produced.

Returns

  • Bool: false to indicate that nothing was printed.
julia
_print_abstract_definition(
    io::IO,
    d::CTModels.Components.Definition
) -> Bool

Print 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: true to indicate that output was produced.

See also: CTModels.Display.__print.

_show_compact [Function] ​

CTModels.Display._show_compact Function
julia
_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
julia
_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
julia
_show_objective(io::IO, model, fields; detailed::Bool)

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
julia
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.

CTModels.Display.print_field Function
julia
print_field(
    io::IO,
    label,
    value;
    last::Bool,
    fmt,
    value_style
)

Print one labelled tree field using semantic palette roles.

CTModels.Display.print_fields Function
julia
print_fields(io::IO, fields; fmt)

Print a sequence of labelled fields and mark the final field with └─.

CTModels.Display.print_header Function
julia
print_header(io::IO, name; fmt)

Print a palette-styled type header without a trailing newline.


From CTModels.PlotCase ​

ConstraintRow [Struct] ​

CTModels.PlotCase.ConstraintRow Type
julia
struct ConstraintRow

A row of the constraint block of the plot: the constraint labelled label.

Fields

  • label::Symbol: The label of the constraint.

  • kind::Symbol: :path, :state (state box) or :control (control box).

  • rows::Vector{Int}: The rows of the constraint in the stacked path constraint (for :path), or the components it bounds (for a box), as returned by CTModels.Models.constraint_rows.

  • dual::Bool: Whether sol knows the dual of the constraint (CTModels.Solutions.has_dual); the right-hand side of the row exists only then.

_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
julia
__control_layout() -> Symbol

Return the default control representation (:components).

__description [Function] ​

CTModels.PlotCase.__description Function
julia
__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
julia
__phase_labels() -> Symbol

Return the default placement of the phase labels (:control).

__plot_jumps [Function] ​

CTModels.PlotCase.__plot_jumps Function
julia
__plot_jumps() -> Symbol

Return 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
julia
__plot_label_suffix() -> String

Return the default suffix appended to plot labels (empty string).

__plot_layout [Function] ​

CTModels.PlotCase.__plot_layout Function
julia
__plot_layout() -> Symbol

Return the default plot layout (:split).

__plot_style [Function] ​

CTModels.PlotCase.__plot_style Function
julia
__plot_style() -> @NamedTuple{}

Return the default plotting style (empty NamedTuple).

__time_normalization [Function] ​

CTModels.PlotCase.__time_normalization Function
julia
__time_normalization() -> Symbol

Return the default time-axis normalization (:default).

_as_value [Function] ​

CTModels.PlotCase._as_value Function
julia
_as_value(row::AbstractVector)

Return 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
julia
_assemble_group(
    cells::AbstractVector{<:CTBase.Plotting.AbstractLayoutNode}
)

Assemble 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
julia
_assemble_split(;
    state,
    costate,
    control,
    rows::AbstractVector{<:CTBase.Plotting.AbstractLayoutNode}
) -> Union{Nothing, CTBase.Plotting.AbstractLayoutNode}

Assemble stacked columns (:split layout).

The layout is (state | costate) over control over the constraint rows, each row being (constraint | dual) (see CTModels.PlotCase._constraint_rows). rows holds the already paired nodes of the rows. Returns nothing when there is nothing to draw.

_base_style [Function] ​

CTModels.PlotCase._base_style Function
julia
_base_style(style::NamedTuple) -> NamedTuple

Return the default per-series style, merged with any user-supplied group style.

_box_hlines [Function] ​

CTModels.PlotCase._box_hlines Function
julia
_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
julia
_build_root(
    sol,
    description::Symbol...;
    layout::Symbol,
    control::Symbol,
    time::Symbol,
    state_style::Union{Symbol, NamedTuple},
    costate_style::Union{Symbol, NamedTuple},
    control_style::Union{Symbol, NamedTuple},
    path_style::Union{Symbol, NamedTuple},
    dual_style::Union{Symbol, NamedTuple},
    time_style::Union{Symbol, NamedTuple},
    state_bounds_style::Union{Symbol, NamedTuple},
    control_bounds_style::Union{Symbol, NamedTuple},
    path_bounds_style::Union{Symbol, NamedTuple},
    switching_style::Union{Symbol, NamedTuple},
    phase_labels::Symbol,
    phase_labels_style::NamedTuple,
    jumps::Symbol
)

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
julia
_check_jumps(jumps::Symbol)

Check the drawing of the jumps: :segment or :none.

Throws

_check_phase_labels [Function] ​

CTModels.PlotCase._check_phase_labels Function
julia
_check_phase_labels(phase_labels::Symbol)

Check the placement of the phase labels: :control, :all or :none.

Throws

_constraint_rows [Function] ​

CTModels.PlotCase._constraint_rows Function
julia
_constraint_rows(
    sol,
    model
) -> Vector{CTModels.PlotCase.ConstraintRow}

List the constraint rows of the plot of sol: the path constraints, in declaration order, then the state boxes, then the control boxes, in the order of the components they bound; one row per label. A box label that is only an alias of a component (a second declaration on a component already bounded, see Building._dedup_box_constraints!) has its row too.

A path constraint is always a row, with or without a dual (row.dual). A box is a row only when its dual is known to sol (see CTModels.Solutions.has_dual): without its dual, the left-hand side would only repeat the component of the state or control panel. Boundary and variable-box labels are not plotted: their duals do not depend on time.

_control_panels [Function] ​

CTModels.PlotCase._control_panels Function
julia
_control_panels(
    sol,
    control::Symbol,
    style::NamedTuple,
    layout::Symbol;
    connect::Bool
) -> 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
julia
_costate_panel(
    sol,
    style::NamedTuple;
    layout::Symbol,
    state_shown::Bool,
    connect::Bool
)

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
julia
_dual_panel(
    sol,
    model,
    style::NamedTuple;
    path_shown::Bool,
    connect::Bool,
    rows::Union{Nothing, AbstractVector{Int64}},
    title::String,
    samples
)

Build a CTBase.Plotting.Panel for the dual variables of the path constraints: all of them, or the rows rows (those of one label). samples are the duals sampled on the path grid, computed here when not given. At a switching time whose dual limits are known, the jump is drawn as for the state (see CTModels.PlotCase._spliced_samples).

_fill_unknown_limits [Function] ​

CTModels.PlotCase._fill_unknown_limits Function
julia
_fill_unknown_limits(
    T::AbstractVector,
    M::AbstractMatrix,
    times::AbstractVector,
    L::AbstractMatrix;
    constant::Bool
)

The limits L (one row per switching time in times, one column per column of the samples (T, M)) with each NaN entry replaced by the value of the samples at that switching time (see CTModels.PlotCase._sample_at): linearly interpolated between the two samples around it, or, for piecewise-constant samples (constant = true), the sample that holds on the interval. Returns L itself when it has no NaN, or when its shape does not match the samples (left to CTBase.Plotting.splice_jumps to report).

_mid_time [Function] ​

CTModels.PlotCase._mid_time Function
julia
_mid_time(T::AbstractVector, time::Symbol) -> Float64

The middle of the time axis of the samples on the grid T, in the coordinates of the plot (time = :normalize or :normalise: [0, 1]): where the text of an empty cell goes.

_pair [Function] ​

CTModels.PlotCase._pair Function
julia
_pair(a, b)

Pair 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
julia
_path_hlines(model, style::NamedTuple)

Build 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
julia
_path_panel(
    sol,
    model,
    style::NamedTuple;
    connect::Bool,
    rows::Union{Nothing, AbstractVector{Int64}},
    title::String,
    samples
) -> CTBase.Plotting.Panel

Build a CTBase.Plotting.Panel for the nonlinear path constraints: all of them, or the rows rows (those of one label). samples are the values of the constraints (see CTModels.PlotCase._path_samples), computed here when not given.

_path_samples [Function] ​

CTModels.PlotCase._path_samples Function
julia
_path_samples(
    sol,
    model
) -> Tuple{Union{StepRangeLen, AbstractVector{<:Real}}, Any, Any, Any}

The samples of the nonlinear path constraints of model along sol, for every row of the stacked constraint: (T, data, left, right), with T the path grid, data the length(T) × nc matrix of values, and left, right the values at the left and right limits of the state and control at the switching times (one row per switching time), or nothing when those limits are not known. Computed once per figure, then sliced per constraint row (see CTModels.PlotCase._path_panel).

_phase_annotations [Function] ​

CTModels.PlotCase._phase_annotations Function
julia
_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
julia
_phase_label_group(
    phase_labels::Symbol;
    state::Bool,
    costate::Bool,
    control::Bool,
    path::Bool,
    dual::Bool
)

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.

_row_dual [Function] ​

CTModels.PlotCase._row_dual Function
julia
_row_dual(sol, model, row::CTModels.PlotCase.ConstraintRow)

The dual of the constraint row row, as a function of time: CTModels.Solutions.dual(sol, model, row.label).

_row_dual_panel [Function] ​

CTModels.PlotCase._row_dual_panel Function
julia
_row_dual_panel(
    sol,
    model,
    row::CTModels.PlotCase.ConstraintRow,
    style::NamedTuple;
    left_shown::Bool,
    connect::Bool,
    title::String,
    dual_samples
)

The right-hand side of the row row: its dual, CTModels.PlotCase._row_dual, sampled on the grid of the row. As for the costate, its ylabels are dropped when the left-hand side is shown alongside (the left cell carries the name), otherwise dual <label>. dual_samples are the path duals sampled on the path grid, shared by the path rows of a figure, computed here when not given.

_row_grid [Function] ​

CTModels.PlotCase._row_grid Function
julia
_row_grid(
    sol,
    row::CTModels.PlotCase.ConstraintRow
) -> Union{StepRangeLen, AbstractVector{<:Real}}

The time grid on which the row row is sampled.

_row_hlines [Function] ​

CTModels.PlotCase._row_hlines Function
julia
_row_hlines(
    model,
    row::CTModels.PlotCase.ConstraintRow,
    style::NamedTuple
)

The horizontal bound lines of the left-hand side of the row row, one vector per component of the panel: the bounds of the path constraint, or of the state or control box components.

_row_left_panel [Function] ​

CTModels.PlotCase._row_left_panel Function
julia
_row_left_panel(
    sol,
    model,
    row::CTModels.PlotCase.ConstraintRow,
    style::NamedTuple;
    connect::Bool,
    title::String,
    path_samples
) -> CTBase.Plotting.Panel

The left-hand side of the row row: the path constraint, or the components of the state or control bounded by the box, as a CTBase.Plotting.Panel. A box cell is labelled with the component and the label of the constraint, e.g. x₂ (x2_box). title is the title of the panel (shown on its first cell). path_samples are the samples of the path constraints shared by the rows of a figure (see CTModels.PlotCase._path_samples), computed here when not given.

_row_seriestype [Function] ​

CTModels.PlotCase._row_seriestype Function
julia
_row_seriestype(
    sol,
    row::CTModels.PlotCase.ConstraintRow
) -> Symbol

The series type of the cells of the row row: :steppost for a control box when the control is piecewise constant (its component and its dual are then step functions), :path otherwise.

_row_unknown_dual_panel [Function] ​

CTModels.PlotCase._row_unknown_dual_panel Function
julia
_row_unknown_dual_panel(
    sol,
    row::CTModels.PlotCase.ConstraintRow,
    style::NamedTuple;
    title::String
) -> CTBase.Plotting.Panel

The right-hand side of a row whose dual is not known, in a block where other rows have theirs: an empty cell on the grid of the row (an invisible curve, so that the cell keeps the time axis of the others), which keeps the two columns of the block aligned. The text dual not known is put in it by the caller.

_rownorm [Function] ​

CTModels.PlotCase._rownorm Function
julia
_rownorm(row)

Return the Euclidean norm of a matrix row.

_sample [Function] ​

CTModels.PlotCase._sample Function
julia
_sample(f, T)

Sample a callable f over grid T into an (n_times, n_components) matrix.

Uniform for scalar and vector-valued f.

_sample_at [Function] ​

CTModels.PlotCase._sample_at Function
julia
_sample_at(
    T::AbstractVector,
    y::AbstractVector,
    τ::Real;
    constant::Bool
) -> Float64

The value at time τ of the samples y on the grid T: linear interpolation between the two samples around τ, or, with constant = true (piecewise-constant samples, drawn as steps), the last sample at or before τ; the first or last sample outside the grid.

_spliced_samples [Function] ​

CTModels.PlotCase._spliced_samples Function
julia
_spliced_samples(
    sol,
    T::AbstractVector,
    M::AbstractMatrix,
    component::Symbol;
    connect::Bool,
    cols::Union{Nothing, AbstractVector{Int64}}
) -> 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. With cols, M holds only those columns of component, and only their limits are used.

A limit may be unknown for some columns only (NaN: the limits of the duals given by label, for a label whose limits were not given). Such a limit is replaced by the value of the samples at the switching time (see CTModels.PlotCase._fill_unknown_limits), so that no jump is drawn for that column, instead of a break in the curve.

Returns

  • (T, M): the time grid (with each switching time twice) and the matrix of samples.

_state_panel [Function] ​

CTModels.PlotCase._state_panel Function
julia
_state_panel(
    sol,
    style::NamedTuple;
    connect::Bool
) -> CTBase.Plotting.Panel

Build a CTBase.Plotting.Panel for the state trajectory.

_switching_style [Function] ​

CTModels.PlotCase._switching_style Function
julia
_switching_style(
    time_style,
    switching_style::NamedTuple
) -> NamedTuple

Style 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
julia
_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
julia
_time_name(sol, time::Symbol) -> String

Return the time-axis label, with the historical "(normalized)" suffix when time is rescaled.

_time_vlines [Function] ​

CTModels.PlotCase._time_vlines Function
julia
_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
julia
build_figure(
    sol::CTModels.Solutions.Solution,
    description::Symbol...;
    layout::Symbol,
    control::Symbol,
    time::Symbol,
    state_style::Union{Symbol, NamedTuple},
    costate_style::Union{Symbol, NamedTuple},
    control_style::Union{Symbol, NamedTuple},
    path_style::Union{Symbol, NamedTuple},
    dual_style::Union{Symbol, NamedTuple},
    time_style::Union{Symbol, NamedTuple},
    state_bounds_style::Union{Symbol, NamedTuple},
    control_bounds_style::Union{Symbol, NamedTuple},
    path_bounds_style::Union{Symbol, NamedTuple},
    switching_style::Union{Symbol, NamedTuple},
    phase_labels::Symbol,
    phase_labels_style::NamedTuple,
    jumps::Symbol,
    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, :norm or :all.

  • time::Symbol = :default: :default or :normalize / :normalise.

  • size: figure size; nothing defers to the engine heuristic.

  • the *_style / *_bounds_style / time_style keywords: a NamedTuple of attributes or :none to hide the group / decoration.

  • switching_style = NamedTuple(): style of the vertical lines at the switching times (see CTModels.Solutions.switching_times); by default they look like the initial/final time lines (time_style included); :none hides them.

  • phase_labels::Symbol = :control: where to write the phase labels (see CTModels.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

clean [Function] ​

CTModels.PlotCase.clean Function
julia
clean(description) -> Tuple

Collapse 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
julia
do_decorate(;
    model::Union{Nothing, CTModels.Models.Model},
    time_style::Union{Symbol, NamedTuple},
    state_bounds_style::Union{Symbol, NamedTuple},
    control_bounds_style::Union{Symbol, NamedTuple},
    path_bounds_style::Union{Symbol, NamedTuple}
)

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
julia
do_plot(
    sol::CTModels.Solutions.AbstractSolution,
    description::Symbol...;
    state_style::Union{Symbol, NamedTuple},
    control_style::Union{Symbol, NamedTuple},
    costate_style::Union{Symbol, NamedTuple},
    path_style::Union{Symbol, NamedTuple},
    dual_style::Union{Symbol, NamedTuple},
    rows::Union{Nothing, AbstractVector{CTModels.PlotCase.ConstraintRow}}
)

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 path constraints, or a box row (see :dual),

  • dual needs the dual of at least one constraint row to be known: a path constraint, a state box or a control box (see CTModels.PlotCase._constraint_rows).

rows are the constraint rows of the figure (see CTModels.PlotCase._constraint_rows), listed here when not given.

Returns

  • NTuple{5, Bool}: flags for (state, costate, control, path, dual).

split_plot_kwargs [Function] ​

CTModels.PlotCase.split_plot_kwargs Function
julia
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
julia
struct CompositeConstraint{Sig, CS} <: Function

In-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

julia
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]

CompositeDynamics [Struct] ​

CTModels.Building.CompositeDynamics Type
julia
struct CompositeDynamics{P<:Tuple} <: Function

In-place callable struct assembling partial dynamics — each declared over a disjoint state range — into a single dyn!(val, t, x, u, v) function.

The concrete tuple type P carries every (range, f!) pair in its type parameters, so the call method resolves each part statically: no runtime dispatch, no boxed @view. Evaluating the composite costs exactly the equivalent monolithic dynamics — the dynamics runs once per solver step, so this is a hot-path invariant (ct-conventions PERF1; issue #496). Storing the parts in a field rather than closing over them follows the same pattern as CTModels.Building.CompositeConstraint.

Fields

  • parts::P: Concrete Tuple of (range, f!) pairs in declaration order; each f! writes view(val, range) with signature f!(r, t, x, u, v).

Examples

julia
using CTModels: Building

f1!(r, t, x, u, v) = (r[1] = x[2])
f2!(r, t, x, u, v) = (r[1] = u[1])
dyn = Building.CompositeDynamics(((1:1, f1!), (2:2, f2!)))
val = zeros(2)
dyn(val, 0.0, [1.0, 2.0], [3.0], Float64[])
# val == [2.0, 3.0]

__build_dynamics_from_parts [Function] ​

CTModels.Building.__build_dynamics_from_parts Function
julia
__build_dynamics_from_parts(
    parts::Vector{<:Tuple{var"#s50", var"#s49"} where {var"#s50"<:(AbstractRange{<:Int64}), var"#s49"<:Function}}
) -> CTModels.Building.CompositeDynamics

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. tuple(parts...) preserves each part's concrete (range, f!) type inside the result's type parameter — what makes the calls in CTModels.Building.CompositeDynamics statically dispatched.

Arguments

  • parts::Vector{<:Tuple{<:AbstractRange{<:Int},<:Function}}: Ordered vector of (range, f!) pairs; each f!(r, t, x, u, v) fills r = view(val, range).

Returns

  • CompositeDynamics: Combined dyn!(val, t, x, u, v) applying all parts in order, with the same allocation cost as a monolithic dynamics (issue #496).

__collect_used_names [Function] ​

CTModels.Building.__collect_used_names Function
julia
__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
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
julia
__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::Union{Nothing, Int64, OrdinalRange{Int64}},
    f::Union{Nothing, Function},
    lb::Union{Nothing, Real, AbstractVector{<:Real}},
    ub::Union{Nothing, Real, AbstractVector{<:Real}},
    label::Symbol,
    codim_f::Union{Nothing, Int64}
)

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 lb and the upper bound ub cannot be both nothing.

  • The lower bound lb and the upper bound ub must have the same length, if both provided.

If rg and f are not provided then,

  • type must be :state, :control, or :variable.

  • lb and ub must be of dimension n, m, or q respectively, when provided.

If rg is provided, then:

  • f must not be provided.

  • type must be :state, :control, or :variable.

  • rg must be a range of integers, and must be contained in 1:n, 1:m, or 1:q respectively.

If f is provided, then:

  • rg must not be provided.

  • type must be :boundary or :path.

  • f must be a function that returns a vector of the same dimension as the constraint.

  • lb and ub must be of the same dimension as the output of f, when provided.

Example

julia
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
julia
__constraint_label() -> Symbol

Return a unique label for a constraint using gensym with prefix :unnamed.

Returns

  • Symbol: A unique constraint label.

__constraints [Function] ​

CTModels.Building.__constraints Function
julia
__constraints()

Return the default value for the constraints.

Returns

  • Nothing

__control_components [Function] ​

CTModels.Building.__control_components Function
julia
__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
julia
__control_interpolation() -> Symbol

Return the default control interpolation type.

Returns

  • Symbol: The interpolation type (:constant for piecewise constant, :linear for piecewise linear).

__control_name [Function] ​

CTModels.Building.__control_name Function
julia
__control_name() -> String

Return the default name of the control variable.

Returns

  • String: The default control name ("u").

__criterion_type [Function] ​

CTModels.Building.__criterion_type Function
julia
__criterion_type() -> Symbol

Return the default optimization criterion type.

Returns

  • Symbol: The criterion type (:min for minimization).

__filename_export_import [Function] ​

CTModels.Building.__filename_export_import Function
julia
__filename_export_import() -> String

Return the default filename (without extension) for exporting and importing solutions.

Returns

  • String: The default filename ("solution").

__format [Function] ​

CTModels.Building.__format Function
julia
__format() -> Symbol

Return 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
julia
__has_name_conflict(
    ocp::CTModels.Building.PreModel,
    new_name::String
) -> Bool
__has_name_conflict(
    ocp::CTModels.Building.PreModel,
    new_name::String,
    exclude_component::Symbol
) -> Bool

Check if a name conflicts with existing names in the PreModel.

Arguments

  • ocp::PreModel: The model to check against

  • new_name::String: The new name to check

  • exclude_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: true if conflict exists, false otherwise

Example

julia
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)
false

See also: CTModels.Building.__collect_used_names, CTModels.Building.__validate_name_uniqueness.

__is_autonomous_set [Function] ​

CTModels.Building.__is_autonomous_set Function
julia
__is_autonomous_set(ocp::CTModels.Building.PreModel) -> Bool

Return true if the autonomous flag has been set in the PreModel.

Returns

  • Bool

__is_consistent [Function] ​

CTModels.Building.__is_consistent Function
julia
__is_consistent(ocp::CTModels.Building.PreModel) -> Bool

Return 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
julia
__is_control_empty(c) -> Bool

Return true if c is an EmptyControlModel.

Returns

  • Bool
julia
__is_control_empty(ocp::CTModels.Building.PreModel) -> Bool

Return true if the control field of the PreModel is an EmptyControlModel.

Returns

  • Bool

__is_definition_empty [Function] ​

CTModels.Building.__is_definition_empty Function
julia
__is_definition_empty(d) -> Bool

Return true if d is an CTModels.Components.EmptyDefinition.

Returns

  • Bool
julia
__is_definition_empty(
    ocp::CTModels.Building.PreModel
) -> Bool

Return 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
julia
__is_dynamics_complete(
    ocp::CTModels.Building.PreModel
) -> Bool

Return 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
julia
__is_dynamics_set(ocp::CTModels.Building.PreModel) -> Bool

Return true if dynamics have been set in the PreModel.

Returns

  • Bool

__is_empty [Function] ​

CTModels.Building.__is_empty Function
julia
__is_empty(ocp::CTModels.Building.PreModel) -> Bool

Return 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
julia
__is_objective_set(ocp::CTModels.Building.PreModel) -> Bool

Return true if objective has been set in the PreModel.

Returns

  • Bool

__is_set [Function] ​

CTModels.Building.__is_set Function
julia
__is_set(x) -> Bool

Return true if x is not nothing.

Returns

  • Bool

__is_state_set [Function] ​

CTModels.Building.__is_state_set Function
julia
__is_state_set(ocp::CTModels.Building.PreModel) -> Bool

Return true if state has been set in the PreModel.

Returns

  • Bool

__is_times_set [Function] ​

CTModels.Building.__is_times_set Function
julia
__is_times_set(ocp::CTModels.Building.PreModel) -> Bool

Return true if times have been set in the PreModel.

Returns

  • Bool

__is_variable_empty [Function] ​

CTModels.Building.__is_variable_empty Function
julia
__is_variable_empty(v) -> Bool

Return true if v is an EmptyVariableModel.

Returns

  • Bool
julia
__is_variable_empty(ocp::CTModels.Building.PreModel) -> Bool

Return true if the variable field of the PreModel is an EmptyVariableModel.

Returns

  • Bool

__state_components [Function] ​

CTModels.Building.__state_components Function
julia
__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
julia
__state_name() -> String

Return 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
julia
__time_grid_default_component() -> Symbol

Return 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
julia
__time_name() -> String

Return the default name of the time variable.

Returns

  • String: The default time name ("t").

__validate_name_uniqueness [Function] ​

CTModels.Building.__validate_name_uniqueness Function
julia
__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 against

  • name::String: The component name

  • components::Vector{String}: The component names

  • component_type::Symbol: Type of component (:state, :control, :variable, :time)

Throws

  • Exceptions.IncorrectArgument: If any validation fails

Example

julia
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: succeeds

See also: CTModels.Building.__has_name_conflict, CTModels.Building.__collect_used_names.

__variable_components [Function] ​

CTModels.Building.__variable_components Function
julia
__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
julia
__variable_name(q::Int64) -> String

Return 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
julia
_dedup_box_constraints!(
    inds::Vector{Int64},
    lbs::Vector{T},
    ubs::Vector{T},
    labels::Vector{Symbol},
    aliases::Vector{Vector{Symbol}},
    kind::String
) where T<:Real

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] = max of all declared lower bounds for component inds[k].

  • ubs[k] = min of all declared upper bounds for component inds[k].

  • labels[k] = the first label that declared component inds[k] (stable order).

  • aliases[k] = all distinct labels that declared component inds[k], in first-seen order (always starts with labels[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 to CTModels.Building.append_box_constraints!.

  • aliases: in-place empty Vector{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.IncorrectArgument if the intersection of declared bounds is empty for some component.

Returns

  • Nothing

as_range [Function] ​

CTModels.Building.as_range Function
julia
as_range(::Nothing) -> Nothing

Return nothing unchanged.

Returns

  • Nothing
julia
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 only r.

Example

julia
julia> as_range(3)
3:3
julia
as_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
julia> as_range(1:5)
1:5

as_vector [Function] ​

CTModels.Building.as_vector Function
julia
as_vector(::Nothing) -> Nothing

Return nothing unchanged.

Returns

  • Nothing
julia
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 containing x.

Example

julia
julia> as_vector(1.0)
1-element Vector{Float64}:
 1.0
julia
as_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
julia> as_vector([1.0, 2.0, 3.0])
3-element Vector{Float64}:
 1.0
 2.0
 3.0

From CTModelsMakie ​

_plot [Function] ​

CTModelsMakie._plot Function
julia
_plot(
    sol::CTModels.Solutions.Solution,
    description::Symbol...;
    size,
    color,
    kwargs...
) -> Makie.Figure

Internal 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
julia
_plot!(
    f::Makie.Figure,
    sol::CTModels.Solutions.Solution,
    description::Symbol...;
    color,
    kwargs...
) -> Makie.Figure

Internal 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
julia
_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
julia
_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
julia
_data_time_grids(data)

Time 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, :costate and :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
julia
_ensure_extension(filename::String, ext::String) -> String

Return filename with ext appended, unless filename already ends with ext (case-insensitively).

Arguments

  • filename::String: base filename, with or without ext.

  • ext::String: extension to ensure, including the leading dot (e.g. ".json").

Returns

  • String: filename unchanged if it already ends with ext; filename * ext otherwise.

Example

julia
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
julia
_extract_optional_vector(x)

Nothing-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
julia
_extract_time_vector(time_data)

Extract 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 Real formats

  • Used by JSON and JLD2 importers to normalize time grid data, and to normalize the "variable" field, which is serialized as a scalar when variable_dimension(ocp) == 1 (per the "1-D is a scalar" convention, see CTModels.Components.variable)

See also: CTModels.Serialization._reconstruct_solution_from_data.

_format_difference [Function] ​

CTModels.Serialization._format_difference Function
julia
_format_difference(d, side::Int64) -> String

Format 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
julia
_ncols(::Nothing)

Number of columns of a stored matrix, or nothing when the entry is absent.

_nlength [Function] ​

CTModels.Serialization._nlength Function
julia
_nlength(::Nothing)

Number of points of a stored time grid, or nothing when the entry is absent.

_nrows [Function] ​

CTModels.Serialization._nrows Function
julia
_nrows(::Nothing)

Number of rows of a stored array, or nothing when the entry is absent.

_optional [Function] ​

CTModels.Serialization._optional Function
julia
_optional(data, key::String, ::Type{T}) where T

Read 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 to T.

_optional_mask [Function] ​

CTModels.Serialization._optional_mask Function
julia
_optional_mask(x)

A mask of the known rows read from serialized data, as a Vector{Bool}, or nothing.

_reconstruct_solution_from_data [Function] ​

CTModels.Serialization._reconstruct_solution_from_data Function
julia
_reconstruct_solution_from_data(ocp, data; infos)

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 model

  • data: Dictionary containing the imported solution data, including all dual fields and control_interpolation

Keyword Arguments

  • infos: Solver information dictionary (Dict{Symbol,Any}). Passed explicitly because JSON deserialization must restore Symbol types before calling this helper.

Returns

  • Solution: Reconstructed solution with appropriate time grid model

Notes

  • If time_grid_state key exists, assumes multiple time grid format

  • Otherwise, uses the current unified format (single time_grid key)

  • The switching structure is rebuilt when the data holds it ("switching_times"), so the trajectories keep their jumps (see CTModels.Solutions.build_solution)

Example

julia
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
julia
_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 (nothing if 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
julia
_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 of ocp (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.