From 1bb40f5fd0add6e94b3254b9faf6154aad68ca50 Mon Sep 17 00:00:00 2001 From: Ravi Budhrani Date: Thu, 9 May 2024 22:41:45 +0200 Subject: [PATCH 1/5] added changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..5891d16 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog + +## [UNRELEASED] - TBD + +### Added + +- Gate execution times. \ No newline at end of file From cffc3c6f35b352eea9bc8b0feaa2c32b100ff0ec Mon Sep 17 00:00:00 2001 From: Ravi Budhrani Date: Thu, 9 May 2024 22:42:53 +0200 Subject: [PATCH 2/5] updated pipeline reference to main from master --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c7b5d4..36aa96d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: QuantumSim CI on: push: - branches: [master] + branches: [main] pull_request: - branches: [master] + branches: [main] jobs: build-ubuntu: From b31f95e5a807f0d0fd2a09f93c9fb905b54621d1 Mon Sep 17 00:00:00 2001 From: Ravi Budhrani Date: Thu, 9 May 2024 22:43:25 +0200 Subject: [PATCH 3/5] renamed private variables with correct convention --- src/QubitLayer.cpp | 82 +++++++++++++++++++++++----------------------- src/QubitLayer.hpp | 4 +-- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/QubitLayer.cpp b/src/QubitLayer.cpp index c0ddd2c..b485845 100644 --- a/src/QubitLayer.cpp +++ b/src/QubitLayer.cpp @@ -11,31 +11,31 @@ QubitLayer::QubitLayer(unsigned int numQubits, qubitLayer *qL) for (unsigned int i = 0; i < numQubits; i++) numStates *= 2; // allocate memory for arrays - qEven_ = new qubitLayer[numStates]; - qOdd_ = new qubitLayer[numStates]; + _qEven = new qubitLayer[numStates]; + _qOdd = new qubitLayer[numStates]; // if input is provided then use that to fill the input qubit state if (!(qL == nullptr)) for (unsigned int row = 0; row < numStates; row++) - qEven_[row] = qL[row]; + _qEven[row] = qL[row]; else - qEven_[0] = {1, 0}; + _qEven[0] = {1, 0}; } QubitLayer::~QubitLayer() { - delete[] qEven_; - delete[] qOdd_; + delete[] _qEven; + delete[] _qOdd; } void QubitLayer::updateLayer() { - parity ? std::fill(qEven_, qEven_ + numStates, zeroComplex) : std::fill(qOdd_, qOdd_ + numStates, zeroComplex); + parity ? std::fill(_qEven, _qEven + numStates, zeroComplex) : std::fill(_qOdd, _qOdd + numStates, zeroComplex); toggleParity(); } bool QubitLayer::checkZeroState(int qubit) { - return parity ? qEven_[qubit].imag() || qEven_[qubit].real() : qOdd_[qubit].imag() || qOdd_[qubit].real(); + return parity ? _qEven[qubit].imag() || _qEven[qubit].real() : _qOdd[qubit].imag() || _qOdd[qubit].real(); } void QubitLayer::applyPauliX(int target) @@ -46,7 +46,7 @@ void QubitLayer::applyPauliX(int target) { std::bitset state = i; state.flip(target); - parity ? qOdd_[state.to_ulong()] = qEven_[i] : qEven_[state.to_ulong()] = qOdd_[i]; + parity ? _qOdd[state.to_ulong()] = _qEven[i] : _qEven[state.to_ulong()] = _qOdd[i]; } updateLayer(); } @@ -62,10 +62,10 @@ void QubitLayer::applyPauliY(int target) state.flip(target); // add phase of -i if bit was 1 (i.e. set) and flip it if (!state.test(target)) - parity ? qOdd_[state.to_ulong()] = -complexImg * qEven_[i] : qEven_[state.to_ulong()] = -complexImg * qOdd_[i]; + parity ? _qOdd[state.to_ulong()] = -complexImg * _qEven[i] : _qEven[state.to_ulong()] = -complexImg * _qOdd[i]; // add phase of i if bit was 0 (i.e. set) and flip it else - parity ? qOdd_[state.to_ulong()] = complexImg * qEven_[i] : qEven_[state.to_ulong()] = complexImg * qOdd_[i]; + parity ? _qOdd[state.to_ulong()] = complexImg * _qEven[i] : _qEven[state.to_ulong()] = complexImg * _qOdd[i]; } updateLayer(); } @@ -79,9 +79,9 @@ void QubitLayer::applyPauliZ(int target) std::bitset state = i; // add phase if bit is 1 (i.e. it is set) if (state.test(target)) - parity ? qOdd_[i] = -qEven_[i] : qEven_[i] = -qOdd_[i]; + parity ? _qOdd[i] = -_qEven[i] : _qEven[i] = -_qOdd[i]; else - parity ? qOdd_[i] = qEven_[i] : qEven_[i] = qOdd_[i]; + parity ? _qOdd[i] = _qEven[i] : _qEven[i] = _qOdd[i]; } updateLayer(); } @@ -95,13 +95,13 @@ void QubitLayer::applyHadamard(int target) { std::bitset state = i; if (state.test(target)) - parity ? qOdd_[i] -= hadamardCoef * qEven_[i] : qEven_[i] -= hadamardCoef * qOdd_[i]; + parity ? _qOdd[i] -= hadamardCoef * _qEven[i] : _qEven[i] -= hadamardCoef * _qOdd[i]; else - parity ? qOdd_[i] += hadamardCoef * qEven_[i] : qEven_[i] += hadamardCoef * qOdd_[i]; + parity ? _qOdd[i] += hadamardCoef * _qEven[i] : _qEven[i] += hadamardCoef * _qOdd[i]; if (!isParallel) { state.flip(target); - parity ? qOdd_[state.to_ulong()] += hadamardCoef * qEven_[i] : qEven_[state.to_ulong()] += hadamardCoef * qOdd_[i]; + parity ? _qOdd[state.to_ulong()] += hadamardCoef * _qEven[i] : _qEven[state.to_ulong()] += hadamardCoef * _qOdd[i]; } } if (isParallel) @@ -114,7 +114,7 @@ void QubitLayer::applyHadamard(int target) { std::bitset state = i; state.flip(target); - parity ? qOdd_[state.to_ulong()] += hadamardCoef * qEven_[i] : qEven_[state.to_ulong()] += hadamardCoef * qOdd_[i]; + parity ? _qOdd[state.to_ulong()] += hadamardCoef * _qEven[i] : _qEven[state.to_ulong()] += hadamardCoef * _qOdd[i]; } } updateLayer(); @@ -130,12 +130,12 @@ void QubitLayer::applyRx(int target, precision theta) for (unsigned long long int i = 0; i < numStates; i++) if (checkZeroState(i)) { - parity ? qOdd_[i] += cosTheta * qEven_[i] : qEven_[i] += cosTheta * qOdd_[i]; + parity ? _qOdd[i] += cosTheta * _qEven[i] : _qEven[i] += cosTheta * _qOdd[i]; if (!isParallel) { std::bitset state = i; state.flip(target); - parity ? qOdd_[state.to_ulong()] += -complexImg * sinTheta * qEven_[i] : qEven_[state.to_ulong()] += -complexImg * sinTheta * qOdd_[i]; + parity ? _qOdd[state.to_ulong()] += -complexImg * sinTheta * _qEven[i] : _qEven[state.to_ulong()] += -complexImg * sinTheta * _qOdd[i]; } } if (isParallel) @@ -148,7 +148,7 @@ void QubitLayer::applyRx(int target, precision theta) { std::bitset state = i; state.flip(target); - parity ? qOdd_[state.to_ulong()] += -complexImg * sinTheta * qEven_[i] : qEven_[state.to_ulong()] += -complexImg * sinTheta * qOdd_[i]; + parity ? _qOdd[state.to_ulong()] += -complexImg * sinTheta * _qEven[i] : _qEven[state.to_ulong()] += -complexImg * sinTheta * _qOdd[i]; } } updateLayer(); @@ -164,17 +164,17 @@ void QubitLayer::applyRy(int target, precision theta) for (unsigned long long int i = 0; i < numStates; i++) if (checkZeroState(i)) { - parity ? qOdd_[i] += cosTheta * qEven_[i] : qEven_[i] += cosTheta * qOdd_[i]; + parity ? _qOdd[i] += cosTheta * _qEven[i] : _qEven[i] += cosTheta * _qOdd[i]; if (!isParallel) { std::bitset state = i; state.flip(target); // action if bit is 1 (i.e. set) if (state.test(target)) - parity ? qOdd_[state.to_ulong()] += sinTheta * qEven_[i] : qEven_[state.to_ulong()] += sinTheta * qOdd_[i]; + parity ? _qOdd[state.to_ulong()] += sinTheta * _qEven[i] : _qEven[state.to_ulong()] += sinTheta * _qOdd[i]; // action if bit is 0 (i.e. not set) else - parity ? qOdd_[state.to_ulong()] -= sinTheta * qEven_[i] : qEven_[state.to_ulong()] -= sinTheta * qOdd_[i]; + parity ? _qOdd[state.to_ulong()] -= sinTheta * _qEven[i] : _qEven[state.to_ulong()] -= sinTheta * _qOdd[i]; } } if (isParallel) @@ -189,10 +189,10 @@ void QubitLayer::applyRy(int target, precision theta) state.flip(target); // action if bit is 1 (i.e. set) if (state.test(target)) - parity ? qOdd_[state.to_ulong()] += sinTheta * qEven_[i] : qEven_[state.to_ulong()] += sinTheta * qOdd_[i]; + parity ? _qOdd[state.to_ulong()] += sinTheta * _qEven[i] : _qEven[state.to_ulong()] += sinTheta * _qOdd[i]; // action if bit is 0 (i.e. not set) else - parity ? qOdd_[state.to_ulong()] -= sinTheta * qEven_[i] : qEven_[state.to_ulong()] -= sinTheta * qOdd_[i]; + parity ? _qOdd[state.to_ulong()] -= sinTheta * _qEven[i] : _qEven[state.to_ulong()] -= sinTheta * _qOdd[i]; } } updateLayer(); @@ -210,10 +210,10 @@ void QubitLayer::applyRz(int target, precision theta) std::bitset state = i; // action if bit is 1 (i.e. set) if (state.test(target)) - parity ? qOdd_[i] += cosTheta * qEven_[i] + complexImg * sinTheta * qEven_[i] : qEven_[i] += cosTheta * qOdd_[i] + complexImg * sinTheta * qOdd_[i]; + parity ? _qOdd[i] += cosTheta * _qEven[i] + complexImg * sinTheta * _qEven[i] : _qEven[i] += cosTheta * _qOdd[i] + complexImg * sinTheta * _qOdd[i]; // action if bit is 0 (i.e. not set) else - parity ? qOdd_[i] += cosTheta * qEven_[i] - complexImg * sinTheta * qEven_[i] : qEven_[i] += cosTheta * qOdd_[i] - complexImg * sinTheta * qOdd_[i]; + parity ? _qOdd[i] += cosTheta * _qEven[i] - complexImg * sinTheta * _qEven[i] : _qEven[i] += cosTheta * _qOdd[i] - complexImg * sinTheta * _qOdd[i]; } updateLayer(); } @@ -238,10 +238,10 @@ void QubitLayer::applyCnot(int control, int target) if (state.test(control)) { state.flip(target); - parity ? qOdd_[state.to_ulong()] = qEven_[i] : qEven_[state.to_ulong()] = qOdd_[i]; + parity ? _qOdd[state.to_ulong()] = _qEven[i] : _qEven[state.to_ulong()] = _qOdd[i]; } else - parity ? qOdd_[i] = qEven_[i] : qEven_[i] = qOdd_[i]; + parity ? _qOdd[i] = _qEven[i] : _qEven[i] = _qOdd[i]; } } updateLayer(); @@ -258,10 +258,10 @@ void QubitLayer::applyToffoli(int control1, int control2, int target) if (state.test(control1) && state.test(control2)) { state.flip(target); - parity ? qOdd_[state.to_ulong()] = qEven_[i] : qEven_[state.to_ulong()] = qOdd_[i]; + parity ? _qOdd[state.to_ulong()] = _qEven[i] : _qEven[state.to_ulong()] = _qOdd[i]; } else - parity ? qOdd_[i] = qEven_[i] : qEven_[i] = qOdd_[i]; + parity ? _qOdd[i] = _qEven[i] : _qEven[i] = _qOdd[i]; } updateLayer(); } @@ -277,10 +277,10 @@ void QubitLayer::applyMcnot(int *controls, int numControls, int target) if (checkControls(controls, numControls, state)) { state.flip(target); - parity ? qOdd_[state.to_ulong()] = qEven_[i] : qEven_[state.to_ulong()] = qOdd_[i]; + parity ? _qOdd[state.to_ulong()] = _qEven[i] : _qEven[state.to_ulong()] = _qOdd[i]; } else - parity ? qOdd_[i] = qEven_[i] : qEven_[i] = qOdd_[i]; + parity ? _qOdd[i] = _qEven[i] : _qEven[i] = _qOdd[i]; } updateLayer(); } @@ -294,9 +294,9 @@ void QubitLayer::applyCz(int control, int target) std::bitset state = i; // add phase to target qubit if control bit and target bits are 1 (i.e. set) if (state.test(control) && state.test(target)) - parity ? qOdd_[i] = -qEven_[i] : qEven_[i] = -qOdd_[i]; + parity ? _qOdd[i] = -_qEven[i] : _qEven[i] = -_qOdd[i]; else - parity ? qOdd_[i] = qEven_[i] : qEven_[i] = qOdd_[i]; + parity ? _qOdd[i] = _qEven[i] : _qEven[i] = _qOdd[i]; } updateLayer(); } @@ -310,9 +310,9 @@ void QubitLayer::applyMcphase(int *controls, int numControls, int target) std::bitset state = i; // add phase to target qubit if control bit(s) and target bit is 1 (i.e. set) if (checkControls(controls, numControls, state) && state.test(target)) - parity ? qOdd_[i] = -qEven_[i] : qEven_[i] = -qOdd_[i]; + parity ? _qOdd[i] = -_qEven[i] : _qEven[i] = -_qOdd[i]; else - parity ? qOdd_[i] = qEven_[i] : qEven_[i] = qOdd_[i]; + parity ? _qOdd[i] = _qEven[i] : _qEven[i] = _qOdd[i]; } updateLayer(); } @@ -326,7 +326,7 @@ qProb QubitLayer::getMaxAmplitude() for (unsigned long long int i = 0; i < numStates; i++) { state = i; - currentProb = parity ? abs(qEven_[i]) * abs(qEven_[i]) : abs(qOdd_[i]) * abs(qOdd_[i]); + currentProb = parity ? abs(_qEven[i]) * abs(_qEven[i]) : abs(_qOdd[i]) * abs(_qOdd[i]); if (currentProb > previousProb) { result.state = state; @@ -357,19 +357,19 @@ void QubitLayer::printQubits() { std::bitset binaryRep = i; std::string state = binaryRep.to_string(); - std::cout << qEven_[i] << " " << qOdd_[i] << " "; + std::cout << _qEven[i] << " " << _qOdd[i] << " "; std::cout << "|" << state << ">\n"; } } qubitLayer *QubitLayer::getQubitLayerEven() { - return qEven_; + return _qEven; } qubitLayer *QubitLayer::getQubitLayerOdd() { - return qOdd_; + return _qOdd; } unsigned long long int QubitLayer::getNumStates() { return numStates; } diff --git a/src/QubitLayer.hpp b/src/QubitLayer.hpp index 9caa3f1..f96459a 100644 --- a/src/QubitLayer.hpp +++ b/src/QubitLayer.hpp @@ -41,8 +41,8 @@ class QubitLayer void toggleParity(); unsigned int numQubits; unsigned long long int numStates; - qubitLayer *qEven_; - qubitLayer *qOdd_; + qubitLayer *_qEven; + qubitLayer *_qOdd; bool parity = true; }; From fd5ab7de31db58dc9fcab687fc4a08c389507e9c Mon Sep 17 00:00:00 2001 From: Ravi Budhrani Date: Thu, 9 May 2024 22:48:34 +0200 Subject: [PATCH 4/5] changed private variables to correct naming convention --- src/QubitLayer.cpp | 114 ++++++++++++++++++++++----------------------- src/QubitLayer.hpp | 7 +-- 2 files changed, 61 insertions(+), 60 deletions(-) diff --git a/src/QubitLayer.cpp b/src/QubitLayer.cpp index b485845..5cc3902 100644 --- a/src/QubitLayer.cpp +++ b/src/QubitLayer.cpp @@ -7,15 +7,15 @@ QubitLayer::QubitLayer(unsigned int numQubits, qubitLayer *qL) { // calculate the number of states - numStates = 1; + _numStates = 1; for (unsigned int i = 0; i < numQubits; i++) - numStates *= 2; + _numStates *= 2; // allocate memory for arrays - _qEven = new qubitLayer[numStates]; - _qOdd = new qubitLayer[numStates]; + _qEven = new qubitLayer[_numStates]; + _qOdd = new qubitLayer[_numStates]; // if input is provided then use that to fill the input qubit state if (!(qL == nullptr)) - for (unsigned int row = 0; row < numStates; row++) + for (unsigned int row = 0; row < _numStates; row++) _qEven[row] = qL[row]; else _qEven[0] = {1, 0}; @@ -29,24 +29,24 @@ QubitLayer::~QubitLayer() void QubitLayer::updateLayer() { - parity ? std::fill(_qEven, _qEven + numStates, zeroComplex) : std::fill(_qOdd, _qOdd + numStates, zeroComplex); + _parity ? std::fill(_qEven, _qEven + _numStates, zeroComplex) : std::fill(_qOdd, _qOdd + _numStates, zeroComplex); toggleParity(); } bool QubitLayer::checkZeroState(int qubit) { - return parity ? _qEven[qubit].imag() || _qEven[qubit].real() : _qOdd[qubit].imag() || _qOdd[qubit].real(); + return _parity ? _qEven[qubit].imag() || _qEven[qubit].real() : _qOdd[qubit].imag() || _qOdd[qubit].real(); } void QubitLayer::applyPauliX(int target) { #pragma omp parallel for shared(qOdd_, qEven_) - for (unsigned long long int i = 0; i < numStates; i++) + for (unsigned long long int i = 0; i < _numStates; i++) if (checkZeroState(i)) { std::bitset state = i; state.flip(target); - parity ? _qOdd[state.to_ulong()] = _qEven[i] : _qEven[state.to_ulong()] = _qOdd[i]; + _parity ? _qOdd[state.to_ulong()] = _qEven[i] : _qEven[state.to_ulong()] = _qOdd[i]; } updateLayer(); } @@ -54,7 +54,7 @@ void QubitLayer::applyPauliX(int target) void QubitLayer::applyPauliY(int target) { #pragma omp parallel for shared(qOdd_, qEven_) - for (unsigned long long int i = 0; i < numStates; i++) + for (unsigned long long int i = 0; i < _numStates; i++) if (checkZeroState(i)) { std::bitset state = i; @@ -62,10 +62,10 @@ void QubitLayer::applyPauliY(int target) state.flip(target); // add phase of -i if bit was 1 (i.e. set) and flip it if (!state.test(target)) - parity ? _qOdd[state.to_ulong()] = -complexImg * _qEven[i] : _qEven[state.to_ulong()] = -complexImg * _qOdd[i]; + _parity ? _qOdd[state.to_ulong()] = -complexImg * _qEven[i] : _qEven[state.to_ulong()] = -complexImg * _qOdd[i]; // add phase of i if bit was 0 (i.e. set) and flip it else - parity ? _qOdd[state.to_ulong()] = complexImg * _qEven[i] : _qEven[state.to_ulong()] = complexImg * _qOdd[i]; + _parity ? _qOdd[state.to_ulong()] = complexImg * _qEven[i] : _qEven[state.to_ulong()] = complexImg * _qOdd[i]; } updateLayer(); } @@ -73,15 +73,15 @@ void QubitLayer::applyPauliY(int target) void QubitLayer::applyPauliZ(int target) { #pragma omp parallel for shared(qOdd_, qEven_) - for (unsigned long long int i = 0; i < numStates; i++) + for (unsigned long long int i = 0; i < _numStates; i++) if (checkZeroState(i)) { std::bitset state = i; // add phase if bit is 1 (i.e. it is set) if (state.test(target)) - parity ? _qOdd[i] = -_qEven[i] : _qEven[i] = -_qOdd[i]; + _parity ? _qOdd[i] = -_qEven[i] : _qEven[i] = -_qOdd[i]; else - parity ? _qOdd[i] = _qEven[i] : _qEven[i] = _qOdd[i]; + _parity ? _qOdd[i] = _qEven[i] : _qEven[i] = _qOdd[i]; } updateLayer(); } @@ -90,18 +90,18 @@ void QubitLayer::applyHadamard(int target) { // map |1> to -hadamardCoef*|1> and |0> to hadamardCoef*|0> #pragma omp parallel for shared(qOdd_, qEven_) - for (unsigned long long int i = 0; i < numStates; i++) + for (unsigned long long int i = 0; i < _numStates; i++) if (checkZeroState(i)) { std::bitset state = i; if (state.test(target)) - parity ? _qOdd[i] -= hadamardCoef * _qEven[i] : _qEven[i] -= hadamardCoef * _qOdd[i]; + _parity ? _qOdd[i] -= hadamardCoef * _qEven[i] : _qEven[i] -= hadamardCoef * _qOdd[i]; else - parity ? _qOdd[i] += hadamardCoef * _qEven[i] : _qEven[i] += hadamardCoef * _qOdd[i]; + _parity ? _qOdd[i] += hadamardCoef * _qEven[i] : _qEven[i] += hadamardCoef * _qOdd[i]; if (!isParallel) { state.flip(target); - parity ? _qOdd[state.to_ulong()] += hadamardCoef * _qEven[i] : _qEven[state.to_ulong()] += hadamardCoef * _qOdd[i]; + _parity ? _qOdd[state.to_ulong()] += hadamardCoef * _qEven[i] : _qEven[state.to_ulong()] += hadamardCoef * _qOdd[i]; } } if (isParallel) @@ -109,12 +109,12 @@ void QubitLayer::applyHadamard(int target) #pragma omp barrier // map |0> to hadamardCoef*|1> and |1> to hadamardCoef*|0> #pragma omp parallel for shared(qOdd_, qEven_) - for (unsigned long long int i = 0; i < numStates; i++) + for (unsigned long long int i = 0; i < _numStates; i++) if (checkZeroState(i)) { std::bitset state = i; state.flip(target); - parity ? _qOdd[state.to_ulong()] += hadamardCoef * _qEven[i] : _qEven[state.to_ulong()] += hadamardCoef * _qOdd[i]; + _parity ? _qOdd[state.to_ulong()] += hadamardCoef * _qEven[i] : _qEven[state.to_ulong()] += hadamardCoef * _qOdd[i]; } } updateLayer(); @@ -127,15 +127,15 @@ void QubitLayer::applyRx(int target, precision theta) precision sinTheta = sin(theta / 2); // map |0> to cosTheta*|0> and |1> to cosTheta*|1> #pragma omp parallel for shared(qOdd_, qEven_) - for (unsigned long long int i = 0; i < numStates; i++) + for (unsigned long long int i = 0; i < _numStates; i++) if (checkZeroState(i)) { - parity ? _qOdd[i] += cosTheta * _qEven[i] : _qEven[i] += cosTheta * _qOdd[i]; + _parity ? _qOdd[i] += cosTheta * _qEven[i] : _qEven[i] += cosTheta * _qOdd[i]; if (!isParallel) { std::bitset state = i; state.flip(target); - parity ? _qOdd[state.to_ulong()] += -complexImg * sinTheta * _qEven[i] : _qEven[state.to_ulong()] += -complexImg * sinTheta * _qOdd[i]; + _parity ? _qOdd[state.to_ulong()] += -complexImg * sinTheta * _qEven[i] : _qEven[state.to_ulong()] += -complexImg * sinTheta * _qOdd[i]; } } if (isParallel) @@ -143,12 +143,12 @@ void QubitLayer::applyRx(int target, precision theta) #pragma omp barrier // map |1> to -isinTheta*|0> and |0> to -isineTheta*|1> #pragma omp parallel for shared(qOdd_, qEven_) - for (unsigned long long int i = 0; i < numStates; i++) + for (unsigned long long int i = 0; i < _numStates; i++) if (checkZeroState(i)) { std::bitset state = i; state.flip(target); - parity ? _qOdd[state.to_ulong()] += -complexImg * sinTheta * _qEven[i] : _qEven[state.to_ulong()] += -complexImg * sinTheta * _qOdd[i]; + _parity ? _qOdd[state.to_ulong()] += -complexImg * sinTheta * _qEven[i] : _qEven[state.to_ulong()] += -complexImg * sinTheta * _qOdd[i]; } } updateLayer(); @@ -161,20 +161,20 @@ void QubitLayer::applyRy(int target, precision theta) precision sinTheta = sin(theta / 2); // map |1> to cosTheta*|1> and |0> to cosTheta*|0> #pragma omp parallel for shared(qOdd_, qEven_) - for (unsigned long long int i = 0; i < numStates; i++) + for (unsigned long long int i = 0; i < _numStates; i++) if (checkZeroState(i)) { - parity ? _qOdd[i] += cosTheta * _qEven[i] : _qEven[i] += cosTheta * _qOdd[i]; + _parity ? _qOdd[i] += cosTheta * _qEven[i] : _qEven[i] += cosTheta * _qOdd[i]; if (!isParallel) { std::bitset state = i; state.flip(target); // action if bit is 1 (i.e. set) if (state.test(target)) - parity ? _qOdd[state.to_ulong()] += sinTheta * _qEven[i] : _qEven[state.to_ulong()] += sinTheta * _qOdd[i]; + _parity ? _qOdd[state.to_ulong()] += sinTheta * _qEven[i] : _qEven[state.to_ulong()] += sinTheta * _qOdd[i]; // action if bit is 0 (i.e. not set) else - parity ? _qOdd[state.to_ulong()] -= sinTheta * _qEven[i] : _qEven[state.to_ulong()] -= sinTheta * _qOdd[i]; + _parity ? _qOdd[state.to_ulong()] -= sinTheta * _qEven[i] : _qEven[state.to_ulong()] -= sinTheta * _qOdd[i]; } } if (isParallel) @@ -182,17 +182,17 @@ void QubitLayer::applyRy(int target, precision theta) #pragma omp barrier // map |0> to sinTheta*|1> and |1> to -sinTheta*|0> #pragma omp parallel for shared(qOdd_, qEven_) - for (unsigned long long int i = 0; i < numStates; i++) + for (unsigned long long int i = 0; i < _numStates; i++) if (checkZeroState(i)) { std::bitset state = i; state.flip(target); // action if bit is 1 (i.e. set) if (state.test(target)) - parity ? _qOdd[state.to_ulong()] += sinTheta * _qEven[i] : _qEven[state.to_ulong()] += sinTheta * _qOdd[i]; + _parity ? _qOdd[state.to_ulong()] += sinTheta * _qEven[i] : _qEven[state.to_ulong()] += sinTheta * _qOdd[i]; // action if bit is 0 (i.e. not set) else - parity ? _qOdd[state.to_ulong()] -= sinTheta * _qEven[i] : _qEven[state.to_ulong()] -= sinTheta * _qOdd[i]; + _parity ? _qOdd[state.to_ulong()] -= sinTheta * _qEven[i] : _qEven[state.to_ulong()] -= sinTheta * _qOdd[i]; } } updateLayer(); @@ -204,16 +204,16 @@ void QubitLayer::applyRz(int target, precision theta) precision cosTheta = cos(theta / 2); precision sinTheta = sin(theta / 2); #pragma omp parallel for shared(qOdd_, qEven_) - for (unsigned long long int i = 0; i < numStates; i++) + for (unsigned long long int i = 0; i < _numStates; i++) if (checkZeroState(i)) { std::bitset state = i; // action if bit is 1 (i.e. set) if (state.test(target)) - parity ? _qOdd[i] += cosTheta * _qEven[i] + complexImg * sinTheta * _qEven[i] : _qEven[i] += cosTheta * _qOdd[i] + complexImg * sinTheta * _qOdd[i]; + _parity ? _qOdd[i] += cosTheta * _qEven[i] + complexImg * sinTheta * _qEven[i] : _qEven[i] += cosTheta * _qOdd[i] + complexImg * sinTheta * _qOdd[i]; // action if bit is 0 (i.e. not set) else - parity ? _qOdd[i] += cosTheta * _qEven[i] - complexImg * sinTheta * _qEven[i] : _qEven[i] += cosTheta * _qOdd[i] - complexImg * sinTheta * _qOdd[i]; + _parity ? _qOdd[i] += cosTheta * _qEven[i] - complexImg * sinTheta * _qEven[i] : _qEven[i] += cosTheta * _qOdd[i] - complexImg * sinTheta * _qOdd[i]; } updateLayer(); } @@ -229,7 +229,7 @@ bool QubitLayer::checkControls(int *controls, int numControls, std::bitset state = i; @@ -258,10 +258,10 @@ void QubitLayer::applyToffoli(int control1, int control2, int target) if (state.test(control1) && state.test(control2)) { state.flip(target); - parity ? _qOdd[state.to_ulong()] = _qEven[i] : _qEven[state.to_ulong()] = _qOdd[i]; + _parity ? _qOdd[state.to_ulong()] = _qEven[i] : _qEven[state.to_ulong()] = _qOdd[i]; } else - parity ? _qOdd[i] = _qEven[i] : _qEven[i] = _qOdd[i]; + _parity ? _qOdd[i] = _qEven[i] : _qEven[i] = _qOdd[i]; } updateLayer(); } @@ -269,7 +269,7 @@ void QubitLayer::applyToffoli(int control1, int control2, int target) void QubitLayer::applyMcnot(int *controls, int numControls, int target) { #pragma omp parallel for shared(qOdd_, qEven_) - for (unsigned long long int i = 0; i < numStates; i++) + for (unsigned long long int i = 0; i < _numStates; i++) if (checkZeroState(i)) { std::bitset state = i; @@ -277,10 +277,10 @@ void QubitLayer::applyMcnot(int *controls, int numControls, int target) if (checkControls(controls, numControls, state)) { state.flip(target); - parity ? _qOdd[state.to_ulong()] = _qEven[i] : _qEven[state.to_ulong()] = _qOdd[i]; + _parity ? _qOdd[state.to_ulong()] = _qEven[i] : _qEven[state.to_ulong()] = _qOdd[i]; } else - parity ? _qOdd[i] = _qEven[i] : _qEven[i] = _qOdd[i]; + _parity ? _qOdd[i] = _qEven[i] : _qEven[i] = _qOdd[i]; } updateLayer(); } @@ -288,15 +288,15 @@ void QubitLayer::applyMcnot(int *controls, int numControls, int target) void QubitLayer::applyCz(int control, int target) { #pragma omp parallel for shared(qOdd_, qEven_) - for (unsigned long long int i = 0; i < numStates; i++) + for (unsigned long long int i = 0; i < _numStates; i++) if (checkZeroState(i)) { std::bitset state = i; // add phase to target qubit if control bit and target bits are 1 (i.e. set) if (state.test(control) && state.test(target)) - parity ? _qOdd[i] = -_qEven[i] : _qEven[i] = -_qOdd[i]; + _parity ? _qOdd[i] = -_qEven[i] : _qEven[i] = -_qOdd[i]; else - parity ? _qOdd[i] = _qEven[i] : _qEven[i] = _qOdd[i]; + _parity ? _qOdd[i] = _qEven[i] : _qEven[i] = _qOdd[i]; } updateLayer(); } @@ -304,15 +304,15 @@ void QubitLayer::applyCz(int control, int target) void QubitLayer::applyMcphase(int *controls, int numControls, int target) { #pragma omp parallel for shared(qOdd_, qEven_) - for (unsigned long long int i = 0; i < numStates; i++) + for (unsigned long long int i = 0; i < _numStates; i++) if (checkZeroState(i)) { std::bitset state = i; // add phase to target qubit if control bit(s) and target bit is 1 (i.e. set) if (checkControls(controls, numControls, state) && state.test(target)) - parity ? _qOdd[i] = -_qEven[i] : _qEven[i] = -_qOdd[i]; + _parity ? _qOdd[i] = -_qEven[i] : _qEven[i] = -_qOdd[i]; else - parity ? _qOdd[i] = _qEven[i] : _qEven[i] = _qOdd[i]; + _parity ? _qOdd[i] = _qEven[i] : _qEven[i] = _qOdd[i]; } updateLayer(); } @@ -323,10 +323,10 @@ qProb QubitLayer::getMaxAmplitude() qProb result; precision currentProb{0}; precision previousProb{0}; - for (unsigned long long int i = 0; i < numStates; i++) + for (unsigned long long int i = 0; i < _numStates; i++) { state = i; - currentProb = parity ? abs(_qEven[i]) * abs(_qEven[i]) : abs(_qOdd[i]) * abs(_qOdd[i]); + currentProb = _parity ? abs(_qEven[i]) * abs(_qEven[i]) : abs(_qOdd[i]) * abs(_qOdd[i]); if (currentProb > previousProb) { result.state = state; @@ -339,7 +339,7 @@ qProb QubitLayer::getMaxAmplitude() void QubitLayer::toggleParity() { - parity = !parity; + _parity = !_parity; } void QubitLayer::printMeasurement() @@ -353,7 +353,7 @@ void QubitLayer::printQubits() { std::cout << "Amplitude, " << "State \n"; - for (unsigned long long int i = 0; i < numStates; i++) + for (unsigned long long int i = 0; i < _numStates; i++) { std::bitset binaryRep = i; std::string state = binaryRep.to_string(); @@ -372,6 +372,6 @@ qubitLayer *QubitLayer::getQubitLayerOdd() return _qOdd; } -unsigned long long int QubitLayer::getNumStates() { return numStates; } +unsigned long long int QubitLayer::getNumStates() { return _numStates; } -unsigned int QubitLayer::getNumQubits() { return numQubits; } \ No newline at end of file +unsigned int QubitLayer::getNumQubits() { return _numQubits; } \ No newline at end of file diff --git a/src/QubitLayer.hpp b/src/QubitLayer.hpp index f96459a..24d92aa 100644 --- a/src/QubitLayer.hpp +++ b/src/QubitLayer.hpp @@ -39,11 +39,12 @@ class QubitLayer bool checkZeroState(int qubit); void updateLayer(); void toggleParity(); - unsigned int numQubits; - unsigned long long int numStates; + unsigned int _numQubits; + unsigned long long int _numStates; + bool _parity = true; + unsigned int _execTime; qubitLayer *_qEven; qubitLayer *_qOdd; - bool parity = true; }; #endif \ No newline at end of file From 8d71c761e1b54181e2e29e8a61394fc9a9ff99a5 Mon Sep 17 00:00:00 2001 From: Ravi Budhrani Date: Wed, 16 Apr 2025 20:53:32 +0200 Subject: [PATCH 5/5] added docs --- src/QubitLayer.cpp | 1 + src/QubitLayer.hpp | 90 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/src/QubitLayer.cpp b/src/QubitLayer.cpp index 5cc3902..a104996 100644 --- a/src/QubitLayer.cpp +++ b/src/QubitLayer.cpp @@ -18,6 +18,7 @@ QubitLayer::QubitLayer(unsigned int numQubits, qubitLayer *qL) for (unsigned int row = 0; row < _numStates; row++) _qEven[row] = qL[row]; else + // the default state is |000...0> _qEven[0] = {1, 0}; } diff --git a/src/QubitLayer.hpp b/src/QubitLayer.hpp index 24d92aa..79ffb2c 100644 --- a/src/QubitLayer.hpp +++ b/src/QubitLayer.hpp @@ -9,23 +9,112 @@ struct qProb precision prob; }; +/** + * @class QubitLayer + * @brief Represents a QubitLayer, which is a pair of qubit states, the input and the ouptut. + */ class QubitLayer { public: + /** + * @brief Default constructor. + * Initialises the qOdd layer to the state |0...0> and the qEven layer to the state |0...01> unless an input is provided. + * + * @param[in] numQubits number of qubits. + * @param[in] qL optional pointer to the array to initialise qEven to. + */ QubitLayer(unsigned int numQubits, qubitLayer *qL = nullptr); + /** + * @brief Default destructor. + * Deletes the memory allocated for qEven and qOdd. + */ ~QubitLayer(); + /** + * @brief Applies Pauli X gate on a qubit. + * + * @param[in] target qubit to apply the gate to. + */ void applyPauliX(int target); + /** + * @brief Applies Pauli Y gate on a qubit. + * + * @param[in] target qubit to apply the gate to. + */ void applyPauliY(int target); + /** + * @brief Applies Pauli Z gate on a qubit. + * + * @param[in] target qubit to apply the gate to. + */ void applyPauliZ(int target); + /** + * @brief Applies Hadamard gate on a qubit. + * + * @param[in] target qubit to apply the gate to. + */ void applyHadamard(int target); + /** + * @brief Applies Rx gate on a qubit. + * + * @param[in] target qubit to apply the gate to. + * @param[in] theta angle to rotate qubit along X axis. + */ void applyRx(int target, precision theta); + /** + * @brief Applies Ry gate on a qubit. + * + * @param[in] target qubit to apply the gate to. + * @param[in] theta angle to rotate qubit along Y axis. + */ void applyRy(int target, precision theta); + /** + * @brief Applies Rz gate on a qubit. + * + * @param[in] target qubit to apply the gate to. + * @param[in] theta angle to rotate qubit along Z axis. + */ void applyRz(int target, precision theta); + /** + * @brief Applies CNOT gate on a qubit given the control qubit. + * + * @param[in] control control qubit. + * @param[in] target target qubit. + */ void applyCnot(int control, int target); + /** + * @brief Applies Toffoli gate on a qubit given the control qubits. + * + * @param[in] control1 control qubit 1. + * @param[in] control1 control qubit 2. + * @param[in] target target qubit. + */ void applyToffoli(int control1, int control2, int target); + /** + * @brief Applies MCNOT gate on a qubit given the control qubits. + * + * @param[in] controls pointer to array of control qubits. + * @param[in] numControls number of control qubits. + * @param[in] target target qubit. + */ void applyMcnot(int *controls, int numControls, int target); + /** + * @brief Applies CZ gate on a qubit given the control qubit. + * + * @param[in] control control qubit. + * @param[in] target target qubit. + */ void applyCz(int control, int target); + /** + * @brief Applies MCPHASE gate on a qubit given the control qubit. + * + * @param[in] controls pointer to array of control qubits. + * @param[in] numControls number of control qubits. + * @param[in] target target qubit. + */ void applyMcphase(int *controls, int numControls, int target); + /** + * @brief Gets the maximum amplitude of the QubitLayer. + */ qProb getMaxAmplitude(); void printMeasurement(); void printQubits(); @@ -42,7 +131,6 @@ class QubitLayer unsigned int _numQubits; unsigned long long int _numStates; bool _parity = true; - unsigned int _execTime; qubitLayer *_qEven; qubitLayer *_qOdd; };