00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <stddef.h>
00016 #include "base/hash.h"
00017 #include <string>
00018 #include <vector>
00019
00020 #include "base/commandlineflags.h"
00021 #include "base/integral_types.h"
00022 #include "base/logging.h"
00023 #include "base/scoped_ptr.h"
00024 #include "base/stringprintf.h"
00025 #include "base/timer.h"
00026 #include "base/concise_iterator.h"
00027 #include "base/hash.h"
00028 #include "linear_solver/linear_solver.h"
00029
00030 #if defined(USE_SCIP)
00031
00032 #include "scip/scip.h"
00033 #include "scip/scipdefplugins.h"
00034
00035
00036
00037
00038
00039
00040
00041
00042 #define ORTOOLS_SCIP_CALL(x) CHECK_EQ(SCIP_OKAY, x)
00043
00044 DECLARE_double(solver_timeout_in_seconds);
00045 DECLARE_string(solver_write_model);
00046
00047 namespace operations_research {
00048
00049 class SCIPInterface : public MPSolverInterface {
00050 public:
00051
00052 explicit SCIPInterface(MPSolver* const solver);
00053 ~SCIPInterface();
00054
00055
00056 virtual void SetOptimizationDirection(bool maximize);
00057
00058
00059
00060 virtual MPSolver::ResultStatus Solve(const MPSolverParameters& param);
00061
00062
00063
00064 virtual void Reset();
00065
00066
00067 virtual void SetVariableBounds(int var_index, double lb, double ub);
00068 virtual void SetVariableInteger(int var_index, bool integer);
00069 virtual void SetConstraintBounds(int row_index, double lb, double ub);
00070
00071
00072 void AddRowConstraint(MPConstraint* const ct);
00073
00074 void AddVariable(MPVariable* const var);
00075
00076 virtual void SetCoefficient(MPConstraint* const constraint,
00077 const MPVariable* const variable,
00078 double new_value,
00079 double old_value);
00080
00081 virtual void ClearConstraint(MPConstraint* const constraint);
00082
00083 virtual void SetObjectiveCoefficient(const MPVariable* const variable,
00084 double coefficient);
00085
00086 virtual void SetObjectiveOffset(double value);
00087
00088 virtual void ClearObjective();
00089
00090
00091
00092 virtual int64 iterations() const;
00093
00094 virtual int64 nodes() const;
00095
00096 virtual double best_objective_bound() const;
00097
00098
00099 virtual MPSolver::BasisStatus row_status(int constraint_index) const {
00100 LOG(FATAL) << "Basis status only available for continuous problems";
00101 return MPSolver::FREE;
00102 }
00103
00104 virtual MPSolver::BasisStatus column_status(int variable_index) const {
00105 LOG(FATAL) << "Basis status only available for continuous problems";
00106 return MPSolver::FREE;
00107 }
00108
00109
00110
00111 virtual void WriteModel(const string& filename);
00112
00113
00114 virtual bool IsContinuous() const { return false; }
00115 virtual bool IsLP() const { return false; }
00116 virtual bool IsMIP() const { return true; }
00117
00118 virtual void ExtractNewVariables();
00119 virtual void ExtractNewConstraints();
00120 virtual void ExtractObjective();
00121
00122 virtual string SolverVersion() const {
00123 return StringPrintf("SCIP %d.%d.%d [LP solver: %s]",
00124 SCIPmajorVersion(), SCIPminorVersion(),
00125 SCIPtechVersion(), SCIPlpiGetSolverName());
00126 }
00127
00128 virtual void* underlying_solver() {
00129 return reinterpret_cast<void*>(scip_);
00130 }
00131
00132 virtual double ComputeExactConditionNumber() const {
00133 LOG(FATAL) << "Condition number only available for continuous problems";
00134 return 0.0;
00135 }
00136
00137 private:
00138
00139 virtual void SetParameters(const MPSolverParameters& param);
00140
00141 virtual void SetRelativeMipGap(double value);
00142 virtual void SetPrimalTolerance(double value);
00143 virtual void SetDualTolerance(double value);
00144 virtual void SetPresolveMode(int value);
00145 virtual void SetLpAlgorithm(int value);
00146
00147 void CreateSCIP();
00148 void DeleteSCIP();
00149
00150 SCIP* scip_;
00151 std::vector<SCIP_VAR*> scip_variables_;
00152 std::vector<SCIP_CONS*> scip_constraints_;
00153 };
00154
00155
00156 SCIPInterface::SCIPInterface(MPSolver* const solver)
00157 : MPSolverInterface(solver), scip_(NULL) {
00158 CreateSCIP();
00159 }
00160
00161
00162 SCIPInterface::~SCIPInterface() {
00163 DeleteSCIP();
00164 }
00165
00166 void SCIPInterface::Reset() {
00167 DeleteSCIP();
00168 CreateSCIP();
00169 ResetExtractionInformation();
00170 }
00171
00172 void SCIPInterface::CreateSCIP() {
00173 ORTOOLS_SCIP_CALL(SCIPcreate(&scip_));
00174 ORTOOLS_SCIP_CALL(SCIPincludeDefaultPlugins(scip_));
00175 ORTOOLS_SCIP_CALL(SCIPcreateProb(
00176 scip_, solver_->name_.c_str(),
00177 NULL, NULL, NULL, NULL, NULL, NULL, NULL));
00178 ORTOOLS_SCIP_CALL(SCIPsetObjsense(
00179 scip_, maximize_ ? SCIP_OBJSENSE_MAXIMIZE : SCIP_OBJSENSE_MINIMIZE));
00180
00181
00182 SCIP_VAR* scip_var = NULL;
00183
00184 double dummy_obj_coef = 0.0;
00185 ORTOOLS_SCIP_CALL(SCIPcreateVar(
00186 scip_, &scip_var, "dummy",
00187 1.0, 1.0, dummy_obj_coef,
00188 SCIP_VARTYPE_CONTINUOUS,
00189 true, false, NULL, NULL, NULL, NULL, NULL));
00190 ORTOOLS_SCIP_CALL(SCIPaddVar(scip_, scip_var));
00191 scip_variables_.push_back(scip_var);
00192 }
00193
00194 void SCIPInterface::DeleteSCIP() {
00195 CHECK_NOTNULL(scip_);
00196 for (int i = 0; i < scip_variables_.size(); ++i) {
00197 ORTOOLS_SCIP_CALL(SCIPreleaseVar(scip_, &scip_variables_[i]));
00198 }
00199 scip_variables_.clear();
00200 for (int j = 0; j < scip_constraints_.size(); ++j) {
00201 ORTOOLS_SCIP_CALL(SCIPreleaseCons(scip_, &scip_constraints_[j]));
00202 }
00203 scip_constraints_.clear();
00204 ORTOOLS_SCIP_CALL(SCIPfree(&scip_));
00205 scip_ = NULL;
00206 }
00207
00208 void SCIPInterface::WriteModel(const string& filename) {
00209
00210
00211 ORTOOLS_SCIP_CALL(SCIPsetDefaultMessagehdlr());
00212 ORTOOLS_SCIP_CALL(SCIPwriteOrigProblem(scip_, filename.c_str(), NULL, false));
00213
00214 if (quiet_) {
00215 ORTOOLS_SCIP_CALL(SCIPsetMessagehdlr(NULL));
00216 }
00217 }
00218
00219
00220
00221
00222 void SCIPInterface::SetOptimizationDirection(bool maximize) {
00223 InvalidateSolutionSynchronization();
00224 ORTOOLS_SCIP_CALL(SCIPfreeTransform(scip_));
00225 ORTOOLS_SCIP_CALL(SCIPsetObjsense(
00226 scip_, maximize ? SCIP_OBJSENSE_MAXIMIZE : SCIP_OBJSENSE_MINIMIZE));
00227 }
00228
00229 void SCIPInterface::SetVariableBounds(int var_index, double lb, double ub) {
00230 InvalidateSolutionSynchronization();
00231 if (var_index != kNoIndex) {
00232
00233 DCHECK_LE(var_index, last_variable_index_);
00234 ORTOOLS_SCIP_CALL(SCIPfreeTransform(scip_));
00235 ORTOOLS_SCIP_CALL(SCIPchgVarLb(scip_, scip_variables_[var_index], lb));
00236 ORTOOLS_SCIP_CALL(SCIPchgVarUb(scip_, scip_variables_[var_index], ub));
00237 } else {
00238 sync_status_ = MUST_RELOAD;
00239 }
00240 }
00241
00242 void SCIPInterface::SetVariableInteger(int var_index, bool integer) {
00243 InvalidateSolutionSynchronization();
00244 if (var_index != kNoIndex) {
00245
00246 ORTOOLS_SCIP_CALL(SCIPfreeTransform(scip_));
00247 #if (SCIP_VERSION >= 210)
00248 SCIP_Bool infeasible = false;
00249 ORTOOLS_SCIP_CALL(SCIPchgVarType(
00250 scip_, scip_variables_[var_index],
00251 integer ? SCIP_VARTYPE_INTEGER : SCIP_VARTYPE_CONTINUOUS,
00252 &infeasible));
00253 #else
00254 ORTOOLS_SCIP_CALL(SCIPchgVarType(
00255 scip_, scip_variables_[var_index],
00256 integer ? SCIP_VARTYPE_INTEGER : SCIP_VARTYPE_CONTINUOUS));
00257 #endif // SCIP_VERSION >= 210
00258 } else {
00259 sync_status_ = MUST_RELOAD;
00260 }
00261 }
00262
00263 void SCIPInterface::SetConstraintBounds(int index, double lb, double ub) {
00264 InvalidateSolutionSynchronization();
00265 if (index != kNoIndex) {
00266
00267 DCHECK_LE(index, last_constraint_index_);
00268 ORTOOLS_SCIP_CALL(SCIPfreeTransform(scip_));
00269 ORTOOLS_SCIP_CALL(SCIPchgLhsLinear(scip_, scip_constraints_[index], lb));
00270 ORTOOLS_SCIP_CALL(SCIPchgRhsLinear(scip_, scip_constraints_[index], ub));
00271 } else {
00272 sync_status_ = MUST_RELOAD;
00273 }
00274 }
00275
00276 void SCIPInterface::SetCoefficient(MPConstraint* const constraint,
00277 const MPVariable* const variable,
00278 double new_value,
00279 double old_value) {
00280 InvalidateSolutionSynchronization();
00281 const int constraint_index = constraint->index();
00282 const int variable_index = variable->index();
00283 if (constraint_index != kNoIndex && variable_index != kNoIndex) {
00284
00285
00286 DCHECK_LE(constraint_index, last_constraint_index_);
00287 DCHECK_LE(variable_index, last_variable_index_);
00288
00289
00290 ORTOOLS_SCIP_CALL(SCIPfreeTransform(scip_));
00291 ORTOOLS_SCIP_CALL(SCIPaddCoefLinear(
00292 scip_, scip_constraints_[constraint_index],
00293 scip_variables_[variable_index], new_value - old_value));
00294 } else {
00295
00296
00297 sync_status_ = MUST_RELOAD;
00298 }
00299 }
00300
00301
00302 void SCIPInterface::ClearConstraint(MPConstraint* const constraint) {
00303 InvalidateSolutionSynchronization();
00304 const int constraint_index = constraint->index();
00305
00306 if (constraint_index != kNoIndex) {
00307 for (ConstIter<hash_map<const MPVariable*, double> >
00308 it(constraint->coefficients_); !it.at_end(); ++it) {
00309 const int var_index = it->first->index();
00310 const double old_coef_value = it->second;
00311 DCHECK_NE(kNoIndex, var_index);
00312 ORTOOLS_SCIP_CALL(SCIPfreeTransform(scip_));
00313
00314 ORTOOLS_SCIP_CALL(SCIPaddCoefLinear(
00315 scip_, scip_constraints_[constraint_index],
00316 scip_variables_[var_index], -old_coef_value));
00317 }
00318 }
00319 }
00320
00321
00322 void SCIPInterface::SetObjectiveCoefficient(const MPVariable* const variable,
00323 double coefficient) {
00324 sync_status_ = MUST_RELOAD;
00325 }
00326
00327
00328 void SCIPInterface::SetObjectiveOffset(double value) {
00329 sync_status_ = MUST_RELOAD;
00330 }
00331
00332
00333 void SCIPInterface::ClearObjective() {
00334 InvalidateSolutionSynchronization();
00335 ORTOOLS_SCIP_CALL(SCIPfreeTransform(scip_));
00336
00337 for (ConstIter<hash_map<const MPVariable*, double> >
00338 it(solver_->objective_->coefficients_);
00339 !it.at_end(); ++it) {
00340 const int var_index = it->first->index();
00341
00342 if (var_index == kNoIndex) {
00343 DCHECK_NE(MODEL_SYNCHRONIZED, sync_status_);
00344 } else {
00345 ORTOOLS_SCIP_CALL(SCIPchgVarObj(scip_, scip_variables_[var_index], 0.0));
00346 }
00347 }
00348
00349 ORTOOLS_SCIP_CALL(SCIPchgVarObj(scip_, scip_variables_[0], 0.0));
00350 }
00351
00352 void SCIPInterface::AddRowConstraint(MPConstraint* const ct) {
00353 sync_status_ = MUST_RELOAD;
00354 }
00355
00356 void SCIPInterface::AddVariable(MPVariable* const var) {
00357 sync_status_ = MUST_RELOAD;
00358 }
00359
00360
00361 void SCIPInterface::ExtractNewVariables() {
00362 int total_num_vars = solver_->variables_.size();
00363 if (total_num_vars > last_variable_index_) {
00364 ORTOOLS_SCIP_CALL(SCIPfreeTransform(scip_));
00365
00366 for (int j = last_variable_index_; j < total_num_vars; ++j) {
00367 MPVariable* const var = solver_->variables_[j];
00368 DCHECK_EQ(kNoIndex, var->index());
00369 var->set_index(j + 1);
00370 SCIP_VAR* scip_var = NULL;
00371
00372 double tmp_obj_coef = 0.0;
00373 ORTOOLS_SCIP_CALL(SCIPcreateVar(
00374 scip_, &scip_var, var->name().c_str(),
00375 var->lb(), var->ub(), tmp_obj_coef,
00376 var->integer() ? SCIP_VARTYPE_INTEGER : SCIP_VARTYPE_CONTINUOUS,
00377 true, false, NULL, NULL, NULL, NULL, NULL));
00378 ORTOOLS_SCIP_CALL(SCIPaddVar(scip_, scip_var));
00379 scip_variables_.push_back(scip_var);
00380 }
00381
00382 for (int i = 0; i < last_constraint_index_; i++) {
00383 MPConstraint* const ct = solver_->constraints_[i];
00384 for (ConstIter<hash_map<const MPVariable*, double> > it(
00385 ct->coefficients_);
00386 !it.at_end(); ++it) {
00387 const int var_index = it->first->index();
00388 DCHECK_NE(kNoIndex, var_index);
00389 if (var_index >= last_variable_index_ + 1) {
00390
00391
00392
00393 ORTOOLS_SCIP_CALL(SCIPaddCoefLinear(
00394 scip_, scip_constraints_[i],
00395 scip_variables_[var_index], it->second));
00396 }
00397 }
00398 }
00399 }
00400 }
00401
00402
00403 void SCIPInterface::ExtractNewConstraints() {
00404 int total_num_rows = solver_->constraints_.size();
00405 if (last_constraint_index_ < total_num_rows) {
00406 ORTOOLS_SCIP_CALL(SCIPfreeTransform(scip_));
00407
00408 int max_row_length = 0;
00409 for (int i = last_constraint_index_; i < total_num_rows; ++i) {
00410 MPConstraint* const ct = solver_->constraints_[i];
00411 DCHECK_EQ(kNoIndex, ct->index());
00412 ct->set_index(i);
00413 if (ct->coefficients_.size() > max_row_length) {
00414 max_row_length = ct->coefficients_.size();
00415 }
00416 }
00417 scoped_array<SCIP_VAR*> vars(new SCIP_VAR*[max_row_length]);
00418 scoped_array<double> coefs(new double[max_row_length]);
00419
00420 for (int i = last_constraint_index_; i < total_num_rows; ++i) {
00421 MPConstraint* const ct = solver_->constraints_[i];
00422 DCHECK_NE(kNoIndex, ct->index());
00423 int size = ct->coefficients_.size();
00424 int j = 0;
00425 for (ConstIter<hash_map<const MPVariable*, double> > it(
00426 ct->coefficients_);
00427 !it.at_end(); ++it) {
00428 const int index = it->first->index();
00429 DCHECK_NE(kNoIndex, index);
00430 vars[j] = scip_variables_[index];
00431 coefs[j] = it->second;
00432 j++;
00433 }
00434 SCIP_CONS* scip_constraint = NULL;
00435 ORTOOLS_SCIP_CALL(SCIPcreateConsLinear(
00436 scip_, &scip_constraint,
00437
00438 ct->name().empty() ? "" : ct->name().c_str(),
00439 size, vars.get(), coefs.get(),
00440 ct->lb(), ct->ub(),
00441 true, true, true, true, true, false, false, false, false, false));
00442 ORTOOLS_SCIP_CALL(SCIPaddCons(scip_, scip_constraint));
00443 scip_constraints_.push_back(scip_constraint);
00444 }
00445 }
00446 }
00447
00448 void SCIPInterface::ExtractObjective() {
00449 ORTOOLS_SCIP_CALL(SCIPfreeTransform(scip_));
00450
00451
00452 for (ConstIter<hash_map<const MPVariable*, double> >
00453 it(solver_->objective_->coefficients_);
00454 !it.at_end(); ++it) {
00455 int var_index = it->first->index();
00456 double obj_coef = it->second;
00457 ORTOOLS_SCIP_CALL(SCIPchgVarObj(
00458 scip_, scip_variables_[var_index], obj_coef));
00459 }
00460
00461
00462 ORTOOLS_SCIP_CALL(SCIPchgVarObj(
00463 scip_, scip_variables_[0], solver_->Objective().offset()));
00464 }
00465
00466
00467 MPSolver::ResultStatus SCIPInterface::Solve(const MPSolverParameters& param) {
00468 WallTimer timer;
00469 timer.Start();
00470
00471
00472 if (param.GetIntegerParam(MPSolverParameters::INCREMENTALITY) ==
00473 MPSolverParameters::INCREMENTALITY_OFF) {
00474 Reset();
00475 }
00476
00477
00478 if (quiet_) {
00479 ORTOOLS_SCIP_CALL(SCIPsetMessagehdlr(NULL));
00480 } else {
00481 ORTOOLS_SCIP_CALL(SCIPsetDefaultMessagehdlr());
00482 }
00483
00484
00485 if (solver_->variables_.size() == 0 && solver_->constraints_.size() == 0) {
00486 sync_status_ = SOLUTION_SYNCHRONIZED;
00487 result_status_ = MPSolver::OPTIMAL;
00488 objective_value_ = solver_->Objective().offset();
00489 return result_status_;
00490 }
00491
00492 ExtractModel();
00493 VLOG(1) << StringPrintf("Model built in %.3f seconds.", timer.Get());
00494
00495 WriteModelToPredefinedFiles();
00496
00497
00498 if (solver_->time_limit()) {
00499 VLOG(1) << "Setting time limit = " << solver_->time_limit() << " ms.";
00500 ORTOOLS_SCIP_CALL(SCIPsetRealParam(
00501 scip_, "limits/time", solver_->time_limit() / 1000.0));
00502 } else {
00503 ORTOOLS_SCIP_CALL(SCIPresetParam(scip_, "limits/time"));
00504 }
00505
00506 SetParameters(param);
00507
00508
00509 timer.Restart();
00510 ORTOOLS_SCIP_CALL(SCIPsolve(scip_));
00511 VLOG(1) << StringPrintf("Solved in %.3f seconds.", timer.Get());
00512
00513
00514 SCIP_SOL* solution = SCIPgetBestSol(scip_);
00515 if (solution != NULL) {
00516
00517 objective_value_ = SCIPgetSolOrigObj(scip_, solution);
00518 VLOG(1) << "objective=" << objective_value_;
00519 for (int i = 0; i < solver_->variables_.size(); ++i) {
00520 MPVariable* const var = solver_->variables_[i];
00521 const int var_index = var->index();
00522 const double val = SCIPgetSolVal(scip_, solution,
00523 scip_variables_[var_index]);
00524 var->set_solution_value(val);
00525 VLOG(3) << var->name() << "=" << val;
00526 }
00527 for (int i = 0; i < solver_->constraints_.size(); ++i) {
00528 MPConstraint* const ct = solver_->constraints_[i];
00529 const int constraint_index = ct->index();
00530 const double row_activity =
00531 SCIPgetActivityLinear(scip_,
00532 scip_constraints_[constraint_index],
00533 solution);
00534 ct->set_activity(row_activity);
00535 VLOG(4) << "row " << ct->index()
00536 << ": activity = " << row_activity;
00537 }
00538 } else {
00539 VLOG(1) << "No feasible solution found.";
00540 }
00541
00542
00543 SCIP_STATUS scip_status = SCIPgetStatus(scip_);
00544 switch (scip_status) {
00545 case SCIP_STATUS_OPTIMAL:
00546 result_status_ = MPSolver::OPTIMAL;
00547 break;
00548 case SCIP_STATUS_GAPLIMIT:
00549
00550 result_status_ = MPSolver::OPTIMAL;
00551 break;
00552 case SCIP_STATUS_INFEASIBLE:
00553 result_status_ = MPSolver::INFEASIBLE;
00554 break;
00555 case SCIP_STATUS_UNBOUNDED:
00556 result_status_ = MPSolver::UNBOUNDED;
00557 break;
00558 case SCIP_STATUS_INFORUNBD:
00559
00560
00561 result_status_ = MPSolver::INFEASIBLE;
00562 break;
00563 default:
00564 if (solution != NULL) {
00565 result_status_ = MPSolver::FEASIBLE;
00566 } else {
00567
00568
00569 result_status_ = MPSolver::ABNORMAL;
00570 }
00571 break;
00572 }
00573
00574 ORTOOLS_SCIP_CALL(SCIPresetParams(scip_));
00575
00576 sync_status_ = SOLUTION_SYNCHRONIZED;
00577 return result_status_;
00578 }
00579
00580 MPSolverInterface* BuildSCIPInterface(MPSolver* const solver) {
00581 return new SCIPInterface(solver);
00582 }
00583
00584
00585
00586 int64 SCIPInterface::iterations() const {
00587 CheckSolutionIsSynchronized();
00588 return SCIPgetNLPIterations(scip_);
00589 }
00590
00591 int64 SCIPInterface::nodes() const {
00592 CheckSolutionIsSynchronized();
00593
00594 return SCIPgetNNodes(scip_);
00595 }
00596
00597 double SCIPInterface::best_objective_bound() const {
00598 CheckSolutionIsSynchronized();
00599 CheckBestObjectiveBoundExists();
00600 if (solver_->variables_.size() == 0 && solver_->constraints_.size() == 0) {
00601
00602 return solver_->Objective().offset();
00603 } else {
00604 return SCIPgetDualbound(scip_);
00605 }
00606 }
00607
00608
00609
00610 void SCIPInterface::SetParameters(const MPSolverParameters& param) {
00611 SetCommonParameters(param);
00612 SetMIPParameters(param);
00613 }
00614
00615 void SCIPInterface::SetRelativeMipGap(double value) {
00616 ORTOOLS_SCIP_CALL(SCIPsetRealParam(scip_, "limits/gap", value));
00617 }
00618
00619 void SCIPInterface::SetPrimalTolerance(double value) {
00620 ORTOOLS_SCIP_CALL(SCIPsetRealParam(scip_, "numerics/feastol", value));
00621 }
00622
00623 void SCIPInterface::SetDualTolerance(double value) {
00624 ORTOOLS_SCIP_CALL(SCIPsetRealParam(scip_, "numerics/dualfeastol", value));
00625 }
00626
00627 void SCIPInterface::SetPresolveMode(int value) {
00628 switch (value) {
00629 case MPSolverParameters::PRESOLVE_OFF: {
00630 ORTOOLS_SCIP_CALL(SCIPsetIntParam(scip_, "presolving/maxrounds", 0));
00631 break;
00632 }
00633 case MPSolverParameters::PRESOLVE_ON: {
00634 ORTOOLS_SCIP_CALL(SCIPsetIntParam(scip_, "presolving/maxrounds", -1));
00635 break;
00636 }
00637 default: {
00638 SetIntegerParamToUnsupportedValue(MPSolverParameters::PRESOLVE, value);
00639 }
00640 }
00641 }
00642
00643
00644
00645
00646 void SCIPInterface::SetLpAlgorithm(int value) {
00647 switch (value) {
00648 case MPSolverParameters::DUAL: {
00649 ORTOOLS_SCIP_CALL(SCIPsetCharParam(scip_, "lp/initalgorithm", 'd'));
00650 break;
00651 }
00652 case MPSolverParameters::PRIMAL: {
00653 ORTOOLS_SCIP_CALL(SCIPsetCharParam(scip_, "lp/initalgorithm", 'p'));
00654 break;
00655 }
00656 case MPSolverParameters::BARRIER: {
00657
00658 ORTOOLS_SCIP_CALL(SCIPsetCharParam(scip_, "lp/initalgorithm", 'p'));
00659 break;
00660 }
00661 default: {
00662 SetIntegerParamToUnsupportedValue(MPSolverParameters::LP_ALGORITHM,
00663 value);
00664 }
00665 }
00666 }
00667
00668 }
00669 #endif // #if defined(USE_SCIP)
00670
00671 #undef ORTOOLS_SCIP_CALL