예제 #1
0
파일: qrtmult.go 프로젝트: hrautila/gomas
/*
 * Solve a system of linear equations A*X = B with general M-by-N
 * matrix A using the QR factorization computed by DecomposeQRT().
 *
 * If flags&gomas.TRANS != 0:
 *   find the minimum norm solution of an overdetermined system A.T * X = B.
 *   i.e min ||X|| s.t A.T*X = B
 *
 * Otherwise:
 *   find the least squares solution of an overdetermined system, i.e.,
 *   solve the least squares problem: min || B - A*X ||.
 *
 * Arguments:
 *  B     On entry, the right hand side N-by-P matrix B. On exit, the solution matrix X.
 *
 *  A     The elements on and above the diagonal contain the min(M,N)-by-N upper
 *        trapezoidal matrix R. The elements below the diagonal with the matrix 'T',
 *        represent the ortogonal matrix Q as product of elementary reflectors.
 *        Matrix A and T are as returned by DecomposeQRT()
 *
 *  T     The block reflector computed from elementary reflectors as returned by
 *        DecomposeQRT() or computed from elementary reflectors and scalar coefficients
 *        by BuildT()
 *
 *  W     Workspace, size as returned by WorkspaceMultQT()
 *
 *  flags Indicator flag
 *
 *  conf  Blocking configuration
 *
 * Compatible with lapack.GELS (the m >= n part)
 */
func QRTSolve(B, A, T, W *cmat.FloatMatrix, flags int, confs ...*gomas.Config) *gomas.Error {
	var err *gomas.Error = nil
	var R, BT cmat.FloatMatrix
	conf := gomas.CurrentConf(confs...)

	if flags&gomas.TRANS != 0 {
		// Solve overdetermined system A.T*X = B

		// B' = R.-1*B
		R.SubMatrix(A, 0, 0, n(A), n(A))
		BT.SubMatrix(B, 0, 0, n(A), n(B))
		err = blasd.SolveTrm(&BT, &R, 1.0, gomas.LEFT|gomas.UPPER|gomas.TRANSA, conf)

		// Clear bottom part of B
		BT.SubMatrix(B, n(A), 0)
		BT.SetFrom(cmat.NewFloatConstSource(0.0))

		// X = Q*B'
		err = QRTMult(B, A, T, W, gomas.LEFT, conf)
	} else {
		// solve least square problem min ||A*X - B||

		// B' = Q.T*B
		err = QRTMult(B, A, T, W, gomas.LEFT|gomas.TRANS, conf)
		if err != nil {
			return err
		}

		// X = R.-1*B'
		R.SubMatrix(A, 0, 0, n(A), n(A))
		BT.SubMatrix(B, 0, 0, n(A), n(B))
		err = blasd.SolveTrm(&BT, &R, 1.0, gomas.LEFT|gomas.UPPER, conf)
	}
	return err
}
예제 #2
0
파일: enc_test.go 프로젝트: hrautila/cmat
func TestSubMatrixGob(t *testing.T) {
	var B, As cmat.FloatMatrix
	var network bytes.Buffer
	N := 32
	A := cmat.NewMatrix(N, N)
	zeromean := cmat.NewFloatNormSource()
	A.SetFrom(zeromean)
	As.SubMatrix(A, 3, 3, N-6, N-6)

	enc := gob.NewEncoder(&network)
	dec := gob.NewDecoder(&network)

	// encode to network
	err := enc.Encode(&As)
	if err != nil {
		t.Logf("encode error: %v\n", err)
		t.FailNow()
	}

	// decode from network
	err = dec.Decode(&B)
	if err != nil {
		t.Logf("decode error: %v\n", err)
		t.FailNow()
	}

	ar, ac := As.Size()
	br, bc := B.Size()
	t.Logf("As[%d,%d] == B[%d,%d]: %v\n", ar, ac, br, bc, B.AllClose(&As))
}
예제 #3
0
파일: ql.go 프로젝트: hrautila/gomas
/*
 * Compute QL factorization of a M-by-N matrix A: A = Q * L.
 *
 * Arguments:
 *  A    On entry, the M-by-N matrix A, M >= N. On exit, lower triangular matrix L
 *       and the orthogonal matrix Q as product of elementary reflectors.
 *
 * tau  On exit, the scalar factors of the elemenentary reflectors.
 *
 * W    Workspace, N-by-nb matrix used for work space in blocked invocations.
 *
 * conf The blocking configuration. If nil then default blocking configuration
 *      is used. Member conf.LB defines blocking size of blocked algorithms.
 *      If it is zero then unblocked algorithm is used.
 *
 * Returns:
 *      Error indicator.
 *
 * Additional information
 *
 *  Ortogonal matrix Q is product of elementary reflectors H(k)
 *
 *    Q = H(K-1)...H(1)H(0), where K = min(M,N)
 *
 *  Elementary reflector H(k) is stored on column k of A above the diagonal with
 *  implicit unit value on diagonal entry. The vector TAU holds scalar factors
 *  of the elementary reflectors.
 *
 *  Contents of matrix A after factorization is as follow:
 *
 *    ( v0 v1 v2 v3 )   for M=6, N=4
 *    ( v0 v1 v2 v3 )
 *    ( l  v1 v2 v3 )
 *    ( l  l  v2 v3 )
 *    ( l  l  l  v3 )
 *    ( l  l  l  l  )
 *
 *  where l is element of L, vk is element of H(k).
 *
 * DecomposeQL is compatible with lapack.DGEQLF
 */
func QLFactor(A, tau, W *cmat.FloatMatrix, confs ...*gomas.Config) *gomas.Error {
	var err *gomas.Error = nil
	var tauh cmat.FloatMatrix
	conf := gomas.CurrentConf(confs...)

	if m(A) < n(A) {
		return gomas.NewError(gomas.ESIZE, "QLFactor")
	}
	wsmin := wsQL(A, 0)
	if W == nil || W.Len() < wsmin {
		return gomas.NewError(gomas.EWORK, "QLFactor", wsmin)
	}
	if tau.Len() < n(A) {
		return gomas.NewError(gomas.ESIZE, "QLFactor")
	}
	tauh.SubMatrix(tau, 0, 0, n(A), 1)
	lb := estimateLB(A, W.Len(), wsQL)
	lb = imin(lb, conf.LB)

	if lb == 0 || n(A) <= lb {
		unblockedQL(A, &tauh, W)
	} else {
		var Twork, Wrk cmat.FloatMatrix
		// block reflector T in first LB*LB elements in workspace
		// the rest, n(A)-LB*LB, is workspace for intermediate matrix operands
		Twork.SetBuf(conf.LB, conf.LB, -1, W.Data())
		Wrk.SetBuf(n(A)-conf.LB, conf.LB, -1, W.Data()[Twork.Len():])
		blockedQL(A, &tauh, &Twork, &Wrk, lb, conf)
	}
	return err
}
예제 #4
0
// test: min ||X|| s.t A.T*X = B
func TestSolveQR(t *testing.T) {
	M := 799
	N := 711
	K := 241
	nb := 32
	conf := gomas.NewConf()
	conf.LB = nb

	tau := cmat.NewMatrix(N, 1)
	A := cmat.NewMatrix(M, N)
	src := cmat.NewFloatNormSource()
	A.SetFrom(src)
	A0 := cmat.NewCopy(A)
	B0 := cmat.NewMatrix(M, K)
	B0.SetFrom(src)
	B := cmat.NewCopy(B0)

	W := lapackd.Workspace(lapackd.QRFactorWork(A, conf))
	lapackd.QRFactor(A, tau, W, conf)

	lapackd.QRSolve(B, A, tau, W, gomas.TRANS, conf)

	var Bmin cmat.FloatMatrix
	Bmin.SubMatrix(B0, 0, 0, N, K)
	blasd.Mult(&Bmin, A0, B, 1.0, -1.0, gomas.TRANSA, conf)

	nrm := lapackd.NormP(&Bmin, lapackd.NORM_ONE)
	t.Logf("M=%d, N=%d ||B - A.T*X||_1: %e\n", M, N, nrm)
}
예제 #5
0
// test: min || B - A.T*X ||
func TestLeastSquaresLQ(t *testing.T) {
	M := 723
	N := 811
	K := 273
	nb := 32
	conf := gomas.NewConf()
	conf.LB = nb

	tau := cmat.NewMatrix(M, 1)
	A := cmat.NewMatrix(M, N)
	src := cmat.NewFloatNormSource()
	A.SetFrom(src)
	B0 := cmat.NewMatrix(M, K)
	B0.SetFrom(src)
	B := cmat.NewMatrix(N, K)

	// B = A.T*B0
	blasd.Mult(B, A, B0, 1.0, 0.0, gomas.TRANSA, conf)

	W := lapackd.Workspace(lapackd.LQFactorWork(A, conf))
	lapackd.LQFactor(A, tau, W, conf)

	// B' = A.-1*B
	lapackd.LQSolve(B, A, tau, W, gomas.TRANS, conf)

	// expect B[0:M,0:K] == B0[0:M,0:K], B[M:N,0:K] == 0
	var X cmat.FloatMatrix

	X.SubMatrix(B, 0, 0, M, K)
	blasd.Plus(&X, B0, 1.0, -1.0, gomas.NONE)
	nrm := lapackd.NormP(&X, lapackd.NORM_ONE)

	t.Logf("M=%d, N=%d  ||B0 - min( ||A.T*X - B0|| ) ||_1: %e\n", M, N, nrm)
}
예제 #6
0
파일: part_test.go 프로젝트: hrautila/gomas
func TestPartition2D(t *testing.T) {
	var ATL, ATR, ABL, ABR, As cmat.FloatMatrix
	var A00, a01, A02, a10, a11, a12, A20, a21, A22 cmat.FloatMatrix

	csource := cmat.NewFloatConstSource(1.0)
	A := cmat.NewMatrix(6, 6)
	As.SubMatrix(A, 1, 1, 4, 4)
	As.SetFrom(csource)

	Partition2x2(&ATL, &ATR, &ABL, &ABR, &As, 0, 0, PTOPLEFT)
	t.Logf("ATL:\n%v\n", &ATL)

	t.Logf("n(ATL)=%d, n(As)=%d\n", n(&ATL), n(&As))
	k := 0
	for n(&ATL) < n(&As) && k < n(&As) {
		Repartition2x2to3x3(&ATL,
			&A00, &a01, &A02,
			&a10, &a11, &a12,
			&A20, &a21, &A22, &As, 1, PBOTTOMRIGHT)
		t.Logf("n(A00)=%d, n(a01)=%d, n(A02)=%d\n", n(&A00), n(&a01), n(&A02))
		t.Logf("n(a10)=%d, n(a11)=%d, n(a12)=%d\n", n(&a10), n(&a11), n(&a12))
		t.Logf("n(A20)=%d, n(a21)=%d, n(A22)=%d\n", n(&A20), n(&a21), n(&A22))
		//t.Logf("n(a12)=%d [%d], n(a11)=%d\n", n(&a12), a12.Len(), a11.Len())
		a11.Set(0, 0, a11.Get(0, 0)+1.0)
		addConst(&a21, -2.0)

		Continue3x3to2x2(&ATL, &ATR, &ABL, &ABR, &A00, &a11, &A22, &As, PBOTTOMRIGHT)
		t.Logf("n(ATL)=%d, n(As)=%d\n", n(&ATL), n(&As))
		k += 1
	}
	t.Logf("A:\n%v\n", A)
}
예제 #7
0
파일: enc_test.go 프로젝트: hrautila/cmat
func TestSubMatrixJSON(t *testing.T) {
	var B, As cmat.FloatMatrix
	var network bytes.Buffer
	N := 26
	A := cmat.NewMatrix(N, N)
	zeromean := cmat.NewFloatNormSource()
	A.SetFrom(zeromean)
	As.SubMatrix(A, 3, 3, N-6, N-6)

	enc := json.NewEncoder(&network)
	dec := json.NewDecoder(&network)

	// encode to network
	err := enc.Encode(&As)
	//t.Logf("bytes: %v\n", string(network.Bytes()))
	if err != nil {
		t.Logf("encode error: %v\n", err)
		t.FailNow()
	}

	// decode from network
	err = dec.Decode(&B)
	if err != nil {
		t.Logf("decode error: %v\n", err)
		t.FailNow()
	}
	t.Logf("As == B: %v\n", B.AllClose(&As))
}
예제 #8
0
파일: partition.go 프로젝트: hrautila/gomas
/*
 * Merge 1 by 1 block from 2 by 1 block.
 *
 *          AT
 * Abkl <-- --
 *          AB
 *
 */
func Merge2x1(ABLK, AT, AB *cmat.FloatMatrix) {
	tr, tc := AT.Size()
	br, _ := AB.Size()
	if tr > 0 {
		ABLK.SubMatrix(AT, 0, 0, tr+br, tc)
	} else {
		ABLK.SubMatrix(AB, 0, 0, br, tc)
	}
}
예제 #9
0
파일: partition.go 프로젝트: hrautila/gomas
/*
 * Merge 1 by 1 block from 1 by 2 block.
 *
 * ABLK <--  AL | AR
 *
 */
func Merge1x2(ABLK, AL, AR *cmat.FloatMatrix) {
	lr, lc := AL.Size()
	_, rc := AR.Size()
	if lc > 0 {
		ABLK.SubMatrix(AL, 0, 0, lr, lc+rc)
	} else {
		ABLK.SubMatrix(AR, 0, 0, lr, rc)
	}
}
예제 #10
0
func test_bdsvd(N, flags, kind int, verbose bool, t *testing.T) {
	var At, sD, sE, tmp cmat.FloatMatrix

	uplo := "upper"
	offdiag := 1
	if flags&gomas.LOWER != 0 {
		offdiag = -1
		uplo = "lower"
	}
	A0 := cmat.NewMatrix(N, N)
	desc := setDiagonals(A0, offdiag, kind)
	At.SubMatrix(A0, 0, 0, N, N)
	sD.Diag(A0, 0)
	sE.Diag(A0, offdiag)
	D := cmat.NewCopy(&sD)
	E := cmat.NewCopy(&sE)

	// unit singular vectors
	U := cmat.NewMatrix(N, N)
	sD.Diag(U, 0)
	sD.Add(1.0)

	V := cmat.NewMatrix(N, N)
	sD.Diag(V, 0)
	sD.Add(1.0)

	W := cmat.NewMatrix(4*N, 1)
	C := cmat.NewMatrix(N, N)

	lapackd.BDSvd(D, E, U, V, W, flags|gomas.WANTU|gomas.WANTV)

	blasd.Mult(C, U, U, 1.0, 0.0, gomas.TRANSA)
	sD.Diag(C)
	sD.Add(-1.0)
	nrmu := lapackd.NormP(C, lapackd.NORM_ONE)

	blasd.Mult(C, V, V, 1.0, 0.0, gomas.TRANSB)
	sD.Add(-1.0)
	nrmv := lapackd.NormP(C, lapackd.NORM_ONE)

	blasd.Mult(C, U, A0, 1.0, 0.0, gomas.TRANSA)
	blasd.Mult(&At, C, V, 1.0, 0.0, gomas.TRANSB)
	if verbose && N < 10 {
		t.Logf("D:\n%v\n", asRow(&tmp, D))
		t.Logf("U:\n%v\n", U)
		t.Logf("V:\n%v\n", V)
		t.Logf("U.T*A*V\n%v\n", &At)
	}
	sD.Diag(&At)
	blasd.Axpy(&sD, D, -1.0)
	nrma := lapackd.NormP(&At, lapackd.NORM_ONE)

	t.Logf("N=%d [%s,%s] ||U.T*A*V - bdsvd(A)||_1: %e\n", N, uplo, desc, nrma)
	t.Logf("  ||I - U.T*U||_1: %e\n", nrmu)
	t.Logf("  ||I - V.T*V||_1: %e\n", nrmv)
}
예제 #11
0
파일: pivot.go 프로젝트: hrautila/gomas
func swapCols(A *cmat.FloatMatrix, src, dst int) {
	var c0, c1 cmat.FloatMatrix
	ar, _ := A.Size()
	if src == dst || ar == 0 {
		return
	}
	c0.SubMatrix(A, 0, src, ar, 1)
	c1.SubMatrix(A, 0, dst, ar, 1)
	blasd.Swap(&c0, &c1)
}
예제 #12
0
파일: pivot.go 프로젝트: hrautila/gomas
func swapRows(A *cmat.FloatMatrix, src, dst int) {
	var r0, r1 cmat.FloatMatrix
	ar, ac := A.Size()
	if src == dst || ar == 0 {
		return
	}
	r0.SubMatrix(A, src, 0, 1, ac)
	r1.SubMatrix(A, dst, 0, 1, ac)
	blasd.Swap(&r0, &r1)
}
예제 #13
0
파일: hess.go 프로젝트: hrautila/gomas
// Compute: (I - Y*T*Y.T).T*C = C - Y*(C.T*Y*T)
func updateHessLeftWY(C, Y1, Y2, T, V *cmat.FloatMatrix, conf *gomas.Config) {
	var C1, C2 cmat.FloatMatrix

	if C.Len() == 0 {
		return
	}
	C1.SubMatrix(C, 1, 0, m(Y1), n(C))
	C2.SubMatrix(C, 1+n(Y1), 0, m(Y2), n(C))

	updateWithQTLeft(&C1, &C2, Y1, Y2, T, V, true, conf)
}
예제 #14
0
파일: hess.go 프로젝트: hrautila/gomas
// Compute: C*(I - Y*T*Y.T) = C - C*Y*T*Y.T = C - V*T*Y.T
func updateHessRightWY(C, Y1, Y2, T, W *cmat.FloatMatrix, conf *gomas.Config) {
	var C1, C2 cmat.FloatMatrix

	if C.Len() == 0 {
		return
	}
	C1.SubMatrix(C, 0, 1, m(C), n(Y1))
	C2.SubMatrix(C, 0, 1+n(Y1), m(C), m(Y2))

	updateWithQTRight(&C1, &C2, Y1, Y2, T, W, false, conf)
}
예제 #15
0
파일: ql.go 프로젝트: hrautila/gomas
/*
 * Build block reflector for QL factorized matrix.
 */
func QLReflector(T, A, tau *cmat.FloatMatrix, confs ...*gomas.Config) *gomas.Error {
	var tauh cmat.FloatMatrix

	if n(T) < n(A) || m(T) < n(A) {
		return gomas.NewError(gomas.ESIZE, "QLReflector")
	}

	tauh.SubMatrix(tau, 0, 0, imin(m(A), n(A)), 1)
	unblkQLBlockReflector(T, A, &tauh)
	return nil
}
예제 #16
0
파일: qrt.go 프로젝트: hrautila/gomas
/*
 * Unblocked QR decomposition with block reflector T.
 */
func unblockedQRT(A, T, W *cmat.FloatMatrix) *gomas.Error {
	var err *gomas.Error = nil
	var ATL, ATR, ABL, ABR cmat.FloatMatrix
	var A00, a10, a11, a12, A20, a21, A22 cmat.FloatMatrix
	var TTL, TTR, TBL, TBR cmat.FloatMatrix
	var T00, t01, T02, t11, t12, T22, w12 cmat.FloatMatrix

	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, util.PTOPLEFT)
	util.Partition2x2(
		&TTL, &TTR,
		&TBL, &TBR, T, 0, 0, util.PTOPLEFT)

	for m(&ABR) > 0 && n(&ABR) > 0 {
		util.Repartition2x2to3x3(&ATL,
			&A00, nil, nil,
			&a10, &a11, &a12,
			&A20, &a21, &A22, A, 1, util.PBOTTOMRIGHT)
		util.Repartition2x2to3x3(&TTL,
			&T00, &t01, &T02,
			nil, &t11, &t12,
			nil, nil, &T22, T, 1, util.PBOTTOMRIGHT)

		// ------------------------------------------------------

		computeHouseholder(&a11, &a21, &t11)

		// H*[a12 A22].T
		w12.SubMatrix(W, 0, 0, a12.Len(), 1)
		applyHouseholder2x1(&t11, &a21, &a12, &A22, &w12, gomas.LEFT)

		// update T
		tauval := t11.Get(0, 0)
		if tauval != 0.0 {
			// t01 := -tauval*(a10.T + &A20.T*a21)
			//a10.CopyTo(&t01)
			blasd.Axpby(&t01, &a10, 1.0, 0.0)
			blasd.MVMult(&t01, &A20, &a21, -tauval, -tauval, gomas.TRANSA)
			// t01 := T00*t01
			blasd.MVMultTrm(&t01, &T00, 1.0, gomas.UPPER)
		}

		// ------------------------------------------------------
		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT)
		util.Continue3x3to2x2(
			&TTL, &TTR,
			&TBL, &TBR, &T00, &t11, &T22, T, util.PBOTTOMRIGHT)
	}
	return err
}
예제 #17
0
파일: qlbld.go 프로젝트: hrautila/gomas
/*
 * Unblocked code for generating M by N matrix Q with orthogonal columns which
 * are defined as the last N columns of the product of K first elementary
 * reflectors.
 *
 * Parameter nk is last nk elementary reflectors that are not used in computing
 * the matrix Q. Parameter mk length of the first unused elementary reflectors
 * First nk columns are zeroed and subdiagonal mk-nk is set to unit.
 *
 * Compatible with lapack.DORG2L subroutine.
 */
func unblkBuildQL(A, Tvec, W *cmat.FloatMatrix, mk, nk int, mayClear bool) {
	var ATL, ATR, ABL, ABR cmat.FloatMatrix
	var A00, a01, a10, a11, a21, A22 cmat.FloatMatrix
	var tT, tB cmat.FloatMatrix
	var t0, tau1, t2, w12, D cmat.FloatMatrix

	// (mk, nk) = (rows, columns) of upper left partition
	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, mk, nk, util.PTOPLEFT)
	util.Partition2x1(
		&tT,
		&tB, Tvec, nk, util.PTOP)

	// zero the left side
	if nk > 0 && mayClear {
		blasd.Scale(&ABL, 0.0)
		blasd.Scale(&ATL, 0.0)
		D.Diag(&ATL, nk-mk)
		blasd.Add(&D, 1.0)
	}

	for m(&ABR) > 0 && n(&ABR) > 0 {
		util.Repartition2x2to3x3(&ATL,
			&A00, &a01, nil,
			&a10, &a11, nil,
			nil, &a21, &A22, A, 1, util.PBOTTOMRIGHT)
		util.Repartition2x1to3x1(&tT,
			&t0,
			&tau1,
			&t2, Tvec, 1, util.PBOTTOM)
		// ------------------------------------------------------
		w12.SubMatrix(W, 0, 0, a10.Len(), 1)
		applyHouseholder2x1(&tau1, &a01, &a10, &A00, &w12, gomas.LEFT)

		blasd.Scale(&a01, -tau1.Get(0, 0))
		a11.Set(0, 0, 1.0-tau1.Get(0, 0))

		// zero bottom elements
		blasd.Scale(&a21, 0.0)
		// ------------------------------------------------------
		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT)
		util.Continue3x1to2x1(
			&tT,
			&tB, &t0, &tau1, Tvec, util.PBOTTOM)
	}
}
예제 #18
0
파일: lqbld.go 프로젝트: hrautila/gomas
/*
 * Unblocked code for generating M by N matrix Q with orthogonal columns which
 * are defined as the first N columns of the product of K first elementary
 * reflectors.
 *
 * Parameters nk = n(A)-K, mk = m(A)-K define the initial partitioning of
 * matrix A.
 *
 *  Q = H(k)H(k-1)...H(1)  , 0 < k <= M, where H(i) = I - tau*v*v.T
 *
 * Computation is ordered as H(k)*H(k-1)...*H(1)*I ie. from bottom to top.
 *
 * If k < M rows k+1:M are cleared and diagonal entries [k+1:M,k+1:M] are
 * set to unit. Then the matrix Q is generated by right multiplying elements below
 * of i'th elementary reflector H(i).
 *
 * Compatible to lapack.xORG2L subroutine.
 */
func unblkBuildLQ(A, Tvec, W *cmat.FloatMatrix, mk, nk int, mayClear bool) {
	var ATL, ATR, ABL, ABR cmat.FloatMatrix
	var A00, a10, a11, a12, a21, A22 cmat.FloatMatrix
	var tT, tB cmat.FloatMatrix
	var t0, tau1, t2, w12, D cmat.FloatMatrix

	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, mk, nk, util.PBOTTOMRIGHT)
	util.Partition2x1(
		&tT,
		&tB, Tvec, mk, util.PBOTTOM)

	// zero the bottom part
	if mk > 0 && mayClear {
		blasd.Scale(&ABL, 0.0)
		blasd.Scale(&ABR, 0.0)
		D.Diag(&ABR)
		blasd.Add(&D, 1.0)
	}

	for m(&ATL) > 0 && n(&ATL) > 0 {
		util.Repartition2x2to3x3(&ATL,
			&A00, nil, nil,
			&a10, &a11, &a12,
			nil, &a21, &A22, A, 1, util.PTOPLEFT)
		util.Repartition2x1to3x1(&tT,
			&t0,
			&tau1,
			&t2, Tvec, 1, util.PTOP)
		// ------------------------------------------------------

		w12.SubMatrix(W, 0, 0, a21.Len(), 1)
		applyHouseholder2x1(&tau1, &a12, &a21, &A22, &w12, gomas.RIGHT)

		blasd.Scale(&a12, -tau1.Get(0, 0))
		a11.Set(0, 0, 1.0-tau1.Get(0, 0))

		// zero
		blasd.Scale(&a10, 0.0)
		// ------------------------------------------------------
		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, util.PTOPLEFT)
		util.Continue3x1to2x1(
			&tT,
			&tB, &t0, &tau1, Tvec, util.PTOP)
	}
}
예제 #19
0
func test_trdevd(N, flags, kind int, verbose bool, t *testing.T) {
	var At, sD, sE, tmp cmat.FloatMatrix

	A0 := cmat.NewMatrix(N, N)
	desc := setTrdDiagonals(A0, kind)
	At.SubMatrix(A0, 0, 0, N, N)
	sD.Diag(A0, 0)
	sE.Diag(A0, 1)
	D := cmat.NewCopy(&sD)
	E := cmat.NewCopy(&sE)

	V := cmat.NewMatrix(N, N)
	sD.Diag(V, 0)
	sD.Add(1.0)

	W := cmat.NewMatrix(4*N, 1)
	C := cmat.NewMatrix(N, N)

	if verbose && N < 10 {
		t.Logf("A0:\n%v\n", A0.ToString("%6.3f"))
		t.Logf("V.pre:\n%v\n", V.ToString("%6.3f"))
	}
	lapackd.TRDEigen(D, E, V, W, flags|gomas.WANTV)
	for k := 0; k < N-1; k++ {
		if E.GetAt(k) != 0.0 {
			t.Logf("E[%d] != 0.0 (%e)\n", k, E.GetAt(k))
		}
	}

	blasd.Mult(C, V, V, 1.0, 0.0, gomas.TRANSB)
	sD.Diag(C)
	sD.Add(-1.0)
	nrmv := lapackd.NormP(C, lapackd.NORM_ONE)

	blasd.Mult(C, V, A0, 1.0, 0.0, gomas.TRANSA)
	blasd.Mult(&At, C, V, 1.0, 0.0, gomas.NONE)
	if verbose && N < 10 {
		t.Logf("D:\n%v\n", asRow(&tmp, D).ToString("%6.3f"))
		t.Logf("V:\n%v\n", V.ToString("%6.3f"))
		t.Logf("V.T*A*V\n%v\n", At.ToString("%6.3f"))
	}
	sD.Diag(&At)
	blasd.Axpy(&sD, D, -1.0)
	nrma := lapackd.NormP(&At, lapackd.NORM_ONE)

	t.Logf("N=%d [%s] ||V.T*A*V - eigen(A)||_1: %e\n", N, desc, nrma)
	t.Logf("  ||I - V.T*V||_1: %e\n", nrmv)
}
예제 #20
0
파일: qrt.go 프로젝트: hrautila/gomas
func blockedQRT(A, T, W *cmat.FloatMatrix, conf *gomas.Config) *gomas.Error {
	var err *gomas.Error = nil
	var ATL, ATR, ABL, ABR, AL, AR cmat.FloatMatrix
	var A00, A01, A02, A10, A11, A12, A20, A21, A22 cmat.FloatMatrix
	var TL, TR, W2 cmat.FloatMatrix
	var T00, T01, T02 cmat.FloatMatrix

	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, util.PTOPLEFT)
	util.Partition1x2(
		&TL, &TR, T, 0, util.PLEFT)

	nb := conf.LB
	for m(&ABR)-nb > 0 && n(&ABR)-nb > 0 {
		util.Repartition2x2to3x3(&ATL,
			&A00, &A01, &A02,
			&A10, &A11, &A12,
			&A20, &A21, &A22, A, nb, util.PBOTTOMRIGHT)
		util.Repartition1x2to1x3(&TL,
			&T00, &T01, &T02, T, nb, util.PRIGHT)
		util.Partition1x2(
			&AL, &AR, &ABR, nb, util.PLEFT)
		// --------------------------------------------------------
		// decompose left side AL == /A11\
		//                           \A21/
		unblockedQRT(&AL, &T01, W)

		// update A'tail i.e. A12 and A22 with (I - Y*T*Y.T).T * A'tail
		// compute: Q*T.C == C - Y*(C.T*Y*T).T
		ar, ac := A12.Size()
		W2.SubMatrix(W, 0, 0, ac, ar)
		updateWithQTLeft(&A12, &A22, &A11, &A21, &T01, &W2, true, conf)
		// --------------------------------------------------------
		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &A11, &A22, A, util.PBOTTOMRIGHT)
		util.Continue1x3to1x2(
			&TL, &TR, &T00, &T01, T, util.PRIGHT)
	}
	if m(&ABR) > 0 && n(&ABR) > 0 {
		T01.SubMatrix(&TR, 0, 0, n(&ABR), n(&ABR))
		unblockedQRT(&ABR, &T01, W)
	}
	return err
}
예제 #21
0
파일: hess_test.go 프로젝트: hrautila/gomas
// test: A - Q*Hess(A)*Q.T  == 0
func TestMultHess(t *testing.T) {
	N := 377
	nb := 16

	conf := gomas.NewConf()
	conf.LB = nb

	A := cmat.NewMatrix(N, N)
	tau := cmat.NewMatrix(N, 1)
	zeromean := cmat.NewFloatNormSource()
	A.SetFrom(zeromean)
	A0 := cmat.NewCopy(A)

	// reduction
	W := lapackd.Workspace(lapackd.HessReduceWork(A, conf))
	lapackd.HessReduce(A, tau, W, conf)

	var Hlow cmat.FloatMatrix
	H := cmat.NewCopy(A)

	// set triangular part below first subdiagonal to zeros
	zeros := cmat.NewFloatConstSource(0.0)
	Hlow.SubMatrix(H, 1, 0, N-1, N-1)
	Hlow.SetFrom(zeros, cmat.LOWER|cmat.UNIT)
	H1 := cmat.NewCopy(H)

	// H := Q*H*Q.T
	conf.LB = nb
	lapackd.HessMult(H, A, tau, W, gomas.LEFT, conf)
	lapackd.HessMult(H, A, tau, W, gomas.RIGHT|gomas.TRANS, conf)

	// H := Q*H*Q.T
	conf.LB = 0
	lapackd.HessMult(H1, A, tau, W, gomas.LEFT, conf)
	lapackd.HessMult(H1, A, tau, W, gomas.RIGHT|gomas.TRANS, conf)

	// compute ||Q*Hess(A)*Q.T - A||_1
	blasd.Plus(H, A0, 1.0, -1.0, gomas.NONE)
	nrm := lapackd.NormP(H, lapackd.NORM_ONE)
	t.Logf("  blk.|| Q*Hess(A)*Q.T - A ||_1 : %e\n", nrm)

	blasd.Plus(H1, A0, 1.0, -1.0, gomas.NONE)
	nrm = lapackd.NormP(H1, lapackd.NORM_ONE)
	t.Logf("unblk.|| Q*Hess(A)*Q.T - A ||_1 : %e\n", nrm)
}
예제 #22
0
파일: view_test.go 프로젝트: hrautila/cmat
func TestViews(t *testing.T) {
	var As cmat.FloatMatrix
	N := 7
	A := cmat.NewMatrix(N, N)
	zeromean := cmat.NewFloatNormSource()
	A.SetFrom(zeromean)
	dlast := A.Get(-1, -1)
	t.Logf("A[-1,-1] = %10.3e\n", dlast)
	for i := 0; i < N; i++ {
		As.SubMatrix(A, i, i)
		As.Set(0, 0, As.Get(0, 0)+float64(i+1))
		if N < 10 {
			t.Logf("A[%d,%d]   = %10.3e\n", i, i, As.Get(0, 0))
		}
	}
	ok := float64(N)+dlast == A.Get(-1, -1)
	nC := int(A.Get(-1, -1) - dlast)
	t.Logf("add 1.0 %d times [%10.3e to %10.3e]: %v\n", nC, dlast, A.Get(-1, -1), ok)
}
예제 #23
0
파일: lqmult.go 프로젝트: hrautila/gomas
/*
 * Solve a system of linear equations A.T*X = B with general M-by-N
 * matrix A using the QR factorization computed by LQFactor().
 *
 * If flags&TRANS != 0:
 *   find the minimum norm solution of an overdetermined system A.T * X = B.
 *   i.e min ||X|| s.t A.T*X = B
 *
 * Otherwise:
 *   find the least squares solution of an overdetermined system, i.e.,
 *   solve the least squares problem: min || B - A*X ||.
 *
 * Arguments:
 *  B     On entry, the right hand side N-by-P matrix B. On exit, the solution matrix X.
 *
 *  A     The elements on and below the diagonal contain the M-by-min(M,N) lower
 *        trapezoidal matrix L. The elements right of the diagonal with the vector 'tau',
 *        represent the ortogonal matrix Q as product of elementary reflectors.
 *        Matrix A is as returned by LQFactor()
 *
 *  tau   The vector of N scalar coefficients that together with trilu(A) define
 *        the ortogonal matrix Q as Q = H(N)H(N-1)...H(1)
 *
 *  W     Workspace, size required returned WorksizeMultLQ().
 *
 *  flags Indicator flags
 *
 *  conf  Optinal blocking configuration. If not given default will be used. Unblocked
 *        invocation is indicated with conf.LB == 0.
 *
 * Compatible with lapack.GELS (the m < n part)
 */
func LQSolve(B, A, tau, W *cmat.FloatMatrix, flags int, confs ...*gomas.Config) *gomas.Error {
	var err *gomas.Error = nil
	var L, BL cmat.FloatMatrix

	conf := gomas.CurrentConf(confs...)

	wsmin := wsMultLQLeft(B, 0)
	if W.Len() < wsmin {
		return gomas.NewError(gomas.EWORK, "SolveLQ", wsmin)
	}

	if flags&gomas.TRANS != 0 {
		// solve: MIN ||A.T*X - B||

		// B' = Q.T*B
		err = LQMult(B, A, tau, W, gomas.LEFT, conf)
		if err != nil {
			return err
		}

		// X = L.-1*B'
		L.SubMatrix(A, 0, 0, m(A), m(A))
		BL.SubMatrix(B, 0, 0, m(A), n(B))
		err = blasd.SolveTrm(&BL, &L, 1.0, gomas.LEFT|gomas.LOWER|gomas.TRANSA, conf)

	} else {
		// Solve underdetermined system A*X = B

		// B' = L.-1*B
		L.SubMatrix(A, 0, 0, m(A), m(A))
		BL.SubMatrix(B, 0, 0, m(A), n(B))
		err = blasd.SolveTrm(&BL, &L, 1.0, gomas.LEFT|gomas.LOWER, conf)

		// Clear bottom part of B
		BL.SubMatrix(B, m(A), 0)
		BL.SetFrom(cmat.NewFloatConstSource(0.0))

		// X = Q.T*B'
		err = LQMult(B, A, tau, W, gomas.LEFT|gomas.TRANS, conf)

	}
	return err
}
예제 #24
0
파일: house.go 프로젝트: hrautila/gomas
func computeHouseholderRev(x, tau *cmat.FloatMatrix) {
	var alpha, x2 cmat.FloatMatrix

	r, _ := x.Size()
	if r == 1 {
		alpha.SubMatrix(x, 0, -1, 1, 1)
		x2.SubMatrix(x, 0, 0, 1, x.Len()-1) // row vector
	} else {
		alpha.SubMatrix(x, -1, 0, 1, 1)
		x2.SubMatrix(x, 0, 0, x.Len()-1, 1)
	}
	computeHouseholder(&alpha, &x2, tau)
}
예제 #25
0
파일: partition.go 프로젝트: hrautila/gomas
/*
 * Continue with 2 by 1 block from 3 by 1 block.
 *
 *           AT      A0            AT       A0
 * pBOTTOM: --  <--  A1   ; pTOP:   -- <--  --
 *           AB      --            AB       A1
 *                   A2                     A2
 */
func Continue3x1to2x1(AT, AB, A0, A1, A *cmat.FloatMatrix, pdir Direction) {
	ar, ac := A.Size()
	n0, _ := A0.Size()
	n1, _ := A1.Size()
	switch pdir {
	case PBOTTOM:
		AT.SubMatrix(A, 0, 0, n0+n1, ac)
		AB.SubMatrix(A, n0+n1, 0, ar-n0-n1, ac)
	case PTOP:
		AT.SubMatrix(A, 0, 0, n0, ac)
		AB.SubMatrix(A, n0, 0, ar-n0, ac)
	}
}
예제 #26
0
파일: partition.go 프로젝트: hrautila/gomas
/*
 * Partition p to 2 by 1 blocks.
 *
 *        AT
 *  A --> --
 *        AB
 *
 * Parameter nb is initial block size for AT (pTOP) or AB (pBOTTOM).
 */
func Partition2x1(AT, AB, A *cmat.FloatMatrix, nb int, side Direction) {
	ar, ac := A.Size()
	if nb > ar {
		nb = ar
	}
	switch side {
	case PTOP:
		AT.SubMatrix(A, 0, 0, nb, ac)
		AB.SubMatrix(A, nb, 0, ar-nb, ac)
	case PBOTTOM:
		AT.SubMatrix(A, 0, 0, ar-nb, ac)
		AB.SubMatrix(A, ar-nb, 0, nb, ac)
	}
}
예제 #27
0
파일: partition.go 프로젝트: hrautila/gomas
/*
 * Partition A to 1 by 2 blocks.
 *
 *  A -->  AL | AR
 *
 * Parameter nb is initial block size for AL (pLEFT) or AR (pRIGHT).
 */
func Partition1x2(AL, AR, A *cmat.FloatMatrix, nb int, side Direction) {
	ar, ac := A.Size()
	if nb > ac {
		nb = ac
	}
	switch side {
	case PLEFT:
		AL.SubMatrix(A, 0, 0, ar, nb)
		AR.SubMatrix(A, 0, nb, ar, ac-nb)
	case PRIGHT:
		AL.SubMatrix(A, 0, 0, ar, ac-nb)
		AR.SubMatrix(A, 0, ac-nb, ar, nb)
	}
}
예제 #28
0
// test: min || B - A*X ||
func TestLeastSquaresQR(t *testing.T) {
	M := 811
	N := 723
	K := 311
	nb := 32
	conf := gomas.NewConf()
	conf.LB = nb

	tau := cmat.NewMatrix(N, 1)
	A := cmat.NewMatrix(M, N)
	src := cmat.NewFloatNormSource()
	A.SetFrom(src)
	B0 := cmat.NewMatrix(N, K)
	B0.SetFrom(src)
	B := cmat.NewMatrix(M, K)

	// B = A*B0
	blasd.Mult(B, A, B0, 1.0, 0.0, gomas.NONE, conf)

	W := lapackd.Workspace(lapackd.QRFactorWork(A, conf))
	err := lapackd.QRFactor(A, tau, W, conf)
	if err != nil {
		t.Logf("DecomposeQR: %v\n", err)
	}

	// B' = A.-1*B
	err = lapackd.QRSolve(B, A, tau, W, gomas.NONE, conf)
	if err != nil {
		t.Logf("SolveQR: %v\n", err)
	}

	// expect B[0:N,0:K] == B0[0:N,0:K], B[N:M,0:K] == 0
	var X cmat.FloatMatrix

	X.SubMatrix(B, 0, 0, N, K)
	blasd.Plus(&X, B0, 1.0, -1.0, gomas.NONE)
	nrm := lapackd.NormP(&X, lapackd.NORM_ONE)

	t.Logf("M=%d, N=%d  ||B0 - min( ||A*X - B0|| ) ||_1: %e\n", M, N, nrm)
}
예제 #29
0
파일: lq.go 프로젝트: hrautila/gomas
/*
 * Blocked LQ decomposition with compact WY transform. As implemented
 * in lapack.DGELQF subroutine.
 */
func blockedLQ(A, Tvec, Twork, W *cmat.FloatMatrix, lb int, conf *gomas.Config) {
	var ATL, ATR, ABL, ABR, AR cmat.FloatMatrix
	var A00, A11, A12, A21, A22 cmat.FloatMatrix
	var TT, TB cmat.FloatMatrix
	var t0, tau, t2 cmat.FloatMatrix
	var Wrk, w1 cmat.FloatMatrix

	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, util.PTOPLEFT)
	util.Partition2x1(
		&TT,
		&TB, Tvec, 0, util.PTOP)

	//nb := conf.LB
	for m(&ABR)-lb > 0 && n(&ABR)-lb > 0 {
		util.Repartition2x2to3x3(&ATL,
			&A00, nil, nil,
			nil, &A11, &A12,
			nil, &A21, &A22, A, lb, util.PBOTTOMRIGHT)
		util.Repartition2x1to3x1(&TT,
			&t0,
			&tau,
			&t2, Tvec, lb, util.PBOTTOM)

		// current block size
		cb, rb := A11.Size()
		if rb < cb {
			cb = rb
		}
		// --------------------------------------------------------
		// decompose left side AL == /A11\
		//                           \A21/
		w1.SubMatrix(W, 0, 0, cb, 1)
		util.Merge1x2(&AR, &A11, &A12)
		unblockedLQ(&AR, &tau, &w1)

		// build block reflector
		unblkBlockReflectorLQ(Twork, &AR, &tau)

		// update A'tail i.e. A21 and A22 with A'*(I - Y*T*Y.T).T
		// compute: C - Y*(C.T*Y*T).T
		ar, ac := A21.Size()
		Wrk.SubMatrix(W, 0, 0, ar, ac)
		updateRightLQ(&A21, &A22, &A11, &A12, Twork, &Wrk, true, conf)
		// --------------------------------------------------------
		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &A11, &A22, A, util.PBOTTOMRIGHT)
		util.Continue3x1to2x1(
			&TT,
			&TB, &t0, &tau, Tvec, util.PBOTTOM)
	}

	// last block with unblocked
	if m(&ABR) > 0 && n(&ABR) > 0 {
		w1.SubMatrix(W, 0, 0, m(&ABR), 1)
		unblockedLQ(&ABR, &t2, &w1)
	}
}
예제 #30
0
파일: ql.go 프로젝트: hrautila/gomas
/*
 * Blocked QR decomposition with compact WY transform.
 *
 * Compatible with lapack.DGEQRF.
 */
func blockedQL(A, Tvec, Twork, W *cmat.FloatMatrix, lb int, conf *gomas.Config) {
	var ATL, ATR, ABL, ABR, AL cmat.FloatMatrix
	var A00, A01, A10, A11, A22 cmat.FloatMatrix
	var TT, TB cmat.FloatMatrix
	var t0, tau, t2 cmat.FloatMatrix
	var Wrk, w1 cmat.FloatMatrix

	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, util.PBOTTOMRIGHT)
	util.Partition2x1(
		&TT,
		&TB, Tvec, 0, util.PBOTTOM)

	nb := lb
	for m(&ATL)-nb > 0 && n(&ATL)-nb > 0 {
		util.Repartition2x2to3x3(&ATL,
			&A00, &A01, nil,
			&A10, &A11, nil,
			nil, nil, &A22, A, nb, util.PTOPLEFT)
		util.Repartition2x1to3x1(&TT,
			&t0,
			&tau,
			&t2, Tvec, nb, util.PTOP)

		// current block size
		cb, rb := A11.Size()
		if rb < cb {
			cb = rb
		}
		// --------------------------------------------------------
		// decompose righ side AL == /A01\
		//                           \A11/
		w1.SubMatrix(W, 0, 0, cb, 1)
		util.Merge2x1(&AL, &A01, &A11)
		unblockedQL(&AL, &tau, &w1)

		// build block reflector
		unblkQLBlockReflector(Twork, &AL, &tau)

		// update A'tail i.e. A10 and A00 with (I - Y*T*Y.T).T * A'tail
		// compute: C - Y*(C.T*Y*T).T
		ar, ac := A10.Size()
		Wrk.SubMatrix(W, 0, 0, ac, ar)
		updateQLLeft(&A10, &A00, &A11, &A01, Twork, &Wrk, true, conf)
		// --------------------------------------------------------
		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &A11, &A22, A, util.PTOPLEFT)
		util.Continue3x1to2x1(
			&TT,
			&TB, &t0, &tau, Tvec, util.PTOP)
	}

	// last block with unblocked
	if m(&ATL) > 0 && n(&ATL) > 0 {
		w1.SubMatrix(W, 0, 0, n(&ATL), 1)
		unblockedQL(&ATL, &t0, &w1)
	}
}