Skip to content

Commit

Permalink
Convert noise_model usage to shared_ptr to fix new test
Browse files Browse the repository at this point in the history
  • Loading branch information
bmhowe23 committed Sep 9, 2023
1 parent 447b7ce commit b46040f
Show file tree
Hide file tree
Showing 12 changed files with 74 additions and 67 deletions.
2 changes: 1 addition & 1 deletion python/runtime/common/py_NoiseModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ void bindNoiseModel(py::module &mod) {
.def("append", &kraus_channel::push_back,
"Add a KrausOperator to this KrausChannel.");

py::class_<noise_model>(
py::class_<noise_model, std::shared_ptr<noise_model>>(
mod, "NoiseModel",
"The cudaq NoiseModel defines a set of KrausChannels applied to "
"specific qubits after the invocation specified quantum operations.")
Expand Down
34 changes: 18 additions & 16 deletions python/runtime/cudaq/algorithms/py_observe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ std::unordered_map<std::size_t, std::unique_ptr<OpaqueArguments>>
/// @brief Run `cudaq::observe` on the provided kernel and spin operator.
observe_result pyObserve(kernel_builder<> &kernel, spin_op &spin_operator,
py::args args, int shots,
std::optional<noise_model> noise) {
std::optional<std::shared_ptr<noise_model>> noise) {
// Ensure the user input is correct.
auto validatedArgs = validateInputArguments(kernel, args);
auto &platform = cudaq::get_platform();
if (noise)
platform.set_noise(&*noise);
platform.set_noise(*noise);

// TODO: would like to handle errors in the case that
// `kernel.num_qubits() >= spin_operator.num_qubits()`
Expand Down Expand Up @@ -98,10 +98,11 @@ async_observe_result pyObserveAsync(kernel_builder<> &kernel,
}

/// @brief Run `cudaq::observe` on the provided kernel and spin operator.
observe_result pyObservePar(const PyParType &type, kernel_builder<> &kernel,
spin_op &spin_operator, py::args args = {},
int shots = defaultShotsValue,
std::optional<noise_model> noise = std::nullopt) {
observe_result
pyObservePar(const PyParType &type, kernel_builder<> &kernel,
spin_op &spin_operator, py::args args = {},
int shots = defaultShotsValue,
std::optional<std::shared_ptr<noise_model>> noise = std::nullopt) {
// Ensure the user input is correct.
auto validatedArgs = validateInputArguments(kernel, args);
auto &platform = cudaq::get_platform();
Expand Down Expand Up @@ -165,13 +166,13 @@ observe_result pyObservePar(const PyParType &type, kernel_builder<> &kernel,
std::vector<observe_result>
pyObserveN(kernel_builder<> &kernel, spin_op &op, py::args args = {},
std::size_t shots = defaultShotsValue,
std::optional<noise_model> noise = std::nullopt) {
std::optional<std::shared_ptr<noise_model>> noise = std::nullopt) {

auto argSet = createArgumentSet(args);
auto N = argSet.size();
auto &platform = cudaq::get_platform();
if (noise)
platform.set_noise(&*noise);
platform.set_noise(*noise);
kernel.jitCode();
auto name = kernel.name();
std::vector<observe_result> results;
Expand Down Expand Up @@ -216,42 +217,43 @@ void bindObserve(py::module &mod) {
"observe",
[&](kernel_builder<> &kernel,
std::variant<spin_op, std::vector<spin_op>> &spin_operator,
py::args arguments, int shots, std::optional<noise_model> noise,
py::args arguments, int shots,
std::optional<std::shared_ptr<noise_model>> noise,
std::optional<py::type> execution)
-> std::variant<observe_result, std::vector<observe_result>> {
// Observe can be a single observe call, a parallel observe call,
// or a observe broadcast. We'll handle them all here.

using ObserveApplicator = std::function<std::vector<observe_result>(
kernel_builder<> &, spin_op &, py::args &, int,
std::optional<noise_model>)>;
std::optional<std::shared_ptr<noise_model>>)>;

std::unordered_map<std::string, ObserveApplicator> applicator{
{"default",
[](kernel_builder<> &kernel, spin_op &spin_operator,
py::args arguments, int shots,
std::optional<noise_model> noise) {
std::optional<std::shared_ptr<noise_model>> noise) {
return std::vector<observe_result>{
pyObserve(kernel, spin_operator, arguments, shots, noise)};
}},
{"broadcast",
[](kernel_builder<> &kernel, spin_op &spin_operator,
py::args arguments, int shots,
std::optional<noise_model> noise) {
std::optional<std::shared_ptr<noise_model>> noise) {
return pyObserveN(kernel, spin_operator, arguments, shots,
noise);
}},
{"thread",
[](kernel_builder<> &kernel, spin_op &spin_operator,
py::args arguments, int shots,
std::optional<noise_model> noise) {
std::optional<std::shared_ptr<noise_model>> noise) {
return std::vector<observe_result>{
pyObservePar(PyParType::thread, kernel, spin_operator,
arguments, shots, noise)};
}},
{"mpi", [](kernel_builder<> &kernel, spin_op &spin_operator,
py::args arguments, int shots,
std::optional<noise_model> noise) {
std::optional<std::shared_ptr<noise_model>> noise) {
return std::vector<observe_result>{
pyObservePar(PyParType::mpi, kernel, spin_operator,
arguments, shots, noise)};
Expand Down Expand Up @@ -341,7 +343,7 @@ all argument sets and a list of `observe_result` instances will be returned.
"observe_async",
[&](kernel_builder<> &kernel, spin_op &spin_operator, py::args arguments,
std::size_t qpu_id, int shots,
std::optional<noise_model> noise_model) {
std::optional<std::shared_ptr<noise_model>> noise_model) {
if (!noise_model)
return pyObserveAsync(kernel, spin_operator, arguments, qpu_id,
shots);
Expand Down Expand Up @@ -384,7 +386,7 @@ can be retrieved via `future.get()`.
mod.def(
"observe_n",
[](kernel_builder<> &self, spin_op &spin_operator, py::args args,
int shots, std::optional<noise_model> noise_model) {
int shots, std::optional<std::shared_ptr<noise_model>> noise_model) {
PyErr_WarnEx(PyExc_DeprecationWarning,
"observe_n() is deprecated, use observe() with the same "
"argument-list structure.",
Expand Down
7 changes: 4 additions & 3 deletions python/runtime/cudaq/algorithms/py_observe.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ inline constexpr int defaultShotsValue = -1;

/// @brief Functions for running `cudaq::observe()` from python.
/// Exposing pyObserve in the header for use elsewhere in the bindings.
observe_result pyObserve(kernel_builder<> &kernel, spin_op &spin_operator,
py::args args = {}, int shots = defaultShotsValue,
std::optional<noise_model> noise = std::nullopt);
observe_result
pyObserve(kernel_builder<> &kernel, spin_op &spin_operator, py::args args = {},
int shots = defaultShotsValue,
std::optional<std::shared_ptr<noise_model>> noise = std::nullopt);

/// @brief Expose binding of `cudaq::observe()` and `cudaq::observe_async` to
/// python.
Expand Down
28 changes: 15 additions & 13 deletions python/runtime/cudaq/algorithms/py_sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@
namespace cudaq {

/// @brief Sample the state produced by the provided builder.
sample_result pySample(kernel_builder<> &builder, py::args args = {},
std::size_t shots = 1000,
std::optional<noise_model> noise = std::nullopt) {
sample_result
pySample(kernel_builder<> &builder, py::args args = {},
std::size_t shots = 1000,
std::optional<std::shared_ptr<noise_model>> noise = std::nullopt) {
// Ensure the user input is correct.
auto validatedArgs = validateInputArguments(builder, args);

Expand All @@ -40,7 +41,7 @@ sample_result pySample(kernel_builder<> &builder, py::args args = {},

auto &platform = cudaq::get_platform();
if (noise)
platform.set_noise(&*noise);
platform.set_noise(*noise);

auto result = details::runSampling(
[&]() mutable { builder.jitAndInvoke(argData.data()); },
Expand All @@ -54,14 +55,14 @@ sample_result pySample(kernel_builder<> &builder, py::args args = {},
std::vector<sample_result>
pySampleN(kernel_builder<> &kernel, py::args args = {},
std::size_t shots = 1000,
std::optional<noise_model> noise = std::nullopt) {
std::optional<std::shared_ptr<noise_model>> noise = std::nullopt) {
auto argSet = createArgumentSet(args);
auto N = argSet.size();
kernel.jitCode();
auto name = kernel.name();
auto &platform = cudaq::get_platform();
if (noise)
platform.set_noise(&*noise);
platform.set_noise(*noise);

std::vector<sample_result> results;
for (std::size_t currentIter = 0; auto &a : argSet) {
Expand Down Expand Up @@ -129,16 +130,16 @@ for more information on this programming pattern.)#")
mod.def(
"sample",
[&](kernel_builder<> &builder, py::args arguments, std::size_t shots,
std::optional<noise_model> noise)
std::optional<std::shared_ptr<noise_model>> noise)
-> std::variant<sample_result, std::vector<sample_result>> {
// Our arguments can be a single set of arguments for the kernel
// in that case the applicator should just be delegating to pySample
std::function<std::vector<sample_result>(kernel_builder<> &, py::args,
std::size_t,
std::optional<noise_model>)>
std::function<std::vector<sample_result>(
kernel_builder<> &, py::args, std::size_t,
std::optional<std::shared_ptr<noise_model>>)>
applicator = [](kernel_builder<> &builder, py::args arguments,
std::size_t shots,
std::optional<noise_model> noise) {
std::optional<std::shared_ptr<noise_model>> noise) {
return std::vector<sample_result>{
pySample(builder, arguments, shots, noise)};
};
Expand All @@ -147,7 +148,8 @@ for more information on this programming pattern.)#")
// we'll delegate to sample_n.
if (isBroadcastRequest(builder, arguments))
applicator = [](kernel_builder<> &builder, py::args arguments,
std::size_t shots, std::optional<noise_model> noise) {
std::size_t shots,
std::optional<std::shared_ptr<noise_model>> noise) {
return pySampleN(builder, arguments, shots, noise);
};

Expand Down Expand Up @@ -222,7 +224,7 @@ future whose results can be retrieved via `future.get()`.
mod.def(
"sample_n",
[](kernel_builder<> &self, py::args args, std::size_t shots,
std::optional<noise_model> noise) {
std::optional<std::shared_ptr<noise_model>> noise) {
PyErr_WarnEx(PyExc_DeprecationWarning,
"sample_n() is deprecated, use sample() with the same "
"argument-list structure.",
Expand Down
2 changes: 1 addition & 1 deletion runtime/common/ExecutionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class ExecutionContext {

/// @brief Noise model to apply to the
/// current execution.
noise_model *noiseModel = nullptr;
std::shared_ptr<cudaq::noise_model> noiseModel = nullptr;

/// @brief Flag to indicate if backend can
/// handle spin_op observe task under this ExecutionContext.
Expand Down
2 changes: 1 addition & 1 deletion runtime/cudaq.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ void set_target_backend(const char *backend);
void set_shots(const std::size_t nShots);

/// @brief Set a custom noise model for simulation
void set_noise(cudaq::noise_model &model);
void set_noise(std::shared_ptr<cudaq::noise_model> model);

/// @brief Remove an existing noise model from simulation.
void unset_noise();
Expand Down
4 changes: 2 additions & 2 deletions runtime/cudaq/cudaq.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,9 @@ void clear_shots(const std::size_t nShots) {
platform.clear_shots();
}

void set_noise(cudaq::noise_model &model) {
void set_noise(std::shared_ptr<cudaq::noise_model> model) {
auto &platform = cudaq::get_platform();
platform.set_noise(&model);
platform.set_noise(model);
}

void unset_noise() {
Expand Down
2 changes: 1 addition & 1 deletion runtime/cudaq/platform/default/rest/RemoteRESTQPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class RemoteRESTQPU : public cudaq::QPU {

/// @brief Set the noise model, only allow this for
/// emulation.
void setNoiseModel(cudaq::noise_model *model) override {
void setNoiseModel(std::shared_ptr<cudaq::noise_model> model) override {
if (!emulate && model)
throw std::runtime_error(
"Noise modeling is not allowed on remote physical quantum backends.");
Expand Down
6 changes: 4 additions & 2 deletions runtime/cudaq/platform/qpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class QPU : public registry::RegisteredType<QPU> {
ExecutionContext *executionContext = nullptr;

/// @brief Noise model specified for QPU execution.
noise_model *noiseModel = nullptr;
std::shared_ptr<noise_model> noiseModel = nullptr;

/// @brief Check if the current execution context is a `spin_op`
/// observation and perform state-preparation circuit measurement
Expand Down Expand Up @@ -100,7 +100,9 @@ class QPU : public registry::RegisteredType<QPU> {
/// The destructor
virtual ~QPU() = default;

virtual void setNoiseModel(noise_model *model) { noiseModel = model; }
virtual void setNoiseModel(std::shared_ptr<noise_model> model) {
noiseModel = model;
}

/// Return the number of qubits
std::size_t getNumQubits() { return numQubits; }
Expand Down
2 changes: 1 addition & 1 deletion runtime/cudaq/platform/quantum_platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ quantum_platform *getQuantumPlatformInternal() {
return platform;
}

void quantum_platform::set_noise(noise_model *model) {
void quantum_platform::set_noise(std::shared_ptr<noise_model> model) {
auto &platformQPU = platformQPUs[platformCurrentQPU];
platformQPU->setNoiseModel(model);
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/cudaq/platform/quantum_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class quantum_platform {

/// @brief Set the noise model for future invocations of
/// quantum kernels.
void set_noise(noise_model *model);
void set_noise(std::shared_ptr<noise_model> model);

/// @brief Turn off any noise models.
void reset_noise();
Expand Down
Loading

0 comments on commit b46040f

Please sign in to comment.