constraint_solver: export from google3
This commit is contained in:
@@ -3416,9 +3416,7 @@ class PathState {
|
||||
// State-dependent accessors.
|
||||
|
||||
// Returns the committed path of a given node, -1 if it is a loop.
|
||||
int Path(int node) const {
|
||||
return committed_nodes_[committed_index_[node]].path;
|
||||
}
|
||||
int Path(int node) const { return committed_paths_[node]; }
|
||||
// Returns the set of paths that actually changed,
|
||||
// i.e. that have more than one chain.
|
||||
const std::vector<int>& ChangedPaths() const { return changed_paths_; }
|
||||
@@ -3476,14 +3474,6 @@ class PathState {
|
||||
int begin_index;
|
||||
int end_index;
|
||||
};
|
||||
struct CommittedNode {
|
||||
CommittedNode(int node, int path) : node(node), path(path) {}
|
||||
int node;
|
||||
// Path of node in the committed state, -1 for loop nodes.
|
||||
// TODO(user): check if path would be better stored
|
||||
// with committed_index_, or in its own vector, or just recomputed.
|
||||
int path;
|
||||
};
|
||||
|
||||
// Copies nodes in chains of path at the end of nodes,
|
||||
// and sets those nodes' path member to value path.
|
||||
@@ -3526,7 +3516,10 @@ class PathState {
|
||||
// Those chains do not overlap with one another or with committed chains.
|
||||
// - committed_nodes_ are not modified, and still represent the committed
|
||||
// paths. committed_index_ is not modified either.
|
||||
std::vector<CommittedNode> committed_nodes_;
|
||||
std::vector<int> committed_nodes_;
|
||||
// Maps nodes to their path in the latest committed state.
|
||||
std::vector<int> committed_paths_;
|
||||
// Maps nodes to their index in the latest committed state.
|
||||
std::vector<int> committed_index_;
|
||||
const int num_nodes_threshold_;
|
||||
std::vector<ChainBounds> chains_;
|
||||
@@ -3549,7 +3542,7 @@ class PathState::Chain {
|
||||
++current_node_;
|
||||
return *this;
|
||||
}
|
||||
int operator*() const { return current_node_->node; }
|
||||
int operator*() const { return *current_node_; }
|
||||
bool operator!=(Iterator other) const {
|
||||
return current_node_ != other.current_node_;
|
||||
}
|
||||
@@ -3557,26 +3550,26 @@ class PathState::Chain {
|
||||
private:
|
||||
// Only a Chain can construct its iterator.
|
||||
friend class PathState::Chain;
|
||||
explicit Iterator(const CommittedNode* node) : current_node_(node) {}
|
||||
const CommittedNode* current_node_;
|
||||
explicit Iterator(const int* node) : current_node_(node) {}
|
||||
const int* current_node_;
|
||||
};
|
||||
|
||||
// Chains hold CommittedNode* values, a Chain may be invalidated
|
||||
// if the underlying vector is modified.
|
||||
Chain(const CommittedNode* begin_node, const CommittedNode* end_node)
|
||||
Chain(const int* begin_node, const int* end_node)
|
||||
: begin_(begin_node), end_(end_node) {}
|
||||
|
||||
int NumNodes() const { return end_ - begin_; }
|
||||
int First() const { return begin_->node; }
|
||||
int Last() const { return (end_ - 1)->node; }
|
||||
int First() const { return *begin_; }
|
||||
int Last() const { return *(end_ - 1); }
|
||||
Iterator begin() const { return Iterator(begin_); }
|
||||
Iterator end() const { return Iterator(end_); }
|
||||
|
||||
Chain WithoutFirstNode() const { return Chain(begin_ + 1, end_); }
|
||||
|
||||
private:
|
||||
const CommittedNode* const begin_;
|
||||
const CommittedNode* const end_;
|
||||
const int* const begin_;
|
||||
const int* const end_;
|
||||
};
|
||||
|
||||
// A ChainRange is a range of Chains, committed or not.
|
||||
@@ -3599,17 +3592,16 @@ class PathState::ChainRange {
|
||||
private:
|
||||
// Only a ChainRange can construct its Iterator.
|
||||
friend class ChainRange;
|
||||
Iterator(const ChainBounds* chain, const CommittedNode* const first_node)
|
||||
Iterator(const ChainBounds* chain, const int* const first_node)
|
||||
: current_chain_(chain), first_node_(first_node) {}
|
||||
const ChainBounds* current_chain_;
|
||||
const CommittedNode* const first_node_;
|
||||
const int* const first_node_;
|
||||
};
|
||||
|
||||
// ChainRanges hold ChainBounds* and CommittedNode*,
|
||||
// a ChainRange may be invalidated if on of the underlying vector is modified.
|
||||
ChainRange(const ChainBounds* const begin_chain,
|
||||
const ChainBounds* const end_chain,
|
||||
const CommittedNode* const first_node)
|
||||
const ChainBounds* const end_chain, const int* const first_node)
|
||||
: begin_(begin_chain), end_(end_chain), first_node_(first_node) {}
|
||||
|
||||
Iterator begin() const { return {begin_, first_node_}; }
|
||||
@@ -3618,7 +3610,7 @@ class PathState::ChainRange {
|
||||
private:
|
||||
const ChainBounds* const begin_;
|
||||
const ChainBounds* const end_;
|
||||
const CommittedNode* const first_node_;
|
||||
const int* const first_node_;
|
||||
};
|
||||
|
||||
// A NodeRange allows to iterate on all nodes of a path,
|
||||
@@ -3639,7 +3631,7 @@ class PathState::NodeRange {
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
int operator*() const { return current_node_->node; }
|
||||
int operator*() const { return *current_node_; }
|
||||
bool operator!=(Iterator other) const {
|
||||
return current_chain_ != other.current_chain_;
|
||||
}
|
||||
@@ -3647,22 +3639,21 @@ class PathState::NodeRange {
|
||||
private:
|
||||
// Only a NodeRange can construct its Iterator.
|
||||
friend class NodeRange;
|
||||
Iterator(const ChainBounds* current_chain,
|
||||
const CommittedNode* const first_node)
|
||||
Iterator(const ChainBounds* current_chain, const int* const first_node)
|
||||
: current_node_(first_node + current_chain->begin_index),
|
||||
end_node_(first_node + current_chain->end_index),
|
||||
current_chain_(current_chain),
|
||||
first_node_(first_node) {}
|
||||
const CommittedNode* current_node_;
|
||||
const CommittedNode* end_node_;
|
||||
const int* current_node_;
|
||||
const int* end_node_;
|
||||
const ChainBounds* current_chain_;
|
||||
const CommittedNode* const first_node_;
|
||||
const int* const first_node_;
|
||||
};
|
||||
|
||||
// NodeRanges hold ChainBounds* and CommittedNode*,
|
||||
// NodeRanges hold ChainBounds* and int* (first committed node),
|
||||
// a NodeRange may be invalidated if on of the underlying vector is modified.
|
||||
NodeRange(const ChainBounds* begin_chain, const ChainBounds* end_chain,
|
||||
const CommittedNode* first_node)
|
||||
const int* first_node)
|
||||
: begin_chain_(begin_chain),
|
||||
end_chain_(end_chain),
|
||||
first_node_(first_node) {}
|
||||
@@ -3674,7 +3665,7 @@ class PathState::NodeRange {
|
||||
private:
|
||||
const ChainBounds* begin_chain_;
|
||||
const ChainBounds* end_chain_;
|
||||
const CommittedNode* const first_node_;
|
||||
const int* const first_node_;
|
||||
};
|
||||
|
||||
// This checker enforces dimension requirements.
|
||||
|
||||
@@ -2663,17 +2663,21 @@ PathState::PathState(int num_nodes, std::vector<int> path_start,
|
||||
}
|
||||
// Initial state is all unperformed: paths go from start to end directly.
|
||||
committed_index_.assign(num_nodes_, -1);
|
||||
committed_nodes_.assign(2 * num_paths_, {-1, -1});
|
||||
committed_paths_.assign(num_nodes_, -1);
|
||||
committed_nodes_.assign(2 * num_paths_, -1);
|
||||
chains_.assign(num_paths_ + 1, {-1, -1}); // Reserve 1 more for sentinel.
|
||||
paths_.assign(num_paths_, {-1, -1});
|
||||
for (int path = 0; path < num_paths_; ++path) {
|
||||
const int index = 2 * path;
|
||||
const PathStartEnd start_end = path_start_end_[path];
|
||||
committed_index_[start_end.start] = index;
|
||||
committed_index_[start_end.end] = index + 1;
|
||||
const auto& [start, end] = path_start_end_[path];
|
||||
committed_index_[start] = index;
|
||||
committed_index_[end] = index + 1;
|
||||
|
||||
committed_nodes_[index] = {start_end.start, path};
|
||||
committed_nodes_[index + 1] = {start_end.end, path};
|
||||
committed_nodes_[index] = start;
|
||||
committed_nodes_[index + 1] = end;
|
||||
|
||||
committed_paths_[start] = path;
|
||||
committed_paths_[end] = path;
|
||||
|
||||
chains_[path] = {index, index + 2};
|
||||
paths_[path] = {path, path + 1};
|
||||
@@ -2683,7 +2687,7 @@ PathState::PathState(int num_nodes, std::vector<int> path_start,
|
||||
for (int node = 0; node < num_nodes_; ++node) {
|
||||
if (committed_index_[node] != -1) continue; // node is start or end.
|
||||
committed_index_[node] = committed_nodes_.size();
|
||||
committed_nodes_.push_back({node, -1});
|
||||
committed_nodes_.push_back(node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2738,18 +2742,17 @@ void PathState::Revert() {
|
||||
|
||||
void PathState::CopyNewPathAtEndOfNodes(int path) {
|
||||
// Copy path's nodes, chain by chain.
|
||||
const int new_path_begin_index = committed_nodes_.size();
|
||||
const PathBounds path_bounds = paths_[path];
|
||||
for (int i = path_bounds.begin_index; i < path_bounds.end_index; ++i) {
|
||||
const ChainBounds chain_bounds = chains_[i];
|
||||
committed_nodes_.insert(committed_nodes_.end(),
|
||||
committed_nodes_.data() + chain_bounds.begin_index,
|
||||
committed_nodes_.data() + chain_bounds.end_index);
|
||||
if (committed_paths_[committed_nodes_.back()] == path) continue;
|
||||
for (int i = chain_bounds.begin_index; i < chain_bounds.end_index; ++i) {
|
||||
const int node = committed_nodes_[i];
|
||||
committed_paths_[node] = path;
|
||||
}
|
||||
const int new_path_end_index = committed_nodes_.size();
|
||||
// Set new nodes' path member to path.
|
||||
for (int i = new_path_begin_index; i < new_path_end_index; ++i) {
|
||||
committed_nodes_[i].path = path;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2766,13 +2769,13 @@ void PathState::IncrementalCommit() {
|
||||
// Re-index all copied nodes.
|
||||
const int new_nodes_end = committed_nodes_.size();
|
||||
for (int i = new_nodes_begin; i < new_nodes_end; ++i) {
|
||||
committed_index_[committed_nodes_[i].node] = i;
|
||||
const int node = committed_nodes_[i];
|
||||
committed_index_[node] = i;
|
||||
}
|
||||
// New loops stay in place: only change their path to -1,
|
||||
// committed_index_ does not change.
|
||||
for (const int loop : ChangedLoops()) {
|
||||
const int index = committed_index_[loop];
|
||||
committed_nodes_[index].path = -1;
|
||||
committed_paths_[loop] = -1;
|
||||
}
|
||||
// Committed part of the state is set up, erase incremental changes.
|
||||
Revert();
|
||||
@@ -2795,13 +2798,14 @@ void PathState::FullCommit() {
|
||||
constexpr int kUnindexed = -1;
|
||||
committed_index_.assign(num_nodes_, kUnindexed);
|
||||
int index = 0;
|
||||
for (const CommittedNode committed_node : committed_nodes_) {
|
||||
committed_index_[committed_node.node] = index++;
|
||||
for (const int node : committed_nodes_) {
|
||||
committed_index_[node] = index++;
|
||||
}
|
||||
for (int node = 0; node < num_nodes_; ++node) {
|
||||
if (committed_index_[node] != kUnindexed) continue;
|
||||
committed_index_[node] = index++;
|
||||
committed_nodes_.push_back({node, -1});
|
||||
committed_nodes_.push_back(node);
|
||||
committed_paths_[node] = -1;
|
||||
}
|
||||
// Committed part of the state is set up, erase incremental changes.
|
||||
Revert();
|
||||
|
||||
@@ -119,16 +119,11 @@ void CPIsFunCp() {
|
||||
letters, Solver::CHOOSE_FIRST_UNBOUND, Solver::ASSIGN_MIN_VALUE);
|
||||
solver.NewSearch(db);
|
||||
while (solver.NextSolution()) {
|
||||
LOG(INFO) << "C=" << c->Value() << " "
|
||||
<< "P=" << p->Value() << " "
|
||||
<< "I=" << i->Value() << " "
|
||||
<< "S=" << s->Value() << " "
|
||||
<< "F=" << f->Value() << " "
|
||||
<< "U=" << u->Value() << " "
|
||||
<< "N=" << n->Value() << " "
|
||||
<< "T=" << t->Value() << " "
|
||||
<< "R=" << r->Value() << " "
|
||||
<< "E=" << e->Value();
|
||||
LOG(INFO) << "C=" << c->Value() << " " << "P=" << p->Value() << " "
|
||||
<< "I=" << i->Value() << " " << "S=" << s->Value() << " "
|
||||
<< "F=" << f->Value() << " " << "U=" << u->Value() << " "
|
||||
<< "N=" << n->Value() << " " << "T=" << t->Value() << " "
|
||||
<< "R=" << r->Value() << " " << "E=" << e->Value();
|
||||
|
||||
// Is CP + IS + FUN = TRUE?
|
||||
CHECK_EQ(p->Value() + s->Value() + n->Value() +
|
||||
|
||||
@@ -191,8 +191,7 @@ void SolveNursesExample() {
|
||||
for (const auto day : days) {
|
||||
LOG(INFO) << "Day " << day << ":";
|
||||
for (const auto nurse : nurses) {
|
||||
LOG(INFO) << "Nurse " << nurse << " assigned to "
|
||||
<< "Task "
|
||||
LOG(INFO) << "Nurse " << nurse << " assigned to Task "
|
||||
<< collector->Value(solution,
|
||||
shifts_flat[nurse * days.size() + day]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user