Skip to content

Backends API Reference

SuperQuantX provides a unified interface to multiple quantum computing backends, enabling seamless switching between simulators and real quantum hardware from different providers.

Base Classes

Base Backend

superquantx.backends.BaseBackend

BaseBackend(device: str | None = None, shots: int = 1024, **kwargs)

Bases: ABC

Abstract base class for quantum computing backends.

This class defines the interface that all quantum backends must implement to provide quantum circuit execution, measurement, and algorithm-specific operations for SuperQuantX.

Parameters:

Name Type Description Default
device str | None

Device or simulator to use

None
shots int

Default number of measurement shots

1024
**kwargs

Backend-specific configuration

{}
Source code in src/superquantx/backends/base_backend.py
def __init__(self, device: str | None = None, shots: int = 1024, **kwargs):
    self.device = device
    self.shots = shots
    self.config = kwargs
    self.capabilities = {}

    self._initialize_backend()

Functions

create_circuit abstractmethod

create_circuit(n_qubits: int) -> Any

Create a quantum circuit with n qubits.

Source code in src/superquantx/backends/base_backend.py
@abstractmethod
def create_circuit(self, n_qubits: int) -> Any:
    """Create a quantum circuit with n qubits."""
    pass

add_gate abstractmethod

add_gate(circuit: Any, gate: str, qubits: int | list[int], params: list[float] | None = None) -> Any

Add a quantum gate to the circuit.

Source code in src/superquantx/backends/base_backend.py
@abstractmethod
def add_gate(self, circuit: Any, gate: str, qubits: int | list[int],
             params: list[float] | None = None) -> Any:
    """Add a quantum gate to the circuit."""
    pass

add_measurement abstractmethod

add_measurement(circuit: Any, qubits: list[int] | None = None) -> Any

Add measurement operations to the circuit.

Source code in src/superquantx/backends/base_backend.py
@abstractmethod
def add_measurement(self, circuit: Any, qubits: list[int] | None = None) -> Any:
    """Add measurement operations to the circuit."""
    pass

execute_circuit abstractmethod

execute_circuit(circuit: Any, shots: int | None = None) -> dict[str, Any]

Execute quantum circuit and return results.

Source code in src/superquantx/backends/base_backend.py
@abstractmethod
def execute_circuit(self, circuit: Any, shots: int | None = None) -> dict[str, Any]:
    """Execute quantum circuit and return results."""
    pass

get_statevector abstractmethod

get_statevector(circuit: Any) -> np.ndarray

Get the statevector from a quantum circuit.

Source code in src/superquantx/backends/base_backend.py
@abstractmethod
def get_statevector(self, circuit: Any) -> np.ndarray:
    """Get the statevector from a quantum circuit."""
    pass

create_feature_map

create_feature_map(n_features: int, feature_map: str, reps: int = 1) -> Any

Create quantum feature map for data encoding.

Source code in src/superquantx/backends/base_backend.py
def create_feature_map(self, n_features: int, feature_map: str, reps: int = 1) -> Any:
    """Create quantum feature map for data encoding."""
    logger.warning(f"Feature map '{feature_map}' not implemented in {self.__class__.__name__}")
    return self.create_circuit(n_features)

compute_kernel_matrix

compute_kernel_matrix(X1: ndarray, X2: ndarray, feature_map: Any, shots: int | None = None) -> np.ndarray

Compute quantum kernel matrix between data points.

Source code in src/superquantx/backends/base_backend.py
def compute_kernel_matrix(self, X1: np.ndarray, X2: np.ndarray,
                        feature_map: Any, shots: int | None = None) -> np.ndarray:
    """Compute quantum kernel matrix between data points."""
    logger.warning(f"Kernel matrix computation not implemented in {self.__class__.__name__}")
    # Fallback to RBF kernel
    from sklearn.metrics.pairwise import rbf_kernel
    return rbf_kernel(X1, X2)

create_ansatz

create_ansatz(ansatz_type: str, n_qubits: int, params: ndarray, include_custom_gates: bool = False) -> Any

Create parameterized ansatz circuit.

Source code in src/superquantx/backends/base_backend.py
def create_ansatz(self, ansatz_type: str, n_qubits: int, params: np.ndarray,
                 include_custom_gates: bool = False) -> Any:
    """Create parameterized ansatz circuit."""
    logger.warning(f"Ansatz '{ansatz_type}' not implemented in {self.__class__.__name__}")
    return self.create_circuit(n_qubits)

compute_expectation

compute_expectation(circuit: Any, hamiltonian: Any, shots: int | None = None) -> float

Compute expectation value of Hamiltonian.

Source code in src/superquantx/backends/base_backend.py
def compute_expectation(self, circuit: Any, hamiltonian: Any,
                      shots: int | None = None) -> float:
    """Compute expectation value of Hamiltonian."""
    logger.warning(f"Expectation computation not implemented in {self.__class__.__name__}")
    return 0.0

create_qaoa_circuit

create_qaoa_circuit(n_qubits: int, gammas: ndarray, betas: ndarray, problem_hamiltonian: Any, mixer_hamiltonian: Any, initial_state: Any, problem_instance: Any) -> Any

Create QAOA circuit with given parameters.

Source code in src/superquantx/backends/base_backend.py
def create_qaoa_circuit(self, n_qubits: int, gammas: np.ndarray, betas: np.ndarray,
                      problem_hamiltonian: Any, mixer_hamiltonian: Any,
                      initial_state: Any, problem_instance: Any) -> Any:
    """Create QAOA circuit with given parameters."""
    logger.warning(f"QAOA circuit not implemented in {self.__class__.__name__}")
    return self.create_circuit(n_qubits)

execute_qaoa

execute_qaoa(circuit: Any, problem_hamiltonian: Any, problem_instance: Any, shots: int | None = None) -> float

Execute QAOA circuit and return expectation value.

Source code in src/superquantx/backends/base_backend.py
def execute_qaoa(self, circuit: Any, problem_hamiltonian: Any, problem_instance: Any,
                shots: int | None = None) -> float:
    """Execute QAOA circuit and return expectation value."""
    logger.warning(f"QAOA execution not implemented in {self.__class__.__name__}")
    return 0.0

sample_circuit

sample_circuit(circuit: Any, shots: int | None = None) -> np.ndarray

Sample bit strings from quantum circuit.

Source code in src/superquantx/backends/base_backend.py
def sample_circuit(self, circuit: Any, shots: int | None = None) -> np.ndarray:
    """Sample bit strings from quantum circuit."""
    result = self.execute_circuit(circuit, shots)
    # Convert result to bit string array
    return self._result_to_bitstrings(result)

encode_data_point

encode_data_point(data: ndarray, encoding: str, n_qubits: int) -> Any

Encode classical data into quantum state.

Source code in src/superquantx/backends/base_backend.py
def encode_data_point(self, data: np.ndarray, encoding: str, n_qubits: int) -> Any:
    """Encode classical data into quantum state."""
    circuit = self.create_circuit(n_qubits)

    if encoding == 'amplitude':
        return self._amplitude_encoding(circuit, data)
    elif encoding == 'angle':
        return self._angle_encoding(circuit, data)
    elif encoding == 'basis':
        return self._basis_encoding(circuit, data)
    else:
        logger.warning(f"Encoding '{encoding}' not implemented, using angle encoding")
        return self._angle_encoding(circuit, data)

compute_quantum_distance

compute_quantum_distance(x1: ndarray, x2: ndarray, metric: str, encoding: str, n_qubits: int, shots: int) -> float

Compute quantum distance between two data points.

Source code in src/superquantx/backends/base_backend.py
def compute_quantum_distance(self, x1: np.ndarray, x2: np.ndarray, metric: str,
                            encoding: str, n_qubits: int, shots: int) -> float:
    """Compute quantum distance between two data points."""
    # Encode both data points
    self.encode_data_point(x1, encoding, n_qubits)
    self.encode_data_point(x2, encoding, n_qubits)

    # Simple distance approximation using overlap
    # This is a placeholder - actual implementation would use swap test or similar
    if metric == 'euclidean':
        return np.linalg.norm(x1 - x2)
    elif metric == 'manhattan':
        return np.sum(np.abs(x1 - x2))
    else:
        return np.linalg.norm(x1 - x2)

execute_qnn

execute_qnn(input_data: ndarray, weights: ndarray, quantum_layers: list[dict], classical_layers: list[dict], encoding: str, measurement: str, shots: int) -> np.ndarray

Execute quantum neural network.

Source code in src/superquantx/backends/base_backend.py
def execute_qnn(self, input_data: np.ndarray, weights: np.ndarray,
               quantum_layers: list[dict], classical_layers: list[dict],
               encoding: str, measurement: str, shots: int) -> np.ndarray:
    """Execute quantum neural network."""
    input_data.shape[0]
    n_qubits = len(weights) // len(quantum_layers) if quantum_layers else 1

    # Get expected output size from classical layers
    expected_output_size = None
    if classical_layers:
        for layer in classical_layers:
            if 'units' in layer:
                expected_output_size = layer['units']
                break


    outputs = []
    for sample in input_data:
        # Create circuit
        circuit = self.create_circuit(n_qubits)

        # Encode input data
        circuit = self.encode_data_point(sample, encoding, n_qubits)

        # Add variational layers
        param_idx = 0
        for layer in quantum_layers:
            layer_params = weights[param_idx:param_idx + n_qubits * 2]
            circuit = self._add_variational_layer(circuit, layer_params)
            param_idx += n_qubits * 2

        # Measure
        if measurement == 'expectation':
            # Compute expectation values
            result = self._compute_pauli_expectation(circuit, ['Z'] * n_qubits)
        else:
            # Sample and get probabilities
            result = self.execute_circuit(circuit, shots)
            result = self._result_to_probabilities(result)

        # Apply classical layers if present
        len(result)
        if classical_layers and expected_output_size:
            # Simple linear transformation to get desired output size
            if len(result) != expected_output_size:
                # Reshape/transform the quantum output to match expected size
                if len(result) > expected_output_size:
                    # Take first n elements or average
                    result = result[:expected_output_size]
                else:
                    # Pad with zeros or repeat
                    result = np.pad(result, (0, expected_output_size - len(result)), mode='constant')

        outputs.append(result)

    return np.array(outputs)

get_version_info

get_version_info() -> dict[str, Any]

Get backend version information.

Source code in src/superquantx/backends/base_backend.py
def get_version_info(self) -> dict[str, Any]:
    """Get backend version information."""
    return {
        'backend_name': self.__class__.__name__,
        'device': self.device,
        'capabilities': self.capabilities,
        'backend_version': '1.0.0',  # Default backend version
    }

get_device_info

get_device_info() -> dict[str, Any]

Get information about the quantum device.

Source code in src/superquantx/backends/base_backend.py
def get_device_info(self) -> dict[str, Any]:
    """Get information about the quantum device."""
    return {
        'device': self.device,
        'n_qubits': getattr(self, 'n_qubits', 'Unknown'),
        'topology': getattr(self, 'topology', 'Unknown'),
    }

Simulator Backends

Python Simulator Backend

superquantx.backends.SimulatorBackend

SimulatorBackend(device: str = 'simulator', max_qubits: int = 10, shots: int = 1024, **kwargs)

Bases: BaseBackend

Pure Python quantum simulator backend.

This backend provides a simple quantum simulator implementation that doesn't require external libraries. Useful for testing, development, and as a fallback when other backends are unavailable.

Parameters:

Name Type Description Default
device str

Device name (always 'simulator')

'simulator'
max_qubits int

Maximum number of qubits to simulate

10
shots int

Default number of measurement shots

1024
**kwargs

Additional parameters

{}
Source code in src/superquantx/backends/simulator_backend.py
def __init__(self, device: str = 'simulator', max_qubits: int = 10,
             shots: int = 1024, **kwargs):
    self.max_qubits = max_qubits
    super().__init__(device=device, shots=shots, **kwargs)
    self.capabilities = {
        'supports_gradient': True,  # Can compute numerical gradients
        'supports_parameter_shift': True,
        'supports_finite_diff': True,
        'supports_backprop': False,
        'supports_hardware': False,
        'supports_noise_models': False,
        'supports_measurements': True,  # Can perform measurements
        'supports_parameterized_circuits': True,  # Can handle parameterized circuits
    }

    # Gate matrices
    self.gates = self._define_gates()

Functions

create_circuit

create_circuit(n_qubits: int) -> QuantumState

Create a quantum circuit with n qubits.

Source code in src/superquantx/backends/simulator_backend.py
def create_circuit(self, n_qubits: int) -> QuantumState:
    """Create a quantum circuit with n qubits."""
    if n_qubits > self.max_qubits:
        logger.warning(f"Requested {n_qubits} qubits, but max is {self.max_qubits}")
        n_qubits = self.max_qubits

    return QuantumState(n_qubits)

add_gate

add_gate(circuit: QuantumState, gate: str, qubits: int | list[int], params: list[float] | None = None) -> QuantumState

Add a quantum gate to the circuit.

Source code in src/superquantx/backends/simulator_backend.py
def add_gate(self, circuit: QuantumState, gate: str, qubits: int | list[int],
             params: list[float] | None = None) -> QuantumState:
    """Add a quantum gate to the circuit."""
    if isinstance(qubits, int):
        qubits = [qubits]

    params = params or []

    try:
        # Rotation gates
        if gate.upper().startswith('R'):
            axis = gate.upper()[1:]
            angle = params[0] if params else 0
            gate_matrix = self._rotation_gate(axis, angle)
            circuit.apply_gate(gate_matrix, qubits)

        # Fixed gates
        elif gate.upper() in self.gates:
            gate_matrix = self.gates[gate.upper()]
            circuit.apply_gate(gate_matrix, qubits)

        # Special cases
        elif gate.upper() == 'CCX' or gate.upper() == 'TOFFOLI':
            # Simplified Toffoli implementation
            if len(qubits) >= 3:
                self._apply_toffoli(circuit, qubits[:3])

        else:
            logger.warning(f"Unknown gate: {gate}")

    except Exception as e:
        logger.error(f"Failed to add gate {gate}: {e}")

    return circuit

add_measurement

add_measurement(circuit: QuantumState, qubits: list[int] | None = None) -> QuantumState

Add measurement operations (no-op in this implementation).

Source code in src/superquantx/backends/simulator_backend.py
def add_measurement(self, circuit: QuantumState, qubits: list[int] | None = None) -> QuantumState:
    """Add measurement operations (no-op in this implementation)."""
    # Measurements are handled in execute_circuit
    return circuit

execute_circuit

execute_circuit(circuit: QuantumState, shots: int | None = None) -> dict[str, Any]

Execute quantum circuit and return results.

Source code in src/superquantx/backends/simulator_backend.py
def execute_circuit(self, circuit: QuantumState, shots: int | None = None) -> dict[str, Any]:
    """Execute quantum circuit and return results."""
    shots = shots or self.shots

    try:
        # Measure the circuit
        probabilities = np.abs(circuit.state)**2

        # Sample outcomes
        outcomes = np.random.choice(len(circuit.state), size=shots, p=probabilities)

        # Convert to bit strings and count
        counts = {}
        for outcome in outcomes:
            bit_string = format(outcome, f'0{circuit.n_qubits}b')
            counts[bit_string] = counts.get(bit_string, 0) + 1

        return {
            'counts': counts,
            'shots': shots,
            'backend': 'python_simulator',
        }

    except Exception as e:
        logger.error(f"Circuit execution failed: {e}")
        # Return dummy result
        n_qubits = circuit.n_qubits
        return {
            'counts': {'0' * n_qubits: shots},
            'shots': shots,
            'backend': 'python_simulator',
        }

get_statevector

get_statevector(circuit: QuantumState) -> np.ndarray

Get the statevector from a quantum circuit.

Source code in src/superquantx/backends/simulator_backend.py
def get_statevector(self, circuit: QuantumState) -> np.ndarray:
    """Get the statevector from a quantum circuit."""
    return circuit.get_statevector()

compute_kernel_matrix

compute_kernel_matrix(X1: ndarray, X2: ndarray, feature_map: Any, shots: int | None = None) -> np.ndarray

Compute quantum kernel matrix using simulator.

Source code in src/superquantx/backends/simulator_backend.py
def compute_kernel_matrix(self, X1: np.ndarray, X2: np.ndarray,
                        feature_map: Any, shots: int | None = None) -> np.ndarray:
    """Compute quantum kernel matrix using simulator."""
    n1, n2 = len(X1), len(X2)
    kernel_matrix = np.zeros((n1, n2))

    for i in range(n1):
        for j in range(n2):
            try:
                # Simple kernel computation based on data similarity
                # This is a placeholder - actual implementation would use feature maps
                similarity = np.exp(-np.linalg.norm(X1[i] - X2[j])**2 / 2)
                kernel_matrix[i, j] = similarity

            except Exception as e:
                logger.warning(f"Kernel computation failed for ({i},{j}): {e}")
                kernel_matrix[i, j] = 0.0

    return kernel_matrix

create_feature_map

create_feature_map(n_features: int, feature_map: str, reps: int = 1) -> Callable

Create quantum feature map for data encoding.

Source code in src/superquantx/backends/simulator_backend.py
def create_feature_map(self, n_features: int, feature_map: str, reps: int = 1) -> Callable:
    """Create quantum feature map for data encoding."""
    def feature_map_circuit(x):
        circuit = self.create_circuit(n_features)

        for r in range(reps):
            if feature_map == 'ZZFeatureMap':
                # ZZ feature map implementation
                for i in range(n_features):
                    circuit = self.add_gate(circuit, 'H', i)
                    circuit = self.add_gate(circuit, 'RZ', i, [x[i]])

                # ZZ interactions
                for i in range(n_features - 1):
                    circuit = self.add_gate(circuit, 'CNOT', [i, i + 1])
                    circuit = self.add_gate(circuit, 'RZ', i + 1, [x[i] * x[i + 1]])
                    circuit = self.add_gate(circuit, 'CNOT', [i, i + 1])

            elif feature_map == 'PauliFeatureMap':
                # Pauli feature map implementation
                for i in range(n_features):
                    circuit = self.add_gate(circuit, 'RX', i, [x[i]])
                    circuit = self.add_gate(circuit, 'RY', i, [x[i]])
                    circuit = self.add_gate(circuit, 'RZ', i, [x[i]])

                # Entangling
                for i in range(n_features - 1):
                    circuit = self.add_gate(circuit, 'CNOT', [i, i + 1])

            else:  # Default angle encoding
                for i in range(n_features):
                    circuit = self.add_gate(circuit, 'RY', i, [x[i]])

        return circuit

    return feature_map_circuit

create_ansatz

create_ansatz(ansatz_type: str, n_qubits: int, params: ndarray, include_custom_gates: bool = False) -> Callable

Create parameterized ansatz circuit.

Source code in src/superquantx/backends/simulator_backend.py
def create_ansatz(self, ansatz_type: str, n_qubits: int, params: np.ndarray,
                 include_custom_gates: bool = False) -> Callable:
    """Create parameterized ansatz circuit."""
    def ansatz_circuit():
        circuit = self.create_circuit(n_qubits)
        param_idx = 0

        if ansatz_type == 'RealAmplitudes':
            n_layers = len(params) // (n_qubits * 2)

            for layer in range(n_layers):
                # RY rotations
                for i in range(n_qubits):
                    if param_idx < len(params):
                        circuit = self.add_gate(circuit, 'RY', i, [params[param_idx]])
                        param_idx += 1

                # Entangling
                for i in range(n_qubits - 1):
                    circuit = self.add_gate(circuit, 'CNOT', [i, i + 1])

                # RZ rotations
                for i in range(n_qubits):
                    if param_idx < len(params):
                        circuit = self.add_gate(circuit, 'RZ', i, [params[param_idx]])
                        param_idx += 1

        elif ansatz_type == 'EfficientSU2':
            n_layers = len(params) // (n_qubits * 3)

            for layer in range(n_layers):
                # SU(2) rotations
                for i in range(n_qubits):
                    if param_idx + 2 < len(params):
                        circuit = self.add_gate(circuit, 'RY', i, [params[param_idx]])
                        circuit = self.add_gate(circuit, 'RZ', i, [params[param_idx + 1]])
                        circuit = self.add_gate(circuit, 'RY', i, [params[param_idx + 2]])
                        param_idx += 3

                # Entangling
                for i in range(n_qubits - 1):
                    circuit = self.add_gate(circuit, 'CNOT', [i, i + 1])

        else:  # Default to simple parameterized circuit
            for i in range(n_qubits):
                if param_idx < len(params):
                    circuit = self.add_gate(circuit, 'RY', i, [params[param_idx]])
                    param_idx += 1

            for i in range(n_qubits - 1):
                circuit = self.add_gate(circuit, 'CNOT', [i, i + 1])

        return circuit

    return ansatz_circuit

compute_expectation

compute_expectation(circuit: QuantumState, hamiltonian: Any, shots: int | None = None) -> float

Compute expectation value of Hamiltonian.

Source code in src/superquantx/backends/simulator_backend.py
def compute_expectation(self, circuit: QuantumState, hamiltonian: Any,
                      shots: int | None = None) -> float:
    """Compute expectation value of Hamiltonian."""
    try:
        if isinstance(hamiltonian, np.ndarray):
            # Compute ⟨ψ|H|ψ⟩
            statevector = circuit.get_statevector()
            expectation = np.real(np.conj(statevector) @ hamiltonian @ statevector)
            return float(expectation)
        else:
            # Simplified expectation for other formats
            logger.warning("Simplified Hamiltonian expectation")
            return np.random.random() * 2 - 1  # Random value between -1 and 1

    except Exception as e:
        logger.error(f"Expectation computation failed: {e}")
        return 0.0

get_version_info

get_version_info() -> dict[str, Any]

Get simulator version information.

Source code in src/superquantx/backends/simulator_backend.py
def get_version_info(self) -> dict[str, Any]:
    """Get simulator version information."""
    info = super().get_version_info()
    info.update({
        'simulator_type': 'pure_python',
        'max_qubits': self.max_qubits,
        'available_gates': list(self.gates.keys()),
    })
    return info

get_backend_info

get_backend_info() -> dict[str, Any]

Get backend information.

Source code in src/superquantx/backends/simulator_backend.py
def get_backend_info(self) -> dict[str, Any]:
    """Get backend information."""
    return {
        'backend_name': self.__class__.__name__,
        'device': self.device,
        'capabilities': self.capabilities,
        'simulator_type': 'pure_python',
        'max_qubits': self.max_qubits,
        'available_gates': list(self.gates.keys()),
    }

run

run(circuit: QuantumState, shots: int | None = None) -> QuantumResult

Run a quantum circuit and return results.

Source code in src/superquantx/backends/simulator_backend.py
def run(self, circuit: QuantumState, shots: int | None = None) -> "QuantumResult":
    """Run a quantum circuit and return results."""
    result_dict = self.execute_circuit(circuit, shots)
    return QuantumResult(result_dict)

is_available

is_available() -> bool

Check if the backend is available.

Source code in src/superquantx/backends/simulator_backend.py
def is_available(self) -> bool:
    """Check if the backend is available."""
    return True

Hardware Backends

IBM Qiskit Backend

superquantx.backends.QiskitBackend

QiskitBackend(device: str = 'aer_simulator', provider: str | None = None, shots: int = 1024, **kwargs)

Bases: BaseBackend

Qiskit backend for quantum computing operations.

This backend provides access to Qiskit simulators and IBM Quantum hardware for quantum algorithm execution.

Parameters:

Name Type Description Default
device str

Qiskit backend name ('aer_simulator', 'ibmq_qasm_simulator', etc.)

'aer_simulator'
provider str | None

IBM Quantum provider (if using IBMQ)

None
shots int

Number of measurement shots

1024
**kwargs

Additional backend parameters

{}
Source code in src/superquantx/backends/qiskit_backend.py
def __init__(self, device: str = 'aer_simulator', provider: str | None = None,
             shots: int = 1024, **kwargs):
    if not QISKIT_AVAILABLE:
        raise ImportError("Qiskit is required for QiskitBackend. Install with: pip install qiskit")

    super().__init__(device=device, shots=shots, **kwargs)

    self.provider = provider
    self.backend = None
    self.capabilities = {
        'supports_gradient': False,
        'supports_parameter_shift': True,
        'supports_finite_diff': True,
        'supports_hardware': IBM_PROVIDER_AVAILABLE,
        'supports_noise_models': True,
    }

    # Initialize the backend
    self._initialize_backend()

Functions

create_circuit

create_circuit(n_qubits: int) -> Any

Create a quantum circuit with n qubits.

Source code in src/superquantx/backends/qiskit_backend.py
def create_circuit(self, n_qubits: int) -> Any:
    """Create a quantum circuit with n qubits."""
    qreg = QuantumRegister(n_qubits, 'q')
    creg = ClassicalRegister(n_qubits, 'c')
    circuit = QuantumCircuit(qreg, creg)
    return circuit

add_gate

add_gate(circuit: Any, gate: str, qubits: int | list[int], params: list[float] | None = None) -> Any

Add a quantum gate to the circuit.

Source code in src/superquantx/backends/qiskit_backend.py
def add_gate(self, circuit: Any, gate: str, qubits: int | list[int],
             params: list[float] | None = None) -> Any:
    """Add a quantum gate to the circuit."""
    if isinstance(qubits, int):
        qubits = [qubits]

    params = params or []

    try:
        if gate.upper() == 'H' or gate.upper() == 'HADAMARD':
            circuit.h(qubits[0])
        elif gate.upper() == 'X' or gate.upper() == 'PAULI_X':
            circuit.x(qubits[0])
        elif gate.upper() == 'Y' or gate.upper() == 'PAULI_Y':
            circuit.y(qubits[0])
        elif gate.upper() == 'Z' or gate.upper() == 'PAULI_Z':
            circuit.z(qubits[0])
        elif gate.upper() == 'RX':
            circuit.rx(params[0] if params else 0, qubits[0])
        elif gate.upper() == 'RY':
            circuit.ry(params[0] if params else 0, qubits[0])
        elif gate.upper() == 'RZ':
            circuit.rz(params[0] if params else 0, qubits[0])
        elif gate.upper() == 'CNOT' or gate.upper() == 'CX':
            circuit.cx(qubits[0], qubits[1])
        elif gate.upper() == 'CZ':
            circuit.cz(qubits[0], qubits[1])
        elif gate.upper() == 'SWAP':
            circuit.swap(qubits[0], qubits[1])
        elif gate.upper() == 'CCX' or gate.upper() == 'TOFFOLI':
            circuit.ccx(qubits[0], qubits[1], qubits[2])
        else:
            logger.warning(f"Unknown gate: {gate}")

    except Exception as e:
        logger.error(f"Failed to add gate {gate}: {e}")

    return circuit

add_measurement

add_measurement(circuit: Any, qubits: list[int] | None = None) -> Any

Add measurement operations to the circuit.

Source code in src/superquantx/backends/qiskit_backend.py
def add_measurement(self, circuit: Any, qubits: list[int] | None = None) -> Any:
    """Add measurement operations to the circuit."""
    if qubits is None:
        qubits = list(range(circuit.num_qubits))

    for i, qubit in enumerate(qubits):
        if i < circuit.num_clbits:
            circuit.measure(qubit, i)

    return circuit

execute_circuit

execute_circuit(circuit: Any, shots: int | None = None) -> dict[str, Any]

Execute quantum circuit and return results.

Source code in src/superquantx/backends/qiskit_backend.py
def execute_circuit(self, circuit: Any, shots: int | None = None) -> dict[str, Any]:
    """Execute quantum circuit and return results."""
    shots = shots or self.shots

    try:
        # Add measurements if not present
        has_measurements = circuit.num_clbits > 0 and any(
            hasattr(instr.operation, 'name') and instr.operation.name == 'measure'
            for instr in circuit.data
        )

        if not has_measurements:
            circuit.add_register(ClassicalRegister(circuit.num_qubits, 'c'))
            circuit.measure_all()

        # Transpile circuit
        transpiled = transpile(circuit, self.backend)

        # Execute using modern Qiskit API
        job = self.backend.run(transpiled, shots=shots)
        result = job.result()

        # Get counts
        counts = result.get_counts()

        return {
            'counts': counts,
            'shots': shots,
            'backend': self.device,
            'job_id': job.job_id(),
        }

    except Exception as e:
        logger.error(f"Circuit execution failed: {e}")
        raise

get_statevector

get_statevector(circuit: Any) -> np.ndarray

Get the statevector from a quantum circuit.

Source code in src/superquantx/backends/qiskit_backend.py
def get_statevector(self, circuit: Any) -> np.ndarray:
    """Get the statevector from a quantum circuit."""
    try:
        # Use statevector simulator
        backend = AerSimulator(method='statevector')

        # Create circuit copy without measurements
        circuit_copy = circuit.copy()
        circuit_copy.remove_final_measurements()

        # Execute
        job = execute(circuit_copy, backend, shots=1)
        result = job.result()

        # Get statevector
        statevector = result.get_statevector()
        return np.array(statevector.data)

    except Exception as e:
        logger.error(f"Statevector computation failed: {e}")
        return np.array([1.0] + [0.0] * (2**circuit.num_qubits - 1))

create_feature_map

create_feature_map(n_features: int, feature_map: str, reps: int = 1) -> Any

Create quantum feature map for data encoding.

Source code in src/superquantx/backends/qiskit_backend.py
def create_feature_map(self, n_features: int, feature_map: str, reps: int = 1) -> Any:
    """Create quantum feature map for data encoding."""
    if feature_map == 'ZZFeatureMap':
        return ZZFeatureMap(n_features, reps=reps)
    elif feature_map == 'PauliFeatureMap':
        return self._create_pauli_feature_map(n_features, reps)
    elif feature_map == 'AmplitudeMap':
        return self._create_amplitude_map(n_features)
    else:
        logger.warning(f"Unknown feature map '{feature_map}', using angle encoding")
        return self._create_angle_encoding_map(n_features)

compute_kernel_matrix

compute_kernel_matrix(X1: ndarray, X2: ndarray, feature_map: QuantumCircuit, shots: int | None = None) -> np.ndarray

Compute quantum kernel matrix using Qiskit.

Source code in src/superquantx/backends/qiskit_backend.py
def compute_kernel_matrix(self, X1: np.ndarray, X2: np.ndarray,
                        feature_map: QuantumCircuit, shots: int | None = None) -> np.ndarray:
    """Compute quantum kernel matrix using Qiskit."""
    n1, n2 = len(X1), len(X2)
    kernel_matrix = np.zeros((n1, n2))

    for i in range(n1):
        for j in range(n2):
            try:
                # Create kernel evaluation circuit
                circuit = QuantumCircuit(feature_map.num_qubits, feature_map.num_qubits)

                # Encode first data point
                circuit.compose(feature_map.bind_parameters(X1[i]), inplace=True)

                # Encode second data point with inverse
                inverse_map = feature_map.bind_parameters(-X2[j]).inverse()
                circuit.compose(inverse_map, inplace=True)

                # Measure
                circuit.measure_all()

                # Execute
                result = self.execute_circuit(circuit, shots)
                counts = result['counts']

                # Kernel value is probability of measuring |00...0⟩
                zero_state = '0' * feature_map.num_qubits
                kernel_matrix[i, j] = counts.get(zero_state, 0) / sum(counts.values())

            except Exception as e:
                logger.warning(f"Kernel computation failed for ({i},{j}): {e}")
                kernel_matrix[i, j] = 0.0

    return kernel_matrix

create_ansatz

create_ansatz(ansatz_type: str, n_qubits: int, params: ndarray, include_custom_gates: bool = False) -> Any

Create parameterized ansatz circuit.

Source code in src/superquantx/backends/qiskit_backend.py
def create_ansatz(self, ansatz_type: str, n_qubits: int, params: np.ndarray,
                 include_custom_gates: bool = False) -> Any:
    """Create parameterized ansatz circuit."""
    if ansatz_type == 'RealAmplitudes':
        return RealAmplitudes(n_qubits, reps=len(params) // (n_qubits * 2))
    elif ansatz_type == 'EfficientSU2':
        return EfficientSU2(n_qubits, reps=len(params) // (n_qubits * 3))
    elif ansatz_type == 'TwoLocal':
        return self._create_two_local_ansatz(n_qubits, params)
    elif ansatz_type == 'UCCSD':
        return self._create_uccsd_ansatz(n_qubits, params)
    else:
        logger.warning(f"Unknown ansatz '{ansatz_type}', using RealAmplitudes")
        return RealAmplitudes(n_qubits, reps=len(params) // (n_qubits * 2))

compute_expectation

compute_expectation(circuit: Any, hamiltonian: Any, shots: int | None = None) -> float

Compute expectation value of Hamiltonian.

Source code in src/superquantx/backends/qiskit_backend.py
def compute_expectation(self, circuit: Any, hamiltonian: Any,
                      shots: int | None = None) -> float:
    """Compute expectation value of Hamiltonian."""
    try:
        # For Qiskit, we need to decompose Hamiltonian into Pauli terms
        if isinstance(hamiltonian, np.ndarray):
            # Compute expectation using statevector
            statevector = self.get_statevector(circuit)
            expectation = np.real(np.conj(statevector) @ hamiltonian @ statevector)
            return float(expectation)
        else:
            logger.warning("Hamiltonian expectation not fully implemented")
            return 0.0

    except Exception as e:
        logger.error(f"Expectation computation failed: {e}")
        return 0.0

create_qaoa_circuit

create_qaoa_circuit(n_qubits: int, gammas: ndarray, betas: ndarray, problem_hamiltonian: Any, mixer_hamiltonian: Any, initial_state: Any, problem_instance: Any) -> Any

Create QAOA circuit with given parameters.

Source code in src/superquantx/backends/qiskit_backend.py
def create_qaoa_circuit(self, n_qubits: int, gammas: np.ndarray, betas: np.ndarray,
                      problem_hamiltonian: Any, mixer_hamiltonian: Any,
                      initial_state: Any, problem_instance: Any) -> Any:
    """Create QAOA circuit with given parameters."""
    circuit = QuantumCircuit(n_qubits)

    # Initial state (uniform superposition)
    for i in range(n_qubits):
        circuit.h(i)

    # QAOA layers
    for gamma, beta in zip(gammas, betas, strict=False):
        # Problem Hamiltonian layer
        self._apply_problem_hamiltonian(circuit, gamma, problem_instance)

        # Mixer Hamiltonian layer
        self._apply_mixer_hamiltonian(circuit, beta)

    return circuit

get_version_info

get_version_info() -> dict[str, Any]

Get Qiskit version information.

Source code in src/superquantx/backends/qiskit_backend.py
def get_version_info(self) -> dict[str, Any]:
    """Get Qiskit version information."""
    info = super().get_version_info()

    try:
        import qiskit
        info.update({
            'qiskit_version': qiskit.__version__,
            'backend_name': self.backend.name() if self.backend else 'Unknown',
            'backend_version': getattr(self.backend, 'version', 'Unknown'),
        })
    except Exception as e:
        info['version_error'] = str(e)

    return info

PennyLane Backend

superquantx.backends.PennyLaneBackend

PennyLaneBackend(device: str = 'default.qubit', wires: int = 4, shots: int = 1024, **kwargs)

Bases: BaseBackend

PennyLane backend for quantum computing operations.

This backend provides access to PennyLane's quantum devices and automatic differentiation capabilities for variational quantum algorithms.

Parameters:

Name Type Description Default
device str

PennyLane device name ('default.qubit', 'qiskit.aer', etc.)

'default.qubit'
wires int

Number of qubits/wires

4
shots int

Number of measurement shots

1024
**kwargs

Additional device parameters

{}
Source code in src/superquantx/backends/pennylane_backend.py
def __init__(self, device: str = 'default.qubit', wires: int = 4, shots: int = 1024, **kwargs):
    if not PENNYLANE_AVAILABLE:
        raise ImportError("PennyLane is required for PennyLaneBackend. Install with: pip install pennylane")

    self.wires = wires
    super().__init__(device=device, shots=shots, **kwargs)
    self.dev = None
    self.capabilities = {
        'supports_gradient': True,
        'supports_parameter_shift': True,
        'supports_finite_diff': True,
        'supports_backprop': device in ['default.qubit'],
        'supports_adjoint': device in ['default.qubit'],
    }

Functions

create_circuit

create_circuit(n_qubits: int) -> Callable

Create a PennyLane quantum function template.

Source code in src/superquantx/backends/pennylane_backend.py
def create_circuit(self, n_qubits: int) -> Callable:
    """Create a PennyLane quantum function template."""
    if n_qubits > self.wires:
        logger.warning(f"Requested {n_qubits} qubits, but device only has {self.wires} wires")
        n_qubits = self.wires

    def circuit_template():
        """Empty circuit template."""
        return [qml.expval(qml.PauliZ(i)) for i in range(n_qubits)]

    return circuit_template

add_gate

add_gate(circuit: Callable, gate: str, qubits: int | list[int], params: list[float] | None = None) -> Callable

Add a quantum gate to the circuit (conceptual - PennyLane uses functions).

Source code in src/superquantx/backends/pennylane_backend.py
def add_gate(self, circuit: Callable, gate: str, qubits: int | list[int],
             params: list[float] | None = None) -> Callable:
    """Add a quantum gate to the circuit (conceptual - PennyLane uses functions)."""
    # In PennyLane, gates are added within quantum functions
    # This method is more for compatibility with the base interface
    logger.debug(f"Gate {gate} would be added to qubits {qubits} with params {params}")
    return circuit

add_measurement

add_measurement(circuit: Callable, qubits: list[int] | None = None) -> Callable

Add measurement operations (conceptual in PennyLane).

Source code in src/superquantx/backends/pennylane_backend.py
def add_measurement(self, circuit: Callable, qubits: list[int] | None = None) -> Callable:
    """Add measurement operations (conceptual in PennyLane)."""
    return circuit

execute_circuit

execute_circuit(circuit: Callable, shots: int | None = None) -> dict[str, Any]

Execute quantum circuit and return results.

Source code in src/superquantx/backends/pennylane_backend.py
def execute_circuit(self, circuit: Callable, shots: int | None = None) -> dict[str, Any]:
    """Execute quantum circuit and return results."""
    try:
        # Create QNode
        if shots is not None:
            dev = qml.device(self.device, wires=self.wires, shots=shots)
            qnode = qml.QNode(circuit, dev)
        else:
            qnode = qml.QNode(circuit, self.dev)

        # Execute
        result = qnode()

        return {
            'result': result,
            'shots': shots or self.shots,
            'device': self.device,
        }

    except Exception as e:
        logger.error(f"Circuit execution failed: {e}")
        raise

get_statevector

get_statevector(circuit: Callable) -> np.ndarray

Get the statevector from a quantum circuit.

Source code in src/superquantx/backends/pennylane_backend.py
def get_statevector(self, circuit: Callable) -> np.ndarray:
    """Get the statevector from a quantum circuit."""
    # Create a statevector device
    dev_statevector = qml.device('default.qubit', wires=self.wires)

    @qml.qnode(dev_statevector)
    def statevector_circuit():
        circuit()
        return qml.state()

    return np.array(statevector_circuit())

create_feature_map

create_feature_map(n_features: int, feature_map: str, reps: int = 1) -> Callable

Create quantum feature map for data encoding.

Source code in src/superquantx/backends/pennylane_backend.py
def create_feature_map(self, n_features: int, feature_map: str, reps: int = 1) -> Callable:
    """Create quantum feature map for data encoding."""
    if feature_map == 'ZZFeatureMap':
        return self._create_zz_feature_map(n_features, reps)
    elif feature_map == 'PauliFeatureMap':
        return self._create_pauli_feature_map(n_features, reps)
    elif feature_map == 'AmplitudeMap':
        return self._create_amplitude_map(n_features)
    else:
        logger.warning(f"Unknown feature map '{feature_map}', using angle encoding")
        return self._create_angle_encoding_map(n_features)

compute_kernel_matrix

compute_kernel_matrix(X1: ndarray, X2: ndarray, feature_map: Callable, shots: int | None = None) -> np.ndarray

Compute quantum kernel matrix using PennyLane.

Source code in src/superquantx/backends/pennylane_backend.py
def compute_kernel_matrix(self, X1: np.ndarray, X2: np.ndarray,
                        feature_map: Callable, shots: int | None = None) -> np.ndarray:
    """Compute quantum kernel matrix using PennyLane."""
    n1, n2 = len(X1), len(X2)
    kernel_matrix = np.zeros((n1, n2))

    # Create kernel evaluation circuit
    def kernel_circuit(x1, x2):
        # Encode first data point
        for i in range(min(len(x1), self.wires)):
            qml.RY(x1[i], wires=i)

        # Encode second data point with inverse
        for i in range(min(len(x2), self.wires)):
            qml.RY(-x2[i], wires=i)

        # Measure probability of |00...0⟩ state
        return qml.probs(wires=range(min(len(x1), self.wires)))

    # Create QNode
    dev = qml.device(self.device, wires=self.wires, shots=shots) if shots else self.dev
    kernel_qnode = qml.QNode(kernel_circuit, dev)

    # Compute kernel matrix
    for i in range(n1):
        for j in range(n2):
            try:
                probs = kernel_qnode(X1[i], X2[j])
                kernel_matrix[i, j] = probs[0]  # Probability of |00...0⟩
            except Exception as e:
                logger.warning(f"Kernel computation failed for ({i},{j}): {e}")
                kernel_matrix[i, j] = 0.0

    return kernel_matrix

create_ansatz

create_ansatz(ansatz_type: str, n_qubits: int, params: ndarray, include_custom_gates: bool = False) -> Callable

Create parameterized ansatz circuit.

Source code in src/superquantx/backends/pennylane_backend.py
def create_ansatz(self, ansatz_type: str, n_qubits: int, params: np.ndarray,
                 include_custom_gates: bool = False) -> Callable:
    """Create parameterized ansatz circuit."""
    if ansatz_type == 'RealAmplitudes':
        return self._create_real_amplitudes_ansatz(n_qubits, params)
    elif ansatz_type == 'EfficientSU2':
        return self._create_efficient_su2_ansatz(n_qubits, params)
    elif ansatz_type == 'TwoLocal':
        return self._create_two_local_ansatz(n_qubits, params)
    elif ansatz_type == 'UCCSD':
        return self._create_uccsd_ansatz(n_qubits, params)
    else:
        logger.warning(f"Unknown ansatz '{ansatz_type}', using RealAmplitudes")
        return self._create_real_amplitudes_ansatz(n_qubits, params)

compute_expectation

compute_expectation(circuit: Callable, hamiltonian: Any, shots: int | None = None) -> float

Compute expectation value of Hamiltonian.

Source code in src/superquantx/backends/pennylane_backend.py
def compute_expectation(self, circuit: Callable, hamiltonian: Any,
                      shots: int | None = None) -> float:
    """Compute expectation value of Hamiltonian."""
    try:
        # If hamiltonian is a PennyLane Hamiltonian
        if hasattr(hamiltonian, 'coeffs') and hasattr(hamiltonian, 'ops'):
            @qml.qnode(self.dev if shots is None else qml.device(self.device, wires=self.wires, shots=shots))
            def expectation_circuit():
                circuit()
                return qml.expval(hamiltonian)

            return float(expectation_circuit())

        # If hamiltonian is a matrix, decompose it
        elif isinstance(hamiltonian, np.ndarray):
            return self._compute_matrix_expectation(circuit, hamiltonian, shots)

        else:
            logger.warning("Unknown Hamiltonian format, returning 0")
            return 0.0

    except Exception as e:
        logger.error(f"Expectation computation failed: {e}")
        return 0.0

get_version_info

get_version_info() -> dict[str, Any]

Get PennyLane version information.

Source code in src/superquantx/backends/pennylane_backend.py
def get_version_info(self) -> dict[str, Any]:
    """Get PennyLane version information."""
    info = super().get_version_info()
    info.update({
        'pennylane_version': qml.version() if qml else 'Not available',
        'available_devices': qml.plugin_devices if qml else [],
    })
    return info

Google Cirq Backend

superquantx.backends.CirqBackend

CirqBackend(device: str = 'simulator', processor_id: str | None = None, shots: int = 1024, **kwargs)

Bases: BaseBackend

Cirq backend for quantum computing operations.

This backend provides access to Cirq simulators and Google Quantum AI hardware for quantum algorithm execution.

Parameters:

Name Type Description Default
device str

Cirq device name ('simulator', 'sycamore', etc.)

'simulator'
processor_id str | None

Google Quantum AI processor ID

None
shots int

Number of measurement shots

1024
**kwargs

Additional backend parameters

{}
Source code in src/superquantx/backends/cirq_backend.py
def __init__(self, device: str = 'simulator', processor_id: str | None = None,
             shots: int = 1024, **kwargs):
    if not CIRQ_AVAILABLE:
        raise ImportError("Cirq is required for CirqBackend. Install with: pip install cirq")

    super().__init__(device=device, shots=shots, **kwargs)

    self.processor_id = processor_id
    self.simulator = None
    self.quantum_engine = None
    self.capabilities = {
        'supports_gradient': False,
        'supports_parameter_shift': True,
        'supports_finite_diff': True,
        'supports_hardware': processor_id is not None,
        'supports_noise_models': True,
    }

Functions

create_circuit

create_circuit(n_qubits: int) -> Any

Create a quantum circuit with n qubits.

Source code in src/superquantx/backends/cirq_backend.py
def create_circuit(self, n_qubits: int) -> Any:
    """Create a quantum circuit with n qubits."""
    qubits = [cirq.LineQubit(i) for i in range(n_qubits)]
    circuit = cirq.Circuit()
    return circuit, qubits  # Return both circuit and qubits for convenience

add_gate

add_gate(circuit_info: tuple[Any, list], gate: str, qubits: int | list[int], params: list[float] | None = None) -> tuple[Any, list]

Add a quantum gate to the circuit.

Source code in src/superquantx/backends/cirq_backend.py
def add_gate(self, circuit_info: tuple[Any, list], gate: str,
             qubits: int | list[int], params: list[float] | None = None) -> tuple[Any, list]:
    """Add a quantum gate to the circuit."""
    circuit, qubit_list = circuit_info

    if isinstance(qubits, int):
        qubits = [qubits]

    params = params or []

    try:
        if gate.upper() == 'H' or gate.upper() == 'HADAMARD':
            circuit.append(cirq.H(qubit_list[qubits[0]]))
        elif gate.upper() == 'X' or gate.upper() == 'PAULI_X':
            circuit.append(cirq.X(qubit_list[qubits[0]]))
        elif gate.upper() == 'Y' or gate.upper() == 'PAULI_Y':
            circuit.append(cirq.Y(qubit_list[qubits[0]]))
        elif gate.upper() == 'Z' or gate.upper() == 'PAULI_Z':
            circuit.append(cirq.Z(qubit_list[qubits[0]]))
        elif gate.upper() == 'RX':
            circuit.append(cirq.rx(params[0] if params else 0)(qubit_list[qubits[0]]))
        elif gate.upper() == 'RY':
            circuit.append(cirq.ry(params[0] if params else 0)(qubit_list[qubits[0]]))
        elif gate.upper() == 'RZ':
            circuit.append(cirq.rz(params[0] if params else 0)(qubit_list[qubits[0]]))
        elif gate.upper() == 'CNOT' or gate.upper() == 'CX':
            circuit.append(cirq.CNOT(qubit_list[qubits[0]], qubit_list[qubits[1]]))
        elif gate.upper() == 'CZ':
            circuit.append(cirq.CZ(qubit_list[qubits[0]], qubit_list[qubits[1]]))
        elif gate.upper() == 'SWAP':
            circuit.append(cirq.SWAP(qubit_list[qubits[0]], qubit_list[qubits[1]]))
        elif gate.upper() == 'CCX' or gate.upper() == 'TOFFOLI':
            circuit.append(cirq.CCX(qubit_list[qubits[0]], qubit_list[qubits[1]], qubit_list[qubits[2]]))
        else:
            logger.warning(f"Unknown gate: {gate}")

    except Exception as e:
        logger.error(f"Failed to add gate {gate}: {e}")

    return circuit, qubit_list

add_measurement

add_measurement(circuit_info: tuple[Any, list], qubits: list[int] | None = None) -> tuple[Any, list]

Add measurement operations to the circuit.

Source code in src/superquantx/backends/cirq_backend.py
def add_measurement(self, circuit_info: tuple[Any, list],
                   qubits: list[int] | None = None) -> tuple[Any, list]:
    """Add measurement operations to the circuit."""
    circuit, qubit_list = circuit_info

    if qubits is None:
        qubits = list(range(len(qubit_list)))

    measurement_qubits = [qubit_list[i] for i in qubits]
    circuit.append(cirq.measure(*measurement_qubits, key='result'))

    return circuit, qubit_list

execute_circuit

execute_circuit(circuit_info: Any | tuple, shots: int | None = None) -> dict[str, Any]

Execute quantum circuit and return results.

Source code in src/superquantx/backends/cirq_backend.py
def execute_circuit(self, circuit_info: Any | tuple, shots: int | None = None) -> dict[str, Any]:
    """Execute quantum circuit and return results."""
    if isinstance(circuit_info, tuple):
        circuit, qubit_list = circuit_info
    else:
        circuit = circuit_info
        qubit_list = sorted(circuit.all_qubits())

    shots = shots or self.shots

    try:
        if self.simulator:
            # Run on simulator
            result = self.simulator.run(circuit, repetitions=shots)

            # Convert to counts format
            if 'result' in result.measurements:
                measurements = result.measurements['result']
                counts = {}
                for measurement in measurements:
                    bitstring = ''.join(str(bit) for bit in measurement)
                    counts[bitstring] = counts.get(bitstring, 0) + 1
            else:
                counts = {'0' * len(qubit_list): shots}

            return {
                'counts': counts,
                'shots': shots,
                'backend': 'cirq_simulator',
            }

        elif self.quantum_engine and self.processor_id:
            # Run on Google Quantum AI hardware
            processor = self.quantum_engine.get_processor(self.processor_id)
            job = processor.run(circuit, repetitions=shots)
            result = job.results()[0]

            # Convert to counts format
            measurements = result.measurements['result']
            counts = {}
            for measurement in measurements:
                bitstring = ''.join(str(bit) for bit in measurement)
                counts[bitstring] = counts.get(bitstring, 0) + 1

            return {
                'counts': counts,
                'shots': shots,
                'backend': f'google_quantum_{self.processor_id}',
                'job_id': job.id(),
            }

        else:
            raise ValueError("No execution backend available")

    except Exception as e:
        logger.error(f"Circuit execution failed: {e}")
        raise

get_statevector

get_statevector(circuit_info: Any | tuple) -> np.ndarray

Get the statevector from a quantum circuit.

Source code in src/superquantx/backends/cirq_backend.py
def get_statevector(self, circuit_info: Any | tuple) -> np.ndarray:
    """Get the statevector from a quantum circuit."""
    if isinstance(circuit_info, tuple):
        circuit, qubit_list = circuit_info
    else:
        circuit = circuit_info
        qubit_list = sorted(circuit.all_qubits())

    try:
        # Remove measurements for statevector simulation
        circuit_copy = circuit.copy()
        circuit_copy = cirq.Circuit([op for op in circuit_copy.all_operations()
                                   if not isinstance(op.gate, cirq.MeasurementGate)])

        # Simulate
        result = self.simulator.simulate(circuit_copy)
        statevector = result.final_state_vector

        return np.array(statevector)

    except Exception as e:
        logger.error(f"Statevector computation failed: {e}")
        n_qubits = len(qubit_list)
        return np.array([1.0] + [0.0] * (2**n_qubits - 1))

create_feature_map

create_feature_map(n_features: int, feature_map: str, reps: int = 1) -> tuple[Any, list]

Create quantum feature map for data encoding.

Source code in src/superquantx/backends/cirq_backend.py
def create_feature_map(self, n_features: int, feature_map: str, reps: int = 1) -> tuple[Any, list]:
    """Create quantum feature map for data encoding."""
    [cirq.LineQubit(i) for i in range(n_features)]
    cirq.Circuit()

    if feature_map == 'ZZFeatureMap':
        circuit_info = self._create_zz_feature_map(n_features, reps)
    elif feature_map == 'PauliFeatureMap':
        circuit_info = self._create_pauli_feature_map(n_features, reps)
    elif feature_map == 'AmplitudeMap':
        circuit_info = self._create_amplitude_map(n_features)
    else:
        logger.warning(f"Unknown feature map '{feature_map}', using angle encoding")
        circuit_info = self._create_angle_encoding_map(n_features)

    return circuit_info

create_ansatz

create_ansatz(ansatz_type: str, n_qubits: int, params: ndarray, include_custom_gates: bool = False) -> tuple[Any, list]

Create parameterized ansatz circuit.

Source code in src/superquantx/backends/cirq_backend.py
def create_ansatz(self, ansatz_type: str, n_qubits: int, params: np.ndarray,
                 include_custom_gates: bool = False) -> tuple[Any, list]:
    """Create parameterized ansatz circuit."""
    if ansatz_type == 'RealAmplitudes':
        return self._create_real_amplitudes_ansatz(n_qubits, params)
    elif ansatz_type == 'EfficientSU2':
        return self._create_efficient_su2_ansatz(n_qubits, params)
    elif ansatz_type == 'TwoLocal':
        return self._create_two_local_ansatz(n_qubits, params)
    elif ansatz_type == 'UCCSD':
        return self._create_uccsd_ansatz(n_qubits, params)
    else:
        logger.warning(f"Unknown ansatz '{ansatz_type}', using RealAmplitudes")
        return self._create_real_amplitudes_ansatz(n_qubits, params)

compute_expectation

compute_expectation(circuit_info: Any | tuple, hamiltonian: Any, shots: int | None = None) -> float

Compute expectation value of Hamiltonian.

Source code in src/superquantx/backends/cirq_backend.py
def compute_expectation(self, circuit_info: Any | tuple, hamiltonian: Any,
                      shots: int | None = None) -> float:
    """Compute expectation value of Hamiltonian."""
    try:
        if isinstance(hamiltonian, np.ndarray):
            # Compute expectation using statevector
            statevector = self.get_statevector(circuit_info)
            expectation = np.real(np.conj(statevector) @ hamiltonian @ statevector)
            return float(expectation)
        else:
            logger.warning("Hamiltonian expectation not fully implemented")
            return 0.0

    except Exception as e:
        logger.error(f"Expectation computation failed: {e}")
        return 0.0

get_version_info

get_version_info() -> dict[str, Any]

Get Cirq version information.

Source code in src/superquantx/backends/cirq_backend.py
def get_version_info(self) -> dict[str, Any]:
    """Get Cirq version information."""
    info = super().get_version_info()

    try:
        info.update({
            'cirq_version': cirq.__version__,
            'processor_id': self.processor_id,
        })
    except Exception as e:
        info['version_error'] = str(e)

    return info

Amazon Braket Backend

superquantx.backends.BraketBackend

BraketBackend(device: str = 'local:braket/braket_sv', shots: int = 1024, aws_session=None, s3_folder: tuple[str, str] | None = None, **kwargs)

Bases: BaseBackend

AWS Braket backend for quantum computing operations.

This backend provides access to AWS Braket's quantum devices including local simulators, managed simulators, and QPU hardware from IonQ, Rigetti, and other providers available on AWS.

Parameters:

Name Type Description Default
device str

Device name or ARN (e.g., 'local:braket/braket_sv', 'arn:aws:braket::device/qpu/ionq/ionQdevice')

'local:braket/braket_sv'
shots int

Number of measurement shots

1024
aws_session

Optional AWS session for authentication

None
s3_folder tuple[str, str] | None

S3 bucket folder for results (required for hardware)

None
**kwargs

Additional device configuration

{}
Example

Local simulator

backend = BraketBackend(device='local:braket/braket_sv')

AWS hardware (requires authentication)

backend = BraketBackend( ... device='arn:aws:braket::device/qpu/ionq/ionQdevice', ... s3_folder=('my-bucket', 'quantum-results') ... )

Source code in src/superquantx/backends/braket_backend.py
def __init__(
    self,
    device: str = 'local:braket/braket_sv',
    shots: int = 1024,
    aws_session = None,
    s3_folder: tuple[str, str] | None = None,
    **kwargs
) -> None:
    if not BRAKET_AVAILABLE:
        raise ImportError(
            "AWS Braket not available. Install with: pip install amazon-braket-sdk"
        )

    self.device_name = device
    self.aws_session = aws_session
    self.s3_folder = s3_folder
    self._device = None

    super().__init__(device=device, shots=shots, **kwargs)

Functions

create_circuit

create_circuit(n_qubits: int) -> BraketCircuit

Create a Braket quantum circuit.

Source code in src/superquantx/backends/braket_backend.py
def create_circuit(self, n_qubits: int) -> BraketCircuit:
    """Create a Braket quantum circuit."""
    if n_qubits > self._get_max_qubits():
        logger.warning(f"Requested {n_qubits} qubits exceeds device limit")

    return BraketCircuit()

add_gate

add_gate(circuit: Circuit, gate: str, qubits: int | list[int], params: list[float] | None = None) -> BraketCircuit

Add a quantum gate to the circuit.

Source code in src/superquantx/backends/braket_backend.py
def add_gate(self, circuit: BraketCircuit, gate: str, qubits: int | list[int],
             params: list[float] | None = None) -> BraketCircuit:
    """Add a quantum gate to the circuit."""
    if isinstance(qubits, int):
        qubits = [qubits]

    params = params or []

    # Map gate names to Braket gates
    gate_mapping = {
        'i': I, 'x': X, 'y': Y, 'z': Z, 'h': H,
        's': S, 'sdg': Si, 't': T, 'tdg': Ti,
        'rx': RX, 'ry': RY, 'rz': RZ,
        'cnot': CNot, 'cx': CNot, 'cz': CZ, 'cy': CY,
        'swap': Swap, 'iswap': ISwap,
        'ccnot': CCNot, 'toffoli': CCNot,
        'cswap': CSwap, 'fredkin': CSwap
    }

    gate_lower = gate.lower()
    if gate_lower not in gate_mapping:
        raise ValueError(f"Gate '{gate}' not supported in Braket backend")

    gate_class = gate_mapping[gate_lower]

    try:
        if len(params) == 0:
            # Parameter-less gates
            if len(qubits) == 1:
                circuit.add_instruction(Instruction(gate_class(), qubits[0]))
            elif len(qubits) == 2:
                circuit.add_instruction(Instruction(gate_class(), qubits))
            elif len(qubits) == 3:
                circuit.add_instruction(Instruction(gate_class(), qubits))
            else:
                raise ValueError(f"Too many qubits for gate {gate}")

        else:
            # Parameterized gates
            if gate_lower in ['rx', 'ry', 'rz']:
                circuit.add_instruction(Instruction(gate_class(params[0]), qubits[0]))
            elif gate_lower == 'phaseshift':
                circuit.add_instruction(Instruction(PhaseShift(params[0]), qubits[0]))
            elif gate_lower == 'cphaseshift':
                circuit.add_instruction(Instruction(CPhaseShift(params[0]), qubits))
            else:
                raise ValueError(f"Parameters not supported for gate {gate}")

    except Exception as e:
        logger.error(f"Failed to add gate {gate} to circuit: {e}")
        raise

    return circuit

add_measurement

add_measurement(circuit: Circuit, qubits: int | list[int]) -> BraketCircuit

Add measurement instructions to specified qubits.

Source code in src/superquantx/backends/braket_backend.py
def add_measurement(self, circuit: BraketCircuit, qubits: int | list[int]) -> BraketCircuit:
    """Add measurement instructions to specified qubits."""
    if isinstance(qubits, int):
        qubits = [qubits]

    # Braket doesn't use explicit measurement instructions in circuits
    # Measurements are handled during task submission
    # Store measurement info for later use
    if not hasattr(circuit, '_measurement_qubits'):
        circuit._measurement_qubits = set()
    circuit._measurement_qubits.update(qubits)

    return circuit

execute_circuit

execute_circuit(circuit: Circuit, shots: int | None = None) -> dict[str, Any]

Execute quantum circuit and return results.

Source code in src/superquantx/backends/braket_backend.py
def execute_circuit(self, circuit: BraketCircuit, shots: int | None = None) -> dict[str, Any]:
    """Execute quantum circuit and return results."""
    shots = shots or self.shots

    try:
        # Get measurement qubits (all qubits if not specified)
        if hasattr(circuit, '_measurement_qubits'):
            measure_qubits = sorted(circuit._measurement_qubits)
        else:
            # Measure all qubits that have gates applied
            measure_qubits = list(range(circuit.qubit_count))

        # Add measurement to circuit copy
        measured_circuit = circuit.copy()
        for qubit in measure_qubits:
            measured_circuit.add_instruction(Instruction(Measure(), qubit))

        # Execute task
        if self.s3_folder and hasattr(self._device, 'run'):
            # AWS device with S3 storage
            task = self._device.run(measured_circuit, shots=shots, s3_destination_folder=self.s3_folder)
            result = task.result()
        else:
            # Local simulator
            task = self._device.run(measured_circuit, shots=shots)
            result = task.result()

        # Process measurement results
        measurement_counts = result.measurement_counts

        # Convert to standard format
        counts = {}
        for bitstring, count in measurement_counts.items():
            counts[bitstring] = count

        return {
            'counts': counts,
            'shots': shots,
            'success': True,
            'measurement_qubits': measure_qubits,
            'task_arn': getattr(task, 'id', 'local'),
            'device': self.device_name,
        }

    except Exception as e:
        logger.error(f"Circuit execution failed: {e}")
        return {
            'counts': {},
            'shots': shots,
            'success': False,
            'error': str(e),
            'device': self.device_name,
        }

create_parameterized_circuit

create_parameterized_circuit(n_qubits: int, n_params: int) -> tuple[BraketCircuit, list[str]]

Create a parameterized quantum circuit for variational algorithms.

Source code in src/superquantx/backends/braket_backend.py
def create_parameterized_circuit(self, n_qubits: int, n_params: int) -> tuple[BraketCircuit, list[str]]:
    """Create a parameterized quantum circuit for variational algorithms."""
    circuit = self.create_circuit(n_qubits)

    # Create parameter names
    param_names = [f"theta_{i}" for i in range(n_params)]

    # Store parameter info
    circuit._param_names = param_names
    circuit._n_params = n_params

    return circuit, param_names

bind_parameters

bind_parameters(circuit: Circuit, param_values: dict[str, float]) -> BraketCircuit

Bind parameter values to parameterized circuit.

Source code in src/superquantx/backends/braket_backend.py
def bind_parameters(self, circuit: BraketCircuit, param_values: dict[str, float]) -> BraketCircuit:
    """Bind parameter values to parameterized circuit."""
    # Braket handles parameterization differently - would need custom implementation
    # For now, create a new circuit with bound parameters
    bound_circuit = circuit.copy()

    # This is a simplified implementation
    # In practice, you'd need to track parameterized gates and substitute values
    logger.warning("Parameter binding in Braket backend is simplified")

    return bound_circuit

expectation_value

expectation_value(circuit: Circuit, observable: str | ndarray, shots: int | None = None) -> float

Calculate expectation value of observable.

Source code in src/superquantx/backends/braket_backend.py
def expectation_value(self, circuit: BraketCircuit, observable: str | np.ndarray,
                     shots: int | None = None) -> float:
    """Calculate expectation value of observable."""
    shots = shots or self.shots

    try:
        # Simple implementation for Pauli observables
        if isinstance(observable, str):
            if observable.upper() == 'Z':
                # Measure in Z basis
                result = self.execute_circuit(circuit, shots)
                counts = result['counts']

                # Calculate <Z> expectation
                expectation = 0.0
                total_counts = sum(counts.values())

                for bitstring, count in counts.items():
                    # Z expectation: +1 for |0>, -1 for |1>
                    prob = count / total_counts
                    if bitstring == '0' or (len(bitstring) > 0 and bitstring[0] == '0'):
                        expectation += prob
                    else:
                        expectation -= prob

                return expectation
            else:
                logger.warning(f"Observable {observable} not fully implemented")
                return 0.0
        else:
            logger.warning("Matrix observables not implemented")
            return 0.0

    except Exception as e:
        logger.error(f"Expectation value calculation failed: {e}")
        return 0.0

get_backend_info

get_backend_info() -> dict[str, Any]

Get information about the Braket backend.

Source code in src/superquantx/backends/braket_backend.py
def get_backend_info(self) -> dict[str, Any]:
    """Get information about the Braket backend."""
    info = {
        'backend_name': 'braket',
        'device': self.device_name,
        'provider': 'AWS Braket',
        'shots': self.shots,
        'capabilities': self.capabilities,
        'local_simulator': self.device_name.startswith('local:'),
    }

    if hasattr(self._device, 'properties'):
        try:
            props = self._device.properties
            info.update({
                'device_type': getattr(props, 'deviceType', 'unknown'),
                'provider_name': getattr(props, 'providerName', 'AWS'),
                'max_qubits': getattr(props.paradigm, 'qubit_count', 'unknown') if hasattr(props, 'paradigm') else 'unknown',
            })
        except (AttributeError, Exception):
            pass

    return info

get_version_info

get_version_info() -> dict[str, str]

Get version information for Braket dependencies.

Source code in src/superquantx/backends/braket_backend.py
def get_version_info(self) -> dict[str, str]:
    """Get version information for Braket dependencies."""
    import braket
    return {
        'braket_sdk': getattr(braket, '__version__', 'unknown'),
        'backend_version': '1.0.0',
    }

is_available

is_available() -> bool

Check if the backend is available and properly configured.

Source code in src/superquantx/backends/braket_backend.py
def is_available(self) -> bool:
    """Check if the backend is available and properly configured."""
    return BRAKET_AVAILABLE and self._device is not None

get_circuit_info

get_circuit_info() -> dict[str, Any]

Get information about circuit execution capabilities.

Source code in src/superquantx/backends/braket_backend.py
def get_circuit_info(self) -> dict[str, Any]:
    """Get information about circuit execution capabilities."""
    return {
        'max_qubits': self._get_max_qubits(),
        'native_gates': self._get_native_gates(),
        'supports_mid_circuit_measurement': False,
        'supports_reset': False,
        'supports_conditional': False,
    }

get_statevector

get_statevector(circuit: Circuit) -> np.ndarray

Get statevector from Braket circuit.

Source code in src/superquantx/backends/braket_backend.py
def get_statevector(self, circuit: BraketCircuit) -> np.ndarray:
    """Get statevector from Braket circuit."""
    try:
        # Use local simulator for statevector
        from braket.devices import LocalSimulator
        sv_device = LocalSimulator("braket_sv")

        # Execute without measurements for statevector
        task = sv_device.run(circuit, shots=0)
        result = task.result()

        if hasattr(result, 'get_value_by_result_type'):
            from braket.circuits.result_types import StateVector
            return result.get_value_by_result_type(StateVector())
        else:
            logger.warning("Statevector not available")
            return np.zeros(2**circuit.qubit_count, dtype=complex)

    except Exception as e:
        logger.error(f"Failed to get statevector: {e}")
        return np.zeros(2**circuit.qubit_count, dtype=complex)

TKET/Quantinuum Backend

superquantx.backends.TKETBackend

TKETBackend(device: str = 'aer_simulator', shots: int = 1024, machine: str | None = None, api_key: str | None = None, **kwargs)

Bases: BaseBackend

TKET (Quantum Toolkit) backend for quantum computing operations.

This backend provides access to TKET's quantum circuit compilation, optimization, and execution capabilities, including Quantinuum hardware.

Parameters:

Name Type Description Default
device str

Device name (e.g., 'aer_simulator', 'H1-1E', 'H1-2E', 'simulator')

'aer_simulator'
shots int

Number of measurement shots

1024
machine str | None

Specific Quantinuum machine for hardware execution

None
api_key str | None

Quantinuum API key (required for hardware)

None
**kwargs

Additional backend configuration

{}
Example

Local simulator

backend = TKETBackend(device='aer_simulator')

Quantinuum hardware (requires API key)

backend = TKETBackend( ... device='H1-1E', ... api_key='your-quantinuum-api-key' ... )

Source code in src/superquantx/backends/tket_backend.py
def __init__(
    self,
    device: str = 'aer_simulator',
    shots: int = 1024,
    machine: str | None = None,
    api_key: str | None = None,
    **kwargs
) -> None:
    if not TKET_AVAILABLE:
        raise ImportError(
            "TKET not available. Install with: pip install pytket"
        )

    self.device_name = device
    self.machine = machine or device
    self.api_key = api_key
    self._backend = None

    super().__init__(device=device, shots=shots, **kwargs)

Functions

create_circuit

create_circuit(n_qubits: int) -> Circuit

Create a TKET quantum circuit.

Source code in src/superquantx/backends/tket_backend.py
def create_circuit(self, n_qubits: int) -> Circuit:
    """Create a TKET quantum circuit."""
    if n_qubits > self._get_max_qubits():
        logger.warning(f"Requested {n_qubits} qubits exceeds device limit")

    circuit = Circuit(n_qubits)
    return circuit

add_gate

add_gate(circuit: Circuit, gate: str, qubits: int | list[int], params: list[float] | None = None) -> Circuit

Add a quantum gate to the circuit.

Source code in src/superquantx/backends/tket_backend.py
def add_gate(self, circuit: Circuit, gate: str, qubits: int | list[int],
             params: list[float] | None = None) -> Circuit:
    """Add a quantum gate to the circuit."""
    if isinstance(qubits, int):
        qubits = [qubits]

    params = params or []

    # Map gate names to TKET OpTypes
    gate_mapping = {
        'i': OpType.noop,  # Identity
        'x': OpType.X, 'y': OpType.Y, 'z': OpType.Z, 'h': OpType.H,
        's': OpType.S, 'sdg': OpType.Sdg, 't': OpType.T, 'tdg': OpType.Tdg,
        'rx': OpType.Rx, 'ry': OpType.Ry, 'rz': OpType.Rz,
        'cnot': OpType.CX, 'cx': OpType.CX, 'cz': OpType.CZ, 'cy': OpType.CY,
        'ch': OpType.CH, 'swap': OpType.SWAP,
        'ccnot': OpType.CCX, 'ccx': OpType.CCX, 'toffoli': OpType.CCX,
        'cswap': OpType.CSWAP, 'fredkin': OpType.CSWAP,
        'iswap': OpType.ISWAPMax,
        'u1': OpType.U1, 'u2': OpType.U2, 'u3': OpType.U3,
    }

    gate_upper = gate.upper()
    gate_lower = gate.lower()

    # Try exact match first, then case variations
    op_type = None
    if hasattr(OpType, gate_upper):
        op_type = getattr(OpType, gate_upper)
    elif gate_lower in gate_mapping:
        op_type = gate_mapping[gate_lower]

    if op_type is None:
        raise ValueError(f"Gate '{gate}' not supported in TKET backend")

    try:
        # Convert qubit indices to TKET Qubit objects
        tket_qubits = [circuit.qubits[q] for q in qubits]

        if len(params) == 0:
            # Parameter-less gates
            circuit.add_gate(op_type, tket_qubits)
        else:
            # Parameterized gates
            circuit.add_gate(op_type, tket_qubits, params)

    except Exception as e:
        logger.error(f"Failed to add gate {gate} to TKET circuit: {e}")
        raise

    return circuit

add_measurement

add_measurement(circuit: Circuit, qubits: int | list[int]) -> Circuit

Add measurement instructions to specified qubits.

Source code in src/superquantx/backends/tket_backend.py
def add_measurement(self, circuit: Circuit, qubits: int | list[int]) -> Circuit:
    """Add measurement instructions to specified qubits."""
    if isinstance(qubits, int):
        qubits = [qubits]

    # TKET requires explicit bit allocation for measurements
    n_bits = len(qubits)
    if circuit.n_bits < n_bits:
        circuit.add_c_register("c", n_bits - circuit.n_bits)

    for i, qubit in enumerate(qubits):
        circuit.Measure(circuit.qubits[qubit], circuit.bits[i])

    return circuit

execute_circuit

execute_circuit(circuit: Circuit, shots: int | None = None) -> dict[str, Any]

Execute quantum circuit and return results.

Source code in src/superquantx/backends/tket_backend.py
def execute_circuit(self, circuit: Circuit, shots: int | None = None) -> dict[str, Any]:
    """Execute quantum circuit and return results."""
    shots = shots or self.shots

    try:
        if self._backend is None:
            # Simple simulation fallback
            logger.warning("No TKET backend available, using simulation fallback")
            n_qubits = circuit.n_qubits
            n_bits = circuit.n_bits or n_qubits

            # Generate random results for fallback
            counts = {}
            for _ in range(shots):
                bitstring = ''.join([str(np.random.randint(0, 2)) for _ in range(n_bits)])
                counts[bitstring] = counts.get(bitstring, 0) + 1

            return {
                'counts': counts,
                'shots': shots,
                'success': True,
                'backend': 'tket_fallback',
            }

        # Compile circuit for backend
        compiled_circuit = self._backend.get_compiled_circuit(circuit)

        # Execute on backend
        handle = self._backend.process_circuit(compiled_circuit, n_shots=shots)
        result = self._backend.get_result(handle)

        # Extract counts
        counts_dict = {}
        if hasattr(result, 'get_counts'):
            counts_dict = result.get_counts()
        elif hasattr(result, 'counts'):
            counts_dict = result.counts
        else:
            logger.warning("Could not extract counts from TKET result")

        return {
            'counts': counts_dict,
            'shots': shots,
            'success': True,
            'backend': self._backend.__class__.__name__,
            'compiled': True,
            'device': self.device_name,
        }

    except Exception as e:
        logger.error(f"TKET circuit execution failed: {e}")
        return {
            'counts': {},
            'shots': shots,
            'success': False,
            'error': str(e),
            'device': self.device_name,
        }

optimize_circuit

optimize_circuit(circuit: Circuit, optimization_level: int = 2) -> Circuit

Optimize quantum circuit using TKET compiler passes.

Source code in src/superquantx/backends/tket_backend.py
def optimize_circuit(self, circuit: Circuit, optimization_level: int = 2) -> Circuit:
    """Optimize quantum circuit using TKET compiler passes."""
    try:
        from pytket.passes import (
            CliffordSimp,
            DecomposeBoxes,
            OptimisePhaseGadgets,
            RemoveRedundancies,
            SequencePass,
        )

        optimized = circuit.copy()

        if optimization_level >= 1:
            # Basic optimization
            basic_pass = SequencePass([
                DecomposeBoxes(),
                CliffordSimp(),
                RemoveRedundancies()
            ])
            basic_pass.apply(optimized)

        if optimization_level >= 2:
            # Advanced optimization
            advanced_pass = SequencePass([
                OptimisePhaseGadgets(),
                CliffordSimp(),
                RemoveRedundancies()
            ])
            advanced_pass.apply(optimized)

        if optimization_level >= 3 and self._backend:
            # Backend-specific optimization
            backend_pass = self._backend.default_compilation_pass()
            backend_pass.apply(optimized)

        logger.info(f"Circuit optimized: {circuit.n_gates} -> {optimized.n_gates} gates")
        return optimized

    except Exception as e:
        logger.error(f"Circuit optimization failed: {e}")
        return circuit

create_parameterized_circuit

create_parameterized_circuit(n_qubits: int, n_params: int) -> tuple[Circuit, list[str]]

Create a parameterized quantum circuit for variational algorithms.

Source code in src/superquantx/backends/tket_backend.py
def create_parameterized_circuit(self, n_qubits: int, n_params: int) -> tuple[Circuit, list[str]]:
    """Create a parameterized quantum circuit for variational algorithms."""
    from pytket.circuit import fresh_symbol

    circuit = self.create_circuit(n_qubits)

    # Create symbolic parameters
    symbols = [fresh_symbol(f"theta_{i}") for i in range(n_params)]
    param_names = [str(symbol) for symbol in symbols]

    # Store parameter info
    circuit._symbols = symbols
    circuit._param_names = param_names

    return circuit, param_names

bind_parameters

bind_parameters(circuit: Circuit, param_values: dict[str, float]) -> Circuit

Bind parameter values to parameterized circuit.

Source code in src/superquantx/backends/tket_backend.py
def bind_parameters(self, circuit: Circuit, param_values: dict[str, float]) -> Circuit:
    """Bind parameter values to parameterized circuit."""
    try:
        bound_circuit = circuit.copy()

        # Create symbol substitution map
        if hasattr(circuit, '_symbols'):
            symbol_map = {}
            for symbol, name in zip(circuit._symbols, circuit._param_names, strict=False):
                if name in param_values:
                    symbol_map[symbol] = param_values[name]

            # Substitute symbols with values
            bound_circuit.symbol_substitution(symbol_map)

        return bound_circuit

    except Exception as e:
        logger.error(f"Parameter binding failed: {e}")
        return circuit

expectation_value

expectation_value(circuit: Circuit, observable: str | ndarray, shots: int | None = None) -> float

Calculate expectation value of observable using TKET.

Source code in src/superquantx/backends/tket_backend.py
def expectation_value(self, circuit: Circuit, observable: str | np.ndarray,
                     shots: int | None = None) -> float:
    """Calculate expectation value of observable using TKET."""
    shots = shots or self.shots

    try:
        if isinstance(observable, str) and observable.upper() == 'Z':
            # Measure in Z basis
            measured_circuit = circuit.copy()
            measured_circuit.add_c_register("c", 1)
            measured_circuit.Measure(measured_circuit.qubits[0], measured_circuit.bits[0])

            result = self.execute_circuit(measured_circuit, shots)
            counts = result['counts']

            # Calculate <Z> expectation
            expectation = 0.0
            total_counts = sum(counts.values())

            for bitstring, count in counts.items():
                prob = count / total_counts
                if bitstring[0] == '0':
                    expectation += prob
                else:
                    expectation -= prob

            return expectation
        else:
            logger.warning("Only Z observable currently implemented")
            return 0.0

    except Exception as e:
        logger.error(f"Expectation value calculation failed: {e}")
        return 0.0

get_backend_info

get_backend_info() -> dict[str, Any]

Get information about the TKET backend.

Source code in src/superquantx/backends/tket_backend.py
def get_backend_info(self) -> dict[str, Any]:
    """Get information about the TKET backend."""
    info = {
        'backend_name': 'tket',
        'device': self.device_name,
        'provider': 'Quantinuum/Cambridge Quantum Computing',
        'shots': self.shots,
        'capabilities': self.capabilities,
    }

    if self._backend:
        info.update({
            'backend_class': self._backend.__class__.__name__,
            'supports_compilation': True,
            'supports_optimization': True,
        })

        if hasattr(self._backend, 'device'):
            device_info = self._backend.device
            info['device_info'] = str(device_info)

    return info

get_version_info

get_version_info() -> dict[str, str]

Get version information for TKET dependencies.

Source code in src/superquantx/backends/tket_backend.py
def get_version_info(self) -> dict[str, str]:
    """Get version information for TKET dependencies."""
    version_info = {'backend_version': '1.0.0'}

    try:
        import pytket
        version_info['pytket'] = pytket.__version__
    except (ImportError, AttributeError):
        pass

    if QUANTINUUM_AVAILABLE:
        try:
            import pytket.extensions.quantinuum
            version_info['pytket_quantinuum'] = getattr(pytket.extensions.quantinuum, '__version__', 'unknown')
        except (ImportError, AttributeError):
            pass

    return version_info

is_available

is_available() -> bool

Check if the backend is available and properly configured.

Source code in src/superquantx/backends/tket_backend.py
def is_available(self) -> bool:
    """Check if the backend is available and properly configured."""
    return TKET_AVAILABLE

get_circuit_info

get_circuit_info() -> dict[str, Any]

Get information about circuit execution capabilities.

Source code in src/superquantx/backends/tket_backend.py
def get_circuit_info(self) -> dict[str, Any]:
    """Get information about circuit execution capabilities."""
    return {
        'max_qubits': self._get_max_qubits(),
        'native_gates': self._get_native_gates(),
        'supports_mid_circuit_measurement': True,
        'supports_reset': True,
        'supports_conditional': True,
        'supports_optimization': True,
        'supports_compilation': True,
    }

get_statevector

get_statevector(circuit: Circuit) -> np.ndarray

Get statevector from TKET circuit.

Source code in src/superquantx/backends/tket_backend.py
def get_statevector(self, circuit: Circuit) -> np.ndarray:
    """Get statevector from TKET circuit."""
    try:
        if TKET_EXTENSIONS_AVAILABLE:
            from pytket.extensions.qiskit import AerStateBackend
            state_backend = AerStateBackend()
            compiled_circuit = state_backend.get_compiled_circuit(circuit)
            handle = state_backend.process_circuit(compiled_circuit)
            result = state_backend.get_result(handle)

            if hasattr(result, 'get_state'):
                return result.get_state()

        logger.warning("Statevector not available with current TKET setup")
        return np.zeros(2**circuit.n_qubits, dtype=complex)

    except Exception as e:
        logger.error(f"Failed to get statevector: {e}")
        return np.zeros(2**circuit.n_qubits, dtype=complex)

D-Wave Ocean Backend

superquantx.backends.OceanBackend

OceanBackend(device: str = 'simulator', solver: str | None = None, token: str | None = None, endpoint: str | None = None, shots: int = 1000, **kwargs)

Bases: BaseBackend

D-Wave Ocean backend for quantum annealing operations.

This backend provides access to D-Wave's quantum annealing systems for solving optimization problems formulated as QUBO or Ising models.

Note: Unlike gate-model quantum computers, D-Wave systems solve optimization problems rather than running quantum circuits.

Parameters:

Name Type Description Default
device str

Sampler type ('DWave', 'hybrid', 'simulator', 'advantage')

'simulator'
solver str | None

Specific solver name (optional)

None
token str | None

D-Wave API token (required for hardware)

None
endpoint str | None

D-Wave API endpoint

None
shots int

Number of samples (reads)

1000
**kwargs

Additional sampler configuration

{}
Example

Simulated annealing (no hardware required)

backend = OceanBackend(device='simulator')

D-Wave hardware (requires API token)

backend = OceanBackend( ... device='advantage', ... token='your-dwave-token' ... )

Source code in src/superquantx/backends/ocean_backend.py
def __init__(
    self,
    device: str = 'simulator',
    solver: str | None = None,
    token: str | None = None,
    endpoint: str | None = None,
    shots: int = 1000,  # Called "num_reads" in D-Wave
    **kwargs
) -> None:
    if not OCEAN_AVAILABLE:
        raise ImportError(
            "D-Wave Ocean not available. Install with: pip install dwave-ocean-sdk"
        )

    self.device_name = device
    self.solver_name = solver
    self.token = token
    self.endpoint = endpoint
    self.num_reads = shots
    self._sampler = None
    self._is_quantum_annealing = True  # This backend is for annealing, not gates

    super().__init__(device=device, shots=shots, **kwargs)

Functions

solve_qubo

solve_qubo(Q: dict[tuple[int, int], float], **kwargs) -> dict[str, Any]

Solve a Quadratic Unconstrained Binary Optimization (QUBO) problem.

Parameters:

Name Type Description Default
Q dict[tuple[int, int], float]

QUBO dictionary where keys are (i, j) variable pairs and values are coefficients

required
**kwargs

Additional solving parameters

{}

Returns:

Type Description
dict[str, Any]

Solution results with energies and samples

Source code in src/superquantx/backends/ocean_backend.py
def solve_qubo(self, Q: dict[tuple[int, int], float], **kwargs) -> dict[str, Any]:
    """Solve a Quadratic Unconstrained Binary Optimization (QUBO) problem.

    Args:
        Q: QUBO dictionary where keys are (i, j) variable pairs and values are coefficients
        **kwargs: Additional solving parameters

    Returns:
        Solution results with energies and samples

    """
    try:
        num_reads = kwargs.get('num_reads', self.num_reads)

        # Create BQM from QUBO
        bqm = dimod.BinaryQuadraticModel.from_qubo(Q)

        # Sample from the BQM
        sampleset = self._sampler.sample(bqm, num_reads=num_reads, **kwargs)

        # Convert results to standard format
        results = {
            'samples': [],
            'energies': [],
            'num_occurrences': [],
            'success': True,
            'num_reads': len(sampleset),
            'timing': getattr(sampleset, 'info', {}).get('timing', {}),
            'problem_type': 'QUBO'
        }

        for sample, energy, num_occur in sampleset.data(['sample', 'energy', 'num_occurrences']):
            results['samples'].append(dict(sample))
            results['energies'].append(energy)
            results['num_occurrences'].append(num_occur)

        return results

    except Exception as e:
        logger.error(f"QUBO solving failed: {e}")
        return {
            'samples': [],
            'energies': [],
            'success': False,
            'error': str(e),
            'problem_type': 'QUBO'
        }

solve_ising

solve_ising(h: dict[int, float], J: dict[tuple[int, int], float], **kwargs) -> dict[str, Any]

Solve an Ising model problem.

Parameters:

Name Type Description Default
h dict[int, float]

Linear coefficients (bias terms) for each variable

required
J dict[tuple[int, int], float]

Quadratic coefficients (coupling terms) between variables

required
**kwargs

Additional solving parameters

{}

Returns:

Type Description
dict[str, Any]

Solution results with energies and samples

Source code in src/superquantx/backends/ocean_backend.py
def solve_ising(self, h: dict[int, float], J: dict[tuple[int, int], float], **kwargs) -> dict[str, Any]:
    """Solve an Ising model problem.

    Args:
        h: Linear coefficients (bias terms) for each variable
        J: Quadratic coefficients (coupling terms) between variables
        **kwargs: Additional solving parameters

    Returns:
        Solution results with energies and samples

    """
    try:
        num_reads = kwargs.get('num_reads', self.num_reads)

        # Create BQM from Ising model
        bqm = dimod.BinaryQuadraticModel.from_ising(h, J)

        # Sample from the BQM
        sampleset = self._sampler.sample(bqm, num_reads=num_reads, **kwargs)

        # Convert results to standard format
        results = {
            'samples': [],
            'energies': [],
            'num_occurrences': [],
            'success': True,
            'num_reads': len(sampleset),
            'timing': getattr(sampleset, 'info', {}).get('timing', {}),
            'problem_type': 'Ising'
        }

        for sample, energy, num_occur in sampleset.data(['sample', 'energy', 'num_occurrences']):
            results['samples'].append(dict(sample))
            results['energies'].append(energy)
            results['num_occurrences'].append(num_occur)

        return results

    except Exception as e:
        logger.error(f"Ising model solving failed: {e}")
        return {
            'samples': [],
            'energies': [],
            'success': False,
            'error': str(e),
            'problem_type': 'Ising'
        }

solve_optimization_problem

solve_optimization_problem(problem: dict | Any, problem_type: str = 'auto') -> dict[str, Any]

Generic optimization problem solver.

Parameters:

Name Type Description Default
problem dict | Any

Problem specification (QUBO dict, Ising model, or BQM)

required
problem_type str

Type of problem ('qubo', 'ising', 'bqm', 'auto')

'auto'

Returns:

Type Description
dict[str, Any]

Solution results

Source code in src/superquantx/backends/ocean_backend.py
def solve_optimization_problem(self, problem: dict | Any, problem_type: str = 'auto') -> dict[str, Any]:
    """Generic optimization problem solver.

    Args:
        problem: Problem specification (QUBO dict, Ising model, or BQM)
        problem_type: Type of problem ('qubo', 'ising', 'bqm', 'auto')

    Returns:
        Solution results

    """
    try:
        if problem_type == 'auto':
            # Try to detect problem type
            if isinstance(problem, dict) and all(len(k) == 2 for k in problem.keys()):
                problem_type = 'qubo'
            elif hasattr(problem, 'linear') and hasattr(problem, 'quadratic'):
                problem_type = 'bqm'
            else:
                raise ValueError("Cannot auto-detect problem type")

        if problem_type == 'qubo':
            return self.solve_qubo(problem)
        elif problem_type == 'ising':
            h, J = problem  # Expecting tuple (h, J)
            return self.solve_ising(h, J)
        elif problem_type == 'bqm':
            # Direct BQM solving
            sampleset = self._sampler.sample(problem, num_reads=self.num_reads)
            return self._convert_sampleset(sampleset, problem_type)
        else:
            raise ValueError(f"Unknown problem type: {problem_type}")

    except Exception as e:
        logger.error(f"Optimization problem solving failed: {e}")
        return {
            'samples': [],
            'energies': [],
            'success': False,
            'error': str(e),
            'problem_type': problem_type
        }

create_circuit

create_circuit(n_qubits: int) -> dict[str, Any]

Limited circuit support for compatibility.

Note: D-Wave is not a gate-model quantum computer. This returns a placeholder for optimization problems.

Source code in src/superquantx/backends/ocean_backend.py
def create_circuit(self, n_qubits: int) -> dict[str, Any]:
    """Limited circuit support for compatibility.

    Note: D-Wave is not a gate-model quantum computer.
    This returns a placeholder for optimization problems.
    """
    logger.warning("D-Wave Ocean backend does not support gate-model circuits")
    return {
        'type': 'optimization_placeholder',
        'n_variables': n_qubits,
        'backend': 'ocean',
        'problem': None
    }

add_gate

add_gate(circuit: dict, gate: str, qubits: int | list[int], params: list[float] | None = None) -> dict

Limited gate support - not applicable for annealing.

Source code in src/superquantx/backends/ocean_backend.py
def add_gate(self, circuit: dict, gate: str, qubits: int | list[int],
             params: list[float] | None = None) -> dict:
    """Limited gate support - not applicable for annealing."""
    logger.warning("Gate operations not supported on D-Wave annealing backend")
    return circuit

add_measurement

add_measurement(circuit: dict, qubits: int | list[int]) -> dict

Limited measurement support - not applicable for annealing.

Source code in src/superquantx/backends/ocean_backend.py
def add_measurement(self, circuit: dict, qubits: int | list[int]) -> dict:
    """Limited measurement support - not applicable for annealing."""
    logger.warning("Measurements not applicable for D-Wave annealing backend")
    return circuit

execute_circuit

execute_circuit(circuit: dict, shots: int | None = None) -> dict[str, Any]

Limited circuit execution - redirects to optimization solving.

Source code in src/superquantx/backends/ocean_backend.py
def execute_circuit(self, circuit: dict, shots: int | None = None) -> dict[str, Any]:
    """Limited circuit execution - redirects to optimization solving."""
    logger.warning("Circuit execution not supported - use solve_qubo() or solve_ising() instead")
    return {
        'counts': {},
        'shots': shots or self.shots,
        'success': False,
        'error': 'Use optimization problem methods instead of circuit execution',
        'backend': 'ocean'
    }

get_backend_info

get_backend_info() -> dict[str, Any]

Get information about the D-Wave Ocean backend.

Source code in src/superquantx/backends/ocean_backend.py
def get_backend_info(self) -> dict[str, Any]:
    """Get information about the D-Wave Ocean backend."""
    info = {
        'backend_name': 'ocean',
        'device': self.device_name,
        'provider': 'D-Wave Systems',
        'num_reads': self.num_reads,
        'capabilities': self.capabilities,
        'quantum_annealing': True,
        'gate_model': False,
    }

    if self._sampler and hasattr(self._sampler, 'properties'):
        try:
            props = self._sampler.properties
            info.update({
                'solver_name': getattr(self._sampler, 'solver', {}).get('name', 'unknown'),
                'num_qubits': len(props.get('qubits', [])),
                'connectivity': 'Chimera/Pegasus/Zephyr',  # D-Wave topologies
            })
        except (AttributeError, Exception):
            pass

    return info

get_version_info

get_version_info() -> dict[str, str]

Get version information for Ocean dependencies.

Source code in src/superquantx/backends/ocean_backend.py
def get_version_info(self) -> dict[str, str]:
    """Get version information for Ocean dependencies."""
    version_info = {'backend_version': '1.0.0'}

    try:
        version_info['dimod'] = dimod.__version__
    except (AttributeError, ImportError):
        pass

    try:
        import dwave.system
        version_info['dwave_system'] = dwave.system.__version__
    except (ImportError, AttributeError):
        pass

    try:
        import dwave.samplers
        version_info['dwave_samplers'] = dwave.samplers.__version__
    except (ImportError, AttributeError):
        pass

    return version_info

is_available

is_available() -> bool

Check if the backend is available and properly configured.

Source code in src/superquantx/backends/ocean_backend.py
def is_available(self) -> bool:
    """Check if the backend is available and properly configured."""
    return OCEAN_AVAILABLE and self._sampler is not None

get_circuit_info

get_circuit_info() -> dict[str, Any]

Get circuit capabilities (limited for annealing backend).

Source code in src/superquantx/backends/ocean_backend.py
def get_circuit_info(self) -> dict[str, Any]:
    """Get circuit capabilities (limited for annealing backend)."""
    return {
        'max_qubits': 0,  # Not applicable
        'max_variables': self._get_max_variables(),
        'native_gates': [],  # Not applicable
        'supports_mid_circuit_measurement': False,
        'supports_reset': False,
        'supports_conditional': False,
        'supports_optimization': True,
        'quantum_annealing': True,
    }

get_statevector

get_statevector(circuit: dict) -> np.ndarray

Get statevector (not applicable for annealing backend).

Source code in src/superquantx/backends/ocean_backend.py
def get_statevector(self, circuit: dict) -> np.ndarray:
    """Get statevector (not applicable for annealing backend)."""
    logger.warning("Statevector not applicable for quantum annealing backend")
    return np.array([1.0 + 0j])  # Dummy statevector

solve_max_cut

solve_max_cut(graph: Any | list[tuple], **kwargs) -> dict[str, Any]

Solve Maximum Cut problem on a graph.

Source code in src/superquantx/backends/ocean_backend.py
def solve_max_cut(self, graph: Any | list[tuple], **kwargs) -> dict[str, Any]:
    """Solve Maximum Cut problem on a graph."""
    try:
        if not nx:
            raise ImportError("NetworkX not available for graph operations")

        if isinstance(graph, list):
            # Convert edge list to networkx graph
            G = nx.Graph()
            G.add_edges_from(graph)
        else:
            G = graph

        # Convert to QUBO formulation
        Q = {}
        for i, j in G.edges():
            Q[(i, i)] = Q.get((i, i), 0) + 1
            Q[(j, j)] = Q.get((j, j), 0) + 1
            Q[(i, j)] = Q.get((i, j), 0) - 2

        return self.solve_qubo(Q, **kwargs)

    except Exception as e:
        logger.error(f"Max Cut solving failed: {e}")
        return {'success': False, 'error': str(e)}

solve_tsp

solve_tsp(distance_matrix: ndarray, **kwargs) -> dict[str, Any]

Solve Traveling Salesman Problem (simplified formulation).

Source code in src/superquantx/backends/ocean_backend.py
def solve_tsp(self, distance_matrix: np.ndarray, **kwargs) -> dict[str, Any]:
    """Solve Traveling Salesman Problem (simplified formulation)."""
    try:
        n_cities = len(distance_matrix)

        # This is a simplified TSP formulation
        # Full TSP requires more complex constraints
        logger.warning("TSP formulation is simplified - may not give valid tours")

        Q = {}
        # Add distance costs
        for i in range(n_cities):
            for j in range(i+1, n_cities):
                for t in range(n_cities):
                    # Variable x_it means city i is visited at time t
                    var_i = i * n_cities + t
                    var_j = j * n_cities + ((t + 1) % n_cities)
                    Q[(var_i, var_j)] = distance_matrix[i, j]

        return self.solve_qubo(Q, **kwargs)

    except Exception as e:
        logger.error(f"TSP solving failed: {e}")
        return {'success': False, 'error': str(e)}

Utility Functions

Backend Management

superquantx.backends.get_backend

get_backend(backend: str | BaseBackend, **kwargs) -> BaseBackend

Get a quantum backend instance.

Parameters:

Name Type Description Default
backend str | BaseBackend

Backend name or instance

required
**kwargs

Backend configuration parameters

{}

Returns:

Type Description
BaseBackend

Backend instance

Raises:

Type Description
ValueError

If backend is not supported

ImportError

If backend dependencies are missing

Example

backend = get_backend('pennylane', device='default.qubit') backend = get_backend('qiskit', provider='IBMQ')

Source code in src/superquantx/backends/__init__.py
def get_backend(backend: str | BaseBackend, **kwargs) -> BaseBackend:
    """Get a quantum backend instance.

    Args:
        backend: Backend name or instance
        **kwargs: Backend configuration parameters

    Returns:
        Backend instance

    Raises:
        ValueError: If backend is not supported
        ImportError: If backend dependencies are missing

    Example:
        >>> backend = get_backend('pennylane', device='default.qubit')
        >>> backend = get_backend('qiskit', provider='IBMQ')

    """
    if isinstance(backend, BaseBackend):
        return backend

    if not isinstance(backend, str):
        raise ValueError(f"Backend must be string or BaseBackend instance, got {type(backend)}")

    # Resolve aliases
    backend_name = BACKEND_ALIASES.get(backend.lower(), backend.lower())

    # Auto-select backend if requested
    if backend_name == 'auto':
        backend_name = _auto_select_backend()

    # Get backend class
    if backend_name not in BACKEND_REGISTRY:
        available = list(BACKEND_REGISTRY.keys())
        raise ValueError(f"Backend '{backend_name}' not supported. Available: {available}")

    backend_class = BACKEND_REGISTRY[backend_name]

    try:
        logger.info(f"Initializing {backend_name} backend")
        return backend_class(**kwargs)
    except ImportError as e:
        logger.error(f"Failed to import {backend_name} backend: {e}")
        raise ImportError(f"Backend '{backend_name}' requires additional dependencies: {e}")
    except Exception as e:
        logger.error(f"Failed to initialize {backend_name} backend: {e}")
        raise

superquantx.backends.list_available_backends

list_available_backends() -> dict[str, dict[str, Any]]

List all available backends and their status.

Returns:

Type Description
dict[str, dict[str, Any]]

Dictionary with backend information

Source code in src/superquantx/backends/__init__.py
def list_available_backends() -> dict[str, dict[str, Any]]:
    """List all available backends and their status.

    Returns:
        Dictionary with backend information

    """
    backend_info = {}

    for name, backend_class in BACKEND_REGISTRY.items():
        if name == 'auto' or backend_class is None:
            continue

        try:
            # Try to instantiate to check availability
            test_instance = backend_class()
            backend_info[name] = {
                'available': True,
                'class': backend_class.__name__,
                'description': getattr(backend_class, '__doc__', '').split('\n')[0] if backend_class.__doc__ else '',
                'capabilities': getattr(test_instance, 'capabilities', {}),
            }
        except ImportError:
            backend_info[name] = {
                'available': False,
                'class': backend_class.__name__,
                'reason': 'Missing dependencies',
            }
        except Exception as e:
            backend_info[name] = {
                'available': False,
                'class': backend_class.__name__,
                'reason': str(e),
            }

    return backend_info

superquantx.backends.check_backend_compatibility

check_backend_compatibility(backend_name: str) -> dict[str, Any]

Check compatibility and requirements for a specific backend.

Parameters:

Name Type Description Default
backend_name str

Name of the backend to check

required

Returns:

Type Description
dict[str, Any]

Compatibility information

Source code in src/superquantx/backends/__init__.py
def check_backend_compatibility(backend_name: str) -> dict[str, Any]:
    """Check compatibility and requirements for a specific backend.

    Args:
        backend_name: Name of the backend to check

    Returns:
        Compatibility information

    """
    backend_name = BACKEND_ALIASES.get(backend_name.lower(), backend_name.lower())

    if backend_name not in BACKEND_REGISTRY:
        return {'compatible': False, 'reason': 'Backend not supported'}

    backend_class = BACKEND_REGISTRY[backend_name]

    try:
        # Try basic instantiation
        test_backend = backend_class()

        return {
            'compatible': True,
            'backend_class': backend_class.__name__,
            'requirements_met': True,
            'capabilities': getattr(test_backend, 'capabilities', {}),
            'version_info': getattr(test_backend, 'get_version_info', lambda: {})(),
        }

    except ImportError as e:
        return {
            'compatible': False,
            'reason': 'Missing dependencies',
            'missing_packages': str(e),
            'requirements_met': False,
        }
    except Exception as e:
        return {
            'compatible': False,
            'reason': str(e),
            'requirements_met': False,
        }

Backend Selection Guide

By Use Case

Development & Prototyping

# Fast local simulation
backend = sqx.get_backend('simulator', max_qubits=10)

# Cross-platform testing
backend = sqx.get_backend('pennylane', device='default.qubit')

Production & Research

# IBM Quantum hardware
backend = sqx.get_backend('qiskit', device='ibmq_manila', token='your-token')

# Google Quantum AI
backend = sqx.get_backend('cirq', processor_id='rainbow', project_id='your-project')

# AWS Braket cloud
backend = sqx.get_backend('braket', device_arn='arn:aws:braket:us-east-1::device/qpu/ionq/ionQdevice')

Specialized Applications

# Quantum chemistry (TKET optimization)
backend = sqx.get_backend('tket', device='H1-1E', api_key='quantinuum-key')

# Optimization problems (D-Wave annealing)
backend = sqx.get_backend('ocean', device='advantage', token='dwave-token')

By Performance Requirements

High Accuracy (Large Shot Counts)

backends_high_accuracy = {
    'simulator': sqx.get_backend('simulator', shots=100000),
    'ibm_hardware': sqx.get_backend('qiskit', device='ibmq_montreal', shots=8192),
    'aws_sv1': sqx.get_backend('braket', device='sv1', shots=100000)
}

Fast Iteration (Low Latency)

backends_fast = {
    'local_sim': sqx.get_backend('simulator', shots=1000),
    'pennylane': sqx.get_backend('pennylane', device='lightning.qubit'),
    'braket_local': sqx.get_backend('braket', device='braket_sv')
}

Cost Optimization

# Free tier resources
free_backends = {
    'simulator': sqx.get_backend('simulator'),
    'ibm_free': sqx.get_backend('qiskit', device='ibmq_qasm_simulator'),
    'aws_sim': sqx.get_backend('braket', device='braket_sv')  # First 1 hour free
}

Integration Examples

Multi-Backend Algorithm Testing

import superquantx as sqx

def test_algorithm_across_backends(algorithm_func, backends, *args, **kwargs):
    """Test quantum algorithm across multiple backends."""

    results = {}

    for backend_name, backend in backends.items():
        try:
            print(f"Testing on {backend_name}...")

            # Run algorithm
            result = algorithm_func(backend, *args, **kwargs)
            results[backend_name] = result

            print(f"  ✓ Success: {result}")

        except Exception as e:
            print(f"  ✗ Failed: {e}")
            results[backend_name] = None

    return results

# Define test backends
test_backends = {
    'simulator': sqx.get_backend('simulator'),
    'pennylane': sqx.get_backend('pennylane', device='default.qubit'),
}

# Example quantum algorithm
def simple_bell_state(backend):
    circuit = backend.create_circuit(2)
    circuit = backend.add_gate(circuit, 'h', 0)
    circuit = backend.add_gate(circuit, 'cx', [0, 1])
    return backend.execute_circuit(circuit)

# Test across backends
results = test_algorithm_across_backends(simple_bell_state, test_backends)

Backend Fallback Strategy

def get_backend_with_fallback(preferences, **kwargs):
    """Get backend with fallback strategy."""

    for backend_name in preferences:
        try:
            backend = sqx.get_backend(backend_name, **kwargs)
            if backend.is_available():
                print(f"Using backend: {backend_name}")
                return backend
        except Exception as e:
            print(f"Backend {backend_name} failed: {e}")
            continue

    raise RuntimeError("No backends available")

# Usage
backend = get_backend_with_fallback([
    'qiskit',      # Try IBM first
    'pennylane',   # Fallback to PennyLane  
    'simulator'    # Final fallback
], shots=1024)

Performance Benchmarking

import time
import numpy as np

def benchmark_backends(backends, circuit_sizes=[2, 4, 6, 8]):
    """Benchmark quantum backends across different circuit sizes."""

    results = {}

    for backend_name, backend in backends.items():
        print(f"\nBenchmarking {backend_name}:")
        results[backend_name] = {}

        for n_qubits in circuit_sizes:
            if n_qubits > backend.get_backend_info().get('capabilities', {}).get('max_qubits', 32):
                continue

            # Create test circuit
            circuit = backend.create_circuit(n_qubits)

            # Add random gates
            for _ in range(n_qubits * 2):
                qubit = np.random.randint(0, n_qubits)
                circuit = backend.add_gate(circuit, 'h', qubit)

            for _ in range(n_qubits - 1):
                q1, q2 = np.random.choice(n_qubits, 2, replace=False)
                circuit = backend.add_gate(circuit, 'cx', [q1, q2])

            # Benchmark execution
            start_time = time.time()
            try:
                result = backend.execute_circuit(circuit, shots=1000)
                execution_time = time.time() - start_time

                results[backend_name][n_qubits] = {
                    'time': execution_time,
                    'success': result.get('success', True),
                    'total_counts': sum(result.get('counts', {}).values())
                }

                print(f"  {n_qubits} qubits: {execution_time:.3f}s")

            except Exception as e:
                print(f"  {n_qubits} qubits: Failed - {e}")
                results[backend_name][n_qubits] = {'error': str(e)}

    return results

# Run benchmark
benchmark_backends({
    'simulator': sqx.get_backend('simulator'),
    'pennylane': sqx.get_backend('pennylane'),
})

Backend Configuration

Environment Setup

import os
import superquantx as sqx

# Configure backends via environment variables
os.environ['QISKIT_IBMQ_TOKEN'] = 'your-ibm-token'
os.environ['BRAKET_AWS_REGION'] = 'us-east-1'
os.environ['DWAVE_API_TOKEN'] = 'your-dwave-token'

# Test configurations
def validate_backend_config():
    """Validate backend configurations."""

    configs = {
        'qiskit': {
            'required_env': ['QISKIT_IBMQ_TOKEN'],
            'test_device': 'ibmq_qasm_simulator'
        },
        'braket': {
            'required_env': ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY'],
            'test_device': 'braket_sv'
        },
        'ocean': {
            'required_env': ['DWAVE_API_TOKEN'],
            'test_device': 'simulator'
        }
    }

    for backend_name, config in configs.items():
        print(f"Validating {backend_name}:")

        # Check environment variables
        missing_env = [env for env in config['required_env'] 
                      if not os.getenv(env)]

        if missing_env:
            print(f"  ✗ Missing environment variables: {missing_env}")
            continue

        # Test backend creation
        try:
            backend = sqx.get_backend(backend_name, device=config['test_device'])
            if backend.is_available():
                print(f"  ✓ Backend available")
            else:
                print(f"  ✗ Backend not available")
        except Exception as e:
            print(f"  ✗ Configuration error: {e}")

validate_backend_config()

Custom Backend Configuration

# Advanced backend configuration
backend_configs = {
    'qiskit_optimized': {
        'backend_type': 'qiskit',
        'device': 'ibmq_montreal',
        'shots': 4096,
        'optimization_level': 3,
        'error_mitigation': True,
        'noise_model': 'device_noise'
    },

    'pennylane_gpu': {
        'backend_type': 'pennylane', 
        'device': 'lightning.gpu',
        'shots': 100000,
        'batch_size': 1024
    },

    'braket_cost_optimized': {
        'backend_type': 'braket',
        'device': 'sv1',  # Simulator for cost optimization
        'shots': 1000,
        'max_parallel_tasks': 5
    }
}

def create_configured_backend(config_name):
    """Create backend from configuration."""
    config = backend_configs[config_name]
    backend_type = config.pop('backend_type')
    return sqx.get_backend(backend_type, **config)

Error Handling

Backend-Specific Error Handling

from superquantx.exceptions import (
    QuantumBackendError, 
    DeviceOfflineError,
    AuthenticationError,
    ResourceExhaustedError
)

def robust_backend_execution(backend, circuit, max_retries=3):
    """Execute circuit with comprehensive error handling."""

    for attempt in range(max_retries):
        try:
            result = backend.execute_circuit(circuit)
            return result

        except AuthenticationError:
            print("Authentication failed - check API tokens")
            raise  # Don't retry auth errors

        except DeviceOfflineError as e:
            print(f"Device offline: {e}")
            if attempt < max_retries - 1:
                print("Waiting 30s before retry...")
                time.sleep(30)

        except ResourceExhaustedError as e:
            print(f"Resources exhausted: {e}")
            # Reduce shots and retry
            circuit.shots = max(circuit.shots // 2, 100)

        except QuantumBackendError as e:
            print(f"Backend error on attempt {attempt + 1}: {e}")
            if attempt == max_retries - 1:
                raise

    raise RuntimeError("All execution attempts failed")

# Usage with error handling
try:
    backend = sqx.get_backend('qiskit', device='ibmq_manila')
    result = robust_backend_execution(backend, circuit)
except Exception as e:
    print(f"Execution failed: {e}")
    # Fallback to simulator
    fallback_backend = sqx.get_backend('simulator')
    result = fallback_backend.execute_circuit(circuit)

Best Practices

Backend Selection Strategy

  1. Development Phase: Use simulator or pennylane for rapid iteration
  2. Testing Phase: Use cloud simulators (braket_sv, qiskit_aer) for validation
  3. Production Phase: Use real hardware with appropriate error mitigation
  4. Cost Optimization: Use free simulators when possible, batch hardware jobs

Performance Optimization

# Optimize circuit for specific backend
def optimize_for_backend(circuit, backend):
    """Optimize circuit for specific backend capabilities."""

    backend_info = backend.get_backend_info()

    if 'qiskit' in backend_info.get('backend_name', ''):
        # Use Qiskit-specific optimizations
        return backend.transpile_circuit(circuit, optimization_level=2)

    elif 'tket' in backend_info.get('backend_name', ''):
        # Use TKET optimizations
        return backend.optimize_circuit(circuit, optimization_level=3)

    elif 'ocean' in backend_info.get('backend_name', ''):
        # Ocean backends use different problem formulations
        return backend.convert_to_qubo(circuit)

    else:
        # Generic optimization
        return circuit

# Batch processing for hardware backends  
def batch_execute_circuits(backend, circuits, max_batch_size=10):
    """Execute circuits in batches for efficiency."""

    results = []

    for i in range(0, len(circuits), max_batch_size):
        batch = circuits[i:i + max_batch_size]

        if hasattr(backend, 'execute_batch'):
            # Use native batch execution if available
            batch_results = backend.execute_batch(batch)
        else:
            # Sequential execution fallback
            batch_results = [backend.execute_circuit(c) for c in batch]

        results.extend(batch_results)

    return results

For detailed backend integration guides, see: - Qiskit Integration - PennyLane Integration - Cirq Integration - Braket Integration - TKET Integration - Ocean Integration - Simulator Backend