예제 #1
0
    def test_delay_circuit_on_single_qubit(self):
        t1s = [0.10, 0.11]
        t2s = [0.20, 0.21]
        dt = 0.01
        duration = 100

        qc = QuantumCircuit(1)
        qc.delay(duration, 0)

        relax_pass = RelaxationNoisePass(t1s=t1s, t2s=t2s, dt=dt)
        actual = qi.SuperOp(relax_pass(qc))
        expected = qi.SuperOp(
            thermal_relaxation_error(t1s[0], t2s[0], duration * dt))
        self.assertEqual(expected, actual)
예제 #2
0
    def test_delay_units(self, duration, unit):
        """Test un-scheduled delay with different units."""
        t1 = 0.004
        t2 = 0.008
        dt = 1e-10  # 0.1 ns
        target_duration = 1e-5

        qc = QuantumCircuit(1)
        qc.delay(duration, 0, unit=unit)

        relax_pass = RelaxationNoisePass(t1s=[t1], t2s=[t2], dt=dt)
        actual = qi.SuperOp(relax_pass(qc))
        expected = qi.SuperOp(thermal_relaxation_error(t1, t2,
                                                       target_duration))
        self.assertEqual(expected, actual)
 def hamiltonian_superop(ham):
     ham = qi.Operator(ham)
     dim, _ = ham.dim
     iden = np.eye(dim)
     super_op = -1j * np.kron(iden, ham.data) + 1j * np.kron(
         np.conj(ham.data), iden)
     return qi.SuperOp(super_op)
 def cost_func(w):
     gen_m = logm(w) - w * sup_l_h.data
     target = qi.SuperOp(la.expm(gen_m))
     if __HAS_DNORM:
         return dnorm(sup_s - target)
     # use 2-norm when old version qiskit is used. both cost functions perform comparably.
     return la.norm(sup_s.data - target.data)
예제 #5
0
    def test_delay_circuit_on_multi_qubits(self):
        t1s = [0.10, 0.11]
        t2s = [0.20, 0.21]
        dt = 0.01
        duration = 100

        qc = QuantumCircuit(2)
        qc.delay(duration, 0)
        qc.delay(duration, 1)

        relax_pass = RelaxationNoisePass(t1s=t1s, t2s=t2s, dt=dt)
        actual = qi.SuperOp(relax_pass(qc))

        noise0 = thermal_relaxation_error(t1s[0], t2s[0], duration * dt)
        noise1 = thermal_relaxation_error(t1s[1], t2s[1], duration * dt)
        expected = qi.SuperOp(noise0.expand(noise1))
        self.assertEqual(expected, actual)
예제 #6
0
    def _test_gate(self, gate, gates_dict, **options):
        """Test standard gates."""

        backend = self.backend(**options)

        gate_cls, num_angles, has_ctrl_qubits = gates_dict[gate]
        circuits = self.gate_circuits(gate_cls,
                                      num_angles=num_angles,
                                      has_ctrl_qubits=has_ctrl_qubits,
                                      rng=self.RNG)

        label = 'final'
        method = backend.options.method
        for circuit in circuits:
            if method == 'density_matrix':
                target = qi.DensityMatrix(circuit)
                circuit.save_density_matrix(label=label)
                state_fn = qi.DensityMatrix
                fidelity_fn = qi.state_fidelity
            elif method == 'stabilizer':
                target = qi.Clifford(circuit)
                circuit.save_stabilizer(label=label)
                state_fn = qi.Clifford.from_dict
                fidelity_fn = qi.process_fidelity
            elif method == 'unitary':
                target = qi.Operator(circuit)
                circuit.save_unitary(label=label)
                state_fn = qi.Operator
                fidelity_fn = qi.process_fidelity
            elif method == 'superop':
                target = qi.SuperOp(circuit)
                circuit.save_superop(label=label)
                state_fn = qi.SuperOp
                fidelity_fn = qi.process_fidelity
            else:
                target = qi.Statevector(circuit)
                circuit.save_statevector(label=label)
                state_fn = qi.Statevector
                fidelity_fn = qi.state_fidelity

            result = backend.run(transpile(circuit,
                                           backend,
                                           optimization_level=0),
                                 shots=1).result()

            # Check results
            success = getattr(result, 'success', False)
            self.assertTrue(success)
            data = result.data(0)
            self.assertIn(label, data)
            value = state_fn(data[label])
            fidelity = fidelity_fn(target, value)
            self.assertGreater(fidelity, 0.9999)
예제 #7
0
    def test_set_superop(self, method, device, num_qubits):
        """Test SetSuperOp instruction"""
        backend = self.backend(method=method, device=device)

        seed = 100
        label = 'state'

        target = qi.SuperOp(qi.random_quantum_channel(2**num_qubits,
                                                      seed=seed))

        circ = QuantumCircuit(num_qubits)
        circ.set_superop(target)
        circ.save_superop(label=label)

        # Run
        result = backend.run(transpile(circ, backend, optimization_level=0),
                             shots=1).result()
        self.assertTrue(result.success)
        simdata = result.data(0)
        self.assertIn(label, simdata)
        value = qi.SuperOp(simdata[label])
        self.assertEqual(value, target)
예제 #8
0
    def test_save_superop(self, method, device):
        """Test save superop instruction"""
        backend = self.backend(method=method, device=device)

        # Test circuit
        SEED = 712
        circ = QuantumVolume(2, seed=SEED)

        # Target unitary
        target = qi.SuperOp(circ)

        # Add save to circuit
        label = 'state'
        circ.save_superop(label=label)

        # Run
        result = backend.run(transpile(circ, backend, optimization_level=0),
                             shots=1).result()
        self.assertTrue(result.success)
        simdata = result.data(0)
        self.assertIn(label, simdata)
        value = qi.SuperOp(simdata[label])
        self.assertEqual(value, target)
예제 #9
0
    def test_pauli_gate(self, method, device, pauli):
        """Test multi-qubit Pauli gate."""
        pauli = qi.Pauli(pauli)
        circuit = QuantumCircuit(pauli.num_qubits)
        circuit.append(pauli, range(pauli.num_qubits))

        backend = self.backend(method=method, device=device)
        label = 'final'
        if method == 'density_matrix':
            target = qi.DensityMatrix(circuit)
            circuit.save_density_matrix(label=label)
            state_fn = qi.DensityMatrix
            fidelity_fn = qi.state_fidelity
        elif method == 'stabilizer':
            target = qi.Clifford(circuit)
            circuit.save_stabilizer(label=label)
            state_fn = qi.Clifford.from_dict
            fidelity_fn = qi.process_fidelity
        elif method == 'unitary':
            target = qi.Operator(circuit)
            circuit.save_unitary(label=label)
            state_fn = qi.Operator
            fidelity_fn = qi.process_fidelity
        elif method == 'superop':
            target = qi.SuperOp(circuit)
            circuit.save_superop(label=label)
            state_fn = qi.SuperOp
            fidelity_fn = qi.process_fidelity
        else:
            target = qi.Statevector(circuit)
            circuit.save_statevector(label=label)
            state_fn = qi.Statevector
            fidelity_fn = qi.state_fidelity

        result = backend.run(transpile(circuit, backend, optimization_level=0),
                             shots=1).result()

        # Check results
        success = getattr(result, 'success', False)
        self.assertTrue(success)
        data = result.data(0)
        self.assertIn(label, data)
        value = state_fn(data[label])
        fidelity = fidelity_fn(target, value)
        self.assertGreater(fidelity, 0.9999)
예제 #10
0
 def test_superop_linop(self):
     orig = qi.SuperOp(qi.random_quantum_channel(4, seed=10))
     compat = cqi.SuperOp(orig.data)
     self.assertEqual(2 * compat - orig, orig)
     self.assertEqual(2 * orig - compat, orig)
예제 #11
0
 def test_superop_eq(self):
     orig = qi.SuperOp(qi.random_quantum_channel(4, seed=10))
     compat = cqi.SuperOp(orig.data)
     self.assertEqual(compat, orig)
     self.assertEqual(orig, compat)
 def logm(w):
     sup_s_h = qi.SuperOp(la.expm(w * sup_l_h.data))
     return la.logm((sup_s @ sup_s_h).data)
def hamiltonian_reconstruction(channels: List[Choi],
                               pauli_labels: List[str],
                               gate_time: float,
                               phase_shifts: List[float] = None,
                               shifter_label: str = 'ZI',
                               sanity_check: bool = False)\
        -> Tuple[Dict[str, np.ndarray], List[float]]:
    """ Extract Pauli term coefficient from quantum channel.
    Args:
        channels: quantum channels to reconstruct Hamiltonian.
        pauli_labels: name of Pauli terms
        gate_time: duration of gate
        phase_shifts: phase shift to unwrap 2pi uncertainty.
        shifter_label: pauli term to shift.
        sanity_check: do sanity check.

    Additional information:
        To remove 2pi uncertainty of Logm, we need decompose superop S to satisfy |M| < 2 pi.
        S_H = exp(w * L_H) where L_H is superop of Pauli term shift.
        According to BCH expansion::
            M = logm(S. S_H)
              = logm(exp(tG).exp(w L_H))
              = tG + w L_H + t*w*[G, L_H] + O(2 coms)
            M' = M - w L_H
        Then Pauli coefficients are::
            b = Tr[B^dag.M']
              = t*Tr[B^dag.G] + t*w*Tr[B^dag.[G, L_H]] + O(2 coms)
              = b_true + + t*w*Tr[B^dag.[G, L_H]] + O(2 coms)
        When commutator of G and L_H is zero, b = b_true.
        Optimizer finds w to calculate principal matrix log.
    """
    threshold_san1 = 1e-3
    threshold_san2 = 1e-1

    def hamiltonian_superop(ham):
        ham = qi.Operator(ham)
        dim, _ = ham.dim
        iden = np.eye(dim)
        super_op = -1j * np.kron(iden, ham.data) + 1j * np.kron(
            np.conj(ham.data), iden)
        return qi.SuperOp(super_op)

    if phase_shifts is None:
        phase_shifts = [0 for _ in range(len(channels))]

    coeffs = defaultdict(list)
    estimated_hamiltonian_fidelities = []
    for phase_shift, chan in zip(phase_shifts, channels):
        sup_s = qi.SuperOp(chan)
        sup_l_h = hamiltonian_superop(qi.Operator.from_label(shifter_label))

        def logm(w):
            sup_s_h = qi.SuperOp(la.expm(w * sup_l_h.data))
            return la.logm((sup_s @ sup_s_h).data)

        def cost_func(w):
            gen_m = logm(w) - w * sup_l_h.data
            target = qi.SuperOp(la.expm(gen_m))
            if __HAS_DNORM:
                return dnorm(sup_s - target)
            # use 2-norm when old version qiskit is used. both cost functions perform comparably.
            return la.norm(sup_s.data - target.data)

        def log_constraint(w):
            return 2 * np.pi - la.norm(logm(w))

        cons = ({'type': 'ineq', 'fun': log_constraint})

        opt_result = opt.minimize(cost_func,
                                  x0=phase_shift,
                                  constraints=cons,
                                  method='SLSQP')
        w_opt = opt_result.x[0]

        # opt status
        print('w_opt = %.3e, cost_func = %.3e, generator norm = %.3e' %
              (w_opt, cost_func(w_opt), log_constraint(w_opt)))

        # sanitary check 1
        sup_s_h_opt = qi.SuperOp(la.expm(w_opt * sup_l_h.data))
        com_norm = la.norm((sup_s @ sup_s_h_opt - sup_s_h_opt @ sup_s).data)
        print('Commutator [S, S_H] norm = %.3e' % com_norm)

        if sanity_check:
            assert com_norm < threshold_san1

        gen_m_opt = logm(w_opt) - w_opt * sup_l_h.data

        for pauli_label in pauli_labels:
            sup_b = hamiltonian_superop(
                0.5 * qi.Operator.from_label(pauli_label).data)
            sup_b_dag = sup_b.adjoint()

            renorm = np.real(np.trace((sup_b_dag @ sup_b).data))
            coeff = np.real(
                np.trace(np.dot(gen_m_opt, sup_b_dag.data)) / renorm)
            coeffs[pauli_label].append(coeff / gate_time)

        # sanitary check 2
        reconst_ham = np.zeros((4, 4))
        for pauli_label in pauli_labels:
            ham_op = 0.5 * qi.Operator.from_label(pauli_label).data
            reconst_ham = reconst_ham + coeffs[pauli_label][-1] * ham_op

        reconst_u = qi.Operator(la.expm(-1j * reconst_ham * gate_time))
        u_fid = qi.average_gate_fidelity(chan, reconst_u)
        estimated_hamiltonian_fidelities.append(u_fid)

        if sanity_check:
            assert 1 - u_fid < threshold_san2

    # list -> ndarray
    coeffs = dict(coeffs)
    for pauli_label in coeffs.keys():
        coeffs[pauli_label] = np.array(coeffs[pauli_label])

    return coeffs, estimated_hamiltonian_fidelities