minor sync with internal code

This commit is contained in:
Laurent Perron
2016-12-09 14:15:01 +01:00
parent 2e89b3c0b8
commit ea71f58ef2
6 changed files with 64 additions and 22 deletions

View File

@@ -40,7 +40,7 @@ void FapModelPrinter::PrintFapVariables() {
for (const int value : it.second.domain) {
StringAppendF(&domain, "%d ", value);
}
StringAppendF(&domain, "}");
domain.append("}");
std::string hard = " ";
if (it.second.hard) {

View File

@@ -337,6 +337,9 @@ int Run() {
printf("s UNSATISFIABLE\n");
}
// Print status.
printf("c status: %s\n", SatStatusString(result).c_str());
// Print objective value.
if (solution.empty()) {
printf("c objective: na\n");
@@ -349,13 +352,13 @@ int Run() {
}
// Print final statistics.
printf("c status: %s\n", SatStatusString(result).c_str());
printf("c booleans: %d\n", solver->NumVariables());
printf("c conflicts: %lld\n", solver->num_failures());
printf("c branches: %lld\n", solver->num_branches());
printf("c propagations: %lld\n", solver->num_propagations());
printf("c walltime: %f\n", wall_timer.Get());
printf("c usertime: %f\n", user_timer.Get());
printf("c deterministic time: %f\n", solver->deterministic_time());
printf("c deterministic_time: %f\n", solver->deterministic_time());
// The SAT competition requires a particular exit code and since we don't
// really use it for any other purpose, we comply.

View File

@@ -194,6 +194,39 @@ void LPSolver::Clear() {
revised_simplex_.reset(nullptr);
}
void LPSolver::SetInitialBasis(
const VariableStatusRow& variable_statuses,
const ConstraintStatusColumn& constraint_statuses) {
// Create the associated basis state.
BasisState state;
state.statuses = variable_statuses;
for (const ConstraintStatus status : constraint_statuses) {
// Note the change of upper/lower bound between the status of a constraint
// and the status of its associated slack variable.
switch (status) {
case ConstraintStatus::FREE:
state.statuses.push_back(VariableStatus::FREE);
break;
case ConstraintStatus::AT_LOWER_BOUND:
state.statuses.push_back(VariableStatus::AT_UPPER_BOUND);
break;
case ConstraintStatus::AT_UPPER_BOUND:
state.statuses.push_back(VariableStatus::AT_LOWER_BOUND);
break;
case ConstraintStatus::FIXED_VALUE:
state.statuses.push_back(VariableStatus::FIXED_VALUE);
break;
case ConstraintStatus::BASIC:
state.statuses.push_back(VariableStatus::BASIC);
break;
}
}
if (revised_simplex_ == nullptr) {
revised_simplex_.reset(new RevisedSimplex());
}
revised_simplex_->LoadStateForNextSolve(state);
}
namespace {
// Computes the "real" problem objective from the one without offset nor
// scaling.

View File

@@ -63,6 +63,23 @@ class LPSolver {
// result, assuming that no time limit was specified.
void Clear();
// Advanced usage. This should be called before calling Solve(). It will
// configure the solver to try to start from the given point. Note that
// calling Clear() will invalidate this information.
//
// If the set of variables/constraints with a BASIC status does not form a
// basis a warning will be logged and the code will ignore it. Otherwise, the
// non-basic variables will be initialized to their given status and solving
// will start from there (even if the solution is not primal/dual feasible).
//
// Important: There is no facility to transform this information in sync with
// presolve. So you should probably disable presolve when using this since
// otherwise there is a good chance that the matrix will change and that the
// given basis will make no sense. Even worse if it happens to be factorizable
// but doesn't correspond to what was intended.
void SetInitialBasis(const VariableStatusRow& variable_statuses,
const ConstraintStatusColumn& constraint_statuses);
// This loads a given solution and computes related quantities so that the
// getters below will refer to it.
//

View File

@@ -118,8 +118,6 @@ RevisedSimplex::RevisedSimplex()
void RevisedSimplex::ClearStateForNextSolve() {
SCOPED_TIME_STAT(&function_stats_);
solution_state_.num_rows = RowIndex(0);
solution_state_.num_cols = ColIndex(0);
solution_state_.statuses.clear();
}
@@ -834,10 +832,8 @@ void RevisedSimplex::InitializeVariableStatusesForWarmStart(
// Start with the given "warm" status from the BasisState if it exists.
VariableStatus status = default_status;
if (col < num_cols_) {
if (col < state.num_cols) {
status = state.statuses[col];
}
if (col < state.statuses.size()) {
status = state.statuses[col];
}
// Remove incompatibilities between the warm status and the variable bounds.
@@ -1176,8 +1172,6 @@ void RevisedSimplex::DisplayBasicVariableStatistics() {
void RevisedSimplex::SaveState() {
DCHECK_EQ(num_cols_, variables_info_.GetStatusRow().size());
solution_state_.num_rows = num_rows_;
solution_state_.num_cols = num_cols_;
solution_state_.statuses = variables_info_.GetStatusRow();
solution_state_has_been_set_externally_ = false;
}

View File

@@ -120,24 +120,19 @@
namespace operations_research {
namespace glop {
// This is the minimal amount of information needed to perform a "warm start".
// Holds the statuses of the all the variables, including slack variables. There
// is no point storing constraint statuses since internally all constraints are
// always fixed to zero.
//
// Holds the statuses of the variables and the slack variables. Using this
// information and the original linear program, the basis can be refactorized
// and all the needed quantities derived.
// Note that this is the minimal amount of information needed to perform a "warm
// start". Using this information and the original linear program, the basis can
// be refactorized and all the needed quantities derived.
//
// TODO(user): Introduce another state class to store a complete state of the
// solver. Using this state and the original linear program, the solver can be
// restarted with as little time overhead as possible. This is especially useful
// for strong branching in a MIP context.
struct BasisState {
// The linear program size for which this state was saved.
RowIndex num_rows;
ColIndex num_cols;
// This vector first contains the num_cols normal variable statuses and then
// the num_rows slack variable statuses.
//
// TODO(user): A MIP solver will potentially store a lot of BasicStates so
// memory usage is important. It is possible to use only 2 bits for one
// VariableStatus enum. To achieve this, the FIXED_VALUE status can be