reindent code in src/base
This commit is contained in:
@@ -89,7 +89,7 @@
|
||||
// as key to hashable containers such as hash_map and hash_set.
|
||||
//
|
||||
// We suggest using the IntTypeIndexedContainer wrapper around STL
|
||||
// vector (see int_type_indexed_vector.h) if an IntType is intended
|
||||
// std::vector (see int_type_indexed_std::vector.h) if an IntType is intended
|
||||
// to be used as an index into these containers. These wrappers are
|
||||
// indexed in a type-safe manner using IntTypes to ensure type-safety.
|
||||
//
|
||||
@@ -259,7 +259,7 @@ std::ostream& operator<<(std::ostream& os, // NOLINT
|
||||
// -- NON-MEMBER ARITHMETIC OPERATORS ------------------------------------------
|
||||
// We support only the +, -, *, and / operators with the same IntType and
|
||||
// ValueType types. The reason is to allow simple manipulation on these IDs
|
||||
// when used as indices in vectors and arrays.
|
||||
// when used as indices in std::vectors and arrays.
|
||||
//
|
||||
// NB: Although it is possible to do IntType * IntType and IntType / IntType,
|
||||
// it is probably non-sensical from a dimensionality analysis perspective.
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This file provides the ITIVector container that wraps around the STL vector.
|
||||
// This file provides the ITIVector container that wraps around the STL
|
||||
// std::vector.
|
||||
// The wrapper restricts indexing to a pre-specified type-safe integer type or
|
||||
// IntType (see base/int_type.h). It prevents accidental indexing
|
||||
// by different "logical" integer-like types (e.g. another IntType) or native
|
||||
@@ -28,7 +29,8 @@
|
||||
// and the ValueType is a supported native integer type such as int or
|
||||
// uint64 (see base/int_type.h for details).
|
||||
//
|
||||
// The wrapper exposes all public methods of STL vector and behaves mostly as
|
||||
// The wrapper exposes all public methods of STL std::vector and behaves mostly
|
||||
// as
|
||||
// a pass-through. The only method modified to ensure type-safety is the
|
||||
// operator [] and the at() method.
|
||||
//
|
||||
@@ -65,7 +67,8 @@
|
||||
#include "base/macros.h"
|
||||
#include "base/int_type.h"
|
||||
|
||||
// STL vector ------------------------------------------------------------------
|
||||
// STL std::vector
|
||||
// ------------------------------------------------------------------
|
||||
template <typename IntType, typename T, typename Alloc = std::allocator<T> >
|
||||
class ITIVector : protected std::vector<T, Alloc> {
|
||||
public:
|
||||
@@ -99,10 +102,11 @@ class ITIVector : protected std::vector<T, Alloc> {
|
||||
// This const accessor is useful in defining the comparison operators below.
|
||||
const ParentType& get() const { return *this; }
|
||||
// The mutable accessor is useful when using auxiliar methods relying on
|
||||
// vector parameters such as JoinUsing(), strings::Split(), etc. Methods
|
||||
// std::vector parameters such as JoinUsing(), strings::Split(), etc. Methods
|
||||
// relying solely on iterators (e.g. STLDeleteElements) should work just fine
|
||||
// without the need for mutable_get(). NB: It should be used only in this
|
||||
// case and thus should not be abused to index the underlying vector without
|
||||
// case and thus should not be abused to index the underlying std::vector
|
||||
// without
|
||||
// the appropriate IntType.
|
||||
ParentType* mutable_get() { return this; }
|
||||
|
||||
@@ -118,7 +122,8 @@ class ITIVector : protected std::vector<T, Alloc> {
|
||||
return ParentType::at(i.template value<size_t>());
|
||||
}
|
||||
|
||||
// -- Pass-through methods to STL vector -------------------------------------
|
||||
// -- Pass-through methods to STL std::vector
|
||||
// -------------------------------------
|
||||
ITIVector& operator=(const ITIVector& x) {
|
||||
ParentType::operator=(x.get());
|
||||
return *this;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "base/logging.h"
|
||||
|
||||
namespace operations_research {
|
||||
// This class implements a simple block-based sparse vector.
|
||||
// This class implements a simple block-based sparse std::vector.
|
||||
template <class T>
|
||||
class sparsetable {
|
||||
public:
|
||||
|
||||
@@ -30,8 +30,8 @@ namespace {
|
||||
// the characters in the std::string, not the entire std::string as a single delimiter.
|
||||
// ----------------------------------------------------------------------
|
||||
template <typename ITR>
|
||||
static inline void InternalSplitStringUsingChar(const std::string& full,
|
||||
char c, ITR* result) {
|
||||
static inline void InternalSplitStringUsingChar(const std::string& full, char c,
|
||||
ITR* result) {
|
||||
const char* p = full.data();
|
||||
const char* end = p + full.size();
|
||||
while (p != end) {
|
||||
@@ -88,8 +88,8 @@ std::vector<std::string> Split(const std::string& full, const char* delim, int f
|
||||
}
|
||||
|
||||
std::vector<::operations_research::StringPiece> Split(const std::string& full,
|
||||
const char* delim,
|
||||
int64 flags) {
|
||||
const char* delim,
|
||||
int64 flags) {
|
||||
CHECK_EQ(SkipEmpty(), flags);
|
||||
std::vector<::operations_research::StringPiece> out;
|
||||
InternalSplitStringUsing(full, delim, &out);
|
||||
|
||||
@@ -35,8 +35,8 @@ std::vector<std::string> Split(const std::string& full, char delim, int flags);
|
||||
// Hack: the int64 allow the C++ compiler to distinguish the two functions. It
|
||||
// is possible to implement this more cleanly at the cost of more complexity.
|
||||
std::vector<::operations_research::StringPiece> Split(const std::string& full,
|
||||
const char* delim,
|
||||
int64 flags);
|
||||
const char* delim,
|
||||
int64 flags);
|
||||
|
||||
namespace delimiter {
|
||||
inline const char* AnyOf(const char* x) { return x; }
|
||||
|
||||
@@ -75,7 +75,7 @@ inline char* string_as_array(std::string* str) {
|
||||
}
|
||||
|
||||
// STLDeleteElements() deletes all the elements in an STL container and clears
|
||||
// the container. This function is suitable for use with a vector, set,
|
||||
// the container. This function is suitable for use with a std::vector, set,
|
||||
// hash_set, or any other STL container which defines sensible begin(), end(),
|
||||
// and clear() methods.
|
||||
//
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
//
|
||||
// SIMPLE EXAMPLE:
|
||||
//
|
||||
// Fill a std::vector<std::vector<int>> graph; representing your graph adjacency lists.
|
||||
// Fill a std::vector<std::vector<int>> graph; representing your graph adjacency
|
||||
// lists.
|
||||
// That is, graph[i] contains the nodes adjacent to node #i. The nodes must be
|
||||
// integers in [0, num_nodes). Then just do:
|
||||
//
|
||||
@@ -76,9 +77,11 @@ void FindStronglyConnectedComponents(const NodeIndex num_nodes,
|
||||
SccOutput* components);
|
||||
|
||||
// A simple custom output class that just counts the number of SCC. Not
|
||||
// allocating many vectors can save both space and speed if your graph is large.
|
||||
// allocating many std::vectors can save both space and speed if your graph is
|
||||
// large.
|
||||
//
|
||||
// Note: If this matters, you probably don't want to use std::vector<std::vector<int>> as
|
||||
// Note: If this matters, you probably don't want to use
|
||||
// std::vector<std::vector<int>> as
|
||||
// an input either. See StaticGraph in graph/graph.h
|
||||
// for an efficient graph data structure compatible with this algorithm.
|
||||
template<typename NodeIndex>
|
||||
@@ -97,7 +100,7 @@ struct SccCounterOutput {
|
||||
// still an iterative DFS.
|
||||
//
|
||||
// TODO(user): Possible optimizations:
|
||||
// - Try to reserve the vectors which sizes are bounded by num_nodes.
|
||||
// - Try to reserve the std::vectors which sizes are bounded by num_nodes.
|
||||
// - Use an index rather than doing push_back(), pop_back() on them.
|
||||
// - For a client needing many Scc computations one after another, it could be
|
||||
// better to wrap this in a class so we don't need to allocate the stacks at
|
||||
|
||||
@@ -468,8 +468,8 @@ int IntegerTrail::FindLowestTrailIndexThatExplainBound(
|
||||
|
||||
bool IntegerTrail::EnqueueAssociatedLiteral(
|
||||
Literal literal, IntegerLiteral i_lit,
|
||||
const std::vector<Literal>& literals_reason,
|
||||
const std::vector<IntegerLiteral>& bounds_reason,
|
||||
const std::vector<Literal>& literal_reason,
|
||||
const std::vector<IntegerLiteral>& integer_reason,
|
||||
BooleanVariable* variable_with_same_reason) {
|
||||
if (!trail_->Assignment().VariableIsAssigned(literal.Variable())) {
|
||||
if (integer_decision_levels_.empty()) {
|
||||
@@ -496,7 +496,7 @@ bool IntegerTrail::EnqueueAssociatedLiteral(
|
||||
}
|
||||
if (trail_->Assignment().LiteralIsFalse(literal)) {
|
||||
std::vector<Literal>* conflict = trail_->MutableConflict();
|
||||
*conflict = literals_reason;
|
||||
*conflict = literal_reason;
|
||||
|
||||
// This is tricky, in some corner cases, the same Enqueue() will call
|
||||
// EnqueueAssociatedLiteral() on a literal and its opposite. In this case,
|
||||
@@ -509,7 +509,7 @@ bool IntegerTrail::EnqueueAssociatedLiteral(
|
||||
integer_trail_.size()) {
|
||||
conflict->push_back(literal);
|
||||
}
|
||||
MergeReasonInto(bounds_reason, conflict);
|
||||
MergeReasonInto(integer_reason, conflict);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -517,15 +517,15 @@ bool IntegerTrail::EnqueueAssociatedLiteral(
|
||||
|
||||
namespace {
|
||||
|
||||
std::string ReasonDebugString(const std::vector<Literal>& literals_reason,
|
||||
const std::vector<IntegerLiteral>& bounds_reason) {
|
||||
std::string ReasonDebugString(const std::vector<Literal>& literal_reason,
|
||||
const std::vector<IntegerLiteral>& integer_reason) {
|
||||
std::string result = "literals:{";
|
||||
for (const Literal l : literals_reason) {
|
||||
for (const Literal l : literal_reason) {
|
||||
if (result.back() != '{') result += ",";
|
||||
result += l.DebugString();
|
||||
}
|
||||
result += "} bounds:{";
|
||||
for (const IntegerLiteral l : bounds_reason) {
|
||||
for (const IntegerLiteral l : integer_reason) {
|
||||
if (result.back() != '{') result += ",";
|
||||
result += l.DebugString();
|
||||
}
|
||||
@@ -555,8 +555,10 @@ std::string IntegerTrail::DebugString() {
|
||||
}
|
||||
|
||||
bool IntegerTrail::Enqueue(IntegerLiteral i_lit,
|
||||
const std::vector<Literal>& literals_reason,
|
||||
const std::vector<IntegerLiteral>& bounds_reason) {
|
||||
const std::vector<Literal>& literal_reason,
|
||||
const std::vector<IntegerLiteral>& integer_reason) {
|
||||
DCHECK(AllLiteralsAreFalse(literal_reason));
|
||||
|
||||
// Nothing to do if the bound is not better than the current one.
|
||||
if (i_lit.bound <= vars_[i_lit.var].current_bound) return true;
|
||||
++num_enqueues_;
|
||||
@@ -564,12 +566,12 @@ bool IntegerTrail::Enqueue(IntegerLiteral i_lit,
|
||||
// This may not indicate an incorectness, but just some propagators that
|
||||
// didn't reach a fixed-point at level zero.
|
||||
if (DEBUG_MODE && !integer_decision_levels_.empty()) {
|
||||
std::vector<Literal> l = literals_reason;
|
||||
MergeReasonInto(bounds_reason, &l);
|
||||
std::vector<Literal> l = literal_reason;
|
||||
MergeReasonInto(integer_reason, &l);
|
||||
CHECK(!l.empty())
|
||||
<< "Propagating a literal with no reason at a positive level!\n"
|
||||
<< "level:" << integer_decision_levels_.size() << " i_lit:" << i_lit
|
||||
<< " " << ReasonDebugString(literals_reason, bounds_reason) << "\n"
|
||||
<< " " << ReasonDebugString(literal_reason, integer_reason) << "\n"
|
||||
<< DebugString();
|
||||
}
|
||||
|
||||
@@ -587,7 +589,7 @@ bool IntegerTrail::Enqueue(IntegerLiteral i_lit,
|
||||
++interval_index;
|
||||
}
|
||||
if (interval_index == end_index) {
|
||||
return ReportConflict(literals_reason, bounds_reason);
|
||||
return ReportConflict(literal_reason, integer_reason);
|
||||
} else {
|
||||
var_to_current_lb_interval_index_.Set(var, interval_index);
|
||||
i_lit.bound = std::max(
|
||||
@@ -615,8 +617,8 @@ bool IntegerTrail::Enqueue(IntegerLiteral i_lit,
|
||||
for (; i < encoding.size(); ++i) {
|
||||
if (i_lit.bound <= encoding[i].value) break;
|
||||
const Literal literal = encoding[i].literal.Negated();
|
||||
if (!EnqueueAssociatedLiteral(literal, i_lit, literals_reason,
|
||||
bounds_reason,
|
||||
if (!EnqueueAssociatedLiteral(literal, i_lit, literal_reason,
|
||||
integer_reason,
|
||||
&first_propagated_variable)) {
|
||||
return false;
|
||||
}
|
||||
@@ -624,7 +626,7 @@ bool IntegerTrail::Enqueue(IntegerLiteral i_lit,
|
||||
|
||||
if (i == encoding.size()) {
|
||||
// Conflict: no possible values left.
|
||||
return ReportConflict(literals_reason, bounds_reason);
|
||||
return ReportConflict(literal_reason, integer_reason);
|
||||
} else {
|
||||
// We have a new min. Note that watched_min_ will be updated on the next
|
||||
// call to Propagate() since we just pushed the watched literal if it
|
||||
@@ -644,19 +646,19 @@ bool IntegerTrail::Enqueue(IntegerLiteral i_lit,
|
||||
if (!IsOptional(var) ||
|
||||
trail_->Assignment().LiteralIsFalse(Literal(is_empty_literals_[var]))) {
|
||||
std::vector<Literal>* conflict = trail_->MutableConflict();
|
||||
*conflict = literals_reason;
|
||||
*conflict = literal_reason;
|
||||
if (IsOptional(var)) {
|
||||
conflict->push_back(Literal(is_empty_literals_[var]));
|
||||
}
|
||||
|
||||
// This is the same as:
|
||||
// MergeReasonInto(bounds_reason, conflict);
|
||||
// MergeReasonInto(integer_reason, conflict);
|
||||
// MergeReasonInto({UpperBoundAsLiteral(var)}, conflict);
|
||||
// but with just one call to MergeReasonIntoInternal() for speed. Note
|
||||
// that it may also produce a smaller reason overall.
|
||||
DCHECK(tmp_queue_.empty());
|
||||
const int size = vars_.size();
|
||||
for (const IntegerLiteral& literal : bounds_reason) {
|
||||
for (const IntegerLiteral& literal : integer_reason) {
|
||||
const int trail_index = FindLowestTrailIndexThatExplainBound(literal);
|
||||
if (trail_index >= size) tmp_queue_.push_back(trail_index);
|
||||
}
|
||||
@@ -686,9 +688,8 @@ bool IntegerTrail::Enqueue(IntegerLiteral i_lit,
|
||||
const LiteralIndex literal_index =
|
||||
encoder_->SearchForLiteralAtOrBefore(i_lit);
|
||||
if (literal_index != kNoLiteralIndex) {
|
||||
if (!EnqueueAssociatedLiteral(Literal(literal_index), i_lit,
|
||||
literals_reason, bounds_reason,
|
||||
&first_propagated_variable)) {
|
||||
if (!EnqueueAssociatedLiteral(Literal(literal_index), i_lit, literal_reason,
|
||||
integer_reason, &first_propagated_variable)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -716,15 +717,15 @@ bool IntegerTrail::Enqueue(IntegerLiteral i_lit,
|
||||
vars_[i_lit.var].current_trail_index = integer_trail_.size() - 1;
|
||||
|
||||
// Save the reason into our internal buffers.
|
||||
if (!literals_reason.empty()) {
|
||||
if (!literal_reason.empty()) {
|
||||
literals_reason_buffer_.insert(literals_reason_buffer_.end(),
|
||||
literals_reason.begin(),
|
||||
literals_reason.end());
|
||||
literal_reason.begin(),
|
||||
literal_reason.end());
|
||||
}
|
||||
if (!bounds_reason.empty()) {
|
||||
CHECK_NE(bounds_reason[0].var, kNoIntegerVariable);
|
||||
if (!integer_reason.empty()) {
|
||||
CHECK_NE(integer_reason[0].var, kNoIntegerVariable);
|
||||
bounds_reason_buffer_.insert(bounds_reason_buffer_.end(),
|
||||
bounds_reason.begin(), bounds_reason.end());
|
||||
integer_reason.begin(), integer_reason.end());
|
||||
}
|
||||
|
||||
// Subtle: We do that after the IntegerLiteral as been enqueued for 2 reasons:
|
||||
@@ -733,7 +734,7 @@ bool IntegerTrail::Enqueue(IntegerLiteral i_lit,
|
||||
// TODO(user): The point 2 is brittle, try to clean it up.
|
||||
if (propagate_is_empty) {
|
||||
const Literal is_empty = Literal(is_empty_literals_[var]);
|
||||
EnqueueLiteral(is_empty, literals_reason, bounds_reason);
|
||||
EnqueueLiteral(is_empty, literal_reason, integer_reason);
|
||||
bounds_reason_buffer_.push_back(UpperBoundAsLiteral(var));
|
||||
}
|
||||
|
||||
@@ -790,6 +791,14 @@ std::vector<Literal> IntegerTrail::ReasonFor(IntegerLiteral literal) const {
|
||||
return reason;
|
||||
}
|
||||
|
||||
bool IntegerTrail::AllLiteralsAreFalse(
|
||||
const std::vector<Literal>& literals) const {
|
||||
for (const Literal lit : literals) {
|
||||
if (!trail_->Assignment().LiteralIsFalse(lit)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO(user): If this is called many time on the same variables, it could be
|
||||
// made faster by using some caching mecanism.
|
||||
void IntegerTrail::MergeReasonInto(const std::vector<IntegerLiteral>& literals,
|
||||
@@ -892,6 +901,7 @@ ClauseRef IntegerTrail::Reason(const Trail& trail, int trail_index) const {
|
||||
void IntegerTrail::EnqueueLiteral(
|
||||
Literal literal, const std::vector<Literal>& literal_reason,
|
||||
const std::vector<IntegerLiteral>& integer_reason) {
|
||||
DCHECK(AllLiteralsAreFalse(literal_reason));
|
||||
if (integer_decision_levels_.empty()) {
|
||||
// Level zero. We don't keep any reason.
|
||||
trail_->EnqueueWithUnitReason(literal);
|
||||
|
||||
@@ -420,22 +420,18 @@ class IntegerTrail : public SatPropagator {
|
||||
IntegerLiteral LowerBoundAsLiteral(IntegerVariable i) const;
|
||||
IntegerLiteral UpperBoundAsLiteral(IntegerVariable i) const;
|
||||
|
||||
// Enqueue new information about a variable bound. Note that this can be used
|
||||
// at the decision level zero to change the initial variable bounds, but only
|
||||
// to make them more restricted. Calling this with a less restrictive bound
|
||||
// than the current one will have no effect.
|
||||
// Enqueue new information about a variable bound. Calling this with a less
|
||||
// restrictive bound than the current one will have no effect.
|
||||
//
|
||||
// The reason for this "assignment" can be a combination of:
|
||||
// The reason for this "assignment" must be provided as:
|
||||
// - A set of Literal currently beeing all false.
|
||||
// - A set of IntegerLiteral currently beeing all satisfied.
|
||||
// - A set of IntegerLiteral currently beeing all true.
|
||||
//
|
||||
// IMPORTANT: Notice the inversed sign in the literal reason. This is a bit
|
||||
// confusing but internally SAT use this direction for efficiency.
|
||||
//
|
||||
// TODO(user): provide an API to give the reason lazily.
|
||||
//
|
||||
// TODO(user): change the Literal signs to all true? it is often confusing to
|
||||
// have all false as a reason. But this is kind of historical because of a
|
||||
// clause beeing a reason for an assignment when all but one of its literals
|
||||
// are false.
|
||||
//
|
||||
// TODO(user): If the given bound is equal to the current bound, maybe the new
|
||||
// reason is better? how to decide and what to do in this case? to think about
|
||||
// it. Currently we simply don't do anything.
|
||||
@@ -444,6 +440,7 @@ class IntegerTrail : public SatPropagator {
|
||||
const std::vector<IntegerLiteral>& integer_reason);
|
||||
|
||||
// Enqueues the given literal on the trail.
|
||||
// See the comment of Enqueue() for the reason format.
|
||||
void EnqueueLiteral(Literal literal,
|
||||
const std::vector<Literal>& literal_reason,
|
||||
const std::vector<IntegerLiteral>& integer_reason);
|
||||
@@ -496,6 +493,10 @@ class IntegerTrail : public SatPropagator {
|
||||
}
|
||||
|
||||
private:
|
||||
// Tests that all the literals in the given reason are assigned to false.
|
||||
// This is used to DCHECK the given reasons to the Enqueue*() functions.
|
||||
bool AllLiteralsAreFalse(const std::vector<Literal>& literals) const;
|
||||
|
||||
// Does the work of MergeReasonInto() when queue_ is already initialized.
|
||||
void MergeReasonIntoInternal(std::vector<Literal>* output) const;
|
||||
|
||||
@@ -503,8 +504,8 @@ class IntegerTrail : public SatPropagator {
|
||||
// the given i_lit and maintained by encoder_.
|
||||
bool EnqueueAssociatedLiteral(
|
||||
Literal literal, IntegerLiteral i_lit,
|
||||
const std::vector<Literal>& literals_reason,
|
||||
const std::vector<IntegerLiteral>& bounds_reason,
|
||||
const std::vector<Literal>& literal_reason,
|
||||
const std::vector<IntegerLiteral>& integer_reason,
|
||||
BooleanVariable* variable_with_same_reason);
|
||||
|
||||
// Returns a lower bound on the given var that will always be valid.
|
||||
|
||||
Reference in New Issue
Block a user