Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cudaq::set_random_seed() #477

Merged
merged 13 commits into from
Jul 29, 2023
14 changes: 13 additions & 1 deletion .github/workflows/python_wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,24 @@ jobs:
image: wheel_validation:local
shell: bash
run: |
python${{ inputs.python_version }} -m pytest /tmp/tests/
python${{ inputs.python_version }} -m pytest --ignore /tmp/tests/backends /tmp/tests/
pytest_status=$?
if [ ! $pytest_status -eq 0 ]; then
echo "pytest status = " $pytest_status
exit 1
fi
apt-get update && apt-get install -y git
git clone https://github.com/nvidia/cuda-quantum
cd cuda-quantum
python${{ inputs.python_version }} -m pip install --user fastapi uvicorn llvmlite
schweitzpgi marked this conversation as resolved.
Show resolved Hide resolved
for backendTest in /tmp/tests/backends/*.py; do
python${{ inputs.python_version }} -m pytest $backendTest
pytest_status=$?
if [ ! $pytest_status -eq 0 ]; then
echo "pytest $backendTest status = " $pytest_status
exit 1
fi
done

- name: Validate Python examples
run: |
Expand Down
14 changes: 11 additions & 3 deletions .github/workflows/test_in_devenv.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,21 @@ jobs:
run: |
cd $CUDAQ_REPO_ROOT
pip install . --user -vvv
python3 -m pytest python/tests/
python3 -m pytest --ignore python/tests/backends python/tests/
pytest_status=$?
if [ ! $pytest_status -eq 0 ]; then
echo "pytest status = " $pytest_status
exit 1
fi

fi
for backendTest in python/tests/backends/*.py; do
schweitzpgi marked this conversation as resolved.
Show resolved Hide resolved
python3 -m pytest $backendTest
pytest_status=$?
if [ ! $pytest_status -eq 0 ]; then
echo "pytest $backendTest status = " $pytest_status
exit 1
fi
done

- name: Save environment
id: env_save
if: inputs.export_environment
Expand Down
3 changes: 3 additions & 0 deletions python/cudaq/_cudaq.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ PYBIND11_MODULE(_pycudaq, mod) {
},
"");

mod.def("set_random_seed", &cudaq::set_random_seed,
"Provide the seed for backend quantum kernel simulation.");

auto mpiSubmodule = mod.def_submodule("mpi");
mpiSubmodule.def(
"initialize", []() { cudaq::mpi::initialize(); },
Expand Down
34 changes: 8 additions & 26 deletions python/tests/backends/test_IonQ.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,38 +10,23 @@
import cudaq, pytest, os, time
from cudaq import spin
from multiprocessing import Process
try:
from utils.mock_qpu.ionq import startServer
except:
print("Mock qpu not available, skipping IonQ tests.")
# TODO: Once we remove the general skip below, it should go here.

pytest.skip(
"This file produces a segmentation fault on the CI but not locally. See https://github.com/NVIDIA/cuda-quantum/issues/303.",
allow_module_level=True)
from utils.mock_qpu.ionq import startServer

# Define the port for the mock server
port = 62455


def assert_close(want, got, tolerance=1.0e-5) -> bool:
return abs(want - got) < tolerance
def assert_close(got) -> bool:
return got < -1.5 and got > -1.9


@pytest.fixture(scope="session", autouse=True)
def startUpMockServer():
# TODO: Support passing credentials via config file
os.environ["IONQ_API_KEY"] = "00000000000000000000000000000000"
credsName = "{}/FakeConfig.config".format(os.environ["HOME"])
f = open(credsName, "w")
f.write("key: {}\nrefresh: {}\ntime: 0".format("hello", "rtoken"))
f.close()

# Set the targeted QPU
cudaq.set_target(
"ionq",
url="http://localhost:{}".format(port),
credentials=credsName,
url="http://localhost:{}".format(port)
)

# Launch the Mock Server
Expand All @@ -51,10 +36,8 @@ def startUpMockServer():

yield "Running the tests."

# Kill the server, remove the file
# Kill the server
p.terminate()
os.remove(credsName)


def test_ionq_sample():
# Create the kernel we'd like to execute on IonQ
Expand Down Expand Up @@ -119,14 +102,13 @@ def test_ionq_observe():

# Run the observe task on IonQ synchronously
res = cudaq.observe(kernel, hamiltonian, 0.59)
want_expectation_value = -1.71
assert assert_close(want_expectation_value, res.expectation_z(), 1e-2)
assert assert_close(res.expectation_z())

# Launch it asynchronously, enters the job into the queue
future = cudaq.observe_async(kernel, hamiltonian, 0.59)
# Retrieve the results (since we're on a mock server)
res = future.get()
assert assert_close(want_expectation_value, res.expectation_z(), 1e-2)
assert assert_close(res.expectation_z())

# Launch the job async, job goes in the queue, and
# we're free to dump the future to file
Expand All @@ -139,7 +121,7 @@ def test_ionq_observe():
# the results from the term job ids.
futureReadIn = cudaq.AsyncObserveResult(futureAsString, hamiltonian)
res = futureReadIn.get()
assert assert_close(want_expectation_value, res.expectation_z(), 1e-2)
assert assert_close(res.expectation_z())


# leave for gdb debugging
Expand Down
19 changes: 6 additions & 13 deletions python/tests/backends/test_Quantinuum.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,25 @@
import cudaq, pytest, os, time
from cudaq import spin
from multiprocessing import Process
try:
from utils.mock_qpu.quantinuum import startServer
except:
print("Mock qpu not available, skipping Quantinuum tests.")
# TODO: Once we remove the general skip below, it should go here.

pytest.skip(
"This file produces a segmentation fault on the CI but not locally. See https://github.com/NVIDIA/cuda-quantum/issues/303.",
allow_module_level=True)
from utils.mock_qpu.quantinuum import startServer

# Define the port for the mock server
port = 62454


def assert_close(got) -> bool:
return got < -1.1 and got > -2.2
return got < -1.5 and got > -1.9


@pytest.fixture(scope="session", autouse=True)
def startUpMockServer():
# We need a Fake Credentials Config file
credsName = '{}/FakeConfig.config'.format(os.environ["HOME"])
credsName = '{}/QuantinuumFakeConfig.config'.format(os.environ["HOME"])
f = open(credsName, 'w')
f.write('key: {}\nrefresh: {}\ntime: 0'.format("hello", "rtoken"))
f.close()

cudaq.set_random_seed(13)

# Set the targeted QPU
cudaq.set_target('quantinuum',
url='http://localhost:{}'.format(port),
Expand Down Expand Up @@ -67,6 +60,7 @@ def test_quantinuum_sample():
# server. In reality you'd probably not want to
# do this with the remote job queue.
counts = cudaq.sample(kernel)
counts.dump()
assert (len(counts) == 2)
assert ('00' in counts)
assert ('11' in counts)
Expand Down Expand Up @@ -115,7 +109,6 @@ def test_quantinuum_observe():

# Run the observe task on quantinuum synchronously
res = cudaq.observe(kernel, hamiltonian, .59)
want_expectation_value = -1.71
assert assert_close(res.expectation_z())

# Launch it asynchronously, enters the job into the queue
Expand Down
32 changes: 8 additions & 24 deletions python/tests/backends/test_Quantinuum_LocalEmulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,10 @@
import cudaq, pytest, os, time
from cudaq import spin
from multiprocessing import Process
try:
from utils.mock_qpu.quantinuum import startServer
except:
print("Mock qpu not available, skipping Quantinuum tests.")
# TODO: Once we remove the general skip below, it should go here.

pytest.skip(
"This file produces a segmentation fault on the CI but not locally. See also https://github.com/NVIDIA/cuda-quantum/issues/303.",
allow_module_level=True)

# Define the port for the mock server
port = 62448


def assert_close(want, got, tolerance=1.e-5) -> bool:
return abs(want - got) < tolerance
def assert_close(got) -> bool:
return got < -1.5 and got > -1.9


@pytest.fixture(scope="session", autouse=True)
Expand All @@ -39,19 +27,15 @@ def startUpMockServer():
# Set the targeted QPU
cudaq.set_target('quantinuum', emulate='true')

# Launch the Mock Server
p = Process(target=startServer, args=(port,))
p.start()
time.sleep(1)

yield "Running the tests."

# Kill the server, remove the file
p.terminate()
# remove the file
os.remove(credsName)


def test_quantinuum_sample():
cudaq.set_random_seed(13)

# Create the kernel we'd like to execute on Quantinuum
kernel = cudaq.make_kernel()
qubits = kernel.qalloc(2)
Expand Down Expand Up @@ -81,6 +65,7 @@ def test_quantinuum_sample():


def test_quantinuum_observe():
cudaq.set_random_seed(13)
# Create the parameterized ansatz
kernel, theta = cudaq.make_kernel(float)
qreg = kernel.qalloc(2)
Expand All @@ -94,14 +79,13 @@ def test_quantinuum_observe():

# Run the observe task on quantinuum synchronously
res = cudaq.observe(kernel, hamiltonian, .59, shots_count=100000)
want_expectation_value = -1.71
assert assert_close(want_expectation_value, res.expectation_z(), 1e-1)
assert assert_close(res.expectation_z())

# Launch it asynchronously, enters the job into the queue
future = cudaq.observe_async(kernel, hamiltonian, .59, shots_count=100000)
# Retrieve the results (since we're on a mock server)
res = future.get()
assert assert_close(want_expectation_value, res.expectation_z(), 1e-1)
assert assert_close(res.expectation_z())


# leave for gdb debugging
Expand Down
3 changes: 2 additions & 1 deletion python/utils/TestingUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@

#include "TestingUtils.h"
#include "common/PluginUtils.h"
#include "cudaq.h"
#include "cudaq/platform.h"
#include "nvqir/CircuitSimulator.h"
#include <fstream>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <regex>
#include <sstream>

namespace py = pybind11;

namespace nvqir {
Expand Down Expand Up @@ -43,6 +43,7 @@ void bindTestUtils(py::module &mod, LinkedLibraryHolder &holder) {
"initialize", [&](std::size_t numQubits, std::size_t numShots) {
cudaq::ExecutionContext *context =
new cudaq::ExecutionContext("sample", numShots);
cudaq::set_random_seed(13);
holder.getSimulator("qpp")->setExecutionContext(context);
return std::make_tuple(
holder.getSimulator("qpp")->allocateQubits(numQubits), context);
Expand Down
4 changes: 4 additions & 0 deletions runtime/cudaq.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ void unset_noise();
/// @brief Utility function for clearing the shots
void clear_shots(const std::size_t nShots);

/// @brief Set a seed for any random number
/// generators used in backend simulations.
void set_random_seed(std::size_t seed);

namespace mpi {

/// @brief Initialize MPI if available. This function
Expand Down
9 changes: 8 additions & 1 deletion runtime/cudaq/cudaq.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@

namespace nvqir {
void tearDownBeforeMPIFinalize();
}
void setRandomSeed(std::size_t);
} // namespace nvqir

namespace cudaq::mpi {

Expand Down Expand Up @@ -192,6 +193,10 @@ bool cudaq::__internal__::isLibraryMode(const std::string &kernelname) {

//===----------------------------------------------------------------------===//

namespace nvqir {
void setRandomSeed(std::size_t);
}

namespace cudaq {

/// @brief Global boolean that disables
Expand Down Expand Up @@ -267,6 +272,8 @@ void unset_noise() {
auto &platform = cudaq::get_platform();
platform.set_noise(nullptr);
}

void set_random_seed(std::size_t seed) { nvqir::setRandomSeed(seed); }
} // namespace cudaq

namespace cudaq::support {
Expand Down
4 changes: 4 additions & 0 deletions runtime/nvqir/CircuitSimulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ class CircuitSimulator {
/// simulation strategies that support noise modeling.
virtual void setNoiseModel(cudaq::noise_model &noise) = 0;

virtual void setRandomSeed(std::size_t seed) {
// do nothing
}

/// @brief Compute the expected value of the given spin op
/// with respect to the current state, <psi | H | psi>.
virtual cudaq::ExecutionResult observe(const cudaq::spin_op &term) = 0;
Expand Down
6 changes: 6 additions & 0 deletions runtime/nvqir/NVQIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ CircuitSimulator *getCircuitSimulatorInternal() {
return simulator;
}

void setRandomSeed(std::size_t seed) {
getCircuitSimulatorInternal()->setRandomSeed(seed);
}

thread_local static bool isBaseProfile = false;
void toggleBaseProfile() { isBaseProfile = !isBaseProfile; }

Expand Down Expand Up @@ -364,6 +368,8 @@ Result *__quantum__qis__mz__to__register(Qubit *q, const char *name) {
return b ? ResultOne : ResultZero;
}

bool __quantum__qis__read_result__body(Result *r) { return false; }

void __quantum__rt__array_start_record_output() {}
void __quantum__rt__array_end_record_output() {}
void __quantum__rt__result_record_output(Result *, int8_t *) {}
Expand Down
Loading
Loading