diff --git a/quantumaudio/schemes/mqsm.py b/quantumaudio/schemes/mqsm.py index ac43ef0..72d0921 100644 --- a/quantumaudio/schemes/mqsm.py +++ b/quantumaudio/schemes/mqsm.py @@ -13,7 +13,7 @@ # limitations under the License. # ========================================================================== -from typing import Optional, Union, Callable, Any, Tuple +from typing import Optional, Union, Tuple import numpy as np import qiskit @@ -360,7 +360,7 @@ def decode_counts( self, counts: Union[dict, qiskit.result.Counts], metadata: dict, - keep_padding: Tuple[int, int] = (False, False), + keep_padding: Tuple[bool, bool] = (False, False), ) -> np.ndarray: """Given a Qiskit counts object or Dictionary, Extract components and restore the conversion did at encoding stage. @@ -411,7 +411,7 @@ def decode_result( self, result: qiskit.result.Result, metadata: Optional[dict] = None, - keep_padding: Tuple[int, int] = (False, False), + keep_padding: Tuple[bool, bool] = (False, False), ) -> np.ndarray: """Given a result object. Extract components and restore the conversion did in the encoding stage. @@ -441,10 +441,8 @@ def decode( self, circuit: qiskit.QuantumCircuit, metadata: Optional[dict] = None, - keep_padding: Tuple[int, int] = (False, False), - execute_function: Callable[ - [qiskit.QuantumCircuit, dict], Any - ] = utils.execute, + keep_padding: Tuple[bool, bool] = (False, False), + execute_function: utils.ExecuteFunction = utils.execute, **kwargs, ) -> np.ndarray: """Given a qiskit circuit, decodes and returns the Original Audio Array. diff --git a/quantumaudio/schemes/msqpam.py b/quantumaudio/schemes/msqpam.py index 821d7be..5c1de3c 100644 --- a/quantumaudio/schemes/msqpam.py +++ b/quantumaudio/schemes/msqpam.py @@ -13,7 +13,7 @@ # limitations under the License. # ========================================================================== -from typing import Optional, Union, Callable, Any, Tuple +from typing import Optional, Union, Tuple import numpy as np import qiskit @@ -370,7 +370,7 @@ def decode_counts( counts: Union[dict, qiskit.result.Counts], metadata: dict, inverted: bool = False, - keep_padding: Tuple[int, int] = (False, False), + keep_padding: Tuple[bool, bool] = (False, False), ) -> np.ndarray: """Given a Qiskit counts object or Dictionary, Extract components and restore the conversion did at encoding stage. @@ -420,7 +420,7 @@ def decode_result( result: qiskit.result.Result, metadata: Optional[dict] = None, inverted: bool = False, - keep_padding: Tuple[int, int] = (False, False), + keep_padding: Tuple[bool, bool] = (False, False), ) -> np.ndarray: """Given a result object. Extract components and restore the conversion did in the encoding stage. @@ -455,10 +455,8 @@ def decode( circuit: qiskit.QuantumCircuit, metadata: Optional[dict] = None, inverted: bool = False, - keep_padding: Tuple[int, int] = (False, False), - execute_function: Callable[ - [qiskit.QuantumCircuit, dict], Any - ] = utils.execute, + keep_padding: Tuple[bool, bool] = (False, False), + execute_function: utils.ExecuteFunction = utils.execute, **kwargs, ) -> np.ndarray: """Given a qiskit circuit, decodes and returns the Original Audio Array. diff --git a/quantumaudio/schemes/qpam.py b/quantumaudio/schemes/qpam.py index 98122ea..ca31bf0 100644 --- a/quantumaudio/schemes/qpam.py +++ b/quantumaudio/schemes/qpam.py @@ -13,7 +13,7 @@ # limitations under the License. # ========================================================================== -from typing import Optional, Union, Callable, Any, Tuple +from typing import Optional, Union, Tuple import numpy as np import qiskit @@ -345,9 +345,7 @@ def decode( shots: Optional[int] = 8000, norm: Optional[float] = None, keep_padding: bool = False, - execute_function: Callable[ - [qiskit.QuantumCircuit, dict], Any - ] = utils.execute, + execute_function: utils.ExecuteFunction = utils.execute, **kwargs, ) -> np.ndarray: """Given a qiskit circuit, decodes and returns back the Original Audio Array. diff --git a/quantumaudio/schemes/qsm.py b/quantumaudio/schemes/qsm.py index ca0b037..23dd259 100644 --- a/quantumaudio/schemes/qsm.py +++ b/quantumaudio/schemes/qsm.py @@ -13,7 +13,7 @@ # limitations under the License. # ========================================================================== -from typing import Optional, Union, Callable, Any, Tuple +from typing import Optional, Union, Tuple import numpy as np import qiskit @@ -361,9 +361,7 @@ def decode( circuit: qiskit.QuantumCircuit, metadata: Optional[dict] = None, keep_padding: bool = False, - execute_function: Callable[ - [qiskit.QuantumCircuit, dict], Any - ] = utils.execute, + execute_function: utils.ExecuteFunction = utils.execute, **kwargs, ) -> np.ndarray: """Given a qiskit circuit, decodes and returns back the Original Audio Array. diff --git a/quantumaudio/schemes/sqpam.py b/quantumaudio/schemes/sqpam.py index e127f98..e2de8d4 100644 --- a/quantumaudio/schemes/sqpam.py +++ b/quantumaudio/schemes/sqpam.py @@ -13,7 +13,7 @@ # limitations under the License. # ========================================================================== -from typing import Optional, Union, Callable, Any, Tuple +from typing import Optional, Union, Tuple import numpy as np import qiskit @@ -378,9 +378,7 @@ def decode( metadata: Optional[dict] = None, inverted: bool = False, keep_padding: bool = False, - execute_function: Callable[ - [qiskit.QuantumCircuit, dict], Any - ] = utils.execute, + execute_function: utils.ExecuteFunction = utils.execute, **kwargs, ) -> np.ndarray: """Given a qiskit circuit, decodes and returns back the Original Audio Array. diff --git a/quantumaudio/utils/execute.py b/quantumaudio/utils/execute.py index e23afed..f23e71e 100644 --- a/quantumaudio/utils/execute.py +++ b/quantumaudio/utils/execute.py @@ -15,9 +15,27 @@ import qiskit_aer from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager -from typing import Type, Any +from typing import Type, Any, Protocol import importlib +import qiskit + + +class ExecuteFunction(Protocol): + """Callable protocol for circuit execution backends used by scheme decoders. + + An execute function takes a ``circuit`` argument and may accept + any number of additional keyword arguments (e.g. ``shots``, ``backend``). + It returns a result object compatible with + :func:`quantumaudio.utils.results.get_counts` and + :func:`quantumaudio.utils.results.get_metadata`. + """ + + def __call__( + self, circuit: qiskit.QuantumCircuit, **kwargs: Any + ) -> Any: ... + + # Optional Import if exists _Sampler = ( getattr(importlib.import_module("qiskit_ibm_runtime"), "SamplerV2", None) @@ -37,6 +55,7 @@ def execute( backend: Any = None, keep_memory: bool = False, optimization_level: int = 3, + **kwargs: Any, ): """ Executes a quantum circuit on a given backend and return the results. @@ -47,6 +66,9 @@ def execute( shots: Total number of times the quantum circuit is measured. keep_memory: Whether to return the memory (quantum state) of each shot. optimization_level: Optimization level for transpiling the circuit. + **kwargs: Accepted for compatibility with the :class:`ExecuteFunction` + protocol (additional keyword arguments forwarded by scheme + ``decode`` calls); ignored by this implementation. Returns: Result: The result of the execution, containing the counts and other metadata. @@ -74,6 +96,7 @@ def execute_with_sampler( backend: Any = None, shots: int = 8000, optimization_level: int = 3, + **kwargs: Any, ): """ Executes a quantum circuit on a given backend using `Sampler Primitive` and return the results. @@ -83,6 +106,9 @@ def execute_with_sampler( backend: The backend on which to run the circuit. If None, the default backend `qiskit_aer.AerSimulator()` is used. shots: Total number of times the quantum circuit is measured. optimization_level: Optimization level for transpiling the circuit. + **kwargs: Accepted for compatibility with the :class:`ExecuteFunction` + protocol (additional keyword arguments forwarded by scheme + ``decode`` calls); ignored by this implementation. Returns: Result: The result of the execution, containing the counts and other metadata.