Commit 086513da authored by Nguyen, Thien Minh's avatar Nguyen, Thien Minh
Browse files

Add a simple arithmetic adder using the new syntax



Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent 7942511b
Loading
Loading
Loading
Loading
+19 −8
Original line number Diff line number Diff line
#include <qcor_arithmetic>

__qpu__ void test_adder(qreg a, qreg b, qubit cin, qubit cout) {
  X(a[0]); // Set input a = 01
  X(b);    // Set input b = 11
  // Apply the adder
  ripple_add(a, b, cin, cout);
  Measure(b);
  Measure(cout);
}

// Compile:
int main(int argc, char **argv) {
  auto q = qalloc(7);
  // New implementation
  controlled_phi_add::print_kernel(q.head(5), 11, {q[5], q[6]});
  
  
  // Deprecated....
  std::cout << "Original:\n";
  ccPhiAdd::print_kernel(q, 5, 6, 11, 0, 5, 0);
  // Set the inputs to the adder
  auto a = qalloc(2);
  auto b = qalloc(2);
  auto carry_in = qalloc(1);
  auto carry_out = qalloc(1);
  // Execute:
  // test_adder();
  // test_adder::print_kernel(a, b, carry_in[0], carry_out[0]);
  test_adder(a, b, carry_in[0], carry_out[0]);
  b.print(); // 00
  carry_out.print(); // 1

  return 0;
}
 No newline at end of file
+21 −0
Original line number Diff line number Diff line
#pragma once
#include "qcor.hpp"

// Majority gate
__qpu__ void majority(qubit a, qubit b, qubit c) {
  X::ctrl(c, b);
  X::ctrl(c, a);
  X::ctrl({a, b}, c);
}

// Add a to b and save to b
// c_in and c_out are carry bits (in and out)
__qpu__ void ripple_add(qreg a, qreg b, qubit c_in, qubit c_out) {
  compute {
    majority(c_in, b[0], a[0]);
    for (auto j : range(a.size() - 1)) {
      majority(a[j], b[j + 1], a[j + 1]);
    }
  }
  action { X::ctrl(a.tail(), c_out); }
}
 No newline at end of file
+1 −0
Original line number Diff line number Diff line
#pragma once
#include "impl/arithmetic.hpp"
#include "impl/integer_arithmetic.hpp"
+3 −14
Original line number Diff line number Diff line
@@ -649,20 +649,11 @@ template <typename... Args>
void apply_control(std::shared_ptr<CompositeInstruction> parent_kernel,
                   const std::vector<qubit> &ctrl_qbits,
                   KernelSignature<Args...> &kernelCallable, Args... args) {
  const auto buffer_name = ctrl_qbits[0].first;

  std::vector<std::pair<std::string, size_t>> ctrl_qubits;
  for (const auto &qb : ctrl_qbits) {
    if (qb.first != buffer_name) {
      // We can only handle control qubits on the same qReg.
      error("Unable to handle control qubits from different registers");
    }
    ctrl_qubits.emplace_back(std::make_pair(qb.first, qb.second));
  }

  std::vector<int> ctrl_bits;
  std::transform(ctrl_qbits.begin(), ctrl_qbits.end(),
                 std::back_inserter(ctrl_bits),
                 [](auto qb) { return qb.second; });

  // Is is in a **compute** segment?
  // i.e. doing control within the compute block itself.
  // need to by-pass the compute marking in order for the control gate to
@@ -682,9 +673,7 @@ void apply_control(std::shared_ptr<CompositeInstruction> parent_kernel,
  }

  auto ctrlKernel = qcor::__internal__::create_ctrl_u();
  ctrlKernel->expand({{"U", tempKernel},
                      {"control-idx", ctrl_bits},
                      {"control-buffer", buffer_name}});
  ctrlKernel->expand({{"U", tempKernel}, {"control-idx", ctrl_qubits}});

  // Mark all the *Controlled* instructions as compute segment
  // if it was in the compute_section.