Skip to content

Commit

Permalink
Merge branch 'master' into unitary-space
Browse files Browse the repository at this point in the history
  • Loading branch information
sergeisakov authored Oct 30, 2020
2 parents e41ddf8 + e283b8b commit 586b499
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 112 deletions.
2 changes: 1 addition & 1 deletion lib/circuit_qsim_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ class CircuitQsimParser final {
return false;
}

MakeControlledGate(std::move(controlled_by), gates.back());
gates.back().ControlledBy(std::move(controlled_by));

if (!ValidateControlledGate(num_qubits, gates.back().qubits,
gates.back().controlled_by)) {
Expand Down
132 changes: 73 additions & 59 deletions lib/gate.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,65 @@ inline void SortQubits(Gate& gate) {

} // namespace detail

template <typename Qubits = std::vector<unsigned>, typename Gate>
inline void MakeControlledGate(Qubits&& controlled_by, Gate& gate) {
gate.controlled_by = std::forward<Qubits>(controlled_by);
gate.cmask = (uint64_t{1} << gate.controlled_by.size()) - 1;

std::sort(gate.controlled_by.begin(), gate.controlled_by.end());
}

template <typename Qubits = std::vector<unsigned>, typename Gate>
inline void MakeControlledGate(Qubits&& controlled_by,
const std::vector<unsigned>& control_values,
Gate& gate) {
// Assume controlled_by.size() == control_values.size().

bool sorted = true;

for (std::size_t i = 1; i < controlled_by.size(); ++i) {
if (controlled_by[i - 1] > controlled_by[i]) {
sorted = false;
break;
}
}

if (sorted) {
gate.controlled_by = std::forward<Qubits>(controlled_by);
gate.cmask = 0;

for (std::size_t i = 0; i < control_values.size(); ++i) {
gate.cmask |= (control_values[i] & 1) << i;
}
} else {
struct ControlPair {
unsigned q;
unsigned v;
};

std::vector<ControlPair> cpairs;
cpairs.reserve(controlled_by.size());

for (std::size_t i = 0; i < controlled_by.size(); ++i) {
cpairs.push_back({controlled_by[i], control_values[i]});
}

// Sort control qubits and control values.
std::sort(cpairs.begin(), cpairs.end(),
[](const ControlPair& l, const ControlPair& r) -> bool {
return l.q < r.q;
});

gate.cmask = 0;
gate.controlled_by.reserve(controlled_by.size());

for (std::size_t i = 0; i < cpairs.size(); ++i) {
gate.cmask |= (cpairs[i].v & 1) << i;
gate.controlled_by.push_back(cpairs[i].q);
}
}
}

namespace gate {

constexpr int kDecomp = 100001; // gate from Schmidt decomposition
Expand Down Expand Up @@ -74,6 +133,20 @@ struct Gate {
bool swapped; // If true, the gate qubits are swapped to make qubits
// ordered in ascending order. This does not apply to
// control qubits of explicitly-controlled gates.

template <typename Qubits = std::vector<unsigned>>
Gate&& ControlledBy(Qubits&& controlled_by) {
MakeControlledGate(std::forward<Qubits>(controlled_by), *this);
return std::move(*this);
}

template <typename Qubits = std::vector<unsigned>>
Gate&& ControlledBy(Qubits&& controlled_by,
const std::vector<unsigned>& control_values) {
MakeControlledGate(
std::forward<Qubits>(controlled_by), control_values, *this);
return std::move(*this);
}
};

template <typename Gate, typename GateDef>
Expand Down Expand Up @@ -130,65 +203,6 @@ inline Gate CreateGate(unsigned time, const std::vector<unsigned>& qubits,
return gate;
}

template <typename Qubits = std::vector<unsigned>&&, typename Gate>
inline void MakeControlledGate(Qubits&& controlled_by, Gate& gate) {
gate.controlled_by = std::forward<Qubits>(controlled_by);
gate.cmask = (uint64_t{1} << gate.controlled_by.size()) - 1;

std::sort(gate.controlled_by.begin(), gate.controlled_by.end());
}

template <typename Qubits = std::vector<unsigned>&&, typename Gate>
inline void MakeControlledGate(Qubits&& controlled_by,
const std::vector<unsigned>& control_values,
Gate& gate) {
// Assume controlled_by.size() == control_values.size().

bool sorted = true;

for (std::size_t i = 1; i < controlled_by.size(); ++i) {
if (controlled_by[i - 1] > controlled_by[i]) {
sorted = false;
break;
}
}

if (sorted) {
gate.controlled_by = std::forward<Qubits>(controlled_by);
gate.cmask = 0;

for (std::size_t i = 0; i < control_values.size(); ++i) {
gate.cmask |= (control_values[i] & 1) << i;
}
} else {
struct ControlPair {
unsigned q;
unsigned v;
};

std::vector<ControlPair> cpairs;
cpairs.reserve(controlled_by.size());

for (std::size_t i = 0; i < controlled_by.size(); ++i) {
cpairs.push_back({controlled_by[i], control_values[i]});
}

// Sort control qubits and control values.
std::sort(cpairs.begin(), cpairs.end(),
[](const ControlPair& l, const ControlPair& r) -> bool {
return l.q < r.q;
});

gate.cmask = 0;
gate.controlled_by.reserve(controlled_by.size());

for (std::size_t i = 0; i < cpairs.size(); ++i) {
gate.cmask |= (cpairs[i].v & 1) << i;
gate.controlled_by.push_back(cpairs[i].q);
}
}
}

namespace gate {

/**
Expand Down
65 changes: 13 additions & 52 deletions tests/simulator_testfixture.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,130 +360,91 @@ void TestApplyControlGate() {
gates.push_back(GateHd<fp_type>::Create(0, 3));
gates.push_back(GateHd<fp_type>::Create(0, 4));
gates.push_back(GateHd<fp_type>::Create(0, 5));

gates.push_back(GateT<fp_type>::Create(1, 1));
MakeControlledGate({0}, {1}, gates.back());

gates.push_back(GateT<fp_type>::Create(1, 1).ControlledBy({0}));
gates.push_back(GateRX<fp_type>::Create(2, 0, 0.1));
gates.push_back(GateRY<fp_type>::Create(2, 1, 0.2));
gates.push_back(GateRZ<fp_type>::Create(2, 2, 0.3));
gates.push_back(GateRX<fp_type>::Create(2, 3, 0.4));
gates.push_back(GateRY<fp_type>::Create(2, 4, 0.5));
gates.push_back(GateRZ<fp_type>::Create(2, 5, 0.6));

gates.push_back(GateHd<fp_type>::Create(3, 2));
MakeControlledGate({1, 0}, {1, 0}, gates.back());

gates.push_back(GateHd<fp_type>::Create(3, 2).ControlledBy({1, 0}, {1, 0}));
gates.push_back(GateRY<fp_type>::Create(4, 0, 0.7));
gates.push_back(GateRZ<fp_type>::Create(4, 1, 0.8));
gates.push_back(GateRX<fp_type>::Create(4, 2, 0.9));
gates.push_back(GateRY<fp_type>::Create(4, 3, 1.0));
gates.push_back(GateRZ<fp_type>::Create(4, 4, 1.1));
gates.push_back(GateRX<fp_type>::Create(4, 5, 1.2));

gates.push_back(GateT<fp_type>::Create(5, 3));
MakeControlledGate({0, 1, 2}, {1, 1, 0}, gates.back());

gates.push_back(GateT<fp_type>::Create(5, 3).ControlledBy({0, 1, 2}, {1, 1, 0}));
gates.push_back(GateRZ<fp_type>::Create(6, 0, 1.3));
gates.push_back(GateRX<fp_type>::Create(6, 1, 1.4));
gates.push_back(GateRY<fp_type>::Create(6, 2, 1.5));
gates.push_back(GateRZ<fp_type>::Create(6, 3, 1.6));
gates.push_back(GateRX<fp_type>::Create(6, 4, 1.7));
gates.push_back(GateRY<fp_type>::Create(6, 5, 1.8));

gates.push_back(GateT<fp_type>::Create(7, 4));
MakeControlledGate({0, 2, 3, 1}, {0, 1, 1, 0}, gates.back());

gates.push_back(GateT<fp_type>::Create(7, 4).ControlledBy({0, 2, 3, 1}, {0, 1, 1, 0}));
gates.push_back(GateRX<fp_type>::Create(8, 0, 1.9));
gates.push_back(GateRY<fp_type>::Create(8, 1, 2.0));
gates.push_back(GateRZ<fp_type>::Create(8, 2, 2.1));
gates.push_back(GateRX<fp_type>::Create(8, 3, 2.2));
gates.push_back(GateRY<fp_type>::Create(8, 4, 2.3));
gates.push_back(GateRZ<fp_type>::Create(8, 5, 2.4));

gates.push_back(GateIS<fp_type>::Create(9, 1, 2));
MakeControlledGate({0}, {0}, gates.back());

gates.push_back(GateIS<fp_type>::Create(9, 1, 2).ControlledBy({0}, {0}));
gates.push_back(GateRY<fp_type>::Create(10, 0, 2.5));
gates.push_back(GateRZ<fp_type>::Create(10, 1, 2.6));
gates.push_back(GateRX<fp_type>::Create(10, 2, 2.7));
gates.push_back(GateRY<fp_type>::Create(10, 3, 2.8));
gates.push_back(GateRZ<fp_type>::Create(10, 4, 2.9));
gates.push_back(GateRX<fp_type>::Create(10, 5, 3.0));

gates.push_back(GateIS<fp_type>::Create(11, 2, 3));
MakeControlledGate({1, 0}, {1, 1}, gates.back());

gates.push_back(GateIS<fp_type>::Create(11, 2, 3).ControlledBy({1, 0}));
gates.push_back(GateRZ<fp_type>::Create(12, 0, 3.1));
gates.push_back(GateRX<fp_type>::Create(12, 1, 3.2));
gates.push_back(GateRY<fp_type>::Create(12, 2, 3.3));
gates.push_back(GateRZ<fp_type>::Create(12, 3, 3.4));
gates.push_back(GateRX<fp_type>::Create(12, 4, 3.5));
gates.push_back(GateRY<fp_type>::Create(12, 5, 3.6));

gates.push_back(GateCNot<fp_type>::Create(13, 3, 4));
MakeControlledGate({0, 2, 1}, {1, 1, 0}, gates.back());

gates.push_back(GateCNot<fp_type>::Create(13, 3, 4).ControlledBy({0, 2, 1}, {1, 1, 0}));
gates.push_back(GateRX<fp_type>::Create(14, 0, 3.7));
gates.push_back(GateRY<fp_type>::Create(14, 1, 3.8));
gates.push_back(GateRZ<fp_type>::Create(14, 2, 3.9));
gates.push_back(GateRX<fp_type>::Create(14, 3, 4.0));
gates.push_back(GateRY<fp_type>::Create(14, 4, 4.1));
gates.push_back(GateRZ<fp_type>::Create(14, 5, 4.2));

gates.push_back(GateIS<fp_type>::Create(15, 4, 5));
MakeControlledGate({3, 1, 0, 2}, {1, 1, 0, 0}, gates.back());

gates.push_back(GateIS<fp_type>::Create(15, 4, 5).ControlledBy({3, 1, 0, 2}, {1, 1, 0, 0}));
gates.push_back(GateRY<fp_type>::Create(16, 0, 4.3));
gates.push_back(GateRZ<fp_type>::Create(16, 1, 4.4));
gates.push_back(GateRX<fp_type>::Create(16, 2, 4.5));
gates.push_back(GateRY<fp_type>::Create(16, 3, 4.6));
gates.push_back(GateRZ<fp_type>::Create(16, 4, 4.7));
gates.push_back(GateRX<fp_type>::Create(16, 5, 4.8));

gates.push_back(GateCNot<fp_type>::Create(17, 5, 4));
MakeControlledGate({3}, {0}, gates.back());

gates.push_back(GateCNot<fp_type>::Create(17, 5, 4).ControlledBy({3}, {0}));
gates.push_back(GateRZ<fp_type>::Create(18, 0, 4.9));
gates.push_back(GateRX<fp_type>::Create(18, 1, 5.0));
gates.push_back(GateRY<fp_type>::Create(18, 2, 5.1));
gates.push_back(GateRZ<fp_type>::Create(18, 3, 5.2));
gates.push_back(GateRX<fp_type>::Create(18, 4, 5.3));
gates.push_back(GateRY<fp_type>::Create(18, 5, 5.4));

gates.push_back(GateIS<fp_type>::Create(19, 0, 1));
MakeControlledGate({4}, {1}, gates.back());

gates.push_back(GateIS<fp_type>::Create(19, 0, 1).ControlledBy({4}));
gates.push_back(GateRX<fp_type>::Create(20, 0, 5.5));
gates.push_back(GateRY<fp_type>::Create(20, 1, 5.6));
gates.push_back(GateRZ<fp_type>::Create(20, 2, 5.7));
gates.push_back(GateRX<fp_type>::Create(20, 3, 5.8));
gates.push_back(GateRY<fp_type>::Create(20, 4, 5.9));
gates.push_back(GateRZ<fp_type>::Create(20, 5, 6.0));

gates.push_back(GateIS<fp_type>::Create(21, 0, 2));
MakeControlledGate({4}, {1}, gates.back());

gates.push_back(GateIS<fp_type>::Create(21, 0, 2).ControlledBy({4}));
gates.push_back(GateRY<fp_type>::Create(22, 0, 6.1));
gates.push_back(GateRZ<fp_type>::Create(22, 1, 6.2));
gates.push_back(GateRX<fp_type>::Create(22, 2, 6.3));
gates.push_back(GateRY<fp_type>::Create(22, 3, 6.4));
gates.push_back(GateRZ<fp_type>::Create(22, 4, 6.5));
gates.push_back(GateRX<fp_type>::Create(22, 5, 6.6));

gates.push_back(GateIS<fp_type>::Create(23, 0, 5));
MakeControlledGate({4}, {0}, gates.back());

gates.push_back(GateIS<fp_type>::Create(23, 0, 5).ControlledBy({4}, {0}));
gates.push_back(GateRZ<fp_type>::Create(24, 0, 6.7));
gates.push_back(GateRX<fp_type>::Create(24, 1, 6.8));
gates.push_back(GateRY<fp_type>::Create(24, 2, 6.9));
gates.push_back(GateRZ<fp_type>::Create(24, 3, 7.0));
gates.push_back(GateRX<fp_type>::Create(24, 4, 7.1));
gates.push_back(GateRY<fp_type>::Create(24, 5, 7.2));

gates.push_back(GateHd<fp_type>::Create(25, 5));
MakeControlledGate({4}, {1}, gates.back());

gates.push_back(GateHd<fp_type>::Create(25, 5).ControlledBy({4}));
gates.push_back(GateRX<fp_type>::Create(26, 0, 7.3));
gates.push_back(GateRY<fp_type>::Create(26, 1, 7.4));
gates.push_back(GateRZ<fp_type>::Create(26, 2, 7.5));
Expand Down

0 comments on commit 586b499

Please sign in to comment.