Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
6da8863
Run all non-performance tests in CI instead of regression tests
tdrwenski Jun 24, 2025
b009b39
Move mpiexec fixture to a conftest.py
tdrwenski Jun 24, 2025
687f251
Add test for cnot example through the python interface
tdrwenski Jun 24, 2025
9b9d0d9
Use more informative array assert
tdrwenski Jun 24, 2025
7f242f9
Ignore spack folders when running pytests
tdrwenski Jun 25, 2025
e890855
Increase test tolerances
tdrwenski Jun 25, 2025
30a6198
Compare infidelity to expected value
tdrwenski Jun 30, 2025
b917c4a
Remove nsteps and dT and update expected results
tdrwenski Jun 30, 2025
69ef06f
Update sampling of test data and small cleanup
tdrwenski Jun 30, 2025
3a3210d
Refactor test assert to helper function
tdrwenski Jun 30, 2025
051f49a
Add cnot with guard levels test
tdrwenski Jul 1, 2025
51d68b2
Add assert result sizes
tdrwenski Jul 1, 2025
a67b8dd
Remove unused constants
tdrwenski Jul 1, 2025
e962b93
Add piecewise constant control test
tdrwenski Jul 1, 2025
125622f
Add qft test
tdrwenski Jul 1, 2025
39f46ad
Add state to state test
tdrwenski Jul 1, 2025
45167de
Add swap02 test
tdrwenski Jul 1, 2025
f650054
Add swap12 test
tdrwenski Jul 1, 2025
9407168
Add note about population levels
tdrwenski Jul 1, 2025
a6a158a
Add spinchain tests
tdrwenski Jul 1, 2025
56d35cc
Whitespace cleanups
tdrwenski Jul 1, 2025
29f5c3f
Add evalControls test case
tdrwenski Jul 1, 2025
813f27b
Use random control with fixed random seed
tdrwenski Jul 1, 2025
17996c3
Update expected values for test
tdrwenski Jul 1, 2025
e141bf8
Use temporary path for test output
tdrwenski Jul 1, 2025
477a14f
Rename variable
tdrwenski Jul 1, 2025
dd835e9
Update expected values
tdrwenski Jul 1, 2025
ef6cab5
Add tmp directory to evalControls test
tdrwenski Jul 1, 2025
bff2943
Use mpiexec fixture
tdrwenski Jul 1, 2025
51e3ddb
Always using mpiexec, even for single process, as on slurm this is ne…
tdrwenski Jul 1, 2025
37895ac
Allow for passing mpi options to the python tests
tdrwenski Jul 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .ci-scripts/build_and_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ then
timed_message "Run regression tests"

mpi_exe=$(grep 'MPIEXEC_EXECUTABLE' "${hostconfig_path}" | cut -d'"' -f2 | sed 's/;/ /g')
pytest -v -s -m regression --mpi-exec="${mpi_exe}"
pytest -v -s -m "not performance" --mpi-exec="${mpi_exe}"

timed_message "Quandary tests completed"
fi
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
run: |
spack env activate .spack_env
python -m pip install -e . --prefer-binary
pytest -v -s tests/regression --mpi-opt="--oversubscribe"
pytest -v -s -m "not performance" --mpi-opt="--oversubscribe"

- name: Push packages and update index
env:
Expand Down
2 changes: 1 addition & 1 deletion .pytest.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[pytest]
addopts = --ignore=blt --ignore=uberenv_libs
addopts = --ignore=blt --ignore=uberenv_libs --ignore=.spack_env --ignore=spack

markers =
regression: mark a test as a regression test
Expand Down
11 changes: 5 additions & 6 deletions quandary.py
Original file line number Diff line number Diff line change
Expand Up @@ -1426,12 +1426,11 @@ def execute(*, runtype="simulation", ncores=1, config_filename="config.cfg", dat
if not verbose:
runcommand += " --quiet"
# If parallel run, specify runcommand. Default is 'mpirun -np ', unless batch args are given, then currently using 'srun -n', see end of this file for changing that to other batch systems.
if ncores > 1:
if len(batchargs)>0:
myrun = batch_run # currently set to "srun -n"
else:
myrun = mpi_exec
runcommand = f"{myrun} {ncores} " + runcommand
if len(batchargs)>0:
myrun = batch_run # currently set to "srun -n"
else:
myrun = mpi_exec
runcommand = f"{myrun} {ncores} " + runcommand
if verbose:
print("Running Quandary ... ")

Expand Down
13 changes: 13 additions & 0 deletions tests/python/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""Shared pytest fixtures for Python tests."""

import pytest


@pytest.fixture
def mpi_exec(request):
"""Get MPI executor and options from pytest options."""
executor = request.config.getoption("--mpi-exec")
options = request.config.getoption("--mpi-opt")
if executor != "mpirun":
return f"{executor} {options} -n"
return f"mpirun {options} -np"
9 changes: 0 additions & 9 deletions tests/python/test_env_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,6 @@ def test_file_as_base_directory(quandary, request, tmp_path, clean_env_var, mpi_
assert file_path in str(excinfo.value)


@pytest.fixture
def mpi_exec(request):
"""Get MPI executor from pytest option."""
executor = request.config.getoption("--mpi-exec")
if executor != "mpirun":
return f"{executor} -n "
return "mpirun -np "


@pytest.fixture
def cd_tmp_path(tmp_path):
"""Change to a temporary directory for the test and return afterward."""
Expand Down
37 changes: 37 additions & 0 deletions tests/python/test_evalControls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import numpy as np
import os
from pytest import approx
from quandary import Quandary


def test_evalControls_updates_timestep(mpi_exec, tmp_path, request):
"""
Test that evalControls properly updates timestep (dT) to match sampling rate.
"""
datadir_path = os.path.join(tmp_path, request.node.name)

T = 5.0
quandary = Quandary(
Ne=[2],
freq01=[4.0],
T=T,
verbose=False
)

original_dT = quandary.dT
original_nsteps = quandary.nsteps

# Test evalControls with different sampling rate
points_per_ns = 2
time, _, _ = quandary.evalControls(points_per_ns=points_per_ns, datadir=datadir_path, mpi_exec=mpi_exec)

expected_nsteps = int(np.floor(T * points_per_ns))
expected_dT = T / expected_nsteps

assert time[0] == approx(0.0)
assert time[-1] == approx(T)
assert time[1] - time[0] == approx(expected_dT)

# Verify original settings are restored
assert quandary.dT == approx(original_dT)
assert quandary.nsteps == original_nsteps
168 changes: 168 additions & 0 deletions tests/python/test_example_cnot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import os
import pytest
import numpy as np
from quandary import Quandary
from utils import assert_results_equal

# Mark all tests in this file as regression tests
pytestmark = pytest.mark.regression

EXPECTED_LENGTH = 1222
EXPECTED_INFIDELITY = 8.878046657001537e-05

EXPECTED_PT = [
[
2.87734000820681, 10.2084828702097, 3.56051692161081, 10.024110887425099, 0.119689588026969,
-0.562436390448981, -8.93345535901571, 3.44484827705617, 2.06286670752315, 3.89249555192154
],
[
-2.9180159231296896, 12.2087515999371, -23.089156431207, -4.19328393381954, -5.69791415120672,
-2.6886978940074, 11.226563801034, -5.036756985169349, 10.5696800602371, -1.62524585211734
],
]

EXPECTED_QT = [
[
-0.348841624741643, 8.53241095717569, -4.4376504465481, 3.8174295155143803, 10.4326608744893,
-0.095498326189503, 5.25168638153997, -2.8110244912535003, -7.59465730686269, 2.47175448714252
],
[
6.427777598244551, -3.3248790239003, -4.5100523360834295, 6.087543657080141, -10.646609746997699,
11.392012292061, -3.3794131918228403, -8.74872063545075, 7.451333086132051, -0.0766950105907232
],
]

EXPECTED_ENERGY = [
[
[
0.0, 0.34901327142301, 0.473011956850604, 0.555285026597096, 0.069842096071947,
0.0494333733507312, 0.0412389950511918, 0.0449879240940497, 0.092441027177265, 8.40973352444999e-05
],
[
0.0, 0.329712745694427, 0.631427344995695, 0.705222483334731, 0.195021533108613,
0.105515613439278, 0.049564530621508, 0.0440871191855571, 0.0578785086924327, 4.80529018699317e-05
],
[
1.0, 0.683972616987854, 0.513519662449962, 0.428832898801532, 0.811508875591578,
0.899674588776469, 0.940734433368898, 0.96799101447616, 0.931984272724262, 0.99993177546283
],
[
1.0, 0.637301365961018, 0.382041036035193, 0.310659591977753, 0.923627496026638,
0.94537642527642, 0.968462041771141, 0.942933942897476, 0.917696192253395, 0.999936075198039
],
],
[
[
0.0, 0.987133111411216, 0.562433193103199, 0.769075465888702, 0.351891781635455,
0.349514600195487, 0.377439464911376, 0.245808211210325, 0.739043033057218, 8.03904470221222e-05
],
[
1.0, 0.0333701947461882, 0.408345432340385, 0.275536717225252, 0.607727573743172,
0.65903560390506, 0.615696981888637, 0.734508095105381, 0.256558085054453, 0.999939827908553
],
[
0.0, 0.958580676348588, 0.583890977393659, 0.788362984366934, 0.433827024077578,
0.929364744019182, 0.419775139103579, 0.871558222749287, 0.211581398264166, 0.99991222208567
],
[
1.0, 0.0209160175402728, 0.445330397327355, 0.167024833245191, 0.606553620954251,
0.0620850525500678, 0.587088414384345, 0.148125472053068, 0.792817484475808, 6.75603725578727e-05
],
],
]

EXPECTED_POPULATION = [
[
[
1.0, 0.650986728594546, 0.526988043322036, 0.444714973597238, 0.930157904163221,
0.950566626905697, 0.958761005215817, 0.955012076207555, 0.907558973131879, 0.999915902999063
],
[
1.0, 0.670287254332655, 0.368572655214771, 0.294777516899832, 0.804978467167963,
0.894484386858014, 0.950435469700482, 0.955912881149872, 0.942121491658557, 0.999951947459561
],
[
0.0, 0.316027383043538, 0.486480337824313, 0.571167101492937, 0.188491124757645,
0.100325411595143, 0.0592655670333261, 0.0320089859467604, 0.0680157277087126, 6.82250014792584e-05
],
[
0.0, 0.362698634062056, 0.617958964216483, 0.68934040830239, 0.0763725043254758,
0.0546235750840321, 0.031537958631141, 0.0570660575129625, 0.0823038081685347, 6.39252396400044e-05
],
],
[
[
1.0, 0.0128668886063392, 0.437566807069441, 0.230924534305633, 0.648108218599712,
0.650485400060942, 0.622560535355633, 0.75419178909128, 0.260956967251926, 0.999919609887286
],
[
0.0, 0.966629805280894, 0.591654567870081, 0.724463283009311, 0.392272426533404,
0.340964396392231, 0.384303018433353, 0.265491905230048, 0.743441915296537, 6.01724528776744e-05
],
[
1.0, 0.0414193236828037, 0.416109022880615, 0.211637015927536, 0.566172976271645,
0.0706352563524305, 0.580224861298645, 0.128441777673634, 0.788418602168809, 8.7778378639303e-05
],
[
0.0, 0.979083982482801, 0.554669602924322, 0.832975167034952, 0.393446379397863,
0.937914947810385, 0.412911586017937, 0.851874528357371, 0.207182515946122, 0.999932440065121
],
],
]

# Compare output to expected result for 10 points
NUM_SAMPLES = 10
SAMPLE_INDICES = [int(i * (EXPECTED_LENGTH - 1) / (NUM_SAMPLES - 1)) for i in range(NUM_SAMPLES)]


def test_example_cnot(mpi_exec, tmp_path, request):
"""Test CNOT gate optimization using Python interface."""
datadir_path = os.path.join(tmp_path, request.node.name)

freq01 = [4.80595, 4.8601]
favg = sum(freq01)/len(freq01)
rotfreq = favg*np.ones(len(freq01))
T = 200.0

unitary = np.identity(4)
unitary[2, 2] = 0.0
unitary[3, 3] = 0.0
unitary[2, 3] = 1.0
unitary[3, 2] = 1.0
n_osc = 2
n_levels = 4

quandary = Quandary(
freq01=freq01,
Jkl=[0.005],
rotfreq=rotfreq,
T=T,
targetgate=unitary,
verbose=False,
rand_seed=1234,
)

t, pt, qt, infidelity, energy, population = quandary.optimize(
mpi_exec=mpi_exec,
maxcores=2,
datadir=datadir_path,
)

assert_results_equal(
t=t,
pt=pt,
qt=qt,
infidelity=infidelity,
energy=energy,
population=population,
T=T,
n_osc=n_osc,
n_levels=n_levels,
expected_length=EXPECTED_LENGTH,
expected_infidelity=EXPECTED_INFIDELITY,
expected_pt=EXPECTED_PT,
expected_qt=EXPECTED_QT,
expected_energy=EXPECTED_ENERGY,
expected_population=EXPECTED_POPULATION,
sample_indices=SAMPLE_INDICES
)
Loading