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

Merge pull request #149 from kharazity/error-kernel

fixes to Assignment Error Kernel, added additional info for returned …
parents 44e63c95 a4d8a117
import xacc
import numpy as np
qpu = xacc.getAccelerator('aer', {'readout_error': True, 'gate_error': True,\
'thermal_relaxation':True, 'shots': 4096,\
'backend':'ibmq_20_tokyo'})
qbits = xacc.qalloc(3)
layout = np.array([1,2,3], dtype=np.uintp)
decorator = xacc.getAcceleratorDecorator('assignment-error-kernel', qpu, {'gen-kernel': True, 'layout': layout})
xacc.qasm('''
.compiler xasm
.circuit foo
.qbit q
H(q[0]);
H(q[1]);
CNOT(q[0], q[2]);
CNOT(q[1], q[2]);
Measure(q[0]);
Measure(q[1]);
Measure(q[2]);
''')
ansatz = xacc.getCompiled('foo')
decorator.execute(qbits, ansatz)
print(qbits)
kernel = qbits.getInformation("error-kernel")
original = qbits.getInformation("unmitigated-counts")
mitigated = qbits.getInformation("Measurements")
kernel = np.array(kernel)
kernel = kernel.reshape(8, 8)
print(kernel)
print(mitigated)
print(original)
/*******************************************************************************
* 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:
* Tyler Kharazi - initial implementation
*******************************************************************************/
#include "AssignmentErrorKernelDecorator.hpp"
#include "InstructionIterator.hpp"
#include "Utils.hpp"
#include "xacc.hpp"
#include <fstream>
#include <set>
#include <Eigen/Dense>
namespace xacc {
namespace quantum {
void AssignmentErrorKernelDecorator::initialize(
const HeterogeneousMap &params) {
if (params.keyExists<bool>("gen-kernel")) {
gen_kernel = params.get<bool>("gen-kernel");
std::cout<<"gen_kernel: "<<gen_kernel<<std::endl;
}
if (params.keyExists<bool>("multiplex")){
multiplex = params.get<bool>("multiplex");
//this is essentially to tell me how to deal with layouts. If multiplex, then we would split layout into two smaller layouts
//and we would generate two error kernels.
}
if (params.keyExists<std::vector<std::size_t>>("layout")){
layout = params.get<std::vector<std::size_t>>("layout");
std::cout<<"layout recieved"<<std::endl;
}
} // initialize
void AssignmentErrorKernelDecorator::execute(
std::shared_ptr<AcceleratorBuffer> buffer,
const std::shared_ptr<CompositeInstruction> function) {
int num_bits = buffer->size();
int size = std::pow(2, num_bits);
// get the raw state
decoratedAccelerator->execute(buffer, function);
int shots = 0;
Eigen::VectorXd init_state(size);
int i = 0;
for (auto &x : buffer->getMeasurementCounts()) {
shots += x.second;
std::cout<<x.second<<std::endl;
init_state(i) = double(x.second);
//std::cout<<init_state(i)<<std::endl;
i++;
}
init_state = (double)1/shots*init_state;
//std::cout<<"num_shots = "<<shots<<std::endl;
std::cout<<"INIT STATE:\n"<<init_state<<std::endl;
if (gen_kernel) {
if (decoratedAccelerator) {
generateKernel(buffer);
}
} else {
// generating the list of permutations is O(2^num_bits), we want to minimize
// the number of times we have to call it.
if (permutations.empty()) {
permutations = generatePermutations(num_bits);
}
}
std::cout<<errorKernel<<std::endl;
Eigen::VectorXd EM_state = errorKernel * init_state;
std::cout<<init_state<<std::endl;
std::cout<<EM_state<<std::endl;
// checking for negative values and performing a "clip and renorm"
for (int i = 0; i < EM_state.size(); i++) {
if (EM_state(i) < 0.0) {
int count = floor(shots * EM_state(i) + 0.5);
shots += count;
EM_state(i) = 0.0;
}
}
// std::cout << "Updated EM_state:" << std::endl << EM_state << std::endl;
// update buffer with new counts and save original counts to extra info
std::map<std::string, double> origCounts;
int total = 0;
i = 0;
for (auto &x : permutations) {
origCounts[x] = (double)buffer->getMeasurementCounts()[x];
int count = floor(shots * EM_state(i) + 0.5);
std::cout<<"EM_state = "<<EM_state(i)<<std::endl;
total += count;
std::cout<<"saving " << count <<" counts in slot: "<< x<<std::endl;
buffer->appendMeasurement(x, count);
i++;
}
// std::cout<<origCounts<<std::endl;
buffer->addExtraInfo("unmitigated-counts", origCounts);
return;
} // execute
void AssignmentErrorKernelDecorator::execute(
const std::shared_ptr<AcceleratorBuffer> buffer,
const std::vector<std::shared_ptr<CompositeInstruction>> functions) {
int num_bits = buffer->size();
if (gen_kernel) {
if (decoratedAccelerator) {
generateKernel(buffer);
}
} else {
if (permutations.empty()) {
permutations = generatePermutations(num_bits);
}
}
// get the raw states
decoratedAccelerator->execute(buffer, functions);
int size = std::pow(2, num_bits);
std::vector<Eigen::VectorXd> init_states;
// compute number of shots;
auto buffers = buffer->getChildren();
int shots = 0;
for (auto &x : buffers[0]->getMeasurementCounts()) {
shots += x.second;
}
// std::cout << "shots = " << shots << std::endl;
int i = 0;
for (auto &b : buffers) {
Eigen::VectorXd temp(size);
int j = 0;
for (auto &x : permutations) {
std::cout << b->computeMeasurementProbability(x) << std::endl;
temp(j) =(double)b->computeMeasurementProbability(x);
j++;
}
// std::cout << "seg fault right here " << std::endl;
init_states.push_back(temp);
}
// std::cout << "unmitigated states: " << std::endl;
std::vector<Eigen::VectorXd> EM_states;
i = 0;
for (auto &x : init_states) {
std::cout << x << std::endl << std::endl;
EM_states.push_back(errorKernel * x);
i++;
}
// std::cout << "mitigated states: " << std::endl;
// for (auto &x : EM_states) {
// std::cout << x << std::endl << std::endl;
// }
for (int i = 0; i < EM_states.size(); i++) {
for (int j = 0; j < EM_states[i].size(); j++) {
if (EM_states[i](j) < 0.0) {
int count = floor(shots * EM_states[i](j) + 0.5);
// std::cout << "found negative value, clipping and renorming "
// << std::endl;
// std::cout << "removed " << abs(count) << " shots from total shots"
// << std::endl;
shots += count;
EM_states[i](j) = 0.0;
}
}
}
// std::cout << "Update EM_states: " << std::endl;
// for (auto &x : EM_states) {
// std::cout << x << std::endl << std::endl;
// }
std::vector<std::map<std::string, double>> origCounts(buffer->nChildren());
int total = 0;
i = 0;
for (auto &b : buffers) {
int j = 0;
for (auto &x : permutations) {
origCounts[i][x] = (double)b->getMeasurementCounts()[x];
int count = floor(shots * EM_states[i](j) + 0.5);
j++;
total += count;
b->appendMeasurement(x, count);
b->addExtraInfo("unmitigated-counts", origCounts[i]);
}
i++;
}
return;
} // execute (vectorized)
} // namespace quantum
} // namespace xacc
/*******************************************************************************
* Copyright (c) 2018 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:
* Tyler Kharazi - initial implementation
*******************************************************************************/
#ifndef XACC_ASSIGNMENTERRORKERNELDECORATOR_HPP_
#define XACC_ASSIGNMENTERRORKERNELDECORATOR_HPP_
#include "AcceleratorDecorator.hpp"
#include <Eigen/Dense>
#include "xacc.hpp"
namespace xacc {
namespace quantum {
class AssignmentErrorKernelDecorator : public AcceleratorDecorator {
protected:
bool gen_kernel;
Eigen::MatrixXd errorKernel;
std::vector<std::string> permutations = {""};
bool multiplex;
std::vector<std::size_t> layout;
std::vector<std::string> generatePermutations(int num_bits) {
int pow_bits = std::pow(2, num_bits);
std::vector<std::string> bitstring(pow_bits);
std::string str = "";
std::string curr;
int counter = 0;
int j = num_bits;
while (j--) {
str.push_back('0');
}
for (int k = 0; k <= num_bits; k++) {
str[num_bits - k] = '1';
curr = str;
do {
bitstring[counter] = curr;
counter++;
} while (next_permutation(curr.begin(), curr.end()));
}
return bitstring;
}
void generateKernel(std::shared_ptr<AcceleratorBuffer> buffer) {
// pow(2, num_bits) gets used a lot, so I figured I should just define it
// here
int num_bits = buffer->size();
int pow_bits = std::pow(2, num_bits);
this->permutations = generatePermutations(num_bits);
// permutations contains all possible permutationss to generate circuits,
// there is direct mapping from permutations to circuit as follows:
// permutations: 10 => X gate on zeroth qubit and nothing on first qubit and
// measure both permutations: 11 => X gate on both qubits and measure both
// etc...
std::shared_ptr<AcceleratorBuffer> tmpBuffer = xacc::qalloc(buffer->size());
// generating list of circuits to evaluate
std::vector<std::shared_ptr<CompositeInstruction>> circuits;
auto provider = xacc::getIRProvider("quantum");
for (int i = 0; i < pow_bits; i++) {
auto circuit = provider->createComposite(permutations[i]);
int j = 0;
for (char c : permutations[i]) {
if (c == '1') {
// std::cout<<"1 found at position: "<<j<<std::endl;
auto x = provider->createInstruction("X", j);
circuit->addInstruction(x);
}
j++;
}
for(int i = 0; i < num_bits; i++){
circuit->addInstruction(provider->createInstruction("Measure", i));
//std::cout<<"added instruction"<<std::endl;
}
if (!layout.empty()){
std::cout<<"running bits on physical bits: "<<layout[0]<<" and "<<layout[1]<<std::endl;
circuit->mapBits(layout);
std::cout<<"we here or nah"<<std::endl;
}
//std::cout<<circuit->toString()<<std::endl;
//decoratedAccelerator->execute(tmpBuffer, circuit);
circuits.push_back(circuit);
}
//std::cout<<tmpBuffer->size()<<std::endl;
decoratedAccelerator->execute(tmpBuffer, circuits);
auto buffers = tmpBuffer->getChildren();
int shots = 0;
// compute num shots;
//std::cout<<tmpBuffer->nChildren()<<std::endl;
for (auto &x : buffers[0]->getMeasurementCounts()) {
shots += x.second;
}
std::cout<<"num_shots = " << shots <<std::endl;
// initializing vector of vector of counts to size 2^num_bits x 2^num_bits
std::vector<std::vector<int>> counts(std::pow(2, num_bits),
std::vector<int>(pow_bits));
int row = 0;
Eigen::MatrixXd K(pow_bits, pow_bits);
for (auto &b : buffers) {
//b->print();
int col = 0;
for (auto &x : permutations) {
auto temp = b->computeMeasurementProbability(x);
K(row, col) = temp;
col++;
}
row++;
}
AssignmentErrorKernelDecorator::errorKernel = K.inverse();
std::vector<double> vec(errorKernel.data(), errorKernel.data() + errorKernel.rows()*errorKernel.cols());
buffer->addExtraInfo("error-kernel", vec);
gen_kernel = false;
}
public:
const std::vector<std::string> configurationKeys() override {
return {"gen-kernel"};
}
void initialize(const HeterogeneousMap &params = {}) override;
void execute(std::shared_ptr<AcceleratorBuffer> buffer,
const std::shared_ptr<CompositeInstruction> function) override;
void execute(std::shared_ptr<AcceleratorBuffer> buffer,
const std::vector<std::shared_ptr<CompositeInstruction>>
functions) override;
const std::string name() const override { return "assignment-error-kernel"; }
const std::string description() const override { return ""; }
~AssignmentErrorKernelDecorator() override {}
};
} // namespace quantum
} // namespace xacc
#endif
......@@ -17,6 +17,7 @@ file (GLOB SRC RDMPurificationDecorator.cpp
ImprovedSamplingDecorator.cpp
ROErrorDecorator.cpp
RichExtrapDecorator.cpp
AssignmentErroerKernelDecorator.cpp
DecoratorsActivator.cpp)
# Set up dependencies to resources to track changes
......
......@@ -14,6 +14,7 @@
#include "RDMPurificationDecorator.hpp"
#include "ROErrorDecorator.hpp"
#include "RichExtrapDecorator.hpp"
#include "AssignmentErrorKernelDecorator.hpp"
#include "cppmicroservices/BundleActivator.h"
#include "cppmicroservices/BundleContext.h"
......@@ -42,6 +43,7 @@ public:
auto c2 = std::make_shared<xacc::quantum::RichExtrapDecorator>();
auto c3 = std::make_shared<xacc::quantum::ROErrorDecorator>();
auto c4 = std::make_shared<xacc::quantum::RDMPurificationDecorator>();
auto c5 = std::make_shared<xacc::quantum::AssignmentErrorKernelDecorator>();
context.RegisterService<xacc::AcceleratorDecorator>(c2);
context.RegisterService<xacc::Accelerator>(c2);
......@@ -55,6 +57,9 @@ public:
context.RegisterService<xacc::AcceleratorDecorator>(c4);
context.RegisterService<xacc::Accelerator>(c4);
context.RegisterService<xacc::AcceleratorDecorator>(c5);
context.RegisterService<xacc::Accelerator>(c5);
}
/**
......
/*******************************************************************************
* 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 "AcceleratorDecorator.hpp"
#include "xacc.hpp"
#include <gtest/gtest.h>
#include <memory>
#include "xacc_service.hpp"
using namespace xacc;
TEST(AssignmentErrorKernelDecoratorTest, checkBasic) {
xacc::set_verbose(true);
if (xacc::hasAccelerator("aer")) {
auto accelerator = xacc::getAccelerator(
"aer", {std::make_pair("shots", 2048),
std::make_pair("backend", "ibmq_johannesburg"),
std::make_pair("readout_error", true),
std::make_pair("gate_error", false),
std::make_pair("thermal_relaxation", false)});
int num_qubits = 2;
auto compiler = xacc::getService<xacc::Compiler>("xasm");
xacc::qasm(R"(
.compiler xasm
.circuit bell
.qbit q
H(q[0]);
CX(q[0], q[1]);
Measure(q[0]);
Measure(q[1]);
)");
auto bell = xacc::getCompiled("bell");
auto decBuffer = xacc::qalloc(num_qubits);
auto decorator =
xacc::getService<AcceleratorDecorator>("assignment-error-kernel");
decorator->initialize({std::make_pair("gen-kernel", true)});
decorator->setDecorated(accelerator);
decorator->execute(decBuffer, bell);
decBuffer->print();
} else {
std::cout << "you do not have aer accelerator installed, please install "
"qiskit if you wish to run this test"
<< std::endl;
}
}
TEST(AssignmentErrorKernelDecoratorTest, checkVectorize) {
xacc::set_verbose(true);
if (xacc::hasAccelerator("aer")) {
auto accelerator = xacc::getAccelerator(
"aer", {std::make_pair("shots", 2048),
std::make_pair("backend", "ibmq_johannesburg"),
std::make_pair("readout_error", true),
std::make_pair("gate_error", true),
std::make_pair("thermal_relaxation", true)});
int num_qbits = 2;
auto compiler = xacc::getService<xacc::Compiler>("xasm");
xacc::qasm(R"(
.compiler xasm
.circuit hadamard
.qbit q
H(q[0]);
Measure(q[0]);
Measure(q[1]);
)");
xacc::qasm(R"(
.compiler xasm
.circuit bell1
.qbit q
H(q[1]);
CX(q[1], q[0]);
Measure(q[0]);
Measure(q[1]);
)");
auto hadamard = xacc::getCompiled("hadamard");
auto bell1 = xacc::getCompiled("bell1");
std::vector<std::shared_ptr<CompositeInstruction>> circuits = {hadamard,
bell1};
auto buffer = xacc::qalloc(num_qbits);
auto decorator =
xacc::getService<AcceleratorDecorator>("assignment-error-kernel");
decorator->initialize({std::make_pair("gen-kernel", true)});
decorator->setDecorated(accelerator);
decorator->execute(buffer, circuits);
buffer->print();
}
}
TEST(AssignmentErrorKernelDecoratorTest, checkLayout) {
xacc::set_verbose(true);
if (xacc::hasAccelerator("aer")) {
auto accelerator = xacc::getAccelerator(
"aer", {std::make_pair("shots", 2048),
std::make_pair("backend", "ibmq_tokyo"),
std::make_pair("readout_error", true),
std::make_pair("gate_error", true),
std::make_pair("thermal_relaxation", true)});
int num_qbits = 2;
auto compiler = xacc::getService<xacc::Compiler>("xasm");
xacc::qasm(R"(
.compiler xasm
.circuit hadamard1
.qbit q
H(q[1]);
Measure(q[0]);
Measure(q[1]);
)");
auto hadamard = xacc::getCompiled("hadamard1");
std::shared_ptr<CompositeInstruction> circuit = hadamard;
auto buffer = xacc::qalloc(num_qbits);
auto decorator =
xacc::getService<AcceleratorDecorator>("assignment-error-kernel");
decorator->initialize({std::make_pair("gen-kernel", true), std::make_pair("layout", std::vector<std::size_t> {6,7})});
decorator->setDecorated(accelerator);
decorator->execute(buffer, circuit);
buffer->print();
}
}
int main(int argc, char **argv) {
int ret = 0;
xacc::Initialize();
xacc::external::load_external_language_plugins();
::testing::InitGoogleTest(&argc, argv);
ret = RUN_ALL_TESTS();
xacc::external::unload_external_language_plugins();
xacc::Finalize();
return ret;
}
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