diff --git a/src/algorithms/sylvester.jl b/src/algorithms/sylvester.jl index 4b68c039..16b53500 100644 --- a/src/algorithms/sylvester.jl +++ b/src/algorithms/sylvester.jl @@ -606,6 +606,88 @@ end +function solve_sylvester_equation( A::AbstractSparseMatrix{Float64}, + B::Matrix{Float64}, + C::AbstractSparseMatrix{Float64}, + ::Val{:doubling}; + initial_guess::AbstractMatrix{<:AbstractFloat} = zeros(0,0), + timer::TimerOutput = TimerOutput(), + verbose::Bool = false, + tol::Float64 = 1e-12) + # see doi:10.1016/j.aml.2009.01.012 + # guess_provided = true + + if length(initial_guess) == 0 + # guess_provided = false + initial_guess = zero(C) + end + + ๐€ = copy(A) + # ๐€ยน = copy(A) + ๐ = copy(B) + ๐ยน = copy(B) + # ๐‚ = length(init) == 0 ? copy(C) : copy(init) + ๐‚ = A * initial_guess * B + C - initial_guess #copy(C) + + if โ„’.norm(๐‚) / โ„’.norm(initial_guess) < tol + if verbose println("Previous solution of sylvester equation achieves relative tol of $(โ„’.norm(๐‚) / โ„’.norm(initial_guess))") end + return initial_guess, true, 0, 0.0 + end + + # โ„’.rmul!(๐‚, -1) + ๐‚ยน = similar(๐‚) + # ๐‚B = copy(C) + + max_iter = 500 + + iters = max_iter + + for i in 1:max_iter + # โ„’.mul!(๐‚B, ๐‚, ๐) + # โ„’.mul!(๐‚ยน, ๐€, ๐‚B) + # โ„’.axpy!(1, ๐‚, ๐‚ยน) + ๐‚ยน = ๐€ * ๐‚ * ๐ + ๐‚ + + # โ„’.mul!(๐€ยน,๐€,๐€) + # copy!(๐€,๐€ยน) + ๐€ = ๐€^2 + โ„’.mul!(๐ยน,๐,๐) + copy!(๐,๐ยน) + # ๐ = ๐^2 + + droptol!(๐€, eps()) + # droptol!(๐, eps()) + + if i % 2 == 0 + normdiff = โ„’.norm(๐‚ยน - ๐‚) + if !isfinite(normdiff) || normdiff / max(โ„’.norm(๐‚), โ„’.norm(๐‚ยน)) < tol + # if isapprox(๐‚ยน, ๐‚, rtol = tol) + iters = i + break + end + end + + # copy!(๐‚,๐‚ยน) + ๐‚ = ๐‚ยน + end + + # โ„’.mul!(๐‚B, ๐‚, ๐) + # โ„’.mul!(๐‚ยน, ๐€, ๐‚B) + # โ„’.axpy!(1, ๐‚, ๐‚ยน) + # ๐‚ยน = ๐€ * ๐‚ * ๐ + ๐‚ + + # denom = max(โ„’.norm(๐‚), โ„’.norm(๐‚ยน)) + + # reached_tol = denom == 0 ? 0.0 : โ„’.norm(๐‚ยน - ๐‚) / denom + + ๐‚ += initial_guess + + reached_tol = โ„’.norm(A * ๐‚ * B + C - ๐‚) / โ„’.norm(๐‚) + + return ๐‚, reached_tol < tol, iters, reached_tol # return info on convergence +end + + function solve_sylvester_equation( A::Matrix{Float64}, B::AbstractSparseMatrix{Float64}, C::AbstractSparseMatrix{Float64},