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

Implemented general Array API's: array creation and concatenate



Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent d112b4b5
Loading
Loading
Loading
Loading
+30 −4
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
namespace xacc {
    class AcceleratorBuffer;
}

extern "C" {
using qreg = xacc::internal_compiler::qreg;
extern Result ResultZero;
@@ -89,11 +90,36 @@ void __quantum__rt__result_update_reference_count(Result *, int64_t count);

Result* __quantum__qis__mz(Qubit* q);

// Qubit Alloc/Dealloc API
Array* __quantum__rt__qubit_allocate_array(uint64_t idx);

// Array functions
int8_t * __quantum__rt__array_get_element_ptr_1d(Array* q,
                                                      uint64_t idx);
void __quantum__rt__qubit_release_array(Array* q);

// Array API
// Create an array
Array *__quantum__rt__array_create_1d(int32_t itemSizeInBytes,
                                      int64_t count_items);
// Get size
int64_t __quantum__rt__array_get_size_1d(Array *array);
// Get element at an index
int8_t *__quantum__rt__array_get_element_ptr_1d(Array *q, uint64_t idx);
// Copy
Array *__quantum__rt__array_copy(Array *array, bool forceNewInstance);
// Concatenate
Array *__quantum__rt__array_concatenate(Array *head, Array *tail);
// Ref. counting
void __quantum__rt__array_update_alias_count(Array *array, int64_t increment);
void __quantum__rt__array_update_reference_count(Array *aux, int64_t count);

// Multi-dimension Array API
int32_t __quantum__rt__array_get_dim(Array *array);
int64_t __quantum__rt__array_get_size(Array *array, int32_t dim);
Array *__quantum__rt__array_create_nonvariadic(int itemSizeInBytes,
                                               int countDimensions,
                                               va_list dims);
Array *__quantum__rt__array_create(int itemSizeInBytes, int countDimensions,
                                   ...);
int8_t *__quantum__rt__array_get_element_ptr_nonvariadic(Array *array,
                                                         va_list args);
int8_t *__quantum__rt__array_get_element_ptr(Array *array, ...);
Array *__quantum__rt__array_project(Array *array, int dim, int64_t index);
}
 No newline at end of file
+14 −0
Original line number Diff line number Diff line
@@ -31,6 +31,20 @@ struct Array {
        m_storage(nbItems * itemSizeInBytes, 0) {
    assert(m_itemSizeInBytes > 0);
  };
  // Copy
  Array(const Array &other)
      : m_itemSizeInBytes(other.m_itemSizeInBytes), m_storage(other.m_storage) {
  }

  void append(const Array &other) {
    if (other.m_itemSizeInBytes != m_itemSizeInBytes) {
      throw std::runtime_error("Cannot append Arrays of different types.");
    }

    m_storage.insert(m_storage.end(), other.m_storage.begin(),
                     other.m_storage.end());
  }

  int64_t size() { return m_storage.size() / m_itemSizeInBytes; }
  void clear() { m_storage.clear(); }

+21 −5
Original line number Diff line number Diff line
@@ -7,15 +7,14 @@ Array *__quantum__rt__array_create_1d(int32_t itemSizeInBytes,
  // TODO
  if (verbose)
    std::cout << "CALL: " << __PRETTY_FUNCTION__ << "\n";

  return nullptr;
  return new Array(count_items, itemSizeInBytes);
}

int64_t __quantum__rt__array_get_size_1d(Array *state1) {
  // TODO
  if (verbose)
    std::cout << "CALL: " << __PRETTY_FUNCTION__ << "\n";
  return 0;
  return state1->size();
}

void __quantum__rt__array_update_alias_count(Array *array, int64_t increment) {
@@ -24,11 +23,17 @@ void __quantum__rt__array_update_alias_count(Array *array, int64_t increment) {
    std::cout << "CALL: " << __PRETTY_FUNCTION__ << "\n";
}

void __quantum__rt__array_update_reference_count(Array *aux, int64_t count) {
  // TODO
  if (verbose)
    std::cout << "CALL: " << __PRETTY_FUNCTION__ << "\n";
}

// Returns the number of dimensions in the array.
int32_t __quantum__rt__array_get_dim(Array *array) {
  if (verbose)
    std::cout << "CALL: " << __PRETTY_FUNCTION__ << "\n";
  return 0;
  return 1;
}

int64_t __quantum__rt__array_get_size(Array *array, int32_t dim) {
@@ -40,12 +45,23 @@ int64_t __quantum__rt__array_get_size(Array *array, int32_t dim) {
Array *__quantum__rt__array_copy(Array *array, bool forceNewInstance) {
  if (verbose)
    std::cout << "CALL: " << __PRETTY_FUNCTION__ << "\n";
  return nullptr;

  if (array && forceNewInstance) {
    return new Array(*array);
  }

  return array;
}

Array *__quantum__rt__array_concatenate(Array *head, Array *tail) {
  if (verbose)
    std::cout << "CALL: " << __PRETTY_FUNCTION__ << "\n";
  if (head && tail) {
    auto resultArray = new Array(*head);
    resultArray->append(*tail);
    return resultArray;
  }

  return nullptr;
}

+35 −0
Original line number Diff line number Diff line
@@ -42,6 +42,41 @@ TEST(QirQrtTester, checkSimple) {
  }
}

TEST(QirQrtTester, checkArray) {
  ::quantum::qrt_impl = xacc::getService<::quantum::QuantumRuntime>("nisq");
  ::quantum::qrt_impl->initialize("empty");
  int nbQubits = 5;
  auto arrayPtr = __quantum__rt__qubit_allocate_array(nbQubits);
  EXPECT_EQ(arrayPtr->size(), nbQubits);
  // Create an alias array of 3 qubits
  const std::vector<int> qubitsToCopy {0, 2, 4};
  auto aliasQubitArray = __quantum__rt__array_create_1d(sizeof(Qubit *), qubitsToCopy.size());
  EXPECT_EQ(aliasQubitArray->size(), qubitsToCopy.size());
  for (int i = 0; i < qubitsToCopy.size(); ++i) {
    auto src_loc =
        __quantum__rt__array_get_element_ptr_1d(arrayPtr, qubitsToCopy[i]);
    auto target_loc =
        __quantum__rt__array_get_element_ptr_1d(aliasQubitArray, i);
    memcpy(target_loc, src_loc, sizeof(Qubit *));
  }

  for (int i = 0; i < aliasQubitArray->size(); ++i) {
    Qubit *qb = *(reinterpret_cast<Qubit **>(
        __quantum__rt__array_get_element_ptr_1d(aliasQubitArray, i)));
    __quantum__qis__h(qb);
  }
  std::cout << "HOWDY:\n"
            << ::quantum::qrt_impl->get_current_program()->toString() << "\n";
  EXPECT_EQ(::quantum::qrt_impl->get_current_program()->nInstructions(), qubitsToCopy.size());
  // Check that the Hadamard gates are applied to the correct qubits {0, 2, 4}
  for (int i = 0; i < qubitsToCopy.size(); ++i) {
    auto inst = ::quantum::qrt_impl->get_current_program()->getInstruction(i);
    EXPECT_EQ(inst->name(), "H");
    EXPECT_EQ(inst->bits().size(), 1);
    EXPECT_EQ(inst->bits()[0], qubitsToCopy[i]);
  }
}

#if __GNUC__ >= 5
# pragma GCC diagnostic pop
#endif
+11 −4
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ import argparse, sys, os, glob, subprocess, mimetypes, re, pathlib
def main(argv=None):
    compiler = '@CLANG_EXECUTABLE@'
    verbose=False
    keep_bit_code_files=False
    baseLibs = ['-rdynamic', '-Wl,-rpath,@XACC_ROOT@/lib:@CMAKE_INSTALL_PREFIX@/lib:@LLVM_INSTALL_PREFIX@/lib:@CMAKE_INSTALL_PREFIX@/clang-plugins',
                            '-L', '@CMAKE_INSTALL_PREFIX@/lib','-lqcor', '-lqrt', '-lqcor-hybrid', '-lqcor-quasimo', '-lqcor-jit',
                             '-L', '@XACC_ROOT@/lib', '-lxacc', '-lCppMicroServices', '-lxacc-quantum-gate',
@@ -59,6 +60,7 @@ def main(argv=None):
        parser.add_argument('-xacc-version', metavar='', help='returns the current build version for underlying xacc install.')
        parser.add_argument('-version', metavar='', help='returns the current qcor build version.')
        parser.add_argument('-pythonpath', metavar='', help='print the correct PYTHONPATH to leverage qcor and xacc python API.')
        parser.add_argument('-keep-llvm-file', metavar='', help='keep intermediate LLVM files.')
        args = parser.parse_args(sys.argv)

    if '-pythonpath' in sys.argv[1:]:
@@ -184,6 +186,9 @@ def main(argv=None):
        print(''.join([l for l in lines]))
        exit(0)

    if '-keep-llvm-file' in sys.argv[1:]:
        keep_bit_code_files=True
        sys.argv.remove('-keep-llvm-file')
    
    sHandlerArgs = []
    # Get the QPU Backend
@@ -371,6 +376,8 @@ def main(argv=None):
                    print(e.returncode)
                base_cpp_name = os.path.splitext(driver_file_name)[0]
                sys.argv.append(base_cpp_name + '.o')     
        
        if not keep_bit_code_files:
            # remove these temp files
            os.remove(ll_file_name)
            os.remove(bc_file_name)