AcceleratorBuffer.hpp 5.22 KB
Newer Older
1
2
3
4
5
6
7
8
/*******************************************************************************
 * Copyright (c) 2017 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
9
10
 *
 * Contributors:
11
12
 *   Alexander J. McCaskey - initial API and implementation
 *******************************************************************************/
13
14
15
#ifndef XACC_ACCELERATOR_ACCELERATORBUFFER_HPP_
#define XACC_ACCELERATOR_ACCELERATORBUFFER_HPP_

16
#include <boost/dynamic_bitset.hpp>
17
#include <string>
18
#include <sstream>
19
#include <iostream>
20
#include "Utils.hpp"
21

22
23
namespace xacc {

24
/**
25
26
27
28
 * The AcceleratorBuffer models an allocated buffer of
 * bits that are operated on by a kernel. As such,
 * the AcceleratorBuffer's primary role is to store
 * Accelerator execution results.
29
30
31
32
 *
 * @author Alex McCaskey
 */
class AcceleratorBuffer {
33

34
public:
35

36
37
38
	/**
	 * The Constructor
	 */
39
	AcceleratorBuffer(const std::string& str, const int N) :
40
			bufferId(str), nBits(N) {
41
	}
42
43
44
45
46
47
48
49
50

	/**
	 * The Constructor, takes as input the name of this buffer,
	 * and the bit indices to model.
	 *
	 * @param str The name of the buffer
	 * @param firstIndex The first bit index
	 * @param indices The remaining bit indices
	 */
51
52
53
	template<typename ... Indices>
	AcceleratorBuffer(const std::string& str, int firstIndex,
			Indices ... indices) :
54
			bufferId(str), nBits(1 + sizeof...(indices)) {
55
	}
56

57
58
59
60
61
62
63
	/**
	 * The copy constructor
	 */
	AcceleratorBuffer(const AcceleratorBuffer& other) :
			nBits(other.nBits), bufferId(other.bufferId) {
	}

64
65
66
67
68
69
	/**
	 * Return the number of bits in this buffer.
	 *
	 * @return size The number of bits in this buffer
	 */
	const int size() const {
70
		return nBits;
71
	}
72

73
74
75
76
77
78
	/**
	 * Return this AcceleratorBuffer's name
	 *
	 * @return name The name of this AcceleratorBuffer
	 */
	const std::string name() const {
79
80
81
		return bufferId;
	}

82
83
84
	/**
	 * Reset the stored measured bit strings.
	 */
85
	virtual void resetBuffer() {
86
		measurements.clear();
87
		bitStringToCounts.clear();
88
	}
89

90
91
92
93
94
	/**
	 * Add a measurement result to this Buffer
	 *
	 * @param measurement The measurement result
	 */
95
	virtual void appendMeasurement(const boost::dynamic_bitset<>& measurement) {
Mengsu Chen's avatar
Mengsu Chen committed
96
		measurements.push_back(measurement);
Mccaskey, Alex's avatar
Mccaskey, Alex committed
97
98
99
		std::stringstream ss;
		ss << measurement;
		bitStringToCounts[ss.str()]++;
100
	}
101

102
103
104
105
106
107
108
109
	virtual void appendMeasurement(const boost::dynamic_bitset<>& measurement, const int count) {
		std::stringstream ss;
		ss << measurement;
		bitStringToCounts[ss.str()] = count;
		for (int i = 0; i < count; i++) measurements.push_back(measurement);
		return;
	}

110
	virtual double computeMeasurementProbability(const std::string& bitStr) {
Mccaskey, Alex's avatar
Mccaskey, Alex committed
111
		return (double) bitStringToCounts[bitStr] / (double)measurements.size();
112
113
	}

114
115
116
117
118
119
120
121
122
	/**
	 * Compute and return the expectation value with respect
	 * to the Pauli-Z operator. Here we provide a base implementation
	 * based on an ensemble of measurement results. Subclasses
	 * are free to implement this as they see fit, ie, for simulators
	 * use the wavefunction.
	 *
	 * @return expVal The expectation value
	 */
Mccaskey, Alex's avatar
Mccaskey, Alex committed
123
	virtual const double getExpectationValueZ() {
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
		double aver = 0.0;
		auto has_even_parity = [](unsigned int x) -> int {
		    unsigned int count = 0, i, b = 1;
		    for(i = 0; i < 32; i++){
		        if( x & (b << i) ){count++;}
		    }
		    if( (count % 2) ){return 0;}
		    return 1;
		};

		for (auto& kv : bitStringToCounts) {
			int i = std::stoi(kv.first, nullptr, 2);
			auto par = has_even_parity(i);
			auto p = computeMeasurementProbability(kv.first);
			if (!par) {
				p = -p;
140
			}
141
			aver += p;
Mengsu Chen's avatar
Mengsu Chen committed
142
143
		}
		return aver;
144
145
	}

146
147
148
149
150
	virtual void setExpectationValueZ(const double exp) {
		XACCLogger::instance()->error("AcceleratorBuffer.setExpectationValueZ not "
				"implemented. This method is intended for subclasses.");
	}

151
	/**
152
	 * Return a read-only view of this Buffer's measurement results
153
	 *
154
	 * @return results Measurement results
155
	 */
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
	virtual const std::vector<boost::dynamic_bitset<>> getMeasurements() {
		return measurements;
	}

	/**
	 * Return all measurements as bit strings.
	 *
	 * @return bitStrings List of bit strings.
	 */
	virtual const std::vector<std::string> getMeasurementStrings() {
		std::vector<std::string> strs;
		for (auto m : measurements) {
			std::stringstream ss;
			ss << m;
			strs.push_back(ss.str());
		}
		return strs;
173
174
	}

175
176
177
178
	/**
	 * Print information about this AcceleratorBuffer to standard out.
	 *
	 */
179
180
	virtual void print() {
	}
181
182
183
184
185
186
187

	/**
	 * Print information about this AcceleratorBuffer to the
	 * given output stream.
	 *
	 * @param stream Stream to write the buffer to.
	 */
188
189
190
	virtual void print(std::ostream& stream) {
	}

191
192
193
	/**
	 * The Destructor
	 */
194
195
	virtual ~AcceleratorBuffer() {
	}
196
197

protected:
198

199
200
201
	/**
	 * Reference to the Accelerator measurement result bit strings
	 */
202
203
	std::vector<boost::dynamic_bitset<>> measurements;

204
205
	std::map<std::string, int> bitStringToCounts;

206
207
208
	/**
	 * The name of this AcceleratorBuffer
	 */
209
	std::string bufferId;
210

211
	/**
212
	 * The number of bits in this buffer.
213
	 */
214
215
	int nBits;

216
217
};

218
}
219

220
#endif