def test_pec_decorator_pyquil(): """Performs the same test as test_mitigate_executor_pyquil(), but using pec_decorator() instead of mitigate_executor(). """ circuit = pyquil.Program(pyquil.gates.H(0)) unmitigated = serial_executor(circuit) mitigated = decorated_serial_executor(circuit) assert np.isclose(unmitigated, mitigated)
def optimize_toffoli(a, b, c): program = pq.Program() program += pq.gates.H(c) program += pq.gates.T(c).dagger() program += pq.gates.CNOT(a, c) program += pq.gates.T(c) program += pq.gates.CNOT(b, c) program += pq.gates.T(c).dagger() program += pq.gates.CNOT(a, c) program += pq.gates.T(c) program += pq.gates.H(c) return program
def QFT(self, qubits): # NOTE: This method will reverse the order of the list of qubits, # rather than implementing a bunch of swaps at the end # Handle with care! program = pq.Program() for i, tq in enumerate(qubits): program += pq.gates.H(tq) for j, cq in list(enumerate(qubits))[i + 1:]: program += pq.gates.RZ(2**(-(j - i)) * np.pi, tq).controlled(cq) program += pq.gates.RZ(2**(-(j - i + 1)) * np.pi, cq) return program
def __init__(self, path: list, test_type: BellTestType, add_measurements, num_shots): super().__init__() assert len(path) >= 2, "qubit path has to have length at least 2" qubit_a = path[0] qubit_b = path[-1] self.qubit_a = qubit_a self.qubit_b = qubit_b self.path = path self.test_type = test_type self.add_measurements = add_measurements self.num_shots = num_shots # Build the circuit program = pq.Program() program += Pragma("INITIAL_REWIRING", ['"NAIVE"']) program += pq.gates.X(qubit_a) program += pq.gates.X(qubit_b) program += pq.gates.H(qubit_a) # CNOT along path for (x, y) in zip(path[:-2], path[1:-1]): program += pq.gates.CNOT(x, y) # CNOT the last pair program += pq.gates.CNOT(path[-2], qubit_b) # undo CNOT along path for (x, y) in reversed(list(zip(path[:-2], path[1:-1]))): program += pq.gates.CNOT(x, y) # measurement directions angle_a, angle_b = test_type.value if angle_a != 0: program += pq.gates.RZ(angle_a, qubit_a) if angle_b != 0: program += pq.gates.RZ(angle_b, qubit_b) # final hadamards program += pq.gates.H(qubit_a) program += pq.gates.H(qubit_b) # store the resulting circuit self.program = program
def test_convert_simple_program_with_parameters_mixed_keys(self): """Test that a parametrized program is properly converted when the variable map contains mixed key types.""" program = pyquil.Program() alpha = program.declare("alpha", "REAL") beta = program.declare("beta", "REAL") gamma = program.declare("gamma", "REAL") delta = program.declare("delta", "REAL") program += g.H(0) program += g.CNOT(0, 1) program += g.RX(alpha, 1) program += g.RZ(beta, 1) program += g.RX(gamma, 1) program += g.CNOT(0, 1) program += g.RZ(delta, 0) program += g.H(0) a, b, c, d = 0.1, 0.2, 0.3, 0.4 parameter_map = { "alpha": a, beta: b, gamma: c, "delta": d, } with OperationRecorder() as rec: load_program(program)(wires=range(2), parameter_map=parameter_map) expected_queue = [ qml.Hadamard(0), qml.CNOT(wires=[0, 1]), qml.RX(0.1, wires=[1]), qml.RZ(0.2, wires=[1]), qml.RX(0.3, wires=[1]), qml.CNOT(wires=[0, 1]), qml.RZ(0.4, wires=[0]), qml.Hadamard(0), ] for converted, expected in zip(rec.queue, expected_queue): assert converted.name == expected.name assert converted.wires == expected.wires assert converted.params == expected.params
def test_mitigate_executor_pyquil(): """Performs the same test as test_execute_with_pec_pyquil_trivial_decomposition(), but using mitigate_executor() instead of execute_with_pec(). """ circuit = pyquil.Program(pyquil.gates.H(0)) rep = OperationRepresentation( circuit, basis_expansion={NoisyOperation(circuit): 1.0} ) unmitigated = serial_executor(circuit) mitigated_executor = mitigate_executor( serial_executor, representations=[rep], num_samples=10, random_state=1, ) mitigated = mitigated_executor(circuit) assert np.isclose(unmitigated, mitigated)
def _run_and_measure( self, program: pq.Program, num_shots: int, measure_qubits: list, optimize, active_reset=False, ): program = program.copy() qubits = measure_qubits if measure_qubits is not None else program.get_qubits( ) # actively reset qubits at start if active_reset: program = pq.Program(pq.gates.RESET()) + program # add measurements everywhere ro = program.declare("ro", "BIT", len(qubits)) for i, q in enumerate(qubits): program.inst(pq.gates.MEASURE(q, ro[i])) program.wrap_in_numshots_loop(shots=num_shots) try: executable = self.device.compile(program, optimize=optimize) bitstring_array = self.device.run(executable=executable) except Exception as e: print_stderr(e) # we want to log, but not interrupt return { "result": ThinPromise(lambda: None), "transpiled_circuit": None } print_hl(program, color="grey") print_hl(executable.program, color="grey") bitstring_dict = {} for i, q in enumerate(qubits): bitstring_dict[q] = bitstring_array[:, i] return { "result": ThinPromise(lambda: bitstring_dict), "transpiled_circuit": executable.asdict(), }
def load_quil(quil_str: str): """Load a quil string as a PennyLane template. During loading, gates are converted to PennyLane gates as far as possible. If the gates are not supported they are replaced with QubitUnitary instances. The import ignores all statements that are not declarations or gates (e.g. pragmas, classical control flow and measurements). Every variable that is present in the Program and that is not used as the target register of a measurement has to be provided in the ``parameter_map`` of the template. Args: quil_str (str): The program that should be loaded Returns: ProgramLoader: a ProgramLoader instance that can be called like a template """ return load_program(pyquil.Program(quil_str))