Skip to content

Commit

Permalink
Refactor RB code to allow cnot-dihedral RB on more than 2 qubits (qis…
Browse files Browse the repository at this point in the history
  • Loading branch information
ShellyGarion authored Oct 22, 2020
1 parent 6ca11ad commit 9b93389
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ def __init__(self, group_gates, num_qubits=2):
self._rb_group = CNOTDihedral
self._rb_circ_type += '_cnotdihedral'
self._group_gates_type = 1
assert num_qubits <= 2, "num_qubits for CNOT-Dihedral RB should be 1 or 2"
else:
raise QiskitError("Unknown group or set of gates.")

Expand All @@ -63,7 +62,6 @@ def iden(self, num_qubits):
"""Initialize an identity group element"""
self._num_qubits = num_qubits
if self._group_gates_type:
assert num_qubits <= 2, "num_qubits for CNOT-Dihedral RB should be 1 or 2"
return CNOTDihedral(num_qubits)
else:
return Clifford(np.eye(2 * num_qubits))
Expand All @@ -72,7 +70,6 @@ def random(self, num_qubits, rand_seed=None):
"""Generate a random group element"""
self._num_qubits = num_qubits
if self._group_gates_type:
assert num_qubits <= 2, "num_qubits for CNOT-Dihedral RB should be 1 or 2"
return random_cnotdihedral(num_qubits, seed=rand_seed)
else:
return random_clifford(num_qubits, seed=rand_seed)
Expand Down
7 changes: 7 additions & 0 deletions releasenotes/notes/RB_dihedral_upgrade-e85c020895bcd2ed.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
upgrade:
- |
The :func:`qiskit.ignis.verification.randomized_benchmarking.randomized_benchmarking_seq`
function is now using the upgraded CNOTDihedral class
:class:`qiskit.ignis.verification.randomized_benchmarking.CNOTDihedral`
to allow CNOT-Dihedral Randomized Benchmarking on more than two qubits.
125 changes: 54 additions & 71 deletions test/rb/test_rb.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,37 +71,29 @@ def choose_pattern(pattern_type, nq):
is_purity = True if the pattern fits for purity rb
(namely, all the patterns have the same dimension:
only 1-qubit or only 2-qubits).
is_dihedral = True if the pattern fits dihedral rb
(namely only 1-qubit & 2-qubit rb)
"""

is_purity = True
is_dihedral = True
if pattern_type == 0:
res = [list(range(nq))]
if nq > 2:
is_purity = False
is_dihedral = False
elif pattern_type == 1:
if nq == 1:
return None, None, None
return None, None
res = [[x] for x in range(nq)]
else:
if nq <= 2:
return None, None, None
return None, None
shuffled_bits = list(range(nq))
random.shuffle(shuffled_bits)
# split_loc = random.randint(1, nq-1)
split_loc = 2 # deterministic test
res = [shuffled_bits[:split_loc], shuffled_bits[split_loc:]]
# for only 1-qubit and 2-qubit RB
if (split_loc > 2) | (nq-split_loc > 2):
is_dihedral = False
if 2*split_loc != nq:
is_purity = False

return res, is_purity, is_dihedral
return res, is_purity

@staticmethod
def choose_multiplier(mult_opt, len_pattern):
Expand Down Expand Up @@ -520,8 +512,7 @@ def test_rb(self, nq, pattern_type, multiplier_type):
rb_opts['nseeds'] = 3
rb_opts['rand_seed'] = 1234
rb_opts['length_vector'] = [1, 3, 4, 7]
rb_opts['rb_pattern'], is_purity, is_dihedral = \
self.choose_pattern(pattern_type, nq)
rb_opts['rb_pattern'], is_purity = self.choose_pattern(pattern_type, nq)
# if the pattern type is not relevant for nq
if rb_opts['rb_pattern'] is None:
raise unittest.SkipTest('pattern type is not relevant for nq')
Expand All @@ -536,9 +527,8 @@ def test_rb(self, nq, pattern_type, multiplier_type):
rb_opts_cnotdihedral = rb_opts.copy()
rb_opts_cnotdihedral['group_gates'] = 'CNOT-Dihedral'
rb_opts_cnotdihedral_interleaved = rb_opts_cnotdihedral.copy()
if is_dihedral:
rb_opts_cnotdihedral_interleaved['interleaved_elem'], interleaved_gates = \
self.choose_interleaved_gates(rb_opts['rb_pattern'])
rb_opts_cnotdihedral_interleaved['interleaved_elem'], interleaved_gates = \
self.choose_interleaved_gates(rb_opts['rb_pattern'])
# Choose options for purity rb
# no length_multiplier
rb_opts_purity['length_multiplier'] = 1
Expand All @@ -556,13 +546,12 @@ def test_rb(self, nq, pattern_type, multiplier_type):
rb_original_circs, _, rb_interleaved_circs = \
rb.randomized_benchmarking_seq(**rb_opts_interleaved)
# Non-Clifford cnot-dihedral RB sequences:
if is_dihedral:
rb_cnotdihedral_Z_circs, _, rb_cnotdihedral_X_circs = \
rb.randomized_benchmarking_seq(**rb_opts_cnotdihedral)
# Non-Clifford interleaved cnot-dihedral RB sequences:
# (these circuits will not be executed to save time)
_, _, _, _, _ = \
rb.randomized_benchmarking_seq(**rb_opts_cnotdihedral_interleaved)
rb_cnotdihedral_Z_circs, _, rb_cnotdihedral_X_circs = \
rb.randomized_benchmarking_seq(**rb_opts_cnotdihedral)
# Non-Clifford interleaved cnot-dihedral RB sequences:
# (these circuits will not be executed to save time)
_, _, _, _, _ = \
rb.randomized_benchmarking_seq(**rb_opts_cnotdihedral_interleaved)
# Purity RB sequences:
if is_purity:
rb_purity_circs, _, npurity = \
Expand All @@ -578,9 +567,8 @@ def test_rb(self, nq, pattern_type, multiplier_type):
result = []
result_original = []
result_interleaved = []
if is_dihedral:
result_cnotdihedral_Z = []
result_cnotdihedral_X = []
result_cnotdihedral_Z = []
result_cnotdihedral_X = []
if is_purity:
result_purity = [[] for d in range(npurity)]
for seed in range(rb_opts['nseeds']):
Expand All @@ -598,17 +586,16 @@ def test_rb(self, nq, pattern_type, multiplier_type):
backend=backend,
basis_gates=basis_gates,
shots=shots).result())
if is_dihedral:
result_cnotdihedral_Z.append(
qiskit.execute(rb_cnotdihedral_Z_circs[seed],
backend=backend,
basis_gates=basis_gates,
shots=shots).result())
result_cnotdihedral_X.append(
qiskit.execute(rb_cnotdihedral_X_circs[seed],
backend=backend,
basis_gates=basis_gates,
shots=shots).result())
result_cnotdihedral_Z.append(
qiskit.execute(rb_cnotdihedral_Z_circs[seed],
backend=backend,
basis_gates=basis_gates,
shots=shots).result())
result_cnotdihedral_X.append(
qiskit.execute(rb_cnotdihedral_X_circs[seed],
backend=backend,
basis_gates=basis_gates,
shots=shots).result())
if is_purity:
for d in range(npurity):
result_purity[d].append(qiskit.execute(
Expand Down Expand Up @@ -638,17 +625,16 @@ def test_rb(self, nq, pattern_type, multiplier_type):
'rb_interleaved_length_%d_seed_%d' % (
circ_index, seed),
'Error: incorrect interleaved circuit name')
if is_dihedral:
self.assertEqual(
rb_cnotdihedral_Z_circs[seed][circ_index].name,
'rb_cnotdihedral_Z_length_%d_seed_%d' % (
circ_index, seed),
'Error: incorrect cnotdihedral circuit name')
self.assertEqual(
rb_cnotdihedral_X_circs[seed][circ_index].name,
'rb_cnotdihedral_X_length_%d_seed_%d' % (
circ_index, seed),
'Error: incorrect non-Clifford CNOT-Dihedral circuit name')
self.assertEqual(
rb_cnotdihedral_Z_circs[seed][circ_index].name,
'rb_cnotdihedral_Z_length_%d_seed_%d' % (
circ_index, seed),
'Error: incorrect cnotdihedral circuit name')
self.assertEqual(
rb_cnotdihedral_X_circs[seed][circ_index].name,
'rb_cnotdihedral_X_length_%d_seed_%d' % (
circ_index, seed),
'Error: incorrect non-Clifford CNOT-Dihedral circuit name')
if is_purity:
for d in range(npurity):
name_type, _ = self.update_purity_gates(
Expand Down Expand Up @@ -676,19 +662,18 @@ def test_rb(self, nq, pattern_type, multiplier_type):
result_interleaved[seed],
shots,
is_interleaved=True)
if is_dihedral:
self.verify_circuit(rb_cnotdihedral_Z_circs[seed]
[circ_index],
nq, rb_opts_cnotdihedral,
vec_len,
result_cnotdihedral_Z[seed],
shots)
self.verify_circuit(rb_cnotdihedral_X_circs[seed]
[circ_index],
nq, rb_opts_cnotdihedral,
vec_len,
result_cnotdihedral_X[seed],
shots, is_cnotdihedral=True)
self.verify_circuit(rb_cnotdihedral_Z_circs[seed]
[circ_index],
nq, rb_opts_cnotdihedral,
vec_len,
result_cnotdihedral_Z[seed],
shots)
self.verify_circuit(rb_cnotdihedral_X_circs[seed]
[circ_index],
nq, rb_opts_cnotdihedral,
vec_len,
result_cnotdihedral_X[seed],
shots, is_cnotdihedral=True)
if is_purity:
self.verify_circuit(rb_purity_circs[seed][0]
[circ_index],
Expand All @@ -710,23 +695,21 @@ def test_rb(self, nq, pattern_type, multiplier_type):
rb_interleaved_circs[seed][circ_index],
nq, rb_opts_interleaved, interleaved_gates, vec_len)
# compare the non-Clifford cnot-dihedral RB circuits
if is_dihedral:
self.compare_cnotdihedral_circuit(
rb_cnotdihedral_Z_circs[seed][circ_index],
rb_cnotdihedral_X_circs[seed][circ_index],
nq, rb_opts_cnotdihedral, vec_len)
self.compare_cnotdihedral_circuit(
rb_cnotdihedral_Z_circs[seed][circ_index],
rb_cnotdihedral_X_circs[seed][circ_index],
nq, rb_opts_cnotdihedral, vec_len)

self.assertEqual(circ_index, len(rb_circs),
"Error: additional circuits exist")
self.assertEqual(circ_index, len(rb_original_circs),
"Error: additional interleaved circuits exist")
self.assertEqual(circ_index, len(rb_interleaved_circs),
"Error: additional interleaved circuits exist")
if is_dihedral:
self.assertEqual(circ_index, len(rb_cnotdihedral_Z_circs),
"Error: additional CNOTDihedral circuits exist")
self.assertEqual(circ_index, len(rb_cnotdihedral_X_circs),
"Error: additional CNOTDihedral circuits exist")
self.assertEqual(circ_index, len(rb_cnotdihedral_Z_circs),
"Error: additional CNOTDihedral circuits exist")
self.assertEqual(circ_index, len(rb_cnotdihedral_X_circs),
"Error: additional CNOTDihedral circuits exist")
if is_purity:
self.assertEqual(circ_index, len(rb_purity_circs),
"Error: additional purity circuits exist")
Expand Down

0 comments on commit 9b93389

Please sign in to comment.