Commit 9635c152 authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

integrating staq rotation_folding with IRTransformation


Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent f1703607
......@@ -12,7 +12,7 @@
# *******************************************************************************/
set(LIBRARY_NAME xacc-staq-compiler)
file(GLOB SRC
compiler/*.cpp *.cpp)
compiler/*.cpp *.cpp optimizers/*.cpp utils/*.cpp)
usfunctiongetresourcesource(TARGET ${LIBRARY_NAME} OUT SRC)
usfunctiongeneratebundleinit(TARGET ${LIBRARY_NAME} OUT SRC)
......@@ -20,10 +20,10 @@ usfunctiongeneratebundleinit(TARGET ${LIBRARY_NAME} OUT SRC)
add_library(${LIBRARY_NAME} SHARED ${SRC})
target_include_directories(${LIBRARY_NAME}
PUBLIC compiler ${STAQ_DIR}/include ${STAQ_DIR}/libs)
PUBLIC compiler utils optimizers ${STAQ_DIR}/include ${STAQ_DIR}/libs)
target_link_libraries(${LIBRARY_NAME}
PUBLIC xacc
PUBLIC xacc xacc-quantum-gate
)
target_compile_features(xacc-staq-compiler
......@@ -57,6 +57,7 @@ endif()
if(XACC_BUILD_TESTS)
add_subdirectory(compiler/tests)
add_subdirectory(optimizers/tests)
endif()
install(TARGETS ${LIBRARY_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/plugins)
......@@ -12,15 +12,14 @@
*******************************************************************************/
#include "staq_compiler.hpp"
#include "ast/decl.hpp"
#include "xacc.hpp"
#include "xacc_service.hpp"
#include "InstructionIterator.hpp"
#include "AcceleratorBuffer.hpp"
#include "parser/parser.hpp"
#include "ast/traversal.hpp"
#include "staq_visitors.hpp"
#include "transformations/desugar.hpp"
#include "transformations/inline.hpp"
#include "transformations/oracle_synthesizer.hpp"
......@@ -29,89 +28,6 @@
using namespace staq::ast;
namespace xacc {
namespace internal_staq {
static const std::map<std::string, std::string> staq_to_xacc{
// "u3", "u2", "u1", "ccx", cu1, cu3
{"cx", "CX"}, {"id", "I"}, {"x", "X"}, {"y", "Y"},
{"z", "Z"}, {"h", "H"}, {"s", "S"}, {"sdg", "Sdg"},
{"t", "T"}, {"tdg", "Tdg"}, {"rx", "Rx"}, {"ry", "Ry"},
{"rz", "Rz"}, {"cz", "CZ"}, {"cy", "CY"}, {"swap", "Swap"},
{"ch", "CH"}, {"crz", "CRZ"}};
class CountQregs : public staq::ast::Traverse {
public:
std::vector<std::string> qregs;
void visit(staq::ast::RegisterDecl &d) override {
if (d.is_quantum()) {
qregs.push_back(d.id());
}
}
};
class CountAncillas : public staq::ast::Traverse {
public:
std::map<std::string, int> ancillas;
void visit(staq::ast::AncillaDecl &d) override {
ancillas.insert({d.id(), d.size()});
}
};
class StaqToXasm : public staq::ast::Visitor {
public:
std::stringstream ss;
void visit(VarAccess &) override {}
// Expressions
void visit(BExpr &) override {}
void visit(UExpr &) override {}
void visit(PiExpr &) override {}
void visit(IntExpr &) override {}
void visit(RealExpr &r) override {}
void visit(VarExpr &v) override {}
void visit(ResetStmt &) override {}
void visit(IfStmt &) override {}
void visit(BarrierGate &) override {}
void visit(GateDecl &) override {}
void visit(OracleDecl &) override {}
void visit(RegisterDecl &) override {}
void visit(AncillaDecl &) override {}
void visit(Program &prog) override {
// Program body
prog.foreach_stmt([this](auto &stmt) { stmt.accept(*this); });
}
void visit(MeasureStmt &m) override {
ss << "Measure(" << m.q_arg().var() << "[" << m.q_arg().offset().value()
<< "]);\n";
}
void visit(UGate &u) override {
ss << "U(" << u.arg().var() << "[" << u.arg().offset().value() << "], " << 0
<< ", " << 0 << ", " << 0 << ");\n";
}
void visit(CNOTGate &cx) override {
ss << "CX(" << cx.ctrl().var() << "[" << cx.ctrl().offset().value() << "],"
<< cx.tgt().var() << "[" << cx.tgt().offset().value() << "]);\n";
}
// void visit(BarrierGate&) = 0;
void visit(DeclaredGate &g) override {
auto xacc_name = staq_to_xacc.at(g.name());
ss << xacc_name << "(" << g.qarg(0).var() << "["
<< g.qarg(0).offset().value() << "]";
for (int i = 1; i < g.num_qargs(); i++) {
ss << ", " << g.qarg(i).var() << "[" << g.qarg(i).offset().value() << "]";
}
if (g.num_cargs() > 0) {
ss << ", " << g.carg(0).constant_eval().value();
for (int i = 1; i < g.num_cargs(); i++) {
ss << ", " << g.carg(i).constant_eval().value() << "\n";
}
}
ss << ");\n";
}
};
} // namespace internal_staq
StaqCompiler::StaqCompiler() {}
......@@ -265,6 +181,35 @@ std::shared_ptr<IR> StaqCompiler::compile(const std::string &src) {
const std::string
StaqCompiler::translate(std::shared_ptr<xacc::CompositeInstruction> function) {
return "";
std::map<std::string,int> bufNamesToSize;
InstructionIterator iter(function);
while(iter.hasNext()) {
auto &next = *iter.next();
if (next.isEnabled()) {
for (int i = 0; i < next.nRequiredBits(); i++) {
auto bufName = next.getBufferName(i);
if (bufNamesToSize.count(bufName)) {
if (bufNamesToSize[bufName] < next.bits()[i]+1) {
bufNamesToSize[bufName] = next.bits()[i]+1;
}
} else {
bufNamesToSize.insert({bufName, next.bits()[i]+1});
}
}
}
}
auto translate = std::make_shared<internal_staq::XACCToStaqOpenQasm>(bufNamesToSize);
InstructionIterator iter2(function);
while(iter2.hasNext()) {
auto &next = *iter2.next();
if (next.isEnabled()) {
next.accept(translate);
}
}
return translate->ss.str();
}
} // namespace xacc
......@@ -49,6 +49,42 @@ TEST(StaqCompilerTester, checkSimple) {
std::cout << "HELLO:\n" << hello->toString() << "\n";
}
TEST(StaqCompilerTester, checkTranslate) {
auto compiler = xacc::getCompiler("staq");
auto IR = compiler->compile(R"(OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];
U(0,0,0) q[0];
CX q[0],q[1];
rx(3.3) q[0];
measure q -> c;
)");
auto hello = IR->getComposites()[0];
std::cout << "HELLO:\n" << hello->toString() << "\n";
std::cout << "TRANSLATED: " << compiler->translate(hello) << "\n";
// auto q = xacc::qalloc(2);
// q->setName("q");
// xacc::storeBuffer(q);
// IR = compiler->compile(R"(__qpu__ void f(qreg q) {
// OPENQASM 2.0;
// include "qelib1.inc";
// creg c[2];
// U(0,0,0) q[0];
// CX q[0],q[1];
// rx(3.3) q[0];
// measure q -> c;
// })");
// hello = IR->getComposites()[0];
// std::cout << "HELLO:\n" << hello->toString() << "\n";
}
TEST(StaqCompilerTester, checkOracle) {
auto a = xacc::qalloc(4);
a->setName("a");
......
/*******************************************************************************
* Copyright (c) 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:
* Alexander J. McCaskey - initial API and implementation
*******************************************************************************/
#include "staq_rotation_folding.hpp"
#include "optimization/simplify.hpp"
#include "xacc_service.hpp"
#include "xacc.hpp"
#include "staq_visitors.hpp"
#include "optimization/rotation_folding.hpp"
namespace xacc {
namespace quantum {
using namespace staq;
using namespace staq::ast;
void RotationFolding::apply(std::shared_ptr<CompositeInstruction> program,
const std::shared_ptr<Accelerator> accelerator,
const HeterogeneousMap &options) {
// map to openqasm
auto staq = xacc::getCompiler("staq");
auto src = staq->translate(program);
// parse that to get staq ast
auto prog = parser::parse_string(src);
// fold rotations
optimization::fold_rotations(*prog);
optimization::simplify(*prog);
// map prog back to staq src string and
// compile to ir
std::stringstream ss;
prog->pretty_print(ss);
auto ir = staq->compile(ss.str());
// reset the program and add optimized instructions
program->clear();
program->addInstructions(ir->getComposites()[0]->getInstructions());
return;
}
} // namespace quantum
} // namespace xacc
\ No newline at end of file
/*******************************************************************************
* Copyright (c) 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:
* Alexander J. McCaskey - initial API and implementation
*******************************************************************************/
#ifndef QUANTUM_GATE_COMPILER_STAQ_ROTATION_FOLDING_HPP_
#define QUANTUM_GATE_COMPILER_STAQ_ROTATION_FOLDING_HPP_
#include "IRTransformation.hpp"
#include "InstructionIterator.hpp"
namespace xacc {
namespace quantum {
class RotationFolding : public IRTransformation {
public:
RotationFolding() {}
void apply(std::shared_ptr<CompositeInstruction> program,
const std::shared_ptr<Accelerator> accelerator,
const HeterogeneousMap& options = {}) override;
const IRTransformationType type() const override {return IRTransformationType::Optimization;}
const std::string name() const override { return "rotation-folding"; }
const std::string description() const override { return ""; }
};
} // namespace quantum
} // namespace xacc
#endif
# *******************************************************************************
# Copyright (c) 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 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
# *******************************************************************************/
add_xacc_test(RotationFolding)
target_link_libraries(RotationFoldingTester xacc )
\ No newline at end of file
/*******************************************************************************
* Copyright (c) 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:
* Alexander J. McCaskey - initial API and implementation
*******************************************************************************/
#include "gtest/gtest.h"
#include "xacc.hpp"
#include "xacc_service.hpp"
TEST(RotationFoldingTester, checkSimple) {
auto irt = xacc::getIRTransformation("rotation-folding");
auto compiler = xacc::getCompiler("xasm");
auto program = compiler->compile(R"(__qpu__ void test_t_t(qreg q) {
T(q[0]);
T(q[0]);
})")->getComposite("test_t_t");
EXPECT_EQ(2, program->nInstructions());
EXPECT_EQ("T", program->getInstruction(0)->name());
EXPECT_EQ("T", program->getInstruction(1)->name());
irt->apply(program, nullptr);
EXPECT_EQ(1, program->nInstructions());
EXPECT_EQ("S", program->getInstruction(0)->name());
program = compiler->compile(R"(__qpu__ void test_t_tdg(qreg q) {
T(q[0]);
Tdg(q[0]);
})")->getComposite("test_t_tdg");
EXPECT_EQ(2, program->nInstructions());
EXPECT_EQ("T", program->getInstruction(0)->name());
EXPECT_EQ("Tdg", program->getInstruction(1)->name());
irt->apply(program, nullptr);
EXPECT_EQ(0, program->nInstructions());
program = compiler->compile(R"(__qpu__ void test_conj_merge(qreg q) {
H(q[0]);
T(q[0]);
H(q[0]);
X(q[0]);
H(q[0]);
T(q[0]);
H(q[0]);
})")->getComposite("test_conj_merge");
irt->apply(program, nullptr);
EXPECT_EQ(4, program->nInstructions());
EXPECT_EQ("X", program->getInstruction(0)->name());
EXPECT_EQ("H", program->getInstruction(1)->name());
EXPECT_EQ("S", program->getInstruction(2)->name());
EXPECT_EQ("H", program->getInstruction(3)->name());
program = compiler->compile(R"(__qpu__ void test_rz_merge(qreg q) {
Rz(q[0],pi/16);
Rz(q[0], pi/16);
})")->getComposite("test_rz_merge");
irt->apply(program, nullptr);
EXPECT_EQ(1, program->nInstructions());
EXPECT_EQ("Rz", program->getInstruction(0)->name());
EXPECT_NEAR(.3927, program->getInstruction(0)->getParameter(0).as<double>(), 1e-3);
program = compiler->compile(R"(__qpu__ void test_cx_merge(qreg q) {
CX(q[0],q[1]);
T(q[1]);
CX(q[0], q[1]);
CX(q[1], q[0]);
T(q[0]);
CX(q[1],q[0]);
})")->getComposite("test_cx_merge");
irt->apply(program, nullptr);
EXPECT_EQ(3, program->nInstructions());
EXPECT_EQ("CNOT", program->getInstruction(0)->name());
EXPECT_EQ(1, program->getInstruction(0)->bits()[0]);
EXPECT_EQ(0, program->getInstruction(0)->bits()[1]);
EXPECT_EQ("S", program->getInstruction(1)->name());
EXPECT_EQ("CNOT", program->getInstruction(2)->name());
EXPECT_EQ(1, program->getInstruction(2)->bits()[0]);
EXPECT_EQ(0, program->getInstruction(2)->bits()[1]);
}
int main(int argc, char **argv) {
xacc::Initialize(argc, argv);
xacc::set_verbose(true);
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
......@@ -11,6 +11,7 @@
* Alexander J. McCaskey - initial API and implementation
*******************************************************************************/
#include "staq_compiler.hpp"
#include "staq_rotation_folding.hpp"
#include "cppmicroservices/BundleActivator.h"
#include "cppmicroservices/BundleContext.h"
......@@ -35,6 +36,9 @@ public:
void Start(BundleContext context) {
auto c = std::make_shared<xacc::StaqCompiler>();
context.RegisterService<xacc::Compiler>(c);
auto c1 = std::make_shared<xacc::quantum::RotationFolding>();
context.RegisterService<xacc::IRTransformation>(c1);
}
/**
......
/*******************************************************************************
* Copyright (c) 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:
* Alexander J. McCaskey - initial API and implementation
*******************************************************************************/
#include "staq_visitors.hpp"
#include "Instruction.hpp"
namespace xacc {
namespace internal_staq {
XACCToStaqOpenQasm::XACCToStaqOpenQasm(std::map<std::string, int> bufNamesToSize) {
ss << "OPENQASM 2.0;\ninclude \"qelib1.inc\";\n";
for (auto &kv : bufNamesToSize) {
ss << "qreg " << kv.first << "[" << kv.second << "];\n";
cregNames.insert({kv.first, kv.first+"_c"});
ss << "creg " << kv.first+"_c" << "[" << kv.second << "];\n";
}
}
void XACCToStaqOpenQasm::visit(Hadamard &h) {
ss << "h " << (h.getBufferNames().empty() ? "q" : h.getBufferName(0))
<< h.bits() << ";\n";
}
void XACCToStaqOpenQasm::visit(CNOT &cx) {
ss << "cx " << (cx.getBufferNames().empty() ? "q" : cx.getBufferName(0))
<< "[" << cx.bits()[0] << "], " << (cx.getBufferNames().empty() ? "q" : cx.getBufferName(1)) << "[" << cx.bits()[1] << "];\n";
}
void XACCToStaqOpenQasm::visit(Rz &rz) {
ss << "rz(" << xacc::InstructionParameterToDouble(rz.getParameter(0)) << ") " << (rz.getBufferNames().empty() ? "q" : rz.getBufferName(0))
<< rz.bits() << ";\n";
}
void XACCToStaqOpenQasm::visit(Ry &ry) {
ss << "ry(" << xacc::InstructionParameterToDouble(ry.getParameter(0)) << ") " << (ry.getBufferNames().empty() ? "q" : ry.getBufferName(0))
<< ry.bits() << ";\n";
}
void XACCToStaqOpenQasm::visit(Rx &rx) {
ss << "rx(" << xacc::InstructionParameterToDouble(rx.getParameter(0)) << ") " << (rx.getBufferNames().empty() ? "q" : rx.getBufferName(0))
<< rx.bits() << ";\n";
}
void XACCToStaqOpenQasm::visit(X &x) {
ss << "x " << (x.getBufferNames().empty() ? "q" : x.getBufferName(0))
<< x.bits() << ";\n";
}
void XACCToStaqOpenQasm::visit(Y &y) {
ss << "y " << (y.getBufferNames().empty() ? "q" : y.getBufferName(0))
<< y.bits() << ";\n";
}
void XACCToStaqOpenQasm::visit(Z &z) {
ss << "z " << (z.getBufferNames().empty() ? "q" : z.getBufferName(0))
<< z.bits() << ";\n";
}
void XACCToStaqOpenQasm::visit(CY &cy) {
ss << "cy " << (cy.getBufferNames().empty() ? "q" : cy.getBufferName(0))
<< "[" << cy.bits()[0] << "], " << (cy.getBufferNames().empty() ? "q" : cy.getBufferName(1)) << "[" << cy.bits()[1] << "];\n";
}
void XACCToStaqOpenQasm::visit(CZ &cz) {
ss << "cz " << (cz.getBufferNames().empty() ? "q" : cz.getBufferName(0))
<< "[" << cz.bits()[0] << "], " << (cz.getBufferNames().empty() ? "q" : cz.getBufferName(1)) << "[" << cz.bits()[1] << "];\n";
}
void XACCToStaqOpenQasm::visit(Swap &s) {
ss << "swap " << (s.getBufferNames().empty() ? "q" : s.getBufferName(0))
<< "[" << s.bits()[0] << "], " << (s.getBufferNames().empty() ? "q" : s.getBufferName(1)) << "[" << s.bits()[1] << "];\n";
}
void XACCToStaqOpenQasm::visit(CRZ &crz) {
ss << "crz(" << xacc::InstructionParameterToDouble(crz.getParameter(0)) << ") " << (crz.getBufferNames().empty() ? "q" : crz.getBufferName(0))
<< "[" << crz.bits()[0] << "], " << (crz.getBufferNames().empty() ? "q" : crz.getBufferName(1)) << "[" << crz.bits()[1] << "];\n";
}
void XACCToStaqOpenQasm::visit(CH &ch) {
ss << "ch " << (ch.getBufferNames().empty() ? "q" : ch.getBufferName(0))
<< "[" << ch.bits()[0] << "], " << (ch.getBufferNames().empty() ? "q" : ch.getBufferName(1)) << "[" << ch.bits()[1] << "];\n";
}
void XACCToStaqOpenQasm::visit(S &s) {
ss << "s " << (s.getBufferNames().empty() ? "q" : s.getBufferName(0))
<< s.bits() << ";\n";
}
void XACCToStaqOpenQasm::visit(Sdg &sdg) {
ss << "sdg " << (sdg.getBufferNames().empty() ? "q" : sdg.getBufferName(0))
<< sdg.bits() << ";\n";
}
void XACCToStaqOpenQasm::visit(T &t) {
ss << "t " << (t.getBufferNames().empty() ? "q" : t.getBufferName(0))
<< t.bits() << ";\n";
}
void XACCToStaqOpenQasm::visit(Tdg &tdg) {
ss << "tdg " << (tdg.getBufferNames().empty() ? "q" : tdg.getBufferName(0))
<< tdg.bits() << ";\n";
}
void XACCToStaqOpenQasm::visit(CPhase &cphase) {
ss << "cu1(" << xacc::InstructionParameterToDouble(cphase.getParameter(0)) << ") " << (cphase.getBufferNames().empty() ? "q" : cphase.getBufferName(0))
<< "[" << cphase.bits()[0] << "], " << (cphase.getBufferNames().empty() ? "q" : cphase.getBufferName(1)) << "[" << cphase.bits()[1] << "];\n";
}
void XACCToStaqOpenQasm::visit(Measure &m) {
ss << "measure " << (m.getBufferNames().empty() ? "q" : m.getBufferName(0)) << m.bits() << " -> " << cregNames[m.getBufferName(0)] << m.bits() << "\n";
}
void XACCToStaqOpenQasm::visit(Identity &i) {}
void XACCToStaqOpenQasm::visit(U &u) {
ss << "u3(" << xacc::InstructionParameterToDouble(u.getParameter(0)) << "," << xacc::InstructionParameterToDouble(u.getParameter(1)) << "," <<xacc::InstructionParameterToDouble(u.getParameter(2)) << ") " << (u.getBufferNames().empty() ? "q" : u.getBufferName(0)) << u.bits() << ";\n";
}
void XACCToStaqOpenQasm::visit(IfStmt &ifStmt) {}
} // namespace internal_staq
} // namespace xacc
\ No newline at end of file
/*******************************************************************************
* Copyright (c) 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:
* Alexander J. McCaskey - initial API and implementation
*******************************************************************************/
#ifndef QUANTUM_GATE_COMPILER_STAQ_VISITORS_HPP_
#define QUANTUM_GATE_COMPILER_STAQ_VISITORS_HPP_
#include "ast/decl.hpp"
#include "parser/parser.hpp"
#include "ast/traversal.hpp"
#include <map>