-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Revert "Maintain API changes for Pilot. "
- Loading branch information
1 parent
73d732b
commit 389d429
Showing
20 changed files
with
1,979 additions
and
595 deletions.
There are no files selected for viewing
1,026 changes: 1,026 additions & 0 deletions
1,026
examples/circuit_execution/pilot-quantum-sshca501f62-312d-11ef-887a-d2b91fefeab2-metrics.csv
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import os | ||
|
||
import pennylane as qml | ||
from examples.circuit_execution.qiskit_benchmark import generate_data | ||
from pilot.pilot_compute_service import PilotComputeService | ||
from time import sleep | ||
from qiskit_aer.primitives import Estimator as AirEstimator | ||
|
||
RESOURCE_URL_HPC = "ssh://localhost" | ||
WORKING_DIRECTORY = os.path.join(os.environ["HOME"], "work") | ||
|
||
pilot_compute_description_dask = { | ||
"resource": RESOURCE_URL_HPC, | ||
"working_directory": WORKING_DIRECTORY, | ||
"type": "dask", | ||
"number_of_nodes": 1, | ||
"cores_per_node": 10, | ||
} | ||
|
||
|
||
def start_pilot(): | ||
pcs = PilotComputeService() | ||
dp = pcs.create_pilot(pilot_compute_description=pilot_compute_description_dask) | ||
dp.wait() | ||
return dp | ||
|
||
def run_circuit(circ_obs, qiskit_backend_options): | ||
estimator_result = AirEstimator(backend_options=qiskit_backend_options).run(circ_obs[0], circ_obs[1]).result() | ||
print(estimator_result) | ||
return estimator_result | ||
|
||
if __name__ == "__main__": | ||
dask_pilot, dask_client = None, None | ||
|
||
try: | ||
# Start Pilot | ||
dask_pilot = start_pilot() | ||
|
||
# Get Dask client details | ||
dask_client = dask_pilot.get_client() | ||
print(dask_client.scheduler_info()) | ||
|
||
|
||
circuits, observables = generate_data( | ||
depth_of_recursion=1, | ||
num_qubits=25, | ||
n_entries=10, | ||
circuit_depth=1, | ||
size_of_observable=1 | ||
) | ||
|
||
circuits_observables = zip(circuits, observables) | ||
|
||
tasks = [] | ||
for i, co in enumerate(circuits_observables): | ||
k = dask_pilot.submit_task(f"task_ce-{i}",run_circuit, co, {"method": "statevector"}) | ||
tasks.append(k) | ||
|
||
dask_pilot.wait_tasks(tasks) | ||
finally: | ||
if dask_pilot: | ||
dask_pilot.cancel() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
# This code is a Qiskit project. | ||
# | ||
# (C) Copyright IBM 2023. | ||
# | ||
# This code is licensed under the Apache License, Version 2.0. You may | ||
# obtain a copy of this license in the LICENSE.txt file in the root directory | ||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. | ||
# | ||
# Any modifications or derivative works of this code must retain this | ||
# copyright notice, and modified files need to carry a notice indicating | ||
# that they have been altered from the originals. | ||
|
||
|
||
"""This is benchmark program for stress testing compute resources.""" | ||
import argparse | ||
import time | ||
from typing import List | ||
|
||
from qiskit import QuantumCircuit, transpile | ||
from qiskit.circuit.random import random_circuit | ||
from qiskit.primitives import Estimator | ||
from qiskit.providers import Backend | ||
from qiskit.providers.fake_provider import ConfigurableFakeBackend | ||
from qiskit.quantum_info.random import random_pauli_list | ||
|
||
|
||
# from quantum_serverless import QuantumServerless, get, distribute_task, put | ||
|
||
|
||
# @distribute_task() | ||
def generate_circuits( | ||
depth_of_recursion: int, num_qubits: int, depth_of_circuit: int, n_circuits: int | ||
): | ||
"""Generates random circuits.""" | ||
circuits = [random_circuit(num_qubits, depth_of_circuit) for _ in range(n_circuits)] | ||
if depth_of_recursion <= 1: | ||
return circuits | ||
else: | ||
return circuits + generate_circuits( | ||
depth_of_recursion - 1, num_qubits, depth_of_circuit, n_circuits | ||
) | ||
|
||
|
||
# @distribute_task() | ||
def generate_observables( | ||
depth_of_recursion: int, num_qubits: int, size: int, n_observables: int | ||
): | ||
"""Generated random observables.""" | ||
observables = [random_pauli_list(num_qubits, size) for _ in range(n_observables)] | ||
if depth_of_recursion <= 1: | ||
return observables | ||
else: | ||
return observables + generate_observables(depth_of_recursion - 1, num_qubits, size, n_observables) | ||
|
||
|
||
# @distribute_task() | ||
def generate_data( | ||
depth_of_recursion: int, | ||
num_qubits: int, | ||
n_entries: int, | ||
circuit_depth: int = 2, | ||
size_of_observable: int = 2, | ||
): | ||
return generate_circuits( | ||
depth_of_recursion=depth_of_recursion, | ||
num_qubits=num_qubits, | ||
n_circuits=n_entries, | ||
depth_of_circuit=circuit_depth, | ||
), generate_observables( | ||
depth_of_recursion=depth_of_recursion, | ||
num_qubits=num_qubits, | ||
size=size_of_observable, | ||
n_observables=n_entries, | ||
) | ||
|
||
|
||
def get_backends(n_backends: int, num_qubits: int): | ||
"""Returns list of backends for program.""" | ||
backend = ConfigurableFakeBackend("Tashkent", n_qubits=num_qubits, version=1) | ||
return [backend for _ in range(n_backends)] | ||
|
||
|
||
# @distribute_task() | ||
def transpile_remote( | ||
circuits: List[QuantumCircuit], backend: Backend | ||
) -> List[QuantumCircuit]: | ||
"""Transpiles circuits against backend.""" | ||
return transpile(circuits, backend) | ||
|
||
|
||
# @distribute_task() | ||
def estimate(circuits: list, observables: list): | ||
"""Estimates expectation values of given circuit.""" | ||
return Estimator().run(circuits, observables).result() | ||
|
||
|
||
# @distribute_task() | ||
def run_graph( | ||
depth_of_recursion: int, | ||
num_qubits: int, | ||
n_entries: int, | ||
circuit_depth: int, | ||
size_of_observable: int, | ||
n_backends: int, | ||
): | ||
backends = get_backends(n_backends, num_qubits) | ||
|
||
circuits, observables = generate_data( | ||
depth_of_recursion=depth_of_recursion, | ||
num_qubits=num_qubits, | ||
n_entries=n_entries, | ||
circuit_depth=circuit_depth, | ||
size_of_observable=size_of_observable, | ||
) | ||
|
||
# observables_ref = put(observables) | ||
|
||
results = [] | ||
for backend in backends: | ||
results.append(estimate(transpile_remote(circuits, backend), observables)) | ||
|
||
return results | ||
|
||
|
||
if __name__ == "__main__": | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument( | ||
"--depth_of_recursion", | ||
help="Depth of recursion in generating data.", | ||
default=3, | ||
type=int, | ||
) | ||
parser.add_argument( | ||
"--num_qubits", help="Number of qubits used in program.", default=2, type=int | ||
) | ||
parser.add_argument("--n_entries", help="Number of circuits.", default=10, type=int) | ||
parser.add_argument( | ||
"--circuit_depth", help="Depth of circuits.", default=3, type=int | ||
) | ||
parser.add_argument( | ||
"--size_of_observable", | ||
help="Size of observables in program.", | ||
default=3, | ||
type=int, | ||
) | ||
parser.add_argument("--n_backends", help="Number of backends", default=3, type=int) | ||
parser.add_argument( | ||
"--n_graphs", help="Number of graphs to run", default=1, type=int | ||
) | ||
|
||
args = parser.parse_args() | ||
|
||
t0: float = time.time() | ||
results = run_graph( | ||
depth_of_recursion=args.depth_of_recursion, | ||
num_qubits=args.num_qubits, | ||
n_entries=args.n_entries, | ||
circuit_depth=args.circuit_depth, | ||
size_of_observable=args.size_of_observable, | ||
n_backends=args.n_backends, | ||
) | ||
runtime = time.time() - t0 | ||
|
||
print(f"Execution time: {runtime}") | ||
print(f"Results: {results}") |
106 changes: 106 additions & 0 deletions
106
examples/pennylane/hybrid_computation/pq_decorator_hc.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import matplotlib.pyplot as plt | ||
import pennylane as qml | ||
from pennylane import numpy as np | ||
|
||
import pilot.pilot_compute_service as pcs | ||
|
||
plt.set_loglevel("warning") | ||
|
||
import os | ||
|
||
import matplotlib.pyplot as plt | ||
|
||
RESOURCE_URL_HPC = "ssh://localhost" | ||
WORKING_DIRECTORY = os.path.join(os.environ["HOME"], "work") | ||
|
||
pilot_compute_description_dask = { | ||
"resource": RESOURCE_URL_HPC, | ||
"working_directory": WORKING_DIRECTORY, | ||
"queue": "debug", | ||
"type": "dask", | ||
"walltime": 15, | ||
"project": "m4408", | ||
"number_of_nodes": 1, | ||
"cores_per_node": 2, | ||
"scheduler_script_commands": ["#SBATCH --constraint=cpu"] | ||
} | ||
|
||
|
||
def start_pilot(): | ||
p = pcs.PilotComputeService() | ||
dp = p.create_pilot(pilot_compute_description=pilot_compute_description_dask) | ||
dp.wait() | ||
return dp | ||
|
||
|
||
dask_pilot = start_pilot() | ||
dev_fock = qml.device("strawberryfields.fock", wires=2, cutoff_dim=10) | ||
dev_qubit = qml.device("default.qubit", wires=1) | ||
|
||
|
||
@qml.qnode(dev_fock) | ||
def photon_redirection(params): | ||
qml.FockState(1, wires=0) | ||
qml.Beamsplitter(params[0], params[1], wires=[0, 1]) | ||
return qml.expval(qml.NumberOperator(1)) | ||
|
||
|
||
@qml.qnode(dev_qubit) | ||
def qubit_rotation(phi1, phi2): | ||
qml.RX(phi1, wires=0) | ||
qml.RY(phi2, wires=0) | ||
return qml.expval(qml.PauliZ(0)) | ||
|
||
|
||
def squared_difference(x, y): | ||
return np.abs(x - y) ** 2 | ||
|
||
|
||
def cost(params, phi1=0.4, phi2=0.8): | ||
qubit_result = qubit_rotation(phi1, phi2) | ||
photon_result = photon_redirection(params) | ||
return squared_difference(qubit_result, photon_result) | ||
|
||
|
||
def get_init_params(init_params): | ||
return np.array(init_params, requires_grad=True) | ||
|
||
|
||
@dask_pilot.task | ||
def get_optimizer(): | ||
return qml.GradientDescentOptimizer(stepsize=0.4) | ||
|
||
|
||
@dask_pilot.task | ||
def training(opt, init_params, cost, steps): | ||
params = init_params | ||
training_steps, cost_steps = [], [] # to record the costs as training progresses | ||
for i in range(steps): | ||
params = opt.step(cost, params) | ||
training_steps.append(i) | ||
cost_steps.append(cost(params)) | ||
return params, training_steps, cost_steps | ||
|
||
|
||
if __name__ == "__main__": | ||
try: | ||
# Workflow | ||
init_params = [0.01, 0.01] | ||
steps = 50 | ||
|
||
opt = get_optimizer() | ||
params = get_init_params(init_params) | ||
t = training(opt, params, cost, steps) | ||
opt_params, training_steps, cost_steps = t.result() | ||
|
||
# Plot the results | ||
fig, ax = plt.subplots(1, 1, figsize=(7, 5), facecolor="w") | ||
ax.plot(training_steps, cost_steps) | ||
ax.set_xlabel("Training steps") | ||
ax.set_ylabel("Cost") | ||
ax.set_title("Cost vs. Training steps") | ||
plt.tight_layout() | ||
plt.show() | ||
finally: | ||
if dask_pilot: | ||
dask_pilot.cancel() |
Oops, something went wrong.