internal API

This commit is contained in:
Laurent Perron
2019-01-02 20:19:25 +01:00
parent d5c49ee23a
commit b4c3e832a1
8 changed files with 106 additions and 0 deletions

View File

@@ -415,6 +415,18 @@ void BasisFactorization::LeftSolveForUnitRow(ColIndex j,
y->SortNonZerosIfNeeded();
}
void BasisFactorization::TemporaryLeftSolveForUnitRow(ColIndex j,
ScatteredRow* y) const {
CHECK(IsRefactorized());
SCOPED_TIME_STAT(&stats_);
RETURN_IF_NULL(y);
BumpDeterministicTimeForSolve(1);
ClearAndResizeVectorWithNonZeros(RowToColIndex(matrix_.num_rows()), y);
lu_factorization_.LeftSolveUForUnitRow(j, y);
lu_factorization_.LeftSolveLWithNonZeros(y, nullptr);
y->SortNonZerosIfNeeded();
}
void BasisFactorization::RightSolveForProblemColumn(ColIndex col,
ScatteredColumn* d) const {
SCOPED_TIME_STAT(&stats_);

View File

@@ -211,6 +211,9 @@ class BasisFactorization {
// coefficient of value 1.0 at position 'j'.
void LeftSolveForUnitRow(ColIndex j, ScatteredRow* y) const;
// Same as LeftSolveForUnitRow() but does not update any internal data.
void TemporaryLeftSolveForUnitRow(ColIndex j, ScatteredRow* y) const;
// Right solves the system B.d = a where the input is the initial value of d.
void RightSolve(ScatteredColumn* d) const;

View File

@@ -218,6 +218,10 @@ class RevisedSimplex {
// class.
ColIndex GetBasis(RowIndex row) const;
const ScatteredRow& GetUnitRowLeftInverse(RowIndex row) {
return update_row_.ComputeAndGetUnitRowLeftInverse(row);
}
// Returns a copy of basis_ vector for outside applications (like cuts) to
// have the correspondence between rows and columns of the dictionary.
RowToColMapping GetBasisVector() const { return basis_; }

View File

@@ -57,6 +57,14 @@ const ScatteredRow& UpdateRow::GetUnitRowLeftInverse() const {
return unit_row_left_inverse_;
}
const ScatteredRow& UpdateRow::ComputeAndGetUnitRowLeftInverse(
RowIndex leaving_row) {
Invalidate();
basis_factorization_.TemporaryLeftSolveForUnitRow(RowToColIndex(leaving_row),
&unit_row_left_inverse_);
return unit_row_left_inverse_;
}
void UpdateRow::ComputeUnitRowLeftInverse(RowIndex leaving_row) {
SCOPED_TIME_STAT(&stats_);
basis_factorization_.LeftSolveForUnitRow(RowToColIndex(leaving_row),

View File

@@ -92,6 +92,10 @@ class UpdateRow {
return DeterministicTimeForFpOperations(num_operations_);
}
// This returns the asked unit row left inverse. It temporarily invalidate
// the class state by calling Invalidate().
const ScatteredRow& ComputeAndGetUnitRowLeftInverse(RowIndex leaving_row);
private:
// Computes the left inverse of the given unit row, and stores it in
// unit_row_left_inverse_.

View File

@@ -73,6 +73,11 @@ inline double ToDouble(IntegerValue value) {
return static_cast<double>(value.value());
}
template <class IntType>
inline IntType IntTypeAbs(IntType t) {
return IntType(std::abs(t.value()));
}
inline IntegerValue CeilRatio(IntegerValue dividend,
IntegerValue positive_divisor) {
CHECK_GT(positive_divisor, 0);

View File

@@ -27,5 +27,65 @@ double ComputeActivity(const LinearConstraint& constraint,
return activity;
}
namespace {
// TODO(user): Template for any integer type and expose this?
IntegerValue ComputeGcd(const std::vector<IntegerValue>& values) {
if (values.empty()) return IntegerValue(1);
IntegerValue gcd = IntTypeAbs(values.front());
const int size = values.size();
for (int i = 1; i < size; ++i) {
// GCD(gcd, value) = GCD(value, gcd % value);
IntegerValue value = IntTypeAbs(values[i]);
while (value != 0) {
const IntegerValue r = gcd % value;
gcd = value;
value = r;
}
if (gcd == 1) break;
}
return gcd;
}
} // namespace
void DivideByGCD(LinearConstraint* constraint) {
if (constraint->coeffs.empty()) return;
const IntegerValue gcd = ComputeGcd(constraint->coeffs);
if (gcd == 1) return;
if (constraint->lb > kMinIntegerValue) {
constraint->lb = CeilRatio(constraint->lb, gcd);
}
if (constraint->ub < kMaxIntegerValue) {
constraint->ub = FloorRatio(constraint->ub, gcd);
}
for (IntegerValue& coeff : constraint->coeffs) coeff /= gcd;
}
void RemoveZeroTerms(LinearConstraint* constraint) {
int new_size = 0;
const int size = constraint->vars.size();
for (int i = 0; i < size; ++i) {
if (constraint->coeffs[i] == 0) continue;
constraint->vars[new_size] = constraint->vars[i];
constraint->coeffs[new_size] = constraint->coeffs[i];
++new_size;
}
constraint->vars.resize(new_size);
constraint->coeffs.resize(new_size);
}
void MakeAllCoefficientsPositive(LinearConstraint* constraint) {
const int size = constraint->vars.size();
for (int i = 0; i < size; ++i) {
const IntegerValue coeff = constraint->coeffs[i];
if (coeff < 0) {
constraint->coeffs[i] = -coeff;
constraint->vars[i] = NegationOf(constraint->vars[i]);
}
}
}
} // namespace sat
} // namespace operations_research

View File

@@ -174,6 +174,16 @@ class LinearConstraintBuilder {
double ComputeActivity(const LinearConstraint& constraint,
const gtl::ITIVector<IntegerVariable, double>& values);
// Computes the GCD of the constraint coefficient, and divide them by it. This
// also tighten the constraint bounds assumming all the variables are integer.
void DivideByGCD(LinearConstraint* constraint);
// Removes the entries with a coefficient of zero.
void RemoveZeroTerms(LinearConstraint* constraint);
// Makes all coefficients positive by transforming a variable to its negation.
void MakeAllCoefficientsPositive(LinearConstraint* constraint);
} // namespace sat
} // namespace operations_research