Skip to content

Commit

Permalink
improve pseudo-cost branching in CP-SAT
Browse files Browse the repository at this point in the history
  • Loading branch information
lperron committed Jan 24, 2020
1 parent 8844610 commit cdf6d28
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 7 deletions.
10 changes: 10 additions & 0 deletions ortools/sat/cp_model.cc
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,12 @@ void CircuitConstraint::AddArc(int tail, int head, BoolVar literal) {
proto_->mutable_circuit()->add_literals(literal.index_);
}

void MultipleCircuitConstraint::AddArc(int tail, int head, BoolVar literal) {
proto_->mutable_routes()->add_tails(tail);
proto_->mutable_routes()->add_heads(head);
proto_->mutable_routes()->add_literals(literal.index_);
}

void TableConstraint::AddTuple(absl::Span<const int64> tuple) {
CHECK_EQ(tuple.size(), proto_->table().vars_size());
for (const int64 t : tuple) {
Expand Down Expand Up @@ -551,6 +557,10 @@ CircuitConstraint CpModelBuilder::AddCircuitConstraint() {
return CircuitConstraint(cp_model_.add_constraints());
}

MultipleCircuitConstraint CpModelBuilder::AddMultipleCircuitConstraint() {
return MultipleCircuitConstraint(cp_model_.add_constraints());
}

TableConstraint CpModelBuilder::AddAllowedAssignments(
absl::Span<const IntVar> vars) {
ConstraintProto* const proto = cp_model_.add_constraints();
Expand Down
40 changes: 40 additions & 0 deletions ortools/sat/cp_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ class BoolVar {
friend class CpModelBuilder;
friend class IntVar;
friend class IntervalVar;
friend class MultipleCircuitConstraint;
friend class LinearExpr;
friend class ReservoirConstraint;
friend bool SolutionBooleanValue(const CpSolverResponse& r, BoolVar x);
Expand Down Expand Up @@ -458,6 +459,29 @@ class CircuitConstraint : public Constraint {
using Constraint::Constraint;
};

/**
* Specialized circuit constraint.
*
* This constraint allows adding arcs to the multiple circuit constraint
* incrementally.
*/
class MultipleCircuitConstraint : public Constraint {
public:
/**
* Add an arc to the circuit.
*
* @param tail the index of the tail node.
* @param head the index of the head node.
* @param literal it will be set to true if the arc is selected.
*/
void AddArc(int tail, int head, BoolVar literal);

private:
friend class CpModelBuilder;

using Constraint::Constraint;
};

/**
* Specialized assignment constraint.
*
Expand Down Expand Up @@ -651,9 +675,25 @@ class CpModelBuilder {
*
* It returns a circuit constraint that allows adding arcs incrementally after
* construction.
*
*/
CircuitConstraint AddCircuitConstraint();

/**
* Adds a multiple circuit constraint, aka the "VRP" (Vehicle Routing Problem)
* constraint.
*
* The direct graph where arc #i (from tails[i] to head[i]) is present iff
* literals[i] is true must satisfy this set of properties:
* - #incoming arcs == 1 except for node 0.
* - #outgoing arcs == 1 except for node 0.
* - for node zero, #incoming arcs == #outgoing arcs.
* - There are no duplicate arcs.
* - Self-arcs are allowed except for node 0.
* - There is no cycle in this graph, except through node 0.
*/
MultipleCircuitConstraint AddMultipleCircuitConstraint();

/**
* Adds an allowed assignments constraint.
*
Expand Down
9 changes: 4 additions & 5 deletions ortools/sat/pseudo_costs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void PseudoCosts::UpdateCostForVar(IntegerVariable var, double new_cost) {
if (var >= pseudo_costs_.size()) {
// Create space for new variable and its negation.
const int new_size = std::max(var, NegationOf(var)).value() + 1;
pseudo_costs_.resize(new_size, IncrementalAverage(initial_cost_));
pseudo_costs_.resize(new_size, IncrementalAverage(0.0));
}
CHECK_LT(var, pseudo_costs_.size());
pseudo_costs_[var].AddData(new_cost);
Expand All @@ -71,8 +71,7 @@ void PseudoCosts::UpdateCost(
// Note that this initial value will be overwritten the first time
// UpdateCostForVar() is called.
if (!pseudo_costs_initialized_) {
initial_cost_ = current_pseudo_cost / 2.0;
InitializeCosts(initial_cost_);
InitializeCosts(0.0);
}
UpdateCostForVar(decision.var, current_pseudo_cost);
}
Expand Down Expand Up @@ -101,8 +100,8 @@ IntegerVariable PseudoCosts::GetBestDecisionVar() {

// TODO(user): Experiment with different ways to merge the costs.
const double current_merged_cost =
std::min(GetCost(positive_var), epsilon) *
std::min(GetCost(negative_var), epsilon);
std::max(GetCost(positive_var), epsilon) *
std::max(GetCost(negative_var), epsilon);

if (current_merged_cost > best_cost) {
chosen_var = positive_var;
Expand Down
2 changes: 0 additions & 2 deletions ortools/sat/pseudo_costs.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ class PseudoCosts {

bool pseudo_costs_initialized_ = false;

double initial_cost_ = 0.0;

gtl::ITIVector<IntegerVariable, IncrementalAverage> pseudo_costs_;
};

Expand Down

0 comments on commit cdf6d28

Please sign in to comment.