Skip to content

Private API

This page lists non-exported (internal) symbols of CTModels.Display, CTModelsPlots, CTModels.Solutions, CTModelsJSON, CTModelsJLD, CTModels.Components, CTModels.Building, CTModels.Init, CTModels.Models, CTModels.Serialization.


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.

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


From CTModelsPlots

_BOUND_STYLE [Constant]

CTModelsPlots._BOUND_STYLE Constant

Default style for box-bound and path-bound horizontal reference lines.

_TIME_STYLE [Constant]

CTModelsPlots._TIME_STYLE Constant

Default style for initial/final time vertical reference lines.

__control_layout [Function]

CTModelsPlots.__control_layout Function
julia
__control_layout() -> Symbol

Return the default control representation (:components).

__description [Function]

CTModelsPlots.__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.

__plot_label_suffix [Function]

CTModelsPlots.__plot_label_suffix Function
julia
__plot_label_suffix() -> String

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

__plot_layout [Function]

CTModelsPlots.__plot_layout Function
julia
__plot_layout() -> Symbol

Return the default plot layout (:split).

__plot_style [Function]

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

Return the default plotting style (empty NamedTuple).

__time_normalization [Function]

CTModelsPlots.__time_normalization Function
julia
__time_normalization() -> Symbol

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

_assemble_group [Function]

CTModelsPlots._assemble_group Function
julia
_assemble_group(
    cells::AbstractVector{<:CTBase.Plotting.AbstractLayoutNode}
) -> Any

Assemble group cells horizontally (:group layout).

Exactly four cells (state, costate, control, control-norm) fold into a 2×2 grid.

_assemble_split [Function]

CTModelsPlots._assemble_split Function
julia
_assemble_split(
;
    state,
    costate,
    control,
    path,
    dual
) -> Union{Nothing, CTBase.Plotting.AbstractLayoutNode}

Assemble stacked columns (:split layout).

The layout is (state | costate) over control over (path | dual). Returns nothing when there is nothing to draw.

_base_style [Function]

CTModelsPlots._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]

CTModelsPlots._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]

CTModelsPlots._build_root Function
julia
_build_root(
    sol,
    description::Symbol...;
    layout,
    control,
    time,
    state_style,
    costate_style,
    control_style,
    path_style,
    dual_style,
    time_style,
    state_bounds_style,
    control_bounds_style,
    path_bounds_style
)

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.

_control_panels [Function]

CTModelsPlots._control_panels Function
julia
_control_panels(
    sol,
    control::Symbol,
    style::NamedTuple,
    layout::Symbol
) -> 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]

CTModelsPlots._costate_panel Function
julia
_costate_panel(sol, style::NamedTuple; layout, state_shown)

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

Labels depend on layout and whether the state panel is shown alongside.

_dual_panel [Function]

CTModelsPlots._dual_panel Function
julia
_dual_panel(sol, model, style::NamedTuple; path_shown)

Build a CTBase.Plotting.Panel for the dual variables of the path constraints.

_pair [Function]

CTModelsPlots._pair Function
julia
_pair(a, b) -> Any

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]

CTModelsPlots._path_hlines Function
julia
_path_hlines(model, style::NamedTuple) -> Any

Build bound lines for nonlinear path constraints.

Each of the nc components carries lower and upper bound lines.

_path_panel [Function]

CTModelsPlots._path_panel Function
julia
_path_panel(
    sol,
    model,
    style::NamedTuple
) -> CTBase.Plotting.Panel

Build a CTBase.Plotting.Panel for the nonlinear path constraints.

_plot [Function]

CTModelsPlots._plot Function
julia
_plot(
    sol::CTModels.Solutions.Solution,
    description::Symbol...;
    layout,
    control,
    time,
    state_style,
    state_bounds_style,
    control_style,
    control_bounds_style,
    costate_style,
    time_style,
    path_style,
    path_bounds_style,
    dual_style,
    size,
    color,
    kwargs...
) -> Any

Internal implementation of Plots.plot(::CTModels.Solution).

Builds the layout tree and renders it via CTBase.Plotting.

_plot! [Function]

CTModelsPlots._plot! Function
julia
_plot!(
    p::Plots.Plot,
    sol::CTModels.Solutions.Solution,
    description::Symbol...;
    layout,
    control,
    time,
    state_style,
    state_bounds_style,
    control_style,
    control_bounds_style,
    costate_style,
    time_style,
    path_style,
    path_bounds_style,
    dual_style,
    color,
    kwargs...
) -> Plots.Plot

Internal implementation of Plots.plot!(::Plots.Plot, ::CTModels.Solution).

Builds the layout tree and overlays it onto the existing plot p via CTBase.Plotting.

_rownorm [Function]

CTModelsPlots._rownorm Function
julia
_rownorm(row) -> Any

Return the Euclidean norm of a matrix row.

_sample [Function]

CTModelsPlots._sample Function
julia
_sample(f, T) -> Any

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

Uniform for scalar and vector-valued f.

_state_panel [Function]

CTModelsPlots._state_panel Function
julia
_state_panel(
    sol,
    style::NamedTuple
) -> CTBase.Plotting.Panel

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

_time_name [Function]

CTModelsPlots._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]

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

clean [Function]

CTModelsPlots.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]

CTModelsPlots.do_decorate Function
julia
do_decorate(
;
    model,
    time_style,
    state_bounds_style,
    control_bounds_style,
    path_bounds_style
)

Decide which decorations to draw (bounds lines and initial/final time lines).

Each decoration needs a non-:none style and a model to read the bounds/times from.

Returns

  • NTuple{4, Bool}: flags for (time, state_bounds, control_bounds, path_bounds).

do_plot [Function]

CTModelsPlots.do_plot Function
julia
do_plot(
    sol::CTModels.Solutions.AbstractSolution,
    description::Symbol...;
    state_style,
    control_style,
    costate_style,
    path_style,
    dual_style
)

Decide which signal groups to draw for the given solution and description.

A group is drawn when it is requested, its style is not :none, and it actually exists in the solution:

  • control needs control_dimension(sol) > 0,

  • path needs dim_path_constraints_nl(ocp) > 0,

  • dual needs path_constraints_dual(sol) to be present.

Returns

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

From CTModels.Solutions

BoxDualDiff [Struct]

CTModels.Solutions.BoxDualDiff Type
julia
BoxDualDiff{DL,DU,I} <: Function

Callable struct computing the net dual of a box constraint: f(t) = lb(t)[idx] - ub(t)[idx].

I = Int gives a scalar; I = Vector{Int} gives a vector.

Replaces anonymous closures t -> duals_lb(t)[i] - duals_ub(t)[i] (and the vector variant) produced by dual(sol, model, label) for state and control box constraints.

DualSlice [Struct]

CTModels.Solutions.DualSlice Type
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).

_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 trajectoryT_state grid

  • Control trajectoryT_control grid

  • Costate trajectoryT_costate grid

  • Path constraint dualsT_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: _serialize_solution, _discretize_function, _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.

_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: _validate_and_fix_time_grid, 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.

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

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

_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

Notes

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

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

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<:CTModels.Solutions.AbstractDualModel}
) -> CTModels.Solutions.AbstractDualModel

Return the dual model containing all constraint multipliers.


From CTModelsJSON

_MATRIX_FIELDS [Constant]

CTModelsJSON._MATRIX_FIELDS Constant

Solution fields that are always serialized as Matrix{Float64} and must be converted to Vector{Vector} for JSON3.

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

_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 JSON3 export.

JSON3 flattens Matrix{Float64} into 1D arrays, 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_to_matrix [Function]

CTModelsJSON._json_to_matrix Function

Convert a JSON field (Vector{Vector} via stack) to Matrix{Float64}.

JSON exports matrices as Vector{Vector}. After stack(blob[field]; dims=1), we get either a Matrix (multi-D) or Vector (1D). This normalizes to Matrix.

Arguments

  • blob_field: JSON array field (Vector of Vectors)

Returns

  • Matrix{Float64}: (n_time_points, n_dim)

_json_to_optional_matrix [Function]

CTModelsJSON._json_to_optional_matrix Function

Convert an optional JSON field to Matrix{Float64} or nothing.

Arguments

  • blob_field: JSON array field or nothing

Returns

  • Matrix{Float64} or nothing

_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.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.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]

__build_dynamics_from_parts [Function]

CTModels.Building.__build_dynamics_from_parts Function
julia
__build_dynamics_from_parts(
    parts::Vector{<:Tuple{var"#s48", var"#s47"} where {var"#s48"<:(AbstractRange{<:Int64}), var"#s47"<:Function}}
) -> CTModels.Building.var"#dyn!#__build_dynamics_from_parts##0"{Vector{var"#s46"}} where var"#s46"<:(Tuple{var"#s45", var"#s44"} where {var"#s45"<:(AbstractRange{<:Int64}), var"#s44"<:Function})

Build a single combined in-place dynamics function from ordered partial parts.

Used internally by CTModels.Building.build after all partial dynamics calls have been collected. Each part function updates its assigned slice of the output vector via a @view, avoiding copies.

Arguments

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

Returns

  • Function: Combined dyn!(val, t, x, u, v) that applies all parts in order.

__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,
    f,
    lb,
    ub,
    label,
    codim_f
)

Add a constraint to a dictionary of constraints.

Arguments

  • ocp_constraints: The dictionary of constraints to which the constraint will be added.

  • type: The type of the constraint. It can be :state, :control, :variable, :boundary, or :path.

  • n: The dimension of the state.

  • m: The dimension of the control.

  • q: The dimension of the variable.

  • rg: The range of the constraint. It can be an integer or a range of integers.

  • f: The function that defines the constraint. It must return a vector of the same dimension as the constraint.

  • lb: The lower bound of the constraint. It can be a number or a vector.

  • ub: The upper bound of the constraint. It can be a number or a vector.

  • label: The label of the constraint. It must be unique in the dictionary of constraints.

Requirements

  • The constraint must not be set before.

  • The lower bound 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:

  1. Name is not empty

  2. Components are not empty

  3. Name not in components (internal conflict)

  4. No duplicates in components

  5. 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::Array{T<:Real, 1},
    ubs::Array{T<:Real, 1},
    labels::Vector{Symbol},
    aliases::Vector{Vector{Symbol}},
    kind::String
)

Deduplicate box-constraint declarations by component, applying the intersection of all declared bounds for each repeated component. Produces an aliases vector recording every label that targeted each component.

After this function returns, the vectors satisfy the invariant:

  • allunique(inds) — each component appears at most once.

  • lbs[k] = 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 CTModels.Init

MergedTrajectory [Struct]

CTModels.Init.MergedTrajectory Type
julia
struct MergedTrajectory{F, C<:(AbstractDict{Int64, <:Function})} <: 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 (dim == 1) or a vector.

base::F is a concrete type parameter, replacing the former base_fun::Function abstract capture. comps::C stores the Dict{Int,Function} override map.

Component index bounds are validated at construction, not at call time, so the call method stays allocation-free beyond what base and the component functions allocate.

Replaces the anonymous closure t -> begin … end (57 lines) produced inside CTModels.Init._build_block_with_components in builders.jl.

Fields

  • base::F: Block-level trajectory function.

  • comps::C: Component-level override map (Dict{Int,Function}).

  • dim::Int: Total dimension.

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

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}
) -> 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
) -> Any

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

_format_init_data_for_grid [Function]

CTModels.Init._format_init_data_for_grid Function
julia
_format_init_data_for_grid(data) -> Any

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) -> Any

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.

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

_wrap_1d [Function]

CTModels.Init._wrap_1d Function
julia
_wrap_1d(v::AbstractVector) -> Any

Normalise a scalar or vector base value to a Vector of length 1 for dim-1 components.

Dispatched overloads replace isa AbstractVector runtime checks with static dispatch, letting the compiler specialise on the return type of the base trajectory.

Arguments

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

Returns

  • Vector: a length-1 vector containing or wrapping v.

See also: CTModels.Init._coerce_base


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.

_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

_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.Serialization

_extract_time_vector [Function]

CTModels.Serialization._extract_time_vector Function
julia
_extract_time_vector(time_data) -> Any

Extract time vector from various data formats.

Arguments

  • time_data: Time data in various formats (Vector, Matrix, etc.)

Returns

  • Vector{Float64}: Time vector

Notes

  • Handles both Vector{Float64} and Matrix{Float64} (single column) formats

  • Used by JSON and JLD2 importers to normalize time grid data

See also: CTModels.Serialization._reconstruct_solution_from_data.

_reconstruct_solution_from_data [Function]

CTModels.Serialization._reconstruct_solution_from_data Function
julia
_reconstruct_solution_from_data(
    ocp,
    data;
    infos
) -> CTModels.Solutions.Solution{TimeGridModelType, TimesModelType, StateModelType, ControlModelType, VariableModelType, ModelType, CostateModelType, Float64, DualModelType, CTModels.Solutions.SolverInfos{Any, Dict{Symbol, Any}}} where {TimeGridModelType<:Union{CTModels.Solutions.MultipleTimeGridModel, CTModels.Solutions.UnifiedTimeGridModel{Vector{Float64}}}, TimesModelType<:CTModels.Components.TimesModel, StateModelType<:(CTModels.Components.StateModelSolution{TS} where TS<:CTModels.Components.CoercedTrajectory), ControlModelType<:(CTModels.Components.ControlModelSolution{TS} where TS<:CTModels.Components.CoercedTrajectory), VariableModelType<:Union{CTModels.Components.VariableModelSolution{Vector{Float64}}, CTModels.Components.VariableModelSolution{Float64}}, ModelType<:(CTModels.Models.Model{<:CTBase.Traits.TimeDependence, T} where T<:CTModels.Components.TimesModel), CostateModelType<:CTModels.Components.CoercedTrajectory, DualModelType<:Union{CTModels.Solutions.EmptyDualModel, CTModels.Solutions.DualModel{PC_Dual, BC_Dual, SC_LB_Dual, SC_UB_Dual, CC_LB_Dual, CC_UB_Dual, VC_LB_Dual, VC_UB_Dual} where {PC_Dual<:Union{Nothing, CTModels.Components.CoercedTrajectory}, BC_Dual<:Union{Nothing, Vector{Float64}}, SC_LB_Dual<:Union{Nothing, CTModels.Components.CoercedTrajectory}, SC_UB_Dual<:Union{Nothing, CTModels.Components.CoercedTrajectory}, CC_LB_Dual<:Union{Nothing, CTModels.Components.CoercedTrajectory}, CC_UB_Dual<:Union{Nothing, CTModels.Components.CoercedTrajectory}, VC_LB_Dual<:Union{Nothing, Vector{Float64}}, VC_UB_Dual<:Union{Nothing, Vector{Float64}}}}}

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)

Example

julia
julia> sol = _reconstruct_solution_from_data(ocp, data; infos=infos)

See also: CTModels.Serialization._extract_time_vector.