Skip to content

Commit da7c7ff

Browse files
authored
Merge pull request #66 from LLNL/add-python-tests
Add python interface tests
2 parents 45ed5f1 + 37895ac commit da7c7ff

16 files changed

+1675
-18
lines changed

.ci-scripts/build_and_test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ then
263263
timed_message "Run regression tests"
264264

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

268268
timed_message "Quandary tests completed"
269269
fi

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
run: |
5151
spack env activate .spack_env
5252
python -m pip install -e . --prefer-binary
53-
pytest -v -s tests/regression --mpi-opt="--oversubscribe"
53+
pytest -v -s -m "not performance" --mpi-opt="--oversubscribe"
5454
5555
- name: Push packages and update index
5656
env:

.pytest.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[pytest]
2-
addopts = --ignore=blt --ignore=uberenv_libs
2+
addopts = --ignore=blt --ignore=uberenv_libs --ignore=.spack_env --ignore=spack
33

44
markers =
55
regression: mark a test as a regression test

quandary.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,12 +1426,11 @@ def execute(*, runtype="simulation", ncores=1, config_filename="config.cfg", dat
14261426
if not verbose:
14271427
runcommand += " --quiet"
14281428
# 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.
1429-
if ncores > 1:
1430-
if len(batchargs)>0:
1431-
myrun = batch_run # currently set to "srun -n"
1432-
else:
1433-
myrun = mpi_exec
1434-
runcommand = f"{myrun} {ncores} " + runcommand
1429+
if len(batchargs)>0:
1430+
myrun = batch_run # currently set to "srun -n"
1431+
else:
1432+
myrun = mpi_exec
1433+
runcommand = f"{myrun} {ncores} " + runcommand
14351434
if verbose:
14361435
print("Running Quandary ... ")
14371436

tests/python/conftest.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""Shared pytest fixtures for Python tests."""
2+
3+
import pytest
4+
5+
6+
@pytest.fixture
7+
def mpi_exec(request):
8+
"""Get MPI executor and options from pytest options."""
9+
executor = request.config.getoption("--mpi-exec")
10+
options = request.config.getoption("--mpi-opt")
11+
if executor != "mpirun":
12+
return f"{executor} {options} -n"
13+
return f"mpirun {options} -np"

tests/python/test_env_variable.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,15 +120,6 @@ def test_file_as_base_directory(quandary, request, tmp_path, clean_env_var, mpi_
120120
assert file_path in str(excinfo.value)
121121

122122

123-
@pytest.fixture
124-
def mpi_exec(request):
125-
"""Get MPI executor from pytest option."""
126-
executor = request.config.getoption("--mpi-exec")
127-
if executor != "mpirun":
128-
return f"{executor} -n "
129-
return "mpirun -np "
130-
131-
132123
@pytest.fixture
133124
def cd_tmp_path(tmp_path):
134125
"""Change to a temporary directory for the test and return afterward."""

tests/python/test_evalControls.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import numpy as np
2+
import os
3+
from pytest import approx
4+
from quandary import Quandary
5+
6+
7+
def test_evalControls_updates_timestep(mpi_exec, tmp_path, request):
8+
"""
9+
Test that evalControls properly updates timestep (dT) to match sampling rate.
10+
"""
11+
datadir_path = os.path.join(tmp_path, request.node.name)
12+
13+
T = 5.0
14+
quandary = Quandary(
15+
Ne=[2],
16+
freq01=[4.0],
17+
T=T,
18+
verbose=False
19+
)
20+
21+
original_dT = quandary.dT
22+
original_nsteps = quandary.nsteps
23+
24+
# Test evalControls with different sampling rate
25+
points_per_ns = 2
26+
time, _, _ = quandary.evalControls(points_per_ns=points_per_ns, datadir=datadir_path, mpi_exec=mpi_exec)
27+
28+
expected_nsteps = int(np.floor(T * points_per_ns))
29+
expected_dT = T / expected_nsteps
30+
31+
assert time[0] == approx(0.0)
32+
assert time[-1] == approx(T)
33+
assert time[1] - time[0] == approx(expected_dT)
34+
35+
# Verify original settings are restored
36+
assert quandary.dT == approx(original_dT)
37+
assert quandary.nsteps == original_nsteps

tests/python/test_example_cnot.py

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import os
2+
import pytest
3+
import numpy as np
4+
from quandary import Quandary
5+
from utils import assert_results_equal
6+
7+
# Mark all tests in this file as regression tests
8+
pytestmark = pytest.mark.regression
9+
10+
EXPECTED_LENGTH = 1222
11+
EXPECTED_INFIDELITY = 8.878046657001537e-05
12+
13+
EXPECTED_PT = [
14+
[
15+
2.87734000820681, 10.2084828702097, 3.56051692161081, 10.024110887425099, 0.119689588026969,
16+
-0.562436390448981, -8.93345535901571, 3.44484827705617, 2.06286670752315, 3.89249555192154
17+
],
18+
[
19+
-2.9180159231296896, 12.2087515999371, -23.089156431207, -4.19328393381954, -5.69791415120672,
20+
-2.6886978940074, 11.226563801034, -5.036756985169349, 10.5696800602371, -1.62524585211734
21+
],
22+
]
23+
24+
EXPECTED_QT = [
25+
[
26+
-0.348841624741643, 8.53241095717569, -4.4376504465481, 3.8174295155143803, 10.4326608744893,
27+
-0.095498326189503, 5.25168638153997, -2.8110244912535003, -7.59465730686269, 2.47175448714252
28+
],
29+
[
30+
6.427777598244551, -3.3248790239003, -4.5100523360834295, 6.087543657080141, -10.646609746997699,
31+
11.392012292061, -3.3794131918228403, -8.74872063545075, 7.451333086132051, -0.0766950105907232
32+
],
33+
]
34+
35+
EXPECTED_ENERGY = [
36+
[
37+
[
38+
0.0, 0.34901327142301, 0.473011956850604, 0.555285026597096, 0.069842096071947,
39+
0.0494333733507312, 0.0412389950511918, 0.0449879240940497, 0.092441027177265, 8.40973352444999e-05
40+
],
41+
[
42+
0.0, 0.329712745694427, 0.631427344995695, 0.705222483334731, 0.195021533108613,
43+
0.105515613439278, 0.049564530621508, 0.0440871191855571, 0.0578785086924327, 4.80529018699317e-05
44+
],
45+
[
46+
1.0, 0.683972616987854, 0.513519662449962, 0.428832898801532, 0.811508875591578,
47+
0.899674588776469, 0.940734433368898, 0.96799101447616, 0.931984272724262, 0.99993177546283
48+
],
49+
[
50+
1.0, 0.637301365961018, 0.382041036035193, 0.310659591977753, 0.923627496026638,
51+
0.94537642527642, 0.968462041771141, 0.942933942897476, 0.917696192253395, 0.999936075198039
52+
],
53+
],
54+
[
55+
[
56+
0.0, 0.987133111411216, 0.562433193103199, 0.769075465888702, 0.351891781635455,
57+
0.349514600195487, 0.377439464911376, 0.245808211210325, 0.739043033057218, 8.03904470221222e-05
58+
],
59+
[
60+
1.0, 0.0333701947461882, 0.408345432340385, 0.275536717225252, 0.607727573743172,
61+
0.65903560390506, 0.615696981888637, 0.734508095105381, 0.256558085054453, 0.999939827908553
62+
],
63+
[
64+
0.0, 0.958580676348588, 0.583890977393659, 0.788362984366934, 0.433827024077578,
65+
0.929364744019182, 0.419775139103579, 0.871558222749287, 0.211581398264166, 0.99991222208567
66+
],
67+
[
68+
1.0, 0.0209160175402728, 0.445330397327355, 0.167024833245191, 0.606553620954251,
69+
0.0620850525500678, 0.587088414384345, 0.148125472053068, 0.792817484475808, 6.75603725578727e-05
70+
],
71+
],
72+
]
73+
74+
EXPECTED_POPULATION = [
75+
[
76+
[
77+
1.0, 0.650986728594546, 0.526988043322036, 0.444714973597238, 0.930157904163221,
78+
0.950566626905697, 0.958761005215817, 0.955012076207555, 0.907558973131879, 0.999915902999063
79+
],
80+
[
81+
1.0, 0.670287254332655, 0.368572655214771, 0.294777516899832, 0.804978467167963,
82+
0.894484386858014, 0.950435469700482, 0.955912881149872, 0.942121491658557, 0.999951947459561
83+
],
84+
[
85+
0.0, 0.316027383043538, 0.486480337824313, 0.571167101492937, 0.188491124757645,
86+
0.100325411595143, 0.0592655670333261, 0.0320089859467604, 0.0680157277087126, 6.82250014792584e-05
87+
],
88+
[
89+
0.0, 0.362698634062056, 0.617958964216483, 0.68934040830239, 0.0763725043254758,
90+
0.0546235750840321, 0.031537958631141, 0.0570660575129625, 0.0823038081685347, 6.39252396400044e-05
91+
],
92+
],
93+
[
94+
[
95+
1.0, 0.0128668886063392, 0.437566807069441, 0.230924534305633, 0.648108218599712,
96+
0.650485400060942, 0.622560535355633, 0.75419178909128, 0.260956967251926, 0.999919609887286
97+
],
98+
[
99+
0.0, 0.966629805280894, 0.591654567870081, 0.724463283009311, 0.392272426533404,
100+
0.340964396392231, 0.384303018433353, 0.265491905230048, 0.743441915296537, 6.01724528776744e-05
101+
],
102+
[
103+
1.0, 0.0414193236828037, 0.416109022880615, 0.211637015927536, 0.566172976271645,
104+
0.0706352563524305, 0.580224861298645, 0.128441777673634, 0.788418602168809, 8.7778378639303e-05
105+
],
106+
[
107+
0.0, 0.979083982482801, 0.554669602924322, 0.832975167034952, 0.393446379397863,
108+
0.937914947810385, 0.412911586017937, 0.851874528357371, 0.207182515946122, 0.999932440065121
109+
],
110+
],
111+
]
112+
113+
# Compare output to expected result for 10 points
114+
NUM_SAMPLES = 10
115+
SAMPLE_INDICES = [int(i * (EXPECTED_LENGTH - 1) / (NUM_SAMPLES - 1)) for i in range(NUM_SAMPLES)]
116+
117+
118+
def test_example_cnot(mpi_exec, tmp_path, request):
119+
"""Test CNOT gate optimization using Python interface."""
120+
datadir_path = os.path.join(tmp_path, request.node.name)
121+
122+
freq01 = [4.80595, 4.8601]
123+
favg = sum(freq01)/len(freq01)
124+
rotfreq = favg*np.ones(len(freq01))
125+
T = 200.0
126+
127+
unitary = np.identity(4)
128+
unitary[2, 2] = 0.0
129+
unitary[3, 3] = 0.0
130+
unitary[2, 3] = 1.0
131+
unitary[3, 2] = 1.0
132+
n_osc = 2
133+
n_levels = 4
134+
135+
quandary = Quandary(
136+
freq01=freq01,
137+
Jkl=[0.005],
138+
rotfreq=rotfreq,
139+
T=T,
140+
targetgate=unitary,
141+
verbose=False,
142+
rand_seed=1234,
143+
)
144+
145+
t, pt, qt, infidelity, energy, population = quandary.optimize(
146+
mpi_exec=mpi_exec,
147+
maxcores=2,
148+
datadir=datadir_path,
149+
)
150+
151+
assert_results_equal(
152+
t=t,
153+
pt=pt,
154+
qt=qt,
155+
infidelity=infidelity,
156+
energy=energy,
157+
population=population,
158+
T=T,
159+
n_osc=n_osc,
160+
n_levels=n_levels,
161+
expected_length=EXPECTED_LENGTH,
162+
expected_infidelity=EXPECTED_INFIDELITY,
163+
expected_pt=EXPECTED_PT,
164+
expected_qt=EXPECTED_QT,
165+
expected_energy=EXPECTED_ENERGY,
166+
expected_population=EXPECTED_POPULATION,
167+
sample_indices=SAMPLE_INDICES
168+
)

0 commit comments

Comments
 (0)