The CinderGraph class, part of the CinderPeak namespace, provides a flexible and type-safe graph data structure for managing vertices and edges. It supports both weighted and unweighted graphs, as well as directed and undirected configurations, based on options specified during graph creation. The implementation leverages a PeakStore backend to handle the underlying storage and operations, ensuring efficient vertex and edge management.
The CinderGraph class is templated to allow customization of vertex (VertexType) and edge (EdgeType) data types, making it versatile for various applications, such as social networks, road networks, or dependency graphs. It includes methods for adding vertices and edges, retrieving edge weights.
namespace CinderPeak {
template <typename VertexType, typename EdgeType>
class CinderGraph {
private:
std::unique_ptr<CinderPeak::PeakStore::PeakStore<VertexType, EdgeType>> peak_store;
public:
CinderGraph(const GraphCreationOptions &options = CinderPeak::GraphCreationOptions::getDefaultCreateOptions());
void addVertex(const VertexType &v);
void addEdge(const VertexType &src, const VertexType &dest);
void addEdge(const VertexType &src, const VertexType &dest, const EdgeType &weight);
EdgeType getEdge(const VertexType &src, const VertexType &dest);
};
}VertexType: The data type for vertices (e.g.,int,std::string, or a custom type).EdgeType: The data type for edge weights (e.g.,int,double, or a custom type). For unweighted graphs, this type is still required but ignored in edge operations.
- Description: Initializes a new graph with the specified creation options. If no options are provided, default options are used (as defined by
GraphCreationOptions::getDefaultCreateOptions()). - Parameters:
options: AGraphCreationOptionsobject specifying graph properties (e.g., directed/undirected, weighted/unweighted).
- Behavior: Creates a
PeakStoreinstance with metadata indicating the graph's name ("cinder_graph") and whether the vertex and edge types are primitive.
- Description: Adds a vertex to the graph.
- Parameters:
v: The vertex to add, of typeVertexType.
- Behavior: Attempts to add the vertex using the
PeakStorebackend. If the operation fails, an exception is handled viaExceptions::handle_exception_map, and the method returns early. - Example: Adding a vertex
1to a graph of integers.
- Description: Adds an unweighted edge between two vertices.
- Parameters:
src: The source vertex.dest: The destination vertex.
- Behavior: Checks if the graph is configured as weighted. If so, logs a critical error and returns. Otherwise, attempts to add the edge using
PeakStore. Handles any errors viaExceptions::handle_exception_map. - Constraints: Only valid for unweighted graphs. Calling this on a weighted graph results in an error.
- Description: Adds a weighted edge between two vertices.
- Parameters:
src: The source vertex.dest: The destination vertex.weight: The weight of the edge, of typeEdgeType.
- Behavior: Checks if the graph is configured as unweighted. If so, logs a critical error and returns. Otherwise, attempts to add the edge with the specified weight using
PeakStore. Logs a message and handles errors viaExceptions::handle_exception_map. - Constraints: Only valid for weighted graphs. Calling this on an unweighted graph results in an error.
- Description: Retrieves the weight of the edge between two vertices.
- Parameters:
src: The source vertex.dest: The destination vertex.
- Returns: The edge weight of type
EdgeTypeif the edge exists; otherwise, a default-constructedEdgeTypeis returned if an error occurs. - Behavior: Queries the
PeakStorefor the edge weight. Logs a message and handles errors viaExceptions::handle_exception_map.
The GraphCreationOptions class (assumed to be defined in CinderPeak) allows configuration of the graph's properties. Common options include:
Directed: Specifies a directed graph (edges have direction).Undirected: Specifies an undirected graph (edges are bidirectional).Weighted: Specifies a weighted graph (edges have weights of typeEdgeType).Unweighted: Specifies an unweighted graph (edges have no weights).getDefaultCreateOptions(): Returns a default configuration (typically undirected and unweighted).
This example creates a directed, weighted graph with integer vertices and edges, adds vertices and edges.
#include "CinderPeak.hpp"
using namespace CinderPeak;
int main() {
GraphCreationOptions opts({GraphCreationOptions::Directed, GraphCreationOptions::Weighted});
CinderGraph<int, int> graph(opts);
graph.addVertex(1);
graph.addVertex(2);
graph.addVertex(3);
graph.addVertex(4);
graph.addVertex(5);
graph.addEdge(1, 3, 10);
graph.addEdge(1, 4, 9);
graph.addEdge(4, 5, 7);
graph.addEdge(1, 2, 6);
return 0;
}Explanation:
- Creates a directed, weighted graph.
- Adds vertices
1to5. - Adds weighted edges (e.g.,
1 -> 3with weight10).
This example demonstrates an undirected, unweighted graph with string vertices.
#include "CinderPeak.hpp"
using namespace CinderPeak;
int main() {
GraphCreationOptions opts({GraphCreationOptions::Undirected, GraphCreationOptions::Unweighted});
CinderGraph<std::string, int> graph(opts);
graph.addVertex("A");
graph.addVertex("B");
graph.addVertex("C");
graph.addVertex("D");
graph.addEdge("A", "B");
graph.addEdge("B", "C");
graph.addEdge("C", "D");
graph.addEdge("D", "A");
return 0;
}Explanation:
- Creates an undirected, unweighted graph with string vertices.
- Adds vertices labeled
"A","B","C", and"D". - Adds unweighted edges to form a cycle (
A-B-C-D-A).
This example creates a weighted graph, adds edges, and retrieves an edge weight.
#include "CinderPeak.hpp"
using namespace CinderPeak;
int main() {
GraphCreationOptions opts({GraphCreationOptions::Directed, GraphCreationOptions::Weighted});
CinderGraph<int, double> graph(opts);
graph.addVertex(1);
graph.addVertex(2);
graph.addVertex(3);
graph.addEdge(1, 2, 5.5);
graph.addEdge(2, 3, 3.2);
double weight = graph.getEdge(1, 2);
std::cout << "Weight of edge 1->2: " << weight << std::endl;
return 0;
}Explanation:
- Creates a directed, weighted graph with integer vertices and double-precision edge weights.
- Adds vertices
1,2, and3. - Adds weighted edges (
1 -> 2with weight5.5,2 -> 3with weight3.2). - Retrieves and prints the weight of the edge
1 -> 2.
This example demonstrates error handling when attempting to add an unweighted edge to a weighted graph.
#include "CinderPeak.hpp"
using namespace CinderPeak;
int main() {
GraphCreationOptions opts({GraphCreationOptions::Directed, GraphCreationOptions::Weighted});
CinderGraph<int, int> graph(opts);
graph.addVertex(1);
graph.addVertex(2);
// This will log an error due to missing weight
graph.addEdge(1, 2);
// Correctly add a weighted edge
graph.addEdge(1, 2, 10);
return 0;
}Explanation:
- Creates a directed, weighted graph.
- Adds vertices
1and2. - Attempts to add an unweighted edge, which logs a critical error (as the graph is weighted).
- Correctly adds a weighted edge (
1 -> 2with weight10).
- Description: Export the current graph to the Graphviz DOT format.
- Parameters:
filename: The path to the output file. (Mandatory)
- Behavior:
- Automatically detects if the graph is Directed (
digraph) or Undirected (graph). - Vertices are labeled with their values.
- Edges are labeled with their weights (if any).
- Uses
strictmode if ParallelEdges are not enabled in options. - Compile-time Check: Only available for graphs with primitive vertex/edge types.
- Automatically detects if the graph is Directed (
- Example:
// Write to file graph.toDot("graph_output.dot");
- Error Handling: The
CinderGraphclass usesExceptions::handle_exception_mapto manage errors fromPeakStoreoperations. Ensure that theExceptionsnamespace is properly configured to handle errors gracefully. - Type Safety: The
VertexTypeandEdgeTypemust be compatible with thePeakStorebackend and support operations like default construction (forgetEdgeerror cases).
CinderPeak.hpp: ProvidesGraphCreationOptions,PeakStore, and related utilities.StorageEngine/Utils.hpp: Likely provides utility functions likeisTypePrimitive.- Standard C++ libraries:
iostream,memory(forstd::unique_ptr).
- The
EdgeTypeparameter is required even for unweighted graphs, though it is unused in such cases. - Error messages are logged but not propagated to the caller, relying on
Exceptions::handle_exception_map.
This documentation provides a complete reference for using the CinderGraph class, with examples covering common use cases and edge cases.