tweak glop crash code
This commit is contained in:
@@ -552,6 +552,14 @@ Fractional BasisFactorization::ComputeInfinityNormConditionNumber() const {
|
||||
return ComputeInfinityNorm() * ComputeInverseInfinityNorm();
|
||||
}
|
||||
|
||||
Fractional BasisFactorization::ComputeInfinityNormConditionNumberUpperBound()
|
||||
const {
|
||||
if (IsIdentityBasis()) return 1.0;
|
||||
BumpDeterministicTimeForSolve(matrix_.num_rows().value());
|
||||
return ComputeInfinityNorm() *
|
||||
lu_factorization_.ComputeInverseInfinityNormUpperBound();
|
||||
}
|
||||
|
||||
double BasisFactorization::DeterministicTime() const {
|
||||
return deterministic_time_;
|
||||
}
|
||||
|
||||
@@ -239,6 +239,7 @@ class BasisFactorization {
|
||||
// A condition number greater than 1E7 will lead to precision problems.
|
||||
Fractional ComputeOneNormConditionNumber() const;
|
||||
Fractional ComputeInfinityNormConditionNumber() const;
|
||||
Fractional ComputeInfinityNormConditionNumberUpperBound() const;
|
||||
|
||||
// Computes the 1-norm of B.
|
||||
// The 1-norm |A| is defined as max_j sum_i |a_ij|
|
||||
|
||||
@@ -95,18 +95,18 @@ void InitialBasis::CompleteBixbyBasis(ColIndex num_cols,
|
||||
}
|
||||
}
|
||||
|
||||
bool InitialBasis::CompleteTriangularPrimalBasis(ColIndex num_cols,
|
||||
void InitialBasis::CompleteTriangularPrimalBasis(ColIndex num_cols,
|
||||
RowToColMapping* basis) {
|
||||
return CompleteTriangularBasis<false>(num_cols, basis);
|
||||
}
|
||||
|
||||
bool InitialBasis::CompleteTriangularDualBasis(ColIndex num_cols,
|
||||
void InitialBasis::CompleteTriangularDualBasis(ColIndex num_cols,
|
||||
RowToColMapping* basis) {
|
||||
return CompleteTriangularBasis<true>(num_cols, basis);
|
||||
}
|
||||
|
||||
template <bool only_allow_zero_cost_column>
|
||||
bool InitialBasis::CompleteTriangularBasis(ColIndex num_cols,
|
||||
void InitialBasis::CompleteTriangularBasis(ColIndex num_cols,
|
||||
RowToColMapping* basis) {
|
||||
// Initialize can_be_replaced.
|
||||
const RowIndex num_rows = matrix_.num_rows();
|
||||
@@ -150,14 +150,6 @@ bool InitialBasis::CompleteTriangularBasis(ColIndex num_cols,
|
||||
queue(residual_singleton_column.begin(), residual_singleton_column.end(),
|
||||
triangular_column_comparator_);
|
||||
|
||||
// If the the product magnitude of the diagonal coefficients become smaller
|
||||
// than a given threshold, we will assume that this method returns an instable
|
||||
// first basis. The threshold is somewhat arbitrary and is mainly here to
|
||||
// avoid an infinite inverse product which will trigger floating point
|
||||
// exceptions in other part of the code.
|
||||
const double kMinimumProductMagnitude = 1e-100;
|
||||
double partial_diagonal_product = 1.0;
|
||||
|
||||
// Process the residual singleton columns by priority and add them to the
|
||||
// basis if their "diagonal" coefficient is not too small.
|
||||
while (!queue.empty()) {
|
||||
@@ -182,14 +174,6 @@ bool InitialBasis::CompleteTriangularBasis(ColIndex num_cols,
|
||||
if (std::abs(coeff) < kStabilityThreshold * max_magnitude) continue;
|
||||
DCHECK_NE(kInvalidRow, row);
|
||||
|
||||
partial_diagonal_product *= coeff;
|
||||
if (std::abs(partial_diagonal_product) < kMinimumProductMagnitude) {
|
||||
VLOG(1) << "Numerical difficulties detected. The product of the "
|
||||
<< "diagonal coefficients is currently equal to "
|
||||
<< partial_diagonal_product;
|
||||
break;
|
||||
}
|
||||
|
||||
// Use this candidate column in the basis.
|
||||
(*basis)[row] = candidate;
|
||||
can_be_replaced[row] = false;
|
||||
@@ -202,8 +186,6 @@ bool InitialBasis::CompleteTriangularBasis(ColIndex num_cols,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::abs(partial_diagonal_product) >= kMinimumProductMagnitude;
|
||||
}
|
||||
|
||||
void InitialBasis::ComputeCandidates(ColIndex num_cols,
|
||||
|
||||
@@ -62,8 +62,8 @@ class InitialBasis {
|
||||
//
|
||||
// Returns false if an error occurred during the algorithm (numerically
|
||||
// instable basis).
|
||||
bool CompleteTriangularPrimalBasis(ColIndex num_cols, RowToColMapping* basis);
|
||||
bool CompleteTriangularDualBasis(ColIndex num_cols, RowToColMapping* basis);
|
||||
void CompleteTriangularPrimalBasis(ColIndex num_cols, RowToColMapping* basis);
|
||||
void CompleteTriangularDualBasis(ColIndex num_cols, RowToColMapping* basis);
|
||||
|
||||
// Visible for testing. Computes a list of candidate column indices out of the
|
||||
// fist num_candidate_columns of A and sorts them using the
|
||||
@@ -74,7 +74,7 @@ class InitialBasis {
|
||||
private:
|
||||
// Internal implementation of the Primal/Dual CompleteTriangularBasis().
|
||||
template <bool only_allow_zero_cost_column>
|
||||
bool CompleteTriangularBasis(ColIndex num_cols, RowToColMapping* basis);
|
||||
void CompleteTriangularBasis(ColIndex num_cols, RowToColMapping* basis);
|
||||
|
||||
// Returns an integer representing the order (the lower the better)
|
||||
// between column categories (known as C2, C3 or C4 in the paper).
|
||||
|
||||
@@ -512,6 +512,11 @@ Fractional LuFactorization::ComputeInfinityNormConditionNumber(
|
||||
return matrix.ComputeInfinityNorm() * ComputeInverseInfinityNorm();
|
||||
}
|
||||
|
||||
Fractional LuFactorization::ComputeInverseInfinityNormUpperBound() const {
|
||||
return lower_.ComputeInverseInfinityNormUpperBound() *
|
||||
upper_.ComputeInverseInfinityNormUpperBound();
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Returns the density of the sparse column 'b' w.r.t. the given permutation.
|
||||
double ComputeDensity(const SparseColumn& b, const RowPermutation& row_perm) {
|
||||
|
||||
@@ -175,6 +175,7 @@ class LuFactorization {
|
||||
// TODO(user): separate this from LuFactorization.
|
||||
Fractional ComputeOneNormConditionNumber(const MatrixView& matrix) const;
|
||||
Fractional ComputeInfinityNormConditionNumber(const MatrixView& matrix) const;
|
||||
Fractional ComputeInverseInfinityNormUpperBound() const;
|
||||
|
||||
// Sets the current parameters.
|
||||
void SetParameters(const GlopParameters& parameters) {
|
||||
|
||||
@@ -998,10 +998,7 @@ Status RevisedSimplex::CreateInitialBasis() {
|
||||
InitialBasis initial_basis(matrix_with_slack_, objective_, lower_bound_,
|
||||
upper_bound_, variables_info_.GetTypeRow());
|
||||
|
||||
if (parameters_.use_dual_simplex()) {
|
||||
// This dual version only uses zero-cost columns to complete the basis.
|
||||
initial_basis.CompleteTriangularDualBasis(num_cols_, &basis);
|
||||
} else if (parameters_.initial_basis() == GlopParameters::BIXBY) {
|
||||
if (parameters_.initial_basis() == GlopParameters::BIXBY) {
|
||||
if (parameters_.use_scaling()) {
|
||||
initial_basis.CompleteBixbyBasis(first_slack_col_, &basis);
|
||||
} else {
|
||||
@@ -1009,15 +1006,31 @@ Status RevisedSimplex::CreateInitialBasis() {
|
||||
<< "to be scaled. Skipping Bixby's algorithm.";
|
||||
}
|
||||
} else if (parameters_.initial_basis() == GlopParameters::TRIANGULAR) {
|
||||
const RowToColMapping basis_copy = basis;
|
||||
|
||||
// Note the use of num_cols_ here because this algorithm
|
||||
// benefits from treating fixed slack columns like any other column.
|
||||
RowToColMapping basis_copy = basis;
|
||||
if (!initial_basis.CompleteTriangularPrimalBasis(num_cols_, &basis)) {
|
||||
VLOG(1) << "Reverting to Bixby's initial basis algorithm.";
|
||||
if (parameters_.use_dual_simplex()) {
|
||||
// This dual version only uses zero-cost columns to complete the
|
||||
// basis.
|
||||
initial_basis.CompleteTriangularDualBasis(num_cols_, &basis);
|
||||
} else {
|
||||
initial_basis.CompleteTriangularPrimalBasis(num_cols_, &basis);
|
||||
}
|
||||
const Status status = InitializeFirstBasis(basis);
|
||||
|
||||
// Check that the upper bound on the condition number of LU is below
|
||||
// 1e50. We have chosen an arbitrarily high threshold, because the
|
||||
// purpose of this code is to just revert to the "safe" basis on large
|
||||
// problematic problem when we observed an "infinity" condition number
|
||||
// (on cond11.mps).
|
||||
if (status.ok() &&
|
||||
basis_factorization_
|
||||
.ComputeInfinityNormConditionNumberUpperBound() < 1e50) {
|
||||
return status;
|
||||
} else {
|
||||
VLOG(1) << "Reverting to all slack basis.";
|
||||
basis = basis_copy;
|
||||
if (parameters_.use_scaling()) {
|
||||
initial_basis.CompleteBixbyBasis(first_slack_col_, &basis);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
VLOG(1) << "Unsupported initial_basis parameters: "
|
||||
@@ -1040,6 +1053,7 @@ Status RevisedSimplex::InitializeFirstBasis(const RowToColMapping& basis) {
|
||||
}
|
||||
variables_info_.Update(basis_[row], VariableStatus::BASIC);
|
||||
}
|
||||
|
||||
GLOP_RETURN_IF_ERROR(basis_factorization_.Initialize());
|
||||
PermuteBasis();
|
||||
DCHECK(BasisIsConsistent());
|
||||
|
||||
Reference in New Issue
Block a user