Пример #1
0
func blkUpperLDL(A, W *matrix.FloatMatrix, p *pPivots, nb int) (err error) {
	var ATL, ATR, ABL, ABR matrix.FloatMatrix
	var A00, A01, A02, A11, A12, A22 matrix.FloatMatrix
	var D1, wrk matrix.FloatMatrix
	var pT, pB, p0, p1, p2 pPivots

	err = nil
	partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, pBOTTOMRIGHT)
	partitionPivot2x1(
		&pT,
		&pB, p, 0, pBOTTOM)

	for ATL.Rows() > 0 {
		repartition2x2to3x3(&ATL,
			&A00, &A01, &A02,
			nil, &A11, &A12,
			nil, nil, &A22, A, nb, pTOPLEFT)
		repartPivot2x1to3x1(&pT,
			&p0, &p1, &p2 /**/, p, nb, pTOP)

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

		// A11 = LDL(A11)
		err = unblkUpperLDL(&A11, &p1)
		if err != nil {
			return
		}
		applyColPivots(&A01, &p1, 0, BACKWARD)
		applyRowPivots(&A12, &p1, 0, BACKWARD)
		scalePivots(&p1, ATL.Rows()-A11.Rows())

		A11.Diag(&D1)

		// A01 = A01*A11.-T
		SolveTrm(&A01, &A11, 1.0, UPPER|UNIT|RIGHT|TRANSA)
		// A01 = A01*D1.-1
		SolveDiag(&A01, &D1, RIGHT)

		// W = D1*U01.T = U01*D1
		W.SubMatrix(&wrk, 0, 0, A01.Rows(), nb)
		A01.CopyTo(&wrk)
		MultDiag(&wrk, &D1, RIGHT)

		// A00 = A00 - U01*D1*U01.T = A22 - U01*W.T
		UpdateTrm(&A00, &A01, &wrk, -1.0, 1.0, UPPER|TRANSB)

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

		continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &A11, &A22, A, pTOPLEFT)
		contPivot3x1to2x1(
			&pT,
			&pB, &p0, &p1, p, pTOP)
	}
	return
}
Пример #2
0
/*
 *  ( A11  a12 )   ( U11 u12 )( D1  0  )( U11.t 0 )
 *  ( a21  a22 )   (  0   1  )(  0  d2 )( u12.t 1 )
 *
 *   a22  =   d2
 *   a01  =   u12*d2                       => u12 = a12/d2
 *   A11  =   u12*d2*u12.t + U11*D1*U11.t  => U11 = A11 - u12*d2*u12.t
 */
func unblkUpperLDL(A *matrix.FloatMatrix, p *pPivots) (err error) {
	var ATL, ATR, ABL, ABR matrix.FloatMatrix
	var A00, a01, A02, a11, a12, A22 matrix.FloatMatrix
	var AL, AR, acol matrix.FloatMatrix
	var pT, pB, p0, p1, p2 pPivots

	err = nil
	partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, pBOTTOMRIGHT)
	partitionPivot2x1(
		&pT,
		&pB, p, 0, pBOTTOM)

	for ATL.Rows() > 0 {
		repartition2x2to3x3(&ATL,
			&A00, &a01, &A02,
			nil, &a11, &a12,
			nil, nil, &A22, A, 1, pTOPLEFT)
		repartPivot2x1to3x1(&pT,
			&p0, &p1, &p2 /**/, p, 1, pTOP)

		// --------------------------------------------------------
		// search diagonal; diag(A00;a11)
		ATL.Diag(&acol)
		//merge2x1(&acol, &a01, &a11)
		imax := IAMax(&acol)
		if imax < ATL.Rows()-1 {
			merge1x2(&AL, &ATL, &ATR)
			merge1x2(&AR, &a11, &a12)
			// pivot diagonal in symmetric matrix; will swap a11 and [imax,imax]
			applyPivotSym(&AL, &AR, imax, UPPER)
			p1.pivots[0] = imax + 1
		} else {
			p1.pivots[0] = 0
		}

		if a11.Float() == 0.0 {
			err = onError("zero on diagonal.")
			return
		}
		// A00 = A00 - u01*d11*u01.T = A00 - a01*a01.T/a11; triangular update
		err = MVUpdateTrm(&A00, &a01, &a01, -1.0/a11.Float(), UPPER)

		// u01 = a01/a11
		InvScale(&a01, a11.Float())
		// ---------------------------------------------------------

		continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, pTOPLEFT)
		contPivot3x1to2x1(
			&pT,
			&pB, &p0, &p1, p, pTOP)
	}
	return
}
Пример #3
0
func blockedBuildQT(A, T, W *matrix.FloatMatrix, nb int) error {
	var err error = nil
	var ATL, ATR, ABL, ABR, AL matrix.FloatMatrix
	var A00, A01, A11, A12, A21, A22 matrix.FloatMatrix
	var TTL, TTR, TBL, TBR matrix.FloatMatrix
	var T00, T01, T02, T11, T12, T22 matrix.FloatMatrix
	var tau1, Wrk matrix.FloatMatrix
	var mb int

	mb = A.Rows() - A.Cols()

	partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, mb, 0, pBOTTOMRIGHT)
	partition2x2(
		&TTL, &TTR,
		&TBL, &TBR, T, 0, 0, pBOTTOMRIGHT)

	// clearing of the columns of the right and setting ABR to unit diagonal
	// (only if not applying all reflectors, kb > 0)

	for ATL.Rows() > 0 && ATL.Cols() > 0 {
		repartition2x2to3x3(&ATL,
			&A00, &A01, nil,
			nil, &A11, &A12,
			nil, &A21, &A22, A, nb, pTOPLEFT)
		repartition2x2to3x3(&TTL,
			&T00, &T01, &T02,
			nil, &T11, &T12,
			nil, nil, &T22, T, nb, pTOPLEFT)

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

		// update with current block reflector (I - Y*T*Y.T)*Atrailing
		W.SubMatrix(&Wrk, 0, 0, A12.Cols(), A11.Cols())
		updateWithQT(&A12, &A22, &A11, &A21, &T11, &Wrk, nb, false)

		// use unblocked version to compute current block
		W.SubMatrix(&Wrk, 0, 0, 1, A11.Cols())
		// elementary scalar coefficients on the diagonal, column vector
		T11.Diag(&tau1)
		merge2x1(&AL, &A11, &A21)
		// do an unblocked update to current block
		unblockedBuildQ(&AL, &tau1, &Wrk, 0)

		// zero upper part
		A01.SetIndexes(0.0)
		// --------------------------------------------------------
		continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &A11, &A22, A, pTOPLEFT)
		continue3x3to2x2(
			&TTL, &TTR,
			&TBL, &TBR, &T00, &T11, &T22, T, pTOPLEFT)
	}
	return err
}
Пример #4
0
func blkUpperLDLnoPiv(A, W *matrix.FloatMatrix, nb int) (err error) {
	var ATL, ATR, ABL, ABR matrix.FloatMatrix
	var A00, A01, A02, A11, A12, A22 matrix.FloatMatrix
	var D1, wrk matrix.FloatMatrix

	err = nil
	partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, pBOTTOMRIGHT)

	for ATL.Rows() > 0 {
		repartition2x2to3x3(&ATL,
			&A00, &A01, &A02,
			nil, &A11, &A12,
			nil, nil, &A22, A, nb, pTOPLEFT)

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

		// A11 = LDL(A11)
		unblkUpperLDLnoPiv(&A11)
		A11.Diag(&D1)

		// A01 = A01*A11.-T
		SolveTrm(&A01, &A11, 1.0, UPPER|UNIT|RIGHT|TRANSA)
		// A01 = A01*D1.-1
		SolveDiag(&A01, &D1, RIGHT)

		// W = D1*U01.T = U01*D1
		W.SubMatrix(&wrk, 0, 0, A01.Rows(), nb)
		A01.CopyTo(&wrk)
		MultDiag(&wrk, &D1, RIGHT)

		// A00 = A00 - U01*D1*U01.T = A22 - U01*W.T
		UpdateTrm(&A00, &A01, &wrk, -1.0, 1.0, UPPER|TRANSB)

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

		continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &A11, &A22, A, pTOPLEFT)
	}
	return
}
Пример #5
0
/*
 * Generic rank update of diagonal matrix.
 *   diag(D) = diag(D) + alpha * x * y.T
 *
 * Arguments:
 *   D     N element column or row vector or N-by-N matrix
 *
 *   x, y  N element vectors
 *
 *   alpha scalar
 */
func MVUpdateDiag(D, x, y *matrix.FloatMatrix, alpha float64) error {
	var d *matrix.FloatMatrix
	var dvec matrix.FloatMatrix

	if !isVector(x) || !isVector(y) {
		return errors.New("x, y not vectors")
	}
	if D.Rows() > 0 && D.Cols() == D.Rows() {
		D.Diag(&dvec)
		d = &dvec
	} else if isVector(D) {
		d = D
	} else {
		return errors.New("D not a diagonal")
	}

	N := d.NumElements()
	for k := 0; k < N; k++ {
		val := d.GetIndex(k)
		val += x.GetIndex(k) * y.GetIndex(k) * alpha
		d.SetIndex(k, val)
	}
	return nil
}
Пример #6
0
/*
 *  ( a11  a12 )   ( 1   0   )( d1  0   )( l  l21.t )
 *  ( a21  A22 )   ( l21 L22 )(  0  A22 )( 0  L22.t )
 *
 *   a11  =   d1
 *   a21  =   l21*d1                       => l21 = a21/d1
 *   A22  =   l21*d1*l21.t + L22*D2*L22.t  => L22 = A22 - l21*d1*l21t
 */
func unblkLowerLDL(A *matrix.FloatMatrix, p *pPivots) (err error) {
	var ATL, ATR, ABL, ABR matrix.FloatMatrix
	var A00, a10, a11, A20, a21, A22, acol matrix.FloatMatrix
	var pT, pB, p0, p1, p2 pPivots

	err = nil
	partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, pTOPLEFT)
	partitionPivot2x1(
		&pT,
		&pB, p, 0, pTOP)

	for ATL.Rows() < A.Rows() {
		repartition2x2to3x3(&ATL,
			&A00, nil, nil,
			&a10, &a11, nil,
			&A20, &a21, &A22, A, 1, pBOTTOMRIGHT)
		repartPivot2x1to3x1(&pT,
			&p0, &p1, &p2 /**/, p, 1, pBOTTOM)

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

		ABR.Diag(&acol)
		//merge2x1(&acol, &a11, &a21)
		imax := IAMax(&acol)
		//fmt.Printf("imax=%d, val=%e\n", imax, acol.GetAt(0, imax))
		if imax > 0 {
			// pivot diagonal in symmetric matrix; will swap a11 and [imax,imax]
			applyPivotSym(&ABL, &ABR, imax, LOWER)
			p1.pivots[0] = imax + ATL.Rows() + 1
		} else {
			p1.pivots[0] = 0
		}
		if a11.Float() == 0.0 {
			err = onError("zero value on diagonal")
			return
		}

		//fmt.Printf("unblk pivoted %d, a11=%e, A:\n%v\n", imax, a11.Float(), A)
		//var Ablk matrix.FloatMatrix
		//merge1x2(&Ablk, &a21, &A22)
		//fmt.Printf("unblk update with a11=%e, a21|A22:\n%v\n", a11.Float(), &Ablk)

		// A22 = A22 - l21*d11*l21.T = A22 - a21*a21.T/a11; triangular update
		err = MVUpdateTrm(&A22, &a21, &a21, -1.0/a11.Float(), LOWER)

		// l21 = a21/a11
		InvScale(&a21, a11.Float())

		//merge1x2(&Ablk, &ABL, &ABR)
		//fmt.Printf("unblk imax=%d, Ablk:\n%v\n", imax, &Ablk)

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

		continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, pBOTTOMRIGHT)
		contPivot3x1to2x1(
			&pT,
			&pB, &p0, &p1, p, pBOTTOM)
	}
	return
}
Пример #7
0
func unblkBoundedLowerLDL(A, W *matrix.FloatMatrix, p *pPivots, ncol int) (error, int) {
	var ATL, ATR, ABL, ABR matrix.FloatMatrix
	var A00, a10, a11, A20, a21, A22, adiag, wcol matrix.FloatMatrix
	var w00, w10, w11 matrix.FloatMatrix
	var pT, pB, p0, p1, p2 pPivots
	var err error = nil

	partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, pTOPLEFT)
	partitionPivot2x1(
		&pT,
		&pB, p, 0, pTOP)

	// copy current diagonal to last column of workspace
	W.SubMatrix(&wcol, 0, W.Cols()-1, A.Rows(), 1)
	A.Diag(&adiag)
	adiag.CopyTo(&wcol)
	//fmt.Printf("initial diagonal:\n%v\n", &wcol)

	nc := 0
	for ABR.Cols() > 0 && nc < ncol {

		partition2x2(
			&w00, nil,
			&w10, &w11, W, nc, nc, pTOPLEFT)

		dmax := findAndBuildPivot(&ABL, &ABR, &w10, &w11, nc)
		//fmt.Printf("dmax=%d\n", dmax)
		if dmax > 0 {
			// pivot diagonal in symmetric matrix; will swap a11 [0,0] and [imax,imax]
			applyPivotSym(&ABL, &ABR, dmax, LOWER)
			swapRows(&w10, 0, dmax)
			pB.pivots[0] = dmax + ATL.Rows() + 1
		} else {
			pB.pivots[0] = 0
		}

		//fmt.Printf("blk pivoted %d, A:\n%v\nW:\n%v\n", dmax, A, W)
		repartition2x2to3x3(&ATL,
			&A00, nil, nil,
			&a10, &a11, nil,
			&A20, &a21, &A22, A, 1, pBOTTOMRIGHT)
		repartPivot2x1to3x1(&pT,
			&p0, &p1, &p2 /**/, p, 1, pBOTTOM)

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

		// Copy updated column from working space
		w11.SubMatrix(&wcol, 1, 0, a21.Rows(), 1)
		wcol.CopyTo(&a21)
		a11.SetAt(0, 0, w11.GetAt(0, 0))
		// l21 = a21/a11
		InvScale(&a21, a11.Float())
		// here: wcol == l21*d11 == a21
		if ncol-nc > 1 {
			// update diagonal in workspace if not last column of block
			w11.SubMatrix(&adiag, 1, w11.Cols()-1, a21.Rows(), 1)
			MVUpdateDiag(&adiag, &wcol, &wcol, -1.0/a11.Float())
		}
		//fmt.Printf("nc=%d, a11=%e\n", nc, a11.Float())
		//fmt.Printf("l21\n%v\n", &a21)
		//fmt.Printf("a21\n%v\n", &wcol)
		//fmt.Printf("diag\n%v\n", &adiag)
		//var Ablk, wblk matrix.FloatMatrix
		//merge1x2(&Ablk, &ABL, &ABR)
		//merge1x2(&wblk, &w10, &w11)
		//fmt.Printf("unblk Ablk:\n%v\n", &Ablk)
		//fmt.Printf("unblk wblk:\n%v\n", &wblk)

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

		nc++
		continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, pBOTTOMRIGHT)
		contPivot3x1to2x1(
			&pT,
			&pB, &p0, &p1, p, pBOTTOM)
	}
	return err, nc
}