等宽矩阵(a)相乘a %*% x = b的逆运算solve(a,b)=x

简介:
solve用来逆运算矩阵相乘.
例如
a %*% x = b的逆运算, solve(a,b) = x
这里必须注意, a必须是等宽矩阵, 如果不等宽, 会报错.  例如 : 
> a <- matrix(1:12,2,6)
> x <- matrix(1:12,6,2)
> a
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    3    5    7    9   11
[2,]    2    4    6    8   10   12
> x
     [,1] [,2]
[1,]    1    7
[2,]    2    8
[3,]    3    9
[4,]    4   10
[5,]    5   11
[6,]    6   12
> b <- a %*% x
> b
     [,1] [,2]
[1,]  161  377
[2,]  182  434
> solve(a,b)
Error in solve.default(a, b) : 'a' (2 x 6) must be square

除此之外, 还有可能因为其他报错, 但实际上是可以逆向解的.  (可能是我对可逆的理解有问题, 以后再来处理这个问题)
错误代码见
src/modules/lapack/Lapack.c

   F77_CALL(dgesv)(&n, &p, avals, &n, ipiv, REAL(B), &n, &info);
    if (info < 0)
        error(_("argument %d of Lapack routine %s had invalid value"),
              -info, "dgesv");
    if (info > 0)
        error(_("Lapack routine %s: system is exactly singular: U[%d,%d] = 0"),
              "dgesv", info, info);

错误举例 : 
> a <- matrix(1:16,4,4)
> solve(a, a %*% a)
Error in solve.default(a, a %*% a) : 
  Lapack routine dgesv: system is exactly singular: U[3,3] = 0

理论上这个值应该是等于a的, 但是报错了.

好了接下来看几个可以计算的例子 : 

> a <- matrix(1:4,2,2)
> a
     [,1] [,2]
[1,]    1    3
[2,]    2    4
> solve(a)   # solve(a) , 不给b的话, 其实b 默认就是和a维度一致并且对角线为1的矩阵.
     [,1] [,2]
[1,]   -2  1.5
[2,]    1 -0.5
> solve(a, diag(1,2,2))   # 可以看到
     [,1] [,2]
[1,]   -2  1.5
[2,]    1 -0.5
> diag(1,2,2)
     [,1] [,2]
[1,]    1    0
[2,]    0    1
> a %*% solve(a)   #  因为solve(a,b) = x, a %*% x = b, 所以 a %*% solve(a) = b = diag(1,2,2)
     [,1] [,2]
[1,]    1    0
[2,]    0    1


b还可以是向量, 向量会自动转成矩阵, 例如
> solve(a, c(2,3))
[1] 0.5 0.5
> a %*% solve(a, c(2,3))
     [,1]
[1,]    2
[2,]    3


[参考]
1. help("solve")

solve                   package:base                   R Documentation

Solve a System of Equations

Description:

     This generic function solves the equation ‘a %*% x = b’ for ‘x’,
     where ‘b’ can be either a vector or a matrix.

Usage:

     solve(a, b, ...)
     
     ## Default S3 method:
     solve(a, b, tol, LINPACK = FALSE, ...)
     
Arguments:

       a: a square numeric or complex matrix containing the
          coefficients of the linear system.  Logical matrices are
          coerced to numeric.

       b: a numeric or complex vector or matrix giving the right-hand
          side(s) of the linear system.  If missing, ‘b’ is taken to be
          an identity matrix and ‘solve’ will return the inverse of
          ‘a’.

     tol: the tolerance for detecting linear dependencies in the
          columns of ‘a’.  The default is ‘.Machine$double.eps’. Not
          currently used with complex matrices ‘a’.

 LINPACK: logical.  Defunct and ignored.

     ...: further arguments passed to or from other methods


2. 
src/modules/lapack/Lapack.c

/* Real case of solve.default */
static SEXP La_solve(SEXP A, SEXP Bin, SEXP tolin)
{
    int n, p;
    double *avals, anorm, rcond, tol = asReal(tolin), *work;
    SEXP B, Adn, Bdn;

    if (!(isMatrix(A) && 
          (TYPEOF(A) == REALSXP || TYPEOF(A) == INTSXP || TYPEOF(A) == LGLSXP)))
        error(_("'a' must be a numeric matrix"));
    int *Adims = INTEGER(coerceVector(getAttrib(A, R_DimSymbol), INTSXP));
    n = Adims[0];
    if(n == 0) error(_("'a' is 0-diml"));
    int n2 = Adims[1];
    if(n2 != n) error(_("'a' (%d x %d) must be square"), n, n2);
    Adn = getAttrib(A, R_DimNamesSymbol);

    if (isMatrix(Bin)) {
        int *Bdims = INTEGER(coerceVector(getAttrib(Bin, R_DimSymbol), INTSXP));
        p = Bdims[1];
        if(p == 0) error(_("no right-hand side in 'b'"));
        int p2 = Bdims[0];
        if(p2 != n)
            error(_("'b' (%d x %d) must be compatible with 'a' (%d x %d)"),
                  p2, p, n, n);
        PROTECT(B = allocMatrix(REALSXP, n, p));
        SEXP Bindn =  getAttrib(Bin, R_DimNamesSymbol);
        // This is somewhat odd, but Matrix relies on dropping NULL dimnames
        if (!isNull(Adn) || !isNull(Bindn)) {
            // rownames(ans) = colnames(A), colnames(ans) = colnames(Bin)
            Bdn = allocVector(VECSXP, 2);
            if (!isNull(Adn)) SET_VECTOR_ELT(Bdn, 0, VECTOR_ELT(Adn, 1));
            if (!isNull(Bindn)) SET_VECTOR_ELT(Bdn, 1, VECTOR_ELT(Bindn, 1));
            if (!isNull(VECTOR_ELT(Bdn, 0)) || !isNull(VECTOR_ELT(Bdn, 1)))
                setAttrib(B, R_DimNamesSymbol, Bdn);
        }
    } else {
        p = 1;
        if(length(Bin) != n)
            error(_("'b' (%d x %d) must be compatible with 'a' (%d x %d)"),
                  length(Bin), p, n, n);        
        PROTECT(B = allocVector(REALSXP, n));
        if (!isNull(Adn)) setAttrib(B, R_NamesSymbol, VECTOR_ELT(Adn, 1));
    }
    PROTECT(Bin = coerceVector(Bin, REALSXP));
    Memcpy(REAL(B), REAL(Bin), (size_t)n * p);
    
    int *ipiv = (int *) R_alloc(n, sizeof(int));

    /* work on a copy of A */
    if (!isReal(A)) {
        A = coerceVector(A, REALSXP);
        avals = REAL(A);
    } else {
        avals = (double *) R_alloc((size_t)n * n, sizeof(double));
        Memcpy(avals, REAL(A), (size_t)n * n);
    }
    PROTECT(A);
    int info;
    F77_CALL(dgesv)(&n, &p, avals, &n, ipiv, REAL(B), &n, &info);
    if (info < 0)
        error(_("argument %d of Lapack routine %s had invalid value"),
              -info, "dgesv");
    if (info > 0)
        error(_("Lapack routine %s: system is exactly singular: U[%d,%d] = 0"),
              "dgesv", info, info);
    if(tol > 0) {
        char one[2] = "1";
        anorm = F77_CALL(dlange)(one, &n, &n, REAL(A), &n, (double*) NULL);
        work = (double *) R_alloc(4*(size_t)n, sizeof(double));
        F77_CALL(dgecon)(one, &n, avals, &n, &anorm, &rcond, work, ipiv, &info);
        if (rcond < tol)
            error(_("system is computationally singular: reciprocal condition number = %g"),
                  rcond);
    }
    UNPROTECT(3); /* B, Bin, A */
    return B;
}

相关文章
|
17天前
|
人工智能 小程序 BI
矩阵的转置、加和乘法写入C++
矩阵的转置、加和乘法写入C++
14 0
|
24天前
L1-048 矩阵A乘以B
L1-048 矩阵A乘以B
22 0
|
25天前
|
索引
转置矩阵-暴力解法&一行代码
转置矩阵-暴力解法&一行代码
12 0
|
6月前
对角矩阵(Diagonal Matrix)
对角矩阵(Diagonal Matrix)是一种特殊的矩阵,其元素仅位于主对角线上。对角矩阵通常用于线性代数和微积分等数学领域,它有以下几个特点:
252 7
|
12月前
7-93 矩阵A乘以B
7-93 矩阵A乘以B
99 0
|
12月前
矩阵相加 / 矩阵相乘(详解版)
矩阵相加 / 矩阵相乘(详解版)
131 0
(二维vector)(绝对值求和等式的处理)B. Playing in a Casino
(二维vector)(绝对值求和等式的处理)B. Playing in a Casino
58 0
|
C语言 UED
[解题报告]【第33题】给定一个 n X n 的矩阵,求它的转置矩阵
[解题报告]【第33题】给定一个 n X n 的矩阵,求它的转置矩阵