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

added observables with xacc updates


Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent 6dd144dc
add_subdirectory(gate)
add_subdirectory(ir_provider)
\ No newline at end of file
add_subdirectory(ir_provider)
add_subdirectory(observable)
\ No newline at end of file
......@@ -45,7 +45,7 @@ public:
// auto qft = std::make_shared<xacc::quantum::QFT>();
// auto iqft = std::make_shared<xacc::quantum::InverseQFT>();
// auto giservice = std::make_shared<xacc::quantum::GateIRProvider>();
// auto giservice = std::make_shared<xacc::InstructionIRProvider>();
// auto opt = std::make_shared<xacc::quantum::CircuitOptimizer>();
......@@ -93,28 +93,28 @@ public:
auto crz= std::make_shared<xacc::quantum::CRZ>();
auto ch = std::make_shared<xacc::quantum::CH>();
context.RegisterService<xacc::quantum::Gate>(h);
context.RegisterService<xacc::quantum::Gate>(cn);
context.RegisterService<xacc::quantum::Gate>(cp);
context.RegisterService<xacc::quantum::Gate>(cz);
context.RegisterService<xacc::quantum::Gate>(id);
context.RegisterService<xacc::quantum::Gate>(m);
context.RegisterService<xacc::quantum::Gate>(rx);
context.RegisterService<xacc::quantum::Gate>(ry);
context.RegisterService<xacc::quantum::Gate>(rz);
context.RegisterService<xacc::quantum::Gate>(x);
context.RegisterService<xacc::quantum::Gate>(y);
context.RegisterService<xacc::quantum::Gate>(z);
context.RegisterService<xacc::quantum::Gate>(sw);
context.RegisterService<xacc::quantum::Gate>(u);
context.RegisterService<xacc::quantum::Gate>(s);
context.RegisterService<xacc::quantum::Gate>(sdg);
context.RegisterService<xacc::quantum::Gate>(t);
context.RegisterService<xacc::quantum::Gate>(tdg);
context.RegisterService<xacc::quantum::Gate>(cy);
context.RegisterService<xacc::quantum::Gate>(crz);
context.RegisterService<xacc::quantum::Gate>(ch);
context.RegisterService<xacc::Instruction>(h);
context.RegisterService<xacc::Instruction>(cn);
context.RegisterService<xacc::Instruction>(cp);
context.RegisterService<xacc::Instruction>(cz);
context.RegisterService<xacc::Instruction>(id);
context.RegisterService<xacc::Instruction>(m);
context.RegisterService<xacc::Instruction>(rx);
context.RegisterService<xacc::Instruction>(ry);
context.RegisterService<xacc::Instruction>(rz);
context.RegisterService<xacc::Instruction>(x);
context.RegisterService<xacc::Instruction>(y);
context.RegisterService<xacc::Instruction>(z);
context.RegisterService<xacc::Instruction>(sw);
context.RegisterService<xacc::Instruction>(u);
context.RegisterService<xacc::Instruction>(s);
context.RegisterService<xacc::Instruction>(sdg);
context.RegisterService<xacc::Instruction>(t);
context.RegisterService<xacc::Instruction>(tdg);
context.RegisterService<xacc::Instruction>(cy);
context.RegisterService<xacc::Instruction>(crz);
context.RegisterService<xacc::Instruction>(ch);
}
......
......@@ -68,6 +68,8 @@ protected:
std::shared_ptr<ExpressionParsingUtil> parsingUtil;
std::complex<double> coefficient = 1.0;
public:
Circuit(const std::string &name)
: circuitName(name),
......@@ -224,6 +226,9 @@ public:
return newF;
}
void setCoefficient(const std::complex<double> c) override {coefficient=c;}
const std::complex<double> getCoefficient() override {return coefficient;}
std::shared_ptr<CompositeInstruction>
operator()(const std::vector<double> &params) override;
......
add_subdirectory(pauli)
add_subdirectory(fermion)
add_subdirectory(transforms)
\ No newline at end of file
set (PACKAGE_NAME "FermionOperator Parser")
set (LIBRARY_NAME xacc-fermion)
file (GLOB_RECURSE HEADERS *.hpp generated/*.hpp)
file (GLOB SRC *.cpp generated/*.cpp)
# Set up dependencies to resources to track changes
usFunctionGetResourceSource(TARGET ${LIBRARY_NAME} OUT SRC)
# Generate bundle initialization code
usFunctionGenerateBundleInit(TARGET ${LIBRARY_NAME} OUT SRC)
add_library(${LIBRARY_NAME} SHARED ${SRC})
target_include_directories(${LIBRARY_NAME}
PUBLIC
.
${CMAKE_SOURCE_DIR}/tpls/antlr/runtime/src
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/generated
${CMAKE_SOURCE_DIR}/tpls/taocpp
#${CMAKE_SOURCE_DIR}/tpls/eigen
${CMAKE_BINARY_DIR})
add_dependencies(${LIBRARY_NAME} antlr4_shared)
set(_bundle_name xacc_fermion)
set_target_properties(${LIBRARY_NAME}
PROPERTIES # This is required for every bundle
COMPILE_DEFINITIONS
US_BUNDLE_NAME=${_bundle_name}
# This is for convenience, used by other CMake
# functions
US_BUNDLE_NAME ${_bundle_name})
# Embed meta-data from a manifest.json file
usFunctionEmbedResources(TARGET
${LIBRARY_NAME}
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
FILES
manifest.json)
if(APPLE)
target_link_libraries(${LIBRARY_NAME} PUBLIC xacc PRIVATE CppMicroServices ${CMAKE_SOURCE_DIR}/dist/libantlr4-runtime.dylib)
set_target_properties(${LIBRARY_NAME} PROPERTIES INSTALL_RPATH "@loader_path")
set_target_properties(${LIBRARY_NAME} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
else()
target_link_libraries(${LIBRARY_NAME} PUBLIC xacc PRIVATE CppMicroServices ${CMAKE_SOURCE_DIR}/dist/libantlr4-runtime.so)
set_target_properties(${LIBRARY_NAME} PROPERTIES INSTALL_RPATH "$ORIGIN")
set_target_properties(${LIBRARY_NAME} PROPERTIES LINK_FLAGS "-shared")
endif()
if(XACC_BUILD_TESTS)
add_subdirectory(tests)
endif()
file (GLOB HEADERS *.hpp)
install(FILES ${HEADERS} DESTINATION include/quantum/gate)
install(TARGETS ${LIBRARY_NAME} DESTINATION lib)
/*******************************************************************************
* Copyright (c) 2019 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 "FermionOperator.hpp"
#include "cppmicroservices/BundleActivator.h"
#include "cppmicroservices/BundleContext.h"
#include "cppmicroservices/ServiceProperties.h"
#include <memory>
#include <set>
using namespace cppmicroservices;
namespace {
/**
*/
class US_ABI_LOCAL FermionActivator : public BundleActivator {
public:
FermionActivator() {}
/**
*/
void Start(BundleContext context) {
auto f =
std::make_shared<xacc::quantum::FermionOperator>();
context.RegisterService<xacc::Observable>(
f);
}
/**
*/
void Stop(BundleContext /*context*/) {}
};
} // namespace
CPPMICROSERVICES_EXPORT_BUNDLE_ACTIVATOR(FermionActivator)
#include "FermionListenerImpl.hpp"
namespace xacc {
namespace quantum {
void FermionListenerImpl::enterPlusorminus(FermionOperatorParser::PlusorminusContext * ctx) {
isMinus = ctx->getText() == "-";
}
void FermionListenerImpl::enterTerm(FermionOperatorParser::TermContext * ctx) {
// std::cout << "ENTER TERM: " << ctx->getText() << ", " << ctx->fermion().size() << "\n";
std::complex<double> coeff(1.0,0.0);
if (ctx->coeff() != nullptr) {
if (ctx->coeff()->complex() != nullptr) {
auto complexAsStr = ctx->coeff()->complex()->getText();
complexAsStr = complexAsStr.substr(1, complexAsStr.length() - 2);
auto split = xacc::split(complexAsStr, ',');
coeff = std::complex<double>(std::stod(split[0]), std::stod(split[1]));
} else if (ctx->coeff()->real() != nullptr) {
auto realAsStr = ctx->coeff()->real()->getText();
coeff = std::complex<double>(std::stod(realAsStr), 0.0);
}
}
if (isMinus) {
coeff *= -1.0;
isMinus=false;
}
Operators term;
for (int i = 0; i < ctx->fermion().size(); i++) {
auto str = ctx->fermion(i)->getText();
bool creation = false;
if (str.find("^") != std::string::npos) {
creation = true;
}
term.push_back({std::stoi(ctx->fermion(i)->op()->INT()->getText()), creation});
// std::cout << "HI: " << ctx->fermion(i)->getText() << ", " << "\n";
}
// std::cout << "SIZE OF TERMS: " << term.size() << "\n";
_op += FermionOperator(term, coeff);
// std::cout << _op.toString() << "\n";
// std::cout << "ENTER TERM: " << ctx->getText() << ", " << ctx->fermion().size() << "\n";
}
}
}
\ No newline at end of file
#include "FermionOperatorBaseListener.h"
#include "Utils.hpp"
#include "FermionOperator.hpp"
using namespace fermion;
namespace xacc {
namespace quantum {
class FermionOperatorErrorListener : public antlr4::BaseErrorListener {
public:
void syntaxError(antlr4::Recognizer *recognizer,
antlr4::Token *offendingSymbol, size_t line,
size_t charPositionInLine, const std::string &msg,
std::exception_ptr e) override {
std::ostringstream output;
output << "Invalid Fermion Operator source: ";
output << "line " << line << ":" << charPositionInLine << " " << msg;
xacc::XACCLogger::instance()->error(output.str());
}
};
class FermionListenerImpl : public FermionOperatorBaseListener {
protected:
FermionOperator _op;
bool isMinus = false;
public:
void enterPlusorminus(FermionOperatorParser::PlusorminusContext * ctx) override;
void enterTerm(FermionOperatorParser::TermContext * ctx) override;
FermionOperator getOperator() {return _op;}
};
}
}
\ No newline at end of file
#include "FermionOperator.hpp"
#include "FermionOperatorLexer.h"
#include "FermionListenerImpl.hpp"
#include "ObservableTransform.hpp"
#include "xacc_service.hpp"
namespace xacc {
namespace quantum {
FermionTerm &FermionTerm::operator*=(const FermionTerm &v) noexcept {
coeff() *= std::get<0>(v);
// std::cout << "FermionTerm: " << id() << ", " << FermionTerm::id(std::get<1>(v)) << "\n";
auto otherOps = std::get<1>(v);
for (auto &kv : otherOps) {
auto site = kv.first;
auto c_or_a = kv.second;
// std::cout << "HELLO: " << site << ", " << std::boolalpha << c_or_a << "\n";
Operators o = ops();
if (!o.empty()) {
auto it = std::find_if(o.begin(), o.end(),
[&](const std::pair<int, bool> &element) {
return element.first == site;
});
// std::cout << it->first << ", " << std::boolalpha << it->second << "\n";
if (it->first == site) {
if (it->second && c_or_a) {
// zero out this FermionTerm
ops().clear();
}
} else {
ops().push_back({site, c_or_a});
}
}
// This means, we have a op on same qubit in both
}
return *this;
}
FermionOperator::FermionOperator() {}
FermionOperator::FermionOperator(std::complex<double> c) {
terms.emplace(std::make_pair("I", c));
}
FermionOperator::FermionOperator(double c) {
terms.emplace(std::make_pair("I", c));
}
FermionOperator::FermionOperator(std::string fromStr) { fromString(fromStr); }
FermionOperator::FermionOperator(const FermionOperator &i) : terms(i.terms) {}
FermionOperator::FermionOperator(Operators operators) {
terms.emplace(std::make_pair(FermionTerm::id(operators), operators));
}
FermionOperator::FermionOperator(Operators operators,
std::complex<double> coeff) {
terms.emplace(std::piecewise_construct,
std::forward_as_tuple(FermionTerm::id(operators)),
std::forward_as_tuple(coeff, operators));
}
FermionOperator::FermionOperator(Operators operators, double coeff)
: FermionOperator(operators, std::complex<double>(coeff, 0)) {}
FermionOperator::FermionOperator(Operators operators, double coeff, std::string var)
{
terms.emplace(std::piecewise_construct,
std::forward_as_tuple(FermionTerm::id(operators)),
std::forward_as_tuple(std::complex<double>(coeff,0.0), operators, var));
}
void FermionOperator::clear() { terms.clear(); }
std::vector<std::shared_ptr<CompositeInstruction>>
FermionOperator::observe(std::shared_ptr<CompositeInstruction> function) {
auto transform = xacc::getService<ObservableTransform>("jw");
return transform->transform(shared_from_this())->observe(function);
}
const std::string FermionOperator::toString() {
std::stringstream s;
for (auto &kv : terms) {
std::complex<double> c = std::get<0>(kv.second);
s << c << " " << std::get<2>(kv.second) << " ";
Operators ops = std::get<1>(kv.second);
std::vector<int> creations, annhilations;
for (auto &t : ops) {
// std::cout << "tostring " << t.first << ", " << t.second << "\n";
if (t.second) {
creations.push_back(t.first);
} else {
annhilations.push_back(t.first);
}
}
std::sort(creations.rbegin(), creations.rend());
std::sort(annhilations.rbegin(), annhilations.rend());
for (auto &t : creations) {
s << t << "^" << std::string(" ");
}
for (auto &t : annhilations) {
s << t << std::string(" ");
}
s << "+ ";
}
// std::cout << "tostring " << s.str() << "\n";
auto r = s.str().substr(0, s.str().size() - 2);
xacc::trim(r);
return r;
}
void FermionOperator::fromString(const std::string str) {
using namespace antlr4;
using namespace fermion;
ANTLRInputStream input(str);
FermionOperatorLexer lexer(&input);
lexer.removeErrorListeners();
lexer.addErrorListener(new FermionOperatorErrorListener());
CommonTokenStream tokens(&lexer);
FermionOperatorParser parser(&tokens);
parser.removeErrorListeners();
parser.addErrorListener(new FermionOperatorErrorListener());
// Walk the Abstract Syntax Tree
tree::ParseTree *tree = parser.fermionSrc();
FermionListenerImpl listener;
tree::ParseTreeWalker::DEFAULT.walk(&listener, tree);
clear();
operator+=(listener.getOperator());
}
const int FermionOperator::nBits() {
auto maxInt = 0;
if (terms.empty())
return 0;
for (auto &kv : terms) {
auto ops = kv.second.ops();
for (auto &kv2 : ops) {
if (maxInt < kv2.first) {
maxInt = kv2.first;
}
}
}
return maxInt + 1;
}
FermionOperator &
FermionOperator::operator+=(const FermionOperator &v) noexcept {
FermionOperator vv = v;
for (auto &kv : v.terms) {
auto termId = kv.first;
auto otherTerm = kv.second;
if (terms.count(termId)) {
terms.at(termId).coeff() += otherTerm.coeff();
} else {
terms.insert({termId, otherTerm});
}
if (std::abs(terms[termId].coeff()) < 1e-12) {
terms.erase(termId);
}
}
// std::cout << "result: " << toString() << "\n";
return *this;
}
FermionOperator &
FermionOperator::operator-=(const FermionOperator &v) noexcept {
return operator+=(-1.0 * v);
}
FermionOperator &
FermionOperator::operator*=(const FermionOperator &v) noexcept {
std::unordered_map<std::string, FermionTerm> newTerms;
for (auto &kv : terms) {
for (auto &vkv : v.terms) {
auto multTerm = kv.second * vkv.second;
if (!multTerm.ops().empty()) {
auto id = multTerm.id();
if (!newTerms.insert({id, multTerm}).second) {
newTerms.at(id).coeff() += multTerm.coeff();
}
if (std::abs(newTerms.at(id).coeff()) < 1e-12) {
newTerms.erase(id);
}
}
}
}
terms = newTerms;
return *this;
}
bool FermionOperator::operator==(const FermionOperator &v) noexcept {
if (terms.size() != v.terms.size()) {
return false;
}
for (auto &kv : terms) {
bool found = false;
for (auto &vkv : v.terms) {
if (kv.second.operator==(vkv.second)) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
}
FermionOperator &FermionOperator::operator*=(const double v) noexcept {
return operator*=(std::complex<double>(v, 0));
}
FermionOperator &
FermionOperator::operator*=(const std::complex<double> v) noexcept {
for (auto &kv : terms) {
std::get<0>(kv.second) *= v;
}
return *this;
}
} // namespace quantum
} // namespace xacc
bool operator==(const xacc::quantum::FermionOperator &lhs,
const xacc::quantum::FermionOperator &rhs) {
if (lhs.getTerms().size() != rhs.getTerms().size()) {
return false;
}
for (auto &kv : lhs.getTerms()) {
bool found = false;
for (auto &vkv : rhs.getTerms()) {
if (kv.second.operator==(vkv.second)) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
}
\ No newline at end of file
grammar FermionOperator;
fermionSrc : term(plusorminus term) *;
plusorminus : '+' | '-';
term : coeff ? (fermion) *;
fermion : op;
op : INT '^' | INT;
coeff : complex | real;
complex : '('(real | INT)','(real | INT)')';
real : REAL;