Loading examples/CMakeLists.txt +4 −1 Original line number Diff line number Diff line Loading @@ -11,3 +11,6 @@ add_test(NAME qrt_kernel_include COMMAND ${CMAKE_BINARY_DIR}/qcor -c -I${CMAKE_C add_test(NAME qrt_period_finding COMMAND ${CMAKE_BINARY_DIR}/qcor -c -I${CMAKE_CURRENT_SOURCE_DIR}/shared ${CMAKE_CURRENT_SOURCE_DIR}/simple/period_finding.cpp) add_test(NAME qrt_grover COMMAND ${CMAKE_BINARY_DIR}/qcor -c ${CMAKE_CURRENT_SOURCE_DIR}/grover/grover.cpp) add_test(NAME qrt_adapt COMMAND ${CMAKE_BINARY_DIR}/qcor -c ${CMAKE_CURRENT_SOURCE_DIR}/hybrid/adapt_h2.cpp) add_test(NAME qrt_ftqc_simple COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/simple-demo.cpp) add_test(NAME qrt_ftqc_rus COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/repeat-until-success.cpp) add_test(NAME qrt_ftqc_qec COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/bit-flip-code.cpp) No newline at end of file examples/ftqc_qrt/bit-flip-code.cpp 0 → 100644 +132 −0 Original line number Diff line number Diff line #include <qalloc> // Example demonstrates a simple 3-qubit bit-flip code. // Compile: // qcor -qpu aer[noise-model:<noise.json>] -qrt ftqc bit-flip-code.cpp // ./a.out bool getLogicalVal(qreg q, int logicalIdx) { if (q.creg[logicalIdx*3] == q.creg[logicalIdx*3]) { // First two bits matched. return q.creg[logicalIdx*3]; } // The last bit is the tie-breaker. return q.creg[logicalIdx*3 + 2]; } // Encode qubits into logical qubits: // Assume q[0], q[3], q[6] are initial physical qubits // that will be mapped to logical qubits q[0-2], q[3-5], etc. __qpu__ void encodeQubits(qreg q) { int nbLogicalQubits = q.size() / 3; for (int i = 0; i < nbLogicalQubits; ++i) { int physicalQubitIdx = 3 * i; CX(q[physicalQubitIdx], q[physicalQubitIdx + 1]); CX(q[physicalQubitIdx], q[physicalQubitIdx + 2]); } } // Logical CNOT b/w two logical qubits __qpu__ void cnotLogical(qreg q) { for (int i = 0; i < 3; ++i) { CX(q[i], q[3 + i]); } } __qpu__ void measureLogical(qreg q, int logicalIdx) { int physicalIdx = logicalIdx * 3; for (int i = physicalIdx; i < physicalIdx + 3; ++i) { Measure(q[i]); } } __qpu__ void correctLogicalQubit(qreg q, int logicalIdx, int ancIdx) { int physicalIdx = logicalIdx * 3; // Assume that we only has 1 ancilla qubit CX(q[physicalIdx], q[ancIdx]); CX(q[physicalIdx + 1], q[ancIdx]); const bool parity01 = Measure(q[ancIdx]); if (parity01) { // Reset anc qubit for reuse X(q[ancIdx]); } CX(q[physicalIdx + 1], q[ancIdx]); CX(q[physicalIdx + 2], q[ancIdx]); const bool parity12 = Measure(q[ancIdx]); if (parity12) { // Reset anc qubit X(q[ancIdx]); } // Correct error based on parity results if (parity01 && !parity12) { X(q[physicalIdx]); } if (parity01 && parity12) { X(q[physicalIdx + 1]); } if (!parity01 && parity12) { X(q[physicalIdx + 2]); } } __qpu__ void runQecCycle(qreg q) { int nbLogicalQubits = q.size() / 3; int ancBitIdx = q.size() - 1; for (int i = 0; i < nbLogicalQubits; ++i) { correctLogicalQubit(q, i, ancBitIdx); } } __qpu__ void resetAll(qreg q) { for (int i = 0; i < q.size(); ++i) { // Reset qubits by measure + correct. if (Measure(q[i])) { X(q[i]); } } } // Error corrected Bell example: // Note: the 3-q bit-flip code can only protect against X errors. __qpu__ void bellQEC(qreg q, int nbRuns) { using qcor::xasm; int ancQbId = 6; for (int i = 0; i < nbRuns; ++i) { // Apply H before encoding. H(q[0]); // Encode the qubits into logical qubits. encodeQubits(q); // Run a QEC cycle runQecCycle(q); // Apply *logical* CNOT cnotLogical(q); // Run a QEC cycle runQecCycle(q); // Measure *logical* qubits measureLogical(q, 0); measureLogical(q, 1); // Get *logical* results const bool logicalReq0 = getLogicalVal(q, 0); const bool logicalReq1 = getLogicalVal(q, 1); if (logicalReq0 == logicalReq1) { std::cout << "Iter " << i << ": Matched!\n"; } else { std::cout << "Iter " << i << ": NOT Matched!\n"; } resetAll(q); } } int main() { // Note: we need 3 physical qubits for each logical qubit + // an ancilla qubit for syndrom measurement. auto q = qalloc(7); bellQEC(q, 100); } No newline at end of file examples/ftqc_qrt/repeat-until-success.cpp 0 → 100644 +43 −0 Original line number Diff line number Diff line #include <qalloc> // Compile with: qcor -qpu qpp -qrt ftqc repeat-until-success.cpp // Execute: ./a.out // We should get the print out conditioned by the measurement. // If not using the "ftqc" QRT, this will cause errors since the Measure results // are not available yet. // Using Repeat-Until-Success pattern to prepare a quantum state. // https://docs.microsoft.com/en-us/quantum/user-guide/using-qsharp/control-flow#rus-to-prepare-a-quantum-state __qpu__ void PrepareStateUsingRUS(qreg q, int maxIter) { using qcor::xasm; // Note: target = q[0], aux = q[1] H(q[1]); // We limit the max number of RUS iterations. for (int i = 0; i < maxIter; ++i) { std::cout << "Iter: " << i << "\n"; Tdg(q[1]); CNOT(q[0], q[1]); T(q[1]); // In order to measure in the PauliX basis, changes the basis. H(q[1]); if (!Measure(q[1])) { // Success (until (outcome == Zero)) std::cout << "Success after " << i + 1 << " iterations.\n"; break; } else { // Measure 1: |1> state // Fix up: Bring the auxiliary and target qubits back to |+> state. X(q[1]); H(q[1]); X(q[0]); H(q[0]); } } } int main() { // qcor::set_verbose(true); auto q = qalloc(2); PrepareStateUsingRUS(q, 100); } examples/ftqc_qrt/simple-demo.cpp 0 → 100644 +33 −0 Original line number Diff line number Diff line #include <qalloc> // Compile with: qcor -qpu qpp -qrt ftqc simple-demo.cpp // or with noise: qcor -qpu aer[noise-model:noise_model.json] -qrt ftqc simple-demo.cpp // Execute: ./a.out // We should get the print out conditioned by the measurement. // If not using the "ftqc" QRT, this will cause errors since the Measure results // are not available yet. __qpu__ void bell(qreg q, int nbRuns) { using qcor::xasm; for (int i = 0; i < nbRuns; ++i) { H(q[0]); CX(q[0], q[1]); const bool q0Result = Measure(q[0]); const bool q1Result = Measure(q[1]); if (q0Result == q1Result) { std::cout << "Iter " << i << ": Matched!\n"; } else { std::cout << "Iter " << i << ": NOT Matched!\n"; } // Reset qubits if (q0Result) { X(q[0]); } if (q1Result) { X(q[1]); } } } int main() { auto q = qalloc(2); bell(q, 100); } examples/hadamard_test/simple_hadamard_test.cpp 0 → 100644 +34 −0 Original line number Diff line number Diff line #include <iomanip> __qpu__ void x_gate(qreg q) { X(q[1]); } __qpu__ void h_gate(qreg q) { H(q[1]); } __qpu__ void htest(qreg q) { // Create the superposition on the first qubit H(q[0]); // create the |1> on the second qubit x_gate(q); // create superposition on second qubit // h_gate(q); // apply ctrl-U x_gate::ctrl(q[0], q); // add the last hadamard H(q[0]); // measure Measure(q[0]); } int main() { auto q = qalloc(2); htest(q); q.print(); auto count1 = q.counts().find("1")->second; auto count2 = q.counts().find("0")->second; std::cout << "<X> = " << std::setprecision(12) << std::fabs((count1 - count2) / (double)(count1 + count2)) << "\n"; } No newline at end of file Loading
examples/CMakeLists.txt +4 −1 Original line number Diff line number Diff line Loading @@ -11,3 +11,6 @@ add_test(NAME qrt_kernel_include COMMAND ${CMAKE_BINARY_DIR}/qcor -c -I${CMAKE_C add_test(NAME qrt_period_finding COMMAND ${CMAKE_BINARY_DIR}/qcor -c -I${CMAKE_CURRENT_SOURCE_DIR}/shared ${CMAKE_CURRENT_SOURCE_DIR}/simple/period_finding.cpp) add_test(NAME qrt_grover COMMAND ${CMAKE_BINARY_DIR}/qcor -c ${CMAKE_CURRENT_SOURCE_DIR}/grover/grover.cpp) add_test(NAME qrt_adapt COMMAND ${CMAKE_BINARY_DIR}/qcor -c ${CMAKE_CURRENT_SOURCE_DIR}/hybrid/adapt_h2.cpp) add_test(NAME qrt_ftqc_simple COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/simple-demo.cpp) add_test(NAME qrt_ftqc_rus COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/repeat-until-success.cpp) add_test(NAME qrt_ftqc_qec COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/bit-flip-code.cpp) No newline at end of file
examples/ftqc_qrt/bit-flip-code.cpp 0 → 100644 +132 −0 Original line number Diff line number Diff line #include <qalloc> // Example demonstrates a simple 3-qubit bit-flip code. // Compile: // qcor -qpu aer[noise-model:<noise.json>] -qrt ftqc bit-flip-code.cpp // ./a.out bool getLogicalVal(qreg q, int logicalIdx) { if (q.creg[logicalIdx*3] == q.creg[logicalIdx*3]) { // First two bits matched. return q.creg[logicalIdx*3]; } // The last bit is the tie-breaker. return q.creg[logicalIdx*3 + 2]; } // Encode qubits into logical qubits: // Assume q[0], q[3], q[6] are initial physical qubits // that will be mapped to logical qubits q[0-2], q[3-5], etc. __qpu__ void encodeQubits(qreg q) { int nbLogicalQubits = q.size() / 3; for (int i = 0; i < nbLogicalQubits; ++i) { int physicalQubitIdx = 3 * i; CX(q[physicalQubitIdx], q[physicalQubitIdx + 1]); CX(q[physicalQubitIdx], q[physicalQubitIdx + 2]); } } // Logical CNOT b/w two logical qubits __qpu__ void cnotLogical(qreg q) { for (int i = 0; i < 3; ++i) { CX(q[i], q[3 + i]); } } __qpu__ void measureLogical(qreg q, int logicalIdx) { int physicalIdx = logicalIdx * 3; for (int i = physicalIdx; i < physicalIdx + 3; ++i) { Measure(q[i]); } } __qpu__ void correctLogicalQubit(qreg q, int logicalIdx, int ancIdx) { int physicalIdx = logicalIdx * 3; // Assume that we only has 1 ancilla qubit CX(q[physicalIdx], q[ancIdx]); CX(q[physicalIdx + 1], q[ancIdx]); const bool parity01 = Measure(q[ancIdx]); if (parity01) { // Reset anc qubit for reuse X(q[ancIdx]); } CX(q[physicalIdx + 1], q[ancIdx]); CX(q[physicalIdx + 2], q[ancIdx]); const bool parity12 = Measure(q[ancIdx]); if (parity12) { // Reset anc qubit X(q[ancIdx]); } // Correct error based on parity results if (parity01 && !parity12) { X(q[physicalIdx]); } if (parity01 && parity12) { X(q[physicalIdx + 1]); } if (!parity01 && parity12) { X(q[physicalIdx + 2]); } } __qpu__ void runQecCycle(qreg q) { int nbLogicalQubits = q.size() / 3; int ancBitIdx = q.size() - 1; for (int i = 0; i < nbLogicalQubits; ++i) { correctLogicalQubit(q, i, ancBitIdx); } } __qpu__ void resetAll(qreg q) { for (int i = 0; i < q.size(); ++i) { // Reset qubits by measure + correct. if (Measure(q[i])) { X(q[i]); } } } // Error corrected Bell example: // Note: the 3-q bit-flip code can only protect against X errors. __qpu__ void bellQEC(qreg q, int nbRuns) { using qcor::xasm; int ancQbId = 6; for (int i = 0; i < nbRuns; ++i) { // Apply H before encoding. H(q[0]); // Encode the qubits into logical qubits. encodeQubits(q); // Run a QEC cycle runQecCycle(q); // Apply *logical* CNOT cnotLogical(q); // Run a QEC cycle runQecCycle(q); // Measure *logical* qubits measureLogical(q, 0); measureLogical(q, 1); // Get *logical* results const bool logicalReq0 = getLogicalVal(q, 0); const bool logicalReq1 = getLogicalVal(q, 1); if (logicalReq0 == logicalReq1) { std::cout << "Iter " << i << ": Matched!\n"; } else { std::cout << "Iter " << i << ": NOT Matched!\n"; } resetAll(q); } } int main() { // Note: we need 3 physical qubits for each logical qubit + // an ancilla qubit for syndrom measurement. auto q = qalloc(7); bellQEC(q, 100); } No newline at end of file
examples/ftqc_qrt/repeat-until-success.cpp 0 → 100644 +43 −0 Original line number Diff line number Diff line #include <qalloc> // Compile with: qcor -qpu qpp -qrt ftqc repeat-until-success.cpp // Execute: ./a.out // We should get the print out conditioned by the measurement. // If not using the "ftqc" QRT, this will cause errors since the Measure results // are not available yet. // Using Repeat-Until-Success pattern to prepare a quantum state. // https://docs.microsoft.com/en-us/quantum/user-guide/using-qsharp/control-flow#rus-to-prepare-a-quantum-state __qpu__ void PrepareStateUsingRUS(qreg q, int maxIter) { using qcor::xasm; // Note: target = q[0], aux = q[1] H(q[1]); // We limit the max number of RUS iterations. for (int i = 0; i < maxIter; ++i) { std::cout << "Iter: " << i << "\n"; Tdg(q[1]); CNOT(q[0], q[1]); T(q[1]); // In order to measure in the PauliX basis, changes the basis. H(q[1]); if (!Measure(q[1])) { // Success (until (outcome == Zero)) std::cout << "Success after " << i + 1 << " iterations.\n"; break; } else { // Measure 1: |1> state // Fix up: Bring the auxiliary and target qubits back to |+> state. X(q[1]); H(q[1]); X(q[0]); H(q[0]); } } } int main() { // qcor::set_verbose(true); auto q = qalloc(2); PrepareStateUsingRUS(q, 100); }
examples/ftqc_qrt/simple-demo.cpp 0 → 100644 +33 −0 Original line number Diff line number Diff line #include <qalloc> // Compile with: qcor -qpu qpp -qrt ftqc simple-demo.cpp // or with noise: qcor -qpu aer[noise-model:noise_model.json] -qrt ftqc simple-demo.cpp // Execute: ./a.out // We should get the print out conditioned by the measurement. // If not using the "ftqc" QRT, this will cause errors since the Measure results // are not available yet. __qpu__ void bell(qreg q, int nbRuns) { using qcor::xasm; for (int i = 0; i < nbRuns; ++i) { H(q[0]); CX(q[0], q[1]); const bool q0Result = Measure(q[0]); const bool q1Result = Measure(q[1]); if (q0Result == q1Result) { std::cout << "Iter " << i << ": Matched!\n"; } else { std::cout << "Iter " << i << ": NOT Matched!\n"; } // Reset qubits if (q0Result) { X(q[0]); } if (q1Result) { X(q[1]); } } } int main() { auto q = qalloc(2); bell(q, 100); }
examples/hadamard_test/simple_hadamard_test.cpp 0 → 100644 +34 −0 Original line number Diff line number Diff line #include <iomanip> __qpu__ void x_gate(qreg q) { X(q[1]); } __qpu__ void h_gate(qreg q) { H(q[1]); } __qpu__ void htest(qreg q) { // Create the superposition on the first qubit H(q[0]); // create the |1> on the second qubit x_gate(q); // create superposition on second qubit // h_gate(q); // apply ctrl-U x_gate::ctrl(q[0], q); // add the last hadamard H(q[0]); // measure Measure(q[0]); } int main() { auto q = qalloc(2); htest(q); q.print(); auto count1 = q.counts().find("1")->second; auto count2 = q.counts().find("0")->second; std::cout << "<X> = " << std::setprecision(12) << std::fabs((count1 - count2) / (double)(count1 + count2)) << "\n"; } No newline at end of file