Skip to content

Commit

Permalink
Revert "Maintain API changes for Pilot. "
Browse files Browse the repository at this point in the history
  • Loading branch information
pradeepmantha authored Aug 22, 2024
1 parent 73d732b commit 389d429
Show file tree
Hide file tree
Showing 20 changed files with 1,979 additions and 595 deletions.

Large diffs are not rendered by default.

62 changes: 62 additions & 0 deletions examples/circuit_execution/pq_circuit_execution.py
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()
165 changes: 165 additions & 0 deletions examples/circuit_execution/qiskit_benchmark.py
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 examples/pennylane/hybrid_computation/pq_decorator_hc.py
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()
Loading

0 comments on commit 389d429

Please sign in to comment.