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
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)
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)
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()
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)
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)
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)
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()
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
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))
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)
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)
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)
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