def test_measure_each(): a = cirq.NamedQubit('a') b = cirq.NamedQubit('b') assert cirq.measure_each() == [] assert cirq.measure_each(a) == [cirq.measure(a)] assert cirq.measure_each(a, b) == [cirq.measure(a), cirq.measure(b)] assert cirq.measure_each(a, b, key_func=lambda e: e.name + '!') == [ cirq.measure(a, key='a!'), cirq.measure(b, key='b!') ]
def get_match_circuit() -> cirq.Circuit: qubits = [cirq.LineQubit(i) for i in range(9)] g = cirq.CZPowGate(exponent=0.1) zz = cirq.ZZPowGate(exponent=0.3) px = cirq.PhasedXPowGate(phase_exponent=0.6, exponent=0.2) circ = cirq.Circuit( [ cirq.H(qubits[0]), cirq.X(qubits[1]), cirq.Y(qubits[2]), cirq.Z(qubits[3]), cirq.S(qubits[4]), cirq.CNOT(qubits[1], qubits[4]), cirq.T(qubits[3]), cirq.CNOT(qubits[6], qubits[8]), cirq.I(qubits[5]), cirq.XPowGate(exponent=0.1)(qubits[5]), cirq.YPowGate(exponent=0.1)(qubits[6]), cirq.ZPowGate(exponent=0.1)(qubits[7]), g(qubits[2], qubits[3]), zz(qubits[3], qubits[4]), px(qubits[6]), cirq.CZ(qubits[2], qubits[3]), cirq.ISWAP(qubits[4], qubits[5]), cirq.FSimGate(1.4, 0.7)(qubits[6], qubits[7]), cirq.google.SYC(qubits[3], qubits[0]), cirq.PhasedISwapPowGate(phase_exponent=0.7, exponent=0.8)( qubits[3], qubits[4]), cirq.GlobalPhaseOperation(1j), cirq.measure_each(*qubits[3:-2]), ], strategy=InsertStrategy.EARLIEST, ) return circ
def simon_quantum_step(function, input_size): """ Performs the quantum portion of Simon's algorithm, by finding an input string X where (X · S) % 2 = 0 (AKA x0*s0 ⊕ x1*s1 ⊕ ... ⊕ xN*sN = 0). Parameters: function (function): The black-box function to run the algorithm on (the function being evaluated). It should take a Circuit as its first input, an input list[Qid] as its second argument, and an output list[Qid] as its third argument. input_size (int): The number of bits that the function expects in its input and output registers. Returns: A bit string representing the measured result of the function. This bit string is a vector X where (X · S) % 2 = 0. Note that this will be the measured result of the INPUT register after it's been evaluated. The OUTPUT register is thrown away, because it doesn't actually matter to the algorithm at all. Remarks: A lot of literature out there will say that this returns a string where s · x = 0. This is misleading, because what they really mean is "dot product mod-2" and they don't usually say the "mod-2" part. Basically, this finds an input value that, when dot product'd with S, gives an even number. """ # Construct the circuit and registers input = cirq.NamedQubit.range(input_size, prefix="input") output = cirq.NamedQubit.range(input_size, prefix="output") circuit = cirq.Circuit() # Run the function with |+...+> as the input and |0...0> as the output circuit.append(cirq.H.on_each(*input)) function(circuit, input, output) circuit.append(cirq.H.on_each(*input)) # At this point, the input bit string has been transformed # from |0...0> into X, where X is some string that is guaranteed # to be even when dot product'd with S. The math behind why this # is true is way beyond an explanation here - you have to look # at the literature to see why this is the case. # Measure the resulting input register circuit.append(cirq.measure_each(*input)) # Run the circuit simulator = cirq.Simulator() result = simulator.run(circuit, repetitions=1) # Return the measurement as a list[bool] for classical postprocessing measurement = [False] * input_size for i in range(0, input_size): result_state = result.histogram(key=f"input{i}") for(state, count) in result_state.items(): measurement[i] = (state == 1) break return measurement
def test_sample_circuit_cirq(measure): circuit = cirq.Circuit( cirq.ops.H.on(cirq.LineQubit(0)), cirq.ops.CNOT.on(*cirq.LineQubit.range(2)), ) if measure: circuit.append(cirq.measure_each(*cirq.LineQubit.range(2))) h_rep = OperationRepresentation( ideal=circuit[:1], basis_expansion={ NoisyOperation.from_cirq(circuit=cirq.X): 0.6, NoisyOperation.from_cirq(circuit=cirq.Z): -0.6, }, ) cnot_rep = OperationRepresentation( ideal=circuit[1:2], basis_expansion={ NoisyOperation.from_cirq(circuit=cirq.CNOT): 0.7, NoisyOperation.from_cirq(circuit=cirq.CZ): -0.7, }, ) for _ in range(50): sampled_circuits, signs, norm = sample_circuit( circuit, representations=[h_rep, cnot_rep]) assert isinstance(sampled_circuits[0], cirq.Circuit) assert len(sampled_circuits[0]) == 2 assert signs[0] in (-1, 1) assert norm >= 1
def make_bb84_circ(num_qubits, alice_basis, bob_basis, alice_state): qubits = [cirq.LineQubit(i) for i in range(num_qubits)] circuit = cirq.Circuit() # Alice prepares her qubits alice_enc = [] for index, _ in enumerate(alice_basis): if alice_state[index] == 1: alice_enc.append(cirq.X(qubits[index])) if alice_basis[index] == 1: alice_enc.append(cirq.H(qubits[index])) circuit.append(alice_enc) # Bob measures the received qubits bob_basis_choice = [] for index, _ in enumerate(bob_basis): if bob_basis[index] == 1: bob_basis_choice.append(cirq.H(qubits[index])) circuit.append(bob_basis_choice) circuit.append(cirq.measure_each(*qubits)) return circuit
def test_zeros_sampler_many_measure(): qubits = cirq.LineQubit.range(6) circuit = cirq.Circuit(cirq.H.on_each(*qubits), cirq.measure_each(*qubits, key_func=str)) sampler = recirq.ZerosSampler() result = sampler.run(circuit, repetitions=155) assert len(result.measurements) == 6 for k, v in result.measurements.items(): assert v.shape == (155, 1)
def test_get_state_histogram_multi_2(): qubits = cirq.LineQubit.range(4) c = cirq.Circuit( cirq.X.on_each(*qubits[1:]), cirq.measure(*qubits[:2]), # One multi-qubit measurement cirq.measure_each(*qubits[2:]), # Multiple single-qubit measurement ) r = cirq.sample(c, repetitions=5) values_to_plot = state_histogram.get_state_histogram(r) expected_values = [0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0] np.testing.assert_equal(values_to_plot, expected_values)
def test_plot_state_histogram_multi_2(): pl.switch_backend('PDF') qubits = cirq.LineQubit.range(4) c = cirq.Circuit( cirq.X.on_each(*qubits[1:]), cirq.measure(*qubits[:2]), # One multi-qubit measurement cirq.measure_each(*qubits[2:]), # Multiple single-qubit measurement ) r = cirq.sample(c, repetitions=5) values_plotted = visualize.plot_state_histogram(r) expected_values = [0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0] np.testing.assert_equal(values_plotted, expected_values)
def test_print_circuit_diagram(self): """ This function shows how to print ASCII-based circuit diagrams. """ qubits = cirq.NamedQubit.range(3, prefix="qubit") circuit = cirq.Circuit() circuit.append(cirq.H.on_each(*qubits)) circuit.append(cirq.X(qubits[2])) circuit.append(cirq.CNOT(qubits[2], qubits[0])) circuit.append(cirq.measure_each(*qubits)) print( circuit.to_text_diagram()) # Print the circuit as an ASCII diagram
def test_measure_each(): a = cirq.NamedQubit('a') b = cirq.NamedQubit('b') assert cirq.measure_each() == [] assert cirq.measure_each([]) == [] assert cirq.measure_each(a) == [cirq.measure(a)] assert cirq.measure_each([a]) == [cirq.measure(a)] assert cirq.measure_each(a, b) == [cirq.measure(a), cirq.measure(b)] assert cirq.measure_each([a, b]) == [cirq.measure(a), cirq.measure(b)] qubit_generator = (q for q in (a, b)) assert cirq.measure_each(qubit_generator) == [cirq.measure(a), cirq.measure(b)] assert cirq.measure_each(a.with_dimension(3), b.with_dimension(3)) == [ cirq.measure(a.with_dimension(3)), cirq.measure(b.with_dimension(3)), ] assert cirq.measure_each(a, b, key_func=lambda e: e.name + '!') == [ cirq.measure(a, key='a!'), cirq.measure(b, key='b!'), ]
def test_set_explicit_initial_state(self): """ This shows how to set the initial state of the qubits in a circuit. """ qubits = cirq.NamedQubit.range(3, prefix="qubit") circuit = cirq.Circuit() circuit.append(cirq.H.on_each(*qubits)) circuit.append(cirq.X(qubits[2])) circuit.append(cirq.CNOT(qubits[2], qubits[0])) circuit.append(cirq.measure_each(*qubits)) simulator = cirq.Simulator() # Set the initial state to 2, which is |010> (this can also be an entire state vector if you need to get fine-grained # or set up superpositions) steps = simulator.simulate_moment_steps(circuit, initial_state=2)
def test_validate_circuit_errors(): d = square_device(2, 2, max_controls=3) q00 = cirq.GridQubit(0, 0) q01 = cirq.GridQubit(0, 1) q10 = cirq.GridQubit(1, 0) q11 = cirq.GridQubit(1, 1) c = cirq.Circuit() c.append(cirq.ParallelGateOperation(cirq.X, d.qubits)) c.append(cirq.CCZ.on(q00, q01, q10)) c.append(cirq.ParallelGateOperation(cirq.Z, [q00, q01, q10])) m = cirq.Moment(cirq.X.on_each(q00, q01) + cirq.Z.on_each(q10, q11)) c.append(m) c.append(cirq.measure_each(*d.qubits)) d.validate_circuit(c) c.append(cirq.Moment([cirq.X.on(q00)])) with pytest.raises(ValueError, match="Non-empty moment after measurement"): d.validate_circuit(c)
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 Circuit as its first input, an input list[Qid] as its second argument, and an output list[Qid] 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 circuit and registers input_size = len(input) input_register = cirq.NamedQubit.range(input_size, prefix="input") output = cirq.NamedQubit.range(input_size, prefix="output") circuit = cirq.Circuit() # Sets up the input register so it has the requested input state, #and runs the function on it. for i in range(0, len(input)): if input[i]: circuit.append(cirq.X(input_register[i])) function(circuit, input_register, output) circuit.append(cirq.measure_each(*output)) # Run the circuit simulator = cirq.Simulator() result = simulator.run(circuit, repetitions=1) # Return the measurement as a list[bool] for classical postprocessing measurement = [False] * input_size for i in range(0, input_size): result_state = result.histogram(key=f"output{i}") for(state, count) in result_state.items(): measurement[i] = (state == 1) break return measurement
def test_to_qiskit_assign_qregs_and_cregs(qreg_sizes, measure, flip_creg): nbits = sum(qreg_sizes) cirq_circuit = cirq.testing.random_circuit( nbits, n_moments=5, op_density=1, random_state=10 ) if measure: cirq_circuit.append(cirq.measure_each(*cirq_circuit.all_qubits())) qregs = [qiskit.QuantumRegister(s) for s in qreg_sizes] cregs = [qiskit.ClassicalRegister(s) for s in qreg_sizes] if flip_creg: cregs = cregs[::-1] qiskit_circuit = to_qiskit(cirq_circuit, qregs=qregs, cregs=cregs) assert qiskit_circuit.qregs == qregs assert qiskit_circuit.cregs == cregs cirq.testing.assert_allclose_up_to_global_phase( cirq.unitary(from_qiskit(qiskit_circuit)), cirq.unitary(cirq_circuit), atol=1e-5, )
def BB84(qubit_num, alice_basis, bob_basis, alice_measures): # 1) allocation n qubits with 0> value qubits = [cirq.LineQubit(i) for i in range(qubit_num)] circuit = cirq.Circuit() # 2) initialize qubits according to alice measures # alice's qubits for idx, basis in enumerate(alice_basis): # qubits of random status prepared by alice circuit.append( cirq.I(qubits[idx]) if alice_measures[idx] == 0 else cirq.X(qubits[idx])) # qubits after alice's measures, status changes if the measure is done on X axis circuit.append( cirq.I(qubits[idx]) if basis == 0 else cirq.H(qubits[idx])) # bob's measures for idx, basis in enumerate(bob_basis): # qubits after bob's measures, status changes if the measure is done on different basis from alice's circuit.append( cirq.I(qubits[idx]) if bob_basis[idx] == 0 else cirq.H(qubits[idx])) circuit.append(cirq.measure_each(*qubits)) return circuit
def run_grover_search(number_of_qubits, oracle, oracle_args): """ Uses Grover's quantum search to find the single answer to a problem with high probability. Parameters: number_of_qubits (int): The number of qubits that the oracle expects (the number of qubits that the answer will contain) oracle (function): The oracle that flags the correct answer to the problem being solved (essentially, this should just implement the function as a quantum circuit) oracle_args (anything): An oracle-specific argument object to pass to the oracle during execution Returns: A list[int] that represents the discovered answer as a bit string """ # Build the circuit and run the search qubits = cirq.NamedQubit.range(number_of_qubits, prefix="qubit") circuit = cirq.Circuit() grover_search(circuit, oracle, qubits, oracle_args) circuit.append(cirq.measure_each(*qubits)) # Run the circuit. simulator = cirq.Simulator() result = simulator.run(circuit, repetitions=1) # Measure the potential solution and return it solution = [0] * number_of_qubits for i in range(0, number_of_qubits): result_state = result.histogram(key=f"qubit{i}") for (state, count) in result_state.items(): solution[i] = state break return solution
def test_step_by_step_circuit_inspection(self): """ This function demonstrates how to use Cirq to print the state vector of every step (moment) in a circuit. It also shows how to get the state vector at each step, and how to print it in ket notation. """ qubits = cirq.NamedQubit.range(3, prefix="qubit") circuit = cirq.Circuit() circuit.append(cirq.H.on_each(*qubits)) circuit.append(cirq.X(qubits[2])) circuit.append(cirq.CNOT(qubits[2], qubits[0])) circuit.append(cirq.measure_each(*qubits)) simulator = cirq.Simulator() steps = simulator.simulate_moment_steps( circuit) # Step through each moment of the circuit for step in steps: print( step.state_vector() ) # Print the entire state vector for all of the qubits in the circuit print(cirq.dirac_notation(step.state_vector( ))) # Print the state vector in big-endian ket (Dirac) notation print("")
import cirq from cirq.contrib.svg.svg import tdd_to_svg import sympy if __name__ == "__main__": qubits = cirq.LineQubit.range(10) x = sympy.symbols("x0:10") thetas = sympy.symbols("t0:10") circuit = cirq.Circuit() for i in range(10): circuit.append(cirq.rx(x[i])(qubits[i])) circuit.append(cirq.ry(thetas[i])(qubits[i])) circuit.append(cirq.measure_each(*qubits)) with open("simple_VQC.svg", "w") as file: file.write( tdd_to_svg( circuit.to_text_diagram_drawer(), ref_boxheight=40, ref_boxwidth=160, ) )
def with_registers(self, *new_registers): return Adder(*new_registers) def apply(self, target_value, input_value): return target_value + input_value """Example of using an Adder in a circuit.""" # Two qubit registers qreg1 = cirq.LineQubit.range(2) qreg2 = cirq.LineQubit.range(2, 4) # Define the circuit circ = cirq.Circuit(cirq.ops.X.on(qreg1[0]), cirq.ops.X.on(qreg2[1]), Adder(input_register=qreg1, target_register=qreg2), cirq.measure_each(*qreg1), cirq.measure_each(*qreg2)) # Display it print("Circuit:\n") print(circ) # Print the measurement outcomes print("\n\nMeasurement outcomes:\n") print(cirq.sample(circ, repetitions=5).data) """Example of the unitary of an Adder operation.""" cirq.unitary(Adder(target_register=cirq.LineQubit.range(2), input_register=1)).astype(np.int32) """Defines the modular exponential operation used in Shor's algorithm.""" class ModularExp(cirq.ArithmeticOperation):
from mitiq.zne.scaling import ( fold_gates_from_left, fold_gates_from_right, fold_gates_at_random, ) from mitiq.zne import execute_with_zne, mitigate_executor, zne_decorator npX = np.array([[0, 1], [1, 0]]) """Defines the sigma_x Pauli matrix in SU(2) algebra as a (2,2) `np.array`.""" npZ = np.array([[1, 0], [0, -1]]) """Defines the sigma_z Pauli matrix in SU(2) algebra as a (2,2) `np.array`.""" # Default qubit register and circuit for unit tests qreg = cirq.GridQubit.rect(2, 1) circ = cirq.Circuit(cirq.ops.H.on_each(*qreg), cirq.measure_each(*qreg)) # Default executor for unit tests def executor(circuit) -> float: wavefunction = circuit.final_wavefunction() return np.real(wavefunction.conj().T @ np.kron(npX, npZ) @ wavefunction) @pytest.mark.parametrize( "fold_method", [fold_gates_from_left, fold_gates_from_right, fold_gates_at_random], ) @pytest.mark.parametrize("factory", [LinearFactory, RichardsonFactory]) @pytest.mark.parametrize("num_to_average", [1, 2, 5]) def test_execute_with_zne_no_noise(fold_method, factory, num_to_average):
def run_test(self, circuit, qubits, description, iterations, target_probabilities, margin): """ Runs a given circuit as a unit test. Parameters: circuit (Circuit): The circuit to run during the test. qubits (list[Qid]): The qubits used in the circuit. description (str): A description of the test, for logging. iterations (int): The number of times to run the circuit before calculating each qubit's |0〉 probability. target_probabilities (list[float]): The expected probabilities for each qubit of being in the |0〉 state. margin (float): The allowed error margin for each qubit's probability. """ print(f"Running test: {description}") number_of_qubits = len(target_probabilities) # Construct the measurement and append it to the circuit. In Cirq, we can construct # measurements for each individual qubit and assign that measurement a unique name, # which we can then look up in simulation results to get the measurement results for # that specific qubit. We can also just measure an entire register at once, as a # big-endian integer. For this experiment, measuring the qubit individually is more # useful. circuit.append(cirq.measure_each(*qubits)) # Run the circuit N times, and count the results. simulator = cirq.Simulator() result = simulator.run(circuit, repetitions=iterations) # Get the |0〉 counts for each individual qubit zero_counts = [0] * number_of_qubits for i in range(number_of_qubits): measurements = result.histogram(key=f"qubit{i}") zero_counts[i] = measurements[0] # Compare the probabilities with the targets target_string = "Target: [ " result_string = "Result: [ " for i in range(number_of_qubits): target_probability = target_probabilities[i] measured_probability = zero_counts[ i] / iterations # Python 3 automatically does float division target_string += "{:.4f}".format(target_probability) + " " result_string += "{:.4f}".format(measured_probability) + " " discrepancy = abs(target_probability - measured_probability) if (discrepancy > margin): self.fail( f"Test {description} failed. Qubit {i} had a |0> probability of " + f"{measured_probability}, but it should have been {target_probability} " + f"(with a margin of {margin}).") # If the test passed, print the results. target_string += "]" result_string += "]" print(target_string) print(result_string) print("Passed!") print()
async def _estimate_single_qubit_readout_errors_async( sampler: 'cirq.Sampler', *, qubits: Iterable['cirq.Qid'], repetitions: int = 1000) -> cirq.experiments.SingleQubitReadoutCalibrationResult: """Estimate single-qubit readout error. TODO: Commit an async version of this function to Cirq. For each qubit, prepare the |0⟩ state and measure. Calculate how often a 1 is measured. Also, prepare the |1⟩ state and calculate how often a 0 is measured. The state preparations and measurements are done in parallel, i.e., for the first experiment, we actually prepare every qubit in the |0⟩ state and measure them simultaneously. Args: sampler: The quantum engine or simulator to run the circuits. qubits: The qubits being tested. repetitions: The number of measurement repetitions to perform. Returns: A SingleQubitReadoutCalibrationResult storing the readout error probabilities as well as the number of repetitions used to estimate the probabilties. Also stores a timestamp indicating the time when data was finished being collected from the sampler. """ qubits = list(qubits) if isinstance(sampler, cirq.DensityMatrixSimulator): # Do each qubit individually to make this simulable zero_state_errors = dict() one_state_errors = dict() for qubit in qubits: zero_circuit = cirq.Circuit(cirq.measure(qubit, key=repr(qubit))) one_circuit = cirq.Circuit(cirq.X(qubit), cirq.measure(qubit, key=repr(qubit))) zero_result = await sampler.run_async(zero_circuit, repetitions=repetitions) one_result = await sampler.run_async(one_circuit, repetitions=repetitions) zero_state_errors[qubit] = np.mean(zero_result.measurements[repr(qubit)]) one_state_errors[qubit] = 1 - np.mean(one_result.measurements[repr(qubit)]) else: zeros_circuit = cirq.Circuit(cirq.measure_each(*qubits, key_func=repr)) ones_circuit = cirq.Circuit(cirq.X.on_each(*qubits), cirq.measure_each(*qubits, key_func=repr)) zeros_result = await sampler.run_async(zeros_circuit, repetitions=repetitions) ones_result = await sampler.run_async(ones_circuit, repetitions=repetitions) zero_state_errors = { q: np.mean(zeros_result.measurements[repr(q)]) for q in qubits } one_state_errors = { q: 1 - np.mean(ones_result.measurements[repr(q)]) for q in qubits } timestamp = time.time() return cirq.experiments.SingleQubitReadoutCalibrationResult( zero_state_errors=zero_state_errors, one_state_errors=one_state_errors, repetitions=repetitions, timestamp=timestamp)
def build_b92_measurement(circuit, qubits, basis): for i in range(len(basis)): if basis[i] == 1: circuit.append(cirq.H(qubits[i])) circuit.append(cirq.measure_each(*qubits)) return circuit