Source code for qc_executor.qiskit.qiskit_circuit
"""Qiskit circuit wrapper for parameter management and circuit caching."""
from __future__ import annotations
from collections import OrderedDict
from typing import List
from qc_executor.qiskit._param_binding import build_params_dict
[docs]
class QiskitCircuit:
"""
Wrapper for Qiskit circuits used by QiskitExecutor.
Provides parameter management and circuit caching functionality.
"""
def __init__(self, circuit):
"""
Initialize QiskitCircuit wrapper.
Args:
circuit: QuantumCircuit object (from qc_executor.quantum_circuit)
"""
# Extract the internal qiskit circuit
self._qiskit_circuit = getattr(circuit, "qiskit_circuit", circuit)
self._num_qubits = self._qiskit_circuit.num_qubits
# Group parameters by ParameterVector name
self._parameter_dimensions = OrderedDict()
self._free_parameters = set()
for p in self._qiskit_circuit.parameters:
self._free_parameters.add(p)
name = p.vector.name
self._parameter_dimensions[name] = self._parameter_dimensions.get(name, 0) + 1
[docs]
@classmethod
def from_quantum_circuit(cls, circuit):
"""Create a native Qiskit circuit wrapper from a generic circuit."""
return cls(circuit)
@property
def num_qubits(self) -> int:
"""Number of qubits in the circuit."""
return self._num_qubits
@property
def hash(self) -> int:
"""Hash of the circuit for caching."""
return hash(str(self._qiskit_circuit))
@property
def parameter_names(self) -> List[str]:
"""List of parameter vector names."""
return list(self._parameter_dimensions.keys())
@property
def parameter_dimensions(self) -> dict:
"""Dictionary mapping parameter names to their dimensions."""
return dict(self._parameter_dimensions)
@property
def qiskit_circuit(self):
"""Access to the underlying Qiskit circuit."""
return self._qiskit_circuit
@property
def free_parameters(self) -> set:
"""Set of all free parameters in the circuit."""
return self._free_parameters
[docs]
def bind_parameters(self, parameter_values: dict):
"""
Bind parameter values to the circuit.
Args:
parameter_values: Dictionary mapping parameter names to values
Returns:
Bound Qiskit circuit
"""
params_dict = build_params_dict(self._free_parameters, parameter_values)
# Bind parameters to circuit
if params_dict:
return self._qiskit_circuit.assign_parameters(params_dict)
return self._qiskit_circuit
[docs]
@classmethod
def from_qiskit(cls, qiskit_circuit) -> "QiskitCircuit":
"""Create a :class:`QiskitCircuit` directly from a Qiskit ``QuantumCircuit``.
This bypasses the normal ``__init__`` path which expects
an executor ``QuantumCircuit`` wrapper and instead accepts
an already-transpiled Qiskit circuit.
"""
wrapper = object.__new__(cls)
wrapper._qiskit_circuit = qiskit_circuit
wrapper._num_qubits = qiskit_circuit.num_qubits
wrapper._parameter_dimensions = OrderedDict()
wrapper._free_parameters = set()
for p in qiskit_circuit.parameters:
wrapper._free_parameters.add(p)
name = p.vector.name if hasattr(p, "vector") else p.name
wrapper._parameter_dimensions[name] = wrapper._parameter_dimensions.get(name, 0) + 1
return wrapper
[docs]
def copy(self):
"""Return a copy of the circuit wrapper."""
return QiskitCircuit(self._qiskit_circuit.copy())
def __str__(self):
return str(self._qiskit_circuit)
def __repr__(self):
return f"QiskitCircuit({self.num_qubits} qubits, {len(self._free_parameters)} parameters)"