qsengine 1.1.1

Release notes

Version 1.1.1

Two fixes. Code that worked in 1.1.0 runs unchanged.

Fixes

  • measure() and if_test() accept NumPy integers, such as an element of np.arange(3), for qubits, classical bits and the condition value, as gate methods already did. Before, they raised TypeError.
  • unitary() records the nearest exactly unitary matrix in place of one that is unitary only to within 1e-9, for example a matrix computed with floating-point arithmetic. Before, the small error was kept, so each such gate changed the state's norm slightly and long circuits drifted. See Your own gates.

Documentation

  • The backends page explains when results are 32-bit: under the default auto from 14 qubits on a machine with a GPU, and for mid-circuit measurements on the GPU.
  • The benchmarks state their caveats: 32-bit GPU against 64-bit Aer, Aer's per-call overhead below 14 qubits, and a single benchmark circuit.

Version 1.1.0

Mid-circuit measurement, classical bits and expectation values. Allows teleportation, error correction, VQE and QAOA.

Measurement and classical bits

  • QuantumCircuit(num_qubits, num_clbits) gives a circuit classical bits.
  • measure(qubit, clbit) measures a qubit at any point, and reset(qubit) returns it to |0⟩.
  • Gates inside with qc.if_test(clbits, value): run only when the classical bits match.
  • When a circuit measures, run() counts its classical bits. A circuit that measures part-way is simulated once per shot. One that only measures at the end still runs once and is sampled, as fast as before.
  • The GPU backend measures single qubits with a new reduction shader. Each mid-circuit measurement waits for the GPU, so auto keeps such circuits on the CPU below 20 qubits.

Expectation values

  • expectation("ZZI") returns the expectation value of a Pauli string; expectation([...]) returns one for each string, from a single simulation.

Other changes

  • print(qc) draws measurements, resets and conditions. A swap now counts as one operation in len(qc), not three.
  • Recording a gate is about 2.3 times faster than in 1.0.2.
  • The Python package is now plain Python around a compiled core (qsengine._core). import qsengine works as before.
  • Release builds use link-time optimisation, which keeps CPU simulation speed steady from build to build.

Version 1.0.2

Circuit drawings, and two fixes for silent failures.

New

Fixes

  • An angle that is NaN or infinite, for example qc.rx(0, float("nan")), now raises ValueError. Before, it was accepted and run() returned all-zero counts.
  • A register too large for memory now raises MemoryError instead of closing Python. On the CPU backend statevector() also no longer copies the state twice, so it needs a third of the memory it needed before.

Version 1.0.1

More gates, and exact results as NumPy arrays.

Gates

  • New single-qubit gates: S dagger sdg, T dagger tdg, phase p and the general u.
  • New gates on several qubits: controlled phase cp, controlled RZ crz, swap and the Toffoli gate ccx.
  • unitary(matrix, target, controls=[]) applies any 2 by 2 unitary, optionally controlled, and rejects matrices that are not unitary.

Results

  • statevector() and probabilities() return NumPy arrays (complex128 and float64) instead of lists. They are built straight from Rust memory, which is much faster for large circuits.
  • NumPy is now installed with qsengine.

Code that indexes, loops over or sums the results works as before. Code that needs a real list, for example result + [0.0] or json.dumps(result), needs .tolist() first.

Version 1.0.0

The first release.

Simulation

  • State-vector simulation of up to 30 qubits.
  • Eleven gates: X, Y, Z, H, S, T, RX, RY, RZ, CNOT and controlled Z.
  • Single-qubit gate fusion: consecutive gates on one qubit cost one pass over the state.
  • run() for measurement counts, probabilities() and statevector() for exact results.
  • Repeatable counts with seed.

Backends

  • A CPU backend in 64-bit precision that uses every core.
  • A GPU backend in 32-bit precision for NVIDIA, AMD, Intel and Apple GPUs, through Vulkan, DirectX 12 or Metal.
  • backend="auto", the default, uses the CPU below 14 qubits and the GPU from 14, and falls back to the CPU when no GPU is available.

Packaging

  • One wheel per platform for CPython 3.9 and newer.
  • Type hints for editors and type checkers.
  • Released under the MIT licence.

Known limits

  • No SWAP gate and no mid-circuit measurement yet.
  • Above about 17 qubits the CPU backend is slower than Qiskit Aer; the GPU backend is not.