예제 #1
0
// replaceBland uses the Bland rule to find the indices to swap if the minimum
// move is 0. The indices to be swapped are replace and minIdx (following the
// nomenclature in the main routine).
func replaceBland(A mat64.Matrix, ab *mat64.Dense, xb []float64, basicIdxs, nonBasicIdx []int, r, move []float64) (replace, minIdx int, err error) {
	// Use the traditional bland rule, except don't replace a constraint which
	// causes the new ab to be singular.
	for i, v := range r {
		if v > -blandNegTol {
			continue
		}
		minIdx = i
		err = computeMove(move, minIdx, A, ab, xb, nonBasicIdx)
		if err != nil {
			// Either unbounded or something went wrong.
			return -1, -1, err
		}
		replace = floats.MinIdx(move)
		if math.Abs(move[replace]) > blandZeroTol {
			// Large enough that it shouldn't be a problem
			return replace, minIdx, nil
		}
		// Find a zero index where replacement is non-singular.
		biCopy := make([]int, len(basicIdxs))
		for replace, v := range move {
			if v > blandZeroTol {
				continue
			}
			copy(biCopy, basicIdxs)
			biCopy[replace] = nonBasicIdx[minIdx]
			abTmp := extractColumns(A, biCopy)
			// If the condition number is reasonable, use this index.
			if mat64.Cond(abTmp, 1) < 1e16 {
				return replace, minIdx, nil
			}
		}
	}
	return -1, -1, ErrBland
}
예제 #2
0
// linearlyDependent returns whether the vector is linearly dependent
// with the columns of A. It assumes that A is a full-rank matrix.
func linearlyDependent(vec *mat64.Vector, A mat64.Matrix) bool {
	// Add vec to the columns of A, and see if the condition number is reasonable.
	m, n := A.Dims()
	aNew := mat64.NewDense(m, n+1, nil)
	aNew.Copy(A)
	col := mat64.Col(nil, 0, vec)
	aNew.SetCol(n, col)
	cond := mat64.Cond(aNew, 1)
	return cond > 1e12
}