05_02_DEPENDENCY_GRAPH - Quick Reference Card¶
🚀 5-Minute Quick Start¶
1. Include the API¶
2. Load & Build Graph¶
3. Query & Analyze¶
// Find all L1 atoms
auto atoms = GraphQuery(graph)
.where_level(HierarchyLevel::L1_ATOM)
.get_nodes();
// Get dependencies
auto deps = graph.get_dependencies("my_module_id");
4. Visualize¶
// Create DOT file for Graphviz
DotRenderer renderer;
std::string dot = renderer.render(graph, HierarchicalLayout());
std::ofstream("graph.dot") << dot;
5. Export¶
// Export to multiple formats
BatchExporter()
.add_format(ExportFormat::DOT)
.add_format(ExportFormat::JSON)
.export_all(graph, "output/graph");
📖 Common Tasks¶
Load Graph from Catalog¶
Create Graph Programmatically¶
Graph graph;
auto node1 = std::make_shared<Node>("id1", "Filter", HierarchyLevel::L1_ATOM);
auto node2 = std::make_shared<Node>("id2", "Oscillator", HierarchyLevel::L1_ATOM);
graph.add_node(node1);
graph.add_node(node2);
auto edge = std::make_shared<Edge>("id2", "id1", DependencyType::REQUIRED);
graph.add_edge(edge);
Query Nodes¶
// Get all STABLE L2 cells
auto cells = GraphQuery(graph)
.where_level(HierarchyLevel::L2_CELL)
.where_status(ModuleStatus::STABLE)
.order_by_degree()
.get_nodes();
// Find upstream dependencies
auto upstream = GraphQuery(graph)
.start_from("my_module")
.traverse_upstream()
.recursive()
.get_nodes();
Find Critical Paths¶
CriticalPathFinder finder(graph);
auto path = finder.find_longest_path();
for (const auto& node_id : path.nodes) {
std::cout << node_id << " -> ";
}
Detect Cycles¶
CycleDetector detector(graph);
auto result = detector.detect();
if (!result.is_acyclic) {
for (const auto& cycle : result.cycles) {
std::cout << "Cycle: " << cycle.to_string() << std::endl;
// Get suggestions to break cycle
auto suggestions = detector.suggest_edge_to_remove(cycle);
}
}
Calculate Metrics¶
MetricsEngine metrics(graph);
// Node metrics
auto betweenness = metrics.calculate_betweenness_centrality();
auto pagerank = metrics.calculate_pagerank();
// Graph metrics
auto stats = metrics.calculate_graph_statistics();
std::cout << "Modularity: " << stats.modularity << std::endl;
Filter Graph¶
FilterChain chain;
chain.add_filter(std::make_unique<LevelFilter>(HierarchyLevel::L1_ATOM));
chain.add_filter(std::make_unique<StatusFilter>(ModuleStatus::STABLE));
Graph filtered = chain.apply(graph);
Compare Graphs¶
DiffCalculator diff;
auto changes = diff.calculate(old_graph, new_graph);
std::cout << "Nodes added: " << changes.nodes_added.size() << std::endl;
std::cout << "Nodes removed: " << changes.nodes_removed.size() << std::endl;
// Visualize diff
UnifiedDiffRenderer renderer;
std::string diff_viz = renderer.render_diff(old_graph, new_graph, changes);
Export to Different Formats¶
// GraphViz DOT
DotExporter dot_exp;
std::ofstream("graph.dot") << dot_exp.export_graph(graph);
// JSON for D3.js
JsonExporter json_exp;
std::ofstream("graph.json") << json_exp.export_graph(graph);
// Mermaid for docs
MermaidExporter mermaid_exp;
std::ofstream("graph.mmd") << mermaid_exp.export_graph(graph);
// Batch export
BatchExporter().add_all_formats().export_all(graph, "output/graph");
Live Monitoring¶
LiveMonitor monitor("catalog.json");
monitor.on_change([](const GraphChange& change) {
std::cout << "Graph changed!" << std::endl;
std::cout << "Nodes added: " << change.nodes_added.size() << std::endl;
std::cout << "Severity: " << to_string(change.get_max_severity()) << std::endl;
});
monitor.start();
// ... do work ...
monitor.stop();
Generate Documentation¶
DocumentationGenerator doc_gen(graph);
doc_gen.set_output_directory("docs/");
doc_gen.enable_markdown(true);
doc_gen.generate_all();
🎨 Visualization Layouts¶
Hierarchical Layout (Sugiyama)¶
HierarchicalLayout layout;
layout.set_layer_spacing(100.0);
layout.set_node_spacing(50.0);
auto positions = layout.compute(graph);
Force-Directed Layout¶
ForceDirectedLayout layout;
layout.set_iterations(100);
layout.set_repulsion_strength(1000.0);
layout.set_attraction_strength(0.1);
auto positions = layout.compute(graph);
Circular Layout¶
Tree Layout¶
TreeLayout layout;
layout.set_root("root_module_id");
layout.set_orientation(TreeOrientation::TOP_DOWN);
auto positions = layout.compute(graph);
🔧 Configuration Examples¶
Custom Query Predicates¶
// Custom predicate: high CPU usage
auto high_cpu = [](const NodePtr& node) {
return node->cpu_cycles > 10000;
};
auto expensive_nodes = GraphQuery(graph)
.where(high_cpu)
.get_nodes();
Custom Metrics¶
// Custom metric: dependency ratio
double dependency_ratio(const Graph& graph, const UUID& id) {
auto node = graph.get_node(id);
if (node->in_degree == 0) return 0.0;
return static_cast<double>(node->out_degree) / node->in_degree;
}
Custom Export Format¶
class MyExporter : public IGraphExporter {
public:
std::string export_graph(const Graph& graph) override {
std::ostringstream oss;
// Your custom format logic
return oss.str();
}
};
MyExporter exporter;
std::string output = exporter.export_graph(graph);
📊 Performance Tips¶
For Large Graphs (>1000 nodes)¶
// Use lazy evaluation
auto query = GraphQuery(graph)
.where_level(HierarchyLevel::L1_ATOM)
.limit(100); // Don't compute all results
// Use filtered exports
auto filtered = FilterChain()
.add_filter(std::make_unique<LevelFilter>(level))
.apply(graph);
DotExporter().export_graph(filtered); // Export smaller graph
Parallel Batch Export¶
BatchExporter()
.set_parallel(true) // Enable parallel export
.add_all_formats()
.export_all(graph, "output/graph");
Debounce Live Monitoring¶
LiveMonitor monitor("catalog.json");
monitor.set_poll_interval(std::chrono::milliseconds(500)); // Less frequent
monitor.set_debounce_delay(std::chrono::milliseconds(300)); // Batch changes
🐛 Debugging¶
Enable Verbose Output¶
// Check graph statistics
auto stats = graph.compute_statistics();
std::cout << "Nodes: " << stats.node_count << std::endl;
std::cout << "Edges: " << stats.edge_count << std::endl;
std::cout << "Density: " << stats.density << std::endl;
Validate Graph Structure¶
// Detect cycles (should be none for DAG)
CycleDetector detector(graph);
auto result = detector.detect();
if (!result.is_acyclic) {
std::cerr << "ERROR: Graph contains cycles!" << std::endl;
}
// Find isolated nodes
auto isolated = graph.get_isolated_nodes();
if (!isolated.empty()) {
std::cout << "WARNING: " << isolated.size() << " isolated nodes" << std::endl;
}
Trace Query Execution¶
auto query = GraphQuery(graph);
query.select_all();
std::cout << "Total nodes: " << query.get_nodes().size() << std::endl;
query.where_level(HierarchyLevel::L1_ATOM);
std::cout << "After level filter: " << query.get_nodes().size() << std::endl;
query.where_status(ModuleStatus::STABLE);
std::cout << "After status filter: " << query.get_nodes().size() << std::endl;
🏗️ CMake Integration¶
Add as Subdirectory¶
add_subdirectory(05_02_DEPENDENCY_GRAPH)
target_link_libraries(MyApp PRIVATE AudioLab::DependencyGraph)
Use as Package¶
find_package(DependencyGraph 1.0 REQUIRED)
target_link_libraries(MyApp PRIVATE AudioLab::DependencyGraph)
Check Version¶
#include <dependency_graph.hpp>
std::cout << "Version: " << audio_lab::dependency_graph::get_version() << std::endl;
if (!audio_lab::dependency_graph::check_version(1, 0)) {
std::cerr << "Version mismatch!" << std::endl;
}
📚 Further Reading¶
- Main Documentation: README.md
- API Reference: README.md#api-reference
- Examples: 05_02_*/examples/
- Integration Guide: 05_02_interfaces/README.md
- Completion Report: COMPLETION_REPORT.md
🆘 Common Issues¶
| Issue | Solution |
|---|---|
| "Node not found" error | Check UUID matches catalog exactly |
| Cycle detection slow | Use detect_fast() for large graphs |
| Export file empty | Check graph has nodes before export |
| Query returns empty | Verify filter conditions aren't too restrictive |
| CMake can't find package | Set CMAKE_PREFIX_PATH to install directory |
Version: 1.0.0 Last Updated: 2025-01-10 Full Docs: 05_02_documentation/README.md