2016-06-15 41 views
5

Devo riscrivere il codice da Python a Swift ma sono bloccato su una funzione che dovrebbe restituire la soluzione dei minimi quadrati a un'equazione a matrice lineare. Qualcuno di voi conosce una libreria scritta in Swift che ha un metodo equivalente allo numpy.linalg.lstsq? Ti sarei grato per il tuo aiuto. codiceFunzione che restituisce la soluzione dei minimi quadrati a un'equazione a matrice lineare

Python:

a = numpy.array([[p2.x-p1.x,p2.y-p1.y],[p4.x-p3.x,p4.y-p3.y],[p4.x-p2.x,p4.y-p2.y],[p3.x-p1.x,p3.y-p1.y]]) 
b = numpy.array([number1,number2,number3,number4]) 
res = numpy.linalg.lstsq(a,b) 
result = [float(res[0][0]),float(res[0][1])] 
return result 

codice Swift finora:

var matrix1 = [[p2.x-p1.x, p2.y-p1.y],[p4.x-p3.x, p4.y-p3.y], [p4.x-p2.x, p4.y-p2.y], [p3.x-p1.x, p3.y-p1.y]] 
var matrix2 = [number1, number2, number3, number4] 
+0

Aggiungere il codice qui! Non posso aiutare senza codice. – Dershowitz123

+1

Il [Accelerate framework] (https://developer.apple.com/library/ios/documentation/Accelerate/Reference/AccelerateFWRef /) include la [libreria BLAS] (http://www.netlib.org/blas/faq.html) che ha funzioni per [Problemi di minimi quadrati lineari] (http : //www.netlib.org/lapack/lug/node27.html). L'uso di queste funzioni da Swift richiede comunque un po 'di lavoro :) –

+0

Sfortunatamente, non esiste un metodo che risolva i problemi di LLS. – wtznc

risposta

3

la distanza di accelerazione quadro incluso il pacchetto algebra lineare LAPACK, che ha una funzione DGELS per risolvere sistemi lineari sotto- o sovradeterminati . Dalla documentazione:

DGELS risolve sistemi reali lineari sovradeterminati o sottodeterminati comportano un M-per-N matrice A, o sua trasposta, utilizzando un QR o LQ fattorizzazione di A. Si assume che A ha pieno rango.

Ecco un esempio di come tale funzione può essere utilizzata da Swift. È essenzialmente una traduzione di this C sample code.

func solveLeastSquare(A A: [[Double]], B: [Double]) -> [Double]? { 
    precondition(A.count == B.count, "Non-matching dimensions") 

    var mode = Int8(bitPattern: UInt8(ascii: "N")) // "Normal" mode 
    var nrows = CInt(A.count) 
    var ncols = CInt(A[0].count) 
    var nrhs = CInt(1) 
    var ldb = max(nrows, ncols) 

    // Flattened columns of matrix A 
    var localA = (0 ..< nrows * ncols).map { 
     A[Int($0 % nrows)][Int($0/nrows)] 
    } 

    // Vector B, expanded by zeros if ncols > nrows 
    var localB = B 
    if ldb > nrows { 
     localB.appendContentsOf([Double](count: ldb - nrows, repeatedValue: 0.0)) 
    } 

    var wkopt = 0.0 
    var lwork: CInt = -1 
    var info: CInt = 0 

    // First call to determine optimal workspace size 
    dgels_(&mode, &nrows, &ncols, &nrhs, &localA, &nrows, &localB, &ldb, &wkopt, &lwork, &info) 
    lwork = Int32(wkopt) 

    // Allocate workspace and do actual calculation 
    var work = [Double](count: Int(lwork), repeatedValue: 0.0) 
    dgels_(&mode, &nrows, &ncols, &nrhs, &localA, &nrows, &localB, &ldb, &work, &lwork, &info) 

    if info != 0 { 
     print("A does not have full rank; the least squares solution could not be computed.") 
     return nil 
    } 
    return Array(localB.prefix(Int(ncols))) 
} 

Alcune note:

  • dgels_() modifica i dati di matrice e vettoriali passati, e aspetta la matrice come matrice "flat" contenente le colonne di A. Anche il lato destro è previsto come array con lunghezza max(M, N). Per questo motivo, i dati di input vengono prima copiati in variabili locali.
  • Tutti gli argomenti devono essere passati con riferimento a dgels_(), ecco perché sono tutti memorizzati in var s.
  • Un numero intero C è un numero intero a 32 bit, che rende necessarie alcune conversioni tra Int e CInt.

Esempio 1: sistema sovradeterminato, da http://www.seas.ucla.edu/~vandenbe/103/lectures/ls.pdf.

let A = [[ 2.0, 0.0 ], 
     [ -1.0, 1.0 ], 
     [ 0.0, 2.0 ]] 
let B = [ 1.0, 0.0, -1.0 ] 
if let x = solveLeastSquare(A: A, B: B) { 
    print(x) // [0.33333333333333326, -0.33333333333333343] 
} 

Esempio 2: sistema sottodeterminato, norma minima soluzione x_1 + x_2 + x_3 = 1.0.

let A = [[ 1.0, 1.0, 1.0 ]] 
let B = [ 1.0 ] 
if let x = solveLeastSquare(A: A, B: B) { 
    print(x) // [0.33333333333333337, 0.33333333333333337, 0.33333333333333337] 
} 

Aggiornamento per Swift 3 e Swift 4:

func solveLeastSquare(A: [[Double]], B: [Double]) -> [Double]? { 
    precondition(A.count == B.count, "Non-matching dimensions") 

    var mode = Int8(bitPattern: UInt8(ascii: "N")) // "Normal" mode 
    var nrows = CInt(A.count) 
    var ncols = CInt(A[0].count) 
    var nrhs = CInt(1) 
    var ldb = max(nrows, ncols) 

    // Flattened columns of matrix A 
    var localA = (0 ..< nrows * ncols).map { (i) -> Double in 
     A[Int(i % nrows)][Int(i/nrows)] 
    } 

    // Vector B, expanded by zeros if ncols > nrows 
    var localB = B 
    if ldb > nrows { 
     localB.append(contentsOf: [Double](repeating: 0.0, count: Int(ldb - nrows))) 
    } 

    var wkopt = 0.0 
    var lwork: CInt = -1 
    var info: CInt = 0 

    // First call to determine optimal workspace size 
    var nrows_copy = nrows // Workaround for SE-0176 
    dgels_(&mode, &nrows, &ncols, &nrhs, &localA, &nrows_copy, &localB, &ldb, &wkopt, &lwork, &info) 
    lwork = Int32(wkopt) 

    // Allocate workspace and do actual calculation 
    var work = [Double](repeating: 0.0, count: Int(lwork)) 
    dgels_(&mode, &nrows, &ncols, &nrhs, &localA, &nrows_copy, &localB, &ldb, &work, &lwork, &info) 

    if info != 0 { 
     print("A does not have full rank; the least squares solution could not be computed.") 
     return nil 
    } 
    return Array(localB.prefix(Int(ncols))) 
} 
Problemi correlati