def verify_one_experiment(row, AG): c_orig = Clifford(QuantumCircuit.from_qasm_str(row['original'])) c_comp = Clifford(QuantumCircuit.from_qasm_str(row['compiled'])) c_opt = Clifford(QuantumCircuit.from_qasm_str(row['optimized'])) assert (c_orig == c_comp) assert (c_comp == c_opt) if AG: c_opt_AG = Clifford( QuantumCircuit.from_qasm_str(row['compiled_aaronson_gottesman'])) assert (c_opt == c_opt_AG)
def assertAllIdentity(self, circuits): """Test if all experiment circuits are identity.""" for circ in circuits: num_qubits = circ.num_qubits iden = Clifford(np.eye(2 * num_qubits, dtype=bool)) circ.remove_final_measurements() self.assertEqual( Clifford(circ), iden, f"Circuit {circ.name} doesn't result in the identity matrix.")
def _generate_circuit(self, elements: Iterable[Clifford], lengths: Iterable[int]) -> List[QuantumCircuit]: """Return the RB circuits constructed from the given element list. Args: elements: A list of Clifford elements lengths: A list of RB sequences lengths. Returns: A list of :class:`QuantumCircuit`s. Additional information: The circuits are constructed iteratively; each circuit is obtained by extending the previous circuit (without the inversion and measurement gates) """ qubits = list(range(self.num_qubits)) circuits = [] circs = [QuantumCircuit(self.num_qubits) for _ in range(len(lengths))] for circ in circs: circ.barrier(qubits) circ_op = Clifford(np.eye(2 * self.num_qubits)) for current_length, group_elt_circ in enumerate(elements): if isinstance(group_elt_circ, tuple): group_elt_gate = group_elt_circ[0] group_elt_op = group_elt_circ[1] else: group_elt_gate = group_elt_circ group_elt_op = Clifford(group_elt_circ) if not isinstance(group_elt_gate, Gate): group_elt_gate = group_elt_gate.to_gate() circ_op = circ_op.compose(group_elt_op) for circ in circs: circ.append(group_elt_gate, qubits) circ.barrier(qubits) if current_length + 1 in lengths: # copy circuit and add inverse inv = circ_op.adjoint() rb_circ = circs.pop() rb_circ.append(inv, qubits) rb_circ.barrier(qubits) rb_circ.metadata = { "experiment_type": self._type, "xval": current_length + 1, "group": "Clifford", "physical_qubits": self.physical_qubits, } rb_circ.measure_all() circuits.append(rb_circ) return circuits
def __init__(self, state): """Create new instruction to set the Clifford stabilizer state of the simulator. Args: state (Clifford): A clifford operator. .. note:: This set instruction must always be performed on the full width of qubits in a circuit, otherwise an exception will be raised during simulation. """ if not isinstance(state, Clifford): state = Clifford(state) super().__init__('set_stabilizer', state.num_qubits, 0, [state.to_dict()])
def test_clifford_1_qubit_generation(self): """Verify 1-qubit clifford indeed generates the correct group""" clifford_dicts = [ {"stabilizer": ["+Z"], "destabilizer": ["+X"]}, {"stabilizer": ["+X"], "destabilizer": ["+Z"]}, {"stabilizer": ["+Y"], "destabilizer": ["+X"]}, {"stabilizer": ["+X"], "destabilizer": ["+Y"]}, {"stabilizer": ["+Z"], "destabilizer": ["+Y"]}, {"stabilizer": ["+Y"], "destabilizer": ["+Z"]}, {"stabilizer": ["-Z"], "destabilizer": ["+X"]}, {"stabilizer": ["+X"], "destabilizer": ["-Z"]}, {"stabilizer": ["-Y"], "destabilizer": ["+X"]}, {"stabilizer": ["+X"], "destabilizer": ["-Y"]}, {"stabilizer": ["-Z"], "destabilizer": ["-Y"]}, {"stabilizer": ["-Y"], "destabilizer": ["-Z"]}, {"stabilizer": ["-Z"], "destabilizer": ["-X"]}, {"stabilizer": ["-X"], "destabilizer": ["-Z"]}, {"stabilizer": ["+Y"], "destabilizer": ["-X"]}, {"stabilizer": ["-X"], "destabilizer": ["+Y"]}, {"stabilizer": ["-Z"], "destabilizer": ["+Y"]}, {"stabilizer": ["+Y"], "destabilizer": ["-Z"]}, {"stabilizer": ["+Z"], "destabilizer": ["-X"]}, {"stabilizer": ["-X"], "destabilizer": ["+Z"]}, {"stabilizer": ["-Y"], "destabilizer": ["-X"]}, {"stabilizer": ["-X"], "destabilizer": ["-Y"]}, {"stabilizer": ["+Z"], "destabilizer": ["-Y"]}, {"stabilizer": ["-Y"], "destabilizer": ["+Z"]}, ] cliffords = [Clifford.from_dict(i) for i in clifford_dicts] utils = rb.CliffordUtils() for n in range(24): clifford = utils.clifford_1_qubit(n) self.assertEqual(clifford, cliffords[n])
def iden(self, num_qubits): """Initialize an identity group element""" self._num_qubits = num_qubits if self._group_gates_type: return CNOTDihedral(num_qubits=num_qubits) else: return Clifford(np.eye(2 * num_qubits))
def format_save_type(data, save_type, save_subtype): """Format raw simulator result data based on save type.""" init_fns = { "save_statevector": Statevector, "save_density_matrix": DensityMatrix, "save_unitary": Operator, "save_superop": SuperOp, "save_stabilizer": (lambda data: StabilizerState(Clifford.from_dict(data))), "save_clifford": Clifford.from_dict, "save_probabilities_dict": ProbDistribution, } # Non-handled cases return raw data if save_type not in init_fns: return data if save_subtype in ["list", "c_list"]: def func(data): init_fn = init_fns[save_type] return [init_fn(i) for i in data] else: func = init_fns[save_type] # Conditional save if save_subtype[:2] == "c_": return {key: func(val) for key, val in data.items()} return func(data)
def assertGraphStateIsCorrect(self, adjacency_matrix, graph_state): """Check the stabilizers of the graph state against the expected stabilizers. Based on https://arxiv.org/pdf/quant-ph/0307130.pdf, Eq. (6). """ stabilizers = Clifford(graph_state).stabilizer.pauli.to_labels() expected_stabilizers = [] # keep track of all expected stabilizers num_vertices = len(adjacency_matrix) for vertex_a in range(num_vertices): stabilizer = [ None ] * num_vertices # Paulis must be put into right place for vertex_b in range(num_vertices): if vertex_a == vertex_b: # self-connection --> 'X' stabilizer[vertex_a] = "X" elif adjacency_matrix[vertex_a][ vertex_b] != 0: # vertices connected --> 'Z' stabilizer[vertex_b] = "Z" else: # else --> 'I' stabilizer[vertex_b] = "I" # need to reverse for Qiskit's tensoring order expected_stabilizers.append("".join(stabilizer)[::-1]) self.assertListEqual(expected_stabilizers, stabilizers)
def set_stabilizer(self, state): """Set the Clifford stabilizer state of the simulator. Args: state (Clifford): A clifford operator. Returns: QuantumCircuit: with attached instruction. Raises: ExtensionError: If the state is the incorrect size for the current circuit. .. note: This instruction is always defined across all qubits in a circuit. """ qubits = default_qubits(self) if not isinstance(state, Clifford): state = Clifford(state) if state.num_qubits != len(qubits): raise ExtensionError( "The size of the Clifford for the set_stabilizer" " instruction must be equal to the number of qubits" f" in the circuit (state.num_qubits ({state.num_qubits})" f" != QuantumCircuit.num_qubits ({self.num_qubits})).") return self.append(SetStabilizer(state), qubits)
def random_cliffords( self, num_qubits: int, size: int = 1, rng: Optional[Union[int, Generator]] = None ): """Generate a list of random clifford elements""" if num_qubits > 2: return random_clifford(num_qubits, seed=rng) if rng is None: rng = default_rng() if isinstance(rng, int): rng = default_rng(rng) if num_qubits == 1: samples = rng.integers(24, size=size) return [Clifford(self.clifford_1_qubit_circuit(i), validate=False) for i in samples] else: samples = rng.integers(11520, size=size) return [Clifford(self.clifford_2_qubit_circuit(i), validate=False) for i in samples]
def test_interleaving_circuit_with_delay(self): """Test circuit with delay can be interleaved.""" delay_qc = QuantumCircuit(2) delay_qc.delay(10, [0], unit="us") delay_qc.x(1) exp = rb.InterleavedRB(interleaved_element=delay_qc, qubits=[1, 2], lengths=[1], seed=123, num_samples=1) _, int_circ = exp.circuits() qc = QuantumCircuit(2) qc.x(1) expected_inversion = Clifford( int_circ.data[1][0]).compose(qc).adjoint() # barrier, clifford, barrier, "interleaved circuit", barrier, inversion, ... self.assertEqual(expected_inversion, Clifford(int_circ.data[5][0]))
def _generate_circuit(self, elements: Iterable[Clifford], lengths: Iterable[int]): """Return the RB circuits constructed from the given element list. Args: elements: A list of Clifford elements lengths: A list of RB sequences lengths. Returns: List[QuantumCircuit]: A list of :class:`QuantumCircuit`s. Additional information: The circuits are constructed iteratively; each circuit is obtained by extending the previous circuit (without the inversion and measurement gates) """ qubits = list(range(self.num_qubits)) circuits = [] circ = QuantumCircuit(self.num_qubits) circ.barrier(qubits) circ_op = Clifford(np.eye(2 * self.num_qubits)) for current_length, group_elt in enumerate(elements): circ_op = circ_op.compose(group_elt) circ.append(group_elt, qubits) circ.barrier(qubits) if current_length + 1 in lengths: # copy circuit and add inverse inv = circ_op.adjoint() rb_circ = circ.copy() rb_circ.append(inv, qubits) rb_circ.barrier(qubits) rb_circ.metadata = { "experiment_type": self._type, "xdata": current_length + 1, "ylabel": self.num_qubits * "0", "group": "Clifford", "qubits": self.physical_qubits, } rb_circ.measure_all() circuits.append(rb_circ) return circuits
def is_identity(self, circuits: list): """Standard randomized benchmarking test - Identity check. (assuming all the operator are spanned by clifford group) Args: circuits (list): list of the circuits which we want to check """ for circ in circuits: num_qubits = circ.num_qubits circ.remove_final_measurements() # Checking if the matrix representation is the identity matrix self.assertTrue( matrix_equal( Clifford(circ).to_matrix(), np.identity(2**num_qubits)), "Clifford sequence doesn't result in the identity matrix.", )
def _set_interleaved_element(self, interleaved_element): """Handle the various types of the interleaved element Args: interleaved_element: The element to interleave Raises: QiskitError: if there is no known conversion of interleaved_element to a Clifford group element """ try: interleaved_element_op = Clifford(interleaved_element) self._interleaved_element = (interleaved_element, interleaved_element_op) except QiskitError as error: raise QiskitError( "Interleaved element {} could not be converted to Clifford element" .format(interleaved_element.name)) from error
def time_compose(self, nqubits_length): (nqubits, length) = map(int, nqubits_length.split(',')) clifford = Clifford(np.eye(2 * nqubits)) for i in range(length): clifford.compose(self.random_clifford[i])
qc.id(0) elif param == 1: qc.H(0) elif param == 2: qc.s(0) elif param == 3: qc.x(0) elif param == 4: qc.y(0) else: qc.z(0) qc.cx(0, 1) qc.swap(1, 3) cliff = Clifford(qc) cliff_circ = cliff.to_circuit() cliff_sf = StateFn(cliff_circ) print(cliff_circ) # help(cliff) # cliff_op = qiskit.quantum_info.random_clifford(4) # print(cliff_op) # # # cliff_circ = cliff_op.to_circuit() # cliff_dense= cliff_circ.to_dense() # representing circuit in the form of ndarray # cliff_operator = qiskit.aqua.operators.legacy.MatrixOperator(cliff_dense) # cliff_detail= cliff_operator.print_details() # cliff_sf = StateFn(cliff_operator)
def clifford_2_qubit(self, num): """Return the 2-qubit clifford element corresponding to `num` where `num` is between 0 and 11519. """ return Clifford(self.clifford_2_qubit_circuit(num), validate=False)