2014-11-07 6 views
3

Следуя хорошим инструкциям, которые я нашел здесь: https://github.com/haginile/SwiftAccelerate Я проверил, что инверсия матрицы работает. Фактически это было сделано для приведенного примера. Но я получаю ошибку EXC_BAD_ACCESS для любой другой матрицы (больше, чем 2х2), например, следующие 2D матрицы (конвертируются как 1D массив) был протестирован в MATLAB и питона успешно и он не работаетМатричная инверсия в Swift с использованием ускорительной структуры

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] 

Сво инвертированная матрица должна быть

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 

Не могли бы вы дать мне другой способ инверсии матрицы в Swift? Или объясните мне, как это исправить? Я действительно не понимаю, почему это не работает.

ответ

8

Это не работает, потому что инструкции, которые вы нашли, не так хороши. В частности, как опорные точки, так и рабочее пространство должны быть массивами, а не скалярными значениями; он работал только для двух-двух матриц случайным образом.

Вот модифицированная версия функции invert, который выделяет рабочие пространства правильно:

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 
} 

Я хотел бы также отметить, что ваша 5x5 матрица очень плохо обусловленной, так что даже если вы можете вычислить «обратный» ошибка в этом вычислении будет очень большой, и обратный действительно не должен использоваться.

версия Swift 4:

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 
} 
+0

Genius! Спасибо огромное! Моя матрица плохо кондиционирована, так как она мала 5х5. Я буду делать другие тесты, но для моих вычислений мне нужно использовать матрицы по крайней мере 21x21. – Nicholas

+0

Ошибка Xcode 9: «Одновременный доступ к var 'N», но для изменения требуется эксклюзивный доступ; рассмотрите возможность копирования в локальную переменную'. Является ли это ошибкой Xcode 9 или мы должны писать вещи по-другому – Guig

+1

@Guig: это следствие https://github.com/apple/swift-evolution/blob/master/proposals/0176-enforce-exclusive-access-to- memory.md, хотя не очевидно, что он предназначен для применения к небезопасным API-интерфейсам типа C, например LAPACK. Вы можете обойти это, просто сделав пару копий 'N'. –

1

Я написал библиотеку для линейной алгебры в Swift. Я называю эту библиотеку swix и включает функции инвертирования матриц (эта функция называется inv).

Пример использования:

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

Источник: https://github.com/stsievert/swix

Документация: http://scottsievert.com/swix/

+0

Где я могу получить эту библиотеку? – Nicholas

+0

О, черт возьми, я добавил ссылки для источника и документации – Scott

+0

гений!Ссылка для сравнения между Swift и Matlab/Python не работает на github, вы можете отремонтировать? Я скоро попробую вашу библиотеку для своих целей. – Nicholas