Commit ef7e3a54 authored by Nguyen, Thien Minh's avatar Nguyen, Thien Minh
Browse files

Added a runtime hook to connect use the mirror circuit validation


Signed-off-by: Nguyen, Thien Minh's avatarThien Nguyen <nguyentm@ornl.gov>
parent fd2bca29
......@@ -157,8 +157,60 @@ getLayer(std::shared_ptr<xacc::CompositeInstruction> circuit, int layerId) {
} // namespace
namespace qcor {
std::pair<bool, xacc::HeterogeneousMap> MirrorCircuitValidator::validate(
std::shared_ptr<xacc::Accelerator> qpu,
std::shared_ptr<qcor::CompositeInstruction> program,
xacc::HeterogeneousMap options) {
// Some default values
int n_trials = 1000;
// 10% error allowed... (away from the expected bitstring)
double eps = 0.1;
int n_shots = 1024;
if (options.keyExists<int>("trials")) {
n_trials = options.get<int>("trials");
}
if (options.keyExists<double>("epsilon")) {
eps = options.get<double>("epsilon");
}
qpu->updateConfiguration({{"shots", n_shots}});
std::vector<double> trial_success_probs;
auto provider = xacc::getIRProvider("quantum");
for (int i = 0; i < n_trials; ++i) {
auto [mirror_circuit, expected_result] =
qcor::MirrorCircuitValidator::createMirrorCircuit(program);
const std::string expectedBitString = [&]() {
std::string bitStr;
for (const auto &bit : expected_result) {
bitStr += std::to_string(bit);
}
return bitStr;
}();
for (size_t qId = 0; qId < mirror_circuit->nPhysicalBits(); ++qId) {
mirror_circuit->addInstruction(
provider->createInstruction("Measure", {qId}));
}
auto mc_buffer = xacc::qalloc(mirror_circuit->nPhysicalBits());
qpu->execute(mc_buffer, mirror_circuit->as_xacc());
// mc_buffer->print();
const auto bitStrProb =
mc_buffer->computeMeasurementProbability(expectedBitString);
trial_success_probs.emplace_back(bitStrProb);
}
xacc::HeterogeneousMap data;
data.insert("trial-success-probabilities", trial_success_probs);
const bool pass_fail_result =
std::all_of(trial_success_probs.begin(), trial_success_probs.end(),
[&eps](double val) { return val > 1.0 - eps; });
return std::make_pair(pass_fail_result, data);
}
std::pair<std::shared_ptr<CompositeInstruction>, std::vector<bool>>
createMirrorCircuit(std::shared_ptr<CompositeInstruction> in_circuit) {
MirrorCircuitValidator::createMirrorCircuit(std::shared_ptr<CompositeInstruction> in_circuit) {
std::vector<std::shared_ptr<xacc::Instruction>> mirrorCircuit;
auto gateProvider = xacc::getService<xacc::IRProvider>("quantum");
......
......@@ -3,11 +3,19 @@
#include <vector>
#include <string>
#include <utility>
#include "qrt.hpp"
// !Temporary: we'll figure out an interface for this later:
namespace qcor {
class CompositeInstruction;
// Return the 'mirrored' circuit along with the expected result.
std::pair<std::shared_ptr<CompositeInstruction>, std::vector<bool>>
createMirrorCircuit(std::shared_ptr<CompositeInstruction> in_circuit);
class MirrorCircuitValidator : public BackendValidator {
public:
virtual const std::string name() const override { return "mirror-rb"; }
virtual const std::string description() const override { return ""; }
virtual std::pair<bool, xacc::HeterogeneousMap>
validate(std::shared_ptr<xacc::Accelerator> qpu,
std::shared_ptr<qcor::CompositeInstruction> program,
xacc::HeterogeneousMap options) override;
// Return the 'mirrored' circuit along with the expected result.
static std::pair<std::shared_ptr<CompositeInstruction>, std::vector<bool>>
createMirrorCircuit(std::shared_ptr<CompositeInstruction> in_circuit);
};
} // namespace qcor
......@@ -25,7 +25,7 @@ TEST(MirrorCircuitTester, checkU3Inverse) {
const double lambda = random_angle();
circuit->addInstruction(provider->createInstruction(
"U", {0}, std::vector<xacc::InstructionParameter>{theta, phi, lambda}));
auto [mirror_cir, expected_result] = qcor::createMirrorCircuit(
auto [mirror_cir, expected_result] = qcor::MirrorCircuitValidator::createMirrorCircuit(
std::make_shared<qcor::CompositeInstruction>(circuit));
EXPECT_EQ(expected_result.size(), 1);
EXPECT_EQ(mirror_cir->nInstructions(), 2);
......@@ -66,7 +66,7 @@ TEST(MirrorCircuitTester, checkMultipleU3) {
const double lambda2 = random_angle();
circuit->addInstruction(provider->createInstruction(
"U", {1}, std::vector<xacc::InstructionParameter>{theta2, phi2, lambda2}));
auto [mirror_cir, expected_result] = qcor::createMirrorCircuit(
auto [mirror_cir, expected_result] = qcor::MirrorCircuitValidator::createMirrorCircuit(
std::make_shared<qcor::CompositeInstruction>(circuit));
EXPECT_EQ(expected_result.size(), 2);
EXPECT_EQ(mirror_cir->nInstructions(), 4);
......@@ -112,7 +112,7 @@ TEST(MirrorCircuitTester, checkCliffordGates) {
circuit->addInstruction(provider->createInstruction("CNOT", {0, 1}));
circuit->addInstruction(provider->createInstruction("H", {0}));
circuit->addInstruction(provider->createInstruction("H", {1}));
auto [mirror_cir, expected_result] = qcor::createMirrorCircuit(
auto [mirror_cir, expected_result] = qcor::MirrorCircuitValidator::createMirrorCircuit(
std::make_shared<qcor::CompositeInstruction>(circuit));
const std::string expectedBitString =
std::to_string(expected_result[0]) + std::to_string(expected_result[1]);
......@@ -145,17 +145,17 @@ TEST(MirrorCircuitTester, checkDeuteron) {
circuit->addInstruction(provider->createInstruction(
"Ry", {1}, std::vector<xacc::InstructionParameter>{random_angle()}));
circuit->addInstruction(provider->createInstruction("CNOT", {1, 0}));
auto [mirror_cir, expected_result] = qcor::createMirrorCircuit(
auto [mirror_cir, expected_result] = qcor::MirrorCircuitValidator::createMirrorCircuit(
std::make_shared<qcor::CompositeInstruction>(circuit));
std::cout << "Expected: " << expected_result[0] << expected_result[1] << "\n";
std::cout << "HOWDY: \n" << mirror_cir->toString() << "\n";
// std::cout << "Expected: " << expected_result[0] << expected_result[1] << "\n";
// std::cout << "HOWDY: \n" << mirror_cir->toString() << "\n";
auto mirror_circuit = provider->createComposite("test_mirror");
mirror_circuit->addInstructions(mirror_cir->getInstructions());
mirror_circuit->addInstruction(provider->createInstruction("Measure", {0}));
mirror_circuit->addInstruction(provider->createInstruction("Measure", {1}));
auto mc_buffer = xacc::qalloc(2);
accelerator->execute(mc_buffer, mirror_circuit);
mc_buffer->print();
// mc_buffer->print();
const std::string expectedBitString =
std::to_string(expected_result[0]) + std::to_string(expected_result[1]);
EXPECT_EQ(mc_buffer->getMeasurementCounts().size(), 1);
......
......@@ -89,7 +89,18 @@ std::string get_native_code(std::shared_ptr<qcor::CompositeInstruction> program,
xacc::HeterogeneousMap options) {
return get_qpu()->getNativeCode(program->as_xacc(), options);
}
} // namespace internal_compiler
std::pair<bool, xacc::HeterogeneousMap>
validate_backend_execution(std::shared_ptr<qcor::CompositeInstruction> program,
xacc::HeterogeneousMap options) {
// FWIW, we only have this method...
static const std::string DEFAULT_METHOD = "mirror-rb";
auto validate_program =
program ? program : ::quantum::qrt_impl->get_current_program();
auto validator = xacc::getService<qcor::BackendValidator>(DEFAULT_METHOD);
return validator->validate(get_qpu(), validate_program, options);
}
} // namespace internal_compiler
} // namespace xacc
namespace quantum {
int current_shots = 0;
......
......@@ -13,6 +13,7 @@ namespace qcor {
using namespace xacc::internal_compiler;
namespace xacc {
class Accelerator;
class AcceleratorBuffer;
// class CompositeInstruction;
class Instruction;
......@@ -256,6 +257,13 @@ void execute_pass_manager(
std::shared_ptr<qcor::CompositeInstruction> optional_composite = nullptr);
std::string get_native_code(std::shared_ptr<qcor::CompositeInstruction> program,
xacc::HeterogeneousMap options);
// Hook to validate backend execution of a circuit
// e.g., via circuit mirror technique
// returns a pass/fail bool along with a untyped result data.
// options data may include method-specific configurations.
std::pair<bool, xacc::HeterogeneousMap> validate_backend_execution(
std::shared_ptr<qcor::CompositeInstruction> program = nullptr,
xacc::HeterogeneousMap options = {});
} // namespace internal_compiler
} // namespace xacc
namespace qcor {
......@@ -280,5 +288,15 @@ protected:
std::vector<xacc::internal_compiler::qubit *> m_allocatedQubits;
std::shared_ptr<xacc::AcceleratorBuffer> m_buffer;
};
// An abstract interface for backend validator
class BackendValidator : public xacc::Identifiable {
public:
// This interface is WIP: we just make it as generic as possible.
virtual std::pair<bool, xacc::HeterogeneousMap>
validate(std::shared_ptr<xacc::Accelerator> qpu,
std::shared_ptr<qcor::CompositeInstruction> program,
xacc::HeterogeneousMap options = {}) = 0;
};
} // namespace qcor
#endif
\ No newline at end of file
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