在R中处理符号矩阵,就像在Matlab中一样。

3

我在使用rSymPy和Ryacas处理符号矩阵时遇到了问题。在Matlab中这很容易。 我正在寻找如何在R中实现类似Matlab的结果的建议。在Matlab中,我需要使用“符号工具箱”。

在这个例子中,我希望生成一个符号转移概率矩阵“P”,该矩阵为5 x 5,其中包含元素P11、P12、...、P55。然后,我想将这个矩阵用于矩阵乘法(与它本身和其他矩阵相乘),并可能执行其他操作。

(1) Matlab - 生成符号矩阵 -> OK

P = sym('P%d%d', [5 5])

(1) R - 获得符号矩阵 -> 完成

library(rSymPy)
P<-matrix(nrow=5, ncol=5)
for (i in 1:5){
  for (j in 1:5) {
P[i,j]<-paste0(Sym("P"), i, j) # tried Var("P") also
  }
}

我想要将这些矩阵相乘。

(2) Matlab - 乘法符号矩阵 -> 成功

P*P 

运行良好。

(2) R - 乘法符号矩阵 -> 问题

sympy("P * P")
Need Help Here!

无法工作。许多其他尝试也没有成功。我需要关于如何正确执行此操作并获得与Matlab(例如(2))相同的输出的建议。

附加任务:

(3)Matlab-将每个元素分别sym() -> OK

此外,我想要一个建议,如何在R中将矩阵P的单个元素Sym(),就像在Matlab中一样。

for i = 1:5;
    for j = 1:5;
    P = sprintf('P%d%d',i,j); 
    assignin('caller',P,sym(P));
    end;
end;

(3) R - Sym() 分别作用于每个元素 -> 问题

Need Help Here!

感谢各位的建议!

2
这个可以运行:library(Ryacas); yacas("P := {{p11, p12}, {p21, p22}}"); yacas("PrettyForm(P*P)") - G. Grothendieck
我建议从sympy文档这里开始,并尝试在rSymPy中进行包装... - Ben Bolker
2个回答

2
最近我做了这件事,最终编写了一个将R矩阵转换为Python所需格式的函数(请参见https://cran.r-project.org/web/packages/rSymPy/rSymPy.pdf第3页示例中给出的2x2矩阵)。首先,我们定义在R中的矩阵P
library(rSymPy)

P<-matrix(nrow=5, ncol=5)
for (i in 1:5){
  for (j in 1:5) {
    P[i,j] = Var(paste0("P", i, j)) # Declare variable in matrix first
  }
}

我刚刚使用了您的代码,并进行了轻微的调整。具体来说,针对矩阵P的每个元素,通过执行Var(paste0("P", i, j))创建一个SymPy变量以表示该元素。例如,当i = j = 1时,我们将创建Sympy变量P11Var的输出是字符串"P11",我们将其存储在P[1,1]中。
此时,我们已经定义了一个R矩阵P,其中P由以下内容给出:
     [,1]  [,2]  [,3]  [,4]  [,5] 
[1,] "P11" "P12" "P13" "P14" "P15"
[2,] "P21" "P22" "P23" "P24" "P25"
[3,] "P31" "P32" "P33" "P34" "P35"
[4,] "P41" "P42" "P43" "P44" "P45"
[5,] "P51" "P52" "P53" "P54" "P55"

我们已经为每个 P 元素创建了一个 SymPy 变量,但我们尚未定义符号矩阵。这是我们接下来要做的步骤。
我们定义函数将 R 矩阵转换为 Python 格式:
# Converts matrix in R to Python's format
mat2py <- function(x){
  str = lapply(1:nrow(x), function(i) paste0(x[i,], collapse = ", "))
  str = paste0("Matrix([", paste0("[", unlist(str), "]", collapse = ", "), "])")
  return (str)
}

您可以按照以下方式使用上述函数来定义符号矩阵P:
cat(sympy(paste0("P = ", mat2py(P))), "\n")

# [P11, P12, P13, P14, P15]
# [P21, P22, P23, P24, P25]
# [P31, P32, P33, P34, P35]
# [P41, P42, P43, P44, P45]
# [P51, P52, P53, P54, P55]

我只是在R中使用cat(..., "\n")来漂亮地打印矩阵。

最后,按以下方式计算P*P

cat(sympy("P*P"), "\n")

感谢您的回答,原则上输出是我想要看到的。但是,我需要实际存储和使用输出。例如,我想访问您最终表达式中计算出的每个元素,使用P[1,1]或类似的方式...这在您的解决方案中似乎很困难。 - Madam Smith
如果您需要之后访问元素,可以使用cat(sympy("B = P*P"), "\n")来定义一些矩阵B,然后只需将元素访问为sympy("B[0,0]")。不过@J_F的答案看起来更简单。 - jav

2

这也适用于rSymPy

library(rSymPy)

a1 <- Var("a1")
a2 <- Var("a2")
a3 <- Var("a3")
a4 <- Var("a4")

A <- Matrix(List(a1, a2), List(a3, a4))

A*A
#[1] "[a2*a3 + a1**2, a1*a2 + a2*a4]\n[a1*a3 + a3*a4, a2*a3 + a4**2]"

谢谢,我之前看过这个例子。但是,对我来说难点在于将所有变量分别sym()或var()。假设你要为1000个变量这样做。那意味着要输入:a1 <- Var("a1") ..... a1000<-Var("a1000")。你会疯掉的。我认为找到一种循环或其他方式来解决这个问题是关键。 - Madam Smith
那么做起来...应该没有问题。 - J_F

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接