Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ Versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### 📚 Documentation

- **Initial guess: check a guess before solving with `build_initial_guess`** ([#965](https://github.com/control-toolbox/OptimalControl.jl/issues/965)). It builds and validates the guess against the problem. The other initial-guess helpers of CTModels (`initial_guess`, `pre_initial_guess`, `validate_initial_guess`, `initial_state`, `initial_control`, `initial_variable`, `PreInitialGuess`) stay unexported, and a test now records that choice.

### 🐛 Bug Fixes

- **`init` and `initial_guess` together raise "Conflicting aliases" in descriptive mode too** ([#964](https://github.com/control-toolbox/OptimalControl.jl/issues/964)). Explicit mode already reported the conflict; descriptive mode, the common case, routed the leftover `init` to the strategies and rejected it as an unknown option, with unrelated suggestions. Both modes now run the same check before any routing.
Expand Down
20 changes: 19 additions & 1 deletion docs/src/solve/initial-guess.md
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ sol = solve(ocp2; init=(state=s -> [-1 + s, 0.0], control=0.1, variable=2.0), di
println(iterations(sol), " iterations")
```

## Inspect a guess
## Inspect or check a guess

Whatever you pass as `init`, `solve` turns it into an initial guess with
[`build_initial_guess`](@ref)`(ocp, init)`. You can call it yourself, and read the result back
Expand All @@ -381,6 +381,24 @@ state(ig)(0.5), control(ig)(0.5), variable(ig)

The same holds for the output of `@init` itself, which is an initial guess already.

`build_initial_guess` also checks the guess against the problem: a component of the wrong
dimension raises an `IncorrectArgument`. To check a guess before solving, build it:

```@example main
err = try
build_initial_guess(ocp2, (state=[-1.0, 0.0, 0.0],)) # ocp2 has a 2-D state
nothing
catch e
e
end
err isa IncorrectArgument
```

```@example main
@assert err isa IncorrectArgument # hide
nothing # hide
```

## Costate and multipliers

There is currently no way to seed the costate or the multipliers — only state, control, and
Expand Down
18 changes: 18 additions & 0 deletions test/suite/reexport/test_ctmodels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,24 @@ function test_ctmodels()
end
Test.@test reexports(OptimalControl, :build_initial_guess, CTModels.Init)
Test.@test isdefined(CurrentModule, :build_initial_guess)

# Deliberately not exported (#965): `build_initial_guess` already builds and
# validates a guess, `@init` and named tuples cover construction, and
# `state`/`control`/`variable` cover inspection.
for f in (
:initial_guess,
:pre_initial_guess,
:validate_initial_guess,
:initial_state,
:initial_control,
:initial_variable,
:PreInitialGuess,
)
Test.@testset "$f not exported" begin
Test.@test !is_exported(OptimalControl, f)
Test.@test !isdefined(CurrentModule, f)
end
end
end

Test.@testset "Serialization" begin
Expand Down
Loading