Implementing the Bartels–Stewart algorithm in Eigen3 — real matrices only?

核能气质少年 提交于 2020-05-31 04:41:06

问题


Based off this question and solution -- Implementing the Bartels–Stewart algorithm in Eigen3? -- I am trying to solve Lyapunov equations (AX + XA^T = C) using the Eigen library, but am limited to real matrices.

The R (with c++) code below works, but involves complex numbers. It can definitely be simplified (since in this framing, there is no B matrix), but the main difficulty is the reliance on complex numbers. The real schur form seems to be the standard alternative in this case, but the Eigen function matrix_function_solve_triangular_sylvester then does not work because the input matrix is not upper triangular, but is upper block triangular. I would be happy to see suggestions to a) remove the need for complex numbers, and then if that is possible, b) any efficiency improvements.

library(expm)
library(Rcpp)
library(RcppEigen)
library(inline)
# R -----------------------------------------------------------------------
d<-6 #dimensions 
A<-matrix(rnorm(d^2),d,d) #continuous time transition
G <- matrix(rnorm(d^2),d,d)
C<-G %*% t(G) #continuous time pos def error
AHATCH<-A %x% diag(d) + diag(d) %x% A
Xtrue<-matrix(-solve(AHATCH,c(C)), d) #asymptotic error from continuous time


# c++ in R ---------------------------------------------------------------------

sylcpp <- '

    using Eigen::Map;
    using Eigen::MatrixXd;

  // Map the double matrix A from Ar
   const Map<MatrixXd> A(as<Map<MatrixXd> >(Ar));

   // Map the double matrix Q from Qr
   const Map<MatrixXd> Q(as<Map<MatrixXd> >(Qr));


  Eigen::MatrixXd B = A.transpose();

  Eigen::ComplexSchur<Eigen::MatrixXd> SchurA(A);
  Eigen::MatrixXcd R = SchurA.matrixT();
  Eigen::MatrixXcd U = SchurA.matrixU();

  Eigen::ComplexSchur<Eigen::MatrixXd> SchurB(B);
  Eigen::MatrixXcd S = SchurB.matrixT();
  Eigen::MatrixXcd V = SchurB.matrixU();

  Eigen::MatrixXcd F = (U.adjoint() * Q) * V;

  Eigen::MatrixXcd Y = Eigen::internal::matrix_function_solve_triangular_sylvester(R, S, F);

  Eigen::MatrixXd X = ((U * Y) * V.adjoint()).real();

  return wrap(X);
'



syl <- cxxfunction(signature(Ar = "matrix",Qr='matrix'), sylcpp, plugin = "RcppEigen")

X=syl(A,-C)
X-Xtrue #approx zero

来源:https://stackoverflow.com/questions/62021064/implementing-the-bartels-stewart-algorithm-in-eigen3-real-matrices-only

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!