00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <math.h>
00015 #include "base/hash.h"
00016 #include "base/callback.h"
00017 #include "base/commandlineflags.h"
00018 #include "base/integral_types.h"
00019 #include "base/macros.h"
00020 #include "base/scoped_ptr.h"
00021 #include "base/stl_util.h"
00022 #include "constraint_solver/constraint_solver.h"
00023 #include "constraint_solver/constraint_solveri.h"
00024 #include "linear_solver/linear_solver.h"
00025 #include "util/string_array.h"
00026
00027 DEFINE_int32(simplex_cleanup_frequency, 0,
00028 "frequency to cleanup the simplex after each call, 0: no cleanup");
00029 DEFINE_bool(verbose_simplex_call, false,
00030 "Do not suppress output of the simplex");
00031 DEFINE_bool(use_clp, true, "use Clp instead of glpk");
00032
00033 namespace operations_research {
00034 namespace {
00035 MPSolver::OptimizationProblemType GetType(bool use_clp) {
00036 if (use_clp) {
00037 #if defined(USE_CLP)
00038 return MPSolver::CLP_LINEAR_PROGRAMMING;
00039 #else
00040 LOG(FATAL) << "CLP not defined";
00041 #endif // USE_CLP
00042 } else {
00043 #if defined(USE_GLPK)
00044 return MPSolver::GLPK_LINEAR_PROGRAMMING;
00045 #else
00046 LOG(FATAL) << "GLPK not defined";
00047 #endif // USE_GLPK
00048 }
00049 }
00050
00051 class SimplexConnection : public SearchMonitor {
00052 public:
00053 SimplexConnection(Solver* const solver,
00054 Callback1<MPSolver*>* const builder,
00055 Callback1<MPSolver*>* const modifier,
00056 Callback1<MPSolver*>* const runner,
00057 int simplex_frequency)
00058 : SearchMonitor(solver),
00059 builder_(builder),
00060 modifier_(modifier),
00061 runner_(runner),
00062 mp_solver_("InSearchSimplex", GetType(FLAGS_use_clp)),
00063 counter_(0LL),
00064 simplex_frequency_(simplex_frequency) {
00065 if (builder != NULL) {
00066 builder->CheckIsRepeatable();
00067 }
00068 if (modifier != NULL) {
00069 modifier->CheckIsRepeatable();
00070 }
00071 if (runner != NULL) {
00072 runner->CheckIsRepeatable();
00073 }
00074 if (!FLAGS_verbose_simplex_call) {
00075 mp_solver_.SuppressOutput();
00076 }
00077 }
00078
00079 virtual void EndInitialPropagation() {
00080 mp_solver_.Clear();
00081 if (builder_.get() != NULL) {
00082 builder_->Run(&mp_solver_);
00083 }
00084 RunOptim();
00085 }
00086
00087 virtual void BeginNextDecision(DecisionBuilder* const b) {
00088 if (++counter_ % simplex_frequency_ == 0) {
00089 const int cleanup = FLAGS_simplex_cleanup_frequency * simplex_frequency_;
00090 if (FLAGS_simplex_cleanup_frequency != 0 && counter_ % cleanup == 0) {
00091 mp_solver_.Clear();
00092 if (builder_.get() != NULL) {
00093 builder_->Run(&mp_solver_);
00094 }
00095 }
00096 RunOptim();
00097 }
00098 }
00099
00100 void RunOptim() {
00101 if (modifier_.get() != NULL) {
00102 modifier_->Run(&mp_solver_);
00103 }
00104 if (runner_.get() != NULL) {
00105 runner_->Run(&mp_solver_);
00106 }
00107 }
00108
00109 private:
00110 scoped_ptr<Callback1<MPSolver*> > builder_;
00111 scoped_ptr<Callback1<MPSolver*> > modifier_;
00112 scoped_ptr<Callback1<MPSolver*> > runner_;
00113 MPSolver mp_solver_;
00114 int64 counter_;
00115 const int simplex_frequency_;
00116 DISALLOW_COPY_AND_ASSIGN(SimplexConnection);
00117 };
00118
00119
00120
00121
00122
00123 typedef hash_map<const IntExpr*, MPVariable*> ExprTranslation;
00124
00125 #define IS_TYPE(type, tag) type.compare(ModelVisitor::tag) == 0
00126
00127
00128
00129 class Linearizer : public ModelParser {
00130 public:
00131 Linearizer(MPSolver* const mp_solver,
00132 ExprTranslation* tr,
00133 IntVar** objective,
00134 bool* maximize)
00135 : mp_solver_(mp_solver),
00136 translation_(tr),
00137 objective_(objective),
00138 maximize_(maximize) {}
00139
00140 virtual ~Linearizer() {}
00141
00142
00143 virtual void BeginVisitModel(const string& solver_name) {
00144 BeginVisit(true);
00145 }
00146
00147 virtual void EndVisitModel(const string& solver_name) {
00148 EndVisit();
00149 }
00150
00151 virtual void BeginVisitConstraint(const string& type_name,
00152 const Constraint* const constraint) {
00153 if (!constraint->IsCastConstraint() &&
00154 (IS_TYPE(type_name, kEquality) ||
00155 IS_TYPE(type_name, kLessOrEqual) ||
00156 IS_TYPE(type_name, kGreaterOrEqual) ||
00157 IS_TYPE(type_name, kScalProdLessOrEqual))) {
00158 BeginVisit(true);
00159 } else {
00160 BeginVisit(false);
00161 }
00162 }
00163
00164 virtual void EndVisitConstraint(const string& type_name,
00165 const Constraint* const constraint) {
00166 if (!constraint->IsCastConstraint()) {
00167 if (IS_TYPE(type_name, kEquality)) {
00168 VisitEquality();
00169 } else if (IS_TYPE(type_name, kLessOrEqual)) {
00170 VisitLessOrEqual();
00171 } else if (IS_TYPE(type_name, kGreaterOrEqual)) {
00172 VisitGreaterOrEqual();
00173 } else if (IS_TYPE(type_name, kScalProdLessOrEqual)) {
00174 VisitScalProdLessOrEqual();
00175 }
00176 }
00177 EndVisit();
00178 }
00179 virtual void BeginVisitExtension(const string& type) {
00180 BeginVisit(true);
00181 }
00182 virtual void EndVisitExtension(const string& type) {
00183 if (IS_TYPE(type, kObjectiveExtension)) {
00184 VisitObjective();
00185 }
00186 EndVisit();
00187 }
00188 virtual void BeginVisitIntegerExpression(const string& type_name,
00189 const IntExpr* const expr) {
00190 BeginVisit(true);
00191 }
00192 virtual void EndVisitIntegerExpression(const string& type_name,
00193 const IntExpr* const expr) {
00194 if (IS_TYPE(type_name, kSum)) {
00195 VisitSum(expr);
00196 } else if (IS_TYPE(type_name, kScalProd)) {
00197 VisitScalProd(expr);
00198 } else if (IS_TYPE(type_name, kDifference)) {
00199 VisitDifference(expr);
00200 } else if (IS_TYPE(type_name, kOpposite)) {
00201 VisitOpposite(expr);
00202 } else if (IS_TYPE(type_name, kProduct)) {
00203 VisitProduct(expr);
00204 } else {
00205 VisitIntegerExpression(expr);
00206 }
00207 EndVisit();
00208 }
00209
00210 virtual void VisitIntegerVariable(const IntVar* const variable,
00211 const string& operation,
00212 int64 value,
00213 const IntVar* const delegate) {
00214 RegisterExpression(const_cast<IntVar*>(variable));
00215 RegisterExpression(const_cast<IntVar*>(delegate));
00216 if (operation == ModelVisitor::kSumOperation) {
00217 MPConstraint* const ct = mp_solver_->MakeRowConstraint(value, value);
00218 ct->SetCoefficient(Translated(variable), 1.0);
00219 ct->SetCoefficient(Translated(delegate), -1.0);
00220 } else if (operation == ModelVisitor::kDifferenceOperation) {
00221 MPConstraint* const ct = mp_solver_->MakeRowConstraint(value, value);
00222 ct->SetCoefficient(Translated(variable), 1.0);
00223 ct->SetCoefficient(Translated(delegate), 1.0);
00224 } else if (operation == ModelVisitor::kProductOperation) {
00225 MPConstraint* const ct = mp_solver_->MakeRowConstraint(0.0, 0.0);
00226 ct->SetCoefficient(Translated(variable), 1.0);
00227 ct->SetCoefficient(Translated(delegate), -value);
00228 }
00229 }
00230
00231 virtual void VisitIntegerVariable(const IntVar* const variable,
00232 const IntExpr* const delegate) {
00233 RegisterExpression(const_cast<IntVar*>(variable));
00234 if (delegate != NULL) {
00235 VisitSubExpression(delegate);
00236 AddMpEquality(const_cast<IntVar*>(variable),
00237 const_cast<IntExpr*>(delegate));
00238 }
00239 }
00240
00241 virtual void VisitIntervalVariable(const IntervalVar* const variable,
00242 const string& operation,
00243 const IntervalVar* const delegate) {}
00244
00245 virtual void VisitIntervalVariable(const IntervalVar* const variable,
00246 const string& operation,
00247 const IntervalVar* const * delegate,
00248 int size) {}
00249
00250
00251 virtual void VisitIntegerArgument(const string& arg_name, int64 value) {
00252 if (DoVisit()) {
00253 Top()->SetIntegerArgument(arg_name, value);
00254 }
00255 }
00256
00257 virtual void VisitIntegerArrayArgument(const string& arg_name,
00258 const int64* const values,
00259 int size) {
00260 if (DoVisit()) {
00261 Top()->SetIntegerArrayArgument(arg_name, values, size);
00262 }
00263 }
00264
00265 virtual void VisitIntegerMatrixArgument(const string& arg_name,
00266 const IntTupleSet& values) {
00267 if (DoVisit()) {
00268 Top()->SetIntegerMatrixArgument(arg_name, values);
00269 }
00270 }
00271
00272
00273 virtual void VisitIntegerExpressionArgument(
00274 const string& arg_name,
00275 const IntExpr* const argument) {
00276 if (DoVisit()) {
00277 Top()->SetIntegerExpressionArgument(arg_name, argument);
00278 VisitSubExpression(argument);
00279 }
00280 }
00281
00282 virtual void VisitIntegerVariableArrayArgument(
00283 const string& arg_name,
00284 const IntVar* const * arguments,
00285 int size) {
00286 if (DoVisit()) {
00287 Top()->SetIntegerVariableArrayArgument(arg_name, arguments, size);
00288 for (int i = 0; i < size; ++i) {
00289 VisitSubExpression(arguments[i]);
00290 }
00291 }
00292 }
00293
00294
00295 virtual void VisitIntervalArgument(const string& arg_name,
00296 const IntervalVar* const argument) {}
00297
00298 virtual void VisitIntervalArrayArgument(const string& arg_name,
00299 const IntervalVar* const * argument,
00300 int size) {}
00301
00302 private:
00303 void BeginVisit(bool active) {
00304 PushActive(active);
00305 PushArgumentHolder();
00306 }
00307
00308 void EndVisit() {
00309 PopArgumentHolder();
00310 PopActive();
00311 }
00312
00313 bool DoVisit() const {
00314 return actives_.back();
00315 }
00316
00317 void PushActive(bool active) {
00318 actives_.push_back(active);
00319 }
00320
00321 void PopActive() {
00322 actives_.pop_back();
00323 }
00324
00325 void RegisterExpression(const IntExpr* const cp_expr) {
00326 if (!ContainsKey(*translation_, cp_expr)) {
00327 MPVariable* const mp_var = mp_solver_->MakeIntVar(cp_expr->Min(),
00328 cp_expr->Max(),
00329 "");
00330 CHECK(cp_expr->Min() != cp_expr->Max());
00331 (*translation_)[cp_expr] = mp_var;
00332 }
00333 }
00334
00335 void VisitSubExpression(const IntExpr* const cp_expr) {
00336 if (!ContainsKey(*translation_, cp_expr)) {
00337 cp_expr->Accept(this);
00338 }
00339 }
00340
00341 void AddMpEquality(IntExpr* const left, IntExpr* const right) {
00342 MPConstraint* const ct = mp_solver_->MakeRowConstraint(0.0, 0.0);
00343 ct->SetCoefficient(Translated(left), 1.0);
00344 ct->SetCoefficient(Translated(right), -1.0);
00345 }
00346
00347 MPVariable* Translated(const IntExpr* const cp_var) {
00348 return FindOrDie((*translation_), cp_var);
00349 }
00350
00351 void VisitBinaryRowConstraint(double lhs, double rhs) {
00352 MPConstraint* const ct = mp_solver_->MakeRowConstraint(lhs, rhs);
00353 const IntExpr* const left =
00354 Top()->FindIntegerExpressionArgumentOrDie(ModelVisitor::kLeftArgument);
00355 const IntExpr* const right =
00356 Top()->FindIntegerExpressionArgumentOrDie(ModelVisitor::kRightArgument);
00357 ct->SetCoefficient(Translated(left), 1.0);
00358 ct->SetCoefficient(Translated(right), -1.0);
00359 }
00360
00361 void VisitUnaryRowConstraint(double lhs, double rhs) {
00362 const IntExpr* const expr =
00363 Top()->FindIntegerExpressionArgumentOrDie(
00364 ModelVisitor::kExpressionArgument);
00365 MPConstraint* const ct = mp_solver_->MakeRowConstraint(lhs, rhs);
00366 ct->SetCoefficient(Translated(expr), 1.0);
00367 }
00368
00369 void VisitEquality() {
00370 if (Top()->HasIntegerExpressionArgument(ModelVisitor::kLeftArgument)) {
00371 VisitBinaryRowConstraint(0.0, 0.0);
00372 } else {
00373 const int64 value =
00374 Top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
00375 VisitUnaryRowConstraint(value, value);
00376 }
00377 }
00378
00379 void VisitLessOrEqual() {
00380 if (Top()->HasIntegerExpressionArgument(ModelVisitor::kLeftArgument)) {
00381 VisitBinaryRowConstraint(-mp_solver_->infinity(), 0.0);
00382 } else {
00383 const int64 value =
00384 Top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
00385 VisitUnaryRowConstraint(-mp_solver_->infinity(), value);
00386 }
00387 }
00388
00389 void VisitGreaterOrEqual() {
00390 if (Top()->HasIntegerExpressionArgument(ModelVisitor::kLeftArgument)) {
00391 VisitBinaryRowConstraint(0.0, mp_solver_->infinity());
00392 } else {
00393 const int64 value =
00394 Top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
00395 VisitUnaryRowConstraint(value, mp_solver_->infinity());
00396 }
00397 }
00398
00399 void VisitScalProdLessOrEqual() {
00400 const std::vector<const IntVar*>& cp_vars =
00401 Top()->FindIntegerVariableArrayArgumentOrDie(
00402 ModelVisitor::kVarsArgument);
00403 const std::vector<int64>& cp_coefficients =
00404 Top()->FindIntegerArrayArgumentOrDie(
00405 ModelVisitor::kCoefficientsArgument);
00406 const int64 constant =
00407 Top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
00408 MPConstraint* const ct =
00409 mp_solver_->MakeRowConstraint(-mp_solver_->infinity(),
00410 constant);
00411 CHECK_EQ(cp_vars.size(), cp_coefficients.size());
00412 for (int i = 0; i < cp_coefficients.size(); ++i) {
00413 MPVariable* const mp_var = Translated(cp_vars[i]);
00414 ct->SetCoefficient(mp_var,
00415 cp_coefficients[i] + ct->GetCoefficient(mp_var));
00416 }
00417 }
00418
00419 void VisitSum(const IntExpr* const cp_expr) {
00420 if (Top()->HasIntegerVariableArrayArgument(ModelVisitor::kVarsArgument)) {
00421 MPConstraint* const ct = mp_solver_->MakeRowConstraint(0.0, 0.0);
00422 const std::vector<const IntVar*>& cp_vars =
00423 Top()->FindIntegerVariableArrayArgumentOrDie(
00424 ModelVisitor::kVarsArgument);
00425 for (int i = 0; i < cp_vars.size(); ++i) {
00426 MPVariable* const mp_var = Translated(cp_vars[i]);
00427 ct->SetCoefficient(mp_var, 1.0 + ct->GetCoefficient(mp_var));
00428 }
00429 RegisterExpression(cp_expr);
00430 ct->SetCoefficient(Translated(cp_expr), -1.0);
00431 } else if (Top()->HasIntegerExpressionArgument(
00432 ModelVisitor::kLeftArgument)) {
00433 MPConstraint* const ct = mp_solver_->MakeRowConstraint(0.0, 0.0);
00434 const IntExpr* const left =
00435 Top()->FindIntegerExpressionArgumentOrDie(
00436 ModelVisitor::kLeftArgument);
00437 const IntExpr* const right =
00438 Top()->FindIntegerExpressionArgumentOrDie(
00439 ModelVisitor::kRightArgument);
00440 if (left != right) {
00441 ct->SetCoefficient(Translated(left), 1.0);
00442 ct->SetCoefficient(Translated(right), 1.0);
00443 } else {
00444 ct->SetCoefficient(Translated(left), 2.0);
00445 }
00446 RegisterExpression(cp_expr);
00447 ct->SetCoefficient(Translated(cp_expr), -1.0);
00448 } else {
00449 const IntExpr* const expr =
00450 Top()->FindIntegerExpressionArgumentOrDie(
00451 ModelVisitor::kExpressionArgument);
00452 const int64 value =
00453 Top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
00454 MPConstraint* const ct = mp_solver_->MakeRowConstraint(-value, -value);
00455 ct->SetCoefficient(Translated(expr), 1.0);
00456 RegisterExpression(cp_expr);
00457 ct->SetCoefficient(Translated(cp_expr), -1.0);
00458 }
00459 }
00460
00461 void VisitScalProd(const IntExpr* const cp_expr) {
00462 const std::vector<const IntVar*>& cp_vars =
00463 Top()->FindIntegerVariableArrayArgumentOrDie(
00464 ModelVisitor::kVarsArgument);
00465 const std::vector<int64>& cp_coefficients =
00466 Top()->FindIntegerArrayArgumentOrDie(
00467 ModelVisitor::kCoefficientsArgument);
00468 CHECK_EQ(cp_vars.size(), cp_coefficients.size());
00469 MPConstraint* const ct = mp_solver_->MakeRowConstraint(0.0, 0.0);
00470 for (int i = 0; i < cp_vars.size(); ++i) {
00471 MPVariable* const mp_var = Translated(cp_vars[i]);
00472 const int64 coefficient = cp_coefficients[i];
00473 ct->SetCoefficient(mp_var, coefficient + ct->GetCoefficient(mp_var));
00474 }
00475 RegisterExpression(cp_expr);
00476 ct->SetCoefficient(Translated(cp_expr), -1.0);
00477 }
00478
00479 void VisitDifference(const IntExpr* const cp_expr) {
00480 if (Top()->HasIntegerExpressionArgument(ModelVisitor::kLeftArgument)) {
00481 MPConstraint* const ct = mp_solver_->MakeRowConstraint(0.0, 0.0);
00482 const IntExpr* const left =
00483 Top()->FindIntegerExpressionArgumentOrDie(
00484 ModelVisitor::kLeftArgument);
00485 const IntExpr* const right =
00486 Top()->FindIntegerExpressionArgumentOrDie(
00487 ModelVisitor::kRightArgument);
00488 ct->SetCoefficient(Translated(left), 1.0);
00489 ct->SetCoefficient(Translated(right), -1.0);
00490 RegisterExpression(cp_expr);
00491 ct->SetCoefficient(Translated(cp_expr), -1.0);
00492 } else {
00493 const IntExpr* const expr =
00494 Top()->FindIntegerExpressionArgumentOrDie(
00495 ModelVisitor::kExpressionArgument);
00496 const int64 value =
00497 Top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
00498 MPConstraint* const ct = mp_solver_->MakeRowConstraint(value, value);
00499 ct->SetCoefficient(Translated(expr), 1.0);
00500 RegisterExpression(cp_expr);
00501 ct->SetCoefficient(Translated(cp_expr), 1.0);
00502 }
00503 }
00504
00505 void VisitOpposite(const IntExpr* const cp_expr) {
00506 const IntExpr* const expr =
00507 Top()->FindIntegerExpressionArgumentOrDie(
00508 ModelVisitor::kExpressionArgument);
00509 MPConstraint* const ct = mp_solver_->MakeRowConstraint(0.0, 0.0);
00510 ct->SetCoefficient(Translated(expr), 1.0);
00511 RegisterExpression(cp_expr);
00512 ct->SetCoefficient(Translated(cp_expr), -1.0);
00513 }
00514
00515 void VisitProduct(const IntExpr* const cp_expr) {
00516 if (Top()->HasIntegerExpressionArgument(
00517 ModelVisitor::kExpressionArgument)) {
00518 const IntExpr* const expr =
00519 Top()->FindIntegerExpressionArgumentOrDie(
00520 ModelVisitor::kExpressionArgument);
00521 const int64 value =
00522 Top()->FindIntegerArgumentOrDie(ModelVisitor::kValueArgument);
00523 MPConstraint* const ct = mp_solver_->MakeRowConstraint(0.0, 0.0);
00524 ct->SetCoefficient(Translated(expr), value);
00525 RegisterExpression(cp_expr);
00526 ct->SetCoefficient(Translated(cp_expr), -1.0);
00527 } else {
00528 RegisterExpression(cp_expr);
00529 }
00530 }
00531
00532 void VisitIntegerExpression(const IntExpr* const cp_expr) {
00533 RegisterExpression(cp_expr);
00534 }
00535
00536 void VisitObjective() {
00537 *maximize_ =
00538 Top()->FindIntegerArgumentOrDie(ModelVisitor::kMaximizeArgument);
00539 *objective_ =
00540 const_cast<IntExpr*>(Top()->FindIntegerExpressionArgumentOrDie(
00541 ModelVisitor::kExpressionArgument))->Var();
00542 mp_solver_->SetObjectiveCoefficient(Translated(*objective_), 1.0);
00543 mp_solver_->SetOptimizationDirection(*maximize_);
00544 }
00545
00546 MPSolver* const mp_solver_;
00547 ExprTranslation* const translation_;
00548 IntVar** objective_;
00549 bool* maximize_;
00550 std::vector<bool> actives_;
00551 };
00552
00553
00554
00555 class AutomaticLinearization : public SearchMonitor {
00556 public:
00557 AutomaticLinearization(Solver* const solver, int frequency)
00558 : SearchMonitor(solver),
00559 mp_solver_("InSearchSimplex", MPSolver::CLP_LINEAR_PROGRAMMING),
00560 counter_(0),
00561 simplex_frequency_(frequency),
00562 objective_(NULL),
00563 maximize_(false) {}
00564
00565 virtual ~AutomaticLinearization() {}
00566
00567 virtual void BeginInitialPropagation() {
00568 mp_solver_.Clear();
00569 translation_.clear();
00570 BuildModel();
00571 }
00572
00573 virtual void EndInitialPropagation() {
00574 RunOptim();
00575 }
00576
00577 virtual void BeginNextDecision(DecisionBuilder* const b) {
00578 if (++counter_ % simplex_frequency_ == 0) {
00579 RunOptim();
00580 }
00581 }
00582
00583 void RunOptim() {
00584 AssignVariables();
00585 SolveProblem();
00586 }
00587
00588 void BuildModel() {
00589 Linearizer linearizer(&mp_solver_, &translation_, &objective_, &maximize_);
00590 solver()->Accept(&linearizer);
00591 }
00592
00593 void AssignVariables() {
00594 for (ConstIter<ExprTranslation> it(translation_); !it.at_end(); ++it) {
00595 it->second->SetBounds(it->first->Min(), it->first->Max());
00596 }
00597 }
00598
00599 void SolveProblem() {
00600 if (objective_ != NULL) {
00601 switch (mp_solver_.Solve()) {
00602 case MPSolver::OPTIMAL: {
00603 const double obj_value = mp_solver_.objective_value();
00604 if (maximize_) {
00605 const int64 int_obj_value = static_cast<int64>(ceil(obj_value));
00606 objective_->SetMax(int_obj_value);
00607 } else {
00608 const int64 int_obj_value = static_cast<int64>(floor(obj_value));
00609 objective_->SetMin(int_obj_value);
00610 }
00611 break;
00612 }
00613 case MPSolver::FEASIBLE:
00614 break;
00615 case MPSolver::INFEASIBLE:
00616 solver()->Fail();
00617 break;
00618 case MPSolver::UNBOUNDED:
00619 LOG(INFO) << "Error: unbounded LP status.";
00620 break;
00621 case MPSolver::ABNORMAL:
00622 LOG(INFO) << "Error: abnormal LP status.";
00623 break;
00624 default:
00625 LOG(FATAL) << "Error: Unknown LP status.";
00626 break;
00627 }
00628 }
00629 }
00630
00631 private:
00632 MPSolver mp_solver_;
00633 int64 counter_;
00634 const int simplex_frequency_;
00635 ExprTranslation translation_;
00636 IntVar* objective_;
00637 bool maximize_;
00638 };
00639
00640
00641 }
00642
00643
00644
00645 SearchMonitor* Solver::MakeSimplexConnection(
00646 Callback1<MPSolver*>* const builder,
00647 Callback1<MPSolver*>* const modifier,
00648 Callback1<MPSolver*>* const runner,
00649 int frequency) {
00650 return RevAlloc(new SimplexConnection(this,
00651 builder,
00652 modifier,
00653 runner,
00654 frequency));
00655 }
00656
00657 SearchMonitor* Solver::MakeSimplexConstraint(int simplex_frequency) {
00658 return RevAlloc(new AutomaticLinearization(this, simplex_frequency));
00659 }
00660 }