Introduce MakeWeightedMinimize objective; deprecate MakeSearchLog(period, var) in favor of MakeSearchLog(period, OptimizeVar)

This commit is contained in:
lperron@google.com
2011-01-18 15:00:12 +00:00
parent 8727e0505f
commit a5e37ab3ed
3 changed files with 167 additions and 34 deletions

View File

@@ -812,7 +812,7 @@ class Solver {
IntVar* MakeIsLessVar(IntExpr* const left, IntExpr* const right);
// b == (left < right)
Constraint* MakeIsLessCt(IntExpr* const left, IntExpr* const right,
IntVar* const b);
IntVar* const b);
// left < right
Constraint* MakeLess(IntVar* const left, IntVar* const right);
// expr < value
@@ -1077,7 +1077,7 @@ class Solver {
//
// This is very useful to implement propagators that may only modify
// the start min or end min.
IntervalVar* MakeIntervalRelaxedMax(IntervalVar* const interval_var);
IntervalVar* MakeIntervalRelaxedMax(IntervalVar* const interval_var);
// ----- scheduling constraints -----
@@ -1198,6 +1198,23 @@ IntervalVar* MakeIntervalRelaxedMax(IntervalVar* const interval_var);
// Create a objective with a given sense (true = maximization).
OptimizeVar* MakeOptimize(bool maximize, IntVar* const v, int64 step);
// Create a minimization weighted objective. The actual objective is
// scalar_prod(vars, weights).
OptimizeVar* MakeWeightedMinimize(const vector<IntVar*>& vars,
const vector<int64>& weights,
int64 step);
// Create a maximization weigthed objective.
OptimizeVar* MakeWeightedMaximize(const vector<IntVar*>& vars,
const vector<int64>& weights,
int64 step);
// Create a weighted objective with a given sense (true = maximization).
OptimizeVar* MakeWeightedOptimize(bool maximize,
const vector<IntVar*>& vars,
const vector<int64>& weights,
int64 step);
// ----- Meta-heuristics -----
// Search monitors which try to get the search out of local optima.
@@ -1380,28 +1397,39 @@ IntervalVar* MakeIntervalRelaxedMax(IntervalVar* const interval_var);
#endif
// TODO(user): DEPRECATE API of MakeSearchLog(.., IntVar* var,..).
// ----- Search Log -----
// The SearchMonitors below will display a periodic search log
// on LOG(INFO) every branch_count branches explored.
// Create a search monitor that will display a periodic search log
// on LOG(INFO).
SearchMonitor* MakeSearchLog(int period);
SearchMonitor* MakeSearchLog(int branch_count);
// Create a search monitor that will display a periodic search log
// on LOG(INFO). At each solution, this monitor will also display
// the objective value.
SearchMonitor* MakeSearchLog(int period, IntVar* const objective);
// At each solution, this monitor also display the objective value.
SearchMonitor* MakeSearchLog(int branch_count, IntVar* const objective);
// Create a search monitor that will call the display callback at each
// solution.
SearchMonitor* MakeSearchLog(int period,
// At each solution, this monitor will also display result of @p
// display_callback.
SearchMonitor* MakeSearchLog(int branch_count,
ResultCallback<string>* display_callback);
// Create a search monitor that will call the display callback and display
// the objective value at each solution.
SearchMonitor* MakeSearchLog(int period,
// At each solution, this monitor will display the objective value and the
// result of @p display_callback.
SearchMonitor* MakeSearchLog(int branch_count,
IntVar* objective,
ResultCallback<string>* display_callback);
// OptimizeVar Search Logs
// At each solution, this monitor will also display the objective->Print().
SearchMonitor* MakeSearchLog(int branch_count, OptimizeVar* const objective);
// Create a search monitor that will also print the result of the
// display callback.
SearchMonitor* MakeSearchLog(int branch_count,
OptimizeVar* const objective,
ResultCallback<string>* display_callback);
// ----- Search Trace ------
// Create a search monitor that will trace precisely the behavior of the
@@ -1588,10 +1616,10 @@ IntervalVar* MakeIntervalRelaxedMax(IntervalVar* const interval_var);
// Returns a decision builder for which the left-most leaf corresponds
// to assignment, the rest of the tree being explored using 'db'.
DecisionBuilder* MakeDecisionBuilderFromAssignment(
Assignment* const assignment,
DecisionBuilder* const db,
const IntVar* const* vars,
int size);
Assignment* const assignment,
DecisionBuilder* const db,
const IntVar* const* vars,
int size);
// SolveOnce will collapse a search tree described by a 'db' decision
// builder, and a set of monitors and wrap it into a single point.
@@ -2587,6 +2615,9 @@ class SolutionCollector : public SearchMonitor {
DISALLOW_COPY_AND_ASSIGN(SolutionCollector);
};
// TODO(user): Refactor this into an Objective class:
// - print methods for AtNode and AtSolution.
// - support for weighted objective and lexicographical objective.
// ---------- Objective Management ----------
@@ -2601,15 +2632,15 @@ class OptimizeVar : public SearchMonitor {
// Returns the best value found during search.
int64 best() const { return best_; }
// Returns the variable passed in the ctor.
// Returns the variable that is optimized.
IntVar* Var() const { return var_; }
// Internal methods
virtual void EnterSearch();
virtual void RestartSearch();
virtual void RefuteDecision(Decision* d);
virtual bool AtSolution();
virtual bool AcceptSolution();
virtual string Print() const;
virtual string DebugString() const;
void ApplyBound();
@@ -2680,8 +2711,8 @@ class IntervalVar : public PropagationBaseObject {
static const int64 kMaxValidValue;
IntervalVar(Solver* const solver, const string& name)
: PropagationBaseObject(solver),
start_expr_(NULL), duration_expr_(NULL), end_expr_(NULL),
performed_expr_(NULL) {
start_expr_(NULL), duration_expr_(NULL), end_expr_(NULL),
performed_expr_(NULL) {
set_name(name);
}
virtual ~IntervalVar() {}

View File

@@ -755,7 +755,9 @@ class SymmetryBreaker : public DecisionVisitor {
class SearchLog : public SearchMonitor {
public:
SearchLog(Solver* const s, IntVar* const obj,
SearchLog(Solver* const s,
OptimizeVar* const obj,
IntVar* const var,
ResultCallback<string>* display_callback,
int period);
virtual ~SearchLog();
@@ -778,7 +780,8 @@ class SearchLog : public SearchMonitor {
const int period_;
scoped_ptr<WallTimer> timer_;
IntVar* const obj_;
IntVar* const var_;
OptimizeVar* const obj_;
scoped_ptr<ResultCallback<string> > display_callback_;
int nsol_;
int64 tick_;

View File

@@ -32,12 +32,15 @@ namespace operations_research {
// ---------- Search Log ---------
SearchLog::SearchLog(Solver* const s, IntVar* const obj,
SearchLog::SearchLog(Solver* const s,
OptimizeVar* const obj,
IntVar* const var,
ResultCallback<string>* display_callback,
int period)
: SearchMonitor(s),
period_(period),
timer_(new WallTimer),
var_(var),
obj_(obj),
display_callback_(display_callback),
nsol_(0),
@@ -48,6 +51,7 @@ SearchLog::SearchLog(Solver* const s, IntVar* const obj,
max_depth_(0),
sliding_min_depth_(0),
sliding_max_depth_(0) {
CHECK(obj == NULL || var == NULL) << "Either var or obj need to be NULL.";
if (display_callback_ != NULL) {
display_callback_->CheckIsRepeatable();
}
@@ -81,9 +85,18 @@ bool SearchLog::AtSolution() {
Maintain();
const int depth = solver()->SearchDepth();
string obj_str = "";
int64 current = 0;
bool objective_updated = false;
if (obj_ != NULL) {
const int64 current = obj_->Value();
obj_str = StringPrintf("objective value = %" GG_LL_FORMAT "d, ", current);
current = obj_->Var()->Value();
obj_str = obj_->Print();
objective_updated = true;
} else if (var_!= NULL) {
current = var_->Value();
StringAppendF(&obj_str, "%" GG_LL_FORMAT "d", current);
objective_updated = true;
}
if (objective_updated) {
if (current >= objective_min_) {
StringAppendF(&obj_str,
"objective minimum = %" GG_LL_FORMAT "d, ",
@@ -233,21 +246,30 @@ string SearchLog::MemoryUsage() {
}
SearchMonitor* Solver::MakeSearchLog(int period) {
return RevAlloc(new SearchLog(this, NULL, NULL, period));
return RevAlloc(new SearchLog(this, NULL, NULL, NULL, period));
}
SearchMonitor* Solver::MakeSearchLog(int period, IntVar* const obj) {
return RevAlloc(new SearchLog(this, obj, NULL, period));
SearchMonitor* Solver::MakeSearchLog(int period, IntVar* const var) {
return RevAlloc(new SearchLog(this, NULL, var, NULL, period));
}
SearchMonitor* Solver::MakeSearchLog(int period,
ResultCallback<string>* display_callback) {
return RevAlloc(new SearchLog(this, NULL, display_callback, period));
return RevAlloc(new SearchLog(this, NULL, NULL, display_callback, period));
}
SearchMonitor* Solver::MakeSearchLog(int period, IntVar* const obj,
SearchMonitor* Solver::MakeSearchLog(int period, IntVar* const var,
ResultCallback<string>* display_callback) {
return RevAlloc(new SearchLog(this, obj, display_callback, period));
return RevAlloc(new SearchLog(this, NULL, var, display_callback, period));
}
SearchMonitor* Solver::MakeSearchLog(int period, OptimizeVar* const obj) {
return RevAlloc(new SearchLog(this, obj, NULL, NULL, period));
}
SearchMonitor* Solver::MakeSearchLog(int period, OptimizeVar* const obj,
ResultCallback<string>* display_callback) {
return RevAlloc(new SearchLog(this, obj, NULL, display_callback, period));
}
// ---------- Search Trace ----------
@@ -2148,6 +2170,10 @@ bool OptimizeVar::AtSolution() {
return true;
}
string OptimizeVar::Print() const {
return StringPrintf("objective value = %" GG_LL_FORMAT "d, ", var_->Value());
}
string OptimizeVar::DebugString() const {
string out;
if (maximize_) {
@@ -2174,6 +2200,79 @@ OptimizeVar* Solver::MakeOptimize(bool maximize, IntVar* const v, int64 step) {
return RevAlloc(new OptimizeVar(this, maximize, v, step));
}
class WeightedOptimizeVar: public OptimizeVar {
public:
WeightedOptimizeVar(Solver* solver,
bool maximize,
const vector<IntVar*>& sub_objectives,
const vector<int64>& weights,
int64 step)
: OptimizeVar(solver,
maximize,
solver->MakeScalProd(sub_objectives, weights)->Var(),
step),
size_(weights.size()) {
CHECK_EQ(sub_objectives.size(), weights.size());
sub_objectives_.reset(new IntVar*[size_]);
memcpy(sub_objectives_.get(),
sub_objectives.data(), size_ * sizeof(*sub_objectives.data()));
weights_.reset(new int64[size_]);
memcpy(weights_.get(),
weights.data(), size_ * sizeof(*weights.data()));
}
virtual ~WeightedOptimizeVar() {}
virtual string Print() const;
private:
const int64 size_;
scoped_array<IntVar*> sub_objectives_;
scoped_array<int64> weights_;
DISALLOW_COPY_AND_ASSIGN(WeightedOptimizeVar);
};
string WeightedOptimizeVar::Print() const {
string result(OptimizeVar::Print());
StringAppendF(&result, "\nWeighted Objective:\n");
for (int i = 0; i < size_; ++i) {
StringAppendF(&result, "Variable %s,\tvalue %lld,\tweight %lld\n",
sub_objectives_[i]->name().c_str(),
sub_objectives_[i]->Value(),
weights_[i]);
}
return result;
}
OptimizeVar* Solver::MakeWeightedOptimize(bool maximize,
const vector<IntVar*>& sub_objectives,
const vector<int64>& weights,
int64 step) {
return RevAlloc(new WeightedOptimizeVar(this,
maximize,
sub_objectives, weights,
step));
}
OptimizeVar* Solver::MakeWeightedMinimize(const vector<IntVar*>& sub_objectives,
const vector<int64>& weights,
int64 step) {
return RevAlloc(new WeightedOptimizeVar(this,
false,
sub_objectives, weights,
step));
}
OptimizeVar* Solver::MakeWeightedMaximize(const vector<IntVar*>& sub_objectives,
const vector<int64>& weights,
int64 step) {
return RevAlloc(new WeightedOptimizeVar(this,
true,
sub_objectives, weights,
step));
}
// ---------- Metaheuristics ---------
class Metaheuristic : public SearchMonitor {