Google OR-Tools v9.12
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// The main ideas are:
22// - Graph nodes and arcs are represented by integers.
23// - Node or arc annotations (weight, cost, ...) are not part of the graph
24// class, they can be stored outside in one or more arrays and can be easily
25// retrieved using a node or arc as an index.
26//
27// Terminology:
28// - An arc of a graph is directed and going from a tail node to a head node.
29// - Some implementations also store 'reverse' arcs and can be used for
30// undirected graph or flow-like algorithm.
31// - A node or arc index is 'valid' if it represents a node or arc of
32// the graph. The validity ranges are always [0, num_nodes()) for nodes and
33// [0, num_arcs()) for forward arcs. Reverse arcs are elements of
34// [-num_arcs(), 0) and are also considered valid by the implementations that
35// store them.
36//
37// Provided implementations:
38// - ListGraph<> for the simplest api. Also aliased to util::Graph.
39// - StaticGraph<> for performance, but require calling Build(), see below
40// - CompleteGraph<> if you need a fully connected graph
41// - CompleteBipartiteGraph<> if you need a fully connected bipartite graph
42// - ReverseArcListGraph<> to add reverse arcs to ListGraph<>
43// - ReverseArcStaticGraph<> to add reverse arcs to StaticGraph<>
44// - ReverseArcMixedGraph<> for a smaller memory footprint
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// It is however possible to do so for the outgoing arcs and the opposite
80// incoming arcs. It is why the OutgoingOrOppositeIncomingArcs() and
81// OutgoingArcs() iterations are more efficient than the IncomingArcs() one.
82// TODO(b/385094969): Once we no longer use `Next()/Ok()` for iterators, we can
83// get rid of `limit_`, which will make iteration much more efficient.
84//
85// If you know the graph size in advance, this already set the number of nodes,
86// reserve space for the arcs and check in DEBUG mode that you don't go over the
87// bounds:
88// Graph graph(num_nodes, arc_capacity);
89//
90// Storing and using node annotations:
91// vector<bool> is_visited(graph.num_nodes(), false);
92// ...
93// for (int node = 0; node < graph.num_nodes(); ++node) {
94// if (!is_visited[node]) ...
95// }
96//
97// Storing and using arc annotations:
98// vector<int> weights;
99// for (...) {
100// graph.AddArc(tail, head);
101// weights.push_back(arc_weight);
102// }
103// ...
104// for (const int arc : graph.OutgoingArcs(node)) {
105// ... weights[arc] ...;
106// }
107//
108// More efficient version:
109// typedef StaticGraph<> Graph;
110// Graph graph(num_nodes, arc_capacity); // Optional, but help memory usage.
111// vector<int> weights;
112// weights.reserve(arc_capacity); // Optional, but help memory usage.
113// for (...) {
114// graph.AddArc(tail, head);
115// weights.push_back(arc_weight);
116// }
117// ...
118// vector<Graph::ArcIndex> permutation;
119// graph.Build(&permutation); // A static graph must be Build() before usage.
120// Permute(permutation, &weights); // Build() may permute the arc index.
121// ...
122//
123// Encoding an undirected graph: If you don't need arc annotation, then the best
124// is to add two arcs for each edge (one in each direction) to a directed graph.
125// Otherwise you can do the following.
126//
127// typedef ReverseArc... Graph;
128// Graph graph;
129// for (...) {
130// graph.AddArc(tail, head); // or graph.AddArc(head, tail) but not both.
131// edge_annotations.push_back(value);
132// }
133// ...
134// for (const Graph::NodeIndex node : graph.AllNodes()) {
135// for (const Graph::ArcIndex arc :
136// graph.OutgoingOrOppositeIncomingArcs(node)) {
137// destination = graph.Head(arc);
138// annotation = edge_annotations[arc < 0 ? graph.OppositeArc(arc) : arc];
139// }
140// }
141//
142// Note: The graphs are primarily designed to be constructed first and then used
143// because it covers most of the use cases. It is possible to extend the
144// interface with more dynamicity (like removing arcs), but this is not done at
145// this point. Note that a "dynamic" implementation will break some assumptions
146// we make on what node or arc are valid and also on the indices returned by
147// AddArc(). Some arguments for simplifying the interface at the cost of
148// dynamicity are:
149//
150// - It is always possible to construct a static graph from a dynamic one
151// before calling a complex algo.
152// - If you really need a dynamic graph, maybe it is better to compute a graph
153// property incrementally rather than calling an algorithm that starts from
154// scratch each time.
155
156#ifndef UTIL_GRAPH_GRAPH_H_
157#define UTIL_GRAPH_GRAPH_H_
158
159#include <algorithm>
160#include <cstddef>
161#include <cstdint>
162#include <cstdlib>
163#include <cstring>
164#include <iterator>
165#include <limits>
166#include <new>
167#include <type_traits>
168#include <vector>
169
170#include "absl/base/port.h"
171#include "absl/debugging/leak_check.h"
172#include "absl/log/check.h"
173#include "absl/types/span.h"
175#include "ortools/base/logging.h"
176#include "ortools/base/macros.h"
177#include "ortools/base/types.h"
179
180namespace util {
181
182// Forward declaration.
183template <typename T>
184class SVector;
185
186// Base class of all Graphs implemented here. The default value for the graph
187// index types is int32_t since almost all graphs that fit into memory do not
188// need bigger indices.
189//
190// Note: The type can be unsigned, except for the graphs with reverse arcs
191// where the ArcIndexType must be signed, but not necessarily the NodeIndexType.
192template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t,
193 bool HasNegativeReverseArcs = false>
195 public:
196 // Typedef so you can use Graph::NodeIndex and Graph::ArcIndex to be generic
197 // but also to improve the readability of your code. We also recommend
198 // that you define a typedef ... Graph; for readability.
199 typedef NodeIndexType NodeIndex;
200 typedef ArcIndexType ArcIndex;
201 static constexpr bool kHasNegativeReverseArcs = HasNegativeReverseArcs;
202
204 : num_nodes_(0),
206 num_arcs_(0),
207 arc_capacity_(0),
208 const_capacities_(false) {}
209 BaseGraph(const BaseGraph&) = default;
210 BaseGraph& operator=(const BaseGraph&) = default;
211
212 virtual ~BaseGraph() = default;
213
214 // Returns the number of valid nodes in the graph. Prefer using num_nodes():
215 // the size() API is here to make Graph and vector<vector<int>> more alike.
216 NodeIndexType num_nodes() const { return num_nodes_; }
217 NodeIndexType size() const { return num_nodes_; } // Prefer num_nodes().
218
219 // Returns the number of valid arcs in the graph.
220 ArcIndexType num_arcs() const { return num_arcs_; }
221
222 // Allows nice range-based for loop:
223 // for (const NodeIndex node : graph.AllNodes()) { ... }
224 // for (const ArcIndex arc : graph.AllForwardArcs()) { ... }
227
228 // Returns true if the given node is a valid node of the graph.
229 bool IsNodeValid(NodeIndexType node) const {
230 return node >= 0 && node < num_nodes_;
231 }
232
233 // Returns true if the given arc is a valid arc of the graph.
234 // Note that the arc validity range changes for graph with reverse arcs.
235 bool IsArcValid(ArcIndexType arc) const {
236 return (HasNegativeReverseArcs ? -num_arcs_ : 0) <= arc && arc < num_arcs_;
237 }
238
239 // Capacity reserved for future nodes, always >= num_nodes_.
240 NodeIndexType node_capacity() const;
241
242 // Capacity reserved for future arcs, always >= num_arcs_.
243 ArcIndexType arc_capacity() const;
244
245 // Changes the graph capacities. The functions will fail in debug mode if:
246 // - const_capacities_ is true.
247 // - A valid node does not fall into the new node range.
248 // - A valid arc does not fall into the new arc range.
249 // In non-debug mode, const_capacities_ is ignored and nothing will happen
250 // if the new capacity value for the arcs or the nodes is too small.
251 virtual void ReserveNodes(NodeIndexType bound) {
252 DCHECK(!const_capacities_);
253 DCHECK_GE(bound, num_nodes_);
254 if (bound <= num_nodes_) return;
255 node_capacity_ = bound;
256 }
257 virtual void ReserveArcs(ArcIndexType bound) {
258 DCHECK(!const_capacities_);
259 DCHECK_GE(bound, num_arcs_);
260 if (bound <= num_arcs_) return;
261 arc_capacity_ = bound;
262 }
263 void Reserve(NodeIndexType node_capacity, ArcIndexType arc_capacity) {
266 }
267
268 // FreezeCapacities() makes any future attempt to change the graph capacities
269 // crash in DEBUG mode.
271
272 // Constants that will never be a valid node or arc.
273 // They are the maximum possible node and arc capacity.
274 static const NodeIndexType kNilNode;
275 static const ArcIndexType kNilArc;
276
277 protected:
278 // Functions commented when defined because they are implementation details.
279 void ComputeCumulativeSum(std::vector<ArcIndexType>* v);
281 std::vector<ArcIndexType>* start,
282 std::vector<ArcIndexType>* permutation);
283
284 NodeIndexType num_nodes_;
285 NodeIndexType node_capacity_;
286 ArcIndexType num_arcs_;
287 ArcIndexType arc_capacity_;
289};
290
291// Basic graph implementation without reverse arc. This class also serves as a
292// documentation for the generic graph interface (minus the part related to
293// reverse arcs).
294//
295// This implementation uses a linked list and compared to StaticGraph:
296// - Is a bit faster to construct (if the arcs are not ordered by tail).
297// - Does not require calling Build().
298// - Has slower outgoing arc iteration.
299// - Uses more memory: ArcIndexType * node_capacity()
300// + (ArcIndexType + NodeIndexType) * arc_capacity().
301// - Has an efficient Tail() but need an extra NodeIndexType/arc memory for it.
302// - Never changes the initial arc index returned by AddArc().
303//
304// All graphs should be -compatible, but we haven't tested that.
305template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
306class ListGraph : public BaseGraph<NodeIndexType, ArcIndexType, false> {
311 using Base::num_arcs_;
312 using Base::num_nodes_;
313
314 public:
317
318 // Reserve space for the graph at construction and do not allow it to grow
319 // beyond that, see FreezeCapacities(). This constructor also makes any nodes
320 // in [0, num_nodes) valid.
321 ListGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity) {
322 this->Reserve(num_nodes, arc_capacity);
323 this->FreezeCapacities();
324 this->AddNode(num_nodes - 1);
325 }
326
327 // If node is not a valid node, sets num_nodes_ to node + 1 so that the given
328 // node becomes valid. It will fail in DEBUG mode if the capacities are fixed
329 // and the new node is out of range.
330 void AddNode(NodeIndexType node);
331
332 // Adds an arc to the graph and returns its current index which will always
333 // be num_arcs() - 1. It will also automatically call AddNode(tail)
334 // and AddNode(head). It will fail in DEBUG mode if the capacities
335 // are fixed and this cause the graph to grow beyond them.
336 //
337 // Note: Self referencing arcs and duplicate arcs are supported.
338 ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
339
340 // Some graph implementations need to be finalized with Build() before they
341 // can be used. After Build() is called, the arc indices (which had been the
342 // return values of previous AddArc() calls) may change: the new index of
343 // former arc #i will be stored in permutation[i] if #i is smaller than
344 // permutation.size() or will be unchanged otherwise. If you don't care about
345 // these, just call the simple no-output version Build().
346 //
347 // Note that some implementations become immutable after calling Build().
348 void Build() { Build(nullptr); }
349 void Build(std::vector<ArcIndexType>* permutation);
350
351 // Do not use directly.
354
355 // Graph jargon: the "degree" of a node is its number of arcs. The out-degree
356 // is the number of outgoing arcs. The in-degree is the number of incoming
357 // arcs, and is only available for some graph implementations, below.
358 //
359 // ListGraph<>::OutDegree() works in O(degree).
360 ArcIndexType OutDegree(NodeIndexType node) const;
361
362 // Allows to iterate over the forward arcs that verify Tail(arc) == node.
363 // This is meant to be used as:
364 // for (const ArcIndex arc : graph.OutgoingArcs(node)) { ... }
366
367 // Advanced usage. Same as OutgoingArcs(), but allows to restart the iteration
368 // from an already known outgoing arc of the given node.
370 NodeIndexType node, ArcIndexType from) const;
371
372 // This loops over the heads of the OutgoingArcs(node). It is just a more
373 // convenient way to achieve this. Moreover this interface is used by some
374 // graph algorithms.
376
377 // Returns the tail/head of a valid arc.
378 NodeIndexType Tail(ArcIndexType arc) const;
379 NodeIndexType Head(ArcIndexType arc) const;
380
381 void ReserveNodes(NodeIndexType bound) override;
382 void ReserveArcs(ArcIndexType bound) override;
383
384 private:
385 std::vector<ArcIndexType> start_;
386 std::vector<ArcIndexType> next_;
387 std::vector<NodeIndexType> head_;
388 std::vector<NodeIndexType> tail_;
389};
390
391// Most efficient implementation of a graph without reverse arcs:
392// - Build() needs to be called after the arc and node have been added.
393// - The graph is really compact memory wise:
394// ArcIndexType * node_capacity() + 2 * NodeIndexType * arc_capacity(),
395// but when Build() is called it uses a temporary extra space of
396// ArcIndexType * arc_capacity().
397// - The construction is really fast.
398//
399// NOTE(user): if the need arises for very-well compressed graphs, we could
400// shave NodeIndexType * arc_capacity() off the permanent memory requirement
401// with a similar class that doesn't support Tail(), i.e.
402// StaticGraphWithoutTail<>. This almost corresponds to a past implementation
403// of StaticGraph<> @CL 116144340.
404template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
405class StaticGraph : public BaseGraph<NodeIndexType, ArcIndexType, false> {
410 using Base::num_arcs_;
411 using Base::num_nodes_;
412
413 public:
415 StaticGraph() : is_built_(false), arc_in_order_(true), last_tail_seen_(0) {}
416 StaticGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
417 : is_built_(false), arc_in_order_(true), last_tail_seen_(0) {
418 this->Reserve(num_nodes, arc_capacity);
419 this->FreezeCapacities();
420 this->AddNode(num_nodes - 1);
421 }
422
423 // Shortcut to directly create a finalized graph, i.e. Build() is called.
424 template <class ArcContainer> // e.g. vector<pair<int, int>>.
425 static StaticGraph FromArcs(NodeIndexType num_nodes,
426 const ArcContainer& arcs);
427
428 // Do not use directly. See instead the arc iteration functions below.
430
431 NodeIndexType Head(ArcIndexType arc) const;
432 NodeIndexType Tail(ArcIndexType arc) const;
433 ArcIndexType OutDegree(NodeIndexType node) const; // Work in O(1).
436 NodeIndexType node, ArcIndexType from) const;
437
438 // This loops over the heads of the OutgoingArcs(node). It is just a more
439 // convenient way to achieve this. Moreover this interface is used by some
440 // graph algorithms.
441 absl::Span<const NodeIndexType> operator[](NodeIndexType node) const;
442
443 void ReserveNodes(NodeIndexType bound) override;
444 void ReserveArcs(ArcIndexType bound) override;
445 void AddNode(NodeIndexType node);
446 ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
447
448 void Build() { Build(nullptr); }
449 void Build(std::vector<ArcIndexType>* permutation);
450
451 private:
452 ArcIndexType DirectArcLimit(NodeIndexType node) const {
453 DCHECK(is_built_);
454 DCHECK(Base::IsNodeValid(node));
455 return node + 1 < num_nodes_ ? start_[node + 1] : num_arcs_;
456 }
457
458 bool is_built_;
459 bool arc_in_order_;
460 NodeIndexType last_tail_seen_;
461 std::vector<ArcIndexType> start_;
462 std::vector<NodeIndexType> head_;
463 std::vector<NodeIndexType> tail_;
464};
465
466// Extends the ListGraph by also storing the reverse arcs.
467// This class also documents the Graph interface related to reverse arc.
468// - NodeIndexType can be unsigned, but ArcIndexType must be signed.
469// - It has most of the same advantanges and disadvantages as ListGraph.
470// - It takes 2 * ArcIndexType * node_capacity()
471// + 2 * (ArcIndexType + NodeIndexType) * arc_capacity() memory.
472template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
474 : public BaseGraph<NodeIndexType, ArcIndexType, true> {
475 static_assert(std::is_signed_v<ArcIndexType>, "ArcIndexType must be signed");
476
481 using Base::num_arcs_;
482 using Base::num_nodes_;
483
484 public:
487 ReverseArcListGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity) {
488 this->Reserve(num_nodes, arc_capacity);
489 this->FreezeCapacities();
490 this->AddNode(num_nodes - 1);
491 }
492
493 // Returns the opposite arc of a given arc. That is the reverse arc of the
494 // given forward arc or the forward arc of a given reverse arc.
495 ArcIndexType OppositeArc(ArcIndexType arc) const;
496
497 // Do not use directly. See instead the arc iteration functions below.
503
504 // ReverseArcListGraph<>::OutDegree() and ::InDegree() work in O(degree).
505 ArcIndexType OutDegree(NodeIndexType node) const;
506 ArcIndexType InDegree(NodeIndexType node) const;
507
508 // Arc iterations functions over the arcs touching a node (see the top-level
509 // comment for the different types). To be used as follows:
510 // for (const Graph::ArcIndex arc : IterationFunction(node)) { ... }
511 //
512 // The StartingFrom() version are similar, but restart the iteration from a
513 // given arc position (which must be valid in the iteration context), or
514 // `kNilArc`, in which case an empty range is returned.
518 OutgoingOrOppositeIncomingArcs(NodeIndexType node) const;
520 NodeIndexType node) const;
522 NodeIndexType node, ArcIndexType from) const;
524 NodeIndexType node, ArcIndexType from) const;
527 ArcIndexType from) const;
529 NodeIndexType node, ArcIndexType from) const;
530
531 // This loops over the heads of the OutgoingArcs(node). It is just a more
532 // convenient way to achieve this. Moreover this interface is used by some
533 // graph algorithms.
535
536 NodeIndexType Head(ArcIndexType arc) const;
537 NodeIndexType Tail(ArcIndexType arc) const;
538
539 void ReserveNodes(NodeIndexType bound) override;
540 void ReserveArcs(ArcIndexType bound) override;
541 void AddNode(NodeIndexType node);
542 ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
543
544 void Build() { Build(nullptr); }
545 void Build(std::vector<ArcIndexType>* permutation);
546
547 private:
548 std::vector<ArcIndexType> start_;
549 std::vector<ArcIndexType> reverse_start_;
552};
553
554// StaticGraph with reverse arc.
555// - NodeIndexType can be unsigned, but ArcIndexType must be signed.
556// - It has most of the same advantanges and disadvantages as StaticGraph.
557// - It takes 2 * ArcIndexType * node_capacity()
558// + 2 * (ArcIndexType + NodeIndexType) * arc_capacity() memory.
559// - If the ArcIndexPermutation is needed, then an extra ArcIndexType *
560// arc_capacity() is needed for it.
561// - The reverse arcs from a node are sorted by head (so we could add a log()
562// time lookup function).
563template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
565 : public BaseGraph<NodeIndexType, ArcIndexType, true> {
566 static_assert(std::is_signed_v<ArcIndexType>, "ArcIndexType must be signed");
567
572 using Base::num_arcs_;
573 using Base::num_nodes_;
574
575 public:
577 ReverseArcStaticGraph() : is_built_(false) {}
578 ReverseArcStaticGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
579 : is_built_(false) {
580 this->Reserve(num_nodes, arc_capacity);
581 this->FreezeCapacities();
582 this->AddNode(num_nodes - 1);
583 }
584
585 // Deprecated.
586 class OutgoingOrOppositeIncomingArcIterator;
587 class OppositeIncomingArcIterator;
588 class IncomingArcIterator;
589 class OutgoingArcIterator;
590
591 // ReverseArcStaticGraph<>::OutDegree() and ::InDegree() work in O(1).
592 ArcIndexType OutDegree(NodeIndexType node) const;
593 ArcIndexType InDegree(NodeIndexType node) const;
594
598 OutgoingOrOppositeIncomingArcs(NodeIndexType node) const;
600 NodeIndexType node) const;
602 NodeIndexType node, ArcIndexType from) const;
604 NodeIndexType node, ArcIndexType from) const;
607 ArcIndexType from) const;
609 NodeIndexType node, ArcIndexType from) const;
610
611 // This loops over the heads of the OutgoingArcs(node). It is just a more
612 // convenient way to achieve this. Moreover this interface is used by some
613 // graph algorithms.
614 absl::Span<const NodeIndexType> operator[](NodeIndexType node) const;
615
616 ArcIndexType OppositeArc(ArcIndexType arc) const;
617 // TODO(user): support Head() and Tail() before Build(), like StaticGraph<>.
618 NodeIndexType Head(ArcIndexType arc) const;
619 NodeIndexType Tail(ArcIndexType arc) const;
620
621 void ReserveArcs(ArcIndexType bound) override;
622 void AddNode(NodeIndexType node);
623 ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
624
625 void Build() { Build(nullptr); }
626 void Build(std::vector<ArcIndexType>* permutation);
627
628 private:
629 ArcIndexType DirectArcLimit(NodeIndexType node) const {
630 DCHECK(is_built_);
631 DCHECK(Base::IsNodeValid(node));
632 return node + 1 < num_nodes_ ? start_[node + 1] : num_arcs_;
633 }
634 ArcIndexType ReverseArcLimit(NodeIndexType node) const {
635 DCHECK(is_built_);
636 DCHECK(Base::IsNodeValid(node));
637 return node + 1 < num_nodes_ ? reverse_start_[node + 1] : 0;
638 }
639
640 bool is_built_;
641 std::vector<ArcIndexType> start_;
642 std::vector<ArcIndexType> reverse_start_;
643 SVector<NodeIndexType> head_;
644 SVector<ArcIndexType> opposite_;
645};
646
647// This graph is a mix between the ReverseArcListGraph and the
648// ReverseArcStaticGraph. It uses less memory:
649// - It takes 2 * ArcIndexType * node_capacity()
650// + (2 * NodeIndexType + ArcIndexType) * arc_capacity() memory.
651// - If the ArcIndexPermutation is needed, then an extra ArcIndexType *
652// arc_capacity() is needed for it.
653template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
655 : public BaseGraph<NodeIndexType, ArcIndexType, true> {
660 using Base::num_arcs_;
661 using Base::num_nodes_;
662
663 public:
665 ReverseArcMixedGraph() : is_built_(false) {}
666 ReverseArcMixedGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
667 : is_built_(false) {
668 this->Reserve(num_nodes, arc_capacity);
669 this->FreezeCapacities();
670 this->AddNode(num_nodes - 1);
671 }
672
673 // Deprecated.
674 class OutgoingOrOppositeIncomingArcIterator;
675 class OppositeIncomingArcIterator;
676 class IncomingArcIterator;
677 class OutgoingArcIterator;
678
679 ArcIndexType OutDegree(NodeIndexType node) const; // O(1)
680 ArcIndexType InDegree(NodeIndexType node) const; // O(in-degree)
681
685 OutgoingOrOppositeIncomingArcs(NodeIndexType node) const;
687 NodeIndexType node) const;
689 NodeIndexType node, ArcIndexType from) const;
691 NodeIndexType node, ArcIndexType from) const;
694 ArcIndexType from) const;
696 NodeIndexType node, ArcIndexType from) const;
697
698 // This loops over the heads of the OutgoingArcs(node). It is just a more
699 // convenient way to achieve this. Moreover this interface is used by some
700 // graph algorithms.
701 absl::Span<const NodeIndexType> operator[](NodeIndexType node) const;
702
703 ArcIndexType OppositeArc(ArcIndexType arc) const;
704 // TODO(user): support Head() and Tail() before Build(), like StaticGraph<>.
705 NodeIndexType Head(ArcIndexType arc) const;
706 NodeIndexType Tail(ArcIndexType arc) const;
707
708 void ReserveArcs(ArcIndexType bound) override;
709 void AddNode(NodeIndexType node);
710 ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head);
711
712 void Build() { Build(nullptr); }
713 void Build(std::vector<ArcIndexType>* permutation);
714
715 private:
716 ArcIndexType DirectArcLimit(NodeIndexType node) const {
717 DCHECK(is_built_);
718 DCHECK(Base::IsNodeValid(node));
719 return node + 1 < num_nodes_ ? start_[node + 1] : num_arcs_;
720 }
721
722 bool is_built_;
723 std::vector<ArcIndexType> start_;
724 std::vector<ArcIndexType> reverse_start_;
725 std::vector<ArcIndexType> next_;
727};
728
729// Permutes the elements of array_to_permute: element #i will be moved to
730// position permutation[i]. permutation must be either empty (in which case
731// nothing happens), or a permutation of [0, permutation.size()).
732//
733// The algorithm is fast but need extra memory for a copy of the permuted part
734// of array_to_permute.
735//
736// TODO(user): consider slower but more memory efficient implementations that
737// follow the cycles of the permutation and use a bitmap to indicate what has
738// been permuted or to mark the beginning of each cycle.
739
740// Some compiler do not know typeof(), so we have to use this extra function
741// internally.
742template <class IntVector, class Array, class ElementType>
743void PermuteWithExplicitElementType(const IntVector& permutation,
744 Array* array_to_permute,
745 ElementType unused) {
746 std::vector<ElementType> temp(permutation.size());
747 for (size_t i = 0; i < permutation.size(); ++i) {
748 temp[i] = (*array_to_permute)[i];
749 }
750 for (size_t i = 0; i < permutation.size(); ++i) {
751 (*array_to_permute)[permutation[i]] = temp[i];
752 }
753}
754
755template <class IntVector, class Array>
756void Permute(const IntVector& permutation, Array* array_to_permute) {
757 if (permutation.empty()) {
758 return;
759 }
760 PermuteWithExplicitElementType(permutation, array_to_permute,
761 (*array_to_permute)[0]);
762}
763
764// We need a specialization for vector<bool>, because the default code uses
765// (*array_to_permute)[0] as ElementType, which isn't 'bool' in that case.
766template <class IntVector>
767void Permute(const IntVector& permutation,
768 std::vector<bool>* array_to_permute) {
769 if (permutation.empty()) {
770 return;
771 }
772 bool unused = false;
773 PermuteWithExplicitElementType(permutation, array_to_permute, unused);
774}
775
776// A vector-like class where valid indices are in [- size_, size_) and reserved
777// indices for future growth are in [- capacity_, capacity_). It is used to hold
778// arc related information for graphs with reverse arcs.
779// It supports only up to 2^31-1 elements, for compactness. If you ever need
780// more, consider using templates for the size/capacity integer types.
781//
782// Sample usage:
783//
784// SVector<int> v;
785// v.grow(left_value, right_value);
786// v.resize(10);
787// v.clear();
788// v.swap(new_v);
789// std:swap(v[i], v[~i]);
790template <typename T>
791class SVector {
792 public:
793 SVector() : base_(nullptr), size_(0), capacity_(0) {}
794
796
797 // Copy constructor and assignment operator.
798 SVector(const SVector& other) : SVector() { *this = other; }
799 SVector& operator=(const SVector& other) {
800 if (capacity_ < other.size_) {
802 // NOTE(user): Alternatively, our capacity could inherit from the other
803 // vector's capacity, which can be (much) greater than its size.
804 capacity_ = other.size_;
805 base_ = Allocate(capacity_);
806 CHECK(base_ != nullptr);
807 base_ += capacity_;
808 } else { // capacity_ >= other.size
809 clear();
810 }
811 // Perform the actual copy of the payload.
812 size_ = other.size_;
813 CopyInternal(other, std::is_integral<T>());
814 return *this;
815 }
816
817 // Move constructor and move assignment operator.
818 SVector(SVector&& other) noexcept : SVector() { swap(other); }
819 SVector& operator=(SVector&& other) noexcept {
820 // NOTE(user): We could just swap() and let the other's destruction take
821 // care of the clean-up, but it is probably less bug-prone to perform the
822 // destruction immediately.
824 swap(other);
825 return *this;
826 }
827
828 T& operator[](int n) {
829 DCHECK_LT(n, size_);
830 DCHECK_GE(n, -size_);
831 return base_[n];
832 }
833
834 const T& operator[](int n) const {
835 DCHECK_LT(n, size_);
836 DCHECK_GE(n, -size_);
837 return base_[n];
838 }
839
840 void resize(int n) {
841 reserve(n);
842 for (int i = -n; i < -size_; ++i) {
843 new (base_ + i) T();
844 }
845 for (int i = size_; i < n; ++i) {
846 new (base_ + i) T();
847 }
848 for (int i = -size_; i < -n; ++i) {
849 base_[i].~T();
850 }
851 for (int i = n; i < size_; ++i) {
852 base_[i].~T();
853 }
854 size_ = n;
855 }
856
857 void clear() { resize(0); }
858
859 T* data() const { return base_; }
860
861 void swap(SVector<T>& x) noexcept {
862 std::swap(base_, x.base_);
863 std::swap(size_, x.size_);
864 std::swap(capacity_, x.capacity_);
865 }
866
867 void reserve(int n) {
868 DCHECK_GE(n, 0);
869 DCHECK_LE(n, max_size());
870 if (n > capacity_) {
871 const int new_capacity = std::min(n, max_size());
872 T* new_storage = Allocate(new_capacity);
873 CHECK(new_storage != nullptr);
874 T* new_base = new_storage + new_capacity;
875 // TODO(user): in C++17 we could use std::uninitialized_move instead
876 // of this loop.
877 for (int i = -size_; i < size_; ++i) {
878 new (new_base + i) T(std::move(base_[i]));
879 }
880 int saved_size = size_;
882 size_ = saved_size;
883 base_ = new_base;
884 capacity_ = new_capacity;
885 }
886 }
887
888 // NOTE(user): This doesn't currently support movable-only objects, but we
889 // could fix that.
890 void grow(const T& left = T(), const T& right = T()) {
891 if (size_ == capacity_) {
892 // We have to copy the elements because they are allowed to be element of
893 // *this.
894 T left_copy(left); // NOLINT
895 T right_copy(right); // NOLINT
896 reserve(NewCapacity(1));
897 new (base_ + size_) T(right_copy);
898 new (base_ - size_ - 1) T(left_copy);
899 ++size_;
900 } else {
901 new (base_ + size_) T(right);
902 new (base_ - size_ - 1) T(left);
903 ++size_;
904 }
905 }
906
907 int size() const { return size_; }
908
909 int capacity() const { return capacity_; }
910
911 int max_size() const { return std::numeric_limits<int>::max(); }
912
914 if (base_ == nullptr) return;
915 clear();
916 if (capacity_ > 0) {
917 free(base_ - capacity_);
918 }
919 capacity_ = 0;
920 base_ = nullptr;
921 }
922
923 private:
924 // Copies other.base_ to base_ in this SVector. Avoids iteration by copying
925 // entire memory range in a single shot for the most commonly used integral
926 // types which should be safe to copy in this way.
927 void CopyInternal(const SVector& other, std::true_type) {
928 std::memcpy(base_ - other.size_, other.base_ - other.size_,
929 2LL * other.size_ * sizeof(T));
930 }
931
932 // Copies other.base_ to base_ in this SVector. Safe for all types as it uses
933 // constructor for each entry.
934 void CopyInternal(const SVector& other, std::false_type) {
935 for (int i = -size_; i < size_; ++i) {
936 new (base_ + i) T(other.base_[i]);
937 }
938 }
939
940 T* Allocate(int capacity) const {
941 return absl::IgnoreLeak(
942 static_cast<T*>(malloc(2LL * capacity * sizeof(T))));
943 }
944
945 int NewCapacity(int delta) {
946 // TODO(user): check validity.
947 double candidate = 1.3 * static_cast<double>(capacity_);
948 if (candidate > static_cast<double>(max_size())) {
949 candidate = static_cast<double>(max_size());
950 }
951 int new_capacity = static_cast<int>(candidate);
952 if (new_capacity > capacity_ + delta) {
953 return new_capacity;
954 }
955 return capacity_ + delta;
956 }
957
958 T* base_; // Pointer to the element of index 0.
959 int size_; // Valid index are [- size_, size_).
960 int capacity_; // Reserved index are [- capacity_, capacity_).
961};
962
963// BaseGraph implementation ----------------------------------------------------
964
965template <typename NodeIndexType, typename ArcIndexType,
966 bool HasNegativeReverseArcs>
968 NodeIndexType, ArcIndexType, HasNegativeReverseArcs>::AllNodes() const {
970}
971
972template <typename NodeIndexType, typename ArcIndexType,
973 bool HasNegativeReverseArcs>
979
980template <typename NodeIndexType, typename ArcIndexType,
981 bool HasNegativeReverseArcs>
982const NodeIndexType
984 std::numeric_limits<NodeIndexType>::max();
985
986template <typename NodeIndexType, typename ArcIndexType,
987 bool HasNegativeReverseArcs>
988const ArcIndexType
990 std::numeric_limits<ArcIndexType>::max();
991
992template <typename NodeIndexType, typename ArcIndexType,
993 bool HasNegativeReverseArcs>
994NodeIndexType BaseGraph<NodeIndexType, ArcIndexType,
995 HasNegativeReverseArcs>::node_capacity() const {
996 // TODO(user): Is it needed? remove completely? return the real capacities
997 // at the cost of having a different implementation for each graphs?
999}
1000
1001template <typename NodeIndexType, typename ArcIndexType,
1002 bool HasNegativeReverseArcs>
1003ArcIndexType BaseGraph<NodeIndexType, ArcIndexType,
1004 HasNegativeReverseArcs>::arc_capacity() const {
1005 // TODO(user): Same questions as the ones in node_capacity().
1007}
1008
1009template <typename NodeIndexType, typename ArcIndexType,
1010 bool HasNegativeReverseArcs>
1011void BaseGraph<NodeIndexType, ArcIndexType,
1012 HasNegativeReverseArcs>::FreezeCapacities() {
1013 // TODO(user): Only define this in debug mode at the cost of having a lot
1014 // of ifndef NDEBUG all over the place? remove the function completely ?
1015 const_capacities_ = true;
1018}
1019
1020// Computes the cumulative sum of the entry in v. We only use it with
1021// in/out degree distribution, hence the Check() at the end.
1022template <typename NodeIndexType, typename ArcIndexType,
1023 bool HasNegativeReverseArcs>
1025 ComputeCumulativeSum(std::vector<ArcIndexType>* v) {
1026 ArcIndexType sum = 0;
1027 for (int i = 0; i < num_nodes_; ++i) {
1028 ArcIndexType temp = (*v)[i];
1029 (*v)[i] = sum;
1030 sum += temp;
1031 }
1032 DCHECK(sum == num_arcs_);
1033}
1034
1035// Given the tail of arc #i in (*head)[i] and the head of arc #i in (*head)[~i]
1036// - Reorder the arc by increasing tail.
1037// - Put the head of the new arc #i in (*head)[i].
1038// - Put in start[i] the index of the first arc with tail >= i.
1039// - Update "permutation" to reflect the change, unless it is NULL.
1040template <typename NodeIndexType, typename ArcIndexType,
1041 bool HasNegativeReverseArcs>
1044 std::vector<ArcIndexType>* start,
1045 std::vector<ArcIndexType>* permutation) {
1046 // Computes the outgoing degree of each nodes and check if we need to permute
1047 // something or not. Note that the tails are currently stored in the positive
1048 // range of the SVector head.
1049 start->assign(num_nodes_, 0);
1050 int last_tail_seen = 0;
1051 bool permutation_needed = false;
1052 for (int i = 0; i < num_arcs_; ++i) {
1053 NodeIndexType tail = (*head)[i];
1054 if (!permutation_needed) {
1055 permutation_needed = tail < last_tail_seen;
1056 last_tail_seen = tail;
1057 }
1058 (*start)[tail]++;
1059 }
1060 ComputeCumulativeSum(start);
1061
1062 // Abort early if we do not need the permutation: we only need to put the
1063 // heads in the positive range.
1064 if (!permutation_needed) {
1065 for (int i = 0; i < num_arcs_; ++i) {
1066 (*head)[i] = (*head)[~i];
1067 }
1068 if (permutation != nullptr) {
1069 permutation->clear();
1070 }
1071 return;
1072 }
1073
1074 // Computes the forward arc permutation.
1075 // Note that this temporarily alters the start vector.
1076 std::vector<ArcIndexType> perm(num_arcs_);
1077 for (int i = 0; i < num_arcs_; ++i) {
1078 perm[i] = (*start)[(*head)[i]]++;
1079 }
1080
1081 // Restore in (*start)[i] the index of the first arc with tail >= i.
1082 for (int i = num_nodes_ - 1; i > 0; --i) {
1083 (*start)[i] = (*start)[i - 1];
1084 }
1085 (*start)[0] = 0;
1086
1087 // Permutes the head into their final position in head.
1088 // We do not need the tails anymore at this point.
1089 for (int i = 0; i < num_arcs_; ++i) {
1090 (*head)[perm[i]] = (*head)[~i];
1091 }
1092 if (permutation != nullptr) {
1093 permutation->swap(perm);
1094 }
1095}
1096
1097// ---------------------------------------------------------------------------
1098// Macros to wrap old style iteration into the new range-based for loop style.
1099// ---------------------------------------------------------------------------
1100
1101// The parameters are:
1102// - c: the class name.
1103// - t: the iteration type (Outgoing, Incoming, OutgoingOrOppositeIncoming
1104// or OppositeIncoming).
1105// - e: the "end" ArcIndexType.
1106#define DEFINE_RANGE_BASED_ARC_ITERATION(c, t) \
1107 template <typename NodeIndexType, typename ArcIndexType> \
1108 BeginEndWrapper<typename c<NodeIndexType, ArcIndexType>::t##ArcIterator> \
1109 c<NodeIndexType, ArcIndexType>::t##Arcs(NodeIndexType node) const { \
1110 return BeginEndWrapper<t##ArcIterator>( \
1111 t##ArcIterator(*this, node), \
1112 t##ArcIterator(*this, node, Base::kNilArc)); \
1113 } \
1114 template <typename NodeIndexType, typename ArcIndexType> \
1115 BeginEndWrapper<typename c<NodeIndexType, ArcIndexType>::t##ArcIterator> \
1116 c<NodeIndexType, ArcIndexType>::t##ArcsStartingFrom( \
1117 NodeIndexType node, ArcIndexType from) const { \
1118 return BeginEndWrapper<t##ArcIterator>( \
1119 t##ArcIterator(*this, node, from), \
1120 t##ArcIterator(*this, node, Base::kNilArc)); \
1121 }
1122
1123// Adapt our old iteration style to support range-based for loops. Add typedefs
1124// required by std::iterator_traits.
1125#define DEFINE_STL_ITERATOR_FUNCTIONS(iterator_class_name) \
1126 using iterator_category = std::input_iterator_tag; \
1127 using difference_type = ptrdiff_t; \
1128 using pointer = const ArcIndexType*; \
1129 using value_type = ArcIndexType; \
1130 using reference = value_type; \
1131 bool operator!=(const iterator_class_name& other) const { \
1132 return this->index_ != other.index_; \
1133 } \
1134 bool operator==(const iterator_class_name& other) const { \
1135 return this->index_ == other.index_; \
1136 } \
1137 ArcIndexType operator*() const { return this->Index(); } \
1138 void operator++() { this->Next(); }
1139
1140// ListGraph implementation ----------------------------------------------------
1141
1142DEFINE_RANGE_BASED_ARC_ITERATION(ListGraph, Outgoing);
1143
1144template <typename NodeIndexType, typename ArcIndexType>
1150 OutgoingHeadIterator(*this, node, Base::kNilArc));
1151}
1152
1153template <typename NodeIndexType, typename ArcIndexType>
1155 ArcIndexType arc) const {
1156 DCHECK(IsArcValid(arc));
1157 return tail_[arc];
1158}
1159
1160template <typename NodeIndexType, typename ArcIndexType>
1162 ArcIndexType arc) const {
1163 DCHECK(IsArcValid(arc));
1164 return head_[arc];
1165}
1166
1167template <typename NodeIndexType, typename ArcIndexType>
1169 NodeIndexType node) const {
1170 ArcIndexType degree(0);
1171 for (auto arc ABSL_ATTRIBUTE_UNUSED : OutgoingArcs(node)) ++degree;
1172 return degree;
1173}
1174
1175template <typename NodeIndexType, typename ArcIndexType>
1176void ListGraph<NodeIndexType, ArcIndexType>::AddNode(NodeIndexType node) {
1177 if (node < num_nodes_) return;
1178 DCHECK(!const_capacities_ || node < node_capacity_);
1179 num_nodes_ = node + 1;
1180 start_.resize(num_nodes_, Base::kNilArc);
1181}
1182
1183template <typename NodeIndexType, typename ArcIndexType>
1185 NodeIndexType tail, NodeIndexType head) {
1186 DCHECK_GE(tail, 0);
1187 DCHECK_GE(head, 0);
1188 AddNode(tail > head ? tail : head);
1189 head_.push_back(head);
1190 tail_.push_back(tail);
1191 next_.push_back(start_[tail]);
1192 start_[tail] = num_arcs_;
1193 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
1194 return num_arcs_++;
1195}
1196
1197template <typename NodeIndexType, typename ArcIndexType>
1199 Base::ReserveNodes(bound);
1200 if (bound <= num_nodes_) return;
1201 start_.reserve(bound);
1202}
1203
1204template <typename NodeIndexType, typename ArcIndexType>
1206 Base::ReserveArcs(bound);
1207 if (bound <= num_arcs_) return;
1208 head_.reserve(bound);
1209 tail_.reserve(bound);
1210 next_.reserve(bound);
1211}
1212
1213template <typename NodeIndexType, typename ArcIndexType>
1215 std::vector<ArcIndexType>* permutation) {
1216 if (permutation != nullptr) {
1217 permutation->clear();
1218 }
1219}
1220
1221template <typename NodeIndexType, typename ArcIndexType>
1222class ListGraph<NodeIndexType, ArcIndexType>::OutgoingArcIterator {
1223 public:
1224 OutgoingArcIterator(const ListGraph& graph, NodeIndexType node)
1225 : graph_(graph), index_(graph.start_[node]) {
1226 DCHECK(graph.IsNodeValid(node));
1227 }
1228 OutgoingArcIterator(const ListGraph& graph, NodeIndexType node,
1229 ArcIndexType arc)
1230 : graph_(graph), index_(arc) {
1231 DCHECK(graph.IsNodeValid(node));
1232 DCHECK(arc == Base::kNilArc || graph.Tail(arc) == node);
1233 }
1234 bool Ok() const { return index_ != Base::kNilArc; }
1235 ArcIndexType Index() const { return index_; }
1236 void Next() {
1237 DCHECK(Ok());
1238 index_ = graph_.next_[index_];
1239 }
1240
1242
1243 private:
1244 const ListGraph& graph_;
1245 ArcIndexType index_;
1246};
1247
1248template <typename NodeIndexType, typename ArcIndexType>
1249class ListGraph<NodeIndexType, ArcIndexType>::OutgoingHeadIterator {
1250 public:
1251 using iterator_category = std::input_iterator_tag;
1252 using difference_type = ptrdiff_t;
1253 using pointer = const NodeIndexType*;
1254 using reference = const NodeIndexType&;
1255 using value_type = NodeIndexType;
1257 OutgoingHeadIterator(const ListGraph& graph, NodeIndexType node)
1258 : graph_(graph), index_(graph.start_[node]) {
1259 DCHECK(graph.IsNodeValid(node));
1260 }
1261 OutgoingHeadIterator(const ListGraph& graph, NodeIndexType node,
1262 ArcIndexType arc)
1263 : graph_(graph), index_(arc) {
1264 DCHECK(graph.IsNodeValid(node));
1265 DCHECK(arc == Base::kNilArc || graph.Tail(arc) == node);
1266 }
1267 bool Ok() const { return index_ != Base::kNilArc; }
1268 NodeIndexType Index() const { return graph_.Head(index_); }
1269 void Next() {
1270 DCHECK(Ok());
1271 index_ = graph_.next_[index_];
1272 }
1273
1274 bool operator!=(
1275 const typename ListGraph<
1276 NodeIndexType, ArcIndexType>::OutgoingHeadIterator& other) const {
1277 return index_ != other.index_;
1278 }
1279 NodeIndexType operator*() const { return Index(); }
1280 void operator++() { Next(); }
1282 private:
1283 const ListGraph& graph_;
1284 ArcIndexType index_;
1285};
1286
1287// StaticGraph implementation --------------------------------------------------
1288
1289template <typename NodeIndexType, typename ArcIndexType>
1290template <class ArcContainer>
1293 const ArcContainer& arcs) {
1294 StaticGraph g(num_nodes, arcs.size());
1295 for (const auto& [from, to] : arcs) g.AddArc(from, to);
1296 g.Build();
1297 return g;
1298}
1299
1301
1302template <typename NodeIndexType, typename ArcIndexType>
1303absl::Span<const NodeIndexType>
1305 return absl::Span<const NodeIndexType>(head_.data() + start_[node],
1306 DirectArcLimit(node) - start_[node]);
1307}
1308
1309template <typename NodeIndexType, typename ArcIndexType>
1311 NodeIndexType node) const {
1312 return DirectArcLimit(node) - start_[node];
1313}
1314
1315template <typename NodeIndexType, typename ArcIndexType>
1317 NodeIndexType bound) {
1319 if (bound <= num_nodes_) return;
1320 start_.reserve(bound);
1321}
1322
1323template <typename NodeIndexType, typename ArcIndexType>
1325 Base::ReserveArcs(bound);
1326 if (bound <= num_arcs_) return;
1327 head_.reserve(bound);
1328 tail_.reserve(bound);
1329}
1330
1331template <typename NodeIndexType, typename ArcIndexType>
1333 if (node < num_nodes_) return;
1334 DCHECK(!const_capacities_ || node < node_capacity_) << node;
1335 num_nodes_ = node + 1;
1336 start_.resize(num_nodes_, 0);
1337}
1338
1339template <typename NodeIndexType, typename ArcIndexType>
1341 NodeIndexType tail, NodeIndexType head) {
1342 DCHECK_GE(tail, 0);
1343 DCHECK_GE(head, 0);
1344 DCHECK(!is_built_);
1345 AddNode(tail > head ? tail : head);
1346 if (arc_in_order_) {
1347 if (tail >= last_tail_seen_) {
1348 start_[tail]++;
1349 last_tail_seen_ = tail;
1350 } else {
1351 arc_in_order_ = false;
1352 }
1353 }
1354 tail_.push_back(tail);
1355 head_.push_back(head);
1356 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
1357 return num_arcs_++;
1358}
1359
1360template <typename NodeIndexType, typename ArcIndexType>
1362 ArcIndexType arc) const {
1363 DCHECK(IsArcValid(arc));
1364 return tail_[arc];
1365}
1366
1367template <typename NodeIndexType, typename ArcIndexType>
1369 ArcIndexType arc) const {
1370 DCHECK(IsArcValid(arc));
1371 return head_[arc];
1372}
1373
1374// Implementation details: A reader may be surprised that we do many passes
1375// into the data where things could be done in one pass. For instance, during
1376// construction, we store the edges first, and then do a second pass at the
1377// end to compute the degree distribution.
1378//
1379// This is because it is a lot more efficient cache-wise to do it this way.
1380// This was determined by various experiments, but can also be understood:
1381// - during repetitive call to AddArc() a client usually accesses various
1382// areas of memory, and there is no reason to pollute the cache with
1383// possibly random access to degree[i].
1384// - When the degrees are needed, we compute them in one go, maximizing the
1385// chance of cache hit during the computation.
1386template <typename NodeIndexType, typename ArcIndexType>
1388 std::vector<ArcIndexType>* permutation) {
1389 DCHECK(!is_built_);
1390 if (is_built_) return;
1391 is_built_ = true;
1392 node_capacity_ = num_nodes_;
1393 arc_capacity_ = num_arcs_;
1394 this->FreezeCapacities();
1395
1396 // If Arc are in order, start_ already contains the degree distribution.
1397 if (arc_in_order_) {
1398 if (permutation != nullptr) {
1399 permutation->clear();
1400 }
1401 this->ComputeCumulativeSum(&start_);
1402 return;
1403 }
1404
1405 // Computes outgoing degree of each nodes. We have to clear start_, since
1406 // at least the first arc was processed with arc_in_order_ == true.
1407 start_.assign(num_nodes_, 0);
1408 for (int i = 0; i < num_arcs_; ++i) {
1409 start_[tail_[i]]++;
1410 }
1411 this->ComputeCumulativeSum(&start_);
1412
1413 // Computes the forward arc permutation.
1414 // Note that this temporarily alters the start_ vector.
1415 std::vector<ArcIndexType> perm(num_arcs_);
1416 for (int i = 0; i < num_arcs_; ++i) {
1417 perm[i] = start_[tail_[i]]++;
1418 }
1419
1420 // We use "tail_" (which now contains rubbish) to permute "head_" faster.
1421 CHECK_EQ(tail_.size(), static_cast<size_t>(num_arcs_));
1422 tail_.swap(head_);
1423 for (int i = 0; i < num_arcs_; ++i) {
1424 head_[perm[i]] = tail_[i];
1425 }
1426
1427 if (permutation != nullptr) {
1428 permutation->swap(perm);
1429 }
1430
1431 // Restore in start_[i] the index of the first arc with tail >= i.
1432 for (int i = num_nodes_ - 1; i > 0; --i) {
1433 start_[i] = start_[i - 1];
1434 }
1435 start_[0] = 0;
1436
1437 // Recompute the correct tail_ vector
1438 for (const NodeIndexType node : Base::AllNodes()) {
1439 for (const ArcIndexType arc : OutgoingArcs(node)) {
1440 tail_[arc] = node;
1441 }
1442 }
1443}
1444
1445template <typename NodeIndexType, typename ArcIndexType>
1446class StaticGraph<NodeIndexType, ArcIndexType>::OutgoingArcIterator {
1447 public:
1450 OutgoingArcIterator(const StaticGraph& graph, NodeIndexType node)
1451 : index_(graph.start_[node]), limit_(graph.DirectArcLimit(node)) {}
1452 OutgoingArcIterator(const StaticGraph& graph, NodeIndexType node,
1453 ArcIndexType arc)
1454 : limit_(graph.DirectArcLimit(node)) {
1455 index_ = arc == Base::kNilArc ? limit_ : arc;
1456 DCHECK_GE(arc, graph.start_[node]);
1457 }
1458
1459 bool Ok() const { return index_ != limit_; }
1460 ArcIndexType Index() const { return index_; }
1461 void Next() {
1462 DCHECK(Ok());
1463 index_++;
1464 }
1465
1466 // Note(user): we lose a bit by returning a BeginEndWrapper<> on top of
1467 // this iterator rather than a simple IntegerRange<> on the arc indices.
1468 // On my computer: around 420M arcs/sec instead of 440M arcs/sec.
1469 //
1470 // However, it is slightly more consistent to do it this way, and we don't
1471 // have two different codes depending on the way a client iterates on the
1472 // arcs.
1474
1475 private:
1476 ArcIndexType index_;
1477 ArcIndexType limit_;
1478};
1479
1480// ReverseArcListGraph implementation ------------------------------------------
1481
1485 OutgoingOrOppositeIncoming);
1487
1488template <typename NodeIndexType, typename ArcIndexType>
1490 NodeIndexType, ArcIndexType>::OutgoingHeadIterator>
1492 NodeIndexType node) const {
1494 OutgoingHeadIterator(*this, node),
1495 OutgoingHeadIterator(*this, node, Base::kNilArc));
1496}
1497
1498template <typename NodeIndexType, typename ArcIndexType>
1500 NodeIndexType node) const {
1501 ArcIndexType degree(0);
1502 for (auto arc ABSL_ATTRIBUTE_UNUSED : OutgoingArcs(node)) ++degree;
1503 return degree;
1504}
1505
1506template <typename NodeIndexType, typename ArcIndexType>
1508 NodeIndexType node) const {
1509 ArcIndexType degree(0);
1510 for (auto arc ABSL_ATTRIBUTE_UNUSED : OppositeIncomingArcs(node)) ++degree;
1511 return degree;
1512}
1513
1514template <typename NodeIndexType, typename ArcIndexType>
1516 ArcIndexType arc) const {
1517 DCHECK(IsArcValid(arc));
1518 return ~arc;
1519}
1520
1521template <typename NodeIndexType, typename ArcIndexType>
1523 ArcIndexType arc) const {
1524 DCHECK(IsArcValid(arc));
1525 return head_[arc];
1526}
1527
1528template <typename NodeIndexType, typename ArcIndexType>
1530 ArcIndexType arc) const {
1531 return head_[OppositeArc(arc)];
1532}
1533
1534template <typename NodeIndexType, typename ArcIndexType>
1536 NodeIndexType bound) {
1538 if (bound <= num_nodes_) return;
1539 start_.reserve(bound);
1540 reverse_start_.reserve(bound);
1541}
1542
1543template <typename NodeIndexType, typename ArcIndexType>
1545 ArcIndexType bound) {
1547 if (bound <= num_arcs_) return;
1548 head_.reserve(bound);
1549 next_.reserve(bound);
1550}
1551
1552template <typename NodeIndexType, typename ArcIndexType>
1554 NodeIndexType node) {
1555 if (node < num_nodes_) return;
1556 DCHECK(!const_capacities_ || node < node_capacity_);
1557 num_nodes_ = node + 1;
1558 start_.resize(num_nodes_, Base::kNilArc);
1559 reverse_start_.resize(num_nodes_, Base::kNilArc);
1560}
1561
1562template <typename NodeIndexType, typename ArcIndexType>
1564 NodeIndexType tail, NodeIndexType head) {
1565 DCHECK_GE(tail, 0);
1566 DCHECK_GE(head, 0);
1567 AddNode(tail > head ? tail : head);
1568 head_.grow(tail, head);
1569 next_.grow(reverse_start_[head], start_[tail]);
1570 start_[tail] = num_arcs_;
1571 reverse_start_[head] = ~num_arcs_;
1572 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
1573 return num_arcs_++;
1574}
1575
1576template <typename NodeIndexType, typename ArcIndexType>
1578 std::vector<ArcIndexType>* permutation) {
1579 if (permutation != nullptr) {
1580 permutation->clear();
1581 }
1582}
1583
1584template <typename NodeIndexType, typename ArcIndexType>
1585class ReverseArcListGraph<NodeIndexType, ArcIndexType>::OutgoingArcIterator {
1586 public:
1588 : graph_(graph), index_(graph.start_[node]) {
1589 DCHECK(graph.IsNodeValid(node));
1590 }
1591 OutgoingArcIterator(const ReverseArcListGraph& graph, NodeIndexType node,
1592 ArcIndexType arc)
1593 : graph_(graph), index_(arc) {
1594 DCHECK(graph.IsNodeValid(node));
1595 DCHECK(arc == Base::kNilArc || arc >= 0);
1596 DCHECK(arc == Base::kNilArc || graph.Tail(arc) == node);
1597 }
1598 bool Ok() const { return index_ != Base::kNilArc; }
1599 ArcIndexType Index() const { return index_; }
1600 void Next() {
1601 DCHECK(Ok());
1602 index_ = graph_.next_[index_];
1603 }
1604
1606
1607 private:
1608 const ReverseArcListGraph& graph_;
1609 ArcIndexType index_;
1610};
1611
1612template <typename NodeIndexType, typename ArcIndexType>
1613class ReverseArcListGraph<NodeIndexType,
1614 ArcIndexType>::OppositeIncomingArcIterator {
1615 public:
1617 NodeIndexType node)
1618 : next_(graph.next_.data()), index_(graph.reverse_start_[node]) {
1619 DCHECK(graph.IsNodeValid(node));
1620 }
1622 NodeIndexType node, ArcIndexType arc)
1623 : next_(graph.next_.data()), index_(arc) {
1624 DCHECK(graph.IsNodeValid(node));
1625 DCHECK(arc == Base::kNilArc || arc < 0);
1626 DCHECK(arc == Base::kNilArc || graph.Tail(arc) == node);
1627 }
1628
1629 bool Ok() const { return index_ != Base::kNilArc; }
1630 ArcIndexType Index() const { return index_; }
1631 void Next() {
1632 DCHECK(Ok());
1637
1638 protected:
1639 const ArcIndexType* next_;
1640 ArcIndexType index_;
1643template <typename NodeIndexType, typename ArcIndexType>
1644class ReverseArcListGraph<NodeIndexType, ArcIndexType>::IncomingArcIterator
1646 public:
1647 IncomingArcIterator(const ReverseArcListGraph& graph, NodeIndexType node)
1648 : OppositeIncomingArcIterator(graph, node), graph_(graph) {}
1650 ArcIndexType arc)
1652 graph, node,
1653 arc == Base::kNilArc ? Base::kNilArc : graph.OppositeArc(arc)),
1654 graph_(graph) {}
1655
1656 // We overwrite OppositeIncomingArcIterator::Index() here.
1657 ArcIndexType Index() const {
1658 return this->index_ == Base::kNilArc ? Base::kNilArc
1659 : graph_.OppositeArc(this->index_);
1660 }
1661
1663
1664 private:
1665 const ReverseArcListGraph& graph_;
1666};
1667
1668template <typename NodeIndexType, typename ArcIndexType>
1669class ReverseArcListGraph<NodeIndexType,
1671 public:
1673 NodeIndexType node)
1674 : graph_(graph), index_(graph.reverse_start_[node]), node_(node) {
1675 DCHECK(graph.IsNodeValid(node));
1676 if (index_ == Base::kNilArc) index_ = graph.start_[node];
1677 }
1679 NodeIndexType node, ArcIndexType arc)
1680 : graph_(graph), index_(arc), node_(node) {
1681 DCHECK(graph.IsNodeValid(node));
1682 DCHECK(arc == Base::kNilArc || graph.Tail(arc) == node);
1683 }
1684
1685 bool Ok() const { return index_ != Base::kNilArc; }
1686 ArcIndexType Index() const { return index_; }
1687 void Next() {
1688 DCHECK(Ok());
1689 if (index_ < 0) {
1690 index_ = graph_.next_[index_];
1691 if (index_ == Base::kNilArc) {
1692 index_ = graph_.start_[node_];
1693 }
1694 } else {
1695 index_ = graph_.next_[index_];
1696 }
1697 }
1698
1699 DEFINE_STL_ITERATOR_FUNCTIONS(OutgoingOrOppositeIncomingArcIterator);
1700
1701 private:
1702 const ReverseArcListGraph& graph_;
1703 ArcIndexType index_;
1704 const NodeIndexType node_;
1705};
1706
1707template <typename NodeIndexType, typename ArcIndexType>
1708class ReverseArcListGraph<NodeIndexType, ArcIndexType>::OutgoingHeadIterator {
1709 public:
1711 : graph_(&graph), index_(graph.start_[node]) {
1712 DCHECK(graph.IsNodeValid(node));
1713 }
1714 OutgoingHeadIterator(const ReverseArcListGraph& graph, NodeIndexType node,
1715 ArcIndexType arc)
1716 : graph_(&graph), index_(arc) {
1717 DCHECK(graph.IsNodeValid(node));
1718 DCHECK(arc == Base::kNilArc || arc >= 0);
1719 DCHECK(arc == Base::kNilArc || graph.Tail(arc) == node);
1720 }
1721 bool Ok() const { return index_ != Base::kNilArc; }
1722 ArcIndexType Index() const { return graph_->Head(index_); }
1723 void Next() {
1724 DCHECK(Ok());
1725 index_ = graph_->next_[index_];
1726 }
1727
1729
1730 private:
1731 const ReverseArcListGraph* graph_;
1732 ArcIndexType index_;
1733};
1734
1735// ReverseArcStaticGraph implementation ----------------------------------------
1736
1740 OutgoingOrOppositeIncoming);
1742
1743template <typename NodeIndexType, typename ArcIndexType>
1745 NodeIndexType node) const {
1746 return DirectArcLimit(node) - start_[node];
1747}
1748
1749template <typename NodeIndexType, typename ArcIndexType>
1751 NodeIndexType node) const {
1752 return ReverseArcLimit(node) - reverse_start_[node];
1753}
1754
1755template <typename NodeIndexType, typename ArcIndexType>
1756absl::Span<const NodeIndexType>
1758 NodeIndexType node) const {
1759 return absl::Span<const NodeIndexType>(head_.data() + start_[node],
1760 DirectArcLimit(node) - start_[node]);
1761}
1762
1763template <typename NodeIndexType, typename ArcIndexType>
1765 ArcIndexType arc) const {
1766 DCHECK(is_built_);
1767 DCHECK(IsArcValid(arc));
1768 return opposite_[arc];
1769}
1770
1771template <typename NodeIndexType, typename ArcIndexType>
1773 ArcIndexType arc) const {
1774 DCHECK(is_built_);
1775 DCHECK(IsArcValid(arc));
1776 return head_[arc];
1777}
1778
1779template <typename NodeIndexType, typename ArcIndexType>
1781 ArcIndexType arc) const {
1782 DCHECK(is_built_);
1783 return head_[OppositeArc(arc)];
1784}
1785
1786template <typename NodeIndexType, typename ArcIndexType>
1788 ArcIndexType bound) {
1790 if (bound <= num_arcs_) return;
1791 head_.reserve(bound);
1792}
1793
1794template <typename NodeIndexType, typename ArcIndexType>
1796 NodeIndexType node) {
1797 if (node < num_nodes_) return;
1798 DCHECK(!const_capacities_ || node < node_capacity_);
1799 num_nodes_ = node + 1;
1800}
1801
1802template <typename NodeIndexType, typename ArcIndexType>
1804 NodeIndexType tail, NodeIndexType head) {
1805 DCHECK_GE(tail, 0);
1806 DCHECK_GE(head, 0);
1807 AddNode(tail > head ? tail : head);
1808
1809 // We inverse head and tail here because it is more convenient this way
1810 // during build time, see Build().
1811 head_.grow(head, tail);
1812 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
1813 return num_arcs_++;
1814}
1815
1816template <typename NodeIndexType, typename ArcIndexType>
1818 std::vector<ArcIndexType>* permutation) {
1819 DCHECK(!is_built_);
1820 if (is_built_) return;
1821 is_built_ = true;
1822 node_capacity_ = num_nodes_;
1823 arc_capacity_ = num_arcs_;
1824 this->FreezeCapacities();
1825 this->BuildStartAndForwardHead(&head_, &start_, permutation);
1826
1827 // Computes incoming degree of each nodes.
1828 reverse_start_.assign(num_nodes_, 0);
1829 for (int i = 0; i < num_arcs_; ++i) {
1830 reverse_start_[head_[i]]++;
1831 }
1832 this->ComputeCumulativeSum(&reverse_start_);
1833
1834 // Computes the reverse arcs of the forward arcs.
1835 // Note that this sort the reverse arcs with the same tail by head.
1836 opposite_.reserve(num_arcs_);
1837 for (int i = 0; i < num_arcs_; ++i) {
1838 // TODO(user): the 0 is wasted here, but minor optimisation.
1839 opposite_.grow(0, reverse_start_[head_[i]]++ - num_arcs_);
1840 }
1841
1842 // Computes in reverse_start_ the start index of the reverse arcs.
1843 for (int i = num_nodes_ - 1; i > 0; --i) {
1844 reverse_start_[i] = reverse_start_[i - 1] - num_arcs_;
1845 }
1846 if (num_nodes_ != 0) {
1847 reverse_start_[0] = -num_arcs_;
1848 }
1849
1850 // Fill reverse arc information.
1851 for (int i = 0; i < num_arcs_; ++i) {
1852 opposite_[opposite_[i]] = i;
1853 }
1854 for (const NodeIndexType node : Base::AllNodes()) {
1855 for (const ArcIndexType arc : OutgoingArcs(node)) {
1856 head_[opposite_[arc]] = node;
1857 }
1858 }
1859}
1860
1861template <typename NodeIndexType, typename ArcIndexType>
1862class ReverseArcStaticGraph<NodeIndexType, ArcIndexType>::OutgoingArcIterator {
1863 public:
1865 : index_(graph.start_[node]), limit_(graph.DirectArcLimit(node)) {}
1867 ArcIndexType arc)
1868 : limit_(graph.DirectArcLimit(node)) {
1869 index_ = arc == Base::kNilArc ? limit_ : arc;
1870 DCHECK_GE(arc, graph.start_[node]);
1871 }
1872
1873 bool Ok() const { return index_ != limit_; }
1874 ArcIndexType Index() const { return index_; }
1875 void Next() {
1876 DCHECK(Ok());
1877 index_++;
1878 }
1879
1880 // TODO(user): we lose a bit by returning a BeginEndWrapper<> on top of this
1881 // iterator rather than a simple IntegerRange on the arc indices.
1883
1884 private:
1885 ArcIndexType index_;
1886 const ArcIndexType limit_;
1887};
1888
1889template <typename NodeIndexType, typename ArcIndexType>
1890class ReverseArcStaticGraph<NodeIndexType,
1891 ArcIndexType>::OppositeIncomingArcIterator {
1892 public:
1894 NodeIndexType node)
1895 : limit_(graph.ReverseArcLimit(node)),
1896 index_(graph.reverse_start_[node]) {
1897 DCHECK(graph.IsNodeValid(node));
1898 DCHECK_LE(index_, limit_);
1899 }
1901 NodeIndexType node, ArcIndexType arc)
1902 : limit_(graph.ReverseArcLimit(node)) {
1903 index_ = arc == Base::kNilArc ? limit_ : arc;
1904 DCHECK(graph.IsNodeValid(node));
1905 DCHECK_GE(index_, graph.reverse_start_[node]);
1906 DCHECK_LE(index_, limit_);
1907 }
1908
1909 bool Ok() const { return index_ != limit_; }
1910 ArcIndexType Index() const { return index_; }
1911 void Next() {
1912 DCHECK(Ok());
1917
1918 protected:
1919 const ArcIndexType limit_;
1920 ArcIndexType index_;
1923template <typename NodeIndexType, typename ArcIndexType>
1924class ReverseArcStaticGraph<NodeIndexType, ArcIndexType>::IncomingArcIterator
1926 public:
1927 IncomingArcIterator(const ReverseArcStaticGraph& graph, NodeIndexType node)
1928 : OppositeIncomingArcIterator(graph, node), graph_(graph) {}
1930 ArcIndexType arc)
1932 arc == Base::kNilArc
1933 ? Base::kNilArc
1934 : (arc == graph.ReverseArcLimit(node)
1935 ? graph.ReverseArcLimit(node)
1936 : graph.OppositeArc(arc))),
1937 graph_(graph) {}
1938
1939 ArcIndexType Index() const {
1940 return this->index_ == this->limit_ ? this->limit_
1941 : graph_.OppositeArc(this->index_);
1942 }
1943
1945
1946 private:
1947 const ReverseArcStaticGraph& graph_;
1948};
1949
1950template <typename NodeIndexType, typename ArcIndexType>
1952 NodeIndexType, ArcIndexType>::OutgoingOrOppositeIncomingArcIterator {
1953 public:
1955 NodeIndexType node)
1956 : index_(graph.reverse_start_[node]),
1957 first_limit_(graph.ReverseArcLimit(node)),
1958 next_start_(graph.start_[node]),
1959 limit_(graph.DirectArcLimit(node)) {
1960 if (index_ == first_limit_) index_ = next_start_;
1961 DCHECK(graph.IsNodeValid(node));
1962 DCHECK((index_ < first_limit_) || (index_ >= next_start_));
1963 }
1965 NodeIndexType node, ArcIndexType arc)
1966 : first_limit_(graph.ReverseArcLimit(node)),
1967 next_start_(graph.start_[node]),
1968 limit_(graph.DirectArcLimit(node)) {
1969 index_ = arc == Base::kNilArc ? limit_ : arc;
1970 DCHECK(graph.IsNodeValid(node));
1971 DCHECK((index_ >= graph.reverse_start_[node] && index_ < first_limit_) ||
1972 (index_ >= next_start_));
1973 }
1974
1975 ArcIndexType Index() const { return index_; }
1976 bool Ok() const { return index_ != limit_; }
1977 void Next() {
1978 DCHECK(Ok());
1979 index_++;
1980 if (index_ == first_limit_) {
1981 index_ = next_start_;
1982 }
1983 }
1984
1985 DEFINE_STL_ITERATOR_FUNCTIONS(OutgoingOrOppositeIncomingArcIterator);
1986
1987 private:
1988 ArcIndexType index_;
1989 const ArcIndexType first_limit_;
1990 const ArcIndexType next_start_;
1991 const ArcIndexType limit_;
1992};
1993
1994// ReverseArcMixedGraph implementation -----------------------------------------
1995
1999 OutgoingOrOppositeIncoming);
2001
2002template <typename NodeIndexType, typename ArcIndexType>
2004 NodeIndexType node) const {
2005 return DirectArcLimit(node) - start_[node];
2006}
2007
2008template <typename NodeIndexType, typename ArcIndexType>
2010 NodeIndexType node) const {
2011 ArcIndexType degree(0);
2012 for (auto arc ABSL_ATTRIBUTE_UNUSED : OppositeIncomingArcs(node)) ++degree;
2013 return degree;
2014}
2015
2016template <typename NodeIndexType, typename ArcIndexType>
2017absl::Span<const NodeIndexType>
2019 NodeIndexType node) const {
2020 return absl::Span<const NodeIndexType>(head_.data() + start_[node],
2021 DirectArcLimit(node) - start_[node]);
2022}
2023
2024template <typename NodeIndexType, typename ArcIndexType>
2026 ArcIndexType arc) const {
2027 DCHECK(IsArcValid(arc));
2028 return ~arc;
2029}
2030
2031template <typename NodeIndexType, typename ArcIndexType>
2033 ArcIndexType arc) const {
2034 DCHECK(is_built_);
2035 DCHECK(IsArcValid(arc));
2036 return head_[arc];
2037}
2038
2039template <typename NodeIndexType, typename ArcIndexType>
2041 ArcIndexType arc) const {
2042 DCHECK(is_built_);
2043 return head_[OppositeArc(arc)];
2044}
2045
2046template <typename NodeIndexType, typename ArcIndexType>
2048 ArcIndexType bound) {
2050 if (bound <= num_arcs_) return;
2051 head_.reserve(bound);
2052}
2053
2054template <typename NodeIndexType, typename ArcIndexType>
2056 NodeIndexType node) {
2057 if (node < num_nodes_) return;
2058 DCHECK(!const_capacities_ || node < node_capacity_);
2059 num_nodes_ = node + 1;
2060}
2061
2062template <typename NodeIndexType, typename ArcIndexType>
2064 NodeIndexType tail, NodeIndexType head) {
2065 DCHECK_GE(tail, 0);
2066 DCHECK_GE(head, 0);
2067 AddNode(tail > head ? tail : head);
2068
2069 // We inverse head and tail here because it is more convenient this way
2070 // during build time, see Build().
2071 head_.grow(head, tail);
2072 DCHECK(!const_capacities_ || num_arcs_ < arc_capacity_);
2073 return num_arcs_++;
2074}
2075
2076template <typename NodeIndexType, typename ArcIndexType>
2078 std::vector<ArcIndexType>* permutation) {
2079 DCHECK(!is_built_);
2080 if (is_built_) return;
2081 is_built_ = true;
2082 node_capacity_ = num_nodes_;
2083 arc_capacity_ = num_arcs_;
2084 this->FreezeCapacities();
2085 this->BuildStartAndForwardHead(&head_, &start_, permutation);
2086
2087 // Fill tails.
2088 for (const NodeIndexType node : Base::AllNodes()) {
2089 for (const ArcIndexType arc : OutgoingArcs(node)) {
2090 head_[~arc] = node;
2091 }
2092 }
2093
2094 // Fill information for iterating over reverse arcs.
2095 reverse_start_.assign(num_nodes_, Base::kNilArc);
2096 next_.reserve(num_arcs_);
2097 for (const ArcIndexType arc : Base::AllForwardArcs()) {
2098 next_.push_back(reverse_start_[Head(arc)]);
2099 reverse_start_[Head(arc)] = -next_.size();
2100 }
2101}
2102
2103template <typename NodeIndexType, typename ArcIndexType>
2104class ReverseArcMixedGraph<NodeIndexType, ArcIndexType>::OutgoingArcIterator {
2105 public:
2109 : index_(graph.start_[node]), limit_(graph.DirectArcLimit(node)) {}
2111 ArcIndexType arc)
2112 : limit_(graph.DirectArcLimit(node)) {
2113 index_ = arc == Base::kNilArc ? limit_ : arc;
2114 DCHECK_GE(arc, graph.start_[node]);
2115 }
2116
2117 bool Ok() const { return index_ != limit_; }
2118 ArcIndexType Index() const { return index_; }
2119 void Next() {
2120 DCHECK(Ok());
2121 index_++;
2122 }
2123
2124 // TODO(user): we lose a bit by returning a BeginEndWrapper<> on top of this
2125 // iterator rather than a simple IntegerRange on the arc indices.
2127
2128 private:
2129 ArcIndexType index_;
2130 ArcIndexType limit_;
2131};
2132
2133template <typename NodeIndexType, typename ArcIndexType>
2134class ReverseArcMixedGraph<NodeIndexType,
2135 ArcIndexType>::OppositeIncomingArcIterator {
2136 public:
2138 NodeIndexType node)
2140 DCHECK(graph.is_built_);
2141 DCHECK(graph.IsNodeValid(node));
2142 index_ = graph.reverse_start_[node];
2143 }
2145 NodeIndexType node, ArcIndexType arc)
2146 : graph_(&graph), index_(arc) {
2147 DCHECK(graph.is_built_);
2148 DCHECK(graph.IsNodeValid(node));
2149 DCHECK(arc == Base::kNilArc || arc < 0);
2150 DCHECK(arc == Base::kNilArc || graph.Tail(arc) == node);
2151 }
2152 bool Ok() const { return index_ != Base::kNilArc; }
2153 ArcIndexType Index() const { return index_; }
2154 void Next() {
2155 DCHECK(Ok());
2160
2161 protected:
2163 ArcIndexType index_;
2166template <typename NodeIndexType, typename ArcIndexType>
2167class ReverseArcMixedGraph<NodeIndexType, ArcIndexType>::IncomingArcIterator
2169 public:
2170 IncomingArcIterator(const ReverseArcMixedGraph& graph, NodeIndexType node)
2173 ArcIndexType arc)
2175 graph, node,
2176 arc == Base::kNilArc ? Base::kNilArc : graph.OppositeArc(arc)) {}
2177 ArcIndexType Index() const {
2178 return this->index_ == Base::kNilArc
2180 : this->graph_->OppositeArc(this->index_);
2181 }
2182
2184};
2186template <typename NodeIndexType, typename ArcIndexType>
2188 NodeIndexType, ArcIndexType>::OutgoingOrOppositeIncomingArcIterator {
2189 public:
2191 NodeIndexType node)
2192 : graph_(&graph) {
2193 limit_ = graph.DirectArcLimit(node); // also DCHECKs node and is_built_.
2194 index_ = graph.reverse_start_[node];
2195 restart_ = graph.start_[node];
2196 if (index_ == Base::kNilArc) {
2197 index_ = restart_;
2198 }
2199 }
2201 NodeIndexType node, ArcIndexType arc)
2202 : graph_(&graph) {
2203 limit_ = graph.DirectArcLimit(node);
2204 index_ = arc == Base::kNilArc ? limit_ : arc;
2205 restart_ = graph.start_[node];
2206 DCHECK(arc == Base::kNilArc || arc == limit_ || graph.Tail(arc) == node);
2207 }
2208 bool Ok() const { return index_ != limit_; }
2209 ArcIndexType Index() const { return index_; }
2210 void Next() {
2211 DCHECK(Ok());
2212 if (index_ < 0) {
2213 index_ = graph_->next_[graph_->OppositeArc(index_)];
2214 if (index_ == Base::kNilArc) {
2215 index_ = restart_;
2216 }
2217 } else {
2218 index_++;
2219 }
2220 }
2221
2222 DEFINE_STL_ITERATOR_FUNCTIONS(OutgoingOrOppositeIncomingArcIterator);
2223
2224 private:
2225 const ReverseArcMixedGraph* graph_;
2226 ArcIndexType index_;
2227 ArcIndexType restart_;
2228 ArcIndexType limit_;
2229};
2230
2231// CompleteGraph implementation ------------------------------------------------
2232// Nodes and arcs are implicit and not stored.
2233
2234template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
2235class CompleteGraph : public BaseGraph<NodeIndexType, ArcIndexType, false> {
2240 using Base::num_arcs_;
2241 using Base::num_nodes_;
2242
2243 public:
2244 // Builds a complete graph with num_nodes nodes.
2245 explicit CompleteGraph(NodeIndexType num_nodes)
2246 : // If there are 0 or 1 nodes, the divisor is arbitrary. We pick 2 as 0
2247 // and 1 are not supported by `ConstantDivisor`.
2248 divisor_(num_nodes > 1 ? num_nodes : 2) {
2249 this->Reserve(num_nodes, num_nodes * num_nodes);
2250 this->FreezeCapacities();
2251 num_nodes_ = num_nodes;
2252 num_arcs_ = num_nodes * num_nodes;
2253 }
2254
2255 NodeIndexType Head(ArcIndexType arc) const;
2256 NodeIndexType Tail(ArcIndexType arc) const;
2257 ArcIndexType OutDegree(NodeIndexType node) const;
2258 IntegerRange<ArcIndexType> OutgoingArcs(NodeIndexType node) const;
2260 ArcIndexType from) const;
2261 IntegerRange<NodeIndexType> operator[](NodeIndexType node) const;
2262
2263 const ::util::math::ConstantDivisor<std::make_unsigned_t<ArcIndexType>>
2264 divisor_;
2265};
2267template <typename NodeIndexType, typename ArcIndexType>
2269 ArcIndexType arc) const {
2270 DCHECK(this->IsArcValid(arc));
2271 return arc % divisor_;
2272}
2273
2274template <typename NodeIndexType, typename ArcIndexType>
2276 ArcIndexType arc) const {
2277 DCHECK(this->IsArcValid(arc));
2278 return arc / divisor_;
2279}
2280
2281template <typename NodeIndexType, typename ArcIndexType>
2283 NodeIndexType node) const {
2284 return num_nodes_;
2285}
2286
2287template <typename NodeIndexType, typename ArcIndexType>
2290 NodeIndexType node) const {
2291 DCHECK_LT(node, num_nodes_);
2293 static_cast<ArcIndexType>(num_nodes_) * node,
2294 static_cast<ArcIndexType>(num_nodes_) * (node + 1));
2295}
2296
2297template <typename NodeIndexType, typename ArcIndexType>
2300 NodeIndexType node, ArcIndexType from) const {
2301 DCHECK_LT(node, num_nodes_);
2303 from, static_cast<ArcIndexType>(num_nodes_) * (node + 1));
2304}
2305
2306template <typename NodeIndexType, typename ArcIndexType>
2309 NodeIndexType node) const {
2310 DCHECK_LT(node, num_nodes_);
2311 return IntegerRange<NodeIndexType>(0, num_nodes_);
2312}
2313
2314// CompleteBipartiteGraph implementation ---------------------------------------
2315// Nodes and arcs are implicit and not stored.
2316
2317template <typename NodeIndexType = int32_t, typename ArcIndexType = int32_t>
2319 : public BaseGraph<NodeIndexType, ArcIndexType, false> {
2321 using Base::arc_capacity_;
2324 using Base::num_arcs_;
2325 using Base::num_nodes_;
2326
2327 public:
2328 // Builds a complete bipartite graph from a set of left nodes to a set of
2329 // right nodes.
2330 // Indices of left nodes of the bipartite graph range from 0 to left_nodes-1;
2331 // indices of right nodes range from left_nodes to left_nodes+right_nodes-1.
2332 CompleteBipartiteGraph(NodeIndexType left_nodes, NodeIndexType right_nodes)
2333 : left_nodes_(left_nodes),
2334 right_nodes_(right_nodes),
2335 // If there are no right nodes, the divisor is arbitrary. We pick 2 as
2336 // 0 and 1 are not supported by `ConstantDivisor`. We handle the case
2337 // where `right_nodes` is 1 explicitly when dividing.
2338 divisor_(right_nodes > 1 ? right_nodes : 2) {
2339 this->Reserve(left_nodes + right_nodes, left_nodes * right_nodes);
2340 this->FreezeCapacities();
2341 num_nodes_ = left_nodes + right_nodes;
2342 num_arcs_ = left_nodes * right_nodes;
2343 }
2344
2345 // Returns the arc index for the arc from `left` to `right`, where `left` is
2346 // in `[0, left_nodes)` and `right` is in
2347 // `[left_nodes, left_nodes + right_nodes)`.
2348 ArcIndexType GetArc(NodeIndexType left_node, NodeIndexType right_node) const;
2349
2350 NodeIndexType Head(ArcIndexType arc) const;
2351 NodeIndexType Tail(ArcIndexType arc) const;
2352 ArcIndexType OutDegree(NodeIndexType node) const;
2353 IntegerRange<ArcIndexType> OutgoingArcs(NodeIndexType node) const;
2355 ArcIndexType from) const;
2356 IntegerRange<NodeIndexType> operator[](NodeIndexType node) const;
2357
2358 // Deprecated interface.
2359 class OutgoingArcIterator {
2360 public:
2362 : index_(static_cast<ArcIndexType>(graph.right_nodes_) * node),
2363 limit_(node >= graph.left_nodes_
2364 ? index_
2365 : static_cast<ArcIndexType>(graph.right_nodes_) *
2366 (node + 1)) {}
2367
2368 bool Ok() const { return index_ < limit_; }
2369 ArcIndexType Index() const { return index_; }
2370 void Next() { index_++; }
2372 private:
2373 ArcIndexType index_;
2374 const ArcIndexType limit_;
2375 };
2376
2377 private:
2378 const NodeIndexType left_nodes_;
2379 const NodeIndexType right_nodes_;
2380 // Note: only valid if `right_nodes_ > 1`.
2381 const ::util::math::ConstantDivisor<std::make_unsigned_t<ArcIndexType>>
2382 divisor_;
2383};
2384
2385template <typename NodeIndexType, typename ArcIndexType>
2387 NodeIndexType left_node, NodeIndexType right_node) const {
2388 DCHECK_LT(left_node, left_nodes_);
2389 DCHECK_GE(right_node, left_nodes_);
2390 DCHECK_LT(right_node, num_nodes_);
2391 return left_node * static_cast<ArcIndexType>(right_nodes_) +
2392 (right_node - left_nodes_);
2393}
2394
2395template <typename NodeIndexType, typename ArcIndexType>
2397 ArcIndexType arc) const {
2398 DCHECK(this->IsArcValid(arc));
2399 // See comment on `divisor_` in the constructor.
2400 return right_nodes_ > 1 ? left_nodes_ + arc % divisor_ : left_nodes_;
2401}
2402
2403template <typename NodeIndexType, typename ArcIndexType>
2405 ArcIndexType arc) const {
2406 DCHECK(this->IsArcValid(arc));
2407 // See comment on `divisor_` in the constructor.
2408 return right_nodes_ > 1 ? arc / divisor_ : arc;
2409}
2410
2411template <typename NodeIndexType, typename ArcIndexType>
2413 NodeIndexType node) const {
2414 return (node < left_nodes_) ? right_nodes_ : 0;
2415}
2416
2417template <typename NodeIndexType, typename ArcIndexType>
2420 NodeIndexType node) const {
2421 if (node < left_nodes_) {
2423 static_cast<ArcIndexType>(right_nodes_) * node,
2424 static_cast<ArcIndexType>(right_nodes_) * (node + 1));
2425 } else {
2426 return IntegerRange<ArcIndexType>(0, 0);
2427 }
2428}
2429
2430template <typename NodeIndexType, typename ArcIndexType>
2433 NodeIndexType node, ArcIndexType from) const {
2434 if (node < left_nodes_) {
2436 from, static_cast<ArcIndexType>(right_nodes_) * (node + 1));
2437 } else {
2438 return IntegerRange<ArcIndexType>(0, 0);
2439 }
2440}
2441
2442template <typename NodeIndexType, typename ArcIndexType>
2445 NodeIndexType node) const {
2446 if (node < left_nodes_) {
2447 return IntegerRange<NodeIndexType>(left_nodes_, left_nodes_ + right_nodes_);
2448 } else {
2449 return IntegerRange<NodeIndexType>(0, 0);
2450 }
2451}
2452
2453// Defining the simplest Graph interface as Graph for convenience.
2454typedef ListGraph<> Graph;
2455
2456} // namespace util
2457
2458#undef DEFINE_RANGE_BASED_ARC_ITERATION
2459#undef DEFINE_STL_ITERATOR_FUNCTIONS
2460
2461#endif // UTIL_GRAPH_GRAPH_H_
const ::util::math::ConstantDivisor< std::make_unsigned_t< int64_t > > divisor_
Definition graph.h:2266
void ComputeCumulativeSum(std::vector< ArcIndexType > *v)
Functions commented when defined because they are implementation details.
Definition graph.h:1025
void FreezeCapacities()
Definition graph.h:1012
NodeIndexType num_nodes() const
Definition graph.h:216
bool IsArcValid(ArcIndexType arc) const
Definition graph.h:235
NodeIndexType node_capacity() const
Capacity reserved for future nodes, always >= num_nodes_.
Definition graph.h:995
ArcIndexType arc_capacity() const
Capacity reserved for future arcs, always >= num_arcs_.
Definition graph.h:1004
IntegerRange< ArcIndex > AllForwardArcs() const
Definition graph.h:975
BaseGraph(const BaseGraph &)=default
virtual void ReserveNodes(NodeIndexType bound)
Definition graph.h:251
NodeIndexType size() const
Definition graph.h:217
virtual void ReserveArcs(ArcIndexType bound)
Definition graph.h:257
void Reserve(NodeIndexType node_capacity, ArcIndexType arc_capacity)
Definition graph.h:263
BaseGraph & operator=(const BaseGraph &)=default
ArcIndexType num_arcs() const
Returns the number of valid arcs in the graph.
Definition graph.h:220
IntegerRange< NodeIndex > AllNodes() const
BaseGraph implementation -------------------------------------------------—.
Definition graph.h:968
void BuildStartAndForwardHead(SVector< NodeIndexType > *head, std::vector< ArcIndexType > *start, std::vector< ArcIndexType > *permutation)
Definition graph.h:1043
virtual ~BaseGraph()=default
bool IsNodeValid(NodeIndexType node) const
Returns true if the given node is a valid node of the graph.
Definition graph.h:229
OutgoingArcIterator(const CompleteBipartiteGraph &graph, NodeIndexType node)
Definition graph.h:2363
ArcIndexType GetArc(NodeIndexType left_node, NodeIndexType right_node) const
Definition graph.h:2388
NodeIndexType Tail(ArcIndexType arc) const
Definition graph.h:2406
CompleteBipartiteGraph(NodeIndexType left_nodes, NodeIndexType right_nodes)
Definition graph.h:2334
IntegerRange< ArcIndexType > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
Definition graph.h:2434
IntegerRange< ArcIndexType > OutgoingArcs(NodeIndexType node) const
Definition graph.h:2421
ArcIndexType OutDegree(NodeIndexType node) const
Definition graph.h:2414
NodeIndexType Head(ArcIndexType arc) const
Definition graph.h:2398
IntegerRange< NodeIndexType > operator[](NodeIndexType node) const
Definition graph.h:2446
const ::util::math::ConstantDivisor< std::make_unsigned_t< ArcIndexType > > divisor_
Definition graph.h:2266
ArcIndexType OutDegree(NodeIndexType node) const
Definition graph.h:2284
IntegerRange< ArcIndexType > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
Definition graph.h:2301
IntegerRange< ArcIndexType > OutgoingArcs(NodeIndexType node) const
Definition graph.h:2291
NodeIndexType Tail(ArcIndexType arc) const
Definition graph.h:2277
IntegerRange< NodeIndexType > operator[](NodeIndexType node) const
Definition graph.h:2310
CompleteGraph(NodeIndexType num_nodes)
Builds a complete graph with num_nodes nodes.
Definition graph.h:2247
NodeIndexType Head(ArcIndexType arc) const
Definition graph.h:2270
OutgoingArcIterator(const ListGraph &graph, NodeIndexType node)
Definition graph.h:1226
OutgoingHeadIterator(const ListGraph &graph, NodeIndexType node)
Definition graph.h:1259
std::input_iterator_tag iterator_category
Definition graph.h:1253
const NodeIndexType * pointer
Definition graph.h:1255
const NodeIndexType & reference
Definition graph.h:1256
BeginEndWrapper< OutgoingHeadIterator > operator[](NodeIndexType node) const
Definition graph.h:1149
ListGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
Definition graph.h:321
bool IsArcValid(ArcIndexType arc) const
Definition graph.h:235
void Build(std::vector< ArcIndexType > *permutation)
Definition graph.h:1216
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
void AddNode(NodeIndexType node)
Definition graph.h:1178
void Build()
Definition graph.h:348
BeginEndWrapper< OutgoingArcIterator > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
NodeIndexType Tail(ArcIndexType arc) const
Returns the tail/head of a valid arc.
Definition graph.h:1156
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Definition graph.h:1186
ArcIndexType OutDegree(NodeIndexType node) const
Definition graph.h:1170
NodeIndexType Head(ArcIndexType arc) const
Definition graph.h:1163
void ReserveNodes(NodeIndexType bound) override
Definition graph.h:1200
void ReserveArcs(ArcIndexType bound) override
Definition graph.h:1207
IncomingArcIterator(const ReverseArcListGraph &graph, NodeIndexType node)
Definition graph.h:1649
OppositeIncomingArcIterator(const ReverseArcListGraph &graph, NodeIndexType node)
Definition graph.h:1618
OutgoingArcIterator(const ReverseArcListGraph &graph, NodeIndexType node)
Definition graph.h:1589
OutgoingHeadIterator(const ReverseArcListGraph &graph, NodeIndexType node)
Definition graph.h:1712
OutgoingOrOppositeIncomingArcIterator(const ReverseArcListGraph &graph, NodeIndexType node)
Definition graph.h:1674
BeginEndWrapper< IncomingArcIterator > IncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
bool IsArcValid(ArcIndexType arc) const
Definition graph.h:235
BeginEndWrapper< OutgoingHeadIterator > operator[](NodeIndexType node) const
Definition graph.h:1493
NodeIndexType Head(ArcIndexType arc) const
Definition graph.h:1524
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcs(NodeIndexType node) const
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcs(NodeIndexType node) const
void Build(std::vector< ArcIndexType > *permutation)
Definition graph.h:1579
void ReserveArcs(ArcIndexType bound) override
Definition graph.h:1546
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Definition graph.h:1565
ReverseArcListGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
Definition graph.h:487
BeginEndWrapper< OutgoingArcIterator > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
ArcIndexType OppositeArc(ArcIndexType arc) const
Definition graph.h:1517
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
void AddNode(NodeIndexType node)
Definition graph.h:1555
BeginEndWrapper< IncomingArcIterator > IncomingArcs(NodeIndexType node) const
NodeIndexType Tail(ArcIndexType arc) const
Definition graph.h:1531
ArcIndexType OutDegree(NodeIndexType node) const
ReverseArcListGraph<>::OutDegree() and InDegree() work in O(degree).
Definition graph.h:1501
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
void ReserveNodes(NodeIndexType bound) override
Definition graph.h:1537
ArcIndexType InDegree(NodeIndexType node) const
Definition graph.h:1509
IncomingArcIterator(const ReverseArcMixedGraph &graph, NodeIndexType node)
Definition graph.h:2172
OppositeIncomingArcIterator(const ReverseArcMixedGraph &graph, NodeIndexType node)
Definition graph.h:2139
OutgoingArcIterator(const ReverseArcMixedGraph &graph, NodeIndexType node)
Definition graph.h:2110
OutgoingArcIterator(const OutgoingArcIterator &)=default
OutgoingOrOppositeIncomingArcIterator(const ReverseArcMixedGraph &graph, NodeIndexType node)
Definition graph.h:2192
bool IsArcValid(ArcIndexType arc) const
Definition graph.h:235
NodeIndexType Tail(ArcIndexType arc) const
Definition graph.h:2042
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Definition graph.h:2065
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
NodeIndexType Head(ArcIndexType arc) const
Definition graph.h:2034
ReverseArcMixedGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
Definition graph.h:666
ArcIndexType OppositeArc(ArcIndexType arc) const
Definition graph.h:2027
BeginEndWrapper< IncomingArcIterator > IncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
void AddNode(NodeIndexType node)
Definition graph.h:2057
BeginEndWrapper< IncomingArcIterator > IncomingArcs(NodeIndexType node) const
void Build(std::vector< ArcIndexType > *permutation)
Definition graph.h:2079
absl::Span< const NodeIndexType > operator[](NodeIndexType node) const
Definition graph.h:2020
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
void ReserveArcs(ArcIndexType bound) override
Definition graph.h:2049
ArcIndexType OutDegree(NodeIndexType node) const
Definition graph.h:2005
ArcIndexType InDegree(NodeIndexType node) const
Definition graph.h:2011
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcs(NodeIndexType node) const
BeginEndWrapper< OutgoingArcIterator > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcs(NodeIndexType node) const
IncomingArcIterator(const ReverseArcStaticGraph &graph, NodeIndexType node)
Definition graph.h:1929
OppositeIncomingArcIterator(const ReverseArcStaticGraph &graph, NodeIndexType node)
Definition graph.h:1895
OutgoingArcIterator(const ReverseArcStaticGraph &graph, NodeIndexType node)
Definition graph.h:1866
OutgoingOrOppositeIncomingArcIterator(const ReverseArcStaticGraph &graph, NodeIndexType node)
Definition graph.h:1956
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Definition graph.h:1805
NodeIndexType Tail(ArcIndexType arc) const
Definition graph.h:1782
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
bool IsArcValid(ArcIndexType arc) const
Definition graph.h:235
BeginEndWrapper< IncomingArcIterator > IncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
BeginEndWrapper< OutgoingOrOppositeIncomingArcIterator > OutgoingOrOppositeIncomingArcs(NodeIndexType node) const
ArcIndexType OppositeArc(ArcIndexType arc) const
Definition graph.h:1766
BeginEndWrapper< IncomingArcIterator > IncomingArcs(NodeIndexType node) const
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcs(NodeIndexType node) const
void Build(std::vector< ArcIndexType > *permutation)
Definition graph.h:1819
absl::Span< const NodeIndexType > operator[](NodeIndexType node) const
Definition graph.h:1759
NodeIndexType Head(ArcIndexType arc) const
Definition graph.h:1774
BeginEndWrapper< OutgoingArcIterator > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
void ReserveArcs(ArcIndexType bound) override
Definition graph.h:1789
ArcIndexType OutDegree(NodeIndexType node) const
ReverseArcStaticGraph<>::OutDegree() and InDegree() work in O(1).
Definition graph.h:1746
ArcIndexType InDegree(NodeIndexType node) const
Definition graph.h:1752
ReverseArcStaticGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
Definition graph.h:578
BeginEndWrapper< OppositeIncomingArcIterator > OppositeIncomingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
void AddNode(NodeIndexType node)
Definition graph.h:1797
Forward declaration.
Definition graph.h:791
const T & operator[](int n) const
Definition graph.h:834
void clear()
Definition graph.h:857
SVector & operator=(SVector &&other) noexcept
Definition graph.h:819
T & operator[](int n)
Definition graph.h:828
void reserve(int n)
Definition graph.h:867
void clear_and_dealloc()
Definition graph.h:913
SVector(const SVector &other)
Copy constructor and assignment operator.
Definition graph.h:798
int capacity() const
Definition graph.h:909
T * data() const
Definition graph.h:859
SVector(SVector &&other) noexcept
Move constructor and move assignment operator.
Definition graph.h:818
void swap(SVector< T > &x) noexcept
Definition graph.h:861
void grow(const T &left=T(), const T &right=T())
Definition graph.h:890
int max_size() const
Definition graph.h:911
SVector & operator=(const SVector &other)
Definition graph.h:799
void resize(int n)
Definition graph.h:840
int size() const
Definition graph.h:907
OutgoingArcIterator(const StaticGraph &graph, NodeIndexType node)
Definition graph.h:1452
OutgoingArcIterator(const OutgoingArcIterator &)=default
absl::Span< const NodeIndexType > operator[](NodeIndexType node) const
Definition graph.h:1306
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Definition graph.h:1342
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:235
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
ArcIndexType OutDegree(NodeIndexType node) const
Definition graph.h:1312
NodeIndexType Tail(ArcIndexType arc) const
Definition graph.h:1363
void ReserveArcs(ArcIndexType bound) override
Definition graph.h:1326
void ReserveNodes(NodeIndexType bound) override
Definition graph.h:1318
void AddNode(NodeIndexType node)
Definition graph.h:1334
BeginEndWrapper< OutgoingArcIterator > OutgoingArcsStartingFrom(NodeIndexType node, ArcIndexType from) const
StaticGraph(NodeIndexType num_nodes, ArcIndexType arc_capacity)
Definition graph.h:416
void Build(std::vector< ArcIndexType > *permutation)
Definition graph.h:1389
NodeIndexType Head(ArcIndexType arc) const
Definition graph.h:1370
#define DEFINE_RANGE_BASED_ARC_ITERATION(c, t)
Definition graph.h:1108
#define DEFINE_STL_ITERATOR_FUNCTIONS(iterator_class_name)
Definition graph.h:1127
dual_gradient T(y - `dual_solution`) class DiagonalTrustRegionProblemFromQp
A collections of i/o utilities for the Graph classes in ./graph.h.
void Permute(const IntVector &permutation, Array *array_to_permute)
Definition graph.h:756
void PermuteWithExplicitElementType(const IntVector &permutation, Array *array_to_permute, ElementType unused)
Definition graph.h:743
ListGraph Graph
Defining the simplest Graph interface as Graph for convenience.
Definition graph.h:2456
bool Next()
trees with all degrees equal to
void * malloc(YYSIZE_T)
void free(void *)