|
nxpp
Header-only graph utilities on top of Boost Graph Library
|
This document is the curated markdown companion to the generated API reference.
Use the repository README.md for:
Use the generated Doxygen site for:
Use this file for:
For complexity guarantees and the side-by-side Boost vs nxpp discussion, use `COMPLEXITY.md`. This file intentionally focuses on API shape, return types, and behavioral notes.
Useful generated-reference cross-links:
It should not try to become a second full copy of the generated declaration reference. When this file and the generated docs overlap, the generated docs win on declaration-level detail.
| Type | Meaning |
|---|---|
nxpp::Graph<NodeID, EdgeWeight, false, false> | Undirected simple weighted graph with default selectors |
nxpp::Graph<NodeID, EdgeWeight, true, false> | Directed simple weighted graph with default selectors |
nxpp::Graph<NodeID, EdgeWeight, false, true> | Undirected multigraph with default selectors |
nxpp::Graph<NodeID, EdgeWeight, true, true> | Directed multigraph with default selectors |
nxpp::Graph<NodeID, EdgeWeight, Directed, Multi, false> | Unweighted variant with default selectors |
nxpp::Graph<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector> | Advanced form with explicit BGL selectors |
| Alias | Expands to | Role |
|---|---|---|
WeightedGraphInt | Graph<int, int> | Explicit weighted preset |
WeightedGraphStr | Graph<std::string> | Explicit weighted preset |
WeightedDiGraphInt | Graph<int, int, true> | Explicit weighted preset |
WeightedDiGraph | Graph<std::string, double, true> | Explicit weighted preset |
WeightedMultiGraphInt | Graph<int, int, false, true> | Explicit weighted preset |
WeightedMultiDiGraphInt | Graph<int, int, true, true> | Explicit weighted preset |
WeightedMultiGraph | Graph<std::string, double, false, true> | Explicit weighted preset |
WeightedMultiDiGraph | Graph<std::string, double, true, true> | Explicit weighted preset |
GraphInt | Graph<int, int> | Thin synonym of WeightedGraphInt |
GraphStr | Graph<std::string> | Thin synonym of WeightedGraphStr |
DiGraphInt | Graph<int, int, true> | Thin synonym of WeightedDiGraphInt |
DiGraph | Graph<std::string, double, true> | Thin synonym of WeightedDiGraph |
MultiGraphInt | Graph<int, int, false, true> | Thin synonym of WeightedMultiGraphInt |
MultiDiGraphInt | Graph<int, int, true, true> | Thin synonym of WeightedMultiDiGraphInt |
MultiGraph | Graph<std::string, double, false, true> | Thin synonym of WeightedMultiGraph |
MultiDiGraph | Graph<std::string, double, true, true> | Thin synonym of WeightedMultiDiGraph |
UnweightedGraphInt | Graph<int, double, false, false, false> | Explicit unweighted preset |
UnweightedDiGraphInt | Graph<int, double, true, false, false> | Explicit unweighted preset |
UnweightedGraphStr | Graph<std::string, double, false, false, false> | Explicit unweighted preset |
UnweightedDiGraph | Graph<std::string, double, true, false, false> | Explicit unweighted preset |
UnweightedMultiGraphInt | Graph<int, double, false, true, false> | Explicit unweighted preset |
UnweightedMultiDiGraphInt | Graph<int, double, true, true, false> | Explicit unweighted preset |
UnweightedMultiGraph | Graph<std::string, double, false, true, false> | Explicit unweighted preset |
UnweightedMultiDiGraph | Graph<std::string, double, true, true, false> | Explicit unweighted preset |
The Weighted* aliases are the clearest explicit names. The shorter aliases such as GraphInt and DiGraph are kept as compatibility-friendly synonyms. All aliases intentionally stay on the default boost::vecS / boost::vecS backend.
This section makes the thin alias story explicit so the canonical entry points stay easier to recognize.
Weighted* aliases are the clearest named presets for the default graph surfaceGraphInt, DiGraph, MultiGraph, and MultiDiGraph are thin compatibility-friendly synonyms of those weighted presetsUnweighted* aliases are explicit presets for graphs without the built-in edge-weight propertyThese methods are supported, but they mainly forward to a more explicit primary name:
| Alias | Primary entry point | Note |
|---|---|---|
single_source_dijkstra(source) | dijkstra_shortest_paths(source) | Same result wrapper under a shorter compatibility-friendly name |
single_source_bellman_ford(source) | bellman_ford_shortest_paths(source) | Same result wrapper under a shorter compatibility-friendly name |
connected_component_map() | connected_components() | Same node -> component_id result |
strongly_connected_components() | strongly_connected_component_groups() | Grouped SCC output under a shorter familiar name |
strongly_connected_component_map() | strong_component_map() | Same SCC map result under a longer explicit alias |
strongly_connected_component_roots() | strong_components() | Same SCC representative/root map |
minimum_spanning_tree() | kruskal_minimum_spanning_tree() | Default thin alias for the Kruskal path |
minimum_spanning_tree(root) | prim_minimum_spanning_tree(root) | Rooted thin alias for the Prim path |
max_flow_min_cost_successive_shortest_path(...) | successive_shortest_path_nonnegative_weights(...) | Compatibility-friendly SSP alias |
max_flow_min_cost(...) | max_flow_min_cost_cycle_canceling(...) | Current default min-cost max-flow wrapper |
The repository still exposes deprecated namespace-scope wrappers such as:
nxpp::bfs_edges(G, start)nxpp::dijkstra_path(G, source, target)nxpp::connected_components(G)nxpp::topological_sort(G)Those exist as migration-friendly compatibility aliases for the method-based API. For existing-graph operations, the canonical public form remains G.foo(...).
nxpp::Graph<NodeID, ...> currently expects NodeID to be:
std::lessThose requirements come from the wrapper's ordered translation maps, ordered result wrappers, and shortest-path predecessor/path reconstruction helpers.
Practical clarifications:
NodeID to be hashableNodeID to provide a public std::hash<NodeID> specializationExamples that fit the current public contract include:
std::stringintstd::less-compatible orderingThe free numeric graph generators in nxpp/generators.hpp have one additional requirement:
NodeID must be constructible from std::size_tThat extra generator constraint is not a global Graph requirement; it only applies to helpers that synthesize node IDs 0..n-1 themselves.
nxpp follows a consistent write-creates / read-does-not-create policy across the public API.
Write-style accessors create missing nodes or edges:
| Call | What gets created |
|---|---|
G.add_node(u) | node u |
G.add_edge(u, v, ...) | both endpoints if absent |
G.node(u)[key] = val | node u (via NodeAttrProxy::operator=) |
G[u][v] = weight | edge (u,v) and both endpoints (via EdgeProxy::operator=) |
G[u][v][key] = val | edge (u,v) if absent (via EdgeAttrProxy::operator=) |
Read-style accessors never create:
| Call | Behavior when absent |
|---|---|
G.has_node(u) | returns false |
G.has_edge(u, v) | returns false |
G.get_node_attr<T>(u, key) | throws std::runtime_error |
G.try_get_node_attr<T>(u, key) | returns std::nullopt |
G.get_edge_attr<T>(u, v, key) | throws std::runtime_error |
G.try_get_edge_attr<T>(u, v, key) | returns std::nullopt |
G.neighbors(u) | throws std::runtime_error |
G.bfs_edges(u) / G.dfs_edges(u) | throws std::runtime_error |
G.shortest_path(u, v) | throws std::runtime_error |
This matches the NetworkX convention: indexing and assignment create implicitly, while pure-read calls assume the element already exists.
| Function | Parameters | Returns | Description | Example |
|---|---|---|---|---|
Graph() | — | graph object | Creates an empty wrapper and initializes internal state. | nxpp::GraphInt G; |
add_node | (const NodeID& id) | void | Inserts the node if absent. | G.add_node(42); |
add_nodes_from | (const std::vector<NodeID>& nodes) | void | Inserts k nodes by repeated add_node. | G.add_nodes_from({1,2,3}); |
has_node | (const NodeID& u) | bool | Checks whether a node exists. | G.has_node(1) |
add_edge | (u, v, w = 1.0) | void | Creates missing endpoints automatically. In simple graphs, a repeated (u, v) overwrites weight. | G.add_edge(1, 2, 3.5); |
add_edge | (u, v) on unweighted graphs | void | Inserts an unweighted edge. | UG.add_edge(1, 2); |
add_edge | (u, v, {"key", value}) | void | Adds one edge attribute with default built-in weight where applicable. In multigraphs this endpoint-based attr-bearing form is now rejected as ambiguous; use add_edge_with_id(...) then set_edge_attr(edge_id, ...). | G.add_edge(0, 1, {"capacity", 5L}); |
add_edge | (u, v, {{"key", value}, ...}) | void | Adds multiple edge attributes with default built-in weight where applicable. In multigraphs this endpoint-based attr-bearing form is now rejected as ambiguous. | G.add_edge(0, 1, {{"capacity", 5L}}); |
add_edge | (u, v, w, {"key", value}) | void | Adds / updates weight and one edge attribute. In multigraphs this endpoint-based attr-bearing form is now rejected as ambiguous. | G.add_edge(0, 1, 3.5, {"capacity", 5L}); |
add_edge | (u, v, w, {{"key", value}, ...}) | void | Adds / updates weight and multiple edge attributes. In multigraphs this endpoint-based attr-bearing form is now rejected as ambiguous. | G.add_edge(0, 1, 3.5, {{"capacity", 5L}}); |
add_edges_from | vector<tuple<u,v,w>> | void | Bulk weighted insertion. | G.add_edges_from({{1,2,2},{2,3,4}}); |
add_edges_from | vector<pair<u,v>> | void | Bulk insertion with default weight or unweighted insertion depending on graph type. | G.add_edges_from({{1,2},{2,3}}); |
has_edge | (u, v) | bool | Checks whether an edge exists. In multigraphs, this means "at least one edge exists". | G.has_edge("A","B") |
has_edge_id | (edge_id) | bool | Checks whether a specific wrapper-tracked edge ID still exists. This is the precise multigraph edge existence check. | G.has_edge_id(eid) |
get_edge_weight | (u, v) | EdgeWeight | Returns the built-in edge weight. In multigraphs, this resolves through one edge returned by boost::edge(u, v, g) and should not be treated as a stable single-parallel-edge lookup. | auto w = G.get_edge_weight(1,2); |
get_edge_weight | (edge_id) | EdgeWeight | Returns the built-in edge weight for one specific wrapper-tracked edge ID. | auto w = G.get_edge_weight(eid); |
nodes | () | std::vector<NodeID> | Materializes all node IDs. | auto ns = G.nodes(); |
edges | () | weighted graphs: std::vector<std::tuple<NodeID, NodeID, EdgeWeight>>; unweighted graphs: std::vector<std::pair<NodeID, NodeID>> | Materializes all edges. | auto es = G.edges(); |
edge_pairs | () | std::vector<std::pair<NodeID, NodeID>> | Materializes edges without weights. Useful for wrappers that rebuild auxiliary graphs. | auto ep = G.edge_pairs(); |
edge_ids | () | std::vector<size_t> | Returns every wrapper-tracked edge ID currently present in the graph. | auto ids = G.edge_ids(); |
edge_ids | (u, v) | std::vector<size_t> | Returns the tracked edge IDs between two endpoints. In multigraphs, this is the main way to enumerate parallel edges precisely. | auto ids = G.edge_ids("A","B"); |
get_edge_endpoints | (edge_id) | std::pair<NodeID, NodeID> | Returns the endpoints of one specific wrapper-tracked edge ID. | auto [u, v] = G.get_edge_endpoints(eid); |
neighbors | (u) | std::vector<NodeID> | Returns out-neighbors. For directed graphs this matches successor semantics. | G.neighbors("A") |
successors | (u) | std::vector<NodeID> | Explicit directed-style successor helper. | G.successors("A") |
predecessors | (u) | std::vector<NodeID> | Returns predecessor IDs in directed graphs. | G.predecessors("B") |
remove_edge | (u, v) | void | Removes the edge and tracked edge metadata. In multigraphs, this removes all parallel edges between u and v and cleans all tracked metadata for that pair. | G.remove_edge(1,2); |
remove_edge | (edge_id) | void | Removes one specific wrapper-tracked edge ID. This is the precise multigraph removal API. | G.remove_edge(eid); |
remove_node | (u) | void | Removes the node, clears incident metadata, erases the vertex, then repairs shifted mappings. | G.remove_node("Rome"); |
clear | () | void | Resets graph structure, translation maps, attribute stores, and edge-ID state. | G.clear(); |
node | (u) | NodeAttrBaseProxy | Returns node-attribute proxy access. Creates the node if absent. | G.node("A")["x"] = 7; |
operator[] | (u) | NodeProxy | Returns a proxy for chained access such as G[u][v] and G[u][v]["key"]. Creates u if absent. | G["A"]["B"] = 2.0; |
get_impl | () | const GraphType& | Exposes the internal BGL graph for wrapper implementation or advanced inspection. | auto& impl = G.get_impl(); |
get_bgl_to_id_map | () | const std::vector<NodeID>& | Exposes the wrapper's maintained index-ordered node list used by result normalization. | auto& map = G.get_bgl_to_id_map(); |
get_id_to_bgl_map | () | const std::map<NodeID, VertexDesc>& | Exposes ID-to-descriptor mapping. | auto& map = G.get_id_to_bgl_map(); |
get_node_id | (vertex_descriptor) | const NodeID& | Returns the user-facing node ID for a descriptor. Mostly useful for advanced integrations. | auto id = G.get_node_id(v); |
get_vertex_index | (vertex_descriptor) | size_t | Returns the wrapper-maintained vertex index used by normalized result containers. | auto i = G.get_vertex_index(v); |
The get_impl() / translation-map getters above are advanced const escape hatches for integrations and wrapper-level utilities. They intentionally expose read-only internal state. The mutable wrapper-owned attribute stores are no longer part of the public surface.
For the generated declaration pages behind this policy, see:
In multigraph mode, nxpp distinguishes between two public API categories:
(u, v) ergonomics but do not promise stable selection of one particular parallel edge unless a function explicitly documents a stronger guaranteePractical rule:
edge_id when one edge instance matters(u, v) forms as existence / convenience / parity helpers in multigraphsG[u][v], get_edge_weight(u, v), or endpoint-based edge-attribute lookups as precise single-parallel-edge handlesExamples of the precise path:
add_edge_with_id(...)has_edge_id(...)edge_ids(...)get_edge_endpoints(edge_id)remove_edge(edge_id)get_edge_attr(edge_id, ...)try_get_edge_attr(edge_id, ...)get_edge_numeric_attr(edge_id, ...)get_edge_weight(edge_id)set_edge_attr(edge_id, ...)set_edge_weight(edge_id, ...)The table below makes the endpoint-based multigraph behavior explicit.
| API | Multigraph meaning | Precise alternative |
|---|---|---|
has_edge(u, v) | Answers only whether at least one parallel edge exists between u and v. | edge_ids(u, v) / has_edge_id(edge_id) |
add_edge(u, v, ...) | Endpoint-based insertion/update convenience form. Not a stable handle to one later edge instance. | add_edge_with_id(...) |
add_edge(u, v, attrs...) | Endpoint-based attr-bearing form. In multigraphs this is now rejected as ambiguous. | add_edge_with_id(...) then set_edge_attr(edge_id, ...) |
remove_edge(u, v) | Removes all parallel edges between u and v. | remove_edge(edge_id) |
get_edge_weight(u, v) | Reads one edge selected through endpoint-based resolution. Not a stable single-edge lookup. | get_edge_weight(edge_id) |
get_edge_attr<T>(u, v, key) | Reads one endpoint-resolved edge attribute. Not a stable single-edge lookup. | get_edge_attr<T>(edge_id, key) |
try_get_edge_attr<T>(u, v, key) | Same endpoint-based ambiguity as get_edge_attr<T>(u, v, key), but with optional-return behavior. | try_get_edge_attr<T>(edge_id, key) |
get_edge_numeric_attr(u, v, key) | Same endpoint-based ambiguity as the other edge lookup helpers. | get_edge_numeric_attr(edge_id, key) |
G[u][v] | Proxy convenience form only. Do not treat as a stable handle to one parallel edge. | edge_ids(u, v) then edge_id APIs |
G[u][v]["key"] | Proxy convenience form only. Not precise per-parallel-edge targeting. | set_edge_attr(edge_id, key, value) / get_edge_attr<T>(edge_id, key) |
Node and edge attributes are stored outside the BGL graph using std::any in ordered std::map-backed stores.
Current direction:
std::any remains the pragmatic storage model for nowedge_id-based access is the precise path while (u, v) access remains convenience-oriented| Function | Parameters | Returns | Description | Example |
|---|---|---|---|---|
has_node_attr | (u, key) | bool | Checks whether node u has attribute key. Here A is the attribute count stored on node u. | G.has_node_attr("A", "color") |
has_edge_attr | (u, v, key) | bool | Checks whether the resolved (u,v) edge has attribute key. In multigraphs, this uses the same non-stable (u, v) resolution as other edge lookups. | G.has_edge_attr("A","B","capacity") |
has_edge_attr | (edge_id, key) | bool | Checks whether a specific wrapper-tracked edge ID has attribute key. | G.has_edge_attr(eid, "capacity") |
get_node_attr<T> | (u, key) | T | Returns node attribute key with checked std::any_cast. Throws on missing key or type mismatch. | G.get_node_attr<int>("Rome", "population") |
get_edge_attr<T> | (u, v, key) | T | Returns edge attribute key with checked std::any_cast. In multigraphs, this resolves through one edge returned by boost::edge(u, v, g) and is not a stable single-parallel-edge API. | G.get_edge_attr<std::string>("A","B","company") |
get_edge_attr<T> | (edge_id, key) | T | Returns edge attribute key for one specific wrapper-tracked edge ID. | G.get_edge_attr<std::string>(eid, "company") |
try_get_node_attr<T> | (u, key) | std::optional<T> | Safe optional-return node attribute lookup. | G.try_get_node_attr<int>(1, "rank") |
try_get_edge_attr<T> | (u, v, key) | std::optional<T> | Safe optional-return edge attribute lookup. In multigraphs, this uses the same non-stable (u, v) resolution as get_edge_attr<T>. | G.try_get_edge_attr<long>(0,1,"capacity") |
try_get_edge_attr<T> | (edge_id, key) | std::optional<T> | Safe optional-return edge attribute lookup for one specific wrapper-tracked edge ID. | G.try_get_edge_attr<long>(eid, "capacity") |
get_edge_numeric_attr | (u, v, key) | double | Returns a numeric edge attribute or the built-in "weight" as double. In multigraphs, this follows the same non-stable (u, v) resolution path as the other edge lookup helpers. | G.get_edge_numeric_attr(0, 1, "capacity") |
get_edge_numeric_attr | (edge_id, key) | double | Returns a numeric edge attribute or built-in "weight" for one specific wrapper-tracked edge ID. | G.get_edge_numeric_attr(eid, "capacity") |
set_edge_attr<T> | (edge_id, key, value) | void | Sets one attribute on a specific wrapper-tracked edge ID after validating that the edge ID still exists. | G.set_edge_attr(eid, "capacity", 5L) |
set_edge_weight | (edge_id, weight) | void | Sets the built-in weight on a specific wrapper-tracked edge ID. | G.set_edge_weight(eid, 3.5) |
| Syntax | Meaning |
|---|---|
G[u][v] = w; | set built-in edge weight; in multigraphs this is not a stable single-parallel-edge handle |
auto w = (EdgeWeight)G[u][v]; | read built-in edge weight through proxy conversion; in multigraphs this follows the same non-stable (u, v) resolution path |
G[u][v]["key"] = value; | set an edge attribute; in multigraphs this is not yet a precise per-parallel-edge API |
auto x = (T)G[u][v]["key"]; | read an edge attribute through proxy conversion; in multigraphs this follows the same non-stable (u, v) resolution path |
G.node(u)["key"] = value; | set a node attribute |
auto x = (T)G.node(u)["key"]; | read a node attribute through proxy conversion |
For multigraph-safe edge access:
Proxy syntax is convenient for writes and demos.
For reads, prefer:
has_*_attrget_*_attr<T>try_get_*_attr<T>because they make type expectations and failure behavior much clearer.
This is the intended long-term direction for the current attribute system too:
std::any as the pragmatic storage backend unless a clearer replacement justifies a larger redesignFor a pragmatic comparison of the current model against future alternatives (std::variant, typed schema) and a conservative migration path, see the Attribute System Design Evaluation.
Weight-name note:
"weight" is treated specially"weight" refers to the built-in edge-weight propertyFor multigraphs, prefer the precise edge_id path whenever:
Why the attr-bearing endpoint forms now throw in multigraphs:
(u, v) is not enough to identify one concrete parallel edgeKeep endpoint-based (u, v) forms for:
These types are part of the public API and are worth knowing because they make some results easier to consume than raw BGL output.
| Type | Main fields / behavior | What it is for |
|---|---|---|
MaximumFlowResult<NodeID> | value, flow, edge_flows_by_id | max-flow total plus aggregate endpoint view and precise per-edge-ID flow map |
MinCostMaxFlowResult<NodeID> | flow, cost, edge_flows, edge_flows_by_id | min-cost max-flow total flow, cost, aggregate endpoint view, and precise per-edge-ID flows |
MinimumCutResult<NodeID> | value, reachable, non_reachable, cut_edges, cut_edge_ids | cut value, partition information, aggregate endpoint cut view, and precise cut-edge IDs |
SingleSourceShortestPathResult<NodeID, Distance> | ordered distance, predecessor, plus has_path_to(target) / path_to(target) | single-source shortest-path results in a C++-friendly shape with tree-based map bounds and on-demand path reconstruction |
lookup_map<Key, Value> | operator[], at, iterators over ordered storage | const-friendly ordered lookup wrapper returned by some component helpers |
indexed_lookup_map<Key, Value> | at, operator[], contains, iterators over key-sorted storage | const-friendly indexed result wrapper that preserves linear materialization while keeping O(log n) key lookup |
visitor | no-op hooks examine_vertex, tree_edge, back_edge | small visitor base for traversal entry points |
This is one of the design directions that makes nxpp more than a thin parity layer: some wrappers return results that are easier to work with directly in C++ than raw Boost primitives.
The public surface intentionally includes a few utility wrappers that are not best described as direct one-to-one ports of a single NetworkX or Boost entry point.
These wrappers exist because they make the result shape more usable from C++:
| Wrapper / helper | Why it exists |
|---|---|
SingleSourceShortestPathResult<NodeID, Distance> | Returns ordered distance / predecessor data plus on-demand path_to(...), instead of forcing eager all-path materialization or lower-level reconstruction code into the caller |
MaximumFlowResult<NodeID> | Bundles the total flow value with both an endpoint-keyed convenience view and a precise edge_id-keyed flow view |
MinimumCutResult<NodeID> | Bundles cut value, partitions, endpoint cut edges, and precise cut-edge IDs into one directly usable return object |
MinCostMaxFlowResult<NodeID> | Bundles total flow, total cost, an endpoint-keyed convenience view, and a precise edge_id-keyed flow view into one C++-friendly return type |
indexed_lookup_map<Key, Value> | Keeps linear materialization and ordered key lookup for public results without baking hash-table assumptions into the API |
degree_centrality() | Exposes a normalized C++-friendly wrapper result rather than raw lower-level bookkeeping |
pagerank() | Exposes a ready-to-consume PageRank wrapper result keyed by NodeID instead of forcing callers to manage property maps and iteration state directly |
betweenness_centrality() | Exposes normalized betweenness scores keyed by NodeID using a self-contained Brandes BFS implementation without requiring callers to configure BGL property maps |
two_sat_satisfiable(...) | Exposes a direct utility surface built on top of the SCC machinery instead of requiring users to assemble the implication-graph workflow themselves |
The intended project shape is:
Use this wrapper when you want:
NodeIDGenerated-reference example page:
Use these wrappers when you want the aggregate answer plus the structured side information in one return object, instead of re-deriving it from lower-level algorithm output.
In multigraphs:
flow and cut_edges are endpoint-keyed convenience viewsedge_flows_by_id and cut_edge_ids are the precise parallel-edge-safe viewGenerated-reference example pages:
This wrapper is the one-shot return shape for the min-cost flow helpers.
In multigraphs:
edge_flows is the endpoint-keyed aggregate convenience viewedge_flows_by_id is the precise parallel-edge-safe viewGenerated-reference example page:
Use this wrapper when you want:
NodeID-keyed lookup without the public API depending on hash-table assumptionsGenerated-reference page:
For operations on an existing graph, the canonical form is method-based: G.foo(...).
| Function | Parameters | Returns | Description | Example |
|---|---|---|---|---|
bfs_edges | (start) | std::vector<std::pair<NodeID, NodeID>> | Runs BFS and returns discovered tree edges. | auto es = G.bfs_edges(0); |
bfs_tree | (start) | Graph<NodeID, double, Directed> | Builds a new graph containing the BFS tree rooted at start. | auto T = G.bfs_tree(0); |
bfs_successors | (start) | indexed_lookup_map<NodeID, std::vector<NodeID>> | Groups BFS tree edges by parent with linear materialization and O(log n) key lookup. | auto s = G.bfs_successors(0); |
dfs_edges | (start) | std::vector<std::pair<NodeID, NodeID>> | Runs DFS and returns DFS tree edges. | auto es = G.dfs_edges(0); |
dfs_tree | (start) | Graph<NodeID, double, Directed> | Builds a new graph containing the DFS tree rooted at start. | auto T = G.dfs_tree(0); |
dfs_predecessors | (start) | indexed_lookup_map<NodeID, NodeID> | Returns DFS predecessor map with linear materialization and O(log n) key lookup. | auto p = G.dfs_predecessors(0); |
dfs_successors | (start) | indexed_lookup_map<NodeID, std::vector<NodeID>> | Groups DFS tree edges by parent with linear materialization and O(log n) key lookup. | auto s = G.dfs_successors(0); |
| Function | Parameters | Returns | Description | Example |
|---|---|---|---|---|
breadth_first_search | (start, visitor) | void | Visitor-object BFS entry point. | G.breadth_first_search(0, vis); |
depth_first_search | (start, visitor) | void | Visitor-object DFS entry point. | G.depth_first_search(0, vis); |
bfs_visit | (start, on_vertex, on_tree_edge) | void | Callback-style BFS adapter around the visitor layer. | G.bfs_visit(0, on_v, on_e); |
dfs_visit | (start, on_tree_edge, on_back_edge) | void | Callback-style DFS adapter around the visitor layer. | G.dfs_visit(0, on_t, on_b); |
In the current API, the string "weight" has a narrow compatibility meaning:
That means calls such as:
shortest_path(..., "weight")dijkstra_path(..., "weight")bellman_ford_path(..., "weight")still route through the built-in weighted edge channel rather than an arbitrary user-defined numeric edge attribute.
| Function | Parameters | Returns | Description | Example |
|---|---|---|---|---|
shortest_path | (source, target) | std::vector<NodeID> | Unweighted shortest path by edge count. | auto p = G.shortest_path(0, 3); |
shortest_path_length | (source, target) | double | Unweighted shortest-path length in edge count. | auto d = G.shortest_path_length(0, 3); |
shortest_path | (source, target, "weight") | std::vector<NodeID> | Weighted shortest path through the built-in edge weight. The string "weight" is a compatibility name for the built-in weight property, not an arbitrary custom key. | auto p = G.shortest_path(0, 3, "weight"); |
shortest_path_length | (source, target, "weight") | double | Weighted shortest-path length through the built-in edge weight. The string "weight" is a compatibility name for the built-in weight property, not an arbitrary custom key. | auto d = G.shortest_path_length(0, 3, "weight"); |
dijkstra_path | (source, target) | std::vector<NodeID> | Direct Dijkstra source-target path wrapper. | auto p = G.dijkstra_path(0, 3); |
dijkstra_path | (source, target, "weight") | std::vector<NodeID> | Same as above; explicit "weight" overload for compatibility-shaped usage around the built-in edge weight. | auto p = G.dijkstra_path(0, 3, "weight"); |
dijkstra_path_length | (source, target) | Distance | Dijkstra distance to one target. | auto d = G.dijkstra_path_length(0, 3); |
dijkstra_path_length | (source, target, "weight") | Distance | Same as above with explicit "weight" overload around the built-in edge weight. | auto d = G.dijkstra_path_length(0, 3, "weight"); |
bellman_ford_path | (source, target) | std::vector<NodeID> | Bellman-Ford path wrapper. Throws on negative cycle. | auto p = G.bellman_ford_path(0, 3); |
bellman_ford_path | (source, target, "weight") | std::vector<NodeID> | Same as above with explicit "weight" overload around the built-in edge weight. | auto p = G.bellman_ford_path(0, 3, "weight"); |
bellman_ford_path_length | (source, target) | Distance | Bellman-Ford distance wrapper with a final accumulation over the reconstructed path. | auto d = G.bellman_ford_path_length(0, 3); |
bellman_ford_path_length | (source, target, "weight") | Distance | Same as above with explicit "weight" overload around the built-in edge weight. | auto d = G.bellman_ford_path_length(0, 3, "weight"); |
| Function | Parameters | Returns | Description | Example |
|---|---|---|---|---|
dijkstra_shortest_paths | (source) | SingleSourceShortestPathResult<NodeID, Distance> | Returns distances and predecessors, with on-demand path reconstruction through the result wrapper. | auto r = G.dijkstra_shortest_paths(0); |
single_source_dijkstra | (source) | SingleSourceShortestPathResult<NodeID, Distance> | Thin alias to dijkstra_shortest_paths. | auto r = G.single_source_dijkstra(0); |
bellman_ford_shortest_paths | (source) | SingleSourceShortestPathResult<NodeID, Distance> | Returns distances and predecessors, with on-demand path reconstruction through the result wrapper. | auto r = G.bellman_ford_shortest_paths(0); |
single_source_bellman_ford | (source) | SingleSourceShortestPathResult<NodeID, Distance> | Thin alias to bellman_ford_shortest_paths. | auto r = G.single_source_bellman_ford(0); |
dag_shortest_paths | (source) | SingleSourceShortestPathResult<NodeID, Distance> | DAG shortest-path helper returning distances and predecessors, with on-demand path reconstruction through the result wrapper. | auto r = G.dag_shortest_paths(0); |
floyd_warshall_all_pairs_shortest_paths | () | std::vector<std::vector<Distance>> | Returns an all-pairs distance matrix. | auto fw = G.floyd_warshall_all_pairs_shortest_paths(); |
floyd_warshall_all_pairs_shortest_paths_map | () | std::map<NodeID, std::map<NodeID, Distance>> | Convenience map wrapper around the Floyd-Warshall matrix. | auto fw = G.floyd_warshall_all_pairs_shortest_paths_map(); |
| Function | Parameters | Returns | Description | Example |
|---|---|---|---|---|
connected_component_groups | () | std::vector<std::vector<NodeID>> | Groups vertices by connected component. | auto cc = G.connected_component_groups(); |
connected_components | () | indexed_lookup_map<NodeID, int> | Returns node -> component_id with linear materialization and O(log n) key lookup. | auto map = G.connected_components(); |
connected_component_map | () | indexed_lookup_map<NodeID, int> | Thin alias to connected_components. | auto map = G.connected_component_map(); |
strongly_connected_component_groups | () | std::vector<std::vector<NodeID>> | Groups vertices by SCC. | auto scc = G.strongly_connected_component_groups(); |
strongly_connected_components | () | std::vector<std::vector<NodeID>> | Thin alias to grouped SCC output. | auto scc = G.strongly_connected_components(); |
strong_component_map | () | indexed_lookup_map<NodeID, int> | Returns node -> component_id for SCCs with linear materialization and O(log n) key lookup. | auto map = G.strong_component_map(); |
strongly_connected_component_map | () | indexed_lookup_map<NodeID, int> | Thin alias to strong_component_map. | auto map = G.strongly_connected_component_map(); |
strong_components | () | indexed_lookup_map<NodeID, NodeID> | Returns a representative/root per SCC with linear materialization and O(log n) key lookup. | auto roots = G.strong_components(); |
strongly_connected_component_roots | () | indexed_lookup_map<NodeID, NodeID> | Thin alias to SCC root map. | auto roots = G.strongly_connected_component_roots(); |
| Function | Parameters | Returns | Description | Example |
|---|---|---|---|---|
topological_sort | () | std::vector<NodeID> | Returns a topological ordering. | auto order = G.topological_sort(); |
kruskal_minimum_spanning_tree | () | std::vector<std::pair<NodeID, NodeID>> | Returns MST edges as pairs. | auto mst = G.kruskal_minimum_spanning_tree(); |
prim_minimum_spanning_tree | (root) | std::map<NodeID, NodeID> | Returns a node -> parent map rooted at root. | auto p = G.prim_minimum_spanning_tree(0); |
minimum_spanning_tree | () | std::vector<std::pair<NodeID, NodeID>> | Thin default wrapper delegating to Kruskal. | auto mst = G.minimum_spanning_tree(); |
minimum_spanning_tree | (root) | std::map<NodeID, NodeID> | Thin rooted wrapper delegating to Prim. | auto p = G.minimum_spanning_tree(0); |
The flow/cost wrappers follow the same rule:
weight_attr = "weight" refers to the built-in edge-weight propertySo the "weight" default in min-cost-flow helpers should be read as a narrow built-in cost channel, not as an open-ended attribute-name policy.
| Function | Parameters | Returns | Description | Example |
|---|---|---|---|---|
edmonds_karp_maximum_flow | (source, sink, capacity_attr = "capacity") | MaximumFlowResult<NodeID> | Max-flow wrapper returning total flow plus both an endpoint-keyed convenience view and a precise edge_id-keyed flow view. | auto f = G.edmonds_karp_maximum_flow(0, 5); |
maximum_flow | (source, sink, capacity_attr = "capacity") | MaximumFlowResult<NodeID> | Backward-compatible default max-flow wrapper returning both aggregate endpoint and precise edge_id views. | auto f = G.maximum_flow(0, 5); |
push_relabel_maximum_flow_result | (source, sink, capacity_attr = "capacity") | MaximumFlowResult<NodeID> | Push-Relabel wrapper returning both aggregate endpoint and precise edge_id views. | auto f = G.push_relabel_maximum_flow_result(0, 5); |
minimum_cut | (source, sink, capacity_attr = "capacity") | MinimumCutResult<NodeID> | Returns cut value, partition, endpoint cut-edge view, and precise cut-edge IDs. In multigraph mode the internal capacity builder now uses precise edge_id lookup per concrete edge instance. | auto c = G.minimum_cut(0, 5); |
| Function | Parameters | Returns | Description | Example |
|---|---|---|---|---|
push_relabel_maximum_flow | (source, sink, capacity_attr = "capacity", weight_attr = "weight") | long | Computes max flow and stages residual state for a later cycle_canceling(). Any later graph mutation invalidates that staged state. The default "weight" still refers to the built-in edge-weight property. | long f = G.push_relabel_maximum_flow(0, 5); |
cycle_canceling | (weight_attr = "weight") | deduced cost type | Runs cycle-canceling over staged state prepared by push_relabel_maximum_flow. If the graph changed in the meantime, this now throws and asks the caller to rerun the push-relabel stage first. The default "weight" still refers to the built-in edge-weight property. | long c = G.cycle_canceling(); |
| Function | Parameters | Returns | Description | Example |
|---|---|---|---|---|
max_flow_min_cost_cycle_canceling | (source, sink, capacity_attr = "capacity", weight_attr = "weight") | MinCostMaxFlowResult<NodeID> | One-shot min-cost max-flow wrapper using cycle canceling. Returns both an endpoint-keyed aggregate view and a precise edge_id-keyed flow view. The default "weight" still refers to the built-in edge-weight property. | auto r = G.max_flow_min_cost_cycle_canceling(0, 5); |
successive_shortest_path_nonnegative_weights | (source, sink, capacity_attr = "capacity", weight_attr = "weight") | MinCostMaxFlowResult<NodeID> | One-shot min-cost max-flow wrapper using SSP. Returns both an endpoint-keyed aggregate view and a precise edge_id-keyed flow view. The default "weight" still refers to the built-in edge-weight property. | auto r = G.successive_shortest_path_nonnegative_weights(0, 5); |
max_flow_min_cost_successive_shortest_path | (source, sink, capacity_attr = "capacity", weight_attr = "weight") | MinCostMaxFlowResult<NodeID> | Thin alias to the SSP wrapper. Returns both an endpoint-keyed aggregate view and a precise edge_id-keyed flow view. The default "weight" still refers to the built-in edge-weight property. | auto r = G.max_flow_min_cost_successive_shortest_path(0, 5); |
max_flow_min_cost | (source, sink, capacity_attr = "capacity", weight_attr = "weight") | MinCostMaxFlowResult<NodeID> | Default min-cost max-flow wrapper; currently delegates to cycle canceling. Returns both an endpoint-keyed aggregate view and a precise edge_id-keyed flow view. The default "weight" still refers to the built-in edge-weight property. | auto r = G.max_flow_min_cost(0, 5); |
These are good examples of public helpers that are useful in real C++ code even when they are not exact one-to-one ports of a single NetworkX or BGL entry point.
| Function | Parameters | Returns | Description | Example |
|---|---|---|---|---|
complete_graph | (n) | GraphType | Generates a complete graph for the chosen graph type template. | auto K5 = nxpp::complete_graph(5); |
path_graph | (n) | GraphType | Generates a path graph. | auto P4 = nxpp::path_graph(4); |
erdos_renyi_graph | (n, p, seed = 42) | GraphType | Generates an Erdős–Rényi random graph. | auto G = nxpp::erdos_renyi_graph(100, 0.05); |
num_vertices | () | int | Convenience wrapper over boost::num_vertices. | auto n = G.num_vertices(); |
degree_centrality | () | indexed_lookup_map<NodeID, double> | Returns degree centrality with NetworkX-like normalization by n - 1, using linear materialization plus O(log n) key lookup. | auto c = G.degree_centrality(); |
pagerank | () | indexed_lookup_map<NodeID, double> | Returns PageRank scores keyed by NodeID, using a small fixed-iteration wrapper result instead of raw property-map plumbing. | auto rank = G.pagerank(); |
betweenness_centrality | () | indexed_lookup_map<NodeID, double> | Returns normalized betweenness centrality for each node, matching NetworkX betweenness_centrality(G, normalized=True) semantics. Implemented via Brandes BFS without BGL property-map setup. | auto bc = G.betweenness_centrality(); |
to_2sat_vertex_id | (literal) | int | Internal/public helper mapping a literal to its implication-graph vertex index. | auto id = nxpp::to_2sat_vertex_id(-2); |
two_sat_satisfiable | (num_variables, clauses) | bool | 2-SAT satisfiability helper built on SCC computation. | bool ok = nxpp::two_sat_satisfiable(2, {{1,2},{-1,2}}); |