-
-
Notifications
You must be signed in to change notification settings - Fork 57
/
linearkoopman.jl
65 lines (46 loc) · 1.58 KB
/
linearkoopman.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
"""
LinearKoopman(K, B, Q, P, discrete)
An approximation of the Koopman operator which is linear in the states.
`K` is the array representing the operator, `B` is the (possible present) array
representing the influence of exogenous inputs on the evolution.
`Q` and `P` are matrices used for updating the operator with new measurements.
`discrete` indicates if the operator is discrete or continuous.
The Koopman operator is callable with the typical signature of `f(u,p,t)` and `f(du,u,p,t)`, respectively.
# Example
```julia
k = LinearKoopman([1.0 0; 0 0.3], [], [], [], true)
u = k([2.0; 0.5], nothing, nothing)
du = similar(u)
k(du, u, nothing, nothing)
```
"""
mutable struct LinearKoopman <: AbstractKoopmanOperator
operator::AbstractArray
input::AbstractArray
Q::AbstractArray
P::AbstractArray
discrete::Bool
end
outputmap(k::LinearKoopman) = throw(AssertionError("Linear Koopman Operator has no output map."))
function (k::LinearKoopman)(u, p, t)
return k.operator*u
end
function (k::LinearKoopman)(du, u, p, t)
mul!(du, k.operator, u)
end
"""
update!(k, X, Y; threshold = eps())
Update the Koopman `k` given new data `X` and `Y`. The operator is updated in place if
the L2 error of the prediction exceeds the `threshold`.
"""
function update!(k::LinearKoopman, X::AbstractArray, Y::AbstractArray; threshold::T = eps()) where {T <: Real}
@assert updatable(k) "Linear Koopman is not updatable."
ϵ = norm(Y-operator(k)*X, 2)
if ϵ < threshold
return
end
k.Q += Y*X'
k.P += X*X'
k.operator .= k.Q*inv(k.P)
return
end