Exemple #1
0
def test_maxima_first_coherent_information_dephrasure():
    r""" Test maxima of first coh-info of dephrasure channel is mixed state and matches paper."""
    def optima_mixed_state_bound(p):
        # Bound for when coherent information is maximized by maximally mixed state.
        a = (1. - 2. * p - 2. * p * (1. - p) * np.log((1. - p) / p))
        return a / (2. - 4. * p - 2. * p * (1. - p) * np.log((1. - p) / p))

    desired = np.array([[0.5, 0.], [0., 0.5]])
    for p in np.arange(0.01, 0.5, 0.1):
        for q in np.arange(0., optima_mixed_state_bound(p), 0.1):
            # Set up actual results.
            single_krauss_ops = set_up_dephrasure_conditions(p, q)
            channel = AnalyticQChan(single_krauss_ops, [1, 1], 2, 3, [2])
            actual = channel.optimize_coherent(n=1,
                                               rank=2,
                                               param="overparam",
                                               maxiter=15)

            # Test optimal coherent information value.
            desired_fun = (1. - 2. * q) * (-np.log2(0.5)) - (1. - q) * \
                (-(1 - p) * np.log2(1 - p) - p * np.log2(p))
            assert np.abs(actual["optimal_val"] - desired_fun) < 1e-5

            # Test optimal density state is the maximally mixed state.
            assert_array_almost_equal(desired,
                                      actual["optimal_rho"],
                                      decimal=3)
Exemple #2
0
def test_optimizing_coherent_information_bit_flip_channels_only_on_one_case():
    r"""Test optimizing once coherent information with an analytic example for bit-flip channel."""
    err = 0.1
    krauss_1 = np.array([[1., 0.], [0., 1]],
                        dtype=np.complex128) * np.sqrt(1 - err)
    krauss_2 = np.array([[0., 1], [1., 0.]],
                        dtype=np.complex128) * np.sqrt(err)
    krauss_ops = [krauss_1, krauss_2]
    desired = 1 + np.log2(err) * err + np.log2(1 - err) * (1 - err)

    # Kraus Operators
    for n in range(1, 3):
        channel = AnalyticQChan(krauss_ops, [1, 1], 2, 2)
        actual = channel.optimize_coherent(n=n,
                                           rank=2**n,
                                           param="cholesky",
                                           maxiter=100,
                                           regularized=True)
        assert np.abs(actual["optimal_val"] - desired) < 1e-3
    # Test downgrading a n.
    actual = channel.optimize_coherent(n=1,
                                       rank=2,
                                       param="overparam",
                                       maxiter=100)
    assert np.abs(actual["optimal_val"] - desired) < 1e-3

    # Choi matrices
    choi_mat = sum([
        np.outer(np.ravel(x, order="F"), np.conj(np.ravel(x, order="F")))
        for x in krauss_ops
    ])
    chan = AnalyticQChan(choi_mat, [1, 1], 2, 2)
    actual = chan.optimize_coherent(n=1,
                                    rank=2,
                                    param="overparam",
                                    maxiter=100)
    assert np.abs(actual["optimal_val"] - desired) < 1e-3
    assert_raises(AssertionError, chan.optimize_coherent, 2, 2)
Exemple #3
0
def compare_lipschitz_slsqp_with_diffev():
    n = 3
    for p in np.arange(0.05, 0.5, 0.01):
        for q in np.arange(0.3, 0.5, 0.01):
            single_krauss_ops = set_up_dephrasure_conditions(p, q)
            orthogonal_krauss_indices = [2]

            channel = AnalyticQChan(single_krauss_ops, [1, 1], 2, 3,
                                    orthogonal_krauss_indices)

            diffev = channel.optimize_coherent(n,
                                               2**n,
                                               "diffev",
                                               maxiter=500,
                                               lipschitz=10)
            slsqp = channel.optimize_coherent(n,
                                              2**n,
                                              "slsqp",
                                              lipschitz=20,
                                              maxiter=100,
                                              use_pool=True)

            # Test optimal coherent information is the same inbetween both of them.
            assert np.abs(diffev["optimal_val"] - slsqp["optimal_val"]) < 1e-3
Exemple #4
0
def test_optimizing_coherent_information_with_erasure_channel():
    r""" Test optimizing coherent information with an analytic example for erasure channel."""
    for err in np.arange(0.01, 1., 0.01):
        krauss_1 = np.sqrt(1 - err) * np.array([[1., 0.], [0., 1.], [0., 0.]])
        krauss_2 = np.sqrt(err) * np.array([[0., 0.], [0., 0.], [0., 1.]])
        krauss_3 = np.sqrt(err) * np.array([[0., 0.], [0., 0.], [1., 0.]])
        krauss_ops = [krauss_1, krauss_3, krauss_2]

        channel = AnalyticQChan(krauss_ops, [1, 1], 2, 3)
        actual = channel.optimize_coherent(n=1,
                                           rank=2,
                                           param="cholesky",
                                           maxiter=50)
        desired = 1. - err * 2.
        if err > 0.5:
            desired = 0.
        assert np.abs(actual["optimal_val"] - desired) < 1e-5
Exemple #5
0
def test_optimizing_coherent_information_bit_flip_channels():
    r"""Test optimizing coherent information with an analytic example for bit-flip channel."""
    for err in np.arange(0.01, 1., 0.01):
        krauss_1 = np.array([[1., 0.], [0., 1]],
                            dtype=np.complex128) * np.sqrt(1 - err)
        krauss_2 = np.array([[0., 1], [1., 0.]],
                            dtype=np.complex128) * np.sqrt(err)
        krauss_ops = [krauss_1, krauss_2]

        channel = AnalyticQChan(krauss_ops, [1, 1], 2, 2)
        actual = channel.optimize_coherent(n=1,
                                           rank=2,
                                           param="cholesky",
                                           maxiter=50)

        desired = 1 + np.log2(err) * err + np.log2(1 - err) * (1 - err)
        print(err, desired, actual["optimal_val"])
        assert np.abs(actual["optimal_val"] - desired) < 1e-3
Exemple #6
0
def test_optimizing_coherent_information_erasure_using_choi_matrix():
    r"""Test optimizing coherent information with an analytic example for erasure channel."""
    for err in np.arange(0.01, 1., 0.01):
        krauss_1 = np.sqrt(1 - err) * np.array([[1., 0.], [0., 1.], [0., 0.]])
        krauss_2 = np.sqrt(err) * np.array([[0., 0.], [0., 0.], [0., 1.]])
        krauss_3 = np.sqrt(err) * np.array([[0., 0.], [0., 0.], [1., 0.]])
        krauss_ops = [krauss_1, krauss_3, krauss_2]
        choi = sum([
            np.outer(np.ravel(x, order="F"), np.conj(np.ravel(x, order="F")))
            for x in krauss_ops
        ])

        channel = AnalyticQChan(choi, numb_qubits=[1, 1], dim_in=2, dim_out=3)
        actual = channel.optimize_coherent(1, 2, param="cholesky", maxiter=50)

        desired = 1. - err * 2.
        if err > 0.5:
            desired = 0.
        assert np.abs(actual["optimal_val"] - desired) < 1e-3
Exemple #7
0
def effective_channel_with_stabilizers(stabilizer,
                                       code_param,
                                       pauli_errors,
                                       optimize="coherent",
                                       sparse=False,
                                       options=None):
    r"""
    Calculate the effective channel with respect to a set of pauli-errors and stabilizer elements.

    Parameters
    ----------
    stabilizer : list
        List of strings representing stabilizer elements.
    code_param : tuple
        A tuple (n, k) where n is the number of encoded qubits and k is the number of logical
        qubits.
    pauli_errors : list
        List of krauss operators as numpy arrays that are scalar multiples of the pauli group and
        hence represent a Pauli Channel.
    optimize : str
        If optimize is "coherent" (default), then it optimizes the coherent information.
        If optimize is "fidelity", then it optimizes the minimum fidelity.
    sparse : bool
        If True, then pauli elements of stabilizer code are sparse.
    options : None or dict
        Dictionary of parameters for 'AnalyticQCodes.optimize_coherent' and
        'AnalyticQCodes.optimize_fidelity' optimizations procedures. Should have parameters,
        'param' : str
            Parameterization of density matrix, default is 'overparam'. Can also be 'cholesky.'
            Can also provide own's own parameterization by being a subclass of ParameterizationABC.
        'lipschitz': int
            Integer of number of samplers to be used for lipschitz sampler. Default is 50
        'use_pool' : int
            The number of pool proccesses to be used by the multiprocessor library. Default is 3.
        'maxiter' : int
            Maximum number of iterations. Default is 500.
        'samples' : list, optional
            List of vectors that satisfy the parameterization from "param", that are served as
            initial guesses for the optimization procedure. Optional, unless 'lipschitz' is zero.

    Returns
    -------
    dict :
        The result is a dictionary with fields:

            optimal_rho : np.ndarray
                The density matrix of the optimal solution.
            optimal_val : float
                The optimal value of either coherent information or fidelity.
            method : str
                Either diffev or slsqp.
            success : bool
                True if optimizer converges.
            objective : str
                Either coherent or fidelity
            lipschitz : bool
                True if uses lipschitz properties to find initial guesses.

    """
    if not isinstance(optimize, str):
        raise TypeError("Optimize should be a string.")
    if not (optimize == "coherent" or optimize == "fidelity"):
        raise TypeError("Optimize should either be coherent or fidelity.")
    if 2**code_param[1] != pauli_errors[0].shape[1]:
        raise TypeError(
            "Number of Columns of Pauli error does not match 2**k.")

    # Parameters for optimization
    # TODO: add coherent information parameters.

    # Set up the objects, stabilizer code, pauli-channel error, respectively.
    stab = StabilizerCode(stabilizer, code_param[0], code_param[1])

    # Figure out the dimensions of channel later.
    error_chan = AnalyticQChan(pauli_errors, [1, 1], 2, 2, sparse=sparse)
    error_chan.krauss.update_kraus_operators(code_param[0] // code_param[1])

    # Get Kraus Operator for encoder.
    encoder = stab.encode_krauss_operators()

    # Get the kraus operators for the stabilizers that anti-commute with each kraus operator.
    kraus = stab.kraus_operators_correcting_errors(
        error_chan.krauss.nth_kraus_ops, sparse=sparse)
    # Multiply by the encoder to get the full approximate error-correcting.
    kraus = [x.dot(encoder) for x in kraus]

    # Construct new kraus operators.
    total_chan = AnalyticQChan(kraus, [code_param[1], code_param[0]],
                               2,
                               2,
                               sparse=True)

    # Solve the objective function
    if optimize == "coherent":
        result = total_chan.optimize_coherent(n=1,
                                              rank=2,
                                              optimizer="slsqp",
                                              param="overparam",
                                              lipschitz=25,
                                              use_pool=3,
                                              maxiter=250)
    else:
        result = total_chan.optimize_fidelity(n=1,
                                              optimizer="slsqp",
                                              param="overparam",
                                              lipschitz=25,
                                              use_pool=3,
                                              maxiter=250)
    return result