ROErrorDecorator.cpp 8.49 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
/*******************************************************************************
 * 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
 *******************************************************************************/
Mccaskey, Alex's avatar
Mccaskey, Alex committed
13
14
#include "ROErrorDecorator.hpp"
#include "InstructionIterator.hpp"
15
#include "Utils.hpp"
16
#include "xacc.hpp"
Mccaskey, Alex's avatar
Mccaskey, Alex committed
17
18
19
20
21
22
23
24
25
26
#include <fstream>
#include <set>

#define RAPIDJSON_HAS_STDSTRING 1

#include "rapidjson/document.h"
using namespace rapidjson;

namespace xacc {
namespace quantum {
27
28
29
void ROErrorDecorator::execute(
    std::shared_ptr<AcceleratorBuffer> buffer,
    const std::shared_ptr<CompositeInstruction> function) {
Mccaskey, Alex's avatar
Mccaskey, Alex committed
30

31
32
  if (decoratedAccelerator)
    decoratedAccelerator->execute(buffer, function);
Mccaskey, Alex's avatar
Mccaskey, Alex committed
33

Mccaskey, Alex's avatar
Mccaskey, Alex committed
34
35
36
37
38
  HeterogeneousMap properties;
  if (decoratedAccelerator) {
    properties = decoratedAccelerator->getProperties();
  }

39
  std::map<int, double> piplus, piminus;
Mccaskey, Alex's avatar
Mccaskey, Alex committed
40

41
42
  if (xacc::fileExists(roErrorFile)) {
    // First: if a readout error file is provided, use it (since user explicitly provided it)
43
    // Get RO error probs
44
    buffer->addExtraInfo("ro-error-file", ExtraInfo(roErrorFile));
Mccaskey, Alex's avatar
Mccaskey, Alex committed
45

46
    std::ifstream t(roErrorFile);
47
48
49
50
    std::string json((std::istreambuf_iterator<char>(t)),
                     std::istreambuf_iterator<char>());

    if (json.empty()) {
51
      xacc::error("Invalid ROError JSON file: " + roErrorFile);
52
    }
Mccaskey, Alex's avatar
Mccaskey, Alex committed
53

54
55
    Document d;
    d.Parse(json);
Mccaskey, Alex's avatar
Mccaskey, Alex committed
56

57
58
59
60
61
62
63
64
    for (auto itr = d.MemberBegin(); itr != d.MemberEnd(); ++itr) {
      std::string key = itr->name.GetString();
      if (key.compare("shots") != 0 && key.compare("backend") != 0) {
        auto &value = d[itr->name.GetString()];
        auto qbit = std::stoi(key);
        piplus.insert({qbit, value["+"].GetDouble()});
        piminus.insert({qbit, value["-"].GetDouble()});
      }
Mccaskey, Alex's avatar
Mccaskey, Alex committed
65
    }
66
67
68
69
70
71
72
73
74
75
76
77
78
79
  } else if (properties.keyExists<std::vector<double>>("p01s") &&
             properties.keyExists<std::vector<double>>("p10s")) {
    // If no readout error file is provided, use the backend's p01s and p10s properties           
    auto p01s = properties.get<std::vector<double>>("p01s");
    auto p10s = properties.get<std::vector<double>>("p10s");
    for (int i = 0; i < p01s.size(); i++) {
      piplus.insert({i, p01s[i] + p10s[i]});
      piminus.insert({i, p01s[i] - p10s[i]});
    }
  } else {
    xacc::warning("Accelerator does not have readout error properties and Cannot "
               "find readout erro file (key 'file'). Skipping ReadoutError "
               "correction.");
    return;
Mccaskey, Alex's avatar
Mccaskey, Alex committed
80
81
82
83
  }

  auto supports = [](std::shared_ptr<CompositeInstruction> f) {
    std::set<int> supportSet;
84
85
    std::map<int, int> support_to_creg_map;
    int creg_count = 0;
Mccaskey, Alex's avatar
Mccaskey, Alex committed
86
87
88
89
90
    InstructionIterator it(f);
    while (it.hasNext()) {
      auto nextInst = it.next();
      if (nextInst->name() == "Measure") {
        auto bits = nextInst->bits();
91
92
93
94
        supportSet.insert(bits[0]);
        support_to_creg_map.insert({bits[0], creg_count});
        creg_count++;
        for (auto &b : bits) {
Mccaskey, Alex's avatar
Mccaskey, Alex committed
95
          supportSet.insert(b);
96
        }
Mccaskey, Alex's avatar
Mccaskey, Alex committed
97
98
      }
    }
99
    return std::make_pair(supportSet, support_to_creg_map);
Mccaskey, Alex's avatar
Mccaskey, Alex committed
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  };

  // Get the number of shots first
  int nShots = 0;
  auto tmpCounts = buffer->getMeasurementCounts();
  for (auto &kv : tmpCounts) {
    nShots += kv.second;
  }

  auto counts = buffer->getMeasurementCounts();

  auto fixedExp = 0.0;
  for (auto &kv : counts) {
    auto prod = 1.0;
    std::string bitString = kv.first;
    auto count = kv.second;
116
117
118
119
120
121
122
123
124
    auto [_supports, supports_to_creg_map] = supports(function);
    for (auto j : _supports) {
      prod *=
          (std::pow(
               -1,
               (int)(bitString[buffer->size() - supports_to_creg_map[j] - 1] -
                     '0')) -
           piminus[j]) /
          (1.0 - piplus[j]);
Mccaskey, Alex's avatar
Mccaskey, Alex committed
125
126
127
128
    }

    fixedExp += ((double)count / (double)nShots) * prod;
  }
129
130
131
132
133
134
  if (fixedExp > 1.0) {
    fixedExp = 1.0;
  }
  if (fixedExp < -1.0) {
    fixedExp = -1.0;
  }
Mccaskey, Alex's avatar
Mccaskey, Alex committed
135
136
137
138
139
140
141
142
143
144
  buffer->addExtraInfo("ro-fixed-exp-val-z", ExtraInfo(fixedExp));

  return;
}

void ROErrorDecorator::execute(
    std::shared_ptr<AcceleratorBuffer> buffer,
    const std::vector<std::shared_ptr<CompositeInstruction>> functions) {

  std::vector<std::shared_ptr<AcceleratorBuffer>> buffers;
145
  std::map<std::string, std::shared_ptr<CompositeInstruction>> nameToFunction;
146
147
  std::map<std::string, std::pair<std::set<int>, std::map<int, int>>>
      supportSets;
Mccaskey, Alex's avatar
Mccaskey, Alex committed
148
149
150
151
152
153
154
155
156
157

  if (decoratedAccelerator) {
    decoratedAccelerator->execute(buffer, functions);
    buffers = buffer->getChildren();
  } else {
    buffers = buffer->getChildren();
  }

  auto supports = [](std::shared_ptr<CompositeInstruction> f) {
    std::set<int> supportSet;
158
159
    std::map<int, int> support_to_creg_map;
    int creg_count = 0;
Mccaskey, Alex's avatar
Mccaskey, Alex committed
160
161
162
163
164
    InstructionIterator it(f);
    while (it.hasNext()) {
      auto nextInst = it.next();
      if (nextInst->name() == "Measure") {
        auto bits = nextInst->bits();
165
166
167
        supportSet.insert(bits[0]);
        support_to_creg_map.insert({bits[0], creg_count});
        creg_count++;
Mccaskey, Alex's avatar
Mccaskey, Alex committed
168
169
170
171
172
        for (auto &b : bits) {
          supportSet.insert(b);
        }
      }
    }
173
    return std::make_pair(supportSet, support_to_creg_map);
Mccaskey, Alex's avatar
Mccaskey, Alex committed
174
175
  };

176
177
178
  for (auto &f : functions) {
    nameToFunction.insert({f->name(), f});
    supportSets.insert({f->name(), supports(f)});
Mccaskey, Alex's avatar
Mccaskey, Alex committed
179
180
  }

181
  std::map<int, double> piplus, piminus;
Mccaskey, Alex's avatar
Mccaskey, Alex committed
182
183
184
185
  HeterogeneousMap properties;
  if (decoratedAccelerator) {
    properties = decoratedAccelerator->getProperties();
  }
186

187
  if (xacc::fileExists(roErrorFile)) {
188
    // Get RO error probs
189
    buffer->addExtraInfo("ro-error-file", ExtraInfo(roErrorFile));
190

191
    std::ifstream t(roErrorFile);
192
193
194
    std::string json((std::istreambuf_iterator<char>(t)),
                     std::istreambuf_iterator<char>());
    if (json.empty()) {
195
      xacc::error("Invalid ROError JSON file: " + roErrorFile);
196
    }
Mccaskey, Alex's avatar
Mccaskey, Alex committed
197

198
199
    Document d;
    d.Parse(json);
Mccaskey, Alex's avatar
Mccaskey, Alex committed
200

201
202
203
204
205
206
207
208
    for (auto itr = d.MemberBegin(); itr != d.MemberEnd(); ++itr) {
      std::string key = itr->name.GetString();
      if (key.compare("shots") != 0 && key.compare("backend") != 0) {
        auto &value = d[itr->name.GetString()];
        auto qbit = std::stoi(key);
        piplus.insert({qbit, value["+"].GetDouble()});
        piminus.insert({qbit, value["-"].GetDouble()});
      }
Mccaskey, Alex's avatar
Mccaskey, Alex committed
209
    }
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
  } else if (properties.keyExists<std::vector<double>>("p01s") &&
             properties.keyExists<std::vector<double>>("p10s")) {

    auto p01s = properties.get<std::vector<double>>("p01s");
    auto p10s = properties.get<std::vector<double>>("p10s");
    for (int i = 0; i < p01s.size(); i++) {

      piplus.insert({i, p01s[i] + p10s[i]});
      piminus.insert({i, p01s[i] - p10s[i]});
    }
  } else {
    xacc::warning(
        "Accelerator does not have readout error properties and Cannot "
        "find readout erro file (key 'file'). Skipping ReadoutError "
        "correction.");
    return;
Mccaskey, Alex's avatar
Mccaskey, Alex committed
226
  }
Mccaskey, Alex's avatar
Mccaskey, Alex committed
227

Mccaskey, Alex's avatar
Mccaskey, Alex committed
228
229
230
231
  // Get the number of shots first
  int nShots = 0;
  std::map<std::string, int> tmpCounts;
  for (auto &b : buffers) {
232
233
234
235
    if (!b->getMeasurementCounts().empty()) {
      tmpCounts = b->getMeasurementCounts();
      break;
    }
Mccaskey, Alex's avatar
Mccaskey, Alex committed
236
237
238
239
240
241
242
243
244
  }
  for (auto &kv : tmpCounts) {
    nShots += kv.second;
  }
  int counter = 0;
  for (auto &b : buffers) {
    auto counts = b->getMeasurementCounts();
    auto functionName = b->name();
    auto f = nameToFunction[functionName];
245
    auto [fSupports, support_to_creg_map] = supportSets[functionName];
Mccaskey, Alex's avatar
Mccaskey, Alex committed
246
247
248
249
250
251
    auto exp_val = b->getExpectationValueZ();
    auto fixedExp = 0.0;
    for (auto &kv : counts) {
      auto prod = 1.0;
      std::string bitString = kv.first;
      auto count = kv.second;
252
      for (auto &j : fSupports) {
Mccaskey, Alex's avatar
Mccaskey, Alex committed
253
        auto denom = (1.0 - piplus[j]);
254
255
256
257
        double numerator =
            (bitString[bitString.length() - 1 - support_to_creg_map[j]] == '1'
                 ? -1
                 : 1) -
258
            piminus[j];
Mccaskey, Alex's avatar
Mccaskey, Alex committed
259
260
261
262
        prod *= (numerator / denom);
      }
      fixedExp += ((double)count / (double)nShots) * prod;
    }
263
264
265
266
267
268
    if (fixedExp > 1.0) {
      fixedExp = 1.0;
    }
    if (fixedExp < -1.0) {
      fixedExp = -1.0;
    }
Mccaskey, Alex's avatar
Mccaskey, Alex committed
269
270
271
272
273
274
275
276
277
278
    b->addExtraInfo("ro-fixed-exp-val-z", ExtraInfo(fixedExp));

    counter++;
  }

  return;
}

} // namespace quantum
} // namespace xacc