From 856bb8e6ca337e05ddebcd8d268601f3b3f813d4 Mon Sep 17 00:00:00 2001 From: ale Date: Wed, 8 Oct 2025 03:59:36 +0200 Subject: [PATCH] fix bridge Signed-off-by: ale --- Dockerfile | 2 +- python/cudaq_bridge.py | 74 ++++++++++++++++++++++++++++++++----- src/bridge/python-bridge.ts | 25 +++++++------ 3 files changed, 79 insertions(+), 22 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1dfafe2..b34573e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ COPY package*.json ./ COPY tsconfig.json ./ # Install Node.js dependencies -RUN npm ci --only=production && npm cache clean --force +RUN npm ci && npm cache clean --force # Copy source code COPY src/ ./src/ diff --git a/python/cudaq_bridge.py b/python/cudaq_bridge.py index 13f9c1e..dcd2f0c 100644 --- a/python/cudaq_bridge.py +++ b/python/cudaq_bridge.py @@ -201,22 +201,39 @@ class QuantumExecutor: def __init__(self, kernel_manager: QuantumKernelManager): self.kernel_manager = kernel_manager - def set_target(self, target: str, configuration: Optional[Dict] = None) -> Dict: - """Set quantum execution target""" + def set_target(self, target_name: str, **kwargs) -> Dict: + """Set the quantum computing target/backend""" if not CUDAQ_AVAILABLE: - return {"error": "CUDA Quantum not available"} + return {"success": True, "target": target_name, "mode": "mock"} try: - if configuration: - cudaq.set_target(target, **configuration) - else: - cudaq.set_target(target) + # Get available targets first + available_targets = cudaq.get_targets() - return {"success": True, "target": target} + # Validate target exists + if target_name not in available_targets: + # Try common fallbacks + fallback_targets = ['qpp-cpu', 'density-matrix-cpu', 'default'] + for fallback in fallback_targets: + if fallback in available_targets: + print(f"WARNING - Target {target_name} not available, using {fallback}", flush=True) + cudaq.set_target(fallback, **kwargs) + return {"success": True, "target": fallback, "original_target": target_name, "fallback": True} + + # If no fallbacks work, return error but don't crash + return {"error": f"Invalid target name ({target_name}). Available targets: {available_targets}", "available_targets": available_targets} + + cudaq.set_target(target_name, **kwargs) + return {"success": True, "target": target_name} except Exception as e: - logger.error(f"Error setting target {target}: {e}") - return {"error": str(e), "traceback": traceback.format_exc()} + print(f"WARNING - Error setting target {target_name}: {e}", flush=True) + # Try to set a default target as fallback + try: + cudaq.reset_target() + return {"success": True, "target": "default", "original_target": target_name, "fallback": True, "warning": str(e)} + except: + return {"error": str(e), "traceback": traceback.format_exc()} def sample(self, kernel_name: str, shots: int = 1000, parameters: Optional[Dict] = None) -> Dict: @@ -399,6 +416,37 @@ kernel_manager = QuantumKernelManager() executor = QuantumExecutor(kernel_manager) +# Add missing methods to executor class +def get_target_info_standalone() -> Dict: + """Get information about available targets""" + if not CUDAQ_AVAILABLE: + return {"target": "mock", "mode": "mock"} + + try: + available_targets = cudaq.get_targets() + return { + "available_targets": available_targets, + "recommended_targets": ['qpp-cpu', 'density-matrix-cpu'] if available_targets else [] + } + + except Exception as e: + print(f"WARNING - Error getting target info: {e}", flush=True) + return {"error": str(e)} + +def get_available_targets_standalone() -> Dict: + """Get list of all available quantum targets""" + if not CUDAQ_AVAILABLE: + return {"targets": ["mock"], "mode": "mock"} + + try: + targets = cudaq.get_targets() + return {"targets": targets, "count": len(targets)} + + except Exception as e: + print(f"WARNING - Error getting available targets: {e}", flush=True) + return {"targets": [], "error": str(e)} + + def dispatch_command(command: str, **kwargs) -> Dict: """Main dispatch function for Python bridge commands""" try: @@ -446,6 +494,12 @@ def dispatch_command(command: str, **kwargs) -> Dict: kwargs.get("parameters") ) + elif command == "get_available_targets": + return get_available_targets_standalone() + + elif command == "get_target_info": + return get_target_info_standalone() + elif command == "list_kernels": return { "success": True, diff --git a/src/bridge/python-bridge.ts b/src/bridge/python-bridge.ts index 2609897..602541b 100644 --- a/src/bridge/python-bridge.ts +++ b/src/bridge/python-bridge.ts @@ -167,24 +167,27 @@ export class PythonBridge extends EventEmitter { /** * Send command to Python process */ - private async sendCommand(command: string, args: Record = {}): Promise { - if (!this.pythonProcess || !this.pythonProcess.stdin) { - throw new Error('Python process not running'); - } - - const requestId = (++this.requestId).toString(); - const commandData = { command, request_id: requestId, ...args }; - + private async sendCommand(command: string, data?: any): Promise { return new Promise((resolve, reject) => { + const requestId = Math.random().toString(36).substring(2, 15); + const request = { command, data, requestId }; + + // Set timeout - longer for target operations + const timeoutDuration = command === 'set_target' ? 10000 : 30000; // 10s for set_target, 30s for others const timeout = setTimeout(() => { this.requestQueue.delete(requestId); reject(new Error(`Python command timeout: ${command}`)); - }, this.config.timeout); + }, timeoutDuration); + // Store request with timeout for cleanup this.requestQueue.set(requestId, { resolve, reject, timeout }); + + if (!this.pythonProcess) { + reject(new Error('Python process not initialized')); + return; + } - const commandJson = JSON.stringify(commandData) + '\n'; - this.pythonProcess!.stdin!.write(commandJson); + this.pythonProcess.stdin?.write(JSON.stringify(request) + '\n'); }); }