def test_collision_probability():
    """
    Test cases for the collision probability algorithm
    Returns True if passed all test cases, otherwise returns False
    """
    print("Testing: collision probability algorithm")
    # n = number of qubits, m = size of qubit gate
    for n in range(1, 10):
        # sim1 is fast and sim2 is slow, as sim2 uses exponential
        # storage and runtime
        sim1 = chp_py.CHP_Simulation(n)
        sim2 = slow_sim.Slow_Simulation(n)

        for m in range(1, min(n, 5)):
            for j in range(100):
                # Get a random symplectic of size 2m x 2m
                i = np.random.randint(symplectic.numberofsymplectic(m))
                S = symplectic.symplectic(i, m)
                S = decompose.transform_symplectic(S)

                # Get m random qubits
                qubits = np.arange(m)
                np.random.shuffle(qubits)
                qubits = qubits[:m]

                # Get the gates and matrix represention of S
                gates = decompose.decompose_state(chp_py.CHP_Simulation(m, S))
                gates = decompose.change_gates(gates, qubits)

                decompose.apply_gates(gates, sim1)
                decompose.apply_gates(gates, sim2)

                k_1 = int(-sim1.log_collision_probability)
                k_2 = np.round(-np.log2(sim2.collision_probability))
                result = (k_1 == k_2)

                if not result:
                    print("Failed: collision probability algorithm returned " +
                          "incorrect result with n = " + str(n) + " and m = " +
                          str(m))
                    return False

    print("Passed: collision probability algorithm passed all tests\n")
    return True
def test_chp_py():
    """
    Test cases for the functions in chp_py.py
    Returns True if passed all test cases, otherwise returns False
    """
    print("Testing: chp_py.py")
    # n = number of qubits, m = size of qubit gate
    for n in range(1, 50):
        # Create two simulations
        # sim1 uses decomposed gates and sim2 uses matrix multiplication
        # apply 100 random gates to each one
        sim1 = chp_py.CHP_Simulation(n)
        sim2 = chp_py.CHP_Simulation(n)

        for m in range(1, min(n, 5)):
            for j in range(100):
                # Get a random symplectic of size 2m x 2m
                i = np.random.randint(symplectic.numberofsymplectic(m))
                S = symplectic.symplectic(i, m)
                S = decompose.transform_symplectic(S)

                # Get m random qubits
                qubits = np.arange(m)
                np.random.shuffle(qubits)
                qubits = qubits[:m]

                # Get the gates and matrix represention of S
                gates = decompose.decompose_state(chp_py.CHP_Simulation(m, S))
                gates = decompose.change_gates(gates, qubits)
                M = decompose.symplectic_to_matrix(S, n, qubits)

                sim1.apply_gates(gates)
                sim2.state = (sim2.state @ M) % 2
                result = (sim1.state == sim2.state).all()

                if not result:
                    print("Failed: found two simulations with different " +
                          "states for n = " + str(n))
                    return False

    print("Passed: chp_py.py passed all tests\n")
    return True
Exemple #3
0
def simulate_qubit_pairs_1D_lattice(n, m):
    """
    Simulates a set of qubits in a 1D lattice of n qubits
    Performs two seperate rounds when applying gates
    to ensure that the depth of the circuit is accurate
    Runs the simulation a total of m times and returns the mean
    and std in the data dictionary
    """
    # Initialize some variables
    x_max = 2 * n
    d = np.linspace(0, x_max, 50, dtype=int)
    k_matrix = np.zeros((m, len(d)))

    # Run the simulation a total of m times
    for i in range(m):
        start = time.time()

        sim = chp_py.CHP_Simulation(n)
        sims = []
        # Add a sim for depth 0
        sims.append(chp_py.CHP_Simulation(n, sim.state))

        for j in range(0, d[-1]):
            gates = utils.get_lattice_gates((n, ), j)
            sim.apply_gates(gates)

            if j + 1 in d:
                sims.append(chp_py.CHP_Simulation(n, sim.state))

        # This computes the collision_probability at different
        # depths in parallel
        k_matrix[i, :] = utils.sims_to_collision_probabilty(sims)

        end = time.time()
        print("Time elapsed = {:0.2f}, for sample = {}".format(end - start, i))

    # Store everything in data
    data = {"d": d, "k_matrix": k_matrix, "n": n, "m": m}

    return data
Exemple #4
0
def simulate_complete_graph(n, m):
    """
    Simulates qubits in a complete graph of n qubits
    Find k as a function of N = number of gates applied
    Performs simulation a total of m times then returns mean and std
    """
    x_max = 2 * n * np.log(n)
    N = np.linspace(0, x_max, 50, dtype=int)
    k_matrix = np.zeros((m, len(N)))

    # Run the simulation a total of m times
    for i in range(m):
        start = time.time()

        sim = chp_py.CHP_Simulation(n)
        sims = []
        # Add a sim for N = 0
        sims.append(chp_py.CHP_Simulation(n, sim.state))

        for j in range(0, N[-1]):
            qubits = np.arange(n)
            np.random.shuffle(qubits)
            q_1, q_2 = qubits[:2]
            gates = utils.get_random_two_qubit_gate(q_1, q_2)
            sim.apply_gates(gates)

            if j + 1 in N:
                sims.append(chp_py.CHP_Simulation(n, sim.state))

        # This computes the collision_probability at different
        # depths in parallel
        k_matrix[i, :] = utils.sims_to_collision_probabilty(sims)

        end = time.time()
        print("Time elapsed = {:0.2f}, for sample = {}".format(end - start, i))

    # Store everything in data
    data = {"N": N, "k_matrix": k_matrix, "n": n, "m": m}

    return data
def test_decompose():
    """
    Test cases for the functions in decompose.py
    Returns True if passed all test cases, otherwise returns False
    """
    print("Testing: decompose.py")

    for n in range(1, 6):
        top = np.hstack((np.zeros((n, n)), np.identity(n)))
        bottom = np.hstack((np.identity(n), np.zeros((n, n))))
        L = np.vstack((top, bottom))

        for j in range(500):
            # Get a random symplectic
            i = np.random.randint(symplectic.numberofsymplectic(n))
            S = symplectic.symplectic(i, n)
            S = decompose.transform_symplectic(S)

            # Make sure the transformation worked
            result = (S.T @ L @ S) % 2
            result = ((result == L).all())
            if not result:
                print("Failed: could not transform symplectic " +
                      "matrix with (n, i)= " + str((n, i)))
                return False

            # Make sure we can decompose it
            # Applying the decomposed gates to the identity should give us S
            gates = decompose.decompose_state(chp_py.CHP_Simulation(n, S))
            new_sim = chp_py.CHP_Simulation(n)
            new_sim.apply_gates(gates)
            result = (new_sim.state == S).all()

            if not result:
                print("Failed: found a bad decomposition for " +
                      "symplectic matrix with (n, i)= " + str((n, i)))
                return False

    print("Passed: decompose.py passed all tests\n")
    return True
Exemple #6
0
def simulate_qubit_pairs_2D_lattice(sqrt_n, m):
    """
    Simulates a set of qubits in a 2D square lattice of shape
    sqrt_n x sqrt_n. Performs four seperate rounds when applying gates
    to ensure that the depth of the circuit is accurate
    Runs the simulation a total of m times and returns the mean
    and std in the data dictionary
    """
    # Initialize some variables
    n = np.power(sqrt_n, 2)
    x_max = 35
    d = np.arange(0, x_max + 1)
    k_matrix = np.zeros((m, x_max + 1))

    # Run the simulation a total of m times
    for i in range(m):
        start = time.time()

        sim = chp_py.CHP_Simulation(n)
        sims = []
        # Add a sim for depth 0
        sims.append(chp_py.CHP_Simulation(n, sim.state))

        for j in range(x_max):
            gates = utils.get_lattice_gates((sqrt_n, sqrt_n), j)
            sim.apply_gates(gates)
            sims.append(chp_py.CHP_Simulation(n, sim.state))

        # This computes the collision_probability at different
        # depths in parallel
        k_matrix[i, :] = utils.sims_to_collision_probabilty(sims)

        end = time.time()
        print("Time elapsed = {:0.2f}, for sample = {}".format(end - start, i))

    # Store everything in data
    data = {"d": d, "k_matrix": k_matrix, "n": n, "m": m}

    return data
Exemple #7
0
def store_all_two_qubit_gates():
    m = 2
    qubit_gates = dict()
    qubit_matrices = dict()

    for i in range(symplectic.numberofsymplectic(m)):
        S = symplectic.symplectic(i, m)
        S = decompose.transform_symplectic(S)
        gates = decompose.decompose_state(chp_py.CHP_Simulation(m, S))
        qubit_gates[i] = gates
        qubit_matrices[i] = S

    save_data(qubit_gates, "two_qubit_gates")
    save_data(qubit_matrices, "two_qubit_matrices")
def test_stored_two_qubit_gates():
    """
    Test cases for the stored two_qubit_gates
    Returns True if passed all test cases, otherwise returns False
    """
    print("Testing: stored two qubit gates")
    utils.store_all_two_qubit_gates()
    two_qubit_gates = utils.load_data("two_qubit_gates")
    two_qubit_matrices = utils.load_data("two_qubit_matrices")

    matrices = set()
    for i in two_qubit_gates:
        # Make sure the gates and matrices have the same effect
        gates = two_qubit_gates[i]
        M = two_qubit_matrices[i]

        sim1 = chp_py.CHP_Simulation(2)
        sim1.apply_gates(gates)

        # Also store the matrices in a set
        M_string = str(M.flatten())
        matrices.add(M_string)

        result = (sim1.state == M).all()
        if not result:
            print("Failed: two qubit gates do not agree with " +
                  "two qubit matrix for i = " + str(i))
            return False

    # Make sure we have the right number of unique matrices
    result = (len(matrices) == symplectic.numberofsymplectic(2))
    if not result:
        print("Failed: did not find the correct number of unique " +
              "two qubit matrices")
        return False

    print("Passed: stored two qubit gates passed all tests\n")
    return True