如何使用代码在R或Python中求解矩阵方程PAP^T=I

2024-06-26 00:20:22 发布

您现在位置:Python中文网/ 问答频道 /正文

x=matrix(c(rnorm(10,1,3), rnorm(10,7,2), rnorm(10,15,4)), byrow=FALSE, nrow=10)
xc=x
for (k in 1:3) {
  xc[,k]=xc[,k]-mean(xc[,k])
}
A=var(xc)

出去

> A
          [,1]      [,2]      [,3]
[1,] 10.166746 -2.619763 -6.717475
[2,] -2.619763  3.291888  3.052898
[3,] -6.717475  3.052898 22.313351

我想解PAP^T=I,其中p是3x3,p^T是p的转置,I是3x3单位矩阵。解算(A)解出PA=I,但我想要PAP^T=I。我找不到答案,将矩阵相乘将花费太长时间。有人知道如何在R或Python中实现这一点吗?我也不想使用P也可以是^(-1/2)的事实。通过代码的解决方案会很好

library(stringr)
A=matrix(c(letters[1:4], letters[6:8], letters[10:11]), nrow=3)
mult=function(A, B) {
  AB=matrix(nrow=3, ncol=3)
  for (r in 1:3) {
    for (c in 1:3) {
      AB[r,c]=str_c("(", A[r,1], ")*(", B[1,c], ")+(", A[r,2], ")*(", B[2,c], ")+(", A[r,3], ")*(", B[3,c], ")")
    }
  }
  return(AB)
}
AB=mult(A,B)
ABAT=mult(AB, t(A))

seteq=function(A, B) {
  E=matrix(nrow=3, ncol=3)
  for (r in 1:3) {
    for (c in 1:3) {
      E[r,c]=str_c(A[r,c], "=", B[r, c])
    }
  }
  dim(E)=c(9,1)
  return(E[,1])
}
Eq=seteq(ABAT, diag(rep(1, 3)))
res=""
for (i in 1:9) {
  res=str_c(res, Eq[i])
  if (i!=9) res=str_c(res, ",")
}
res

给我方程式

((a)*(18.9052758456522)+(d)*(0.834836569187845)+(h)*(9.76575358263375))*(a)+((a)*(0.834836569187845)+(d)*(0.555656932954595)+(h)*(1.03585433030833))*(d)+((a)*(9.76575358263375)+(d)*(1.03585433030833)+(h)*(6.84209765783974))*(h)=1,((b)*(18.9052758456522)+(f)*(0.834836569187845)+(j)*(9.76575358263375))*(a)+((b)*(0.834836569187845)+(f)*(0.555656932954595)+(j)*(1.03585433030833))*(d)+((b)*(9.76575358263375)+(f)*(1.03585433030833)+(j)*(6.84209765783974))*(h)=0,((c)*(18.9052758456522)+(g)*(0.834836569187845)+(k)*(9.76575358263375))*(a)+((c)*(0.834836569187845)+(g)*(0.555656932954595)+(k)*(1.03585433030833))*(d)+((c)*(9.76575358263375)+(g)*(1.03585433030833)+(k)*(6.84209765783974))*(h)=0,((a)*(18.9052758456522)+(d)*(0.834836569187845)+(h)*(9.76575358263375))*(b)+((a)*(0.834836569187845)+(d)*(0.555656932954595)+(h)*(1.03585433030833))*(f)+((a)*(9.76575358263375)+(d)*(1.03585433030833)+(h)*(6.84209765783974))*(j)=0,((b)*(18.9052758456522)+(f)*(0.834836569187845)+(j)*(9.76575358263375))*(b)+((b)*(0.834836569187845)+(f)*(0.555656932954595)+(j)*(1.03585433030833))*(f)+((b)*(9.76575358263375)+(f)*(1.03585433030833)+(j)*(6.84209765783974))*(j)=1,((c)*(18.9052758456522)+(g)*(0.834836569187845)+(k)*(9.76575358263375))*(b)+((c)*(0.834836569187845)+(g)*(0.555656932954595)+(k)*(1.03585433030833))*(f)+((c)*(9.76575358263375)+(g)*(1.03585433030833)+(k)*(6.84209765783974))*(j)=0,((a)*(18.9052758456522)+(d)*(0.834836569187845)+(h)*(9.76575358263375))*(c)+((a)*(0.834836569187845)+(d)*(0.555656932954595)+(h)*(1.03585433030833))*(g)+((a)*(9.76575358263375)+(d)*(1.03585433030833)+(h)*(6.84209765783974))*(k)=0,((b)*(18.9052758456522)+(f)*(0.834836569187845)+(j)*(9.76575358263375))*(c)+((b)*(0.834836569187845)+(f)*(0.555656932954595)+(j)*(1.03585433030833))*(g)+((b)*(9.76575358263375)+(f)*(1.03585433030833)+(j)*(6.84209765783974))*(k)=0,((c)*(18.9052758456522)+(g)*(0.834836569187845)+(k)*(9.76575358263375))*(c)+((c)*(0.834836569187845)+(g)*(0.555656932954595)+(k)*(1.03585433030833))*(g)+((c)*(9.76575358263375)+(g)*(1.03585433030833)+(k)*(6.84209765783974))*(k)=1

但是Wolfram Alpha没有识别出这个输入


Tags: inforreturnabfunctionresmatrixpap
2条回答

正如你所注意到的,如果你用代数“平方根”分解A

A = L * L^T

那么问题就变成了:

(P*L) * (P*L)^T = Id

这意味着P*L是酉矩阵https://en.wikipedia.org/wiki/Unitary_matrix

因此,该解由任何酉矩阵U(U * U^T=Id)形成

P=inv(L)*U

有无限多的解决方案

您明确地声明不希望使用U=Id的平凡解决方案P=inv(L),但您没有说明原因,并且您没有提供关于p

请注意,@G.Grothendieck的好答案中的第一个解决方案就是:用特征向量V以对角形式D(特征值)减少A

inv(V)*A*V = D
D = sqrt(D)*sqrt(D)
P = inv(sqrt(D))*V

由于对这一点存在一些混淆,为了澄清问题,需要在注释末尾输入A的情况下找到p

1)本征值假设A是对称正定矩阵,在问题中它是:

P <- with(eigen(A), diag(1/sqrt(values)) %*% t(vectors))

# check
P %*% A %*% t(P)
## [1,]  1.000000e+00 -6.661338e-16 2.775558e-17
## [2,] -6.661338e-16  1.000000e+00 3.469447e-16
## [3,]  2.775558e-17  1.994932e-16 1.000000e+00

2)optim另一种方法是数值求解这6个方程。请注意,参数化将P约束为对称,从而将参数数量减少到6。一个完整的3x3=9参数可能会导致数值问题,因为如注释中所述,如果P是一个解,那么HP对于任何正交H都太过重要

# input is upper triangle of P incl diagonal and output is P
p2P <- function(p) {
   P <- diag(3)
   P[upper.tri(P, diag = TRUE)] <- p
   P + t(P) - diag(diag(P))
}

# sum of squares of difference between PAP' and diag(3)
f <- function(p) {
   P <- p2P(p)
   sum(c(P %*% A %*% t(P) - diag(3))^2)
}

res <- optim(1:6, f, method = "BFGS")
str(res)
## List of 5
##  $ par        : num [1:6] -0.2605 0.2573 0.5745 -0.0776 -0.027 ...
##  $ value      : num 4.69e-10
##  $ counts     : Named int [1:2] 167 49
##   ..- attr(*, "names")= chr [1:2] "function" "gradient"
##  $ convergence: int 0
##  $ message    : NULL

# check that PAP' is diag(3)
P <- p2P(res$par)
P %*% A %*% t(P)
##               [,1]          [,2]         [,3]
## [1,]  9.999948e-01 -8.654260e-08 8.333054e-06
## [2,] -8.654260e-08  9.999955e-01 3.266114e-07
## [3,]  8.333054e-06  3.266114e-07 9.999832e-01

3)nls我们可以交替使用nls来解方程。我们从上面使用p2P,但不需要f。请注意,P也是对称的

result2 <- nls(c(diag(3)) ~ c(p2P(p) %*% A %*% t(p2P(p))), 
  start = list(p = 1:6), algorithm = "port")
result2
## Nonlinear regression model
##   model: c(diag(3)) ~ c(p2P(p) %*% A %*% t(p2P(p)))
##    data: parent.frame()
##       p1       p2       p3       p4       p5       p6 
##  0.26049 -0.25733 -0.57448  0.07757  0.02702  0.22665 
##  residual sum-of-squares: 1.354e-22
##
## Algorithm "port", convergence message: absolute function convergence (6)

# check that PAP' equals diag(3)
P <- p2P(coef(result2))
P %*% A %*% t(P)
##              [,1]          [,2]          [,3]
## [1,] 1.000000e+00  7.954436e-13  5.084821e-14
## [2,] 7.954401e-13  1.000000e+00 -1.869643e-12
## [3,] 5.073719e-14 -1.869574e-12  1.000000e+00

4)nls-2这也使用nls,但使用不同的p参数化,即对角矩阵(3个参数)乘以斜对称矩阵(3个参数)的指数。请注意,斜对称矩阵的指数是正交的,因此参数化将P约束为对角乘以正交

library(expm)

p2P4 <- function(p) {
  X <- matrix(0, 3, 3)
  X[upper.tri(X)] <- p[1:3]
  diag(p[4:6]) %*% expm(X - t(X)) 
}

res4 <- nls(c(diag(3)) ~ c(p2P4(p) %*% A %*% t(p2P4(p))), start = list(p = 1:6),
  algorithm = "port")
res4
## Nonlinear regression model
##   model: c(diag(3)) ~ c(p2P4(p) %*% A %*% t(p2P4(p)))
##    data: parent.frame()
##     p1     p2     p3     p4     p5     p6 
## 3.3142 1.9743 1.6253 0.6500 0.1963 0.3663 
##  residual sum-of-squares: 2.863e-30
##
## Algorithm "port", convergence message: X-convergence (3)

# check that PAP' equals diag(3)
P <- p2P4(coef(res4))
P %*% A %*% t(P)
##               [,1]          [,2]          [,3]
## [1,]  1.000000e+00  9.367507e-16 -2.827599e-16
## [2,]  9.159340e-16  1.000000e+00 -6.661338e-16
## [3,] -2.289835e-16 -6.106227e-16  1.000000e+00

我们将其用于:

Lines <- "
10.166746 -2.619763 -6.717475
-2.619763  3.291888  3.052898
-6.717475  3.052898 22.313351"
A <- as.matrix(read.table(text = Lines))

相关问题 更多 >