Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
graph.h
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// This file defines a generic graph interface on which most algorithms can be
15// built and provides a few efficient implementations with a fast construction
16// time. Its design is based on the experience acquired by the Operations
17// Research team in their various graph algorithm implementations.
18//
19// Also see README.md#basegraph for a more graphical documentation of the
20// concepts presented here.
21//
22// The main ideas are:
23// - Graph nodes and arcs are represented by integers.
24// - Node or arc annotations (weight, cost, ...) are not part of the graph
25// class, they can be stored outside in one or more arrays and can be easily
26// retrieved using a node or arc as an index.
27//
28// Terminology:
29// - An arc of a graph is directed and going from a tail node to a head node.
30// - Some implementations also store 'reverse' arcs and can be used for
31// undirected graph or flow-like algorithm.
32// - A node or arc index is 'valid' if it represents a node or arc of
33// the graph. The validity ranges are always [0, num_nodes()) for nodes and
34// [0, num_arcs()) for forward arcs. Reverse arcs are elements of
35// [-num_arcs(), 0) and are also considered valid by the implementations that
36// store them.
37//
38// Provided implementations:
39// - ListGraph<> for the simplest api. Also aliased to util::Graph.
40// - StaticGraph<> for performance, but require calling Build(), see below
41// - CompleteGraph<> if you need a fully connected graph
42// - CompleteBipartiteGraph<> if you need a fully connected bipartite graph
43// - ReverseArcListGraph<> to add reverse arcs to ListGraph<>
44// - ReverseArcStaticGraph<> to add reverse arcs to StaticGraph<>
45//
46// Utility classes & functions:
47// - Permute() to permute an array according to a given permutation.
48// - SVector<> vector with index range [-size(), size()) for ReverseArcGraph.
49//
50// Basic usage:
51// typedef ListGraph<> Graph; // Choose a graph implementation.
52// Graph graph;
53// for (...) {
54// graph.AddArc(tail, head);
55// }
56// ...
57// for (int node = 0; node < graph.num_nodes(); ++node) {
58// for (const int arc : graph.OutgoingArcs(node)) {
59// head = graph.Head(arc);
60// tail = node; // or graph.Tail(arc) which is fast but not as much.
61// }
62// }
63//
64// Iteration over the arcs touching a node:
65//
66// - OutgoingArcs(node): All the forward arcs leaving the node.
67// - IncomingArcs(node): All the forward arcs arriving at the node.
68//
69// And two more involved ones:
70//
71// - OutgoingOrOppositeIncomingArcs(node): This returns both the forward arcs
72// leaving the node (i.e. OutgoingArcs(node)) and the reverse arcs leaving the
73// node (i.e. the opposite arcs of the ones returned by IncomingArcs(node)).
74// - OppositeIncomingArcs(node): This returns the reverse arcs leaving the node.
75//
76// Note on iteration efficiency: When re-indexing the arcs it is not possible to
77// have both the outgoing arcs and the incoming ones form a consecutive range.
78//
79// Iterators are invalidated by any operation that changes the graph (e.g.
80// `AddArc()`).
81//
82// It is however possible to do so for the outgoing arcs and the opposite
83// incoming arcs. It is why the OutgoingOrOppositeIncomingArcs() and
84// OutgoingArcs() iterations are more efficient than the IncomingArcs() one.
85// TODO(b/385094969): Once we no longer use `Next()/Ok()` for iterators, we can
86// get rid of `limit_`, which will make iteration much more efficient.
87//
88// If you know the graph size in advance, this already set the number of nodes,
89// reserve space for the arcs and check in DEBUG mode that you don't go over the
90// bounds:
91// Graph graph(num_nodes, arc_capacity);
92//
93// Storing and using node annotations:
94// vector<bool> is_visited(graph.num_nodes(), false);
95// ...
96// for (int node = 0; node < graph.num_nodes(); ++node) {
97// if (!is_visited[node]) ...
98// }
99//
100// Storing and using arc annotations:
101// vector<int> weights;
102// for (...) {
103// graph.AddArc(tail, head);
104// weights.push_back(arc_weight);
105// }
106// ...
107// for (const int arc : graph.OutgoingArcs(node)) {
108// ... weights[arc] ...;
109// }
110//
111// More efficient version:
112// typedef StaticGraph<> Graph;
113// Graph graph(num_nodes, arc_capacity); // Optional, but help memory usage.
114// vector<int> weights;
115// weights.reserve(arc_capacity); // Optional, but help memory usage.
116// for (...) {
117// graph.AddArc(tail, head);
118// weights.push_back(arc_weight);
119// }
120// ...
121// vector<Graph::ArcIndex> permutation;
122// graph.Build(&permutation); // A static graph must be Build() before usage.
123// Permute(permutation, &weights); // Build() may permute the arc index.
124// ...
125//
126// Encoding an undirected graph: If you don't need arc annotation, then the best
127// is to add two arcs for each edge (one in each direction) to a directed graph.
128// Otherwise you can do the following.
129//
130// typedef ReverseArc... Graph;
131// Graph graph;
132// for (...) {
133// graph.AddArc(tail, head); // or graph.AddArc(head, tail) but not both.
134// edge_annotations.push_back(value);
135// }
136// ...
137// for (const Graph::NodeIndex node : graph.AllNodes()) {
138// for (const Graph::ArcIndex arc :
139// graph.OutgoingOrOppositeIncomingArcs(node)) {
140// destination = graph.Head(arc);
141// annotation = edge_annotations[arc < 0 ? graph.OppositeArc(arc) : arc];
142// }
143// }
144//
145// Note: The graphs are primarily designed to be constructed first and then used
146// because it covers most of the use cases. It is possible to extend the
147// interface with more dynamicity (like removing arcs), but this is not done at
148// this point. Note that a "dynamic" implementation will break some assumptions
149// we make on what node or arc are valid and also on the indices returned by
150// AddArc(). Some arguments for simplifying the interface at the cost of
151// dynamicity are:
152//
153// - It is always possible to construct a static graph from a dynamic one
154// before calling a complex algo.
155// - If you really need a dynamic graph, maybe it is better to compute a graph
156// property incrementally rather than calling an algorithm that starts from
157// scratch each time.
158
159#ifndef UTIL_GRAPH_GRAPH_H_
160#define UTIL_GRAPH_GRAPH_H_
161
162#include <algorithm>
163#include <cstddef>
164#include <cstdint>
165#include <cstdio>
166#include <cstdlib>
167#include <cstring>
168#include <iterator>
169#include <limits>
170#include <type_traits>
171#include <vector>
172
173#include "absl/base/attributes.h"
174#include "absl/debugging/leak_check.h"
175#include "absl/log/check.h"
176#include "absl/types/span.h"
178#include "ortools/base/logging.h"
180
181namespace util {
182
183namespace internal {
184
185template <typename IndexT, typename T>
186class SVector;
187
188template <typename IndexT, typename T>
189class Vector;
190
191} // namespace internal
192
193// Base class of all Graphs implemented here. The default value for the graph
194// index types is int32_t since almost all graphs that fit into memory do not
195// need bigger indices.
196//
197// Note: The type can be unsigned, except for the graphs with reverse arcs
198// where the ArcIndexType must be signed, but not necessarily the NodeIndexType.
199//
200// `NodeIndexType` and `ArcIndexType` can be any integer type, but can also be
201// strong integer types (e.g. `StrongInt`). Strong integer types are types that
202// behave like integers (comparison, arithmetic, etc.), and are (explicitly)
203// constructible/convertible from/to integers.
204template <typename Impl, typename NodeIndexType = int32_t,
205 typename ArcIndexType = int32_t, bool HasNegativeReverseArcs = false>
206class BaseGraph //
207{
208 public:
209 // Typedef so you can use Graph::NodeIndex and Graph::ArcIndex to be generic
210 // but also to improve the readability of your code. We also recommend
211 // that you define a typedef ... Graph; for readability.
212 typedef NodeIndexType NodeIndex;
213 typedef ArcIndexType ArcIndex;
214 static constexpr bool kHasNegativeReverseArcs = HasNegativeReverseArcs;
215
217 : num_nodes_(0),
219 num_arcs_(0),
220 arc_capacity_(0),
221 const_capacities_(false) {}
222 BaseGraph(const BaseGraph&) = default;
223 BaseGraph& operator=(const BaseGraph&) = default;
224
225 virtual ~BaseGraph() = default;
226
227 // Returns the number of valid nodes in the graph. Prefer using num_nodes():
228 // the size() API is here to make Graph and vector<vector<int>> more alike.
229 NodeIndexType num_nodes() const { return num_nodes_; }
230 NodeIndexType size() const { return num_nodes_; } // Prefer num_nodes().
231
232 // Returns the number of valid arcs in the graph.
233 ArcIndexType num_arcs() const { return num_arcs_; }
234
235 // Allows nice range-based for loop:
236 // for (const NodeIndex node : graph.AllNodes()) { ... }
237 // for (const ArcIndex arc : graph.AllForwardArcs()) { ... }
240
241 // Returns true if the given node is a valid node of the graph.
242 bool IsNodeValid(NodeIndexType node) const {
243 return node >= NodeIndexType(0) && node < num_nodes_;
244 }
245
246 // Returns true if the given arc is a valid arc of the graph.
247 // Note that the arc validity range changes for graph with reverse arcs.
248 bool IsArcValid(ArcIndexType arc) const {
249 return (HasNegativeReverseArcs ? -num_arcs_ : ArcIndexType(0)) <= arc &&
250 arc < num_arcs_;
251 }
252
253 // Capacity reserved for future nodes, always >= num_nodes_.
254 NodeIndexType node_capacity() const;
255
256 // Capacity reserved for future arcs, always >= num_arcs_.
257 ArcIndexType arc_capacity() const;
258
259 // Changes the graph capacities. The functions will fail in debug mode if:
260 // - const_capacities_ is true.
261 // - A valid node does not fall into the new node range.
262 // - A valid arc does not fall into the new arc range.
263 // In non-debug mode, const_capacities_ is ignored and nothing will happen
264 // if the new capacity value for the arcs or the nodes is too small.
265 virtual void ReserveNodes(NodeIndexType bound) {
266 DCHECK(!const_capacities_);
267 DCHECK_GE(bound, num_nodes_);
268 if (bound <= num_nodes_) return;
269 node_capacity_ = bound;
270 }
271 virtual void ReserveArcs(ArcIndexType bound) {
272 DCHECK(!const_capacities_);
273 DCHECK_GE(bound, num_arcs_);
274 if (bound <= num_arcs_) return;
275 arc_capacity_ = bound;
276 }
277 void Reserve(NodeIndexType node_capacity, ArcIndexType arc_capacity) {
280 }
281
282 // FreezeCapacities() makes any future attempt to change the graph capacities
283 // crash in DEBUG mode.
285
286 // Constants that will never be a valid node or arc.
287 // They are the maximum possible node and arc capacity.
288 static_assert(std::numeric_limits<NodeIndexType>::is_specialized);
289 static constexpr NodeIndexType kNilNode =
290 std::numeric_limits<NodeIndexType>::max();
291 static_assert(std::numeric_limits<ArcIndexType>::is_specialized);
292 static constexpr ArcIndexType kNilArc =
293 std::numeric_limits<ArcIndexType>::max();
294
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
310 protected:
311 // Functions commented when defined because they are implementation details.
316 std::vector<ArcIndexType>* permutation);
317
318 NodeIndexType num_nodes_;
319 NodeIndexType node_capacity_;
320 ArcIndexType num_arcs_;
321 ArcIndexType arc_capacity_;
323};
324
325// An iterator that wraps an arc iterator and retrieves a property of the arc.
326// The property to retrieve is specified by a `Graph` member function taking an
327// `ArcIndex` parameter. For example, `ArcHeadIterator` retrieves the head of an
328// arc with `&Graph::Head`.
329template <typename Graph, typename ArcIterator, typename PropertyT,
330 PropertyT (Graph::*property)(typename Graph::ArcIndex) const>
332#if __cplusplus < 201703L
333 : public std::iterator<std::input_iterator_tag, PropertyT>
334#endif
335{
336 public:
337 using value_type = PropertyT;
338 // TODO(b/385094969): This should be `NodeIndex` for integers,
339 // `NodeIndex::value_type` for strong signed integer types.
340 using difference_type = std::ptrdiff_t;
341#if __cplusplus >= 201703L && __cplusplus < 202002L
342 using iterator_category = std::input_iterator_tag;
343 using pointer = PropertyT*;
344 using reference = PropertyT&;
345#endif
346
348
349 ArcPropertyIterator(const Graph& graph, ArcIterator arc_it)
350 : arc_it_(std::move(arc_it)), graph_(&graph) {}
351
352 value_type operator*() const { return (graph_->*property)(*arc_it_); }
353
355 ++arc_it_;
356 return *this;
357 }
359 auto tmp = *this;
360 ++arc_it_;
361 return tmp;
362 }
363
364 friend bool operator==(const ArcPropertyIterator& l,
365 const ArcPropertyIterator& r) {
366 return l.arc_it_ == r.arc_it_;
367 }
368
369 friend bool operator!=(const ArcPropertyIterator& l,
370 const ArcPropertyIterator& r) {
371 return !(l == r);
372 }
373
374 private:
375 ArcIterator arc_it_;
376 const Graph* graph_;
377};
378
379// An iterator that iterates on the heads of the arcs of another iterator.
380template <typename Graph, typename ArcIterator>
382 ArcPropertyIterator<Graph, ArcIterator, typename Graph::NodeIndex,
383 &Graph::Head>;
384
385// An iterator that iterates on the opposite arcs of another iterator.
386template <typename Graph, typename ArcIterator>
388 ArcPropertyIterator<Graph, ArcIterator, typename Graph::ArcIndex,
389 &Graph::OppositeArc>;
390
391namespace internal {
392
393// Returns true if `ArcIndexType` is signed. Work for integers and strong
394// integer types.
395template <typename ArcIndexType>
396constexpr bool IsSigned() {
397 return ArcIndexType(-1) < ArcIndexType(0);
398}
399
400// Allows indexing into a vector with an edge or node index.
401template <typename IndexT, typename T>
402class Vector : public std::vector<T> {
403 public:
404 const T& operator[](IndexT index) const {
405 return std::vector<T>::operator[](static_cast<size_t>(index));
406 }
407 T& operator[](IndexT index) {
408 return std::vector<T>::operator[](static_cast<size_t>(index));
409 }
410
411 void resize(IndexT index, const T& value) {
412 return std::vector<T>::resize(static_cast<size_t>(index), value);
413 }
414
415 void reserve(IndexT index) {
416 return std::vector<T>::reserve(static_cast<size_t>(index));
417 }
418
419 void assign(IndexT index, const T& value) {
420 return std::vector<T>::assign(static_cast<size_t>(index), value);
421 }
422
423 IndexT size() const { return IndexT(std::vector<T>::size()); }
424};
425
426// A vector-like class where valid indices are in [- size_, size_) and reserved
427// indices for future growth are in [- capacity_, capacity_). It is used to hold
428// arc related information for graphs with reverse arcs.
429// It supports only up to 2^31-1 elements, for compactness. If you ever need
430// more, consider using templates for the size/capacity integer types.
431//
432// Sample usage:
433//
434// SVector<int> v;
435// v.grow(left_value, right_value);
436// v.resize(10);
437// v.clear();
438// v.swap(new_v);
439// std:swap(v[i], v[~i]);
440template <typename IndexT, typename T>
441class SVector {
442 public:
443 using value_type = T;
444
445 SVector() : base_(nullptr), size_(0), capacity_(0) {}
446
448
449 // Copy constructor and assignment operator.
450 SVector(const SVector& other) : SVector() { *this = other; }
451 SVector& operator=(const SVector& other) {
452 if (capacity_ < other.size_) {
454 // NOTE(user): Alternatively, our capacity could inherit from the other
455 // vector's capacity, which can be (much) greater than its size.
456 capacity_ = other.size_;
457 base_ = Allocate(capacity_);
458 CHECK(base_ != nullptr);
459 base_ += static_cast<ptrdiff_t>(capacity_);
460 } else { // capacity_ >= other.size
461 clear();
462 }
463 // Perform the actual copy of the payload.
464 size_ = other.size_;
465 CopyInternal(other, std::is_integral<T>());
466 return *this;
467 }
468
469 // Move constructor and move assignment operator.
470 SVector(SVector&& other) noexcept : SVector() { swap(other); }
471 SVector& operator=(SVector&& other) noexcept {
472 // NOTE(user): We could just swap() and let the other's destruction take
473 // care of the clean-up, but it is probably less bug-prone to perform the
474 // destruction immediately.
476 swap(other);
477 return *this;
478 }
479
480 T& operator[](IndexT n) {
481 DCHECK_LT(n, size_);
482 DCHECK_GE(n, -size_);
483 return base_[static_cast<ptrdiff_t>(n)];
484 }
485
486 const T& operator[](IndexT n) const {
487 DCHECK_LT(n, size_);
488 DCHECK_GE(n, -size_);
489 return base_[static_cast<ptrdiff_t>(n)];
490 }
491
492 void resize(IndexT n) {
493 reserve(n);
494 for (IndexT i = -n; i < -size_; ++i) {
495 new (base_ + static_cast<ptrdiff_t>(i)) T();
496 }
497 for (IndexT i = size_; i < n; ++i) {
498 new (base_ + static_cast<ptrdiff_t>(i)) T();
499 }
500 for (IndexT i = -size_; i < -n; ++i) {
501 base_[static_cast<ptrdiff_t>(i)].~T();
502 }
503 for (IndexT i = n; i < size_; ++i) {
504 base_[static_cast<ptrdiff_t>(i)].~T();
505 }
506 size_ = n;
507 }
508
509 void clear() { resize(IndexT(0)); }
510
511 T* data() const { return base_; }
512
513 const T* begin() const { return base_; }
514 const T* end() const { return base_ + static_cast<ptrdiff_t>(size_); }
515
516 void swap(SVector<IndexT, T>& x) noexcept {
517 std::swap(base_, x.base_);
518 std::swap(size_, x.size_);
519 std::swap(capacity_, x.capacity_);
520 }
521
522 void reserve(IndexT n) {
523 DCHECK_GE(n, IndexT(0));
524 DCHECK_LE(n, max_size());
525 if (n > capacity_) {
526 const IndexT new_capacity = std::min(n, max_size());
527 T* new_storage = Allocate(new_capacity);
528 CHECK(new_storage != nullptr);
529 T* new_base = new_storage + static_cast<ptrdiff_t>(new_capacity);
530 // TODO(user): in C++17 we could use std::uninitialized_move instead
531 // of this loop.
532 for (ptrdiff_t i = static_cast<ptrdiff_t>(-size_);
533 i < static_cast<ptrdiff_t>(size_); ++i) {
534 new (new_base + i) T(std::move(base_[i]));
535 }
536 IndexT saved_size = size_;
538 size_ = saved_size;
539 base_ = new_base;
540 capacity_ = new_capacity;
541 }
542 }
543
544 // NOTE(user): This doesn't currently support movable-only objects, but we
545 // could fix that.
546 void grow(const T& left = T(), const T& right = T()) {
547 if (size_ == capacity_) {
548 // We have to copy the elements because they are allowed to be element of
549 // *this.
550 T left_copy(left); // NOLINT
551 T right_copy(right); // NOLINT
552 reserve(NewCapacity(IndexT(1)));
553 new (base_ + static_cast<ptrdiff_t>(size_)) T(right_copy);
554 new (base_ - static_cast<ptrdiff_t>(size_) - 1) T(left_copy);
555 ++size_;
556 } else {
557 new (base_ + static_cast<ptrdiff_t>(size_)) T(right);
558 new (base_ - static_cast<ptrdiff_t>(size_) - 1) T(left);
559 ++size_;
560 }
561 }
562
563 IndexT size() const { return size_; }
564
565 IndexT capacity() const { return capacity_; }
566
567 IndexT max_size() const { return std::numeric_limits<IndexT>::max(); }
568
570 if (base_ == nullptr) return;
571 clear();
572 if (capacity_ > IndexT(0)) {
573 free(base_ - static_cast<ptrdiff_t>(capacity_));
574 }
575 capacity_ = IndexT(0);
576 base_ = nullptr;
577 }
578
579 private:
580 // Copies other.base_ to base_ in this SVector. Avoids iteration by copying
581 // entire memory range in a single shot for the most commonly used integral
582 // types which should be safe to copy in this way.
583 void CopyInternal(const SVector& other, std::true_type) {
584 std::memcpy(base_ - static_cast<ptrdiff_t>(other.size_),
585 other.base_ - static_cast<ptrdiff_t>(other.size_),
586 2LL * static_cast<ptrdiff_t>(other.size_) * sizeof(T));
587 }
588
589 // Copies other.base_ to base_ in this SVector. Safe for all types as it uses
590 // constructor for each entry.
591 void CopyInternal(const SVector& other, std::false_type) {
592 for (IndexT i = -size_; i < size_; ++i) {
593 new (base_ + static_cast<ptrdiff_t>(i))
594 T(other.base_[static_cast<ptrdiff_t>(i)]);
595 }
596 }
597
598 T* Allocate(IndexT capacity) const {
599 return absl::IgnoreLeak(static_cast<T*>(
600 malloc(2LL * static_cast<ptrdiff_t>(capacity) * sizeof(T))));
601 }
602
603 IndexT NewCapacity(IndexT delta) {
604 // TODO(user): check validity.
605 double candidate = 1.3 * static_cast<size_t>(capacity_);
606 if (candidate > static_cast<size_t>(max_size())) {
607 candidate = static_cast<size_t>(max_size());
608 }
609 IndexT new_capacity(candidate);
610 if (new_capacity > capacity_ + delta) {
611 return new_capacity;
612 }
613 return capacity_ + delta;
614 }
615
616 T* base_; // Pointer to the element of index 0.
617 IndexT size_; // Valid index are [- size_, size_).
618 IndexT capacity_; // Reserved index are [- capacity_, capacity_).
619};
620
621} // namespace internal
622
623// Graph traits, to allow algorithms to manipulate graphs as adjacency lists.
624// This works with any graph type, and any object that has:
625// - a size() method returning the number of nodes.
626// - an operator[] method taking a node index and returning a range of neighbour
627// node indices.
628// One common example is using `std::vector<std::vector<int>>` to represent
629// adjacency lists.
630template <typename Graph>
632 private:
633 // The type of the range returned by `operator[]`.
634 using NeighborRangeType = std::decay_t<
635 decltype(std::declval<Graph>()[std::declval<Graph>().size()])>;
636
637 public:
638 // The index type for nodes of the graph.
639 using NodeIndex =
640 std::decay_t<decltype(*(std::declval<NeighborRangeType>().begin()))>;
641};
642
643// Basic graph implementation without reverse arc. This class also serves as a
644// documentation for the generic graph interface (minus the part related to
645// reverse arcs).
646//
647// This implementation uses a linked list and compared to StaticGraph:
648// - Is a bit faster to construct (if the arcs are not ordered by tail).
649// - Does not require calling Build().
650// - Has slower outgoing arc iteration.
651// - Uses more memory: ArcIndexType * node_capacity()
652// + (ArcIndexType + NodeIndexType) * arc_capacity().
653// - Has an efficient Tail() but need an extra NodeIndexType/arc memory for it.
654// - Never changes the initial arc index returned by AddArc().
655//
656// OutgoingArcs(), OutgoingArcsStartingFrom(), and the [] operator are all
657// deterministic. Specifically, for two graphs constructed from the same
658// sequence of node and arc creation calls, these iterators will return the
659// result in the same order).
660//
661template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
662class ListGraph : public BaseGraph<ListGraph<NodeIndexType, ArcIndexType>,
663 NodeIndexType, ArcIndexType, false> {
665 ArcIndexType, false>
666 Base;
670 using Base::num_arcs_;
671 using Base::num_nodes_;
672
673 public:
674 using Base::IsArcValid;
675 ListGraph() = default;
676
677 // Reserve space for the graph at construction and do not allow it to grow
678 // beyond that, see FreezeCapacities(). This constructor also makes any nodes
679 // in [0, num_nodes) valid.
680 ListGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity) {
681 this->Reserve(num_nodes, arc_capacity);
682 this->FreezeCapacities();
683 if (num_nodes > NodeIndexType(0)) {
684 this->AddNode(num_nodes - NodeIndexType(1));
685 }
686 }
687
688 // If node is not a valid node, sets num_nodes_ to node + 1 so that the given
689 // node becomes valid. It will fail in DEBUG mode if the capacities are fixed
690 // and the new node is out of range.
691 void AddNode(NodeIndexType node);
692
693 // Adds an arc to the graph and returns its current index which will always
694 // be num_arcs() - 1. It will also automatically call AddNode(tail)
695 // and AddNode(head). It will fail in DEBUG mode if the capacities
696 // are fixed and this cause the graph to grow beyond them.
697 //
698 // Note: Self referencing arcs and duplicate arcs are supported.
699 ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
700
701 // Returns the tail/head of a valid arc.
702 NodeIndexType Tail(ArcIndexType arc) const;
703 NodeIndexType Head(ArcIndexType arc) const;
704
705 // Do not use directly.
710
711 // Graph jargon: the "degree" of a node is its number of arcs. The out-degree
712 // is the number of outgoing arcs. The in-degree is the number of incoming
713 // arcs, and is only available for some graph implementations, below.
714 //
715 // ListGraph<>::OutDegree() works in O(degree).
716 ArcIndexType OutDegree(NodeIndexType node) const;
717
718 // Allows to iterate over the forward arcs that verify Tail(arc) == node.
719 // This is meant to be used as:
720 // for (const ArcIndex arc : graph.OutgoingArcs(node)) { ... }
722 DCHECK(Base::IsNodeValid(node));
723 return {OutgoingArcIterator(start_[node], next_.data()),
725 }
726
727 // Advanced usage. Same as OutgoingArcs(), but allows to restart the iteration
728 // from an already known outgoing arc of the given node. If `from` is
729 // `kNilArc`, an empty range is returned.
731 NodeIndexType node, ArcIndexType from) const {
732 DCHECK(Base::IsNodeValid(node));
733 if (from == Base::kNilArc) return {};
734 DCHECK_EQ(Tail(from), node);
735 return {OutgoingArcIterator(from, next_.data()), OutgoingArcIterator()};
736 }
737
738 // This loops over the heads of the OutgoingArcs(node). It is just a more
739 // convenient way to achieve this. Moreover this interface is used by some
740 // graph algorithms.
742 return {OutgoingHeadIterator(*this, OutgoingArcs(node).begin()),
744 }
745
746 void ReserveNodes(NodeIndexType bound) override;
747 void ReserveArcs(ArcIndexType bound) override;
748
749 private:
754};
755
756// Most efficient implementation of a graph without reverse arcs:
757// - Build() needs to be called after the arc and node have been added.
758// - The graph is really compact memory wise:
759// ArcIndexType * node_capacity() + 2 * NodeIndexType * arc_capacity(),
760// but when Build() is called it uses a temporary extra space of
761// ArcIndexType * arc_capacity().
762// - The construction is really fast.
763//
764// NOTE(user): if the need arises for very-well compressed graphs, we could
765// shave NodeIndexType * arc_capacity() off the permanent memory requirement
766// with a similar class that doesn't support Tail(), i.e.
767// StaticGraphWithoutTail<>. This almost corresponds to a past implementation
768// of StaticGraph<> @CL 116144340.
769template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
770class StaticGraph : public BaseGraph<StaticGraph<NodeIndexType, ArcIndexType>,
771 NodeIndexType, ArcIndexType, false> {
773 ArcIndexType, false>
774 Base;
778 using Base::num_arcs_;
779 using Base::num_nodes_;
780
781 public:
782 using Base::IsArcValid;
783 StaticGraph() : is_built_(false), arc_in_order_(true), last_tail_seen_(0) {}
784 StaticGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
785 : is_built_(false), arc_in_order_(true), last_tail_seen_(0) {
786 this->Reserve(num_nodes, arc_capacity);
787 this->FreezeCapacities();
788 if (num_nodes > NodeIndexType(0)) {
789 this->AddNode(num_nodes - NodeIndexType(1));
790 }
791 }
792
793 // Shortcut to directly create a finalized graph, i.e. Build() is called.
794 template <class ArcContainer> // e.g. vector<pair<int, int>>.
795 static StaticGraph FromArcs(NodeIndexType num_nodes,
796 const ArcContainer& arcs);
797
798 // Do not use directly. See instead the arc iteration functions below.
799 class OutgoingArcIterator;
800
801 NodeIndexType Head(ArcIndexType arc) const;
802 NodeIndexType Tail(ArcIndexType arc) const;
803 ArcIndexType OutDegree(NodeIndexType node) const; // Work in O(1).
804 IntegerRange<ArcIndexType> OutgoingArcs(NodeIndexType node) const {
805 return IntegerRange<ArcIndexType>(start_[node], DirectArcLimit(node));
806 }
808 ArcIndexType from) const {
809 DCHECK_GE(from, start_[node]);
810 const ArcIndexType limit = DirectArcLimit(node);
811 return IntegerRange<ArcIndexType>(from == Base::kNilArc ? limit : from,
812 limit);
813 }
814
815 // This loops over the heads of the OutgoingArcs(node). It is just a more
816 // convenient way to achieve this. Moreover this interface is used by some
817 // graph algorithms.
818 absl::Span<const NodeIndexType> operator[](NodeIndexType node) const;
819
820 void ReserveNodes(NodeIndexType bound) override;
821 void ReserveArcs(ArcIndexType bound) override;
822 void AddNode(NodeIndexType node);
823 ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
824
825 void Build(std::vector<ArcIndexType>* permutation) final;
826 void Build() { Build(nullptr); }
827 bool IsBuilt() const final { return is_built_; }
828
829 private:
830 ArcIndexType DirectArcLimit(NodeIndexType node) const {
831 DCHECK(is_built_);
832 DCHECK(Base::IsNodeValid(node));
833 return start_[node + NodeIndexType(1)];
834 }
835
836 bool is_built_;
837 bool arc_in_order_;
838 NodeIndexType last_tail_seen_;
839 // First outgoing arc for each node. If `num_nodes_ > 0`, the "past-the-end"
840 // value is a sentinel (`start_[num_nodes_] == num_arcs_`).
841 internal::Vector<NodeIndexType, ArcIndexType> start_;
842 internal::Vector<ArcIndexType, NodeIndexType> head_;
843 internal::Vector<ArcIndexType, NodeIndexType> tail_;
844};
845
846// Extends the ListGraph by also storing the reverse arcs.
847// This class also documents the Graph interface related to reverse arc.
848// - NodeIndexType can be unsigned, but ArcIndexType must be signed.
849// - It has most of the same advantanges and disadvantages as ListGraph.
850// - It takes 2 * ArcIndexType * node_capacity()
851// + 2 * (ArcIndexType + NodeIndexType) * arc_capacity() memory.
852template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
854 : public BaseGraph<ReverseArcListGraph<NodeIndexType, ArcIndexType>,
855 NodeIndexType, ArcIndexType, true> {
856 static_assert(internal::IsSigned<ArcIndexType>(),
857 "ArcIndexType must be signed");
858
860 NodeIndexType, ArcIndexType, true>
861 Base;
865 using Base::num_arcs_;
866 using Base::num_nodes_;
867
868 public:
869 using Base::IsArcValid;
871 ReverseArcListGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity) {
872 this->Reserve(num_nodes, arc_capacity);
873 this->FreezeCapacities();
874 if (num_nodes > NodeIndexType(0)) {
875 this->AddNode(num_nodes - NodeIndexType(1));
876 }
877 }
878
879 NodeIndexType Head(ArcIndexType arc) const;
880 NodeIndexType Tail(ArcIndexType arc) const;
881
882 // Returns the opposite arc of a given arc. That is the reverse arc of the
883 // given forward arc or the forward arc of a given reverse arc.
884 ArcIndexType OppositeArc(ArcIndexType arc) const;
885
886 // Do not use directly. See instead the arc iteration functions below.
892 ChasingIterator<ArcIndexType, Base::kNilArc,
899
900 // ReverseArcListGraph<>::OutDegree() and ::InDegree() work in O(degree).
901 ArcIndexType OutDegree(NodeIndexType node) const;
902 ArcIndexType InDegree(NodeIndexType node) const;
903
904 // Arc iterations functions over the arcs touching a node (see the top-level
905 // comment for the different types). To be used as follows:
906 // for (const Graph::ArcIndex arc : IterationFunction(node)) { ... }
907 //
908 // The StartingFrom() version are similar, but restart the iteration from a
909 // given arc position (which must be valid in the iteration context), or
910 // `kNilArc`, in which case an empty range is returned.
912 DCHECK(Base::IsNodeValid(node));
913 return {OutgoingArcIterator(start_[node], next_.data()),
915 }
917 NodeIndexType node, ArcIndexType from) const {
918 DCHECK(Base::IsNodeValid(node));
919 if (from == Base::kNilArc) return {};
920 DCHECK_GE(from, ArcIndexType(0));
921 DCHECK_EQ(Tail(from), node);
922 return {OutgoingArcIterator(from, next_.data()), OutgoingArcIterator()};
923 }
924
926 return {IncomingArcIterator(*this, OppositeIncomingArcs(node).begin()),
928 }
930 NodeIndexType node, ArcIndexType from) const {
931 DCHECK(Base::IsNodeValid(node));
932 if (from == Base::kNilArc) return {};
933 return {
935 *this,
936 OppositeIncomingArcsStartingFrom(node, OppositeArc(from)).begin()),
938 }
939
941 OutgoingOrOppositeIncomingArcs(NodeIndexType node) const;
943 NodeIndexType node) const {
944 DCHECK(Base::IsNodeValid(node));
945 return {OppositeIncomingArcIterator(reverse_start_[node], next_.data()),
947 }
949 NodeIndexType node, ArcIndexType from) const {
950 DCHECK(Base::IsNodeValid(node));
951 if (from == Base::kNilArc) return {};
952 DCHECK_LT(from, ArcIndexType(0));
953 DCHECK_EQ(Tail(from), node);
954 return {OppositeIncomingArcIterator(from, next_.data()),
956 }
957
960 ArcIndexType from) const;
961
962 // This loops over the heads of the OutgoingArcs(node). It is just a more
963 // convenient way to achieve this. Moreover this interface is used by some
964 // graph algorithms.
966
967 void ReserveNodes(NodeIndexType bound) override;
968 void ReserveArcs(ArcIndexType bound) override;
969 void AddNode(NodeIndexType node);
970 ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
971
972 private:
977};
978
979// StaticGraph with reverse arc.
980// - NodeIndexType can be unsigned, but ArcIndexType must be signed.
981// - It has most of the same advantanges and disadvantages as StaticGraph.
982// - It takes 2 * ArcIndexType * node_capacity()
983// + 2 * (ArcIndexType + NodeIndexType) * arc_capacity() memory.
984// - If the ArcIndexPermutation is needed, then an extra ArcIndexType *
985// arc_capacity() is needed for it.
986// - The reverse arcs from a node are sorted by head (so we could add a log()
987// time lookup function).
988template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
990 : public BaseGraph<ReverseArcStaticGraph<NodeIndexType, ArcIndexType>,
991 NodeIndexType, ArcIndexType, true> {
992 static_assert(internal::IsSigned<ArcIndexType>(),
993 "ArcIndexType must be signed");
994
996 NodeIndexType, ArcIndexType, true>
997 Base;
1001 using Base::num_arcs_;
1002 using Base::num_nodes_;
1003
1004 public:
1005 using Base::IsArcValid;
1006 ReverseArcStaticGraph() : is_built_(false) {}
1007 ReverseArcStaticGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
1008 : is_built_(false) {
1009 this->Reserve(num_nodes, arc_capacity);
1010 this->FreezeCapacities();
1011 if (num_nodes > NodeIndexType(0)) {
1012 this->AddNode(num_nodes - NodeIndexType(1));
1013 }
1014 }
1015
1016 ArcIndexType OppositeArc(ArcIndexType arc) const;
1017 // TODO(user): support Head() and Tail() before Build(), like StaticGraph<>.
1018 NodeIndexType Head(ArcIndexType arc) const;
1019 NodeIndexType Tail(ArcIndexType arc) const;
1020
1021 // ReverseArcStaticGraph<>::OutDegree() and ::InDegree() work in O(1).
1022 ArcIndexType OutDegree(NodeIndexType node) const;
1023 ArcIndexType InDegree(NodeIndexType node) const;
1024
1025 // Deprecated.
1026 class OutgoingOrOppositeIncomingArcIterator;
1032
1033 IntegerRange<ArcIndexType> OutgoingArcs(NodeIndexType node) const {
1034 return IntegerRange<ArcIndexType>(start_[node], DirectArcLimit(node));
1035 }
1037 ArcIndexType from) const {
1038 DCHECK_GE(from, start_[node]);
1039 const ArcIndexType limit = DirectArcLimit(node);
1040 return IntegerRange<ArcIndexType>(from == Base::kNilArc ? limit : from,
1041 limit);
1042 }
1043
1045 return IntegerRange<ArcIndexType>(reverse_start_[node],
1046 ReverseArcLimit(node));
1047 }
1049 NodeIndexType node, ArcIndexType from) const {
1050 DCHECK_GE(from, reverse_start_[node]);
1051 const ArcIndexType limit = ReverseArcLimit(node);
1052 return IntegerRange<ArcIndexType>(from == Base::kNilArc ? limit : from,
1053 limit);
1054 }
1055
1057 const auto opposite_incoming_arcs = OppositeIncomingArcs(node);
1058 return {IncomingArcIterator(*this, opposite_incoming_arcs.begin()),
1059 IncomingArcIterator(*this, opposite_incoming_arcs.end())};
1060 }
1061
1063 NodeIndexType node, ArcIndexType from) const {
1064 DCHECK(Base::IsNodeValid(node));
1065 const auto opposite_incoming_arcs = OppositeIncomingArcsStartingFrom(
1066 node, from == Base::kNilArc ? Base::kNilArc : OppositeArc(from));
1067 return {IncomingArcIterator(*this, opposite_incoming_arcs.begin()),
1068 IncomingArcIterator(*this, opposite_incoming_arcs.end())};
1069 }
1070
1072 OutgoingOrOppositeIncomingArcs(NodeIndexType node) const;
1073
1076 ArcIndexType from) const;
1077
1078 // This loops over the heads of the OutgoingArcs(node). It is just a more
1079 // convenient way to achieve this. Moreover this interface is used by some
1080 // graph algorithms.
1081 absl::Span<const NodeIndexType> operator[](NodeIndexType node) const;
1082
1083 void ReserveArcs(ArcIndexType bound) override;
1084 void AddNode(NodeIndexType node);
1085 ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
1086
1087 void Build(std::vector<ArcIndexType>* permutation) final;
1088 void Build() { Build(nullptr); }
1089 bool IsBuilt() const final { return is_built_; }
1090
1091 private:
1092 ArcIndexType DirectArcLimit(NodeIndexType node) const {
1093 DCHECK(is_built_);
1094 DCHECK(Base::IsNodeValid(node));
1095 return start_[node + NodeIndexType(1)];
1096 }
1097 ArcIndexType ReverseArcLimit(NodeIndexType node) const {
1098 DCHECK(is_built_);
1099 DCHECK(Base::IsNodeValid(node));
1100 return reverse_start_[node + NodeIndexType(1)];
1101 }
1102
1103 bool is_built_;
1104 // First outgoing arc for each node. If `num_nodes_ > 0`, the "past-the-end"
1105 // value is a sentinel (`start_[num_nodes_] == num_arcs_`).
1106 internal::Vector<NodeIndexType, ArcIndexType> start_;
1107 // First reverse outgoing arc for each node. If `num_nodes_ > 0`,
1108 // the "past-the-end" value is a sentinel (`reverse_start_[num_nodes_] == 0`).
1109 internal::Vector<NodeIndexType, ArcIndexType> reverse_start_;
1110 internal::SVector<ArcIndexType, NodeIndexType> head_;
1111 internal::SVector<ArcIndexType, ArcIndexType> opposite_;
1112};
1113
1114// Permutes the elements of array_to_permute: element #i will be moved to
1115// position permutation[i]. permutation must be either empty (in which case
1116// nothing happens), or a permutation of [0, permutation.size()).
1117//
1118// The algorithm is fast but need extra memory for a copy of the permuted part
1119// of array_to_permute.
1120//
1121// TODO(user): consider slower but more memory efficient implementations that
1122// follow the cycles of the permutation and use a bitmap to indicate what has
1123// been permuted or to mark the beginning of each cycle.
1124template <class IntVector, class Array>
1125void Permute(const IntVector& permutation, Array* array_to_permute) {
1126 if (permutation.empty()) {
1127 return;
1128 }
1129 const auto size = permutation.size();
1130 auto& array = *array_to_permute;
1131 using ElementType =
1132 typename std::iterator_traits<decltype(std::begin(array))>::value_type;
1133 std::vector<ElementType> temp(size);
1134 auto array_begin = std::begin(array);
1135 std::copy_n(array_begin, size, temp.begin());
1136 for (size_t i = 0; i < permutation.size(); ++i) {
1137 *(array_begin + static_cast<size_t>(permutation[i])) = temp[i];
1138 }
1139}
1140
1141// BaseGraph implementation ----------------------------------------------------
1142
1143template <typename Impl, typename NodeIndexType, typename ArcIndexType,
1144 bool HasNegativeReverseArcs>
1145IntegerRange<NodeIndexType>
1150
1151template <typename Impl, typename NodeIndexType, typename ArcIndexType,
1152 bool HasNegativeReverseArcs>
1153IntegerRange<ArcIndexType> BaseGraph<Impl, NodeIndexType, ArcIndexType,
1154 HasNegativeReverseArcs>::AllForwardArcs()
1155 const {
1156 return IntegerRange<ArcIndexType>(ArcIndexType(0), num_arcs_);
1157}
1158
1159template <typename Impl, typename NodeIndexType, typename ArcIndexType,
1160 bool HasNegativeReverseArcs>
1161NodeIndexType BaseGraph<Impl, NodeIndexType, ArcIndexType,
1162 HasNegativeReverseArcs>::node_capacity() const {
1163 // TODO(user): Is it needed? remove completely? return the real capacities
1164 // at the cost of having a different implementation for each graphs?
1166}
1167
1168template <typename Impl, typename NodeIndexType, typename ArcIndexType,
1169 bool HasNegativeReverseArcs>
1170ArcIndexType BaseGraph<Impl, NodeIndexType, ArcIndexType,
1171 HasNegativeReverseArcs>::arc_capacity() const {
1172 // TODO(user): Same questions as the ones in node_capacity().
1174}
1175
1176template <typename Impl, typename NodeIndexType, typename ArcIndexType,
1177 bool HasNegativeReverseArcs>
1178void BaseGraph<Impl, NodeIndexType, ArcIndexType,
1179 HasNegativeReverseArcs>::FreezeCapacities() {
1180 // TODO(user): Only define this in debug mode at the cost of having a lot
1181 // of ifndef NDEBUG all over the place? remove the function completely ?
1182 const_capacities_ = true;
1185}
1186
1187// Computes the cumulative sum of the entry in v. We only use it with
1188// in/out degree distribution, hence the Check() at the end.
1189template <typename Impl, typename NodeIndexType, typename ArcIndexType,
1190 bool HasNegativeReverseArcs>
1193 DCHECK_EQ(v->size(), num_nodes_ + NodeIndexType(1));
1194 ArcIndexType sum(0);
1195 for (NodeIndexType i(0); i < num_nodes_; ++i) {
1196 ArcIndexType temp = (*v)[i];
1197 (*v)[i] = sum;
1198 sum += temp;
1199 }
1200 DCHECK_EQ(sum, num_arcs_);
1201 (*v)[num_nodes_] = sum; // Sentinel.
1202}
1203
1204// Given the tail of arc #i in (*head)[i] and the head of arc #i in (*head)[~i]
1205// - Reorder the arc by increasing tail.
1206// - Put the head of the new arc #i in (*head)[i].
1207// - Put in start[i] the index of the first arc with tail >= i.
1208// - Update "permutation" to reflect the change, unless it is NULL.
1209template <typename Impl, typename NodeIndexType, typename ArcIndexType,
1210 bool HasNegativeReverseArcs>
1215 std::vector<ArcIndexType>* permutation) {
1216 // Computes the outgoing degree of each nodes and check if we need to permute
1217 // something or not. Note that the tails are currently stored in the positive
1218 // range of the SVector head.
1219 start->assign(num_nodes_ + NodeIndexType(1), ArcIndexType(0));
1220 NodeIndexType last_tail_seen(0);
1221 bool permutation_needed = false;
1222 for (ArcIndexType i(0); i < num_arcs_; ++i) {
1223 NodeIndexType tail = (*head)[i];
1224 if (!permutation_needed) {
1225 permutation_needed = tail < last_tail_seen;
1226 last_tail_seen = tail;
1227 }
1228 (*start)[tail]++;
1229 }
1230 ComputeCumulativeSum(start);
1231
1232 // Abort early if we do not need the permutation: we only need to put the
1233 // heads in the positive range.
1234 if (!permutation_needed) {
1235 for (ArcIndexType i(0); i < num_arcs_; ++i) {
1236 (*head)[i] = (*head)[~i];
1237 }
1238 if (permutation != nullptr) {
1239 permutation->clear();
1240 }
1241 return;
1242 }
1243
1244 // Computes the forward arc permutation.
1245 // Note that this temporarily alters the start vector.
1246 std::vector<ArcIndexType> perm(static_cast<size_t>(num_arcs_));
1247 for (ArcIndexType i(0); i < num_arcs_; ++i) {
1248 perm[static_cast<size_t>(i)] = (*start)[(*head)[i]]++;
1249 }
1250
1251 // Restore in (*start)[i] the index of the first arc with tail >= i.
1252 DCHECK_GE(num_nodes_, NodeIndexType(1));
1253 for (NodeIndexType i = num_nodes_ - NodeIndexType(1); i > NodeIndexType(0);
1254 --i) {
1255 (*start)[i] = (*start)[i - NodeIndexType(1)];
1256 }
1257 (*start)[NodeIndexType(0)] = ArcIndexType(0);
1258
1259 // Permutes the head into their final position in head.
1260 // We do not need the tails anymore at this point.
1261 for (ArcIndexType i(0); i < num_arcs_; ++i) {
1262 (*head)[perm[static_cast<size_t>(i)]] = (*head)[~i];
1263 }
1264 if (permutation != nullptr) {
1265 permutation->swap(perm);
1266 }
1267}
1268
1269// ---------------------------------------------------------------------------
1270// Macros to wrap old style iteration into the new range-based for loop style.
1271// ---------------------------------------------------------------------------
1272
1273// The parameters are:
1274// - c: the class name.
1275// - t: the iteration type (Outgoing, Incoming, OutgoingOrOppositeIncoming
1276// or OppositeIncoming).
1277// - e: the "end" ArcIndexType.
1278#define DEFINE_RANGE_BASED_ARC_ITERATION(c, t) \
1279 template <typename NodeIndexType, typename ArcIndexType> \
1280 BeginEndWrapper<typename c<NodeIndexType, ArcIndexType>::t##ArcIterator> \
1281 c<NodeIndexType, ArcIndexType>::t##Arcs(NodeIndexType node) const { \
1282 return BeginEndWrapper<t##ArcIterator>( \
1283 t##ArcIterator(*this, node), \
1284 t##ArcIterator(*this, node, Base::kNilArc)); \
1285 } \
1286 template <typename NodeIndexType, typename ArcIndexType> \
1287 BeginEndWrapper<typename c<NodeIndexType, ArcIndexType>::t##ArcIterator> \
1288 c<NodeIndexType, ArcIndexType>::t##ArcsStartingFrom( \
1289 NodeIndexType node, ArcIndexType from) const { \
1290 return BeginEndWrapper<t##ArcIterator>( \
1291 t##ArcIterator(*this, node, from), \
1292 t##ArcIterator(*this, node, Base::kNilArc)); \
1293 }
1294
1295// Adapt our old iteration style to support range-based for loops. Add typedefs
1296// required by std::iterator_traits.
1297#define DEFINE_STL_ITERATOR_FUNCTIONS(iterator_class_name) \
1298 using iterator_category = std::input_iterator_tag; \
1299 using difference_type = ptrdiff_t; \
1300 using pointer = const ArcIndexType*; \
1301 using value_type = ArcIndexType; \
1302 using reference = value_type; \
1303 bool operator!=(const iterator_class_name& other) const { \
1304 return this->index_ != other.index_; \
1305 } \
1306 bool operator==(const iterator_class_name& other) const { \
1307 return this->index_ == other.index_; \
1308 } \
1309 ArcIndexType operator*() const { return this->Index(); } \
1310 iterator_class_name& operator++() { \
1311 this->Next(); \
1312 return *this; \
1313 } \
1314 iterator_class_name operator++(int) { \
1315 auto tmp = *this; \
1316 this->Next(); \
1317 return tmp; \
1318 }
1319
1320// ListGraph implementation ----------------------------------------------------
1321
1322template <typename NodeIndexType, typename ArcIndexType>
1324 ArcIndexType arc) const {
1325 DCHECK(IsArcValid(arc));
1326 return tail_[arc];
1327}
1328
1329template <typename NodeIndexType, typename ArcIndexType>
1331 ArcIndexType arc) const {
1332 DCHECK(IsArcValid(arc)) << arc;
1333 return head_[arc];
1334}
1335
1336template <typename NodeIndexType, typename ArcIndexType>
1338 NodeIndexType node) const {
1339 ArcIndexType degree(0);
1340 for (auto arc ABSL_ATTRIBUTE_UNUSED : OutgoingArcs(node)) ++degree;
1341 return degree;
1342}
1343
1344template <typename NodeIndexType, typename ArcIndexType>
1345void ListGraph<NodeIndexType, ArcIndexType>::AddNode(NodeIndexType node) {
1346 if (node < num_nodes_) return;
1347 DCHECK(!const_capacities_ || node < node_capacity_);
1348 num_nodes_ = node + NodeIndexType(1);
1349 start_.resize(num_nodes_, Base::kNilArc);
1350}
1351
1352template <typename NodeIndexType, typename ArcIndexType>
1354 NodeIndexType tail, NodeIndexType head) {
1355 DCHECK_GE(tail, NodeIndexType(0));
1356 DCHECK_GE(head, NodeIndexType(0));
1357 AddNode(tail > head ? tail : head);
1358 head_.push_back(head);
1359 tail_.push_back(tail);
1360 next_.push_back(start_[tail]);
1361 start_[tail] = num_arcs_;
1362 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
1363 return num_arcs_++;
1364}
1365
1366template <typename NodeIndexType, typename ArcIndexType>
1368 Base::ReserveNodes(bound);
1369 if (bound <= num_nodes_) return;
1370 start_.reserve(bound);
1371}
1372
1373template <typename NodeIndexType, typename ArcIndexType>
1375 Base::ReserveArcs(bound);
1376 if (bound <= num_arcs_) return;
1377 head_.reserve(bound);
1378 tail_.reserve(bound);
1379 next_.reserve(bound);
1380}
1381
1382// StaticGraph implementation --------------------------------------------------
1383
1384template <typename NodeIndexType, typename ArcIndexType>
1385template <class ArcContainer>
1388 const ArcContainer& arcs) {
1389 StaticGraph g(num_nodes, arcs.size());
1390 for (const auto& [from, to] : arcs) g.AddArc(from, to);
1391 g.Build();
1392 return g;
1393}
1394
1395template <typename NodeIndexType, typename ArcIndexType>
1396absl::Span<const NodeIndexType>
1398 return absl::Span<const NodeIndexType>(
1399 head_.data() + static_cast<size_t>(start_[node]),
1400 static_cast<size_t>(DirectArcLimit(node) - start_[node]));
1401}
1402
1403template <typename NodeIndexType, typename ArcIndexType>
1405 NodeIndexType node) const {
1406 return DirectArcLimit(node) - start_[node];
1407}
1408
1409template <typename NodeIndexType, typename ArcIndexType>
1411 NodeIndexType bound) {
1413 if (bound <= num_nodes_) return;
1414 start_.reserve(bound + NodeIndexType(1));
1415}
1416
1417template <typename NodeIndexType, typename ArcIndexType>
1419 Base::ReserveArcs(bound);
1420 if (bound <= num_arcs_) return;
1421 head_.reserve(bound);
1422 tail_.reserve(bound);
1423}
1424
1425template <typename NodeIndexType, typename ArcIndexType>
1427 if (node < num_nodes_) return;
1428 DCHECK(!const_capacities_ || node < node_capacity_) << node;
1429 num_nodes_ = node + NodeIndexType(1);
1430 start_.resize(num_nodes_ + NodeIndexType(1), ArcIndexType(0));
1431}
1432
1433template <typename NodeIndexType, typename ArcIndexType>
1435 NodeIndexType tail, NodeIndexType head) {
1436 DCHECK_GE(tail, NodeIndexType(0));
1437 DCHECK_GE(head, NodeIndexType(0));
1438 DCHECK(!is_built_);
1439 AddNode(tail > head ? tail : head);
1440 if (arc_in_order_) {
1441 if (tail >= last_tail_seen_) {
1442 start_[tail]++;
1443 last_tail_seen_ = tail;
1444 } else {
1445 arc_in_order_ = false;
1446 }
1447 }
1448 tail_.push_back(tail);
1449 head_.push_back(head);
1450 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
1451 return num_arcs_++;
1452}
1453
1454template <typename NodeIndexType, typename ArcIndexType>
1456 ArcIndexType arc) const {
1457 DCHECK(IsArcValid(arc));
1458 return tail_[arc];
1459}
1460
1461template <typename NodeIndexType, typename ArcIndexType>
1463 ArcIndexType arc) const {
1464 DCHECK(IsArcValid(arc));
1465 return head_[arc];
1466}
1467
1468// Implementation details: A reader may be surprised that we do many passes
1469// into the data where things could be done in one pass. For instance, during
1470// construction, we store the edges first, and then do a second pass at the
1471// end to compute the degree distribution.
1472//
1473// This is because it is a lot more efficient cache-wise to do it this way.
1474// This was determined by various experiments, but can also be understood:
1475// - during repetitive call to AddArc() a client usually accesses various
1476// areas of memory, and there is no reason to pollute the cache with
1477// possibly random access to degree[i].
1478// - When the degrees are needed, we compute them in one go, maximizing the
1479// chance of cache hit during the computation.
1480template <typename NodeIndexType, typename ArcIndexType>
1482 std::vector<ArcIndexType>* permutation) {
1483 DCHECK(!is_built_);
1484 if (is_built_) return;
1485 is_built_ = true;
1486 node_capacity_ = num_nodes_;
1487 arc_capacity_ = num_arcs_;
1488 this->FreezeCapacities();
1489 if (num_nodes_ == NodeIndexType(0)) {
1490 return;
1491 }
1492
1493 // If Arc are in order, start_ already contains the degree distribution.
1494 if (arc_in_order_) {
1495 if (permutation != nullptr) {
1496 permutation->clear();
1497 }
1498 this->ComputeCumulativeSum(&start_);
1499 return;
1500 }
1501
1502 // Computes outgoing degree of each nodes. We have to clear start_, since
1503 // at least the first arc was processed with arc_in_order_ == true.
1504 start_.assign(num_nodes_ + NodeIndexType(1), ArcIndexType(0));
1505 for (ArcIndexType i(0); i < num_arcs_; ++i) {
1506 start_[tail_[i]]++;
1507 }
1508 this->ComputeCumulativeSum(&start_);
1509
1510 // Computes the forward arc permutation.
1511 // Note that this temporarily alters the start_ vector.
1512 std::vector<ArcIndexType> perm(static_cast<size_t>(num_arcs_));
1513 for (ArcIndexType i(0); i < num_arcs_; ++i) {
1514 perm[static_cast<size_t>(i)] = start_[tail_[i]]++;
1515 }
1516
1517 // We use "tail_" (which now contains rubbish) to permute "head_" faster.
1518 CHECK_EQ(tail_.size(), num_arcs_);
1519 tail_.swap(head_);
1520 for (ArcIndexType i(0); i < num_arcs_; ++i) {
1521 head_[perm[static_cast<size_t>(i)]] = tail_[i];
1522 }
1523
1524 if (permutation != nullptr) {
1525 permutation->swap(perm);
1526 }
1527
1528 // Restore in start_[i] the index of the first arc with tail >= i.
1529 DCHECK_GE(num_nodes_, NodeIndexType(1));
1530 for (NodeIndexType i = num_nodes_ - NodeIndexType(1); i > NodeIndexType(0);
1531 --i) {
1532 start_[i] = start_[i - NodeIndexType(1)];
1533 }
1534 start_[NodeIndexType(0)] = ArcIndexType(0);
1535
1536 // Recompute the correct tail_ vector
1537 for (const NodeIndexType node : Base::AllNodes()) {
1538 for (const ArcIndexType arc : OutgoingArcs(node)) {
1539 tail_[arc] = node;
1540 }
1541 }
1542}
1543
1544// ReverseArcListGraph implementation ------------------------------------------
1546 OutgoingOrOppositeIncoming);
1548template <typename NodeIndexType, typename ArcIndexType>
1550 NodeIndexType, ArcIndexType>::OutgoingHeadIterator>
1552 NodeIndexType node) const {
1553 const auto outgoing_arcs = OutgoingArcs(node);
1554 // Note: `BeginEndWrapper` is a borrowed range (`std::ranges::borrowed_range`)
1555 // so copying begin/end is safe.
1557 OutgoingHeadIterator(*this, outgoing_arcs.begin()),
1558 OutgoingHeadIterator(*this, outgoing_arcs.end()));
1559}
1560
1561template <typename NodeIndexType, typename ArcIndexType>
1563 NodeIndexType node) const {
1564 ArcIndexType degree(0);
1565 for (auto arc ABSL_ATTRIBUTE_UNUSED : OutgoingArcs(node)) ++degree;
1566 return degree;
1567}
1568
1569template <typename NodeIndexType, typename ArcIndexType>
1571 NodeIndexType node) const {
1572 ArcIndexType degree(0);
1573 for (auto arc ABSL_ATTRIBUTE_UNUSED : OppositeIncomingArcs(node)) ++degree;
1574 return degree;
1575}
1576
1577template <typename NodeIndexType, typename ArcIndexType>
1579 ArcIndexType arc) const {
1580 DCHECK(IsArcValid(arc));
1581 return ~arc;
1582}
1583
1584template <typename NodeIndexType, typename ArcIndexType>
1586 ArcIndexType arc) const {
1587 DCHECK(IsArcValid(arc));
1588 return head_[arc];
1589}
1590
1591template <typename NodeIndexType, typename ArcIndexType>
1593 ArcIndexType arc) const {
1594 return head_[OppositeArc(arc)];
1595}
1596
1597template <typename NodeIndexType, typename ArcIndexType>
1599 NodeIndexType bound) {
1601 if (bound <= num_nodes_) return;
1602 start_.reserve(bound);
1603 reverse_start_.reserve(bound);
1604}
1605
1606template <typename NodeIndexType, typename ArcIndexType>
1608 ArcIndexType bound) {
1610 if (bound <= num_arcs_) return;
1611 head_.reserve(bound);
1612 next_.reserve(bound);
1613}
1614
1615template <typename NodeIndexType, typename ArcIndexType>
1617 NodeIndexType node) {
1618 if (node < num_nodes_) return;
1619 DCHECK(!const_capacities_ || node < node_capacity_);
1620 num_nodes_ = node + NodeIndexType(1);
1621 start_.resize(num_nodes_, Base::kNilArc);
1622 reverse_start_.resize(num_nodes_, Base::kNilArc);
1623}
1624
1625template <typename NodeIndexType, typename ArcIndexType>
1627 NodeIndexType tail, NodeIndexType head) {
1628 DCHECK_GE(tail, NodeIndexType(0));
1629 DCHECK_GE(head, NodeIndexType(0));
1630 AddNode(tail > head ? tail : head);
1631 head_.grow(tail, head);
1632 next_.grow(reverse_start_[head], start_[tail]);
1633 start_[tail] = num_arcs_;
1634 reverse_start_[head] = ~num_arcs_;
1635 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
1636 return num_arcs_++;
1637}
1638
1639template <typename NodeIndexType, typename ArcIndexType>
1640class ReverseArcListGraph<NodeIndexType,
1641 ArcIndexType>::OutgoingOrOppositeIncomingArcIterator {
1642 public:
1644 NodeIndexType node)
1645 : graph_(&graph), index_(graph.reverse_start_[node]), node_(node) {
1646 DCHECK(graph.IsNodeValid(node));
1647 if (index_ == Base::kNilArc) index_ = graph.start_[node];
1648 }
1650 NodeIndexType node, ArcIndexType arc)
1651 : graph_(&graph), index_(arc), node_(node) {
1652 DCHECK(graph.IsNodeValid(node));
1653 DCHECK(arc == Base::kNilArc || graph.Tail(arc) == node);
1654 }
1655
1656 bool Ok() const { return index_ != Base::kNilArc; }
1657 ArcIndexType Index() const { return index_; }
1658 void Next() {
1659 DCHECK(Ok());
1660 if (index_ < ArcIndexType(0)) {
1661 index_ = graph_->next_[index_];
1662 if (index_ == Base::kNilArc) {
1663 index_ = graph_->start_[node_];
1664 }
1665 } else {
1666 index_ = graph_->next_[index_];
1667 }
1668 }
1669
1670 DEFINE_STL_ITERATOR_FUNCTIONS(OutgoingOrOppositeIncomingArcIterator);
1671
1672 private:
1673 const ReverseArcListGraph* graph_;
1674 ArcIndexType index_;
1675 NodeIndexType node_;
1676};
1677
1678// ReverseArcStaticGraph implementation ----------------------------------------
1679
1681 OutgoingOrOppositeIncoming);
1683template <typename NodeIndexType, typename ArcIndexType>
1685 NodeIndexType node) const {
1686 return DirectArcLimit(node) - start_[node];
1687}
1688
1689template <typename NodeIndexType, typename ArcIndexType>
1691 NodeIndexType node) const {
1692 return ReverseArcLimit(node) - reverse_start_[node];
1693}
1694
1695template <typename NodeIndexType, typename ArcIndexType>
1696absl::Span<const NodeIndexType>
1698 NodeIndexType node) const {
1699 return absl::Span<const NodeIndexType>(
1700 head_.data() + static_cast<size_t>(start_[node]),
1701 static_cast<size_t>(DirectArcLimit(node) - start_[node]));
1702}
1703
1704template <typename NodeIndexType, typename ArcIndexType>
1706 ArcIndexType arc) const {
1707 DCHECK(is_built_);
1708 DCHECK(IsArcValid(arc));
1709 return opposite_[arc];
1710}
1711
1712template <typename NodeIndexType, typename ArcIndexType>
1714 ArcIndexType arc) const {
1715 DCHECK(is_built_);
1716 DCHECK(IsArcValid(arc));
1717 return head_[arc];
1718}
1719
1720template <typename NodeIndexType, typename ArcIndexType>
1722 ArcIndexType arc) const {
1723 DCHECK(is_built_);
1724 return head_[OppositeArc(arc)];
1725}
1726
1727template <typename NodeIndexType, typename ArcIndexType>
1729 ArcIndexType bound) {
1731 if (bound <= num_arcs_) return;
1732 head_.reserve(bound);
1733}
1734
1735template <typename NodeIndexType, typename ArcIndexType>
1737 NodeIndexType node) {
1738 if (node < num_nodes_) return;
1739 DCHECK(!const_capacities_ || node < node_capacity_);
1740 num_nodes_ = node + NodeIndexType(1);
1741}
1742
1743template <typename NodeIndexType, typename ArcIndexType>
1745 NodeIndexType tail, NodeIndexType head) {
1746 DCHECK_GE(tail, NodeIndexType(0));
1747 DCHECK_GE(head, NodeIndexType(0));
1748 AddNode(tail > head ? tail : head);
1749
1750 // We inverse head and tail here because it is more convenient this way
1751 // during build time, see Build().
1752 head_.grow(head, tail);
1753 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
1754 return num_arcs_++;
1755}
1756
1757template <typename NodeIndexType, typename ArcIndexType>
1759 std::vector<ArcIndexType>* permutation) {
1760 DCHECK(!is_built_);
1761 if (is_built_) return;
1762 is_built_ = true;
1763 node_capacity_ = num_nodes_;
1764 arc_capacity_ = num_arcs_;
1765 this->FreezeCapacities();
1766 if (num_nodes_ == NodeIndexType(0)) {
1767 return;
1768 }
1769 this->BuildStartAndForwardHead(&head_, &start_, permutation);
1770
1771 // Computes incoming degree of each nodes.
1772 reverse_start_.assign(num_nodes_ + NodeIndexType(1), ArcIndexType(0));
1773 for (ArcIndexType i(0); i < num_arcs_; ++i) {
1774 reverse_start_[head_[i]]++;
1775 }
1776 this->ComputeCumulativeSum(&reverse_start_);
1777
1778 // Computes the reverse arcs of the forward arcs.
1779 // Note that this sort the reverse arcs with the same tail by head.
1780 opposite_.reserve(num_arcs_);
1781 for (ArcIndexType i(0); i < num_arcs_; ++i) {
1782 // TODO(user): the 0 is wasted here, but minor optimisation.
1783 opposite_.grow(ArcIndexType(0), reverse_start_[head_[i]]++ - num_arcs_);
1784 }
1785
1786 // Computes in reverse_start_ the start index of the reverse arcs.
1787 DCHECK_GE(num_nodes_, NodeIndexType(1));
1788 reverse_start_[num_nodes_] = ArcIndexType(0); // Sentinel.
1789 for (NodeIndexType i = num_nodes_ - NodeIndexType(1); i > NodeIndexType(0);
1790 --i) {
1791 reverse_start_[i] = reverse_start_[i - NodeIndexType(1)] - num_arcs_;
1792 }
1793 if (num_nodes_ != NodeIndexType(0)) {
1794 reverse_start_[NodeIndexType(0)] = -num_arcs_;
1795 }
1796
1797 // Fill reverse arc information.
1798 for (ArcIndexType i(0); i < num_arcs_; ++i) {
1799 opposite_[opposite_[i]] = i;
1800 }
1801 for (const NodeIndexType node : Base::AllNodes()) {
1802 for (const ArcIndexType arc : OutgoingArcs(node)) {
1803 head_[opposite_[arc]] = node;
1804 }
1805 }
1806}
1807
1808template <typename NodeIndexType, typename ArcIndexType>
1810 NodeIndexType, ArcIndexType>::OutgoingOrOppositeIncomingArcIterator {
1811 public:
1813 NodeIndexType node)
1814 : index_(graph.reverse_start_[node]),
1815 first_limit_(graph.ReverseArcLimit(node)),
1816 next_start_(graph.start_[node]),
1817 limit_(graph.DirectArcLimit(node)) {
1818 if (index_ == first_limit_) index_ = next_start_;
1819 DCHECK(graph.IsNodeValid(node));
1820 DCHECK((index_ < first_limit_) || (index_ >= next_start_));
1821 }
1823 NodeIndexType node, ArcIndexType arc)
1824 : first_limit_(graph.ReverseArcLimit(node)),
1825 next_start_(graph.start_[node]),
1826 limit_(graph.DirectArcLimit(node)) {
1827 index_ = arc == Base::kNilArc ? limit_ : arc;
1828 DCHECK(graph.IsNodeValid(node));
1829 DCHECK((index_ >= graph.reverse_start_[node] && index_ < first_limit_) ||
1830 (index_ >= next_start_));
1831 }
1832
1833 ArcIndexType Index() const { return index_; }
1834 bool Ok() const { return index_ != limit_; }
1835 void Next() {
1836 DCHECK(Ok());
1837 index_++;
1838 if (index_ == first_limit_) {
1839 index_ = next_start_;
1840 }
1841 }
1842
1843 DEFINE_STL_ITERATOR_FUNCTIONS(OutgoingOrOppositeIncomingArcIterator);
1844
1845 private:
1846 ArcIndexType index_;
1847 const ArcIndexType first_limit_;
1848 const ArcIndexType next_start_;
1849 const ArcIndexType limit_;
1850};
1851
1852// CompleteGraph implementation ------------------------------------------------
1853// Nodes and arcs are implicit and not stored.
1854
1855template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
1856class CompleteGraph
1857 : public BaseGraph<CompleteGraph<NodeIndexType, ArcIndexType>,
1858 NodeIndexType, ArcIndexType, false> {
1860 ArcIndexType, false>
1861 Base;
1862 using Base::arc_capacity_;
1865 using Base::num_arcs_;
1866 using Base::num_nodes_;
1867
1868 public:
1869 // Builds a complete graph with num_nodes nodes.
1870 explicit CompleteGraph(NodeIndexType num_nodes)
1871 : // If there are 0 or 1 nodes, the divisor is arbitrary. We pick 2 as 0
1872 // and 1 are not supported by `ConstantDivisor`.
1873 divisor_(num_nodes > 1 ? num_nodes : 2) {
1874 this->Reserve(num_nodes, num_nodes * num_nodes);
1875 this->FreezeCapacities();
1876 num_nodes_ = num_nodes;
1877 num_arcs_ = num_nodes * num_nodes;
1878 }
1879
1880 NodeIndexType Head(ArcIndexType arc) const;
1881 NodeIndexType Tail(ArcIndexType arc) const;
1882 ArcIndexType OutDegree(NodeIndexType node) const;
1883 IntegerRange<ArcIndexType> OutgoingArcs(NodeIndexType node) const;
1885 ArcIndexType from) const;
1886 IntegerRange<NodeIndexType> operator[](NodeIndexType node) const;
1887
1888 const ::util::math::ConstantDivisor<std::make_unsigned_t<ArcIndexType>>
1889 divisor_;
1890};
1892template <typename NodeIndexType, typename ArcIndexType>
1894 ArcIndexType arc) const {
1895 DCHECK(this->IsArcValid(arc));
1896 return arc % divisor_;
1897}
1898
1899template <typename NodeIndexType, typename ArcIndexType>
1901 ArcIndexType arc) const {
1902 DCHECK(this->IsArcValid(arc));
1903 return arc / divisor_;
1904}
1905
1906template <typename NodeIndexType, typename ArcIndexType>
1908 NodeIndexType node) const {
1909 return num_nodes_;
1910}
1911
1912template <typename NodeIndexType, typename ArcIndexType>
1915 NodeIndexType node) const {
1916 DCHECK_LT(node, num_nodes_);
1918 static_cast<ArcIndexType>(num_nodes_) * node,
1919 static_cast<ArcIndexType>(num_nodes_) * (node + 1));
1920}
1921
1922template <typename NodeIndexType, typename ArcIndexType>
1925 NodeIndexType node, ArcIndexType from) const {
1926 DCHECK_LT(node, num_nodes_);
1928 from, static_cast<ArcIndexType>(num_nodes_) * (node + 1));
1929}
1930
1931template <typename NodeIndexType, typename ArcIndexType>
1934 NodeIndexType node) const {
1935 DCHECK_LT(node, num_nodes_);
1936 return IntegerRange<NodeIndexType>(NodeIndexType(0), num_nodes_);
1937}
1938
1939// CompleteBipartiteGraph implementation ---------------------------------------
1940// Nodes and arcs are implicit and not stored.
1941
1942template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
1944 : public BaseGraph<CompleteBipartiteGraph<NodeIndexType, ArcIndexType>,
1945 NodeIndexType, ArcIndexType, false> {
1947 NodeIndexType, ArcIndexType, false>
1948 Base;
1949 using Base::arc_capacity_;
1952 using Base::num_arcs_;
1953 using Base::num_nodes_;
1954
1955 public:
1956 // Builds a complete bipartite graph from a set of left nodes to a set of
1957 // right nodes.
1958 // Indices of left nodes of the bipartite graph range from 0 to left_nodes-1;
1959 // indices of right nodes range from left_nodes to left_nodes+right_nodes-1.
1960 CompleteBipartiteGraph(NodeIndexType left_nodes, NodeIndexType right_nodes)
1961 : left_nodes_(left_nodes),
1962 right_nodes_(right_nodes),
1963 // If there are no right nodes, the divisor is arbitrary. We pick 2 as
1964 // 0 and 1 are not supported by `ConstantDivisor`. We handle the case
1965 // where `right_nodes` is 1 explicitly when dividing.
1966 divisor_(right_nodes > 1 ? right_nodes : 2) {
1967 this->Reserve(left_nodes + right_nodes, left_nodes * right_nodes);
1968 this->FreezeCapacities();
1969 num_nodes_ = left_nodes + right_nodes;
1970 num_arcs_ = left_nodes * right_nodes;
1971 }
1972
1973 // Returns the arc index for the arc from `left` to `right`, where `left` is
1974 // in `[0, left_nodes)` and `right` is in
1975 // `[left_nodes, left_nodes + right_nodes)`.
1976 ArcIndexType GetArc(NodeIndexType left_node, NodeIndexType right_node) const;
1977
1978 NodeIndexType Head(ArcIndexType arc) const;
1979 NodeIndexType Tail(ArcIndexType arc) const;
1980 ArcIndexType OutDegree(NodeIndexType node) const;
1981 IntegerRange<ArcIndexType> OutgoingArcs(NodeIndexType node) const;
1983 ArcIndexType from) const;
1984 IntegerRange<NodeIndexType> operator[](NodeIndexType node) const;
1985
1986 private:
1987 const NodeIndexType left_nodes_;
1988 const NodeIndexType right_nodes_;
1989 // Note: only valid if `right_nodes_ > 1`.
1990 const ::util::math::ConstantDivisor<std::make_unsigned_t<ArcIndexType>>
1991 divisor_;
1992};
1993
1994template <typename NodeIndexType, typename ArcIndexType>
1996 NodeIndexType left_node, NodeIndexType right_node) const {
1997 DCHECK_LT(left_node, left_nodes_);
1998 DCHECK_GE(right_node, left_nodes_);
1999 DCHECK_LT(right_node, num_nodes_);
2000 return left_node * static_cast<ArcIndexType>(right_nodes_) +
2001 (right_node - left_nodes_);
2002}
2003
2004template <typename NodeIndexType, typename ArcIndexType>
2006 ArcIndexType arc) const {
2007 DCHECK(this->IsArcValid(arc));
2008 // See comment on `divisor_` in the constructor.
2009 return right_nodes_ > 1 ? left_nodes_ + arc % divisor_ : left_nodes_;
2010}
2011
2012template <typename NodeIndexType, typename ArcIndexType>
2014 ArcIndexType arc) const {
2015 DCHECK(this->IsArcValid(arc));
2016 // See comment on `divisor_` in the constructor.
2017 return right_nodes_ > 1 ? arc / divisor_ : arc;
2018}
2019
2020template <typename NodeIndexType, typename ArcIndexType>
2022 NodeIndexType node) const {
2023 return (node < left_nodes_) ? right_nodes_ : 0;
2024}
2025
2026template <typename NodeIndexType, typename ArcIndexType>
2029 NodeIndexType node) const {
2030 if (node < left_nodes_) {
2032 static_cast<ArcIndexType>(right_nodes_) * node,
2033 static_cast<ArcIndexType>(right_nodes_) * (node + 1));
2034 } else {
2035 return IntegerRange<ArcIndexType>(ArcIndexType(0), ArcIndexType(0));
2036 }
2037}
2038
2039template <typename NodeIndexType, typename ArcIndexType>
2042 NodeIndexType node, ArcIndexType from) const {
2043 if (node < left_nodes_) {
2045 from, static_cast<ArcIndexType>(right_nodes_) * (node + 1));
2046 } else {
2047 return IntegerRange<ArcIndexType>(ArcIndexType(0), ArcIndexType(0));
2048 }
2049}
2050
2051template <typename NodeIndexType, typename ArcIndexType>
2054 NodeIndexType node) const {
2055 if (node < left_nodes_) {
2056 return IntegerRange<NodeIndexType>(left_nodes_, left_nodes_ + right_nodes_);
2057 } else {
2058 return IntegerRange<NodeIndexType>(ArcIndexType(0), ArcIndexType(0));
2059 }
2060}
2061
2062// Defining the simplest Graph interface as Graph for convenience.
2063typedef ListGraph<> Graph;
2064
2065} // namespace util
2066
2067#undef DEFINE_RANGE_BASED_ARC_ITERATION
2068#undef DEFINE_STL_ITERATOR_FUNCTIONS
2069
2070#endif // UTIL_GRAPH_GRAPH_H_
const ::util::math::ConstantDivisor< std::make_unsigned_t< int64_t > > divisor_
Definition graph.h:1891
OutgoingOrOppositeIncomingArcIterator(const ReverseArcListGraph &graph, NodeIndexType node)
Definition graph.h:1645
BeginEndWrapper< OutgoingHeadIterator > operator[](NodeIndexType node) const
Definition graph.h:1553
NodeIndexType Head(ArcIndexType arc) const
Definition graph.h:1587
void ReserveArcs(ArcIndexType bound) override
Definition graph.h:1609
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Definition graph.h:1628
ArcIndexType OppositeArc(ArcIndexType arc) const
Definition graph.h:1580
void AddNode(NodeIndexType node)
Definition graph.h:1618
NodeIndexType Tail(ArcIndexType arc) const
Definition graph.h:1594
ArcIndexType OutDegree(NodeIndexType node) const
Definition graph.h:1564
void ReserveNodes(NodeIndexType bound) override
Definition graph.h:1600
ArcIndexType InDegree(NodeIndexType node) const
Definition graph.h:1572
std::ptrdiff_t difference_type
Definition graph.h:340
friend bool operator!=(const ArcPropertyIterator &l, const ArcPropertyIterator &r)
Definition graph.h:369
friend bool operator==(const ArcPropertyIterator &l, const ArcPropertyIterator &r)
Definition graph.h:364
IntegerRange< ArcIndex > AllForwardArcs() const
Definition graph.h:1154
NodeIndexType num_nodes() const
Definition graph.h:229
ArcIndexType num_arcs() const
Definition graph.h:233
ArcIndexType arc_capacity() const
Definition graph.h:1171
void FreezeCapacities()
Definition graph.h:1179
void ComputeCumulativeSum(internal::Vector< NodeIndexType, ArcIndexType > *v)
Definition graph.h:1192
virtual bool IsBuilt() const
Definition graph.h:308
BaseGraph & operator=(const BaseGraph &)=default
virtual void Build(std::vector< ArcIndexType > *permutation)
Definition graph.h:304
void BuildStartAndForwardHead(internal::SVector< ArcIndexType, NodeIndexType > *head, internal::Vector< NodeIndexType, ArcIndexType > *start, std::vector< ArcIndexType > *permutation)
Definition graph.h:1212
NodeIndexType size() const
Definition graph.h:230
IntegerRange< NodeIndex > AllNodes() const
Definition graph.h:1146
void Reserve(NodeIndexType node_capacity, ArcIndexType arc_capacity)
Definition graph.h:277
virtual void ReserveNodes(NodeIndexType bound)
Definition graph.h:265
bool IsNodeValid(NodeIndexType node) const
Definition graph.h:242
bool IsArcValid(ArcIndexType arc) const
Definition graph.h:248
virtual void ReserveArcs(ArcIndexType bound)
Definition graph.h:271
NodeIndexType node_capacity() const
Definition graph.h:1162
void Build()
Definition graph.h:307
BaseGraph(const BaseGraph &)=default
virtual ~BaseGraph()=default
ArcIndexType GetArc(NodeIndexType left_node, NodeIndexType right_node) const
Definition graph.h:1997
NodeIndexType Tail(ArcIndexType arc) const
Definition graph.h:2015
CompleteBipartiteGraph(NodeIndexType left_nodes, NodeIndexType right_nodes)
Definition graph.h:1962
IntegerRange< ArcIndexType > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
Definition graph.h:2043
IntegerRange< ArcIndexType > OutgoingArcs(NodeIndexType node) const
Definition graph.h:2030
ArcIndexType OutDegree(NodeIndexType node) const
Definition graph.h:2023
NodeIndexType Head(ArcIndexType arc) const
Definition graph.h:2007
IntegerRange< NodeIndexType > operator[](NodeIndexType node) const
Definition graph.h:2055
const ::util::math::ConstantDivisor< std::make_unsigned_t< ArcIndexType > > divisor_
Definition graph.h:1891
ArcIndexType OutDegree(NodeIndexType node) const
Definition graph.h:1909
IntegerRange< ArcIndexType > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
Definition graph.h:1926
IntegerRange< ArcIndexType > OutgoingArcs(NodeIndexType node) const
Definition graph.h:1916
NodeIndexType Tail(ArcIndexType arc) const
Definition graph.h:1902
IntegerRange< NodeIndexType > operator[](NodeIndexType node) const
Definition graph.h:1935
CompleteGraph(NodeIndexType num_nodes)
Definition graph.h:1872
NodeIndexType Head(ArcIndexType arc) const
Definition graph.h:1895
ListGraph()=default
ListGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
Definition graph.h:680
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
Definition graph.h:721
void AddNode(NodeIndexType node)
Definition graph.h:1347
bool IsArcValid(ArcIndexType arc) const
Definition graph.h:248
ArcHeadIterator< ListGraph, OutgoingArcIterator > OutgoingHeadIterator
Definition graph.h:709
BeginEndWrapper< OutgoingArcIterator > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
Definition graph.h:730
NodeIndexType Tail(ArcIndexType arc) const
Definition graph.h:1325
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Definition graph.h:1355
ArcIndexType OutDegree(NodeIndexType node) const
Definition graph.h:1339
NodeIndexType Head(ArcIndexType arc) const
Definition graph.h:1332
BeginEndWrapper< OutgoingHeadIterator > operator[](NodeIndexType node) const
Definition graph.h:741
void ReserveNodes(NodeIndexType bound) override
Definition graph.h:1369
ChasingIterator< ArcIndexType, Base::kNilArc, OutgoingArcIteratorTag > OutgoingArcIterator
Definition graph.h:707
void ReserveArcs(ArcIndexType bound) override
Definition graph.h:1376
BeginEndWrapper< IncomingArcIterator > IncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
Definition graph.h:929
BeginEndWrapper< OutgoingHeadIterator > operator[](NodeIndexType node) const
Definition graph.h:1553
NodeIndexType Head(ArcIndexType arc) const
Definition graph.h:1587
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcs(NodeIndexType node) const
ChasingIterator< ArcIndexType, Base::kNilArc, OutgoingArcIteratorTag > OutgoingArcIterator
Definition graph.h:888
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcs(NodeIndexType node) const
Definition graph.h:942
void ReserveArcs(ArcIndexType bound) override
Definition graph.h:1609
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
Definition graph.h:911
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Definition graph.h:1628
ReverseArcListGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
Definition graph.h:871
BeginEndWrapper< OutgoingArcIterator > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
Definition graph.h:916
bool IsArcValid(ArcIndexType arc) const
Definition graph.h:248
ArcOppositeArcIterator< ReverseArcListGraph, OppositeIncomingArcIterator > IncomingArcIterator
Definition graph.h:897
ArcIndexType OppositeArc(ArcIndexType arc) const
Definition graph.h:1580
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
void AddNode(NodeIndexType node)
Definition graph.h:1618
BeginEndWrapper< IncomingArcIterator > IncomingArcs(NodeIndexType node) const
Definition graph.h:925
NodeIndexType Tail(ArcIndexType arc) const
Definition graph.h:1594
ChasingIterator< ArcIndexType, Base::kNilArc, OppositeIncomingArcIteratorTag > OppositeIncomingArcIterator
Definition graph.h:891
ArcIndexType OutDegree(NodeIndexType node) const
Definition graph.h:1564
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
Definition graph.h:948
void ReserveNodes(NodeIndexType bound) override
Definition graph.h:1600
ArcHeadIterator< ReverseArcListGraph, OutgoingArcIterator > OutgoingHeadIterator
Definition graph.h:895
ArcIndexType InDegree(NodeIndexType node) const
Definition graph.h:1572
OutgoingOrOppositeIncomingArcIterator(const ReverseArcStaticGraph &graph, NodeIndexType node)
Definition graph.h:1814
bool IsArcValid(ArcIndexType arc) const
Definition graph.h:248
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Definition graph.h:1746
NodeIndexType Tail(ArcIndexType arc) const
Definition graph.h:1723
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
IntegerRangeIterator< ArcIndexType > OppositeIncomingArcIterator
Definition graph.h:1027
IntegerRange< ArcIndexType > OutgoingArcs(NodeIndexType node) const
Definition graph.h:1033
BeginEndWrapper< IncomingArcIterator > IncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
Definition graph.h:1062
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcs(NodeIndexType node) const
ArcIndexType OppositeArc(ArcIndexType arc) const
Definition graph.h:1707
IntegerRange< ArcIndexType > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
Definition graph.h:1036
BeginEndWrapper< IncomingArcIterator > IncomingArcs(NodeIndexType node) const
Definition graph.h:1056
absl::Span< const NodeIndexType > operator[](NodeIndexType node) const
Definition graph.h:1699
NodeIndexType Head(ArcIndexType arc) const
Definition graph.h:1715
bool IsBuilt() const final
Definition graph.h:1089
void ReserveArcs(ArcIndexType bound) override
Definition graph.h:1730
ArcIndexType OutDegree(NodeIndexType node) const
Definition graph.h:1686
ArcIndexType InDegree(NodeIndexType node) const
Definition graph.h:1692
IntegerRangeIterator< ArcIndexType > OutgoingArcIterator
Definition graph.h:1031
ReverseArcStaticGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
Definition graph.h:1007
ArcOppositeArcIterator< ReverseArcStaticGraph, OppositeIncomingArcIterator > IncomingArcIterator
Definition graph.h:1028
IntegerRange< ArcIndexType > OppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
Definition graph.h:1048
void Build(std::vector< ArcIndexType > *permutation) final
Definition graph.h:1760
void AddNode(NodeIndexType node)
Definition graph.h:1738
IntegerRange< ArcIndexType > OppositeIncomingArcs(NodeIndexType node) const
Definition graph.h:1044
absl::Span< const NodeIndexType > operator[](NodeIndexType node) const
Definition graph.h:1399
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Definition graph.h:1436
bool IsArcValid(ArcIndexType arc) const
Definition graph.h:248
static StaticGraph FromArcs(NodeIndexType num_nodes, const ArcContainer &arcs)
IntegerRange< ArcIndexType > OutgoingArcs(NodeIndexType node) const
Definition graph.h:804
ArcIndexType OutDegree(NodeIndexType node) const
Definition graph.h:1406
NodeIndexType Tail(ArcIndexType arc) const
Definition graph.h:1457
void ReserveArcs(ArcIndexType bound) override
Definition graph.h:1420
void ReserveNodes(NodeIndexType bound) override
Definition graph.h:1412
void AddNode(NodeIndexType node)
Definition graph.h:1428
bool IsBuilt() const final
Definition graph.h:827
StaticGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
Definition graph.h:784
IntegerRange< ArcIndexType > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
Definition graph.h:807
NodeIndexType Head(ArcIndexType arc) const
Definition graph.h:1464
void grow(const T &left=T(), const T &right=T())
Definition graph.h:546
void swap(SVector< IndexT, T > &x) noexcept
Definition graph.h:516
SVector(const SVector &other)
Definition graph.h:450
IndexT capacity() const
Definition graph.h:565
SVector & operator=(const SVector &other)
Definition graph.h:451
SVector & operator=(SVector &&other) noexcept
Definition graph.h:471
void reserve(IndexT n)
Definition graph.h:522
IndexT max_size() const
Definition graph.h:567
T * data() const
Definition graph.h:511
const T * begin() const
Definition graph.h:513
const T * end() const
Definition graph.h:514
SVector(SVector &&other) noexcept
Definition graph.h:470
void resize(IndexT n)
Definition graph.h:492
T & operator[](IndexT n)
Definition graph.h:480
const T & operator[](IndexT n) const
Definition graph.h:486
IndexT size() const
Definition graph.h:563
void reserve(IndexT index)
Definition graph.h:415
T & operator[](IndexT index)
Definition graph.h:407
void assign(IndexT index, const T &value)
Definition graph.h:419
const T & operator[](IndexT index) const
Definition graph.h:404
void resize(IndexT index, const T &value)
Definition graph.h:411
IndexT size() const
Definition graph.h:423
#define DEFINE_RANGE_BASED_ARC_ITERATION(c, t)
Definition graph.h:1280
#define DEFINE_STL_ITERATOR_FUNCTIONS(iterator_class_name)
Definition graph.h:1299
dual_gradient T(y - `dual_solution`) class DiagonalTrustRegionProblemFromQp
STL namespace.
constexpr bool IsSigned()
Definition graph.h:396
ArcPropertyIterator< Graph, ArcIterator, typename Graph::ArcIndex, &Graph::OppositeArc > ArcOppositeArcIterator
Definition graph.h:387
ArcPropertyIterator< Graph, ArcIterator, typename Graph::NodeIndex, &Graph::Head > ArcHeadIterator
Definition graph.h:381
void Permute(const IntVector &permutation, Array *array_to_permute)
Definition graph.h:1125
ListGraph Graph
Definition graph.h:2065
bool Next()
trees with all degrees equal to
void * malloc(YYSIZE_T)
void free(void *)
std::decay_t< decltype(*(std::declval< NeighborRangeType >().begin()))> NodeIndex
Definition graph.h:639