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