Skip to content

Commit 0422071

Browse files
authored
Merge branch 'main' into tnguyen/payload-decoder-quantinuum
2 parents 7f8736c + 86e83e0 commit 0422071

File tree

2 files changed

+147
-0
lines changed

2 files changed

+147
-0
lines changed

unittests/dynamics/test_EvolveBatchedImpl.cpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,3 +809,90 @@ TEST(BatchedEvolveTester, checkParamSweep) {
809809

810810
EXPECT_GT(maxOverlap, 0.98); // Expect a high overlap with the target state
811811
}
812+
813+
TEST(BatchedEvolveTester, checkIntermediateResultSaveAll) {
814+
const cudaq::dimension_map dims = {{0, 2}};
815+
cudaq::product_op<cudaq::matrix_handler> ham_1 =
816+
(2.0 * M_PI * 0.1 * cudaq::spin_op::x(0));
817+
cudaq::sum_op<cudaq::matrix_handler> ham1(ham_1);
818+
819+
cudaq::product_op<cudaq::matrix_handler> ham_2 =
820+
(2.0 * M_PI * 0.2 * cudaq::spin_op::x(0));
821+
cudaq::sum_op<cudaq::matrix_handler> ham2(ham_2);
822+
823+
constexpr int numSteps = 5; // Use fewer steps for this test
824+
std::vector<double> steps = cudaq::linspace(0.0, 1.0, numSteps);
825+
cudaq::schedule schedule(steps, {"t"});
826+
827+
cudaq::product_op<cudaq::matrix_handler> pauliZ_t = cudaq::spin_op::z(0);
828+
cudaq::sum_op<cudaq::matrix_handler> pauliZ(pauliZ_t);
829+
auto initialState1 =
830+
cudaq::state::from_data(std::vector<std::complex<double>>{1.0, 0.0});
831+
auto initialState2 =
832+
cudaq::state::from_data(std::vector<std::complex<double>>{1.0, 0.0});
833+
834+
cudaq::integrators::runge_kutta integrator(4, 0.01);
835+
auto results = cudaq::__internal__::evolveBatched(
836+
{ham1, ham2}, dims, schedule, {initialState1, initialState2}, integrator,
837+
{}, {pauliZ}, cudaq::IntermediateResultSave::All);
838+
839+
EXPECT_EQ(results.size(), 2);
840+
841+
// Check that both results have states and expectation values
842+
for (const auto &result : results) {
843+
EXPECT_TRUE(result.states.has_value());
844+
EXPECT_TRUE(result.expectation_values.has_value());
845+
846+
// For IntermediateResultSave::All, we should have states for each time step
847+
EXPECT_EQ(result.states.value().size(), numSteps);
848+
EXPECT_EQ(result.expectation_values.value().size(), numSteps);
849+
850+
// Check that each time step has expectation values
851+
for (const auto &expVals : result.expectation_values.value()) {
852+
EXPECT_EQ(expVals.size(), 1); // One observable (pauliZ)
853+
}
854+
}
855+
}
856+
857+
TEST(BatchedEvolveTester, checkIntermediateResultSaveNoneWithObservables) {
858+
const cudaq::dimension_map dims = {{0, 2}};
859+
cudaq::product_op<cudaq::matrix_handler> ham_1 =
860+
(2.0 * M_PI * 0.1 * cudaq::spin_op::x(0));
861+
cudaq::sum_op<cudaq::matrix_handler> ham1(ham_1);
862+
863+
cudaq::product_op<cudaq::matrix_handler> ham_2 =
864+
(2.0 * M_PI * 0.2 * cudaq::spin_op::x(0));
865+
cudaq::sum_op<cudaq::matrix_handler> ham2(ham_2);
866+
867+
constexpr int numSteps = 3; // Use fewer steps for this test
868+
std::vector<double> steps = cudaq::linspace(0.0, 1.0, numSteps);
869+
cudaq::schedule schedule(steps, {"t"});
870+
871+
cudaq::product_op<cudaq::matrix_handler> pauliZ_t = cudaq::spin_op::z(0);
872+
cudaq::sum_op<cudaq::matrix_handler> pauliZ(pauliZ_t);
873+
auto initialState1 =
874+
cudaq::state::from_data(std::vector<std::complex<double>>{1.0, 0.0});
875+
auto initialState2 =
876+
cudaq::state::from_data(std::vector<std::complex<double>>{1.0, 0.0});
877+
878+
cudaq::integrators::runge_kutta integrator(4, 0.01);
879+
auto results = cudaq::__internal__::evolveBatched(
880+
{ham1, ham2}, dims, schedule, {initialState1, initialState2}, integrator,
881+
{}, {pauliZ}, cudaq::IntermediateResultSave::None);
882+
883+
EXPECT_EQ(results.size(), 2);
884+
885+
// Check that both results have final states and final expectation values
886+
for (const auto &result : results) {
887+
EXPECT_TRUE(result.states.has_value());
888+
EXPECT_TRUE(result.expectation_values.has_value());
889+
890+
// For IntermediateResultSave::None, we should have only final state
891+
EXPECT_EQ(result.states.value().size(), 1);
892+
EXPECT_EQ(result.expectation_values.value().size(), 1);
893+
894+
// Check that final expectation value is computed
895+
EXPECT_EQ(result.expectation_values.value()[0].size(),
896+
1); // One observable (pauliZ)
897+
}
898+
}

unittests/dynamics/test_EvolveSingle.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,3 +276,63 @@ TEST(EvolveTester, checkScalarTd) {
276276
count++;
277277
}
278278
}
279+
280+
TEST(EvolveTester, checkSimpleNoIntermediateResults) {
281+
const cudaq::dimension_map dims = {{0, 2}};
282+
cudaq::product_op<cudaq::matrix_handler> ham1 =
283+
(2.0 * M_PI * 0.1 * cudaq::spin_op::x(0));
284+
cudaq::sum_op<cudaq::matrix_handler> ham(ham1);
285+
286+
constexpr int numSteps = 10;
287+
std::vector<double> steps = cudaq::linspace(0.0, 1.0, numSteps);
288+
cudaq::schedule schedule(steps, {"t"});
289+
290+
cudaq::product_op<cudaq::matrix_handler> pauliZ_t = cudaq::spin_op::z(0);
291+
cudaq::sum_op<cudaq::matrix_handler> pauliZ(pauliZ_t);
292+
auto initialState =
293+
cudaq::state::from_data(std::vector<std::complex<double>>{1.0, 0.0});
294+
295+
cudaq::integrators::runge_kutta integrator(1, 0.001);
296+
auto result = cudaq::__internal__::evolveSingle(
297+
ham, dims, schedule, initialState, integrator, {}, {pauliZ},
298+
cudaq::IntermediateResultSave::None);
299+
300+
// Verify final expectation value only (no intermediate results)
301+
EXPECT_TRUE(result.expectation_values.has_value());
302+
EXPECT_EQ(result.expectation_values.value().size(), 1);
303+
EXPECT_EQ(result.expectation_values.value()[0].size(), 1);
304+
305+
const double finalTime = steps.back();
306+
const double expected = std::cos(2 * 2.0 * M_PI * 0.1 * finalTime);
307+
EXPECT_NEAR(result.expectation_values.value()[0][0], expected, 1e-3);
308+
}
309+
310+
TEST(EvolveTester, checkDensityMatrixNoIntermediateResults) {
311+
const cudaq::dimension_map dims = {{0, 2}};
312+
cudaq::product_op<cudaq::matrix_handler> ham1 =
313+
(2.0 * M_PI * 0.1 * cudaq::spin_op::x(0));
314+
cudaq::sum_op<cudaq::matrix_handler> ham(ham1);
315+
316+
constexpr int numSteps = 10;
317+
std::vector<double> steps = cudaq::linspace(0.0, 1.0, numSteps);
318+
cudaq::schedule schedule(steps, {"t"});
319+
320+
cudaq::product_op<cudaq::matrix_handler> pauliZ_t = cudaq::spin_op::z(0);
321+
cudaq::sum_op<cudaq::matrix_handler> pauliZ(pauliZ_t);
322+
auto initialState = cudaq::state::from_data(
323+
std::vector<std::complex<double>>{1.0, 0.0, 0.0, 0.0});
324+
325+
cudaq::integrators::runge_kutta integrator(1, 0.001);
326+
auto result = cudaq::__internal__::evolveSingle(
327+
ham, dims, schedule, initialState, integrator, {}, {pauliZ},
328+
cudaq::IntermediateResultSave::None);
329+
330+
// Verify final expectation value only (no intermediate results)
331+
EXPECT_TRUE(result.expectation_values.has_value());
332+
EXPECT_EQ(result.expectation_values.value().size(), 1);
333+
EXPECT_EQ(result.expectation_values.value()[0].size(), 1);
334+
335+
const double finalTime = steps.back();
336+
const double expected = std::cos(2 * 2.0 * M_PI * 0.1 * finalTime);
337+
EXPECT_NEAR(result.expectation_values.value()[0][0], expected, 1e-3);
338+
}

0 commit comments

Comments
 (0)