05_02_DEPENDENCY_GRAPH - Documentation Package¶
📋 Overview¶
Complete documentation package for the Dependency Graph Visualizer subsystem. This document consolidates all information needed to understand, use, extend, and maintain the system.
🎯 What is the Dependency Graph Visualizer?¶
A comprehensive system for analyzing, visualizing, and managing module dependencies in the AudioLab framework. It provides tools to:
- Visualize dependency relationships between modules
- Analyze paths, cycles, and bottlenecks
- Query the graph with a fluent API
- Export to multiple standard formats
- Monitor changes in real-time
- Generate documentation automatically
🏗️ Architecture Overview¶
Subsystem Components¶
The system consists of 14 integrated modules:
05_02_DEPENDENCY_GRAPH/
├── 05_02_00_graph_construction # Core graph data structures
├── 05_02_01_visualization_engine # Layout algorithms and renderers
├── 05_02_02_path_analysis # Critical paths and impact analysis
├── 05_02_03_cycle_detection # DAG validation and cycle detection
├── 05_02_04_metrics_calculator # Graph metrics and centrality
├── 05_02_05_filtering_system # Multi-criteria filtering
├── 05_02_06_diff_visualization # Change detection and comparison
├── 05_02_07_export_formats # Multi-format export (6+ formats)
├── 05_02_08_query_interface # Fluent query API
├── 05_02_09_live_monitoring # Real-time change monitoring
├── 05_02_10_documentation_integration # Auto-generate docs
├── 05_02_test_integration # Integration test suite
├── 05_02_interfaces # Public API and CMake integration
└── 05_02_documentation # Complete documentation (you are here)
Data Flow¶
graph LR
A[catalog.json] -->|Load| B[GraphBuilder]
B -->|Build| C[Graph]
C -->|Query| D[GraphQuery]
C -->|Analyze| E[Metrics/Paths]
C -->|Visualize| F[Renderers]
C -->|Export| G[Multiple Formats]
C -->|Monitor| H[LiveMonitor]
C -->|Document| I[DocGenerator]
Key Design Principles¶
- Modularity: Each subsystem is independent and composable
- Performance: O(V+E) algorithms, lazy evaluation
- Extensibility: Plugin architecture for new formats/layouts
- Type Safety: Modern C++20 with strong typing
- Header-Only: Most components are header-only for easy integration
📚 Documentation Index¶
Getting Started¶
- Quick Start Guide - Get up and running in 5 minutes
- Installation - Building and installing the library
- Basic Usage - Your first dependency graph
- Examples - Real-world usage scenarios
Core Concepts¶
- Graph Model - Understanding nodes, edges, and hierarchy
- Catalog Format - JSON schema for dependency catalogs
- Hierarchy Levels - L0_KERNEL through L3_ENGINE
- Query Language - Fluent API for graph interrogation
Subsystem Guides¶
- Graph Construction - Loading and building graphs
- Visualization - Layouts and rendering
- Path Analysis - Finding critical paths
- Cycle Detection - DAG validation
- Metrics - Computing graph metrics
- Filtering - Multi-criteria filters
- Diff Visualization - Comparing graphs
- Export Formats - DOT, JSON, GML, etc.
- Query Interface - Declarative queries
- Live Monitoring - Real-time updates
- Documentation Generation - Auto-docs
Advanced Topics¶
- Integration Guide - Using in your project
- Testing - Test suite and benchmarks
- Performance Tuning - Optimization strategies
- Extending the System - Adding new features
Reference¶
- API Reference - Complete class documentation
- CMake Reference - Build configuration
- Troubleshooting - Common issues and solutions
- FAQ - Frequently asked questions
Quick Start Guide¶
1. Install¶
2. Create CMake Project¶
# CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(MyApp)
set(CMAKE_CXX_STANDARD 20)
find_package(DependencyGraph REQUIRED)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE AudioLab::DependencyGraph)
3. Write Code¶
// main.cpp
#include <audio_lab/dependency_graph/dependency_graph.hpp>
#include <iostream>
int main() {
using namespace audio_lab::dependency_graph;
// Load dependency graph
GraphBuilder builder;
builder.load_from_catalog("catalog.json");
Graph graph = builder.build();
// Print statistics
auto stats = graph.compute_statistics();
std::cout << "Modules: " << stats.node_count << "\n";
std::cout << "Dependencies: " << stats.edge_count << "\n";
// Export visualization
DotExporter exporter;
exporter.export_to_file(graph, "dependencies.dot");
std::cout << "✅ Exported to dependencies.dot\n";
return 0;
}
4. Build and Run¶
5. Visualize¶
Installation¶
Prerequisites¶
- C++20 compiler (gcc 10+, clang 12+, MSVC 19.28+)
- CMake 3.20+
- Optional: Catch2 (for tests), GraphViz (for rendering)
Building from Source¶
# Clone repository
git clone https://github.com/audiolab/audio-lab.git
cd audio-lab/3\ -\ COMPONENTS/05_MODULES/05_02_DEPENDENCY_GRAPH
# Configure
mkdir build && cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/local
# Build
make -j$(nproc)
# Test (optional)
make test
# Install
sudo make install
Verify Installation¶
# Check if package is found
cmake --find-package -DNAME=DependencyGraph -DCOMPILER_ID=GNU -DLANGUAGE=CXX
# Or try the example
cd /usr/local/bin/examples
./simple_usage_example
Basic Usage¶
Loading a Graph¶
#include <audio_lab/dependency_graph/dependency_graph.hpp>
using namespace audio_lab::dependency_graph;
// From JSON catalog
GraphBuilder builder;
builder.load_from_catalog("catalog.json");
Graph graph = builder.build();
// Or build programmatically
Graph graph;
auto node1 = std::make_shared<Node>("id1", "Module 1", L1_ATOM);
auto node2 = std::make_shared<Node>("id2", "Module 2", L0_KERNEL);
graph.add_node(node1);
graph.add_node(node2);
graph.add_edge(std::make_shared<Edge>("id1", "id2"));
Querying¶
// Find all L3 engines
auto engines = GraphQuery(graph)
.select_all()
.where_level(HierarchyLevel::L3_ENGINE)
.get_nodes();
// Find expensive modules
auto expensive = GraphQuery(graph)
.select_all()
.where_cpu_greater_than(100)
.order_by_cpu()
.limit(10)
.get_nodes();
// Find dependencies
auto deps = GraphQuery(graph)
.start_from("my_module")
.traverse_downstream()
.recursive()
.get_nodes();
Exporting¶
// Single format
DotExporter dot_exporter;
dot_exporter.export_to_file(graph, "output.dot");
// Multiple formats
BatchExporter batch;
batch.add_formats({ExportFormat::DOT, ExportFormat::JSON, ExportFormat::MERMAID});
auto results = batch.export_all(graph, "my_graph");
// All formats at once
auto all = ExportTemplates::full_export();
all.export_all(graph, "complete");
Analyzing¶
// Compute metrics
MetricsEngine metrics(graph);
metrics.compute_all();
auto node_metrics = metrics.get_node_metrics("my_module");
std::cout << "Betweenness: " << node_metrics.betweenness << "\n";
// Find critical path
CriticalPathAnalyzer analyzer(graph);
auto path = analyzer.find_critical_path("start", [](auto n) {
return n->cpu_cycles;
});
// Detect cycles
auto cycles = GraphQuery(graph).get_cycles();
if (!cycles.empty()) {
std::cout << "⚠️ Cycles detected!\n";
}
Graph Model¶
Nodes (Modules)¶
Each node represents a module with properties:
- id: Unique identifier (UUID)
- label: Human-readable name
- level: Hierarchy level (L0/L1/L2/L3)
- category: Functional category (FILTER, OSC, etc.)
- status: Development status (STABLE, BETA, EXPERIMENTAL)
- cpu_cycles: Performance cost
- latency_samples: Processing latency
- version: Semantic version
- author: Creator
Edges (Dependencies)¶
Each edge represents a dependency:
- source: Dependent module (who needs)
- target: Required module (what is needed)
- type: Dependency type (REQUIRED, OPTIONAL, RUNTIME, BUILD)
- version_constraint: Version requirement (e.g., ">=1.5.0")
Graph Structure¶
- Directed: Dependencies flow in one direction
- Acyclic (DAG): No circular dependencies allowed
- Sparse: Typically 0.01-0.05 density
- Hierarchical: 4 levels with dependency rules
Catalog Format¶
JSON schema for dependency catalogs:
{
"version": "1.0",
"modules": [
{
"id": "filter_biquad",
"label": "Biquad Filter",
"level": "L1_ATOM",
"category": "FILTER",
"status": "STABLE",
"cpu_cycles": 50,
"latency_samples": 0,
"version": "1.0.0",
"author": "AudioLab",
"dependencies": [
{
"target": "mul",
"type": "REQUIRED",
"version": ">=1.0.0"
}
]
}
]
}
Fields:
- version: Catalog schema version
- modules: Array of module definitions
- dependencies: Array of dependency relationships
Hierarchy Levels¶
L0_KERNEL - Primitives¶
Basic mathematical and DSP operations: - Multiply, Add, Subtract - Bitwise operations - Type conversions
Rules: - No dependencies (or only other L0) - Minimal CPU (<5 cycles) - No latency
L1_ATOM - Basic Blocks¶
Fundamental DSP components: - Filters (biquad, one-pole, SVF) - Oscillators (sine, saw, square) - Envelopes (ADSR, AR)
Rules: - Depend only on L0 - Low CPU (<100 cycles) - Minimal latency (<64 samples)
L2_CELL - Complex Components¶
Higher-level components: - Voices (mono, poly) - Effects (reverb, delay, chorus) - Modulators (LFO, step sequencer)
Rules: - Depend on L0 and L1 - Moderate CPU (<500 cycles) - Can have latency
L3_ENGINE - Complete Systems¶
Full processing systems: - Synthesizers - Complete effect chains - Audio engines
Rules: - Can depend on L0, L1, L2 - High CPU allowed - Can have significant latency
Performance Tuning¶
For Large Graphs (500+ nodes)¶
// Use lazy evaluation
auto query = GraphQuery(graph)
.select_all()
.where_level(L2_CELL);
// Query not executed yet
// Execute when needed
auto results = query.get_nodes(); // Now executes
// Limit results for performance
auto top_10 = GraphQuery(graph)
.select_all()
.order_by_cpu()
.limit(10) // Stop after 10
.get_nodes();
Export Optimization¶
// Parallel export
BatchExporter batch;
batch.set_parallel(true); // Export formats in parallel
// Disable metadata for faster export
ExportOptions opts;
opts.include_metadata = false;
exporter.set_options(opts);
// Filter before exporting
auto filtered = FilterChain()
.by_level({L3_ENGINE})
.apply(graph);
// Export smaller graph
Metrics Caching¶
// Compute once
MetricsEngine metrics(graph);
metrics.compute_all();
// Query multiple times without recomputing
auto m1 = metrics.get_node_metrics("node1");
auto m2 = metrics.get_node_metrics("node2");
Extending the System¶
Adding a New Export Format¶
class MyCustomExporter : public IGraphExporter {
public:
std::string export_graph(const Graph& graph) override {
std::ostringstream oss;
// Your export logic here
for (const auto& [id, node] : graph.get_nodes()) {
oss << "NODE: " << node->label << "\n";
}
return oss.str();
}
protected:
std::string escape_string(const std::string& str) const override {
return str; // Implement escaping
}
};
// Usage
MyCustomExporter exporter;
std::string output = exporter.export_graph(graph);
Adding a Custom Metric¶
// Extend MetricsEngine
double calculate_custom_metric(const Graph& graph, const UUID& node_id) {
// Your metric calculation
auto node = graph.get_node(node_id);
auto deps = graph.get_dependencies(node_id);
return deps.size() * node->cpu_cycles; // Example
}
Adding a Custom Filter¶
class CustomFilter {
public:
Graph apply(const Graph& input) const {
Graph output;
for (const auto& [id, node] : input.get_nodes()) {
if (meets_criteria(node)) {
output.add_node(node);
}
}
// Add edges for included nodes
for (const auto& edge : input.get_edges()) {
if (output.get_node(edge->source) &&
output.get_node(edge->target)) {
output.add_edge(edge);
}
}
return output;
}
private:
bool meets_criteria(const NodePtr& node) const {
return node->category == "FILTER" && node->cpu_cycles < 50;
}
};
API Reference¶
Core Classes¶
Graph: Main graph containerNode: Module representationEdge: Dependency representationGraphBuilder: Catalog loader and graph builder
Query & Analysis¶
GraphQuery: Fluent query APIMetricsEngine: Graph metrics calculatorCriticalPathAnalyzer: Path analysisDfsCycleDetector: Cycle detection
Visualization & Export¶
DotExporter: GraphViz DOT formatJsonExporter: JSON formatMermaidExporter: Mermaid diagram formatBatchExporter: Multi-format export
Utilities¶
FilterChain: Graph filteringLiveMonitor: Change monitoringDocumentationGenerator: Auto-documentation
Troubleshooting¶
Common Issues¶
Problem: CMake can't find DependencyGraph
Solution:
Problem: Undefined symbols when linking
Solution:
Problem: C++20 features not available
Solution:
FAQ¶
Q: Is this library thread-safe?
A: Graph construction and queries are read-only and thread-safe. LiveMonitor uses mutexes for callbacks.
Q: What's the performance for large graphs?
A: Most operations are O(V+E). A graph with 500 nodes and 1500 edges processes in <1 second.
Q: Can I use this in a commercial project?
A: Yes, see LICENSE file for details.
Q: How do I report bugs?
A: Open an issue on GitHub with a minimal reproducible example.
Q: Can I export to custom formats?
A: Yes, extend IGraphExporter interface. See Extending the System.
License¶
Copyright © 2025 AudioLab Team
See LICENSE file for details.
Contributors¶
Developed as part of the AudioLab framework by the AudioLab team.
Changelog¶
v1.0.0 (2025-01-10)¶
Initial release with complete feature set: - ✅ Graph construction from JSON catalogs - ✅ 4 layout algorithms (hierarchical, force-directed, circular, tree) - ✅ 6+ export formats (DOT, GML, GraphML, JSON, Mermaid, CSV) - ✅ Fluent query API - ✅ Real-time monitoring - ✅ Auto-documentation generation - ✅ Complete test suite (85% coverage) - ✅ CMake integration
End of Documentation Package
For more information, explore the individual subsystem READMEs or contact the AudioLab team.