def rus_single(input, theta): reg = list() reg.append(input) reg.append(QubitPlaceholder()) reg.append(QubitPlaceholder()) # Gates and classical memory preparation prep_pq = Program() prep_pq += dg_cry prep_pq += dg_cy acl_ro = prep_pq.declare('acl_ro', 'BIT', 1) # Rotation gates rot_pq = Program() rot_pq += CRY(2 * theta)(reg[0], reg[1]) rot_pq += CY(reg[1], reg[2]) rot_pq += RZ(-np.pi / 2, reg[1]) rot_pq += CRY(2 * theta)(reg[0], reg[1]) # Ancilla bit measurement pq = Program() pq += prep_pq pq += rot_pq pq += MEASURE(reg[1], acl_ro) # Repeated circuit rep_pq = Program() # rep_pq += RESET(reg[1]) rep_pq += RY(-np.pi / 2, reg[2]) rep_pq += rot_pq rep_pq += MEASURE(reg[1], acl_ro) pq.while_do(acl_ro, rep_pq) return pq, reg[2]
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_alloc_new(): p = Program() q0 = QubitPlaceholder() p.inst(H(q0)) # H 0 q1 = QubitPlaceholder() q2 = QubitPlaceholder() p.inst(CNOT(q1, q2)) # CNOT 1 3 qxxx = QubitPlaceholder() p.inst(H(qxxx)) q3 = QubitPlaceholder() p.inst(X(q3)) # X 4 p = address_qubits(p, { q1: 1, q2: 3, q3: 4, q0: 0, qxxx: 2, }) assert p.out() == "H 0\n" \ "CNOT 1 3\n" \ "H 2\n" \ "X 4\n"
def rus(inputs, w, b): in_reg = list() for i in inputs: in_reg.append(i) an_reg = list() an_reg.append(QubitPlaceholder()) an_reg.append(QubitPlaceholder()) # Gates and classical memory preparation prep_pq = Program() acl_ro = prep_pq.declare('acl_{}_ro'.format(an_reg[0]), 'BIT', 1) # Rotation gates rot_linear_pq = Program() for i in range(len(w)): rot_linear_pq += CRY(w[i])(in_reg[i], an_reg[0]) rot_linear_pq += RY(b, an_reg[0]) rot_pq = Program() rot_pq += rot_linear_pq rot_pq += CY(an_reg[0], an_reg[1]) rot_pq += RZ(-np.pi / 2, an_reg[0]) rot_pq += rot_linear_pq # Ancilla bit measurement pq = Program() pq += prep_pq pq += rot_pq pq += MEASURE(an_reg[0], acl_ro) # Repeated circuit rep_pq = Program() # rep_pq += RESET(reg[1]) rep_pq += RY(-np.pi / 2, an_reg[1]) rep_pq += rot_pq rep_pq += MEASURE(an_reg[0], acl_ro) pq.while_do(acl_ro, rep_pq) return pq, an_reg[1]
def run_test(self, description, iterations, buffer): """ Runs the superdense coding algorithm on the given classical buffer. Parameters: description (str): A description of the test, for logging. iterations (int): The number of times to run the program. buffer (list[Bool]): The buffer containing the two bits to send. """ # Construct the registers print(f"Running test: {description}") pair_a = QubitPlaceholder() pair_b = QubitPlaceholder() # Entangle the qubits together self.program += H(pair_a) self.program += CNOT(pair_a, pair_b) # Encode the buffer into the qubits, then decode them into classical measurements self.encode_message(buffer, pair_a) (a_measurement_index, b_measurement_index) = self.decode_message(pair_a, pair_b) # Run the program N times. assigned_program = address_qubits(self.program) assigned_program.wrap_in_numshots_loop(iterations) computer = get_qc(f"2q-qvm", as_qvm=True) executable = computer.compile(assigned_program) results = computer.run(executable) # Check the first qubit to make sure it was always the expected value desired_a_state = int(buffer[0]) for result in results: if result[a_measurement_index] != desired_a_state: self.fail( f"Test {description} failed. The first bit should have been {desired_a_state} " + f"but it was {result[a_measurement_index]}.") else: print( f"The first qubit was {desired_a_state} all {iterations} times." ) # Check the second qubit to make sure it was always the expected value desired_b_state = int(buffer[1]) for result in results: if result[b_measurement_index] != desired_b_state: self.fail( f"Test {description} failed. The first bit should have been {desired_b_state} " + f"but it was {result[b_measurement_index]}.") else: print( f"The second qubit was {desired_b_state} all {iterations} times." ) print("Passed!") print()
def test_reuse_placeholder(): p = Program() q1 = QubitPlaceholder() q2 = QubitPlaceholder() p.inst(H(q1)) p.inst(H(q2)) p.inst(CNOT(q1, q2)) p = address_qubits(p) assert p.out() == "H 0\nH 1\nCNOT 0 1\n"
def test_allocating_qubits_on_multiple_programs(): p = Program() qubit0 = QubitPlaceholder() p.inst(X(qubit0)) q = Program() qubit1 = QubitPlaceholder() q.inst(X(qubit1)) assert address_qubits(p + q).out() == "X 0\nX 1\n"
def test_eq(): p1 = Program() q1 = QubitPlaceholder() q2 = QubitPlaceholder() p1.inst([H(q1), CNOT(q1, q2)]) p1 = address_qubits(p1) p2 = Program() p2.inst([H(0), CNOT(0, 1)]) assert p1 == p2 assert not p1 != p2
def entangle_test(n=5): phi = QubitPlaceholder() p = [QubitPlaceholder() for i in range(n)] test_pqs = [ init_p(p) + entangle(phi, p), init_p(p) + entangle(phi, p) + disentangle(phi, p), init_p(p) + H(phi) + entangle(phi, p), init_p(p) + H(phi) + entangle(phi, p) + disentangle(phi, p), ] wf_sim = WavefunctionSimulator() for pq in test_pqs: print(wf_sim.wavefunction(address_qubits(pq)))
def run_code(error_code, noise, trials=10): """ Takes in an error_code function (e.g. bit_code, phase_code or shor) and runs this code on the QVM""" pq, code_register = error_code(QubitPlaceholder(), noise=noise) ro = pq.declare('ro', 'BIT', len(code_register)) pq += [MEASURE(qq, rr) for qq, rr in zip(code_register, ro)] return qvm.run(address_qubits(pq), trials=trials)
def simulate_code(kraus_operators, trials, error_code) -> int: """ :param kraus_operators: The set of Kraus operators to apply as the noise model on the identity gate :param trials: The number of times to simulate the program :param error_code: The error code {bit_code, phase_code or shor} to use :return: The number of times the code did not correct back to the logical zero state for "trials" attempts """ # Apply the error_code to some qubits and return back a Program pq pq, code_register = error_code(QubitPlaceholder()) ro = pq.declare('ro', 'BIT', len(code_register)) pq += [MEASURE(qq, rr) for qq, rr in zip(code_register, ro)] # THIS CODE APPLIES THE NOISE FOR YOU kraus_ops = kraus_operators noise_data = Program() for qq in range(3): noise_data.define_noisy_gate("I", [qq], kraus_ops) pq = noise_data + pq # Run the simulation trials times using the QVM and check how many times it did not work results = qvm.run(address_qubits(pq), trials=trials) score = 0 for i in results: count = np.sum(i) #if count >= len(code_register)/2 if count == len(code_register): score += 1 return int(score)
def run_flip_marker_as_phase_marker(program, ancilla_cache, oracle, qubits, oracle_args): """ Runs an oracle, flipping the phase of the input array if the result was |1> instead of flipping the target qubit. Parameters: program (Program): The program being constructed ancilla_cache (dict[string, QubitPlaceholder]): A collection of ancilla qubits that have been allocated in the program for use, paired with a name to help determine when they're free for use. oracle (function): The oracle to run qubits (list[QubitPlaceholder]): The register to run the oracle on oracle_args (anything): An oracle-specific argument object to pass to the oracle during execution """ # Add the phase-flip ancilla qubit to the program if it doesn't already # exist, and set it up in the |-> state phase_marker_target = None if not "phase_marker_target" in ancilla_cache: phase_marker_target = QubitPlaceholder() ancilla_cache["phase_marker_target"] = phase_marker_target program += X(phase_marker_target) program += H(phase_marker_target) else: phase_marker_target = ancilla_cache["phase_marker_target"] # Run the oracle with the phase-flip ancilla as the target - when the # oracle flips this target, it will actually flip the phase of the input # instead of entangling it with the target. if oracle_args is None: oracle(program, qubits, phase_marker_target) else: oracle(program, qubits, phase_marker_target, oracle_args)
def test_multiple_instantiate(): p = Program() q = QubitPlaceholder() p.inst(H(q)) p = address_qubits(p) assert p.out() == "H 0\n" assert p.out() == "H 0\n"
def new_logical_qubit(prog: Program, qecc: QECC, name: str) -> CodeBlock: n = qecc.n raw_mem = prog.declare(name, 'BIT', 2 * n) mem = MemoryChunk(raw_mem, 0, raw_mem.declared_size) qubits = [QubitPlaceholder() for _ in range(n)] _initialize_memory(prog, raw_mem, qubits) return CodeBlock(qubits, mem[:n], mem[n:])
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 alloc(self): """ Get a new qubit. :return: A qubit. :rtype: Qubit """ return QubitPlaceholder()
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_simplify_term_xz(): q0 = QubitPlaceholder() term1 = (-0.5 * PauliTerm('X', q0)) * (-1.0 * PauliTerm('Z', q0)) term2 = -0.5 * PauliTerm('X', q0) * (-1.0) * PauliTerm('Z', q0) term3 = 0.5 * PauliTerm('X', q0) * PauliTerm('Z', q0) for term in [term1, term2, term3]: assert term.id() == 'Y{}'.format(q0) assert term.coefficient == -0.5j
def test_pragma_with_placeholders(): q = QubitPlaceholder() q2 = QubitPlaceholder() p = Program() p.inst(Pragma('FENCE', [q, q2])) address_map = {q: 0, q2: 1} addressed_pragma = address_qubits(p, address_map)[0] parse_equals('PRAGMA FENCE 0 1\n', addressed_pragma) pq = Program(X(q)) pq.define_noisy_readout(q, .8, .9) pq.inst(X(q2)) pq.define_noisy_readout(q2, .9, .8) ret = address_qubits(pq, address_map).out() assert ret == """X 0
def qft_tests(n=4): phi = [QubitPlaceholder() for i in range(n)] tests = [ init_pure(phi) + H(phi[0]) + qft(phi, n) + iqft(phi, n), # Should be H(0) init_pure(phi) + iqft(phi, n) + qft(phi, n), # Should be pure |1>'s ] wf_sim = WavefunctionSimulator() for test in tests: print(wf_sim.wavefunction(address_qubits(test)))
def test_qubit_placeholder(): p = Program() p.inst(H(0)) # H 0 q1 = QubitPlaceholder() # q1 = 1 q2 = QubitPlaceholder() # q2 = 3 p.inst(CNOT(q1, q2)) # CNOT 1 3 p.inst(H(2)) q3 = QubitPlaceholder() # q3 = 4 p.inst(X(q3)) # X 4 with pytest.raises(RuntimeError) as e: _ = p.out() assert e.match(r"Qubit q\d+ has not been assigned an index")
def test_qubit_placeholder_2(): p = Program() p.inst(H(0)) # H 0 q1 = QubitPlaceholder() # q1 = 1 q2 = QubitPlaceholder() # q2 = 3 p.inst(CNOT(q1, q2)) # CNOT 1 3 p.inst(H(2)) q3 = QubitPlaceholder() # q3 = 4 p.inst(X(q3)) # X 4 with pytest.raises(ValueError) as e: _ = address_qubits(p, {q1: 1, q2: 3, q3: 4}) assert e.match("Your program mixes instantiated qubits with placeholders")
def test_zero_term(): qubit_id = QubitPlaceholder() coefficient = 10 ps = sI(qubit_id) + sX(qubit_id) assert coefficient * ZERO() == ZERO() assert ZERO() * coefficient == ZERO() assert ZERO() * ID() == ZERO() assert ZERO() + ID() == ID() assert ZERO() + ps == ps assert ps + ZERO() == ps
def test_get_qubits(): pq = Program(Declare('ro', 'BIT'), X(0), CNOT(0, 4), MEASURE(5, MemoryReference("ro", 0))) assert pq.get_qubits() == {0, 4, 5} q = [QubitPlaceholder() for _ in range(6)] pq = Program(Declare('ro', 'BIT'), X(q[0]), CNOT(q[0], q[4]), MEASURE(q[5], MemoryReference("ro", 0))) qq = QubitPlaceholder() pq.inst(Y(q[2]), X(qq)) assert address_qubits(pq).get_qubits() == {0, 1, 2, 3, 4} qubit_index = 1 p = Program(("H", qubit_index)) assert p.get_qubits() == {qubit_index} q1 = QubitPlaceholder() q2 = QubitPlaceholder() p.inst(("CNOT", q1, q2)) with pytest.raises(ValueError) as e: _ = address_qubits(p).get_qubits() assert e.match('Your program mixes instantiated qubits with placeholders')
def alloc(self): """ Get a new qubit. :return: A qubit. :rtype: Qubit """ warnings.warn("`alloc` is deprecated and will be removed in a future version of pyQuil. " "Please create a `QubitPlaceholder` directly", DeprecationWarning) return QubitPlaceholder()
def test_ps_sub(): q0 = QubitPlaceholder() term = 3 * ID() b = term - 1.0 assert str(b) == "(2+0j)*I" assert str(b - 1.0) == "(1+0j)*I" assert str(1.0 - b) == "(-1+0j)*I" b = 1.0 - sX(q0) assert re.match(r"\(1\+0j\)\*I \+ \(-1\+0j\)\*Xq\d+", str(b)) b = sX(q0) - 1.0 assert re.match(r"\(1\+0j\)\*Xq\d+ \+ \(-1\+0j\)\*I", str(b))
def phase_code(qubit: QubitPlaceholder, noise=None) -> (Program, List[QubitPlaceholder]): ### Do your encoding step here q0 = QubitPlaceholder() q1 = QubitPlaceholder() a0 = QubitPlaceholder() a1 = QubitPlaceholder() code_register = [qubit, q0, q1, a0, a1] # the List[QubitPlaceholder] of the qubits you have encoded into pq = Program(CNOT(code_register[0], code_register[1]), CNOT(code_register[0], code_register[2])) pq += (H(q) for q in code_register[:3]) # DON'T CHANGE THIS CODE BLOCK. It applies the errors for simulations if noise is None: pq += [I(qq) for qq in code_register] else: pq += noise(code_register) ### Do your decoding and correction steps here pq += (H(q) for q in code_register[:3]) ro = pq.declare('ro', 'BIT', 2) pq += Program(CNOT(code_register[0], code_register[3]), CNOT(code_register[1], code_register[3])) pq = pq + MEASURE(code_register[3], ro[0])
def main(): A_SIZE = 4 a = QubitPlaceholder.register(A_SIZE) n = QubitPlaceholder.register(A_SIZE) b = QubitPlaceholder.register(A_SIZE) c = QubitPlaceholder.register(A_SIZE) exp = QubitPlaceholder.register(A_SIZE) t = QubitPlaceholder() nila = QubitPlaceholder.register(A_SIZE) master = QubitPlaceholder() N = 3 base = 2 p = Program() p += write_in(1, exp) p += write_in(1, a) p += write_in(0, b) p += write_in(N, n) p += write_in(0, c) p += EXP_MOD(c, a, b, n, N, t, nila, base, exp) #p += MUL_MOD(c, a, b, n, N, t, nila, multiplier, master) #p += ADDER_MOD(c, a, b, n, N, t) #p += REVERSE(ADDER(c, a, b)) #p += ADDER(c, a, b) res, code = read_out(p, a) print(res) #qbit_lookup = {} #lookup_append(qbit_lookup, a, "a") #lookup_append(qbit_lookup, b, "b") #lookup_append(qbit_lookup, c, "c") #pretty_print(qbit_lookup) embed(colors="Neutral")
def construct_toric_code(L: int) -> Tuple[nx.Graph]: '''Constructs a toric code as a NetworkX graph structure. Args - L: int, # of physical qubits on one side of the square lattice Returns - primal_graph: nx.Graph, L x L lattice - dual_graph: nx.Graph, L x L lattice - distance_graph: nx.Graph, nodes are primal_graph edges (qubits), edges indicate adjacency between those qubits, needed for MWPM algorithm ''' # Generate a L x L lattice with periodic boundary conditions primal_graph = nx.generators.lattice.grid_2d_graph(L, L, periodic=True) for edge in primal_graph.edges: # Add data qubits to edges primal_graph.edges[edge]['data_qubit'] = QubitPlaceholder() for node in primal_graph.nodes: # Add ancilla qubits to nodes primal_graph.nodes[node]['ancilla_qubit'] = QubitPlaceholder() dual_graph = nx.generators.lattice.grid_2d_graph(L, L, periodic=True) for edge in dual_graph.edges: dual_graph.edges[edge]['data_qubit'] = primal_graph.edges[dual_edge_to_primal_edge(edge, L)]['data_qubit'] for node in dual_graph.nodes: dual_graph.nodes[node]['ancilla_qubit'] = QubitPlaceholder() distance_graph = nx.Graph() for edge in primal_graph.edges: edge = sort_edge(edge, L) distance_graph.add_node(edge) distance_graph.nodes[edge]['data_qubit'] = primal_graph.edges[edge]['data_qubit'] for n1 in distance_graph.nodes: for n2 in distance_graph.nodes: if n1 == n2: continue if (n1[0] == n2[0]) or (n1[0] == n2[1]) or (n1[1] == n2[0]) or (n1[1] == n2[1]): distance_graph.add_edge(n1, n2) return primal_graph, dual_graph, distance_graph
def test_pragma_with_placeholders(): q = QubitPlaceholder() q2 = QubitPlaceholder() p = Program() p.inst(Pragma("FENCE", [q, q2])) address_map = {q: 0, q2: 1} addressed_pragma = address_qubits(p, address_map)[0] parse_equals("PRAGMA FENCE 0 1\n", addressed_pragma) pq = Program(X(q)) pq.define_noisy_readout(q, 0.8, 0.9) pq.inst(X(q2)) pq.define_noisy_readout(q2, 0.9, 0.8) ret = address_qubits(pq, address_map).out() assert (ret == """X 0 PRAGMA READOUT-POVM 0 "(0.8 0.09999999999999998 0.19999999999999996 0.9)" X 1 PRAGMA READOUT-POVM 1 "(0.9 0.19999999999999996 0.09999999999999998 0.8)" """)