def build_correction(self): # Build Correction Circuit circ = QuantumCircuit(self.code, self.syndrm) circ.append(XGate().control(4, ctrl_state='0010'), [self.syndrm[i] for i in range(4)] + [self.code[0]]) circ.append(YGate().control(4, ctrl_state='1110'), [self.syndrm[i] for i in range(4)] + [self.code[0]]) circ.append(ZGate().control(4, ctrl_state='1100'), [self.syndrm[i] for i in range(4)] + [self.code[0]]) circ.append(XGate().control(4, ctrl_state='0101'), [self.syndrm[i] for i in range(4)] + [self.code[1]]) circ.append(YGate().control(4, ctrl_state='1101'), [self.syndrm[i] for i in range(4)] + [self.code[1]]) circ.append(ZGate().control(4, ctrl_state='1000'), [self.syndrm[i] for i in range(4)] + [self.code[1]]) circ.append(XGate().control(4, ctrl_state='1010'), [self.syndrm[i] for i in range(4)] + [self.code[2]]) circ.append(YGate().control(4, ctrl_state='1011'), [self.syndrm[i] for i in range(4)] + [self.code[2]]) circ.append(ZGate().control(4, ctrl_state='0001'), [self.syndrm[i] for i in range(4)] + [self.code[2]]) circ.append(XGate().control(4, ctrl_state='0100'), [self.syndrm[i] for i in range(4)] + [self.code[3]]) circ.append(YGate().control(4, ctrl_state='0111'), [self.syndrm[i] for i in range(4)] + [self.code[3]]) circ.append(ZGate().control(4, ctrl_state='0011'), [self.syndrm[i] for i in range(4)] + [self.code[3]]) circ.append(XGate().control(4, ctrl_state='1001'), [self.syndrm[i] for i in range(4)] + [self.code[4]]) circ.append(YGate().control(4, ctrl_state='1111'), [self.syndrm[i] for i in range(4)] + [self.code[4]]) circ.append(ZGate().control(4, ctrl_state='0110'), [self.syndrm[i] for i in range(4)] + [self.code[4]]) return circ
def to_instruction(self): """Convert to Pauli circuit instruction.""" from math import pi pauli, phase = self._to_label(self.z, self.x, self._phase[0], full_group=False, return_phase=True) if len(pauli) == 1: gate = { "I": IGate(), "X": XGate(), "Y": YGate(), "Z": ZGate() }[pauli] else: gate = PauliGate(pauli) if not phase: return gate # Add global phase circuit = QuantumCircuit(self.num_qubits, name=str(self)) circuit.global_phase = -phase * pi / 2 circuit.append(gate, range(self.num_qubits)) return circuit.to_instruction()
def setUp(self): super().setUp() self.ops = { 'X': XGate(), 'Y': YGate(), 'Z': ZGate(), 'H': HGate(), 'S': SGate() }
def from_label(cls, label): """Return a tensor product of single-qubit operators. Args: label (string): single-qubit operator string. Returns: Operator: The N-qubit operator. Raises: QiskitError: if the label contains invalid characters, or the length of the label is larger than an explicitly specified num_qubits. Additional Information: The labels correspond to the single-qubit matrices: 'I': [[1, 0], [0, 1]] 'X': [[0, 1], [1, 0]] 'Y': [[0, -1j], [1j, 0]] 'Z': [[1, 0], [0, -1]] 'H': [[1, 1], [1, -1]] / sqrt(2) 'S': [[1, 0], [0 , 1j]] 'T': [[1, 0], [0, (1+1j) / sqrt(2)]] '0': [[1, 0], [0, 0]] '1': [[0, 0], [0, 1]] '+': [[0.5, 0.5], [0.5 , 0.5]] '-': [[0.5, -0.5], [-0.5 , 0.5]] 'r': [[0.5, -0.5j], [0.5j , 0.5]] 'l': [[0.5, 0.5j], [-0.5j , 0.5]] """ # Check label is valid label_mats = { 'I': IGate().to_matrix(), 'X': XGate().to_matrix(), 'Y': YGate().to_matrix(), 'Z': ZGate().to_matrix(), 'H': HGate().to_matrix(), 'S': SGate().to_matrix(), 'T': TGate().to_matrix(), '0': np.array([[1, 0], [0, 0]], dtype=complex), '1': np.array([[0, 0], [0, 1]], dtype=complex), '+': np.array([[0.5, 0.5], [0.5, 0.5]], dtype=complex), '-': np.array([[0.5, -0.5], [-0.5, 0.5]], dtype=complex), 'r': np.array([[0.5, -0.5j], [0.5j, 0.5]], dtype=complex), 'l': np.array([[0.5, 0.5j], [-0.5j, 0.5]], dtype=complex), } if re.match(r'^[IXYZHST01rl\-+]+$', label) is None: raise QiskitError('Label contains invalid characters.') # Initialize an identity matrix and apply each gate num_qubits = len(label) op = Operator(np.eye(2 ** num_qubits, dtype=complex)) for qubit, char in enumerate(reversed(label)): if char != 'I': op = op.compose(label_mats[char], qargs=[qubit]) return op
def from_label(label): """Return a tensor product of single-qubit Clifford gates. Args: label (string): single-qubit operator string. Returns: Clifford: The N-qubit Clifford operator. Raises: QiskitError: if the label contains invalid characters. Additional Information: The labels correspond to the single-qubit Cliffords are * - Label - Stabilizer - Destabilizer * - ``"I"`` - +Z - +X * - ``"X"`` - -Z - +X * - ``"Y"`` - -Z - -X * - ``"Z"`` - +Z - -X * - ``"H"`` - +X - +Z * - ``"S"`` - +Z - +Y """ # Check label is valid label_gates = { 'I': IGate(), 'X': XGate(), 'Y': YGate(), 'Z': ZGate(), 'H': HGate(), 'S': SGate() } if re.match(r'^[IXYZHS\-+]+$', label) is None: raise QiskitError('Label contains invalid characters.') # Initialize an identity matrix and apply each gate num_qubits = len(label) op = Clifford(np.eye(2 * num_qubits, dtype=np.bool)) for qubit, char in enumerate(reversed(label)): _append_circuit(op, label_gates[char], qargs=[qubit]) return op
def to_instruction(self): """Convert to Pauli circuit instruction.""" from qiskit.circuit import QuantumCircuit, QuantumRegister from qiskit.circuit.library.standard_gates import IGate, XGate, YGate, ZGate gates = {'I': IGate(), 'X': XGate(), 'Y': YGate(), 'Z': ZGate()} label = self.to_label() num_qubits = self.num_qubits qreg = QuantumRegister(num_qubits) circuit = QuantumCircuit(qreg, name='Pauli:{}'.format(label)) for i, pauli in enumerate(reversed(label)): circuit.append(gates[pauli], [qreg[i]]) return circuit.to_instruction()
def test_pauli_error_1q_gate_from_string(self): """Test single-qubit pauli error as gate qobj from string label""" paulis = ['I', 'X', 'Y', 'Z'] probs = [0.4, 0.3, 0.2, 0.1] actual = pauli_error(zip(paulis, probs)) expected = QuantumError([(IGate(), 0.4), (XGate(), 0.3), (YGate(), 0.2), (ZGate(), 0.1)]) for i in range(actual.size): circ, prob = actual.error_term(i) expected_circ, expected_prob = expected.error_term(i) self.assertEqual(circ, expected_circ, msg=f"Incorrect {i}-th circuit") self.assertAlmostEqual(prob, expected_prob, msg=f"Incorrect {i}-th probability")
def test_depolarizing_error_1q_gate(self): """Test 1-qubit depolarizing error as gate qobj""" p_depol = 0.3 actual = depolarizing_error(p_depol, 1) expected = QuantumError([ (IGate(), 1 - p_depol*3/4), (XGate(), p_depol/4), (YGate(), p_depol/4), (ZGate(), p_depol/4) ]) for i in range(actual.size): circ, prob = actual.error_term(i) expected_circ, expected_prob = expected.error_term(i) self.assertEqual(circ, expected_circ, msg=f"Incorrect {i}-th circuit") self.assertAlmostEqual(prob, expected_prob, msg=f"Incorrect {i}-th probability")
if a ``dict`` is given, ``list`` is overwritten. The ``string`` supports only 1- or 2-qubit errors and its possible values are ``'pauli'``, ``'reset'``, ``'clifford'``. The ``'clifford'`` does not support 2-qubit errors. """ def approximate(noise): return approximate_quantum_error(noise, operator_string=operator_string, operator_dict=operator_dict, operator_list=operator_list) return transform_noise_model(model, approximate) # pauli operators _PAULIS_Q0 = [[(IGate(), [0])], [(XGate(), [0])], [(YGate(), [0])], [(ZGate(), [0])]] _PAULIS_Q1 = [[(IGate(), [1])], [(XGate(), [1])], [(YGate(), [1])], [(ZGate(), [1])]] _PAULIS_Q0Q1 = [op_q0 + op_q1 for op_q0 in _PAULIS_Q0 for op_q1 in _PAULIS_Q1] # reset operators _RESET_Q0_TO_0 = [(Reset(), [0])] _RESET_Q0_TO_1 = [(Reset(), [0]), (XGate(), [0])] _RESET_Q0 = [[(IGate(), [0])], _RESET_Q0_TO_0, _RESET_Q0_TO_1] _RESET_Q1_TO_0 = [(Reset(), [1])] _RESET_Q1_TO_1 = [(Reset(), [1]), (XGate(), [1])] _RESET_Q1 = [[(IGate(), [1])], _RESET_Q1_TO_0, _RESET_Q1_TO_1] _RESET_Q0Q1 = [op_q0 + op_q1 for op_q0 in _RESET_Q0 for op_q1 in _RESET_Q1] # preset operator table _PRESET_OPERATOR_TABLE = { "pauli": {
def _standard_gate_instruction(instruction, ignore_phase=True): """Temporary function to create Instruction objects from a json string, which is necessary for creating a new QuantumError object from deprecated json-based input. Note that the type of returned object is different from the deprecated standard_gate_instruction. TODO: to be removed after deprecation period. Args: instruction (dict): A qobj instruction. ignore_phase (bool): Ignore global phase on unitary matrix in comparison to canonical unitary. Returns: list: a list of (instructions, qubits) equivalent to in input instruction. """ gate = { "id": IGate(), "x": XGate(), "y": YGate(), "z": ZGate(), "h": HGate(), "s": SGate(), "sdg": SdgGate(), "t": TGate(), "tdg": TdgGate(), "cx": CXGate(), "cz": CZGate(), "swap": SwapGate() } name = instruction.get("name", None) qubits = instruction["qubits"] if name in gate: return [(gate[name], qubits)] if name not in ["mat", "unitary", "kraus"]: return [instruction] params = instruction["params"] with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=DeprecationWarning, module="qiskit.providers.aer.noise.errors.errorutils") # Check for single-qubit reset Kraus if name == "kraus": if len(qubits) == 1: superop = SuperOp(Kraus(params)) # Check if reset to |0> reset0 = reset_superop(1) if superop == reset0: return [(Reset(), [0])] # Check if reset to |1> reset1 = reset0.compose(Operator(standard_gate_unitary('x'))) if superop == reset1: return [(Reset(), [0]), (XGate(), [0])] return [instruction] # Check single qubit gates mat = params[0] if len(qubits) == 1: # Check clifford gates for j in range(24): if matrix_equal( mat, single_qubit_clifford_matrix(j), ignore_phase=ignore_phase): return [(gate, [0]) for gate in _CLIFFORD_GATES[j]] # Check t gates for name in ["t", "tdg"]: if matrix_equal( mat, standard_gate_unitary(name), ignore_phase=ignore_phase): return [(gate[name], qubits)] # TODO: u1,u2,u3 decomposition # Check two qubit gates if len(qubits) == 2: for name in ["cx", "cz", "swap"]: if matrix_equal( mat, standard_gate_unitary(name), ignore_phase=ignore_phase): return [(gate[name], qubits)] # Check reversed CX if matrix_equal( mat, standard_gate_unitary("cx_10"), ignore_phase=ignore_phase): return [(CXGate(), [qubits[1], qubits[0]])] # Check 2-qubit Pauli's paulis = ["id", "x", "y", "z"] for pauli0 in paulis: for pauli1 in paulis: pmat = np.kron( standard_gate_unitary(pauli1), standard_gate_unitary(pauli0)) if matrix_equal(mat, pmat, ignore_phase=ignore_phase): if pauli0 == "id": return [(gate[pauli1], [qubits[1]])] elif pauli1 == "id": return [(gate[pauli0], [qubits[0]])] else: return [(gate[pauli0], [qubits[0]]), (gate[pauli1], [qubits[1]])] # Check three qubit toffoli if len(qubits) == 3: if matrix_equal( mat, standard_gate_unitary("ccx_012"), ignore_phase=ignore_phase): return [(CCXGate(), qubits)] if matrix_equal( mat, standard_gate_unitary("ccx_021"), ignore_phase=ignore_phase): return [(CCXGate(), [qubits[0], qubits[2], qubits[1]])] if matrix_equal( mat, standard_gate_unitary("ccx_120"), ignore_phase=ignore_phase): return [(CCXGate(), [qubits[1], qubits[2], qubits[0]])] # Else return input in return [instruction]
(HGate(), SGate()), (SGate(), HGate()), (HGate(), SdgGate()), (SdgGate(), HGate()), (SGate(), HGate(), SGate()), (SdgGate(), HGate(), SGate()), (ZGate(), HGate(), SGate()), (SGate(), HGate(), SdgGate()), (SdgGate(), HGate(), SdgGate()), (ZGate(), HGate(), SdgGate()), (SGate(), HGate(), ZGate()), (SdgGate(), HGate(), ZGate()), (ZGate(), HGate(), ZGate()), # u3 gates (XGate(), ), (YGate(), ), (SGate(), XGate()), (SdgGate(), XGate()) ] def single_qubit_clifford_matrix(j): """Return Numpy array for a single qubit Clifford. Args: j (int): Clifford index 0, ..., 23. Returns: np.array: The matrix for the indexed clifford. Raises: NoiseError: If index is out of range [0, 23]. """ warnings.warn(
def depolarizing_error(param, num_qubits, standard_gates=None): r""" Return a depolarizing quantum error channel. The depolarizing channel is defined as: .. math:: E(ρ) = (1 - λ) ρ + λ \text{Tr}[ρ] \frac{I}{2^n} with :math:`0 \le λ \le 4^n / (4^n - 1)` where :math:`λ` is the depolarizing error param and :math`n` is the number of qubits. * If :math:`λ = 0` this is the identity channel :math:`E(ρ) = ρ` * If :math:`λ = 1` this is a completely depolarizing channel :math:`E(ρ) = I / 2^n` * If :math:`λ = 4^n / (4^n - 1)` this is a uniform Pauli error channel: :math:`E(ρ) = \sum_j P_j ρ P_j / (4^n - 1)` for all :math:`P_j != I`. Args: param (double): depolarizing error parameter. num_qubits (int): the number of qubits for the error channel. standard_gates (bool): DEPRECATED, if True return the operators as Pauli gates. If false return as unitary gates. (Default: None) Returns: QuantumError: The quantum error object. Raises: NoiseError: If noise parameters are invalid. """ if not isinstance(num_qubits, int) or num_qubits < 1: raise NoiseError("num_qubits must be a positive integer.") # Check that the depolarizing parameter gives a valid CPTP num_terms = 4**num_qubits max_param = num_terms / (num_terms - 1) if param < 0 or param > max_param: raise NoiseError("Depolarizing parameter must be in between 0 " "and {}.".format(max_param)) # Rescale completely depolarizing channel error probs # with the identity component removed prob_iden = 1 - param / max_param prob_pauli = param / num_terms probs = [prob_iden] + (num_terms - 1) * [prob_pauli] if standard_gates is not None: warnings.warn( '"standard_gates" option has been deprecated as of qiskit-aer 0.10.0' ' and will be removed no earlier than 3 months from that release date.', DeprecationWarning, stacklevel=2) circs = [] for pauli_list in it.product( [IGate(), XGate(), YGate(), ZGate()], repeat=num_qubits): qc = QuantumCircuit(num_qubits) for q, pauli in enumerate(pauli_list): if not standard_gates: pauli = UnitaryGate(pauli.to_matrix()) qc.append(pauli, qargs=[q]) circs.append(qc) return QuantumError(zip(circs, probs)) # Generate pauli strings. The order doesn't matter as long # as the all identity string is first. paulis = [ Pauli("".join(tup)) for tup in it.product(['I', 'X', 'Y', 'Z'], repeat=num_qubits) ] return QuantumError(zip(paulis, probs))