From b8ab1944393fcaf502edcdd00b058c89abe0e057 Mon Sep 17 00:00:00 2001 From: trbromley Date: Tue, 16 Mar 2021 12:53:09 -0400 Subject: [PATCH 01/26] Expose inverse --- pennylane_lightning/lightning_qubit.py | 3 ++- pennylane_lightning/src/Apply.cpp | 4 +++- pennylane_lightning/src/Apply.hpp | 5 +++++ pennylane_lightning/src/Bindings.cpp | 3 ++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index 4e5ffadce5..5d29eb0421 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -136,7 +136,8 @@ def apply_lightning(self, state, operations): op_names = [o.name for o in operations] op_wires = [self.wires.indices(o.wires) for o in operations] op_param = [o.parameters for o in operations] + op_inverse = [o.inverse for o in operations] state_vector = np.ravel(state) - apply(state_vector, op_names, op_wires, op_param, self.num_wires) + apply(state_vector, op_names, op_wires, op_param, op_inverse, self.num_wires) return np.reshape(state_vector, state.shape) diff --git a/pennylane_lightning/src/Apply.cpp b/pennylane_lightning/src/Apply.cpp index 866ec6c39a..d9009a7a3e 100644 --- a/pennylane_lightning/src/Apply.cpp +++ b/pennylane_lightning/src/Apply.cpp @@ -53,6 +53,7 @@ void Pennylane::constructAndApplyOperation( const string& opLabel, const vector& opWires, const vector& opParams, + bool inverse, const unsigned int qubits ) { unique_ptr gate = constructGate(opLabel, opParams); @@ -72,6 +73,7 @@ void Pennylane::apply( const vector& ops, const vector>& wires, const vector>& params, + const std::vector& inverse, const unsigned int qubits ) { if (qubits <= 0) @@ -86,7 +88,7 @@ void Pennylane::apply( 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], qubits); + constructAndApplyOperation(state, ops[i], wires[i], params[i], inverse[i], qubits); } } diff --git a/pennylane_lightning/src/Apply.hpp b/pennylane_lightning/src/Apply.hpp index 0ec1d79ca4..6f7db3afd1 100644 --- a/pennylane_lightning/src/Apply.hpp +++ b/pennylane_lightning/src/Apply.hpp @@ -62,6 +62,7 @@ namespace Pennylane { * @param opLabel unique string corresponding to a gate type * @param opWires index of qubits on which the gate acts * @param opParams defines the gate parameterisation (may be zero-length for some gates) + * @param inverse boolean indicating whether to apply the gate or its inverse * @param qubits number of qubits */ void constructAndApplyOperation( @@ -69,6 +70,7 @@ namespace Pennylane { const std::string& opLabel, const std::vector& opWires, const std::vector& opParams, + bool inverse, const unsigned int qubits ); @@ -79,12 +81,15 @@ namespace Pennylane { * @param ops list of unique string names corresponding to gate types, in the order they should be applied * @param wires list of wires on which each gate acts * @param params list of parameters that defines the gate parameterisation + * @param inverse list of bools indicating whether a given gate or its inverse should be applied + * @param qubits total number of qubits */ void apply( StateVector& state, const std::vector& ops, const std::vector>& wires, const std::vector>& params, + const std::vector& inverse, const unsigned int qubits ); diff --git a/pennylane_lightning/src/Bindings.cpp b/pennylane_lightning/src/Bindings.cpp index d05772ecc7..5dc66ee941 100644 --- a/pennylane_lightning/src/Bindings.cpp +++ b/pennylane_lightning/src/Bindings.cpp @@ -39,10 +39,11 @@ void apply( vector ops, vector> wires, vector> params, + vector inverse, const unsigned int qubits ) { StateVector state = create(&stateNumpyArray); - Pennylane::apply(state, ops, wires, params, qubits); + Pennylane::apply(state, ops, wires, params, inverse, qubits); } PYBIND11_MODULE(lightning_qubit_ops, m) From 4b049e7a66a7760d6cc6c5b8b0b4bf73f0e39252 Mon Sep 17 00:00:00 2001 From: trbromley Date: Tue, 16 Mar 2021 13:05:42 -0400 Subject: [PATCH 02/26] Expose inverse to kernels --- pennylane_lightning/src/Apply.cpp | 2 +- pennylane_lightning/src/Gates.cpp | 36 +++++++++++++++---------------- pennylane_lightning/src/Gates.hpp | 36 +++++++++++++++---------------- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/pennylane_lightning/src/Apply.cpp b/pennylane_lightning/src/Apply.cpp index d9009a7a3e..c09a26705d 100644 --- a/pennylane_lightning/src/Apply.cpp +++ b/pennylane_lightning/src/Apply.cpp @@ -65,7 +65,7 @@ void Pennylane::constructAndApplyOperation( vector externalWires = getIndicesAfterExclusion(opWires, qubits); vector externalIndices = generateBitPatterns(externalWires, qubits); - gate->applyKernel(state, internalIndices, externalIndices); + gate->applyKernel(state, internalIndices, externalIndices, inverse); } void Pennylane::apply( diff --git a/pennylane_lightning/src/Gates.cpp b/pennylane_lightning/src/Gates.cpp index 9699481cbd..1cf4004480 100644 --- a/pennylane_lightning/src/Gates.cpp +++ b/pennylane_lightning/src/Gates.cpp @@ -44,7 +44,7 @@ Pennylane::AbstractGate::AbstractGate(int numQubits) , length(exp2(numQubits)) {} -void Pennylane::AbstractGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::AbstractGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { const vector& matrix = asMatrix(); assert(indices.size() == length); @@ -89,7 +89,7 @@ const vector Pennylane::XGate::matrix{ 0, 1, 1, 0 }; -void Pennylane::XGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::XGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; swap(shiftedState[indices[0]], shiftedState[indices[1]]); @@ -109,7 +109,7 @@ const vector Pennylane::YGate::matrix{ 0, -IMAG, IMAG, 0 }; -void Pennylane::YGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::YGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; CplxType v0 = shiftedState[indices[0]]; @@ -131,7 +131,7 @@ const std::vector Pennylane::ZGate::matrix{ 1, 0, 0, -1 }; -void Pennylane::ZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::ZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; shiftedState[indices[1]] *= -1; @@ -151,7 +151,7 @@ const vector Pennylane::HadamardGate::matrix{ SQRT2INV, SQRT2INV, SQRT2INV, -SQRT2INV }; -void Pennylane::HadamardGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::HadamardGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; CplxType v0 = shiftedState[indices[0]]; @@ -174,7 +174,7 @@ const vector Pennylane::SGate::matrix{ 1, 0, 0, IMAG }; -void Pennylane::SGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::SGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; shiftedState[indices[1]] *= IMAG; @@ -196,7 +196,7 @@ const vector Pennylane::TGate::matrix{ 1, 0, 0, Pennylane::TGate::shift }; -void Pennylane::TGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::TGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; shiftedState[indices[1]] *= Pennylane::TGate::shift; @@ -254,7 +254,7 @@ Pennylane::RotationZGate::RotationZGate(double rotationAngle) 0, second } {} -void Pennylane::RotationZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::RotationZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; shiftedState[indices[0]] *= first; @@ -278,7 +278,7 @@ Pennylane::PhaseShiftGate::PhaseShiftGate(double rotationAngle) 0, shift } {} -void Pennylane::PhaseShiftGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::PhaseShiftGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; shiftedState[indices[1]] *= shift; @@ -327,7 +327,7 @@ const std::vector Pennylane::CNOTGate::matrix{ 0, 0, 0, 1, 0, 0, 1, 0 }; -void Pennylane::CNOTGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::CNOTGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; swap(shiftedState[indices[2]], shiftedState[indices[3]]); @@ -349,7 +349,7 @@ const std::vector Pennylane::SWAPGate::matrix{ 0, 1, 0, 0, 0, 0, 0, 1 }; -void Pennylane::SWAPGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::SWAPGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; swap(shiftedState[indices[1]], shiftedState[indices[2]]); @@ -371,7 +371,7 @@ const std::vector Pennylane::CZGate::matrix{ 0, 0, 1, 0, 0, 0, 0, -1 }; -void Pennylane::CZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::CZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; shiftedState[indices[3]] *= -1; @@ -397,7 +397,7 @@ Pennylane::CRotationXGate::CRotationXGate(double rotationAngle) 0, 0, js, c } {} -void Pennylane::CRotationXGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::CRotationXGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; CplxType v0 = shiftedState[indices[2]]; @@ -426,7 +426,7 @@ Pennylane::CRotationYGate::CRotationYGate(double rotationAngle) 0, 0, s, c } {} -void Pennylane::CRotationYGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::CRotationYGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; CplxType v0 = shiftedState[indices[2]]; @@ -455,7 +455,7 @@ Pennylane::CRotationZGate::CRotationZGate(double rotationAngle) 0, 0, 0, second } {} -void Pennylane::CRotationZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::CRotationZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; shiftedState[indices[2]] *= first; @@ -486,7 +486,7 @@ Pennylane::CGeneralRotationGate::CGeneralRotationGate(double phi, double theta, 0, 0, r3, r4 } {} -void Pennylane::CGeneralRotationGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::CGeneralRotationGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; CplxType v0 = shiftedState[indices[2]]; @@ -521,7 +521,7 @@ const std::vector Pennylane::ToffoliGate::matrix{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0 }; -void Pennylane::ToffoliGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::ToffoliGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; swap(shiftedState[indices[6]], shiftedState[indices[7]]); @@ -547,7 +547,7 @@ const std::vector Pennylane::CSWAPGate::matrix{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; -void Pennylane::CSWAPGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices) { +void Pennylane::CSWAPGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; swap(shiftedState[indices[5]], shiftedState[indices[6]]); diff --git a/pennylane_lightning/src/Gates.hpp b/pennylane_lightning/src/Gates.hpp index d5f1d43ece..516086ca0f 100644 --- a/pennylane_lightning/src/Gates.hpp +++ b/pennylane_lightning/src/Gates.hpp @@ -43,7 +43,7 @@ namespace Pennylane { /** * Generic matrix-multiplication kernel */ - virtual void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + virtual void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; // Single-qubit gates: @@ -62,7 +62,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class YGate : public SingleQubitGate { @@ -74,7 +74,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class ZGate : public SingleQubitGate { @@ -86,7 +86,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class HadamardGate : public SingleQubitGate { @@ -98,7 +98,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class SGate : public SingleQubitGate { @@ -110,7 +110,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class TGate : public SingleQubitGate { @@ -123,7 +123,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class RotationXGate : public SingleQubitGate { @@ -163,7 +163,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class PhaseShiftGate : public SingleQubitGate { @@ -177,7 +177,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class GeneralRotationGate : public SingleQubitGate { @@ -209,7 +209,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class SWAPGate : public TwoQubitGate { @@ -221,7 +221,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class CZGate : public TwoQubitGate { @@ -233,7 +233,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class CRotationXGate : public TwoQubitGate { @@ -247,7 +247,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class CRotationYGate : public TwoQubitGate { @@ -261,7 +261,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class CRotationZGate : public TwoQubitGate { @@ -275,7 +275,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class CGeneralRotationGate : public TwoQubitGate { @@ -289,7 +289,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; // Three-qubit gates @@ -308,7 +308,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class CSWAPGate : public ThreeQubitGate { @@ -320,7 +320,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } - void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices); + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; /** From e066a813a5dd129fc2fd79aa884055b0842c3bae Mon Sep 17 00:00:00 2001 From: trbromley Date: Tue, 16 Mar 2021 13:33:45 -0400 Subject: [PATCH 03/26] Add inverses --- pennylane_lightning/src/Gates.cpp | 40 +++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/pennylane_lightning/src/Gates.cpp b/pennylane_lightning/src/Gates.cpp index 1cf4004480..e8c840125d 100644 --- a/pennylane_lightning/src/Gates.cpp +++ b/pennylane_lightning/src/Gates.cpp @@ -28,6 +28,7 @@ using std::string; using std::swap; using std::unique_ptr; using std::vector; +using std::conj; using Pennylane::CplxType; @@ -90,6 +91,7 @@ const vector Pennylane::XGate::matrix{ 1, 0 }; void Pennylane::XGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + (void)inverse; // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; swap(shiftedState[indices[0]], shiftedState[indices[1]]); @@ -110,6 +112,7 @@ const vector Pennylane::YGate::matrix{ IMAG, 0 }; void Pennylane::YGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + (void)inverse; // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; CplxType v0 = shiftedState[indices[0]]; @@ -132,6 +135,7 @@ const std::vector Pennylane::ZGate::matrix{ 0, -1 }; void Pennylane::ZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + (void)inverse; // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; shiftedState[indices[1]] *= -1; @@ -152,6 +156,7 @@ const vector Pennylane::HadamardGate::matrix{ SQRT2INV, -SQRT2INV }; void Pennylane::HadamardGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + (void)inverse; // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; CplxType v0 = shiftedState[indices[0]]; @@ -175,9 +180,13 @@ const vector Pennylane::SGate::matrix{ 0, IMAG }; void Pennylane::SGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + + CplxType shift = IMAG; + if (inverse == true) {shift *= -1;} + for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; - shiftedState[indices[1]] *= IMAG; + shiftedState[indices[1]] *= shift; } } @@ -197,9 +206,13 @@ const vector Pennylane::TGate::matrix{ 0, Pennylane::TGate::shift }; void Pennylane::TGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + + CplxType shift = Pennylane::TGate::shift; + if (inverse == true) {shift *= -1;} + for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; - shiftedState[indices[1]] *= Pennylane::TGate::shift; + shiftedState[indices[1]] *= shift; } } @@ -255,10 +268,19 @@ Pennylane::RotationZGate::RotationZGate(double rotationAngle) {} void Pennylane::RotationZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + + CplxType shift1 = first; + CplxType shift2 = second; + + if (inverse == true) { + shift1 = conj(first); + shift2 = conj(second); + } + for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; - shiftedState[indices[0]] *= first; - shiftedState[indices[1]] *= second; + shiftedState[indices[0]] *= shift1; + shiftedState[indices[1]] *= shift2; } } @@ -279,9 +301,14 @@ Pennylane::PhaseShiftGate::PhaseShiftGate(double rotationAngle) {} void Pennylane::PhaseShiftGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + + CplxType s = shift; + + if (inverse == true){s *= -1;} + for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; - shiftedState[indices[1]] *= shift; + shiftedState[indices[1]] *= s; } } @@ -328,6 +355,7 @@ const std::vector Pennylane::CNOTGate::matrix{ 0, 0, 1, 0 }; void Pennylane::CNOTGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + (void)inverse; // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; swap(shiftedState[indices[2]], shiftedState[indices[3]]); @@ -350,6 +378,7 @@ const std::vector Pennylane::SWAPGate::matrix{ 0, 0, 0, 1 }; void Pennylane::SWAPGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + (void)inverse; // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; swap(shiftedState[indices[1]], shiftedState[indices[2]]); @@ -372,6 +401,7 @@ const std::vector Pennylane::CZGate::matrix{ 0, 0, 0, -1 }; void Pennylane::CZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + (void)inverse; // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; shiftedState[indices[3]] *= -1; From 5bfcc8a35145b2ca877beb8dd4f3627edb06da5f Mon Sep 17 00:00:00 2001 From: trbromley Date: Tue, 16 Mar 2021 13:48:08 -0400 Subject: [PATCH 04/26] Add to inverses --- pennylane_lightning/src/Gates.cpp | 50 ++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/pennylane_lightning/src/Gates.cpp b/pennylane_lightning/src/Gates.cpp index e8c840125d..9fede79011 100644 --- a/pennylane_lightning/src/Gates.cpp +++ b/pennylane_lightning/src/Gates.cpp @@ -428,12 +428,17 @@ Pennylane::CRotationXGate::CRotationXGate(double rotationAngle) {} void Pennylane::CRotationXGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + + CplxType js_ = js; + + if (inverse == true) {js_ *= -1;} + for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; CplxType v0 = shiftedState[indices[2]]; CplxType v1 = shiftedState[indices[3]]; - shiftedState[indices[2]] = c * v0 + js * v1; - shiftedState[indices[3]] = js * v0 + c * v1; + shiftedState[indices[2]] = c * v0 + js_ * v1; + shiftedState[indices[3]] = js_ * v0 + c * v1; } } @@ -457,12 +462,17 @@ Pennylane::CRotationYGate::CRotationYGate(double rotationAngle) {} void Pennylane::CRotationYGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + + CplxType s_ = s; + + if (inverse == true) {s_ *= -1;} + for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; CplxType v0 = shiftedState[indices[2]]; CplxType v1 = shiftedState[indices[3]]; - shiftedState[indices[2]] = c * v0 - s * v1; - shiftedState[indices[3]] = s * v0 + c * v1; + shiftedState[indices[2]] = c * v0 - s_ * v1; + shiftedState[indices[3]] = s_ * v0 + c * v1; } } @@ -486,10 +496,19 @@ Pennylane::CRotationZGate::CRotationZGate(double rotationAngle) {} void Pennylane::CRotationZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + + CplxType shift1 = first; + CplxType shift2 = second; + + if (inverse == true) { + shift1 = conj(first); + shift2 = conj(second); + } + for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; - shiftedState[indices[2]] *= first; - shiftedState[indices[3]] *= second; + shiftedState[indices[2]] *= shift1; + shiftedState[indices[3]] *= shift2; } } @@ -517,12 +536,25 @@ Pennylane::CGeneralRotationGate::CGeneralRotationGate(double phi, double theta, {} void Pennylane::CGeneralRotationGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + + CplxType t1 = r1; + CplxType t2 = r2; + CplxType t3 = r3; + CplxType t4 = r4; + + if (inverse == true) { + t1 = conj(r1); + t2 *= -1; + t3 *= -1; + t4 = conj(t4); + } + for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; CplxType v0 = shiftedState[indices[2]]; CplxType v1 = shiftedState[indices[3]]; - shiftedState[indices[2]] = r1 * v0 + r2 * v1; - shiftedState[indices[3]] = r3 * v0 + r4 * v1; + shiftedState[indices[2]] = t1 * v0 + t2 * v1; + shiftedState[indices[3]] = t3 * v0 + t4 * v1; } } @@ -552,6 +584,7 @@ const std::vector Pennylane::ToffoliGate::matrix{ 0, 0, 0, 0, 0, 0, 1, 0 }; void Pennylane::ToffoliGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + (void)inverse; // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; swap(shiftedState[indices[6]], shiftedState[indices[7]]); @@ -578,6 +611,7 @@ const std::vector Pennylane::CSWAPGate::matrix{ 0, 0, 0, 0, 0, 0, 0, 1 }; void Pennylane::CSWAPGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + (void)inverse; // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; swap(shiftedState[indices[5]], shiftedState[indices[6]]); From a98e895b3c10382a65d547a3ab80a220b20c0a1e Mon Sep 17 00:00:00 2001 From: trbromley Date: Tue, 16 Mar 2021 13:54:37 -0400 Subject: [PATCH 05/26] Add missing kernels --- pennylane_lightning/src/Gates.cpp | 30 ++++++++++++++++++++++++++++++ pennylane_lightning/src/Gates.hpp | 2 ++ 2 files changed, 32 insertions(+) diff --git a/pennylane_lightning/src/Gates.cpp b/pennylane_lightning/src/Gates.cpp index 9fede79011..6bb69cdb78 100644 --- a/pennylane_lightning/src/Gates.cpp +++ b/pennylane_lightning/src/Gates.cpp @@ -233,6 +233,21 @@ Pennylane::RotationXGate::RotationXGate(double rotationAngle) js, c } {} +void Pennylane::RotationXGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + + CplxType js_ = js; + + if (inverse == true) {js_ *= -1;} + + for (const size_t& externalIndex : externalIndices) { + CplxType* shiftedState = state.arr + externalIndex; + CplxType v0 = shiftedState[indices[0]]; + CplxType v1 = shiftedState[indices[1]]; + shiftedState[indices[0]] = c * v0 + js_ * v1; + shiftedState[indices[1]] = js_ * v0 + c * v1; + } +} + // ------------------------------------------------------------------------------------------------------------- const string Pennylane::RotationYGate::label = "RY"; @@ -250,6 +265,21 @@ Pennylane::RotationYGate::RotationYGate(double rotationAngle) s, c } {} +void Pennylane::RotationYGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + + CplxType s_ = s; + + if (inverse == true) {s_ *= -1;} + + for (const size_t& externalIndex : externalIndices) { + CplxType* shiftedState = state.arr + externalIndex; + CplxType v0 = shiftedState[indices[0]]; + CplxType v1 = shiftedState[indices[1]]; + shiftedState[indices[0]] = c * v0 - s_ * v1; + shiftedState[indices[1]] = s_ * v0 + c * v1; + } +} + // ------------------------------------------------------------------------------------------------------------- const string Pennylane::RotationZGate::label = "RZ"; diff --git a/pennylane_lightning/src/Gates.hpp b/pennylane_lightning/src/Gates.hpp index 516086ca0f..50decc7886 100644 --- a/pennylane_lightning/src/Gates.hpp +++ b/pennylane_lightning/src/Gates.hpp @@ -137,6 +137,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class RotationYGate : public SingleQubitGate { @@ -150,6 +151,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; class RotationZGate : public SingleQubitGate { From 9e9ce90c4f916e70e1e473378cf2166699d7a53c Mon Sep 17 00:00:00 2001 From: Tom Bromley <49409390+trbromley@users.noreply.github.com> Date: Tue, 16 Mar 2021 13:57:32 -0400 Subject: [PATCH 06/26] Update pennylane_lightning/src/Apply.hpp --- pennylane_lightning/src/Apply.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/src/Apply.hpp b/pennylane_lightning/src/Apply.hpp index 6f7db3afd1..4d9cfec615 100644 --- a/pennylane_lightning/src/Apply.hpp +++ b/pennylane_lightning/src/Apply.hpp @@ -82,7 +82,7 @@ namespace Pennylane { * @param wires list of wires on which each gate acts * @param params list of parameters that defines the gate parameterisation * @param inverse list of bools indicating whether a given gate or its inverse should be applied - * @param qubits total number of qubits + * @param qubits number of qubits */ void apply( StateVector& state, From cfe99dec29f616c3e7ddc7559376a66dd3cf59df Mon Sep 17 00:00:00 2001 From: trbromley Date: Tue, 16 Mar 2021 14:10:31 -0400 Subject: [PATCH 07/26] Add inverse in general kernel: --- pennylane_lightning/src/Gates.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/pennylane_lightning/src/Gates.cpp b/pennylane_lightning/src/Gates.cpp index 6bb69cdb78..e772b098cd 100644 --- a/pennylane_lightning/src/Gates.cpp +++ b/pennylane_lightning/src/Gates.cpp @@ -63,9 +63,17 @@ void Pennylane::AbstractGate::applyKernel(const StateVector& state, const std::v for (size_t i = 0; i < indices.size(); i++) { size_t index = indices[i]; shiftedState[index] = 0; - size_t baseIndex = i * indices.size(); - for (size_t j = 0; j < indices.size(); j++) { - shiftedState[index] += matrix[baseIndex + j] * v[j]; + + if (inverse == true) { + for (size_t j = 0; j < indices.size(); j++) { + size_t baseIndex = j * indices.size(); + shiftedState[index] += conj(matrix[baseIndex + i]) * v[j]; + } + } else { + size_t baseIndex = i * indices.size(); + for (size_t j = 0; j < indices.size(); j++) { + shiftedState[index] += matrix[baseIndex + j] * v[j]; + } } } } From 680e3fc0eaca77209eaa85be8c805aa47121acb2 Mon Sep 17 00:00:00 2001 From: trbromley Date: Tue, 16 Mar 2021 14:17:51 -0400 Subject: [PATCH 08/26] Update capability --- pennylane_lightning/lightning_qubit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index 5d29eb0421..a872328d08 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -85,7 +85,7 @@ def capabilities(cls): capabilities.update( model="qubit", supports_reversible_diff=False, - supports_inverse_operations=False, + supports_inverse_operations=True, supports_analytic_computation=True, returns_state=True, ) From 0653d4f617d1144717fe1237c7ed851428e51d38 Mon Sep 17 00:00:00 2001 From: trbromley Date: Tue, 16 Mar 2021 14:22:26 -0400 Subject: [PATCH 09/26] Remove .inv from string --- pennylane_lightning/lightning_qubit.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index a872328d08..5b040a9898 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -133,7 +133,7 @@ def apply_lightning(self, state, operations): Returns: array[complex]: the output state tensor """ - op_names = [o.name for o in operations] + op_names = [self._remove_inverse_string(o.name) for o in operations] op_wires = [self.wires.indices(o.wires) for o in operations] op_param = [o.parameters for o in operations] op_inverse = [o.inverse for o in operations] @@ -141,3 +141,8 @@ def apply_lightning(self, state, operations): state_vector = np.ravel(state) apply(state_vector, op_names, op_wires, op_param, op_inverse, self.num_wires) return np.reshape(state_vector, state.shape) + + @staticmethod + def _remove_inverse_string(str): + return str.split(".")[0] + From cffc956791fc32f2a6e22621324ee6f55224aabb Mon Sep 17 00:00:00 2001 From: trbromley Date: Tue, 16 Mar 2021 18:00:22 -0400 Subject: [PATCH 10/26] Add tests --- pennylane_lightning/lightning_qubit.py | 23 +++++++++++ tests/test_inverse.py | 56 ++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 tests/test_inverse.py diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index 5b040a9898..4446fac903 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -74,6 +74,29 @@ class LightningQubit(DefaultQubit): "CRot", } + kernel_operations = { + "PauliX", + "PauliY", + "PauliZ", + "Hadamard", + "Hadamard", + "S", + "T", + "RX", + "RY", + "RZ", + "PhaseShift", + "CNOT", + "SWAP", + "CZ", + "CRX", + "CRY", + "CRZ", + "CRot", + "Toffoli", + "CSWAP", + } + observables = {"PauliX", "PauliY", "PauliZ", "Hadamard", "Hermitian", "Identity"} def __init__(self, wires, *, shots=1000, analytic=True): diff --git a/tests/test_inverse.py b/tests/test_inverse.py new file mode 100644 index 0000000000..fbe7310d08 --- /dev/null +++ b/tests/test_inverse.py @@ -0,0 +1,56 @@ +# 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. +""" +Unit tests for the inverse of gates with lightning.qubit +""" +import pytest +import pennylane as qml +from pennylane_lightning import LightningQubit +import numpy as np +import itertools + +@pytest.fixture +def op(op_name): + return getattr(qml, op_name) + + +@pytest.mark.parametrize("op_name", LightningQubit.kernel_operations) +def test_inverse_correct(op, op_name): + wires = op.num_wires + dev = qml.device("lightning.qubit", wires=wires) + num_params = op.num_params + p = [0.1] * num_params + + @qml.qnode(dev) + def output(input): + qml.BasisState(input, wires=range(wires)) + op(*p, wires=range(wires)).inv() + return qml.state() + + unitary = np.zeros((2 ** wires, 2 ** wires)) + + for i, input in enumerate(itertools.product([0, 1], repeat=wires)): + out = output(input) + unitary[:, i] = out + + unitary_expected = op(*p, wires=range(wires)).inv().matrix + + # assert np.allclose(unitary, unitary_expected) + + if not np.allclose(unitary, unitary_expected): + print(op_name) + print(unitary) + print(unitary_expected) + print() + From 00f07cd35a6162ae97b621c126ab160b2e2f2bd3 Mon Sep 17 00:00:00 2001 From: trbromley Date: Wed, 17 Mar 2021 07:58:57 -0400 Subject: [PATCH 11/26] Fix phase shift --- pennylane_lightning/src/Gates.cpp | 2 +- tests/{test_inverse.py => test_gates.py} | 44 ++++++++++++++++++------ 2 files changed, 34 insertions(+), 12 deletions(-) rename tests/{test_inverse.py => test_gates.py} (52%) diff --git a/pennylane_lightning/src/Gates.cpp b/pennylane_lightning/src/Gates.cpp index e772b098cd..074944680c 100644 --- a/pennylane_lightning/src/Gates.cpp +++ b/pennylane_lightning/src/Gates.cpp @@ -342,7 +342,7 @@ void Pennylane::PhaseShiftGate::applyKernel(const StateVector& state, const std: CplxType s = shift; - if (inverse == true){s *= -1;} + if (inverse == true){s *= conj(shift);} for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; diff --git a/tests/test_inverse.py b/tests/test_gates.py similarity index 52% rename from tests/test_inverse.py rename to tests/test_gates.py index fbe7310d08..927d05fac3 100644 --- a/tests/test_inverse.py +++ b/tests/test_gates.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. """ -Unit tests for the inverse of gates with lightning.qubit +Unit tests for the correct application of gates with lightning.qubit """ import pytest import pennylane as qml @@ -20,13 +20,16 @@ import numpy as np import itertools + @pytest.fixture def op(op_name): return getattr(qml, op_name) @pytest.mark.parametrize("op_name", LightningQubit.kernel_operations) -def test_inverse_correct(op, op_name): +def test_gate_unitary_correct(op, op_name): + """Test if lightning.qubit correctly applies gates by reconstructing the unitary matrix and + comparing to the expected version""" wires = op.num_wires dev = qml.device("lightning.qubit", wires=wires) num_params = op.num_params @@ -35,22 +38,41 @@ def test_inverse_correct(op, op_name): @qml.qnode(dev) def output(input): qml.BasisState(input, wires=range(wires)) - op(*p, wires=range(wires)).inv() + op(*p, wires=range(wires)) return qml.state() - unitary = np.zeros((2 ** wires, 2 ** wires)) + unitary = np.zeros((2 ** wires, 2 ** wires), dtype=np.complex128) for i, input in enumerate(itertools.product([0, 1], repeat=wires)): out = output(input) unitary[:, i] = out - unitary_expected = op(*p, wires=range(wires)).inv().matrix + unitary_expected = op(*p, wires=range(wires)).matrix + + assert np.allclose(unitary, unitary_expected) + + +@pytest.mark.parametrize("op_name", LightningQubit.kernel_operations) +def test_inverse_unitary_correct(op, op_name): + """Test if lightning.qubit correctly applies inverse gates by reconstructing the unitary matrix + and comparing to the expected version""" + wires = op.num_wires + dev = qml.device("lightning.qubit", wires=wires) + num_params = op.num_params + p = [0.1] * num_params - # assert np.allclose(unitary, unitary_expected) + @qml.qnode(dev) + def output(input): + qml.BasisState(input, wires=range(wires)) + op(*p, wires=range(wires)).inv() + return qml.state() + + unitary = np.zeros((2 ** wires, 2 ** wires), dtype=np.complex128) - if not np.allclose(unitary, unitary_expected): - print(op_name) - print(unitary) - print(unitary_expected) - print() + for i, input in enumerate(itertools.product([0, 1], repeat=wires)): + out = output(input) + unitary[:, i] = out + + unitary_expected = op(*p, wires=range(wires)).inv().matrix + assert np.allclose(unitary, unitary_expected) From 7b3a183700f0dc97b949dcb3cc255ded11518d8f Mon Sep 17 00:00:00 2001 From: trbromley Date: Wed, 17 Mar 2021 08:02:11 -0400 Subject: [PATCH 12/26] Fix --- pennylane_lightning/src/Gates.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pennylane_lightning/src/Gates.cpp b/pennylane_lightning/src/Gates.cpp index 074944680c..7b53f6ee54 100644 --- a/pennylane_lightning/src/Gates.cpp +++ b/pennylane_lightning/src/Gates.cpp @@ -216,7 +216,7 @@ const vector Pennylane::TGate::matrix{ void Pennylane::TGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { CplxType shift = Pennylane::TGate::shift; - if (inverse == true) {shift *= -1;} + if (inverse == true) {shift = conj(Pennylane::TGate::shift);} for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; @@ -342,7 +342,7 @@ void Pennylane::PhaseShiftGate::applyKernel(const StateVector& state, const std: CplxType s = shift; - if (inverse == true){s *= conj(shift);} + if (inverse == true){s = conj(shift);} for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; From 4183b81ff3ee24461e86bdb4fb26a2c259bc1af2 Mon Sep 17 00:00:00 2001 From: trbromley Date: Wed, 17 Mar 2021 08:07:01 -0400 Subject: [PATCH 13/26] Add Rot kernel --- pennylane_lightning/lightning_qubit.py | 1 + pennylane_lightning/src/Gates.cpp | 23 +++++++++++++++++++++++ pennylane_lightning/src/Gates.hpp | 1 + 3 files changed, 25 insertions(+) diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index 4446fac903..be98437764 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -86,6 +86,7 @@ class LightningQubit(DefaultQubit): "RY", "RZ", "PhaseShift", + "Rot", "CNOT", "SWAP", "CZ", diff --git a/pennylane_lightning/src/Gates.cpp b/pennylane_lightning/src/Gates.cpp index 7b53f6ee54..4e167fe03a 100644 --- a/pennylane_lightning/src/Gates.cpp +++ b/pennylane_lightning/src/Gates.cpp @@ -371,6 +371,29 @@ Pennylane::GeneralRotationGate::GeneralRotationGate(double phi, double theta, do r3, r4 } {} +void Pennylane::GeneralRotationGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { + + CplxType t1 = r1; + CplxType t2 = r2; + CplxType t3 = r3; + CplxType t4 = r4; + + if (inverse == true) { + t1 = conj(r1); + t2 *= -1; + t3 *= -1; + t4 = conj(t4); + } + + for (const size_t& externalIndex : externalIndices) { + CplxType* shiftedState = state.arr + externalIndex; + CplxType v0 = shiftedState[indices[0]]; + CplxType v1 = shiftedState[indices[1]]; + shiftedState[indices[0]] = t1 * v0 + t2 * v1; + shiftedState[indices[1]] = t3 * v0 + t4 * v1; + } +} + // ------------------------------------------------------------------------------------------------------------- Pennylane::TwoQubitGate::TwoQubitGate() diff --git a/pennylane_lightning/src/Gates.hpp b/pennylane_lightning/src/Gates.hpp index 50decc7886..4d6b3e7341 100644 --- a/pennylane_lightning/src/Gates.hpp +++ b/pennylane_lightning/src/Gates.hpp @@ -193,6 +193,7 @@ namespace Pennylane { inline const std::vector& asMatrix() { return matrix; } + void applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse); }; // Two-qubit gates From 43a5d07bb26f0c1db6efa07a0541f46395e89aeb Mon Sep 17 00:00:00 2001 From: trbromley Date: Wed, 17 Mar 2021 14:53:58 -0400 Subject: [PATCH 14/26] Add tests for arbitrary unitary --- tests/test_gates.py | 55 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tests/test_gates.py b/tests/test_gates.py index 927d05fac3..d98de14cee 100644 --- a/tests/test_gates.py +++ b/tests/test_gates.py @@ -76,3 +76,58 @@ def output(input): unitary_expected = op(*p, wires=range(wires)).inv().matrix assert np.allclose(unitary, unitary_expected) + + +random_unitary = np.array([[-0.48401572-0.11012304j, -0.44806504+0.46775911j, + -0.36968281+0.19235993j, -0.37561358+0.13887962j], + [-0.12838047+0.13992187j, 0.14531831+0.45319438j, + 0.28902175-0.71158765j, -0.24333677-0.29721109j], + [ 0.26400811-0.72519269j, 0.13965687+0.35092711j, + 0.09141515-0.14367072j, 0.14894673+0.45886629j], + [-0.04067799+0.34681783j, -0.45852968-0.03214391j, + -0.10528164-0.4431247j , 0.50251451+0.45476965j]]) + + +@pytest.mark.xfail(strict=True) # needs support for QubitUnitary +def test_arbitrary_unitary_correct(): + """Test if lightning.qubit correctly applies an arbitrary unitary by reconstructing its + matrix""" + wires = 2 + dev = qml.device("lightning.qubit", wires=wires) + + @qml.qnode(dev) + def output(input): + qml.BasisState(input, wires=range(wires)) + qml.QubitUnitary(random_unitary, wires=range(2)) + return qml.state() + + unitary = np.zeros((2 ** wires, 2 ** wires), dtype=np.complex128) + + for i, input in enumerate(itertools.product([0, 1], repeat=wires)): + out = output(input) + unitary[:, i] = out + + assert np.allclose(unitary, random_unitary) + + +@pytest.mark.xfail(strict=True) # needs support for QubitUnitary +def test_arbitrary_inv_unitary_correct(): + """Test if lightning.qubit correctly applies the inverse of an arbitrary unitary by + reconstructing its matrix""" + wires = 2 + dev = qml.device("lightning.qubit", wires=wires) + + @qml.qnode(dev) + def output(input): + qml.BasisState(input, wires=range(wires)) + qml.QubitUnitary(random_unitary, wires=range(2)).inv() + return qml.state() + + unitary = np.zeros((2 ** wires, 2 ** wires), dtype=np.complex128) + + for i, input in enumerate(itertools.product([0, 1], repeat=wires)): + out = output(input) + unitary[:, i] = out + + random_unitary_inv = random_unitary.conj().T + assert np.allclose(unitary, random_unitary_inv) From 04bbe3509c2428e387c3658e057a4c27740dbdb4 Mon Sep 17 00:00:00 2001 From: trbromley Date: Wed, 17 Mar 2021 16:00:21 -0400 Subject: [PATCH 15/26] Remove --- tests/test_gates.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_gates.py b/tests/test_gates.py index d98de14cee..703cfd4942 100644 --- a/tests/test_gates.py +++ b/tests/test_gates.py @@ -27,7 +27,7 @@ def op(op_name): @pytest.mark.parametrize("op_name", LightningQubit.kernel_operations) -def test_gate_unitary_correct(op, op_name): +def test_gate_unitary_correct(op): """Test if lightning.qubit correctly applies gates by reconstructing the unitary matrix and comparing to the expected version""" wires = op.num_wires @@ -53,7 +53,7 @@ def output(input): @pytest.mark.parametrize("op_name", LightningQubit.kernel_operations) -def test_inverse_unitary_correct(op, op_name): +def test_inverse_unitary_correct(op): """Test if lightning.qubit correctly applies inverse gates by reconstructing the unitary matrix and comparing to the expected version""" wires = op.num_wires From bed0ac8b663f65e8856b99b0eb44b1106972d05e Mon Sep 17 00:00:00 2001 From: trbromley Date: Wed, 17 Mar 2021 16:01:15 -0400 Subject: [PATCH 16/26] Rename --- pennylane_lightning/lightning_qubit.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index be98437764..a2753f6db5 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -167,6 +167,5 @@ def apply_lightning(self, state, operations): return np.reshape(state_vector, state.shape) @staticmethod - def _remove_inverse_string(str): - return str.split(".")[0] - + def _remove_inverse_string(string): + return string.split(".")[0] From 1d46c6a7b4a6439e5672573c39a0c58dfb7c25d1 Mon Sep 17 00:00:00 2001 From: trbromley Date: Wed, 17 Mar 2021 16:01:57 -0400 Subject: [PATCH 17/26] Fix --- tests/test_gates.py | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/tests/test_gates.py b/tests/test_gates.py index 703cfd4942..8781579b5a 100644 --- a/tests/test_gates.py +++ b/tests/test_gates.py @@ -14,11 +14,13 @@ """ Unit tests for the correct application of gates with lightning.qubit """ -import pytest +import itertools + +import numpy as np import pennylane as qml +import pytest + from pennylane_lightning import LightningQubit -import numpy as np -import itertools @pytest.fixture @@ -78,14 +80,34 @@ def output(input): assert np.allclose(unitary, unitary_expected) -random_unitary = np.array([[-0.48401572-0.11012304j, -0.44806504+0.46775911j, - -0.36968281+0.19235993j, -0.37561358+0.13887962j], - [-0.12838047+0.13992187j, 0.14531831+0.45319438j, - 0.28902175-0.71158765j, -0.24333677-0.29721109j], - [ 0.26400811-0.72519269j, 0.13965687+0.35092711j, - 0.09141515-0.14367072j, 0.14894673+0.45886629j], - [-0.04067799+0.34681783j, -0.45852968-0.03214391j, - -0.10528164-0.4431247j , 0.50251451+0.45476965j]]) +random_unitary = np.array( + [ + [ + -0.48401572 - 0.11012304j, + -0.44806504 + 0.46775911j, + -0.36968281 + 0.19235993j, + -0.37561358 + 0.13887962j, + ], + [ + -0.12838047 + 0.13992187j, + 0.14531831 + 0.45319438j, + 0.28902175 - 0.71158765j, + -0.24333677 - 0.29721109j, + ], + [ + 0.26400811 - 0.72519269j, + 0.13965687 + 0.35092711j, + 0.09141515 - 0.14367072j, + 0.14894673 + 0.45886629j, + ], + [ + -0.04067799 + 0.34681783j, + -0.45852968 - 0.03214391j, + -0.10528164 - 0.4431247j, + 0.50251451 + 0.45476965j, + ], + ] +) @pytest.mark.xfail(strict=True) # needs support for QubitUnitary From 44ef2618ba608fbdfe12c8c2a03a98aa54c4a660 Mon Sep 17 00:00:00 2001 From: trbromley Date: Wed, 17 Mar 2021 16:03:22 -0400 Subject: [PATCH 18/26] Add to changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c25397694a..82c7de27e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ ### Improvements +* Inverse gates are now supported. + [(#89)](https://github.com/PennyLaneAI/pennylane-lightning/pull/89) + * Add new lightweight backend with performance improvements. [(#57)](https://github.com/PennyLaneAI/pennylane-lightning/pull/57) From 44a5d166838dad131d760651966143f5057e27b1 Mon Sep 17 00:00:00 2001 From: trbromley Date: Thu, 18 Mar 2021 14:28:33 -0400 Subject: [PATCH 19/26] Try fix codefactor --- pennylane_lightning/src/Gates.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/pennylane_lightning/src/Gates.cpp b/pennylane_lightning/src/Gates.cpp index 4e167fe03a..3a52e71b51 100644 --- a/pennylane_lightning/src/Gates.cpp +++ b/pennylane_lightning/src/Gates.cpp @@ -175,7 +175,6 @@ void Pennylane::HadamardGate::applyKernel(const StateVector& state, const std::v } // ------------------------------------------------------------------------------------------------------------- - const string Pennylane::SGate::label = "S"; Pennylane::SGate Pennylane::SGate::create(const vector& parameters) { From 5087ff2ea311f7656ff4188e2e2f0f36f17923a7 Mon Sep 17 00:00:00 2001 From: trbromley Date: Thu, 18 Mar 2021 14:31:09 -0400 Subject: [PATCH 20/26] Probably fix codefactor --- pennylane_lightning/src/Gates.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/pennylane_lightning/src/Gates.cpp b/pennylane_lightning/src/Gates.cpp index 3a52e71b51..cefb87d513 100644 --- a/pennylane_lightning/src/Gates.cpp +++ b/pennylane_lightning/src/Gates.cpp @@ -175,6 +175,7 @@ void Pennylane::HadamardGate::applyKernel(const StateVector& state, const std::v } // ------------------------------------------------------------------------------------------------------------- + const string Pennylane::SGate::label = "S"; Pennylane::SGate Pennylane::SGate::create(const vector& parameters) { @@ -187,7 +188,6 @@ const vector Pennylane::SGate::matrix{ 0, IMAG }; void Pennylane::SGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType shift = IMAG; if (inverse == true) {shift *= -1;} @@ -213,7 +213,6 @@ const vector Pennylane::TGate::matrix{ 0, Pennylane::TGate::shift }; void Pennylane::TGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType shift = Pennylane::TGate::shift; if (inverse == true) {shift = conj(Pennylane::TGate::shift);} @@ -241,7 +240,6 @@ Pennylane::RotationXGate::RotationXGate(double rotationAngle) {} void Pennylane::RotationXGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType js_ = js; if (inverse == true) {js_ *= -1;} @@ -273,7 +271,6 @@ Pennylane::RotationYGate::RotationYGate(double rotationAngle) {} void Pennylane::RotationYGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType s_ = s; if (inverse == true) {s_ *= -1;} @@ -305,7 +302,6 @@ Pennylane::RotationZGate::RotationZGate(double rotationAngle) {} void Pennylane::RotationZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType shift1 = first; CplxType shift2 = second; @@ -338,7 +334,6 @@ Pennylane::PhaseShiftGate::PhaseShiftGate(double rotationAngle) {} void Pennylane::PhaseShiftGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType s = shift; if (inverse == true){s = conj(shift);} @@ -371,7 +366,6 @@ Pennylane::GeneralRotationGate::GeneralRotationGate(double phi, double theta, do {} void Pennylane::GeneralRotationGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType t1 = r1; CplxType t2 = r2; CplxType t3 = r3; @@ -488,7 +482,6 @@ Pennylane::CRotationXGate::CRotationXGate(double rotationAngle) {} void Pennylane::CRotationXGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType js_ = js; if (inverse == true) {js_ *= -1;} @@ -522,7 +515,6 @@ Pennylane::CRotationYGate::CRotationYGate(double rotationAngle) {} void Pennylane::CRotationYGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType s_ = s; if (inverse == true) {s_ *= -1;} @@ -556,7 +548,6 @@ Pennylane::CRotationZGate::CRotationZGate(double rotationAngle) {} void Pennylane::CRotationZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType shift1 = first; CplxType shift2 = second; @@ -596,7 +587,6 @@ Pennylane::CGeneralRotationGate::CGeneralRotationGate(double phi, double theta, {} void Pennylane::CGeneralRotationGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType t1 = r1; CplxType t2 = r2; CplxType t3 = r3; From 0b095df56fab5f6732865d1a2d4a096e2923d19b Mon Sep 17 00:00:00 2001 From: Tom Bromley <49409390+trbromley@users.noreply.github.com> Date: Fri, 19 Mar 2021 13:13:36 -0400 Subject: [PATCH 21/26] Apply suggestions from code review Co-authored-by: antalszava --- pennylane_lightning/lightning_qubit.py | 1 - pennylane_lightning/src/Apply.cpp | 2 +- pennylane_lightning/src/Apply.hpp | 2 +- tests/test_gates.py | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index a2753f6db5..0796b5411a 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -79,7 +79,6 @@ class LightningQubit(DefaultQubit): "PauliY", "PauliZ", "Hadamard", - "Hadamard", "S", "T", "RX", diff --git a/pennylane_lightning/src/Apply.cpp b/pennylane_lightning/src/Apply.cpp index c09a26705d..3198ea7690 100644 --- a/pennylane_lightning/src/Apply.cpp +++ b/pennylane_lightning/src/Apply.cpp @@ -73,7 +73,7 @@ void Pennylane::apply( const vector& ops, const vector>& wires, const vector>& params, - const std::vector& inverse, + const vector& inverse, const unsigned int qubits ) { if (qubits <= 0) diff --git a/pennylane_lightning/src/Apply.hpp b/pennylane_lightning/src/Apply.hpp index 4d9cfec615..91d67778bc 100644 --- a/pennylane_lightning/src/Apply.hpp +++ b/pennylane_lightning/src/Apply.hpp @@ -81,7 +81,7 @@ namespace Pennylane { * @param ops list of unique string names corresponding to gate types, in the order they should be applied * @param wires list of wires on which each gate acts * @param params list of parameters that defines the gate parameterisation - * @param inverse list of bools indicating whether a given gate or its inverse should be applied + * @param inverse list of booleans indicating whether a given gate or its inverse should be applied * @param qubits number of qubits */ void apply( diff --git a/tests/test_gates.py b/tests/test_gates.py index 8781579b5a..741684caa6 100644 --- a/tests/test_gates.py +++ b/tests/test_gates.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. """ -Unit tests for the correct application of gates with lightning.qubit +Unit tests for the correct application of gates with lightning.qubit. """ import itertools From e56529aa6211ac3e921c4151afa8b05d010ea438 Mon Sep 17 00:00:00 2001 From: trbromley Date: Fri, 19 Mar 2021 13:19:32 -0400 Subject: [PATCH 22/26] Remove kernel operations --- tests/test_gates.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/test_gates.py b/tests/test_gates.py index 741684caa6..6b6e53374c 100644 --- a/tests/test_gates.py +++ b/tests/test_gates.py @@ -28,10 +28,14 @@ def op(op_name): return getattr(qml, op_name) -@pytest.mark.parametrize("op_name", LightningQubit.kernel_operations) -def test_gate_unitary_correct(op): +@pytest.mark.parametrize("op_name", LightningQubit.operations) +def test_gate_unitary_correct(op, op_name): """Test if lightning.qubit correctly applies gates by reconstructing the unitary matrix and comparing to the expected version""" + + if op_name in ("BasisState", "QubitStateVector"): + pytest.skip("Skipping operation because it is a state preparation") + wires = op.num_wires dev = qml.device("lightning.qubit", wires=wires) num_params = op.num_params @@ -54,10 +58,14 @@ def output(input): assert np.allclose(unitary, unitary_expected) -@pytest.mark.parametrize("op_name", LightningQubit.kernel_operations) -def test_inverse_unitary_correct(op): +@pytest.mark.parametrize("op_name", LightningQubit.operations) +def test_inverse_unitary_correct(op, op_name): """Test if lightning.qubit correctly applies inverse gates by reconstructing the unitary matrix and comparing to the expected version""" + + if op_name in ("BasisState", "QubitStateVector"): + pytest.skip("Skipping operation because it is a state preparation") + wires = op.num_wires dev = qml.device("lightning.qubit", wires=wires) num_params = op.num_params From 8b64d8d7ff76a47e23cab03adcab84fe54cb94ad Mon Sep 17 00:00:00 2001 From: trbromley Date: Fri, 19 Mar 2021 13:21:30 -0400 Subject: [PATCH 23/26] Add to docstrings --- pennylane_lightning/lightning_qubit.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index 0796b5411a..474cb6a4b1 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -167,4 +167,12 @@ def apply_lightning(self, state, operations): @staticmethod def _remove_inverse_string(string): - return string.split(".")[0] + """Removes the ``.inv`` appended to the end of inverse gates. + + Args: + string (str): name of operation + + Returns: + str: name of operation with ``.inv`` removed (if present) + """ + return string.replace(".inv", "") From 9023567d35a1056f09f4f1b56102a0e4f978dfb7 Mon Sep 17 00:00:00 2001 From: trbromley Date: Fri, 19 Mar 2021 13:33:23 -0400 Subject: [PATCH 24/26] Update one-liners --- pennylane_lightning/src/Gates.cpp | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/pennylane_lightning/src/Gates.cpp b/pennylane_lightning/src/Gates.cpp index cefb87d513..8979942665 100644 --- a/pennylane_lightning/src/Gates.cpp +++ b/pennylane_lightning/src/Gates.cpp @@ -188,8 +188,7 @@ const vector Pennylane::SGate::matrix{ 0, IMAG }; void Pennylane::SGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType shift = IMAG; - if (inverse == true) {shift *= -1;} + CplxType shift = (inverse == true) ? -IMAG : IMAG; for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; @@ -213,8 +212,7 @@ const vector Pennylane::TGate::matrix{ 0, Pennylane::TGate::shift }; void Pennylane::TGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType shift = Pennylane::TGate::shift; - if (inverse == true) {shift = conj(Pennylane::TGate::shift);} + CplxType shift = (inverse == true) ? conj(Pennylane::TGate::shift) : Pennylane::TGate::shift; for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; @@ -240,9 +238,7 @@ Pennylane::RotationXGate::RotationXGate(double rotationAngle) {} void Pennylane::RotationXGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType js_ = js; - - if (inverse == true) {js_ *= -1;} + CplxType js_ = (inverse == true) ? -js : js; for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; @@ -271,9 +267,7 @@ Pennylane::RotationYGate::RotationYGate(double rotationAngle) {} void Pennylane::RotationYGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType s_ = s; - - if (inverse == true) {s_ *= -1;} + CplxType s_ = (inverse == true) ? -s : s; for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; @@ -334,9 +328,7 @@ Pennylane::PhaseShiftGate::PhaseShiftGate(double rotationAngle) {} void Pennylane::PhaseShiftGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType s = shift; - - if (inverse == true){s = conj(shift);} + CplxType s = (inverse == true) ? conj(shift) : shift; for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; @@ -482,9 +474,7 @@ Pennylane::CRotationXGate::CRotationXGate(double rotationAngle) {} void Pennylane::CRotationXGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType js_ = js; - - if (inverse == true) {js_ *= -1;} + CplxType js_ = (inverse == true) ? -js : js; for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; @@ -515,9 +505,7 @@ Pennylane::CRotationYGate::CRotationYGate(double rotationAngle) {} void Pennylane::CRotationYGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - CplxType s_ = s; - - if (inverse == true) {s_ *= -1;} + CplxType s_ = (inverse == true) ? -s : s; for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; From fcd1c29a6755c013b916a651e2b724c834f0db9c Mon Sep 17 00:00:00 2001 From: trbromley Date: Mon, 22 Mar 2021 09:29:11 -0400 Subject: [PATCH 25/26] Use unnamed param --- pennylane_lightning/src/Gates.cpp | 36 +++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/pennylane_lightning/src/Gates.cpp b/pennylane_lightning/src/Gates.cpp index 8979942665..53c5a07271 100644 --- a/pennylane_lightning/src/Gates.cpp +++ b/pennylane_lightning/src/Gates.cpp @@ -98,8 +98,8 @@ const vector Pennylane::XGate::matrix{ 0, 1, 1, 0 }; -void Pennylane::XGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - (void)inverse; // gate is its own inverse +void Pennylane::XGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool) { + // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; swap(shiftedState[indices[0]], shiftedState[indices[1]]); @@ -119,8 +119,8 @@ const vector Pennylane::YGate::matrix{ 0, -IMAG, IMAG, 0 }; -void Pennylane::YGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - (void)inverse; // gate is its own inverse +void Pennylane::YGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool) { + // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; CplxType v0 = shiftedState[indices[0]]; @@ -142,8 +142,8 @@ const std::vector Pennylane::ZGate::matrix{ 1, 0, 0, -1 }; -void Pennylane::ZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - (void)inverse; // gate is its own inverse +void Pennylane::ZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool) { + // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; shiftedState[indices[1]] *= -1; @@ -163,8 +163,8 @@ const vector Pennylane::HadamardGate::matrix{ SQRT2INV, SQRT2INV, SQRT2INV, -SQRT2INV }; -void Pennylane::HadamardGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - (void)inverse; // gate is its own inverse +void Pennylane::HadamardGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool) { + // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; CplxType v0 = shiftedState[indices[0]]; @@ -400,8 +400,8 @@ const std::vector Pennylane::CNOTGate::matrix{ 0, 0, 0, 1, 0, 0, 1, 0 }; -void Pennylane::CNOTGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - (void)inverse; // gate is its own inverse +void Pennylane::CNOTGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool) { + // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; swap(shiftedState[indices[2]], shiftedState[indices[3]]); @@ -423,8 +423,8 @@ const std::vector Pennylane::SWAPGate::matrix{ 0, 1, 0, 0, 0, 0, 0, 1 }; -void Pennylane::SWAPGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - (void)inverse; // gate is its own inverse +void Pennylane::SWAPGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool) { + // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; swap(shiftedState[indices[1]], shiftedState[indices[2]]); @@ -446,8 +446,8 @@ const std::vector Pennylane::CZGate::matrix{ 0, 0, 1, 0, 0, 0, 0, -1 }; -void Pennylane::CZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - (void)inverse; // gate is its own inverse +void Pennylane::CZGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool) { + // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; shiftedState[indices[3]] *= -1; @@ -621,8 +621,8 @@ const std::vector Pennylane::ToffoliGate::matrix{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0 }; -void Pennylane::ToffoliGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - (void)inverse; // gate is its own inverse +void Pennylane::ToffoliGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool) { + // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; swap(shiftedState[indices[6]], shiftedState[indices[7]]); @@ -648,8 +648,8 @@ const std::vector Pennylane::CSWAPGate::matrix{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; -void Pennylane::CSWAPGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool inverse) { - (void)inverse; // gate is its own inverse +void Pennylane::CSWAPGate::applyKernel(const StateVector& state, const std::vector& indices, const std::vector& externalIndices, bool) { + // gate is its own inverse for (const size_t& externalIndex : externalIndices) { CplxType* shiftedState = state.arr + externalIndex; swap(shiftedState[indices[5]], shiftedState[indices[6]]); From 006ff7fd5d4e7df43db7f6341e4306f55feb01f4 Mon Sep 17 00:00:00 2001 From: trbromley Date: Mon, 22 Mar 2021 15:36:35 -0400 Subject: [PATCH 26/26] Remove kernel_operations --- pennylane_lightning/lightning_qubit.py | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index 474cb6a4b1..dac0a34f2c 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -74,29 +74,6 @@ class LightningQubit(DefaultQubit): "CRot", } - kernel_operations = { - "PauliX", - "PauliY", - "PauliZ", - "Hadamard", - "S", - "T", - "RX", - "RY", - "RZ", - "PhaseShift", - "Rot", - "CNOT", - "SWAP", - "CZ", - "CRX", - "CRY", - "CRZ", - "CRot", - "Toffoli", - "CSWAP", - } - observables = {"PauliX", "PauliY", "PauliZ", "Hadamard", "Hermitian", "Identity"} def __init__(self, wires, *, shots=1000, analytic=True):