Commit e22bc7eb authored by Nguyen, Thien Minh's avatar Nguyen, Thien Minh
Browse files

Added circuit construction and optimizer


Signed-off-by: Nguyen, Thien Minh's avatarThien Nguyen <nguyentm@ornl.gov>
parent 9b5f2d04
......@@ -13,8 +13,10 @@
#include "qaoa.hpp"
#include "xacc.hpp"
#include "xacc_service.hpp"
#include "xacc_observable.hpp"
#include "Circuit.hpp"
#include <cassert>
#include <iomanip>
namespace xacc {
namespace algorithm {
......@@ -65,16 +67,17 @@ bool QAOA::initialize(const HeterogeneousMap& parameters)
initializeOk = false;
}
// (7) Reference Hamiltonian
if (!parameters.keyExists<std::vector<std::string>>("ref-ham"))
// (7) Reference Hamiltonian: optional.
// Default is X0 + X1 + ...
// i.e. the X-basis where |+>|+>... is the ground state.
m_refHam.clear();
if (parameters.keyExists<std::vector<std::string>>("ref-ham"))
{
std::cout << "'ref-ham' is required.\n";
initializeOk = false;
m_refHam = parameters.get<std::vector<std::string>>("ref-ham");
}
if (initializeOk)
{
m_refHam = parameters.get<std::vector<std::string>>("ref-ham");
m_costHam = parameters.get<std::vector<std::string>>("cost-ham");
m_qpu = parameters.getPointerLike<Accelerator>("accelerator");
m_optimizer = parameters.getPointerLike<Optimizer>("optimizer");
......@@ -101,24 +104,33 @@ std::shared_ptr<CompositeInstruction> QAOA::constructParameterizedKernel(const s
}
// Trotter layers (parameterized): mixing b/w cost and drive (reference) Hamiltonian
auto expCirc = std::dynamic_pointer_cast<xacc::quantum::Circuit>(xacc::getService<Instruction>("exp_i_theta"));
int betaParamCounter = 0;
int gammaParamCounter = 0;
for (size_t i = 0; i < m_nbSteps; ++i)
{
for (const auto& term : m_costHam)
{
auto expCirc = std::dynamic_pointer_cast<xacc::quantum::Circuit>(xacc::getService<Instruction>("exp_i_theta"));
const std::string paramName = "gamma" + std::to_string(gammaParamCounter++);
expCirc->addVariable(paramName);
expCirc->expand({ std::make_pair("pauli", term) });
std::cout << "Term: '" << term << "': \n" << expCirc->toString() << "\n";
qaoaKernel->addVariable(paramName);
qaoaKernel->addInstructions(expCirc->getInstructions());
}
// Beta params:
for (const auto& term : m_refHam)
{
auto expCirc = std::dynamic_pointer_cast<xacc::quantum::Circuit>(xacc::getService<Instruction>("exp_i_theta"));
const std::string paramName = "beta" + std::to_string(betaParamCounter++);
expCirc->addVariable(paramName);
expCirc->expand({ std::make_pair("pauli", term) });
std::cout << "Term: '" << term << "': \n" << expCirc->toString() << "\n";
qaoaKernel->addVariable(paramName);
qaoaKernel->addInstructions(expCirc->getInstructions());
}
// TODO: add the instructions from exponential circuits to the kernel:
// need to re-map the variables to make sure we capture all parameters.
}
return qaoaKernel;
......@@ -129,6 +141,93 @@ void QAOA::execute(const std::shared_ptr<AcceleratorBuffer> buffer) const
const int nbQubits = buffer->size();
auto kernel = constructParameterizedKernel(buffer);
std::cout << "Kernel: \n" << kernel->toString() << "\n\n";
// Construct the cost Hamiltonian Observable:
std::string obsString;
for (const auto& term : m_costHam)
{
obsString.append(" + " + term);
}
// Observe the cost Hamiltonian:
auto costObs = xacc::quantum::getObservable("pauli", obsString);
auto kernels = costObs->observe(kernel);
// Construct the optimizer/minimizer:
OptFunction f(
[&, this](const std::vector<double>& x, std::vector<double>& dx) {
std::vector<double> coefficients;
std::vector<std::string> kernelNames;
std::vector<std::shared_ptr<CompositeInstruction>> fsToExec;
double identityCoeff = 0.0;
for (auto &f : kernels)
{
kernelNames.push_back(f->name());
std::complex<double> coeff = f->getCoefficient();
int nFunctionInstructions = 0;
if (f->getInstruction(0)->isComposite())
{
nFunctionInstructions = kernel->nInstructions() + f->nInstructions() - 1;
}
else
{
nFunctionInstructions = f->nInstructions();
}
if (nFunctionInstructions > kernel->nInstructions())
{
auto evaled = f->operator()(x);
fsToExec.push_back(evaled);
coefficients.push_back(std::real(coeff));
}
else
{
identityCoeff += std::real(coeff);
}
}
auto tmpBuffer = xacc::qalloc(buffer->size());
m_qpu->execute(tmpBuffer, fsToExec);
auto buffers = tmpBuffer->getChildren();
double energy = identityCoeff;
auto idBuffer = xacc::qalloc(buffer->size());
idBuffer->addExtraInfo("coefficient", identityCoeff);
idBuffer->setName("I");
idBuffer->addExtraInfo("kernel", "I");
idBuffer->addExtraInfo("parameters", x);
idBuffer->addExtraInfo("exp-val-z", 1.0);
buffer->appendChild("I", idBuffer);
for (int i = 0; i < buffers.size(); i++)
{
auto expval = buffers[i]->getExpectationValueZ();
energy += expval * coefficients[i];
buffers[i]->addExtraInfo("coefficient", coefficients[i]);
buffers[i]->addExtraInfo("kernel", fsToExec[i]->name());
buffers[i]->addExtraInfo("exp-val-z", expval);
buffers[i]->addExtraInfo("parameters", x);
buffer->appendChild(fsToExec[i]->name(), buffers[i]);
}
std::stringstream ss;
ss << "E(" << ( !x.empty() ? std::to_string(x[0]) : "");
for (int i = 1; i < x.size(); i++)
ss << "," << x[i];
ss << ") = " << std::setprecision(12) << energy;
std::cout << ss.str() << '\n';
return energy;
},
kernel->nVariables());
auto result = m_optimizer->optimize(f);
buffer->addExtraInfo("opt-val", ExtraInfo(result.first));
buffer->addExtraInfo("opt-params", ExtraInfo(result.second));
}
std::vector<double> QAOA::execute(const std::shared_ptr<AcceleratorBuffer> buffer, const std::vector<double>& x)
......
......@@ -22,10 +22,10 @@ using namespace xacc;
TEST(QAOATester, checkSimple)
{
auto acc = xacc::getAccelerator("qpp");
auto buffer = xacc::qalloc(2);
auto buffer = xacc::qalloc(6);
const std::vector<std::string> costHam { "Z0 Z1" };
const std::vector<std::string> refHam { "X0 X1" };
const std::vector<std::string> costHam { "Z0 Z1", "Z3", "Z4 Z5" };
const std::vector<std::string> refHam { "X0" };
auto optimizer = xacc::getOptimizer("nlopt");
auto qaoa = xacc::getService<Algorithm>("QAOA");
......@@ -34,7 +34,9 @@ TEST(QAOATester, checkSimple)
std::make_pair("accelerator", acc),
std::make_pair("optimizer", optimizer),
std::make_pair("cost-ham", costHam),
std::make_pair("ref-ham", refHam)
std::make_pair("ref-ham", refHam),
// number of time steps (p) param
std::make_pair("steps", 1)
}));
qaoa->execute(buffer);
}
......
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