-
Notifications
You must be signed in to change notification settings - Fork 42
/
Copy pathApply.cpp
94 lines (78 loc) · 3.5 KB
/
Apply.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// Copyright 2021 Xanadu Quantum Technologies Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <set>
#include "Apply.hpp"
#include "Gates.hpp"
#include "StateVector.hpp"
#include "Util.hpp"
using std::set;
using std::string;
using std::unique_ptr;
using std::vector;
vector<unsigned int> Pennylane::getIndicesAfterExclusion(const vector<unsigned int>& indicesToExclude, const unsigned int qubits) {
set<unsigned int> indices;
for (unsigned int i = 0; i < qubits; i++) {
indices.insert(indices.end(), i);
}
for (const unsigned int& excludedIndex : indicesToExclude) {
indices.erase(excludedIndex);
}
return vector<unsigned int>(indices.begin(), indices.end());
}
vector<size_t> Pennylane::generateBitPatterns(const vector<unsigned int>& qubitIndices, const unsigned int qubits) {
vector<size_t> indices;
indices.reserve(exp2(qubitIndices.size()));
indices.push_back(0);
for (int i = qubitIndices.size() - 1; i >= 0; i--) {
size_t value = maxDecimalForQubit(qubitIndices[i], qubits);
size_t currentSize = indices.size();
for (size_t j = 0; j < currentSize; j++) {
indices.push_back(indices[j] + value);
}
}
return indices;
}
void Pennylane::constructAndApplyOperation(
StateVector& state,
const string& opLabel,
const vector<unsigned int>& opWires,
const vector<double>& opParams,
bool inverse,
const unsigned int qubits
) {
unique_ptr<AbstractGate> gate = constructGate(opLabel, opParams);
if (gate->numQubits != opWires.size())
throw std::invalid_argument(string("The gate of type ") + opLabel + " requires " + std::to_string(gate->numQubits) + " wires, but " + std::to_string(opWires.size()) + " were supplied");
vector<size_t> internalIndices = generateBitPatterns(opWires, qubits);
vector<unsigned int> externalWires = getIndicesAfterExclusion(opWires, qubits);
vector<size_t> externalIndices = generateBitPatterns(externalWires, qubits);
gate->applyKernel(state, internalIndices, externalIndices, inverse);
}
void Pennylane::apply(
StateVector& state,
const vector<string>& ops,
const vector<vector<unsigned int>>& wires,
const vector<vector<double>>& params,
const vector<bool>& inverse,
const unsigned int qubits
) {
if (qubits <= 0)
throw std::invalid_argument("Must specify one or more qubits");
size_t expectedLength = exp2(qubits);
if (state.length != expectedLength)
throw std::invalid_argument(string("Input state vector length (") + std::to_string(state.length) + ") does not match the given number of qubits " + std::to_string(qubits));
size_t numOperations = ops.size();
if (numOperations != wires.size() || numOperations != params.size())
throw std::invalid_argument("Invalid arguments: number of operations, wires, and parameters must all be equal");
for (int i = 0; i < numOperations; i++) {
constructAndApplyOperation(state, ops[i], wires[i], params[i], inverse[i], qubits);
}
}