Skip to content

Commit

Permalink
Improved QubitPool
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Claudino <[email protected]>
  • Loading branch information
danclaudino committed Oct 3, 2024
1 parent ee60711 commit 5a60e55
Showing 1 changed file with 78 additions and 66 deletions.
144 changes: 78 additions & 66 deletions quantum/plugins/algorithms/adapt/operator_pools/QubitPool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,53 @@ class QubitPool : public OperatorPool {
return true;
}

// Helper function to generate a Pauli string from a pattern and indices
std::string generate_pauli_string(const std::vector<std::pair<char, int>>& pattern) {
std::string result;
for (const auto& [pauli, index] : pattern) {
result += pauli;
result += std::to_string(index);
result += " ";
}
return result;
}

// Generate all combinations of two unique indices for n qubits
std::vector<std::pair<int, int>> generate_two_index_combinations(int n) {
std::vector<std::pair<int, int>> combinations;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
combinations.emplace_back(i, j);
}
}
return combinations;
}

// Generate all combinations of four unique indices for n qubits
std::vector<std::tuple<int, int, int, int>> generate_four_index_combinations(int n) {
std::vector<std::tuple<int, int, int, int>> combinations;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
for (int k = j + 1; k < n; ++k) {
for (int l = k + 1; l < n; ++l) {
combinations.emplace_back(i, j, k, l);
}
}
}
}
return combinations;
}

// Generate all permutations of a given pattern of X and Y
std::vector<std::vector<char>> generate_permutations(const std::vector<char>& pattern) {
std::vector<std::vector<char>> permutations;
std::vector<char> p = pattern;
do {
permutations.push_back(p);
} while (std::next_permutation(p.begin(), p.end()));
return permutations;
}

// generate the pool
std::vector<std::shared_ptr<Observable>> generate(const int &nQubits) override {

Expand All @@ -52,82 +99,47 @@ class QubitPool : public OperatorPool {
// number of Y's and only add unique operators, i.e., those which
// survive symmetry operations in the PauliOperator class.

std::vector<PauliOperator> pauliOps;
std::vector<std::string> label;
std::string opStr;
PauliOperator op;

for (int q0 = 0; q0 < nQubits; q0++){
std::cout << "Pauli strings of the form Xa Yb and permutations:\n";
std::vector<std::string> ops;
for (const auto& [a, b] : generate_two_index_combinations(nQubits)) {
std::vector<char> base_pattern = {'X', 'Y'};
auto permutations = generate_permutations(base_pattern);

for (auto op0 : {"X", "Y", "Z"}){

label.push_back(op0);
if (op0 == "Y"){
opStr = "Y" + std::to_string(q0);
op.fromString("(0,1)" + opStr);
pauliOps.push_back(op);
for (const auto& perm : permutations) {
std::vector<std::pair<char, int>> pattern = {{perm[0], a}, {perm[1], b}};
ops.push_back(generate_pauli_string(pattern));
}
}

for (int q1 = q0 + 1; q1 < nQubits; q1++){

for (auto op1 : {"X", "Y", "Z"}){

label.push_back(op1);
if (std::count(label.begin(), label.end(), "Y") == 1){
opStr = op0 + std::to_string(q0) + op1 + std::to_string(q1);
op.fromString("(0,1)" + opStr);
if(!(std::find(pauliOps.begin(), pauliOps.end(), op) != pauliOps.end())){
pauliOps.push_back(op);
}

}

for (int q2 = q1 + 1; q2 < nQubits; q2++){

for (auto op2 : {"X", "Y", "Z"}){

label.push_back(op2);
if (std::count(label.begin(), label.end(), "Y") == 1 || std::count(label.begin(), label.end(), "Y") == 3){

opStr = op0 + std::to_string(q0) + op1 + std::to_string(q1) + op2 + std::to_string(q2);
op.fromString("(0,1)" + opStr);
if(!(std::find(pauliOps.begin(), pauliOps.end(), op) != pauliOps.end())){
pauliOps.push_back(op);
}
}

for (int q3 = q2 + 1; q3 < nQubits; q3++){

for (auto op3 : {"X", "Y", "Z"}){

label.push_back(op3);
if (std::count(label.begin(), label.end(), "Y") == 1 || std::count(label.begin(), label.end(), "Y") == 3){
// Case 2: Xa Xb Xc Yd and permutations (XXXY and all permutations)
std::cout << "\nPauli strings of the form Xa Xb Xc Yd and permutations:\n";
for (const auto& [a, b, c, d] : generate_four_index_combinations(nQubits)) {
std::vector<char> base_pattern = {'X', 'X', 'X', 'Y'};
auto permutations = generate_permutations(base_pattern);

opStr = op0 + std::to_string(q0) + op1 + std::to_string(q1) + op2 + std::to_string(q2) + op3 + std::to_string(q3);
op.fromString("(0,1)" + opStr);
if(!(std::find(pauliOps.begin(), pauliOps.end(), op) != pauliOps.end())){
pauliOps.push_back(op);
}
for (const auto& perm : permutations) {
std::vector<std::pair<char, int>> pattern = {{perm[0], a}, {perm[1], b}, {perm[2], c}, {perm[3], d}};
ops.push_back(generate_pauli_string(pattern));
}
}

}
// Case 3: Xa Yb Yc Yd and permutations (XYXX and all permutations)
std::cout << "\nPauli strings of the form Xa Yb Yc Yd and permutations:\n";
for (const auto& [a, b, c, d] : generate_four_index_combinations(nQubits)) {
std::vector<char> base_pattern = {'X', 'Y', 'Y', 'Y'};
auto permutations = generate_permutations(base_pattern);

label.pop_back();
}
}
label.pop_back();
}
}
label.pop_back();
}
for (const auto& perm : permutations) {
std::vector<std::pair<char, int>> pattern = {{perm[0], a}, {perm[1], b}, {perm[2], c}, {perm[3], d}};
ops.push_back(generate_pauli_string(pattern));
}
label.pop_back();
}
}

for (auto op: pauliOps){
pool.push_back(std::dynamic_pointer_cast<Observable>(std::make_shared<PauliOperator>(op)));
const std::complex<double> i{0, 1};
for (auto op : ops) {
pool.push_back(std::dynamic_pointer_cast<Observable>(std::make_shared<PauliOperator>("(0, 1)" + op)));
}

// exit(0);
return pool;
}

Expand Down

0 comments on commit 5a60e55

Please sign in to comment.