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

Removing Fire as submodule. Adding dependency on cpprestsdk. Updating Simple...

Removing Fire as submodule. Adding dependency on cpprestsdk. Updating Simple Accelerator to use Eigen and not fire Tensor
parent dc8753b8
[submodule "tpls/fire"]
path = tpls/fire
url = https://github.com/jayjaybillings/fire
......@@ -42,11 +42,7 @@ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
# Modify our CMAKE_MODULE_PATH
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules")
if (EXISTS ${CMAKE_SOURCE_DIR}/tpls/fire)
message(STATUS "Fire found in tpls")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/tpls/fire/cmake/Modules")
include(tests)
endif()
include(tests)
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set (CMAKE_INSTALL_PREFIX "/usr/local/xacc" CACHE PATH "default install path" FORCE )
......
#------------------------------------------------------------------------------
# Copyright (c) 2015-, UT-Battelle, LLC
# All rights reserved.
#
# Author Contact: Jay Jay Billings, jayjaybillings <at> gmail <dot> com
#
# 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 fern 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
#
# Author(s): Jay Jay Billings
#----------------------------------------------------------------------------*/
# tests.cmake
#
# This is a CMake script with various unit testing utilities for doing boost-
# based testing. It is called by issuing the command "include(tests)" when the
# tests.cmake file is in the module path. It always attempts to find BOOST
# regardless of whether or not one of its functions is called.
#
# From the main build CMake file with this script in the module path, it is
# sufficient to do
#
# include(tests)
# add_tests(...)
#
# This also works fine when include(tests) is called from a parent and the
# functions from this script are called from submodules.
# Find the BOOST
FIND_PACKAGE(Boost)
# Enable testing if boost is found.
if(Boost_FOUND)
# Turn on the testing harness
enable_testing()
# Let the user know that tests will be built
message(STATUS "Boost version ${Boost_VERSION} found.")
message(STATUS "Tests will be built since Boost was found.")
message(STATUS "Tests can be run with the 'make test' command.")
else(Boost_FOUND)
# Complain that tests will be disabled
message(WARNING "Tests enabled, but BOOST is unavailable!")
message(WARNING "Tests will not be built!")
endif(Boost_FOUND)
# This function builds and configures ctest for a list of test files.
# @param tests - the list of test files to be built
# @param test_include_dirs - the list of header directories to include
# @param test_libs - the list of libraries to link for the tests
#
# This is a convenience call around add_tests_with_flags where the
# test_cflags argument is set to the default.
#
# This function sets the working directory of the tests to the directory
# where the binary is build, which means that ctest will not execute it
# from the root of your build directory. Instead, it will be run from the
# subdirectory of the build directory for your module.
#
# When you call this function, you need to quote your variables like so:
# add_tests("${intTests}" "${test_include_dirs}" "${FIRE_LIBS}")
function(add_tests tests test_include_dirs test_libs)
add_tests_with_flags("${tests}" "${test_include_dirs}" "${test_libs}" "")
endfunction()
# This function builds and configures ctest for a list of test files.
# @param tests - the list of test files to be built
# @param test_include_dirs - the list of header directories to include
# @param test_libs - the list of libraries to link for the tests
# @param test_cflags - compiler flags for the tests. If this flag is
# empty, the default flags are used.
#
# This function sets the working directory of the tests to the directory
# where the binary is build, which means that ctest will not execute it
# from the root of your build directory. Instead, it will be run from the
# subdirectory of the build directory for your module.
#
# When you call this function, you need to quote your variables like so:
# add_tests("${intTests}" "${test_include_dirs}" "${FIRE_LIBS}" "${flags}")
function(add_tests_with_flags tests test_include_dirs test_libs test_cflags)
if(Boost_FOUND)
# Include all the required headers and BOOST
include_directories("${Boost_INCLUDE_DIR}" "${test_include_dirs}")
# Make executables and link libraries for testers
foreach(test ${tests})
message(STATUS "Adding test ${test}")
get_filename_component(testName ${test} NAME_WE)
# Add the executable to the build and the test list
add_executable(${testName} ${test})
add_test(${testName} ${testName} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
# Overwrite the default compile flags if needed.
if (NOT test_cflags STREQUAL "")
target_compile_options(${testName} PUBLIC "${test_cflags}")
endif()
# Only link libraries if they are provided
if (test_libs)
target_link_libraries(${testName} ${test_libs})
endif(test_libs)
# Add a label so the tests can be run on its own by label
set_property(TEST ${testName} PROPERTY LABELS ${PACKAGE_NAME})
endforeach(test ${tests})
else(Boost_FOUND)
message(WARNING "Tests - ${tests} - not built because BOOST is unavailable!")
endif()
endfunction()
\ No newline at end of file
......@@ -34,8 +34,6 @@ include_directories(${CMAKE_SOURCE_DIR}/quantum/aqc/ir)
include_directories(${CMAKE_SOURCE_DIR}/quantum/aqc/compiler)
include_directories(${CMAKE_SOURCE_DIR}/quantum/aqc/compiler/default)
include_directories(${CMAKE_SOURCE_DIR}/quantum/aqc/accelerator)
include_directories(${CMAKE_SOURCE_DIR}/tpls/fire/util)
include_directories(${CMAKE_SOURCE_DIR}/tpls/fire/tpls/simpleweb)
include_directories(${CMAKE_SOURCE_DIR}/tpls/rapidjson/include)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/accelerator)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/compiler)
......
......@@ -30,8 +30,13 @@
#**********************************************************************************/
find_package(OpenSSL)
find_path(CPPREST_INCLUDE cpprest/http_client.h)
find_library(CPPREST_LIB NAMES cpprest_2_9d cpprest_2_9 cpprestd cpprest)
if (OPENSSL_FOUND AND CPPREST_LIB)
include_directories(${CPPREST_INCLUDE})
if (OPENSSL_FOUND)
set (PACKAGE_NAME "D-Wave XACC Accelerator")
set (PACKAGE_DESCIPTION "D-Wave XACC Accelerator Bundle")
set (LIBRARY_NAME xacc-dwave-accelerator)
......@@ -70,9 +75,9 @@ if (OPENSSL_FOUND)
manifest.json
)
target_link_libraries(${LIBRARY_NAME} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} CppMicroServices xacc-quantum-aqc)
target_link_libraries(${LIBRARY_NAME} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${CPPREST_LIB} CppMicroServices xacc xacc-quantum-aqc)
install(TARGETS ${LIBRARY_NAME} DESTINATION lib/plugins/accelerators)
else()
message(STATUS "OpenSSL not found, cannot include D-Wave Accelerator plugin")
message(STATUS "OpenSSL or cpprestsdk not found, cannot include D-Wave Accelerator plugin")
endif()
......@@ -32,14 +32,34 @@
#include <fstream>
#include <memory>
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include "DWAccelerator.hpp"
using namespace utility;
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace concurrency::streams;
namespace xacc {
namespace quantum {
template<typename T>
bool IsInBounds(const T& value, const T& low, const T& high) {
return !(value < low) && !(high < value);
std::shared_ptr<AcceleratorBuffer> DWAccelerator::createBuffer(
const std::string& varId) {
auto options = RuntimeOptions::instance();
std::string solverName = "DW_2000Q_VFYC";
if (options->exists("dwave-solver")) {
solverName = (*options)["dwave-solver"];
}
if (!availableSolvers.count(solverName)) {
XACCError(solverName + " is not available for creating a buffer.");
}
auto solver = availableSolvers[solverName];
auto buffer = std::make_shared<AQCAcceleratorBuffer>(varId, solver.nQubits);
storeBuffer(varId, buffer);
return buffer;
}
std::shared_ptr<AcceleratorBuffer> DWAccelerator::createBuffer(
......@@ -70,6 +90,8 @@ void DWAccelerator::execute(std::shared_ptr<AcceleratorBuffer> buffer,
XACCError("Invalid Accelerator Buffer.");
}
Document doc;
bool jobCompleted = false;
std::vector<std::string> splitLines;
boost::split(splitLines, dwKernel->toString(""), boost::is_any_of("\n"));
auto nQMILines = splitLines.size();
......@@ -121,66 +143,60 @@ void DWAccelerator::execute(std::shared_ptr<AcceleratorBuffer> buffer,
+ trials + ", \"annealing_time\" : " + annealTime + "} }]";
boost::replace_all(jsonStr, "\n", "\\n");
std::cout << "\nJsonPost= " << jsonStr << "\n\n\n";
auto newclient = fire::util::AsioNetworkingTool<SimpleWeb::HTTPS>("qubist.dwavesys.com", false);
auto postResponse = newclient.post("/sapi/problems/", jsonStr, headers);
if (!postResponse.successful) {
XACCError("HTTP Post was not successful");
// Create the URI, HTTP Client and Post and Get request
// add our headers to it - this contains the API key
http::uri uri = http::uri(url);
http_client postClient(
http::uri_builder(uri).append_path(U("/sapi/problems")).to_uri());
http_request postRequest(methods::POST), getRequest(methods::GET);
for (auto& kv : headers) {
postRequest.headers().add(kv.first, kv.second);
getRequest.headers().add(kv.first, kv.second);
}
postRequest.set_body(jsonStr);
std::stringstream ss2;
ss2 << postResponse.content.rdbuf();
auto message = ss2.str();
// Post the problem, get the response as json
auto postResponse = postClient.request(postRequest);
auto respJson = postResponse.get().extract_json().get();
std::cout << "D-Wave Server Response = " << message << "\n";
// Map that response to a string
std::stringstream x;
x << respJson;
Document document;
document.Parse(message.c_str());
// Parse the json string
doc.Parse(x.str());
auto jobId = std::string(document[0]["id"].GetString());
std::cout << "JOB ID IS " << jobId << "\n";
bool finished = false;
std::cout << "\nDWAccelerator Awaiting Job Results";
std::cout.flush();
int count = 1;
while(!finished) {
auto c = fire::util::AsioNetworkingTool<SimpleWeb::HTTPS>("qubist.dwavesys.com", false);
auto r = c.get("/sapi/problems/"+jobId, headers);
std::stringstream ss3;
ss3 << r.content.rdbuf();
message = ss3.str();
if (boost::contains(message, "COMPLETED")) {
finished = true;
}
// Get the JobID
std::string jobId = std::string(doc[0]["id"].GetString());
std::cout << ".";
std::cout.flush();
// Create a client to execute HTTP Get requests
http_client getClient(
http::uri_builder(uri).append_path(U("/sapi/problems/" + jobId)).to_uri());
if (!(count % 3)) {
std::cout << "\b\b\b \b\b\b";
}
count++;
document.Parse(message.c_str());
// Loop until the job is complete,
// get the JSON response
std::string msg;
while (!jobCompleted) {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
std::cout << "\n";
std::cout << "\nJob Completion Results " << message << "\n";
// Execute HTTP Get
auto getResponse = getClient.request(getRequest);
// get the result as a string
std::stringstream z;
z << getResponse.get().extract_json().get();
msg = z.str();
/**
* Looks like we now want document["answer"]["energies"].GetArray(),
* and document["answer"]["num_occurrences"].GetArray(), and
* document["answer"]["solutions"]. Then we have to decode
* solutions string
*/
// Search the result for the status : COMPLETED indicator
if (boost::contains(msg, "COMPLETED")) {
jobCompleted = true;
}
Document doc;
doc.Parse(message.c_str());
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
// We've completed, so let's get
// teh results.
doc.Parse(msg);
if (doc["status"] == "COMPLETED") {
std::vector<double> energies;
std::vector<int> numOccurrences, active_vars;
......@@ -192,7 +208,7 @@ void DWAccelerator::execute(std::shared_ptr<AcceleratorBuffer> buffer,
}
auto solutionsStrEncoded = std::string(doc["answer"]["solutions"].GetString());
auto decoded = newclient.base64_decode(solutionsStrEncoded);
auto decoded = base64_decode(solutionsStrEncoded);
std::string bitStr = "";
std::stringstream ss;
for (std::size_t i = 0; i < decoded.size(); ++i) {
......@@ -235,21 +251,30 @@ void DWAccelerator::execute(std::shared_ptr<AcceleratorBuffer> buffer,
void DWAccelerator::initialize() {
auto options = RuntimeOptions::instance();
searchAPIKey(apiKey, url);
auto tempURL = url;
boost::replace_all(tempURL, "https://", "");
boost::replace_all(tempURL, "/sapi", "");
// Set up the extra HTTP headers we are going to need
headers.insert(std::make_pair("X-Auth-Token", apiKey));
headers.insert(std::make_pair("Content-type", "application/x-www-form-urlencoded"));
headers.insert(std::make_pair("Accept", "*/*"));
// Get the Remote URL Solver data...
auto getSolverClient = fire::util::AsioNetworkingTool<SimpleWeb::HTTPS>(tempURL, false);
auto r = getSolverClient.get("/sapi/solvers/remote", headers);
http::uri uri = http::uri(url);
http_request getRequest(methods::GET);
for (auto& kv : headers) {
getRequest.headers().add(kv.first, kv.second);
}
// Create a client to execute HTTP Get requests
http_client getClient(
http::uri_builder(uri).append_path(U("/sapi/solvers/remote")).to_uri());
// Execute HTTP Get
auto getResponse = getClient.request(getRequest);
// get the result as a string
std::stringstream ss;
ss << r.content.rdbuf();
ss << getResponse.get().extract_json().get();
auto message = ss.str();
Document document;
......
......@@ -32,7 +32,6 @@
#define QUANTUM_GATE_ACCELERATORS_DWACCELERATOR_HPP_
#include "Accelerator.hpp"
#include "AsioNetworkingTool.hpp"
#include "RuntimeOptions.hpp"
#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
......@@ -157,98 +156,12 @@ public:
return desc;
}
virtual bool handleOptions(variables_map& map){
if(map.count("dwave-list-solvers")) {
std::string tempApiKey, tempUrl;
auto findApiKeyInFile = [](std::string& apiKey, std::string& url,
boost::filesystem::path &p) {
std::ifstream stream(p.string());
std::string contents(
(std::istreambuf_iterator<char>(stream)),
std::istreambuf_iterator<char>());
std::vector<std::string> lines;
boost::split(lines, contents, boost::is_any_of("\n"));
for (auto l : lines) {
if (boost::contains(l, "key")) {
std::vector<std::string> split;
boost::split(split, l, boost::is_any_of(":"));
auto key = split[1];
boost::trim(key);
apiKey = key;
} else if (boost::contains(l, "url")) {
std::vector<std::string> split;
boost::split(split, l, boost::is_any_of(":"));
auto key = split[1] + ":" + split[2];
boost::trim(key);
url = key;
}
}
};
auto searchAPIKey = [&](std::string& key, std::string& url) {
// Search for the API Key in $HOME/.dwave_config,
// $DWAVE_CONFIG, or in the command line argument --dwave-api-key
auto options = RuntimeOptions::instance();
boost::filesystem::path dwaveConfig(
std::string(getenv("HOME")) + "/.dwave_config");
if (boost::filesystem::exists(dwaveConfig)) {
findApiKeyInFile(key, url, dwaveConfig);
} else if (const char * nonStandardPath = getenv("DWAVE_CONFIG")) {
boost::filesystem::path nonStandardDwaveConfig(
nonStandardPath);
findApiKeyInFile(key, url, nonStandardDwaveConfig);
} else {
// Ensure that the user has provided an api-key
if (!options->exists("dwave-api-key")) {
XACCError("Cannot list D-Wave solvers without API Key.");
}
// Set the API Key
key = (*options)["dwave-api-key"];
if (options->exists("dwave-api-url")) {
url = (*options)["dwave-api-url"];
}
}
// If its still empty, then we have a problem
if (key.empty()) {
XACCError("Error. The API Key is empty. Please place it "
"in your $HOME/.dwave_config file, $DWAVE_CONFIG env var, "
"or provide --dwave-api-key argument.");
}
};
searchAPIKey(tempApiKey, tempUrl);
boost::replace_all(tempUrl, "https://", "");
boost::replace_all(tempUrl, "/sapi", "");
std::map<std::string, std::string> headers;
// Set up the extra HTTP headers we are going to need
headers.insert(std::make_pair("X-Auth-Token", tempApiKey));
headers.insert(std::make_pair("Content-type", "application/x-www-form-urlencoded"));
headers.insert(std::make_pair("Accept", "*/*"));
// Get the Remote URL Solver data...
auto getSolverClient = fire::util::AsioNetworkingTool<SimpleWeb::HTTPS>(tempUrl, false);
auto r = getSolverClient.get("/sapi/solvers/remote", headers);
std::stringstream ss;
ss << r.content.rdbuf();
auto message = ss.str();
Document document;
document.Parse(message.c_str());
if (document.IsArray()) {
for (auto i = 0; i < document.Size(); i++) {
XACCInfo("Available D-Wave Solver: " + std::string(document[i]["id"].GetString()));
}
virtual bool handleOptions(variables_map& map) {
if (map.count("dwave-list-solvers")) {
initialize();
for (auto s : availableSolvers) {
XACCInfo("Available D-Wave Solver: " + std::string(s.first));
}
return true;
}
......@@ -269,20 +182,7 @@ public:
* @return buffer The AcceleratorBuffer
*/
virtual std::shared_ptr<AcceleratorBuffer> createBuffer(
const std::string& varId) {
auto options = RuntimeOptions::instance();
std::string solverName = "DW_2000Q_VFYC";
if (options->exists("dwave-solver")) {
solverName = (*options)["dwave-solver"];
}
if (!availableSolvers.count(solverName)) {
XACCError(solverName + " is not available for creating a buffer.");
}
auto solver = availableSolvers[solverName];
auto buffer = std::make_shared<AQCAcceleratorBuffer>(varId, solver.nQubits);
storeBuffer(varId, buffer);
return buffer;
}
const std::string& varId);
virtual const std::string name() const {
return "dwave";
......
......@@ -37,78 +37,35 @@
using namespace xacc::quantum;
class FakeHttpClient: public fire::util::INetworkingTool {
public:
bool postOccured = false;
virtual fire::util::HttpResponse get(const std::string& relativePath,
const std::map<std::string, std::string>& header = std::map<
std::string, std::string>()) {
std::stringstream ss;
ss << "HELLO\n";
fire::util::HttpResponse r(ss);
r.successful = true;
return r;
}
/**
* Issue an HTTP Post command at the given relative path with
* the provided message. Clients can provide a map of header key values to modify the
* POST request.
*
* @param relativePath The path relative to the hostname/port provided to this NetworkingTool
* @param message The message to post
* @param header The map of additional HTTP POST header information
* @return success Boolean indicating if post was successful
*
*/
virtual fire::util::HttpResponse post(const std::string& relativePath,
const std::string& message,
const std::map<std::string, std::string>& header = std::map<
std::string, std::string>()) {
postOccured = true;
std::stringstream ss;
ss << "HELLO\n";
fire::util::HttpResponse r(ss);
r.successful = true;
return r;
}
};
BOOST_AUTO_TEST_CASE(checkKernelExecution) {
auto options = RuntimeOptions::instance();
// auto options = RuntimeOptions::instance();
//
// DWAccelerator acc;
// acc.initialize();
// auto buffer = acc.createBuffer("qubits");
auto f = std::make_shared<DWKernel>("simple");
f->addInstruction(std::make_shared<DWQMI>(0, 0, 20));
f->addInstruction(std::make_shared<DWQMI>(1, 1, 50));
f->addInstruction(std::make_shared<DWQMI>(2, 2, 60));
f->addInstruction(std::make_shared<DWQMI>(4, 4, 50));
f->addInstruction(std::make_shared<DWQMI>(5, 5, 60));
f->addInstruction(std::make_shared<DWQMI>(6, 6, -160));
f->addInstruction(std::make_shared<DWQMI>(1, 4, -1000));
f->addInstruction(std::make_shared<DWQMI>(2, 5, -1000));
f->addInstruction(std::make_shared<DWQMI>(0, 4, -14));
f->addInstruction(std::make_shared<DWQMI>(0, 5, -12));
f->addInstruction(std::make_shared<DWQMI>(0, 6, 32));
f->addInstruction(std::make_shared<DWQMI>(1, 5, 68));
f->addInstruction(std::make_shared<DWQMI>(1, 6, -128));
f->addInstruction(std::make_shared<DWQMI>(2, 6, -128));
//
// auto f = std::make_shared<DWKernel>("simple");
//
// f->addInstruction(std::make_shared<DWQMI>(0, 0, 20));
// f->addInstruction(std::make_shared<DWQMI>(1, 1, 50));
// f->addInstruction(std::make_shared<DWQMI>(2, 2, 60));
// f->addInstruction(std::make_shared<DWQMI>(4, 4, 50));