Skip to content

Dim 0 control#283

Merged
ocots merged 9 commits intomainfrom
282-feature-dim-0-control
Mar 11, 2026
Merged

Dim 0 control#283
ocots merged 9 commits intomainfrom
282-feature-dim-0-control

Conversation

@ocots
Copy link
Copy Markdown
Member

@ocots ocots commented Mar 10, 2026

Close #282

Phase 1:
- Add EmptyControlModel sentinel type
- Change PreModel.control default from nothing to EmptyControlModel()
- Add __is_control_empty and redefine __is_control_set helpers
- Remove control requirement from __is_consistent and __is_complete
- Export EmptyControlModel
- Add getters for EmptyControlModel (name, components, dimension)

Phase 2:
- Remove control precondition from dynamics! (full and partial)
- Remove control precondition from objective!
- Add conditional control precondition in constraint! (only for :control and :path types)
- Update regression tests to reflect new behavior

All tests pass (128/128 for Phase 2 regression tests)
@ocots ocots linked an issue Mar 10, 2026 that may be closed by this pull request
- Change constraint! to only require control for :control type
- Path constraints can now work without control (e.g., state-only path constraints)
- Add test for path constraint without control
- Update test description for control constraint
- All tests pass (17/17 for control_zero, 39/39 for constraints)
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 10, 2026

Breakage test results
Date: 2026-03-10 23:35:10

Name Latest Stable
CTDirect compat: v0.9.6 compat: v0.9.6
CTFlows compat: v0.9.6 compat: v0.9.6
OptimalControl compat: v0.6.10-beta.2 compat: v0.9.6

ocots added 7 commits March 10, 2026 23:08
- Remove control requirement from build() function
- Control is now optional when building a Model
- Add test for building Model without control
- All tests pass (21/21 for control_zero, 60/60 for model regression)

This allows creating optimal control problems without control input (control dimension = 0).
- Make control display conditional based on u_dim > 0
- Skip control in objective function display when u_dim == 0
- Skip control in dynamics arguments when u_dim == 0
- Skip control in 'where' clause when u_dim == 0
- Add test for display without control
- All tests pass (25/25 for control_zero, 4/4 for print regression)

This allows proper display of optimal control problems without control input.
- Add zero dimension handling in initial_control for Real input
- Add zero dimension handling in initial_control for Vector input
- Return empty vector function when control dimension is 0 and input is nothing
- Throw appropriate errors when trying to initialize zero-dim control with non-empty data
- Add comprehensive tests for initialization without control
- All tests pass (33/33 for control_zero, 239/239 for initial_guess regression)

This allows proper initialization of optimal control problems without control input.
Phase 6: Validation - No changes needed
- Name validation helpers already handle EmptyControlModel correctly via __is_control_set()
- Tests pass (39/39)

Phase 7: Serialization - No changes needed
- Serialization handles zero control dimension correctly (creates n×0 matrices)
- Tests pass (1831/1831)

Phase 8: Plotting - Skip control plots when dim=0
- Modified do_plot() in ext/plot_utils.jl to check control_dimension(sol) > 0
- Control plots are now skipped when control dimension is zero
- Tests pass (33/33)

All 8 phases of the refactoring are now complete. The codebase fully supports
optimal control problems without control input (control dimension = 0) while
maintaining backward compatibility.
Phase 6: Name validation tests
- Verify that control names are not collected when control is not set
- Test that 'u' can be used as state component name when control is empty

Phase 7: Serialization tests
- Test solution building with zero control dimension
- Verify control function returns empty vector
- Test solution properties (state_dimension, objective)

Phase 8: Plotting tests
- Import Plots at module level
- Test subplot count with :group layout (state + costate = 2 subplots)
- Test subplot count with :split layout (2 state + 2 costate = 4 subplots)
- Verify control plots are correctly skipped when dim=0

All tests pass (45/45) including the new comprehensive tests for
zero control dimension support.
…pport

Tests added to test_control_zero.jl:
- Serialization round-trip JSON export/import with control_dimension=0
- Serialization round-trip JLD2 export/import with control_dimension=0
- initial_control with empty vector Float64[] accepted when dim=0
- Plotting: explicit :control in description silently skipped when dim=0
- Plotting: state-only description with :split layout
- build() with variable but no control (dimension 0)
- Display: model without control but with variable (J(x,v) not J(x,u,v))

Docstrings updated:
- __is_control_set(::Model): clarify EmptyControlModel case
- PreModel: update control field type annotation
- dynamics!(ocp, f): remove outdated control precondition mention
- dynamics!(ocp, rg, f): same
- objective!(ocp, ...): remove control from preconditions list
- constraint!(ocp, ...): document control only needed for :control type
- build(pre_ocp): document control as optional, add zero-control example
- __print_mathematical_definition: document u_dim=0 behavior
- do_plot: document control skipped when control_dimension=0
- EmptyControlModel: enhance with usage context and See also refs
@ocots ocots merged commit 8b9310c into main Mar 11, 2026
18 checks passed
@ocots ocots deleted the 282-feature-dim-0-control branch March 11, 2026 10:04
@ocots ocots mentioned this pull request Mar 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Dim 0 control

1 participant