Esempio n. 1
0
def period_helper(a, N, size):
    c1 = QubitPlaceholder()
    zero = QubitPlaceholder()
    x = QubitPlaceholder.register(size)
    b = QubitPlaceholder.register(size + 1)
    #takes in x and b as zero, finds
    p = Program()

    n = 2 * size
    def_regs = Program()
    period_regs = def_regs.declare('ro', 'BIT', n)

    #For one reg, we want H, CUA, R_i m_i, X^m_i
    for i in range(n - 1, -1, -1):
        R = Program()
        R += H(c1)
        for j in range(i - 1, -1, -1):
            k = i - j + 1
            doit = Program()
            doit += RK(k)(c1).dagger()
            R = Program().if_then(period_regs[j], doit, I(c1)) + R
        R += MEASURE(c1, period_regs[i])
        R += Program().if_then(period_regs[i], X(c1), I(c1))
        #R = Program(H(c1)) + R
        R = Program(H(c1)) + UA(c1, x, b, a**(2**i), N, zero) + R
        p = R + p
    p = write_in(1, x) + p
    p = def_regs + p
    p = get_defs() + p
    p = address_qubits(p)
    return p
Esempio n. 2
0
def test_placeholders_preserves_modifiers():
    cs = QubitPlaceholder.register(3)
    ts = QubitPlaceholder.register(1)

    g = X(ts[0])
    for c in cs:
        g = g.controlled(c).dagger()

    p = Program(g)
    a = address_qubits(p)

    assert a[0].modifiers == g.modifiers
def test_pauli_sum():
    q = QubitPlaceholder.register(8)
    q_plus = 0.5 * PauliTerm('X', q[0]) + 0.5j * PauliTerm('Y', q[0])
    the_sum = q_plus * PauliSum([PauliTerm('X', q[0])])
    term_strings = [str(x) for x in the_sum.terms]
    assert '(0.5+0j)*I' in term_strings
    assert len(term_strings) == 2
    assert len(the_sum.terms) == 2

    the_sum = q_plus * PauliTerm('X', q[0])
    term_strings = [str(x) for x in the_sum.terms]
    assert '(0.5+0j)*I' in term_strings
    assert len(term_strings) == 2
    assert len(the_sum.terms) == 2

    the_sum = PauliTerm('X', q[0]) * q_plus
    term_strings = [str(x) for x in the_sum.terms]
    assert '(0.5+0j)*I' in term_strings
    assert len(term_strings) == 2
    assert len(the_sum.terms) == 2

    with pytest.raises(ValueError):
        _ = PauliSum(sI(q[0]))
    with pytest.raises(ValueError):
        _ = PauliSum([1, 1, 1, 1])
    with pytest.raises(ValueError):
        _ = the_sum * []
def test_enumerate():
    q0, q1, q5 = QubitPlaceholder.register(3)
    term = PauliTerm("Z", q0, 1.0) * PauliTerm("Z", q1, 1.0) * PauliTerm(
        "X", q5, 5)
    position_op_pairs = [(q0, "Z"), (q1, "Z"), (q5, "X")]
    for key, val in term:
        assert (key, val) in position_op_pairs
def test_exponentiate_identity():
    q = QubitPlaceholder.register(11)
    mapping = {qp: Qubit(i) for i, qp in enumerate(q)}
    generator = PauliTerm("I", q[1], 0.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst()
    assert address_qubits(prog,
                          mapping) == address_qubits(result_prog, mapping)

    generator = PauliTerm("I", q[1], 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(
        [X(q[0]), PHASE(-1.0, q[0]),
         X(q[0]), PHASE(-1.0, q[0])])
    assert address_qubits(prog,
                          mapping) == address_qubits(result_prog, mapping)

    generator = PauliTerm("I", q[10], 0.08)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(
        [X(q[0]), PHASE(-0.08, q[0]),
         X(q[0]), PHASE(-0.08, q[0])])
    assert address_qubits(prog,
                          mapping) == address_qubits(result_prog, mapping)
Esempio n. 6
0
def test_exponentiate_3ns():
    # testing circuit for 3-terms non-sequential
    q = QubitPlaceholder.register(8)
    generator = (
        PauliTerm("Y", q[0], 1.0)
        * PauliTerm("I", q[1], 1.0)
        * PauliTerm("Y", q[2], 1.0)
        * PauliTerm("Y", q[3], 1.0)
    )
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(
        [
            RX(math.pi / 2.0, q[0]),
            RX(math.pi / 2.0, q[2]),
            RX(math.pi / 2.0, q[3]),
            CNOT(q[0], q[2]),
            CNOT(q[2], q[3]),
            RZ(2.0, q[3]),
            CNOT(q[2], q[3]),
            CNOT(q[0], q[2]),
            RX(-math.pi / 2.0, q[0]),
            RX(-math.pi / 2.0, q[2]),
            RX(-math.pi / 2.0, q[3]),
        ]
    )
    assert address_qubits(prog) == address_qubits(result_prog)
Esempio n. 7
0
def NN_encode(qubit: QubitPlaceholder,
              N: int) -> (Program, List[QubitPlaceholder]):

    ### qubit: qubit you want to encode (main qubit)
    ### N: number of qubits you want to encode the main qubit in.
    ### For N=1, there is no encoding

    code_register = QubitPlaceholder.register(
        N)  # the List[QubitPlaceholder] of the qubits you have encoded into
    code_register[0] = qubit

    pq = Program()

    ### creation of GHZ state:
    for ii in range(N - 1):
        pq += CNOT(code_register[ii], code_register[ii + 1])

    for jj in range(N - 1):
        pq += H(code_register[jj])
        pq += CZ(code_register[jj + 1], code_register[jj])

    for kk in range(N - 1):
        pq += CNOT(code_register[kk], code_register[-1])

    return pq, code_register
def test_operations_as_set():
    q = QubitPlaceholder.register(6)
    term_1 = PauliTerm("Z", q[0], 1.0) * PauliTerm("Z", q[1], 1.0) * PauliTerm(
        "X", q[5], 5)
    term_2 = PauliTerm("X", q[5], 5) * PauliTerm("Z", q[0], 1.0) * PauliTerm(
        "Z", q[1], 1.0)
    assert term_1.operations_as_set() == term_2.operations_as_set()
Esempio n. 9
0
    def detect_error(self, program, qubits):
        """
        Detects a bit-flip error on one of the three qubits in a logical qubit register.

        Parameters:
            program (Program): The program to add the error detection to
            qubits (list[QubitPlaceholder]): The logical qubit register to check for errors

        Returns:
            A MemoryReference list representing the parity measurements. The first one
            contains the parity of qubits 0 and 1, and the second contains the parity
            of qubits 0 and 2.
        """

        # The plan here is to check if q0 and q1 have the same parity (00 or 11), and if q0 and q2
        # have the same parity. If both checks come out true, then there isn't an error. Otherwise,
        # if one of the checks reveals a parity discrepancy, we can use the other check to tell us
        # which qubit is broken.
        
        parity_qubits = QubitPlaceholder.register(2)
        parity_measurement = program.declare("parity_measurement", "BIT", 2)

        # Check if q0 and q1 have the same value
        program += CNOT(qubits[0], parity_qubits[0])
        program += CNOT(qubits[1], parity_qubits[0])
        
        # Check if q0 and q2 have the same value
        program += CNOT(qubits[0], parity_qubits[1])
        program += CNOT(qubits[2], parity_qubits[1])

        # Measure the parity values and return the measurement register
        program += MEASURE(parity_qubits[0], parity_measurement[0])
        program += MEASURE(parity_qubits[1], parity_measurement[1])

        return parity_measurement
def test_commuting_sets():
    q = QubitPlaceholder.register(8)
    term1 = PauliTerm("X", q[0]) * PauliTerm("X", q[1])
    term2 = PauliTerm("Y", q[0]) * PauliTerm("Y", q[1])
    term3 = PauliTerm("Y", q[0]) * PauliTerm("Z", q[2])
    pauli_sum = term1 + term2 + term3
    commuting_sets(pauli_sum)
Esempio n. 11
0
    def correct_errors(self, program, qubits):
        """
        Corrects any errors that have occurred within the logical qubit register.

        Parameters:
            program (Program): The program to add the error correction to
            qubits (list[QubitPlaceholder]): The logical qubit register to check and correct
        """

        parity_qubits = QubitPlaceholder.register(3)
        parity_measurement = program.declare("parity_measurement", "BIT", 3)

        # Correct bit flips
        self.detect_bit_flip_error(program, qubits, parity_qubits,
                                   parity_measurement)
        self.generate_classical_control_corrector(program, qubits,
                                                  parity_measurement, X)
        for qubit in parity_qubits:
            program += RESET(qubit)

        # Correct phase flips
        self.detect_phase_flip_error(program, qubits, parity_qubits,
                                     parity_measurement)
        self.generate_classical_control_corrector(program, qubits,
                                                  parity_measurement, Z)
def test_check_commutation_rigorous():
    # more rigorous test.  Get all operators in Pauli group
    p_n_group = ("I", "X", "Y", "Z")
    pauli_list = list(product(p_n_group, repeat=3))
    pauli_ops = [
        list(zip(x, QubitPlaceholder.register(3))) for x in pauli_list
    ]
    pauli_ops_pq = [
        reduce(mul, (PauliTerm(*x) for x in op)) for op in pauli_ops
    ]

    non_commuting_pairs = []
    commuting_pairs = []
    for x in range(len(pauli_ops_pq)):
        for y in range(x, len(pauli_ops_pq)):

            tmp_op = _commutator(pauli_ops_pq[x], pauli_ops_pq[y])
            assert len(tmp_op.terms) == 1
            if is_zero(tmp_op.terms[0]):
                commuting_pairs.append((pauli_ops_pq[x], pauli_ops_pq[y]))
            else:
                non_commuting_pairs.append((pauli_ops_pq[x], pauli_ops_pq[y]))

    # now that we have our sets let's check against our code.
    for t1, t2 in non_commuting_pairs:
        assert not check_commutation([t1], t2)

    for t1, t2 in commuting_pairs:
        assert check_commutation([t1], t2)
Esempio n. 13
0
    def test_multi_control(self):
        """
        Tests entanglement with more than one control qubit.

        NOTE: This will currently fail because pyQuil has a bug with controlled gates
        and QubitPlaceholder: https://github.com/rigetti/pyquil/issues/905
        Once that gets fixed, I'll revisit this function.
        """

        # Construct the program and the qubits - we're going to use 2 separate registers,
        # where one will be a bunch of control qubits and the other will be a single target
        # qubit.
        valid_states = [
            "0000", "0010", "0100", "0110", "1000", "1010", "1100", "1111"
        ]
        controls = QubitPlaceholder.register(len(valid_states[0]) - 1)
        target = QubitPlaceholder()
        program = Program()

        # Hadamard the first three qubits - these will be the controls
        for control in controls:
            program += H(control)

        # pyQuil supports gates that are controlled by arbitrary many qubits, so
        # we don't need to mess with Toffoli gates or custom multi-control implementations.
        # We just have to chain a bunch of controlled() calls for each control qubit.
        gate = X(target)
        for control in controls:
            gate = gate.controlled(control)
        program += gate

        # Run the test
        self.run_test("multi-controlled operation", program,
                      controls + [target], 1000, valid_states)
Esempio n. 14
0
def controlled_modular_multiply(ancilla_cache, program, control, constant,
                                modulus, multiplier):
    """
    This function implements the operation (A*B mod C), where A and C are constants,
    and B is a qubit register representing a little-endian integer.

    Remarks:
        See the Q# source for the "ModularMultiplyByConstantLE" function at
        https://github.com/Microsoft/QuantumLibraries/blob/master/Canon/src/Arithmetic/Arithmetic.qs
    """

    summand = None
    if not "summand" in ancilla_cache:
        summand = QubitPlaceholder.register(len(multiplier))
        ancilla_cache["summand"] = summand
    else:
        summand = ancilla_cache["summand"]

    program += controlled_modular_add_product(ancilla_cache, control, constant,
                                              modulus, multiplier, summand)

    for i in range(0, len(multiplier)):
        program += CSWAP(control, summand[i], multiplier[i])

    inverse_mod_value = inverse_mod(constant, modulus)

    program += controlled_modular_add_product(ancilla_cache, control,
                                              inverse_mod_value, modulus,
                                              multiplier, summand).dagger()
Esempio n. 15
0
def test_simplify_term_single():
    q0, q1, q2 = QubitPlaceholder.register(3)
    term = (
        PauliTerm("Z", q0) * PauliTerm("I", q1) * PauliTerm("X", q2, 0.5j) * PauliTerm("Z", q0, 1.0)
    )
    assert term.id() == "X{}".format(q2)
    assert term.coefficient == 0.5j
Esempio n. 16
0
def run_function_in_classical_mode(function, input):
    """
    Runs the given function on the provided input, returning the results.
	The function will not be run on a superposition on the input, the input
	state will directly match what is provided here; thus, this is basically
	just running the function classically.

    Parameters:
        function (function): The black-box function to run the algorithm on (the function being
	        evaluated). It should take a Program as its first input, an input list[QubitPlaceholder]
            as its second argument, and an output list[QubitPlaceholder] as its third argument.

        input (list[bool]): The bit string you want to provide as input to the function

    Returns:
        A bit string representing the measured result of the function.
    """

    # Construct the program and registers
    input_size = len(input)
    input_register = QubitPlaceholder.register(input_size)
    output = QubitPlaceholder.register(input_size)
    program = Program()

    # Sets up the input register so it has the requested input state,
    # and runs the function on it.
    for i in range(0, input_size):
        if input[i]:
            program += X(input_register[i])
    function(program, input_register, output)

    measurement = program.declare("ro", "BIT", input_size)
    for i in range(0, input_size):
        program += MEASURE(output[i], measurement[i])

    # Run the program
    assigned_program = address_qubits(program)
    computer = get_qc(f"{input_size * 2}q-qvm", as_qvm=True)
    executable = computer.compile(assigned_program)
    results = computer.run(executable)

    # Return the measurement as a list[bool] for classical postprocessing
    for result in results:
        measurement = [False] * input_size
        for i in range(0, input_size):
            measurement[i] = (result[i] == 1)
        return measurement
def test_exponentiate_commuting_pauli_sum():
    q = QubitPlaceholder.register(8)
    pauli_sum = PauliSum(
        [PauliTerm('Z', q[0], 0.5),
         PauliTerm('Z', q[1], 0.5)])
    prog = Program().inst(RZ(1., q[0])).inst(RZ(1., q[1]))
    result_prog = exponentiate_commuting_pauli_sum(pauli_sum)(1.)
    assert address_qubits(prog) == address_qubits(result_prog)
def test_simplify_terms():
    q = QubitPlaceholder.register(1)
    term = PauliTerm('Z', q[0]) * -1.0 * PauliTerm('Z', q[0])
    assert term.id() == ''
    assert term.coefficient == -1.0

    term = PauliTerm('Z', q[0]) + PauliTerm('Z', q[0], 1.0)
    assert str(term).startswith('(2+0j)*Zq')
def test_ids_no_sort():
    q = QubitPlaceholder.register(6)
    term_1 = PauliTerm("Z", q[0], 1.0) * PauliTerm("Z", q[1], 1.0) * PauliTerm(
        "X", q[5], 5)
    term_2 = PauliTerm("X", q[5], 5) * PauliTerm("Z", q[0], 1.0) * PauliTerm(
        "Z", q[1], 1.0)
    assert re.match('Z.+Z.+X.+', term_1.id(sort_ops=False))
    assert re.match('X.+Z.+Z.+', term_2.id(sort_ops=False))
Esempio n. 20
0
def test_get_qubits():
    q = QubitPlaceholder.register(2)
    term = PauliTerm("Z", q[0]) * PauliTerm("X", q[1])
    assert term.get_qubits() == q

    q10 = QubitPlaceholder()
    sum_term = PauliTerm("X", q[0], 0.5) + 0.5j * PauliTerm("Y", q10) * PauliTerm("Y", q[0], 0.5j)
    assert sum_term.get_qubits() == [q[0], q10]
def test_exponentiate_1():
    # test rotation of single qubit
    q = QubitPlaceholder.register(8)
    generator = PauliTerm("Z", q[0], 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(RZ(2.0, q[0]))
    assert address_qubits(prog) == address_qubits(result_prog)
Esempio n. 22
0
def test_ids():
    q = QubitPlaceholder.register(6)
    term_1 = PauliTerm("Z", q[0], 1.0) * PauliTerm("Z", q[1], 1.0) * PauliTerm("X", q[5], 5)
    term_2 = PauliTerm("X", q[5], 5) * PauliTerm("Z", q[0], 1.0) * PauliTerm("Z", q[1], 1.0)
    # Not sortable
    with pytest.raises(TypeError):
        with pytest.warns(FutureWarning):
            term_1.id() == term_2.id()
def test_simplify_warning():
    q = QubitPlaceholder.register(8)
    t1 = sZ(q[0]) * sZ(q[1])
    t2 = sZ(q[1]) * sZ(q[0])
    with pytest.warns(UserWarning) as e:
        tsum = t1 + t2

    assert tsum == 2 * sZ(q[0]) * sZ(q[1])
    assert 'will be combined with' in str(e[0].message)
Esempio n. 24
0
def test_simplify_term_multindex():
    q0, q2 = QubitPlaceholder.register(2)
    term = (
        PauliTerm("X", q0, coefficient=-0.5)
        * PauliTerm("Z", q0, coefficient=-1.0)
        * PauliTerm("X", q2, 0.5)
    )
    assert term.id(sort_ops=False) == "Y{q0}X{q2}".format(q0=q0, q2=q2)
    assert term.coefficient == -0.25j
def test_ids():
    q = QubitPlaceholder.register(6)
    term_1 = PauliTerm("Z", q[0], 1.0) * PauliTerm("Z", q[1], 1.0) * PauliTerm(
        "X", q[5], 5)
    term_2 = PauliTerm("X", q[5], 5) * PauliTerm("Z", q[0], 1.0) * PauliTerm(
        "Z", q[1], 1.0)
    with pytest.raises(TypeError):
        # Not sortable
        t = term_1.id() == term_2.id()
def test_check_commutation():
    q = QubitPlaceholder.register(8)
    term1 = PauliTerm("X", q[0]) * PauliTerm("X", q[1])
    term2 = PauliTerm("Y", q[0]) * PauliTerm("Y", q[1])
    term3 = PauliTerm("Y", q[0]) * PauliTerm("Z", q[2])
    # assert check_commutation(PauliSum([term1]), term2)
    assert check_commutation([term2], term3)
    assert check_commutation([term2], term3)
    assert not check_commutation([term1], term3)
Esempio n. 27
0
def test_exponentiate_bp1_XZ():
    # testing change of basis position 1
    q = QubitPlaceholder.register(8)
    generator = PauliTerm("Z", q[0], 1.0) * PauliTerm("X", q[1], 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(
        [H(q[1]), CNOT(q[0], q[1]), RZ(2.0, q[1]), CNOT(q[0], q[1]), H(q[1])]
    )
    assert address_qubits(prog) == address_qubits(result_prog)
def test_ordered():
    q = QubitPlaceholder.register(8)
    mapping = {x: i for i, x in enumerate(q)}
    term = sZ(q[3]) * sZ(q[2]) * sZ(q[1])
    prog = address_qubits(exponential_map(term)(0.5), mapping)
    assert prog.out() == "CNOT 3 2\n" \
                         "CNOT 2 1\n" \
                         "RZ(1.0) 1\n" \
                         "CNOT 2 1\n" \
                         "CNOT 3 2\n"
def test_sum_power():
    q = QubitPlaceholder.register(8)
    pauli_sum = (sY(q[0]) - sX(q[0])) * (1.0 / np.sqrt(2))
    assert pauli_sum**2 == PauliSum([sI(q[0])])
    with pytest.raises(ValueError):
        _ = pauli_sum**-1
    pauli_sum = sI(q[0]) + sI(q[1])
    assert pauli_sum**0 == sI(q[0])
    # Test to make sure large powers can be computed
    pauli_sum**400
def test_term_powers():
    for qubit in QubitPlaceholder.register(2):
        pauli_terms = [sI(qubit), sX(qubit), sY(qubit), sZ(qubit)]
        for pauli_term in pauli_terms:
            assert pauli_term**0 == sI(qubit)
            assert pauli_term**1 == pauli_term
            assert pauli_term**2 == sI(qubit)
            assert pauli_term**3 == pauli_term
    with pytest.raises(ValueError):
        pauli_terms[0]**-1