|
| 1 | +module CTModelsJSON |
| 2 | + |
| 3 | +using CTBase |
| 4 | +using CTModels |
| 5 | +using DocStringExtensions |
| 6 | + |
| 7 | +using JSON3 |
| 8 | + |
| 9 | +""" |
| 10 | +$(TYPEDSIGNATURES) |
| 11 | + |
| 12 | +Export OCP solution in JSON format |
| 13 | +""" |
| 14 | +function CTModels.export_ocp_solution( |
| 15 | + ::CTModels.JSON3Tag, sol::CTModels.Solution; filename_prefix="solution" |
| 16 | +) |
| 17 | + |
| 18 | + T = CTModels.time_grid(sol) |
| 19 | + |
| 20 | + blob = Dict( |
| 21 | + "time_grid" => CTModels.time_grid(sol), |
| 22 | + "state" => CTModels.state_discretized(sol), |
| 23 | + "control" => CTModels.control_discretized(sol), |
| 24 | + "variable" => CTModels.variable(sol), |
| 25 | + "costate" => CTModels.costate_discretized(sol)[1:(end - 1), :], |
| 26 | + "objective" => CTModels.objective(sol), |
| 27 | + "iterations" => CTModels.iterations(sol), |
| 28 | + "constraints_violation" => CTModels.constraints_violation(sol), |
| 29 | + "message" => CTModels.message(sol), |
| 30 | + "stopping" => CTModels.stopping(sol), |
| 31 | + "success" => CTModels.success(sol), |
| 32 | + "path_constraints" => CTModels.discretize(CTModels.path_constraints(sol), T), |
| 33 | + "path_constraints_dual" => CTModels.discretize(CTModels.path_constraints_dual(sol), T), |
| 34 | + "state_constraints_lb_dual" => CTModels.discretize(CTModels.state_constraints_lb_dual(sol), T), |
| 35 | + "state_constraints_ub_dual" => CTModels.discretize(CTModels.state_constraints_ub_dual(sol), T), |
| 36 | + "control_constraints_lb_dual" => CTModels.discretize(CTModels.control_constraints_lb_dual(sol), T), |
| 37 | + "control_constraints_ub_dual" => CTModels.discretize(CTModels.control_constraints_ub_dual(sol), T), |
| 38 | + "boundary_constraints" => CTModels.boundary_constraints(sol), # ctVector or Nothing |
| 39 | + "boundary_constraints_dual" => CTModels.boundary_constraints_dual(sol), # ctVector or Nothing |
| 40 | + "variable_constraints_lb_dual" => CTModels.variable_constraints_lb_dual(sol), # ctVector or Nothing |
| 41 | + "variable_constraints_ub_dual" => CTModels.variable_constraints_ub_dual(sol), # ctVector or Nothing |
| 42 | + ) |
| 43 | + |
| 44 | + open(filename_prefix * ".json", "w") do io |
| 45 | + JSON3.pretty(io, blob) |
| 46 | + end |
| 47 | + |
| 48 | + return nothing |
| 49 | +end |
| 50 | + |
| 51 | +""" |
| 52 | +$(TYPEDSIGNATURES) |
| 53 | + |
| 54 | +Read OCP solution in JSON format |
| 55 | +""" |
| 56 | +function CTModels.import_ocp_solution( |
| 57 | + ::CTModels.JSON3Tag, ocp::CTModels.Model; filename_prefix="solution" |
| 58 | +) |
| 59 | + |
| 60 | + json_string = read(filename_prefix * ".json", String) |
| 61 | + blob = JSON3.read(json_string) |
| 62 | + |
| 63 | + # get state |
| 64 | + X = stack(blob["state"]; dims=1) |
| 65 | + if X isa Vector # if X is a Vector, convert it to a Matrix |
| 66 | + X = Matrix{Float64}(reduce(hcat, X)') |
| 67 | + end |
| 68 | + |
| 69 | + # get control |
| 70 | + U = stack(blob["control"]; dims=1) |
| 71 | + if U isa Vector # if U is a Vector, convert it to a Matrix |
| 72 | + U = Matrix{Float64}(reduce(hcat, U)') |
| 73 | + end |
| 74 | + |
| 75 | + # get costate |
| 76 | + P = stack(blob["costate"]; dims=1) |
| 77 | + if P isa Vector # if P is a Vector, convert it to a Matrix |
| 78 | + P = Matrix{Float64}(reduce(hcat, P)') |
| 79 | + end |
| 80 | + |
| 81 | + # get path constraints (and dual): convert to matrix |
| 82 | + path_constraints = isnothing(blob["path_constraints"]) ? nothing : stack(blob["path_constraints"]; dims=1) |
| 83 | + if path_constraints isa Vector # if path_constraints is a Vector, convert it to a Matrix |
| 84 | + path_constraints = Matrix{Float64}(reduce(hcat, path_constraints)') |
| 85 | + end |
| 86 | + path_constraints_dual = isnothing(blob["path_constraints_dual"]) ? nothing : stack(blob["path_constraints_dual"]; dims=1) |
| 87 | + if path_constraints_dual isa Vector # if path_constraints_dual is a Vector, convert it to a Matrix |
| 88 | + path_constraints_dual = Matrix{Float64}(reduce(hcat, path_constraints_dual)') |
| 89 | + end |
| 90 | + |
| 91 | + # get state constraints (and dual): convert to matrix |
| 92 | + state_constraints_lb_dual = isnothing(blob["state_constraints_lb_dual"]) ? nothing : stack(blob["state_constraints_lb_dual"]; dims=1) |
| 93 | + if state_constraints_lb_dual isa Vector # if state_constraints_lb_dual is a Vector, convert it to a Matrix |
| 94 | + state_constraints_lb_dual = Matrix{Float64}(reduce(hcat, state_constraints_lb_dual)') |
| 95 | + end |
| 96 | + state_constraints_ub_dual = isnothing(blob["state_constraints_ub_dual"]) ? nothing : stack(blob["state_constraints_ub_dual"]; dims=1) |
| 97 | + if state_constraints_ub_dual isa Vector # if state_constraints_ub_dual is a Vector, convert it to a Matrix |
| 98 | + state_constraints_ub_dual = Matrix{Float64}(reduce(hcat, state_constraints_ub_dual)') |
| 99 | + end |
| 100 | + |
| 101 | + # get control constraints (and dual): convert to matrix |
| 102 | + control_constraints_lb_dual = isnothing(blob["control_constraints_lb_dual"]) ? nothing : stack(blob["control_constraints_lb_dual"]; dims=1) |
| 103 | + if control_constraints_lb_dual isa Vector # if control_constraints_lb_dual is a Vector, convert it to a Matrix |
| 104 | + control_constraints_lb_dual = Matrix{Float64}(reduce(hcat, control_constraints_lb_dual)') |
| 105 | + end |
| 106 | + control_constraints_ub_dual = isnothing(blob["control_constraints_ub_dual"]) ? nothing : stack(blob["control_constraints_ub_dual"]; dims=1) |
| 107 | + if control_constraints_ub_dual isa Vector # if control_constraints_ub_dual is a Vector, convert it to a Matrix |
| 108 | + control_constraints_ub_dual = Matrix{Float64}(reduce(hcat, control_constraints_ub_dual)') |
| 109 | + end |
| 110 | + |
| 111 | + # get boundary constraints (and dual): no conversion needed |
| 112 | + boundary_constraints = blob["boundary_constraints"] |
| 113 | + boundary_constraints_dual = blob["boundary_constraints_dual"] |
| 114 | + |
| 115 | + # get variable constraints dual: no conversion needed |
| 116 | + variable_constraints_lb_dual = blob["variable_constraints_lb_dual"] |
| 117 | + variable_constraints_ub_dual = blob["variable_constraints_ub_dual"] |
| 118 | + |
| 119 | + # NB. convert vect{vect} to matrix |
| 120 | + return CTModels.build_solution( |
| 121 | + ocp, |
| 122 | + Vector{Float64}(blob.time_grid), |
| 123 | + X, |
| 124 | + U, |
| 125 | + Vector{Float64}(blob.variable), |
| 126 | + P; |
| 127 | + objective=Float64(blob.objective), |
| 128 | + iterations=blob.iterations, |
| 129 | + constraints_violation=Float64(blob.constraints_violation), |
| 130 | + message=blob.message, |
| 131 | + stopping=Symbol(blob.stopping), |
| 132 | + success=blob.success, |
| 133 | + path_constraints=path_constraints, |
| 134 | + path_constraints_dual=path_constraints_dual, |
| 135 | + state_constraints_lb_dual=state_constraints_lb_dual, |
| 136 | + state_constraints_ub_dual=state_constraints_ub_dual, |
| 137 | + control_constraints_lb_dual=control_constraints_lb_dual, |
| 138 | + control_constraints_ub_dual=control_constraints_ub_dual, |
| 139 | + boundary_constraints=boundary_constraints, |
| 140 | + boundary_constraints_dual=boundary_constraints_dual, |
| 141 | + variable_constraints_lb_dual=variable_constraints_lb_dual, |
| 142 | + variable_constraints_ub_dual=variable_constraints_ub_dual, |
| 143 | + ) |
| 144 | + |
| 145 | +end |
| 146 | + |
| 147 | +end |
0 commit comments