Unverified Commit fb36089b authored by Mccaskey, Alex's avatar Mccaskey, Alex Committed by GitHub
Browse files

Merge pull request #396 from tnguyen-ornl/tnguyen/config-parser

Added an INI-style config file parser
parents 7af6eeae e3188341
Pipeline #135808 passed with stage
in 20 minutes
......@@ -183,8 +183,8 @@ final_distance = get_distance(ans, umat)
py::buffer_info buffer = gateMat.request();
const size_t nbRows = buffer.shape[0];
const size_t nbCols = buffer.shape[1];
assert(nbRows = 4);
assert(nbCols = 4);
assert(nbRows == 4);
assert(nbCols == 4);
std::complex<double> *buffer_ptr = (std::complex<double> *)buffer.ptr;
std::vector<std::complex<double>> gateUnitaryFlatten;
gateUnitaryFlatten.assign(buffer_ptr, buffer_ptr + nbRows * nbCols);
......
......@@ -128,4 +128,5 @@ install(TARGETS xacc DESTINATION lib)
add_subdirectory(optimizer)
add_subdirectory(utils/exprtk_parsing)
add_subdirectory(ir/graph-impl)
\ No newline at end of file
add_subdirectory(ir/graph-impl)
add_subdirectory(utils/ini_config_parsing)
......@@ -2,7 +2,9 @@
#include "Instruction.hpp"
#include "Utils.hpp"
#include "heterogeneous.hpp"
#include "config_file_parser.hpp"
#include "xacc.hpp"
#include "xacc_service.hpp"
#include "InstructionIterator.hpp"
#include <CompositeInstruction.hpp>
#include <stdlib.h>
......@@ -55,18 +57,35 @@ auto process_qpu_backend_str = [](const std::string &qpu_backend_str)
auto tmp = split(key_value, ':');
auto key = tmp[0];
auto value = tmp[1];
// check if int first, then double,
// finally just throw it in as a string
try {
auto i = std::stoi(value);
options.insert(key, i);
} catch (std::exception &e) {
if (key == "qcor_qpu_config") {
// If the config is provided in a file:
// We could check for file extension here to
// determine a parsing plugin.
// Currently, we only support a simple key-value format (INI like).
// e.g.
// String like config:
// name=XACC
// Boolean configs
// true_val=true
// false_val=false
// Array/vector configs
// array=[1,2,3]
// array_double=[1.0,2.0,3.0]
auto parser = xacc::getService<ConfigFileParsingUtil>("ini");
options = parser->parse(value);
} else {
// check if int first, then double,
// finally just throw it in as a string
try {
auto d = std::stod(value);
options.insert(key, d);
auto i = std::stoi(value);
options.insert(key, i);
} catch (std::exception &e) {
options.insert(key, value);
try {
auto d = std::stod(value);
options.insert(key, d);
} catch (std::exception &e) {
options.insert(key, value);
}
}
}
}
......
#pragma once
#include "heterogeneous.hpp"
#include "Identifiable.hpp"
namespace xacc {
// Parse a config file to a HeterogeneousMap
class ConfigFileParsingUtil : public Identifiable {
public:
virtual HeterogeneousMap parse(const std::string &in_fileName) = 0;
};
} // namespace xacc
\ No newline at end of file
# *******************************************************************************
# 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 v.10 which accompany 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
# *******************************************************************************/
set(LIBRARY_NAME xacc-ini-config-parsing)
file(GLOB SRC ini_config_parser.cpp)
usfunctiongetresourcesource(TARGET ${LIBRARY_NAME} OUT SRC)
usfunctiongeneratebundleinit(TARGET ${LIBRARY_NAME} OUT SRC)
add_library(${LIBRARY_NAME} SHARED ${SRC})
target_include_directories(
${LIBRARY_NAME}
PRIVATE ${BOOST_SOURCE})
target_link_libraries(${LIBRARY_NAME} PUBLIC xacc)
set(_bundle_name xacc_ini_config_parsing)
set_target_properties(${LIBRARY_NAME}
PROPERTIES COMPILE_DEFINITIONS
US_BUNDLE_NAME=${_bundle_name}
US_BUNDLE_NAME
${_bundle_name})
usfunctionembedresources(TARGET
${LIBRARY_NAME}
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
FILES
manifest.json)
if(APPLE)
set_target_properties(${LIBRARY_NAME}
PROPERTIES INSTALL_RPATH "@loader_path/../lib")
set_target_properties(${LIBRARY_NAME}
PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
else()
set_target_properties(${LIBRARY_NAME}
PROPERTIES INSTALL_RPATH "$ORIGIN/../lib")
set_target_properties(${LIBRARY_NAME} PROPERTIES LINK_FLAGS "-shared")
endif()
if(XACC_BUILD_TESTS)
add_subdirectory(tests)
endif()
install(TARGETS ${LIBRARY_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/plugins)
/*******************************************************************************
* 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 "xacc_plugin.hpp"
#include "config_file_parser.hpp"
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/lexical_cast.hpp>
namespace {
template <typename T>
bool addPrimitiveFieldToMap(const std::string &in_fieldPath,
const boost::property_tree::ptree &in_ptree,
xacc::HeterogeneousMap &io_mapToAdd) {
try {
T val = in_ptree.get<T>(in_fieldPath);
// std::cout << in_fieldPath << " --> " << val << "\n";
io_mapToAdd.insert(in_fieldPath, val);
return true;
} catch (...) {
return false;
}
}
bool isContainerField(const std::string &in_fieldName,
const boost::property_tree::ptree &in_tree) {
const std::string fieldAsString = in_tree.get<std::string>(in_fieldName);
return !fieldAsString.empty() && fieldAsString.front() == '[' &&
fieldAsString.back() == ']';
}
template <typename T> std::vector<T> to_array(const std::string &s) {
std::vector<T> result;
std::string arrayStr = s.substr(1, s.size() - 2);
std::stringstream ss(arrayStr);
std::string item;
while (std::getline(ss, item, ',')) {
result.emplace_back(boost::lexical_cast<T>(item));
}
return result;
}
template <>
std::vector<std::pair<int, int>>
to_array<std::pair<int, int>>(const std::string &s) {
std::string arrayStr = s;
arrayStr.erase(std::remove_if(arrayStr.begin(), arrayStr.end(), isspace),
arrayStr.end());
std::vector<std::pair<int, int>> result;
arrayStr = arrayStr.substr(1, s.size() - 2);
std::stringstream ss(arrayStr);
std::string pairItem;
while (std::getline(ss, pairItem, ']')) {
pairItem += ']';
const std::vector<int> pairAsVec = to_array<int>(pairItem);
if (pairAsVec.size() == 2) {
result.emplace_back(std::make_pair(pairAsVec[0], pairAsVec[1]));
}
std::string temp;
std::getline(ss, pairItem, ',');
}
return result;
}
template <typename T>
bool addArrayFieldToMap(const std::string &in_fieldPath,
const boost::property_tree::ptree &in_ptree,
xacc::HeterogeneousMap &io_mapToAdd) {
try {
auto array = to_array<T>(in_ptree.get<std::string>(in_fieldPath));
io_mapToAdd.insert(in_fieldPath, array);
return true;
} catch (...) {
return false;
}
}
} // namespace
namespace xacc {
class IniFileParsingUtil : public ConfigFileParsingUtil {
public:
HeterogeneousMap parse(const std::string &in_fileName) override {
// TODO: check file exists
boost::property_tree::ptree parsedTree;
boost::property_tree::ini_parser::read_ini(in_fileName, parsedTree);
HeterogeneousMap result;
for (const auto &it : parsedTree) {
// std::cout << it.first << ": " << it.second.data() << "\n";
if (isContainerField(it.first, parsedTree)) {
for (auto &converter : CONTAINER_TYPE_CONVERTERS) {
if (converter(it.first, parsedTree, result)) {
break;
}
}
} else {
for (auto &converter : PRIMITIVE_TYPE_CONVERTERS) {
if (converter(it.first, parsedTree, result)) {
break;
}
}
}
}
return result;
}
const std::string name() const override { return "ini"; }
const std::string description() const override {
return "Parse config file in INI format";
}
private:
using AddFieldFnType = std::function<bool(const std::string &,
const boost::property_tree::ptree &,
HeterogeneousMap &)>;
static inline const std::vector<AddFieldFnType> PRIMITIVE_TYPE_CONVERTERS{
addPrimitiveFieldToMap<int>, addPrimitiveFieldToMap<double>,
addPrimitiveFieldToMap<bool>, addPrimitiveFieldToMap<std::string>};
static inline const std::vector<AddFieldFnType> CONTAINER_TYPE_CONVERTERS{
addArrayFieldToMap<int>, addArrayFieldToMap<double>,
addArrayFieldToMap<std::pair<int, int>>};
};
} // namespace xacc
REGISTER_PLUGIN(xacc::IniFileParsingUtil, xacc::ConfigFileParsingUtil)
\ No newline at end of file
{
"bundle.symbolic_name" : "xacc_ini_config_parsing",
"bundle.activator" : true,
"bundle.name" : "XACC INI file parsing utility",
"bundle.description" : ""
}
# *******************************************************************************
# 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 v.10 which accompany 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
# *******************************************************************************/
add_xacc_test(IniFileParsing)
target_link_libraries(IniFileParsingTester xacc)
target_compile_definitions(IniFileParsingTester PRIVATE INI_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}/resources")
/*******************************************************************************
* 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 <gtest/gtest.h>
#include "xacc.hpp"
#include "xacc_service.hpp"
#include "config_file_parser.hpp"
using namespace xacc;
TEST(IniFileParsingTester, checkSimple) {
const std::string testFile = std::string(INI_SOURCE_DIR) + "/test1.ini";
auto parser = xacc::getService<ConfigFileParsingUtil>("ini");
auto config = parser->parse(testFile);
EXPECT_EQ(config.get<int>("one"), 1);
EXPECT_NEAR(config.get<double>("pi"), M_PI, 0.01);
EXPECT_EQ(config.getString("name"), "XACC");
EXPECT_TRUE(config.get<bool>("true_val"));
EXPECT_FALSE(config.get<bool>("false_val"));
}
TEST(IniFileParsingTester, checkArrays) {
const std::string testFile = std::string(INI_SOURCE_DIR) + "/test1.ini";
auto parser = xacc::getService<ConfigFileParsingUtil>("ini");
auto config = parser->parse(testFile);
const auto intArray = config.get<std::vector<int>>("array");
EXPECT_EQ(intArray.size(), 3);
for (int i = 0; i < intArray.size(); ++i) {
EXPECT_EQ(intArray[i], i + 1);
}
const auto doubleArray = config.get<std::vector<double>>("array_double");
EXPECT_EQ(doubleArray.size(), 3);
for (int i = 0; i < doubleArray.size(); ++i) {
EXPECT_NEAR(doubleArray[i], 1.0 * (i + 1), 1e-12);
}
const auto connectivity =
config.get<std::vector<std::pair<int, int>>>("connectivity");
EXPECT_EQ(connectivity.size(), 3);
for (int i = 0; i < connectivity.size(); ++i) {
std::cout << connectivity[i].first << "-->" << connectivity[i].second
<< "\n";
}
}
int main(int argc, char **argv) {
xacc::Initialize(argc, argv);
::testing::InitGoogleTest(&argc, argv);
auto ret = RUN_ALL_TESTS();
xacc::Finalize();
return ret;
}
one=1
pi=3.14
name=XACC
true_val=true
false_val=false
; Simple Array
array=[1,2,3]
array_double=[1.0,2.0,3.0]
; Array of arrays (e.g. connectivity graph)
connectivity=[[0, 1], [0, 2], [1, 2]]
Supports Markdown
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