constraint_solver: export from google3

This commit is contained in:
Corentin Le Molgat
2024-01-22 14:37:08 +01:00
parent dd77367f5c
commit 399034ce82
4 changed files with 53 additions and 64 deletions

View File

@@ -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.

View File

@@ -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();

View File

@@ -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() +

View File

@@ -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]);
}