
Graph Input/Output
BGL provides functions to read and write graphs in various standard formats. This allows you to exchange graph data with other tools, load test cases, or persist graphs to disk.
Supported File Formats
| Format | Description | Read Function | Write Function |
|---|---|---|---|
| GraphML | XML-based graph format with properties | read_graphml | write_graphml |
| GraphViz DOT | Text-based visualization format | read_graphviz | write_graphviz |
| DIMACS | Max-flow/min-cut problem format | read_dimacs_max_flow | write_dimacs_max_flow |
Reading GraphML Files
GraphML is an XML-based format that supports both graph structure and properties. It's the recommended format for general graph data exchange.
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphml.hpp>
#include <fstream>
using namespace boost;
typedef adjacency_list<vecS, vecS, directedS,
property<vertex_name_t, std::string>,
property<edge_weight_t, double> > Graph;
int main()
{
Graph g;
dynamic_properties dp;
// Tell dynamic_properties about the properties we want to read
dp.property("name", get(vertex_name, g));
dp.property("weight", get(edge_weight, g));
// Read the graph
std::ifstream infile("graph.graphml");
read_graphml(infile, g, dp);
std::cout << "Loaded " << num_vertices(g) << " vertices and "
<< num_edges(g) << " edges\n";
return 0;
}
Key points:
- Use dynamic_properties to map GraphML attribute names to property maps
- GraphML format preserves both graph structure and all properties
- Supports both directed and undirected graphs
- Can handle multiple graphs in one file (use graph_index parameter)
Writing GraphML Files
#include <boost/graph/graphml.hpp>
#include <fstream>
int main()
{
Graph g;
// ... build graph ...
dynamic_properties dp;
dp.property("name", get(vertex_name, g));
dp.property("weight", get(edge_weight, g));
// Write the graph
std::ofstream outfile("output.graphml");
write_graphml(outfile, g, dp);
return 0;
}
Reading GraphViz DOT Files
The DOT format is widely used for graph visualization with Graphviz tools.
#include <boost/graph/graphviz.hpp>
#include <fstream>
int main()
{
Graph g;
dynamic_properties dp;
dp.property("node_id", get(vertex_name, g));
dp.property("weight", get(edge_weight, g));
std::ifstream infile("graph.dot");
read_graphviz(infile, g, dp);
return 0;
}
Writing GraphViz DOT Files
You can write graphs in DOT format for visualization:
#include <boost/graph/graphviz.hpp>
#include <fstream>
int main()
{
Graph g;
// ... build graph ...
// Simple version: just structure, no properties
std::ofstream outfile("graph.dot");
write_graphviz(outfile, g);
return 0;
}
For custom vertex/edge labels in the output:
// Write with vertex labels
write_graphviz(outfile, g,
make_label_writer(get(vertex_name, g)));
// Write with vertex and edge labels
write_graphviz(outfile, g,
make_label_writer(get(vertex_name, g)),
make_label_writer(get(edge_weight, g)));
DIMACS Max-Flow Format
DIMACS format is used for max-flow and min-cut problems. It's a specialized format used in algorithm competitions and benchmarks.
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/read_dimacs.hpp>
typedef adjacency_list<vecS, vecS, directedS,
no_property,
property<edge_capacity_t, int> > FlowGraph;
int main()
{
FlowGraph g;
typedef graph_traits<FlowGraph>::vertex_descriptor Vertex;
Vertex source, sink;
property_map<FlowGraph, edge_capacity_t>::type capacity
= get(edge_capacity, g);
// Read DIMACS max-flow file from stdin
read_dimacs_max_flow(g, capacity, source, sink);
std::cout << "Source: " << source << ", Sink: " << sink << "\n";
std::cout << "Edges: " << num_edges(g) << "\n";
return 0;
}
Using dynamic_properties for Flexible I/O
The dynamic_properties class allows you to read/write properties without knowing their types at compile time:
#include <boost/graph/graphml.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
int main()
{
typedef adjacency_list<vecS, vecS, directedS> Graph;
Graph g;
// Create maps for storing properties externally
std::map<graph_traits<Graph>::vertex_descriptor, std::string> vertex_names;
std::map<graph_traits<Graph>::edge_descriptor, double> edge_weights;
// Wrap maps in associative property maps
auto name_map = make_assoc_property_map(vertex_names);
auto weight_map = make_assoc_property_map(edge_weights);
// Create dynamic_properties object
dynamic_properties dp;
dp.property("name", name_map);
dp.property("weight", weight_map);
// Read graph
std::ifstream infile("graph.graphml");
read_graphml(infile, g, dp);
// Access properties
auto vp = vertices(g);
for (auto vi = vp.first; vi != vp.second; ++vi) {
std::cout << "Vertex " << *vi
<< " name: " << vertex_names[*vi] << "\n";
}
return 0;
}
Example GraphML File
Here's what a simple GraphML file looks like:
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns">
<key id="name" for="node" attr.name="name" attr.type="string"/>
<key id="weight" for="edge" attr.name="weight" attr.type="double"/>
<graph id="G" edgedefault="directed">
<node id="n0">
<data key="name">Alice</data>
</node>
<node id="n1">
<data key="name">Bob</data>
</node>
<edge source="n0" target="n1">
<data key="weight">3.14</data>
</edge>
</graph>
</graphml>
Example DOT File
digraph G {
0 [label="Alice"];
1 [label="Bob"];
2 [label="Charlie"];
0 -> 1 [label="3.14"];
0 -> 2 [label="2.71"];
1 -> 2 [label="1.41"];
}
Error Handling
I/O functions can throw exceptions on error:
#include <boost/graph/graphml.hpp>
try {
std::ifstream infile("graph.graphml");
if (!infile) {
throw std::runtime_error("Could not open file");
}
read_graphml(infile, g, dp);
} catch (const boost::parse_error& e) {
std::cerr << "Parse error: " << e.what() << "\n";
} catch (const boost::directed_graph_error& e) {
std::cerr << "Graph type mismatch: " << e.what() << "\n";
} catch (const boost::graph_exception& e) {
std::cerr << "Graph error: " << e.what() << "\n";
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << "\n";
}
Format Comparison
| Feature | GraphML | DOT | DIMACS |
|---|---|---|---|
| Human-readable | Semi (XML) | Yes | Yes |
| Properties support | Full | Full | Limited |
| Directed graphs | Yes | Yes | Yes |
| Undirected graphs | Yes | Yes | Limited |
| Tool support | Good | Excellent (Graphviz) | Benchmarks |
| Best for | Data exchange | Visualization | Flow problems |
Recommendations
- Use GraphML for general-purpose graph storage and exchange
- Use DOT when you want to visualize graphs with Graphviz
- Use DIMACS for max-flow/min-cut benchmarking
- Always use dynamic_properties to make I/O code flexible
- Remember to build and link against the boost_graph library for GraphML support
For more details, see:
- read_graphml - Reading GraphML files
- write_graphml - Writing GraphML files
- read_graphviz - Reading DOT files
- write_graphviz - Writing DOT files
- read_dimacs_max_flow - Reading DIMACS files
- write_dimacs_max_flow - Writing DIMACS files
Copyright © 2000-2001 Jeremy Siek, Indiana University