简体   繁体   中英

Matrix inversion in Swift using Accelerate Framework

Following the good instructions that I found here: https://github.com/haginile/SwiftAccelerate I verified that matrix inversion works. In fact it did for the example given. But I get a EXC_BAD_ACCESS error for any other matrix (bigger than 2x2) for example the following 2D matrix (converted as a 1D array) has been tested in matlab and python successfully and it does not work

m = [0.55481645013013, -1.15522603580724, 0.962090414322894, -0.530226035807236, 0.168545207161447, -0.38627124296868, 0.93401699437494, -0.999999999999995, 0.684016994374945, -0.23176274578121, 0.123606797749979, -0.323606797749979, 0.432893622827287, -0.323606797749979, 0.123606797749979, 0.231762745781211, -0.684016994374948, 1.0, -0.934016994374947, 0.386271242968684, 0.168545207161448, -0.530226035807237, 0.962090414322895, -1.15522603580724, 0.554816450130132]

Its inverted matrix should be

inv(AA)

ans =

  Columns 1 through 3

          -262796763616197          -656991909040516          4.90007819375216
          -162417332048282          -406043330120712          14.6405748712708
         0.718958226823704          7.87760147961979          30.4010295628018
           162417332048287           406043330120730          46.1614842543337
           262796763616208           656991909040536          55.9019809318537

  Columns 4 through 5

          -656991909040528           262796763616211
          -406043330120721           162417332048287
         -4.28281034550088        -0.718958226823794
           406043330120704          -162417332048283
           656991909040497          -262796763616196

Could you please give me another way of matrix inversion in Swift? Or explain me how to fix this? I really don't understand why it does not work.

It doesn't work because the instructions that you found are not so good. Specifically, both pivots and workspace need to be Arrays, not scalar values; it was only working for two-by-two matrices by random chance.

Here's a modified version of the invert function that allocates the workspaces correctly:

func invert(matrix : [Double]) -> [Double] {
  var inMatrix = matrix
  var N = __CLPK_integer(sqrt(Double(matrix.count)))
  var pivots = [__CLPK_integer](count: Int(N), repeatedValue: 0)
  var workspace = [Double](count: Int(N), repeatedValue: 0.0)
  var error : __CLPK_integer = 0
  dgetrf_(&N, &N, &inMatrix, &N, &pivots, &error)
  dgetri_(&N, &inMatrix, &N, &pivots, &workspace, &N, &error)
  return inMatrix
}

I should also note that your 5x5 matrix is extremely ill-conditioned, so even when you can compute the "inverse" the error of that computation will be very large, and the inverse really shouldn't be used.

A Swift 4 version:

func invert(matrix : [Double]) -> [Double] {
    var inMatrix = matrix
    var N = __CLPK_integer(sqrt(Double(matrix.count)))
    var pivots = [__CLPK_integer](repeating: 0, count: Int(N))
    var workspace = [Double](repeating: 0.0, count: Int(N))
    var error : __CLPK_integer = 0

    withUnsafeMutablePointer(to: &N) {
        dgetrf_($0, $0, &inMatrix, $0, &pivots, &error)
        dgetri_($0, &inMatrix, $0, &pivots, &workspace, $0, &error)
    }
    return inMatrix
}

I have written a library for linear algebra in Swift. I call this library swix and it includes functions to invert matrices (this function is called inv ).

Example use case:

var b = ones(10)
var A = rand((10, 10))
var AI = inv(A)
var x = AI.dot(b)

Source: https://github.com/stsievert/swix

Documentation: http://scottsievert.com/swix/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM