Skip to content

Commit

Permalink
add C++ unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
multiphaseCFD committed Oct 18, 2024
1 parent 015b50a commit 2f65169
Showing 1 changed file with 207 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -1105,4 +1105,210 @@ TEMPLATE_TEST_CASE("StateVectorCudaManaged::SetIthStates",

CHECK(expected_state == Pennylane::Util::approx(sv.getDataVector()));
}
}
}

TEMPLATE_TEST_CASE("StateVectorCudaManaged::applyOperation non-param "
"one-qubit with controls",
"[StateVectorCudaManaged]", float, double) {
using PrecisionT = TestType;
std::mt19937 re{1337};
const int num_qubits = 4;
const auto margin = PrecisionT{1e-5};
const std::size_t control = GENERATE(0, 1, 2, 3);
const std::size_t wire = GENERATE(0, 1, 2, 3);
auto st0 = createRandomStateVectorData<PrecisionT>(re, num_qubits);
StateVectorCudaManaged<PrecisionT> sv0(num_qubits);
StateVectorCudaManaged<PrecisionT> sv1(num_qubits);

sv0.CopyHostDataToGpu(st0.data(), st0.size());
sv1.CopyHostDataToGpu(st0.data(), st0.size());

DYNAMIC_SECTION("N-controlled PauliX - "
<< "controls = {" << control << "} "
<< ", wires = {" << wire << "} - "
<< PrecisionToName<PrecisionT>::value) {
if (control != wire) {
sv0.applyOperation("CNOT", {control, wire});
sv1.applyOperation("PauliX", std::vector<std::size_t>{control},
std::vector<bool>{true},
std::vector<std::size_t>{wire});
REQUIRE(sv0.getDataVector() ==
approx(sv1.getDataVector()).margin(margin));
}

if (control != 0 && wire != 0 && control != wire) {
sv0.applyOperation("Toffoli", {0, control, wire});
sv1.applyOperation("PauliX", std::vector<std::size_t>{0, control},
std::vector<bool>{true, true},
std::vector<std::size_t>{wire});
REQUIRE(sv0.getDataVector() ==
approx(sv1.getDataVector()).margin(margin));

sv0.applyOperation("Toffoli", {control, 0, wire});
sv1.applyOperation("PauliX", std::vector<std::size_t>{control, 0},
std::vector<bool>{true, true},
std::vector<std::size_t>{wire});
REQUIRE(sv0.getDataVector() ==
approx(sv1.getDataVector()).margin(margin));
}
}

DYNAMIC_SECTION("N-controlled PauliY - "
<< "controls = {" << control << "} "
<< ", wires = {" << wire << "} - "
<< PrecisionToName<PrecisionT>::value) {
if (control != wire) {
sv0.applyOperation("CY", {control, wire});
sv1.applyOperation("PauliY", std::vector<std::size_t>{control},
std::vector<bool>{true},
std::vector<std::size_t>{wire});
REQUIRE(sv0.getDataVector() ==
approx(sv1.getDataVector()).margin(margin));
}
}

DYNAMIC_SECTION("N-controlled PauliZ - "
<< "controls = {" << control << "} "
<< ", wires = {" << wire << "} - "
<< PrecisionToName<PrecisionT>::value) {
if (control != wire) {
sv0.applyOperation("CZ", {control, wire});
sv1.applyOperation("PauliZ", std::vector<std::size_t>{control},
std::vector<bool>{true},
std::vector<std::size_t>{wire});
REQUIRE(sv0.getDataVector() ==
approx(sv1.getDataVector()).margin(margin));
}
}

DYNAMIC_SECTION("N-controlled Hadamard - "
<< "controls = {" << control << "} "
<< ", wires = {" << wire << "} - "
<< PrecisionToName<PrecisionT>::value) {
if (control != wire) {
const auto matrix = getHadamard<std::complex, PrecisionT>();

sv0.applyControlledMatrix(
matrix.data(), matrix.size(), std::vector<std::size_t>{control},
std::vector<bool>{true}, std::vector<std::size_t>{wire});
sv1.applyOperation("Hadamard", std::vector<std::size_t>{control},
std::vector<bool>{true},
std::vector<std::size_t>{wire});
REQUIRE(sv0.getDataVector() ==
approx(sv1.getDataVector()).margin(margin));
}
}
DYNAMIC_SECTION("N-controlled S - "
<< "controls = {" << control << "} "
<< ", wires = {" << wire << "} - "
<< PrecisionToName<PrecisionT>::value) {
if (control != wire) {
const auto matrix = getS<std::complex, PrecisionT>();

sv0.applyControlledMatrix(
matrix.data(), matrix.size(), std::vector<std::size_t>{control},
std::vector<bool>{true}, std::vector<std::size_t>{wire});
sv1.applyOperation("S", std::vector<std::size_t>{control},
std::vector<bool>{true},
std::vector<std::size_t>{wire});
REQUIRE(sv0.getDataVector() ==
approx(sv1.getDataVector()).margin(margin));
}
}

DYNAMIC_SECTION("N-controlled T - "
<< "controls = {" << control << "} "
<< ", wires = {" << wire << "} - "
<< PrecisionToName<PrecisionT>::value) {
if (control != wire) {
const std::vector<std::complex<PrecisionT>> matrix =
getT<std::complex, PrecisionT>();

sv0.applyControlledMatrix(
matrix.data(), matrix.size(), std::vector<std::size_t>{control},
std::vector<bool>{true}, std::vector<std::size_t>{wire});
sv1.applyOperation("T", std::vector<std::size_t>{control},
std::vector<bool>{true},
std::vector<std::size_t>{wire});
REQUIRE(sv0.getDataVector() ==
approx(sv1.getDataVector()).margin(margin));
}
}
}

TEMPLATE_TEST_CASE("StateVectorCudaManaged::applyOperation non-param "
"two-qubit with controls",
"[StateVectorCudaManaged]", float, double) {
using PrecisionT = TestType;
std::mt19937 re{1337};
const int num_qubits = 4;
const auto margin = PrecisionT{1e-5};
const std::size_t control = GENERATE(0, 1, 2, 3);
const std::size_t wire0 = GENERATE(0, 1, 2, 3);
const std::size_t wire1 = GENERATE(0, 1, 2, 3);
auto st0 = createRandomStateVectorData<PrecisionT>(re, num_qubits);
StateVectorCudaManaged<PrecisionT> sv0(num_qubits);
StateVectorCudaManaged<PrecisionT> sv1(num_qubits);

sv0.CopyHostDataToGpu(st0.data(), st0.size());
sv1.CopyHostDataToGpu(st0.data(), st0.size());

DYNAMIC_SECTION("N-controlled SWAP - "
<< "controls = {" << control << "} "
<< ", wires = {" << wire0 << ", " << wire1 << "} - "
<< PrecisionToName<PrecisionT>::value) {
if (control != wire0 && control != wire1 && wire0 != wire1) {
sv0.applyOperation("CSWAP", {control, wire0, wire1});
sv1.applyOperation("SWAP", std::vector<std::size_t>{control},
std::vector<bool>{true},
std::vector<std::size_t>{wire0, wire1});
REQUIRE(sv0.getDataVector() ==
approx(sv1.getDataVector()).margin(margin));
}
}

DYNAMIC_SECTION("N-controlled SWAP with matrix- "
<< "controls = {" << control << "} "
<< ", wires = {" << wire0 << ", " << wire1 << "} - "
<< PrecisionToName<PrecisionT>::value) {
if (control != wire0 && control != wire1 && wire0 != wire1) {
const std::vector<std::complex<PrecisionT>> matrix =
getSWAP<std::complex, PrecisionT>();
sv0.applyControlledMatrix(matrix.data(), matrix.size(),
std::vector<std::size_t>{control},
std::vector<bool>{true},
std::vector<std::size_t>{wire0, wire1});
sv1.applyOperation("SWAP", std::vector<std::size_t>{control},
std::vector<bool>{true},
std::vector<std::size_t>{wire0, wire1});
REQUIRE(sv0.getDataVector() ==
approx(sv1.getDataVector()).margin(margin));
}
}
}

TEMPLATE_TEST_CASE("StateVectorCudaManaged::controlled Toffoli",
"[StateVectorCudaManaged]", float, double) {
using PrecisionT = TestType;
std::mt19937 re{1337};
const int num_qubits = 6;
const auto margin = PrecisionT{1e-5};
const std::size_t control = GENERATE(0, 1, 2);
auto st0 = createRandomStateVectorData<PrecisionT>(re, num_qubits);

StateVectorCudaManaged<PrecisionT> sv0(num_qubits);
StateVectorCudaManaged<PrecisionT> sv1(num_qubits);

sv0.CopyHostDataToGpu(st0.data(), st0.size());
sv1.CopyHostDataToGpu(st0.data(), st0.size());

const std::vector<std::complex<PrecisionT>> matrix =
getToffoli<std::complex, PrecisionT>();
sv0.applyControlledMatrix(
matrix.data(), matrix.size(), std::vector<std::size_t>{control},
std::vector<bool>{true}, std::vector<std::size_t>{3, 4, 5});
sv1.applyOperation("PauliX", std::vector<std::size_t>{control, 3, 4},
std::vector<bool>{true, true, true},
std::vector<std::size_t>{5});
REQUIRE(sv0.getDataVector() == approx(sv1.getDataVector()).margin(margin));
}

0 comments on commit 2f65169

Please sign in to comment.