Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. More...
Classes | |
| class | BaseGraph |
| Base class of all Graphs implemented here. More... | |
| class | CompleteBipartiteGraph |
| CompleteBipartiteGraph implementation ------------------------------------— Nodes and arcs are implicit and not stored. More... | |
| class | CompleteGraph |
| CompleteGraph implementation ---------------------------------------------— Nodes and arcs are implicit and not stored. More... | |
| class | ListGraph |
| Basic graph implementation without reverse arc. More... | |
| class | ReverseArcListGraph |
| Extends the ListGraph by also storing the reverse arcs. More... | |
| class | ReverseArcMixedGraph |
| This graph is a mix between the ReverseArcListGraph and the ReverseArcStaticGraph. More... | |
| class | ReverseArcStaticGraph |
| StaticGraph with reverse arc. More... | |
| class | StaticGraph |
| Most efficient implementation of a graph without reverse arcs: More... | |
| class | SVector |
| Forward declaration. More... | |
| class | UndirectedAdjacencyListsOfDirectedGraph |
| This can be used to view a directed graph (that supports reverse arcs) from graph.h as un undirected graph: operator[](node) returns a pseudo-container that iterates over all nodes adjacent to "node" (from outgoing or incoming arcs). More... | |
Typedefs | |
| typedef ListGraph | Graph |
| Defining the simplest Graph interface as Graph for convenience. More... | |
Enumerations | |
| enum | GraphToStringFormat { PRINT_GRAPH_ARCS, PRINT_GRAPH_ADJACENCY_LISTS, PRINT_GRAPH_ADJACENCY_LISTS_SORTED } |
| Returns a std::string representation of a graph. More... | |
Functions | |
| template<class UndirectedGraph > | |
| std::vector< int > | GetConnectedComponents (int num_nodes, const UndirectedGraph &graph) |
| Finds the connected components of the graph, using BFS internally. More... | |
| template<class IntVector , class Array , class ElementType > | |
| void | PermuteWithExplicitElementType (const IntVector &permutation, Array *array_to_permute, ElementType unused) |
| Permutes the elements of array_to_permute: element #i will be moved to position permutation[i]. More... | |
| template<class IntVector , class Array > | |
| void | Permute (const IntVector &permutation, Array *array_to_permute) |
| template<class IntVector > | |
| void | Permute (const IntVector &permutation, std::vector< bool > *array_to_permute) |
| We need a specialization for std::vector<bool>, because the default code uses (*array_to_permute)[0] as ElementType, which isn't 'bool' in that case. More... | |
| DEFINE_RANGE_BASED_ARC_ITERATION (ListGraph, Outgoing, Base::kNilArc) | |
| ListGraph implementation -------------------------------------------------—. More... | |
| DEFINE_RANGE_BASED_ARC_ITERATION (StaticGraph, Outgoing, DirectArcLimit(node)) | |
| StaticGraph implementation -----------------------------------------------—. More... | |
| DEFINE_RANGE_BASED_ARC_ITERATION (ReverseArcListGraph, Outgoing, Base::kNilArc) | |
| ReverseArcListGraph implementation ---------------------------------------—. More... | |
| DEFINE_RANGE_BASED_ARC_ITERATION (ReverseArcListGraph, Incoming, Base::kNilArc) | |
| DEFINE_RANGE_BASED_ARC_ITERATION (ReverseArcListGraph, OutgoingOrOppositeIncoming, Base::kNilArc) | |
| DEFINE_RANGE_BASED_ARC_ITERATION (ReverseArcListGraph, OppositeIncoming, Base::kNilArc) | |
| DEFINE_RANGE_BASED_ARC_ITERATION (ReverseArcStaticGraph, Outgoing, DirectArcLimit(node)) | |
| ReverseArcStaticGraph implementation -------------------------------------—. More... | |
| DEFINE_RANGE_BASED_ARC_ITERATION (ReverseArcStaticGraph, Incoming, ReverseArcLimit(node)) | |
| DEFINE_RANGE_BASED_ARC_ITERATION (ReverseArcStaticGraph, OutgoingOrOppositeIncoming, DirectArcLimit(node)) | |
| DEFINE_RANGE_BASED_ARC_ITERATION (ReverseArcStaticGraph, OppositeIncoming, ReverseArcLimit(node)) | |
| DEFINE_RANGE_BASED_ARC_ITERATION (ReverseArcMixedGraph, Outgoing, DirectArcLimit(node)) | |
| ReverseArcMixedGraph implementation --------------------------------------—. More... | |
| DEFINE_RANGE_BASED_ARC_ITERATION (ReverseArcMixedGraph, Incoming, Base::kNilArc) | |
| DEFINE_RANGE_BASED_ARC_ITERATION (ReverseArcMixedGraph, OutgoingOrOppositeIncoming, DirectArcLimit(node)) | |
| DEFINE_RANGE_BASED_ARC_ITERATION (ReverseArcMixedGraph, OppositeIncoming, Base::kNilArc) | |
| template<class Graph > | |
| std::string | GraphToString (const Graph &graph, GraphToStringFormat format) |
| Implementations of the templated methods. More... | |
| false | ValueOrDie ()) |
| Read a graph file in the simple ".g" format: the file should be a text file containing only space-separated integers, whose first line is: <num nodes>=""> <num edges>=""> [<num_colors> <index of first node with color #1> <index of first node with color #2> ...] and whose subsequent lines represent edges if "directed" is false, or arcs if "directed" is true: <node1> <node2>. More... | |
| * | if (!error_or_graph.ok()) |
| template<class Graph > | |
| ***util::StatusOr< Graph * > | ReadGraphFile (const std::string &filename, bool directed, std::vector< int > *num_nodes_with_color_or_null) |
| template<class Graph > | |
| util::Status | WriteGraphToFile (const Graph &graph, const std::string &filename, bool directed, const std::vector< int > &num_nodes_with_color) |
| Writes a graph to the ".g" file format described above. More... | |
| template<class Graph > | |
| util::StatusOr< Graph * > | ReadGraphFile (const std::string &filename, bool directed, std::vector< int > *num_nodes_with_color_or_null) |
| template<class Graph > | |
| bool | GraphHasSelfArcs (const Graph &graph) |
| Here's a set of simple diagnosis tools. More... | |
| template<class Graph > | |
| bool | GraphHasDuplicateArcs (const Graph &graph) |
| template<class Graph > | |
| bool | GraphIsSymmetric (const Graph &graph) |
| template<class Graph > | |
| bool | GraphIsWeaklyConnected (const Graph &graph) |
| template<class Graph > | |
| std::unique_ptr< Graph > | CopyGraph (const Graph &graph) |
| Returns a fresh copy of a given graph. More... | |
| template<class Graph > | |
| std::unique_ptr< Graph > | RemapGraph (const Graph &graph, const std::vector< int > &new_node_index) |
| Creates a remapped copy of graph "graph", where node i becomes node new_node_index[i]. More... | |
| template<class Graph > | |
| std::unique_ptr< Graph > | GetSubgraphOfNodes (const Graph &graph, const std::vector< int > &nodes) |
| Gets the induced subgraph of "graph" restricted to the nodes in "nodes": the resulting graph will have exactly nodes.size() nodes, and its node #0 will be the former graph's node #nodes[0], etc. More... | |
| template<class Graph > | |
| std::vector< int > | GetWeaklyConnectedComponents (const Graph &graph) |
| Computes the weakly connected components of a directed graph that provides the OutgoingOrOppositeIncomingArcs() API, and returns them as a mapping from node to component index. More... | |
| bool | IsSubsetOf0N (const std::vector< int > &v, int n) |
| Returns true iff the given vector is a subset of [0..n-1], i.e. More... | |
| bool | IsValidPermutation (const std::vector< int > &v) |
| Returns true iff the given vector is a permutation of [0..size()-1]. More... | |
| template<class Graph > | |
| std::unique_ptr< Graph > | RemoveSelfArcsAndDuplicateArcs (const Graph &graph) |
| Returns a copy of "graph", without self-arcs and duplicate arcs. More... | |
| template<class Graph > | |
| void | RemoveCyclesFromPath (const Graph &graph, std::vector< int > *arc_path) |
| Given an arc path, changes it to a sub-path with the same source and destination but without any cycle. More... | |
| template<class Graph > | |
| bool | PathHasCycle (const Graph &graph, const std::vector< int > &arc_path) |
| Returns true iff the given path contains a cycle. More... | |
| template<class Graph > | |
| std::vector< int > | ComputeOnePossibleReverseArcMapping (const Graph &graph, bool die_if_not_symmetric) |
| Returns a vector representing a mapping from arcs to arcs such that each arc is mapped to another arc with its (tail, head) flipped, if such an arc exists (otherwise it is mapped to -1). More... | |
Variables | |
| ***util::StatusOr< MyGraph * > | error_or_graph |
| < More complicated error handling. More... | |
| else | |
| false | |
| This is useful for wrapping iterators of a class that support many different iterations. More... | |
| *OutgoingArcIterator | this |
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
Implementations of the method templates.
You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Finds the connected components in an undirected graph: https://en.wikipedia.org/wiki/Connected_component_(graph_theory)
If you have a fixed graph where the node are dense integers, use GetConnectedComponents(): it's very fast and uses little memory.
If you have a more dynamic scenario where you want to incrementally add nodes or edges and query the connectivity between them, use the [Dense]ConnectedComponentsFinder class, which uses the union-find algorithm aka disjoint sets: https://en.wikipedia.org/wiki/Disjoint-set_data_structure.
You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. This file defines a generic graph interface on which most algorithms can be built and provides a few efficient implementations with a fast construction time. Its design is based on the experience acquired by the Operations Research team in their various graph algorithm implementations.
The main ideas are:
Terminology:
Provided implementations:
Utility classes & functions:
Basic usage: typedef ListGraph<> Graph; ///< Choose a graph implementation. Graph graph; for (...) { graph.AddArc(tail, head); } ... for (int node = 0; node < graph.num_nodes(); ++node) { for (const int arc : graph.OutgoingArcs(node)) { head = graph.Head(arc); tail = node; ///< or graph.Tail(arc) which is fast but not as much. } }
Iteration over the arcs touching a node:
And two more involved ones:
Note on iteration efficiency: When re-indexing the arcs it is not possible to have both the outgoing arcs and the incoming ones form a consecutive range.
It is however possible to do so for the outgoing arcs and the opposite incoming arcs. It is why the OutgoingOrOppositeIncomingArcs() and OutgoingArcs() iterations are more efficient than the IncomingArcs() one.
If you know the graph size in advance, this already set the number of nodes, reserve space for the arcs and check in DEBUG mode that you don't go over the bounds: Graph graph(num_nodes, arc_capacity);
Storing and using node annotations: std::vector<bool> is_visited(graph.num_nodes(), false); ... for (int node = 0; node < graph.num_nodes(); ++node) { if (!is_visited[node]) ... }
Storing and using arc annotations: std::vector<int> weights; for (...) { graph.AddArc(tail, head); weights.push_back(arc_weight); } ... for (const int arc : graph.OutgoingArcs(node)) { ... weights[arc] ...; }
More efficient version: typedef StaticGraph<> Graph; Graph graph(num_nodes, arc_capacity); ///< Optional, but help memory usage. std::vector<int> weights; weights.reserve(arc_capacity); ///< Optional, but help memory usage. for (...) { graph.AddArc(tail, head); weights.push_back(arc_weight); } ... std::vector<Graph::ArcIndex> permutation; graph.Build(&permutation); ///< A static graph must be Build() before usage. Permute(permutation, &weights); ///< Build() may permute the arc index. ...
Encoding an undirected graph: If you don't need arc annotation, then the best is to add two arcs for each edge (one in each direction) to a directed graph. Otherwise you can do the following.
typedef ReverseArc... Graph; Graph graph; for (...) { graph.AddArc(tail, head); ///< or graph.AddArc(head, tail) but not both. edge_annotations.push_back(value); } ... for (const Graph::NodeIndex node : graph.AllNodes()) { for (const Graph::ArcIndex arc : graph.OutgoingOrOppositeIncomingArcs(node)) { destination = graph.Head(arc); annotation = edge_annotations[arc < 0 ? graph.OppositeArc(arc) : arc]; } }
You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. A collections of i/o utilities for the Graph classes in ./graph.h.
You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Helper classes to make it easy to implement range-based for loops.
You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. A collections of utilities for the Graph classes in ./graph.h.
| typedef ListGraph util::Graph |
Returns a std::string representation of a graph.
| std::vector< int > util::ComputeOnePossibleReverseArcMapping | ( | const Graph & | graph, |
| bool | die_if_not_symmetric | ||
| ) |
Returns a vector representing a mapping from arcs to arcs such that each arc is mapped to another arc with its (tail, head) flipped, if such an arc exists (otherwise it is mapped to -1).
If the graph is symmetric, the returned mapping is bijective and reflexive, i.e. out[out[arc]] = arc for all "arc", where "out" is the returned vector. If "die_if_not_symmetric" is true, this function CHECKs() that the graph is symmetric.
Self-arcs are always mapped to themselves.
Special case: directly map any self-arc to itself.
Lookup for the reverse arc of the current one...
Found a reverse arc! Store the mapping and remove the reverse arc from the map.
Reverse arc not in the map. Add the current arc to the map.
Algorithm check, for debugging.
Special case: directly map any self-arc to itself.
Lookup for the reverse arc of the current one...
Found a reverse arc! Store the mapping and remove the reverse arc from the map.
Reverse arc not in the map. Add the current arc to the map.
Algorithm check, for debugging.
| util::DEFINE_RANGE_BASED_ARC_ITERATION | ( | ListGraph | , |
| Outgoing | , | ||
| Base::kNilArc | |||
| ) |
ListGraph implementation -------------------------------------------------—.
| util::DEFINE_RANGE_BASED_ARC_ITERATION | ( | StaticGraph | , |
| Outgoing | , | ||
| DirectArcLimit(node) | |||
| ) |
StaticGraph implementation -----------------------------------------------—.
| util::DEFINE_RANGE_BASED_ARC_ITERATION | ( | ReverseArcListGraph | , |
| Outgoing | , | ||
| Base::kNilArc | |||
| ) |
ReverseArcListGraph implementation ---------------------------------------—.
| util::DEFINE_RANGE_BASED_ARC_ITERATION | ( | ReverseArcListGraph | , |
| Incoming | , | ||
| Base::kNilArc | |||
| ) |
| util::DEFINE_RANGE_BASED_ARC_ITERATION | ( | ReverseArcListGraph | , |
| OutgoingOrOppositeIncoming | , | ||
| Base::kNilArc | |||
| ) |
| util::DEFINE_RANGE_BASED_ARC_ITERATION | ( | ReverseArcListGraph | , |
| OppositeIncoming | , | ||
| Base::kNilArc | |||
| ) |
| util::DEFINE_RANGE_BASED_ARC_ITERATION | ( | ReverseArcStaticGraph | , |
| Outgoing | , | ||
| DirectArcLimit(node) | |||
| ) |
ReverseArcStaticGraph implementation -------------------------------------—.
| util::DEFINE_RANGE_BASED_ARC_ITERATION | ( | ReverseArcStaticGraph | , |
| Incoming | , | ||
| ReverseArcLimit(node) | |||
| ) |
| util::DEFINE_RANGE_BASED_ARC_ITERATION | ( | ReverseArcStaticGraph | , |
| OutgoingOrOppositeIncoming | , | ||
| DirectArcLimit(node) | |||
| ) |
| util::DEFINE_RANGE_BASED_ARC_ITERATION | ( | ReverseArcStaticGraph | , |
| OppositeIncoming | , | ||
| ReverseArcLimit(node) | |||
| ) |
| util::DEFINE_RANGE_BASED_ARC_ITERATION | ( | ReverseArcMixedGraph | , |
| Outgoing | , | ||
| DirectArcLimit(node) | |||
| ) |
ReverseArcMixedGraph implementation --------------------------------------—.
| util::DEFINE_RANGE_BASED_ARC_ITERATION | ( | ReverseArcMixedGraph | , |
| Incoming | , | ||
| Base::kNilArc | |||
| ) |
| util::DEFINE_RANGE_BASED_ARC_ITERATION | ( | ReverseArcMixedGraph | , |
| OutgoingOrOppositeIncoming | , | ||
| DirectArcLimit(node) | |||
| ) |
| util::DEFINE_RANGE_BASED_ARC_ITERATION | ( | ReverseArcMixedGraph | , |
| OppositeIncoming | , | ||
| Base::kNilArc | |||
| ) |
| std::vector< int > util::GetConnectedComponents | ( | int | num_nodes, |
| const UndirectedGraph & | graph | ||
| ) |
Finds the connected components of the graph, using BFS internally.
Works on any undirected graph class whose nodes are dense integers and that supports the [] operator for adjacency lists: graph[x] must be an integer container listing the nodes that are adjacent to node #x. Example: std::vector<std::vector<int>>.
"Undirected" means that for all y in graph[x], x is in graph[y].
Returns the mapping from node to component index. The component indices are deterministic: Component #0 will be the one that has node #0, component #1 the one that has the lowest-index node that isn't in component #0, and so on.
Example on the following 6-node graph: 5–3–0–1 2–4 std::vector<std::vector<int>> graph = {{1, 3}, {0}, {4}, {0, 5}, {2}, {3}}; GetConnectedComponents(graph); ///< returns [0, 0, 1, 0, 1, 0].
Definition at line 289 of file connected_components.h.
| std::unique_ptr< Graph > util::GetSubgraphOfNodes | ( | const Graph & | graph, |
| const std::vector< int > & | nodes | ||
| ) |
Gets the induced subgraph of "graph" restricted to the nodes in "nodes": the resulting graph will have exactly nodes.size() nodes, and its node #0 will be the former graph's node #nodes[0], etc.
See https://en.wikipedia.org/wiki/Induced_subgraph . The "nodes" must be a valid subset (no repetitions) of [0..graph.num_nodes()-1], or the behavior is undefined (it may die).
Current complexity: O(num old nodes + num new arcs). It could easily be done in O(num new nodes + num new arcs) but with a higher constant.
Do a first pass to count the arcs, so that we don't allocate more memory than needed.
A second pass where we actually copy the subgraph. NOTE(user): there might seem to be a bit of duplication with RemapGraph(), but there is a key difference: the loop below only iterates on "nodes", which could be much smaller than all the graph's nodes.
Do a first pass to count the arcs, so that we don't allocate more memory than needed.
A second pass where we actually copy the subgraph. NOTE(user): there might seem to be a bit of duplication with RemapGraph(), but there is a key difference: the loop below only iterates on "nodes", which could be much smaller than all the graph's nodes.
| std::vector<int> util::GetWeaklyConnectedComponents | ( | const Graph & | graph | ) |
| bool util::GraphHasDuplicateArcs | ( | const Graph & | graph | ) |
| bool util::GraphHasSelfArcs | ( | const Graph & | graph | ) |
Here's a set of simple diagnosis tools.
Implementations of the templated methods.
Notes:
All these diagnosis work in O(graph size), since the inverse Ackerman function is <= 5 for all practical instances, and are very fast.
If the graph is a "static" kind, they must be finalized, except for GraphHasSelfArcs() and GraphIsWeaklyConnected() which also support non-finalized StaticGraph<>.
| bool util::GraphIsSymmetric | ( | const Graph & | graph | ) |
| bool util::GraphIsWeaklyConnected | ( | const Graph & | graph | ) |
| std::string util::GraphToString | ( | const Graph & | graph, |
| GraphToStringFormat | format | ||
| ) |
| bool util::IsSubsetOf0N | ( | const std::vector< int > & | v, |
| int | n | ||
| ) |
Returns true iff the given vector is a subset of [0..n-1], i.e.
all elements i are such that 0 <= i < n and no two elements are equal. "n" must be >= 0 or the result is undefined.
|
inline |
| bool util::PathHasCycle | ( | const Graph & | graph, |
| const std::vector< int > & | arc_path | ||
| ) |
| void util::Permute | ( | const IntVector & | permutation, |
| Array * | array_to_permute | ||
| ) |
| void util::Permute | ( | const IntVector & | permutation, |
| std::vector< bool > * | array_to_permute | ||
| ) |
| void util::PermuteWithExplicitElementType | ( | const IntVector & | permutation, |
| Array * | array_to_permute, | ||
| ElementType | unused | ||
| ) |
Permutes the elements of array_to_permute: element #i will be moved to position permutation[i].
permutation must be either empty (in which case nothing happens), or a permutation of [0, permutation.size()).
The algorithm is fast but need extra memory for a copy of the permuted part of array_to_permute.
Some compiler do not know typeof(), so we have to use this extra function internally.
| * * * util::StatusOr<Graph*> util::ReadGraphFile | ( | const std::string & | filename, |
| bool | directed, | ||
| std::vector< int > * | num_nodes_with_color_or_null | ||
| ) |
if (!SplitStringAndParse(line, " ", &absl::SimpleAtoi, &header_ints) || header_ints.size() < 2 || header_ints[0] < 0 || header_ints[1] < 0) { return util::Status( util::error::INVALID_ARGUMENT, absl::StrCat("First line of '", filename, "' should be at least two nonnegative integers.")); }
No coloring: all the nodes have the same color.
We don't add superfluous arcs to the graph, but we still keep reading the file, to get better error messages: we want to know the actual number of lines, and also want to check the validity of the superfluous arcs (i.e. that their src/dst nodes are ok).
| util::StatusOr<Graph*> util::ReadGraphFile | ( | const std::string & | filename, |
| bool | directed, | ||
| std::vector< int > * | num_nodes_with_color_or_null | ||
| ) |
if (!SplitStringAndParse(line, " ", &absl::SimpleAtoi, &header_ints) || header_ints.size() < 2 || header_ints[0] < 0 || header_ints[1] < 0) { return util::Status( util::error::INVALID_ARGUMENT, absl::StrCat("First line of '", filename, "' should be at least two nonnegative integers.")); }
No coloring: all the nodes have the same color.
We don't add superfluous arcs to the graph, but we still keep reading the file, to get better error messages: we want to know the actual number of lines, and also want to check the validity of the superfluous arcs (i.e. that their src/dst nodes are ok).
| std::unique_ptr< Graph > util::RemapGraph | ( | const Graph & | graph, |
| const std::vector< int > & | new_node_index | ||
| ) |
Creates a remapped copy of graph "graph", where node i becomes node new_node_index[i].
"new_node_index" must be a valid permutation of [0..num_nodes-1] or the behavior is undefined (it may die).
| void util::RemoveCyclesFromPath | ( | const Graph & | graph, |
| std::vector< int > * | arc_path | ||
| ) |
Given an arc path, changes it to a sub-path with the same source and destination but without any cycle.
Nothing happen if the path was already without cycle.
The graph class should support Tail(arc) and Head(arc). They should both return an integer representing the corresponding tail/head of the passed arc.
This maps each node to the latest arc in the given path that leaves it.
Special case for the destination.
Reconstruct the path by starting at the source and then following the "next" arcs. We override the given arc_path at the same time.
This maps each node to the latest arc in the given path that leaves it.
Special case for the destination.
Reconstruct the path by starting at the source and then following the "next" arcs. We override the given arc_path at the same time.
| false util::ValueOrDie | ( | ) |
Read a graph file in the simple ".g" format: the file should be a text file containing only space-separated integers, whose first line is: <num nodes>=""> <num edges>=""> [<num_colors> <index of first node with color #1> <index of first node with color #2> ...] and whose subsequent lines represent edges if "directed" is false, or arcs if "directed" is true: <node1> <node2>.
This returns a newly created graph upon success, which the user needs to take ownership of, or a failure status. See ortools/base/statusor.h.
If "num_nodes_with_color_or_null" is not nullptr, it will be filled with the color information: num_nodes_with_color_or_null[i] will be the number of nodes with color #i. Furthermore, nodes are sorted by color.
Examples: ///< Simply crash if the graph isn't successfully read from the file. typedef StaticGraph<> MyGraph; ///< This is just an example. std::unique_ptr<MyGraph> my_graph( ReadGraphFile<MyGraph>("graph.g", /*directed=
| util::Status util::WriteGraphToFile | ( | const Graph & | graph, |
| const std::string & | filename, | ||
| bool | directed, | ||
| const std::vector< int > & | num_nodes_with_color | ||
| ) |
Writes a graph to the ".g" file format described above.
If "directed" is true, all arcs are written to the file. If it is false, the graph is expected to be undirected (i.e. the number of arcs a->b is equal to the number of arcs b->a for all nodes a,b); and only the arcs a->b where a<=b are written. Note however that in this case, the symmetry of the graph is not fully checked (only the parity of the number of non-self arcs is).
"num_nodes_with_color" is optional. If it is not empty, then the color information will be written to the header of the .g file. See ReadGraphFile.
This method is the reverse of ReadGraphFile (with the same value for "directed").
In undirected mode, we must count the self-arcs separately. All other arcs should be duplicated.
In undirected mode, we must count the self-arcs separately. All other arcs should be duplicated.
| util::else |
| * * * util::StatusOr<MyGraph*> util::error_or_graph |
| util::false |
This is useful for wrapping iterators of a class that support many different iterations.
For instance, on a Graph class, one can write:
BeginEndWrapper<OutgoingArcIterator> Graph::OutgoingArcs(NodeInde node) const { return BeginEndRange( OutgoingArcIterator(*this, node, /*at_end=
Definition at line 30 of file iterators.h.
| * OutgoingArcIterator util::this |
Definition at line 31 of file iterators.h.