Dionysos aims to design a controller for a system
- the system
$\mathcal{S}$ is specified byMathematicalSystems
orHybridSystems
objects; - the specification
$\Sigma$ is specified byProblemType
objects; - the solver
$\mathcal{O}$ implementents the abstract typeAbstractOptimizer
ofMathOptInterface
.
So a control problem JuMP
interface, with Dionysos inheriting JuMP's powerful and practical optimization framework.
Description of the core of the Dionysos.jl package, the src
folder:
Subfolder | Description |
---|---|
utils |
Contains useful functions, data structures, classic search algorithms, file management, ... |
domain |
Contains structures defining the domain of a system |
system |
Contains a description of specific systems |
problem |
Contains control problems that can be solved by Dionysos solvers |
symbolic |
Contains the data structures needed to encode the abstractions |
optim |
Contains the solvers |
The system types supported in Dionysos.jl are:
-
MathematicalSystems
, which proposes generic and flexible system definitions (e.g. discrete-time/continuous-time, constrained, noisy systems), such that, for example, the systemMathematicalSystems.NoisyConstrainedAffineControlDiscreteSystem
of the form$$x(k+1) = A x(k) + B u(k) + c + D w(k), \ x(k)\in\mathcal{X}, \ u(k)\in\mathcal{U},\ w(k)\in\mathcal{W}\ \forall k$$ where$\mathcal{X}$ is the state constraint,$\mathcal{U}$ is the input constraint and$\mathcal{W}$ is the noise constraint. -
HybridSystems
, which extends the class of systems ofMathematicalSystems
to hybrid systems.
The problem types supported in Dionysos.jl are:
Type | Description |
---|---|
Reach-avoid optimal control problem |
|
Safety control problem |
|
Extensions for linear temporal logic (LTL) specifications are currently being implemented.
The following tables summarize the different solvers.
Abstraction-based solver types implemented in Dionysos.jl:
Type | Full vs partial discretization | Partition vs Cover | Shape | Local controller | Abstraction | System | Reference |
---|---|---|---|---|---|---|---|
Uniform grid abstraction |
Full | Partition | Hyperrectangle | Piece-wise constant | Non-determinisitic | Continuous-time | SCOTS: A Tool for the Synthesis of Symbolic Controllers |
Lazy abstraction |
Partial | Partition | Hyperrectangle | Piece-wise constant | Non-determinisitic | Continuous-time | Alternating simulation on hierarchical abstractions |
Hierarchical abstraction |
Partial | Partition | Hyperrectangle | Piece-wise constant | Non-determinisitic | Continuous-time | Alternating simulation on hierarchical abstractions |
Ellipsoid abstraction |
Full | Cover | Ellipsoid | Piece-wise affine | Determinisitic | Discrete-time affine | State-feedback Abstractions for Optimal Control of Piecewise-affine Systems |
Lazy ellipsoid abstraction |
Partial | Cover | Ellipsoid | Piece-wise affine | Determinisitic | Discrete-time non-linear | Not yet published |
Non abstraction-based solver types implemented in Dionysos.jl:
Type | Description | Reference |
---|---|---|
Bemporad Morari |
Optimal control of hybrid systems via a predictive control scheme using mixed integer quadratic programming (MIQP) online optimization procedures. | Control of systems integrating logic, dynamics, and constraints |
BranchAndBound |
Optimal control of hybrid systems via a predictive control scheme combining a branch and bound algorithm that can refine Q-functions using Lagrangian duality. | Abstraction-based branch and bound approach to Q-learning for hybrid optimal control |
Solver interface
Each solver is defined by a module which must implement the abstract type AbstractOptimizer
and the Optimize!
function.
For example, for the UniformGridAbstraction solver, this structure and function are defined as follows
using JuMP
mutable struct Optimizer{T} <: MOI.AbstractOptimizer
concrete_problem::Union{Nothing, PR.ProblemType}
abstract_problem::Union{Nothing, PR.OptimalControlProblem, PR.SafetyProblem}
abstract_system::Union{Nothing, SY.SymbolicModelList}
abstract_controller::Union{Nothing, UT.SortedTupleSet{2, NTuple{2, Int}}}
concrete_controller::Any
state_grid::Union{Nothing, DO.Grid}
input_grid::Union{Nothing, DO.Grid}
function Optimizer{T}() where {T}
return new{T}(nothing, nothing, nothing, nothing, nothing, nothing, nothing)
end
end
and
function MOI.optimize!(optimizer::Optimizer)
# Build the abstraction
abstract_system = build_abstraction(
optimizer.concrete_problem.system,
optimizer.state_grid,
optimizer.input_grid,
)
optimizer.abstract_system = abstract_system
# Build the abstract problem
abstract_problem = build_abstract_problem(optimizer.concrete_problem, abstract_system)
optimizer.abstract_problem = abstract_problem
# Solve the abstract problem
abstract_controller = solve_abstract_problem(abstract_problem)
optimizer.abstract_controller = abstract_controller
# Solve the concrete problem
optimizer.concrete_controller =
solve_concrete_problem(abstract_system, abstract_controller)
return
end
In this section, we outline how to define and solve a control problem with Dionsysos.
For an executable version of this example, see Solvers: Path planning problem
in the documentation.
Define a control problem, i.e., the system and the specification of the desired closed loop behaviour. To do this, you can define new ones yourself or directly load an existing benchmark, for example
concrete_problem = PathPlanning.problem(; simple = true, approx_mode = PathPlanning.GROWTH);
concrete_system = concrete_problem.system;
Choose the solver you wish to use
using JuMP
optimizer = MOI.instantiate(AB.UniformGridAbstraction.Optimizer)
Define the solver's meta-parameters
x0 = SVector(0.0, 0.0, 0.0);
hx = SVector(0.2, 0.2, 0.2);
state_grid = DO.GridFree(x0, hx);
u0 = SVector(0.0, 0.0);
hu = SVector(0.3, 0.3);
input_grid = DO.GridFree(u0, hu);
Set the solver's meta-parameters
MOI.set(optimizer, MOI.RawOptimizerAttribute("concrete_problem"), concrete_problem)
MOI.set(optimizer, MOI.RawOptimizerAttribute("state_grid"), state_grid)
MOI.set(optimizer, MOI.RawOptimizerAttribute("input_grid"), input_grid)
Solve the control problem
MOI.optimize!(optimizer)
Get the results
abstract_system = MOI.get(optimizer, MOI.RawOptimizerAttribute("abstract_system"))
abstract_problem = MOI.get(optimizer, MOI.RawOptimizerAttribute("abstract_problem"))
abstract_controller = MOI.get(optimizer, MOI.RawOptimizerAttribute("abstract_controller"))
concrete_controller = MOI.get(optimizer, MOI.RawOptimizerAttribute("concrete_controller"))
In Dionysos, all the structures that could be relevant to plot (such as trajectories, state-space discretization, specifications, obstacles, etc.)
have an associated @recipe
function, which makes it very easy to plot all the results using the single common plot
function of Plots.jl
.
For example
using Plots
plot!(concrete_system.X; color = :yellow, opacity = 0.5);
plot!(abstract_system.Xdom; color = :blue, opacity = 0.5);
plot!(concrete_problem.initial_set; color = :green, opacity = 0.2);
plot!(concrete_problem.target_set; dims = [1, 2], color = :red, opacity = 0.2);
plot!(control_trajectory; ms = 0.5)