Open ajavadia opened 4 years ago
How does this algorithm fundamentally work? Can you point me to some resources @ajavadia ? Also, has there been any progress in this project so far?
Updated 2nd part of the original example eliminating deprecated u3
:
circ = QuantumCircuit(4)
circ.u(np.pi/2, -np.pi/2, 3*np.pi/2, 0)
circ.u(np.pi/2, -np.pi/2, np.pi, 1)
circ.u(np.pi/2, 0, np.pi, 2)
circ.u(np.pi, -np.pi/2, np.pi/2, 3)
Furthermore, the first example transpiled generates U3 gates (deprecated)
Hi @ajavadia. The open-source library qclib (https://github.com/qclib/qclib) has a state preparation (called Low-Rank State Preparation or LRSP) that can adjust the complexity (depth and number of CNOTs) of the circuit to the degree of state entanglement, so it does not use CNOTs for the initialization of a product state (no entanglement).
import numpy as np
from qiskit.circuit import QuantumCircuit
from qiskit.compiler import transpile
from qclib.state_preparation import LowRankInitialize
v = np.sqrt(1/8) *np.array([0, 0, 0, 0, 0, 0, 0, 0, 1, -1j, -1j, -1, 1, -1j, -1j, -1])
circ = QuantumCircuit(4)
LowRankInitialize.initialize(circ, v)
unrolled_circ = transpile(circ, basis_gates=['cx', 'u3'], optimization_level=3)
unrolled_circ.draw('mpl')
The paper "Approximated quantum-state preparation with entanglement dependent complexity" (https://arxiv.org/abs/2111.03132) describes the algorithm. It produces more efficient circuits (shallower and with fewer CNOTs) than isometry decomposition, as demonstrated by the following example.
import numpy as np
from IPython.display import Markdown
from qiskit import QuantumCircuit, QuantumRegister, transpile
from qclib.state_preparation import LowRankInitialize
n_qubits = 10
state = np.random.rand(2 ** n_qubits) + np.random.rand(2 ** n_qubits) * 1j
state = state/np.linalg.norm(state)
# qclib low-rank
circuit_low = QuantumCircuit(n_qubits)
LowRankInitialize.initialize(circuit_low, state)
# qiskit multiplexor
circuit_mul = QuantumCircuit(n_qubits)
circuit_mul.initialize(state)
# qiskit isometry
reg_iso = QuantumRegister(n_qubits)
circuit_iso = QuantumCircuit(reg_iso)
circuit_iso.isometry(state, q_input=[], q_ancillas_for_output=reg_iso)
# print results
circuits = [('low-rank', 'qclib', circuit_low), ('isometry', 'qiskit', circuit_iso), ('multiplexor', 'qiskit', circuit_mul)]
table = '| method | lib | cnots | depth |\n'
table += '| --- | --- |:---:|:---:|\n'
for label, lib, circuit in circuits:
transpiled = transpile(circuit, basis_gates=['u', 'cx'], optimization_level=0)
depth = transpiled.depth()
cx = transpiled.count_ops()['cx'] if 'cx' in transpiled.count_ops() else 0
table += f'| {label} | {lib} | {cx} | {depth} |\n'
Markdown(table)
method | lib | cnots | depth |
---|---|---|---|
low-rank | qclib | 913 | 1042 |
isometry | qiskit | 1013 | 4055 |
multiplexor | qiskit | 2026 | 4064 |
Please let me know if you need additional information.
Kind regards.
Qiskit's isometry synthesis algorithm can be used to synthesize state preparation circuits.
However for some product states it it not able to find a 0-CNOT circuit.
Example:
Yields:
However this state is synthesizable using only single-qubit gates:
Note: the actual synthesis algorithm produces an 11-CNOT circuit but optimization_level=3 was able to bring this cost down to 3 CNOTs.