Skip to content

Commit

Permalink
Merge pull request #134 from JuliaReach/schillic/131
Browse files Browse the repository at this point in the history
#131 - Matrix power via square decomposition, v2
  • Loading branch information
schillic authored Feb 12, 2020
2 parents b9685ca + 6811d03 commit 97e4f02
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 2 deletions.
22 changes: 20 additions & 2 deletions src/power.jl
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,12 @@ function IntervalMatrixPower(M::IntervalMatrix{T}) where {T}
return IntervalMatrixPower(M, M, 1)
end

function IntervalMatrixPower(M::IntervalMatrix{T}, k::Int) where {T}
function IntervalMatrixPower(M::IntervalMatrix{T}, k::Int;
algorithm::String="power") where {T}
@assert k >= 1 "matrix powers must be positive"
pow = IntervalMatrixPower(M, M, 1)
@inbounds for i in 1:(k-1)
increment!(pow)
increment!(pow; algorithm=algorithm)
end
return pow
end
Expand All @@ -93,6 +94,7 @@ Increment a matrix power in-place (i.e., storing the result in `pow`).
* `"multiply"` -- fast computation using `*` from the previous result
* `"power"` -- recomputation using `^`
* `"intersect"` -- combination of `"multiply"` and `"power"`
* `"sqrt"` -- decompose `k = a² + b`
### Output
Expand All @@ -113,6 +115,8 @@ function increment!(pow::IntervalMatrixPower; algorithm::String="intersect")
pow.Mᵏ = _eval_power(pow)
elseif algorithm == "intersect"
pow.Mᵏ = _eval_intersect(pow)
elseif algorithm == "sqrt"
pow.Mᵏ = _eval_sqrt(pow)
else
throw(ArgumentError("algorithm $algorithm is not available; choose " *
"from 'multiply', 'power', 'intersect'"))
Expand Down Expand Up @@ -164,6 +168,20 @@ function _eval_intersect(pow::IntervalMatrixPower)
return intersect(_eval_multiply(pow), _eval_power(pow))
end

function _eval_sqrt(pow::IntervalMatrixPower; algorithm::String="power")
# decompose k = a² + b with a, b being integers
k = pow.k
a = floor(Int, sqrt(k))
b = k - a^2

# recursively compute M^a and M^b
Mᵏ = square(get(IntervalMatrixPower(pow.M, a; algorithm=algorithm)))
if b > 0
Mᵏ *= get(IntervalMatrixPower(pow.M, b; algorithm=algorithm))
end
return Mᵏ
end

"""
base(pow::IntervalMatrixPower)
Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,5 @@ end
increment!(pow) # power of two
increment!(pow, algorithm="power")
increment!(pow, algorithm="intersect")
increment!(pow, algorithm="sqrt")
end

0 comments on commit 97e4f02

Please sign in to comment.