Description
When defining a ProjectedDynamicalSystem
, the user must define a function complete_state
that must returns a vector of the same dimension than the original dynamical system. Such that:
ds = Systems.lorenz96(5)
projection(u) = [sum(u), sqrt(u[1]^2 + u[2]^2)]
complete_state(y) = repeat([y[1]/5], 5)
prods = ProjectedDynamicalSystem(ds, projection, complete_state)
The docstring says:
complete_state produces the state for the original system from
the projected state. complete_state can always be a function
that given the projected state returns a state in the original
space.
In the previous example this is not true, since the projected space is a 2D space and the complete_state function only takes the first dimension of the input vector y.
In fact the complete_state function can be a crazy input y
, the only requisite is to return a valid vector on the original phase space.
I propose a minor change in the docstring and small modification of the source code:
function ProjectedDynamicalSystem(ds::DynamicalSystem, projection, complete_state)
u0 = initial_state(ds)
if projection isa AbstractVector{Int}
all(1 .≤ projection .≤ dimension(ds)) || error("Dim. of projection must be in 1 ≤ np ≤ dimension(ds)")
projection = SVector(projection...)
y = u0[projection]
else
projection(u0) isa AbstractVector || error("Projected state must be an AbstracVector")
y = projection(u0)
end
if complete_state isa AbstractVector
projection isa AbstractVector{Int} || error("Projection vector must be of type Int")
length(complete_state) + length(projection) == dimension(ds) ||
error("Wrong dimensions for complete_state and projection")
remidxs = setdiff(1:dimension(ds), projection)
!isempty(remidxs) || error("Error with the indices of the projection")
else
# Define a wrapper function to check the state since we do not know what will be the input y
comp_state(y) = length(complete_state(y)) == dimension(ds) ? complete_state(y) : error("The returned vector of complete_state must equal dimension(ds)")
remidxs = nothing
end
u = zeros(dimension(ds))
return ProjectedDynamicalSystem{
typeof(projection), length(y), typeof(complete_state),
typeof(remidxs), typeof(ds)}(projection, comp_state, u, remidxs, ds)
end
The change introduces a small overhead in the computation of the initial state. Maybe there is a better solution. Maybe a special error definition if the case arises that complete_state(y) != dimension(ds)