Skip to content
Construct PsiQDK Algorithms

quantum_phase_estimation

quantum_phase_estimation

Top-level import for experimental implementation of quantum phase estimation.

FrequencyInterpreter module-attribute

FrequencyInterpreter = Callable[[float], float]

GenericUnitaryCallable module-attribute

GenericUnitaryCallable: TypeAlias = Callable[[BaseQubits, BaseQubits], None]

DebugQFTQPEFrequencyResolver dataclass

DebugQFTQPEFrequencyResolver(frequency_interpreter: FrequencyInterpreter = default_frequency_interpreter)

Class to handle QPE data accumulation.

This class specifically handles the cases where we use classical "cheat" methods to pull out information about probabilities etc rather than using measurements as you'd have to do for a real QPU.

frequency_interpreter class-attribute instance-attribute

frequency_interpreter: FrequencyInterpreter = default_frequency_interpreter

measurement_outcomes property

measurement_outcomes: dict[float, float]

fixed_point_measurement_outcomes property

fixed_point_measurement_outcomes: dict[float, float]

Get the measurement outcomes interpreted as raw fixed point numbers.

phases class-attribute instance-attribute

phases = ...

probabilities class-attribute instance-attribute

probabilities = ...

iterate

iterate() -> Iterator[None]

Iteration for building up QFT QPE statistics.

Since we're debugging, this is effectively just a dummy method that just yields None once. The statistics we're going to get are going to come from read probabilities instead of repeated measurements.

resolve

resolve(time_frequency_register: Qubits)

calculate_holevo_variance

calculate_holevo_variance() -> float

get_most_probable_phase

get_most_probable_phase() -> float

reset

reset() -> None

Reset the frequency resolver.

Allows the same qpe_program to be used with different variables without reinitialising it. Since this is debugging this doesn't need to do anything here.

QFTQPEFrequencyResolver dataclass

QFTQPEFrequencyResolver(num_shots: int = 1, all_measurement_outcomes: list[float] = list(), frequency_interpreter: FrequencyInterpreter = default_frequency_interpreter, early_exit_function: Callable[[QFTQPEFrequencyResolver, int], bool] = _default_exit_function)

Frequency resolver for "standard" measurement-based QFT QPE.

num_shots class-attribute instance-attribute

num_shots: int = 1

all_measurement_outcomes class-attribute instance-attribute

all_measurement_outcomes: list[float] = field(default_factory=list)

frequency_interpreter class-attribute instance-attribute

frequency_interpreter: FrequencyInterpreter = default_frequency_interpreter

early_exit_function class-attribute instance-attribute

early_exit_function: Callable[[QFTQPEFrequencyResolver, int], bool] = _default_exit_function

measurement_outcomes property

measurement_outcomes: dict[float, float]

Create dictionary of phases and their probabilities.

fixed_point_measurement_outcomes property

fixed_point_measurement_outcomes: dict[float, float]

Get the measurement outcomes interpreted as raw fixed point numbers.

exit_condition class-attribute instance-attribute

exit_condition = ...

phases class-attribute instance-attribute

phases = ...

iterate

iterate() -> Iterator[None]

Iteration for building up QFT QPE statistics.

resolve

resolve(time_frequency_register: Qubits)

Collect measurement data.

get_most_probable_phase

get_most_probable_phase() -> float

Get the most likely phase.

calculate_holevo_variance

calculate_holevo_variance() -> float

reset

reset() -> None

Reset the all_measurement_outcomes list.

Allows the same qpe_program to be used with different variables without reinitialising it.

FrequencyResolver

Bases: Protocol

iterate

iterate() -> Iterable

resolve

resolve(time_frequency_register: Qubits)

QPEConfig

Bases: Protocol

Configuration for QPE programs.

bits_of_precision property

bits_of_precision: int

Number of qubits needed to represent the phase in QPE.

num_time_samples property

num_time_samples: int | None

Total number of times sampled in QPE.

iterations_per_time_step property

iterations_per_time_step: Iterable[int]

Number of time samples at each time step in QPE.

get_num_iterations_per_time_step

get_num_iterations_per_time_step(time_step: int) -> int

Given a specific time step, return the number of time samples that need to be taken.

SignalGeneratorInterface

Bases: Protocol

Interface for QPE signal generators.

compute

compute(time_frequency_register: Qubits, signal_source_register: Qubits, config: QPEConfig, ctrl: Qubits | int = 0)

SignalSampler

Bases: ABC, Generic[SigReg]

Base class for signal samplers in QPE.

MAX_SAMPLE_SIZE class-attribute instance-attribute

MAX_SAMPLE_SIZE: int = 10000000

sample_signal

sample_signal(qpe_config: QPEConfig) -> Iterator[Callable[[SigReg, Qubits], None]]

SignalSourceStateFactory

Bases: Protocol

Allocates the register that holds the signal source state for QPE.

The factory receives a QPU so it can allocate the correct qubit register on that machine.

get_signal_source_state

get_signal_source_state(qpu: QPU) -> Qubits | None

TimeFrequencyTransformation

Bases: Protocol

Interface for time-frequency transformations in QPE.

compute

compute(time_frequency_register: Qubits, num_time_steps: int | None = None, ctrl: Qubits | None = None)

TimeSampler

Bases: ABC

Base class for time sampling in QPE.

sample_from

sample_from(time_frequency_register: Qubits, qpe_config: QPEConfig) -> Iterator[Qubits]

WindowFunction

Bases: Protocol

Interface for QPE window functions.

compute

compute(time_frequency_register: Qubits, num_time_steps: int | None = None, ctrl: Qubits | int = 0)

QPEBuilder dataclass

QPEBuilder(*, signal_source_state_factory: SignalSourceStateFactory, config: QPEConfig, window_function: WindowFunction | None = None, time_frequency_transformation: TimeFrequencyTransformation | None = None, frequency_resolver: FrequencyResolver | None = None, signal_sampler: SignalSampler | None = None, time_sampler: TimeSampler | None = None, signal_generator: SignalGeneratorInterface | None = None, frequency_interpreter: FrequencyInterpreter = default_frequency_interpreter)

Builder class for instantiating QPE programs.

Designed to make it easy to build QPE programs for common cases without sacrificing flexibility for advanced users.

The core idea is that this class serves as a single entry point for composing the different parts of a quantum phase estimation program, and provides functionality for using that program in different contexts. For example, using this class instantiated with a signal sampler and time sampler, you can define the quantum program for a particular instantiation of QPE, but you might want to do different things with it. For example, you might want to run it with the debug frequency resolver for validation, then run it with the sampling based frequency resolver to generate QREs (or run on a real QPU). Using this class, you can do both of those things with the same setup using the with_resolver functionality.

A deep dive into this class and the functionality it exposes is given in [TODO: ADD TUTORIAL FOR THIS IN DOCS PASS!]

Parameters:

Name Type Description Default
signal_source_state_factory SignalSourceStateFactory

Factory for the register that holds the signal source state (e.g. textbook QPE eigenstate).

required
config QPEConfig

Dataclass containing the configuration for the QPE.

required
window_function WindowFunction | None

Qubrick for applying a window function on the time/frequency register.

None
time_frequency_transformation TimeFrequencyTransformation | None

Qubrick for transforming between time and frequency domains.

None
frequency_resolver FrequencyResolver | None

Class for collating and analyzing the output from QPE shots.

None
signal_sampler SignalSampler | None

Class for sampling the signal at a single point in time.

None
time_sampler TimeSampler | None

Class for returning time samples throughout the QPE routine.

None
signal_generator SignalGeneratorInterface | None

Qubrick that implements the entire signal generation and sampling step of QPE. Not needed if signal_sampler and time_sampler are independently supplied.

None
frequency_interpreter FrequencyInterpreter

Callable that determines how a measured frequency should be interpreted (e.g. as an energy or simply as a phase multiplied by 2 pi).

default_frequency_interpreter

signal_source_state_factory instance-attribute

signal_source_state_factory: SignalSourceStateFactory

config instance-attribute

config: QPEConfig

window_function class-attribute instance-attribute

window_function: WindowFunction | None = None

time_frequency_transformation class-attribute instance-attribute

time_frequency_transformation: TimeFrequencyTransformation | None = None

frequency_resolver class-attribute instance-attribute

frequency_resolver: FrequencyResolver | None = None

signal_sampler class-attribute instance-attribute

signal_sampler: SignalSampler | None = None

time_sampler class-attribute instance-attribute

time_sampler: TimeSampler | None = None

signal_generator class-attribute instance-attribute

signal_generator: SignalGeneratorInterface | None = None

frequency_interpreter class-attribute instance-attribute

frequency_interpreter: FrequencyInterpreter = default_frequency_interpreter

qpe_subroutine property

qpe_subroutine: QPESubroutine

The QPE subroutine that forms the core of the QPE algorithm.

with_debug_resolver

with_debug_resolver() -> QPEBuilder

Return a QPEBuilder with a debug frequency resolver bound to it.

with_measurement_based_resolver

with_measurement_based_resolver(num_shots: int = 1) -> QPEBuilder

Return a QPEBuilder with a measurement-based frequency resolver bound to it.

with_resolver

with_resolver(frequency_resolver: FrequencyResolver) -> QPEBuilder

Return a QPEBuilder with a supplied frequency resolver bound to it.

build

build() -> QFTBasedQPE

Build the QPE program.

BitwiseQPEConfig dataclass

BitwiseQPEConfig(*, num_time_samples: int | None = None, bits_of_precision: int | None = None)

Bases: QPEConfig

Configuration for bitwise QPE programs.

num_time_samples class-attribute instance-attribute

num_time_samples: int | None = None

bits_of_precision class-attribute instance-attribute

bits_of_precision: int | None = None

iterations_per_time_step cached property

iterations_per_time_step

QFTBasedQPE

QFTBasedQPE(signal_source_state_factory: SignalSourceStateFactory, qpe_subroutine: QPESubroutine, frequency_resolver: FrequencyResolver | None = None, config: QPEConfig | None = None)

Quantum program for running QFT based QPE.

signal_source_state_factory instance-attribute

signal_source_state_factory: Incomplete = signal_source_state_factory

qpe_subroutine instance-attribute

qpe_subroutine: Incomplete = qpe_subroutine

frequency_resolver instance-attribute

frequency_resolver: Incomplete = frequency_resolver

config instance-attribute

config: Incomplete = config

pre_allocated_qubits instance-attribute

pre_allocated_qubits: Incomplete = None

QPESubroutine

QPESubroutine(signal_generator: SignalGeneratorInterface, window_function: WindowFunction, time_frequency_transformation: TimeFrequencyTransformation | None = None, **kwargs)

Bases: Qubrick

Qubrick for the core QPE subroutine.

signal_generator instance-attribute

signal_generator: Incomplete = signal_generator

window_function instance-attribute

window_function: Incomplete = window_function

time_frequency_transformation instance-attribute

time_frequency_transformation: Incomplete = time_frequency_transformation

compute

compute(time_frequency_reg: Qubits, signal_source_reg: Qubits, config: QPEConfig, ctrl: Qubits | int = 0)

DiagonalMatrixSignalSampler

DiagonalMatrixSignalSampler(matrix_diag: Iterable[complex])

Bases: SignalSampler

Signal sampler where the signal unitary is a classically-defined diagonal matrix.

matrix_diag instance-attribute

matrix_diag: Incomplete = np.asarray(matrix_diag)

FastForwardPhaseSignalSampler

FastForwardPhaseSignalSampler(angle: float | RotationAngle | None = None)

Bases: SignalSampler[Qubits]

Signal sampler that just applies phase gates directly onto the time-frequency register.

Note that for interface compatibility, this signal sampler accepts a signal_source_register, but it is ignored.

angle instance-attribute

angle: Incomplete = angle

GenericUnitarySignalSampler

GenericUnitarySignalSampler(op: Qubrick | GenericUnitaryCallable)

Bases: SignalSampler[Qubits]

This is an adaptor for handling generic, arbitrary unitaries for QPE.

The op is either a callable taking the signal source register and the time sample register and nothing else, or a Qubrick that already has that shape: its _compute needs a ctrl parameter for the time sample register, and at most one other parameter without a default, for the signal source register.

Any other unitary has to have its remaining arguments frozen first, with bind_generic_unitary_arguments. The generic_unitary preset does this for you.

While this is pretty generic and flexible, there are unitaries that can't easily be fit into this structure. The suggested API is to write a custom adaptor for whatever specific unitary you have in mind.

Note
  • For high performance applications, this is probably not the way to go.
  • We are not doing bidirectional phase kickback, as there is no generic way to do so.
  • This is only intended to support textbook (e.g. Nielsen and Chuang) QPE, with the exponentiation achieved by applying the unitary exponentially many times.

Parameters:

Name Type Description Default
op Qubrick | GenericUnitaryCallable

The operation to sample the signal from, taking the signal source register and the time sample register.

required

Raises:

Type Description
ValueError

if a Qubrick is supplied whose _compute still needs other arguments.

TypeError

if the op is neither a Qubrick nor callable.

fn instance-attribute

fn: Incomplete = bind_generic_unitary_arguments(op)

SamplingStrategy dataclass

SamplingStrategy(time_sampler: TimeSampler, signal_sampler: SignalSampler)

Bases: Generic[SigReg]

Utility class for combining time and signal sampling iterators.

Users should be able to take this class and use it without modification with any compatible time_sampler and signal_sampler.

time_sampler instance-attribute

time_sampler: TimeSampler

signal_sampler instance-attribute

signal_sampler: SignalSampler

sample_from

sample_from(time_frequency_register: Qubits, qpe_config: QPEConfig) -> Iterator[tuple[Qubits, Callable[[SigReg, Qubits], None]]]

SignalGenerator

SignalGenerator(sampling_strategy: SamplingStrategy[SigReg], **kwargs)

Bases: Qubrick, Generic[SigReg]

Qubrick for generating the signal for QPE.

sampling_strategy instance-attribute

sampling_strategy: Incomplete = sampling_strategy

compute

compute(time_frequency_register: Qubits, signal_source_register: SigReg, config: QPEConfig, ctrl: Qubits | int = 0)

ComputationalBasisStateFactory

ComputationalBasisStateFactory(num_qubits: int | Parameter, basis_state: int = 0)

Initialize a register holding the signal source state in computational basis \(|basis\rangle\).

num_qubits instance-attribute

num_qubits: Incomplete = num_qubits

basis_state instance-attribute

basis_state: Incomplete = basis_state

get_signal_source_state

get_signal_source_state(qpu: BaseQPU) -> BaseQubits

EmptyStateFactory

get_signal_source_state

get_signal_source_state(qpu: QPU) -> None

FourierBasisStateFactory

FourierBasisStateFactory(num_qubits: int, basis_state: int = 0)

Prepare the signal source state in a Fourier basis.

num_qubits instance-attribute

num_qubits: Incomplete = num_qubits

basis_state instance-attribute

basis_state: Incomplete = basis_state

get_signal_source_state

get_signal_source_state(qpu: QPU) -> BaseQubits

HadamardBasisStateFactory

HadamardBasisStateFactory(num_qubits: int, basis_state: int = 0)

Prepare the signal source state in a Hadamard basis.

num_qubits instance-attribute

num_qubits: Incomplete = num_qubits

basis_state instance-attribute

basis_state: Incomplete = basis_state

get_signal_source_state

get_signal_source_state(qpu: QPU) -> BaseQubits

PushStateVectorFactory

PushStateVectorFactory(state: Iterable[complex])

Initialize a register with the provided signal source state injected (state vector sim only).

state instance-attribute

state: Incomplete = state

get_signal_source_state

get_signal_source_state(qpu) -> BaseQubits

BitwiseTimeSampler

Bases: TimeSampler

Yields samples of the time-frequency register where each bit in the register is set.

Explicitly, this just means that we yield each qubit in the time-frequency register and use that to obtain samples for multiple times in superposition.

For example, yielding the qubit corresponding to the least significant bit will correspond to sampling all odd times simultaneously. Yielding the second least significant bit will correspond to sampling all times with a set bit in the second least significant position (i.e. 2 = 0b10, 3 = 0b11, 6 = 0b110, 7 = 0b111, etc.) and so on for the other bits.

Note

This is the "standard" sampling protocol that you see in, e.g. Nielsen and Chuang.

CosineWindowV2

CosineWindowV2(adder: Adder | None = None, **kwargs)

Bases: Qubrick

Cosine window from arxiv:2110.09590  ⧉.

adder instance-attribute

adder: Incomplete = adder

compute

compute(time_frequency_register: Qubits, num_time_steps: int | None = None, ctrl: Qubits | int = 0)

Executes circuit for implementing cosine window.

Parameters:

Name Type Description Default
time_frequency_register Qubits

Phase qubit register

required
num_time_steps int | None

The number of time steps to include in the window function

None
ctrl (Optional, int, Qubits)

Control register

0

RectWindowV2

RectWindowV2(name=None, **kwargs)

Bases: Qubrick

Rectangular/Dirichlet window. This is the default window function for the textbook QPE.

compute

compute(time_frequency_register: Qubits, num_time_steps: int | None = None, ctrl: Qubits | int = 0)

Executes circuit for implementing rectangular window.

Parameters:

Name Type Description Default
time_frequency_register Qubits

Phase qubit register

required
num_time_steps int | None

The number of time steps to include in the window function

None
ctrl (Optional, int, Qubits)

Control register

0

SineWindowPhaseCatalysisRUSV2

SineWindowPhaseCatalysisRUSV2(use_real_amps: bool = True, **kwargs)

Bases: SineWindowRUSV2

Qubrick for window state with the sine function over the amplitudes.

Prepared via phase catalyst register using repeat-until-success.

This window state can be used to achieve an optimal Holevo variance as outlined in Section II B. of arxiv:1805.03662  ⧉. See \(\Xi_m\) state.

The phase catalyst implementation is outlined in Appendix B of arxiv:1805.03662  ⧉

Note
  • This version uses repeat until success to avoid the need for amplitude amplification at the cost of the routine not being coherently invertible.
  • The state prepared here will be the same as SineWindowV2 up to a global phase.

compute

compute(time_frequency_register: Qubits, num_time_steps: int | None = None, ctrl: Qubits | int = 0)

Computes sine window function.

Parameters:

Name Type Description Default
time_frequency_register Qubits

register on which the sine window state is prepared

required
num_time_steps int | None

The number of time steps to include in the window function

None
ctrl Qubits

control qubit

0
Note
  • This version uses repeat until success to avoid the need for amplitude amplification at the cost of the routine not being coherently invertible.

SineWindowPhaseCatalysisV2

SineWindowPhaseCatalysisV2(use_real_amps: bool = True, fixed_point: bool = False, eps: float = 0.0001, **kwargs)

Bases: SineWindowV2

Qubrick for window state with the sine function over the amplitudes.

Prepared via phase catalyst register.

This window state can be used to achieve an optimal Holevo variance as outlined in Section II B. of arxiv:1805.03662  ⧉. See \(\Xi_m\) state.

The phase catalyst implementation is outlined in Appendix B of arxiv:1805.03662  ⧉

Note

The state prepared here will be the same as SineWindowV2 up to a global phase.

compute

compute(time_frequency_register: Qubits, num_time_steps: int | None = None, ctrl: Qubits | int = 0)

SineWindowQubitEfficientV2

SineWindowQubitEfficientV2(name=None, **kwargs)

Bases: Qubrick

Qubrick for window state with the sine function over the amplitudes using only two active qubits at a time.

This window state can be used to achieve an optimal Holevo variance with the construction of the circuit outlined in Section IV of arxiv:2303.12505 ⧉.

compute

compute(time_frequency_register: Qubits, num_time_steps: int | None = None, ctrl: Qubits | int = 0)

Computes sine window function.

Parameters:

Name Type Description Default
time_frequency_register Qubits

phase qubit register

required
num_time_steps int | None

The number of time steps to include in the window function

None
ctrl (Optional, int, Qubits)

control register

0

SineWindowRUSV2

SineWindowRUSV2(use_real_amps: bool = True, **kwargs)

Bases: Qubrick

Qubrick for window state with the sine function over the amplitudes.

This window state can be used to achieve an optimal Holevo variance as outlined in Section II B. of arxiv:1805.03662  ⧉. See \(\Xi_m\) state.

Note

The state prepared here has a global phase of pi. Additionally, if the user does not care about having purely real or purely imaginary values in the prepared state, the rz gates can be replaced by phase gates in which case the magnitudes will be the same as the expected state, but each amplitude will be rotated by some (global) phase.

use_real_amps instance-attribute

use_real_amps: Incomplete = use_real_amps

compute

compute(time_frequency_register: Qubits, num_time_steps: int | None = None, ctrl: Qubits | int = 0)

Computes sine window function.

Parameters:

Name Type Description Default
time_frequency_register Qubits

register on which the sine window state is prepared

required
num_time_steps int | None

The number of time steps to include in the window function

None
ctrl Qubits

control qubit

0
Note
  • This version uses repeat until success to avoid the need for amplitude amplification at the cost of the routine not being coherently invertible.

SineWindowV2

SineWindowV2(use_real_amps: bool = True, fixed_point: bool = False, eps: float = 0.0001, **kwargs)

Bases: Qubrick

Qubrick for window state with the sine function over the amplitudes.

This window state can be used to achieve an optimal Holevo variance as outlined in Section II B. of arxiv:1805.03662  ⧉. See \(\Xi_m\) state.

The state is prepared coherently via amplitude amplification on :class:_SineWindow.

Note

The state prepared here has a global phase of pi. Additionally, if the user does not care about having purely real or purely imaginary values in the prepared state, the rz gates can be replaced by phase gates in which case the magnitudes will be the same as the expected state, but each amplitude will be rotated by some (global) phase.

use_real_amps instance-attribute

use_real_amps: Incomplete = use_real_amps

fixed_point instance-attribute

fixed_point: Incomplete = fixed_point

eps instance-attribute

eps: Incomplete = eps

compute

compute(time_frequency_register: Qubits, num_time_steps: int | None = None, ctrl: Qubits | int = 0)

WindowEmulatorV2

WindowEmulatorV2(emulator_func: Callable[Concatenate[int, P], NDArray], emulator_function_options: dict[str, Any] | None = None, **kwargs)

Bases: Qubrick

Constructor for window emulator.

Note
  • Check the window utils module for emulator_func options.
  • Note that this Qubrick does not execute quantum operations; it directly touches the state vector and is not meant to run on a real QPU program.

Parameters:

Name Type Description Default
emulator_func callable

method for computing amplitudes of a window state

required
emulator_function_options dict[str, Any]

Extra keyword arguments for the emulator_func

None
**kwargs dict[str, Any]

Other arguments to pass to the init.

{}

emulator_func instance-attribute

emulator_func: Incomplete = emulator_func

emulator_func_kwargs instance-attribute

emulator_func_kwargs: Incomplete = emulator_function_options or {}

modifies_state_vector_directly instance-attribute

modifies_state_vector_directly: bool = True

uncompute

uncompute() -> None

Override the default uncomputation.

compute

compute(time_frequency_register: Qubits, num_time_steps: int | None = None, ctrl: Qubits | int = 0)

Compute amplitudes of taper state.

Parameters:

Name Type Description Default
time_frequency_register Qubits

Phase qubit register

required
num_time_steps int | None

The number of time steps to include in the window function

None
ctrl (Optional, int, Qubits)

Control register

0
Note
  • Use emulators for a reasonably small number of phase qubits!
  • The control version is not currently implemented

WindowStatePrepV2

WindowStatePrepV2(amps, state_prep: StatePreparation | None = None, **kwargs)

Bases: Qubrick

General class for simulating window state via state prep.

Parameters:

Name Type Description Default
amps ndarray

Amplitudes for window state.

required
state_prep Qubrick

Qubrick to implement the state preparation for the window function.

None
**kwargs dict[str, Any]

Other arguments to pass to the init.

{}

amps instance-attribute

amps: Incomplete = amps

state_prep instance-attribute

state_prep: Incomplete = ArbitraryStatePrep(amps_rot, phases_rot)

prep_data instance-attribute

prep_data: Incomplete = StatePrepData(self.amps, 1e-06)

compute

compute(time_frequency_register: Qubits, num_time_steps: int | None = None, ctrl: Qubits | int = 0)

Executes circuit for preparing window state.

Parameters:

Name Type Description Default
time_frequency_register Qubits

Phase qubit register.

required
num_time_steps int | None

The number of time steps to include in the window function

None
ctrl (Optional, int, Qubits)

Control register.

0

default_frequency_interpreter

default_frequency_interpreter(phase: float) -> float

Interprets the phase as an undifferentiated frequency in the range [0, 2pi].

Assumes the phase is represented in the range [0, 1] rather than [-1, 1].

bind_generic_unitary_arguments

bind_generic_unitary_arguments(op: Qubrick | Callable, *, skip_params: Iterable[str] = (), **kwargs: Any) -> GenericUnitaryCallable

Adapter for the GenericUnitarySignalSampler that allows for arbitrary functions and Qubricks to be used.

Takes a function or a Qubrick with arbitrary signature and returns a new function with two unbound parameters of type BaseQubits, one corresponding to the signal source register, one corresponding to the time sample register. The unbound parameters will be positional only in the returned function.

Note that any return from the function will not be accessible. Functions that have return values may still be used, but they will be treated as though they do not return anything.

This is essentially functools.partial in combination with functools.Placeholder to allow for unbound key word arguments to be supplied to the partial function positionally. Since functools.Placeholder was only added in Python 3.14, we have to use our own adapter. The logic in this function can thus be significantly simplified once support for Python < 3.14 is dropped.

Parameters:

Name Type Description Default
op Qubrick | Callable

the function or Qubrick we want to bind arguments to.

required
skip_params Iterable[str]

the names of any arguments we want to skip in the binding (mostly for interaction with class methods).

()
**kwargs Any

keyword arguments to bind to the op.

{}