func TestQRSmal(t *testing.T) { data := [][]float64{ []float64{12.0, -51.0, 4.0}, []float64{6.0, 167.0, -68.0}, []float64{-4.0, 24.0, -41.0}} A := matrix.FloatMatrixFromTable(data, matrix.RowOrder) T := matrix.FloatZeros(A.Cols(), A.Cols()) T0 := T.Copy() M := A.Rows() //N := A.Cols() Tau := matrix.FloatZeros(M, 1) X, _ := DecomposeQR(A.Copy(), Tau, nil, 0) t.Logf("A\n%v\n", A) t.Logf("X\n%v\n", X) t.Logf("Tau\n%v\n", Tau) Tau0 := matrix.FloatZeros(M, 1) lapack.Geqrf(A, Tau0) t.Logf("lapack X\n%v\n", A) t.Logf("lapack Tau\n%v\n", Tau0) unblkQRBlockReflector(X, Tau, T) t.Logf("T:\n%v\n", T) V := TriLU(X.Copy()) lapack.LarftFloat(V, Tau, T0) t.Logf("T0:\n%v\n", T0) }
func runRefTest(A *matrix.FloatMatrix, ntest, LB int) time.Duration { var mintime time.Duration N := A.Cols() tau := matrix.FloatZeros(N, 1) fnc := func() { ERRlapack = lapack.Geqrf(A, tau) } A0 := A.Copy() for n := 0; n < ntest; n++ { if n > 0 { // restore original A A0.CopyTo(A) tau.Scale(0.0) } mperf.FlushCache() time0 := mperf.Timeit(fnc) if n == 0 || time0 < mintime { mintime = time0 } } return mintime }
// single invocation for matops and lapack functions func runCheck(A *matrix.FloatMatrix, LB int) (bool, time.Duration, time.Duration) { var W *matrix.FloatMatrix = nil N := A.Cols() tau := matrix.FloatZeros(N, 1) if LB > 0 { W = matrix.FloatZeros(A.Rows(), LB) } fnc := func() { _, ERRmatops = matops.DecomposeQR(A, tau, W, LB) } if verbose && N < 10 { fmt.Fprintf(os.Stderr, "A start:\n%v\n", A) } A0 := A.Copy() tau0 := tau.Copy() mperf.FlushCache() time0 := mperf.Timeit(fnc) if verbose && N < 10 { fmt.Fprintf(os.Stderr, "A end:\n%v\n", A) tau.SetSize(1, N, 1) fmt.Fprintf(os.Stderr, "tau: %v\n", tau) } fn2 := func() { ERRlapack = lapack.Geqrf(A0, tau0) } mperf.FlushCache() time2 := mperf.Timeit(fn2) if verbose && N < 10 { fmt.Fprintf(os.Stderr, "A0 end:\n%v\n", A0) tau0.SetSize(1, N, 1) // row vector fmt.Fprintf(os.Stderr, "tau0: %v\n", tau0) } // now A == A0 && tau == tau0 ok := A.AllClose(A0) oktau := tau.AllClose(tau0) if !ok || !oktau { // save result to globals Rlapack = A0 Rmatops = A TAUlapack = tau0 TAUmatops = tau } return ok && oktau, time0, time2 }
func TestQRBlk(t *testing.T) { M := 8 N := 6 nb := 2 A := matrix.FloatUniform(M, N) Tau := matrix.FloatZeros(M, 1) Tz := matrix.FloatZeros(N, N) Tx := matrix.FloatZeros(N, N) DecomposeBlockSize(0) Z, _ := DecomposeQRT(A.Copy(), Tz, nil, 0) _ = Z DecomposeBlockSize(nb) //X, _ := DecomposeQR(A.Copy(), Tau, nil) X, _ := DecomposeQRT(A.Copy(), Tx, nil, nb) Tau0 := matrix.FloatZeros(M, 1) A0 := A.Copy() lapack.Geqrf(A0, Tau0) ok := X.AllClose(A0) var dx matrix.FloatMatrix dx.DiagOf(Tx) //okt := Tau.AllClose(Tau0) okt := true _ = Tau t.Logf("lapack QR == DecomposeQR: %v\n", ok && okt) if !ok || !okt || true { t.Logf("A0: %d, %d, %d\n", A0.Rows(), A0.Cols(), A0.LeadingIndex()) t.Logf("A\n%v\n", A) t.Logf("X\n%v\n", X) t.Logf("Tz\n%v\n", Tz) t.Logf("Tx\n%v\n", Tx) t.Logf("Tau\n%v\n", &dx) t.Logf("lapack X\n%v\n", A0) t.Logf("lapack Tau\n%v\n", Tau0) } }
func TestQRT(t *testing.T) { M := 6 N := 5 var Tau matrix.FloatMatrix A := matrix.FloatUniform(M, N) T := matrix.FloatZeros(A.Cols(), A.Cols()) T0 := T.Copy() X, _ := DecomposeQRT(A.Copy(), T, nil, 0) Tau.DiagOf(T) Tau0 := matrix.FloatZeros(M, 1) A0 := A.Copy() lapack.Geqrf(A0, Tau0) ok := X.AllClose(A0) okt := Tau.AllClose(Tau0) t.Logf("lapack QR == DecomposeQR: %v\n", ok && okt) if !ok || !okt { t.Logf("A0: %d, %d, %d\n", A0.Rows(), A0.Cols(), A0.LeadingIndex()) t.Logf("A\n%v\n", A) t.Logf("X\n%v\n", X) t.Logf("Tau\n%v\n", &Tau) t.Logf("lapack X\n%v\n", A0) t.Logf("lapack Tau\n%v\n", Tau0) } // build block reflectors //unblkQRBlockReflector(X, Tau, T) V := TriLU(A0.Copy()) lapack.LarftFloat(V, Tau0, T0) ok = T0.AllClose(T) t.Logf("lapack.dlarft == QRBlockReflector: %v\n", ok) if !ok { t.Logf("T:\n%v\n", T) t.Logf("lapack T0:\n%v\n", T0) } }
// Solution of KKT equations by reduction to a 2 x 2 system, a QR // factorization to eliminate the equality constraints, and a dense // Cholesky factorization of order n-p. // // Computes the QR factorization // // A' = [Q1, Q2] * [R; 0] // // and returns a function that (1) computes the Cholesky factorization // // Q_2^T * (H + GG^T * W^{-1} * W^{-T} * GG) * Q2 = L * L^T, // // given H, Df, W, where GG = [Df; G], and (2) returns a function for // solving // // [ H A' GG' ] [ ux ] [ bx ] // [ A 0 0 ] * [ uy ] = [ by ]. // [ GG 0 -W'*W ] [ uz ] [ bz ] // // H is n x n, A is p x n, Df is mnl x n, G is N x n where // N = dims['l'] + sum(dims['q']) + sum( k**2 for k in dims['s'] ). // func kktChol(G *matrix.FloatMatrix, dims *sets.DimensionSet, A *matrix.FloatMatrix, mnl int) (kktFactor, error) { p, n := A.Size() cdim := mnl + dims.Sum("l", "q") + dims.SumSquared("s") cdim_pckd := mnl + dims.Sum("l", "q") + dims.SumPacked("s") QA := A.Transpose() tauA := matrix.FloatZeros(p, 1) lapack.Geqrf(QA, tauA) Gs := matrix.FloatZeros(cdim, n) K := matrix.FloatZeros(n, n) bzp := matrix.FloatZeros(cdim_pckd, 1) yy := matrix.FloatZeros(p, 1) checkpnt.AddMatrixVar("tauA", tauA) checkpnt.AddMatrixVar("Gs", Gs) checkpnt.AddMatrixVar("K", K) factor := func(W *sets.FloatMatrixSet, H, Df *matrix.FloatMatrix) (KKTFunc, error) { // Compute // // K = [Q1, Q2]' * (H + GG' * W^{-1} * W^{-T} * GG) * [Q1, Q2] // // and take the Cholesky factorization of the 2,2 block // // Q_2' * (H + GG^T * W^{-1} * W^{-T} * GG) * Q2. var err error = nil minor := 0 if !checkpnt.MinorEmpty() { minor = checkpnt.MinorTop() } // Gs = W^{-T} * GG in packed storage. if mnl > 0 { Gs.SetSubMatrix(0, 0, Df) } Gs.SetSubMatrix(mnl, 0, G) checkpnt.Check("00factor_chol", minor) scale(Gs, W, true, true) pack2(Gs, dims, mnl) //checkpnt.Check("10factor_chol", minor) // K = [Q1, Q2]' * (H + Gs' * Gs) * [Q1, Q2]. blas.SyrkFloat(Gs, K, 1.0, 0.0, la.OptTrans, &la.IOpt{"k", cdim_pckd}) if H != nil { K.SetSubMatrix(0, 0, matrix.Plus(H, K.GetSubMatrix(0, 0, H.Rows(), H.Cols()))) } //checkpnt.Check("20factor_chol", minor) symm(K, n, 0) lapack.Ormqr(QA, tauA, K, la.OptLeft, la.OptTrans) lapack.Ormqr(QA, tauA, K, la.OptRight) //checkpnt.Check("30factor_chol", minor) // Cholesky factorization of 2,2 block of K. lapack.Potrf(K, &la.IOpt{"n", n - p}, &la.IOpt{"offseta", p * (n + 1)}) checkpnt.Check("40factor_chol", minor) solve := func(x, y, z *matrix.FloatMatrix) (err error) { // Solve // // [ 0 A' GG'*W^{-1} ] [ ux ] [ bx ] // [ A 0 0 ] * [ uy ] = [ by ] // [ W^{-T}*GG 0 -I ] [ W*uz ] [ W^{-T}*bz ] // // and return ux, uy, W*uz. // // On entry, x, y, z contain bx, by, bz. On exit, they contain // the solution ux, uy, W*uz. // // If we change variables ux = Q1*v + Q2*w, the system becomes // // [ K11 K12 R ] [ v ] [Q1'*(bx+GG'*W^{-1}*W^{-T}*bz)] // [ K21 K22 0 ] * [ w ] = [Q2'*(bx+GG'*W^{-1}*W^{-T}*bz)] // [ R^T 0 0 ] [ uy ] [by ] // // W*uz = W^{-T} * ( GG*ux - bz ). minor := 0 if !checkpnt.MinorEmpty() { minor = checkpnt.MinorTop() } // bzp := W^{-T} * bz in packed storage scale(z, W, true, true) pack(z, bzp, dims, &la.IOpt{"mnl", mnl}) // x := [Q1, Q2]' * (x + Gs' * bzp) // = [Q1, Q2]' * (bx + Gs' * W^{-T} * bz) blas.GemvFloat(Gs, bzp, x, 1.0, 1.0, la.OptTrans, &la.IOpt{"m", cdim_pckd}) lapack.Ormqr(QA, tauA, x, la.OptLeft, la.OptTrans) // y := x[:p] // = Q1' * (bx + Gs' * W^{-T} * bz) blas.Copy(y, yy) blas.Copy(x, y, &la.IOpt{"n", p}) // x[:p] := v = R^{-T} * by blas.Copy(yy, x) lapack.Trtrs(QA, x, la.OptUpper, la.OptTrans, &la.IOpt{"n", p}) // x[p:] := K22^{-1} * (x[p:] - K21*x[:p]) // = K22^{-1} * (Q2' * (bx + Gs' * W^{-T} * bz) - K21*v) blas.GemvFloat(K, x, x, -1.0, 1.0, &la.IOpt{"m", n - p}, &la.IOpt{"n", p}, &la.IOpt{"offseta", p}, &la.IOpt{"offsety", p}) lapack.Potrs(K, x, &la.IOpt{"n", n - p}, &la.IOpt{"offseta", p * (n + 1)}, &la.IOpt{"offsetb", p}) // y := y - [K11, K12] * x // = Q1' * (bx + Gs' * W^{-T} * bz) - K11*v - K12*w blas.GemvFloat(K, x, y, -1.0, 1.0, &la.IOpt{"m", p}, &la.IOpt{"n", n}) // y := R^{-1}*y // = R^{-1} * (Q1' * (bx + Gs' * W^{-T} * bz) - K11*v // - K12*w) lapack.Trtrs(QA, y, la.OptUpper, &la.IOpt{"n", p}) // x := [Q1, Q2] * x lapack.Ormqr(QA, tauA, x, la.OptLeft) // bzp := Gs * x - bzp. // = W^{-T} * ( GG*ux - bz ) in packed storage. // Unpack and copy to z. blas.GemvFloat(Gs, x, bzp, 1.0, -1.0, &la.IOpt{"m", cdim_pckd}) unpack(bzp, z, dims, &la.IOpt{"mnl", mnl}) checkpnt.Check("90solve_chol", minor) return nil } return solve, err } return factor, nil }
// Solution of KKT equations with zero 1,1 block, by eliminating the // equality constraints via a QR factorization, and solving the // reduced KKT system by another QR factorization. // // Computes the QR factorization // // A' = [Q1, Q2] * [R1; 0] // // and returns a function that (1) computes the QR factorization // // W^{-T} * G * Q2 = Q3 * R3 // // (with columns of W^{-T}*G in packed storage), and (2) returns a function for solving // // [ 0 A' G' ] [ ux ] [ bx ] // [ A 0 0 ] * [ uy ] = [ by ]. // [ G 0 -W'*W ] [ uz ] [ bz ] // // A is p x n and G is N x n where N = dims['l'] + sum(dims['q']) + // sum( k**2 for k in dims['s'] ). // func kktQr(G *matrix.FloatMatrix, dims *sets.DimensionSet, A *matrix.FloatMatrix, mnl int) (kktFactor, error) { p, n := A.Size() cdim := dims.Sum("l", "q") + dims.SumSquared("s") cdim_pckd := dims.Sum("l", "q") + dims.SumPacked("s") QA := A.Transpose() tauA := matrix.FloatZeros(p, 1) lapack.Geqrf(QA, tauA) Gs := matrix.FloatZeros(cdim, n) tauG := matrix.FloatZeros(n-p, 1) u := matrix.FloatZeros(cdim_pckd, 1) vv := matrix.FloatZeros(n, 1) w := matrix.FloatZeros(cdim_pckd, 1) checkpnt.AddMatrixVar("tauA", tauA) checkpnt.AddMatrixVar("tauG", tauG) checkpnt.AddMatrixVar("Gs", Gs) checkpnt.AddMatrixVar("qr_u", u) checkpnt.AddMatrixVar("qr_vv", vv) factor := func(W *sets.FloatMatrixSet, H, Df *matrix.FloatMatrix) (KKTFunc, error) { var err error = nil minor := 0 if !checkpnt.MinorEmpty() { minor = checkpnt.MinorTop() } // Gs = W^{-T}*G, in packed storage. blas.Copy(G, Gs) //checkpnt.Check("00factor_qr", minor) scale(Gs, W, true, true) //checkpnt.Check("01factor_qr", minor) pack2(Gs, dims, 0) //checkpnt.Check("02factor_qr", minor) // Gs := [ Gs1, Gs2 ] // = Gs * [ Q1, Q2 ] lapack.Ormqr(QA, tauA, Gs, la.OptRight, &la.IOpt{"m", cdim_pckd}) //checkpnt.Check("03factor_qr", minor) // QR factorization Gs2 := [ Q3, Q4 ] * [ R3; 0 ] lapack.Geqrf(Gs, tauG, &la.IOpt{"n", n - p}, &la.IOpt{"m", cdim_pckd}, &la.IOpt{"offseta", Gs.Rows() * p}) checkpnt.Check("10factor_qr", minor) solve := func(x, y, z *matrix.FloatMatrix) (err error) { // On entry, x, y, z contain bx, by, bz. On exit, they // contain the solution x, y, W*z of // // [ 0 A' G'*W^{-1} ] [ x ] [bx ] // [ A 0 0 ] * [ y ] = [by ]. // [ W^{-T}*G 0 -I ] [ W*z ] [W^{-T}*bz] // // The system is solved in five steps: // // w := W^{-T}*bz - Gs1*R1^{-T}*by // u := R3^{-T}*Q2'*bx + Q3'*w // W*z := Q3*u - w // y := R1^{-1} * (Q1'*bx - Gs1'*(W*z)) // x := [ Q1, Q2 ] * [ R1^{-T}*by; R3^{-1}*u ] minor := 0 if !checkpnt.MinorEmpty() { minor = checkpnt.MinorTop() } // w := W^{-T} * bz in packed storage scale(z, W, true, true) pack(z, w, dims) //checkpnt.Check("00solve_qr", minor) // vv := [ Q1'*bx; R3^{-T}*Q2'*bx ] blas.Copy(x, vv) lapack.Ormqr(QA, tauA, vv, la.OptTrans) lapack.Trtrs(Gs, vv, la.OptUpper, la.OptTrans, &la.IOpt{"n", n - p}, &la.IOpt{"offseta", Gs.Rows() * p}, &la.IOpt{"offsetb", p}) //checkpnt.Check("10solve_qr", minor) // x[:p] := R1^{-T} * by blas.Copy(y, x) lapack.Trtrs(QA, x, la.OptUpper, la.OptTrans, &la.IOpt{"n", p}) //checkpnt.Check("20solve_qr", minor) // w := w - Gs1 * x[:p] // = W^{-T}*bz - Gs1*by blas.GemvFloat(Gs, x, w, -1.0, 1.0, &la.IOpt{"n", p}, &la.IOpt{"m", cdim_pckd}) //checkpnt.Check("30solve_qr", minor) // u := [ Q3'*w + v[p:]; 0 ] // = [ Q3'*w + R3^{-T}*Q2'*bx; 0 ] blas.Copy(w, u) lapack.Ormqr(Gs, tauG, u, la.OptTrans, &la.IOpt{"k", n - p}, &la.IOpt{"offseta", Gs.Rows() * p}, &la.IOpt{"m", cdim_pckd}) blas.AxpyFloat(vv, u, 1.0, &la.IOpt{"offsetx", p}, &la.IOpt{"n", n - p}) blas.ScalFloat(u, 0.0, &la.IOpt{"offset", n - p}) //checkpnt.Check("40solve_qr", minor) // x[p:] := R3^{-1} * u[:n-p] blas.Copy(u, x, &la.IOpt{"offsety", p}, &la.IOpt{"n", n - p}) lapack.Trtrs(Gs, x, la.OptUpper, &la.IOpt{"n", n - p}, &la.IOpt{"offset", Gs.Rows() * p}, &la.IOpt{"offsetb", p}) //checkpnt.Check("50solve_qr", minor) // x is now [ R1^{-T}*by; R3^{-1}*u[:n-p] ] // x := [Q1 Q2]*x lapack.Ormqr(QA, tauA, x) //checkpnt.Check("60solve_qr", minor) // u := [Q3, Q4] * u - w // = Q3 * u[:n-p] - w lapack.Ormqr(Gs, tauG, u, &la.IOpt{"k", n - p}, &la.IOpt{"m", cdim_pckd}, &la.IOpt{"offseta", Gs.Rows() * p}) blas.AxpyFloat(w, u, -1.0) //checkpnt.Check("70solve_qr", minor) // y := R1^{-1} * ( v[:p] - Gs1'*u ) // = R1^{-1} * ( Q1'*bx - Gs1'*u ) blas.Copy(vv, y, &la.IOpt{"n", p}) blas.GemvFloat(Gs, u, y, -1.0, 1.0, &la.IOpt{"m", cdim_pckd}, &la.IOpt{"n", p}, la.OptTrans) lapack.Trtrs(QA, y, la.OptUpper, &la.IOpt{"n", p}) //checkpnt.Check("80solve_qr", minor) unpack(u, z, dims) checkpnt.Check("90solve_qr", minor) return nil } return solve, err } return factor, nil }