Commit ad04435e authored by Nguyen, Thien's avatar Nguyen, Thien
Browse files

Merge remote-tracking branch 'upstream/master' into tnguyen/fix-ionq-backend

parents 5c0dd934 c3faf15a
......@@ -18,6 +18,7 @@ add_subdirectory(algorithms)
add_subdirectory(decorators)
add_subdirectory(circuits)
add_subdirectory(optimizers)
add_subdirectory(iontrap)
add_subdirectory(ionq)
add_subdirectory(placement)
#add_subdirectory(scaffold)
......
......@@ -325,6 +325,7 @@ singleQubitGateGen(const Eigen::Matrix2cd &in_mat, size_t in_bitIdx) {
}
}
assert(found);
return std::make_tuple(a, bHalf, cHalf, dHalf);
} else if (std::abs(matrix(0, 0)) < TOLERANCE) {
auto two_a = fmod(std::arg(-matrix(0, 1) * matrix(1, 0)), 2 * M_PI);
a = (std::abs(two_a) < TOLERANCE ||
......@@ -351,6 +352,7 @@ singleQubitGateGen(const Eigen::Matrix2cd &in_mat, size_t in_bitIdx) {
}
}
assert(found);
return std::make_tuple(a, bHalf, cHalf, dHalf);
} else {
auto two_a = fmod(std::arg(matrix(0, 0) * matrix(1, 1)), 2 * M_PI);
a = (std::abs(two_a) < TOLERANCE ||
......@@ -392,11 +394,8 @@ singleQubitGateGen(const Eigen::Matrix2cd &in_mat, size_t in_bitIdx) {
}
}
assert(found);
return std::make_tuple(a, bHalf, cHalf, dHalf);
}
// Final check:
assert(checkParams(a, bHalf, cHalf, dHalf));
return std::make_tuple(a, bHalf, cHalf, dHalf);
};
// Use Z-Y decomposition of Nielsen and Chuang (Theorem 4.1).
// An arbitrary one qubit gate matrix can be writen as
......
# *******************************************************************************
# Copyright (c) 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 v.10 which accompany 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:
# Alexander J. McCaskey - initial API and implementation
# Austin Adams - aggressive copying and pasting for GTRI testbed
# *******************************************************************************/
set(LIBRARY_NAME xacc-iontrap)
file(GLOB SRC
*.cpp
transformations/*.cpp)
usfunctiongetresourcesource(TARGET ${LIBRARY_NAME} OUT SRC)
usfunctiongeneratebundleinit(TARGET ${LIBRARY_NAME} OUT SRC)
add_library(${LIBRARY_NAME} SHARED ${SRC})
target_include_directories(${LIBRARY_NAME}
PUBLIC .
./transformations
${CMAKE_SOURCE_DIR}/tpls/ensmallen
${CMAKE_SOURCE_DIR}/tpls/armadillo)
target_link_libraries(${LIBRARY_NAME}
PUBLIC xacc
xacc-quantum-gate
xacc-circuit-optimizers
)
if(LAPACK_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAS_LAPACK")
target_link_libraries(${LIBRARY_NAME} PUBLIC ${LAPACK_LIBRARIES})
else()
message(STATUS "LAPACK NOT FOUND. ion trap plugin may not work.")
endif()
set(_bundle_name xacc_iontrap)
set_target_properties(${LIBRARY_NAME}
PROPERTIES COMPILE_DEFINITIONS
US_BUNDLE_NAME=${_bundle_name}
US_BUNDLE_NAME
${_bundle_name})
usfunctionembedresources(TARGET
${LIBRARY_NAME}
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
FILES
manifest.json)
if(APPLE)
set_target_properties(${LIBRARY_NAME}
PROPERTIES INSTALL_RPATH "@loader_path/../lib")
set_target_properties(${LIBRARY_NAME}
PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
else()
set_target_properties(${LIBRARY_NAME}
PROPERTIES INSTALL_RPATH "$ORIGIN/../lib")
set_target_properties(${LIBRARY_NAME} PROPERTIES LINK_FLAGS "-shared")
endif()
if(XACC_BUILD_TESTS)
add_subdirectory(tests)
endif()
install(TARGETS ${LIBRARY_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/plugins)
/*******************************************************************************
* Copyright (c) 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 - aggressive copying and pasting for GTRI testbed
*******************************************************************************/
#include "cppmicroservices/BundleActivator.h"
#include "cppmicroservices/BundleContext.h"
#include "cppmicroservices/ServiceProperties.h"
#include "IonTrapTwoQubitPass.hpp"
using namespace cppmicroservices;
class US_ABI_LOCAL IonTrapActivator : public BundleActivator {
public:
IonTrapActivator() {}
void Start(BundleContext context) {
auto twoQubitPass = std::make_shared<xacc::quantum::IonTrapTwoQubitPass>();
context.RegisterService<xacc::IRTransformation>(twoQubitPass);
}
void Stop(BundleContext context) {}
};
CPPMICROSERVICES_EXPORT_BUNDLE_ACTIVATOR(IonTrapActivator)
Ion Trap Testbed Backend
========================
This is a backend that targets the quantum testbed developed by the CIPHER
[Quantum Systems Division][1] at Georgia Tech Research Institute (GTRI). The
following 2016 paper describes the testbed:
https://doi.org/10.1088/1367-2630/18/2/023048. However, due to recent hardware
upgrades, we assume that the gate beam is now tightly-focused enough for
single-ion addressing. (That is, such that the cascading scheme is no longer
necessary for single-qubit gates.) We also assume that the MS phases are 0,
meaning the native entangling gate is an XX-Ising gate. We also do not consider
the MS echo scheme described in the paper.
This is designed for modified version of the control software, which is written
in IGOR Pro and is not currently public.
Please contact Austin Adams at <aja@gatech.edu> if you have any questions about
this backend.
[1]: https://www.gtri.gatech.edu/focus-areas/quantum-computing-sensing
{
"bundle.symbolic_name" : "xacc_iontrap",
"bundle.activator" : true,
"bundle.name" : "XACC Ion Trap Testbed Accelerator",
"bundle.description" : "This bundle provides an Accelerator for an ion trap quantum testbed."
}
# *******************************************************************************
# 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 v.10 which accompany 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
# *******************************************************************************/
add_xacc_test(IonTrapTwoQubitPass)
target_link_libraries(IonTrapTwoQubitPassTester xacc-iontrap)
/*******************************************************************************
* 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
*******************************************************************************/
#include <gtest/gtest.h>
#include "xacc.hpp"
#include "xacc_service.hpp"
#include "IonTrapTwoQubitPass.hpp"
namespace {
// Give us some nice breathing room
const double ERR = 1e-4;
}
//
// Two-qubit pass tests
//
TEST(IonTrapTwoQubitPassTester, twoQubitPassDecomposesCnot)
{
auto c = xacc::getService<xacc::Compiler>("xasm");
auto ir = c->compile(R"(__qpu__ void my_bell(qbit q) {
H(q[0]);
X(q[1]);
CX(q[0],q[1]);
Measure(q[0]);
Measure(q[1]);
})")->getComposites()[0];
auto twoQubitPass = xacc::getService<xacc::IRTransformation>("iontrap-2q-pass");
xacc::quantum::IonTrapMSPhaseMap msPhases({{{0, 1}, {0.0, 0.0}}});
twoQubitPass->apply(ir, nullptr, {{"ms-phases", &msPhases}});
std::vector<std::size_t> bits0({0});
std::vector<std::size_t> bits1({1});
std::vector<std::size_t> bits01({0,1});
EXPECT_EQ(9, ir->nInstructions());
EXPECT_EQ("H", ir->getInstruction(0)->name());
EXPECT_EQ(bits0, ir->getInstruction(0)->bits());
EXPECT_EQ("X", ir->getInstruction(1)->name());
EXPECT_EQ(bits1, ir->getInstruction(1)->bits());
EXPECT_EQ("Ry", ir->getInstruction(2)->name());
EXPECT_EQ(bits0, ir->getInstruction(2)->bits());
EXPECT_NEAR(-M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(2)->getParameter(0)),
ERR);
EXPECT_EQ("XX", ir->getInstruction(3)->name());
EXPECT_EQ(bits01, ir->getInstruction(3)->bits());
EXPECT_NEAR(M_PI/4.0,
xacc::InstructionParameterToDouble(ir->getInstruction(3)->getParameter(0)),
ERR);
EXPECT_EQ("Ry", ir->getInstruction(4)->name());
EXPECT_EQ(bits0, ir->getInstruction(4)->bits());
EXPECT_NEAR(M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(4)->getParameter(0)),
ERR);
EXPECT_EQ("Rz", ir->getInstruction(5)->name());
EXPECT_EQ(bits0, ir->getInstruction(5)->bits());
EXPECT_NEAR(M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(5)->getParameter(0)),
ERR);
EXPECT_EQ("Rx", ir->getInstruction(6)->name());
EXPECT_EQ(bits1, ir->getInstruction(6)->bits());
EXPECT_NEAR(M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(6)->getParameter(0)),
ERR);
EXPECT_EQ("Measure", ir->getInstruction(7)->name());
EXPECT_EQ(bits0, ir->getInstruction(7)->bits());
EXPECT_EQ("Measure", ir->getInstruction(8)->name());
EXPECT_EQ(bits1, ir->getInstruction(8)->bits());
}
TEST(IonTrapTwoQubitPassTester, twoQubitPassDecomposesCZ)
{
auto c = xacc::getService<xacc::Compiler>("xasm");
auto ir = c->compile(R"(__qpu__ void my_cz(qbit q) {
CZ(q[1],q[0]);
})")->getComposites()[0];
auto twoQubitPass = xacc::getService<xacc::IRTransformation>("iontrap-2q-pass");
xacc::quantum::IonTrapMSPhaseMap msPhases({{{0, 1}, {0.0, 0.0}}});
twoQubitPass->apply(ir, nullptr, {{"ms-phases", &msPhases}});
std::vector<std::size_t> bits0({0});
std::vector<std::size_t> bits1({1});
std::vector<std::size_t> bits10({1,0});
EXPECT_EQ(7, ir->nInstructions());
EXPECT_EQ("H", ir->getInstruction(0)->name());
EXPECT_EQ(bits0, ir->getInstruction(0)->bits());
EXPECT_EQ("Ry", ir->getInstruction(1)->name());
EXPECT_EQ(bits1, ir->getInstruction(1)->bits());
EXPECT_NEAR(-M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(1)->getParameter(0)),
ERR);
EXPECT_EQ("XX", ir->getInstruction(2)->name());
EXPECT_EQ(bits10, ir->getInstruction(2)->bits());
EXPECT_NEAR(M_PI/4.0,
xacc::InstructionParameterToDouble(ir->getInstruction(2)->getParameter(0)),
ERR);
EXPECT_EQ("Ry", ir->getInstruction(3)->name());
EXPECT_EQ(bits1, ir->getInstruction(3)->bits());
EXPECT_NEAR(M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(3)->getParameter(0)),
ERR);
EXPECT_EQ("Rz", ir->getInstruction(4)->name());
EXPECT_EQ(bits1, ir->getInstruction(4)->bits());
EXPECT_NEAR(M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(4)->getParameter(0)),
ERR);
EXPECT_EQ("Rx", ir->getInstruction(5)->name());
EXPECT_EQ(bits0, ir->getInstruction(5)->bits());
EXPECT_NEAR(M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(5)->getParameter(0)),
ERR);
EXPECT_EQ("H", ir->getInstruction(6)->name());
EXPECT_EQ(bits0, ir->getInstruction(6)->bits());
}
TEST(IonTrapTwoQubitPassTester, twoQubitPassDecomposesSwap)
{
auto c = xacc::getService<xacc::Compiler>("xasm");
auto ir = c->compile(R"(__qpu__ void my_swap(qbit q) {
Swap(q[0],q[1]);
})")->getComposites()[0];
auto twoQubitPass = xacc::getService<xacc::IRTransformation>("iontrap-2q-pass");
xacc::quantum::IonTrapMSPhaseMap msPhases({{{0, 1}, {0.0, 0.0}}});
twoQubitPass->apply(ir, nullptr, {{"ms-phases", &msPhases}});
std::vector<std::size_t> bits0({0});
std::vector<std::size_t> bits1({1});
std::vector<std::size_t> bits01({0,1});
std::vector<std::size_t> bits10({1,0});
EXPECT_EQ(15, ir->nInstructions());
// CNOT 0,1
EXPECT_EQ("Ry", ir->getInstruction(0)->name());
EXPECT_EQ(bits0, ir->getInstruction(0)->bits());
EXPECT_NEAR(-M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(0)->getParameter(0)),
ERR);
EXPECT_EQ("XX", ir->getInstruction(1)->name());
EXPECT_EQ(bits01, ir->getInstruction(1)->bits());
EXPECT_NEAR(M_PI/4.0,
xacc::InstructionParameterToDouble(ir->getInstruction(1)->getParameter(0)),
ERR);
EXPECT_EQ("Ry", ir->getInstruction(2)->name());
EXPECT_EQ(bits0, ir->getInstruction(2)->bits());
EXPECT_NEAR(M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(2)->getParameter(0)),
ERR);
EXPECT_EQ("Rz", ir->getInstruction(3)->name());
EXPECT_EQ(bits0, ir->getInstruction(3)->bits());
EXPECT_NEAR(M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(3)->getParameter(0)),
ERR);
EXPECT_EQ("Rx", ir->getInstruction(4)->name());
EXPECT_EQ(bits1, ir->getInstruction(4)->bits());
EXPECT_NEAR(M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(4)->getParameter(0)),
ERR);
// CNOT 1,0
EXPECT_EQ("Ry", ir->getInstruction(5)->name());
EXPECT_EQ(bits1, ir->getInstruction(5)->bits());
EXPECT_NEAR(-M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(5)->getParameter(0)),
ERR);
EXPECT_EQ("XX", ir->getInstruction(6)->name());
EXPECT_EQ(bits10, ir->getInstruction(6)->bits());
EXPECT_NEAR(M_PI/4.0,
xacc::InstructionParameterToDouble(ir->getInstruction(6)->getParameter(0)),
ERR);
EXPECT_EQ("Ry", ir->getInstruction(7)->name());
EXPECT_EQ(bits1, ir->getInstruction(7)->bits());
EXPECT_NEAR(M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(7)->getParameter(0)),
ERR);
EXPECT_EQ("Rz", ir->getInstruction(8)->name());
EXPECT_EQ(bits1, ir->getInstruction(8)->bits());
EXPECT_NEAR(M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(8)->getParameter(0)),
ERR);
EXPECT_EQ("Rx", ir->getInstruction(9)->name());
EXPECT_EQ(bits0, ir->getInstruction(9)->bits());
EXPECT_NEAR(M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(9)->getParameter(0)),
ERR);
// CNOT 0,1
EXPECT_EQ("Ry", ir->getInstruction(10)->name());
EXPECT_EQ(bits0, ir->getInstruction(10)->bits());
EXPECT_NEAR(-M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(10)->getParameter(0)),
ERR);
EXPECT_EQ("XX", ir->getInstruction(11)->name());
EXPECT_EQ(bits01, ir->getInstruction(11)->bits());
EXPECT_NEAR(M_PI/4.0,
xacc::InstructionParameterToDouble(ir->getInstruction(11)->getParameter(0)),
ERR);
EXPECT_EQ("Ry", ir->getInstruction(12)->name());
EXPECT_EQ(bits0, ir->getInstruction(12)->bits());
EXPECT_NEAR(M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(12)->getParameter(0)),
ERR);
EXPECT_EQ("Rz", ir->getInstruction(13)->name());
EXPECT_EQ(bits0, ir->getInstruction(13)->bits());
EXPECT_NEAR(M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(13)->getParameter(0)),
ERR);
EXPECT_EQ("Rx", ir->getInstruction(14)->name());
EXPECT_EQ(bits1, ir->getInstruction(14)->bits());
EXPECT_NEAR(M_PI/2.0,
xacc::InstructionParameterToDouble(ir->getInstruction(14)->getParameter(0)),
ERR);
}
int main(int argc, char **argv) {
xacc::Initialize();
::testing::InitGoogleTest(&argc, argv);
const auto result = RUN_ALL_TESTS();
xacc::Finalize();
return result;
}
/*******************************************************************************
* Copyright (c) 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:
* Austin Adams - initial API and implementation
*******************************************************************************/
#include "InstructionIterator.hpp"
#include "IonTrapPassesCommon.hpp"
namespace xacc {
namespace quantum {
// Yoinked from MergeSingleQubitGatesOptimizer, except does not clone()
// instructions
void iontrapFlattenComposite(std::shared_ptr<CompositeInstruction> composite) {
std::vector<xacc::InstPtr> flatten;
InstructionIterator iter(composite);
while (iter.hasNext()) {
auto inst = iter.next();
if (!inst->isComposite()) {
// Previously, inst was clone()d here
flatten.emplace_back(inst);
}
}
composite->clear();
composite->addInstructions(flatten);
}
}
}
/*******************************************************************************
* Copyright (c) 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:
* Austin Adams - initial API and implementation
*******************************************************************************/
#ifndef QUANTUM_ACCELERATORS_IONTRAPPASSESCOMMON_HPP_
#define QUANTUM_ACCELERATORS_IONTRAPPASSESCOMMON_HPP_
#include "CompositeInstruction.hpp"
namespace xacc {
namespace quantum {
typedef std::function<void(std::vector<InstPtr>, std::vector<InstPtr>)> IonTrapLogTransformCallback;
void iontrapFlattenComposite(std::shared_ptr<CompositeInstruction> composite);
}
}
#endif
/*******************************************************************************
* Copyright (c) 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:
* Alexander J. McCaskey - initial API and implementation
* Austin Adams - adapted for GTRI testbed
*******************************************************************************/
#include "xacc.hpp"
#include "xacc_service.hpp"
#include "IonTrapTwoQubitPass.hpp"
#include "Accelerator.hpp"
namespace xacc {
namespace quantum {
//
// Two-qubit decompositions
//
std::pair<double, double> IonTrapTwoQubitPass::findMSPhases(IonTrapMSPhaseMap *msPhases, InstPtr 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]);
auto idxPair = std::make_pair(leftIdx, rightIdx);
if (!msPhases->count(idxPair)) {
xacc::error("pair " + std::to_string(leftIdx) + "," + std::to_string(rightIdx)
+ " missing from set of MS phases");
}
auto phasePair = (*msPhases)[idxPair];
double controlMSPhase = (leftIdx == cnot->bits()[0])? phasePair.first : phasePair.second;
double targetMSPhase = (rightIdx == cnot->bits()[1])? phasePair.second : phasePair.first;
return std::make_pair(controlMSPhase, targetMSPhase);
}
void IonTrapTwoQubitPass::apply(std::shared_ptr<CompositeInstruction> program,
const std::shared_ptr<Accelerator> accelerator,
const HeterogeneousMap &options) {
if (!options.keyExists<IonTrapMSPhaseMap*>("ms-phases")) {
xacc::error("IonTrapTwoQubitPass requires the ms-phases option");
return;
}
IonTrapMSPhaseMap *msPhases = options.get<IonTrapMSPhaseMap*>("ms-phases");
IonTrapLogTransformCallback logTransCallback = nullptr;
if (options.keyExists<IonTrapLogTransformCallback>("log-trans-cb")) {
logTransCallback = options.get<IonTrapLogTransformCallback>("log-trans-cb");
}
auto gateRegistry = xacc::getService<IRProvider>("quantum");