Export & import
export_ocp_solution writes a Solution to disk; import_ocp_solution reads it back, given the Model it belongs to. Two formats are available, each behind its extension:
format | Extension | File |
|---|---|---|
:JLD (default) | CTModelsJLD (JLD2) | binary .jld2 |
:JSON | CTModelsJSON (JSON3) | text .json |
using CTModels
using JSON3 # CTModelsJSON
using JLD2 # CTModelsJLD
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)
N = 101
T = collect(range(0.0, 1.0; length=N))
sol = CTModels.build_solution(ocp, T, hcat(cos.(T), -sin.(T)),
reshape(-cos.(T), N, 1), Float64[], zeros(N, 2);
objective=0.5, iterations=10, constraints_violation=1e-9,
message="ok", status=:optimal, successful=true)Both formats round-trip
The filename is a base path; the extension is appended automatically.
base = joinpath(tempdir(), "ctmodels_demo")
CTModels.export_ocp_solution(sol; filename=base, format=:JSON)
CTModels.export_ocp_solution(sol; filename=base, format=:JLD)
from_json = CTModels.import_ocp_solution(ocp; filename=base, format=:JSON)
from_jld = CTModels.import_ocp_solution(ocp; filename=base, format=:JLD)
(CTModels.objective(from_json), CTModels.objective(from_jld))(0.5, 0.5)The reloaded solution behaves exactly like the original — its trajectories are again callables of time:
x = CTModels.state(from_json)
x(0.5)2-element Vector{Float64}:
0.8775825618903728
-0.479425538604203How trajectories survive serialization
A trajectory is a function t -> x(t), which neither JSON nor JLD2 can store directly. CTModels works around this by resampling: before writing, each trajectory is evaluated on its time grid (the helpers in OCP/Building/discretization_utils.jl), and only the resulting arrays are persisted. On import, the arrays are wrapped back into interpolated callables — the same mechanism used when building a solution.