Skip to content

Commit 2b3439a

Browse files
committed
graph: export from google3
1 parent f11ca04 commit 2b3439a

File tree

5 files changed

+87
-67
lines changed

5 files changed

+87
-67
lines changed

ortools/graph/connected_components.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020
#include <numeric>
2121
#include <vector>
2222

23+
#include "absl/log/check.h"
2324
#include "ortools/base/stl_util.h"
2425

2526
void DenseConnectedComponentsFinder::SetNumberOfNodes(int num_nodes) {
2627
const int old_num_nodes = GetNumberOfNodes();
2728
if (num_nodes == old_num_nodes) {
2829
return;
2930
}
31+
CHECK_GE(num_nodes, 0) << "Number of nodes overflowed the `int` type.";
3032
CHECK_GT(num_nodes, old_num_nodes);
3133
// Each new node starts as an isolated component:
3234
// It has itself as root.

ortools/graph/flow_graph.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,13 @@ namespace util {
4949
// TODO(user): Currently only max-flow handles this graph, but not
5050
// min-cost-flow.
5151
template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
52-
class FlowGraph : public BaseGraph<NodeIndexType, ArcIndexType, false> {
52+
class FlowGraph : public BaseGraph<FlowGraph<NodeIndexType, ArcIndexType>,
53+
NodeIndexType, ArcIndexType, false> {
5354
// Note that we do NOT use negated indices for reverse arc. So we use false
5455
// for the last template argument here HasNegativeReverseArcs.
55-
typedef BaseGraph<NodeIndexType, ArcIndexType, false> Base;
56+
typedef BaseGraph<FlowGraph<NodeIndexType, ArcIndexType>, NodeIndexType,
57+
ArcIndexType, false>
58+
Base;
5659
using Base::arc_capacity_;
5760
using Base::const_capacities_;
5861
using Base::node_capacity_;
@@ -146,7 +149,7 @@ class FlowGraph : public BaseGraph<NodeIndexType, ArcIndexType, false> {
146149
}
147150

148151
void Build() { Build(nullptr); }
149-
void Build(std::vector<ArcIndexType>* permutation);
152+
void Build(std::vector<ArcIndexType>* permutation) final;
150153

151154
// This influence what Build() does. If true, we will detect already existing
152155
// pairs of (arc, reverse_arc) and only construct new reverse arc for the one

ortools/graph/graph.h

Lines changed: 71 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,10 @@ class Vector;
201201
// strong integer types (e.g. `StrongInt`). Strong integer types are types that
202202
// behave like integers (comparison, arithmetic, etc.), and are (explicitly)
203203
// constructible/convertible from/to integers.
204-
template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t,
205-
bool HasNegativeReverseArcs = false>
206-
class BaseGraph {
204+
template <typename Impl, typename NodeIndexType = int32_t,
205+
typename ArcIndexType = int32_t, bool HasNegativeReverseArcs = false>
206+
class BaseGraph //
207+
{
207208
public:
208209
// Typedef so you can use Graph::NodeIndex and Graph::ArcIndex to be generic
209210
// but also to improve the readability of your code. We also recommend
@@ -291,6 +292,21 @@ class BaseGraph {
291292
static constexpr ArcIndexType kNilArc =
292293
std::numeric_limits<ArcIndexType>::max();
293294

295+
// Some graph implementations need to be finalized with Build() before they
296+
// can be used. Build() may change the arc indices (which had been the
297+
// return values of previous AddArc() calls): the new index of former arc #i
298+
// will be stored in permutation[i] if #i is smaller than permutation.size(),
299+
// or will be unchanged otherwise. If you don't care about these, just call
300+
// the simple no-output version Build().
301+
//
302+
// Note that some implementations become immutable after calling Build().
303+
// By default, Build() is a no-op.
304+
virtual void Build(std::vector<ArcIndexType>* permutation) {
305+
if (permutation != nullptr) permutation->clear();
306+
}
307+
void Build() { Build(nullptr); }
308+
virtual bool IsBuilt() const { return true; }
309+
294310
protected:
295311
// Functions commented when defined because they are implementation details.
296312
void ComputeCumulativeSum(internal::Vector<NodeIndexType, ArcIndexType>* v);
@@ -643,8 +659,11 @@ struct GraphTraits {
643659
// result in the same order).
644660
//
645661
template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
646-
class ListGraph : public BaseGraph<NodeIndexType, ArcIndexType, false> {
647-
typedef BaseGraph<NodeIndexType, ArcIndexType, false> Base;
662+
class ListGraph : public BaseGraph<ListGraph<NodeIndexType, ArcIndexType>,
663+
NodeIndexType, ArcIndexType, false> {
664+
typedef BaseGraph<ListGraph<NodeIndexType, ArcIndexType>, NodeIndexType,
665+
ArcIndexType, false>
666+
Base;
648667
using Base::arc_capacity_;
649668
using Base::const_capacities_;
650669
using Base::node_capacity_;
@@ -679,17 +698,6 @@ class ListGraph : public BaseGraph<NodeIndexType, ArcIndexType, false> {
679698
// Note: Self referencing arcs and duplicate arcs are supported.
680699
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
681700

682-
// Some graph implementations need to be finalized with Build() before they
683-
// can be used. After Build() is called, the arc indices (which had been the
684-
// return values of previous AddArc() calls) may change: the new index of
685-
// former arc #i will be stored in permutation[i] if #i is smaller than
686-
// permutation.size() or will be unchanged otherwise. If you don't care about
687-
// these, just call the simple no-output version Build().
688-
//
689-
// Note that some implementations become immutable after calling Build().
690-
void Build() { Build(nullptr); }
691-
void Build(std::vector<ArcIndexType>* permutation);
692-
693701
// Returns the tail/head of a valid arc.
694702
NodeIndexType Tail(ArcIndexType arc) const;
695703
NodeIndexType Head(ArcIndexType arc) const;
@@ -759,8 +767,11 @@ class ListGraph : public BaseGraph<NodeIndexType, ArcIndexType, false> {
759767
// StaticGraphWithoutTail<>. This almost corresponds to a past implementation
760768
// of StaticGraph<> @CL 116144340.
761769
template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
762-
class StaticGraph : public BaseGraph<NodeIndexType, ArcIndexType, false> {
763-
typedef BaseGraph<NodeIndexType, ArcIndexType, false> Base;
770+
class StaticGraph : public BaseGraph<StaticGraph<NodeIndexType, ArcIndexType>,
771+
NodeIndexType, ArcIndexType, false> {
772+
typedef BaseGraph<StaticGraph<NodeIndexType, ArcIndexType>, NodeIndexType,
773+
ArcIndexType, false>
774+
Base;
764775
using Base::arc_capacity_;
765776
using Base::const_capacities_;
766777
using Base::node_capacity_;
@@ -811,8 +822,9 @@ class StaticGraph : public BaseGraph<NodeIndexType, ArcIndexType, false> {
811822
void AddNode(NodeIndexType node);
812823
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
813824

825+
void Build(std::vector<ArcIndexType>* permutation) final;
814826
void Build() { Build(nullptr); }
815-
void Build(std::vector<ArcIndexType>* permutation);
827+
bool IsBuilt() const final { return is_built_; }
816828

817829
private:
818830
ArcIndexType DirectArcLimit(NodeIndexType node) const {
@@ -839,11 +851,14 @@ class StaticGraph : public BaseGraph<NodeIndexType, ArcIndexType, false> {
839851
// + 2 * (ArcIndexType + NodeIndexType) * arc_capacity() memory.
840852
template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
841853
class ReverseArcListGraph
842-
: public BaseGraph<NodeIndexType, ArcIndexType, true> {
854+
: public BaseGraph<ReverseArcListGraph<NodeIndexType, ArcIndexType>,
855+
NodeIndexType, ArcIndexType, true> {
843856
static_assert(internal::IsSigned<ArcIndexType>(),
844857
"ArcIndexType must be signed");
845858

846-
typedef BaseGraph<NodeIndexType, ArcIndexType, true> Base;
859+
typedef BaseGraph<ReverseArcListGraph<NodeIndexType, ArcIndexType>,
860+
NodeIndexType, ArcIndexType, true>
861+
Base;
847862
using Base::arc_capacity_;
848863
using Base::const_capacities_;
849864
using Base::node_capacity_;
@@ -954,9 +969,6 @@ class ReverseArcListGraph
954969
void AddNode(NodeIndexType node);
955970
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
956971

957-
void Build() { Build(nullptr); }
958-
void Build(std::vector<ArcIndexType>* permutation);
959-
960972
private:
961973
internal::Vector<NodeIndexType, ArcIndexType> start_;
962974
internal::Vector<NodeIndexType, ArcIndexType> reverse_start_;
@@ -975,11 +987,14 @@ class ReverseArcListGraph
975987
// time lookup function).
976988
template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
977989
class ReverseArcStaticGraph
978-
: public BaseGraph<NodeIndexType, ArcIndexType, true> {
990+
: public BaseGraph<ReverseArcStaticGraph<NodeIndexType, ArcIndexType>,
991+
NodeIndexType, ArcIndexType, true> {
979992
static_assert(internal::IsSigned<ArcIndexType>(),
980993
"ArcIndexType must be signed");
981994

982-
typedef BaseGraph<NodeIndexType, ArcIndexType, true> Base;
995+
typedef BaseGraph<ReverseArcStaticGraph<NodeIndexType, ArcIndexType>,
996+
NodeIndexType, ArcIndexType, true>
997+
Base;
983998
using Base::arc_capacity_;
984999
using Base::const_capacities_;
9851000
using Base::node_capacity_;
@@ -1069,8 +1084,9 @@ class ReverseArcStaticGraph
10691084
void AddNode(NodeIndexType node);
10701085
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
10711086

1087+
void Build(std::vector<ArcIndexType>* permutation) final;
10721088
void Build() { Build(nullptr); }
1073-
void Build(std::vector<ArcIndexType>* permutation);
1089+
bool IsBuilt() const final { return is_built_; }
10741090

10751091
private:
10761092
ArcIndexType DirectArcLimit(NodeIndexType node) const {
@@ -1124,41 +1140,42 @@ void Permute(const IntVector& permutation, Array* array_to_permute) {
11241140

11251141
// BaseGraph implementation ----------------------------------------------------
11261142

1127-
template <typename NodeIndexType, typename ArcIndexType,
1143+
template <typename Impl, typename NodeIndexType, typename ArcIndexType,
11281144
bool HasNegativeReverseArcs>
1129-
IntegerRange<NodeIndexType> BaseGraph<
1130-
NodeIndexType, ArcIndexType, HasNegativeReverseArcs>::AllNodes() const {
1145+
IntegerRange<NodeIndexType>
1146+
BaseGraph<Impl, NodeIndexType, ArcIndexType, HasNegativeReverseArcs>::AllNodes()
1147+
const {
11311148
return IntegerRange<NodeIndexType>(NodeIndexType(0), num_nodes_);
11321149
}
11331150

1134-
template <typename NodeIndexType, typename ArcIndexType,
1151+
template <typename Impl, typename NodeIndexType, typename ArcIndexType,
11351152
bool HasNegativeReverseArcs>
1136-
IntegerRange<ArcIndexType>
1137-
BaseGraph<NodeIndexType, ArcIndexType, HasNegativeReverseArcs>::AllForwardArcs()
1153+
IntegerRange<ArcIndexType> BaseGraph<Impl, NodeIndexType, ArcIndexType,
1154+
HasNegativeReverseArcs>::AllForwardArcs()
11381155
const {
11391156
return IntegerRange<ArcIndexType>(ArcIndexType(0), num_arcs_);
11401157
}
11411158

1142-
template <typename NodeIndexType, typename ArcIndexType,
1159+
template <typename Impl, typename NodeIndexType, typename ArcIndexType,
11431160
bool HasNegativeReverseArcs>
1144-
NodeIndexType BaseGraph<NodeIndexType, ArcIndexType,
1161+
NodeIndexType BaseGraph<Impl, NodeIndexType, ArcIndexType,
11451162
HasNegativeReverseArcs>::node_capacity() const {
11461163
// TODO(user): Is it needed? remove completely? return the real capacities
11471164
// at the cost of having a different implementation for each graphs?
11481165
return node_capacity_ > num_nodes_ ? node_capacity_ : num_nodes_;
11491166
}
11501167

1151-
template <typename NodeIndexType, typename ArcIndexType,
1168+
template <typename Impl, typename NodeIndexType, typename ArcIndexType,
11521169
bool HasNegativeReverseArcs>
1153-
ArcIndexType BaseGraph<NodeIndexType, ArcIndexType,
1170+
ArcIndexType BaseGraph<Impl, NodeIndexType, ArcIndexType,
11541171
HasNegativeReverseArcs>::arc_capacity() const {
11551172
// TODO(user): Same questions as the ones in node_capacity().
11561173
return arc_capacity_ > num_arcs_ ? arc_capacity_ : num_arcs_;
11571174
}
11581175

1159-
template <typename NodeIndexType, typename ArcIndexType,
1176+
template <typename Impl, typename NodeIndexType, typename ArcIndexType,
11601177
bool HasNegativeReverseArcs>
1161-
void BaseGraph<NodeIndexType, ArcIndexType,
1178+
void BaseGraph<Impl, NodeIndexType, ArcIndexType,
11621179
HasNegativeReverseArcs>::FreezeCapacities() {
11631180
// TODO(user): Only define this in debug mode at the cost of having a lot
11641181
// of ifndef NDEBUG all over the place? remove the function completely ?
@@ -1169,9 +1186,9 @@ void BaseGraph<NodeIndexType, ArcIndexType,
11691186

11701187
// Computes the cumulative sum of the entry in v. We only use it with
11711188
// in/out degree distribution, hence the Check() at the end.
1172-
template <typename NodeIndexType, typename ArcIndexType,
1189+
template <typename Impl, typename NodeIndexType, typename ArcIndexType,
11731190
bool HasNegativeReverseArcs>
1174-
void BaseGraph<NodeIndexType, ArcIndexType, HasNegativeReverseArcs>::
1191+
void BaseGraph<Impl, NodeIndexType, ArcIndexType, HasNegativeReverseArcs>::
11751192
ComputeCumulativeSum(internal::Vector<NodeIndexType, ArcIndexType>* v) {
11761193
DCHECK_EQ(v->size(), num_nodes_ + NodeIndexType(1));
11771194
ArcIndexType sum(0);
@@ -1189,9 +1206,9 @@ void BaseGraph<NodeIndexType, ArcIndexType, HasNegativeReverseArcs>::
11891206
// - Put the head of the new arc #i in (*head)[i].
11901207
// - Put in start[i] the index of the first arc with tail >= i.
11911208
// - Update "permutation" to reflect the change, unless it is NULL.
1192-
template <typename NodeIndexType, typename ArcIndexType,
1209+
template <typename Impl, typename NodeIndexType, typename ArcIndexType,
11931210
bool HasNegativeReverseArcs>
1194-
void BaseGraph<NodeIndexType, ArcIndexType, HasNegativeReverseArcs>::
1211+
void BaseGraph<Impl, NodeIndexType, ArcIndexType, HasNegativeReverseArcs>::
11951212
BuildStartAndForwardHead(
11961213
internal::SVector<ArcIndexType, NodeIndexType>* head,
11971214
internal::Vector<NodeIndexType, ArcIndexType>* start,
@@ -1362,14 +1379,6 @@ void ListGraph<NodeIndexType, ArcIndexType>::ReserveArcs(ArcIndexType bound) {
13621379
next_.reserve(bound);
13631380
}
13641381

1365-
template <typename NodeIndexType, typename ArcIndexType>
1366-
void ListGraph<NodeIndexType, ArcIndexType>::Build(
1367-
std::vector<ArcIndexType>* permutation) {
1368-
if (permutation != nullptr) {
1369-
permutation->clear();
1370-
}
1371-
}
1372-
13731382
// StaticGraph implementation --------------------------------------------------
13741383

13751384
template <typename NodeIndexType, typename ArcIndexType>
@@ -1627,14 +1636,6 @@ ArcIndexType ReverseArcListGraph<NodeIndexType, ArcIndexType>::AddArc(
16271636
return num_arcs_++;
16281637
}
16291638

1630-
template <typename NodeIndexType, typename ArcIndexType>
1631-
void ReverseArcListGraph<NodeIndexType, ArcIndexType>::Build(
1632-
std::vector<ArcIndexType>* permutation) {
1633-
if (permutation != nullptr) {
1634-
permutation->clear();
1635-
}
1636-
}
1637-
16381639
template <typename NodeIndexType, typename ArcIndexType>
16391640
class ReverseArcListGraph<NodeIndexType,
16401641
ArcIndexType>::OutgoingOrOppositeIncomingArcIterator {
@@ -1852,8 +1853,12 @@ class ReverseArcStaticGraph<
18521853
// Nodes and arcs are implicit and not stored.
18531854

18541855
template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
1855-
class CompleteGraph : public BaseGraph<NodeIndexType, ArcIndexType, false> {
1856-
typedef BaseGraph<NodeIndexType, ArcIndexType, false> Base;
1856+
class CompleteGraph
1857+
: public BaseGraph<CompleteGraph<NodeIndexType, ArcIndexType>,
1858+
NodeIndexType, ArcIndexType, false> {
1859+
typedef BaseGraph<CompleteGraph<NodeIndexType, ArcIndexType>, NodeIndexType,
1860+
ArcIndexType, false>
1861+
Base;
18571862
using Base::arc_capacity_;
18581863
using Base::const_capacities_;
18591864
using Base::node_capacity_;
@@ -1936,8 +1941,11 @@ CompleteGraph<NodeIndexType, ArcIndexType>::operator[](
19361941

19371942
template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
19381943
class CompleteBipartiteGraph
1939-
: public BaseGraph<NodeIndexType, ArcIndexType, false> {
1940-
typedef BaseGraph<NodeIndexType, ArcIndexType, false> Base;
1944+
: public BaseGraph<CompleteBipartiteGraph<NodeIndexType, ArcIndexType>,
1945+
NodeIndexType, ArcIndexType, false> {
1946+
typedef BaseGraph<CompleteBipartiteGraph<NodeIndexType, ArcIndexType>,
1947+
NodeIndexType, ArcIndexType, false>
1948+
Base;
19411949
using Base::arc_capacity_;
19421950
using Base::const_capacities_;
19431951
using Base::node_capacity_;

ortools/graph/graph_test.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <vector>
2626

2727
#include "absl/algorithm/container.h"
28+
#include "absl/base/log_severity.h"
2829
#include "absl/log/check.h"
2930
#include "absl/random/random.h"
3031
#include "absl/strings/str_cat.h"
@@ -37,7 +38,10 @@
3738

3839
namespace util {
3940

41+
using testing::_;
42+
using testing::AllOf;
4043
using testing::ElementsAre;
44+
using testing::Field;
4145
using testing::Pair;
4246
using testing::UnorderedElementsAre;
4347

ortools/graph/topologicalsorter.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ namespace graph {
6363
// StaticGraph<> in ./graph.h: FastTopologicalSort() can take any such graph as
6464
// input.
6565
//
66+
// If you have a util_graph::Graph and don't need input validation, consider
67+
// util_graph::TopoOrder(): it has an even simpler API and is only 1.5x slower.
68+
//
6669
// ERRORS: returns InvalidArgumentError if the input is broken (negative or
6770
// out-of-bounds integers) or if the graph is cyclic. In the latter case, the
6871
// error message will contain "cycle". Note that if cycles may occur in your
@@ -72,7 +75,7 @@ namespace graph {
7275
// TIE BREAKING: the returned topological order is deterministic and fixed, and
7376
// corresponds to iterating on nodes in a LIFO (Breadth-first) order.
7477
//
75-
// Benchmark: gpaste/6147236302946304, 4-10x faster than util_graph::TopoSort().
78+
// Benchmark: gpaste/4894742655664128.
7679
//
7780
// EXAMPLES:
7881
// std::vector<std::vector<int>> adj = {{..}, {..}, ..};

0 commit comments

Comments
 (0)