Commit debdfbe9 authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

Adding CPhase gate, implementing QFT lambda

parent 83737268
......@@ -146,6 +146,13 @@ public:
+ ") " + std::to_string(rz.bits()[0]) + "\n";
}
void visit(CPhase& cp) {
auto angleStr = boost::lexical_cast<std::string>(cp.getParameter(0));
quilStr += "CPHASE("
+ angleStr
+ ") " + std::to_string(cp.bits()[0]) + " " + std::to_string(cp.bits()[1]) + "\n";
}
void visit(GateFunction& f) {
return;
}
......
......@@ -34,6 +34,7 @@
#include <memory>
#include <boost/test/included/unit_test.hpp>
#include "RigettiAccelerator.hpp"
#include "JsonVisitor.hpp"
using namespace xacc::quantum;
......@@ -121,3 +122,142 @@ BOOST_AUTO_TEST_CASE(checkKernelExecution) {
BOOST_VERIFY(client->postOccured);
}
BOOST_AUTO_TEST_CASE(buildQFT) {
std::function<std::vector<std::shared_ptr<Instruction>>(std::vector<int>&)> coreqft;
coreqft =
[&](std::vector<int>& qubits) -> std::vector<std::shared_ptr<Instruction>> {
// Get the first qubit
auto q = qubits[0];
// If we have only one left, then
// just return a hadamard, if not,
// then we need to build up some cphase gates
if (qubits.size() == 1) {
auto hadamard = GateInstructionRegistry::instance()->create("H", std::vector<int> {q});
return std::vector<std::shared_ptr<Instruction>>{hadamard};
} else {
// Get the 1 the N qubits
std::vector<int> qs(qubits.begin()+1, qubits.end());
// Compute the number of qubits
auto n = 1 + qs.size();
// Build up a list of cphase gates
std::vector<std::shared_ptr<GateInstruction>> cphaseGates;
int idx = 0;
for (int i = n-1; i > 0; --i) {
auto q_idx = qs[idx];
auto angle = 3.1415926 / std::pow(2, n - i);
InstructionParameter p(angle);
auto cp = GateInstructionRegistry::instance()->create("CPhase", std::vector<int> {q, q_idx});
cp->setParameter(0, p);
cphaseGates.push_back(cp);
idx++;
}
// Recursively build these up...
auto insts = coreqft(qs);
// Reverse the cphase gates
std::reverse(cphaseGates.begin(), cphaseGates.end());
// Add them to the return list
for (auto cp : cphaseGates) {
insts.push_back(cp);
}
// add a final hadamard...
insts.push_back(GateInstructionRegistry::instance()->create("H", std::vector<int> {q}));
// and return
return insts;
}
};
std::vector<int> qbits {0, 1, 2};
auto qftInstructions = coreqft(qbits);
auto qftKernel = std::make_shared<GateFunction>("foo");
for (auto i : qftInstructions) {
qftKernel->addInstruction(i);
}
JsonVisitor v(qftKernel);
std::cout << v.write() << "\n";
std::string expectedQuil(
"H 2\n"
"CPHASE(1.5708) 1 2\n"
"H 1\n"
"CPHASE(0.785398) 0 2\n"
"CPHASE(1.5708) 0 1\n"
"H 0\n");
auto quilV = std::make_shared<QuilVisitor>();
InstructionIterator it(qftKernel);
while (it.hasNext()) {
// Get the next node in the tree
auto nextInst = it.next();
// If enabled, invoke the accept
// method which kicks off the visitor
// to execute the appropriate lambda.
if (nextInst->isEnabled()) {
nextInst->accept(quilV);
}
}
BOOST_VERIFY(quilV->getQuilString() == expectedQuil);
expectedQuil =
"H 4\n"
"CPHASE(1.5708) 3 4\n"
"H 3\n"
"CPHASE(0.785398) 2 4\n"
"CPHASE(1.5708) 2 3\n"
"H 2\n"
"CPHASE(0.392699) 1 4\n"
"CPHASE(0.785398) 1 3\n"
"CPHASE(1.5708) 1 2\n"
"H 1\n"
"CPHASE(0.19635) 0 4\n"
"CPHASE(0.392699) 0 3\n"
"CPHASE(0.785398) 0 2\n"
"CPHASE(1.57078) 0 1\n"
"H 0\n";
std::vector<int> qbits5 {0, 1, 2, 3, 4};
auto qft5Instructions = coreqft(qbits5);
auto qft5Kernel = std::make_shared<GateFunction>("foo");
for (auto i : qft5Instructions) {
qft5Kernel->addInstruction(i);
}
JsonVisitor v5(qft5Kernel);
std::cout << v5.write() << "\n";
auto quilV5 = std::make_shared<QuilVisitor>();
InstructionIterator it5(qft5Kernel);
while (it5.hasNext()) {
// Get the next node in the tree
auto nextInst = it5.next();
// If enabled, invoke the accept
// method which kicks off the visitor
// to execute the appropriate lambda.
if (nextInst->isEnabled()) {
nextInst->accept(quilV5);
}
}
std::cout << quilV5->getQuilString() << "\n" << expectedQuil << "\n";
BOOST_VERIFY(quilV5->getQuilString() == expectedQuil);
}
......@@ -56,7 +56,7 @@ void SimpleAccelerator::execute(std::shared_ptr<AcceleratorBuffer> buffer,
if (!qubits) {
XACCError("Invalid derived AcceleratorBuffer passed to "
"SimpleAccelerator. Must be of type SimulatedQubits<10>.");
"SimpleAccelerator. Must be of type SimulatedQubits.");
}
// Create a lambda for each type of gate we may encounter,
......@@ -319,51 +319,54 @@ void SimpleAccelerator::execute(std::shared_ptr<AcceleratorBuffer> buffer,
qubits->applyUnitary(localU);
};
// auto cphase = [&] (Rz& rZGate) {
// const std::complex<double> i(0, 1);
// double angle = boost::get<double>(rZGate.getParameter(0));
// auto matElement = std::exp(i * angle);
// ComplexTensor rz(2,2), I(2,2);
// I.setValues( { {1, 0}, {0, 1}});
// rz.setValues( { {1, 0}, {0, matElement}});
// auto actingQubits = rZGate.bits();
// ProductList productList;
// for (int j = 0; j < qubits->size(); j++) {
// productList.push_back(I);
// }
// // If this is a one qubit gate, just replace
// // the currect I in the list with the gate
// productList.at(actingQubits[0]) = rz;
// // Create a total unitary for this layer of the circuit
// ComplexTensor localU = productList.at(0);
// for (int j = 1; j < productList.size(); j++) {
// localU = localU.kronProd(productList.at(j));
// }
// qubits->applyUnitary(localU);
// };
auto cphase = [&] (CPhase& cpGate) {
const std::complex<double> i(0, 1);
double angle = boost::get<double>(cpGate.getParameter(0));
auto matElement = std::exp(i * angle);
ComplexTensor rz(2,2), I(2,2);
I.setValues( { {1, 0}, {0, 1}});
rz.setValues( { {1, 0}, {0, matElement}});
auto actingQubits = cpGate.bits();
ProductList productList;
for (int j = 0; j < qubits->size(); j++) {
productList.push_back(I);
}
// If this is a one qubit gate, just replace
// the currect I in the list with the gate
productList.at(actingQubits[0]) = rz;
// Create a total unitary for this layer of the circuit
ComplexTensor localU = productList.at(0);
for (int j = 1; j < productList.size(); j++) {
localU = localU.kronProd(productList.at(j));
}
qubits->applyUnitary(localU);
};
// Create a Visitor that will execute our lambdas when
// we encounter one
auto visitor = std::make_shared<FunctionalGateInstructionVisitor>(hadamard,
cnot, x, y, z, rx, ry, rz, measure, cond);
cnot, x, y, z, rx, ry, rz, measure, cond, cphase);
XACCInfo("Execution Simple Accelerator Simulation.");
// Our QIR is really a tree structure
// so create a pre-order tree traversal
// InstructionIterator to walk it
InstructionIterator it(kernel);
while (it.hasNext()) {
// Get the next node in the tree
auto nextInst = it.next();
// If enabled, invoke the accept
// method which kicks off the visitor
// to execute the appropriate lambda.
if (nextInst->isEnabled()) {
nextInst->accept(visitor);
// Our QIR is really a tree structure
// so create a pre-order tree traversal
// InstructionIterator to walk it
InstructionIterator it(kernel);
while (it.hasNext()) {
// Get the next node in the tree
auto nextInst = it.next();
// If enabled, invoke the accept
// method which kicks off the visitor
// to execute the appropriate lambda.
if (nextInst->isEnabled()) {
nextInst->accept(visitor);
}
}
}
// qubits->getAcceleratorBitState()
}
}
......
/***********************************************************************************
* Copyright (c) 2017, UT-Battelle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the xacc nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* Initial API and implementation - Alex McCaskey
*
**********************************************************************************/
#include "CPhase.hpp"
namespace xacc {
namespace quantum {
CPhase::CPhase(int controlQubit, int targetQubit, double theta) :
GateInstruction("CPhase", std::vector<int> { controlQubit, targetQubit },
std::vector<InstructionParameter> { InstructionParameter(theta) }) {
}
CPhase::CPhase(std::vector<int> qbits) :
GateInstruction("CPhase", qbits, std::vector<InstructionParameter> {
InstructionParameter(0.0) }) {
}
RegisterGateInstruction<CPhase> CPHASETEMP("CPhase");
}
}
/***********************************************************************************
* Copyright (c) 2017, UT-Battelle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the xacc nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* Initial API and implementation - Alex McCaskey
*
**********************************************************************************/
#ifndef QUANTUM_GATE_GATEQIR_INSTRUCTIONS_CPHASE_HPP_
#define QUANTUM_GATE_GATEQIR_INSTRUCTIONS_CPHASE_HPP_
#include "GateInstruction.hpp"
namespace xacc {
namespace quantum {
class CPhase: public virtual GateInstruction {
public:
CPhase(std::vector<int> qbits);
CPhase(int controlQubit, int targetQubit, double theta);
DEFINE_VISITABLE()
};
}
}
#endif
/***********************************************************************************
* Copyright (c) 2016, UT-Battelle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the xacc nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* Initial API and implementation - Alex McCaskey
*
**********************************************************************************/
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE CPhaseTester
#include <boost/test/included/unit_test.hpp>
#include "CPhase.hpp"
using namespace xacc::quantum;
BOOST_AUTO_TEST_CASE(checkCreation) {
CPhase cp(0, 1, 3.14);
BOOST_VERIFY(boost::get<double>(cp.getParameter(0)) == 3.14);
BOOST_VERIFY(cp.toString("qreg") == "CPhase(3.14) qreg0 qreg1");
BOOST_VERIFY(cp.bits().size() == 2);
BOOST_VERIFY(cp.bits()[0] == 0);
BOOST_VERIFY(cp.bits()[1] == 1);
BOOST_VERIFY(cp.getName() == "CPhase");
CPhase cp2(44, 45, 1.71234);
BOOST_VERIFY(boost::get<double>(cp2.getParameter(0)) == 1.71234);
BOOST_VERIFY(cp2.toString("qreg") == "CPhase(1.71234) qreg44 qreg45");
BOOST_VERIFY(cp2.bits().size() == 2);
BOOST_VERIFY(cp2.bits()[0] == 44);
BOOST_VERIFY(cp2.bits()[1] == 45);
BOOST_VERIFY(cp2.getName() == "CPhase");
}
BOOST_AUTO_TEST_CASE(checkAutoRegistration) {
xacc::InstructionParameter p = 3.1415;
auto cp = GateInstructionRegistry::instance()->create("CPhase", std::vector<int>{0, 1});
cp->setParameter(0, p);
BOOST_VERIFY(cp->getName() == "CPhase");
BOOST_VERIFY(boost::get<double>(cp->getParameter(0)) == 3.1415);
}
......@@ -41,6 +41,7 @@
#include "Rz.hpp"
#include "Rx.hpp"
#include "Ry.hpp"
#include "CPhase.hpp"
#include "Measure.hpp"
namespace xacc {
......@@ -61,6 +62,7 @@ class AllGateVisitor:
public InstructionVisitor<X>,
public InstructionVisitor<Y>,
public InstructionVisitor<Z>,
public InstructionVisitor<CPhase>,
public InstructionVisitor<Measure> {
};
......
......@@ -50,13 +50,14 @@ protected:
std::function<void(Rx&)> rxAction;
std::function<void(Ry&)> ryAction;
std::function<void(Rz&)> rzAction;
std::function<void(CPhase&)> cpAction;
public:
template<typename HF, typename CNF, typename XF, typename YF, typename ZF,
typename RXF, typename RYF, typename RZF, typename MF, typename CF>
FunctionalGateInstructionVisitor(HF h, CNF cn, XF x, YF y, ZF z, RXF rx, RYF ry, RZF rz, MF m, CF c) :
typename RXF, typename RYF, typename RZF, typename MF, typename CF, typename CPF>
FunctionalGateInstructionVisitor(HF h, CNF cn, XF x, YF y, ZF z, RXF rx, RYF ry, RZF rz, MF m, CF c, CPF cp) :
hAction(h), cnotAction(cn), xAction(x), yAction(y), zAction(z), measureAction(
m), condAction(c), rxAction(rx), ryAction(ry), rzAction(rz) {
m), condAction(c), rxAction(rx), ryAction(ry), rzAction(rz), cpAction(cp) {
}
void visit(Hadamard& h) {
......@@ -90,6 +91,10 @@ public:
ryAction(ry);
}
void visit(CPhase& cp) {
cpAction(cp);
}
void visit(Rz& rz) {
rzAction(rz);
}
......
......@@ -184,6 +184,20 @@ public:
writer->EndObject();
}
void visit(CPhase& cp) {
baseGateInst(dynamic_cast<GateInstruction&>(cp), false);
writer->String("angle");
auto p = cp.getParameter(0);
switch(p.which()) {
case 0: writer->Int(boost::get<int>(p));break;
case 1: writer->Double(boost::get<double>(p));break;
case 2: writer->Double((double)boost::get<float>(p));break;
case 3: writer->String(boost::get<std::string>(p));break;
}
writer->EndObject();
}
void visit(ConditionalFunction& cn) {
writer->StartObject();
writer->String("conditional_function");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment