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_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_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_exponentiate_2(): # testing general 2-circuit q = QubitPlaceholder.register(8) generator = PauliTerm("Z", q[0], 1.0) * PauliTerm("Z", q[1], 1.0) para_prog = exponential_map(generator) prog = para_prog(1) result_prog = Program().inst(CNOT(q[0], q[1])).inst(RZ(2.0, q[1])).inst(CNOT(q[0], q[1])) mapping = get_default_qubit_mapping(prog) assert address_qubits(prog, mapping) == address_qubits(result_prog, mapping)
def train_xor_single(samples): param = [np.pi, np.pi, np.pi] s = samples[0] val = sim.expectation(address_qubits(fun_rus(s[1], param, s[0])), [sZ(3)]).real[0] print(address_qubits(fun_rus(s[1], param, s[0]))) print(val) print(s[2]) print(abs(val-s[2])) # for s in samples: fun = lambda x: abs(sim.expectation(address_qubits(fun_rus(s[1], param, s[0])), [sZ(3)]).real[0] - s[2]) # fun = lambda x: sim.expectation(address_qubits(fun_xor(s[1], sec_reg, s[2], x, s[0]), [sZ(8)*sZ(0)])) res = minimize(fun, np.array(param), method="Nelder-Mead", tol=10**-6) return res.x, res.fun
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 syndrome_extraction(G: nx.Graph, L: int, pq: Program, op: str) -> List[Node]: ''' Args - G: graph - L: int - pq: Program - op: str, one of ['X', 'Z'] Returns - faulty_nodes: list of nodes, representing plaquette or vertex operators that measured a -1 eigenvalue ''' assert op in ['X', 'Z'] faulty_nodes = [] for node in G.nodes: # each node is a plaquette or vertex operator # neighbors = sorted(G.edges(node)) # qubits that the operator acts on neighbors = nwes(node, L) # Extract the necessary qubits qubits = [G.nodes[node]["ancilla_qubit"]] for edge in neighbors: qubits.append(G.edges[edge]["data_qubit"]) if op == 'X': syndrome = pq + X_syndrome_extraction(qubits) else: syndrome = pq + Z_syndrome_extraction(qubits) syndrome = address_qubits(syndrome) result = qvm.run(syndrome) if result[0][0]: # Error detected faulty_nodes.append(node) return faulty_nodes
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 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 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 _rb_sequence_payload(depth, gateset, seed=None, interleaver=None): """ Prepares a JSON payload for generating a randomized benchmarking sequence. See :py:func:`generate_rb_sequence`. :param int depth: The number of cliffords per rb sequences to generate. :param list gateset: A list of Gate objects that make up the gateset to decompose the Cliffords into. :return: The JSON payload, with keys "depth", "qubits", and "gateset". """ # Support QubitPlaceholders: we temporarily index to arbitrary integers. # `generate_rb_sequence` handles mapping back to the original gateset gates. gateset_as_program = address_qubits(sum(gateset, Program())) n_qubits = len(gateset_as_program.get_qubits()) gateset_for_api = gateset_as_program.out().splitlines() payload = { "depth": depth, "qubits": n_qubits, "gateset": gateset_for_api, "seed": seed } if interleaver: assert (isinstance(interleaver, Program)) payload["interleaver"] = interleaver.out() return payload
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_multiple_instantiate(): p = Program() q = p.alloc() p.inst(H(q)) p = address_qubits(p) assert p.out() == 'H 0\n' assert p.out() == 'H 0\n'
def build_circuit(self, qubit_ops): program = Program() self.qubits = [program.alloc() for _ in range(len(qubit_ops))] program_readout_reg = program.declare("ro", memory_type="BIT", memory_size=len(self.qubits)) for qb, gatestr in zip(self.qubits, qubit_ops): if gatestr == "I": pass elif gatestr == "X": program.gate("X", qubits=[qb], params=[]) elif gatestr == "H": program.gate("H", qubits=[qb], params=[]) elif gatestr == "K": # our one char CX label program.gate( "CNOT", qubits=[self.qubits[self.qubits.index(qb) - 1], qb], params=[]) program.measure_all(*zip(self.qubits, program_readout_reg)) program = address_qubits(program) program.wrap_in_numshots_loop(shots=10) self.program = program
def NN_test(qubit, prep_program, N_encode, N_decode): ### qubit: qubit we want to encode (main qubit) ### prep_program: arbitrary program to put the main qubit in the state we want to ### transmit ### N_encode: number of qubits to encode the main qubit in ### N_decode: number of qubits to read out ### if N_decode < N_encode, we will always get alpha squared = beta squared = 0.5, ### no matter what we originally encoded the qubit in. ### Note that this test only gives the absolute squared values of alpha and beta pq = Program() pq += prep_program prog, code_register = NN_encode(qubit, N_encode) pq += prog progg, out = NN_decode(code_register[0:N_decode]) pq += progg ro = pq.declare('ro', 'BIT', 1) pq += MEASURE(out, ro) result = np.sum(qvm.run(address_qubits(pq), trials=1000)) / 1000.0 alpha_sqrd = 1.0 - result beta_sqrd = result print('alpha squared = {}'.format(alpha_sqrd)) print('beta squared = {}'.format(beta_sqrd)) return alpha_sqrd, beta_sqrd
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 run_test(self, description, program, qubits, iterations, valid_states): """ Runs a given program as a unit test, measuring the results and ensuring that the resulting state matches one of the provided target states. Parameters: description (str): A human-readable description of the test, which will be printed to the log. program (Program): The program to run during the test. qubits (list[QubitPlaceholder]): The qubits used in the program. iterations (int): The number of times to run the test and check that the results match a valid state. valid_states (list[string]): A list of valid states that the qubits could be in. Each time the test is run, this function will check the result and make sure that it matches one of these states. If it doesn't match any of these states, the test has failed. """ print(f"Running test: {description}") number_of_qubits = len(valid_states[0]) number_of_valid_states = len(valid_states) # Construct the measurement and append it to the program. In this case, we don't care about the # individual qubits - we just want the overall result of all of the qubits together, so we can # use the measure() function instead of measure_each() like we did in the superposition tests. measurement = program.declare("ro", "BIT", number_of_qubits) for i in range(0, number_of_qubits): program += MEASURE(qubits[i], measurement[i]) # Run the program N times. assigned_program = address_qubits(program) assigned_program.wrap_in_numshots_loop(iterations) computer = get_qc(f"{number_of_qubits}q-qvm", as_qvm=True) executable = computer.compile(assigned_program) results = computer.run(executable) # Check each result to make sure it's one of the valid states success_message = "" counts = {} for result in results: # Create a state string from the individual bits state_string = "" for bit in result: state_string += str(bit) if state_string not in counts: counts[state_string] = 0 counts[state_string] += 1 if state_string not in valid_states: self.fail( f"Test {description} failed. Resulting state {state_string} " + "didn't match any valid target states.") for (state_string, count) in counts.items(): success_message += f"Found state [{state_string}] {count} times.{os.linesep}" # If all of the results are valid, print them out with a success message. print(success_message) print("Passed!")
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_create_bell_program(wfn): tree = nx.from_edgelist([(0, 1), (0, 2)], create_using=nx.DiGraph()) prog = create_bell_program(tree) for _ in tree.nodes: prog.pop() # remove measurements prog = address_qubits(prog) wf = wfn.wavefunction(prog) should_be = [0.5] + [0] * (2 ** tree.number_of_nodes() - 2) + [0.5] np.testing.assert_allclose(should_be, wf.probabilities())
def test_reuse_alloc(): p = Program() q1 = p.alloc() q2 = p.alloc() 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_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_multiaddress(): p = Program() q0, q1 = [QubitPlaceholder() for _ in range(2)] p += exponential_map(sZ(q0) * sZ(q1))(0.5) map1 = {q0: 0, q1: 1} map2 = {q0: 9, q1: 10} p1 = address_qubits(p, map1) with pytest.raises(RuntimeError): _ = p.out() # make sure the original isn't affected assert p1.out() == "CNOT 0 1\nRZ(1.0) 1\nCNOT 0 1\n" p2 = address_qubits(p, map2) assert p1.out() == "CNOT 0 1\nRZ(1.0) 1\nCNOT 0 1\n" assert p2.out() == "CNOT 9 10\nRZ(1.0) 10\nCNOT 9 10\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 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_exponentiate_identity(): q = QubitPlaceholder.register(11) generator = PauliTerm("I", q[1], 0.0) para_prog = exponential_map(generator) prog = para_prog(1) assert len(prog) == 0 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) == address_qubits(result_prog) 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) == address_qubits(result_prog)
def test_exponentiate_3cob(): # testing circuit for 3-terms with change of basis q = QubitPlaceholder.register(8) generator = PauliTerm("Z", q[0], 1.0) * PauliTerm( "Y", q[1], 1.0) * PauliTerm("X", q[2], 1.0) para_prog = exponential_map(generator) prog = para_prog(1) result_prog = Program().inst([ RX(math.pi / 2.0, q[1]), H(q[2]), CNOT(q[0], q[1]), CNOT(q[1], q[2]), RZ(2.0, q[2]), CNOT(q[1], q[2]), CNOT(q[0], q[1]), RX(-math.pi / 2.0, q[1]), H(q[2]) ]) assert address_qubits(prog) == address_qubits(result_prog)
def test_get_qubits(): pq = Program(X(0), CNOT(0, 4), MEASURE(5, 5)) assert pq.get_qubits() == {0, 4, 5} q = [QubitPlaceholder() for _ in range(6)] pq = Program(X(q[0]), CNOT(q[0], q[4]), MEASURE(q[5], 5)) qq = pq.alloc() 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 = p.alloc() q2 = p.alloc() 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 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 measure_all_qubits(G: nx.Graph, pq: Program): num_qubits = len(G.edges) ro = pq.declare('ro', 'BIT', num_qubits) edge_list = list(G.edges) for i, edge in enumerate(edge_list): # sort for determinism pq += MEASURE(G.edges[edge]['data_qubit'], ro[i]) pq = address_qubits(pq) result = qvm.run(pq)[0] for edge, bit in zip(edge_list, result): G.edges[edge]['value'] = bit
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