Commit 872b8afc authored by Mccaskey, Alex's avatar Mccaskey, Alex

adding observable and paulioperator

Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent ad2724ec
Pipeline #44140 passed with stages
in 9 minutes and 23 seconds
......@@ -70,9 +70,19 @@ endif()
message(STATUS "${BoldGreen}Installing XACC to ${CMAKE_INSTALL_PREFIX}. Override with -DCMAKE_INSTALL_PREFIX=...${ColorReset}")
#if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "7.0.0")
# set (CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-Wimplicit-fallthrough=0")
#endif()
if (XACC_BUILD_TESTS)
enable_testing()
macro(add_xacc_test _TEST_NAME)
add_executable(${_TEST_NAME}Tester ${_TEST_NAME}Tester.cpp)
target_include_directories(${_TEST_NAME}Tester PRIVATE ${GTEST_INCLUDE_DIRS})
add_test(NAME xacc_${_TEST_NAME}Tester COMMAND ${_TEST_NAME}Tester)
target_link_libraries(${_TEST_NAME}Tester ${GTEST_LIBRARIES} xacc)
endmacro()
macro(set_cache_variable VAR_NAME VAR_DESCRIPTION)
set(${VAR_NAME} ${${VAR_NAME}} CACHE INTERNAL ${VAR_DESCRIPTION})
message(STATUS "Set ${VAR_NAME} to ${${VAR_NAME}}.")
endmacro()
endif()
include_directories(${CMAKE_BINARY_DIR}/tpls/cppmicroservices/include)
add_subdirectory(tpls)
......@@ -90,9 +100,10 @@ endif()
# and CMake loads include paths, libs, etc
configure_file("${CMAKE_SOURCE_DIR}/cmake/xacc-config.cmake.in" "${CMAKE_BINARY_DIR}/xacc-config.cmake" @ONLY)
install(FILES "${CMAKE_BINARY_DIR}/xacc-config.cmake" DESTINATION .)
install(FILES "${CMAKE_SOURCE_DIR}/cmake/Modules/tests.cmake" DESTINATION share/xacc/)
install(FILES "${CMAKE_SOURCE_DIR}/cmake/Modules/format.cmake" DESTINATION share/xacc/)
install(FILES "${CMAKE_SOURCE_DIR}/tpls/mpark-variant/variant.hpp" DESTINATION include/xacc/)
install(FILES "${CMAKE_SOURCE_DIR}/tpls/taocpp/operators.hpp" DESTINATION include/xacc/)
install( DIRECTORY "${CMAKE_SOURCE_DIR}/tpls/spdlog" DESTINATION include )
install( DIRECTORY "${CMAKE_SOURCE_DIR}/tpls/exprtk" DESTINATION include )
install( DIRECTORY "${CMAKE_SOURCE_DIR}/tpls/eigen" DESTINATION include )
......
......@@ -6,24 +6,28 @@
# XACC_INCLUDE_DIRS - include directories for XACC
# XACC_LIBRARIES - libraries to link against
# XACC_LIBRARY_DIR - the XACC library directory
include(CTest)
if (NOT XACC_ROOT)
get_filename_component(XACC_ROOT "${CMAKE_CURRENT_LIST_FILE}" PATH)
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${XACC_ROOT}/share/xacc)
if (NOT TARGET format)
include(format)
endif()
set (XACC_LIBRARY_DIR "${XACC_ROOT}/lib")
link_directories("${XACC_ROOT}/lib")
set(XACC_INCLUDE_ROOT "${XACC_ROOT}/include")
set(XACC_HAS_ANTLR @XACC_HAS_ANTLR@)
set (XACC_INCLUDE_DIRS "${XACC_INCLUDE_ROOT}/antlr4-runtime;${XACC_INCLUDE_ROOT}/cppmicroservices4;${XACC_INCLUDE_ROOT}/xacc;${XACC_INCLUDE_ROOT}/quantum/gate;${XACC_INCLUDE_ROOT}/quantum/utils;${XACC_INCLUDE_ROOT}/quantum/aqc;${XACC_INCLUDE_ROOT}/spdlog;${XACC_INCLUDE_ROOT}/exprtk;${XACC_INCLUDE_ROOT}/eigen;${XACC_INCLUDE_ROOT}/rapidjson/include;${XACC_INCLUDE_ROOT};${XACC_INCLUDE_ROOT}/gtest")
set (XACC_LIBRARIES "xacc;xacc-quantum-gate;xacc-quantum-aqc;antlr4-runtime;CppMicroServices")
set (XACC_TEST_LIBRARIES "${XACC_LIBRARIES};gtest;gtest_main")
set(BOOST_ROOT ${XACC_ROOT})
macro(add_xacc_test _TEST_NAME)
add_executable(${_TEST_NAME}Tester ${_TEST_NAME}Tester.cpp)
add_test(NAME xacc_${_TEST_NAME}Tester COMMAND ${_TEST_NAME}Tester)
......
......@@ -12,6 +12,7 @@ include_directories(${CMAKE_SOURCE_DIR}/tpls/rapidjson/include)
include_directories(${CMAKE_SOURCE_DIR}/tpls/exprtk)
include_directories(${CMAKE_SOURCE_DIR}/tpls/spdlog)
include_directories(${CMAKE_SOURCE_DIR}/tpls/eigen)
include_directories(${CMAKE_SOURCE_DIR}/tpls/taocpp)
include_directories(${CMAKE_SOURCE_DIR}/quantum/utils)
include_directories(${CMAKE_SOURCE_DIR}/quantum/aqc/ir)
......@@ -35,7 +36,7 @@ add_library(_pyxacc SHARED xacc-py.cpp)
set_target_properties(_pyxacc PROPERTIES PREFIX "")
target_link_libraries(_pyxacc PUBLIC CppMicroServices xacc Boost::graph)
target_link_libraries(_pyxacc PUBLIC CppMicroServices xacc xacc-quantum-gate Boost::graph)
if(APPLE)
set_target_properties(_pyxacc PROPERTIES INSTALL_RPATH "@loader_path/lib")
......
......@@ -19,6 +19,7 @@
#include "InstructionParameter.hpp"
#include "DWGraph.hpp"
#include "EmbeddingAlgorithm.hpp"
#include "PauliOperator.hpp"
#include <pybind11/complex.h>
#include <pybind11/numpy.h>
......@@ -30,6 +31,7 @@
namespace py = pybind11;
using namespace xacc;
using namespace xacc::quantum;
// `boost::variant` as an example -- can be any `std::variant`-like container
namespace pybind11 {
......@@ -408,6 +410,45 @@ PYBIND11_MODULE(_pyxacc, m) {
"Translate the given IR Function instance to source code in this "
"Compiler's language.");
py::class_<Term>(m, "Term").def("coeff", &Term::coeff).def("ops",&Term::ops);
py::class_<PauliOperator>(m, "PauliOperator")
.def(py::init<>())
.def(py::init<std::complex<double>>())
.def(py::init<double>())
.def(py::init<std::string>())
.def(py::init<std::map<int, std::string>>())
.def(py::init<std::map<int, std::string>, double>())
.def(py::init<std::map<int, std::string>, std::complex<double>>())
.def(py::init<std::map<int, std::string>, std::string>())
.def(py::init<std::map<int, std::string>, std::complex<double>,
std::string>())
.def(py::self + py::self)
.def(py::self += py::self)
.def(py::self *= py::self)
.def(py::self *= double())
.def(py::self * py::self)
.def(py::self *= std::complex<double>())
.def(py::self -= py::self)
.def(py::self - py::self)
.def("__eq__", &PauliOperator::operator==)
.def("__repr__", &PauliOperator::toString)
.def("eval", &PauliOperator::eval)
.def("toBinaryVectors", &PauliOperator::toBinaryVectors)
.def("toXACCIR", &PauliOperator::toXACCIR)
.def("fromXACCIR", &PauliOperator::fromXACCIR)
.def("fromString", &PauliOperator::fromString)
.def("nTerms", &PauliOperator::nTerms)
.def("isClose", &PauliOperator::isClose)
.def("commutes", &PauliOperator::commutes)
.def("__len__", &PauliOperator::nTerms)
.def("nQubits", &PauliOperator::nQubits)
.def("computeActionOnKet", &PauliOperator::computeActionOnKet)
.def("computeActionOnBra", &PauliOperator::computeActionOnBra)
.def("__iter__",
[](PauliOperator &op) {
return py::make_iterator(op.begin(), op.end());
},
py::keep_alive<0, 1>());
// Expose the Program object
py::class_<xacc::Program>(
m, "Program",
......@@ -527,7 +568,7 @@ PYBIND11_MODULE(_pyxacc, m) {
m.def("getCache", &xacc::getCache, "");
m.def(
"appendCache",
(void (*)(const std::string, const std::string, InstructionParameter &)) &
(void (*)(const std::string, const std::string, InstructionParameter &,const std::string)) &
xacc::appendCache,
"");
m.def("Finalize", &xacc::Finalize, "Finalize the framework");
......
......@@ -42,8 +42,10 @@ target_include_directories(${LIBRARY_NAME}
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/quantum/utils
${CMAKE_SOURCE_DIR}/tpls/exprtk
${CMAKE_SOURCE_DIR}/tpls/rapidjson/include)
${CMAKE_SOURCE_DIR}/tpls/rapidjson/include
${CMAKE_SOURCE_DIR}/tpls/taocpp
${CMAKE_SOURCE_DIR}/tpls/eigen)
set(_bundle_name xacc_quantum_gate)
set_target_properties(${LIBRARY_NAME}
PROPERTIES # This is required for every bundle
......
......@@ -53,10 +53,14 @@ auto splitParameter = [](InstructionParameter instParam) {
std::vector<std::string> split;
InstructionParameter rawParam;
auto paramStr = mpark::get<std::string>(instParam);
std::replace(mpark::get<std::string>(instParam).begin(), mpark::get<std::string>(instParam).end(), '-', ' ');
std::replace(mpark::get<std::string>(instParam).begin(), mpark::get<std::string>(instParam).end(), '+', ' ');
std::replace(mpark::get<std::string>(instParam).begin(), mpark::get<std::string>(instParam).end(), '*', ' ');
std::replace(mpark::get<std::string>(instParam).begin(), mpark::get<std::string>(instParam).end(), '/', ' ');
std::replace(mpark::get<std::string>(instParam).begin(),
mpark::get<std::string>(instParam).end(), '-', ' ');
std::replace(mpark::get<std::string>(instParam).begin(),
mpark::get<std::string>(instParam).end(), '+', ' ');
std::replace(mpark::get<std::string>(instParam).begin(),
mpark::get<std::string>(instParam).end(), '*', ' ');
std::replace(mpark::get<std::string>(instParam).begin(),
mpark::get<std::string>(instParam).end(), '/', ' ');
auto instParamStr = instParam.as<std::string>();
split = xacc::split(instParamStr, ' ');
......@@ -68,6 +72,37 @@ auto splitParameter = [](InstructionParameter instParam) {
return rawParam;
};
const int GateFunction::nLogicalBits() {
std::set<int> local_bits;
xacc::InstructionIterator it(shared_from_this());
while (it.hasNext()) {
auto nextInst = it.next();
if (nextInst->isEnabled()) {
for (auto &i : nextInst->bits()) {
local_bits.insert(i);
}
}
}
return local_bits.size();
}
const int GateFunction::nPhysicalBits() {
int maxBitIdx = 0;
xacc::InstructionIterator it(shared_from_this());
while (it.hasNext()) {
auto nextInst = it.next();
if (nextInst->isEnabled()) {
for (auto &i : nextInst->bits()) {
if (maxBitIdx < i) {
maxBitIdx = i;
}
}
}
}
maxBitIdx++;
return maxBitIdx;
}
void GateFunction::removeInstruction(const int idx) {
auto instruction = getInstruction(idx);
// Check to see if instruction being removed is parameterized
......@@ -211,7 +246,7 @@ void GateFunction::replaceInstruction(const int idx, InstPtr replacingInst) {
void GateFunction::insertInstruction(const int idx, InstPtr newInst) {
// Check if new GateInstruction is parameterized with 1 parameter
if (newInst->isParameterized() && newInst->nParameters() <= 1) {
if (newInst->isParameterized() && !newInst->isComposite()) {
xacc::InstructionParameter param = newInst->getParameter(0);
// Check if new parameter is a string
if (param.isVariable()) {
......@@ -286,8 +321,8 @@ const std::string GateFunction::toString(const std::string &bufferVarName) {
return retStr;
}
std::shared_ptr<Function> GateFunction::
operator()(const std::vector<double> &params) {
std::shared_ptr<Function>
GateFunction::operator()(const std::vector<double> &params) {
if (params.size() != nParameters()) {
xacc::error("Invalid GateFunction evaluation: number "
"of parameters don't match. " +
......@@ -322,8 +357,7 @@ operator()(const std::vector<double> &params) {
for (auto inst : getInstructions()) {
if (inst->isComposite()) {
// If a Function, call this method recursively
auto evaled =
std::dynamic_pointer_cast<Function>(inst)->operator()(p);
auto evaled = std::dynamic_pointer_cast<Function>(inst)->operator()(p);
evaluatedFunction->addInstruction(evaled);
} else {
// If a concrete GateInstruction, then check that it
......
......@@ -91,8 +91,9 @@ public:
const int nInstructions() override;
const int nRequiredBits() const override {
XACCLogger::instance()->error("GateFunction nRequiredBits() not implemented.");
return 0;
XACCLogger::instance()->error(
"GateFunction nRequiredBits() not implemented.");
return 0;
}
InstPtr getInstruction(const int idx) override;
......@@ -121,7 +122,7 @@ public:
for (int i = 0; i < instructions.size(); i++) {
auto inst = *std::next(instructions.begin(), i);
if (inst->isAnalog()) {
return true;
return true;
}
}
return false;
......@@ -193,7 +194,7 @@ public:
*
* @return qasm The instruction as qasm
*/
const std::string toString() override {return toString("q");}
const std::string toString() override { return toString("q"); }
InstructionParameter getParameter(const int idx) const override;
......@@ -207,32 +208,26 @@ public:
const int nParameters() override;
std::shared_ptr<Function> operator()(const std::vector<double> &params) override;
std::shared_ptr<Function>
operator()(const std::vector<double> &params) override;
Graph<CircuitNode, Directed> toGraph() override;
// void fromGraph(Graph<CircuitNode>& graph) override;
// void fromGraph(std::istream& input) override;
/**
* Return the number of logical qubits.
*
* @return nLogical The number of logical qubits.
*/
const int nLogicalBits() override {
XACCLogger::instance()->error("GateFunction nLogicalBits() not implemented.");
return 0;
}
const int nLogicalBits() override;
/**
* Return the number of physical qubits.
*
* @return nPhysical The number of physical qubits.
*/
const int nPhysicalBits() override {
XACCLogger::instance()->error("GateFunction nPhysicalBits() not implemented.");
return 0;
}
const int nPhysicalBits() override;
/**
* Return true if this Instruction has
......@@ -240,7 +235,7 @@ public:
*
* @return hasOptions
*/
bool hasOptions() override {return false;}
bool hasOptions() override { return !options.empty(); }
/**
* Set the value of an option with the given name.
......@@ -249,7 +244,10 @@ public:
* @param option The value of the option
*/
void setOption(const std::string optName,
InstructionParameter option) override {}
InstructionParameter option) override {
options.insert({optName, option});
}
/**
* Get the value of an option with the given name.
*
......@@ -257,8 +255,7 @@ public:
* @return option The value of the option.
*/
InstructionParameter getOption(const std::string optName) override {
XACCLogger::instance()->error("GateFunction does not have options.");
return InstructionParameter(0);
return options[optName];
}
/**
......@@ -267,8 +264,7 @@ public:
* @return optMap The options map.
*/
std::map<std::string, InstructionParameter> getOptions() override {
XACCLogger::instance()->error("GateFunction does not have options.");
return std::map<std::string, InstructionParameter>{};
return options;
}
DEFINE_VISITABLE()
......@@ -284,6 +280,9 @@ protected:
std::vector<InstructionParameter> parameters;
std::string tag = "";
std::map<std::string, InstructionParameter> options;
};
} // namespace quantum
......
This diff is collapsed.
/*******************************************************************************
* 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
*******************************************************************************/
#ifndef QUANTUM_UTILS_PAULIOPERATOR_HPP_
#define QUANTUM_UTILS_PAULIOPERATOR_HPP_
#include <unordered_map>
#include <map>
#include <stdio.h>
#include <stdlib.h>
#include "Observable.hpp"
#include "IR.hpp"
// Putting this here due to clang error
// not able to find operator!= from operators.hpp
namespace xacc {
namespace quantum {
class PauliOperator;
}
} // namespace xacc
bool operator==(const xacc::quantum::PauliOperator &lhs,
const xacc::quantum::PauliOperator &rhs);
#include "operators.hpp"
namespace xacc {
namespace quantum {
// A Term can be a coefficient, a variable coefficient, and the terms themselves
using TermTuple =
std::tuple<std::complex<double>, std::string, std::map<int, std::string>>;
using c = std::complex<double>;
using ActionResult = std::pair<std::string, c>;
enum ActionType { Bra, Ket };
class Triplet : std::tuple<std::uint64_t, std::uint64_t, std::complex<double>> {
public:
Triplet(std::uint64_t r, std::uint64_t c, std::complex<double> coeff) {
std::get<0>(*this) = r;
std::get<1>(*this) = c;
std::get<2>(*this) = coeff;
}
const std::uint64_t row() { return std::get<0>(*this); }
const std::uint64_t col() { return std::get<1>(*this); }
const std::complex<double> coeff() { return std::get<2>(*this); }
};
class Term : public TermTuple,
public tao::operators::commutative_multipliable<Term>,
public tao::operators::equality_comparable<Term> {
protected:
// static std::map<std::string, std::pair<c, std::string>>
void create_map() {
// static std::map<std::string, std::pair<c, std::string>> m;
pauliProducts.insert({"II", {c(1.0, 0.0), "I"}});
pauliProducts.insert({"IX", {c(1.0, 0.0), "X"}});
pauliProducts.insert({"XI", {c(1.0, 0.0), "X"}});
pauliProducts.insert({"IY", {c(1.0, 0.0), "Y"}});
pauliProducts.insert({"YI", {c(1.0, 0.0), "Y"}});
pauliProducts.insert({"ZI", {c(1.0, 0.0), "Z"}});
pauliProducts.insert({"IZ", {c(1.0, 0.0), "Z"}});
pauliProducts.insert({"XX", {c(1.0, 0.0), "I"}});
pauliProducts.insert({"YY", {c(1.0, 0.0), "I"}});
pauliProducts.insert({"ZZ", {c(1.0, 0.0), "I"}});
pauliProducts.insert({"XY", {c(0.0, 1.0), "Z"}});
pauliProducts.insert({"XZ", {c(0.0, -1.0), "Y"}});
pauliProducts.insert({"YX", {c(0.0, -1.0), "Z"}});
pauliProducts.insert({"YZ", {c(0.0, 1.0), "X"}});
pauliProducts.insert({"ZX", {c(0.0, 1.0), "Y"}});
pauliProducts.insert({"ZY", {c(0.0, -1.0), "X"}});
// return m;
}
std::map<std::string, std::pair<c, std::string>> pauliProducts;
public:
Term() {
std::get<0>(*this) = std::complex<double>(0, 0);
std::get<1>(*this) = "";
std::get<2>(*this) = {};
create_map();
}
Term(const Term &t) {
std::get<0>(*this) = std::get<0>(t);
std::get<1>(*this) = std::get<1>(t);
std::get<2>(*this) = std::get<2>(t);
create_map();
}
Term(std::complex<double> c) {
std::get<0>(*this) = c;
std::get<1>(*this) = "";
std::get<2>(*this) = {};
create_map();
}
Term(double c) {
std::get<0>(*this) = std::complex<double>(c, 0);
std::get<1>(*this) = "";
std::get<2>(*this) = {};
create_map();
}
Term(std::complex<double> c, std::map<int, std::string> ops) {
std::get<0>(*this) = c;
std::get<1>(*this) = "";
std::get<2>(*this) = ops;
create_map();
}
Term(std::string var) {
std::get<0>(*this) = std::complex<double>(1, 0);
std::get<1>(*this) = var;
std::get<2>(*this) = {};
create_map();
}
Term(std::complex<double> c, std::string var) {
std::get<0>(*this) = c;
std::get<1>(*this) = var;
std::get<2>(*this) = {};
create_map();
}
Term(std::string var, std::map<int, std::string> ops) {
std::get<0>(*this) = std::complex<double>(1, 0);
std::get<1>(*this) = var;
std::get<2>(*this) = ops;
create_map();
}
Term(std::complex<double> c, std::string var,
std::map<int, std::string> ops) {
std::get<0>(*this) = c;
std::get<1>(*this) = var;
std::get<2>(*this) = ops;
create_map();
}
Term(std::map<int, std::string> ops) {
std::get<0>(*this) = std::complex<double>(1, 0);
std::get<1>(*this) = "";
std::get<2>(*this) = ops;
create_map();
}
static const std::string id(const std::map<int, std::string> &ops,
const std::string &var = "") {
std::string s;
s = var;
for (auto &t : ops) {
if (t.second != "I") {
s += t.second + std::to_string(t.first);
}
}
if (s.empty()) {
return "I";
}
return s;
}
const std::string id() const {
std::string s;
s = std::get<1>(*this);
for (auto &t : std::get<2>(*this)) {
if (t.second != "I") {
s += t.second + std::to_string(t.first);
}
}
if (s.empty()) {
return "I";
}
return s;
}
std::map<int, std::string> &ops() { return std::get<2>(*this); }
bool isIdentity() {
if (ops().empty()) {
return true;
} else {
return false;
}
}
std::complex<double> &coeff() { return std::get<0>(*this); }
std::string &var() { return std::get<1>(*this); }
Term &operator*=(const Term &v) noexcept;
bool operator==(const Term &v) noexcept {
return std::get<1>(*this) == std::get<1>(v) && ops() == std::get<2>(v);
}
std::vector<Triplet> getSparseMatrixElements(const int nQubits);
ActionResult action(const std::string &bitString, ActionType type);
std::pair<std::vector<int>, std::vector<int>>
toBinaryVector(const int nQubits);
};
class PauliOperator
: public xacc::Observable,
public tao::operators::commutative_ring<PauliOperator>,
public tao::operators::equality_comparable<PauliOperator>,
public tao::operators::commutative_multipliable<PauliOperator, double>,
public tao::operators::commutative_multipliable<PauliOperator,
std::complex<double>> {
protected:
std::unordered_map<std::string, Term> terms;
public:
std::unordered_map<std::string, Term>::iterator begin() {
return terms.begin();
}
std::unordered_map<std::string, Term>::iterator end() { return terms.end(); }
PauliOperator();
PauliOperator(std::complex<double> c);
PauliOperator(double c);
PauliOperator(std::string var);
PauliOperator(std::complex<double> c, std::string var);
PauliOperator(const PauliOperator &i);
PauliOperator(std::map<int, std::string> operators);
PauliOperator(std::map<int, std::string> operators, std::string var);
PauliOperator(std::map<int, std::string> operators,
std::complex<double> coeff);
PauliOperator(std::map<int, std::string> operators, double coeff);
PauliOperator(std::map<int, std::string> operators,
std::complex<double> coeff, std::string var);
std::vector<std::shared_ptr<Function>>
observe(std::shared_ptr<Function> function) override;