def test_two_q_gates(self):
        """The method dag.twoQ_gates() returns all 2Q gate nodes"""
        self.dag.apply_operation_back(HGate(), [self.qubit0], [])
        self.dag.apply_operation_back(CnotGate(), [self.qubit0, self.qubit1],
                                      [])
        self.dag.apply_operation_back(Barrier(2), [self.qubit0, self.qubit1],
                                      [])
        self.dag.apply_operation_back(Reset(), [self.qubit0], [])

        op_nodes = self.dag.twoQ_gates()
        self.assertEqual(len(op_nodes), 1)

        op_node = op_nodes.pop()
        self.assertIsInstance(op_node.op, Gate)
        self.assertEqual(len(op_node.qargs), 2)
    def test_get_gates_nodes(self):
        """The method dag.gate_nodes() returns all gate nodes"""
        self.dag.apply_operation_back(HGate(), [self.qubit0], [])
        self.dag.apply_operation_back(CnotGate(), [self.qubit0, self.qubit1],
                                      [])
        self.dag.apply_operation_back(Reset(), [self.qubit0], [])

        op_nodes = self.dag.gate_nodes()
        self.assertEqual(len(op_nodes), 2)

        op_node_1 = op_nodes.pop()
        op_node_2 = op_nodes.pop()

        self.assertIsInstance(op_node_1.op, Gate)
        self.assertIsInstance(op_node_2.op, Gate)
Пример #3
0
    def test_quantum_successors(self):
        """The method dag.quantum_successors() returns successors connected by quantum edges"""
        self.dag.apply_operation_back(Measure(self.qubit1, self.clbit1))
        self.dag.apply_operation_back(CnotGate(self.qubit0, self.qubit1))
        self.dag.apply_operation_back(Reset(self.qubit0))

        successor_measure = self.dag.quantum_successors(self.dag.named_nodes('measure').pop())
        self.assertEqual(len(successor_measure), 1)
        cnot_node = successor_measure[0]
        self.assertIsInstance(self.dag.multi_graph.nodes[cnot_node]["op"], CnotGate)

        successor_cnot = self.dag.quantum_successors(cnot_node)
        self.assertEqual(len(successor_cnot), 2)
        self.assertEqual(self.dag.multi_graph.nodes[successor_cnot[0]]["type"], 'out')
        self.assertIsInstance(self.dag.multi_graph.nodes[successor_cnot[1]]["op"], Reset)
Пример #4
0
    def test_get_op_nodes_particular(self):
        """The method dag.get_gates_nodes(op=AGate) returns all the AGate nodes"""
        self.dag.apply_operation_back(HGate(self.qubit0))
        self.dag.apply_operation_back(HGate(self.qubit1))
        self.dag.apply_operation_back(Reset(self.qubit0))

        self.dag.apply_operation_back(CnotGate(self.qubit0, self.qubit1))

        op_nodes = self.dag.get_op_nodes(op=HGate(self.qubit0))
        self.assertEqual(len(op_nodes), 2)

        op_node_1 = op_nodes.pop()
        op_node_2 = op_nodes.pop()

        self.assertIsInstance(self.dag.multi_graph.nodes[op_node_1]["op"], HGate)
        self.assertIsInstance(self.dag.multi_graph.nodes[op_node_2]["op"], HGate)
Пример #5
0
    def test_get_op_nodes_particular(self):
        """The method dag.gates_nodes(op=AGate) returns all the AGate nodes"""
        self.dag.apply_operation_back(HGate(), [self.qubit0], [])
        self.dag.apply_operation_back(HGate(), [self.qubit1], [])
        self.dag.apply_operation_back(Reset(), [self.qubit0], [])

        self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], [])

        op_nodes = self.dag.op_nodes(op=HGate)
        self.assertEqual(len(op_nodes), 2)

        op_node_1 = op_nodes.pop()
        op_node_2 = op_nodes.pop()

        self.assertIsInstance(op_node_1.op, HGate)
        self.assertIsInstance(op_node_2.op, HGate)
Пример #6
0
    def test_quantum_successors(self):
        """The method dag.quantum_successors() returns successors connected by quantum edges"""
        self.dag.apply_operation_back(Measure(), [self.qubit1, self.clbit1], [])
        self.dag.apply_operation_back(CnotGate(), [self.qubit0, self.qubit1], [])
        self.dag.apply_operation_back(Reset(), [self.qubit0], [])

        successor_measure = self.dag.quantum_successors(
            self.dag.named_nodes('measure').pop())
        self.assertEqual(len(successor_measure), 1)
        cnot_node = successor_measure[0]

        self.assertIsInstance(cnot_node.op, CnotGate)

        successor_cnot = self.dag.quantum_successors(cnot_node)
        self.assertEqual(len(successor_cnot), 2)
        self.assertEqual(successor_cnot[0].type, 'out')
        self.assertIsInstance(successor_cnot[1].op, Reset)
Пример #7
0
    def test_auto_method_clifford_circuits_and_reset_noise(self):
        """Test statevector method is used for Clifford circuit"""
        # Test noise model
        noise_circs = [Reset(), IGate()]
        noise_probs = [0.5, 0.5]
        error = QuantumError(zip(noise_circs, noise_probs))
        noise_model = NoiseModel()
        noise_model.add_all_qubit_quantum_error(
            error, ['id', 'x', 'y', 'z', 'h', 's', 'sdg'])
        backend = self.backend(noise_model=noise_model)

        # Test circuits
        shots = 100
        circuits = ref_2q_clifford.cz_gate_circuits_deterministic(
            final_measure=True)
        result = backend.run(circuits, shots=shots).result()
        success = getattr(result, 'success', False)
        self.assertTrue(success)
        self.compare_result_metadata(result, circuits, 'method', 'stabilizer')
Пример #8
0
    def test_quantum_predecessors(self):
        """The method dag.quantum_predecessors() returns predecessors connected by quantum edges"""
        self.dag.apply_operation_back(Reset(), [self.qubit0], [])
        self.dag.apply_operation_back(CnotGate(), [self.qubit0, self.qubit1], [])
        self.dag.apply_operation_back(Measure(), [self.qubit1, self.clbit1], [])

        predecessor_measure = self.dag.quantum_predecessors(
            self.dag.named_nodes('measure').pop())
        cnot_node = next(predecessor_measure)
        with self.assertRaises(StopIteration):
            next(predecessor_measure)

        self.assertIsInstance(cnot_node.op, CnotGate)

        predecessor_cnot = self.dag.quantum_predecessors(cnot_node)
        self.assertIsInstance(next(predecessor_cnot).op, Reset)
        self.assertEqual(next(predecessor_cnot).type, 'in')
        with self.assertRaises(StopIteration):
            next(predecessor_cnot)
Пример #9
0
    def test_quantum_predecessors(self):
        """The method dag.quantum_predecessors() returns predecessors connected by quantum edges"""

        # q_0: |0>─|0>───■─────
        #              ┌─┴─┐┌─┐
        # q_1: |0>─────┤ X ├┤M├
        #              └───┘└╥┘
        #  c_0: 0 ═══════════╬═
        #                    ║
        #  c_1: 0 ═══════════╩═

        self.dag.apply_operation_back(Reset(), [self.qubit0], [])
        self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], [])
        self.dag.apply_operation_back(Measure(), [self.qubit1, self.clbit1],
                                      [])

        predecessor_measure = self.dag.quantum_predecessors(
            self.dag.named_nodes('measure').pop())
        cnot_node = next(predecessor_measure)
        with self.assertRaises(StopIteration):
            next(predecessor_measure)

        self.assertIsInstance(cnot_node.op, CXGate)

        predecessor_cnot = self.dag.quantum_predecessors(cnot_node)
        # Ordering between Reset and in[q1] is indeterminant.

        predecessor1 = next(predecessor_cnot)
        predecessor2 = next(predecessor_cnot)
        with self.assertRaises(StopIteration):
            next(predecessor_cnot)

        self.assertTrue(
            (predecessor1.type == 'in' and isinstance(predecessor2.op, Reset))
            or
            (predecessor2.type == 'in' and isinstance(predecessor1.op, Reset)))
Пример #10
0
    def _to_circuit(cls, op):
        if isinstance(op, QuantumCircuit):
            return op
        if isinstance(op, tuple):
            inst, qubits = op
            circ = QuantumCircuit(max(qubits) + 1)
            circ.append(inst, qargs=qubits)
            return circ
        if isinstance(op, Instruction):
            if op.num_clbits > 0:
                raise NoiseError(
                    f"Unable to convert instruction with clbits: {op.__class__.__name__}"
                )
            circ = QuantumCircuit(op.num_qubits)
            circ.append(op, qargs=list(range(op.num_qubits)))
            return circ
        if isinstance(op, QuantumChannel):
            if not op.is_cptp(atol=cls.atol):
                raise NoiseError("Input quantum channel is not CPTP.")
            try:
                return cls._to_circuit(Kraus(op).to_instruction())
            except QiskitError as err:
                raise NoiseError(
                    f"Fail to convert {op.__class__.__name__} to Instruction."
                ) from err
        if isinstance(op, BaseOperator):
            if hasattr(op, 'to_instruction'):
                try:
                    return cls._to_circuit(op.to_instruction())
                except QiskitError as err:
                    raise NoiseError(
                        f"Fail to convert {op.__class__.__name__} to Instruction."
                    ) from err
            else:
                raise NoiseError(
                    f"Unacceptable Operator, not implementing to_instruction: "
                    f"{op.__class__.__name__}")
        if isinstance(op, list):
            if all(isinstance(aop, tuple) for aop in op):
                num_qubits = max([max(qubits) for _, qubits in op]) + 1
                circ = QuantumCircuit(num_qubits)
                for inst, qubits in op:
                    try:
                        circ.append(inst, qargs=qubits)
                    except CircuitError as err:
                        raise NoiseError(
                            f"Invalid operation type: {inst.__class__.__name__},"
                            f" not appendable to circuit.") from err
                return circ
            # Support for old-style json-like input TODO: to be removed
            elif all(isinstance(aop, dict) for aop in op):
                warnings.warn(
                    'Constructing QuantumError with list of dict representing a mixed channel'
                    ' 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=3)
                # Convert json-like to non-kraus Instruction
                num_qubits = max([max(dic['qubits']) for dic in op]) + 1
                circ = QuantumCircuit(num_qubits)
                for dic in op:
                    if dic['name'] == 'reset':
                        # pylint: disable=import-outside-toplevel
                        from qiskit.circuit import Reset
                        circ.append(Reset(), qargs=dic['qubits'])
                    elif dic['name'] == 'kraus':
                        circ.append(Instruction(name='kraus',
                                                num_qubits=len(dic['qubits']),
                                                num_clbits=0,
                                                params=dic['params']),
                                    qargs=dic['qubits'])
                    elif dic['name'] == 'unitary':
                        circ.append(UnitaryGate(data=dic['params'][0]),
                                    qargs=dic['qubits'])
                    else:
                        with warnings.catch_warnings():
                            warnings.filterwarnings(
                                "ignore",
                                category=DeprecationWarning,
                                module=
                                "qiskit.providers.aer.noise.errors.errorutils")
                            circ.append(UnitaryGate(label=dic['name'],
                                                    data=standard_gate_unitary(
                                                        dic['name'])),
                                        qargs=dic['qubits'])
                return circ
            else:
                raise NoiseError(f"Invalid type of op list: {op}")

        raise NoiseError(
            f"Invalid noise op type {op.__class__.__name__}: {op}")
Пример #11
0
        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": {
        1: _PAULIS_Q0[1:],
        2: _PAULIS_Q0Q1[1:],
    },
    "reset": {
        1: _RESET_Q0[1:],
        2: _RESET_Q0Q1[1:],
Пример #12
0
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]
Пример #13
0
def thermal_relaxation_error(t1, t2, time, excited_state_population=0):
    r"""
    Return a single-qubit thermal relaxation quantum error channel.

    Args:
        t1 (double): the :math:`T_1` relaxation time constant.
        t2 (double): the :math:`T_2` relaxation time constant.
        time (double): the gate time for relaxation error.
        excited_state_population (double): the population of :math:`|1\rangle`
                                           state at equilibrium (default: 0).

    Returns:
        QuantumError: a quantum error object for a noise model.

    Raises:
        NoiseError: If noise parameters are invalid.

    Additional information:
        * For parameters to be valid :math:`T_1` and :math:`T_2` must
          satisfy :math:`T_2 \le 2 T_1`.

        * If :math:`T_2 \le T_1` the error can be expressed as a mixed
          reset and unitary error channel.

        * If :math:`T_1 < T_2 \le 2 T_1` the error must be expressed as a
          general non-unitary Kraus error channel.
    """
    if excited_state_population < 0:
        raise NoiseError("Invalid excited state population "
                         "({} < 0).".format(excited_state_population))
    if excited_state_population > 1:
        raise NoiseError("Invalid excited state population "
                         "({} > 1).".format(excited_state_population))
    if time < 0:
        raise NoiseError("Invalid gate_time ({} < 0)".format(time))
    if t1 <= 0:
        raise NoiseError("Invalid T_1 relaxation time parameter: T_1 <= 0.")
    if t2 <= 0:
        raise NoiseError("Invalid T_2 relaxation time parameter: T_2 <= 0.")
    if t2 - 2 * t1 > 0:
        raise NoiseError(
            "Invalid T_2 relaxation time parameter: T_2 greater than 2 * T_1.")

    # T1 relaxation rate
    if t1 == np.inf:
        rate1 = 0
        p_reset = 0
    else:
        rate1 = 1 / t1
        p_reset = 1 - np.exp(-time * rate1)
    # T2 dephasing rate
    if t2 == np.inf:
        rate2 = 0
        exp_t2 = 1
    else:
        rate2 = 1 / t2
        exp_t2 = np.exp(-time * rate2)
    # Qubit state equilibrium probabilities
    p0 = 1 - excited_state_population
    p1 = excited_state_population

    if t2 > t1:
        # If T_2 > T_1 we must express this as a Kraus channel
        # We start with the Choi-matrix representation:
        chan = Choi(
            np.array([[1 - p1 * p_reset, 0, 0, exp_t2],
                      [0, p1 * p_reset, 0, 0], [0, 0, p0 * p_reset, 0],
                      [exp_t2, 0, 0, 1 - p0 * p_reset]]))
        return QuantumError(Kraus(chan))
    else:
        # If T_2 < T_1 we can express this channel as a probabilistic
        # mixture of reset operations and unitary errors:
        circuits = [[(IGate(), [0])], [(ZGate(), [0])], [(Reset(), [0])],
                    [(Reset(), [0]), (XGate(), [0])]]
        # Probability
        p_reset0 = p_reset * p0
        p_reset1 = p_reset * p1
        p_z = (1 - p_reset) * (1 - np.exp(-time * (rate2 - rate1))) / 2
        p_identity = 1 - p_z - p_reset0 - p_reset1
        probabilities = [p_identity, p_z, p_reset0, p_reset1]
        return QuantumError(zip(circuits, probabilities))