Skip to content

05_02_DEPENDENCY_GRAPH - Quick Reference Card

🚀 5-Minute Quick Start

1. Include the API

#include <dependency_graph.hpp>
using namespace audio_lab::dependency_graph;

2. Load & Build Graph

auto builder = GraphBuilder::from_catalog("modules_catalog.json");
Graph graph = builder.build();

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

auto builder = GraphBuilder::from_catalog("catalog.json");
Graph graph = builder.build();

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

CircularLayout layout;
layout.set_radius(200.0);
auto positions = layout.compute(graph);

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


🆘 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