Building a model
build turns a fully-declared, mutable PreModel into an immutable Model. build_model is an alias of build.
Prerequisites
Before building, the pre-model must be consistent: times, state, complete dynamics, objective and the time-dependence flag must all be set. The check is __is_consistent; build raises a structured error if a piece is missing. Control and variable are optional — their absence is represented by the EmptyControlModel / EmptyVariableModel sentinels.
Two extra declarations complete the problem:
time_dependence!— marks the systemautonomous=true|false(sets theTimeDependencetrait);definition!— optional — attaches the symbolic problem definition (a JuliaExpr) as aDefinition; without it the model carries anEmptyDefinition.
using CTModels
pre = CTModels.PreModel()
CTModels.variable!(pre, 0)
CTModels.time!(pre; t0=0.0, tf=1.0)
CTModels.state!(pre, 2)
CTModels.control!(pre, 1)
CTModels.dynamics!(pre, (r, t, x, u, v) -> (r[1] = x[2]; r[2] = u[1]; nothing))
CTModels.objective!(pre, :min; lagrange=(t, x, u, v) -> u[1]^2)
CTModels.time_dependence!(pre; autonomous=true)
ocp = CTModels.build(pre)The (autonomous) optimal control problem is of the form:
minimize J(x, u) = ∫ f⁰(x(t), u(t)) dt, over [0.0, 1.0]
subject to
ẋ(t) = f(x(t), u(t)), t in [0.0, 1.0] a.e.,
where x(t) ∈ R² and u(t) ∈ R.
What a built Model guarantees
Building freezes the structure and exposes it through accessors. Because every component is a concrete typed field, queries are type-stable and need no closure inspection:
(CTModels.state_dimension(ocp),
CTModels.control_dimension(ocp),
CTModels.variable_dimension(ocp),
CTModels.initial_time(ocp),
CTModels.final_time(ocp),
CTModels.is_autonomous(ocp),
CTModels.has_lagrange_cost(ocp))(2, 1, 0, 0.0, 1.0, true, true)Missing a required piece is caught at build time:
incomplete = CTModels.PreModel()
CTModels.state!(incomplete, 1)
try
CTModels.build(incomplete) # no times, dynamics, objective…
catch e
typeof(e)
endCTBase.Exceptions.PreconditionErrorWhere build sits in the pipeline
PreModel ──validate──► consistent? ──freeze──► Model
│ │ │
state!/… __is_consistent immutable, typed
time_dependence! name uniqueness accessor surface
definition! (opt.) dynamics completeThe immutable Model is the object every downstream package consumes: it is the input to Solutions, Initial guesses and Serialization.