Registers#
QCDL supports integer and fixed-point registers you can use for simple classical expressions (e.g., multiplication and XOR), and comparisons. The Classical Registers & Arithmetic section introduces registers.
- class Array(modules: Sequence[QCDLModule], initial_value: Any, name: str | None = None, dtype: str = 'int', master_kwargs: dict[str, Any] | None = None, alias: bool | str = False, ignore_reallocation: bool = False, signed: bool = True, scope_id: int | None = None)[source]#
Bases:
RegisterInitializerMixinAn array of contiguous addresses in memory.
You can use an array to access a register, such as the
FixedPointRegisterandRegisterclass registers, based on its index in a list.Warning
The compiler does not check bounds for your access. Use with care.
- Parameters:
modules – Modules, typically qubits, associated with the register.
initial_value – Initial values. An integer initializes a list of zeros of that length. A list or NumPy array sets a number of values that depends on its length.
name – Optional name for the register.
dtype –
Type of registers in the array. Defaults to “int”. Supported values are:
”int”: Integer.
”float”: Floating point.
master_kwargs – Propagate this to the master instruction. This parameter is intended for use by developers of QCDL.
alias – Set to True if you are aliasing an existing register, and for type punning reuse that register’s name in the
nameparameter. Aliased registers are not reinitialized.ignore_reallocation – If True, the compiler does not reallocate if already allocated (and does not raise an exception).
Note
The assignment operator is not
<<=for arrays.Examples
This example uses an array to access and set register values.
import numpy as np from dwave.gate.qcdl import qcdl, Scope from dwave.gate.qcdl.operations import measure @qcdl(2) def array_example(q0, q1): # Create an array of 10 integers, with initial values 0, 1, 2, 3, ... arr = Scope.Array(np.arange(10)) # Create registers sc = Scope(q0, q1) r1 = sc.Register(3) r2 = scope.Register() # r gets the value of the array at the index of the current value of r1 r <<= arr[r1] # Set the value of the array at index r1 to 0 arr[r1] = 0 # Note the assignment operator is not <<= qcdl_program = array_example()
- class ExpressionAggregator(modules: Sequence[QCDLModule], master_kwargs: dict[str, Any] | None = None, scope_id: int | None = None)[source]#
Bases:
objectCombine several expressions into one CPU program.
This class is intended for use by developers of QCDL and advanced users.
This class can reduce the number of QCDL instructions. Its primary use is for GOF category of QPU registers (see the
Outputclass), where the number of instruction set architecture (ISA) instructions must be controlled.- Parameters:
modules – Module, typically qubits.
master_kwargs – Forwarded to the master instruction that is emitted. Defaults to None. This parameter is intended for use by developers of QCDL.
Examples
from dwave.gate.qcdl import qcdl, Scope from dwave.gate.qcdl.registers import ExpressionAggregator @qcdl(2) def aggregate_example(q0, q1): sc = Scope(q0, q1) r0 = sc.Register(name="r0") r1 = sc.Register(name="r1") with ExpressionAggregator(sc.qcdl_modules): # These two instructions are aggregated into one QCDL instruction r0 <<= 1 r1 <<= r0 qcdl_program = aggregate_example()
- class FixedPointRegister(modules: Sequence[QCDLModule], initial_value: float = 0.0, name: str | None = None, master_kwargs: dict[str, Any] | None = None, alias: bool | str = False, ignore_reallocation: bool = False, scope_id: int | None = None)[source]#
Bases:
NumberOpsMixin,AssignmentOpsMixin,RegisterInitializerMixin,TargetFixed-point register.
Supports a range of values between -2, inclusive, to 2, non-inclusive (\([-2,2)\) or \([-2, 2 - 2^{-16}]\)). This is Q2.16 in Q notation: the register’s 18 bits use 1 bit for the sign, 1 for a digit to the left of the decimal, and 16 bits to the right of the decimal, giving a resolution of \(2^{-16}\).
Note
The dual-rail simulator in the Leap service supports floating-point numbers for this register.
The Classical Registers & Arithmetic section introduces registers. Use the
<<=(in-place left shift) operator to assign a value to a register. See the mixin classes for supported operations and theRegisterclass on using thealiasargument for type punning.- Parameters:
modules – Modules where this register is created, typically representing one or more qubits. Typically, you create a register from a
Scopeobject, which handles this parameter for you.initial_value – Initial value. Defaults to 0.0.
name – Name for this register; useful for troubleshooting. If None, a name is generated. See the
aliasparameter for type punning.master_kwargs – Propagate this to the master instruction. This parameter is intended for use by developers of QCDL.
alias – Set to True if you are aliasing an existing register, and for type punning reuse that register’s name in the
nameparameter. Aliased registers are not reinitialized.ignore_reallocation – If True, the compiler does not reallocate if already allocated (and does not raise an exception).
scope_id – Identity of the
Scopethis register is derived from. TheFixedPointRegister()method sets this value when you create a register from aScopeinstance.
Examples
This is a typical example of instantiating a register from a
Scopeobject for the relevant qubits.from dwave.gate.qcdl import qcdl, Scope from dwave.gate.qcdl.operations import measure @qcdl(2) def create_fixed_reg(q0, q1): sc = Scope(q0, q1) r0 = sc.Register(name="r0") r1 = sc.FixedPointRegister(name="r1") r1 <<= 1.274 q0.h() measure(q0, register=r0) qcdl_program = create_fixed_reg()
See additional examples in the
Registerclass.See also
- class Output(modules: Sequence[QCDLModule], name: str | None = None, category: str | None = None, master_kwargs: dict[str, Any] | None = None, scope_id: int | None = None)[source]#
Bases:
TargetOutputs for writing.
This class is intended for use by developers of QCDL and advanced users.
You can write data to these outputs but not read from them. For usage, see the
append_table_row()method.- Parameters:
modules – Modules, typically qubits.
name – Reserve a specific name. Defaults to None.
category –
Category of registers. Defaults to None. Supported values are:
DYN
GOF
master_kwargs – Propagate this to the master instruction. This parameter is intended for use by developers of QCDL.
- class Register(modules: Sequence[QCDLModule], initial_value: int = 0, name: str | None = None, master_kwargs: dict[str, Any] | None = None, alias: bool | str = False, ignore_reallocation: bool = False, scope_id: int | None = None)[source]#
Bases:
IntegerOpsMixin,AssignmentOpsMixin,RegisterInitializerMixin,Target18-bit signed integer register.
Supports a range of values between -131,072 and 131,071 (\([-2^{17}, 2^{17-1}]\))).
Note
The dual-rail simulator in the Leap service supports floating-point numbers for this register.
The Classical Registers & Arithmetic section introduces registers. Use the
<<=(in-place left shift) operator to assign a value to a register. See the mixin classes for supported operations.Aliasing
You can alias registers, meaning that two registers point to the same memory address. This can be useful if, for example, you want to use the
Registerinterface to manipulate memory already allocated by another register; a specialized use case is using bitwise operators on aFixedPointRegister. This is supported with type punning, as shown in the example below.- Parameters:
modules – Modules where this register is created, typically representing one or more qubits. Typically, you create a register from a
Scopeobject, which handles this parameter for you.initial_value – Initial value. Defaults to 0.
name – Name for this register; useful for troubleshooting. If None, a name is generated. See the
aliasparameter for type punning.master_kwargs – Propagate this to the master instruction. This parameter is intended for use by developers of QCDL.
alias – Set to True if you are aliasing an existing register, and for type punning reuse that register’s name in the
nameparameter. Aliased registers are not reinitialized.ignore_reallocation – If True, the compiler does not reallocate if already allocated (and does not raise an exception).
scope_id – Identity of the
Scopethis register is derived from. TheRegister()method sets this value when you create a register from aScopeinstance.
Examples
This example shows operations between registers.
from dwave.gate.qcdl import qcdl, Scope @qcdl(2) def register_ops(q0, q1): sc = Scope(q0, q1) r1 = sc.Register(initial_value=2, name="r1") # name for debugging r2 = sc.Register() r2 <<= 1 # set r2 to 1 r2 <<= 2 * r1 # set r2 to 2*r1 qcdl_program = register_ops()
This example demonstrates type punning.
from dwave.gate.qcdl import qcdl, Scope @qcdl(2) def punning(q0, q1): sc = Scope(q0, q1) fr = sc.FixedPointRegister(initial_value=1, name="fr") ir = sc.Register(name="fr", alias=True) ir += ir & 4 qcdl_program = punning()
This example instantiates a register directly for qubit
q0and sets itsscope_idto aScopethat includes that qubit.from dwave.gate.qcdl import qcdl, Register, Scope @qcdl(2) def direct(q0, q1): sc = Scope(q0, q1) r1 = Register(q0, initial_value=2, name="r1", scope_id=sc.scope_id) qcdl_program = direct()
See also
- validate_name(name: str) None[source]#
Check if the specified string is valid as a name for a register.
- Parameters:
name – Proposed register name.
- Raises:
QCDLUserError – If the string is not supported for a register name.
Examples
from dwave.gate.qcdl.registers import validate_name validate_name("r0")
- validate_value(value: Any, dtype: str | type, signed: bool = True) None[source]#
Check if the specified value can be assigned to a register.
Note
This is a convenience function you can use from Python to check your QCDL program.
- Raises:
QCDLUserError – If the assignment is not supported.
- Parameters:
value – Value or array of values to validate.
dtype – int or float.
signed – Only integers may be unsigned.
Examples
from dwave.gate.qcdl.registers import validate_value validate_value(1.5, dtype=float)
Mixin Classes#
- class IntegerOpsMixin[source]#
Supported operations for integers.
Used by the
Registerclass.\(<<=\) (assignment)
\(==, !=, <, >, <=, >=\)
\(+, -, *\)
\(\&, |\), ^ (bitwise operations)
right shift
- class NumberOpsMixin[source]#
Supported operations for floats.
Used by the
FixedPointRegisterclass.\(<<=\) (assignment)
\(==, !=, <, >, <=, >=\) (equality)
\(+, -, *\) (standard arithmetic)