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

Merge pull request #392 from jhuber6/verifier

Add IR verification interface and QCEC implementation
parents 7af6eeae f5bd40db
......@@ -13,6 +13,7 @@
#include "py_ir.hpp"
#include "CompositeInstruction.hpp"
#include "IRTransformation.hpp"
#include "IRVerifier.hpp"
#include "heterogeneous.hpp"
#include "xacc.hpp"
#include "xacc_service.hpp"
......@@ -217,7 +218,6 @@ void bind_ir(py::module &m) {
"")
.def(
"createIR", [](IRProvider &p) { return p.createIR(); }, "");
// Expose the IR interface
py::class_<xacc::IR, std::shared_ptr<xacc::IR>>(
m, "IR",
......@@ -263,4 +263,26 @@ void bind_ir(py::module &m) {
},
py::arg("k"), py::arg("acc"),
py::arg("options") = PyHeterogeneousMap(), "");
}
\ No newline at end of file
py::class_<xacc::IRVerifier, std::shared_ptr<xacc::IRVerifier>>(
m, "IRVerifier", "")
.def(
"verify",
[](IRVerifier &v, std::shared_ptr<CompositeInstruction> o,
std::shared_ptr<CompositeInstruction> t,
const PyHeterogeneousMap &options = {}) {
HeterogeneousMap m;
for (auto &item : options) {
PyHeterogeneousMap2HeterogeneousMap vis(m, item.first);
mpark::visit(vis, item.second);
}
return v.verify(o, t, m);
},
py::arg("o"), py::arg("t"), py::arg("options") = PyHeterogeneousMap(),
"");
m.def(
"getVerifier",
[](const std::string name) {
return xacc::getService<xacc::IRVerifier>(name);
},
"");
}
......@@ -22,6 +22,7 @@ add_subdirectory(ionq)
add_subdirectory(placement)
#add_subdirectory(scaffold)
add_subdirectory(xasm)
add_subdirectory(verifiers)
add_subdirectory(qpp)
add_subdirectory(staq)
add_subdirectory(observable_transforms)
......
option(XACC_ENABLE_QCEC "Build QCEC IR Verifier" OFF)
if (XACC_ENABLE_QCEC)
add_subdirectory(qcec)
endif()
set(LIBRARY_NAME xacc-verifier-qcec)
set(QCEC_INSTALL_ROOT "/usr/local" CACHE PATH "QCEC installation directory")
set(JSON_INSTALL_ROOT "/usr/local" CACHE PATH "nlohmann JSON installation directory")
list(APPEND CMAKE_PREFIX_PATH "${QCEC_INSTALL_ROOT}/lib/cmake/DDpackage/")
list(APPEND CMAKE_PREFIX_PATH "${QCEC_INSTALL_ROOT}/lib/cmake/qcec/")
list(APPEND CMAKE_PREFIX_PATH "${QCEC_INSTALL_ROOT}/lib/cmake/qfr/")
list(APPEND CMAKE_PREFIX_PATH "${JSON_INSTALL_ROOT}/lib/cmake/")
find_package(qcec REQUIRED CONFIG)
find_package(nlohmann_json 3.2.0 REQUIRED CONFIG)
usfunctiongetresourcesource(TARGET ${LIBRARY_NAME} OUT SRC)
usfunctiongeneratebundleinit(TARGET ${LIBRARY_NAME} OUT SRC)
add_library(${LIBRARY_NAME} SHARED ${SRC})
target_include_directories(${LIBRARY_NAME}
PUBLIC JKQ::qcec
nlohmann_json::nlohmann_json
)
target_link_libraries(${LIBRARY_NAME}
PUBLIC xacc
xacc-quantum-gate
JKQ::qcec
nlohmann_json::nlohmann_json
)
target_sources(${LIBRARY_NAME} PRIVATE
qcec.cpp)
set(_bundle_name xacc_verfier_qcec)
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)
{
"bundle.symbolic_name" : "xacc_verfier_qcec",
"bundle.activator" : true,
"bundle.name" : "XACC qcec circuit equivalence checker",
"bundle.description" : "This bundle provides equivalence checking of transforms through qcec"
}
#include "xacc.hpp"
#include "qcec.hpp"
#include "CompilationFlowEquivalenceChecker.hpp"
#include "EquivalenceChecker.hpp"
#include "IRVerifier.hpp"
#include "ImprovedDDEquivalenceChecker.hpp"
#include "PowerOfSimulationEquivalenceChecker.hpp"
#include "xacc_plugin.hpp"
#include <unordered_map>
#include <iostream>
#include <sstream>
#include <fstream>
namespace xacc {
namespace quantum {
const std::unordered_map<std::string, ec::Method> strToMethod = {
{"reference", ec::Reference},
{"naive", ec::Naive},
{"proportional", ec::Proportional},
{"lookahead", ec::Lookahead},
{"simulation", ec::PowerOfSimulation},
{"compilationflow", ec::CompilationFlow}};
const std::unordered_map<std::string, ec::StimuliType> strToStimuli = {
{"classical", ec::Classical},
{"localquantum", ec::LocalQuantum},
{"globalquantum", ec::GlobalQuantum}};
std::pair<bool, std::string>
getResults(ec::EquivalenceCheckingResults &result) {
auto &equivalence = result.equivalence;
if (equivalence == ec::NoInformation || result.error())
return {false, "{\"error\":\"No equivalence information avalible\""};
result.name1 = "original";
result.name2 = "transformed";
if (equivalence == ec::Equivalent || equivalence == ec::ProbablyEquivalent ||
equivalence == ec::EquivalentUpToGlobalPhase)
return {true, result.produceJSON(true).dump()};
return {false, result.produceJSON(true).dump()};
}
static std::string writeTempFile(const std::string &str) {
auto &&hash = std::hash<std::string>{};
auto filename = "/tmp/xacc-verifier-" + std::to_string(hash(str)) + ".qasm";
std::ofstream(filename) << str;
return filename;
}
std::pair<bool, std::string>
qcec::verify(std::shared_ptr<CompositeInstruction> original,
std::shared_ptr<CompositeInstruction> transformed,
const HeterogeneousMap &options) {
auto staq = xacc::getCompiler("staq");
auto originalFile = writeTempFile(staq->translate(original));
auto transformedFile = writeTempFile(staq->translate(transformed));
qc::QuantumComputation originalQC(originalFile);
qc::QuantumComputation transformedQC(transformedFile);
std::remove(originalFile.c_str());
std::remove(transformedFile.c_str());
ec::Method method = ec::Proportional;
ec::Configuration config{};
if (options.stringExists("method"))
method = strToMethod.at(options.getString("method"));
if (options.stringExists("stimuli"))
config.stimuliType = strToStimuli.at(options.getString("stimuli"));
if (options.stringExists("numsims"))
config.max_sims = options.get<unsigned long>("numsims");
if (options.stringExists("tolerance"))
config.tolerance = options.get<double>("tolerance");
if (options.stringExists("fidelity"))
config.fidelity_limit =
std::clamp(options.get<double>("fidelity"), 0.0, 1.0);
if (method == ec::CompilationFlow) {
ec::CompilationFlowEquivalenceChecker ec(originalQC, transformedQC);
ec.expectNothing();
ec.check(config);
return getResults(ec.results);
} else if (method == ec::PowerOfSimulation) {
ec::PowerOfSimulationEquivalenceChecker ec(originalQC, transformedQC);
ec.expectNothing();
ec.check(config);
return getResults(ec.results);
} else {
ec::ImprovedDDEquivalenceChecker ec(originalQC, transformedQC, method);
ec.expectNothing();
ec.check(config);
return getResults(ec.results);
}
return {false, "{\"error\":\"No verification method used\""};
}
} // namespace quantum
} // namespace xacc
REGISTER_PLUGIN(xacc::quantum::qcec, xacc::IRVerifier)
#pragma once
#include "IRVerifier.hpp"
namespace xacc {
namespace quantum {
class qcec : public IRVerifier {
std::pair<bool, std::string>
verify(std::shared_ptr<CompositeInstruction> original,
std::shared_ptr<CompositeInstruction> transformed,
const HeterogeneousMap &options = {}) override;
const std::string name() const override { return "qcec"; }
const std::string description() const override { return ""; }
};
} // namespace quantum
} // namespace xacc
# *******************************************************************************
# 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:
# Thien Nguyen - initial API and implementation
# *******************************************************************************/
add_xacc_test(qcec)
target_link_libraries(qcecTester xacc xacc-quantum-gate)
/*******************************************************************************
* 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:
* Joseph N. Huber - Initial API and implementation
*******************************************************************************/
#include <gtest/gtest.h>
#include "IRVerifier.hpp"
#include "xacc.hpp"
#include "xacc_service.hpp"
TEST(qcecTester, checkSimpleHadamard) {
auto verifier = xacc::getService<xacc::IRVerifier>("qcec");
auto xasmCompiler = xacc::getCompiler("xasm");
auto program1 = xasmCompiler
->compile(R"(__qpu__ void test1(qbit q) {
H(q[0]);
H(q[0]);
H(q[0]);
CX(q[0], q[1]);
Measure(q[0]);
Measure(q[1]);
})")
->getComposites()[0];
auto program2 = xasmCompiler
->compile(R"(__qpu__ void test2(qbit q) {
H(q[0]);
CX(q[0], q[1]);
Measure(q[0]);
Measure(q[1]);
})")
->getComposites()[0];
EXPECT_TRUE(
verifier->verify(program1, program2, {{"method", "lookahead"}}).first);
}
TEST(qcecTester, checkUnequivalent) {
auto verifier = xacc::getService<xacc::IRVerifier>("qcec");
auto xasmCompiler = xacc::getCompiler("xasm");
auto program1 = xasmCompiler
->compile(R"(__qpu__ void test1(qbit q) {
H(q[0]);
CX(q[0], q[1]);
})")
->getComposites()[0];
auto program2 = xasmCompiler
->compile(R"(__qpu__ void test2(qbit q) {
H(q[0]);
CY(q[0], q[1]);
})")
->getComposites()[0];
EXPECT_FALSE(verifier
->verify(program1, program2,
{{"method", "simulation"},
{"stimuli", "globalquantum"},
{"numsims", 20}})
.first);
}
int main(int argc, char **argv) {
xacc::Initialize();
::testing::InitGoogleTest(&argc, argv);
const auto result = RUN_ALL_TESTS();
xacc::Finalize();
return result;
}
#pragma once
#include "CompositeInstruction.hpp"
#include "Identifiable.hpp"
namespace xacc {
class IRVerifier : public Identifiable {
public:
virtual std::pair<bool, std::string>
verify(std::shared_ptr<CompositeInstruction> original,
std::shared_ptr<CompositeInstruction> transformed,
const HeterogeneousMap &options = {}) = 0;
virtual ~IRVerifier() = default;
};
} // namespace xacc
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