Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revise ResetMap code #3183

Merged
merged 1 commit into from
Nov 13, 2022
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: 2 additions & 2 deletions docs/src/lib/lazy_operations/ResetMap.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ dim(::ResetMap)
an_element(::ResetMap)
matrix(::ResetMap)
vector(::ResetMap)
constraints_list(::ResetMap{N}) where {N}
constraints_list(::ResetMap{N, S}) where {N, S<:AbstractHyperrectangle}
set(::ResetMap)
constraints_list(::ResetMap)
```
Inherited from [`AbstractAffineMap`](@ref):
* [`isempty`](@ref isempty(::AbstractAffineMap))
Expand Down
98 changes: 47 additions & 51 deletions src/LazyOperations/ResetMap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ julia> rm = ResetMap(X, r);
Here `rm` modifies the set `X` such that `x1` is reset to 4 and `x3` is reset to
0, while `x2` is not modified.
Hence `rm` is equivalent to the set
`Hyperrectangle([4.0, 2.0, 0.0], [0.0, 1.0, 0.0])`, i.e., an axis-aligned line
`VPolytope([[4.0, 1.0, 0.0], [4.0, 3.0, 0.0]])`, i.e., an axis-aligned line
segment embedded in 3D.

The corresponding affine map ``A x + b`` would be:
Expand Down Expand Up @@ -71,7 +71,7 @@ julia> ResetMap(EmptySet(3), r)
∅(3)
```

The (in this case unique) support vector of `rm` in direction `ones(3)` is:
The (in this case unique) support vector of `rm` in direction `[1, 1, 1]` is:

```jldoctest resetmap
julia> σ(ones(3), rm)
Expand All @@ -87,10 +87,11 @@ struct ResetMap{N, S<:ConvexSet{N}} <: AbstractAffineMap{N, S}
end

isoperationtype(::Type{<:ResetMap}) = true

isconvextype(::Type{ResetMap{N, S}}) where {N, S} = isconvextype(S)

# ZeroSet is "almost absorbing" for the linear map (only the dimension changes)
# such that only the translation vector remains
# ZeroSet is "almost absorbing" for the reset map because only the translation
# vector remains
function ResetMap(Z::ZeroSet{N}, resets::Dict{Int, N}) where {N}
return Singleton(_vector_from_dictionary(resets, dim(Z)))
end
Expand All @@ -100,10 +101,6 @@ function ResetMap(∅::EmptySet{N}, resets::Dict{Int, N}) where {N}
return ∅
end


# --- AbstractAffineMap interface functions ---


"""
matrix(rm::ResetMap{N}) where {N}

Expand All @@ -116,7 +113,7 @@ reset map.

### Output

The (diagonal) matrix for the affine map ``A x + b, x ∈ X`` represented by the
The (`Diagonal`) matrix for the affine map ``A x + b, x ∈ X`` represented by the
reset map.

### Algorithm
Expand Down Expand Up @@ -147,8 +144,8 @@ reset map.

The (sparse) vector for the affine map ``A x + b, x ∈ X`` represented by the
reset map.
The vector contains the reset value for all reset dimensions, and is zero for
all other dimensions.
The vector contains the reset value for all reset dimensions and is zero for all
other dimensions.
"""
function vector(rm::ResetMap)
return _vector_from_dictionary(rm.resets, dim(rm))
Expand All @@ -162,13 +159,22 @@ function _vector_from_dictionary(dict::Dict{Int, N}, n::Int) where {N}
return b
end

function set(rm::ResetMap)
return rm.X
end
"""
set(rm::ResetMap)

Return the set wrapped by a reset map.

# --- ConvexSet interface functions ---
### Input

- `rm` -- reset map

### Output

The wrapped set.
"""
function set(rm::ResetMap)
return rm.X
end

"""
dim(rm::ResetMap)
Expand All @@ -181,7 +187,7 @@ Return the dimension of a reset map.

### Output

The dimension of a reset map.
The ambient dimension of a reset map.
"""
function dim(rm::ResetMap)
return dim(rm.X)
Expand All @@ -190,7 +196,7 @@ end
"""
σ(d::AbstractVector, rm::ResetMap)

Return the support vector of a reset map.
Return a support vector of a reset map.

### Input

Expand All @@ -199,7 +205,7 @@ Return the support vector of a reset map.

### Output

The support vector in the given direction.
A support vector in the given direction.
If the direction has norm zero, the result depends on the wrapped set.
"""
function σ(d::AbstractVector, rm::ResetMap)
Expand All @@ -214,7 +220,7 @@ end
"""
ρ(d::AbstractVector, rm::ResetMap)

Return the support function of a reset map.
Evaluate the support function of a reset map.

### Input

Expand All @@ -223,7 +229,7 @@ Return the support function of a reset map.

### Output

The support function in the given direction.
The evaluation of the support function in the given direction.

### Notes

Expand Down Expand Up @@ -254,7 +260,10 @@ Return some element of a reset map.
### Output

An element in the reset map.
It relies on the `an_element` function of the wrapped set.

### Algorithm

This method relies on the `an_element` implementation for the wrapped set.
"""
function an_element(rm::ResetMap)
return substitute(rm.resets, an_element(rm.X))
Expand All @@ -265,27 +274,32 @@ function isboundedtype(::Type{<:ResetMap{N, S}}) where {N, S}
end

"""
constraints_list(rm::ResetMap{N}) where {N}
constraints_list(rm::ResetMap)

Return the list of constraints of a polytopic reset map.
Return a list of constraints of a polyhedral reset map.

### Input

- `rm` -- reset map of a polytope
- `rm` -- reset map of a polyhedron

### Output

The list of constraints of the reset map.
A list of constraints of the reset map.

### Notes

We assume that the underlying set `X` is a polytope, i.e., is bounded and offers
a method `constraints_list(X)`.
We assume that the underlying set `rm.X` is a polyhedron, i.e., offers a method
`constraints_list(X)`.

### Algorithm

We fall back to `constraints_list` of a `LinearMap` of the `A`-matrix in the
affine-map view of a reset map.
If the set `rm.X` is hyperrectangular, we iterate through all dimensions.
For each reset we construct the corresponding (flat) constraints, and in the
other dimensions we construct the corresponding constraints of the underlying
set.

For more general sets, we fall back to `constraints_list` of a `LinearMap` of
the `A`-matrix in the affine-map view of a reset map.
Each reset dimension ``i`` is projected to zero, expressed by two constraints
for each reset dimension.
Then it remains to shift these constraints to the new value.
Expand All @@ -295,11 +309,12 @@ constraints ``x₅ ≤ 0`` and ``-x₅ ≤ 0``.
We then modify the right-hand side of these constraints to ``x₅ ≤ 4`` and
``-x₅ ≤ -4``, respectively.
"""
function constraints_list(rm::ResetMap{N}) where {N}
function constraints_list(rm::ResetMap)
constraints = constraints_list(LinearMap(matrix(rm), set(rm)))
N = eltype(rm)
for (i, c) in enumerate(constraints)
constrained_dim = find_unique_nonzero_entry(c.a)
if constrained_dim > 0 # constraint in only one dimension
if constrained_dim > 0 # constrained in only one dimension
if !haskey(rm.resets, constrained_dim)
continue # not a dimension we are interested in
end
Expand All @@ -318,29 +333,10 @@ function constraints_list(rm::ResetMap{N}) where {N}
return constraints
end

"""
constraints_list(rm::ResetMap{N, S}) where {N, S<:AbstractHyperrectangle}

Return the list of constraints of a hyperrectangular reset map.

### Input

- `rm` -- reset map of a hyperrectangular set

### Output

The list of constraints of the reset map.

### Algorithm

We iterate through all dimensions.
If there is a reset, we construct the corresponding (flat) constraints.
Otherwise, we construct the corresponding constraints of the underlying set.
"""
function constraints_list(rm::ResetMap{N, S}) where {N, S<:AbstractHyperrectangle}
H = rm.X
n = dim(H)
constraints = Vector{LinearConstraint{N, SingleEntryVector{N}}}(undef, 2*n)
constraints = Vector{HalfSpace{N, SingleEntryVector{N}}}(undef, 2*n)
j = 1
for i in 1:n
ei = SingleEntryVector(i, n, one(N))
Expand Down