Skip to content

Commit 0c3bd30

Browse files
committed
Cache 2q clifford integer table of the tensor product of 1q clifford integers in a file
1 parent 38e4636 commit 0c3bd30

File tree

4 files changed

+25
-15
lines changed

4 files changed

+25
-15
lines changed

qiskit_experiments/library/randomized_benchmarking/clifford_utils.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
_valid_sparse_indices = _clifford_compose_2q_data["valid_sparse_indices"]
4747
# map a clifford number to the index of _CLIFFORD_COMPOSE_2Q_DENSE
4848
_clifford_num_to_dense_index = {idx: ii for ii, idx in enumerate(_valid_sparse_indices)}
49+
_CLIFFORD_TENSOR_1Q = np.load(f"{_DATA_FOLDER}/clifford_tensor_1q.npz")["table"]
4950

5051
# Transpilation utilities
5152
def _transpile_clifford_circuit(
@@ -740,12 +741,6 @@ def _layer_indices_from_num(num: Integral) -> Tuple[Integral, Integral, Integral
740741
return idx0, idx1, idx2
741742

742743

743-
@lru_cache(maxsize=24 * 24)
744-
def _product_1q_nums(first: Integral, second: Integral) -> Integral:
745-
"""Return the 2-qubit Clifford integer that represents the product of 1-qubit Cliffords."""
746-
qc0 = CliffordUtils.clifford_1_qubit_circuit(first)
747-
qc1 = CliffordUtils.clifford_1_qubit_circuit(second)
748-
qc = QuantumCircuit(2)
749-
qc.compose(qc0, qubits=(0,), inplace=True)
750-
qc.compose(qc1, qubits=(1,), inplace=True)
751-
return num_from_2q_circuit(qc)
744+
def _tensor_1q_nums(first: Integral, second: Integral) -> Integral:
745+
"""Return the 2-qubit Clifford integer that is the tensor product of 1-qubit Cliffords."""
746+
return _CLIFFORD_TENSOR_1Q[first, second]
1.32 KB
Binary file not shown.

qiskit_experiments/library/randomized_benchmarking/data/generate_clifford_data.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def _hash_cliff(cliff):
5959

6060

6161
def gen_clifford_inverse_1q():
62-
"""Generate table data for integer 1Q Clifford inversion"""
62+
"""Generate data for integer 1Q Clifford inversion table"""
6363
invs = np.empty(NUM_CLIFFORD_1Q, dtype=int)
6464
for i, cliff_i in _CLIFF_1Q.items():
6565
invs[i] = _TO_INT_1Q[_hash_cliff(cliff_i.adjoint())]
@@ -68,7 +68,7 @@ def gen_clifford_inverse_1q():
6868

6969

7070
def gen_clifford_compose_1q():
71-
"""Generate table data for integer 1Q Clifford composition."""
71+
"""Generate data for integer 1Q Clifford composition table"""
7272
products = np.empty((NUM_CLIFFORD_1Q, NUM_CLIFFORD_1Q), dtype=int)
7373
for i, cliff_i in _CLIFF_1Q.items():
7474
for j, cliff_j in _CLIFF_1Q.items():
@@ -83,7 +83,7 @@ def gen_clifford_compose_1q():
8383

8484

8585
def gen_clifford_inverse_2q():
86-
"""Generate table data for integer 2Q Clifford inversion"""
86+
"""Generate data for integer 2Q Clifford inversion table"""
8787
invs = np.empty(NUM_CLIFFORD_2Q, dtype=int)
8888
for i, cliff_i in _CLIFF_2Q.items():
8989
invs[i] = _TO_INT_2Q[_hash_cliff(cliff_i.adjoint())]
@@ -191,6 +191,16 @@ def gen_cliff_single_2q_gate_map():
191191
return table
192192

193193

194+
def gen_clifford_tensor_1q():
195+
"""Generate data for 2Q integer Clifford table of the tensor product of 1Q integer Cliffords."""
196+
products = np.empty((NUM_CLIFFORD_1Q, NUM_CLIFFORD_1Q), dtype=int)
197+
for i, cliff_i in _CLIFF_1Q.items():
198+
for j, cliff_j in _CLIFF_1Q.items():
199+
cliff = cliff_i.tensor(cliff_j)
200+
products[i, j] = _TO_INT_2Q[_hash_cliff(cliff)]
201+
return products
202+
203+
194204
if __name__ == "__main__":
195205
if _CLIFF_SINGLE_GATE_MAP_1Q != gen_cliff_single_1q_gate_map():
196206
raise Exception(
@@ -212,3 +222,5 @@ def gen_cliff_single_2q_gate_map():
212222
table=_CLIFFORD_COMPOSE_2Q_DENSE,
213223
valid_sparse_indices=valid_sparse_indices,
214224
)
225+
226+
np.savez_compressed("clifford_tensor_1q.npz", table=gen_clifford_tensor_1q())

qiskit_experiments/library/randomized_benchmarking/layer_fidelity.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
inverse_1q,
4141
inverse_2q,
4242
num_from_2q_circuit,
43-
_product_1q_nums,
43+
_tensor_1q_nums,
4444
_clifford_1q_int_to_instruction,
4545
_clifford_2q_int_to_instruction,
4646
_decompose_clifford_ops,
@@ -403,8 +403,11 @@ def __circuit_body(
403403
for j, qpair in enumerate(two_qubit_layer):
404404
# sample product of two 1q-Cliffords as 2q interger Clifford
405405
samples = rng.integers(NUM_1Q_CLIFFORD, size=2)
406-
cliffs_2q[j] = compose_2q(cliffs_2q[j], _product_1q_nums(*samples))
407-
for sample, q in zip(samples, qpair):
406+
cliffs_2q[j] = compose_2q(cliffs_2q[j], _tensor_1q_nums(*samples))
407+
# For Clifford 1 (x) Clifford 2, in its circuit representation,
408+
# Clifford 1 acts on the 2nd qubit and Clifford 2 acts on the 1st qubit.
409+
# That's why the qpair is reversed here.
410+
for sample, q in zip(samples, reversed(qpair)):
408411
circ._append(_to_gate_1q(sample), (circ.qubits[q],), ())
409412
for k, q in enumerate(one_qubits):
410413
sample = rng.integers(NUM_1Q_CLIFFORD)

0 commit comments

Comments
 (0)