Commit 3a4002a9 authored by Daniel Strano's avatar Daniel Strano
Browse files

Merge branch 'master' of https://github.com/eclipse/xacc into qrack_update


Signed-off-by: default avatarDaniel Strano <stranoj@gmail.com>
parents 41e1546b 46d11bc1
name: "Linux CI"
on:
push:
branches: [ master, xacc-devel ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
name: "Linux CI"
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Create Build Environment
run: cmake -E make_directory build
- name: Install dependencies
run: sudo apt-get -y update && sudo apt-get install -y --no-install-recommends ninja-build libssl-dev python3 libpython3-dev python3-pip libblas-dev liblapack-dev
- name: Configure
working-directory: build/
run: cmake -GNinja $GITHUB_WORKSPACE -DXACC_BUILD_TESTS=TRUE -DXACC_BUILD_EXAMPLES=TRUE
- name: Build
working-directory: build/
run: cmake --build . --target install
- name: Test
working-directory: build/
run: ctest --output-on-failure
\ No newline at end of file
name: "macOS CI"
on:
push:
branches: [ master, xacc-devel ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: macos-latest
name: "Mac CI"
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup XCode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: Create Build Environment
run: cmake -E make_directory build
- name: Install ninja
run: brew install ninja
- name: Install dependencies
run: brew install python3 openssl curl
- name: Configure
working-directory: build/
run: export SDKROOT="`xcrun --show-sdk-path`" && cmake -GNinja $GITHUB_WORKSPACE -DXACC_BUILD_TESTS=TRUE -DXACC_BUILD_EXAMPLES=TRUE
- name: Build
working-directory: build/
run: export SDKROOT="`xcrun --show-sdk-path`" && cmake --build . --target install
- name: Test
working-directory: build/
run: export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$HOME/.xacc/lib && ctest --output-on-failure
\ No newline at end of file
![XACC](docs/assets/xacc_full_logo.svg)
| master | xacc-devel |
| Branch | Status |
|:-------|:-------|
|[![pipeline status](https://code.ornl.gov/qci/xacc/badges/master/pipeline.svg)](https://code.ornl.gov/qci/xacc/commits/master) | [![pipeline status](https://code.ornl.gov/qci/xacc/badges/xacc-devel/pipeline.svg)](https://code.ornl.gov/qci/xacc/commits/xacc-devel) |
|master | [![Linux CI](https://github.com/eclipse/xacc/actions/workflows/ci-linux.yml/badge.svg?branch=master)](https://github.com/eclipse/xacc/actions/workflows/ci-linux.yml) [![Mac CI](https://github.com/eclipse/xacc/actions/workflows/ci-mac.yml/badge.svg?branch=master)](https://github.com/eclipse/xacc/actions/workflows/ci-mac.yml) |
|devel | [![Linux CI](https://github.com/eclipse/xacc/actions/workflows/ci-linux.yml/badge.svg?branch=xacc-devel)](https://github.com/eclipse/xacc/actions/workflows/ci-linux.yml) [![Mac CI](https://github.com/eclipse/xacc/actions/workflows/ci-mac.yml/badge.svg?branch=xacc-devel)](https://github.com/eclipse/xacc/actions/workflows/ci-mac.yml)|
## Language and Hardware Independent Quantum Programming Framework
XACC is an extensible compilation framework for hybrid quantum-classical computing architectures.
......
......@@ -30,6 +30,8 @@ namespace {
// By default, this accelerator targets ORNL's QLM installation.
// It can be used w/ other QLM by providing the host address explicitly.
const std::string QLM_HOST_NAME = "quantumbull.ornl.gov";
// Remote access QLM (via qlmaas) limits the number of CPU threads.
constexpr int QLMAAS_MAX_CORE_COUNT = 75;
inline bool isMeasureGate(const xacc::InstPtr &in_instr) {
return (in_instr->name() == "Measure");
......@@ -1010,7 +1012,7 @@ void QlmAccelerator::execute(
if (!m_remoteAccess) {
return m_qlmQpuServer.attr("submit")(qlmJob);
} else {
auto asynchronous_result = m_qlmQpuServer.attr("submit")(qlmJob);
auto asynchronous_result = m_qlmQpuServer.attr("submit")(qlmJob, "core_usage"_a = QLMAAS_MAX_CORE_COUNT);
// wait
auto sync_result = asynchronous_result.attr("join")();
return sync_result;
......@@ -1039,7 +1041,7 @@ void QlmAccelerator::execute(
if (!m_remoteAccess) {
return m_qlmQpuServer.attr("submit")(qlmJob);
} else {
auto asynchronous_result = m_qlmQpuServer.attr("submit")(qlmJob);
auto asynchronous_result = m_qlmQpuServer.attr("submit")(qlmJob, "core_usage"_a = QLMAAS_MAX_CORE_COUNT);
// wait
auto sync_result = asynchronous_result.attr("join")();
return sync_result;
......@@ -1068,7 +1070,7 @@ void QlmAccelerator::execute(
if (!m_remoteAccess) {
return m_qlmQpuServer.attr("submit")(batch);
} else {
auto asynchronous_result = m_qlmQpuServer.attr("submit")(batch);
auto asynchronous_result = m_qlmQpuServer.attr("submit")(batch, "core_usage"_a = QLMAAS_MAX_CORE_COUNT);
// wait
auto sync_result = asynchronous_result.attr("join")();
return sync_result;
......
......@@ -38,23 +38,8 @@ void ROErrorDecorator::execute(
std::map<int, double> piplus, piminus;
if (properties.keyExists<std::vector<double>>("p01s") &&
properties.keyExists<std::vector<double>>("p10s")) {
auto p01s = properties.get<std::vector<double>>("p01s");
auto p10s = properties.get<std::vector<double>>("p10s");
for (int i = 0; i < p01s.size(); i++) {
piplus.insert({i, p01s[i] + p10s[i]});
piminus.insert({i, p01s[i] - p10s[i]});
}
} else {
if (!xacc::fileExists(roErrorFile)) {
xacc::info(
"Cannot find readout erro file (key 'file'). Skipping ReadoutError "
"correction.");
return;
}
if (xacc::fileExists(roErrorFile)) {
// First: if a readout error file is provided, use it (since user explicitly provided it)
// Get RO error probs
buffer->addExtraInfo("ro-error-file", ExtraInfo(roErrorFile));
......@@ -78,6 +63,20 @@ void ROErrorDecorator::execute(
piminus.insert({qbit, value["-"].GetDouble()});
}
}
} else if (properties.keyExists<std::vector<double>>("p01s") &&
properties.keyExists<std::vector<double>>("p10s")) {
// If no readout error file is provided, use the backend's p01s and p10s properties
auto p01s = properties.get<std::vector<double>>("p01s");
auto p10s = properties.get<std::vector<double>>("p10s");
for (int i = 0; i < p01s.size(); i++) {
piplus.insert({i, p01s[i] + p10s[i]});
piminus.insert({i, p01s[i] - p10s[i]});
}
} else {
xacc::warning("Accelerator does not have readout error properties and Cannot "
"find readout erro file (key 'file'). Skipping ReadoutError "
"correction.");
return;
}
auto supports = [](std::shared_ptr<CompositeInstruction> f) {
......@@ -184,24 +183,8 @@ void ROErrorDecorator::execute(
if (decoratedAccelerator) {
properties = decoratedAccelerator->getProperties();
}
if (properties.keyExists<std::vector<double>>("p01s") &&
properties.keyExists<std::vector<double>>("p10s")) {
auto p01s = properties.get<std::vector<double>>("p01s");
auto p10s = properties.get<std::vector<double>>("p10s");
for (int i = 0; i < p01s.size(); i++) {
piplus.insert({i, p01s[i] + p10s[i]});
piminus.insert({i, p01s[i] - p10s[i]});
}
} else {
if (!xacc::fileExists(roErrorFile)) {
xacc::info(
"Cannot find readout error file (key 'file'). Skipping ReadoutError "
"correction.");
return;
}
if (xacc::fileExists(roErrorFile)) {
// Get RO error probs
buffer->addExtraInfo("ro-error-file", ExtraInfo(roErrorFile));
......@@ -224,6 +207,22 @@ void ROErrorDecorator::execute(
piminus.insert({qbit, value["-"].GetDouble()});
}
}
} else if (properties.keyExists<std::vector<double>>("p01s") &&
properties.keyExists<std::vector<double>>("p10s")) {
auto p01s = properties.get<std::vector<double>>("p01s");
auto p10s = properties.get<std::vector<double>>("p10s");
for (int i = 0; i < p01s.size(); i++) {
piplus.insert({i, p01s[i] + p10s[i]});
piminus.insert({i, p01s[i] - p10s[i]});
}
} else {
xacc::warning(
"Accelerator does not have readout error properties and Cannot "
"find readout erro file (key 'file'). Skipping ReadoutError "
"correction.");
return;
}
// Get the number of shots first
......
......@@ -167,13 +167,24 @@ void HoneywellAccelerator::execute(
"Please specify a honeywell backend in your getAccelerator() call.");
}
auto qasm = getNativeCode(circuit);
auto backend_status = get(url, "machine/"+backend, generateRequestHeader());
auto status_J = nlohmann::json::parse(backend_status);
if (status_J["state"] != "online") {
xacc::error("Cannot run on " + backend + ", it is not online.");
while (true) {
auto backend_status =
get(url, "machine/" + backend, generateRequestHeader());
auto status_J = nlohmann::json::parse(backend_status);
// xacc::info("\nHoneywell status:\n" + backend_status);
// If offline, terminate
if (status_J["state"] == "offline") {
xacc::error("Cannot run on " + backend + ", it is offline.");
}
// If online, continue to run
if (status_J["state"] == "online") {
break;
}
// If status = 'in maintenance', wait for a bit and try again
xacc::info("Honeywell is '" + std::string(status_J["state"]) +
"', waiting for a bit...");
std::this_thread::sleep_for(std::chrono::seconds(60));
}
xacc::info("\nHoneywell sending qasm:\n" + qasm);
nlohmann::json j;
......
......@@ -892,10 +892,14 @@ HeterogeneousMap IBMAccelerator::getProperties() {
if (q["name"].get<std::string>() == "prob_meas0_prep1") {
p01s.push_back(q["value"].get<double>());
} else if (q["name"].get<std::string>() == "prob_meas1_prep0") {
p10s.push_back(q["value"].get<double>());
}
p10s.push_back(q["value"].get<double>());
}
}
assert(std::all_of(p01s.begin(), p01s.end(),
[](double x) { return x >= 0.0 && x < 1.0; }));
assert(std::all_of(p10s.begin(), p10s.end(),
[](double x) { return x >= 0.0 && x < 1.0; }));
m.insert("p01s", p01s);
m.insert("p10s", p10s);
......
......@@ -50,6 +50,20 @@ void IonQAccelerator::initialize(const HeterogeneousMap &params) {
}
}
// Note: IonQ don't support batching.
void IonQAccelerator::execute(
std::shared_ptr<AcceleratorBuffer> buffer,
const std::vector<std::shared_ptr<CompositeInstruction>> circuits) {
for (const auto &f : circuits) {
auto tmpBuffer =
std::make_shared<xacc::AcceleratorBuffer>(f->name(), buffer->size());
// Run each circuit
RemoteAccelerator::execute(tmpBuffer, f);
// tmpBuffer->print();
buffer->appendChild(f->name(), tmpBuffer);
}
}
const std::string IonQAccelerator::processInput(
std::shared_ptr<AcceleratorBuffer> buffer,
std::vector<std::shared_ptr<CompositeInstruction>> functions) {
......@@ -80,7 +94,7 @@ const std::string IonQAccelerator::processInput(
using json = nlohmann::json;
json jj;
to_json(jj, prog);
xacc::info("IonQ Job JSON:\n" + jj.dump(4) + "\n");
return jj.dump();
}
......@@ -145,6 +159,8 @@ void IonQAccelerator::processResponse(std::shared_ptr<AcceleratorBuffer> buffer,
buffer->appendMeasurement(getBitStrForInt(std::stoi(kv.first)),
std::ceil(kv.second * shots));
}
xacc::info("IonQ Result JSON:\n" + j.dump(4) + "\n");
return;
}
......
......@@ -24,7 +24,9 @@ namespace quantum {
class IonQAccelerator : public RemoteAccelerator {
public:
void cancel() override;
void execute(std::shared_ptr<AcceleratorBuffer> buffer,
const std::vector<std::shared_ptr<CompositeInstruction>>
circuits) override;
void initialize(const HeterogeneousMap &params = {}) override;
void updateConfiguration(const HeterogeneousMap &config) override {
if (config.keyExists<int>("shots")) {
......
......@@ -151,16 +151,49 @@ public:
}
void visit(U &u) override {
auto t = u.getParameter(0).toString();
auto p = u.getParameter(1).toString();
auto l = u.getParameter(2).toString();
Rz rz(u.bits()[0], t);
Ry ry(u.bits()[0], p);
Rz rz2(u.bits()[0], l);
visit(rz);
visit(ry);
visit(rz2);
auto t = u.getParameter(0).as<double>();
auto p = u.getParameter(1).as<double>();
auto l = u.getParameter(2).as<double>();
auto qubit = u.bits()[0];
{
// u3_qasm_def.rz(lam, 0)
xacc::ionq::CircuitInstruction inst;
inst.set_gate("rz");
inst.set_target(qubit);
inst.set_rotation(l);
instructions.push_back(inst);
}
{
// u3_qasm_def.sx(0)
// v = Square root of not gate
xacc::ionq::CircuitInstruction inst;
inst.set_gate("v");
inst.set_target(qubit);
instructions.push_back(inst);
}
{
// u3_qasm_def.rz(theta+pi, 0)
xacc::ionq::CircuitInstruction inst;
inst.set_gate("rz");
inst.set_target(qubit);
inst.set_rotation(t + M_PI);
instructions.push_back(inst);
}
{
// u3_qasm_def.sx(0)
xacc::ionq::CircuitInstruction inst;
inst.set_gate("v");
inst.set_target(qubit);
instructions.push_back(inst);
}
{
// u3_qasm_def.rz(phi+3*pi, 0)
xacc::ionq::CircuitInstruction inst;
inst.set_gate("rz");
inst.set_target(qubit);
inst.set_rotation(p + 3.0 * M_PI);
instructions.push_back(inst);
}
}
void visit(Rx &rx) override {
......
......@@ -15,6 +15,8 @@ set(LIBRARY_NAME xacc-iontrap)
file(GLOB SRC
*.cpp
accelerator/*.cpp
decomp/*.cpp
transformations/*.cpp)
usfunctiongetresourcesource(TARGET ${LIBRARY_NAME} OUT SRC)
......@@ -24,6 +26,8 @@ add_library(${LIBRARY_NAME} SHARED ${SRC})
target_include_directories(${LIBRARY_NAME}
PUBLIC .
./accelerator
./decomp
./transformations
${CMAKE_SOURCE_DIR}/tpls/ensmallen
${CMAKE_SOURCE_DIR}/tpls/armadillo)
......
......@@ -15,6 +15,8 @@
#include "cppmicroservices/BundleActivator.h"
#include "cppmicroservices/BundleContext.h"
#include "cppmicroservices/ServiceProperties.h"
#include "IonTrapAccelerator.hpp"
#include "IonTrapOneQubitPass.hpp"
#include "IonTrapTwoQubitPass.hpp"
using namespace cppmicroservices;
......@@ -24,8 +26,14 @@ public:
IonTrapActivator() {}
void Start(BundleContext context) {
auto acc = std::make_shared<xacc::quantum::IonTrapAccelerator>();
context.RegisterService<xacc::Accelerator>(acc);
auto twoQubitPass = std::make_shared<xacc::quantum::IonTrapTwoQubitPass>();
context.RegisterService<xacc::IRTransformation>(twoQubitPass);
auto oneQubitPass = std::make_shared<xacc::quantum::IonTrapOneQubitPass>();
context.RegisterService<xacc::IRTransformation>(oneQubitPass);
}
void Stop(BundleContext context) {}
......
This diff is collapsed.
/*******************************************************************************
* Copyright (c) 2019-2021 UT-Battelle, LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompanies this
* distribution. The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
* License is available at https://eclipse.org/org/documents/edl-v10.php
*
* Contributors:
* Thien Nguyen - initial API and implementation
* Daniel Strano - adaption from Quantum++ to Qrack
* Austin Adams - adaption for GTRI testbed
*******************************************************************************/
#ifndef QUANTUM_ACCELERATORS_IONTRAPACCELERATOR_HPP_
#define QUANTUM_ACCELERATORS_IONTRAPACCELERATOR_HPP_
#include "xacc.hpp"
#include "IonTrapOneQubitPass.hpp"
#include "IonTrapTwoQubitPass.hpp"
#include "IonTrapQasmVisitor.hpp"
#include "IonTrapPassesCommon.hpp"
// On Linux, use inotify to check for result files. On other operating
// systems, use polling instead
#ifdef __linux__
#define IONTRAP_USE_INOTIFY
#endif
namespace xacc {
namespace quantum {
class IonTrapAccelerator : public Accelerator {
public:
// Identifiable interface impls
virtual const std::string name() const override { return "iontrap"; }
virtual const std::string description() const override { return "XACC Accelerator targetting the IonTrap general-purpose quantum testbed"; }
// Accelerator interface impls
virtual void initialize(const HeterogeneousMap& params = {}) override;
virtual void updateConfiguration(const HeterogeneousMap& config) override;
virtual const std::vector<std::string> configurationKeys() override;
virtual BitOrder getBitOrder() override { return BitOrder::LSB; }
virtual std::vector<std::pair<int, int>> getConnectivity() override;
virtual void execute(std::shared_ptr<AcceleratorBuffer> buffer, const std::shared_ptr<CompositeInstruction> compositeInstruction) override;
virtual void execute(std::shared_ptr<AcceleratorBuffer> buffer, const std::vector<std::shared_ptr<CompositeInstruction>> compositeInstructions) override;
private:
static constexpr double RESULT_CHECK_INTERVAL_SEC = 1;
std::string inputExt;
bool adjacentIonCouplingsOnly;
bool serializedSeq;
bool keepTempFiles;
bool emitQasm;
bool keepTrailingGates;
bool keepRzBeforeMeas;
bool keepRxBeforeXX;
bool keepLeadingRz;
double threshold;
std::size_t numQubits;
IonTrapCouplingMap couplingMap;
IonTrapMSPhaseMap msPhases;
std::string watchdir;
std::string logTransformsPath;
void readConfig();
std::map<std::string, std::string> readConfigKeys();
void compileToNativeGatesAndLogTransforms(std::shared_ptr<CompositeInstruction>);
void compileToNativeGates(std::shared_ptr<CompositeInstruction>, IonTrapLogTransformCallback);
#ifdef IONTRAP_USE_INOTIFY
int getInotifyFd(std::string);
void waitForResultFileInotify(int, std::string &);
#else
void waitForResultFile(std::string &);
#endif
std::vector<InstPtr> findOpTableRow(const std::shared_ptr<CompositeInstruction>,
std::size_t &);
void writeOpTable(const std::shared_ptr<CompositeInstruction>, std::ostream &);
void writeInput(std::shared_ptr<AcceleratorBuffer>,
const std::shared_ptr<CompositeInstruction>,
const std::string &,
std::multimap<std::size_t, std::size_t> &);
double calcExpZ(std::vector<std::complex<double>> &,
std::multimap<std::size_t, std::size_t> &);
void readResult(std::shared_ptr<AcceleratorBuffer>, const std::string &,
std::multimap<std::size_t, std::size_t> &);
std::string randomChars();
};
}}
#endif
/*******************************************************************************
* Copyright (c) 2019-2020 UT-Battelle, LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompanies this
* distribution. The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
* License is available at https://eclipse.org/org/documents/edl-v10.php
*
* Contributors:
* Thien Nguyen - initial API and implementation
* Daniel Strano - adaption from Quantum++ to Qrack
* Austin Adams - adaption for GTRI testbed
*******************************************************************************/
#include "IonTrapQasmVisitor.hpp"
#include "xacc.hpp"
namespace xacc {
namespace quantum {
void IonTrapQasmVisitor::writeHeader() {
for (int i = 0; i < nQubits; i++) {
qasmFile << "\tqubit q" << i << "\r\n";
}
qasmFile << "\r\n";
}
void IonTrapQasmVisitor::visit(Hadamard &h) {
qasmFile << "\tH q" << h.bits()[0] << "\r\n";
}
void IonTrapQasmVisitor::visit(CNOT &cnot) {
std::size_t leftIdx = std::min(cnot.bits()[0], cnot.bits()[1]);
std::size_t rightIdx = std::max(cnot.bits()[0], cnot.bits()[1]);
if (!couplingMap.count(std::make_pair(leftIdx, rightIdx))) {
xacc::error("CNOT on non-adjacent qubits " + std::to_string(leftIdx)
+ "," + std::to_string(rightIdx));
return;
}
qasmFile << "\tCNOT q" << cnot.bits()[0] << ",q" << cnot.bits()[1] << "\r\n";
}
void IonTrapQasmVisitor::visit(Rz &rz) {
double theta = rz.getParameter(0).as<double>();
qasmFile << "\tRZ(" << theta << ") q" << rz.bits()[0] << "\r\n";
}
void IonTrapQasmVisitor::visit(Ry &ry) {
double theta = ry.getParameter(0).as<double>();
S s(ry.bits()[0]);
Rx rx(ry.bits()[0], theta);
Sdg sdg(ry.bits()[0]);
// Ry(theta) = S.Rx(theta).Sdg
visit(sdg);
visit(rx);
visit(s);
}
void IonTrapQasmVisitor::visit(Rx &rx) {
double theta = rx.getParameter(0).as<double>();
Hadamard h1(rx.bits()[0]);
Rz rz(rx.bits()[0], theta);
Hadamard h2(rx.bits()[0]);