tweak glop crash code

This commit is contained in:
Laurent Perron
2018-07-24 08:28:16 -07:00
parent f73841ef38
commit 1d07ca59d0
7 changed files with 45 additions and 34 deletions

View File

@@ -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_;
}

View File

@@ -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|

View File

@@ -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,

View File

@@ -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).

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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());