Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 13 additions & 19 deletions src/na/zoned/decomposer/NativeGateDecomposer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@
if (std::fabs(quat[0]) > epsilon || std::fabs(quat[3]) > epsilon) {
theta = 2. * std::atan2(std::sqrt(quat[2] * quat[2] + quat[1] * quat[1]),
std::sqrt(quat[0] * quat[0] + quat[3] * quat[3]));
qc::fp alpha_1 = std::atan2(quat[3], quat[0]); // phi+ lambda
qc::fp alpha_1 = std::atan2(quat[3], quat[0]); // (phi+ lambda) /2
if (std::fabs(quat[1]) > epsilon || std::fabs(quat[2]) > epsilon) {
qc::fp alpha_2 = -1 * std::atan2(quat[1], quat[2]);
qc::fp alpha_2 = -1 * std::atan2(quat[1], quat[2]); //(phi-lambda)/2
phi = alpha_1 + alpha_2; // phi
lambda = alpha_1 - alpha_2;
} else {
Expand Down Expand Up @@ -313,6 +313,9 @@
-> std::pair<std::vector<std::size_t>, double> {
std::vector<std::pair<std::vector<std::size_t>, double>> possible_paths = {};
// Check if leaf nodes are reached

// TODO: Check if Path cost takes into account edge weight from current node
// to next node!!!
for (auto edge : subproblem_graph.get_adjacent(current_node)) {
if (leaf_nodes.contains(edge.first)) {
possible_paths.push_back({std::pair<std::vector<std::size_t>, double>(
Expand Down Expand Up @@ -417,12 +420,12 @@
potential_arg = {};
auto prev_theta =
std::get<StructU3>(circuit.get_Node_Value(v_sort[0])).angles[0];
auto this_theta = prev_theta;

Check warning on line 423 in src/na/zoned/decomposer/NativeGateDecomposer.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/na/zoned/decomposer/NativeGateDecomposer.cpp:423:8 [clang-analyzer-deadcode.DeadStores]

Value stored to 'this_theta' during its initialization is never read
std::set<qc::Qubit> mk_qubits = {
std::get<StructU3>(circuit.get_Node_Value(v_sort[0])).qubit};
for (auto i = 0; i < v_sort.size(); i++) {

Check warning on line 426 in src/na/zoned/decomposer/NativeGateDecomposer.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/na/zoned/decomposer/NativeGateDecomposer.cpp:426:22 [clang-diagnostic-sign-compare]

comparison of integers of different signs: 'int' and 'size_type' (aka 'unsigned long')
this_theta =
std::get<StructU3>(circuit.get_Node_Value(v_sort[i])).angles[0];

Check warning on line 428 in src/na/zoned/decomposer/NativeGateDecomposer.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/na/zoned/decomposer/NativeGateDecomposer.cpp:428:58 [clang-diagnostic-sign-conversion]

implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long')
if (this_theta != prev_theta) {
std::vector<std::size_t> discarded = {v_sort.begin(), v_sort.begin() + i};
std::vector<std::size_t> kept = {v_sort.begin() + i, v_sort.end()};
Expand All @@ -434,7 +437,7 @@
mk_qubits.clear();
}
mk_qubits.insert(
std::get<StructU3>(circuit.get_Node_Value(v_sort[i])).qubit);

Check warning on line 440 in src/na/zoned/decomposer/NativeGateDecomposer.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/na/zoned/decomposer/NativeGateDecomposer.cpp:440:58 [clang-diagnostic-sign-conversion]

implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long')
}
std::vector<std::size_t> push_back_nodes = {};
std::set<qc::Qubit> p_square_qubits = {};
Expand Down Expand Up @@ -508,13 +511,13 @@
DiGraph<std::variant<StructU3, std::array<qc::Qubit, 2>>>();
std::vector<std::vector<size_t>> qubit_paths(nQubits);
// TODO:assert that One more sql exists than mql ??
for (auto i = 0; i < schedule.second.size(); ++i) {

Check warning on line 514 in src/na/zoned/decomposer/NativeGateDecomposer.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/na/zoned/decomposer/NativeGateDecomposer.cpp:514:22 [clang-diagnostic-sign-compare]

comparison of integers of different signs: 'int' and 'size_type' (aka 'unsigned long')
for (const auto& s : schedule.first.at(i)) {

Check warning on line 515 in src/na/zoned/decomposer/NativeGateDecomposer.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/na/zoned/decomposer/NativeGateDecomposer.cpp:515:44 [clang-diagnostic-sign-conversion]

implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long')
size_t node = graph.add_Node(s);
qubit_paths.at(s.qubit).push_back(node);
}

for (const auto& gate : schedule.second.at(i)) {

Check warning on line 520 in src/na/zoned/decomposer/NativeGateDecomposer.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/na/zoned/decomposer/NativeGateDecomposer.cpp:520:48 [clang-diagnostic-sign-conversion]

implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long')
size_t node = graph.add_Node(gate);
qubit_paths.at(gate[0]).push_back(node);
qubit_paths.at(gate[1]).push_back(node);
Expand Down Expand Up @@ -545,7 +548,6 @@
}
return max_cost;
}
// TODO: This only ever gives the first Moment?????
auto NativeGateDecomposer::sift(
DiGraph<std::variant<StructU3, std::array<qc::Qubit, 2>>>& circuit,
std::vector<std::size_t> v, size_t nQubits)
Expand All @@ -557,31 +559,25 @@
std::set<std::size_t> v_rem = std::set(v.begin(), v.end());
std::set<size_t> removed = std::set<size_t>();

// We traverse the graph rather than v_rem to use the graph's topological
// ordering
for (auto node = 0; node < circuit.size(); node++) {

Check warning on line 564 in src/na/zoned/decomposer/NativeGateDecomposer.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/na/zoned/decomposer/NativeGateDecomposer.cpp:564:28 [clang-diagnostic-sign-compare]

comparison of integers of different signs: 'int' and 'std::size_t' (aka 'unsigned long')
if (v_rem.contains(node)) { // TODO: SORT V_rem??? Needs to be a topological
if (v_rem.contains(node)) {

Check warning on line 565 in src/na/zoned/decomposer/NativeGateDecomposer.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/na/zoned/decomposer/NativeGateDecomposer.cpp:565:24 [clang-diagnostic-sign-conversion]

implicit conversion changes signedness: 'int' to 'const key_type' (aka 'const unsigned long')
auto op = circuit.get_Node_Value(node);

Check warning on line 566 in src/na/zoned/decomposer/NativeGateDecomposer.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

src/na/zoned/decomposer/NativeGateDecomposer.cpp:566:40 [clang-diagnostic-sign-conversion]

implicit conversion changes signedness: 'int' to 'std::size_t' (aka 'unsigned long')

std::set<size_t> op_qubits = std::set<size_t>();

std::set<size_t> used_qubits;
if (std::holds_alternative<StructU3>(op)) {
used_qubits = {std::get<StructU3>(op).qubit};
op_qubits = {std::get<StructU3>(op).qubit};
} else {
used_qubits = {std::get<std::array<qc::Qubit, 2>>(op)[0],
std::get<std::array<qc::Qubit, 2>>(op)[1]};
}

for (auto qubit : used_qubits) {
op_qubits.insert(qubit);
op_qubits = {std::get<std::array<qc::Qubit, 2>>(op)[0],
std::get<std::array<qc::Qubit, 2>>(op)[1]};
}
if (removed.size() < nQubits && disjunct(removed, op_qubits)) {
if (std::holds_alternative<StructU3>(op)) {
v_c.push_back(node);
removed.insert(std::get<StructU3>(op).qubit);
} else {
v_p.push_back(node);
// Add something to make it only pick one 2-Qubit gate per Qubit per
// moment???
}
} else {
v_r.push_back(node);
Expand Down Expand Up @@ -676,7 +672,6 @@
// TODO: Check if subproblem has been computed
std::size_t id = std::hash<std::array<std::vector<size_t>, 3>>{}(v);
if (memo.contains(id)) {
// Wrong memory Call!!!
std::size_t sub_node = memo.at(id).first;
double edge_weight = memo.at(id).second[1];
cost = memo.at(id).second[0];
Expand Down Expand Up @@ -708,7 +703,6 @@
for (const auto& val : args) {
auto new_node = add_node_to_sub_prob_graph(v[0], val.first[0], val.second,
subproblem_graph, prev_node);
// USdingg v_new is incorrect!! need adjusted one for arg
temp_cost = schedule_remaining({val.first[1], val.first[2], val.first[3]},
circuit, subproblem_graph, new_node, nQubits, check_final_cond, memo) + val.second;
if (temp_cost < min_cost) {
Expand Down Expand Up @@ -747,8 +741,8 @@
std::pair<std::vector<std::size_t>, std::vector<std::size_t>>({}, {}));
std::map<std::size_t, std::pair<std::size_t, std::array<double, 2>>> memo =
{};
auto cost = schedule_remaining(v, circuit, sub_prob_graph, base_node,
nQubits_, config_.check_final_cond, memo);
auto cost = schedule_remaining(v, circuit, sub_prob_graph, base_node, nQubits,
config_.check_final_cond, memo);
// TODO: Create Schedule from Subproblem Graph
std::pair<std::vector<std::vector<StructU3>>, std::vector<TwoQubitGateLayer>>
final_circuit = build_schedule(circuit, sub_prob_graph);
Expand Down
179 changes: 152 additions & 27 deletions test/na/zoned/test_theta_opt_scheduler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,19 +312,24 @@ TEST_F(ThetaOptTest, NextMomentsCond3Test) {

TEST_F(ThetaOptTest, RecursionBaseTest) {
// Circuit
// ┌─────────────────┐ ┌───────┐ ┌─────────────────┐
// q_0: ──┤ U(PI,Pi/2,PI/4) ├─────────■───┤ X ├─────────■───┤
// U(PI/2,PI/2,PI) ├──
// ┌─────────────────┐ ┌───────┐
// q_0: ──┤ U(PI,Pi/2,PI/4) ├─────────■───┤ X ├─────────■─ ─ ─
// └─────────────────┘ │ └───────┘ │
// └─────────────────┘
// │ ┌───────┐ │
// q_1: ──────────────────────────■───■───┤ Y
// ├─────────│───────────────────────
// q_1: ──────────────────────────■───■───┤ Y ├─────────│─ ─ ─
// │ └───────┘ │
// ┌───────────────────┐ │ ┌────────────────┐ │
// q_2: ──┤ U(PI/4,PI/4,PI/4) ├───■───┤ U(PI/2,0,PI/2)
// ├────■───────────────────────
// q_2: ──┤ U(PI/4,PI/4,PI/4) ├───■───┤ U(PI/2,0,PI/2) ├────■─ ─ ─
// └───────────────────┘ └────────────────┘
//
// ┌─────────────────┐
// q_0: ─ ─ ─┤ U(PI/2,PI/2,PI) ├──
// └─────────────────┘
//
// q_1: ─ ─ ──────────────────────
//
// q_2: ─ ─ ──────────────────────

size_t n = 3;
qc::QuantumComputation qc(n);
qc.u(qc::PI, qc::PI_2, qc::PI_4, 0);
Expand Down Expand Up @@ -353,9 +358,48 @@ TEST_F(ThetaOptTest, RecursionBaseTest) {
auto result = NativeGateDecomposer::schedule_remaining(
v, graph, subproblem_graph, 0, n, false, memo);

EXPECT_EQ(result, 5 * qc::PI_2);

EXPECT_EQ(subproblem_graph.size(), 1 + 6);
auto t = subproblem_graph.get_adjacent(0);
EXPECT_THAT(subproblem_graph.get_adjacent(0),
::testing::UnorderedElementsAre(::testing::Pair(1, qc::PI),
::testing::Pair(4, qc::PI_4)));

EXPECT_THAT(subproblem_graph.get_Node_Value(1).first, ::testing::IsEmpty());
EXPECT_THAT(subproblem_graph.get_Node_Value(1).second,
::testing::ElementsAre(0, 1));
::testing::UnorderedElementsAre(0, 1));
EXPECT_THAT(subproblem_graph.get_adjacent(1),
::testing::UnorderedElementsAre(::testing::Pair(2, qc::PI)));
EXPECT_THAT(subproblem_graph.get_Node_Value(2).first,
::testing::UnorderedElementsAre(2, 4));
EXPECT_THAT(subproblem_graph.get_Node_Value(2).second,
::testing::UnorderedElementsAre(3, 5, 6));
EXPECT_THAT(subproblem_graph.get_adjacent(2),
::testing::UnorderedElementsAre(::testing::Pair(3, qc::PI_2)));
EXPECT_THAT(subproblem_graph.get_Node_Value(3).first,
::testing::UnorderedElementsAre(7));
EXPECT_THAT(subproblem_graph.get_Node_Value(3).second,
::testing::UnorderedElementsAre(8));
EXPECT_THAT(subproblem_graph.get_adjacent(3), ::testing::IsEmpty());

EXPECT_THAT(subproblem_graph.get_Node_Value(4).first, ::testing::IsEmpty());
EXPECT_THAT(subproblem_graph.get_Node_Value(4).second,
::testing::UnorderedElementsAre(1));
EXPECT_THAT(subproblem_graph.get_adjacent(4),
::testing::UnorderedElementsAre(::testing::Pair(5, qc::PI)));
EXPECT_THAT(subproblem_graph.get_Node_Value(5).first,
::testing::UnorderedElementsAre(2));
EXPECT_THAT(subproblem_graph.get_Node_Value(5).second,
::testing::UnorderedElementsAre(0, 3));
EXPECT_THAT(subproblem_graph.get_adjacent(5),
::testing::UnorderedElementsAre(::testing::Pair(6, qc::PI)));
EXPECT_THAT(subproblem_graph.get_Node_Value(6).first,
::testing::UnorderedElementsAre(4));
EXPECT_THAT(subproblem_graph.get_Node_Value(6).second,
::testing::UnorderedElementsAre(5, 6));
EXPECT_THAT(subproblem_graph.get_adjacent(6),
::testing::UnorderedElementsAre(::testing::Pair(3,qc::PI_2)));
}


Expand Down Expand Up @@ -482,38 +526,119 @@ TEST_F(ThetaOptTest, BuildScheduleTest) {

EXPECT_EQ(schedule.first.at(3).at(0).qubit,0);
EXPECT_THAT(schedule.first.at(3).at(0).angles,::testing::ElementsAre(one_qubit_gates.at(3).at(0).angles[0],
one_qubit_gates.at(3).at(0).angles[1],one_qubit_gates.at(3).at(0).angles[2]));

one_qubit_gates.at(3).at(0).angles[1],
one_qubit_gates.at(3).at(0).angles[2]));
}

TEST_F(ThetaOptTest, CompleteTestSmall) {
// Circuit
// ┌───────┐ ┌───────┐ ┌───────┐
// q_0: ──┤ X ├───■───────┤ Z ├───■───┤ Y ├─
// └───────┘ │ └───────┘ │ └───────┘
// │ ┌───────┐ │
// q_1: ──────────────■───■───┤ X ├───│─────────────
// │ └───────┘ │
// ┌───────┐ │ ┌───────┐ │
// q_2: ──┤ X ├───────■───┤ Y ├───■─────────────
// └───────┘ └───────┘
// ┌─────────────────┐ ┌───────┐
// q_0: ──┤ U(PI,PI/2,PI/4) ├─────────■───┤ X ├─────────■─ ─ ─
// └─────────────────┘ │ └───────┘ │
// │ ┌───────┐ │
// q_1: ──────────────────────────■───■───┤ Y ├─────────│─ ─ ─
// │ └───────┘ │
// ┌───────────────────┐ │ ┌────────────────┐ │
// q_2: ──┤ U(PI/4,PI/4,PI/4) ├───■───┤ U(PI/2,0,PI/2) ├────■─ ─ ─
// └───────────────────┘ └────────────────┘
//
// ┌─────────────────┐
// q_0: ─ ─ ─┤ U(PI/2,PI/2,PI) ├──
// └─────────────────┘
//
// q_1: ─ ─ ──────────────────────
//
// q_2: ─ ─ ──────────────────────

size_t n = 3;
qc::QuantumComputation qc(n);
qc.x(0);
qc.x(2);
qc.cz(0, 1);
qc.u(qc::PI, qc::PI_2, qc::PI_4, 0);
qc.u(qc::PI_4, qc::PI_4, qc::PI_4, 2);
qc.cz(1, 2);
qc.z(0);
qc.x(1);
qc.y(2);
qc.cz(0, 1);
qc.x(0);
qc.y(1);
qc.u(qc::PI_2, 0.0, qc::PI_2, 2);
qc.cz(0, 2);
qc.y(0);
qc.u(qc::PI_2, qc::PI_2, qc::PI, 0);

auto schedule = scheduler.schedule(qc);
auto one_qubit_gates = NativeGateDecomposer::transformToU3(schedule.first, n);
auto theta_opt_schedule =
decomposer.schedule_theta_opt({one_qubit_gates, schedule.second}, n);

EXPECT_EQ(theta_opt_schedule.first.size(), 4);
EXPECT_EQ(theta_opt_schedule.second.size(), 3);

EXPECT_EQ(theta_opt_schedule.first.at(0).size(), 2);
EXPECT_EQ(theta_opt_schedule.first.at(1).size(), 0);
EXPECT_EQ(theta_opt_schedule.first.at(2).size(), 3);
EXPECT_EQ(theta_opt_schedule.first.at(3).size(), 1);

EXPECT_EQ(theta_opt_schedule.second.at(0).size(), 1);
EXPECT_EQ(theta_opt_schedule.second.at(1).size(), 1);
EXPECT_EQ(theta_opt_schedule.second.at(2).size(), 1);

EXPECT_EQ(theta_opt_schedule.first.at(0).at(0).qubit, 0);
// TODO: DOUBLE Nears!!!
EXPECT_THAT(
theta_opt_schedule.first.at(0).at(0).angles,
::testing::ElementsAre(
::testing::DoubleNear(one_qubit_gates.at(0).at(0).angles[0], epsilon),
::testing::DoubleNear(one_qubit_gates.at(0).at(0).angles[1], epsilon),
::testing::DoubleNear(one_qubit_gates.at(0).at(0).angles[2],
epsilon)));
EXPECT_EQ(theta_opt_schedule.first.at(0).at(1).qubit, 2);
EXPECT_THAT(
theta_opt_schedule.first.at(0).at(1).angles,
::testing::ElementsAre(
::testing::DoubleNear(one_qubit_gates.at(0).at(1).angles[0], epsilon),
::testing::DoubleNear(one_qubit_gates.at(0).at(1).angles[1], epsilon),
::testing::DoubleNear(one_qubit_gates.at(0).at(1).angles[2],
epsilon)));

EXPECT_THAT(theta_opt_schedule.second.at(0).front(),
::testing::ElementsAre(1, 2));

EXPECT_THAT(theta_opt_schedule.second.at(1).front(),
::testing::ElementsAre(0, 1));
// QUAT
EXPECT_EQ(theta_opt_schedule.first.at(2).at(0).qubit, 2);
EXPECT_THAT(
theta_opt_schedule.first.at(2).at(0).angles,
::testing::ElementsAre(
::testing::DoubleNear(one_qubit_gates.at(1).at(0).angles[0], epsilon),
::testing::DoubleNear(one_qubit_gates.at(1).at(0).angles[1], epsilon),
::testing::DoubleNear(one_qubit_gates.at(1).at(0).angles[2],
epsilon)));
EXPECT_EQ(theta_opt_schedule.first.at(2).at(1).qubit, 0);
EXPECT_THAT(
theta_opt_schedule.first.at(2).at(1).angles,
::testing::ElementsAre(
::testing::DoubleNear(one_qubit_gates.at(2).at(0).angles[0], epsilon),
::testing::DoubleNear(one_qubit_gates.at(2).at(0).angles[1], epsilon),
::testing::DoubleNear(one_qubit_gates.at(2).at(0).angles[2],
epsilon)));
EXPECT_EQ(theta_opt_schedule.first.at(2).at(2).qubit, 1);
EXPECT_THAT(
theta_opt_schedule.first.at(2).at(2).angles,
::testing::ElementsAre(
::testing::DoubleNear(one_qubit_gates.at(2).at(1).angles[0], epsilon),
::testing::DoubleNear(one_qubit_gates.at(2).at(1).angles[1], epsilon),
::testing::DoubleNear(one_qubit_gates.at(2).at(1).angles[2], epsilon)));

EXPECT_THAT(theta_opt_schedule.second.at(2).front(),::testing::ElementsAre(0,2));

EXPECT_EQ(theta_opt_schedule.first.at(3).at(0).qubit,0);
EXPECT_THAT(theta_opt_schedule.first.at(3).at(0).angles,::testing::ElementsAre(
::testing::DoubleNear(one_qubit_gates.at(3).at(0).angles[0], epsilon),
::testing::DoubleNear(one_qubit_gates.at(3).at(0).angles[1], epsilon),
::testing::DoubleNear(one_qubit_gates.at(3).at(0).angles[2], epsilon)));

}

TEST_F(ThetaOptTest, CompleteTestBig) {
//Circuit BIG
//Circuit BIG
}
} // namespace na::zoned
Loading