func (gp *gpConvexProg) F1(x *matrix.FloatMatrix) (f, Df *matrix.FloatMatrix, err error) { f = nil Df = nil err = nil f = matrix.FloatZeros(gp.mnl+1, 1) Df = matrix.FloatZeros(gp.mnl+1, gp.n) y := gp.g.Copy() blas.GemvFloat(gp.F, x, y, 1.0, 1.0) for i, s := range gp.ind { start := s[0] stop := s[1] // yi := exp(yi) = exp(Fi*x+gi) ymax := maxvec(y.FloatArray()[start:stop]) // ynew = exp(y[start:stop] - ymax) ynew := matrix.Exp(matrix.FloatVector(y.FloatArray()[start:stop]).Add(-ymax)) y.SetIndexesFromArray(ynew.FloatArray(), matrix.Indexes(start, stop)...) // fi = log sum yi = log sum exp(Fi*x+gi) ysum := blas.AsumFloat(y, &la.IOpt{"n", stop - start}, &la.IOpt{"offset", start}) f.SetIndex(i, ymax+math.Log(ysum)) blas.ScalFloat(y, 1.0/ysum, &la.IOpt{"n", stop - start}, &la.IOpt{"offset", start}) blas.GemvFloat(gp.F, y, Df, 1.0, 0.0, la.OptTrans, &la.IOpt{"m", stop - start}, &la.IOpt{"incy", gp.mnl + 1}, &la.IOpt{"offseta", start}, &la.IOpt{"offsetx", start}, &la.IOpt{"offsety", i}) } return }
func _TestMultMV(t *testing.T) { bM := 100 * M bN := 100 * N A := matrix.FloatNormal(bM, bN) X := matrix.FloatNormal(bN, 1) Y1 := matrix.FloatZeros(bM, 1) Y0 := matrix.FloatZeros(bM, 1) Ar := A.FloatArray() Xr := X.FloatArray() Y1r := Y1.FloatArray() blas.GemvFloat(A, X, Y0, 1.0, 1.0) DMultMV(Y1r, Ar, Xr, 1.0, 1.0, NOTRANS, 1, A.LeadingIndex(), 1, 0, bN, 0, bM, 32, 32) t.Logf("Y0 == Y1: %v\n", Y0.AllClose(Y1)) /* if ! Y0.AllClose(Y1) { y0 := Y0.SubMatrix(0, 0, 2, 1) y1 := Y1.SubMatrix(0, 0, 2, 1) t.Logf("y0=\n%v\n", y0) t.Logf("y1=\n%v\n", y1) } */ }
func _TestMultMVTransA(t *testing.T) { bM := 1000 * M bN := 1000 * N A := matrix.FloatNormal(bN, bM) X := matrix.FloatWithValue(bN, 1, 1.0) Y1 := matrix.FloatZeros(bM, 1) Y0 := matrix.FloatZeros(bM, 1) Ar := A.FloatArray() Xr := X.FloatArray() Y1r := Y1.FloatArray() blas.GemvFloat(A, X, Y0, 1.0, 1.0, linalg.OptTrans) DMultMV(Y1r, Ar, Xr, 1.0, 1.0, TRANSA, 1, A.LeadingIndex(), 1, 0, bN, 0, bM, 4, 4) ok := Y0.AllClose(Y1) t.Logf("Y0 == Y1: %v\n", ok) if !ok { var y1, y0 matrix.FloatMatrix Y1.SubMatrix(&y1, 0, 0, 5, 1) t.Logf("Y1[0:5]:\n%v\n", y1) Y0.SubMatrix(&y0, 0, 0, 5, 1) t.Logf("Y0[0:5]:\n%v\n", y0) } }
/* Matrix-vector multiplication. A is a matrix or spmatrix of size (m, n) where N = dims['l'] + sum(dims['q']) + sum( k**2 for k in dims['s'] ) representing a mapping from R^n to S. If trans is 'N': y := alpha*A*x + beta * y (trans = 'N'). x is a vector of length n. y is a vector of length N. If trans is 'T': y := alpha*A'*x + beta * y (trans = 'T'). x is a vector of length N. y is a vector of length n. The 's' components in S are stored in unpacked 'L' storage. */ func sgemv(A, x, y *matrix.FloatMatrix, alpha, beta float64, dims *sets.DimensionSet, opts ...la_.Option) error { m := dims.Sum("l", "q") + dims.SumSquared("s") n := la_.GetIntOpt("n", -1, opts...) if n == -1 { n = A.Cols() } trans := la_.GetIntOpt("trans", int(la_.PNoTrans), opts...) offsetX := la_.GetIntOpt("offsetx", 0, opts...) offsetY := la_.GetIntOpt("offsety", 0, opts...) offsetA := la_.GetIntOpt("offseta", 0, opts...) if trans == int(la_.PTrans) && alpha != 0.0 { trisc(x, dims, offsetX) //fmt.Printf("trisc x=\n%v\n", x.ConvertToString()) } //fmt.Printf("alpha=%.4f beta=%.4f m=%d n=%d\n", alpha, beta, m, n) //fmt.Printf("A=\n%v\nx=\n%v\ny=\n%v\n", A, x.ConvertToString(), y.ConvertToString()) err := blas.GemvFloat(A, x, y, alpha, beta, &la_.IOpt{"trans", trans}, &la_.IOpt{"n", n}, &la_.IOpt{"m", m}, &la_.IOpt{"offseta", offsetA}, &la_.IOpt{"offsetx", offsetX}, &la_.IOpt{"offsety", offsetY}) //fmt.Printf("gemv y=\n%v\n", y.ConvertToString()) if trans == int(la_.PTrans) && alpha != 0.0 { triusc(x, dims, offsetX) } return err }
func CTestGemv(m, n, p int) (fnc func(), A, X, Y *matrix.FloatMatrix) { A = matrix.FloatNormal(m, n) X = matrix.FloatNormal(n, 1) Y = matrix.FloatZeros(m, 1) fnc = func() { blas.GemvFloat(A, X, Y, 1.0, 1.0) } return }
func (gp *gpConvexProg) F2(x, z *matrix.FloatMatrix) (f, Df, H *matrix.FloatMatrix, err error) { err = nil f = matrix.FloatZeros(gp.mnl+1, 1) Df = matrix.FloatZeros(gp.mnl+1, gp.n) H = matrix.FloatZeros(gp.n, gp.n) y := gp.g.Copy() Fsc := matrix.FloatZeros(gp.maxK, gp.n) blas.GemvFloat(gp.F, x, y, 1.0, 1.0) //fmt.Printf("y=\n%v\n", y.ToString("%.3f")) for i, s := range gp.ind { start := s[0] stop := s[1] // yi := exp(yi) = exp(Fi*x+gi) ymax := maxvec(y.FloatArray()[start:stop]) ynew := matrix.Exp(matrix.FloatVector(y.FloatArray()[start:stop]).Add(-ymax)) y.SetIndexesFromArray(ynew.FloatArray(), matrix.Indexes(start, stop)...) // fi = log sum yi = log sum exp(Fi*x+gi) ysum := blas.AsumFloat(y, &la.IOpt{"n", stop - start}, &la.IOpt{"offset", start}) f.SetIndex(i, ymax+math.Log(ysum)) blas.ScalFloat(y, 1.0/ysum, &la.IOpt{"n", stop - start}, &la.IOpt{"offset", start}) blas.GemvFloat(gp.F, y, Df, 1.0, 0.0, la.OptTrans, &la.IOpt{"m", stop - start}, &la.IOpt{"incy", gp.mnl + 1}, &la.IOpt{"offseta", start}, &la.IOpt{"offsetx", start}, &la.IOpt{"offsety", i}) Fsc.SetSubMatrix(0, 0, gp.F.GetSubMatrix(start, 0, stop-start)) for k := start; k < stop; k++ { blas.AxpyFloat(Df, Fsc, -1.0, &la.IOpt{"n", gp.n}, &la.IOpt{"incx", gp.mnl + 1}, &la.IOpt{"incy", Fsc.Rows()}, &la.IOpt{"offsetx", i}, &la.IOpt{"offsety", k - start}) blas.ScalFloat(Fsc, math.Sqrt(y.GetIndex(k)), &la.IOpt{"inc", Fsc.Rows()}, &la.IOpt{"offset", k - start}) } // H += z[i]*Hi = z[i] *Fisc' * Fisc blas.SyrkFloat(Fsc, H, z.GetIndex(i), 1.0, la.OptTrans, &la.IOpt{"k", stop - start}) } return }
func CTestGemvTransA(m, n, p int) (fnc func(), A, X, Y *matrix.FloatMatrix) { A = matrix.FloatNormal(n, m) X = matrix.FloatNormal(n, 1) Y = matrix.FloatZeros(m, 1) A = A.Transpose() fnc = func() { blas.GemvFloat(A, X, Y, 1.0, 1.0, linalg.OptTrans) } return }
func (a *epMatrixA) Af(u, v MatrixVariable, alpha, beta float64, trans la.Option) (err error) { err = nil if trans.Equal(la.OptNoTrans) { ue, u_ok := u.(*epigraph) ve := v.Matrix() if !u_ok { return errors.New("'u' not a epigraph") } err = blas.GemvFloat(a.A, ue.m(), ve, alpha, beta) } else { ve, v_ok := v.(*epigraph) ue := u.Matrix() if !v_ok { return errors.New("'v' not a epigraph") } err = blas.GemvFloat(a.A, ue, ve.m(), alpha, beta, trans) ve.set(ve.t() * beta) } return }
func (d *epigraphDf) Df(u, v MatrixVariable, alpha, beta float64, trans la.Option) (err error) { err = nil if trans.Equal(la.OptNoTrans) { u_e, u_ok := u.(*epigraph) v_e := v.Matrix() if !u_ok { fmt.Printf("Df: not a epigraph\n") return errors.New("'u' not a epigraph") } err = blas.GemvFloat(d.df, u_e.m(), v_e, alpha, beta, la.OptNoTrans) v_e.Add(-alpha*u_e.t(), 0) } else { v_e, v_ok := v.(*epigraph) u_e := u.Matrix() if !v_ok { fmt.Printf("Df: not a epigraph\n") return errors.New("'v' not a epigraph") } err = blas.GemvFloat(d.df, u_e, v_e.m(), alpha, beta, la.OptTrans) v_e.set(-alpha*u_e.GetIndex(0) + beta*v_e.t()) } return }
func _TestMultMVSmall(t *testing.T) { bM := 5 bN := 4 A := matrix.FloatNormal(bM, bN) X := matrix.FloatVector([]float64{1.0, 2.0, 3.0, 4.0}) Y1 := matrix.FloatZeros(bM, 1) Y0 := matrix.FloatZeros(bM, 1) Ar := A.FloatArray() Xr := X.FloatArray() Y1r := Y1.FloatArray() blas.GemvFloat(A, X, Y0, 1.0, 1.0) DMultMV(Y1r, Ar, Xr, 1.0, 1.0, NOTRANS, 1, A.LeadingIndex(), 1, 0, bN, 0, bM, 4, 4) ok := Y0.AllClose(Y1) t.Logf("Y0 == Y1: %v\n", ok) if !ok { t.Logf("blas: Y=A*X\n%v\n", Y0) t.Logf("Y1: Y1 = A*X\n%v\n", Y1) } }
func (a *matrixVarA) Af(u, v MatrixVariable, alpha, beta float64, trans la.Option) (err error) { err = blas.GemvFloat(a.mA, u.Matrix(), v.Matrix(), alpha, beta, trans) return }
func kktChol2(G *matrix.FloatMatrix, dims *sets.DimensionSet, A *matrix.FloatMatrix, mnl int) (kktFactor, error) { if len(dims.At("q")) > 0 || len(dims.At("s")) > 0 { return nil, errors.New("'chol2' solver only for problems with no second-order or " + "semidefinite cone constraints") } p, n := A.Size() ml := dims.At("l")[0] F := &chol2Data{firstcall: true, singular: false, A: A, G: G, dims: dims} factor := func(W *sets.FloatMatrixSet, H, Df *matrix.FloatMatrix) (KKTFunc, error) { var err error = nil minor := 0 if !checkpnt.MinorEmpty() { minor = checkpnt.MinorTop() } if F.firstcall { F.Gs = matrix.FloatZeros(F.G.Size()) if mnl > 0 { F.Dfs = matrix.FloatZeros(Df.Size()) } F.S = matrix.FloatZeros(n, n) F.K = matrix.FloatZeros(p, p) checkpnt.AddMatrixVar("Gs", F.Gs) checkpnt.AddMatrixVar("Dfs", F.Dfs) checkpnt.AddMatrixVar("S", F.S) checkpnt.AddMatrixVar("K", F.K) } if mnl > 0 { dnli := matrix.FloatZeros(mnl, mnl) dnli.SetIndexesFromArray(W.At("dnli")[0].FloatArray(), matrix.DiagonalIndexes(dnli)...) blas.GemmFloat(dnli, Df, F.Dfs, 1.0, 0.0) } checkpnt.Check("02factor_chol2", minor) di := matrix.FloatZeros(ml, ml) di.SetIndexesFromArray(W.At("di")[0].FloatArray(), matrix.DiagonalIndexes(di)...) err = blas.GemmFloat(di, G, F.Gs, 1.0, 0.0) checkpnt.Check("06factor_chol2", minor) if F.firstcall { blas.SyrkFloat(F.Gs, F.S, 1.0, 0.0, la.OptTrans) if mnl > 0 { blas.SyrkFloat(F.Dfs, F.S, 1.0, 1.0, la.OptTrans) } if H != nil { F.S.Plus(H) } checkpnt.Check("10factor_chol2", minor) err = lapack.Potrf(F.S) if err != nil { err = nil // reset error F.singular = true // original code recreates F.S as dense if it is sparse and // A is dense, we don't do it as currently no sparse matrices //F.S = matrix.FloatZeros(n, n) //checkpnt.AddMatrixVar("S", F.S) blas.SyrkFloat(F.Gs, F.S, 1.0, 0.0, la.OptTrans) if mnl > 0 { blas.SyrkFloat(F.Dfs, F.S, 1.0, 1.0, la.OptTrans) } checkpnt.Check("14factor_chol2", minor) blas.SyrkFloat(F.A, F.S, 1.0, 1.0, la.OptTrans) if H != nil { F.S.Plus(H) } lapack.Potrf(F.S) } F.firstcall = false checkpnt.Check("20factor_chol2", minor) } else { blas.SyrkFloat(F.Gs, F.S, 1.0, 0.0, la.OptTrans) if mnl > 0 { blas.SyrkFloat(F.Dfs, F.S, 1.0, 1.0, la.OptTrans) } if H != nil { F.S.Plus(H) } checkpnt.Check("40factor_chol2", minor) if F.singular { blas.SyrkFloat(F.A, F.S, 1.0, 1.0, la.OptTrans) } lapack.Potrf(F.S) checkpnt.Check("50factor_chol2", minor) } // Asct := L^{-1}*A'. Factor K = Asct'*Asct. Asct := F.A.Transpose() blas.TrsmFloat(F.S, Asct, 1.0) blas.SyrkFloat(Asct, F.K, 1.0, 0.0, la.OptTrans) lapack.Potrf(F.K) checkpnt.Check("90factor_chol2", minor) solve := func(x, y, z *matrix.FloatMatrix) (err error) { // Solve // // [ H 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. // // If not F['singular']: // // K*uy = A * S^{-1} * ( bx + GG'*W^{-1}*W^{-T}*bz ) - by // S*ux = bx + GG'*W^{-1}*W^{-T}*bz - A'*uy // W*uz = W^{-T} * ( GG*ux - bz ). // // If F['singular']: // // K*uy = A * S^{-1} * ( bx + GG'*W^{-1}*W^{-T}*bz + A'*by ) // - by // S*ux = bx + GG'*W^{-1}*W^{-T}*bz + A'*by - A'*y. // W*uz = W^{-T} * ( GG*ux - bz ). minor := 0 if !checkpnt.MinorEmpty() { minor = checkpnt.MinorTop() } // z := W^{-1} * z = W^{-1} * bz scale(z, W, true, true) checkpnt.Check("10solve_chol2", minor) // If not F['singular']: // x := L^{-1} * P * (x + GGs'*z) // = L^{-1} * P * (x + GG'*W^{-1}*W^{-T}*bz) // // If F['singular']: // x := L^{-1} * P * (x + GGs'*z + A'*y)) // = L^{-1} * P * (x + GG'*W^{-1}*W^{-T}*bz + A'*y) if mnl > 0 { blas.GemvFloat(F.Dfs, z, x, 1.0, 1.0, la.OptTrans) } blas.GemvFloat(F.Gs, z, x, 1.0, 1.0, la.OptTrans, &la.IOpt{"offsetx", mnl}) //checkpnt.Check("20solve_chol2", minor) if F.singular { blas.GemvFloat(F.A, y, x, 1.0, 1.0, la.OptTrans) } checkpnt.Check("30solve_chol2", minor) blas.TrsvFloat(F.S, x) //checkpnt.Check("50solve_chol2", minor) // y := K^{-1} * (Asc*x - y) // = K^{-1} * (A * S^{-1} * (bx + GG'*W^{-1}*W^{-T}*bz) - by) // (if not F['singular']) // = K^{-1} * (A * S^{-1} * (bx + GG'*W^{-1}*W^{-T}*bz + // A'*by) - by) // (if F['singular']). blas.GemvFloat(Asct, x, y, 1.0, -1.0, la.OptTrans) //checkpnt.Check("55solve_chol2", minor) lapack.Potrs(F.K, y) //checkpnt.Check("60solve_chol2", minor) // x := P' * L^{-T} * (x - Asc'*y) // = S^{-1} * (bx + GG'*W^{-1}*W^{-T}*bz - A'*y) // (if not F['singular']) // = S^{-1} * (bx + GG'*W^{-1}*W^{-T}*bz + A'*by - A'*y) // (if F['singular']) blas.GemvFloat(Asct, y, x, -1.0, 1.0) blas.TrsvFloat(F.S, x, la.OptTrans) checkpnt.Check("70solve_chol2", minor) // W*z := GGs*x - z = W^{-T} * (GG*x - bz) if mnl > 0 { blas.GemvFloat(F.Dfs, x, z, 1.0, -1.0) } blas.GemvFloat(F.Gs, x, z, 1.0, -1.0, &la.IOpt{"offsety", mnl}) checkpnt.Check("90solve_chol2", minor) return nil } return solve, err } return factor, nil }
func TestMultMVTransASmall(t *testing.T) { data6 := [][]float64{ []float64{-1.59e+00, 6.56e-02, 2.14e-01, 6.79e-01, 2.93e-01, 5.24e-01}, []float64{4.28e-01, 1.57e-01, 3.81e-01, 2.19e-01, 2.97e-01, 2.83e-02}, []float64{3.02e-01, 9.70e-02, 3.18e-01, 2.03e-01, 7.53e-01, 1.58e-01}, []float64{1.99e-01, 3.01e-01, 4.69e-01, 3.61e-01, 2.07e-01, 6.07e-01}, []float64{1.93e-01, 5.15e-01, 2.83e-01, 5.71e-01, 8.65e-01, 9.75e-01}, []float64{3.13e-01, 8.14e-01, 2.93e-01, 8.62e-01, 6.97e-01, 7.95e-02}} data5 := [][]float64{ []float64{1.57e-01, 3.81e-01, 2.19e-01, 2.97e-01, 2.83e-02}, []float64{9.70e-02, 3.18e-01, 2.03e-01, 7.53e-01, 1.58e-01}, []float64{3.01e-01, 4.69e-01, 3.61e-01, 2.07e-01, 6.07e-01}, []float64{5.15e-01, 2.83e-01, 5.71e-01, 8.65e-01, 9.75e-01}, []float64{8.14e-01, 2.93e-01, 8.62e-01, 6.97e-01, 7.95e-02}} data2 := []float64{4.28e-01, 3.02e-01, 1.99e-01, 1.93e-01, 3.13e-01} bM := 5 bN := 4 nb := 2 //A := matrix.FloatNormal(bN, bM) //X := matrix.FloatWithValue(bN, 1, 1.0) A := matrix.FloatMatrixFromTable(data5, matrix.RowOrder) X := matrix.FloatNew(5, 1, data2) bM = A.Rows() bN = A.Cols() Ym := matrix.FloatZeros(3, bM) Y1 := matrix.FloatZeros(bM, 1) Y0 := matrix.FloatZeros(bM, 1) Ar := A.FloatArray() Xr := X.FloatArray() Y1r := Y1.FloatArray() blas.GemvFloat(A, X, Y0, 1.0, 1.0, linalg.OptTrans) DMultMV(Y1r, Ar, Xr, 1.0, 1.0, TRANSA, 1, A.LeadingIndex(), 1, 0, bN, 0, bM, nb, nb) ok := Y0.AllClose(Y1) t.Logf("Y0 == Y1: %v\n", ok) if ok || !ok { t.Logf("blas: Y=A.T*X\n%v\n", Y0) t.Logf("Y1: Y1 = A*X\n%v\n", Y1) } // zero Y0, Y1 Y0.Scale(0.0) Y1.Scale(0.0) // test with matrix view; A is view var A0 matrix.FloatMatrix A6 := matrix.FloatMatrixFromTable(data6, matrix.RowOrder) A0.SubMatrixOf(A6, 1, 1) blas.GemvFloat(&A0, X, Y0, 1.0, 1.0, linalg.OptTrans) Ar = A0.FloatArray() DMultMV(Y1r, Ar, Xr, 1.0, 1.0, TRANSA, 1, A0.LeadingIndex(), 1, 0, bN, 0, bM, nb, nb) ok = Y0.AllClose(Y1) t.Logf("lda>rows: Y0 == Y1: %v\n", ok) if ok || !ok { t.Logf("blas: Y=A.T*X\n%v\n", Y0) t.Logf("Y1: Y1 = A*X\n%v\n", Y1) } // Y is view too. Y1.SubMatrixOf(Ym, 0, 0, 1, bM) Y1r = Y1.FloatArray() DMultMV(Y1r, Ar, Xr, 1.0, 1.0, TRANSA, Y1.LeadingIndex(), A0.LeadingIndex(), 1, 0, bN, 0, bM, nb, nb) ok = Y0.AllClose(Y1.Transpose()) t.Logf("Y0 == Y1 row: %v\n", ok) t.Logf("row Y1: %v\n", Y1) }
func (d *matrixVarDf) Df(u, v MatrixVariable, alpha, beta float64, trans la.Option) error { return blas.GemvFloat(d.df, u.Matrix(), v.Matrix(), alpha, beta, trans) }
// 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 }
func CheckNoTrans(A, X, Y *matrix.FloatMatrix) { blas.GemvFloat(A, X, Y, 1.0, 1.0) }
/* Applies Nesterov-Todd scaling or its inverse. Computes x := W*x (trans is false 'N', inverse = false 'N') x := W^T*x (trans is true 'T', inverse = false 'N') x := W^{-1}*x (trans is false 'N', inverse = true 'T') x := W^{-T}*x (trans is true 'T', inverse = true 'T'). x is a dense float matrix. W is a MatrixSet with entries: - W['dnl']: positive vector - W['dnli']: componentwise inverse of W['dnl'] - W['d']: positive vector - W['di']: componentwise inverse of W['d'] - W['v']: lists of 2nd order cone vectors with unit hyperbolic norms - W['beta']: list of positive numbers - W['r']: list of square matrices - W['rti']: list of square matrices. rti[k] is the inverse transpose of r[k]. The 'dnl' and 'dnli' entries are optional, and only present when the function is called from the nonlinear solver. */ func scale(x *matrix.FloatMatrix, W *sets.FloatMatrixSet, trans, inverse bool) (err error) { /*DEBUGGED*/ var wl []*matrix.FloatMatrix var w *matrix.FloatMatrix ind := 0 err = nil // var minor int = 0 //if ! checkpnt.MinorEmpty() { // minor = checkpnt.MinorTop() //} //fmt.Printf("\n%d.%04d scaling x=\n%v\n", checkpnt.Major(), minor, x.ToString("%.17f")) // Scaling for nonlinear component xk is xk := dnl .* xk; inverse // scaling is xk ./ dnl = dnli .* xk, where dnl = W['dnl'], // dnli = W['dnli']. if wl = W.At("dnl"); wl != nil { if inverse { w = W.At("dnli")[0] } else { w = W.At("dnl")[0] } for k := 0; k < x.Cols(); k++ { err = blas.TbmvFloat(w, x, &la_.IOpt{"n", w.Rows()}, &la_.IOpt{"k", 0}, &la_.IOpt{"lda", 1}, &la_.IOpt{"offsetx", k * x.Rows()}) if err != nil { //fmt.Printf("1. TbmvFloat: %v\n", err) return } } ind += w.Rows() } //if ! checkpnt.MinorEmpty() { // checkpnt.Check("000scale", minor) //} // Scaling for linear 'l' component xk is xk := d .* xk; inverse // scaling is xk ./ d = di .* xk, where d = W['d'], di = W['di']. if inverse { w = W.At("di")[0] } else { w = W.At("d")[0] } for k := 0; k < x.Cols(); k++ { err = blas.TbmvFloat(w, x, &la_.IOpt{"n", w.Rows()}, &la_.IOpt{"k", 0}, &la_.IOpt{"lda", 1}, &la_.IOpt{"offsetx", k*x.Rows() + ind}) if err != nil { //fmt.Printf("2. TbmvFloat: %v\n", err) return } } ind += w.Rows() //if ! checkpnt.MinorEmpty() { // checkpnt.Check("010scale", minor) //} // Scaling for 'q' component is // // xk := beta * (2*v*v' - J) * xk // = beta * (2*v*(xk'*v)' - J*xk) // // where beta = W['beta'][k], v = W['v'][k], J = [1, 0; 0, -I]. // //Inverse scaling is // // xk := 1/beta * (2*J*v*v'*J - J) * xk // = 1/beta * (-J) * (2*v*((-J*xk)'*v)' + xk). //wf := matrix.FloatZeros(x.Cols(), 1) w = matrix.FloatZeros(x.Cols(), 1) for k, v := range W.At("v") { m := v.Rows() if inverse { blas.ScalFloat(x, -1.0, &la_.IOpt{"offset", ind}, &la_.IOpt{"inc", x.Rows()}) } err = blas.GemvFloat(x, v, w, 1.0, 0.0, la_.OptTrans, &la_.IOpt{"m", m}, &la_.IOpt{"n", x.Cols()}, &la_.IOpt{"offsetA", ind}, &la_.IOpt{"lda", x.Rows()}) if err != nil { //fmt.Printf("3. GemvFloat: %v\n", err) return } err = blas.ScalFloat(x, -1.0, &la_.IOpt{"offset", ind}, &la_.IOpt{"inc", x.Rows()}) if err != nil { return } err = blas.GerFloat(v, w, x, 2.0, &la_.IOpt{"m", m}, &la_.IOpt{"n", x.Cols()}, &la_.IOpt{"lda", x.Rows()}, &la_.IOpt{"offsetA", ind}) if err != nil { //fmt.Printf("4. GerFloat: %v\n", err) return } var a float64 if inverse { blas.ScalFloat(x, -1.0, &la_.IOpt{"offset", ind}, &la_.IOpt{"inc", x.Rows()}) // a[i,j] := 1.0/W[i,j] a = 1.0 / W.At("beta")[0].GetIndex(k) } else { a = W.At("beta")[0].GetIndex(k) } for i := 0; i < x.Cols(); i++ { blas.ScalFloat(x, a, &la_.IOpt{"n", m}, &la_.IOpt{"offset", ind + i*x.Rows()}) } ind += m } //if ! checkpnt.MinorEmpty() { // checkpnt.Check("020scale", minor) //} // Scaling for 's' component xk is // // xk := vec( r' * mat(xk) * r ) if trans = 'N' // xk := vec( r * mat(xk) * r' ) if trans = 'T'. // // r is kth element of W['r']. // // Inverse scaling is // // xk := vec( rti * mat(xk) * rti' ) if trans = 'N' // xk := vec( rti' * mat(xk) * rti ) if trans = 'T'. // // rti is kth element of W['rti']. maxn := 0 for _, r := range W.At("r") { if r.Rows() > maxn { maxn = r.Rows() } } a := matrix.FloatZeros(maxn, maxn) for k, v := range W.At("r") { t := trans var r *matrix.FloatMatrix if !inverse { r = v t = !trans } else { r = W.At("rti")[k] } n := r.Rows() for i := 0; i < x.Cols(); i++ { // scale diagonal of xk by 0.5 blas.ScalFloat(x, 0.5, &la_.IOpt{"offset", ind + i*x.Rows()}, &la_.IOpt{"inc", n + 1}, &la_.IOpt{"n", n}) // a = r*tril(x) (t is 'N') or a = tril(x)*r (t is 'T') blas.Copy(r, a) if !t { err = blas.TrmmFloat(x, a, 1.0, la_.OptRight, &la_.IOpt{"m", n}, &la_.IOpt{"n", n}, &la_.IOpt{"lda", n}, &la_.IOpt{"ldb", n}, &la_.IOpt{"offsetA", ind + i*x.Rows()}) if err != nil { //fmt.Printf("5. TrmmFloat: %v\n", err) return } // x := (r*a' + a*r') if t is 'N' err = blas.Syr2kFloat(r, a, x, 1.0, 0.0, la_.OptNoTrans, &la_.IOpt{"n", n}, &la_.IOpt{"k", n}, &la_.IOpt{"ldb", n}, &la_.IOpt{"ldc", n}, &la_.IOpt{"offsetC", ind + i*x.Rows()}) if err != nil { //fmt.Printf("6. Syr2kFloat: %v\n", err) return } } else { err = blas.TrmmFloat(x, a, 1.0, la_.OptLeft, &la_.IOpt{"m", n}, &la_.IOpt{"n", n}, &la_.IOpt{"lda", n}, &la_.IOpt{"ldb", n}, &la_.IOpt{"offsetA", ind + i*x.Rows()}) if err != nil { //fmt.Printf("7. TrmmFloat: %v\n", err) return } // x := (r'*a + a'*r) if t is 'T' err = blas.Syr2kFloat(r, a, x, 1.0, 0.0, la_.OptTrans, &la_.IOpt{"n", n}, &la_.IOpt{"k", n}, &la_.IOpt{"ldb", n}, &la_.IOpt{"ldc", n}, &la_.IOpt{"offsetC", ind + i*x.Rows()}) if err != nil { //fmt.Printf("8. Syr2kFloat: %v\n", err) return } } } ind += n * n } //if ! checkpnt.MinorEmpty() { // checkpnt.Check("030scale", minor) //} return }
func (a *matrixA) Af(x, y *matrix.FloatMatrix, alpha, beta float64, trans la.Option) error { return blas.GemvFloat(a.mA, x, y, alpha, beta, trans) }
func CheckTransA(A, X, Y *matrix.FloatMatrix) { blas.GemvFloat(A, X, Y, 1.0, 1.0, linalg.OptTrans) }
// 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 }