Exemple #1
0
def entangling_power(U):
    """
    Calculate the entangling power of a two-qubit gate U, which
    is zero of nonentangling gates and 1 and 2/9 for maximally
    entangling gates.

    Parameters
    ----------
    U : qobj
        Qobj instance representing a two-qubit gate.

    Returns
    -------
    ep : float
        The entanglement power of U (real number between 0 and 1)

    References:

        Explorations in Quantum Computing, Colin P. Williams (Springer, 2011)
    """

    if not U.isoper:
        raise Exception("U must be an operator.")

    if U.dims != [[2, 2], [2, 2]]:
        raise Exception("U must be a two-qubit gate.")

    a = (tensor(U, U).dag() * swap(N=4, targets=[1, 3]) * tensor(U, U) *
         swap(N=4, targets=[1, 3]))
    b = (tensor(swap() * U,
                swap() * U).dag() * swap(N=4, targets=[1, 3]) *
         tensor(swap() * U,
                swap() * U) * swap(N=4, targets=[1, 3]))

    return 5.0 / 9 - 1.0 / 36 * (a.tr() + b.tr()).real
Exemple #2
0
def entangling_power(U):
    """
    Calculate the entangling power of a two-qubit gate U, which
    is zero of nonentangling gates and 1 and 2/9 for maximally
    entangling gates.

    Parameters
    ----------
    U : qobj
        Qobj instance representing a two-qubit gate.

    Returns
    -------
    ep : float
        The entanglement power of U (real number between 0 and 1)

    References:

        Explorations in Quantum Computing, Colin P. Williams (Springer, 2011)
    """

    if not U.isoper:
        raise Exception("U must be an operator.")

    if U.dims != [[2, 2], [2, 2]]:
        raise Exception("U must be a two-qubit gate.")

    a = (tensor(U, U).dag() * swap(N=4, targets=[1, 3]) *
         tensor(U, U) * swap(N=4, targets=[1, 3]))
    b = (tensor(swap() * U, swap() * U).dag() * swap(N=4, targets=[1, 3]) *
         tensor(swap() * U, swap() * U) * swap(N=4, targets=[1, 3]))

    return 5.0/9 - 1.0/36 * (a.tr() + b.tr()).real
    def test_known_iscptp(self):
        """
        Superoperator: iscp, istp and iscptp known cases.
        """
        # Check that unitaries are CPTP.
        assert_(identity(2).iscptp)
        assert_(sigmax().iscptp)

        # The partial transpose map, whose Choi matrix is SWAP, is TP but not
        # CP.
        W = Qobj(swap(), type='super', superrep='choi')
        assert_(W.istp)
        assert_(not W.iscp)
        assert_(not W.iscptp)

        # Subnormalized maps (representing erasure channels, for instance)
        # can be CP but not TP.
        subnorm_map = Qobj(identity(4) * 0.9, type='super', superrep='super')
        assert_(subnorm_map.iscp)
        assert_(not subnorm_map.istp)
        assert_(not subnorm_map.iscptp)

        # Check that things which aren't even operators aren't identified as
        # CPTP.
        assert_(not (basis(2).iscptp))
Exemple #4
0
def qft_steps(N=1, swapping=True):
    """
    Quantum Fourier Transform operator on N qubits returning the individual
    steps as unitary matrices operating from left to right.

    Parameters
    ----------
    N: int
        Number of qubits.
    swap: boolean
        Flag indicating sequence of swap gates to be applied at the end or not.

    Returns
    -------
    U_step_list: list of qobj
        List of Hadamard and controlled rotation gates implementing QFT.

    """
    if N < 1:
        raise ValueError("Minimum value of N can be 1")

    U_step_list = []
    if N == 1:
        U_step_list.append(snot())
    else:
        for i in range(N):
            for j in range(i):
                U_step_list.append(
                    cphase(np.pi / (2**(i - j)), N, control=i, target=j))
            U_step_list.append(snot(N, i))
        if swapping is True:
            for i in range(N // 2):
                U_step_list.append(swap(N, [N - i - 1, i]))

    return U_step_list
    def test_known_iscptp(self):
        """
        Superoperator: iscp, istp and iscptp known cases.
        """
        # Check that unitaries are CPTP.
        assert_(identity(2).iscptp)
        assert_(sigmax().iscptp)
        
        # The partial transpose map, whose Choi matrix is SWAP, is TP but not
        # CP.
        W = Qobj(swap(), type='super', superrep='choi')
        assert_(W.istp)
        assert_(not W.iscp)
        assert_(not W.iscptp)
        
        # Subnormalized maps (representing erasure channels, for instance)
        # can be CP but not TP.
        subnorm_map = Qobj(identity(4) * 0.9, type='super', superrep='super')
        assert_(subnorm_map.iscp)
        assert_(not subnorm_map.istp)
        assert_(not subnorm_map.iscptp)

        
        # Check that things which aren't even operators aren't identified as
        # CPTP.
        assert_(not (basis(2).iscptp))
Exemple #6
0
def qft_steps(N=1, swapping=True):
    """
    Quantum Fourier Transform operator on N qubits returning the individual
    steps as unitary matrices operating from left to right.
    
    Parameters
    ----------
    N: int
        Number of qubits.
    swap: boolean
        Flag indicating sequence of swap gates to be applied at the end or not.
    
    Returns
    -------
    U_step_list: list of qobj
        List of Hadamard and controlled rotation gates implementing QFT.
    
    """
    if N < 1:
        raise ValueError("Minimum value of N can be 1")
    
    U_step_list = []
    if N == 1:
        U_step_list.append(snot())
    else:
        for i in range(N):
            for j in range(i):
                U_step_list.append(cphase(np.pi/(2**(i-j)), N,
                                   control=i, target=j))
            U_step_list.append(snot(N, i))
        if swapping == True:
            for i in range(N//2):
                U_step_list.append(swap(N, [N-i-1, i]))

    return U_step_list
    def test_known_iscptp(self):
        """
        Superoperator: ishp, iscp, istp and iscptp known cases.
        """
        def case(qobj, shouldhp, shouldcp, shouldtp):
            hp = qobj.ishp
            cp = qobj.iscp
            tp = qobj.istp
            cptp = qobj.iscptp

            shouldcptp = shouldcp and shouldtp

            if (
                hp == shouldhp and
                cp == shouldcp and
                tp == shouldtp and
                cptp == shouldcptp
            ):
                return

            fails = []
            if hp != shouldhp:
                fails.append(("ishp", shouldhp, hp))
            if tp != shouldtp:
                fails.append(("istp", shouldtp, tp))
            if cp != shouldcp:
                fails.append(("iscp", shouldcp, cp))
            if cptp != shouldcptp:
                fails.append(("iscptp", shouldcptp, cptp))

            raise AssertionError("Expected {}.".format(" and ".join([
                "{} == {} (got {})".format(fail, expected, got)
                for fail, expected, got in fails
            ])))

        # Conjugation by a creation operator should
        # have be CP (and hence HP), but not TP.
        a = create(2).dag()
        S = sprepost(a, a.dag())
        yield case, S, True, True, False

        # A single off-diagonal element should not be CP,
        # nor even HP.
        S = sprepost(a, a)
        yield case, S, False, False, False
        
        # Check that unitaries are CPTP and HP.
        yield case, identity(2), True, True, True
        yield case, sigmax(), True, True, True

        # The partial transpose map, whose Choi matrix is SWAP, is TP
        # and HP but not CP (one negative eigenvalue).
        W = Qobj(swap(), type='super', superrep='choi')
        yield case, W, True, False, True

        # Subnormalized maps (representing erasure channels, for instance)
        # can be CP but not TP.
        subnorm_map = Qobj(identity(4) * 0.9, type='super', superrep='super')
        yield case, subnorm_map, True, True, False

        # Check that things which aren't even operators aren't identified as
        # CPTP.
        yield case, basis(2), False, False, False
Exemple #8
0
    def test_known_iscptp(self):
        """
        Superoperator: ishp, iscp, istp and iscptp known cases.
        """
        def case(qobj, shouldhp, shouldcp, shouldtp):
            hp = qobj.ishp
            cp = qobj.iscp
            tp = qobj.istp
            cptp = qobj.iscptp

            shouldcptp = shouldcp and shouldtp

            if (
                hp == shouldhp and
                cp == shouldcp and
                tp == shouldtp and
                cptp == shouldcptp
            ):
                return

            fails = []
            if hp != shouldhp:
                fails.append(("ishp", shouldhp, hp))
            if tp != shouldtp:
                fails.append(("istp", shouldtp, tp))
            if cp != shouldcp:
                fails.append(("iscp", shouldcp, cp))
            if cptp != shouldcptp:
                fails.append(("iscptp", shouldcptp, cptp))

            raise AssertionError("Expected {}.".format(" and ".join([
                "{} == {} (got {})".format(fail, expected, got)
                for fail, expected, got in fails
            ])))

        # Conjugation by a creation operator should
        # have be CP (and hence HP), but not TP.
        a = create(2).dag()
        S = sprepost(a, a.dag())
        case(S, True, True, False)

        # A single off-diagonal element should not be CP,
        # nor even HP.
        S = sprepost(a, a)
        case(S, False, False, False)
        
        # Check that unitaries are CPTP and HP.
        case(identity(2), True, True, True)
        case(sigmax(), True, True, True)

        # The partial transpose map, whose Choi matrix is SWAP, is TP
        # and HP but not CP (one negative eigenvalue).
        W = Qobj(swap(), type='super', superrep='choi')
        case(W, True, False, True)

        # Subnormalized maps (representing erasure channels, for instance)
        # can be CP but not TP.
        subnorm_map = Qobj(identity(4) * 0.9, type='super', superrep='super')
        case(subnorm_map, True, True, False)

        # Check that things which aren't even operators aren't identified as
        # CPTP.
        case(basis(2), False, False, False)
Exemple #9
0
def test_dnorm_qubit_known_cases():
    """
    Metrics: check agreement for known qubit channels.
    """
    def case(chan1, chan2, expected, significant=4):
        # We again take a generous tolerance so that we don't kill off
        # SCS solvers.
        assert_approx_equal(dnorm(chan1, chan2),
                            expected,
                            significant=significant)

    id_chan = to_choi(qeye(2))
    S_eye = to_super(id_chan)
    X_chan = to_choi(sigmax())
    depol = to_choi(
        Qobj(diag(ones((4, ))), dims=[[[2], [2]], [[2], [2]]], superrep='chi'))
    S_H = to_super(hadamard_transform())

    W = swap()

    # We need to restrict the number of iterations for things on the boundary,
    # such as perfectly distinguishable channels.
    yield case, id_chan, X_chan, 2
    yield case, id_chan, depol, 1.5

    # Next, we'll generate some test cases based on comparisons to pre-existing
    # dnorm() implementations. In particular, the targets for the following
    # test cases were generated using QuantumUtils for MATLAB (https://goo.gl/oWXhO9).

    def overrotation(x):
        return to_super((1j * np.pi * x * sigmax() / 2).expm())

    for x, target in {
            1.000000e-03: 3.141591e-03,
            3.100000e-03: 9.738899e-03,
            1.000000e-02: 3.141463e-02,
            3.100000e-02: 9.735089e-02,
            1.000000e-01: 3.128689e-01,
            3.100000e-01: 9.358596e-01
    }.items():
        yield case, overrotation(x), id_chan, target

    def had_mixture(x):
        return (1 - x) * S_eye + x * S_H

    for x, target in {
            1.000000e-03: 2.000000e-03,
            3.100000e-03: 6.200000e-03,
            1.000000e-02: 2.000000e-02,
            3.100000e-02: 6.200000e-02,
            1.000000e-01: 2.000000e-01,
            3.100000e-01: 6.200000e-01
    }.items():
        yield case, had_mixture(x), id_chan, target

    def swap_map(x):
        S = (1j * x * W).expm()
        S._type = None
        S.dims = [[[2], [2]], [[2], [2]]]
        S.superrep = 'super'
        return S

    for x, target in {
            1.000000e-03: 2.000000e-03,
            3.100000e-03: 6.199997e-03,
            1.000000e-02: 1.999992e-02,
            3.100000e-02: 6.199752e-02,
            1.000000e-01: 1.999162e-01,
            3.100000e-01: 6.173918e-01
    }.items():
        yield case, swap_map(x), id_chan, target

    # Finally, we add a known case from Johnston's QETLAB documentation,
    # || Phi - I ||,_♢ where Phi(X) = UXU⁺ and U = [[1, 1], [-1, 1]] / sqrt(2).
    yield case, Qobj([[1, 1], [-1, 1]]) / np.sqrt(2), qeye(2), np.sqrt(2)
Exemple #10
0
def test_dnorm_qubit_known_cases():
    """
    Metrics: check agreement for known qubit channels.
    """
    def case(chan1, chan2, expected, significant=4):
        # We again take a generous tolerance so that we don't kill off
        # SCS solvers.
        assert_approx_equal(
            dnorm(chan1, chan2), expected,
            significant=significant
        )

    id_chan = to_choi(qeye(2))
    S_eye = to_super(id_chan)
    X_chan = to_choi(sigmax())
    depol = to_choi(Qobj(
        diag(ones((4,))),
        dims=[[[2], [2]], [[2], [2]]], superrep='chi'
    ))
    S_H = to_super(hadamard_transform())

    W = swap()

    # We need to restrict the number of iterations for things on the boundary,
    # such as perfectly distinguishable channels.
    yield case, id_chan, X_chan, 2
    yield case, id_chan, depol, 1.5

    # Next, we'll generate some test cases based on comparisons to pre-existing
    # dnorm() implementations. In particular, the targets for the following
    # test cases were generated using QuantumUtils for MATLAB (https://goo.gl/oWXhO9).

    def overrotation(x):
        return to_super((1j * np.pi * x * sigmax() / 2).expm())

    for x, target in {
        1.000000e-03: 3.141591e-03,
        3.100000e-03: 9.738899e-03,
        1.000000e-02: 3.141463e-02,
        3.100000e-02: 9.735089e-02,
        1.000000e-01: 3.128689e-01,
        3.100000e-01: 9.358596e-01
    }.items():
        yield case, overrotation(x), id_chan, target

    def had_mixture(x):
        return (1 - x) * S_eye + x * S_H

    for x, target in {
        1.000000e-03: 2.000000e-03,
        3.100000e-03: 6.200000e-03,
        1.000000e-02: 2.000000e-02,
        3.100000e-02: 6.200000e-02,
        1.000000e-01: 2.000000e-01,
        3.100000e-01: 6.200000e-01
    }.items():
        yield case, had_mixture(x), id_chan, target

    def swap_map(x):
        S = (1j * x * W).expm()
        S._type = None
        S.dims = [[[2], [2]], [[2], [2]]]
        S.superrep = 'super'
        return S

    for x, target in {
        1.000000e-03: 2.000000e-03,
        3.100000e-03: 6.199997e-03,
        1.000000e-02: 1.999992e-02,
        3.100000e-02: 6.199752e-02,
        1.000000e-01: 1.999162e-01,
        3.100000e-01: 6.173918e-01
    }.items():
        yield case, swap_map(x), id_chan, target

    # Finally, we add a known case from Johnston's QETLAB documentation,
    # || Phi - I ||,_♢ where Phi(X) = UXU⁺ and U = [[1, 1], [-1, 1]] / sqrt(2).
    yield case, Qobj([[1, 1], [-1, 1]]) / np.sqrt(2), qeye(2), np.sqrt(2)
ket_zero = qubit_states(N=1, states=[0])

print(ket_zero)
print("\n")

print(x * ket_zero)
print("\n")

print(tensor([identity(N=2), hadamard_transform(N=1)]))
print("\n")

print(snot(N=2, target=1))
print("\n")

print(swap(N=2, targets=[0, 1]))
print("\n")

print(cnot(N=2, control=0, target=1))
print("\n")

print(cnot(N=4, control=0, target=3))
print("\n")

print(hadamard_transform(N=2) * qubit_states(N=2, states=[0, 0]))
print("\n")

qc3 = QubitCircuit(N=3)
qc3.add_gate("CNOT", 1, 0)
qc3.add_gate("RX", 0, None, pi / 2, r"\pi/2")
qc3.add_gate("RY", 1, None, pi / 2, r"\pi/2")
Exemple #12
0
    # taking the trace
    f = uu.tr()
    # absolute value of the trace
    fi = abs(f)
    return fi


success_amt = []
n_trials = 100
opt_repeat = 5  #50
fid_check = []
g_check = []
for p in range(n_trials):
    # g_target = random_sample()
    # U_target = u_W_deltaa_T_g(W, deltaa, T, g_target)
    U_target = swap()
    fid_this_repeat = []
    g_this_repeat = []
    for q in range(opt_repeat):

        g0 = random(1)  # random_sample()

        def one_minus_fid_Utarg_Uofg(nelder_g):
            nelder_g_num = nelder_g[0]

            U_nelder = u_W_deltaa_T_g(W, deltaa, T, nelder_g_num)
            fi = 1 - fid_U_targ_U(U_target, U_nelder)
            return fi

        optim = minimize(one_minus_fid_Utarg_Uofg,
                         g0,