Google OR-Tools v9.9
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
ebert_graph.h
Go to the documentation of this file.
1// Copyright 2010-2024 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#ifndef OR_TOOLS_GRAPH_EBERT_GRAPH_H_
15#define OR_TOOLS_GRAPH_EBERT_GRAPH_H_
16
17// A few variations on a theme of the "star" graph representation by
18// Ebert, as described in J. Ebert, "A versatile data structure for
19// edge-oriented graph algorithms." Communications of the ACM
20// 30(6):513-519 (June 1987).
21// http://portal.acm.org/citation.cfm?id=214769
22//
23// In this file there are three representations that have much in
24// common. The general one, called simply EbertGraph, contains both
25// forward- and backward-star representations. The other, called
26// ForwardEbertGraph, contains only the forward-star representation of
27// the graph, and is appropriate for applications where the reverse
28// arcs are not needed.
29//
30// The point of including all the representations in this one file is
31// to capitalize, where possible, on the commonalities among them, and
32// those commonalities are mostly factored out into base classes as
33// described below. Despite the commonalities, however, each of the
34// three representations presents a somewhat different interface
35// because of their different underlying semantics. A quintessential
36// example is that the AddArc() method, very natural for the
37// EbertGraph representation, cannot exist for an inherently static
38// representation like ForwardStaticGraph.
39//
40// Many clients are expected to use the interfaces to the graph
41// objects directly, but some clients are parameterized by graph type
42// and need a consistent interface for their underlying graph
43// objects. For such clients, a small library of class templates is
44// provided to give a consistent interface to clients where the
45// underlying graph interfaces differ. Examples are the
46// AnnotatedGraphBuildManager<> template, which provides a uniform
47// interface for building the various types of graphs; and the
48// TailArrayManager<> template, which provides a uniform interface for
49// applications that need to map from arc indices to arc tail nodes,
50// accounting for the fact that such a mapping has to be requested
51// explicitly from the ForwardStaticGraph and ForwardStarGraph
52// representations.
53//
54// There are two base class templates, StarGraphBase, and
55// EbertGraphBase; their purpose is to hold methods and data
56// structures that are in common among their descendants. Only classes
57// that are leaves in the following hierarchy tree are eligible for
58// free-standing instantiation and use by clients. The parentheses
59// around StarGraphBase and EbertGraphBase indicate that they should
60// not normally be instantiated by clients:
61//
62// (StarGraphBase) |
63// / \ |
64// / \ |
65// / \ |
66// / \ |
67// (EbertGraphBase) ForwardStaticGraph |
68// / \ |
69// / \ |
70// EbertGraph ForwardEbertGraph |
71//
72// In the general EbertGraph case, the graph is represented with three
73// arrays.
74// Let n be the number of nodes and m be the number of arcs.
75// Let i be an integer in [0..m-1], denoting the index of an arc.
76// * head_[i] contains the end-node of arc i,
77// * head_[-i-1] contains the start-node of arc i.
78// Note that in two's-complement arithmetic, -i-1 = ~i.
79// Consequently:
80// * head_[~i] contains the end-node of the arc reverse to arc i,
81// * head_[i] contains the start-node of the arc reverse to arc i.
82// Note that if arc (u, v) is defined, then the data structure also stores
83// (v, u).
84// Arc ~i thus denotes the arc reverse to arc i.
85// This is what makes this representation useful for undirected graphs and for
86// implementing algorithms like bidirectional shortest paths.
87// Also note that the representation handles multi-graphs. If several arcs
88// going from node u to node v are added to the graph, they will be handled as
89// separate arcs.
90//
91// Now, for an integer u in [0..n-1] denoting the index of a node:
92// * first_incident_arc_[u] denotes the first arc in the adjacency list of u.
93// * going from an arc i, the adjacency list can be traversed using
94// j = next_adjacent_arc_[i].
95//
96// The EbertGraph implementation has the following benefits:
97// * It is able to handle both directed or undirected graphs.
98// * Being based on indices, it is easily serializable. Only the contents
99// of the head_ array need to be stored. Even so, serialization is
100// currently not implemented.
101// * The node indices and arc indices can be stored in 32 bits, while
102// still allowing to go a bit further than the 4-gigabyte
103// limitation (48 gigabytes for a pure graph, without capacities or
104// costs.)
105// * The representation can be recomputed if edges have been loaded from
106// * The representation can be recomputed if edges have been loaded from
107// external memory or if edges have been re-ordered.
108// * The memory consumption is: 2 * m * sizeof(NodeIndexType)
109// + 2 * m * sizeof(ArcIndexType)
110// + n * sizeof(ArcIndexType)
111// plus a small constant.
112//
113// The EbertGraph implementation differs from the implementation described in
114// [Ebert 1987] in the following respects:
115// * arcs are represented using an (i, ~i) approach, whereas Ebert used
116// (i, -i). Indices for direct arcs thus start at 0, in a fashion that is
117// compatible with the index numbering in C and C++. Note that we also tested
118// a (2*i, 2*i+1) storage pattern, which did not show any speed benefit, and
119// made the use of the API much more difficult.
120// * because of this, the 'nil' values for nodes and arcs are not 0, as Ebert
121// first described. The value for the 'nil' node is set to -1, while the
122// value for the 'nil' arc is set to the smallest integer representable with
123// ArcIndexSize bytes.
124// * it is possible to add arcs to the graph, with AddArc, in a much simpler
125// way than described by Ebert.
126// * TODO(user) although it is already possible, using the
127// GroupForwardArcsByFunctor method, to group all the outgoing (resp.
128// incoming) arcs of a node, the iterator logic could still be improved to
129// allow traversing the outgoing (resp. incoming) arcs in O(out_degree(node))
130// (resp. O(in_degree(node))) instead of O(degree(node)).
131// * TODO(user) it is possible to implement arc deletion and garbage collection
132// in an efficient (relatively) manner. For the time being we haven't seen an
133// application for this.
134//
135// The ForwardEbertGraph representation is like the EbertGraph case described
136// above, with the following modifications:
137// * The part of the head_[] array with negative indices is absent. In its
138// place is a pointer tail_ which, if assigned, points to an array of tail
139// nodes indexed by (nonnegative) arc index. In typical usage tail_ is NULL
140// and the memory for the tail nodes need not be allocated.
141// * The array of arc tails can be allocated as needed and populated from the
142// adjacency lists of the graph.
143// * Representing only the forward star of each node implies that the graph
144// cannot be serialized directly nor rebuilt from scratch from just the head_
145// array. Rebuilding from scratch requires constructing the array of arc
146// tails from the adjacency lists first, and serialization can be done either
147// by first constructing the array of arc tails from the adjacency lists, or
148// by serializing directly from the adjacency lists.
149// * The memory consumption is: m * sizeof(NodeIndexType)
150// + m * sizeof(ArcIndexType)
151// + n * sizeof(ArcIndexType)
152// plus a small constant when the array of arc tails is absent. Allocating
153// the arc tail array adds another m * sizeof(NodeIndexType).
154//
155// The ForwardStaticGraph representation is restricted yet farther
156// than ForwardEbertGraph, with the benefit that it provides higher
157// performance to those applications that can use it.
158// * As with ForwardEbertGraph, the presence of the array of arc
159// tails is optional.
160// * The outgoing adjacency list for each node is stored in a
161// contiguous segment of the head_[] array, obviating the
162// next_adjacent_arc_ structure entirely and ensuring good locality
163// of reference for applications that iterate over outgoing
164// adjacency lists.
165// * The memory consumption is: m * sizeof(NodeIndexType)
166// + n * sizeof(ArcIndexType)
167// plus a small constant when the array of arc tails is absent. Allocating
168// the arc tail array adds another m * sizeof(NodeIndexType).
169
170#include <algorithm>
171#include <cstdint>
172#include <limits>
173#include <memory>
174#include <string>
175#include <utility>
176#include <vector>
177
178#include "absl/strings/str_cat.h"
179#include "ortools/base/logging.h"
180#include "ortools/base/types.h"
182#include "ortools/util/zvector.h"
183
184namespace operations_research {
185
186// Forward declarations.
187template <typename NodeIndexType, typename ArcIndexType>
188class EbertGraph;
189template <typename NodeIndexType, typename ArcIndexType>
190class ForwardEbertGraph;
191template <typename NodeIndexType, typename ArcIndexType>
192class ForwardStaticGraph;
193
194// Standard instantiation of ForwardEbertGraph (named 'ForwardStarGraph') of
195// EbertGraph (named 'StarGraph'); and relevant type shortcuts. Unless their use
196// cases prevent them from doing so, users are encouraged to use StarGraph or
197// ForwardStarGraph according to whether or not they require reverse arcs to be
198// represented explicitly. Along with either graph representation, the other
199// type shortcuts here will often come in handy.
200typedef int32_t NodeIndex;
201typedef int32_t ArcIndex;
202typedef int64_t FlowQuantity;
203typedef int64_t CostValue;
211
212template <typename NodeIndexType, typename ArcIndexType, typename DerivedGraph>
214 public:
215 // The index of the 'nil' node in the graph.
216 static const NodeIndexType kNilNode;
217
218 // The index of the 'nil' arc in the graph.
219 static const ArcIndexType kNilArc;
220
221 // The index of the first node in the graph.
222 static const NodeIndexType kFirstNode;
223
224 // The index of the first arc in the graph.
225 static const ArcIndexType kFirstArc;
226
227 // The maximum possible number of nodes in the graph. (The maximum
228 // index is kMaxNumNodes-1, since indices start at 0. Unfortunately
229 // we waste a value representing this and the max_num_nodes_ member.)
230 static const NodeIndexType kMaxNumNodes;
231
232 // The maximum possible number of arcs in the graph. (The maximum
233 // index is kMaxNumArcs-1, since indices start at 0. Unfortunately
234 // we waste a value representing this and the max_num_arcs_ member.)
235 static const ArcIndexType kMaxNumArcs;
236 // Returns the number of nodes in the graph.
237 NodeIndexType num_nodes() const { return num_nodes_; }
238
239 // Returns the number of original arcs in the graph
240 // (The ones with positive indices.)
241 ArcIndexType num_arcs() const { return num_arcs_; }
242
243 // Returns one more than the largest index of an extant node,
244 // meaning a node that is mentioned as the head or tail of some arc
245 // in the graph. To be used as a helper when clients need to
246 // dimension or iterate over arrays of node annotation information.
247 NodeIndexType end_node_index() const { return kFirstNode + num_nodes_; }
248
249 // Returns one more than the largest index of an extant direct
250 // arc. To be used as a helper when clients need to dimension or
251 // iterate over arrays of arc annotation information.
252 ArcIndexType end_arc_index() const { return kFirstArc + num_arcs_; }
253
254 // Returns the maximum possible number of nodes in the graph.
255 NodeIndexType max_num_nodes() const { return max_num_nodes_; }
256
257 // Returns the maximum possible number of original arcs in the graph.
258 // (The ones with positive indices.)
259 ArcIndexType max_num_arcs() const { return max_num_arcs_; }
260
261 // Returns one more than the largest valid index of a node. To be
262 // used as a helper when clients need to dimension or iterate over
263 // arrays of node annotation information.
264 NodeIndexType max_end_node_index() const {
265 return kFirstNode + max_num_nodes_;
266 }
267
268 // Returns one more than the largest valid index of a direct arc. To
269 // be used as a helper when clients need to dimension or iterate
270 // over arrays of arc annotation information.
271 ArcIndexType max_end_arc_index() const { return kFirstArc + max_num_arcs_; }
272
273 // Utility function to check that a node index is within the bounds AND
274 // different from kNilNode.
275 // Returns true if node is in the range [kFirstNode .. max_num_nodes_).
276 // It is exported so that users of the DerivedGraph class can use it.
277 // To be used in a DCHECK; also used internally to validate
278 // arguments passed to our methods from clients (e.g., AddArc()).
279 bool IsNodeValid(NodeIndexType node) const {
280 return node >= kFirstNode && node < max_num_nodes_;
281 }
282
283 // Returns the first arc going from tail to head, if it exists, or kNilArc
284 // if such an arc does not exist.
285 ArcIndexType LookUpArc(const NodeIndexType tail,
286 const NodeIndexType head) const {
287 for (ArcIndexType arc = FirstOutgoingArc(tail); arc != kNilArc;
288 arc = ThisAsDerived()->NextOutgoingArc(tail, arc)) {
289 if (Head(arc) == head) {
290 return arc;
291 }
292 }
293 return kNilArc;
294 }
295
296 // Returns the head or end-node of arc.
297 NodeIndexType Head(const ArcIndexType arc) const {
298 DCHECK(ThisAsDerived()->CheckArcValidity(arc));
299 return head_[arc];
300 }
301
302 std::string NodeDebugString(const NodeIndexType node) const {
303 if (node == kNilNode) {
304 return "NilNode";
305 } else {
306 return absl::StrCat(static_cast<int64_t>(node));
307 }
308 }
309
310 std::string ArcDebugString(const ArcIndexType arc) const {
311 if (arc == kNilArc) {
312 return "NilArc";
313 } else {
314 return absl::StrCat(static_cast<int64_t>(arc));
315 }
316 }
317
318#if !defined(SWIG)
319 // Iterator class for traversing all the nodes in the graph.
321 public:
322 explicit NodeIterator(const DerivedGraph& graph)
323 : graph_(graph), head_(graph_.StartNode(kFirstNode)) {}
324
325 // Returns true unless all the nodes have been traversed.
326 bool Ok() const { return head_ != kNilNode; }
327
328 // Advances the current node index.
329 void Next() { head_ = graph_.NextNode(head_); }
330
331 // Returns the index of the node currently pointed to by the iterator.
332 NodeIndexType Index() const { return head_; }
333
334 private:
335 // A reference to the current DerivedGraph considered.
336 const DerivedGraph& graph_;
337
338 // The index of the current node considered.
339 NodeIndexType head_;
340 };
341
342 // Iterator class for traversing the arcs in the graph.
344 public:
345 explicit ArcIterator(const DerivedGraph& graph)
346 : graph_(graph), arc_(graph_.StartArc(kFirstArc)) {}
347
348 // Returns true unless all the arcs have been traversed.
349 bool Ok() const { return arc_ != kNilArc; }
350
351 // Advances the current arc index.
352 void Next() { arc_ = graph_.NextArc(arc_); }
353
354 // Returns the index of the arc currently pointed to by the iterator.
355 ArcIndexType Index() const { return arc_; }
356
357 private:
358 // A reference to the current DerivedGraph considered.
359 const DerivedGraph& graph_;
360
361 // The index of the current arc considered.
362 ArcIndexType arc_;
363 };
364
365 // Iterator class for traversing the outgoing arcs associated to a given node.
367 public:
368 OutgoingArcIterator(const DerivedGraph& graph, NodeIndexType node)
369 : graph_(graph),
370 node_(graph_.StartNode(node)),
371 arc_(graph_.StartArc(graph_.FirstOutgoingArc(node))) {
372 DCHECK(CheckInvariant());
373 }
374
375 // This constructor takes an arc as extra argument and makes the iterator
376 // start at arc.
377 OutgoingArcIterator(const DerivedGraph& graph, NodeIndexType node,
378 ArcIndexType arc)
379 : graph_(graph),
380 node_(graph_.StartNode(node)),
381 arc_(graph_.StartArc(arc)) {
382 DCHECK(CheckInvariant());
383 }
384
385 // Can only assign from an iterator on the same graph.
386 void operator=(const OutgoingArcIterator& iterator) {
387 DCHECK(&iterator.graph_ == &graph_);
388 node_ = iterator.node_;
389 arc_ = iterator.arc_;
390 }
391
392 // Returns true unless all the outgoing arcs have been traversed.
393 bool Ok() const { return arc_ != kNilArc; }
394
395 // Advances the current outgoing arc index.
396 void Next() {
397 arc_ = graph_.NextOutgoingArc(node_, arc_);
398 DCHECK(CheckInvariant());
399 }
400
401 // Returns the index of the arc currently pointed to by the iterator.
402 ArcIndexType Index() const { return arc_; }
403
404 private:
405 // Returns true if the invariant for the iterator is verified.
406 // To be used in a DCHECK.
407 bool CheckInvariant() const {
408 if (arc_ == kNilArc) {
409 return true; // This occurs when the iterator has reached the end.
410 }
411 DCHECK(graph_.IsOutgoing(arc_, node_));
412 return true;
413 }
414
415 // A reference to the current DerivedGraph considered.
416 const DerivedGraph& graph_;
417
418 // The index of the node on which arcs are iterated.
419 NodeIndexType node_;
420
421 // The index of the current arc considered.
422 ArcIndexType arc_;
423 };
424#endif // SWIG
425
426 protected:
433
435
436 // Returns kNilNode if the graph has no nodes or node if it has at least one
437 // node. Useful for initializing iterators correctly in the case of empty
438 // graphs.
439 NodeIndexType StartNode(NodeIndexType node) const {
440 return num_nodes_ == 0 ? kNilNode : node;
441 }
442
443 // Returns kNilArc if the graph has no arcs arc if it has at least one arc.
444 // Useful for initializing iterators correctly in the case of empty graphs.
445 ArcIndexType StartArc(ArcIndexType arc) const {
446 return num_arcs_ == 0 ? kNilArc : arc;
447 }
448
449 // Returns the node following the argument in the graph.
450 // Returns kNilNode (= end) if the range of nodes has been exhausted.
451 // It is called by NodeIterator::Next() and as such does not expect to be
452 // passed an argument equal to kNilNode.
453 // This is why the return line is simplified from
454 // return (node == kNilNode || next_node >= num_nodes_)
455 // ? kNilNode : next_node;
456 // to
457 // return next_node < num_nodes_ ? next_node : kNilNode;
458 NodeIndexType NextNode(const NodeIndexType node) const {
459 DCHECK(IsNodeValid(node));
460 const NodeIndexType next_node = node + 1;
461 return next_node < num_nodes_ ? next_node : kNilNode;
462 }
463
464 // Returns the arc following the argument in the graph.
465 // Returns kNilArc (= end) if the range of arcs has been exhausted.
466 // It is called by ArcIterator::Next() and as such does not expect to be
467 // passed an argument equal to kNilArc.
468 // This is why the return line is simplified from
469 // return ( arc == kNilArc || next_arc >= num_arcs_) ? kNilArc : next_arc;
470 // to
471 // return next_arc < num_arcs_ ? next_arc : kNilArc;
472 ArcIndexType NextArc(const ArcIndexType arc) const {
473 DCHECK(ThisAsDerived()->CheckArcValidity(arc));
474 const ArcIndexType next_arc = arc + 1;
475 return next_arc < num_arcs_ ? next_arc : kNilArc;
476 }
477
478 // Returns the first outgoing arc for node.
479 ArcIndexType FirstOutgoingArc(const NodeIndexType node) const {
480 DCHECK(IsNodeValid(node));
481 return ThisAsDerived()->FindNextOutgoingArc(
482 ThisAsDerived()->FirstOutgoingOrOppositeIncomingArc(node));
483 }
484
485 // The maximum number of nodes that the graph can hold.
486 NodeIndexType max_num_nodes_;
487
488 // The maximum number of arcs that the graph can hold.
489 ArcIndexType max_num_arcs_;
490
491 // The maximum index of the node currently held by the graph.
492 NodeIndexType num_nodes_;
493
494 // The current number of arcs held by the graph.
495 ArcIndexType num_arcs_;
496
497 // Array of node indices. head_[i] contains the head node of arc i.
499
500 // Array of arc indices. first_incident_arc_[i] contains the first arc
501 // incident to node i.
503
504 private:
505 // Shorthand: returns a const DerivedGraph*-typed version of our
506 // "this" pointer.
507 inline const DerivedGraph* ThisAsDerived() const {
508 return static_cast<const DerivedGraph*>(this);
509 }
510
511 // Shorthand: returns a DerivedGraph*-typed version of our "this"
512 // pointer.
513 inline DerivedGraph* ThisAsDerived() {
514 return static_cast<DerivedGraph*>(this);
515 }
516};
517
518template <typename NodeIndexType, typename ArcIndexType>
520 public:
524
525 bool operator()(ArcIndexType a, ArcIndexType b) const {
526 return head_[a] < head_[b];
527 }
528
529 private:
530 const ZVector<NodeIndexType>& head_;
531};
532
533template <typename NodeIndexType, typename ArcIndexType>
535 : public StarGraphBase<NodeIndexType, ArcIndexType,
536 ForwardStaticGraph<NodeIndexType, ArcIndexType> > {
537 typedef StarGraphBase<NodeIndexType, ArcIndexType,
540 friend class StarGraphBase<NodeIndexType, ArcIndexType,
541 ForwardStaticGraph<NodeIndexType, ArcIndexType> >;
542
545
547 using Base::head_;
550 using Base::num_arcs_;
551 using Base::num_nodes_;
552
553 public:
554#if !defined(SWIG)
556 using Base::Head;
557 using Base::IsNodeValid;
558
559 using Base::kFirstArc;
560 using Base::kFirstNode;
561 using Base::kNilArc;
562#endif // SWIG
563
564 typedef NodeIndexType NodeIndex;
565 typedef ArcIndexType ArcIndex;
566
567// TODO(user): Configure SWIG to handle the
568// CycleHandlerForAnnotatedArcs class.
569#if !defined(SWIG)
571 : public ArrayIndexCycleHandler<NodeIndexType, ArcIndexType> {
573
574 public:
576 PermutationCycleHandler<ArcIndexType>* annotation_handler,
577 NodeIndexType* data)
578 : ArrayIndexCycleHandler<NodeIndexType, ArcIndexType>(&data[kFirstArc]),
579 annotation_handler_(annotation_handler) {}
580
581 // This type is neither copyable nor movable.
584 const CycleHandlerForAnnotatedArcs&) = delete;
585
586 void SetTempFromIndex(ArcIndexType source) override {
588 annotation_handler_->SetTempFromIndex(source);
589 }
590
591 void SetIndexFromIndex(ArcIndexType source,
592 ArcIndexType destination) const override {
593 Base::SetIndexFromIndex(source, destination);
594 annotation_handler_->SetIndexFromIndex(source, destination);
595 }
596
597 void SetIndexFromTemp(ArcIndexType destination) const override {
598 Base::SetIndexFromTemp(destination);
599 annotation_handler_->SetIndexFromTemp(destination);
600 }
601
602 private:
603 PermutationCycleHandler<ArcIndexType>* annotation_handler_;
604 };
605#endif // SWIG
606
607 // Constructor for use by GraphBuilderFromArcs instances and direct
608 // clients that want to materialize a graph in one step.
609 // Materializing all at once is the only choice available with a
610 // static graph.
611 //
612 // Args:
613 // sort_arcs_by_head: determines whether arcs incident to each tail
614 // node are sorted by head node.
615 // client_cycle_handler: if non-NULL, mediates the permutation of
616 // arbitrary annotation data belonging to the client according
617 // to the permutation applied to the arcs in forming the
618 // graph. Two permutations may be composed to form the final one
619 // that affects the arcs. First, the arcs are always permuted to
620 // group them by tail node because ForwardStaticGraph requires
621 // this. Second, if each node's outgoing arcs are sorted by head
622 // node (according to sort_arcs_by_head), that sorting implies
623 // an additional permutation on the arcs.
625 const NodeIndexType num_nodes, const ArcIndexType num_arcs,
626 const bool sort_arcs_by_head,
627 std::vector<std::pair<NodeIndexType, NodeIndexType> >* client_input_arcs,
628 // TODO(user): For some reason, SWIG breaks if the
629 // operations_research namespace is not explicit in the
630 // following argument declaration.
632 client_cycle_handler) {
636 // A more convenient name for a parameter required by style to be
637 // a pointer, because we modify its referent.
638 std::vector<std::pair<NodeIndexType, NodeIndexType> >& input_arcs =
639 *client_input_arcs;
640
641 // We coopt the first_incident_arc_ array as a node-indexed vector
642 // used for two purposes related to degree before setting up its
643 // final values. First, it counts the out-degree of each
644 // node. Second, it is reused to count the number of arcs outgoing
645 // from each node that have already been put in place from the
646 // given input_arcs. We reserve an extra entry as a sentinel at
647 // the end.
650 for (ArcIndexType arc = kFirstArc; arc < kFirstArc + num_arcs; ++arc) {
651 first_incident_arc_[kFirstNode + input_arcs[arc].first] += 1;
652 // Take this opportunity to see how many nodes are really
653 // mentioned in the arc list.
654 num_nodes_ = std::max(
655 num_nodes_, static_cast<NodeIndexType>(input_arcs[arc].first + 1));
656 num_nodes_ = std::max(
657 num_nodes_, static_cast<NodeIndexType>(input_arcs[arc].second + 1));
658 }
659 ArcIndexType next_arc = kFirstArc;
660 for (NodeIndexType node = 0; node < num_nodes; ++node) {
661 ArcIndexType degree = first_incident_arc_[kFirstNode + node];
662 first_incident_arc_[kFirstNode + node] = next_arc;
663 next_arc += degree;
664 }
665 DCHECK_EQ(num_arcs, next_arc);
667 std::unique_ptr<ArcIndexType[]> arc_permutation;
668 if (client_cycle_handler != nullptr) {
669 arc_permutation.reset(new ArcIndexType[end_arc_index()]);
670 for (ArcIndexType input_arc = 0; input_arc < num_arcs; ++input_arc) {
671 NodeIndexType tail = input_arcs[input_arc].first;
672 NodeIndexType head = input_arcs[input_arc].second;
673 ArcIndexType arc = first_incident_arc_[kFirstNode + tail];
674 // The head_ entry will get permuted into the right place
675 // later.
676 head_[kFirstArc + input_arc] = kFirstNode + head;
677 arc_permutation[kFirstArc + arc] = input_arc;
679 }
680 } else {
681 if (sizeof(input_arcs[0].first) >= sizeof(first_incident_arc_[0])) {
682 // We reuse the input_arcs[].first entries to hold our
683 // mapping to the head_ array. This allows us to spread out
684 // cache badness.
685 for (ArcIndexType input_arc = 0; input_arc < num_arcs; ++input_arc) {
686 NodeIndexType tail = input_arcs[input_arc].first;
687 ArcIndexType arc = first_incident_arc_[kFirstNode + tail];
689 input_arcs[input_arc].first = static_cast<NodeIndexType>(arc);
690 }
691 for (ArcIndexType input_arc = 0; input_arc < num_arcs; ++input_arc) {
692 ArcIndexType arc =
693 static_cast<ArcIndexType>(input_arcs[input_arc].first);
694 NodeIndexType head = input_arcs[input_arc].second;
696 }
697 } else {
698 // We cannot reuse the input_arcs[].first entries so we map to
699 // the head_ array in a single loop.
700 for (ArcIndexType input_arc = 0; input_arc < num_arcs; ++input_arc) {
701 NodeIndexType tail = input_arcs[input_arc].first;
702 NodeIndexType head = input_arcs[input_arc].second;
703 ArcIndexType arc = first_incident_arc_[kFirstNode + tail];
706 }
707 }
708 }
709 // Shift the entries in first_incident_arc_ to compensate for the
710 // counting each one has done through its incident arcs. Note that
711 // there is a special sentry element at the end of
712 // first_incident_arc_.
713 for (NodeIndexType node = kFirstNode + num_nodes; node > /* kFirstNode */ 0;
714 --node) {
716 }
718 if (sort_arcs_by_head) {
719 ArcIndexType begin = first_incident_arc_[kFirstNode];
720 if (client_cycle_handler != nullptr) {
721 for (NodeIndexType node = 0; node < num_nodes; ++node) {
722 ArcIndexType end = first_incident_arc_[node + 1];
723 std::sort(
724 &arc_permutation[begin], &arc_permutation[end],
726 head_));
727 begin = end;
728 }
729 } else {
730 for (NodeIndexType node = 0; node < num_nodes; ++node) {
731 ArcIndexType end = first_incident_arc_[node + 1];
732 // The second argument in the following has a strange index
733 // expression because ZVector claims that no index is valid
734 // unless it refers to an element in the vector. In particular
735 // an index one past the end is invalid.
736 ArcIndexType begin_index = (begin < num_arcs ? begin : begin - 1);
737 ArcIndexType begin_offset = (begin < num_arcs ? 0 : 1);
738 ArcIndexType end_index = (end > 0 ? end - 1 : end);
739 ArcIndexType end_offset = (end > 0 ? 1 : 0);
740 std::sort(&head_[begin_index] + begin_offset,
741 &head_[end_index] + end_offset);
742 begin = end;
743 }
744 }
745 }
746 if (client_cycle_handler != nullptr && num_arcs > 0) {
747 // Apply the computed permutation if we haven't already.
748 CycleHandlerForAnnotatedArcs handler_for_constructor(
749 client_cycle_handler, &head_[kFirstArc] - kFirstArc);
750 // We use a permutation cycle handler to place the head array
751 // indices and permute the client's arc annotation data along
752 // with them.
753 PermutationApplier<ArcIndexType> permutation(&handler_for_constructor);
754 permutation.Apply(&arc_permutation[0], kFirstArc, end_arc_index());
755 }
756 }
757
758 // Returns the tail or start-node of arc.
759 NodeIndexType Tail(const ArcIndexType arc) const {
760 DCHECK(CheckArcValidity(arc));
762 return (*tail_)[arc];
763 }
764
765 // Returns true if arc is incoming to node.
766 bool IsIncoming(ArcIndexType arc, NodeIndexType node) const {
767 return Head(arc) == node;
768 }
769
770 // Utility function to check that an arc index is within the bounds.
771 // It is exported so that users of the ForwardStaticGraph class can use it.
772 // To be used in a DCHECK.
773 bool CheckArcBounds(const ArcIndexType arc) const {
774 return ((arc == kNilArc) || (arc >= kFirstArc && arc < max_num_arcs_));
775 }
776
777 // Utility function to check that an arc index is within the bounds AND
778 // different from kNilArc.
779 // It is exported so that users of the ForwardStaticGraph class can use it.
780 // To be used in a DCHECK.
781 bool CheckArcValidity(const ArcIndexType arc) const {
782 return ((arc != kNilArc) && (arc >= kFirstArc && arc < max_num_arcs_));
783 }
784
785 // Returns true if arc is a valid index into the (*tail_) array.
786 bool CheckTailIndexValidity(const ArcIndexType arc) const {
787 return ((tail_ != nullptr) && (arc >= kFirstArc) &&
788 (arc <= tail_->max_index()));
789 }
790
791 ArcIndexType NextOutgoingArc(const NodeIndexType node,
792 ArcIndexType arc) const {
793 DCHECK(IsNodeValid(node));
794 DCHECK(CheckArcValidity(arc));
795 ++arc;
796 if (arc < first_incident_arc_[node + 1]) {
797 return arc;
798 } else {
799 return kNilArc;
800 }
801 }
802
803 // Returns a debug string containing all the information contained in the
804 // data structure in raw form.
805 std::string DebugString() const {
806 std::string result = "Arcs:(node) :\n";
807 for (ArcIndexType arc = kFirstArc; arc < num_arcs_; ++arc) {
808 result += " " + ArcDebugString(arc) + ":(" + NodeDebugString(head_[arc]) +
809 ")\n";
810 }
811 result += "Node:First arc :\n";
812 for (NodeIndexType node = kFirstNode; node <= num_nodes_; ++node) {
813 result += " " + NodeDebugString(node) + ":" +
815 }
816 return result;
817 }
818
820 // If (*tail_) is already allocated, we have the invariant that
821 // its contents are canonical, so we do not need to do anything
822 // here in that case except return true.
823 if (tail_ == nullptr) {
824 if (!RepresentationClean()) {
825 // We have been asked to build the (*tail_) array, but we have
826 // no valid information from which to build it. The graph is
827 // in an unrecoverable, inconsistent state.
828 return false;
829 }
830 // Reallocate (*tail_) and rebuild its contents from the
831 // adjacency lists.
832 tail_.reset(new ZVector<NodeIndexType>);
833 tail_->Reserve(kFirstArc, max_num_arcs_ - 1);
834 typename Base::NodeIterator node_it(*this);
835 for (; node_it.Ok(); node_it.Next()) {
836 NodeIndexType node = node_it.Index();
837 typename Base::OutgoingArcIterator arc_it(*this, node);
838 for (; arc_it.Ok(); arc_it.Next()) {
839 (*tail_)[arc_it.Index()] = node;
840 }
841 }
842 }
843 DCHECK(TailArrayComplete());
844 return true;
845 }
846
847 void ReleaseTailArray() { tail_.reset(nullptr); }
848
849 // To be used in a DCHECK().
850 bool TailArrayComplete() const {
851 CHECK(tail_);
852 for (ArcIndexType arc = kFirstArc; arc < num_arcs_; ++arc) {
854 CHECK(IsNodeValid((*tail_)[arc]));
855 }
856 return true;
857 }
858
859 private:
860 bool IsDirect() const { return true; }
861 bool RepresentationClean() const { return true; }
862 bool IsOutgoing(const NodeIndexType node,
863 const ArcIndexType unused_arc) const {
864 return true;
865 }
866
867 // Returns the first arc in node's incidence list.
868 ArcIndexType FirstOutgoingOrOppositeIncomingArc(NodeIndexType node) const {
869 DCHECK(RepresentationClean());
870 DCHECK(IsNodeValid(node));
871 ArcIndexType result = first_incident_arc_[node];
872 return ((result != first_incident_arc_[node + 1]) ? result : kNilArc);
873 }
874
875 // Utility method that finds the next outgoing arc.
876 ArcIndexType FindNextOutgoingArc(ArcIndexType arc) const {
877 DCHECK(CheckArcBounds(arc));
878 return arc;
879 }
880
881 // Array of node indices, not always present. (*tail_)[i] contains
882 // the tail node of arc i. This array is not needed for normal graph
883 // traversal operations, but is used in optimizing the graph's
884 // layout so arcs are grouped by tail node, and can be used in one
885 // approach to serializing the graph.
886 //
887 // Invariants: At any time when we are not executing a method of
888 // this class, either tail_ == NULL or the tail_ array's contents
889 // are kept canonical. If tail_ != NULL, any method that modifies
890 // adjacency lists must also ensure (*tail_) is modified
891 // correspondingly. The converse does not hold: Modifications to
892 // (*tail_) are allowed without updating the adjacency lists. If
893 // such modifications take place, representation_clean_ must be set
894 // to false, of course, to indicate that the adjacency lists are no
895 // longer current.
896 std::unique_ptr<ZVector<NodeIndexType> > tail_;
897};
898
899// The index of the 'nil' node in the graph.
900template <typename NodeIndexType, typename ArcIndexType, typename DerivedGraph>
901const NodeIndexType
903
904// The index of the 'nil' arc in the graph.
905template <typename NodeIndexType, typename ArcIndexType, typename DerivedGraph>
906const ArcIndexType
908 std::numeric_limits<ArcIndexType>::min();
909
910// The index of the first node in the graph.
911template <typename NodeIndexType, typename ArcIndexType, typename DerivedGraph>
912const NodeIndexType
914
915// The index of the first arc in the graph.
916template <typename NodeIndexType, typename ArcIndexType, typename DerivedGraph>
917const ArcIndexType
919
920// The maximum possible node index in the graph.
921template <typename NodeIndexType, typename ArcIndexType, typename DerivedGraph>
922const NodeIndexType
924 std::numeric_limits<NodeIndexType>::max();
925
926// The maximum possible number of arcs in the graph.
927// (The maximum index is kMaxNumArcs-1, since indices start at 0.)
928template <typename NodeIndexType, typename ArcIndexType, typename DerivedGraph>
929const ArcIndexType
931 std::numeric_limits<ArcIndexType>::max();
932
933// A template for the base class that holds the functionality that exists in
934// common between the EbertGraph<> template and the ForwardEbertGraph<>
935// template.
936//
937// This template is for internal use only, and this is enforced by making all
938// constructors for this class template protected. Clients should use one of the
939// two derived-class templates. Most clients will not even use those directly,
940// but will use the StarGraph and ForwardStarGraph typenames declared above.
941//
942// The DerivedGraph template argument must be the type of the class (typically
943// itself built from a template) that:
944// 1. implements the full interface expected for either ForwardEbertGraph or
945// EbertGraph, and
946// 2. inherits from an instance of this template.
947// The base class needs access to some members of the derived class such as, for
948// example, NextOutgoingArc(), and it gets this access via the DerivedGraph
949// template argument.
950template <typename NodeIndexType, typename ArcIndexType, typename DerivedGraph>
952 : public StarGraphBase<NodeIndexType, ArcIndexType, DerivedGraph> {
954 friend class StarGraphBase<NodeIndexType, ArcIndexType, DerivedGraph>;
955
956 protected:
963
964 public:
965#if !SWIG
968
975#endif // SWIG
976
977 // Reserves memory needed for max_num_nodes nodes and max_num_arcs arcs.
978 // Returns false if the parameters passed are not OK.
979 // It can be used to enlarge the graph, but does not shrink memory
980 // if called with smaller values.
981 bool Reserve(NodeIndexType new_max_num_nodes, ArcIndexType new_max_num_arcs) {
982 if (new_max_num_nodes < 0 || new_max_num_nodes > kMaxNumNodes) {
983 return false;
984 }
985 if (new_max_num_arcs < 0 || new_max_num_arcs > kMaxNumArcs) {
986 return false;
987 }
988 first_incident_arc_.Reserve(kFirstNode, new_max_num_nodes - 1);
989 for (NodeIndexType node = max_num_nodes_;
990 node <= first_incident_arc_.max_index(); ++node) {
992 }
993 ThisAsDerived()->ReserveInternal(new_max_num_nodes, new_max_num_arcs);
994 max_num_nodes_ = new_max_num_nodes;
995 max_num_arcs_ = new_max_num_arcs;
996 return true;
997 }
998
999 // Adds an arc to the graph and returns its index.
1000 // Returns kNilArc if the arc could not be added.
1001 // Note that for a given pair (tail, head) AddArc does not overwrite an
1002 // already-existing arc between tail and head: Another arc is created
1003 // instead. This makes it possible to handle multi-graphs.
1004 ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head) {
1006 !IsNodeValid(head)) {
1007 return kNilArc;
1008 }
1009 if (tail + 1 > num_nodes_) {
1010 num_nodes_ = tail + 1; // max does not work on int16_t.
1011 }
1012 if (head + 1 > num_nodes_) {
1013 num_nodes_ = head + 1;
1014 }
1015 ArcIndexType arc = num_arcs_;
1016 ++num_arcs_;
1017 ThisAsDerived()->RecordArc(arc, tail, head);
1018 return arc;
1019 }
1020
1021// TODO(user): Configure SWIG to handle the GroupForwardArcsByFunctor
1022// member template and the CycleHandlerForAnnotatedArcs class.
1023#if !SWIG
1024 template <typename ArcIndexTypeStrictWeakOrderingFunctor>
1026 const ArcIndexTypeStrictWeakOrderingFunctor& compare,
1027 PermutationCycleHandler<ArcIndexType>* annotation_handler) {
1028 std::unique_ptr<ArcIndexType[]> arc_permutation(
1029 new ArcIndexType[end_arc_index()]);
1030
1031 // Determine the permutation that groups arcs by their tail nodes.
1032 for (ArcIndexType i = 0; i < end_arc_index(); ++i) {
1033 // Start with the identity permutation.
1034 arc_permutation[i] = i;
1035 }
1036 std::sort(&arc_permutation[kFirstArc], &arc_permutation[end_arc_index()],
1037 compare);
1038
1039 // Now we actually permute the head_ array and the
1040 // scaled_arc_cost_ array according to the sorting permutation.
1041 CycleHandlerForAnnotatedArcs cycle_handler(annotation_handler,
1042 ThisAsDerived());
1043 PermutationApplier<ArcIndexType> permutation(&cycle_handler);
1044 permutation.Apply(&arc_permutation[0], kFirstArc, end_arc_index());
1045
1046 // Finally, rebuild the graph from its permuted head_ array.
1047 ThisAsDerived()->BuildRepresentation();
1048 }
1049
1051 : public PermutationCycleHandler<ArcIndexType> {
1052 public:
1054 PermutationCycleHandler<ArcIndexType>* annotation_handler,
1055 DerivedGraph* graph)
1056 : annotation_handler_(annotation_handler),
1057 graph_(graph),
1058 head_temp_(kNilNode),
1059 tail_temp_(kNilNode) {}
1060
1061 // This type is neither copyable nor movable.
1064 const CycleHandlerForAnnotatedArcs&) = delete;
1065
1066 void SetTempFromIndex(ArcIndexType source) override {
1067 if (annotation_handler_ != nullptr) {
1068 annotation_handler_->SetTempFromIndex(source);
1069 }
1070 head_temp_ = graph_->Head(source);
1071 tail_temp_ = graph_->Tail(source);
1072 }
1073
1074 void SetIndexFromIndex(ArcIndexType source,
1075 ArcIndexType destination) const override {
1076 if (annotation_handler_ != nullptr) {
1077 annotation_handler_->SetIndexFromIndex(source, destination);
1078 }
1079 graph_->SetHead(destination, graph_->Head(source));
1080 graph_->SetTail(destination, graph_->Tail(source));
1081 }
1082
1083 void SetIndexFromTemp(ArcIndexType destination) const override {
1084 if (annotation_handler_ != nullptr) {
1085 annotation_handler_->SetIndexFromTemp(destination);
1086 }
1087 graph_->SetHead(destination, head_temp_);
1088 graph_->SetTail(destination, tail_temp_);
1089 }
1090
1091 // Since we are free to destroy the permutation array we use the
1092 // kNilArc value to mark entries in the array that have been
1093 // processed already. There is no need to be able to recover the
1094 // original permutation array entries once they have been seen.
1095 void SetSeen(ArcIndexType* permutation_element) const override {
1096 *permutation_element = kNilArc;
1097 }
1098
1099 bool Unseen(ArcIndexType permutation_element) const override {
1100 return permutation_element != kNilArc;
1101 }
1102
1104
1105 private:
1106 PermutationCycleHandler<ArcIndexType>* annotation_handler_;
1107 DerivedGraph* graph_;
1108 NodeIndexType head_temp_;
1109 NodeIndexType tail_temp_;
1110 };
1111#endif // SWIG
1112
1113 protected:
1115
1117
1118 void Initialize(NodeIndexType max_num_nodes, ArcIndexType max_num_arcs) {
1120 LOG(DFATAL) << "Could not reserve memory for "
1121 << static_cast<int64_t>(max_num_nodes) << " nodes and "
1122 << static_cast<int64_t>(max_num_arcs) << " arcs.";
1123 }
1125 ThisAsDerived()->InitializeInternal(max_num_nodes, max_num_arcs);
1126 }
1127
1128 // Returns the first arc in node's incidence list.
1130 const NodeIndexType node) const {
1131 DCHECK(representation_clean_);
1132 DCHECK(IsNodeValid(node));
1133 return first_incident_arc_[node];
1134 }
1135
1136 // Returns the next arc following the passed argument in its adjacency list.
1137 ArcIndexType NextAdjacentArc(const ArcIndexType arc) const {
1138 DCHECK(representation_clean_);
1139 DCHECK(ThisAsDerived()->CheckArcValidity(arc));
1140 return next_adjacent_arc_[arc];
1141 }
1142
1143 // Returns the outgoing arc following the argument in the adjacency list.
1144 ArcIndexType NextOutgoingArc(const NodeIndexType unused_node,
1145 const ArcIndexType arc) const {
1146 DCHECK(ThisAsDerived()->CheckArcValidity(arc));
1147 DCHECK(ThisAsDerived()->IsDirect(arc));
1148 return ThisAsDerived()->FindNextOutgoingArc(NextAdjacentArc(arc));
1149 }
1150
1151 // Array of next indices.
1152 // next_adjacent_arc_[i] contains the next arc in the adjacency list of arc i.
1154
1155 // Flag to indicate that BuildRepresentation() needs to be called
1156 // before the adjacency lists are examined. Only for DCHECK in debug
1157 // builds.
1159
1160 private:
1161 // Shorthand: returns a const DerivedGraph*-typed version of our
1162 // "this" pointer.
1163 inline const DerivedGraph* ThisAsDerived() const {
1164 return static_cast<const DerivedGraph*>(this);
1165 }
1166
1167 // Shorthand: returns a DerivedGraph*-typed version of our "this"
1168 // pointer.
1169 inline DerivedGraph* ThisAsDerived() {
1170 return static_cast<DerivedGraph*>(this);
1171 }
1172
1173 void InitializeInternal(NodeIndexType max_num_nodes,
1174 ArcIndexType max_num_arcs) {
1176 }
1177
1178 bool RepresentationClean() const { return representation_clean_; }
1179
1180 // Using the SetHead() method implies that the BuildRepresentation()
1181 // method must be called to restore consistency before the graph is
1182 // used.
1183 void SetHead(const ArcIndexType arc, const NodeIndexType head) {
1184 representation_clean_ = false;
1185 head_.Set(arc, head);
1186 }
1187};
1188
1189// Most users should only use StarGraph, which is EbertGraph<int32_t, int32_t>,
1190// and other type shortcuts; see the bottom of this file.
1191template <typename NodeIndexType, typename ArcIndexType>
1193 : public EbertGraphBase<NodeIndexType, ArcIndexType,
1194 EbertGraph<NodeIndexType, ArcIndexType> > {
1195 typedef EbertGraphBase<NodeIndexType, ArcIndexType,
1198 friend class EbertGraphBase<NodeIndexType, ArcIndexType,
1199 EbertGraph<NodeIndexType, ArcIndexType> >;
1200 friend class StarGraphBase<NodeIndexType, ArcIndexType,
1201 EbertGraph<NodeIndexType, ArcIndexType> >;
1202
1205 using Base::Initialize;
1208
1210 using Base::head_;
1211 using Base::max_num_arcs_;
1214 using Base::num_arcs_;
1215 using Base::num_nodes_;
1217
1218 public:
1219#if !SWIG
1220 using Base::Head;
1221 using Base::IsNodeValid;
1222
1223 using Base::kFirstArc;
1224 using Base::kFirstNode;
1225 using Base::kNilArc;
1226 using Base::kNilNode;
1227#endif // SWIG
1228
1229 typedef NodeIndexType NodeIndex;
1230 typedef ArcIndexType ArcIndex;
1231
1233
1234 EbertGraph(NodeIndexType max_num_nodes, ArcIndexType max_num_arcs) {
1236 }
1237
1239
1240#if !SWIG
1241 // Iterator class for traversing the arcs incident to a given node in the
1242 // graph.
1244 public:
1246 NodeIndexType node)
1247 : graph_(graph),
1248 node_(graph_.StartNode(node)),
1249 arc_(graph_.StartArc(
1250 graph_.FirstOutgoingOrOppositeIncomingArc(node))) {
1251 DCHECK(CheckInvariant());
1252 }
1253
1254 // This constructor takes an arc as extra argument and makes the iterator
1255 // start at arc.
1257 NodeIndexType node, ArcIndexType arc)
1258 : graph_(graph),
1259 node_(graph_.StartNode(node)),
1260 arc_(graph_.StartArc(arc)) {
1261 DCHECK(CheckInvariant());
1262 }
1263
1264 // Can only assign from an iterator on the same graph.
1266 DCHECK(&iterator.graph_ == &graph_);
1267 node_ = iterator.node_;
1268 arc_ = iterator.arc_;
1269 }
1270
1271 // Returns true unless all the adjancent arcs have been traversed.
1272 bool Ok() const { return arc_ != kNilArc; }
1273
1274 // Advances the current adjacent arc index.
1275 void Next() {
1276 arc_ = graph_.NextAdjacentArc(arc_);
1277 DCHECK(CheckInvariant());
1278 }
1279
1280 // Returns the index of the arc currently pointed to by the iterator.
1281 ArcIndexType Index() const { return arc_; }
1282
1283 private:
1284 // Returns true if the invariant for the iterator is verified.
1285 // To be used in a DCHECK.
1286 bool CheckInvariant() const {
1287 if (arc_ == kNilArc) {
1288 return true; // This occurs when the iterator has reached the end.
1289 }
1290 DCHECK(graph_.IsOutgoingOrOppositeIncoming(arc_, node_));
1291 return true;
1292 }
1293 // A reference to the current EbertGraph considered.
1294 const EbertGraph& graph_;
1295
1296 // The index of the node on which arcs are iterated.
1297 NodeIndexType node_;
1298
1299 // The index of the current arc considered.
1300 ArcIndexType arc_;
1301 };
1302
1303 // Iterator class for traversing the incoming arcs associated to a given node.
1305 public:
1306 IncomingArcIterator(const EbertGraph& graph, NodeIndexType node)
1307 : graph_(graph),
1308 node_(graph_.StartNode(node)),
1309 arc_(graph_.StartArc(graph_.FirstIncomingArc(node))) {
1310 DCHECK(CheckInvariant());
1311 }
1312
1313 // This constructor takes an arc as extra argument and makes the iterator
1314 // start at arc.
1315 IncomingArcIterator(const EbertGraph& graph, NodeIndexType node,
1316 ArcIndexType arc)
1317 : graph_(graph),
1318 node_(graph_.StartNode(node)),
1319 arc_(arc == kNilArc ? kNilArc
1320 : graph_.StartArc(graph_.Opposite(arc))) {
1321 DCHECK(CheckInvariant());
1322 }
1323
1324 // Can only assign from an iterator on the same graph.
1325 void operator=(const IncomingArcIterator& iterator) {
1326 DCHECK(&iterator.graph_ == &graph_);
1327 node_ = iterator.node_;
1328 arc_ = iterator.arc_;
1329 }
1330
1331 // Returns true unless all the incoming arcs have been traversed.
1332 bool Ok() const { return arc_ != kNilArc; }
1333
1334 // Advances the current incoming arc index.
1335 void Next() {
1336 arc_ = graph_.NextIncomingArc(arc_);
1337 DCHECK(CheckInvariant());
1338 }
1339
1340 // Returns the index of the arc currently pointed to by the iterator.
1341 ArcIndexType Index() const {
1342 return arc_ == kNilArc ? kNilArc : graph_.Opposite(arc_);
1343 }
1344
1345 private:
1346 // Returns true if the invariant for the iterator is verified.
1347 // To be used in a DCHECK.
1348 bool CheckInvariant() const {
1349 if (arc_ == kNilArc) {
1350 return true; // This occurs when the iterator has reached the end.
1351 }
1352 DCHECK(graph_.IsIncoming(Index(), node_));
1353 return true;
1354 }
1355 // A reference to the current EbertGraph considered.
1356 const EbertGraph& graph_;
1357
1358 // The index of the node on which arcs are iterated.
1359 NodeIndexType node_;
1360
1361 // The index of the current arc considered.
1362 ArcIndexType arc_;
1363 };
1364#endif // SWIG
1365
1366 // Utility function to check that an arc index is within the bounds.
1367 // It is exported so that users of the EbertGraph class can use it.
1368 // To be used in a DCHECK.
1369 bool CheckArcBounds(const ArcIndexType arc) const {
1370 return (arc == kNilArc) || (arc >= -max_num_arcs_ && arc < max_num_arcs_);
1371 }
1372
1373 // Utility function to check that an arc index is within the bounds AND
1374 // different from kNilArc.
1375 // It is exported so that users of the EbertGraph class can use it.
1376 // To be used in a DCHECK.
1377 bool CheckArcValidity(const ArcIndexType arc) const {
1378 return (arc != kNilArc) && (arc >= -max_num_arcs_ && arc < max_num_arcs_);
1379 }
1380
1381 // Returns the tail or start-node of arc.
1382 NodeIndexType Tail(const ArcIndexType arc) const {
1383 DCHECK(CheckArcValidity(arc));
1384 return head_[Opposite(arc)];
1385 }
1386
1387 // Returns the tail or start-node of arc if it is positive
1388 // (i.e. it is taken in the direction it was entered in the graph),
1389 // and the head or end-node otherwise. 'This' in Ebert's paper.
1390 NodeIndexType DirectArcTail(const ArcIndexType arc) const {
1391 return Tail(DirectArc(arc));
1392 }
1393
1394 // Returns the head or end-node of arc if it is positive
1395 // (i.e. it is taken in the direction it was entered in the graph),
1396 // and the tail or start-node otherwise. 'That' in Ebert's paper.
1397 NodeIndexType DirectArcHead(const ArcIndexType arc) const {
1398 return Head(DirectArc(arc));
1399 }
1400
1401 // Returns the arc in normal/direct direction.
1402 ArcIndexType DirectArc(const ArcIndexType arc) const {
1403 DCHECK(CheckArcValidity(arc));
1404 return std::max(arc, Opposite(arc));
1405 }
1406
1407 // Returns the arc in reverse direction.
1408 ArcIndexType ReverseArc(const ArcIndexType arc) const {
1409 DCHECK(CheckArcValidity(arc));
1410 return std::min(arc, Opposite(arc));
1411 }
1412
1413 // Returns the opposite arc, i.e. the direct arc is the arc is in reverse
1414 // direction, and the reverse arc if the arc is direct.
1415 ArcIndexType Opposite(const ArcIndexType arc) const {
1416 const ArcIndexType opposite = ~arc;
1417 DCHECK(CheckArcValidity(arc));
1418 DCHECK(CheckArcValidity(opposite));
1419 return opposite;
1420 }
1421
1422 // Returns true if the arc is direct.
1423 bool IsDirect(const ArcIndexType arc) const {
1424 DCHECK(CheckArcBounds(arc));
1425 return arc != kNilArc && arc >= 0;
1426 }
1427
1428 // Returns true if the arc is in the reverse direction.
1429 bool IsReverse(const ArcIndexType arc) const {
1430 DCHECK(CheckArcBounds(arc));
1431 return arc != kNilArc && arc < 0;
1432 }
1433
1434 // Returns true if arc is incident to node.
1436 NodeIndexType node) const {
1437 return Tail(arc) == node;
1438 }
1439
1440 // Returns true if arc is incoming to node.
1441 bool IsIncoming(ArcIndexType arc, NodeIndexType node) const {
1442 return IsDirect(arc) && Head(arc) == node;
1443 }
1444
1445 // Returns true if arc is outgoing from node.
1446 bool IsOutgoing(ArcIndexType arc, NodeIndexType node) const {
1447 return IsDirect(arc) && Tail(arc) == node;
1448 }
1449
1450 // Recreates the next_adjacent_arc_ and first_incident_arc_ variables from
1451 // the array head_ in O(n + m) time.
1452 // This is useful if head_ array has been sorted according to a given
1453 // criterion, for example.
1456 for (ArcIndexType arc = kFirstArc; arc < max_num_arcs_; ++arc) {
1457 Attach(arc);
1458 }
1459 representation_clean_ = true;
1460 }
1461
1462 // Returns a debug string containing all the information contained in the
1463 // data structure in raw form.
1464 std::string DebugString() const {
1465 DCHECK(representation_clean_);
1466 std::string result = "Arcs:(node, next arc) :\n";
1467 for (ArcIndexType arc = -num_arcs_; arc < num_arcs_; ++arc) {
1468 result += " " + ArcDebugString(arc) + ":(" + NodeDebugString(head_[arc]) +
1469 "," + ArcDebugString(next_adjacent_arc_[arc]) + ")\n";
1470 }
1471 result += "Node:First arc :\n";
1472 for (NodeIndexType node = kFirstNode; node < num_nodes_; ++node) {
1473 result += " " + NodeDebugString(node) + ":" +
1474 ArcDebugString(first_incident_arc_[node]) + "\n";
1475 }
1476 return result;
1477 }
1478
1479 private:
1480 // Handles reserving space in the next_adjacent_arc_ and head_
1481 // arrays, which are always present and are therefore in the base
1482 // class. Although they reside in the base class, those two arrays
1483 // are maintained differently by different derived classes,
1484 // depending on whether the derived class stores reverse arcs. Hence
1485 // the code to set those arrays up is in a method of the derived
1486 // class.
1487 void ReserveInternal(NodeIndexType new_max_num_nodes,
1488 ArcIndexType new_max_num_arcs) {
1489 head_.Reserve(-new_max_num_arcs, new_max_num_arcs - 1);
1490 next_adjacent_arc_.Reserve(-new_max_num_arcs, new_max_num_arcs - 1);
1491 for (ArcIndexType arc = -new_max_num_arcs; arc < -max_num_arcs_; ++arc) {
1494 }
1495 for (ArcIndexType arc = max_num_arcs_; arc < new_max_num_arcs; ++arc) {
1498 }
1499 }
1500
1501 // Returns the first incoming arc for node.
1502 ArcIndexType FirstIncomingArc(const NodeIndexType node) const {
1503 DCHECK_LE(kFirstNode, node);
1504 DCHECK_GE(max_num_nodes_, node);
1505 return FindNextIncomingArc(FirstOutgoingOrOppositeIncomingArc(node));
1506 }
1507
1508 // Returns the incoming arc following the argument in the adjacency list.
1509 ArcIndexType NextIncomingArc(const ArcIndexType arc) const {
1510 DCHECK(CheckArcValidity(arc));
1511 DCHECK(IsReverse(arc));
1512 return FindNextIncomingArc(NextAdjacentArc(arc));
1513 }
1514
1515 // Handles the part of AddArc() that is not in common with other
1516 // graph classes based on the EbertGraphBase template.
1517 void RecordArc(ArcIndexType arc, NodeIndexType tail, NodeIndexType head) {
1519 head_.Set(arc, head);
1520 Attach(arc);
1521 }
1522
1523 // Using the SetTail() method implies that the BuildRepresentation()
1524 // method must be called to restore consistency before the graph is
1525 // used.
1526 void SetTail(const ArcIndexType arc, const NodeIndexType tail) {
1527 representation_clean_ = false;
1529 }
1530
1531 // Utility method to attach a new arc.
1532 void Attach(ArcIndexType arc) {
1533 DCHECK(CheckArcValidity(arc));
1534 const NodeIndexType tail = head_[Opposite(arc)];
1535 DCHECK(IsNodeValid(tail));
1538 const NodeIndexType head = head_[arc];
1539 DCHECK(IsNodeValid(head));
1542 }
1543
1544 // Utility method that finds the next outgoing arc.
1545 ArcIndexType FindNextOutgoingArc(ArcIndexType arc) const {
1546 DCHECK(CheckArcBounds(arc));
1547 while (IsReverse(arc)) {
1549 DCHECK(CheckArcBounds(arc));
1550 }
1551 return arc;
1552 }
1553
1554 // Utility method that finds the next incoming arc.
1555 ArcIndexType FindNextIncomingArc(ArcIndexType arc) const {
1556 DCHECK(CheckArcBounds(arc));
1557 while (IsDirect(arc)) {
1559 DCHECK(CheckArcBounds(arc));
1560 }
1561 return arc;
1562 }
1563};
1564
1565// A forward-star-only graph representation for greater efficiency in
1566// those algorithms that don't need reverse arcs.
1567template <typename NodeIndexType, typename ArcIndexType>
1569 : public EbertGraphBase<NodeIndexType, ArcIndexType,
1570 ForwardEbertGraph<NodeIndexType, ArcIndexType> > {
1571 typedef EbertGraphBase<NodeIndexType, ArcIndexType,
1574 friend class EbertGraphBase<NodeIndexType, ArcIndexType,
1575 ForwardEbertGraph<NodeIndexType, ArcIndexType> >;
1576 friend class StarGraphBase<NodeIndexType, ArcIndexType,
1577 ForwardEbertGraph<NodeIndexType, ArcIndexType> >;
1578
1580 using Base::Initialize;
1583
1585 using Base::head_;
1586 using Base::max_num_arcs_;
1589 using Base::num_arcs_;
1590 using Base::num_nodes_;
1592
1593 public:
1594#if !SWIG
1595 using Base::Head;
1596 using Base::IsNodeValid;
1597
1598 using Base::kFirstArc;
1599 using Base::kFirstNode;
1600 using Base::kNilArc;
1601 using Base::kNilNode;
1602#endif // SWIG
1603
1604 typedef NodeIndexType NodeIndex;
1605 typedef ArcIndexType ArcIndex;
1606
1608
1612
1614
1615 // Utility function to check that an arc index is within the bounds.
1616 // It is exported so that users of the ForwardEbertGraph class can use it.
1617 // To be used in a DCHECK.
1618 bool CheckArcBounds(const ArcIndexType arc) const {
1619 return (arc == kNilArc) || (arc >= kFirstArc && arc < max_num_arcs_);
1620 }
1621
1622 // Utility function to check that an arc index is within the bounds AND
1623 // different from kNilArc.
1624 // It is exported so that users of the ForwardEbertGraph class can use it.
1625 // To be used in a DCHECK.
1626 bool CheckArcValidity(const ArcIndexType arc) const {
1627 return (arc != kNilArc) && (arc >= kFirstArc && arc < max_num_arcs_);
1628 }
1629
1630 // Returns true if arc is a valid index into the (*tail_) array.
1631 bool CheckTailIndexValidity(const ArcIndexType arc) const {
1632 return (tail_ != nullptr) && (arc >= kFirstArc) &&
1633 (arc <= tail_->max_index());
1634 }
1635
1636 // Returns the tail or start-node of arc.
1637 NodeIndexType Tail(const ArcIndexType arc) const {
1638 DCHECK(CheckArcValidity(arc));
1639 DCHECK(CheckTailIndexValidity(arc));
1640 return (*tail_)[arc];
1641 }
1642
1643 // Returns true if arc is incoming to node.
1644 bool IsIncoming(ArcIndexType arc, NodeIndexType node) const {
1645 return IsDirect(arc) && Head(arc) == node;
1646 }
1647
1648 // Recreates the next_adjacent_arc_ and first_incident_arc_
1649 // variables from the arrays head_ and tail_ in O(n + m) time. This
1650 // is useful if the head_ and tail_ arrays have been sorted
1651 // according to a given criterion, for example.
1654 DCHECK(TailArrayComplete());
1655 for (ArcIndexType arc = kFirstArc; arc < max_num_arcs_; ++arc) {
1656 DCHECK(CheckTailIndexValidity(arc));
1657 Attach((*tail_)[arc], arc);
1658 }
1659 representation_clean_ = true;
1660 }
1661
1663 // If (*tail_) is already allocated, we have the invariant that
1664 // its contents are canonical, so we do not need to do anything
1665 // here in that case except return true.
1666 if (tail_ == nullptr) {
1667 if (!representation_clean_) {
1668 // We have been asked to build the (*tail_) array, but we have
1669 // no valid information from which to build it. The graph is
1670 // in an unrecoverable, inconsistent state.
1671 return false;
1672 }
1673 // Reallocate (*tail_) and rebuild its contents from the
1674 // adjacency lists.
1675 tail_.reset(new ZVector<NodeIndexType>);
1676 tail_->Reserve(kFirstArc, max_num_arcs_ - 1);
1677 typename Base::NodeIterator node_it(*this);
1678 for (; node_it.Ok(); node_it.Next()) {
1679 NodeIndexType node = node_it.Index();
1680 typename Base::OutgoingArcIterator arc_it(*this, node);
1681 for (; arc_it.Ok(); arc_it.Next()) {
1682 (*tail_)[arc_it.Index()] = node;
1683 }
1684 }
1685 }
1686 DCHECK(TailArrayComplete());
1687 return true;
1688 }
1689
1690 void ReleaseTailArray() { tail_.reset(nullptr); }
1691
1692 // To be used in a DCHECK().
1693 bool TailArrayComplete() const {
1694 CHECK(tail_);
1695 for (ArcIndexType arc = kFirstArc; arc < num_arcs_; ++arc) {
1697 CHECK(IsNodeValid((*tail_)[arc]));
1698 }
1699 return true;
1700 }
1701
1702 // Returns a debug string containing all the information contained in the
1703 // data structure in raw form.
1704 std::string DebugString() const {
1705 DCHECK(representation_clean_);
1706 std::string result = "Arcs:(node, next arc) :\n";
1707 for (ArcIndexType arc = kFirstArc; arc < num_arcs_; ++arc) {
1708 result += " " + ArcDebugString(arc) + ":(" + NodeDebugString(head_[arc]) +
1709 "," + ArcDebugString(next_adjacent_arc_[arc]) + ")\n";
1710 }
1711 result += "Node:First arc :\n";
1712 for (NodeIndexType node = kFirstNode; node < num_nodes_; ++node) {
1713 result += " " + NodeDebugString(node) + ":" +
1714 ArcDebugString(first_incident_arc_[node]) + "\n";
1715 }
1716 return result;
1717 }
1718
1719 private:
1720 // Reserves space for the (*tail_) array.
1721 //
1722 // This method is separate from ReserveInternal() because our
1723 // practice of making the (*tail_) array optional implies that the
1724 // tail_ pointer might not be constructed when the ReserveInternal()
1725 // method is called. Therefore we have this method also, and we
1726 // ensure that it is called only when tail_ is guaranteed to have
1727 // been initialized.
1728 void ReserveTailArray(ArcIndexType new_max_num_arcs) {
1729 if (tail_ != nullptr) {
1730 // The (*tail_) values are already canonical, so we're just
1731 // reserving additional space for new arcs that haven't been
1732 // added yet.
1733 if (tail_->Reserve(kFirstArc, new_max_num_arcs - 1)) {
1734 for (ArcIndexType arc = tail_->max_index() + 1; arc < new_max_num_arcs;
1735 ++arc) {
1736 tail_->Set(arc, kNilNode);
1737 }
1738 }
1739 }
1740 }
1741
1742 // Reserves space for the arrays indexed by arc indices, except
1743 // (*tail_) even if it is present. We cannot grow the (*tail_) array
1744 // in this method because this method is called from
1745 // Base::Reserve(), which in turn is called from the base template
1746 // class constructor. That base class constructor is called on *this
1747 // before tail_ is constructed. Hence when this method is called,
1748 // tail_ might contain garbage. This method can safely refer only to
1749 // fields of the base template class, not to fields of *this outside
1750 // the base template class.
1751 //
1752 // The strange situation in which this method of a derived class can
1753 // refer only to members of the base class arises because different
1754 // derived classes use the data members of the base class in
1755 // slightly different ways. The purpose of this derived class
1756 // method, then, is only to encode the derived-class-specific
1757 // conventions for how the derived class uses the data members of
1758 // the base class.
1759 //
1760 // To be specific, the forward-star graph representation, lacking
1761 // reverse arcs, allocates only the positive index range for the
1762 // head_ and next_adjacent_arc_ arrays, while the general
1763 // representation allocates space for both positive- and
1764 // negative-indexed arcs (i.e., both forward and reverse arcs).
1765 void ReserveInternal(NodeIndexType new_max_num_nodes,
1766 ArcIndexType new_max_num_arcs) {
1767 head_.Reserve(kFirstArc, new_max_num_arcs - 1);
1768 next_adjacent_arc_.Reserve(kFirstArc, new_max_num_arcs - 1);
1769 for (ArcIndexType arc = max_num_arcs_; arc < new_max_num_arcs; ++arc) {
1772 }
1773 ReserveTailArray(new_max_num_arcs);
1774 }
1775
1776 // Handles the part of AddArc() that is not in common wth other
1777 // graph classes based on the EbertGraphBase template.
1778 void RecordArc(ArcIndexType arc, NodeIndexType tail, NodeIndexType head) {
1779 head_.Set(arc, head);
1780 Attach(tail, arc);
1781 }
1782
1783 // Using the SetTail() method implies that the BuildRepresentation()
1784 // method must be called to restore consistency before the graph is
1785 // used.
1786 void SetTail(const ArcIndexType arc, const NodeIndexType tail) {
1787 DCHECK(CheckTailIndexValidity(arc));
1788 CHECK(tail_);
1789 representation_clean_ = false;
1790 tail_->Set(arc, tail);
1791 }
1792
1793 // Utility method to attach a new arc.
1794 void Attach(NodeIndexType tail, ArcIndexType arc) {
1795 DCHECK(CheckArcValidity(arc));
1796 DCHECK(IsNodeValid(tail));
1799 const NodeIndexType head = head_[arc];
1800 DCHECK(IsNodeValid(head));
1801 // Because Attach() is a public method, keeping (*tail_) canonical
1802 // requires us to record the new arc's tail here.
1803 if (tail_ != nullptr) {
1804 DCHECK(CheckTailIndexValidity(arc));
1805 tail_->Set(arc, tail);
1806 }
1807 }
1808
1809 // Utility method that finds the next outgoing arc.
1810 ArcIndexType FindNextOutgoingArc(ArcIndexType arc) const {
1811 DCHECK(CheckArcBounds(arc));
1812 return arc;
1813 }
1814
1815 private:
1816 // Always returns true because for any ForwardEbertGraph, only
1817 // direct arcs are represented, so all valid arc indices refer to
1818 // arcs that are outgoing from their tail nodes.
1819 bool IsOutgoing(const ArcIndex unused_arc,
1820 const NodeIndex unused_node) const {
1821 return true;
1822 }
1823
1824 // Always returns true because for any ForwardEbertGraph, only
1825 // outgoing arcs are represented, so all valid arc indices refer to
1826 // direct arcs.
1827 bool IsDirect(const ArcIndex unused_arc) const { return true; }
1828
1829 // Array of node indices, not always present. (*tail_)[i] contains
1830 // the tail node of arc i. This array is not needed for normal graph
1831 // traversal operations, but is used in optimizing the graph's
1832 // layout so arcs are grouped by tail node, and can be used in one
1833 // approach to serializing the graph.
1834 //
1835 // Invariants: At any time when we are not executing a method of
1836 // this class, either tail_ == NULL or the tail_ array's contents
1837 // are kept canonical. If tail_ != NULL, any method that modifies
1838 // adjacency lists must also ensure (*tail_) is modified
1839 // correspondingly. The converse does not hold: Modifications to
1840 // (*tail_) are allowed without updating the adjacency lists. If
1841 // such modifications take place, representation_clean_ must be set
1842 // to false, of course, to indicate that the adjacency lists are no
1843 // longer current.
1844 std::unique_ptr<ZVector<NodeIndexType> > tail_;
1845};
1846
1847// Traits for EbertGraphBase types, for use in testing and clients
1848// that work with both forward-only and forward/reverse graphs.
1849//
1850// The default is to assume reverse arcs so if someone forgets to
1851// specialize the traits of a new forward-only graph type, they will
1852// get errors from tests rather than incomplete testing.
1853template <typename GraphType>
1855 static constexpr bool has_reverse_arcs = true;
1856 static constexpr bool is_dynamic = true;
1857};
1858
1859template <typename NodeIndexType, typename ArcIndexType>
1860struct graph_traits<ForwardEbertGraph<NodeIndexType, ArcIndexType> > {
1861 static constexpr bool has_reverse_arcs = false;
1862 static constexpr bool is_dynamic = true;
1863};
1864
1865template <typename NodeIndexType, typename ArcIndexType>
1866struct graph_traits<ForwardStaticGraph<NodeIndexType, ArcIndexType> > {
1867 static constexpr bool has_reverse_arcs = false;
1868 static constexpr bool is_dynamic = false;
1869};
1870
1871namespace or_internal {
1872
1873// The TailArrayBuilder class template is not expected to be used by
1874// clients. It is a helper for the TailArrayManager template.
1875//
1876// The TailArrayBuilder for graphs with reverse arcs does nothing.
1877template <typename GraphType, bool has_reverse_arcs>
1879 explicit TailArrayBuilder(GraphType* unused_graph) {}
1880
1881 bool BuildTailArray() const { return true; }
1882};
1883
1884// The TailArrayBuilder for graphs without reverse arcs calls the
1885// appropriate method on the graph from the TailArrayBuilder
1886// constructor.
1887template <typename GraphType>
1888struct TailArrayBuilder<GraphType, false> {
1889 explicit TailArrayBuilder(GraphType* graph) : graph_(graph) {}
1890
1891 bool BuildTailArray() const { return graph_->BuildTailArray(); }
1892
1893 GraphType* const graph_;
1894};
1895
1896// The TailArrayReleaser class template is not expected to be used by
1897// clients. It is a helper for the TailArrayManager template.
1898//
1899// The TailArrayReleaser for graphs with reverse arcs does nothing.
1900template <typename GraphType, bool has_reverse_arcs>
1902 explicit TailArrayReleaser(GraphType* unused_graph) {}
1903
1904 void ReleaseTailArray() const {}
1905};
1906
1907// The TailArrayReleaser for graphs without reverse arcs calls the
1908// appropriate method on the graph from the TailArrayReleaser
1909// constructor.
1910template <typename GraphType>
1911struct TailArrayReleaser<GraphType, false> {
1912 explicit TailArrayReleaser(GraphType* graph) : graph_(graph) {}
1913
1914 void ReleaseTailArray() const { graph_->ReleaseTailArray(); }
1915
1916 GraphType* const graph_;
1917};
1918
1919} // namespace or_internal
1920
1921template <typename GraphType>
1923 public:
1924 explicit TailArrayManager(GraphType* g) : graph_(g) {}
1925
1929 tail_array_builder(graph_);
1930 return tail_array_builder.BuildTailArray();
1931 }
1932
1936 tail_array_releaser(graph_);
1937 tail_array_releaser.ReleaseTailArray();
1938 }
1939
1940 private:
1941 GraphType* graph_;
1942};
1943
1944template <typename GraphType>
1946 public:
1947 explicit ArcFunctorOrderingByTailAndHead(const GraphType& graph)
1948 : graph_(graph) {}
1949
1950 bool operator()(typename GraphType::ArcIndex a,
1951 typename GraphType::ArcIndex b) const {
1952 return ((graph_.Tail(a) < graph_.Tail(b)) ||
1953 ((graph_.Tail(a) == graph_.Tail(b)) &&
1954 (graph_.Head(a) < graph_.Head(b))));
1955 }
1956
1957 private:
1958 const GraphType& graph_;
1959};
1960
1961namespace or_internal {
1962
1963// The GraphBuilderFromArcs class template is not expected to be used
1964// by clients. It is a helper for the AnnotatedGraphBuildManager
1965// template.
1966//
1967// Deletes itself upon returning the graph!
1968template <typename GraphType, bool is_dynamic>
1970 public:
1971 GraphBuilderFromArcs(typename GraphType::NodeIndex max_num_nodes,
1972 typename GraphType::ArcIndex max_num_arcs,
1973 bool sort_arcs)
1974 : num_arcs_(0), sort_arcs_(sort_arcs) {
1975 Reserve(max_num_nodes, max_num_arcs);
1976 }
1977
1978 typename GraphType::ArcIndex AddArc(typename GraphType::NodeIndex tail,
1979 typename GraphType::NodeIndex head) {
1980 DCHECK_LT(num_arcs_, max_num_arcs_);
1981 DCHECK_LT(tail, GraphType::kFirstNode + max_num_nodes_);
1982 DCHECK_LT(head, GraphType::kFirstNode + max_num_nodes_);
1983 if (num_arcs_ < max_num_arcs_ &&
1984 tail < GraphType::kFirstNode + max_num_nodes_ &&
1985 head < GraphType::kFirstNode + max_num_nodes_) {
1986 typename GraphType::ArcIndex result = GraphType::kFirstArc + num_arcs_;
1987 arcs_.push_back(std::make_pair(tail, head));
1988 num_arcs_ += 1;
1989 return result;
1990 } else {
1991 // Too many arcs or node index out of bounds!
1992 return GraphType::kNilArc;
1993 }
1994 }
1995
1996 // Builds the graph from the given arcs.
1998 client_cycle_handler) {
1999 GraphType* graph = new GraphType(max_num_nodes_, num_arcs_, sort_arcs_,
2000 &arcs_, client_cycle_handler);
2001 delete this;
2002 return graph;
2003 }
2004
2005 private:
2006 bool Reserve(typename GraphType::NodeIndex new_max_num_nodes,
2007 typename GraphType::ArcIndex new_max_num_arcs) {
2008 max_num_nodes_ = new_max_num_nodes;
2009 max_num_arcs_ = new_max_num_arcs;
2010 arcs_.reserve(new_max_num_arcs);
2011 return true;
2012 }
2013
2014 typename GraphType::NodeIndex max_num_nodes_;
2015 typename GraphType::ArcIndex max_num_arcs_;
2016 typename GraphType::ArcIndex num_arcs_;
2017
2018 std::vector<
2019 std::pair<typename GraphType::NodeIndex, typename GraphType::NodeIndex> >
2020 arcs_;
2021
2022 const bool sort_arcs_;
2023};
2024
2025// Trivial delegating specialization for dynamic graphs.
2026//
2027// Deletes itself upon returning the graph!
2028template <typename GraphType>
2029class GraphBuilderFromArcs<GraphType, true> {
2030 public:
2031 GraphBuilderFromArcs(typename GraphType::NodeIndex max_num_nodes,
2032 typename GraphType::ArcIndex max_num_arcs,
2033 bool sort_arcs)
2034 : graph_(new GraphType(max_num_nodes, max_num_arcs)),
2035 sort_arcs_(sort_arcs) {}
2036
2037 bool Reserve(const typename GraphType::NodeIndex new_max_num_nodes,
2038 const typename GraphType::ArcIndex new_max_num_arcs) {
2039 return graph_->Reserve(new_max_num_nodes, new_max_num_arcs);
2040 }
2041
2042 typename GraphType::ArcIndex AddArc(
2043 const typename GraphType::NodeIndex tail,
2044 const typename GraphType::NodeIndex head) {
2045 return graph_->AddArc(tail, head);
2046 }
2047
2049 client_cycle_handler) {
2050 if (sort_arcs_) {
2051 TailArrayManager<GraphType> tail_array_manager(graph_);
2053 ArcFunctorOrderingByTailAndHead<GraphType> arc_ordering(*graph_);
2054 graph_->GroupForwardArcsByFunctor(arc_ordering, client_cycle_handler);
2055 tail_array_manager.ReleaseTailArrayIfForwardGraph();
2056 }
2057 GraphType* result = graph_;
2058 delete this;
2059 return result;
2060 }
2061
2062 private:
2063 GraphType* const graph_;
2064 const bool sort_arcs_;
2065};
2066
2067} // namespace or_internal
2068
2069template <typename GraphType>
2072 GraphType, graph_traits<GraphType>::is_dynamic> {
2073 public:
2074 AnnotatedGraphBuildManager(typename GraphType::NodeIndex num_nodes,
2075 typename GraphType::ArcIndex num_arcs,
2076 bool sort_arcs)
2077 : or_internal::GraphBuilderFromArcs<GraphType,
2078 graph_traits<GraphType>::is_dynamic>(
2079 num_nodes, num_arcs, sort_arcs) {}
2080};
2081
2082// Builds a directed line graph for 'graph' (see "directed line graph" in
2083// http://en.wikipedia.org/wiki/Line_graph). Arcs of the original graph
2084// become nodes and the new graph contains only nodes created from arcs in the
2085// original graph (we use the notation (a->b) for these new nodes); the index
2086// of the node (a->b) in the new graph is exactly the same as the index of the
2087// arc a->b in the original graph.
2088// An arc from node (a->b) to node (c->d) in the new graph is added if and only
2089// if b == c in the original graph.
2090// This method expects that 'line_graph' is an empty graph (it has no nodes
2091// and no arcs).
2092// Returns false on an error.
2093template <typename GraphType>
2094bool BuildLineGraph(const GraphType& graph, GraphType* const line_graph) {
2095 if (line_graph == nullptr) {
2096 LOG(DFATAL) << "line_graph must not be NULL";
2097 return false;
2098 }
2099 if (line_graph->num_nodes() != 0) {
2100 LOG(DFATAL) << "line_graph must be empty";
2101 return false;
2102 }
2103 typedef typename GraphType::ArcIterator ArcIterator;
2104 typedef typename GraphType::OutgoingArcIterator OutgoingArcIterator;
2105 // Sizing then filling.
2106 typename GraphType::ArcIndex num_arcs = 0;
2107 for (ArcIterator arc_iterator(graph); arc_iterator.Ok();
2108 arc_iterator.Next()) {
2109 const typename GraphType::ArcIndex arc = arc_iterator.Index();
2110 const typename GraphType::NodeIndex head = graph.Head(arc);
2111 for (OutgoingArcIterator iterator(graph, head); iterator.Ok();
2112 iterator.Next()) {
2113 ++num_arcs;
2114 }
2115 }
2116 line_graph->Reserve(graph.num_arcs(), num_arcs);
2117 for (ArcIterator arc_iterator(graph); arc_iterator.Ok();
2118 arc_iterator.Next()) {
2119 const typename GraphType::ArcIndex arc = arc_iterator.Index();
2120 const typename GraphType::NodeIndex head = graph.Head(arc);
2121 for (OutgoingArcIterator iterator(graph, head); iterator.Ok();
2122 iterator.Next()) {
2123 line_graph->AddArc(arc, iterator.Index());
2124 }
2125 }
2126 return true;
2127}
2128
2129} // namespace operations_research
2130#endif // OR_TOOLS_GRAPH_EBERT_GRAPH_H_
AnnotatedGraphBuildManager(typename GraphType::NodeIndex num_nodes, typename GraphType::ArcIndex num_arcs, bool sort_arcs)
bool operator()(typename GraphType::ArcIndex a, typename GraphType::ArcIndex b) const
void SetIndexFromTemp(ArcIndexType destination) const override
void SetIndexFromIndex(ArcIndexType source, ArcIndexType destination) const override
CycleHandlerForAnnotatedArcs & operator=(const CycleHandlerForAnnotatedArcs &)=delete
CycleHandlerForAnnotatedArcs(PermutationCycleHandler< ArcIndexType > *annotation_handler, DerivedGraph *graph)
void SetSeen(ArcIndexType *permutation_element) const override
CycleHandlerForAnnotatedArcs(const CycleHandlerForAnnotatedArcs &)=delete
This type is neither copyable nor movable.
void SetIndexFromTemp(ArcIndexType destination) const override
Sets a data element from the temporary.
void SetIndexFromIndex(ArcIndexType source, ArcIndexType destination) const override
Moves a data element one step along its cycle.
bool Unseen(ArcIndexType permutation_element) const override
static const ArcIndexType kMaxNumArcs
ZVector< NodeIndexType > head_
Array of node indices. head_[i] contains the head node of arc i.
ZVector< ArcIndexType > next_adjacent_arc_
bool Reserve(NodeIndexType new_max_num_nodes, ArcIndexType new_max_num_arcs)
static const NodeIndexType kFirstNode
The index of the first node in the graph.
static const NodeIndexType kNilNode
The index of the 'nil' node in the graph.
static const ArcIndexType kFirstArc
The index of the first arc in the graph.
ArcIndexType NextOutgoingArc(const NodeIndexType unused_node, const ArcIndexType arc) const
Returns the outgoing arc following the argument in the adjacency list.
NodeIndexType max_num_nodes_
The maximum number of nodes that the graph can hold.
ArcIndexType end_arc_index() const
ArcIndexType FirstOutgoingOrOppositeIncomingArc(const NodeIndexType node) const
Returns the first arc in node's incidence list.
static const ArcIndexType kNilArc
The index of the 'nil' arc in the graph.
ArcIndexType num_arcs_
The current number of arcs held by the graph.
void GroupForwardArcsByFunctor(const ArcIndexTypeStrictWeakOrderingFunctor &compare, PermutationCycleHandler< ArcIndexType > *annotation_handler)
ArcIndexType NextAdjacentArc(const ArcIndexType arc) const
Returns the next arc following the passed argument in its adjacency list.
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
ArcIndexType max_num_arcs_
The maximum number of arcs that the graph can hold.
bool IsNodeValid(NodeIndexType node) const
NodeIndexType num_nodes_
The maximum index of the node currently held by the graph.
static const NodeIndexType kMaxNumNodes
The maximum possible node index in the graph.
void Initialize(NodeIndexType max_num_nodes, ArcIndexType max_num_arcs)
ZVector< ArcIndexType > first_incident_arc_
Iterator class for traversing the incoming arcs associated to a given node.
void operator=(const IncomingArcIterator &iterator)
Can only assign from an iterator on the same graph.
IncomingArcIterator(const EbertGraph &graph, NodeIndexType node, ArcIndexType arc)
bool Ok() const
Returns true unless all the incoming arcs have been traversed.
ArcIndexType Index() const
Returns the index of the arc currently pointed to by the iterator.
IncomingArcIterator(const EbertGraph &graph, NodeIndexType node)
void Next()
Advances the current incoming arc index.
OutgoingOrOppositeIncomingArcIterator(const EbertGraph &graph, NodeIndexType node)
ArcIndexType Index() const
Returns the index of the arc currently pointed to by the iterator.
bool Ok() const
Returns true unless all the adjancent arcs have been traversed.
OutgoingOrOppositeIncomingArcIterator(const EbertGraph &graph, NodeIndexType node, ArcIndexType arc)
void operator=(const OutgoingOrOppositeIncomingArcIterator &iterator)
Can only assign from an iterator on the same graph.
ArcIndexType Opposite(const ArcIndexType arc) const
NodeIndexType DirectArcHead(const ArcIndexType arc) const
bool IsOutgoingOrOppositeIncoming(ArcIndexType arc, NodeIndexType node) const
Returns true if arc is incident to node.
EbertGraph(NodeIndexType max_num_nodes, ArcIndexType max_num_arcs)
bool IsReverse(const ArcIndexType arc) const
Returns true if the arc is in the reverse direction.
bool CheckArcBounds(const ArcIndexType arc) const
NodeIndexType Tail(const ArcIndexType arc) const
Returns the tail or start-node of arc.
bool CheckArcValidity(const ArcIndexType arc) const
ArcIndexType DirectArc(const ArcIndexType arc) const
Returns the arc in normal/direct direction.
NodeIndexType DirectArcTail(const ArcIndexType arc) const
bool IsDirect(const ArcIndexType arc) const
Returns true if the arc is direct.
bool IsIncoming(ArcIndexType arc, NodeIndexType node) const
Returns true if arc is incoming to node.
ArcIndexType ReverseArc(const ArcIndexType arc) const
Returns the arc in reverse direction.
bool IsOutgoing(ArcIndexType arc, NodeIndexType node) const
Returns true if arc is outgoing from node.
std::string DebugString() const
bool IsIncoming(ArcIndexType arc, NodeIndexType node) const
Returns true if arc is incoming to node.
bool CheckArcValidity(const ArcIndexType arc) const
ForwardEbertGraph(NodeIndexType max_num_nodes, ArcIndexType max_num_arcs)
NodeIndexType Tail(const ArcIndexType arc) const
Returns the tail or start-node of arc.
bool CheckTailIndexValidity(const ArcIndexType arc) const
Returns true if arc is a valid index into the (*tail_) array.
bool TailArrayComplete() const
To be used in a DCHECK().
bool CheckArcBounds(const ArcIndexType arc) const
CycleHandlerForAnnotatedArcs(PermutationCycleHandler< ArcIndexType > *annotation_handler, NodeIndexType *data)
CycleHandlerForAnnotatedArcs & operator=(const CycleHandlerForAnnotatedArcs &)=delete
CycleHandlerForAnnotatedArcs(const CycleHandlerForAnnotatedArcs &)=delete
This type is neither copyable nor movable.
void SetIndexFromTemp(ArcIndexType destination) const override
void SetIndexFromIndex(ArcIndexType source, ArcIndexType destination) const override
bool CheckArcValidity(const ArcIndexType arc) const
ForwardStaticGraph(const NodeIndexType num_nodes, const ArcIndexType num_arcs, const bool sort_arcs_by_head, std::vector< std::pair< NodeIndexType, NodeIndexType > > *client_input_arcs, operations_research::PermutationCycleHandler< ArcIndexType > *const client_cycle_handler)
bool CheckArcBounds(const ArcIndexType arc) const
bool CheckTailIndexValidity(const ArcIndexType arc) const
Returns true if arc is a valid index into the (*tail_) array.
bool TailArrayComplete() const
To be used in a DCHECK().
ArcIndexType NextOutgoingArc(const NodeIndexType node, ArcIndexType arc) const
NodeIndexType Tail(const ArcIndexType arc) const
Returns the tail or start-node of arc.
bool IsIncoming(ArcIndexType arc, NodeIndexType node) const
Returns true if arc is incoming to node.
void Apply(IndexType permutation[], int permutation_start, int permutation_end)
virtual void SetIndexFromTemp(IndexType destination) const =0
Sets a data element from the temporary.
virtual void SetTempFromIndex(IndexType source)=0
virtual void SetIndexFromIndex(IndexType source, IndexType destination) const =0
Moves a data element one step along its cycle.
bool operator()(ArcIndexType a, ArcIndexType b) const
PermutationIndexComparisonByArcHead(const ZVector< NodeIndexType > &head)
Iterator class for traversing the arcs in the graph.
void Next()
Advances the current arc index.
ArcIndexType Index() const
Returns the index of the arc currently pointed to by the iterator.
bool Ok() const
Returns true unless all the arcs have been traversed.
Iterator class for traversing all the nodes in the graph.
bool Ok() const
Returns true unless all the nodes have been traversed.
NodeIndexType Index() const
Returns the index of the node currently pointed to by the iterator.
void Next()
Advances the current node index.
Iterator class for traversing the outgoing arcs associated to a given node.
OutgoingArcIterator(const DerivedGraph &graph, NodeIndexType node)
void operator=(const OutgoingArcIterator &iterator)
Can only assign from an iterator on the same graph.
void Next()
Advances the current outgoing arc index.
OutgoingArcIterator(const DerivedGraph &graph, NodeIndexType node, ArcIndexType arc)
ArcIndexType Index() const
Returns the index of the arc currently pointed to by the iterator.
bool Ok() const
Returns true unless all the outgoing arcs have been traversed.
NodeIndexType end_node_index() const
static const ArcIndexType kMaxNumArcs
ZVector< NodeIndexType > head_
Array of node indices. head_[i] contains the head node of arc i.
static const NodeIndexType kFirstNode
The index of the first node in the graph.
static const NodeIndexType kNilNode
The index of the 'nil' node in the graph.
ArcIndexType NextArc(const ArcIndexType arc) const
std::string ArcDebugString(const ArcIndexType arc) const
static const ArcIndexType kFirstArc
The index of the first arc in the graph.
NodeIndexType max_num_nodes() const
Returns the maximum possible number of nodes in the graph.
NodeIndexType max_num_nodes_
The maximum number of nodes that the graph can hold.
std::string NodeDebugString(const NodeIndexType node) const
ArcIndexType end_arc_index() const
NodeIndexType max_end_node_index() const
static const ArcIndexType kNilArc
The index of the 'nil' arc in the graph.
ArcIndexType num_arcs_
The current number of arcs held by the graph.
NodeIndexType StartNode(NodeIndexType node) const
ArcIndexType max_end_arc_index() const
NodeIndexType NextNode(const NodeIndexType node) const
ArcIndexType max_num_arcs() const
ArcIndexType max_num_arcs_
The maximum number of arcs that the graph can hold.
ArcIndexType StartArc(ArcIndexType arc) const
NodeIndexType num_nodes() const
Returns the number of nodes in the graph.
NodeIndexType Head(const ArcIndexType arc) const
Returns the head or end-node of arc.
ArcIndexType LookUpArc(const NodeIndexType tail, const NodeIndexType head) const
bool IsNodeValid(NodeIndexType node) const
NodeIndexType num_nodes_
The maximum index of the node currently held by the graph.
ArcIndexType FirstOutgoingArc(const NodeIndexType node) const
Returns the first outgoing arc for node.
static const NodeIndexType kMaxNumNodes
The maximum possible node index in the graph.
ZVector< ArcIndexType > first_incident_arc_
bool BuildTailArrayFromAdjacencyListsIfForwardGraph() const
bool Reserve(int64_t new_min_index, int64_t new_max_index)
Definition zvector.h:95
void Set(int64_t index, T value)
Sets to value the content of the array at index.
Definition zvector.h:85
int64_t max_index() const
Definition zvector.h:57
void SetAll(T value)
Sets all the elements in the array to value.
Definition zvector.h:130
GraphType * Graph(PermutationCycleHandler< typename GraphType::ArcIndex > *client_cycle_handler)
bool Reserve(const typename GraphType::NodeIndex new_max_num_nodes, const typename GraphType::ArcIndex new_max_num_arcs)
GraphBuilderFromArcs(typename GraphType::NodeIndex max_num_nodes, typename GraphType::ArcIndex max_num_arcs, bool sort_arcs)
GraphType::ArcIndex AddArc(const typename GraphType::NodeIndex tail, const typename GraphType::NodeIndex head)
GraphType * Graph(PermutationCycleHandler< typename GraphType::ArcIndex > *client_cycle_handler)
Builds the graph from the given arcs.
GraphBuilderFromArcs(typename GraphType::NodeIndex max_num_nodes, typename GraphType::ArcIndex max_num_arcs, bool sort_arcs)
GraphType::ArcIndex AddArc(typename GraphType::NodeIndex tail, typename GraphType::NodeIndex head)
int64_t b
Definition table.cc:45
int64_t a
Definition table.cc:44
int arc
In SWIG mode, we don't want anything besides these top-level includes.
ZVector< NodeIndex > NodeIndexArray
ForwardEbertGraph< NodeIndex, ArcIndex > ForwardStarGraph
ZVector< FlowQuantity > QuantityArray
ZVector< ArcIndex > ArcIndexArray
ForwardStaticGraph< NodeIndex, ArcIndex > ForwardStarStaticGraph
bool BuildLineGraph(const GraphType &graph, GraphType *const line_graph)
EbertGraph< NodeIndex, ArcIndex > StarGraph
ZVector< CostValue > CostArray
int head
int tail
std::optional< int64_t > end
*vec begin()+0)
static constexpr bool has_reverse_arcs
static constexpr bool is_dynamic