Python

qblaze

class qblaze.Simulator

Create a new simulator object.

The simulator supports Simulator.max_qubit_count() qubits, which are initially all 0.

Example:

>>> from qblaze import Simulator
>>> sim = Simulator()

Read the amplitudes of the \(\ket{00\ldots}\) and \(\ket{10\ldots}\) basis states:

>>> state = numpy.zeros(2**1, numpy.complex128)
>>> sim.copy_amplitudes(state)
>>> state
array([1.+0.j, 0.+0.j])

Apply a Hadamard gate to qubit 0, and then a controlled X gate to qubit 1:

>>> sim.h(0)
>>> sim.cx(0, 1)

Read the amplitudes of the basis states \(\ket{ij0\dots}\), where \(i, j \in \{0, 1\}\):

>>> state = numpy.zeros(2**2, numpy.complex128)
>>> sim.copy_amplitudes(state)
>>> state
array([0.70710678+0.j, 0.        +0.j, 0.        +0.j, 0.70710678+0.j])

Measure qubit 1:

>>> sim.measure(1, 11853927852089066602)
True

Read the amplitudes again:

>>> state = numpy.zeros(2**2, numpy.complex128)
>>> sim.copy_amplitudes(state)
>>> state
array([0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j])
classmethod max_qubit_count() int

Return the maxumum supported qubit count.

Example:

>>> Simulator.max_qubit_count()
3968
flush() None

Apply all gates in the gate queue.

Example:

>>> sim.flush()
dump() None

Dump the state vector to stderr.

x(target: int, /) None

Apply an X gate.

Equivalent to sim.u3(target, math.pi, math.pi, 0).

Example:

>>> sim.x(0)
y(target: int, /) None

Apply a Y gate.

Equivalent to sim.u3(target, math.pi, 0, 0).

Example:

>>> sim.y(0)
z(target: int, /) None

Apply a Z gate.

Equivalent to sim.u3(target, 0, math.pi, 0).

Example:

>>> sim.z(0)
h(target: int, /) None

Apply a Hadamard gate.

Equivalent to sim.u3(target, math.pi / 2, 0, math.pi).

Example:

>>> sim.h(0)
s(target: int, /) None

Apply an S gate.

Equivalent to sim.u3(target, 0, math.pi / 2, 0).

Example:

>>> sim.s(0)
sdg(target: int, /) None

Apply an inverse S gate.

Equivalent to sim.u3(target, 0, -math.pi / 2, 0).

Example:

>>> sim.sdg(0)
t(target: int, /) None

Apply a T gate.

Equivalent to sim.u3(target, 0, math.pi / 4, 0).

Example:

>>> sim.t(0)
tdg(target: int, /) None

Apply an inverse T gate.

Equivalent to sim.u3(target, 0, -math.pi / 4, 0).

Example:

>>> sim.tdg(0)
rx(target: int, theta: float, /) None

Apply a rotation about the X axis.

Equivalent to sim.u3(target, theta, -math.pi / 2, math.pi / 2).

Example:

>>> sim.rx(0, math.pi / 2)
ry(target: int, theta: float, /) None

Apply a rotation about the Y axis.

Equivalent to sim.u3(target, theta, 0, 0).

Example:

>>> sim.ry(0, math.pi / 2)
rz(target: int, theta: float, /) None

Apply a rotation about the Z axis.

Equivalent to sim.u3(target, 0, theta, 0).

Example:

>>> sim.rz(0, math.pi / 2)
u3(target: int, theta: float, phi: float, lam: float, /) None

Apply a general single-qubit gate.

The definition is equivalent up to global phase to the OpenQASM U gate:

\[\begin{split}U3(\theta, \phi, \lambda) = \left( \begin{matrix} \cos \frac{\theta}{2} & -e^{i \lambda} \sin \frac{\theta}{2} \\ e^{i \phi} \sin \frac{\theta}{2} & e^{i(\phi + \lambda)} \cos \frac{\theta}{2} \end{matrix} \right)\end{split}\]

Example:

>>> sim.u3(0, math.pi / 2, math.pi / 2, math.pi / 2)
cx(control: int, target: int, /) None

Apply a controlled X gate.

Example:

>>> sim.cx(0, 1)
ccx(control1: int, control2: int, target: int, /) None

Apply a doubly-controlled X gate.

Example:

>>> sim.ccx(0, 1, 2)
mcx(controls: list[tuple[int, bool]], target: int, /) None

Apply a multiply-controlled X gate.

Each of the controls is a pair of (qubit, value). The gate is applied to all basis states where the controls have the desired values.

Example:

>>> sim.mcx([(0, True), (1, True), (2, True)], 3)
swap(target1: int, target2: int, /) None

Apply a swap gate.

Example:

>>> sim.swap(0, 1)
cswap(control: int, target1: int, target2: int, /) None

Apply a controlled swap gate.

Example:

>>> sim.cswap(0, 1, 2)
mcswap(controls: list[tuple[int, bool]], target1: int, target2: int, /) None

Apply a multiply-controlled swap gate.

Each of the controls is a pair of (qubit, value). The gate is applied to all basis states where the controls have the desired values.

Example:

>>> sim.mcswap([(0, True), (1, True), (2, True)], 3, 4)
cz(control: int, target: int, /) None

Apply a controlled Z gate.

Example:

>>> sim.cz(0, 1)
mcphase(controls: list[tuple[int, bool]], theta: float, /) None

Apply a multi-controlled global phase gate.

Each of the controls is a pair of (qubit, value). The gate is applied to all basis states where the controls have the desired values.

Example: The gate sim.cz(0, 1) is equivalent to

>>> sim.mcphase([(0, True), (1, True)], math.pi)
measure(target: int, random: int | None = None, /) bool

Measure a single qubit. Return the outcome.

The state vector is collapsed.

The parameter random must be a random 64-bit integer (e.g., random.getrandbits(64)).

Example:

>>> sim.h(0)
>>> sim.measure(0, 2375645456254334209)
False
measure_ext(target: int, random: int | None = None, /) tuple[bool, float, float]

Similar to measure, but also returns the probabilities.

Example:

>>> sim.h(0)
>>> sim.measure_ext(0, 2375645456254334209)
(False, 0.5, 0.5)
qubit_probs(target: int, /) tuple[float, float]

Compute the measurement probabilities for the target qubit without measuring it.

Example:

>>> sim.qubit_probs(0)
(1.0, 0.0)
>>> sim.h(0)
>>> sim.qubit_probs(0)
(0.5, 0.5)
copy_amplitudes(buffer: Buffer, /) None

Copy the state vector amplitudes to buffer.

The amplitude of the ‘i’th state vector is stored at position ‘i’, where the ‘k’th bit of ‘i’ equals the basis value of the ‘k’th qubit.

The buffer must be one of the following:

  • A single-dimensional array of complex double-precision floating-point numbers.

  • A single-dimensional array of double-precision floating-point numbers of even length. Even-indexed elements will store the real parts and odd-indexed elements will store the imaginary parts.

  • A C-contiguous two-dimensional array of double-precision floating-point numbers with shape (n, 2). Elements buf[i][0] will store the real part and buf[i][1] will store the imaginary part.

Example:

>>> for i in range(3): sim.h(i)
>>> state = numpy.zeros(2**3, numpy.complex128)
>>> sim.copy_amplitudes(state)
>>> state
array([0.35355339+0.j, 0.35355339+0.j, 0.35355339+0.j, 0.35355339+0.j,
       0.35355339+0.j, 0.35355339+0.j, 0.35355339+0.j, 0.35355339+0.j])
clone() Simulator

Clone the quantum state.

A new independent simulator is returned with a copy of the state of this one.

Example:

>>> sim.h(0)
>>> sim2 = sim.clone()
>>> sim2.measure_ext(0, 15980756942077321109)
(True, 0.5, 0.5)
>>> sim.measure_ext(0, 1933827847985506032)
(False, 0.5, 0.5)
>>> sim3 = sim.clone()
>>> sim3.measure_ext(0, 15980756942077321109)
(False, 1.0, 0.0)
class qblaze.Config

Simulator configuration options.

Examples:

>>> sim = Simulator(dump_config=False)
>>> sim = Simulator(qubit_count=1)
>>> sim = Simulator(thread_count=16)
>>> sim = Simulator(chunk_size=128*2**10)
>>> sim = Simulator(multithreading_threshold=64*2**10)
>>> sim = Simulator(work_item_min_size=1*2**10)
>>> sim = Simulator(work_item_max_size=16*2**20)
dump_config: bool

Dumps the simulator configuration to stderr.

Default: no.

qubit_count: int

Hint about how many qubits will be used.

This option determines how many bits are used to represent qubit indices. The representation is changed automatically when a qubit with a higher index is used. The maximum supported qubit count is returned by by Simulator.max_qubit_count().

Default: 1.

thread_count: int

The number of threads in the thread pool.

Default: nproc.

chunk_size: int

The chunk size for processing superposition-free gates (in bytes).

If set to SIZE_MAX, then a single chunk is used.

Default: smallest L2 cache size.

multithreading_threshold: int

The state vector size after which multiple threads will be used (in bytes).

Default: 64 KiB.

work_item_min_size: int

The minimum size of a thread work item (in bytes).

Use to ensure that the work per item is larger that the communication overhead.

Default: 1 KiB.

work_item_max_size: int

The maximum size of a thread work item (in bytes).

Use to ensure that there are enough items for threads that finish early.

Default: 16 MiB.

qblaze.qiskit

qblaze.qiskit.run_circuit(sim: Simulator, qc: QuantumCircuit, /, rng: Random | None = None, *, force_clbits: dict[Clbit, bool] = {}, respect_barriers: bool = False) tuple[dict[Clbit, bool], list[ndarray[tuple[int, ...], dtype[complex128]]]]

Run a circuit on the given simulator.

force_clbits can be used to force the outcomes of measurements associated with particular classical bits. Simulation will fail if a force outcome has zero (or very close to zero) probability.

Returns (clbits, statevectors), where clbits is the value of all classical bits at the end of the simulation, and statevectors is the list of all statevectors at save_statevector instructions.

Example:

>>> import qiskit
>>> import qiskit_aer
>>> from qblaze.qiskit import run_circuit
>>>
>>> def make_circuit():
...     circ = qiskit.QuantumCircuit(2, 1)
...     circ.h(0)
...     circ.save_statevector()
...     circ.cx(0, 1)
...     circ.measure(1, 0)
...     circ.save_statevector()
...     return circ
>>>
>>> circ = make_circuit()
>>> sim = Simulator()
>>> rng = random.Random(42)
>>>
>>> (clbits, [sv1, sv2]) = run_circuit(sim, circ, rng=rng)
>>>
>>> [complex(v) for v in sv1]
[(0.7071067812+0j), (0.7071067812+0j), 0j, 0j]
>>> clbits[circ.clbits[0]]
False
>>> [complex(v) for v in sv2]
[(1+0j), 0j, 0j, 0j]
class qblaze.qiskit.Backend(provider: Any = None)

Implements qiskit.providers.BackendV2.

property max_circuits: int

Returns 1.

property target: Target

Returns a qiskit.transpiler.Target corresponding to the gates natively supported by qblaze.

run(run_input: Any, **options: Any) Job

Simulates the given circuit.

class qblaze.qiskit.Job(backend: Backend, quantum_circuits: list[QuantumCircuit], options: dict[str, Any])

Implements qiskit.providers.JobV1.

status() JobStatus

Returns the status of the job.

result() Result

Returns the result of the job.

submit() None

Runs the job.