-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add implementations for optimised gate kernels #85
Changes from 2 commits
7b1fa00
e660d94
f2c4db7
011e9bc
88a9e97
f305304
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -14,6 +14,7 @@ | |||||
|
||||||
#define _USE_MATH_DEFINES | ||||||
|
||||||
#include <algorithm> | ||||||
#include <cmath> | ||||||
#include <functional> | ||||||
#include <map> | ||||||
|
@@ -24,6 +25,7 @@ | |||||
using std::function; | ||||||
using std::map; | ||||||
using std::string; | ||||||
using std::swap; | ||||||
using std::unique_ptr; | ||||||
using std::vector; | ||||||
|
||||||
|
@@ -42,6 +44,28 @@ Pennylane::AbstractGate::AbstractGate(int numQubits) | |||||
, length(exp2(numQubits)) | ||||||
{} | ||||||
|
||||||
void Pennylane::AbstractGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
const vector<CplxType>& matrix = asMatrix(); | ||||||
trbromley marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
assert(indices.size() == length && v.size() == length); | ||||||
|
||||||
// Gather | ||||||
size_t pos = 0; | ||||||
for (const size_t& index : indices) { | ||||||
v[pos] = state[index]; | ||||||
pos++; | ||||||
} | ||||||
|
||||||
// Apply + scatter | ||||||
for (size_t i = 0; i < indices.size(); i++) { | ||||||
size_t index = indices[i]; | ||||||
state[index] = 0; | ||||||
size_t baseIndex = i * indices.size(); | ||||||
for (size_t j = 0; j < indices.size(); j++) { | ||||||
state[index] += matrix[baseIndex + j] * v[j]; | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
Pennylane::SingleQubitGate::SingleQubitGate() | ||||||
|
@@ -61,6 +85,10 @@ const vector<CplxType> Pennylane::XGate::matrix{ | |||||
0, 1, | ||||||
1, 0 }; | ||||||
|
||||||
void Pennylane::XGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. constness and making
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm okay with adding the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it! A reason to make There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True; although I think that's indication we should rework the API (i.e. we shouldn't be passing in parameters we don't need if we don't have to). As mentioned in the PR description, its probably beneficial, although it will unfortunately result in some measure of code duplication. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or if branching off would result in a performance degradation, how about incorporating the internal loop in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would be ideal. However, ultimately I think we want to inline |
||||||
swap(state[indices[0]], state[indices[1]]); | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
const string Pennylane::YGate::label = "PauliY"; | ||||||
|
@@ -74,6 +102,12 @@ const vector<CplxType> Pennylane::YGate::matrix{ | |||||
0, -IMAG, | ||||||
IMAG, 0 }; | ||||||
|
||||||
void Pennylane::YGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
v[0] = state[indices[0]]; | ||||||
state[indices[0]] = -IMAG * state[indices[1]]; | ||||||
state[indices[1]] = IMAG * v[0]; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How come we need to update There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it!
This would be preferable as just creating There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The allocation for |
||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
const string Pennylane::ZGate::label = "PauliZ"; | ||||||
|
@@ -87,6 +121,10 @@ const std::vector<CplxType> Pennylane::ZGate::matrix{ | |||||
1, 0, | ||||||
0, -1 }; | ||||||
|
||||||
void Pennylane::ZGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
state[indices[1]] *= -1; | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
const string Pennylane::HadamardGate::label = "Hadamard"; | ||||||
|
@@ -100,6 +138,13 @@ const vector<CplxType> Pennylane::HadamardGate::matrix{ | |||||
SQRT2INV, SQRT2INV, | ||||||
SQRT2INV, -SQRT2INV }; | ||||||
|
||||||
void Pennylane::HadamardGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
v[0] = state[indices[0]]; | ||||||
v[1] = state[indices[1]]; | ||||||
state[indices[0]] = SQRT2INV * (v[0] + v[1]); | ||||||
state[indices[1]] = SQRT2INV * (v[0] - v[1]); | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
const string Pennylane::SGate::label = "S"; | ||||||
|
@@ -113,6 +158,10 @@ const vector<CplxType> Pennylane::SGate::matrix{ | |||||
1, 0, | ||||||
0, IMAG }; | ||||||
|
||||||
void Pennylane::SGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
state[indices[1]] *= IMAG; | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
const string Pennylane::TGate::label = "T"; | ||||||
|
@@ -122,9 +171,15 @@ Pennylane::TGate Pennylane::TGate::create(const vector<double>& parameters) { | |||||
return Pennylane::TGate(); | ||||||
} | ||||||
|
||||||
const CplxType Pennylane::TGate::shift = std::pow(M_E, CplxType(0, M_PI / 4)); | ||||||
|
||||||
const vector<CplxType> Pennylane::TGate::matrix{ | ||||||
1, 0, | ||||||
0, std::pow(M_E, CplxType(0, M_PI / 4)) }; | ||||||
0, Pennylane::TGate::shift }; | ||||||
|
||||||
void Pennylane::TGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
state[indices[1]] *= Pennylane::TGate::shift; | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
|
@@ -177,6 +232,11 @@ Pennylane::RotationZGate::RotationZGate(double rotationAngle) | |||||
0, second } | ||||||
{} | ||||||
|
||||||
void Pennylane::RotationZGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
state[indices[0]] *= first; | ||||||
state[indices[1]] *= second; | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
const string Pennylane::PhaseShiftGate::label = "PhaseShift"; | ||||||
|
@@ -193,6 +253,10 @@ Pennylane::PhaseShiftGate::PhaseShiftGate(double rotationAngle) | |||||
0, shift } | ||||||
{} | ||||||
|
||||||
void Pennylane::PhaseShiftGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
state[indices[1]] *= shift; | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
const string Pennylane::GeneralRotationGate::label = "Rot"; | ||||||
|
@@ -205,9 +269,13 @@ Pennylane::GeneralRotationGate Pennylane::GeneralRotationGate::create(const vect | |||||
Pennylane::GeneralRotationGate::GeneralRotationGate(double phi, double theta, double omega) | ||||||
: c(std::cos(theta / 2), 0) | ||||||
, s(std::sin(theta / 2), 0) | ||||||
, r1(c* std::pow(M_E, CplxType(0, (-phi - omega) / 2))) | ||||||
, r2(-s * std::pow(M_E, CplxType(0, (phi - omega) / 2))) | ||||||
, r3(s* std::pow(M_E, CplxType(0, (-phi + omega) / 2))) | ||||||
, r4(c* std::pow(M_E, CplxType(0, (phi + omega) / 2))) | ||||||
, matrix{ | ||||||
c * std::pow(M_E, CplxType(0, (-phi - omega) / 2)), -s * std::pow(M_E, CplxType(0, (phi - omega) / 2)), | ||||||
s * std::pow(M_E, CplxType(0, (-phi + omega) / 2)), c * std::pow(M_E, CplxType(0, (phi + omega) / 2)) } | ||||||
r1, r2, | ||||||
r3, r4 } | ||||||
Comment on lines
+300
to
+306
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice! |
||||||
{} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
@@ -231,6 +299,10 @@ const std::vector<CplxType> Pennylane::CNOTGate::matrix{ | |||||
0, 0, 0, 1, | ||||||
0, 0, 1, 0 }; | ||||||
|
||||||
void Pennylane::CNOTGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
swap(state[indices[2]], state[indices[3]]); | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
const string Pennylane::SWAPGate::label = "SWAP"; | ||||||
|
@@ -246,6 +318,10 @@ const std::vector<CplxType> Pennylane::SWAPGate::matrix{ | |||||
0, 1, 0, 0, | ||||||
0, 0, 0, 1 }; | ||||||
|
||||||
void Pennylane::SWAPGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
swap(state[indices[1]], state[indices[2]]); | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
const string Pennylane::CZGate::label = "CZ"; | ||||||
|
@@ -261,6 +337,10 @@ const std::vector<CplxType> Pennylane::CZGate::matrix{ | |||||
0, 0, 1, 0, | ||||||
0, 0, 0, -1 }; | ||||||
|
||||||
void Pennylane::CZGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
state[indices[3]] *= -1; | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
const string Pennylane::CRotationXGate::label = "CRX"; | ||||||
|
@@ -280,6 +360,13 @@ Pennylane::CRotationXGate::CRotationXGate(double rotationAngle) | |||||
0, 0, js, c } | ||||||
{} | ||||||
|
||||||
void Pennylane::CRotationXGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
v[0] = state[indices[2]]; | ||||||
v[1] = state[indices[3]]; | ||||||
state[indices[2]] = c * v[0] + js * v[1]; | ||||||
state[indices[3]] = js * v[0] + c * v[1]; | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
const string Pennylane::CRotationYGate::label = "CRY"; | ||||||
|
@@ -299,6 +386,13 @@ Pennylane::CRotationYGate::CRotationYGate(double rotationAngle) | |||||
0, 0, s, c } | ||||||
{} | ||||||
|
||||||
void Pennylane::CRotationYGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
v[0] = state[indices[2]]; | ||||||
v[1] = state[indices[3]]; | ||||||
state[indices[2]] = c * v[0] - s * v[1]; | ||||||
state[indices[3]] = s * v[0] + c * v[1]; | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
const string Pennylane::CRotationZGate::label = "CRZ"; | ||||||
|
@@ -318,6 +412,11 @@ Pennylane::CRotationZGate::CRotationZGate(double rotationAngle) | |||||
0, 0, 0, second } | ||||||
{} | ||||||
|
||||||
void Pennylane::CRotationZGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
state[indices[2]] *= first; | ||||||
state[indices[3]] *= second; | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
const string Pennylane::CGeneralRotationGate::label = "CRot"; | ||||||
|
@@ -330,13 +429,24 @@ Pennylane::CGeneralRotationGate Pennylane::CGeneralRotationGate::create(const ve | |||||
Pennylane::CGeneralRotationGate::CGeneralRotationGate(double phi, double theta, double omega) | ||||||
: c(std::cos(theta / 2), 0) | ||||||
, s(std::sin(theta / 2), 0) | ||||||
, r1(c* std::pow(M_E, CplxType(0, (-phi - omega) / 2))) | ||||||
, r2(-s * std::pow(M_E, CplxType(0, (phi - omega) / 2))) | ||||||
, r3(s* std::pow(M_E, CplxType(0, (-phi + omega) / 2))) | ||||||
, r4(c* std::pow(M_E, CplxType(0, (phi + omega) / 2))) | ||||||
, matrix{ | ||||||
1, 0, 0, 0, | ||||||
0, 1, 0, 0, | ||||||
0, 0, c * std::pow(M_E, CplxType(0, (-phi - omega) / 2)), -s * std::pow(M_E, CplxType(0, (phi - omega) / 2)), | ||||||
0, 0, s * std::pow(M_E, CplxType(0, (-phi + omega) / 2)), c * std::pow(M_E, CplxType(0, (phi + omega) / 2)) } | ||||||
0, 0, r1, r2, | ||||||
0, 0, r3, r4 } | ||||||
{} | ||||||
|
||||||
void Pennylane::CGeneralRotationGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
v[0] = state[indices[2]]; | ||||||
v[1] = state[indices[3]]; | ||||||
state[indices[2]] = r1 * v[0] + r2 * v[1]; | ||||||
state[indices[3]] = r3 * v[0] + r4 * v[1]; | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
Pennylane::ThreeQubitGate::ThreeQubitGate() | ||||||
|
@@ -362,6 +472,10 @@ const std::vector<CplxType> Pennylane::ToffoliGate::matrix{ | |||||
0, 0, 0, 0, 0, 0, 0, 1, | ||||||
0, 0, 0, 0, 0, 0, 1, 0 }; | ||||||
|
||||||
void Pennylane::ToffoliGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
swap(state[indices[6]], state[indices[7]]); | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
const string Pennylane::CSWAPGate::label = "CSWAP"; | ||||||
|
@@ -381,6 +495,10 @@ const std::vector<CplxType> Pennylane::CSWAPGate::matrix{ | |||||
0, 0, 0, 0, 0, 1, 0, 0, | ||||||
0, 0, 0, 0, 0, 0, 0, 1 }; | ||||||
|
||||||
void Pennylane::CSWAPGate::applyKernel(CplxType* state, vector<size_t>& indices, vector<CplxType>& v) { | ||||||
swap(state[indices[5]], state[indices[6]]); | ||||||
} | ||||||
|
||||||
// ------------------------------------------------------------------------------------------------------------- | ||||||
|
||||||
template<class GateType> | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯