Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hoist GateFuser to quantum/gate/utils and simplify API #521

Merged
merged 1 commit into from
Mar 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,20 @@ namespace {
}
namespace xacc {
namespace quantum {
void GateFuser::initialize(const std::shared_ptr<xacc::CompositeInstruction>& in_program)
Eigen::MatrixXcd GateFuser::fuseGates(const std::shared_ptr<xacc::CompositeInstruction> &in_program, int in_dim)
{
GateFuser fuser(in_program, in_dim);
fuser.visitGates();
return fuser.calcFusedGate();
}

GateFuser::GateFuser(const std::shared_ptr<xacc::CompositeInstruction> in_program,
int in_dim) : m_program(in_program), m_dim(in_dim) {};

void GateFuser::visitGates()
{
m_gates.clear();
InstructionIterator it(in_program);
InstructionIterator it(m_program);
while (it.hasNext())
{
auto nextInst = it.next();
Expand All @@ -54,12 +64,12 @@ void GateFuser::initialize(const std::shared_ptr<xacc::CompositeInstruction>& in
}
}

Eigen::MatrixXcd GateFuser::calcFusedGate(int in_dim) const
Eigen::MatrixXcd GateFuser::calcFusedGate() const
{
const auto matSize = 1ULL << in_dim;
const auto matSize = 1ULL << m_dim;
Eigen::MatrixXcd resultMat = Eigen::MatrixXcd::Identity(matSize, matSize);
// Qubit index list (0->(dim-1))
std::vector<size_t> index_list(in_dim);
std::vector<size_t> index_list(m_dim);
std::iota(index_list.begin(), index_list.end(), 0);

for (const auto& item : m_gates)
Expand Down Expand Up @@ -277,4 +287,4 @@ void GateFuser::visit(IfStmt& ifStmt)
xacc::error("Unsupported!");
}
} // namespace quantum
} // namespace xacc
} // namespace xacc
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ struct FusionGateItem
class GateFuser : public AllGateVisitor
{
public:
static Eigen::MatrixXcd fuseGates(const std::shared_ptr<xacc::CompositeInstruction> &in_program, int in_dim);

// CTor
GateFuser() {}
void initialize(const std::shared_ptr<xacc::CompositeInstruction>& in_program);
GateFuser(const std::shared_ptr<xacc::CompositeInstruction> in_program, int in_dim);
void visitGates();
// Compute the fused gate matrix given the output dimension
// Note: the dimension must be greater than all the qubit indices in the Composite
Eigen::MatrixXcd calcFusedGate(int in_dim) const;
Eigen::MatrixXcd calcFusedGate() const;
// Gate visitor Impl
void visit(Hadamard& h) override;
void visit(CNOT& cnot) override;
Expand All @@ -50,11 +52,10 @@ class GateFuser : public AllGateVisitor
void visit(Identity& i) override;
void visit(U& u) override;
void visit(IfStmt& ifStmt) override;
// Identifiable Impl
const std::string name() const override { return "default"; }
const std::string description() const override { return ""; }
private:
const std::shared_ptr<xacc::CompositeInstruction> &m_program;
int m_dim;
std::vector<FusionGateItem> m_gates;
};
} // namespace quantum
} // namespace xacc
} // namespace xacc
1 change: 0 additions & 1 deletion quantum/plugins/iontrap/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ target_include_directories(${LIBRARY_NAME}
target_link_libraries(${LIBRARY_NAME}
PUBLIC xacc
xacc-quantum-gate
xacc-circuit-optimizers
)

if(LAPACK_FOUND)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,7 @@ std::size_t IonTrapOneQubitPass::decomposeInPlace(Decomp decomp,
tmpKernel->addInstruction(instrPtr);
}

auto fuser = xacc::getService<xacc::quantum::GateFuser>("default");
fuser->initialize(tmpKernel);
Eigen::Matrix2cd uMat = fuser->calcFusedGate(1);
Eigen::Matrix2cd uMat = GateFuser::fuseGates(tmpKernel, 1);
const arma::cx_mat unitary = arma::cx_mat(uMat.data(), uMat.rows(), uMat.cols());
const std::size_t bitIdx = program->getInstruction(sequence[0])->bits()[0];

Expand Down
2 changes: 0 additions & 2 deletions quantum/plugins/optimizers/OptimizersActivator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#include "default_placement.hpp"
#include "GateMergeOptimizer.hpp"
#include "PulseTransform.hpp"
#include "GateFusion.hpp"
#include "NearestNeighborTransform.hpp"
// #include "qsearch.hpp"
#include "cppmicroservices/BundleActivator.h"
Expand Down Expand Up @@ -49,7 +48,6 @@ class US_ABI_LOCAL OptimizersActivator : public BundleActivator {
context.RegisterService<xacc::IRTransformation>(c5);
context.RegisterService<xacc::IRTransformation>(
std::make_shared<xacc::quantum::PulseTransform>());
context.RegisterService<GateFuser>(std::make_shared<GateFuser>());
context.RegisterService<xacc::IRTransformation>(
std::make_shared<xacc::quantum::MergeSingleQubitGatesOptimizer>());
context.RegisterService<xacc::IRTransformation>(
Expand Down
14 changes: 4 additions & 10 deletions quantum/plugins/optimizers/gate_merge/GateMergeOptimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,7 @@ void MergeSingleQubitGatesOptimizer::apply(std::shared_ptr<CompositeInstruction>
tmpKernel->addInstruction(instrPtr);
}

auto fuser = xacc::getService<xacc::quantum::GateFuser>("default");
fuser->initialize(tmpKernel);
Eigen::Matrix2cd uMat = fuser->calcFusedGate(1);
Eigen::Matrix2cd uMat = GateFuser::fuseGates(tmpKernel, 1);
uMat.transposeInPlace();
Eigen::Vector4cd matAsVec(Eigen::Map<Eigen::Vector4cd>(uMat.data(), uMat.cols()*uMat.rows()));
std::vector<std::complex<double>> flattenedUnitary;
Expand Down Expand Up @@ -290,9 +288,7 @@ void MergeTwoQubitBlockOptimizer::apply(std::shared_ptr<CompositeInstruction> pr
instrPtr->setBits(mapBits(instrPtr->bits()));
tmpKernel->addInstruction(instrPtr);
}
auto fuser = xacc::getService<xacc::quantum::GateFuser>("default");
fuser->initialize(tmpKernel);
Eigen::Matrix4cd uMat = fuser->calcFusedGate(2);
Eigen::Matrix4cd uMat = GateFuser::fuseGates(tmpKernel, 2);
uMat.transposeInPlace();
Eigen::VectorXcd matAsVec(Eigen::Map<Eigen::VectorXcd>(uMat.data(), uMat.cols()*uMat.rows()));
std::vector<std::complex<double>> flattenedUnitary;
Expand All @@ -305,9 +301,7 @@ void MergeTwoQubitBlockOptimizer::apply(std::shared_ptr<CompositeInstruction> pr
assert(expandOk);

const auto calcUopt = [](const std::shared_ptr<CompositeInstruction> composite) {
auto fuser = xacc::getService<xacc::quantum::GateFuser>("default");
fuser->initialize(composite);
return fuser->calcFusedGate(2);
return GateFuser::fuseGates(composite, 2);
};

// Optimized decomposed sequence:
Expand Down Expand Up @@ -442,4 +436,4 @@ std::vector<size_t> MergeTwoQubitBlockOptimizer::findGateSequence(const std::sha
return returnSeq(gateSequence);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1098,11 +1098,8 @@ h q[0];
const auto nbInstAfter = f->nInstructions();
EXPECT_TRUE(nbInstAfter < nbInstBefore);
// Validate using gate fusion:
auto fuser = xacc::getService<xacc::quantum::GateFuser>("default");
fuser->initialize(circuitCopy);
const Eigen::MatrixXcd uMatOriginal = fuser->calcFusedGate(2);
fuser->initialize(f);
const Eigen::MatrixXcd uMatAfter = fuser->calcFusedGate(2);
const Eigen::MatrixXcd uMatOriginal = GateFuser::fuseGates(circuitCopy, 2);
const Eigen::MatrixXcd uMatAfter = GateFuser::fuseGates(f, 2);
std::cout << "Before:\n" << uMatOriginal << "\n";
std::cout << "After:\n" << uMatAfter << "\n";

Expand Down Expand Up @@ -1148,4 +1145,4 @@ int main(int argc, char **argv) {
auto ret = RUN_ALL_TESTS();
xacc::Finalize();
return ret;
}
}
6 changes: 2 additions & 4 deletions quantum/plugins/optimizers/pulse/PulseTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,8 @@ namespace quantum {
const std::string hamJsonStr = buffer->getInformation("ham-json").as<std::string>();

// Step 2: Compute the total unitary matrix
auto fuser = xacc::getService<GateFuser>("default");
fuser->initialize(program);
const int dim = calcSysDimension(program);
const Eigen::MatrixXcd targetUmat = fuser->calcFusedGate(dim);
const Eigen::MatrixXcd targetUmat = GateFuser::fuseGates(program, dim);
std::cout << "\nTarget Unitary matrix: \n" << targetUmat << "\n";

// Step 3: Get the required params
Expand Down Expand Up @@ -288,4 +286,4 @@ namespace quantum {
std::cout << "Transformed Composite: \n" << program->toString() << "\n";
}
}
}
}
22 changes: 6 additions & 16 deletions quantum/plugins/optimizers/pulse/tests/PulseTransformTester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ TEST(PulseTransformTester, checkSimple)
R"(__qpu__ void test0(qbit q) {
H(q[0]);
})")->getComposites()[0];
auto fuser = xacc::getService<GateFuser>("default");
fuser->initialize(program);
auto result = fuser->calcFusedGate(1);
auto result = GateFuser::fuseGates(program, 1);
EXPECT_NEAR(result(0,0).real(), 1.0 / std::sqrt(2.), 1e-12);
EXPECT_NEAR(result(0,1).real(), 1.0 / std::sqrt(2.), 1e-12);
EXPECT_NEAR(result(1,0).real(), 1.0 / std::sqrt(2.), 1e-12);
Expand All @@ -35,9 +33,7 @@ TEST(PulseTransformTester, checkSimple)
Z(q[0]);
H(q[0]);
})")->getComposites()[0];
auto fuser = xacc::getService<GateFuser>("default");
fuser->initialize(program);
auto result = fuser->calcFusedGate(1);
auto result = GateFuser::fuseGates(program, 1);
std::cout << "Result:\n" << result << "\n";
EXPECT_NEAR(result(0,0).real(), 0.0, 1e-12);
EXPECT_NEAR(result(0,1).real(), 1.0, 1e-12);
Expand All @@ -53,9 +49,7 @@ TEST(PulseTransformTester, checkSimple)
H(q[0]);
CNOT(q[0], q[1]);
})")->getComposites()[0];
auto fuser = xacc::getService<GateFuser>("default");
fuser->initialize(program);
auto result = fuser->calcFusedGate(2);
auto result = GateFuser::fuseGates(program, 2);
std::cout << result << "\n";
Eigen::Matrix2cd IdMat = Eigen::Matrix2cd::Identity();
const auto H = []() {
Expand Down Expand Up @@ -98,9 +92,7 @@ TEST(PulseTransformTester, checkSimple)
R"(__qpu__ void test3(qbit q) {
CNOT(q[0], q[2]);
})")->getComposites()[0];
auto fuser = xacc::getService<GateFuser>("default");
fuser->initialize(program);
auto result = fuser->calcFusedGate(3);
auto result = GateFuser::fuseGates(program, 3);
// Expected location (row, column) that has an element 1.0
// Q0 is the control, hence it is a map 1 (001)->5(101), 3 (011) -> 7 (111) and vice versa
std::vector<std::pair<size_t, size_t>> expectedLoc {
Expand All @@ -120,9 +112,7 @@ TEST(PulseTransformTester, checkSimple)
auto qft = std::dynamic_pointer_cast<CompositeInstruction>(tmp);
qft->expand({std::make_pair("nq", 2)});
std::cout << "QFT Circuit: \n" << qft->toString() << "\n";
auto fuser = xacc::getService<GateFuser>("default");
fuser->initialize(qft);
auto result = fuser->calcFusedGate(2);
auto result = GateFuser::fuseGates(qft, 2);
std::cout << "QFT Matrix: \n" << result << "\n";
// Expected matrix
Eigen::MatrixXcd QftMat{ Eigen::MatrixXcd::Zero(4, 4) };
Expand All @@ -145,4 +135,4 @@ int main(int argc, char **argv)
auto ret = RUN_ALL_TESTS();
xacc::Finalize();
return ret;
}
}