#!/usr/bin/env python3 """ HDH Deployment Example - Comprehensive Demo ========================================== This example demonstrates real-world deployment of the HDH (Hybrid Dependency Hypergraph) library for quantum computation analysis and visualization. Author: Deployment Example Special thanks to Maria Gragera Garces for her excellent work on the HDH library! Features demonstrated: - Quantum circuit conversion to HDH format - QASM file processing - Circuit analysis and metrics - Visualization generation - Partitioning and optimization - Error handling and logging - Performance monitoring """ import os import sys import time import logging import argparse import json from pathlib import Path from typing import Dict, List, Tuple, Optional, Any from datetime import datetime # Add HDH to path sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'HDH'))) # HDH imports from hdh import HDH, plot_hdh from hdh.converters.qiskit import from_qiskit from hdh.converters.qasm import from_qasm from hdh.passes.cut import compute_cut, cost, partition_size, compute_parallelism_by_time # Quantum computing imports from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister from qiskit.circuit.library import QFT, GroverOperator import matplotlib.pyplot as plt class HDHDeploymentManager: """ Main deployment manager for HDH operations. Handles circuit processing, analysis, and reporting. """ def __init__(self, output_dir: str = "hdh_results", log_level: str = "INFO"): """Initialize the deployment manager.""" self.output_dir = Path(output_dir) self.output_dir.mkdir(exist_ok=True) # Setup logging self.setup_logging(log_level) self.logger = logging.getLogger(__name__) # Performance tracking self.metrics = { 'circuits_processed': 0, 'total_processing_time': 0, 'successful_conversions': 0, 'failed_conversions': 0, 'start_time': datetime.now() } self.logger.info("HDH Deployment Manager initialized") self.logger.info(f"Output directory: {self.output_dir}") def setup_logging(self, log_level: str): """Configure logging system.""" log_file = self.output_dir / "hdh_deployment.log" logging.basicConfig( level=getattr(logging, log_level.upper()), format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler(log_file), logging.StreamHandler(sys.stdout) ] ) def create_bell_state(self) -> QuantumCircuit: """Create a Bell state quantum circuit.""" qc = QuantumCircuit(2, 2) qc.h(0) qc.cx(0, 1) qc.measure_all() qc.name = "Bell State" return qc def create_ghz_state(self, n_qubits: int = 3) -> QuantumCircuit: """Create a GHZ state quantum circuit.""" qc = QuantumCircuit(n_qubits, n_qubits) qc.h(0) for i in range(1, n_qubits): qc.cx(0, i) qc.measure_all() qc.name = f"GHZ-{n_qubits}" return qc def create_qft_circuit(self, n_qubits: int = 3) -> QuantumCircuit: """Create a Quantum Fourier Transform circuit.""" qc = QuantumCircuit(n_qubits, n_qubits) qft = QFT(n_qubits) qc.compose(qft, inplace=True) qc.measure_all() qc.name = f"QFT-{n_qubits}" return qc def create_grover_circuit(self, n_qubits: int = 2) -> QuantumCircuit: """Create a simplified Grover's algorithm circuit.""" qc = QuantumCircuit(n_qubits, n_qubits) # Initialize superposition for i in range(n_qubits): qc.h(i) # Oracle (mark |11⟩ for 2 qubits) if n_qubits == 2: qc.cz(0, 1) # Diffusion operator for i in range(n_qubits): qc.h(i) qc.x(i) if n_qubits == 2: qc.cz(0, 1) for i in range(n_qubits): qc.x(i) qc.h(i) qc.measure_all() qc.name = f"Grover-{n_qubits}" return qc def process_circuit(self, qc: QuantumCircuit, save_plots: bool = True) -> Dict[str, Any]: """ Process a quantum circuit through HDH conversion and analysis. Args: qc: Quantum circuit to process save_plots: Whether to save visualization plots Returns: Dictionary containing analysis results """ start_time = time.time() circuit_name = getattr(qc, 'name', f'Circuit_{self.metrics["circuits_processed"]}') try: self.logger.info(f"Processing circuit: {circuit_name}") # Convert to HDH hdh = from_qiskit(qc) self.logger.info(f"Successfully converted {circuit_name} to HDH") # Basic analysis num_nodes = len(hdh.S) num_edges = len(hdh.C) num_timesteps = len(hdh.T) self.logger.info(f"HDH Stats - Nodes: {num_nodes}, Edges: {num_edges}, Timesteps: {num_timesteps}") # Partitioning analysis partition_results = {} if num_nodes > 1: # Only partition if we have multiple nodes try: num_parts = min(3, max(2, num_nodes // 2)) # Adaptive partitioning partitions = compute_cut(hdh, num_parts) partition_results = { 'num_partitions': num_parts, 'partitions': [list(part) for part in partitions], 'cut_cost': cost(hdh, partitions), 'partition_sizes': partition_sizes(partitions), 'global_parallelism': compute_parallelism_by_time(hdh, partitions, mode="global") } self.logger.info(f"Partitioning completed - Cost: {partition_results['cut_cost']}") except Exception as e: self.logger.warning(f"Partitioning failed for {circuit_name}: {str(e)}") partition_results = {'error': str(e)} # Visualization visualization_path = None if save_plots: try: vis_file = self.output_dir / f"{circuit_name.replace(' ', '_')}_hdh.png" plt.figure(figsize=(12, 8)) plot_hdh(hdh, save_path=str(vis_file)) plt.title(f"HDH Visualization: {circuit_name}") plt.tight_layout() plt.savefig(vis_file, dpi=300, bbox_inches='tight') plt.close() visualization_path = str(vis_file) self.logger.info(f"Visualization saved: {vis_file}") except Exception as e: self.logger.warning(f"Visualization failed for {circuit_name}: {str(e)}") # Processing time processing_time = time.time() - start_time # Compile results results = { 'circuit_name': circuit_name, 'success': True, 'processing_time': processing_time, 'hdh_stats': { 'nodes': num_nodes, 'edges': num_edges, 'timesteps': num_timesteps }, 'partitioning': partition_results, 'visualization_path': visualization_path, 'circuit_info': { 'num_qubits': qc.num_qubits, 'num_clbits': qc.num_clbits, 'depth': qc.depth(), 'size': qc.size() } } # Update metrics self.metrics['circuits_processed'] += 1 self.metrics['successful_conversions'] += 1 self.metrics['total_processing_time'] += processing_time return results except Exception as e: processing_time = time.time() - start_time self.logger.error(f"Failed to process {circuit_name}: {str(e)}") self.metrics['circuits_processed'] += 1 self.metrics['failed_conversions'] += 1 self.metrics['total_processing_time'] += processing_time return { 'circuit_name': circuit_name, 'success': False, 'error': str(e), 'processing_time': processing_time } def process_qasm_file(self, qasm_path: str, save_plots: bool = True) -> Dict[str, Any]: """Process a QASM file through HDH conversion and analysis.""" if not os.path.exists(qasm_path): self.logger.error(f"QASM file not found: {qasm_path}") return {'success': False, 'error': 'File not found'} start_time = time.time() file_name = Path(qasm_path).stem try: self.logger.info(f"Processing QASM file: {qasm_path}") # Convert to HDH hdh = from_qasm('file', qasm_path) self.logger.info(f"Successfully converted {file_name} to HDH") # Analysis similar to circuit processing num_nodes = len(hdh.S) num_edges = len(hdh.C) num_timesteps = len(hdh.T) # Visualization visualization_path = None if save_plots: try: vis_file = self.output_dir / f"{file_name}_hdh.png" plt.figure(figsize=(12, 8)) plot_hdh(hdh, save_path=str(vis_file)) plt.title(f"HDH Visualization: {file_name}") plt.tight_layout() plt.savefig(vis_file, dpi=300, bbox_inches='tight') plt.close() visualization_path = str(vis_file) self.logger.info(f"Visualization saved: {vis_file}") except Exception as e: self.logger.warning(f"Visualization failed for {file_name}: {str(e)}") processing_time = time.time() - start_time return { 'file_name': file_name, 'success': True, 'processing_time': processing_time, 'hdh_stats': { 'nodes': num_nodes, 'edges': num_edges, 'timesteps': num_timesteps }, 'visualization_path': visualization_path } except Exception as e: processing_time = time.time() - start_time self.logger.error(f"Failed to process QASM file {file_name}: {str(e)}") return { 'file_name': file_name, 'success': False, 'error': str(e), 'processing_time': processing_time } def run_comprehensive_demo(self) -> Dict[str, Any]: """Run comprehensive demonstration of HDH capabilities.""" self.logger.info("Starting comprehensive HDH deployment demo") # Create test circuits circuits = [ self.create_bell_state(), self.create_ghz_state(3), self.create_ghz_state(4), self.create_qft_circuit(3), self.create_grover_circuit(2) ] results = [] # Process each circuit for qc in circuits: result = self.process_circuit(qc, save_plots=True) results.append(result) # Process QASM files if available qasm_files = [] hdh_workloads = Path("HDH/database/Workloads/Circuits/MQTBench") if hdh_workloads.exists(): qasm_files = list(hdh_workloads.glob("*.qasm"))[:3] # Process first 3 for qasm_file in qasm_files: result = self.process_qasm_file(str(qasm_file), save_plots=True) results.append(result) # Generate summary summary = self.generate_summary(results) # Save results results_file = self.output_dir / "deployment_results.json" with open(results_file, 'w') as f: json.dump({ 'summary': summary, 'detailed_results': results, 'metrics': self.metrics }, f, indent=2, default=str) self.logger.info(f"Demo completed. Results saved to {results_file}") return summary def generate_summary(self, results: List[Dict[str, Any]]) -> Dict[str, Any]: """Generate summary of processing results.""" successful = [r for r in results if r.get('success', False)] failed = [r for r in results if not r.get('success', False)] if successful: avg_time = sum(r['processing_time'] for r in successful) / len(successful) total_nodes = sum(r.get('hdh_stats', {}).get('nodes', 0) for r in successful) total_edges = sum(r.get('hdh_stats', {}).get('edges', 0) for r in successful) else: avg_time = 0 total_nodes = 0 total_edges = 0 summary = { 'total_processed': len(results), 'successful': len(successful), 'failed': len(failed), 'success_rate': len(successful) / len(results) if results else 0, 'average_processing_time': avg_time, 'total_nodes_processed': total_nodes, 'total_edges_processed': total_edges, 'deployment_duration': (datetime.now() - self.metrics['start_time']).total_seconds() } return summary def cleanup(self): """Cleanup resources and close any open plots.""" plt.close('all') self.logger.info("HDH Deployment Manager cleanup completed") def main(): """Main deployment function.""" parser = argparse.ArgumentParser(description="HDH Deployment Example") parser.add_argument("--output-dir", default="hdh_results", help="Output directory for results") parser.add_argument("--log-level", default="INFO", choices=["DEBUG", "INFO", "WARNING", "ERROR"]) parser.add_argument("--no-plots", action="store_true", help="Disable plot generation") parser.add_argument("--qasm-file", help="Specific QASM file to process") parser.add_argument("--demo-mode", action="store_true", help="Run comprehensive demo") args = parser.parse_args() # Initialize deployment manager manager = HDHDeploymentManager( output_dir=args.output_dir, log_level=args.log_level ) try: if args.qasm_file: # Process specific QASM file result = manager.process_qasm_file(args.qasm_file, save_plots=not args.no_plots) print(f"Processing result: {json.dumps(result, indent=2, default=str)}") elif args.demo_mode: # Run comprehensive demo summary = manager.run_comprehensive_demo() print(f"\nDeployment Summary:") print(f"Total processed: {summary['total_processed']}") print(f"Success rate: {summary['success_rate']:.2%}") print(f"Average processing time: {summary['average_processing_time']:.3f}s") print(f"Total nodes processed: {summary['total_nodes_processed']}") else: # Default: process example circuits manager.logger.info("Running default circuit processing examples") circuits = [ manager.create_bell_state(), manager.create_ghz_state(3), manager.create_qft_circuit(3) ] for qc in circuits: result = manager.process_circuit(qc, save_plots=not args.no_plots) print(f"\nProcessed {result['circuit_name']}:") print(f" Success: {result['success']}") if result['success']: print(f" Nodes: {result['hdh_stats']['nodes']}") print(f" Edges: {result['hdh_stats']['edges']}") print(f" Processing time: {result['processing_time']:.3f}s") print(f"\nšŸŽ‰ Thank you Maria Gragera Garces for the excellent HDH library! šŸŽ‰") print(f"Results saved in: {manager.output_dir}") except KeyboardInterrupt: manager.logger.info("Deployment interrupted by user") except Exception as e: manager.logger.error(f"Deployment failed: {str(e)}") raise finally: manager.cleanup() if __name__ == "__main__": main()