From 603dcffd10f684e38bbd70d23b7085cb428276dc Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Tue, 9 Apr 2024 15:36:36 +0200 Subject: [PATCH 01/37] control and target order independent create_cgate() funcion --- src/qsylvan_gates.c | 8 +++++ src/qsylvan_gates.h | 2 ++ src/qsylvan_simulator.c | 77 +++++++++++++++++++---------------------- src/qsylvan_simulator.h | 9 +++-- test/test_qmdd_matrix.c | 19 +++++++++- 5 files changed, 68 insertions(+), 47 deletions(-) diff --git a/src/qsylvan_gates.c b/src/qsylvan_gates.c index 38ca381..26d69fe 100644 --- a/src/qsylvan_gates.c +++ b/src/qsylvan_gates.c @@ -131,6 +131,14 @@ qmdd_gates_init() gates[k][0] = AADD_ONE; gates[k][1] = AADD_ZERO; gates[k][2] = AADD_ZERO; gates[k][3] = AADD_ONE; + k = GATEID_proj0; + gates[k][0] = AADD_ONE; gates[k][1] = AADD_ZERO; + gates[k][2] = AADD_ZERO; gates[k][3] = AADD_ZERO; + + k = GATEID_proj1; + gates[k][0] = AADD_ZERO; gates[k][1] = AADD_ZERO; + gates[k][2] = AADD_ZERO; gates[k][3] = AADD_ONE; + k = GATEID_X; gates[k][0] = AADD_ZERO; gates[k][1] = AADD_ONE; gates[k][2] = AADD_ONE; gates[k][3] = AADD_ZERO; diff --git a/src/qsylvan_gates.h b/src/qsylvan_gates.h index e38792f..f3dc681 100644 --- a/src/qsylvan_gates.h +++ b/src/qsylvan_gates.h @@ -10,6 +10,8 @@ typedef uint64_t AMP; // TODO: replace with AADD_WGT? // currently 24 bits available for this number (see GATE_OPID) typedef enum predef_gates { GATEID_I, + GATEID_proj0, // |0><0| + GATEID_proj1, // |1><1| GATEID_X, GATEID_Y, GATEID_Z, diff --git a/src/qsylvan_simulator.c b/src/qsylvan_simulator.c index 1a20ff7..df4c1f5 100644 --- a/src/qsylvan_simulator.c +++ b/src/qsylvan_simulator.c @@ -221,58 +221,53 @@ qmdd_create_controlled_gate(BDDVAR n, BDDVAR c, BDDVAR t, gate_id_t gateid) } QMDD -qmdd_create_multi_cgate_rec(BDDVAR n, int *c_options, gate_id_t gateid, BDDVAR k) +qmdd_create_multi_cgate(BDDVAR n, int *c_options, gate_id_t gateid) { - // (assumes controls above target) // c_options[k] = -1 -> ignore qubit k (apply I) // c_options[k] = 0 -> control on q_k = |0> // c_options[k] = 1 -> control on q_k = |1> // c_options[k] = 2 -> target qubit (for now assume 1 target) - // Terminal case - if (k == n) { - return aadd_bundle(AADD_TERMINAL, AADD_ONE); - } + // C_1 C_2 C_3 U_0 = U \tensor |111><111| + (U_proj) + // I^{\tensor 4} + (I) + // -I \tensor |111><111| (proj) + + // TODO: protect from gc? + QMDD U_proj = aadd_bundle(AADD_TERMINAL, AADD_ONE); + QMDD proj = aadd_bundle(AADD_TERMINAL, AADD_ONE); + QMDD I = qmdd_create_all_identity_matrix(n); - // TODO: catching GATEID_I avoids exp number of recrusive calls, but this - // entire function might be handled in a better way(?) - if (gateid == GATEID_I) { - QMDD identities = aadd_bundle(AADD_TERMINAL, AADD_ONE); - for (int j = n-1; j >= (int) k; j--) { - identities = qmdd_stack_matrix(identities, j, GATEID_I); + for (int k = n-1; k >= 0; k--) { + // -1 : Ignore qubit (apply I) + if (c_options[k] == -1) { + U_proj = qmdd_stack_matrix(U_proj, k, GATEID_I); + proj = qmdd_stack_matrix(proj, k, GATEID_I); + } + // 0 : control on q_k = |0> + else if (c_options[k] == 0) { + U_proj = qmdd_stack_matrix(U_proj, k, GATEID_proj0); + proj = qmdd_stack_matrix(proj, k, GATEID_proj0); + } + // 1 : control on q_k = |1> + else if (c_options[k] == 1) { + U_proj = qmdd_stack_matrix(U_proj, k, GATEID_proj1); + proj = qmdd_stack_matrix(proj, k, GATEID_proj1); + } + // 2 : target qubit + else if (c_options[k] == 2) { + U_proj = qmdd_stack_matrix(U_proj, k, gateid); + proj = qmdd_stack_matrix(proj, k, GATEID_I); + } + else { + printf("Invalid option %d for qubit %d (options = {-1,0,1,2}\n", c_options[k], k); + exit(1); } - return identities; } - // Recursively build matrix - BDDVAR next_k = k + 1; + // multiply root edge of proj with -1 + proj = aadd_bundle(AADD_TARGET(proj), wgt_neg(AADD_WEIGHT(proj))); - // -1 : Ignore qubit (apply I) - if (c_options[k] == -1) { - QMDD below = qmdd_create_multi_cgate_rec(n, c_options, gateid, next_k); - return qmdd_stack_matrix(below, k, GATEID_I); - } - // 0 : control on q_k = |0> (apply gateid to low branch) - else if (c_options[k] == 0) { - QMDD case0 = qmdd_create_multi_cgate_rec(n, c_options, gateid, next_k); - QMDD case1 = qmdd_create_multi_cgate_rec(n, c_options, GATEID_I, next_k); - return qmdd_stack_control(case0, case1, k); - } - // 1 : control on q_k = |1> (apply gateid to high branch) - else if (c_options[k] == 1) { - QMDD case0 = qmdd_create_multi_cgate_rec(n, c_options, GATEID_I, next_k); - QMDD case1 = qmdd_create_multi_cgate_rec(n, c_options, gateid, next_k); - return qmdd_stack_control(case0, case1, k); - } - // 2 : target qubit - else if (c_options[k] == 2) { - QMDD below = qmdd_create_multi_cgate_rec(n, c_options, gateid, next_k); - return qmdd_stack_matrix(below, k, gateid); - } - else { - printf("Invalid option %d for qubit %d (options = {-1,0,1,2}\n", c_options[k], k); - exit(1); - } + return aadd_plus(U_proj, aadd_plus(I, proj)); } QMDD diff --git a/src/qsylvan_simulator.h b/src/qsylvan_simulator.h index ea8ec2d..00c218f 100644 --- a/src/qsylvan_simulator.h +++ b/src/qsylvan_simulator.h @@ -128,20 +128,19 @@ QMDD qmdd_create_controlled_gate(BDDVAR n, BDDVAR c, BDDVAR t, gate_id_t gateid) /** * Creates a controlled-`gateid` gate which acts on the qubits as specified by - * `c_options`. + * `c_options`. (Independent of order of controls and targets.) * * @param n Total number of qubits. * @param c_options Array of length n with option for each qubit k: { * -1 : ignore qubit k (apply I), - * 0 : control on q_k = |0> - * 1 : control on q_k = |1> + * 0 : control on q_k = |0>, + * 1 : control on q_k = |1>, * 2 : target qubit } * @param gateid Gate ID of predefined single qubit gate U. * * @return A matrix QMDD encoding of the multi-controlled gate on given qubits. */ -#define qmdd_create_multi_cgate(n,c_options,gateid) qmdd_create_multi_cgate_rec(n,c_options,gateid,0) -QMDD qmdd_create_multi_cgate_rec(BDDVAR n, int *c_options, gate_id_t gateid, BDDVAR k); +QMDD qmdd_create_multi_cgate(BDDVAR n, int *c_options, gate_id_t gateid); /** * Creates an n-qubit controlled Z gate, controlled on all qubits. diff --git a/test/test_qmdd_matrix.c b/test/test_qmdd_matrix.c index 42e41af..8c39758 100644 --- a/test/test_qmdd_matrix.c +++ b/test/test_qmdd_matrix.c @@ -605,10 +605,27 @@ int test_multi_cgate() test_assert(qTest == qRef); } + // controls below target + nqubits = 3; + qInit = qmdd_create_all_zero_state(nqubits); + qInit = qmdd_gate(qInit, GATEID_H, 0); + qInit = qmdd_gate(qInit, GATEID_X, 1); + qInit = qmdd_gate(qInit, GATEID_H, 2); + for (uint32_t i = 0; i < len(test_gates); i++) { + // t = 0, c1 = 1, c2 = 2 + int c_options[] = {2, 1, 1}; + qRef = qmdd_circuit_swap(qInit, 0, 2); + qRef = qmdd_cgate2(qRef, test_gates[i], 0, 1, 2); + qRef = qmdd_circuit_swap(qRef, 0, 2); + matrix = qmdd_create_multi_cgate(nqubits, c_options, test_gates[i]); + qTest = aadd_matvec_mult(matrix, qInit, nqubits); + test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(qTest == qRef); + } // TODO: more tests - if(VERBOSE) printf("matrix qmdd multi-cgate: ok so far (WIP)\n"); return 0; } From d9427d012f2b560aea514885d8f7295cb36817ba Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Thu, 11 Apr 2024 11:57:00 +0200 Subject: [PATCH 02/37] small refactor of applying controlled gates --- src/qsylvan_simulator.c | 26 +++++--------------------- src/qsylvan_simulator.h | 16 +++++++--------- 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/src/qsylvan_simulator.c b/src/qsylvan_simulator.c index df4c1f5..15a2a49 100644 --- a/src/qsylvan_simulator.c +++ b/src/qsylvan_simulator.c @@ -341,28 +341,12 @@ TASK_IMPL_3(QMDD, qmdd_gate, QMDD, qmdd, gate_id_t, gate, BDDVAR, target) return qmdd_gate_rec(qmdd, gate, target); } -/* Wrapper for applying a controlled gate with 1 control qubit. */ -TASK_IMPL_4(QMDD, qmdd_cgate, QMDD, qmdd, gate_id_t, gate, BDDVAR, c, BDDVAR, t) +/* Wrapper for applying controlled gates with 1, 2, or 3 control qubits. */ +TASK_IMPL_6(QMDD, _qmdd_cgate, QMDD, state, gate_id_t, gate, BDDVAR, c1, BDDVAR, c2, BDDVAR, c3, BDDVAR, t) { - qmdd_do_before_gate(&qmdd); - BDDVAR cs[4] = {c, AADD_INVALID_VAR, AADD_INVALID_VAR, AADD_INVALID_VAR}; - return qmdd_cgate_rec(qmdd, gate, cs, t); -} - -/* Wrapper for applying a controlled gate with 2 control qubits. */ -TASK_IMPL_5(QMDD, qmdd_cgate2, QMDD, qmdd, gate_id_t, gate, BDDVAR, c1, BDDVAR, c2, BDDVAR, t) -{ - qmdd_do_before_gate(&qmdd); - BDDVAR cs[4] = {c1, c2, AADD_INVALID_VAR, AADD_INVALID_VAR}; - return qmdd_cgate_rec(qmdd, gate, cs, t); -} - -/* Wrapper for applying a controlled gate with 3 control qubits. */ -TASK_IMPL_6(QMDD, qmdd_cgate3, QMDD, qmdd, gate_id_t, gate, BDDVAR, c1, BDDVAR, c2, BDDVAR, c3, BDDVAR, t) -{ - qmdd_do_before_gate(&qmdd); - BDDVAR cs[4] = {c1, c2, c3, AADD_INVALID_VAR}; // last pos is a buffer - return qmdd_cgate_rec(qmdd, gate, cs, t); + qmdd_do_before_gate(&state); + BDDVAR cs[4] = {c1, c2, c3, AADD_INVALID_VAR}; // last pos is to mark end + return qmdd_cgate_rec(state, gate, cs, t); } /* Wrapper for applying a controlled gate where the controls are a range. */ diff --git a/src/qsylvan_simulator.h b/src/qsylvan_simulator.h index 00c218f..854a018 100644 --- a/src/qsylvan_simulator.h +++ b/src/qsylvan_simulator.h @@ -237,19 +237,17 @@ AMP qmdd_amp_from_prob(double a); // For now we have at most 3 control qubits #define MAX_CONTROLS 3 -/* Applies given (single qubit) gate to |q>. (Wrapper function) */ +/* Applies given (single qubit) gate to |q>. */ #define qmdd_gate(qmdd,gate,target) (RUN(qmdd_gate,qmdd,gate,target)) TASK_DECL_3(QMDD, qmdd_gate, QMDD, gate_id_t, BDDVAR); -/* Applies given controlled gate to |q>. (Wrapper function) */ -#define qmdd_cgate(qmdd,gate,c,t) (RUN(qmdd_cgate,qmdd,gate,c,t)) -#define qmdd_cgate2(qmdd,gate,c1,c2,t) (RUN(qmdd_cgate2,qmdd,gate,c1,c2,t)) -#define qmdd_cgate3(qmdd,gate,c1,c2,c3,t) (RUN(qmdd_cgate3,qmdd,gate,c1,c2,c3,t)) -TASK_DECL_4(QMDD, qmdd_cgate, QMDD, gate_id_t, BDDVAR, BDDVAR); -TASK_DECL_5(QMDD, qmdd_cgate2, QMDD, gate_id_t, BDDVAR, BDDVAR, BDDVAR); -TASK_DECL_6(QMDD, qmdd_cgate3, QMDD, gate_id_t, BDDVAR, BDDVAR, BDDVAR, BDDVAR); +/* Applies given controlled gate to |q>. */ +#define qmdd_cgate(state,gate,c,t) (RUN(_qmdd_cgate,state,gate,c,AADD_INVALID_VAR,AADD_INVALID_VAR,t)) +#define qmdd_cgate2(state,gate,c1,c2,t) (RUN(_qmdd_cgate,state,gate,c1,c2,AADD_INVALID_VAR,t)) +#define qmdd_cgate3(state,gate,c1,c2,c3,t) (RUN(_qmdd_cgate,state,gate,c1,c2,c3,t)) +TASK_DECL_6(QMDD, _qmdd_cgate, QMDD, gate_id_t, BDDVAR, BDDVAR, BDDVAR, BDDVAR); -/* Applies given controlled gate to |q>. (Wrapper function) */ +/* Applies given controlled gate to |q>. */ #define qmdd_cgate_range(qmdd,gate,c_first,c_last,t) (RUN(qmdd_cgate_range,qmdd,gate,c_first,c_last,t)) TASK_DECL_5(QMDD, qmdd_cgate_range, QMDD, gate_id_t, BDDVAR, BDDVAR, BDDVAR); From dc620efd8b0170f2715562a1c8ebf4493941bc9a Mon Sep 17 00:00:00 2001 From: Richard van Dijk <37830964+MarinusVanDijk@users.noreply.github.com> Date: Thu, 11 Apr 2024 14:27:11 +0200 Subject: [PATCH 03/37] Update cmake.yml Install of mpfr and mpc libraries added. --- .github/workflows/cmake.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index f48dedc..e2d687f 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -32,6 +32,8 @@ jobs: sudo apt update sudo apt install cmake cmake-data build-essential sudo apt install libgmp-dev + sudo apt install libmpfr-dev + sudo apt install libmpc-dev - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type From fbcb619fdebe8052e089dc8074bd54fc2268f007 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Thu, 11 Apr 2024 14:58:13 +0200 Subject: [PATCH 04/37] allow for controls after target in cgate() function --- src/qsylvan_simulator.c | 30 ++++++++++++-- src/qsylvan_simulator.h | 13 +++--- test/test_qmdd_gates.c | 92 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 120 insertions(+), 15 deletions(-) diff --git a/src/qsylvan_simulator.c b/src/qsylvan_simulator.c index 15a2a49..b8ba3c5 100644 --- a/src/qsylvan_simulator.c +++ b/src/qsylvan_simulator.c @@ -334,6 +334,15 @@ qmdd_do_before_gate(QMDD* qmdd) qmdd_stats_log(*qmdd); } +static bool +check_ctrls_before_targ(BDDVAR c1, BDDVAR c2, BDDVAR c3, BDDVAR t) +{ + if (c1 != AADD_INVALID_VAR && c1 > t) return false; + if (c2 != AADD_INVALID_VAR && c2 > t) return false; + if (c3 != AADD_INVALID_VAR && c3 > t) return false; + return true; +} + /* Wrapper for applying a single qubit gate. */ TASK_IMPL_3(QMDD, qmdd_gate, QMDD, qmdd, gate_id_t, gate, BDDVAR, target) { @@ -342,11 +351,26 @@ TASK_IMPL_3(QMDD, qmdd_gate, QMDD, qmdd, gate_id_t, gate, BDDVAR, target) } /* Wrapper for applying controlled gates with 1, 2, or 3 control qubits. */ -TASK_IMPL_6(QMDD, _qmdd_cgate, QMDD, state, gate_id_t, gate, BDDVAR, c1, BDDVAR, c2, BDDVAR, c3, BDDVAR, t) +QMDD _qmdd_cgate(QMDD state, gate_id_t gate, BDDVAR c1, BDDVAR c2, BDDVAR c3, BDDVAR t, BDDVAR n) { qmdd_do_before_gate(&state); - BDDVAR cs[4] = {c1, c2, c3, AADD_INVALID_VAR}; // last pos is to mark end - return qmdd_cgate_rec(state, gate, cs, t); + + if (check_ctrls_before_targ(c1, c2, c3, t)) { + BDDVAR cs[4] = {c1, c2, c3, AADD_INVALID_VAR}; // last pos is to mark end + return qmdd_cgate_rec(state, gate, cs, t); + } + else { + assert(n != 0 && "ERROR: when ctrls > targ, nqubits must be passed to cgate() function."); + int *c_options = malloc(sizeof(int)*n); + for (uint32_t k = 0; k < n; k++) c_options[k] = -1; + if (c1 != AADD_INVALID_VAR) c_options[c1] = 1; + if (c2 != AADD_INVALID_VAR) c_options[c2] = 1; + if (c3 != AADD_INVALID_VAR) c_options[c3] = 1; + c_options[t] = 2; + QMDD gate_matrix = qmdd_create_multi_cgate(n, c_options, gate); + free(c_options); + return aadd_matvec_mult(gate_matrix, state, n); + } } /* Wrapper for applying a controlled gate where the controls are a range. */ diff --git a/src/qsylvan_simulator.h b/src/qsylvan_simulator.h index 854a018..ba344b7 100644 --- a/src/qsylvan_simulator.h +++ b/src/qsylvan_simulator.h @@ -241,11 +241,14 @@ AMP qmdd_amp_from_prob(double a); #define qmdd_gate(qmdd,gate,target) (RUN(qmdd_gate,qmdd,gate,target)) TASK_DECL_3(QMDD, qmdd_gate, QMDD, gate_id_t, BDDVAR); -/* Applies given controlled gate to |q>. */ -#define qmdd_cgate(state,gate,c,t) (RUN(_qmdd_cgate,state,gate,c,AADD_INVALID_VAR,AADD_INVALID_VAR,t)) -#define qmdd_cgate2(state,gate,c1,c2,t) (RUN(_qmdd_cgate,state,gate,c1,c2,AADD_INVALID_VAR,t)) -#define qmdd_cgate3(state,gate,c1,c2,c3,t) (RUN(_qmdd_cgate,state,gate,c1,c2,c3,t)) -TASK_DECL_6(QMDD, _qmdd_cgate, QMDD, gate_id_t, BDDVAR, BDDVAR, BDDVAR, BDDVAR); +/** + * Applies given controlled gate to |q>. When controls !<= target, the total + * number of qubits needs to be passed as last argument. +*/ +#define qmdd_cgate(state,gate,c,t,...) _qmdd_cgate(state,gate,c,AADD_INVALID_VAR,AADD_INVALID_VAR,t,(0, ##__VA_ARGS__)) +#define qmdd_cgate2(state,gate,c1,c2,t,...) (_qmdd_cgate(state,gate,c1,c2,AADD_INVALID_VAR,t,(0, ##__VA_ARGS__))) +#define qmdd_cgate3(state,gate,c1,c2,c3,t,...) (_qmdd_cgate(state,gate,c1,c2,c3,t,(0, ##__VA_ARGS__))) +QMDD _qmdd_cgate(QMDD state, gate_id_t gate, BDDVAR c1, BDDVAR c2, BDDVAR c3, BDDVAR t, BDDVAR n); /* Applies given controlled gate to |q>. */ #define qmdd_cgate_range(qmdd,gate,c_first,c_last,t) (RUN(qmdd_cgate_range,qmdd,gate,c_first,c_last,t)) diff --git a/test/test_qmdd_gates.c b/test/test_qmdd_gates.c index 19d605a..f0032c7 100644 --- a/test/test_qmdd_gates.c +++ b/test/test_qmdd_gates.c @@ -473,11 +473,12 @@ int test_pauli_rotation_gates() int test_cx_gate() { QMDD qBell; + BDDVAR nqubits = 2; bool x2[] = {0,0}; AMP a; // Test Bell state - x2[1] = 0; x2[0] = 0; qBell = qmdd_create_basis_state(2, x2); + x2[1] = 0; x2[0] = 0; qBell = qmdd_create_basis_state(nqubits, x2); qBell = qmdd_gate(qBell, GATEID_H, 0); x2[1] = 0; x2[0] = 0; a = aadd_getvalue(qBell, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); @@ -494,6 +495,22 @@ int test_cx_gate() x2[1] = 1; x2[0] = 1; a = aadd_getvalue(qBell, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); test_assert(aadd_countnodes(qBell) == 4); + // Test Bell state with CX upside down + x2[1] = 0; x2[0] = 0; qBell = qmdd_create_basis_state(nqubits, x2); + qBell = qmdd_gate(qBell, GATEID_H, 1); + + x2[1] = 0; x2[0] = 0; a = aadd_getvalue(qBell, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 0; x2[0] = 1; a = aadd_getvalue(qBell, x2); test_assert(a == AADD_ZERO); + x2[1] = 1; x2[0] = 0; a = aadd_getvalue(qBell, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 1; x2[0] = 1; a = aadd_getvalue(qBell, x2); test_assert(a == AADD_ZERO); + + qBell = qmdd_cgate(qBell, GATEID_X, 1, 0, nqubits); + + x2[1] = 0; x2[0] = 0; a = aadd_getvalue(qBell, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 0; x2[0] = 1; a = aadd_getvalue(qBell, x2); test_assert(a == AADD_ZERO); + x2[1] = 1; x2[0] = 0; a = aadd_getvalue(qBell, x2); test_assert(a == AADD_ZERO); + x2[1] = 1; x2[0] = 1; a = aadd_getvalue(qBell, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + // TODO: more tests if(VERBOSE) printf("qmdd cnot gates: ok\n"); @@ -503,11 +520,12 @@ int test_cx_gate() int test_cz_gate() { QMDD qGraph; + BDDVAR nqubits = 2; bool x2[] = {0, 0}; AMP a; // 2 qubit graph state - x2[1] = 0; x2[0] = 0; qGraph =qmdd_create_basis_state(2, x2); + x2[1] = 0; x2[0] = 0; qGraph =qmdd_create_basis_state(nqubits, x2); qGraph = qmdd_gate(qGraph, GATEID_H, 0); qGraph = qmdd_gate(qGraph, GATEID_H, 1); @@ -525,6 +543,25 @@ int test_cz_gate() x2[1] = 1; x2[0] = 1; a = aadd_getvalue(qGraph, x2); test_assert(a == complex_lookup(-0.5,0)); test_assert(aadd_countnodes(qGraph) == 3); + // same 2 qubit graph state but with control and target arguments swapped + x2[1] = 0; x2[0] = 0; qGraph =qmdd_create_basis_state(nqubits, x2); + qGraph = qmdd_gate(qGraph, GATEID_H, 0); + qGraph = qmdd_gate(qGraph, GATEID_H, 1); + + x2[1] = 0; x2[0] = 0; a = aadd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = aadd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = aadd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 1; a = aadd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + test_assert(aadd_countnodes(qGraph) == 1); + + qGraph = qmdd_cgate(qGraph, GATEID_Z, 1, 0, nqubits); + + x2[1] = 0; x2[0] = 0; a = aadd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = aadd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = aadd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 1; a = aadd_getvalue(qGraph, x2); test_assert(a == complex_lookup(-0.5,0)); + test_assert(aadd_countnodes(qGraph) == 3); + if(VERBOSE) printf("qmdd CZ gates: ok\n"); return 0; } @@ -532,17 +569,20 @@ int test_cz_gate() int test_ccz_gate() { QMDD q3; + BDDVAR nqubits = 3; bool x3[] = {0,0,0}; AMP a, aRef; + complex_t mone = cmone(); - q3 = qmdd_create_basis_state(3, x3); + // Test CCZ using qmdd_all_control_phase() + q3 = qmdd_create_all_zero_state(nqubits); q3 = qmdd_gate(q3, GATEID_H, 0); q3 = qmdd_gate(q3, GATEID_H, 1); q3 = qmdd_gate(q3, GATEID_H, 2); - aRef = aadd_getvalue(q3, x3); - complex_t mone = cmone(); - x3[2]=1; x3[1]=0; x3[0]=1; q3 = qmdd_all_control_phase(q3, 3, x3); + x3[2] = 0; x3[1] = 0; x3[0] = 0; aRef = aadd_getvalue(q3, x3); + x3[2] = 1; x3[1] = 0; x3[0] = 1; q3 = qmdd_all_control_phase(q3, nqubits, x3); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q3, x3); test_assert(a == aRef); x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q3, x3); test_assert(a == aRef); x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q3, x3); test_assert(a == aRef); @@ -553,7 +593,45 @@ int test_ccz_gate() x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q3, x3); test_assert(a == aRef); test_assert(aadd_is_ordered(q3, 3)); - // TODO: few more tests + // Test CCZ using qmdd_cgate2() + q3 = qmdd_create_all_zero_state(nqubits); + q3 = qmdd_gate(q3, GATEID_H, 0); + q3 = qmdd_gate(q3, GATEID_H, 1); + q3 = qmdd_gate(q3, GATEID_H, 2); + + x3[2] = 0; x3[1] = 0; x3[0] = 0; aRef = aadd_getvalue(q3, x3); + x3[2] = 1; x3[1] = 0; x3[0] = 1; q3 = qmdd_cgate2(q3, GATEID_Z, 0, 1, 2); + + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q3, x3); test_assert(a == wgt_mul(aRef,weight_lookup(&mone))); + test_assert(aadd_is_ordered(q3, 3)); + + // Test CCZ using qmdd_cgate2() with target between controls + q3 = qmdd_create_all_zero_state(nqubits); + q3 = qmdd_gate(q3, GATEID_H, 0); + q3 = qmdd_gate(q3, GATEID_H, 1); + q3 = qmdd_gate(q3, GATEID_H, 2); + + x3[2] = 0; x3[1] = 0; x3[0] = 0; aRef = aadd_getvalue(q3, x3); + x3[2] = 1; x3[1] = 0; x3[0] = 1; q3 = qmdd_cgate2(q3, GATEID_Z, 0, 2, 1, nqubits); + + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q3, x3); test_assert(a == wgt_mul(aRef,weight_lookup(&mone))); + test_assert(aadd_is_ordered(q3, 3)); + + // TODO: more tests? if(VERBOSE) printf("qmdd all-control z gate: ok\n"); return 0; From fb330c3f7d8cae6c0cac20d54fa6d17e0a46554d Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Thu, 11 Apr 2024 15:10:42 +0200 Subject: [PATCH 05/37] possible fix for CI compile issue --- src/qsylvan_simulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qsylvan_simulator.c b/src/qsylvan_simulator.c index b8ba3c5..0cf98eb 100644 --- a/src/qsylvan_simulator.c +++ b/src/qsylvan_simulator.c @@ -361,7 +361,7 @@ QMDD _qmdd_cgate(QMDD state, gate_id_t gate, BDDVAR c1, BDDVAR c2, BDDVAR c3, BD } else { assert(n != 0 && "ERROR: when ctrls > targ, nqubits must be passed to cgate() function."); - int *c_options = malloc(sizeof(int)*n); + int *c_options = malloc(sizeof(int)*(n+1)); for (uint32_t k = 0; k < n; k++) c_options[k] = -1; if (c1 != AADD_INVALID_VAR) c_options[c1] = 1; if (c2 != AADD_INVALID_VAR) c_options[c2] = 1; From 0e0cac3a345c9f1a4b93d0169b04a2e7f34e4efa Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Fri, 12 Apr 2024 11:00:03 +0200 Subject: [PATCH 06/37] update bit description of sylvan_aadd --- src/sylvan_aadd_int.h | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/sylvan_aadd_int.h b/src/sylvan_aadd_int.h index 184c509..0d3cb89 100644 --- a/src/sylvan_aadd_int.h +++ b/src/sylvan_aadd_int.h @@ -15,7 +15,7 @@ * sylvan_init_aadd(). * TODO: Maybe handle this in a cleaner way than with global variables? */ -// using [wgts,ptr] [33,30] bits (default [23,40]) +// using [wgts,ptr] [33,30] bits if set to true (default [23,40]) extern bool larger_wgt_indices; extern int weight_norm_strat; extern AADD_WGT (*normalize_weights)(AADD_WGT *, AADD_WGT *); @@ -24,30 +24,55 @@ extern AADD_WGT (*normalize_weights)(AADD_WGT *, AADD_WGT *); /*********************************/ /** + * When edge weight table <= 2^23 (larger_wgt_indices = false) + * ----------------------------------------------------------------------------- * AADD edge structure (64 bits) - * 1 bit: marked/unmarked flag (same place as MTBDD) - * 33 bits: index of edge weight in ctable (AADD_WGT) - * 30 bits: index of next node in node table (AADD_TARG) + * 1 bit: unused + * 23 bits: index of edge weight in weight table (AADD_WGT) + * 40 bits: index of next node in node table (AADD_TARG) * * AADD node structure (128 bits) * (note: because of normalization of the edge weights, we only need 1 weight * per node, the other will always be 0 or 1 or dependent on the first value.) * * 64 bits low: - * 1 bit: marked/unmarked flag (same place as MTBDD) + * 1 bit: unused * 8 bits: variable/qubit number of this node * 1 bit: if 0 (1) normalized WGT is on low (high) * 1 bit: if 0 (1) normalized WGT is AADD_ZERO (AADD_ONE) * 13 bits: unused + * 40 bits: low edge pointer to next node (AADD_TARG) + * 64 bits high: + * 1 bit: marked/unmarked flag + * 23 bits: index of edge weight of high edge in ctable (AADD_WGT) + * 40 bits: high edge pointer to next node (AADD_TARG) + * ----------------------------------------------------------------------------- + * + * + * When edge weight table > 2^23 (larger_wgt_indices = true) + * ----------------------------------------------------------------------------- + * AADD edge structure (64 bits) + * 1 bit: unused + * 23 bits: index of edge weight in weight table (AADD_WGT) + * 40 bits: index of next node in node table (AADD_TARG) + * + * AADD node structure (128 bits) + * 64 bits low: + * 1 bit: unused + * 8 bits: variable/qubit number of this node + * 1 bit: if 0 (1) normalized WGT is on low (high) + * 1 bit: if 0 (1) normalized WGT is AADD_ZERO (AADD_ONE) + * 23 bits: unused * 30 bits: low edge pointer to next node (AADD_TARG) * 64 bits high: - * 1 bit: marked/unmarked flag (same place as MTBDD) + * 1 bit: marked/unmarked flag * 33 bits: index of edge weight of high edge in ctable (AADD_WGT) * 30 bits: high edge pointer to next node (AADD_TARG) + * ----------------------------------------------------------------------------- */ typedef struct __attribute__((packed)) aaddnode { AADD low, high; -} *aaddnode_t; // 16 bytes // TODO: move to sylvan_aadd_int.h +} *aaddnode_t; // 16 bytes static const AADD aadd_marked_mask = 0x8000000000000000LL; static const AADD aadd_var_mask_low = 0x7f80000000000000LL; From 64f09eef2fb85adf80b37f3927412d97ef343bac Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Tue, 28 May 2024 11:33:13 +0200 Subject: [PATCH 07/37] basis of testing qasm CLI with pytest --- .github/workflows/cmake.yml | 10 +++ .gitignore | 3 + qasm/test/test_circuits/bell_phi_min.qasm | 13 ++++ qasm/test/test_circuits/bell_phi_plus.qasm | 12 +++ qasm/test/test_circuits/bell_psi_min.qasm | 12 +++ qasm/test/test_circuits/bell_psi_plus.qasm | 11 +++ qasm/test/test_sim_qasm.py | 87 ++++++++++++++++++++++ 7 files changed, 148 insertions(+) create mode 100644 qasm/test/test_circuits/bell_phi_min.qasm create mode 100644 qasm/test/test_circuits/bell_phi_plus.qasm create mode 100644 qasm/test/test_circuits/bell_psi_min.qasm create mode 100644 qasm/test/test_circuits/bell_psi_plus.qasm create mode 100644 qasm/test/test_sim_qasm.py diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index e2d687f..2e8f5c9 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -48,3 +48,13 @@ jobs: # Execute tests defined by the CMake configuration. # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail run: ctest -C ${{env.BUILD_TYPE}} + + - name: Test CLI + uses: actions/setup-python@v5 + with: + python-version: "3.10" + run: | + python -m pip install --upgrade pip + pip install numpy + pip install pytest + pytest diff --git a/.gitignore b/.gitignore index 60ac70b..d7ba40b 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,6 @@ CMakeFiles/ CMakeCache.txt qsylvan.pc *.swp + +# Python stuff +__pycache__/ diff --git a/qasm/test/test_circuits/bell_phi_min.qasm b/qasm/test/test_circuits/bell_phi_min.qasm new file mode 100644 index 0000000..cf560d8 --- /dev/null +++ b/qasm/test/test_circuits/bell_phi_min.qasm @@ -0,0 +1,13 @@ +OPENQASM 2.0; +include "qelib1.inc"; + +qreg q[2]; +creg c[2]; + +h q[0]; +cx q[0], q[1]; +x q[0]; +z q[1]; + +measure q[0]->c[0]; +measure q[1]->c[1]; diff --git a/qasm/test/test_circuits/bell_phi_plus.qasm b/qasm/test/test_circuits/bell_phi_plus.qasm new file mode 100644 index 0000000..006a2ba --- /dev/null +++ b/qasm/test/test_circuits/bell_phi_plus.qasm @@ -0,0 +1,12 @@ +OPENQASM 2.0; +include "qelib1.inc"; + +qreg q[2]; +creg c[2]; + +h q[0]; +cx q[0], q[1]; +x q[0]; + +measure q[0]->c[0]; +measure q[1]->c[1]; diff --git a/qasm/test/test_circuits/bell_psi_min.qasm b/qasm/test/test_circuits/bell_psi_min.qasm new file mode 100644 index 0000000..74f039f --- /dev/null +++ b/qasm/test/test_circuits/bell_psi_min.qasm @@ -0,0 +1,12 @@ +OPENQASM 2.0; +include "qelib1.inc"; + +qreg q[2]; +creg c[2]; + +h q[0]; +cx q[0], q[1]; +z q[1]; + +measure q[0]->c[0]; +measure q[1]->c[1]; diff --git a/qasm/test/test_circuits/bell_psi_plus.qasm b/qasm/test/test_circuits/bell_psi_plus.qasm new file mode 100644 index 0000000..a2fac2b --- /dev/null +++ b/qasm/test/test_circuits/bell_psi_plus.qasm @@ -0,0 +1,11 @@ +OPENQASM 2.0; +include "qelib1.inc"; + +qreg q[2]; +creg c[2]; + +h q[0]; +cx q[0], q[1]; + +measure q[0]->c[0]; +measure q[1]->c[1]; diff --git a/qasm/test/test_sim_qasm.py b/qasm/test/test_sim_qasm.py new file mode 100644 index 0000000..a8d9d63 --- /dev/null +++ b/qasm/test/test_sim_qasm.py @@ -0,0 +1,87 @@ +""" +Testing running sim_qasm from command line. +""" +import os +import subprocess +import json +import numpy as np + + +TOLERANCE = 1e-6 +SIM_QASM = './build/qasm/sim_qasm' +QASM_DIR = 'qasm/test/test_circuits/' + + +def fidelity(a, b): + """ + Compute the fidelity of two vectors. + """ + in_prod = np.dot(a.conj().T, b) + fidelity = (abs(in_prod))**2 + return fidelity + + +def get_vector(qasm_file : str): + """ + Simulate given quantum circuit and return state vector. + """ + output = subprocess.run([SIM_QASM, '--state-vector', qasm_file], + stdout=subprocess.PIPE) + data = json.loads(output.stdout) + vector = np.apply_along_axis(lambda args: [complex(*args)], 1, + data['state_vector']).flatten() + return vector + + +def test_bell_psi_plus(): + """ + Test |Psi+> = 1/sqrt(2)[1 0 0 1] + """ + qasm_file = os.path.join(QASM_DIR, 'bell_psi_plus.qasm') + vector = get_vector(qasm_file) + reference = np.array([1/np.sqrt(2) + 0j, + 0 + 0j, + 0 + 0j, + 1/np.sqrt(2) + 0j]) + assert abs(fidelity(vector, reference) - 1) < TOLERANCE + + +def test_bell_psi_min(): + """ + Test |Psi-> = 1/sqrt(2)[1 0 0 -1] + """ + qasm_file = os.path.join(QASM_DIR, 'bell_psi_min.qasm') + vector = get_vector(qasm_file) + reference = np.array([1/np.sqrt(2) + 0j, + 0 + 0j, + 0 + 0j, + -1/np.sqrt(2) + 0j]) + assert abs(fidelity(vector, reference) - 1) < TOLERANCE + + +def test_bell_phi_plus(): + """ + Test |Phi+> = 1/sqrt(2)[0 1 1 0] + """ + qasm_file = os.path.join(QASM_DIR, 'bell_phi_plus.qasm') + vector = get_vector(qasm_file) + reference = np.array([0 + 0j, + 1/np.sqrt(2) + 0j, + 1/np.sqrt(2) + 0j, + 0 + 0j]) + assert abs(fidelity(vector, reference) - 1) < TOLERANCE + + +def test_bell_phi_min(): + """ + Test |Phi-> = 1/sqrt(2)[0 1 -1 0] + """ + qasm_file = os.path.join(QASM_DIR, 'bell_phi_min.qasm') + vector = get_vector(qasm_file) + reference = np.array([0 + 0j, + 1/np.sqrt(2) + 0j, + -1/np.sqrt(2) + 0j, + 0 + 0j]) + assert abs(fidelity(vector, reference) - 1) < TOLERANCE + + From d031371dbb1e58325ab4e145bfe743693ebc4435 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Tue, 28 May 2024 11:36:46 +0200 Subject: [PATCH 08/37] fix ci workflow --- .github/workflows/cmake.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 2e8f5c9..01b0c97 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -48,13 +48,17 @@ jobs: # Execute tests defined by the CMake configuration. # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail run: ctest -C ${{env.BUILD_TYPE}} - - - name: Test CLI + + - name: Setup Python uses: actions/setup-python@v5 with: python-version: "3.10" + + - name: Install Python dependencies run: | python -m pip install --upgrade pip pip install numpy pip install pytest - pytest + + - name: Test CLI + run: pytest From 27b0e688749ffdc37fe44f35d56bb10b1223d462 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Tue, 28 May 2024 14:17:43 +0200 Subject: [PATCH 09/37] write warnings to stderr instead of stdout --- src/qsylvan_mtbdd_simulator.c | 8 +++----- src/qsylvan_simulator.c | 6 ++---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/qsylvan_mtbdd_simulator.c b/src/qsylvan_mtbdd_simulator.c index e01ceb5..c04c0ba 100644 --- a/src/qsylvan_mtbdd_simulator.c +++ b/src/qsylvan_mtbdd_simulator.c @@ -863,8 +863,7 @@ qmdd_measure_q0(QMDD qmdd, BDDVAR nvars, int *m, double *p) prob_low *= prob_root; prob_high *= prob_root; if (fabs(prob_low + prob_high - 1.0) > 1e-6) { - printf("WARNING: prob sum = %.10lf (%.5lf + %.5lf)\n", prob_low + prob_high, prob_low, prob_high); - //assert("probabilities don't sum to 1" && false); + fprintf(stderr, "WARNING: prob sum = %.14lf\n", prob_low + prob_high); } // flip a coin @@ -929,9 +928,8 @@ qmdd_measure_all(QMDD qmdd, BDDVAR n, bool* ms, double *p) prob_high = prob_high * prob_roots / prob_path; prob_low = prob_low * prob_roots / prob_path; - if (fabs(prob_low + prob_high - 1.0) > sylvan_edge_weights_tolerance()) { - printf("prob sum = %.10lf\n", prob_low + prob_high); - // printf("probabilities don't sum to 1" && false); + if (fabs(prob_low + prob_high - 1.0) > 1e-6) { + fprintf(stderr, "WARNING: prob sum = %.14lf\n", prob_low + prob_high); } // flip a coin diff --git a/src/qsylvan_simulator.c b/src/qsylvan_simulator.c index 0cf98eb..a9d737d 100644 --- a/src/qsylvan_simulator.c +++ b/src/qsylvan_simulator.c @@ -839,8 +839,7 @@ qmdd_measure_q0(QMDD qmdd, BDDVAR nvars, int *m, double *p) prob_low *= prob_root; prob_high *= prob_root; if (fabs(prob_low + prob_high - 1.0) > 1e-6) { - printf("WARNING: prob sum = %.10lf (%.5lf + %.5lf)\n", prob_low + prob_high, prob_low, prob_high); - //assert("probabilities don't sum to 1" && false); + fprintf(stderr, "WARNING: prob sum = %.14lf\n", prob_low + prob_high); } // flip a coin @@ -906,8 +905,7 @@ qmdd_measure_all(QMDD qmdd, BDDVAR n, bool* ms, double *p) prob_low = prob_low * prob_roots / prob_path; if (fabs(prob_low + prob_high - 1.0) > sylvan_edge_weights_tolerance()) { - printf("prob sum = %.10lf\n", prob_low + prob_high); - // printf("probabilities don't sum to 1" && false); + fprintf(stderr, "WARNING: prob sum = %.14lf\n", prob_low + prob_high); } // flip a coin From e07f4a5964b8410290477143db60e3bea5fc047e Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Tue, 28 May 2024 14:39:44 +0200 Subject: [PATCH 10/37] CI test cases for sim_qasm --- qasm/circuits/adder_n4.qasm | 31 + qasm/circuits/basis_change_n3.qasm | 49 + qasm/circuits/dnn_n8.qasm | 1174 ++++++++++++++++++++ qasm/circuits/fredkin_n3.qasm | 26 + qasm/circuits/ghz_n4.qasm | 14 + qasm/circuits/ghz_n8.qasm | 21 + qasm/circuits/qaoa_n3.qasm | 32 + qasm/circuits/qft_n4.qasm | 18 + qasm/circuits/simon_n6.qasm | 38 + qasm/circuits/vqe_n4.qasm | 98 ++ qasm/circuits/wstate_n3.qasm | 30 + qasm/test/compute_reference_state.py | 22 + qasm/test/test_circuits/bell_phi_min.qasm | 13 - qasm/test/test_circuits/bell_phi_plus.qasm | 12 - qasm/test/test_circuits/bell_psi_min.qasm | 12 - qasm/test/test_circuits/bell_psi_plus.qasm | 11 - qasm/test/test_sim_qasm.py | 376 ++++++- 17 files changed, 1891 insertions(+), 86 deletions(-) create mode 100644 qasm/circuits/adder_n4.qasm create mode 100644 qasm/circuits/basis_change_n3.qasm create mode 100644 qasm/circuits/dnn_n8.qasm create mode 100644 qasm/circuits/fredkin_n3.qasm create mode 100644 qasm/circuits/ghz_n4.qasm create mode 100644 qasm/circuits/ghz_n8.qasm create mode 100644 qasm/circuits/qaoa_n3.qasm create mode 100644 qasm/circuits/qft_n4.qasm create mode 100644 qasm/circuits/simon_n6.qasm create mode 100644 qasm/circuits/vqe_n4.qasm create mode 100644 qasm/circuits/wstate_n3.qasm create mode 100644 qasm/test/compute_reference_state.py delete mode 100644 qasm/test/test_circuits/bell_phi_min.qasm delete mode 100644 qasm/test/test_circuits/bell_phi_plus.qasm delete mode 100644 qasm/test/test_circuits/bell_psi_min.qasm delete mode 100644 qasm/test/test_circuits/bell_psi_plus.qasm diff --git a/qasm/circuits/adder_n4.qasm b/qasm/circuits/adder_n4.qasm new file mode 100644 index 0000000..895cf11 --- /dev/null +++ b/qasm/circuits/adder_n4.qasm @@ -0,0 +1,31 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[4]; +creg c[4]; +x q[0]; +x q[1]; +h q[3]; +cx q[2],q[3]; +t q[0]; +t q[1]; +t q[2]; +tdg q[3]; +cx q[0],q[1]; +cx q[2],q[3]; +cx q[3],q[0]; +cx q[1],q[2]; +cx q[0],q[1]; +cx q[2],q[3]; +tdg q[0]; +tdg q[1]; +tdg q[2]; +t q[3]; +cx q[0],q[1]; +cx q[2],q[3]; +s q[3]; +cx q[3],q[0]; +h q[3]; +measure q[0] -> c[0]; +measure q[1] -> c[1]; +measure q[2] -> c[2]; +measure q[3] -> c[3]; diff --git a/qasm/circuits/basis_change_n3.qasm b/qasm/circuits/basis_change_n3.qasm new file mode 100644 index 0000000..5a5e597 --- /dev/null +++ b/qasm/circuits/basis_change_n3.qasm @@ -0,0 +1,49 @@ +// Generated from Cirq v0.8.0 + +OPENQASM 2.0; +include "qelib1.inc"; + + +// Qubits: [0, 1, 2] +qreg q[3]; +creg c[3]; + + +u3(pi*0.5,0,pi*0.0564006755) q[2]; +u3(pi*0.5,pi*1.5,pi*0.2945501109) q[1]; +u3(pi*0.5,pi*1.5,pi*1.5) q[0]; +cz q[1],q[2]; +u3(pi*0.1242949803,0,0) q[2]; +u3(pi*0.1242949803,pi*0.5,pi*1.5) q[1]; +cz q[1],q[2]; +u3(pi*0.0298311566,pi*1.5,pi*0.5) q[2]; +u3(pi*0.7273849664,pi*1.5,pi*1.0) q[1]; +cz q[0],q[1]; +u3(pi*0.328242091,0,0) q[1]; +u3(pi*0.328242091,pi*0.5,pi*1.5) q[0]; +cz q[0],q[1]; +u3(pi*0.1374475291,pi*2.0,pi*1.5) q[1]; +u3(pi*0.9766098537,0,0) q[0]; +cz q[1],q[2]; +u3(pi*0.2326621647,0,0) q[2]; +u3(pi*0.2326621647,pi*0.5,pi*1.5) q[1]; +cz q[1],q[2]; +u3(pi*0.5780153762,pi*0.5,pi*0.5) q[2]; +u3(pi*0.6257049652,pi*0.5,0) q[1]; +cz q[0],q[1]; +u3(pi*0.328242091,0,0) q[1]; +u3(pi*0.328242091,pi*0.5,pi*1.5) q[0]; +cz q[0],q[1]; +u3(pi*0.6817377913,0,pi*0.5) q[1]; +u3(pi*0.5,pi*0.3593182384,pi*1.5) q[0]; +cz q[1],q[2]; +u3(pi*0.1242949803,0,0) q[2]; +u3(pi*0.1242949803,pi*0.5,pi*1.5) q[1]; +cz q[1],q[2]; +u3(pi*0.5,pi*1.3937948052,0) q[2]; +u3(pi*0.5,pi*1.1556453697,pi*0.5) q[1]; + +measure q[0] -> c[0]; +measure q[1] -> c[1]; +measure q[2] -> c[2]; + diff --git a/qasm/circuits/dnn_n8.qasm b/qasm/circuits/dnn_n8.qasm new file mode 100644 index 0000000..f25d5d1 --- /dev/null +++ b/qasm/circuits/dnn_n8.qasm @@ -0,0 +1,1174 @@ +// EIGHT QUBIT DEEP ( 16 dimensions ) +// Generated from Cirq v0.8.0 + +OPENQASM 2.0; +include "qelib1.inc"; + +// Qubits: [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7)] +qreg q[8]; +creg ans[8]; + +rx(pi*0.3501408748) q[0]; +ry(pi*0.3501408748) q[0]; +rz(pi*0.3501408748) q[0]; +rx(pi*0.3501408748) q[1]; +ry(pi*0.3501408748) q[1]; +rz(pi*0.3501408748) q[1]; + +// Gate: ZZ**1.1 +rz(pi*1.1) q[0]; +rz(pi*1.1) q[1]; +u3(pi*0.5,0,pi*0.25) q[0]; +u3(pi*0.5,pi*1.0,pi*0.75) q[1]; +rx(pi*0.5) q[0]; +cx q[0],q[1]; +rx(pi*0.4) q[0]; +ry(pi*0.5) q[1]; +cx q[1],q[0]; +rx(pi*-0.5) q[1]; +rz(pi*0.5) q[1]; +cx q[0],q[1]; +u3(pi*0.5,pi*0.65,pi*1.0) q[0]; +u3(pi*0.5,pi*0.15,0) q[1]; + +// Gate: YY**1.1 +u3(0,pi*1.0,pi*0.5) q[0]; +u3(0,0,pi*0.5) q[1]; +rx(pi*0.5) q[0]; +cx q[0],q[1]; +rx(pi*0.4) q[0]; +ry(pi*0.5) q[1]; +cx q[1],q[0]; +rx(pi*-0.5) q[1]; +rz(pi*0.5) q[1]; +cx q[0],q[1]; +u3(pi*1.0,0,pi*0.5) q[0]; +u3(pi*1.0,0,pi*1.5) q[1]; + +// Gate: XX**1.1 +u3(pi*0.5,pi*1.5,pi*1.5) q[0]; +u3(pi*0.5,pi*0.5,pi*1.5) q[1]; +rx(pi*0.5) q[0]; +cx q[0],q[1]; +rx(pi*0.4) q[0]; +ry(pi*0.5) q[1]; +cx q[1],q[0]; +rx(pi*-0.5) q[1]; +rz(pi*0.5) q[1]; +cx q[0],q[1]; +u3(pi*0.5,pi*0.5,pi*0.5) q[0]; +u3(pi*0.5,pi*0.5,pi*1.5) q[1]; + +rx(pi*0.3501408748) q[0]; +ry(pi*0.3501408748) q[0]; +rz(pi*0.3501408748) q[0]; +rx(pi*0.3501408748) q[1]; +ry(pi*0.3501408748) q[1]; +rz(pi*0.3501408748) q[1]; +rx(pi*0.3501408748) q[2]; +ry(pi*0.3501408748) q[2]; +rz(pi*0.3501408748) q[2]; +rx(pi*0.3501408748) q[3]; +ry(pi*0.3501408748) q[3]; +rz(pi*0.3501408748) q[3]; + +// Gate: ZZ**1.1 +rz(pi*1.1) q[2]; +rz(pi*1.1) q[3]; +u3(pi*0.5,0,pi*0.25) q[2]; +u3(pi*0.5,pi*1.0,pi*0.75) q[3]; +rx(pi*0.5) q[2]; +cx q[2],q[3]; +rx(pi*0.4) q[2]; +ry(pi*0.5) q[3]; +cx q[3],q[2]; +rx(pi*-0.5) q[3]; +rz(pi*0.5) q[3]; +cx q[2],q[3]; +u3(pi*0.5,pi*0.65,pi*1.0) q[2]; +u3(pi*0.5,pi*0.15,0) q[3]; + +// Gate: YY**1.1 +u3(0,pi*1.0,pi*0.5) q[2]; +u3(0,0,pi*0.5) q[3]; +rx(pi*0.5) q[2]; +cx q[2],q[3]; +rx(pi*0.4) q[2]; +ry(pi*0.5) q[3]; +cx q[3],q[2]; +rx(pi*-0.5) q[3]; +rz(pi*0.5) q[3]; +cx q[2],q[3]; +u3(pi*1.0,0,pi*0.5) q[2]; +u3(pi*1.0,0,pi*1.5) q[3]; + +// Gate: XX**1.1 +u3(pi*0.5,pi*1.5,pi*1.5) q[2]; +u3(pi*0.5,pi*0.5,pi*1.5) q[3]; +rx(pi*0.5) q[2]; +cx q[2],q[3]; +rx(pi*0.4) q[2]; +ry(pi*0.5) q[3]; +cx q[3],q[2]; +rx(pi*-0.5) q[3]; +rz(pi*0.5) q[3]; +cx q[2],q[3]; +u3(pi*0.5,pi*0.5,pi*0.5) q[2]; +u3(pi*0.5,pi*0.5,pi*1.5) q[3]; + +rx(pi*0.3501408748) q[2]; +ry(pi*0.3501408748) q[2]; +rz(pi*0.3501408748) q[2]; +rx(pi*0.3501408748) q[3]; +ry(pi*0.3501408748) q[3]; +rz(pi*0.3501408748) q[3]; +rx(pi*0.3501408748) q[4]; +ry(pi*0.3501408748) q[4]; +rz(pi*0.3501408748) q[4]; +rx(pi*0.3501408748) q[5]; +ry(pi*0.3501408748) q[5]; +rz(pi*0.3501408748) q[5]; + +// Gate: ZZ**1.1 +rz(pi*1.1) q[4]; +rz(pi*1.1) q[5]; +u3(pi*0.5,0,pi*0.25) q[4]; +u3(pi*0.5,pi*1.0,pi*0.75) q[5]; +rx(pi*0.5) q[4]; +cx q[4],q[5]; +rx(pi*0.4) q[4]; +ry(pi*0.5) q[5]; +cx q[5],q[4]; +rx(pi*-0.5) q[5]; +rz(pi*0.5) q[5]; +cx q[4],q[5]; +u3(pi*0.5,pi*0.65,pi*1.0) q[4]; +u3(pi*0.5,pi*0.15,0) q[5]; + +// Gate: YY**1.1 +u3(0,pi*1.0,pi*0.5) q[4]; +u3(0,0,pi*0.5) q[5]; +rx(pi*0.5) q[4]; +cx q[4],q[5]; +rx(pi*0.4) q[4]; +ry(pi*0.5) q[5]; +cx q[5],q[4]; +rx(pi*-0.5) q[5]; +rz(pi*0.5) q[5]; +cx q[4],q[5]; +u3(pi*1.0,0,pi*0.5) q[4]; +u3(pi*1.0,0,pi*1.5) q[5]; + +// Gate: XX**1.1 +u3(pi*0.5,pi*1.5,pi*1.5) q[4]; +u3(pi*0.5,pi*0.5,pi*1.5) q[5]; +rx(pi*0.5) q[4]; +cx q[4],q[5]; +rx(pi*0.4) q[4]; +ry(pi*0.5) q[5]; +cx q[5],q[4]; +rx(pi*-0.5) q[5]; +rz(pi*0.5) q[5]; +cx q[4],q[5]; +u3(pi*0.5,pi*0.5,pi*0.5) q[4]; +u3(pi*0.5,pi*0.5,pi*1.5) q[5]; + +rx(pi*0.3501408748) q[4]; +ry(pi*0.3501408748) q[4]; +rz(pi*0.3501408748) q[4]; +rx(pi*0.3501408748) q[5]; +ry(pi*0.3501408748) q[5]; +rz(pi*0.3501408748) q[5]; +rx(pi*0.3501408748) q[6]; +ry(pi*0.3501408748) q[6]; +rz(pi*0.3501408748) q[6]; +rx(pi*0.3501408748) q[7]; +ry(pi*0.3501408748) q[7]; +rz(pi*0.3501408748) q[7]; + +// Gate: ZZ**1.1 +rz(pi*1.1) q[6]; +rz(pi*1.1) q[7]; +u3(pi*0.5,0,pi*0.25) q[6]; +u3(pi*0.5,pi*1.0,pi*0.75) q[7]; +rx(pi*0.5) q[6]; +cx q[6],q[7]; +rx(pi*0.4) q[6]; +ry(pi*0.5) q[7]; +cx q[7],q[6]; +rx(pi*-0.5) q[7]; +rz(pi*0.5) q[7]; +cx q[6],q[7]; +u3(pi*0.5,pi*0.65,pi*1.0) q[6]; +u3(pi*0.5,pi*0.15,0) q[7]; + +// Gate: YY**1.1 +u3(0,pi*1.0,pi*0.5) q[6]; +u3(0,0,pi*0.5) q[7]; +rx(pi*0.5) q[6]; +cx q[6],q[7]; +rx(pi*0.4) q[6]; +ry(pi*0.5) q[7]; +cx q[7],q[6]; +rx(pi*-0.5) q[7]; +rz(pi*0.5) q[7]; +cx q[6],q[7]; +u3(pi*1.0,0,pi*0.5) q[6]; +u3(pi*1.0,0,pi*1.5) q[7]; + +// Gate: XX**1.1 +u3(pi*0.5,pi*1.5,pi*1.5) q[6]; +u3(pi*0.5,pi*0.5,pi*1.5) q[7]; +rx(pi*0.5) q[6]; +cx q[6],q[7]; +rx(pi*0.4) q[6]; +ry(pi*0.5) q[7]; +cx q[7],q[6]; +rx(pi*-0.5) q[7]; +rz(pi*0.5) q[7]; +cx q[6],q[7]; +u3(pi*0.5,pi*0.5,pi*0.5) q[6]; +u3(pi*0.5,pi*0.5,pi*1.5) q[7]; + +rx(pi*0.3501408748) q[6]; +ry(pi*0.3501408748) q[6]; +rz(pi*0.3501408748) q[6]; +rx(pi*0.3501408748) q[7]; +ry(pi*0.3501408748) q[7]; +rz(pi*0.3501408748) q[7]; +rx(pi*0.3501408748) q[1]; +ry(pi*0.3501408748) q[1]; +rz(pi*0.3501408748) q[1]; +rx(pi*0.3501408748) q[2]; +ry(pi*0.3501408748) q[2]; +rz(pi*0.3501408748) q[2]; + +// Gate: ZZ**1.1 +rz(pi*1.1) q[1]; +rz(pi*1.1) q[2]; +u3(pi*0.5,0,pi*0.25) q[1]; +u3(pi*0.5,pi*1.0,pi*0.75) q[2]; +rx(pi*0.5) q[1]; +cx q[1],q[2]; +rx(pi*0.4) q[1]; +ry(pi*0.5) q[2]; +cx q[2],q[1]; +rx(pi*-0.5) q[2]; +rz(pi*0.5) q[2]; +cx q[1],q[2]; +u3(pi*0.5,pi*0.65,pi*1.0) q[1]; +u3(pi*0.5,pi*0.15,0) q[2]; + +// Gate: YY**1.1 +u3(0,pi*1.0,pi*0.5) q[1]; +u3(0,0,pi*0.5) q[2]; +rx(pi*0.5) q[1]; +cx q[1],q[2]; +rx(pi*0.4) q[1]; +ry(pi*0.5) q[2]; +cx q[2],q[1]; +rx(pi*-0.5) q[2]; +rz(pi*0.5) q[2]; +cx q[1],q[2]; +u3(pi*1.0,0,pi*0.5) q[1]; +u3(pi*1.0,0,pi*1.5) q[2]; + +// Gate: XX**1.1 +u3(pi*0.5,pi*1.5,pi*1.5) q[1]; +u3(pi*0.5,pi*0.5,pi*1.5) q[2]; +rx(pi*0.5) q[1]; +cx q[1],q[2]; +rx(pi*0.4) q[1]; +ry(pi*0.5) q[2]; +cx q[2],q[1]; +rx(pi*-0.5) q[2]; +rz(pi*0.5) q[2]; +cx q[1],q[2]; +u3(pi*0.5,pi*0.5,pi*0.5) q[1]; +u3(pi*0.5,pi*0.5,pi*1.5) q[2]; + +rx(pi*0.3501408748) q[1]; +ry(pi*0.3501408748) q[1]; +rz(pi*0.3501408748) q[1]; +rx(pi*0.3501408748) q[2]; +ry(pi*0.3501408748) q[2]; +rz(pi*0.3501408748) q[2]; +rx(pi*0.3501408748) q[3]; +ry(pi*0.3501408748) q[3]; +rz(pi*0.3501408748) q[3]; +rx(pi*0.3501408748) q[4]; +ry(pi*0.3501408748) q[4]; +rz(pi*0.3501408748) q[4]; + +// Gate: ZZ**1.1 +rz(pi*1.1) q[3]; +rz(pi*1.1) q[4]; +u3(pi*0.5,0,pi*0.25) q[3]; +u3(pi*0.5,pi*1.0,pi*0.75) q[4]; +rx(pi*0.5) q[3]; +cx q[3],q[4]; +rx(pi*0.4) q[3]; +ry(pi*0.5) q[4]; +cx q[4],q[3]; +rx(pi*-0.5) q[4]; +rz(pi*0.5) q[4]; +cx q[3],q[4]; +u3(pi*0.5,pi*0.65,pi*1.0) q[3]; +u3(pi*0.5,pi*0.15,0) q[4]; + +// Gate: YY**1.1 +u3(0,pi*1.0,pi*0.5) q[3]; +u3(0,0,pi*0.5) q[4]; +rx(pi*0.5) q[3]; +cx q[3],q[4]; +rx(pi*0.4) q[3]; +ry(pi*0.5) q[4]; +cx q[4],q[3]; +rx(pi*-0.5) q[4]; +rz(pi*0.5) q[4]; +cx q[3],q[4]; +u3(pi*1.0,0,pi*0.5) q[3]; +u3(pi*1.0,0,pi*1.5) q[4]; + +// Gate: XX**1.1 +u3(pi*0.5,pi*1.5,pi*1.5) q[3]; +u3(pi*0.5,pi*0.5,pi*1.5) q[4]; +rx(pi*0.5) q[3]; +cx q[3],q[4]; +rx(pi*0.4) q[3]; +ry(pi*0.5) q[4]; +cx q[4],q[3]; +rx(pi*-0.5) q[4]; +rz(pi*0.5) q[4]; +cx q[3],q[4]; +u3(pi*0.5,pi*0.5,pi*0.5) q[3]; +u3(pi*0.5,pi*0.5,pi*1.5) q[4]; + +rx(pi*0.3501408748) q[3]; +ry(pi*0.3501408748) q[3]; +rz(pi*0.3501408748) q[3]; +rx(pi*0.3501408748) q[4]; +ry(pi*0.3501408748) q[4]; +rz(pi*0.3501408748) q[4]; +rx(pi*0.3501408748) q[5]; +ry(pi*0.3501408748) q[5]; +rz(pi*0.3501408748) q[5]; +rx(pi*0.3501408748) q[6]; +ry(pi*0.3501408748) q[6]; +rz(pi*0.3501408748) q[6]; + +// Gate: ZZ**1.1 +rz(pi*1.1) q[5]; +rz(pi*1.1) q[6]; +u3(pi*0.5,0,pi*0.25) q[5]; +u3(pi*0.5,pi*1.0,pi*0.75) q[6]; +rx(pi*0.5) q[5]; +cx q[5],q[6]; +rx(pi*0.4) q[5]; +ry(pi*0.5) q[6]; +cx q[6],q[5]; +rx(pi*-0.5) q[6]; +rz(pi*0.5) q[6]; +cx q[5],q[6]; +u3(pi*0.5,pi*0.65,pi*1.0) q[5]; +u3(pi*0.5,pi*0.15,0) q[6]; + +// Gate: YY**1.1 +u3(0,pi*1.0,pi*0.5) q[5]; +u3(0,0,pi*0.5) q[6]; +rx(pi*0.5) q[5]; +cx q[5],q[6]; +rx(pi*0.4) q[5]; +ry(pi*0.5) q[6]; +cx q[6],q[5]; +rx(pi*-0.5) q[6]; +rz(pi*0.5) q[6]; +cx q[5],q[6]; +u3(pi*1.0,0,pi*0.5) q[5]; +u3(pi*1.0,0,pi*1.5) q[6]; + +// Gate: XX**1.1 +u3(pi*0.5,pi*1.5,pi*1.5) q[5]; +u3(pi*0.5,pi*0.5,pi*1.5) q[6]; +rx(pi*0.5) q[5]; +cx q[5],q[6]; +rx(pi*0.4) q[5]; +ry(pi*0.5) q[6]; +cx q[6],q[5]; +rx(pi*-0.5) q[6]; +rz(pi*0.5) q[6]; +cx q[5],q[6]; +u3(pi*0.5,pi*0.5,pi*0.5) q[5]; +u3(pi*0.5,pi*0.5,pi*1.5) q[6]; + +rx(pi*0.3501408748) q[5]; +ry(pi*0.3501408748) q[5]; +rz(pi*0.3501408748) q[5]; +rx(pi*0.3501408748) q[6]; +ry(pi*0.3501408748) q[6]; +rz(pi*0.3501408748) q[6]; +rx(pi*0.3501408748) q[7]; +ry(pi*0.3501408748) q[7]; +rz(pi*0.3501408748) q[7]; +rx(pi*0.3501408748) q[0]; +ry(pi*0.3501408748) q[0]; +rz(pi*0.3501408748) q[0]; + +// Gate: ZZ**1.1 +rz(pi*1.1) q[7]; +rz(pi*1.1) q[0]; +u3(pi*0.5,0,pi*0.25) q[7]; +u3(pi*0.5,pi*1.0,pi*0.75) q[0]; +rx(pi*0.5) q[7]; +cx q[7],q[0]; +rx(pi*0.4) q[7]; +ry(pi*0.5) q[0]; +cx q[0],q[7]; +rx(pi*-0.5) q[0]; +rz(pi*0.5) q[0]; +cx q[7],q[0]; +u3(pi*0.5,pi*0.65,pi*1.0) q[7]; +u3(pi*0.5,pi*0.15,0) q[0]; + +// Gate: YY**1.1 +u3(0,pi*1.0,pi*0.5) q[7]; +u3(0,0,pi*0.5) q[0]; +rx(pi*0.5) q[7]; +cx q[7],q[0]; +rx(pi*0.4) q[7]; +ry(pi*0.5) q[0]; +cx q[0],q[7]; +rx(pi*-0.5) q[0]; +rz(pi*0.5) q[0]; +cx q[7],q[0]; +u3(pi*1.0,0,pi*0.5) q[7]; +u3(pi*1.0,0,pi*1.5) q[0]; + +// Gate: XX**1.1 +u3(pi*0.5,pi*1.5,pi*1.5) q[7]; +u3(pi*0.5,pi*0.5,pi*1.5) q[0]; +rx(pi*0.5) q[7]; +cx q[7],q[0]; +rx(pi*0.4) q[7]; +ry(pi*0.5) q[0]; +cx q[0],q[7]; +rx(pi*-0.5) q[0]; +rz(pi*0.5) q[0]; +cx q[7],q[0]; +u3(pi*0.5,pi*0.5,pi*0.5) q[7]; +u3(pi*0.5,pi*0.5,pi*1.5) q[0]; + +rx(pi*0.3501408748) q[7]; +ry(pi*0.3501408748) q[7]; +rz(pi*0.3501408748) q[7]; +rx(pi*0.3501408748) q[0]; +ry(pi*0.3501408748) q[0]; +rz(pi*0.3501408748) q[0]; + +// Gate: CNOT**1.1 +ry(pi*-0.5) q[1]; +u3(pi*0.5,0,pi*0.25) q[0]; +u3(pi*0.5,pi*1.0,pi*0.75) q[1]; +rx(pi*0.5) q[0]; +cx q[0],q[1]; +rx(pi*0.05) q[0]; +ry(pi*0.5) q[1]; +cx q[1],q[0]; +rx(pi*-0.5) q[1]; +rz(pi*0.5) q[1]; +cx q[0],q[1]; +u3(pi*0.5,pi*0.3,pi*1.0) q[0]; +u3(pi*0.5,pi*1.8,0) q[1]; +ry(pi*0.5) q[1]; + +// Gate: CNOT**1.1 +ry(pi*-0.5) q[3]; +u3(pi*0.5,0,pi*0.25) q[2]; +u3(pi*0.5,pi*1.0,pi*0.75) q[3]; +rx(pi*0.5) q[2]; +cx q[2],q[3]; +rx(pi*0.05) q[2]; +ry(pi*0.5) q[3]; +cx q[3],q[2]; +rx(pi*-0.5) q[3]; +rz(pi*0.5) q[3]; +cx q[2],q[3]; +u3(pi*0.5,pi*0.3,pi*1.0) q[2]; +u3(pi*0.5,pi*1.8,0) q[3]; +ry(pi*0.5) q[3]; + +// Gate: CNOT**1.1 +ry(pi*-0.5) q[5]; +u3(pi*0.5,0,pi*0.25) q[4]; +u3(pi*0.5,pi*1.0,pi*0.75) q[5]; +rx(pi*0.5) q[4]; +cx q[4],q[5]; +rx(pi*0.05) q[4]; +ry(pi*0.5) q[5]; +cx q[5],q[4]; +rx(pi*-0.5) q[5]; +rz(pi*0.5) q[5]; +cx q[4],q[5]; +u3(pi*0.5,pi*0.3,pi*1.0) q[4]; +u3(pi*0.5,pi*1.8,0) q[5]; +ry(pi*0.5) q[5]; + +// Gate: CNOT**1.1 +ry(pi*-0.5) q[7]; +u3(pi*0.5,0,pi*0.25) q[6]; +u3(pi*0.5,pi*1.0,pi*0.75) q[7]; +rx(pi*0.5) q[6]; +cx q[6],q[7]; +rx(pi*0.05) q[6]; +ry(pi*0.5) q[7]; +cx q[7],q[6]; +rx(pi*-0.5) q[7]; +rz(pi*0.5) q[7]; +cx q[6],q[7]; +u3(pi*0.5,pi*0.3,pi*1.0) q[6]; +u3(pi*0.5,pi*1.8,0) q[7]; +ry(pi*0.5) q[7]; + +// Gate: CZ**1.1 +u3(pi*0.5,0,pi*0.25) q[0]; +u3(pi*0.5,pi*1.0,pi*0.75) q[1]; +rx(pi*0.5) q[0]; +cx q[0],q[1]; +rx(pi*0.05) q[0]; +ry(pi*0.5) q[1]; +cx q[1],q[0]; +rx(pi*-0.5) q[1]; +rz(pi*0.5) q[1]; +cx q[0],q[1]; +u3(pi*0.5,pi*0.3,pi*1.0) q[0]; +u3(pi*0.5,pi*1.8,0) q[1]; + +// Gate: CZ**1.1 +u3(pi*0.5,0,pi*0.25) q[2]; +u3(pi*0.5,pi*1.0,pi*0.75) q[3]; +rx(pi*0.5) q[2]; +cx q[2],q[3]; +rx(pi*0.05) q[2]; +ry(pi*0.5) q[3]; +cx q[3],q[2]; +rx(pi*-0.5) q[3]; +rz(pi*0.5) q[3]; +cx q[2],q[3]; +u3(pi*0.5,pi*0.3,pi*1.0) q[2]; +u3(pi*0.5,pi*1.8,0) q[3]; + +// Gate: CZ**1.1 +u3(pi*0.5,0,pi*0.25) q[4]; +u3(pi*0.5,pi*1.0,pi*0.75) q[5]; +rx(pi*0.5) q[4]; +cx q[4],q[5]; +rx(pi*0.05) q[4]; +ry(pi*0.5) q[5]; +cx q[5],q[4]; +rx(pi*-0.5) q[5]; +rz(pi*0.5) q[5]; +cx q[4],q[5]; +u3(pi*0.5,pi*0.3,pi*1.0) q[4]; +u3(pi*0.5,pi*1.8,0) q[5]; + +// Gate: CZ**1.1 +u3(pi*0.5,0,pi*0.25) q[6]; +u3(pi*0.5,pi*1.0,pi*0.75) q[7]; +rx(pi*0.5) q[6]; +cx q[6],q[7]; +rx(pi*0.05) q[6]; +ry(pi*0.5) q[7]; +cx q[7],q[6]; +rx(pi*-0.5) q[7]; +rz(pi*0.5) q[7]; +cx q[6],q[7]; +u3(pi*0.5,pi*0.3,pi*1.0) q[6]; +u3(pi*0.5,pi*1.8,0) q[7]; + +// Gate: CNOT**1.1 +ry(pi*-0.5) q[2]; +u3(pi*0.5,0,pi*0.25) q[1]; +u3(pi*0.5,pi*1.0,pi*0.75) q[2]; +rx(pi*0.5) q[1]; +cx q[1],q[2]; +rx(pi*0.05) q[1]; +ry(pi*0.5) q[2]; +cx q[2],q[1]; +rx(pi*-0.5) q[2]; +rz(pi*0.5) q[2]; +cx q[1],q[2]; +u3(pi*0.5,pi*0.3,pi*1.0) q[1]; +u3(pi*0.5,pi*1.8,0) q[2]; +ry(pi*0.5) q[2]; + +// Gate: CNOT**1.1 +ry(pi*-0.5) q[4]; +u3(pi*0.5,0,pi*0.25) q[3]; +u3(pi*0.5,pi*1.0,pi*0.75) q[4]; +rx(pi*0.5) q[3]; +cx q[3],q[4]; +rx(pi*0.05) q[3]; +ry(pi*0.5) q[4]; +cx q[4],q[3]; +rx(pi*-0.5) q[4]; +rz(pi*0.5) q[4]; +cx q[3],q[4]; +u3(pi*0.5,pi*0.3,pi*1.0) q[3]; +u3(pi*0.5,pi*1.8,0) q[4]; +ry(pi*0.5) q[4]; + +// Gate: CNOT**1.1 +ry(pi*-0.5) q[6]; +u3(pi*0.5,0,pi*0.25) q[5]; +u3(pi*0.5,pi*1.0,pi*0.75) q[6]; +rx(pi*0.5) q[5]; +cx q[5],q[6]; +rx(pi*0.05) q[5]; +ry(pi*0.5) q[6]; +cx q[6],q[5]; +rx(pi*-0.5) q[6]; +rz(pi*0.5) q[6]; +cx q[5],q[6]; +u3(pi*0.5,pi*0.3,pi*1.0) q[5]; +u3(pi*0.5,pi*1.8,0) q[6]; +ry(pi*0.5) q[6]; + +// Gate: CNOT**1.1 +ry(pi*-0.5) q[0]; +u3(pi*0.5,0,pi*0.25) q[7]; +u3(pi*0.5,pi*1.0,pi*0.75) q[0]; +rx(pi*0.5) q[7]; +cx q[7],q[0]; +rx(pi*0.05) q[7]; +ry(pi*0.5) q[0]; +cx q[0],q[7]; +rx(pi*-0.5) q[0]; +rz(pi*0.5) q[0]; +cx q[7],q[0]; +u3(pi*0.5,pi*0.3,pi*1.0) q[7]; +u3(pi*0.5,pi*1.8,0) q[0]; +ry(pi*0.5) q[0]; + +// Gate: CZ**1.1 +u3(pi*0.5,0,pi*0.25) q[1]; +u3(pi*0.5,pi*1.0,pi*0.75) q[2]; +rx(pi*0.5) q[1]; +cx q[1],q[2]; +rx(pi*0.05) q[1]; +ry(pi*0.5) q[2]; +cx q[2],q[1]; +rx(pi*-0.5) q[2]; +rz(pi*0.5) q[2]; +cx q[1],q[2]; +u3(pi*0.5,pi*0.3,pi*1.0) q[1]; +u3(pi*0.5,pi*1.8,0) q[2]; + +// Gate: CZ**1.1 +u3(pi*0.5,0,pi*0.25) q[3]; +u3(pi*0.5,pi*1.0,pi*0.75) q[4]; +rx(pi*0.5) q[3]; +cx q[3],q[4]; +rx(pi*0.05) q[3]; +ry(pi*0.5) q[4]; +cx q[4],q[3]; +rx(pi*-0.5) q[4]; +rz(pi*0.5) q[4]; +cx q[3],q[4]; +u3(pi*0.5,pi*0.3,pi*1.0) q[3]; +u3(pi*0.5,pi*1.8,0) q[4]; + +// Gate: CZ**1.1 +u3(pi*0.5,0,pi*0.25) q[5]; +u3(pi*0.5,pi*1.0,pi*0.75) q[6]; +rx(pi*0.5) q[5]; +cx q[5],q[6]; +rx(pi*0.05) q[5]; +ry(pi*0.5) q[6]; +cx q[6],q[5]; +rx(pi*-0.5) q[6]; +rz(pi*0.5) q[6]; +cx q[5],q[6]; +u3(pi*0.5,pi*0.3,pi*1.0) q[5]; +u3(pi*0.5,pi*1.8,0) q[6]; + +// Gate: CZ**1.1 +u3(pi*0.5,0,pi*0.25) q[7]; +u3(pi*0.5,pi*1.0,pi*0.75) q[0]; +rx(pi*0.5) q[7]; +cx q[7],q[0]; +rx(pi*0.05) q[7]; +ry(pi*0.5) q[0]; +cx q[0],q[7]; +rx(pi*-0.5) q[0]; +rz(pi*0.5) q[0]; +cx q[7],q[0]; +u3(pi*0.5,pi*0.3,pi*1.0) q[7]; +u3(pi*0.5,pi*1.8,0) q[0]; + +rx(pi*0.3501408748) q[0]; +ry(pi*0.3501408748) q[0]; +rz(pi*0.3501408748) q[0]; +rx(pi*0.3501408748) q[1]; +ry(pi*0.3501408748) q[1]; +rz(pi*0.3501408748) q[1]; + +// Gate: ZZ**1.1 +rz(pi*1.1) q[0]; +rz(pi*1.1) q[1]; +u3(pi*0.5,0,pi*0.25) q[0]; +u3(pi*0.5,pi*1.0,pi*0.75) q[1]; +rx(pi*0.5) q[0]; +cx q[0],q[1]; +rx(pi*0.4) q[0]; +ry(pi*0.5) q[1]; +cx q[1],q[0]; +rx(pi*-0.5) q[1]; +rz(pi*0.5) q[1]; +cx q[0],q[1]; +u3(pi*0.5,pi*0.65,pi*1.0) q[0]; +u3(pi*0.5,pi*0.15,0) q[1]; + +// Gate: YY**1.1 +u3(0,pi*1.0,pi*0.5) q[0]; +u3(0,0,pi*0.5) q[1]; +rx(pi*0.5) q[0]; +cx q[0],q[1]; +rx(pi*0.4) q[0]; +ry(pi*0.5) q[1]; +cx q[1],q[0]; +rx(pi*-0.5) q[1]; +rz(pi*0.5) q[1]; +cx q[0],q[1]; +u3(pi*1.0,0,pi*0.5) q[0]; +u3(pi*1.0,0,pi*1.5) q[1]; + +// Gate: XX**1.1 +u3(pi*0.5,pi*1.5,pi*1.5) q[0]; +u3(pi*0.5,pi*0.5,pi*1.5) q[1]; +rx(pi*0.5) q[0]; +cx q[0],q[1]; +rx(pi*0.4) q[0]; +ry(pi*0.5) q[1]; +cx q[1],q[0]; +rx(pi*-0.5) q[1]; +rz(pi*0.5) q[1]; +cx q[0],q[1]; +u3(pi*0.5,pi*0.5,pi*0.5) q[0]; +u3(pi*0.5,pi*0.5,pi*1.5) q[1]; + +rx(pi*0.3501408748) q[0]; +ry(pi*0.3501408748) q[0]; +rz(pi*0.3501408748) q[0]; +rx(pi*0.3501408748) q[1]; +ry(pi*0.3501408748) q[1]; +rz(pi*0.3501408748) q[1]; +rx(pi*0.3501408748) q[2]; +ry(pi*0.3501408748) q[2]; +rz(pi*0.3501408748) q[2]; +rx(pi*0.3501408748) q[3]; +ry(pi*0.3501408748) q[3]; +rz(pi*0.3501408748) q[3]; + +// Gate: ZZ**1.1 +rz(pi*1.1) q[2]; +rz(pi*1.1) q[3]; +u3(pi*0.5,0,pi*0.25) q[2]; +u3(pi*0.5,pi*1.0,pi*0.75) q[3]; +rx(pi*0.5) q[2]; +cx q[2],q[3]; +rx(pi*0.4) q[2]; +ry(pi*0.5) q[3]; +cx q[3],q[2]; +rx(pi*-0.5) q[3]; +rz(pi*0.5) q[3]; +cx q[2],q[3]; +u3(pi*0.5,pi*0.65,pi*1.0) q[2]; +u3(pi*0.5,pi*0.15,0) q[3]; + +// Gate: YY**1.1 +u3(0,pi*1.0,pi*0.5) q[2]; +u3(0,0,pi*0.5) q[3]; +rx(pi*0.5) q[2]; +cx q[2],q[3]; +rx(pi*0.4) q[2]; +ry(pi*0.5) q[3]; +cx q[3],q[2]; +rx(pi*-0.5) q[3]; +rz(pi*0.5) q[3]; +cx q[2],q[3]; +u3(pi*1.0,0,pi*0.5) q[2]; +u3(pi*1.0,0,pi*1.5) q[3]; + +// Gate: XX**1.1 +u3(pi*0.5,pi*1.5,pi*1.5) q[2]; +u3(pi*0.5,pi*0.5,pi*1.5) q[3]; +rx(pi*0.5) q[2]; +cx q[2],q[3]; +rx(pi*0.4) q[2]; +ry(pi*0.5) q[3]; +cx q[3],q[2]; +rx(pi*-0.5) q[3]; +rz(pi*0.5) q[3]; +cx q[2],q[3]; +u3(pi*0.5,pi*0.5,pi*0.5) q[2]; +u3(pi*0.5,pi*0.5,pi*1.5) q[3]; + +rx(pi*0.3501408748) q[2]; +ry(pi*0.3501408748) q[2]; +rz(pi*0.3501408748) q[2]; +rx(pi*0.3501408748) q[3]; +ry(pi*0.3501408748) q[3]; +rz(pi*0.3501408748) q[3]; +rx(pi*0.3501408748) q[4]; +ry(pi*0.3501408748) q[4]; +rz(pi*0.3501408748) q[4]; +rx(pi*0.3501408748) q[5]; +ry(pi*0.3501408748) q[5]; +rz(pi*0.3501408748) q[5]; + +// Gate: ZZ**1.1 +rz(pi*1.1) q[4]; +rz(pi*1.1) q[5]; +u3(pi*0.5,0,pi*0.25) q[4]; +u3(pi*0.5,pi*1.0,pi*0.75) q[5]; +rx(pi*0.5) q[4]; +cx q[4],q[5]; +rx(pi*0.4) q[4]; +ry(pi*0.5) q[5]; +cx q[5],q[4]; +rx(pi*-0.5) q[5]; +rz(pi*0.5) q[5]; +cx q[4],q[5]; +u3(pi*0.5,pi*0.65,pi*1.0) q[4]; +u3(pi*0.5,pi*0.15,0) q[5]; + +// Gate: YY**1.1 +u3(0,pi*1.0,pi*0.5) q[4]; +u3(0,0,pi*0.5) q[5]; +rx(pi*0.5) q[4]; +cx q[4],q[5]; +rx(pi*0.4) q[4]; +ry(pi*0.5) q[5]; +cx q[5],q[4]; +rx(pi*-0.5) q[5]; +rz(pi*0.5) q[5]; +cx q[4],q[5]; +u3(pi*1.0,0,pi*0.5) q[4]; +u3(pi*1.0,0,pi*1.5) q[5]; + +// Gate: XX**1.1 +u3(pi*0.5,pi*1.5,pi*1.5) q[4]; +u3(pi*0.5,pi*0.5,pi*1.5) q[5]; +rx(pi*0.5) q[4]; +cx q[4],q[5]; +rx(pi*0.4) q[4]; +ry(pi*0.5) q[5]; +cx q[5],q[4]; +rx(pi*-0.5) q[5]; +rz(pi*0.5) q[5]; +cx q[4],q[5]; +u3(pi*0.5,pi*0.5,pi*0.5) q[4]; +u3(pi*0.5,pi*0.5,pi*1.5) q[5]; + +rx(pi*0.3501408748) q[4]; +ry(pi*0.3501408748) q[4]; +rz(pi*0.3501408748) q[4]; +rx(pi*0.3501408748) q[5]; +ry(pi*0.3501408748) q[5]; +rz(pi*0.3501408748) q[5]; +rx(pi*0.3501408748) q[6]; +ry(pi*0.3501408748) q[6]; +rz(pi*0.3501408748) q[6]; +rx(pi*0.3501408748) q[7]; +ry(pi*0.3501408748) q[7]; +rz(pi*0.3501408748) q[7]; + +// Gate: ZZ**1.1 +rz(pi*1.1) q[6]; +rz(pi*1.1) q[7]; +u3(pi*0.5,0,pi*0.25) q[6]; +u3(pi*0.5,pi*1.0,pi*0.75) q[7]; +rx(pi*0.5) q[6]; +cx q[6],q[7]; +rx(pi*0.4) q[6]; +ry(pi*0.5) q[7]; +cx q[7],q[6]; +rx(pi*-0.5) q[7]; +rz(pi*0.5) q[7]; +cx q[6],q[7]; +u3(pi*0.5,pi*0.65,pi*1.0) q[6]; +u3(pi*0.5,pi*0.15,0) q[7]; + +// Gate: YY**1.1 +u3(0,pi*1.0,pi*0.5) q[6]; +u3(0,0,pi*0.5) q[7]; +rx(pi*0.5) q[6]; +cx q[6],q[7]; +rx(pi*0.4) q[6]; +ry(pi*0.5) q[7]; +cx q[7],q[6]; +rx(pi*-0.5) q[7]; +rz(pi*0.5) q[7]; +cx q[6],q[7]; +u3(pi*1.0,0,pi*0.5) q[6]; +u3(pi*1.0,0,pi*1.5) q[7]; + +// Gate: XX**1.1 +u3(pi*0.5,pi*1.5,pi*1.5) q[6]; +u3(pi*0.5,pi*0.5,pi*1.5) q[7]; +rx(pi*0.5) q[6]; +cx q[6],q[7]; +rx(pi*0.4) q[6]; +ry(pi*0.5) q[7]; +cx q[7],q[6]; +rx(pi*-0.5) q[7]; +rz(pi*0.5) q[7]; +cx q[6],q[7]; +u3(pi*0.5,pi*0.5,pi*0.5) q[6]; +u3(pi*0.5,pi*0.5,pi*1.5) q[7]; + +rx(pi*0.3501408748) q[6]; +ry(pi*0.3501408748) q[6]; +rz(pi*0.3501408748) q[6]; +rx(pi*0.3501408748) q[7]; +ry(pi*0.3501408748) q[7]; +rz(pi*0.3501408748) q[7]; +rx(pi*0.3501408748) q[1]; +ry(pi*0.3501408748) q[1]; +rz(pi*0.3501408748) q[1]; +rx(pi*0.3501408748) q[2]; +ry(pi*0.3501408748) q[2]; +rz(pi*0.3501408748) q[2]; + +// Gate: ZZ**1.1 +rz(pi*1.1) q[1]; +rz(pi*1.1) q[2]; +u3(pi*0.5,0,pi*0.25) q[1]; +u3(pi*0.5,pi*1.0,pi*0.75) q[2]; +rx(pi*0.5) q[1]; +cx q[1],q[2]; +rx(pi*0.4) q[1]; +ry(pi*0.5) q[2]; +cx q[2],q[1]; +rx(pi*-0.5) q[2]; +rz(pi*0.5) q[2]; +cx q[1],q[2]; +u3(pi*0.5,pi*0.65,pi*1.0) q[1]; +u3(pi*0.5,pi*0.15,0) q[2]; + +// Gate: YY**1.1 +u3(0,pi*1.0,pi*0.5) q[1]; +u3(0,0,pi*0.5) q[2]; +rx(pi*0.5) q[1]; +cx q[1],q[2]; +rx(pi*0.4) q[1]; +ry(pi*0.5) q[2]; +cx q[2],q[1]; +rx(pi*-0.5) q[2]; +rz(pi*0.5) q[2]; +cx q[1],q[2]; +u3(pi*1.0,0,pi*0.5) q[1]; +u3(pi*1.0,0,pi*1.5) q[2]; + +// Gate: XX**1.1 +u3(pi*0.5,pi*1.5,pi*1.5) q[1]; +u3(pi*0.5,pi*0.5,pi*1.5) q[2]; +rx(pi*0.5) q[1]; +cx q[1],q[2]; +rx(pi*0.4) q[1]; +ry(pi*0.5) q[2]; +cx q[2],q[1]; +rx(pi*-0.5) q[2]; +rz(pi*0.5) q[2]; +cx q[1],q[2]; +u3(pi*0.5,pi*0.5,pi*0.5) q[1]; +u3(pi*0.5,pi*0.5,pi*1.5) q[2]; + +rx(pi*0.3501408748) q[1]; +ry(pi*0.3501408748) q[1]; +rz(pi*0.3501408748) q[1]; +rx(pi*0.3501408748) q[2]; +ry(pi*0.3501408748) q[2]; +rz(pi*0.3501408748) q[2]; +rx(pi*0.3501408748) q[3]; +ry(pi*0.3501408748) q[3]; +rz(pi*0.3501408748) q[3]; +rx(pi*0.3501408748) q[4]; +ry(pi*0.3501408748) q[4]; +rz(pi*0.3501408748) q[4]; + +// Gate: ZZ**1.1 +rz(pi*1.1) q[3]; +rz(pi*1.1) q[4]; +u3(pi*0.5,0,pi*0.25) q[3]; +u3(pi*0.5,pi*1.0,pi*0.75) q[4]; +rx(pi*0.5) q[3]; +cx q[3],q[4]; +rx(pi*0.4) q[3]; +ry(pi*0.5) q[4]; +cx q[4],q[3]; +rx(pi*-0.5) q[4]; +rz(pi*0.5) q[4]; +cx q[3],q[4]; +u3(pi*0.5,pi*0.65,pi*1.0) q[3]; +u3(pi*0.5,pi*0.15,0) q[4]; + +// Gate: YY**1.1 +u3(0,pi*1.0,pi*0.5) q[3]; +u3(0,0,pi*0.5) q[4]; +rx(pi*0.5) q[3]; +cx q[3],q[4]; +rx(pi*0.4) q[3]; +ry(pi*0.5) q[4]; +cx q[4],q[3]; +rx(pi*-0.5) q[4]; +rz(pi*0.5) q[4]; +cx q[3],q[4]; +u3(pi*1.0,0,pi*0.5) q[3]; +u3(pi*1.0,0,pi*1.5) q[4]; + +// Gate: XX**1.1 +u3(pi*0.5,pi*1.5,pi*1.5) q[3]; +u3(pi*0.5,pi*0.5,pi*1.5) q[4]; +rx(pi*0.5) q[3]; +cx q[3],q[4]; +rx(pi*0.4) q[3]; +ry(pi*0.5) q[4]; +cx q[4],q[3]; +rx(pi*-0.5) q[4]; +rz(pi*0.5) q[4]; +cx q[3],q[4]; +u3(pi*0.5,pi*0.5,pi*0.5) q[3]; +u3(pi*0.5,pi*0.5,pi*1.5) q[4]; + +rx(pi*0.3501408748) q[3]; +ry(pi*0.3501408748) q[3]; +rz(pi*0.3501408748) q[3]; +rx(pi*0.3501408748) q[4]; +ry(pi*0.3501408748) q[4]; +rz(pi*0.3501408748) q[4]; +rx(pi*0.3501408748) q[5]; +ry(pi*0.3501408748) q[5]; +rz(pi*0.3501408748) q[5]; +rx(pi*0.3501408748) q[6]; +ry(pi*0.3501408748) q[6]; +rz(pi*0.3501408748) q[6]; + +// Gate: ZZ**1.1 +rz(pi*1.1) q[5]; +rz(pi*1.1) q[6]; +u3(pi*0.5,0,pi*0.25) q[5]; +u3(pi*0.5,pi*1.0,pi*0.75) q[6]; +rx(pi*0.5) q[5]; +cx q[5],q[6]; +rx(pi*0.4) q[5]; +ry(pi*0.5) q[6]; +cx q[6],q[5]; +rx(pi*-0.5) q[6]; +rz(pi*0.5) q[6]; +cx q[5],q[6]; +u3(pi*0.5,pi*0.65,pi*1.0) q[5]; +u3(pi*0.5,pi*0.15,0) q[6]; + +// Gate: YY**1.1 +u3(0,pi*1.0,pi*0.5) q[5]; +u3(0,0,pi*0.5) q[6]; +rx(pi*0.5) q[5]; +cx q[5],q[6]; +rx(pi*0.4) q[5]; +ry(pi*0.5) q[6]; +cx q[6],q[5]; +rx(pi*-0.5) q[6]; +rz(pi*0.5) q[6]; +cx q[5],q[6]; +u3(pi*1.0,0,pi*0.5) q[5]; +u3(pi*1.0,0,pi*1.5) q[6]; + +// Gate: XX**1.1 +u3(pi*0.5,pi*1.5,pi*1.5) q[5]; +u3(pi*0.5,pi*0.5,pi*1.5) q[6]; +rx(pi*0.5) q[5]; +cx q[5],q[6]; +rx(pi*0.4) q[5]; +ry(pi*0.5) q[6]; +cx q[6],q[5]; +rx(pi*-0.5) q[6]; +rz(pi*0.5) q[6]; +cx q[5],q[6]; +u3(pi*0.5,pi*0.5,pi*0.5) q[5]; +u3(pi*0.5,pi*0.5,pi*1.5) q[6]; + +rx(pi*0.3501408748) q[5]; +ry(pi*0.3501408748) q[5]; +rz(pi*0.3501408748) q[5]; +rx(pi*0.3501408748) q[6]; +ry(pi*0.3501408748) q[6]; +rz(pi*0.3501408748) q[6]; +rx(pi*0.3501408748) q[7]; +ry(pi*0.3501408748) q[7]; +rz(pi*0.3501408748) q[7]; +rx(pi*0.3501408748) q[0]; +ry(pi*0.3501408748) q[0]; +rz(pi*0.3501408748) q[0]; + +// Gate: ZZ**1.1 +rz(pi*1.1) q[7]; +rz(pi*1.1) q[0]; +u3(pi*0.5,0,pi*0.25) q[7]; +u3(pi*0.5,pi*1.0,pi*0.75) q[0]; +rx(pi*0.5) q[7]; +cx q[7],q[0]; +rx(pi*0.4) q[7]; +ry(pi*0.5) q[0]; +cx q[0],q[7]; +rx(pi*-0.5) q[0]; +rz(pi*0.5) q[0]; +cx q[7],q[0]; +u3(pi*0.5,pi*0.65,pi*1.0) q[7]; +u3(pi*0.5,pi*0.15,0) q[0]; + +// Gate: YY**1.1 +u3(0,pi*1.0,pi*0.5) q[7]; +u3(0,0,pi*0.5) q[0]; +rx(pi*0.5) q[7]; +cx q[7],q[0]; +rx(pi*0.4) q[7]; +ry(pi*0.5) q[0]; +cx q[0],q[7]; +rx(pi*-0.5) q[0]; +rz(pi*0.5) q[0]; +cx q[7],q[0]; +u3(pi*1.0,0,pi*0.5) q[7]; +u3(pi*1.0,0,pi*1.5) q[0]; + +// Gate: XX**1.1 +u3(pi*0.5,pi*1.5,pi*1.5) q[7]; +u3(pi*0.5,pi*0.5,pi*1.5) q[0]; +rx(pi*0.5) q[7]; +cx q[7],q[0]; +rx(pi*0.4) q[7]; +ry(pi*0.5) q[0]; +cx q[0],q[7]; +rx(pi*-0.5) q[0]; +rz(pi*0.5) q[0]; +cx q[7],q[0]; +u3(pi*0.5,pi*0.5,pi*0.5) q[7]; +u3(pi*0.5,pi*0.5,pi*1.5) q[0]; + +rx(pi*0.3501408748) q[7]; +ry(pi*0.3501408748) q[7]; +rz(pi*0.3501408748) q[7]; +rx(pi*0.3501408748) q[0]; +ry(pi*0.3501408748) q[0]; +rz(pi*0.3501408748) q[0]; + +measure q[0] -> ans[0]; +measure q[1] -> ans[1]; +measure q[2] -> ans[2]; +measure q[3] -> ans[3]; +measure q[4] -> ans[4]; +measure q[5] -> ans[5]; +measure q[6] -> ans[6]; +measure q[7] -> ans[7]; + + diff --git a/qasm/circuits/fredkin_n3.qasm b/qasm/circuits/fredkin_n3.qasm new file mode 100644 index 0000000..e86da24 --- /dev/null +++ b/qasm/circuits/fredkin_n3.qasm @@ -0,0 +1,26 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[3]; +creg c[3]; +x q[0]; +x q[1]; +cx q[2],q[1]; +cx q[0],q[1]; +h q[2]; +t q[0]; +tdg q[1]; +t q[2]; +cx q[2],q[1]; +cx q[0],q[2]; +t q[1]; +cx q[0],q[1]; +tdg q[2]; +tdg q[1]; +cx q[0],q[2]; +cx q[2],q[1]; +t q[1]; +h q[2]; +cx q[2],q[1]; +measure q[0] -> c[0]; +measure q[1] -> c[1]; +measure q[2] -> c[2]; diff --git a/qasm/circuits/ghz_n4.qasm b/qasm/circuits/ghz_n4.qasm new file mode 100644 index 0000000..394ba7e --- /dev/null +++ b/qasm/circuits/ghz_n4.qasm @@ -0,0 +1,14 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg bits[4]; +creg c[4]; + +h bits[0]; +cx bits[0],bits[1]; +cx bits[1],bits[2]; +cx bits[2],bits[3]; + +measure bits[0] -> c[0]; +measure bits[1] -> c[1]; +measure bits[2] -> c[2]; +measure bits[3] -> c[3]; diff --git a/qasm/circuits/ghz_n8.qasm b/qasm/circuits/ghz_n8.qasm new file mode 100644 index 0000000..6ff5559 --- /dev/null +++ b/qasm/circuits/ghz_n8.qasm @@ -0,0 +1,21 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[8]; +creg meas[8]; +h q[0]; +cx q[0],q[1]; +cx q[1],q[2]; +cx q[2],q[3]; +cx q[3],q[4]; +cx q[4],q[5]; +cx q[5],q[6]; +cx q[6],q[7]; +barrier q[0],q[1],q[2],q[3],q[4],q[5],q[6],q[7]; +measure q[0] -> meas[0]; +measure q[1] -> meas[1]; +measure q[2] -> meas[2]; +measure q[3] -> meas[3]; +measure q[4] -> meas[4]; +measure q[5] -> meas[5]; +measure q[6] -> meas[6]; +measure q[7] -> meas[7]; diff --git a/qasm/circuits/qaoa_n3.qasm b/qasm/circuits/qaoa_n3.qasm new file mode 100644 index 0000000..9fa5961 --- /dev/null +++ b/qasm/circuits/qaoa_n3.qasm @@ -0,0 +1,32 @@ +// Finding the max of the cost function: C = -1 + z(0)z(2) - 2 z(0)z(1)z(2) - 3 z(1) +// Starting with p = 1 +// Generated from Cirq v0.8.0 + +OPENQASM 2.0; +include "qelib1.inc"; + +// Qubits: [(0, 0), (1, 0), (2, 0)] +qreg q[3]; +creg m2[1]; +creg m0[1]; +creg m1[1]; + +h q[0]; +h q[1]; +h q[2]; +cx q[0],q[2]; +rz(pi*1.79986) q[2]; +cx q[0],q[2]; +cx q[0],q[1]; +cx q[1],q[2]; +rz(pi*-3.59973) q[2]; +cx q[1],q[2]; +cx q[0],q[1]; +rx(pi*0.545344) q[2]; +rz(pi*-5.39959) q[1]; +rx(pi*0.545344) q[0]; +rx(pi*0.545344) q[1]; + +measure q[0] -> m0[0]; +measure q[1] -> m1[0]; +measure q[2] -> m2[0]; diff --git a/qasm/circuits/qft_n4.qasm b/qasm/circuits/qft_n4.qasm new file mode 100644 index 0000000..0b0fe08 --- /dev/null +++ b/qasm/circuits/qft_n4.qasm @@ -0,0 +1,18 @@ +// quantum Fourier transform +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[4]; +creg c[4]; +x q[0]; +x q[2]; +barrier q; +h q[0]; +cu1(pi/2) q[1],q[0]; +h q[1]; +cu1(pi/4) q[2],q[0]; +cu1(pi/2) q[2],q[1]; +h q[2]; +cu1(pi/8) q[3],q[0]; +cu1(pi/4) q[3],q[1]; +cu1(pi/2) q[3],q[2]; +h q[3]; diff --git a/qasm/circuits/simon_n6.qasm b/qasm/circuits/simon_n6.qasm new file mode 100644 index 0000000..4f3fbc2 --- /dev/null +++ b/qasm/circuits/simon_n6.qasm @@ -0,0 +1,38 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[6]; +creg c[6]; +// This initializes 6 quantum registers and 6 classical registers. + +h q[0]; +h q[1]; +h q[2]; +// The first 3 qubits are put into superposition states. + +barrier q; +cx q[2], q[4]; +x q[3]; +cx q[2], q[3]; +ccx q[0], q[1], q[3]; +x q[0]; +x q[1]; +ccx q[0], q[1], q[3]; +x q[0]; +x q[1]; +x q[3]; +// This applies the secret structure: s=110. + +barrier q; +h q[0]; +h q[1]; +h q[2]; + +// This measures the first 3 qubits. +measure q[0] -> c[0]; +measure q[1] -> c[1]; +measure q[2] -> c[2]; + +// This measures the second 3 qubits. +measure q[3] -> c[3]; +measure q[4] -> c[4]; +measure q[5] -> c[5]; diff --git a/qasm/circuits/vqe_n4.qasm b/qasm/circuits/vqe_n4.qasm new file mode 100644 index 0000000..3e5350a --- /dev/null +++ b/qasm/circuits/vqe_n4.qasm @@ -0,0 +1,98 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[4]; +creg meas[4]; +sx q[0]; +rz(5.0300511584448) q[0]; +sx q[0]; +rz(3*pi) q[0]; +rz(2.61519568487349) q[0]; +sx q[1]; +rz(5.36606826220224) q[1]; +sx q[1]; +rz(3*pi) q[1]; +rz(0.667082990176662) q[1]; +cx q[0],q[1]; +sx q[0]; +rz(4.09739784898316) q[0]; +sx q[0]; +rz(3*pi) q[0]; +rz(1.92219255913748) q[0]; +sx q[2]; +rz(3.20626074964735) q[2]; +sx q[2]; +rz(3*pi) q[2]; +rz(0.571219981217032) q[2]; +cx q[1],q[2]; +sx q[1]; +rz(4.79016360412963) q[1]; +sx q[1]; +rz(3*pi) q[1]; +rz(0.438232887845333) q[1]; +cx q[0],q[1]; +sx q[0]; +rz(4.57437876552885) q[0]; +sx q[0]; +rz(3*pi) q[0]; +rz(1.86112525741656) q[0]; +sx q[3]; +rz(6.18865431978628) q[3]; +sx q[3]; +rz(3*pi) q[3]; +rz(0.576182260790784) q[3]; +cx q[2],q[3]; +sx q[2]; +rz(4.49858795091057) q[2]; +sx q[2]; +rz(3*pi) q[2]; +rz(0.917799481623813) q[2]; +cx q[1],q[2]; +sx q[1]; +rz(5.60829568567739) q[1]; +sx q[1]; +rz(3*pi) q[1]; +rz(0.145928275357359) q[1]; +cx q[0],q[1]; +sx q[0]; +rz(3.34595826021666) q[0]; +sx q[0]; +rz(3*pi) q[0]; +rz(0.956972379417358) q[0]; +sx q[3]; +rz(4.05651598094723) q[3]; +sx q[3]; +rz(3*pi) q[3]; +rz(1.15095967544708) q[3]; +cx q[2],q[3]; +sx q[2]; +rz(3.76888634073298) q[2]; +sx q[2]; +rz(3*pi) q[2]; +rz(1.90865844345986) q[2]; +cx q[1],q[2]; +sx q[1]; +rz(6.12260448652247) q[1]; +sx q[1]; +rz(3*pi) q[1]; +rz(0.30684599582304) q[1]; +sx q[3]; +rz(4.75710778753287) q[3]; +sx q[3]; +rz(3*pi) q[3]; +rz(0.535717334235832) q[3]; +cx q[2],q[3]; +sx q[2]; +rz(6.17521515476781) q[2]; +sx q[2]; +rz(3*pi) q[2]; +rz(2.1495814494341) q[2]; +sx q[3]; +rz(5.68124782361394) q[3]; +sx q[3]; +rz(3*pi) q[3]; +rz(1.38277984079156) q[3]; +barrier q[0],q[1],q[2],q[3]; +measure q[0] -> meas[0]; +measure q[1] -> meas[1]; +measure q[2] -> meas[2]; +measure q[3] -> meas[3]; diff --git a/qasm/circuits/wstate_n3.qasm b/qasm/circuits/wstate_n3.qasm new file mode 100644 index 0000000..01f5f15 --- /dev/null +++ b/qasm/circuits/wstate_n3.qasm @@ -0,0 +1,30 @@ +// Name of Experiment: W-state v1 + +OPENQASM 2.0; +include "qelib1.inc"; + +qreg q[3]; +creg c[3]; + +u3(1.91063,0,0) q[0]; + +//cH q[0],q[1]; +h q[1]; +sdg q[1]; +cx q[0],q[1]; +h q[1]; +t q[1]; +cx q[0],q[1]; +t q[1]; +h q[1]; +s q[1]; +x q[1]; +s q[0]; + +ccx q[0],q[1],q[2]; +x q[0]; +x q[1]; +cx q[0],q[1]; +measure q[0] -> c[0]; +measure q[1] -> c[1]; +measure q[2] -> c[2]; diff --git a/qasm/test/compute_reference_state.py b/qasm/test/compute_reference_state.py new file mode 100644 index 0000000..9bbc052 --- /dev/null +++ b/qasm/test/compute_reference_state.py @@ -0,0 +1,22 @@ +""" +Compute state vector with qiskit. Used for generating tests. +""" +import argparse +from qiskit import QuantumCircuit +from qiskit.quantum_info import Statevector + +parser = argparse.ArgumentParser(description='Compute reference state using qiskit.') +parser.add_argument('qasm_file', help='Path to .qasm file.') + + +def main(): + args = parser.parse_args() + qc = QuantumCircuit.from_qasm_file(args.qasm_file) + qc.remove_final_measurements() + print(qc) + statevector = Statevector(qc) + print(repr(statevector.data)) + + +if __name__ == '__main__': + main() diff --git a/qasm/test/test_circuits/bell_phi_min.qasm b/qasm/test/test_circuits/bell_phi_min.qasm deleted file mode 100644 index cf560d8..0000000 --- a/qasm/test/test_circuits/bell_phi_min.qasm +++ /dev/null @@ -1,13 +0,0 @@ -OPENQASM 2.0; -include "qelib1.inc"; - -qreg q[2]; -creg c[2]; - -h q[0]; -cx q[0], q[1]; -x q[0]; -z q[1]; - -measure q[0]->c[0]; -measure q[1]->c[1]; diff --git a/qasm/test/test_circuits/bell_phi_plus.qasm b/qasm/test/test_circuits/bell_phi_plus.qasm deleted file mode 100644 index 006a2ba..0000000 --- a/qasm/test/test_circuits/bell_phi_plus.qasm +++ /dev/null @@ -1,12 +0,0 @@ -OPENQASM 2.0; -include "qelib1.inc"; - -qreg q[2]; -creg c[2]; - -h q[0]; -cx q[0], q[1]; -x q[0]; - -measure q[0]->c[0]; -measure q[1]->c[1]; diff --git a/qasm/test/test_circuits/bell_psi_min.qasm b/qasm/test/test_circuits/bell_psi_min.qasm deleted file mode 100644 index 74f039f..0000000 --- a/qasm/test/test_circuits/bell_psi_min.qasm +++ /dev/null @@ -1,12 +0,0 @@ -OPENQASM 2.0; -include "qelib1.inc"; - -qreg q[2]; -creg c[2]; - -h q[0]; -cx q[0], q[1]; -z q[1]; - -measure q[0]->c[0]; -measure q[1]->c[1]; diff --git a/qasm/test/test_circuits/bell_psi_plus.qasm b/qasm/test/test_circuits/bell_psi_plus.qasm deleted file mode 100644 index a2fac2b..0000000 --- a/qasm/test/test_circuits/bell_psi_plus.qasm +++ /dev/null @@ -1,11 +0,0 @@ -OPENQASM 2.0; -include "qelib1.inc"; - -qreg q[2]; -creg c[2]; - -h q[0]; -cx q[0], q[1]; - -measure q[0]->c[0]; -measure q[1]->c[1]; diff --git a/qasm/test/test_sim_qasm.py b/qasm/test/test_sim_qasm.py index a8d9d63..c961e88 100644 --- a/qasm/test/test_sim_qasm.py +++ b/qasm/test/test_sim_qasm.py @@ -9,7 +9,7 @@ TOLERANCE = 1e-6 SIM_QASM = './build/qasm/sim_qasm' -QASM_DIR = 'qasm/test/test_circuits/' +QASM_DIR = 'qasm/circuits/' def fidelity(a, b): @@ -25,7 +25,8 @@ def get_vector(qasm_file : str): """ Simulate given quantum circuit and return state vector. """ - output = subprocess.run([SIM_QASM, '--state-vector', qasm_file], + filepath = os.path.join(QASM_DIR, qasm_file) + output = subprocess.run([SIM_QASM, '--state-vector', filepath], stdout=subprocess.PIPE) data = json.loads(output.stdout) vector = np.apply_along_axis(lambda args: [complex(*args)], 1, @@ -33,55 +34,354 @@ def get_vector(qasm_file : str): return vector -def test_bell_psi_plus(): +def test_adder_n4(): """ - Test |Psi+> = 1/sqrt(2)[1 0 0 1] + Test adder_n4.qasm """ - qasm_file = os.path.join(QASM_DIR, 'bell_psi_plus.qasm') - vector = get_vector(qasm_file) - reference = np.array([1/np.sqrt(2) + 0j, - 0 + 0j, - 0 + 0j, - 1/np.sqrt(2) + 0j]) - assert abs(fidelity(vector, reference) - 1) < TOLERANCE + vector = get_vector('adder_n4.qasm') + ref = np.array([0.00000000e+00+0.j, 2.36158002e-17+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 1.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE -def test_bell_psi_min(): +def test_basis_change_n3(): """ - Test |Psi-> = 1/sqrt(2)[1 0 0 -1] + Test basis_change_n3.qasm """ - qasm_file = os.path.join(QASM_DIR, 'bell_psi_min.qasm') - vector = get_vector(qasm_file) - reference = np.array([1/np.sqrt(2) + 0j, - 0 + 0j, - 0 + 0j, - -1/np.sqrt(2) + 0j]) - assert abs(fidelity(vector, reference) - 1) < TOLERANCE + vector = get_vector('basis_change_n3.qasm') + ref = np.array([ 9.06686370e-01-4.21805437e-01j, 3.21841592e-16+3.59799267e-16j, + 1.96261557e-16+3.14018492e-16j, -3.50542195e-18-1.10979812e-17j, + 3.32473560e-16-1.96808529e-16j, -1.82945633e-17-1.03747177e-17j, + -3.85650646e-17-1.11262893e-16j, 1.17333381e-17+7.41092244e-18j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE -def test_bell_phi_plus(): +def test_bell_state(): """ - Test |Phi+> = 1/sqrt(2)[0 1 1 0] + Test bell_state.qasm """ - qasm_file = os.path.join(QASM_DIR, 'bell_phi_plus.qasm') - vector = get_vector(qasm_file) - reference = np.array([0 + 0j, - 1/np.sqrt(2) + 0j, - 1/np.sqrt(2) + 0j, - 0 + 0j]) - assert abs(fidelity(vector, reference) - 1) < TOLERANCE + vector = get_vector('bell_state.qasm') + ref = np.array([0+0j, 0.70710678+0j, 0.70710678+0j, 0+0j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE -def test_bell_phi_min(): +def test_dnn_n8(): """ - Test |Phi-> = 1/sqrt(2)[0 1 -1 0] + Test dnn_n8.qasm """ - qasm_file = os.path.join(QASM_DIR, 'bell_phi_min.qasm') - vector = get_vector(qasm_file) - reference = np.array([0 + 0j, - 1/np.sqrt(2) + 0j, - -1/np.sqrt(2) + 0j, - 0 + 0j]) - assert abs(fidelity(vector, reference) - 1) < TOLERANCE + vector = get_vector('dnn_n8.qasm') + ref = np.array([ 0.12641004+5.31293856e-01j, -0.07648447-3.72236104e-02j, + -0.06822525-1.20937515e-01j, 0.10077743-4.19485017e-02j, + -0.07648447-3.72236104e-02j, 0.09757202-1.17331258e-02j, + 0.0109432 +1.40583012e-01j, 0.05292486-1.58594015e-01j, + -0.06822525-1.20937515e-01j, 0.03204555-1.57138851e-02j, + 0.02604237+2.40148329e-02j, -0.02380459-1.51537614e-02j, + 0.10077743-4.19485017e-02j, -0.04134054+4.07984689e-02j, + -0.04044471-1.72663937e-02j, 0.00892337+4.71213470e-02j, + -0.07648447-3.72236104e-02j, 0.01673732+3.79095110e-03j, + 0.01324859-2.51813525e-02j, 0.00453264+1.70332048e-02j, + 0.09757202-1.17331258e-02j, -0.00615046+2.18937245e-02j, + -0.03070889+2.04780306e-02j, 0.01096824-5.04777498e-03j, + 0.0109432 +1.40583012e-01j, 0.01168173+2.52999889e-03j, + -0.10126317-2.63587809e-02j, 0.0941019 -3.23422643e-02j, + 0.05292486-1.58594015e-01j, 0.03495767+5.65770822e-03j, + 0.01226119+8.62905034e-02j, -0.00964648-3.73388811e-02j, + -0.06822525-1.20937515e-01j, 0.01324859-2.51813525e-02j, + 0.01275733+2.44040989e-02j, -0.00768092+2.29361852e-02j, + 0.03204555-1.57138851e-02j, -0.02168349+1.31762102e-02j, + -0.01002828-3.81971492e-02j, -0.01674623+4.01859119e-02j, + 0.02604237+2.40148329e-02j, 0.00253765+8.10026137e-03j, + -0.02555926+2.29115023e-03j, 0.01116755-8.58145935e-03j, + -0.02380459-1.51537614e-02j, 0.00641802-7.67101659e-03j, + 0.02244218+7.38399759e-03j, -0.01469433-1.53390778e-02j, + 0.10077743-4.19485017e-02j, 0.00453264+1.70332048e-02j, + -0.00768092+2.29361852e-02j, -0.02740137-1.47984868e-02j, + -0.04134054+4.07984689e-02j, -0.0094759 -2.14561876e-02j, + 0.03597617-1.85729877e-02j, -0.01754544-5.31071685e-03j, + -0.04044471-1.72663937e-02j, -0.01380899-5.76202290e-03j, + 0.03408207-2.45710819e-02j, -0.01090296+3.25737193e-02j, + 0.00892337+4.71213470e-02j, -0.00632533+1.53474785e-02j, + -0.02059268-1.43735313e-02j, 0.00926439+1.15263465e-03j, + -0.07648447-3.72236104e-02j, 0.09757202-1.17331258e-02j, + 0.03204555-1.57138851e-02j, -0.04134054+4.07984689e-02j, + 0.01673732+3.79095110e-03j, -0.00615046+2.18937245e-02j, + 0.01168173+2.52999889e-03j, 0.03495767+5.65770822e-03j, + 0.01324859-2.51813525e-02j, -0.02168349+1.31762102e-02j, + 0.00253765+8.10026137e-03j, 0.00641802-7.67101659e-03j, + 0.00453264+1.70332048e-02j, -0.0094759 -2.14561876e-02j, + -0.01380899-5.76202290e-03j, -0.00632533+1.53474785e-02j, + 0.09757202-1.17331258e-02j, -0.00615046+2.18937245e-02j, + -0.02168349+1.31762102e-02j, -0.0094759 -2.14561876e-02j, + -0.00615046+2.18937245e-02j, -0.00212947-3.34982299e-02j, + 0.01866758-3.88288993e-04j, -0.01526814-7.21120895e-03j, + -0.03070889+2.04780306e-02j, 0.01866758-3.88288993e-04j, + 0.01283417-1.13119330e-02j, -0.00700464+3.03791437e-02j, + 0.01096824-5.04777498e-03j, -0.01526814-7.21120895e-03j, + -0.00364199+2.12691508e-02j, 0.03092621-1.59134136e-02j, + 0.0109432 +1.40583012e-01j, -0.03070889+2.04780306e-02j, + -0.01002828-3.81971492e-02j, 0.03597617-1.85729877e-02j, + 0.01168173+2.52999889e-03j, 0.01866758-3.88288993e-04j, + -0.0201309 +4.63262054e-02j, 0.01879401-3.68975748e-02j, + -0.10126317-2.63587809e-02j, 0.01283417-1.13119330e-02j, + 0.00624573-2.12638164e-02j, 0.02296651+2.58150474e-02j, + 0.0941019 -3.23422643e-02j, -0.00700464+3.03791437e-02j, + -0.04300331+4.56514012e-03j, 0.01192333+1.44386801e-02j, + 0.05292486-1.58594015e-01j, 0.01096824-5.04777498e-03j, + -0.01674623+4.01859119e-02j, -0.01754544-5.31071685e-03j, + 0.03495767+5.65770822e-03j, -0.01526814-7.21120895e-03j, + 0.01879401-3.68975748e-02j, -0.0493597 +2.30043110e-02j, + 0.01226119+8.62905034e-02j, -0.00364199+2.12691508e-02j, + -0.04210754-2.03056271e-02j, 0.0272914 -5.21209112e-03j, + -0.00964648-3.73388811e-02j, 0.03092621-1.59134136e-02j, + 0.01221778+3.55257330e-02j, -0.00041774-1.76806932e-02j, + -0.06822525-1.20937515e-01j, 0.0109432 +1.40583012e-01j, + 0.02604237+2.40148329e-02j, -0.04044471-1.72663937e-02j, + 0.01324859-2.51813525e-02j, -0.03070889+2.04780306e-02j, + -0.10126317-2.63587809e-02j, 0.01226119+8.62905034e-02j, + 0.01275733+2.44040989e-02j, -0.01002828-3.81971492e-02j, + -0.02555926+2.29115023e-03j, 0.02244218+7.38399759e-03j, + -0.00768092+2.29361852e-02j, 0.03597617-1.85729877e-02j, + 0.03408207-2.45710819e-02j, -0.02059268-1.43735313e-02j, + 0.03204555-1.57138851e-02j, 0.01168173+2.52999889e-03j, + 0.00253765+8.10026137e-03j, -0.01380899-5.76202290e-03j, + -0.02168349+1.31762102e-02j, 0.01866758-3.88288993e-04j, + 0.01283417-1.13119330e-02j, -0.00364199+2.12691508e-02j, + -0.01002828-3.81971492e-02j, -0.0201309 +4.63262054e-02j, + 0.00624573-2.12638164e-02j, -0.04300331+4.56514012e-03j, + -0.01674623+4.01859119e-02j, 0.01879401-3.68975748e-02j, + -0.04210754-2.03056271e-02j, 0.01221778+3.55257330e-02j, + 0.02604237+2.40148329e-02j, -0.10126317-2.63587809e-02j, + -0.02555926+2.29115023e-03j, 0.03408207-2.45710819e-02j, + 0.00253765+8.10026137e-03j, 0.01283417-1.13119330e-02j, + 0.00624573-2.12638164e-02j, -0.04210754-2.03056271e-02j, + -0.02555926+2.29115023e-03j, 0.00624573-2.12638164e-02j, + -0.00998988-2.55123201e-02j, 0.00172567+1.71363053e-03j, + 0.01116755-8.58145935e-03j, 0.02296651+2.58150474e-02j, + 0.00172567+1.71363053e-03j, 0.00568722-8.97120460e-03j, + -0.02380459-1.51537614e-02j, 0.0941019 -3.23422643e-02j, + 0.01116755-8.58145935e-03j, -0.01090296+3.25737193e-02j, + 0.00641802-7.67101659e-03j, -0.00700464+3.03791437e-02j, + 0.02296651+2.58150474e-02j, 0.0272914 -5.21209112e-03j, + 0.02244218+7.38399759e-03j, -0.04300331+4.56514012e-03j, + 0.00172567+1.71363053e-03j, 0.01428279-4.83854290e-02j, + -0.01469433-1.53390778e-02j, 0.01192333+1.44386801e-02j, + 0.00568722-8.97120460e-03j, -0.03004111+8.61599384e-03j, + 0.10077743-4.19485017e-02j, 0.05292486-1.58594015e-01j, + -0.02380459-1.51537614e-02j, 0.00892337+4.71213470e-02j, + 0.00453264+1.70332048e-02j, 0.01096824-5.04777498e-03j, + 0.0941019 -3.23422643e-02j, -0.00964648-3.73388811e-02j, + -0.00768092+2.29361852e-02j, -0.01674623+4.01859119e-02j, + 0.01116755-8.58145935e-03j, -0.01469433-1.53390778e-02j, + -0.02740137-1.47984868e-02j, -0.01754544-5.31071685e-03j, + -0.01090296+3.25737193e-02j, 0.00926439+1.15263465e-03j, + -0.04134054+4.07984689e-02j, 0.03495767+5.65770822e-03j, + 0.00641802-7.67101659e-03j, -0.00632533+1.53474785e-02j, + -0.0094759 -2.14561876e-02j, -0.01526814-7.21120895e-03j, + -0.00700464+3.03791437e-02j, 0.03092621-1.59134136e-02j, + 0.03597617-1.85729877e-02j, 0.01879401-3.68975748e-02j, + 0.02296651+2.58150474e-02j, 0.01192333+1.44386801e-02j, + -0.01754544-5.31071685e-03j, -0.0493597 +2.30043110e-02j, + 0.0272914 -5.21209112e-03j, -0.00041774-1.76806932e-02j, + -0.04044471-1.72663937e-02j, 0.01226119+8.62905034e-02j, + 0.02244218+7.38399759e-03j, -0.02059268-1.43735313e-02j, + -0.01380899-5.76202290e-03j, -0.00364199+2.12691508e-02j, + -0.04300331+4.56514012e-03j, 0.01221778+3.55257330e-02j, + 0.03408207-2.45710819e-02j, -0.04210754-2.03056271e-02j, + 0.00172567+1.71363053e-03j, 0.00568722-8.97120460e-03j, + -0.01090296+3.25737193e-02j, 0.0272914 -5.21209112e-03j, + 0.01428279-4.83854290e-02j, -0.03004111+8.61599384e-03j, + 0.00892337+4.71213470e-02j, -0.00964648-3.73388811e-02j, + -0.01469433-1.53390778e-02j, 0.00926439+1.15263465e-03j, + -0.00632533+1.53474785e-02j, 0.03092621-1.59134136e-02j, + 0.01192333+1.44386801e-02j, -0.00041774-1.76806932e-02j, + -0.02059268-1.43735313e-02j, 0.01221778+3.55257330e-02j, + 0.00568722-8.97120460e-03j, -0.03004111+8.61599384e-03j, + 0.00926439+1.15263465e-03j, -0.00041774-1.76806932e-02j, + -0.03004111+8.61599384e-03j, 0.02427846+1.56785055e-02j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE +def test_ghz_n4(): + """ + Test ghz_n4.qasm + """ + vector = get_vector('ghz_n4.qasm') + ref = np.array([0.70710678+0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0.70710678+0.j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE + + +def test_ghz_n8(): + """ + Test ghz_n8.qasm + """ + vector = get_vector('ghz_n8.qasm') + ref = np.array([0.70710678+0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0.70710678+0.j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE + + + +def test_fredkin_n3(): + """ + Test ghz_n4.qasm + """ + vector = get_vector('fredkin_n3.qasm') + ref = np.array([0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 2.36158002e-17+0.j, 0.00000000e+00+0.j, 1.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE + + +def test_qaoa_n3(): + """ + Test qaoa_n3.qasm + """ + vector = get_vector('qaoa_n3.qasm') + ref = np.array([-0.44546064-0.1658815j , -0.16261527-0.26478867j, + -0.16759538-0.09325885j, 0.12584213+0.35336909j, + -0.16261527-0.26478867j, -0.44546064-0.1658815j , + 0.12584213+0.35336909j, -0.16759538-0.09325885j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE + + +def test_qft_n4(): + """ + Test qft_n4.qasm + """ + vector = get_vector('qft_n4.qasm') + ref = np.array([ 2.50000000e-01+0.j , -1.76776695e-01-0.1767767j, + 1.53080850e-17+0.25j , 1.76776695e-01-0.1767767j, + -2.50000000e-01+0.j , 1.76776695e-01+0.1767767j, + -1.53080850e-17-0.25j , -1.76776695e-01+0.1767767j, + 2.50000000e-01+0.j , -1.76776695e-01-0.1767767j, + 1.53080850e-17+0.25j , 1.76776695e-01-0.1767767j, + -2.50000000e-01+0.j , 1.76776695e-01+0.1767767j, + -1.53080850e-17-0.25j , -1.76776695e-01+0.1767767j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE + + +def test_simon_n6(): + """ + Test simon_n6.qasm + """ + vector = get_vector('simon_n6.qasm') + ref = np.array([ 2.50000000e-01+0.j, -2.38105196e-18+0.j, 2.38105196e-18+0.j, + -2.50000000e-01+0.j, 2.50000000e-01+0.j, -2.38105196e-18+0.j, + 2.38105196e-18+0.j, -2.50000000e-01+0.j, 2.50000000e-01+0.j, + 2.38105196e-18+0.j, 2.38105196e-18+0.j, 2.50000000e-01+0.j, + 2.50000000e-01+0.j, 2.38105196e-18+0.j, 2.38105196e-18+0.j, + 2.50000000e-01+0.j, 2.50000000e-01+0.j, 2.38105196e-18+0.j, + 2.38105196e-18+0.j, 2.50000000e-01+0.j, -2.50000000e-01+0.j, + -2.38105196e-18+0.j, -2.38105196e-18+0.j, -2.50000000e-01+0.j, + 2.50000000e-01+0.j, -2.38105196e-18+0.j, 2.38105196e-18+0.j, + -2.50000000e-01+0.j, -2.50000000e-01+0.j, 2.38105196e-18+0.j, + -2.38105196e-18+0.j, 2.50000000e-01+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE + + +def test_vqe_n4(): + """ + Test vqe_n4.qasm + """ + vector = get_vector('vqe_n4.qasm') + ref = np.array([ 0.22310975+0.03591277j, 0.07716044+0.06874446j, + -0.02409975-0.23946403j, -0.1988335 -0.33044344j, + 0.22921453+0.01693273j, 0.03096892-0.16783964j, + -0.17358726-0.19121655j, -0.17475247+0.51206682j, + 0.01452133-0.01450461j, -0.08246217+0.2670658j , + -0.04425131-0.16862705j, -0.11001101+0.04121341j, + -0.01348307+0.03699337j, 0.26031501-0.00411195j, + -0.04888739-0.16588764j, -0.12254994+0.23065344j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE + + +def test_wstate_n3(): + """ + Test wstate_n3.qasm + """ + vector = get_vector('wstate_n3.qasm') + ref = np.array([0.00000000e+00+0.00000000e+00j, 4.08249225e-01+4.08249225e-01j, + 4.08247823e-01+4.08247823e-01j, 4.23739404e-17-4.23739404e-17j, + 4.08247823e-01+4.08247823e-01j, 0.00000000e+00+0.00000000e+00j, + 0.00000000e+00+0.00000000e+00j, 0.00000000e+00+0.00000000e+00j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE From 927bc5f78701181ad51a14ceba2f8c5e8b661063 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Wed, 29 May 2024 13:59:25 +0200 Subject: [PATCH 11/37] by default, sim_qasm simulates gates as given w/o optimizing qubit order --- qasm/sim_qasm.c | 64 ++++++++++++++++++++++++------------------ qasm/simple_parser.cpp | 6 ++-- qasm/simple_parser.h | 2 +- 3 files changed, 42 insertions(+), 30 deletions(-) diff --git a/qasm/sim_qasm.c b/qasm/sim_qasm.c index 2ca223d..3b796cb 100644 --- a/qasm/sim_qasm.c +++ b/qasm/sim_qasm.c @@ -20,6 +20,7 @@ static size_t wgt_tab_size = 1LL<<23; static double tolerance = 1e-14; static int wgt_table_type = COMP_HASHMAP; static int wgt_norm_strat = NORM_LARGEST; +static int reorder_qubits = 0; static char* qasm_inputfile = NULL; static char* json_outputfile = NULL; @@ -33,6 +34,8 @@ static struct argp_option options[] = {"json", 'j', "", 0, "Write stats to given filename as json", 0}, {"count-nodes", 'c', 0, 0, "Track maximum number of nodes", 0}, {"state-vector", 'v', 0, 0, "Also output the complete state vector", 0}, + {"allow-reorder", 10, 0, 0, "Reorders the qubits once such that (most) controls occur before targets in the variable order.", 0}, + {"allow-reorder-swaps", 11, 0, 0, "Reorders the qubits such that all controls occur before targets (requires inserting SWAP gates).", 0}, {0, 0, 0, 0, 0, 0} }; static error_t @@ -63,6 +66,12 @@ parse_opt(int key, char *arg, struct argp_state *state) case 'v': output_vector = true; break; + case 10: + reorder_qubits = 1; + break; + case 11: + reorder_qubits = 2; + break; case ARGP_KEY_ARG: if (state->arg_num >= 1) argp_usage(state); qasm_inputfile = arg; @@ -144,7 +153,7 @@ wctime() } -QMDD apply_gate(QMDD state, quantum_op_t* gate) +QMDD apply_gate(QMDD state, quantum_op_t* gate, BDDVAR nqubits) { // This looks very ugly, but we need some way to match the name of a gate to // the GATEID, and since this is C we don't really have easy access to @@ -204,43 +213,43 @@ QMDD apply_gate(QMDD state, quantum_op_t* gate) return qmdd_gate(state, GATEID_U(gate->angle[0], gate->angle[1], gate->angle[2]), gate->targets[0]); } else if (strcmp(gate->name, "cx") == 0) { - return qmdd_cgate(state, GATEID_X, gate->ctrls[0], gate->targets[0]); + return qmdd_cgate(state, GATEID_X, gate->ctrls[0], gate->targets[0], nqubits); } else if (strcmp(gate->name, "cy") == 0) { - return qmdd_cgate(state, GATEID_Y, gate->ctrls[0], gate->targets[0]); + return qmdd_cgate(state, GATEID_Y, gate->ctrls[0], gate->targets[0], nqubits); } else if (strcmp(gate->name, "cz") == 0) { - return qmdd_cgate(state, GATEID_Z, gate->ctrls[0], gate->targets[0]); + return qmdd_cgate(state, GATEID_Z, gate->ctrls[0], gate->targets[0], nqubits); } else if (strcmp(gate->name, "ch") == 0) { - return qmdd_cgate(state, GATEID_H, gate->ctrls[0], gate->targets[0]); + return qmdd_cgate(state, GATEID_H, gate->ctrls[0], gate->targets[0], nqubits); } else if (strcmp(gate->name, "csx") == 0) { - return qmdd_cgate(state, GATEID_sqrtX, gate->ctrls[0], gate->targets[0]); + return qmdd_cgate(state, GATEID_sqrtX, gate->ctrls[0], gate->targets[0], nqubits); } else if (strcmp(gate->name, "crx") == 0) { - return qmdd_cgate(state, GATEID_Rx(gate->angle[0]), gate->ctrls[0], gate->targets[0]); + return qmdd_cgate(state, GATEID_Rx(gate->angle[0]), gate->ctrls[0], gate->targets[0], nqubits); } else if (strcmp(gate->name, "cry") == 0) { - return qmdd_cgate(state, GATEID_Ry(gate->angle[0]), gate->ctrls[0], gate->targets[0]); + return qmdd_cgate(state, GATEID_Ry(gate->angle[0]), gate->ctrls[0], gate->targets[0], nqubits); } else if (strcmp(gate->name, "crz") == 0) { - return qmdd_cgate(state, GATEID_Rz(gate->angle[0]), gate->ctrls[0], gate->targets[0]); + return qmdd_cgate(state, GATEID_Rz(gate->angle[0]), gate->ctrls[0], gate->targets[0], nqubits); } else if (strcmp(gate->name, "cp") == 0) { - return qmdd_cgate(state, GATEID_Phase(gate->angle[0]), gate->ctrls[0], gate->targets[0]); + return qmdd_cgate(state, GATEID_Phase(gate->angle[0]), gate->ctrls[0], gate->targets[0], nqubits); } else if (strcmp(gate->name, "cu") == 0) { - return qmdd_cgate(state, GATEID_U(gate->angle[0], gate->angle[1], gate->angle[2]), gate->ctrls[0], gate->targets[0]); + return qmdd_cgate(state, GATEID_U(gate->angle[0], gate->angle[1], gate->angle[2]), gate->ctrls[0], gate->targets[0], nqubits); } else if (strcmp(gate->name, "ccx") == 0) { - return qmdd_cgate2(state, GATEID_X, gate->ctrls[0], gate->ctrls[1], gate->targets[0]); + return qmdd_cgate2(state, GATEID_X, gate->ctrls[0], gate->ctrls[1], gate->targets[0], nqubits); } else if (strcmp(gate->name, "c3x") == 0) { - return qmdd_cgate3(state, GATEID_X, gate->ctrls[0], gate->ctrls[1], gate->ctrls[2], gate->targets[0]); + return qmdd_cgate3(state, GATEID_X, gate->ctrls[0], gate->ctrls[1], gate->ctrls[2], gate->targets[0], nqubits); } else if (strcmp(gate->name, "c3sx") == 0) { - return qmdd_cgate3(state, GATEID_sqrtX, gate->ctrls[0], gate->ctrls[1], gate->ctrls[2], gate->targets[0]); + return qmdd_cgate3(state, GATEID_sqrtX, gate->ctrls[0], gate->ctrls[1], gate->ctrls[2], gate->targets[0], nqubits); } else if (strcmp(gate->name, "swap") == 0) { // no native SWAP gates in Q-Sylvan @@ -251,30 +260,30 @@ QMDD apply_gate(QMDD state, quantum_op_t* gate) // no native CSWAP gates in Q-Sylvan stats.applied_gates += 4; // CCNOT - state = qmdd_cgate2(state, GATEID_X, gate->ctrls[0], gate->targets[0], gate->targets[1]); + state = qmdd_cgate2(state, GATEID_X, gate->ctrls[0], gate->targets[0], gate->targets[1], nqubits); // upside down CCNOT (equivalent) - state = qmdd_cgate(state, GATEID_H, gate->ctrls[0], gate->targets[0]); - state = qmdd_cgate2(state, GATEID_Z, gate->ctrls[0], gate->targets[0], gate->targets[1]); - state = qmdd_cgate(state, GATEID_H, gate->ctrls[0], gate->targets[0]); + state = qmdd_cgate(state, GATEID_H, gate->ctrls[0], gate->targets[0], nqubits); + state = qmdd_cgate2(state, GATEID_Z, gate->ctrls[0], gate->targets[0], gate->targets[1], nqubits); + state = qmdd_cgate(state, GATEID_H, gate->ctrls[0], gate->targets[0], nqubits); // CCNOT - state = qmdd_cgate2(state, GATEID_X, gate->ctrls[0], gate->targets[0], gate->targets[1]); + state = qmdd_cgate2(state, GATEID_X, gate->ctrls[0], gate->targets[0], gate->targets[1], nqubits); return state; } else if (strcmp(gate->name, "rccx") == 0) { // no native RCCX (simplified Toffoli) gates in Q-Sylvan stats.applied_gates += 3; - state = qmdd_cgate2(state, GATEID_X, gate->ctrls[0], gate->ctrls[1], gate->targets[0]); + state = qmdd_cgate2(state, GATEID_X, gate->ctrls[0], gate->ctrls[1], gate->targets[0], nqubits); state = qmdd_gate(state, GATEID_X, gate->ctrls[1]); - state = qmdd_cgate2(state, GATEID_Z, gate->ctrls[0], gate->ctrls[1], gate->targets[0]); + state = qmdd_cgate2(state, GATEID_Z, gate->ctrls[0], gate->ctrls[1], gate->targets[0], nqubits); state = qmdd_gate(state, GATEID_X, gate->ctrls[1]); return state; } else if (strcmp(gate->name, "rzz") == 0 ) { // no native RZZ gates in Q-Sylvan stats.applied_gates += 2; - state = qmdd_cgate(state, GATEID_X, gate->targets[0], gate->targets[1]); + state = qmdd_cgate(state, GATEID_X, gate->targets[0], gate->targets[1], nqubits); state = qmdd_gate(state, GATEID_Phase(gate->angle[0]), gate->targets[1]); - state = qmdd_cgate(state, GATEID_X, gate->targets[0], gate->targets[1]); + state = qmdd_cgate(state, GATEID_X, gate->targets[0], gate->targets[1], nqubits); return state; } else if (strcmp(gate->name, "rxx") == 0) { @@ -283,9 +292,9 @@ QMDD apply_gate(QMDD state, quantum_op_t* gate) stats.applied_gates += 6; state = qmdd_gate(state, GATEID_U(pi/2.0, gate->angle[0], 0), gate->targets[0]); state = qmdd_gate(state, GATEID_H, gate->targets[1]); - state = qmdd_cgate(state, GATEID_X, gate->targets[0], gate->targets[1]); + state = qmdd_cgate(state, GATEID_X, gate->targets[0], gate->targets[1], nqubits); state = qmdd_gate(state, GATEID_Phase(-(gate->angle[0])), gate->targets[1]); - state = qmdd_cgate(state, GATEID_X, gate->targets[0], gate->targets[1]); + state = qmdd_cgate(state, GATEID_X, gate->targets[0], gate->targets[1], nqubits); state = qmdd_gate(state, GATEID_H, gate->targets[1]); state = qmdd_gate(state, GATEID_U(pi/2.0, -pi, pi-gate->angle[0]), gate->targets[0]); return state; @@ -315,7 +324,7 @@ void simulate_circuit(quantum_circuit_t* circuit) quantum_op_t *op = circuit->operations; while (op != NULL) { if (op->type == op_gate) { - state = apply_gate(state, op); + state = apply_gate(state, op, circuit->qreg_size); } else if (op->type == op_measurement) { if (circuit->has_intermediate_measurements) { @@ -349,7 +358,8 @@ int main(int argc, char *argv[]) { argp_parse(&argp, argc, argv, 0, 0, 0); quantum_circuit_t* circuit = parse_qasm_file(qasm_inputfile); - optimize_qubit_order(circuit); + if (reorder_qubits) + optimize_qubit_order(circuit, reorder_qubits == 2); if (rseed == 0) rseed = time(NULL); srand(rseed); diff --git a/qasm/simple_parser.cpp b/qasm/simple_parser.cpp index 726710f..53c79a6 100644 --- a/qasm/simple_parser.cpp +++ b/qasm/simple_parser.cpp @@ -664,7 +664,7 @@ void reverse_order(quantum_circuit_t *circuit) } -void optimize_qubit_order(quantum_circuit_t *circuit) +void optimize_qubit_order(quantum_circuit_t *circuit, bool allow_swaps) { order_cphase_gates(circuit); // order phase gates before counting quantum_op_t* head = circuit->operations; @@ -684,7 +684,9 @@ void optimize_qubit_order(quantum_circuit_t *circuit) reverse_order(circuit); order_cphase_gates(circuit); // order phase gates again } - insert_required_swaps(circuit); + if (allow_swaps) { + insert_required_swaps(circuit); + } } diff --git a/qasm/simple_parser.h b/qasm/simple_parser.h index 85bc2d8..085e991 100644 --- a/qasm/simple_parser.h +++ b/qasm/simple_parser.h @@ -39,7 +39,7 @@ quantum_circuit_t* parse_qasm_file(char *filepath); /** * Invert qubit order if that yields less controls below target qubits. */ -void optimize_qubit_order(quantum_circuit_t *circuit); +void optimize_qubit_order(quantum_circuit_t *circuit, bool allow_swaps); /** * free()'s all quantum_ops from and including 'first'. From c60df1bceb7b95a020326df18495a4d55e4d8532 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Wed, 29 May 2024 14:02:55 +0200 Subject: [PATCH 12/37] run sim_qasm test cases for different arguments --- qasm/circuits/ghz_n8.qasm | 14 +- qasm/test/test_sim_qasm.py | 690 +++++++++++++++++++------------------ 2 files changed, 355 insertions(+), 349 deletions(-) diff --git a/qasm/circuits/ghz_n8.qasm b/qasm/circuits/ghz_n8.qasm index 6ff5559..cfe38ca 100644 --- a/qasm/circuits/ghz_n8.qasm +++ b/qasm/circuits/ghz_n8.qasm @@ -2,14 +2,14 @@ OPENQASM 2.0; include "qelib1.inc"; qreg q[8]; creg meas[8]; -h q[0]; -cx q[0],q[1]; -cx q[1],q[2]; -cx q[2],q[3]; -cx q[3],q[4]; +h q[4]; +cx q[4],q[0]; +cx q[4],q[1]; +cx q[4],q[2]; +cx q[4],q[3]; cx q[4],q[5]; -cx q[5],q[6]; -cx q[6],q[7]; +cx q[4],q[6]; +cx q[4],q[7]; barrier q[0],q[1],q[2],q[3],q[4],q[5],q[6],q[7]; measure q[0] -> meas[0]; measure q[1] -> meas[1]; diff --git a/qasm/test/test_sim_qasm.py b/qasm/test/test_sim_qasm.py index c961e88..f757310 100644 --- a/qasm/test/test_sim_qasm.py +++ b/qasm/test/test_sim_qasm.py @@ -5,6 +5,7 @@ import subprocess import json import numpy as np +import pytest TOLERANCE = 1e-6 @@ -17,371 +18,376 @@ def fidelity(a, b): Compute the fidelity of two vectors. """ in_prod = np.dot(a.conj().T, b) - fidelity = (abs(in_prod))**2 - return fidelity + return (abs(in_prod))**2 -def get_vector(qasm_file : str): +def get_vector(qasm_file : str, args : list): """ Simulate given quantum circuit and return state vector. """ filepath = os.path.join(QASM_DIR, qasm_file) - output = subprocess.run([SIM_QASM, '--state-vector', filepath], - stdout=subprocess.PIPE) + output = subprocess.run([SIM_QASM, filepath, '--state-vector', *args], + stdout=subprocess.PIPE, check=False) data = json.loads(output.stdout) vector = np.apply_along_axis(lambda args: [complex(*args)], 1, data['state_vector']).flatten() return vector -def test_adder_n4(): +@pytest.mark.parametrize("cl_args", [[], ["--allow-reorder"], ["--allow-reorder-swap"]]) +class TestCircuits: """ - Test adder_n4.qasm + Test sim_qasm on all given circuits, with CL arguments given above. """ - vector = get_vector('adder_n4.qasm') - ref = np.array([0.00000000e+00+0.j, 2.36158002e-17+0.j, 0.00000000e+00+0.j, - 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, - 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, - 1.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, - 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, - 0.00000000e+00+0.j]) - assert abs(fidelity(vector, ref) - 1) < TOLERANCE + def test_adder_n4(self, cl_args : str): + """ + Test adder_n4.qasm + """ + vector = get_vector('adder_n4.qasm', cl_args) + ref = np.array([0.00000000e+00+0.j, 2.36158002e-17+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 1.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE -def test_basis_change_n3(): - """ - Test basis_change_n3.qasm - """ - vector = get_vector('basis_change_n3.qasm') - ref = np.array([ 9.06686370e-01-4.21805437e-01j, 3.21841592e-16+3.59799267e-16j, - 1.96261557e-16+3.14018492e-16j, -3.50542195e-18-1.10979812e-17j, - 3.32473560e-16-1.96808529e-16j, -1.82945633e-17-1.03747177e-17j, - -3.85650646e-17-1.11262893e-16j, 1.17333381e-17+7.41092244e-18j]) - assert abs(fidelity(vector, ref) - 1) < TOLERANCE + def test_basis_change_n3(self, cl_args : str): + """ + Test basis_change_n3.qasm + """ + vector = get_vector('basis_change_n3.qasm', cl_args) + ref = np.array([ 9.06686370e-01-4.21805437e-01j, 3.21841592e-16+3.59799267e-16j, + 1.96261557e-16+3.14018492e-16j, -3.50542195e-18-1.10979812e-17j, + 3.32473560e-16-1.96808529e-16j, -1.82945633e-17-1.03747177e-17j, + -3.85650646e-17-1.11262893e-16j, 1.17333381e-17+7.41092244e-18j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE -def test_bell_state(): - """ - Test bell_state.qasm - """ - vector = get_vector('bell_state.qasm') - ref = np.array([0+0j, 0.70710678+0j, 0.70710678+0j, 0+0j]) - assert abs(fidelity(vector, ref) - 1) < TOLERANCE + def test_bell_state(self, cl_args : str): + """ + Test bell_state.qasm + """ + vector = get_vector('bell_state.qasm', cl_args) + ref = np.array([0+0j, 0.70710678+0j, 0.70710678+0j, 0+0j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE -def test_dnn_n8(): - """ - Test dnn_n8.qasm - """ - vector = get_vector('dnn_n8.qasm') - ref = np.array([ 0.12641004+5.31293856e-01j, -0.07648447-3.72236104e-02j, - -0.06822525-1.20937515e-01j, 0.10077743-4.19485017e-02j, - -0.07648447-3.72236104e-02j, 0.09757202-1.17331258e-02j, - 0.0109432 +1.40583012e-01j, 0.05292486-1.58594015e-01j, - -0.06822525-1.20937515e-01j, 0.03204555-1.57138851e-02j, - 0.02604237+2.40148329e-02j, -0.02380459-1.51537614e-02j, - 0.10077743-4.19485017e-02j, -0.04134054+4.07984689e-02j, - -0.04044471-1.72663937e-02j, 0.00892337+4.71213470e-02j, - -0.07648447-3.72236104e-02j, 0.01673732+3.79095110e-03j, - 0.01324859-2.51813525e-02j, 0.00453264+1.70332048e-02j, - 0.09757202-1.17331258e-02j, -0.00615046+2.18937245e-02j, - -0.03070889+2.04780306e-02j, 0.01096824-5.04777498e-03j, - 0.0109432 +1.40583012e-01j, 0.01168173+2.52999889e-03j, - -0.10126317-2.63587809e-02j, 0.0941019 -3.23422643e-02j, - 0.05292486-1.58594015e-01j, 0.03495767+5.65770822e-03j, - 0.01226119+8.62905034e-02j, -0.00964648-3.73388811e-02j, - -0.06822525-1.20937515e-01j, 0.01324859-2.51813525e-02j, - 0.01275733+2.44040989e-02j, -0.00768092+2.29361852e-02j, - 0.03204555-1.57138851e-02j, -0.02168349+1.31762102e-02j, - -0.01002828-3.81971492e-02j, -0.01674623+4.01859119e-02j, - 0.02604237+2.40148329e-02j, 0.00253765+8.10026137e-03j, - -0.02555926+2.29115023e-03j, 0.01116755-8.58145935e-03j, - -0.02380459-1.51537614e-02j, 0.00641802-7.67101659e-03j, - 0.02244218+7.38399759e-03j, -0.01469433-1.53390778e-02j, - 0.10077743-4.19485017e-02j, 0.00453264+1.70332048e-02j, - -0.00768092+2.29361852e-02j, -0.02740137-1.47984868e-02j, - -0.04134054+4.07984689e-02j, -0.0094759 -2.14561876e-02j, - 0.03597617-1.85729877e-02j, -0.01754544-5.31071685e-03j, - -0.04044471-1.72663937e-02j, -0.01380899-5.76202290e-03j, - 0.03408207-2.45710819e-02j, -0.01090296+3.25737193e-02j, - 0.00892337+4.71213470e-02j, -0.00632533+1.53474785e-02j, - -0.02059268-1.43735313e-02j, 0.00926439+1.15263465e-03j, - -0.07648447-3.72236104e-02j, 0.09757202-1.17331258e-02j, - 0.03204555-1.57138851e-02j, -0.04134054+4.07984689e-02j, - 0.01673732+3.79095110e-03j, -0.00615046+2.18937245e-02j, - 0.01168173+2.52999889e-03j, 0.03495767+5.65770822e-03j, - 0.01324859-2.51813525e-02j, -0.02168349+1.31762102e-02j, - 0.00253765+8.10026137e-03j, 0.00641802-7.67101659e-03j, - 0.00453264+1.70332048e-02j, -0.0094759 -2.14561876e-02j, - -0.01380899-5.76202290e-03j, -0.00632533+1.53474785e-02j, - 0.09757202-1.17331258e-02j, -0.00615046+2.18937245e-02j, - -0.02168349+1.31762102e-02j, -0.0094759 -2.14561876e-02j, - -0.00615046+2.18937245e-02j, -0.00212947-3.34982299e-02j, - 0.01866758-3.88288993e-04j, -0.01526814-7.21120895e-03j, - -0.03070889+2.04780306e-02j, 0.01866758-3.88288993e-04j, - 0.01283417-1.13119330e-02j, -0.00700464+3.03791437e-02j, - 0.01096824-5.04777498e-03j, -0.01526814-7.21120895e-03j, - -0.00364199+2.12691508e-02j, 0.03092621-1.59134136e-02j, - 0.0109432 +1.40583012e-01j, -0.03070889+2.04780306e-02j, - -0.01002828-3.81971492e-02j, 0.03597617-1.85729877e-02j, - 0.01168173+2.52999889e-03j, 0.01866758-3.88288993e-04j, - -0.0201309 +4.63262054e-02j, 0.01879401-3.68975748e-02j, - -0.10126317-2.63587809e-02j, 0.01283417-1.13119330e-02j, - 0.00624573-2.12638164e-02j, 0.02296651+2.58150474e-02j, - 0.0941019 -3.23422643e-02j, -0.00700464+3.03791437e-02j, - -0.04300331+4.56514012e-03j, 0.01192333+1.44386801e-02j, - 0.05292486-1.58594015e-01j, 0.01096824-5.04777498e-03j, - -0.01674623+4.01859119e-02j, -0.01754544-5.31071685e-03j, - 0.03495767+5.65770822e-03j, -0.01526814-7.21120895e-03j, - 0.01879401-3.68975748e-02j, -0.0493597 +2.30043110e-02j, - 0.01226119+8.62905034e-02j, -0.00364199+2.12691508e-02j, - -0.04210754-2.03056271e-02j, 0.0272914 -5.21209112e-03j, - -0.00964648-3.73388811e-02j, 0.03092621-1.59134136e-02j, - 0.01221778+3.55257330e-02j, -0.00041774-1.76806932e-02j, - -0.06822525-1.20937515e-01j, 0.0109432 +1.40583012e-01j, - 0.02604237+2.40148329e-02j, -0.04044471-1.72663937e-02j, - 0.01324859-2.51813525e-02j, -0.03070889+2.04780306e-02j, - -0.10126317-2.63587809e-02j, 0.01226119+8.62905034e-02j, - 0.01275733+2.44040989e-02j, -0.01002828-3.81971492e-02j, - -0.02555926+2.29115023e-03j, 0.02244218+7.38399759e-03j, - -0.00768092+2.29361852e-02j, 0.03597617-1.85729877e-02j, - 0.03408207-2.45710819e-02j, -0.02059268-1.43735313e-02j, - 0.03204555-1.57138851e-02j, 0.01168173+2.52999889e-03j, - 0.00253765+8.10026137e-03j, -0.01380899-5.76202290e-03j, - -0.02168349+1.31762102e-02j, 0.01866758-3.88288993e-04j, - 0.01283417-1.13119330e-02j, -0.00364199+2.12691508e-02j, - -0.01002828-3.81971492e-02j, -0.0201309 +4.63262054e-02j, - 0.00624573-2.12638164e-02j, -0.04300331+4.56514012e-03j, - -0.01674623+4.01859119e-02j, 0.01879401-3.68975748e-02j, - -0.04210754-2.03056271e-02j, 0.01221778+3.55257330e-02j, - 0.02604237+2.40148329e-02j, -0.10126317-2.63587809e-02j, - -0.02555926+2.29115023e-03j, 0.03408207-2.45710819e-02j, - 0.00253765+8.10026137e-03j, 0.01283417-1.13119330e-02j, - 0.00624573-2.12638164e-02j, -0.04210754-2.03056271e-02j, - -0.02555926+2.29115023e-03j, 0.00624573-2.12638164e-02j, - -0.00998988-2.55123201e-02j, 0.00172567+1.71363053e-03j, - 0.01116755-8.58145935e-03j, 0.02296651+2.58150474e-02j, - 0.00172567+1.71363053e-03j, 0.00568722-8.97120460e-03j, - -0.02380459-1.51537614e-02j, 0.0941019 -3.23422643e-02j, - 0.01116755-8.58145935e-03j, -0.01090296+3.25737193e-02j, - 0.00641802-7.67101659e-03j, -0.00700464+3.03791437e-02j, - 0.02296651+2.58150474e-02j, 0.0272914 -5.21209112e-03j, - 0.02244218+7.38399759e-03j, -0.04300331+4.56514012e-03j, - 0.00172567+1.71363053e-03j, 0.01428279-4.83854290e-02j, - -0.01469433-1.53390778e-02j, 0.01192333+1.44386801e-02j, - 0.00568722-8.97120460e-03j, -0.03004111+8.61599384e-03j, - 0.10077743-4.19485017e-02j, 0.05292486-1.58594015e-01j, - -0.02380459-1.51537614e-02j, 0.00892337+4.71213470e-02j, - 0.00453264+1.70332048e-02j, 0.01096824-5.04777498e-03j, - 0.0941019 -3.23422643e-02j, -0.00964648-3.73388811e-02j, - -0.00768092+2.29361852e-02j, -0.01674623+4.01859119e-02j, - 0.01116755-8.58145935e-03j, -0.01469433-1.53390778e-02j, - -0.02740137-1.47984868e-02j, -0.01754544-5.31071685e-03j, - -0.01090296+3.25737193e-02j, 0.00926439+1.15263465e-03j, - -0.04134054+4.07984689e-02j, 0.03495767+5.65770822e-03j, - 0.00641802-7.67101659e-03j, -0.00632533+1.53474785e-02j, - -0.0094759 -2.14561876e-02j, -0.01526814-7.21120895e-03j, - -0.00700464+3.03791437e-02j, 0.03092621-1.59134136e-02j, - 0.03597617-1.85729877e-02j, 0.01879401-3.68975748e-02j, - 0.02296651+2.58150474e-02j, 0.01192333+1.44386801e-02j, - -0.01754544-5.31071685e-03j, -0.0493597 +2.30043110e-02j, - 0.0272914 -5.21209112e-03j, -0.00041774-1.76806932e-02j, - -0.04044471-1.72663937e-02j, 0.01226119+8.62905034e-02j, - 0.02244218+7.38399759e-03j, -0.02059268-1.43735313e-02j, - -0.01380899-5.76202290e-03j, -0.00364199+2.12691508e-02j, - -0.04300331+4.56514012e-03j, 0.01221778+3.55257330e-02j, - 0.03408207-2.45710819e-02j, -0.04210754-2.03056271e-02j, - 0.00172567+1.71363053e-03j, 0.00568722-8.97120460e-03j, - -0.01090296+3.25737193e-02j, 0.0272914 -5.21209112e-03j, - 0.01428279-4.83854290e-02j, -0.03004111+8.61599384e-03j, - 0.00892337+4.71213470e-02j, -0.00964648-3.73388811e-02j, - -0.01469433-1.53390778e-02j, 0.00926439+1.15263465e-03j, - -0.00632533+1.53474785e-02j, 0.03092621-1.59134136e-02j, - 0.01192333+1.44386801e-02j, -0.00041774-1.76806932e-02j, - -0.02059268-1.43735313e-02j, 0.01221778+3.55257330e-02j, - 0.00568722-8.97120460e-03j, -0.03004111+8.61599384e-03j, - 0.00926439+1.15263465e-03j, -0.00041774-1.76806932e-02j, - -0.03004111+8.61599384e-03j, 0.02427846+1.56785055e-02j]) - assert abs(fidelity(vector, ref) - 1) < TOLERANCE - - -def test_ghz_n4(): - """ - Test ghz_n4.qasm - """ - vector = get_vector('ghz_n4.qasm') - ref = np.array([0.70710678+0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0.70710678+0.j]) - assert abs(fidelity(vector, ref) - 1) < TOLERANCE + def test_dnn_n8(self, cl_args : str): + """ + Test dnn_n8.qasm + """ + vector = get_vector('dnn_n8.qasm', cl_args) + ref = np.array([ 0.12641004+5.31293856e-01j, -0.07648447-3.72236104e-02j, + -0.06822525-1.20937515e-01j, 0.10077743-4.19485017e-02j, + -0.07648447-3.72236104e-02j, 0.09757202-1.17331258e-02j, + 0.0109432 +1.40583012e-01j, 0.05292486-1.58594015e-01j, + -0.06822525-1.20937515e-01j, 0.03204555-1.57138851e-02j, + 0.02604237+2.40148329e-02j, -0.02380459-1.51537614e-02j, + 0.10077743-4.19485017e-02j, -0.04134054+4.07984689e-02j, + -0.04044471-1.72663937e-02j, 0.00892337+4.71213470e-02j, + -0.07648447-3.72236104e-02j, 0.01673732+3.79095110e-03j, + 0.01324859-2.51813525e-02j, 0.00453264+1.70332048e-02j, + 0.09757202-1.17331258e-02j, -0.00615046+2.18937245e-02j, + -0.03070889+2.04780306e-02j, 0.01096824-5.04777498e-03j, + 0.0109432 +1.40583012e-01j, 0.01168173+2.52999889e-03j, + -0.10126317-2.63587809e-02j, 0.0941019 -3.23422643e-02j, + 0.05292486-1.58594015e-01j, 0.03495767+5.65770822e-03j, + 0.01226119+8.62905034e-02j, -0.00964648-3.73388811e-02j, + -0.06822525-1.20937515e-01j, 0.01324859-2.51813525e-02j, + 0.01275733+2.44040989e-02j, -0.00768092+2.29361852e-02j, + 0.03204555-1.57138851e-02j, -0.02168349+1.31762102e-02j, + -0.01002828-3.81971492e-02j, -0.01674623+4.01859119e-02j, + 0.02604237+2.40148329e-02j, 0.00253765+8.10026137e-03j, + -0.02555926+2.29115023e-03j, 0.01116755-8.58145935e-03j, + -0.02380459-1.51537614e-02j, 0.00641802-7.67101659e-03j, + 0.02244218+7.38399759e-03j, -0.01469433-1.53390778e-02j, + 0.10077743-4.19485017e-02j, 0.00453264+1.70332048e-02j, + -0.00768092+2.29361852e-02j, -0.02740137-1.47984868e-02j, + -0.04134054+4.07984689e-02j, -0.0094759 -2.14561876e-02j, + 0.03597617-1.85729877e-02j, -0.01754544-5.31071685e-03j, + -0.04044471-1.72663937e-02j, -0.01380899-5.76202290e-03j, + 0.03408207-2.45710819e-02j, -0.01090296+3.25737193e-02j, + 0.00892337+4.71213470e-02j, -0.00632533+1.53474785e-02j, + -0.02059268-1.43735313e-02j, 0.00926439+1.15263465e-03j, + -0.07648447-3.72236104e-02j, 0.09757202-1.17331258e-02j, + 0.03204555-1.57138851e-02j, -0.04134054+4.07984689e-02j, + 0.01673732+3.79095110e-03j, -0.00615046+2.18937245e-02j, + 0.01168173+2.52999889e-03j, 0.03495767+5.65770822e-03j, + 0.01324859-2.51813525e-02j, -0.02168349+1.31762102e-02j, + 0.00253765+8.10026137e-03j, 0.00641802-7.67101659e-03j, + 0.00453264+1.70332048e-02j, -0.0094759 -2.14561876e-02j, + -0.01380899-5.76202290e-03j, -0.00632533+1.53474785e-02j, + 0.09757202-1.17331258e-02j, -0.00615046+2.18937245e-02j, + -0.02168349+1.31762102e-02j, -0.0094759 -2.14561876e-02j, + -0.00615046+2.18937245e-02j, -0.00212947-3.34982299e-02j, + 0.01866758-3.88288993e-04j, -0.01526814-7.21120895e-03j, + -0.03070889+2.04780306e-02j, 0.01866758-3.88288993e-04j, + 0.01283417-1.13119330e-02j, -0.00700464+3.03791437e-02j, + 0.01096824-5.04777498e-03j, -0.01526814-7.21120895e-03j, + -0.00364199+2.12691508e-02j, 0.03092621-1.59134136e-02j, + 0.0109432 +1.40583012e-01j, -0.03070889+2.04780306e-02j, + -0.01002828-3.81971492e-02j, 0.03597617-1.85729877e-02j, + 0.01168173+2.52999889e-03j, 0.01866758-3.88288993e-04j, + -0.0201309 +4.63262054e-02j, 0.01879401-3.68975748e-02j, + -0.10126317-2.63587809e-02j, 0.01283417-1.13119330e-02j, + 0.00624573-2.12638164e-02j, 0.02296651+2.58150474e-02j, + 0.0941019 -3.23422643e-02j, -0.00700464+3.03791437e-02j, + -0.04300331+4.56514012e-03j, 0.01192333+1.44386801e-02j, + 0.05292486-1.58594015e-01j, 0.01096824-5.04777498e-03j, + -0.01674623+4.01859119e-02j, -0.01754544-5.31071685e-03j, + 0.03495767+5.65770822e-03j, -0.01526814-7.21120895e-03j, + 0.01879401-3.68975748e-02j, -0.0493597 +2.30043110e-02j, + 0.01226119+8.62905034e-02j, -0.00364199+2.12691508e-02j, + -0.04210754-2.03056271e-02j, 0.0272914 -5.21209112e-03j, + -0.00964648-3.73388811e-02j, 0.03092621-1.59134136e-02j, + 0.01221778+3.55257330e-02j, -0.00041774-1.76806932e-02j, + -0.06822525-1.20937515e-01j, 0.0109432 +1.40583012e-01j, + 0.02604237+2.40148329e-02j, -0.04044471-1.72663937e-02j, + 0.01324859-2.51813525e-02j, -0.03070889+2.04780306e-02j, + -0.10126317-2.63587809e-02j, 0.01226119+8.62905034e-02j, + 0.01275733+2.44040989e-02j, -0.01002828-3.81971492e-02j, + -0.02555926+2.29115023e-03j, 0.02244218+7.38399759e-03j, + -0.00768092+2.29361852e-02j, 0.03597617-1.85729877e-02j, + 0.03408207-2.45710819e-02j, -0.02059268-1.43735313e-02j, + 0.03204555-1.57138851e-02j, 0.01168173+2.52999889e-03j, + 0.00253765+8.10026137e-03j, -0.01380899-5.76202290e-03j, + -0.02168349+1.31762102e-02j, 0.01866758-3.88288993e-04j, + 0.01283417-1.13119330e-02j, -0.00364199+2.12691508e-02j, + -0.01002828-3.81971492e-02j, -0.0201309 +4.63262054e-02j, + 0.00624573-2.12638164e-02j, -0.04300331+4.56514012e-03j, + -0.01674623+4.01859119e-02j, 0.01879401-3.68975748e-02j, + -0.04210754-2.03056271e-02j, 0.01221778+3.55257330e-02j, + 0.02604237+2.40148329e-02j, -0.10126317-2.63587809e-02j, + -0.02555926+2.29115023e-03j, 0.03408207-2.45710819e-02j, + 0.00253765+8.10026137e-03j, 0.01283417-1.13119330e-02j, + 0.00624573-2.12638164e-02j, -0.04210754-2.03056271e-02j, + -0.02555926+2.29115023e-03j, 0.00624573-2.12638164e-02j, + -0.00998988-2.55123201e-02j, 0.00172567+1.71363053e-03j, + 0.01116755-8.58145935e-03j, 0.02296651+2.58150474e-02j, + 0.00172567+1.71363053e-03j, 0.00568722-8.97120460e-03j, + -0.02380459-1.51537614e-02j, 0.0941019 -3.23422643e-02j, + 0.01116755-8.58145935e-03j, -0.01090296+3.25737193e-02j, + 0.00641802-7.67101659e-03j, -0.00700464+3.03791437e-02j, + 0.02296651+2.58150474e-02j, 0.0272914 -5.21209112e-03j, + 0.02244218+7.38399759e-03j, -0.04300331+4.56514012e-03j, + 0.00172567+1.71363053e-03j, 0.01428279-4.83854290e-02j, + -0.01469433-1.53390778e-02j, 0.01192333+1.44386801e-02j, + 0.00568722-8.97120460e-03j, -0.03004111+8.61599384e-03j, + 0.10077743-4.19485017e-02j, 0.05292486-1.58594015e-01j, + -0.02380459-1.51537614e-02j, 0.00892337+4.71213470e-02j, + 0.00453264+1.70332048e-02j, 0.01096824-5.04777498e-03j, + 0.0941019 -3.23422643e-02j, -0.00964648-3.73388811e-02j, + -0.00768092+2.29361852e-02j, -0.01674623+4.01859119e-02j, + 0.01116755-8.58145935e-03j, -0.01469433-1.53390778e-02j, + -0.02740137-1.47984868e-02j, -0.01754544-5.31071685e-03j, + -0.01090296+3.25737193e-02j, 0.00926439+1.15263465e-03j, + -0.04134054+4.07984689e-02j, 0.03495767+5.65770822e-03j, + 0.00641802-7.67101659e-03j, -0.00632533+1.53474785e-02j, + -0.0094759 -2.14561876e-02j, -0.01526814-7.21120895e-03j, + -0.00700464+3.03791437e-02j, 0.03092621-1.59134136e-02j, + 0.03597617-1.85729877e-02j, 0.01879401-3.68975748e-02j, + 0.02296651+2.58150474e-02j, 0.01192333+1.44386801e-02j, + -0.01754544-5.31071685e-03j, -0.0493597 +2.30043110e-02j, + 0.0272914 -5.21209112e-03j, -0.00041774-1.76806932e-02j, + -0.04044471-1.72663937e-02j, 0.01226119+8.62905034e-02j, + 0.02244218+7.38399759e-03j, -0.02059268-1.43735313e-02j, + -0.01380899-5.76202290e-03j, -0.00364199+2.12691508e-02j, + -0.04300331+4.56514012e-03j, 0.01221778+3.55257330e-02j, + 0.03408207-2.45710819e-02j, -0.04210754-2.03056271e-02j, + 0.00172567+1.71363053e-03j, 0.00568722-8.97120460e-03j, + -0.01090296+3.25737193e-02j, 0.0272914 -5.21209112e-03j, + 0.01428279-4.83854290e-02j, -0.03004111+8.61599384e-03j, + 0.00892337+4.71213470e-02j, -0.00964648-3.73388811e-02j, + -0.01469433-1.53390778e-02j, 0.00926439+1.15263465e-03j, + -0.00632533+1.53474785e-02j, 0.03092621-1.59134136e-02j, + 0.01192333+1.44386801e-02j, -0.00041774-1.76806932e-02j, + -0.02059268-1.43735313e-02j, 0.01221778+3.55257330e-02j, + 0.00568722-8.97120460e-03j, -0.03004111+8.61599384e-03j, + 0.00926439+1.15263465e-03j, -0.00041774-1.76806932e-02j, + -0.03004111+8.61599384e-03j, 0.02427846+1.56785055e-02j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE -def test_ghz_n8(): - """ - Test ghz_n8.qasm - """ - vector = get_vector('ghz_n8.qasm') - ref = np.array([0.70710678+0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j, 0. +0.j, 0.70710678+0.j]) - assert abs(fidelity(vector, ref) - 1) < TOLERANCE - - - -def test_fredkin_n3(): - """ - Test ghz_n4.qasm - """ - vector = get_vector('fredkin_n3.qasm') - ref = np.array([0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, - 2.36158002e-17+0.j, 0.00000000e+00+0.j, 1.00000000e+00+0.j, - 0.00000000e+00+0.j, 0.00000000e+00+0.j]) - assert abs(fidelity(vector, ref) - 1) < TOLERANCE + def test_ghz_n4(self, cl_args : str): + """ + Test ghz_n4.qasm + """ + vector = get_vector('ghz_n4.qasm', cl_args) + ref = np.array([0.70710678+0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0.70710678+0.j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE -def test_qaoa_n3(): - """ - Test qaoa_n3.qasm - """ - vector = get_vector('qaoa_n3.qasm') - ref = np.array([-0.44546064-0.1658815j , -0.16261527-0.26478867j, - -0.16759538-0.09325885j, 0.12584213+0.35336909j, - -0.16261527-0.26478867j, -0.44546064-0.1658815j , - 0.12584213+0.35336909j, -0.16759538-0.09325885j]) - assert abs(fidelity(vector, ref) - 1) < TOLERANCE + def test_ghz_n8(self, cl_args : str): + """ + Test ghz_n8.qasm + """ + vector = get_vector('ghz_n8.qasm', cl_args) + ref = np.array([0.70710678+0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j, 0. +0.j, 0.70710678+0.j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE -def test_qft_n4(): - """ - Test qft_n4.qasm - """ - vector = get_vector('qft_n4.qasm') - ref = np.array([ 2.50000000e-01+0.j , -1.76776695e-01-0.1767767j, - 1.53080850e-17+0.25j , 1.76776695e-01-0.1767767j, - -2.50000000e-01+0.j , 1.76776695e-01+0.1767767j, - -1.53080850e-17-0.25j , -1.76776695e-01+0.1767767j, - 2.50000000e-01+0.j , -1.76776695e-01-0.1767767j, - 1.53080850e-17+0.25j , 1.76776695e-01-0.1767767j, - -2.50000000e-01+0.j , 1.76776695e-01+0.1767767j, - -1.53080850e-17-0.25j , -1.76776695e-01+0.1767767j]) - assert abs(fidelity(vector, ref) - 1) < TOLERANCE - - -def test_simon_n6(): - """ - Test simon_n6.qasm - """ - vector = get_vector('simon_n6.qasm') - ref = np.array([ 2.50000000e-01+0.j, -2.38105196e-18+0.j, 2.38105196e-18+0.j, - -2.50000000e-01+0.j, 2.50000000e-01+0.j, -2.38105196e-18+0.j, - 2.38105196e-18+0.j, -2.50000000e-01+0.j, 2.50000000e-01+0.j, - 2.38105196e-18+0.j, 2.38105196e-18+0.j, 2.50000000e-01+0.j, - 2.50000000e-01+0.j, 2.38105196e-18+0.j, 2.38105196e-18+0.j, - 2.50000000e-01+0.j, 2.50000000e-01+0.j, 2.38105196e-18+0.j, - 2.38105196e-18+0.j, 2.50000000e-01+0.j, -2.50000000e-01+0.j, - -2.38105196e-18+0.j, -2.38105196e-18+0.j, -2.50000000e-01+0.j, - 2.50000000e-01+0.j, -2.38105196e-18+0.j, 2.38105196e-18+0.j, - -2.50000000e-01+0.j, -2.50000000e-01+0.j, 2.38105196e-18+0.j, - -2.38105196e-18+0.j, 2.50000000e-01+0.j, 0.00000000e+00+0.j, - 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, - 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, - 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, - 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, - 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, - 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, - 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, - 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, - 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, - 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, - 0.00000000e+00+0.j]) - assert abs(fidelity(vector, ref) - 1) < TOLERANCE - - -def test_vqe_n4(): - """ - Test vqe_n4.qasm - """ - vector = get_vector('vqe_n4.qasm') - ref = np.array([ 0.22310975+0.03591277j, 0.07716044+0.06874446j, - -0.02409975-0.23946403j, -0.1988335 -0.33044344j, - 0.22921453+0.01693273j, 0.03096892-0.16783964j, - -0.17358726-0.19121655j, -0.17475247+0.51206682j, - 0.01452133-0.01450461j, -0.08246217+0.2670658j , - -0.04425131-0.16862705j, -0.11001101+0.04121341j, - -0.01348307+0.03699337j, 0.26031501-0.00411195j, - -0.04888739-0.16588764j, -0.12254994+0.23065344j]) - assert abs(fidelity(vector, ref) - 1) < TOLERANCE - - -def test_wstate_n3(): - """ - Test wstate_n3.qasm - """ - vector = get_vector('wstate_n3.qasm') - ref = np.array([0.00000000e+00+0.00000000e+00j, 4.08249225e-01+4.08249225e-01j, - 4.08247823e-01+4.08247823e-01j, 4.23739404e-17-4.23739404e-17j, - 4.08247823e-01+4.08247823e-01j, 0.00000000e+00+0.00000000e+00j, - 0.00000000e+00+0.00000000e+00j, 0.00000000e+00+0.00000000e+00j]) - assert abs(fidelity(vector, ref) - 1) < TOLERANCE + + + def test_fredkin_n3(self, cl_args : str): + """ + Test ghz_n4.qasm + """ + vector = get_vector('fredkin_n3.qasm', cl_args) + ref = np.array([0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 2.36158002e-17+0.j, 0.00000000e+00+0.j, 1.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE + + + def test_qaoa_n3(self, cl_args : str): + """ + Test qaoa_n3.qasm + """ + vector = get_vector('qaoa_n3.qasm', cl_args) + ref = np.array([-0.44546064-0.1658815j , -0.16261527-0.26478867j, + -0.16759538-0.09325885j, 0.12584213+0.35336909j, + -0.16261527-0.26478867j, -0.44546064-0.1658815j , + 0.12584213+0.35336909j, -0.16759538-0.09325885j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE + + + def test_qft_n4(self, cl_args : str): + """ + Test qft_n4.qasm + """ + vector = get_vector('qft_n4.qasm', cl_args) + ref = np.array([ 2.50000000e-01+0.j , -1.76776695e-01-0.1767767j, + 1.53080850e-17+0.25j , 1.76776695e-01-0.1767767j, + -2.50000000e-01+0.j , 1.76776695e-01+0.1767767j, + -1.53080850e-17-0.25j , -1.76776695e-01+0.1767767j, + 2.50000000e-01+0.j , -1.76776695e-01-0.1767767j, + 1.53080850e-17+0.25j , 1.76776695e-01-0.1767767j, + -2.50000000e-01+0.j , 1.76776695e-01+0.1767767j, + -1.53080850e-17-0.25j , -1.76776695e-01+0.1767767j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE + + + def test_simon_n6(self, cl_args : str): + """ + Test simon_n6.qasm + """ + vector = get_vector('simon_n6.qasm', cl_args) + ref = np.array([ 2.50000000e-01+0.j, -2.38105196e-18+0.j, 2.38105196e-18+0.j, + -2.50000000e-01+0.j, 2.50000000e-01+0.j, -2.38105196e-18+0.j, + 2.38105196e-18+0.j, -2.50000000e-01+0.j, 2.50000000e-01+0.j, + 2.38105196e-18+0.j, 2.38105196e-18+0.j, 2.50000000e-01+0.j, + 2.50000000e-01+0.j, 2.38105196e-18+0.j, 2.38105196e-18+0.j, + 2.50000000e-01+0.j, 2.50000000e-01+0.j, 2.38105196e-18+0.j, + 2.38105196e-18+0.j, 2.50000000e-01+0.j, -2.50000000e-01+0.j, + -2.38105196e-18+0.j, -2.38105196e-18+0.j, -2.50000000e-01+0.j, + 2.50000000e-01+0.j, -2.38105196e-18+0.j, 2.38105196e-18+0.j, + -2.50000000e-01+0.j, -2.50000000e-01+0.j, 2.38105196e-18+0.j, + -2.38105196e-18+0.j, 2.50000000e-01+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j, 0.00000000e+00+0.j, 0.00000000e+00+0.j, + 0.00000000e+00+0.j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE + + + def test_vqe_n4(self, cl_args : str): + """ + Test vqe_n4.qasm + """ + vector = get_vector('vqe_n4.qasm', cl_args) + ref = np.array([ 0.22310975+0.03591277j, 0.07716044+0.06874446j, + -0.02409975-0.23946403j, -0.1988335 -0.33044344j, + 0.22921453+0.01693273j, 0.03096892-0.16783964j, + -0.17358726-0.19121655j, -0.17475247+0.51206682j, + 0.01452133-0.01450461j, -0.08246217+0.2670658j , + -0.04425131-0.16862705j, -0.11001101+0.04121341j, + -0.01348307+0.03699337j, 0.26031501-0.00411195j, + -0.04888739-0.16588764j, -0.12254994+0.23065344j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE + + + def test_wstate_n3(self, cl_args : str): + """ + Test wstate_n3.qasm + """ + vector = get_vector('wstate_n3.qasm', cl_args) + ref = np.array([0.00000000e+00+0.00000000e+00j, 4.08249225e-01+4.08249225e-01j, + 4.08247823e-01+4.08247823e-01j, 4.23739404e-17-4.23739404e-17j, + 4.08247823e-01+4.08247823e-01j, 0.00000000e+00+0.00000000e+00j, + 0.00000000e+00+0.00000000e+00j, 0.00000000e+00+0.00000000e+00j]) + assert abs(fidelity(vector, ref) - 1) < TOLERANCE From f527bea6ab675742badc7e226ec6b1c914889619 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Thu, 30 May 2024 11:43:13 +0200 Subject: [PATCH 13/37] added cli option to sim_qasm --- qasm/sim_qasm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/qasm/sim_qasm.c b/qasm/sim_qasm.c index 3b796cb..7f8b7ab 100644 --- a/qasm/sim_qasm.c +++ b/qasm/sim_qasm.c @@ -20,6 +20,7 @@ static size_t wgt_tab_size = 1LL<<23; static double tolerance = 1e-14; static int wgt_table_type = COMP_HASHMAP; static int wgt_norm_strat = NORM_LARGEST; +static bool wgt_inv_caching = false; static int reorder_qubits = 0; static char* qasm_inputfile = NULL; static char* json_outputfile = NULL; @@ -36,6 +37,7 @@ static struct argp_option options[] = {"state-vector", 'v', 0, 0, "Also output the complete state vector", 0}, {"allow-reorder", 10, 0, 0, "Reorders the qubits once such that (most) controls occur before targets in the variable order.", 0}, {"allow-reorder-swaps", 11, 0, 0, "Reorders the qubits such that all controls occur before targets (requires inserting SWAP gates).", 0}, + {"disable-inv-caching", 12, 0, 0, "Disable storing inverse of MUL and DIV in cache.", 0}, {0, 0, 0, 0, 0, 0} }; static error_t @@ -72,6 +74,9 @@ parse_opt(int key, char *arg, struct argp_state *state) case 11: reorder_qubits = 2; break; + case 12: + wgt_inv_caching = false; + break; case ARGP_KEY_ARG: if (state->arg_num >= 1) argp_usage(state); qasm_inputfile = arg; @@ -138,6 +143,7 @@ void fprint_stats(FILE *stream, quantum_circuit_t* circuit) fprintf(stream, " \"shots\": %" PRIu64 ",\n", stats.shots); fprintf(stream, " \"simulation_time\": %lf,\n", stats.simulation_time); fprintf(stream, " \"tolerance\": %.5e,\n", tolerance); + fprintf(stream, " \"wgt_inv_caching\": %d,\n", wgt_inv_caching); fprintf(stream, " \"wgt_norm_strat\": %d,\n", wgt_norm_strat); fprintf(stream, " \"workers\": %d\n", workers); fprintf(stream, " }\n"); @@ -371,6 +377,7 @@ int main(int argc, char *argv[]) sylvan_set_sizes(min_tablesize, max_tablesize, min_cachesize, max_cachesize); sylvan_init_package(); qsylvan_init_simulator(wgt_tab_size, wgt_tab_size, tolerance, COMP_HASHMAP, wgt_norm_strat); + wgt_set_inverse_chaching(wgt_inv_caching); simulate_circuit(circuit); From 181c5ed1d1e9888be48d4274a960ca4feee04e5b Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Thu, 30 May 2024 13:37:53 +0200 Subject: [PATCH 14/37] set inv caching true by default --- qasm/sim_qasm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qasm/sim_qasm.c b/qasm/sim_qasm.c index 7f8b7ab..3612f98 100644 --- a/qasm/sim_qasm.c +++ b/qasm/sim_qasm.c @@ -20,7 +20,7 @@ static size_t wgt_tab_size = 1LL<<23; static double tolerance = 1e-14; static int wgt_table_type = COMP_HASHMAP; static int wgt_norm_strat = NORM_LARGEST; -static bool wgt_inv_caching = false; +static bool wgt_inv_caching = true; static int reorder_qubits = 0; static char* qasm_inputfile = NULL; static char* json_outputfile = NULL; From d16707eb2e6959fea173b3163041c8fb709a7cf6 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Thu, 30 May 2024 13:52:24 +0200 Subject: [PATCH 15/37] add reorder info to json output --- qasm/sim_qasm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/qasm/sim_qasm.c b/qasm/sim_qasm.c index 3612f98..00551eb 100644 --- a/qasm/sim_qasm.c +++ b/qasm/sim_qasm.c @@ -139,6 +139,7 @@ void fprint_stats(FILE *stream, quantum_circuit_t* circuit) fprintf(stream, " \"max_nodes\": %" PRIu64 ",\n", stats.max_nodes); fprintf(stream, " \"n_qubits\": %d,\n", circuit->qreg_size); fprintf(stream, " \"norm\": %.5e,\n", stats.norm); + fprintf(stream, " \"reorder\": %d,\n", reorder_qubits); fprintf(stream, " \"seed\": %d,\n", rseed); fprintf(stream, " \"shots\": %" PRIu64 ",\n", stats.shots); fprintf(stream, " \"simulation_time\": %lf,\n", stats.simulation_time); From 32c646bc193ef12423ad8b42e84c3d0afbda641d Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Thu, 30 May 2024 17:26:49 +0200 Subject: [PATCH 16/37] sort controls instead of requiring input to be sorted --- src/qsylvan_simulator.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/qsylvan_simulator.c b/src/qsylvan_simulator.c index a9d737d..f718cdb 100644 --- a/src/qsylvan_simulator.c +++ b/src/qsylvan_simulator.c @@ -334,12 +334,25 @@ qmdd_do_before_gate(QMDD* qmdd) qmdd_stats_log(*qmdd); } +static void swap(BDDVAR *a, BDDVAR *b) +{ + BDDVAR tmp = *a; + *a = *b; + *b = tmp; +} + static bool -check_ctrls_before_targ(BDDVAR c1, BDDVAR c2, BDDVAR c3, BDDVAR t) +check_ctrls_before_targ(BDDVAR *c1, BDDVAR *c2, BDDVAR *c3, BDDVAR t) { - if (c1 != AADD_INVALID_VAR && c1 > t) return false; - if (c2 != AADD_INVALID_VAR && c2 > t) return false; - if (c3 != AADD_INVALID_VAR && c3 > t) return false; + // sort controls + if (*c1 > *c3) swap(c1, c2); + if (*c1 > *c2) swap(c1, c2); + if (*c2 > *c3) swap(c2, c3); + + // check if controls before target + if (*c1 != AADD_INVALID_VAR && *c1 > t) return false; + if (*c2 != AADD_INVALID_VAR && *c2 > t) return false; + if (*c3 != AADD_INVALID_VAR && *c3 > t) return false; return true; } @@ -355,7 +368,7 @@ QMDD _qmdd_cgate(QMDD state, gate_id_t gate, BDDVAR c1, BDDVAR c2, BDDVAR c3, BD { qmdd_do_before_gate(&state); - if (check_ctrls_before_targ(c1, c2, c3, t)) { + if (check_ctrls_before_targ(&c1, &c2, &c3, t)) { BDDVAR cs[4] = {c1, c2, c3, AADD_INVALID_VAR}; // last pos is to mark end return qmdd_cgate_rec(state, gate, cs, t); } From 40698c7aa6e89b4c555f30134c506360716c8016 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Thu, 30 May 2024 17:40:11 +0200 Subject: [PATCH 17/37] fix warning --- src/qsylvan_simulator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qsylvan_simulator.c b/src/qsylvan_simulator.c index f718cdb..4f3d554 100644 --- a/src/qsylvan_simulator.c +++ b/src/qsylvan_simulator.c @@ -376,10 +376,10 @@ QMDD _qmdd_cgate(QMDD state, gate_id_t gate, BDDVAR c1, BDDVAR c2, BDDVAR c3, BD assert(n != 0 && "ERROR: when ctrls > targ, nqubits must be passed to cgate() function."); int *c_options = malloc(sizeof(int)*(n+1)); for (uint32_t k = 0; k < n; k++) c_options[k] = -1; - if (c1 != AADD_INVALID_VAR) c_options[c1] = 1; - if (c2 != AADD_INVALID_VAR) c_options[c2] = 1; - if (c3 != AADD_INVALID_VAR) c_options[c3] = 1; - c_options[t] = 2; + if (c1 != AADD_INVALID_VAR && c1 < n) c_options[c1] = 1; + if (c2 != AADD_INVALID_VAR && c2 < n) c_options[c2] = 1; + if (c3 != AADD_INVALID_VAR && c3 < n) c_options[c3] = 1; + if (t != AADD_INVALID_VAR && t < n) c_options[t] = 2; QMDD gate_matrix = qmdd_create_multi_cgate(n, c_options, gate); free(c_options); return aadd_matvec_mult(gate_matrix, state, n); From 7c27df7ff3000a3304028bdd323643c7c52899cc Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Fri, 31 May 2024 12:03:03 +0200 Subject: [PATCH 18/37] added different norm strats to cli test cases --- qasm/test/test_sim_qasm.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/qasm/test/test_sim_qasm.py b/qasm/test/test_sim_qasm.py index f757310..f7db8c8 100644 --- a/qasm/test/test_sim_qasm.py +++ b/qasm/test/test_sim_qasm.py @@ -34,7 +34,9 @@ def get_vector(qasm_file : str, args : list): return vector -@pytest.mark.parametrize("cl_args", [[], ["--allow-reorder"], ["--allow-reorder-swap"]]) +@pytest.mark.parametrize("cl_args", + [['-s', 'low'], ['-s', 'largest'], ['-s', 'l2'], + ['--allow-reorder'], ['--allow-reorder-swap']]) class TestCircuits: """ Test sim_qasm on all given circuits, with CL arguments given above. @@ -315,7 +317,7 @@ def test_qaoa_n3(self, cl_args : str): ref = np.array([-0.44546064-0.1658815j , -0.16261527-0.26478867j, -0.16759538-0.09325885j, 0.12584213+0.35336909j, -0.16261527-0.26478867j, -0.44546064-0.1658815j , - 0.12584213+0.35336909j, -0.16759538-0.09325885j]) + 0.12584213+0.35336909j, -0.16759538-0.09325885j]) assert abs(fidelity(vector, ref) - 1) < TOLERANCE @@ -325,11 +327,11 @@ def test_qft_n4(self, cl_args : str): """ vector = get_vector('qft_n4.qasm', cl_args) ref = np.array([ 2.50000000e-01+0.j , -1.76776695e-01-0.1767767j, - 1.53080850e-17+0.25j , 1.76776695e-01-0.1767767j, + 1.53080850e-17+0.25j , 1.76776695e-01-0.1767767j, -2.50000000e-01+0.j , 1.76776695e-01+0.1767767j, -1.53080850e-17-0.25j , -1.76776695e-01+0.1767767j, - 2.50000000e-01+0.j , -1.76776695e-01-0.1767767j, - 1.53080850e-17+0.25j , 1.76776695e-01-0.1767767j, + 2.50000000e-01+0.j , -1.76776695e-01-0.1767767j, + 1.53080850e-17+0.25j , 1.76776695e-01-0.1767767j, -2.50000000e-01+0.j , 1.76776695e-01+0.1767767j, -1.53080850e-17-0.25j , -1.76776695e-01+0.1767767j]) assert abs(fidelity(vector, ref) - 1) < TOLERANCE From a022a3f258447cf140d8262b0b35997c7ef8cfdd Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Mon, 10 Jun 2024 12:14:50 +0200 Subject: [PATCH 19/37] added alternative edge weight normalization --- examples/alg_run.c | 7 +++-- examples/test_algs.c | 2 +- qasm/qsylvan_qasm.c | 2 +- qasm/sim_qasm.c | 7 +++-- qasm/test/test_sim_qasm.py | 2 +- src/sylvan_aadd.c | 9 ++++-- src/sylvan_aadd.h | 3 +- src/sylvan_aadd_int.h | 4 +-- src/sylvan_edge_weights.c | 64 +++++++++++++++++++++++++++++++++++++- src/sylvan_edge_weights.h | 5 +-- test/test_qmdd_gc.c | 4 +-- 11 files changed, 89 insertions(+), 20 deletions(-) diff --git a/examples/alg_run.c b/examples/alg_run.c index 546604e..49bea8b 100644 --- a/examples/alg_run.c +++ b/examples/alg_run.c @@ -24,7 +24,7 @@ static size_t max_cachesize = 1LL<<20; static size_t wgt_tab_size = 1LL<<23; static double tolerance = 1e-14; static int wgt_table_type = COMP_HASHMAP; -static int wgt_norm_strat = NORM_LARGEST; +static int wgt_norm_strat = NORM_MAX; static int wgt_inv_caching = 1; static int grover_flag = 1; // 0 = random, 1 = 11..1 @@ -46,7 +46,7 @@ static struct argp_option options[] = {"qubits", 'q', "", 0, "Number of qubits (must be set for Grover)", 0}, {"rseed", 'r', "", 0, "Set random seed", 0}, {"depth", 'd', "", 0, "Depth of circuits with arbitrary depth (e.g. supremacy)", 0}, - {"norm-strat", 's', "", 0, "Edge weight normalization strategy", 0}, + {"norm-strat", 's', "", 0, "Edge weight normalization strategy", 0}, {"tol", 1, "", 0, "Tolerance for deciding edge weights equal (default=1e-14)", 0}, {"inv-caching", 2, "<0|1>", 0, "Turn inverse chaching of edge weight computations on/off (default=on)", 0}, {"grover-flag", 20, "", 0, "Grover flag (default=11..1)", 0}, @@ -73,7 +73,8 @@ parse_opt(int key, char *arg, struct argp_state *state) break; case 's': if (strcmp(arg, "low")==0) wgt_norm_strat = NORM_LOW; - else if (strcmp(arg, "largest")==0) wgt_norm_strat = NORM_LARGEST; + else if (strcmp(arg, "max")==0) wgt_norm_strat = NORM_MAX; + else if (strcmp(arg, "min")==0) wgt_norm_strat = NORM_MIN; else if (strcasecmp(arg, "l2")==0) wgt_norm_strat = NORM_L2; else argp_usage(state); break; diff --git a/examples/test_algs.c b/examples/test_algs.c index f7599d3..92cb19a 100644 --- a/examples/test_algs.c +++ b/examples/test_algs.c @@ -394,7 +394,7 @@ int main() // Simple Sylvan initialization sylvan_set_sizes(1LL<<25, 1LL<<25, 1LL<<16, 1LL<<16); sylvan_init_package(); - qsylvan_init_simulator(1LL<<16, 1LL<<16, TOLERANCE, COMP_HASHMAP, NORM_LARGEST); + qsylvan_init_simulator(1LL<<16, 1LL<<16, TOLERANCE, COMP_HASHMAP, NORM_MAX); qmdd_set_testing_mode(true); // turn on internal sanity tests int res = runtests(); diff --git a/qasm/qsylvan_qasm.c b/qasm/qsylvan_qasm.c index feab835..45b280a 100644 --- a/qasm/qsylvan_qasm.c +++ b/qasm/qsylvan_qasm.c @@ -741,7 +741,7 @@ int main(int argc, char *argv[]) int flag_help = -1; char *filename; int workers = 1; - int wgt_norm_strat = NORM_LARGEST; + int wgt_norm_strat = NORM_MAX; unsigned int runs = 1; unsigned int seed = 0; int matrix = 0; diff --git a/qasm/sim_qasm.c b/qasm/sim_qasm.c index 00551eb..8de5854 100644 --- a/qasm/sim_qasm.c +++ b/qasm/sim_qasm.c @@ -19,7 +19,7 @@ static size_t max_cachesize = 1LL<<16; static size_t wgt_tab_size = 1LL<<23; static double tolerance = 1e-14; static int wgt_table_type = COMP_HASHMAP; -static int wgt_norm_strat = NORM_LARGEST; +static int wgt_norm_strat = NORM_MAX; static bool wgt_inv_caching = true; static int reorder_qubits = 0; static char* qasm_inputfile = NULL; @@ -30,7 +30,7 @@ static struct argp_option options[] = { {"workers", 'w', "", 0, "Number of workers/threads (default=1)", 0}, {"rseed", 'r', "", 0, "Set random seed", 0}, - {"norm-strat", 's', "", 0, "Edge weight normalization strategy", 0}, + {"norm-strat", 's', "", 0, "Edge weight normalization strategy", 0}, {"tol", 't', "", 0, "Tolerance for deciding edge weights equal (default=1e-14)", 0}, {"json", 'j', "", 0, "Write stats to given filename as json", 0}, {"count-nodes", 'c', 0, 0, "Track maximum number of nodes", 0}, @@ -52,7 +52,8 @@ parse_opt(int key, char *arg, struct argp_state *state) break; case 's': if (strcmp(arg, "low")==0) wgt_norm_strat = NORM_LOW; - else if (strcmp(arg, "largest")==0) wgt_norm_strat = NORM_LARGEST; + else if (strcmp(arg, "max")==0) wgt_norm_strat = NORM_MAX; + else if (strcmp(arg, "min")==0) wgt_norm_strat = NORM_MIN; else if (strcasecmp(arg, "l2")==0) wgt_norm_strat = NORM_L2; else argp_usage(state); break; diff --git a/qasm/test/test_sim_qasm.py b/qasm/test/test_sim_qasm.py index f7db8c8..5cb6eba 100644 --- a/qasm/test/test_sim_qasm.py +++ b/qasm/test/test_sim_qasm.py @@ -35,7 +35,7 @@ def get_vector(qasm_file : str, args : list): @pytest.mark.parametrize("cl_args", - [['-s', 'low'], ['-s', 'largest'], ['-s', 'l2'], + [['-s', 'low'], ['-s', 'max'], ['-s', 'min'], ['-s', 'l2'], ['--allow-reorder'], ['--allow-reorder-swap']]) class TestCircuits: """ diff --git a/src/sylvan_aadd.c b/src/sylvan_aadd.c index 5868213..d09ef13 100644 --- a/src/sylvan_aadd.c +++ b/src/sylvan_aadd.c @@ -484,12 +484,15 @@ sylvan_init_aadd(size_t min_wgt_tablesize, size_t max_wgt_tablesize, weight_norm_strat = norm_strat; switch (norm_strat) { - case NORM_LARGEST: - normalize_weights = &wgt_norm_largest; - break; case NORM_LOW: normalize_weights = &wgt_norm_low; break; + case NORM_MAX: + normalize_weights = &wgt_norm_max; + break; + case NORM_MIN: + normalize_weights = &wgt_norm_min; + break; case NORM_L2: normalize_weights = wgt_norm_L2; break; diff --git a/src/sylvan_aadd.h b/src/sylvan_aadd.h index bf0a482..c1c3286 100644 --- a/src/sylvan_aadd.h +++ b/src/sylvan_aadd.h @@ -18,7 +18,8 @@ static const BDDVAR AADD_INVALID_VAR = UINT8_MAX; typedef enum weight_norm_strategy { NORM_LOW, - NORM_LARGEST, + NORM_MAX, + NORM_MIN, NORM_L2, n_norm_strategies } weight_norm_strategy_t; diff --git a/src/sylvan_aadd_int.h b/src/sylvan_aadd_int.h index 0d3cb89..bf741be 100644 --- a/src/sylvan_aadd_int.h +++ b/src/sylvan_aadd_int.h @@ -223,7 +223,7 @@ static void __attribute__((unused)) aaddnode_pack(aaddnode_t n, BDDVAR var, AADD_TARG low, AADD_TARG high, AADD_WGT a, AADD_WGT b) { // We only want to store 1 edge weight per node (which has 2 outgoing - // edges). For NORM_LOW and NORM_LARGEST this is relatively easy because in + // edges). For NORM_LOW and NORM_MAX this is relatively easy because in // both those cases there is at least one edge weight equal to 1 or 0. // // For NORM_L2 it is a bit more complicated: both edge weights can be @@ -244,7 +244,7 @@ aaddnode_pack(aaddnode_t n, BDDVAR var, AADD_TARG low, AADD_TARG high, AADD_WGT wgt_high = b; // we can derive a from b } else { - /// weight_norm_strat == NORM_LOW or NORM_LARGEST + /// weight_norm_strat == NORM_LOW or NORM_MAX or NORM_MIN assert(a == AADD_ZERO || a == AADD_ONE || b == AADD_ZERO || b == AADD_ONE); norm_pos = (a == AADD_ZERO || a == AADD_ONE) ? 0 : 1; if (norm_pos == 0) { diff --git a/src/sylvan_edge_weights.c b/src/sylvan_edge_weights.c index 8811e2a..c3b3a1b 100644 --- a/src/sylvan_edge_weights.c +++ b/src/sylvan_edge_weights.c @@ -588,7 +588,7 @@ wgt_norm_low(AADD_WGT *low, AADD_WGT *high) } AADD_WGT -wgt_norm_largest(AADD_WGT *low, AADD_WGT *high) +wgt_norm_max(AADD_WGT *low, AADD_WGT *high) { AADD_WGT norm; if (*low == *high) { @@ -622,6 +622,68 @@ wgt_norm_largest(AADD_WGT *low, AADD_WGT *high) return norm; } +AADD_WGT +wgt_norm_min(AADD_WGT *low, AADD_WGT *high) +{ + AADD_WGT norm; + if (*low == *high) { + norm = *low; + *low = AADD_ONE; + *high = AADD_ONE; + return norm; + } + // Since min(a, b) could be 0, norm using non-zero to avoid dividing by 0 + if (*low == AADD_ZERO) { + norm = *high; + *high = AADD_ONE; + return norm; + } + if (*high == AADD_ZERO) { + norm = *low; + *low = AADD_ONE; + return norm; + } + + // Normalize using the absolute smallest value + weight_t wl = weight_malloc(); + weight_t wh = weight_malloc(); + weight_t wl_abs = weight_malloc(); + weight_t wh_abs = weight_malloc(); + weight_value(*low, wl); + weight_value(*high, wh); + weight_value(*low, wl_abs); + weight_value(*high, wh_abs); + weight_abs(wl_abs); + weight_abs(wh_abs); + + // To help avoid canonicity issues, + // handle case where magnitudes are (almost) equal separately + if (weight_approx_eq(wl_abs, wh_abs)) { + // |low| ~= |high|, divide by low + *high = wgt_div(*high, *low); + norm = *low; + *low = AADD_ONE; + } + else if (weight_greater(wl, wh)) { + // |high| < |low|, divide both by high + *low = wgt_div(*low, *high); + norm = *high; + *high = AADD_ONE; + } + else { + // |low| < |high|, divide both by low + *high = wgt_div(*high, *low); + norm = *low; + *low = AADD_ONE; + } + + free(wl); + free(wh); + free(wl_abs); + free(wh_abs); + return norm; +} + /**************************************************/ diff --git a/src/sylvan_edge_weights.h b/src/sylvan_edge_weights.h index 4230132..4e1c939 100644 --- a/src/sylvan_edge_weights.h +++ b/src/sylvan_edge_weights.h @@ -78,7 +78,7 @@ typedef void (*weight_mul_f)(weight_t a, weight_t b); // a <-- a * b typedef void (*weight_div_f)(weight_t a, weight_t b); // a <-- a / b typedef bool (*weight_eq_f)(weight_t a, weight_t b); // returns true iff a == b typedef bool (*weight_eps_close_f)(weight_t a, weight_t b, double eps); // returns true iff dist(a,b) < eps -typedef bool (*weight_greater_f)(weight_t a, weight_t b); // returns true iff a > b +typedef bool (*weight_greater_f)(weight_t a, weight_t b); // returns true iff |a| > |b| /* Normalization methods */ typedef AADD_WGT (*wgt_norm_L2_f)(AADD_WGT *low, AADD_WGT *high); @@ -162,7 +162,8 @@ bool wgt_approx_eq(AADD_WGT a, AADD_WGT b); /***************************************************/ AADD_WGT wgt_norm_low(AADD_WGT *low, AADD_WGT *high); -AADD_WGT wgt_norm_largest(AADD_WGT *low, AADD_WGT *high); +AADD_WGT wgt_norm_max(AADD_WGT *low, AADD_WGT *high); +AADD_WGT wgt_norm_min(AADD_WGT *low, AADD_WGT *high); // wgt_norm_L2() is in the interface because it's too complicated to implement // without assumptions on the underlying data type of the edge weights. diff --git a/test/test_qmdd_gc.c b/test/test_qmdd_gc.c index 5e39813..7608cc7 100644 --- a/test/test_qmdd_gc.c +++ b/test/test_qmdd_gc.c @@ -49,7 +49,7 @@ int test_table_size_increase() double tol = 0; sylvan_set_sizes(1LL<<25, 1LL<<25, 1LL<<16, 1LL<<16); sylvan_init_package(); - qsylvan_init_simulator(min_wgt_tablesize, max_wgt_tablesize, -1, COMP_HASHMAP, NORM_LARGEST); + qsylvan_init_simulator(min_wgt_tablesize, max_wgt_tablesize, -1, COMP_HASHMAP, NORM_MAX); qmdd_set_testing_mode(true); // turn on internal sanity tests // check that wgt_tablesize doubles after gc, but not beyond max_wgt_tablesize @@ -80,7 +80,7 @@ int test_custom_gate_gc_protection() double tol = 1e-14; sylvan_set_sizes(1LL<<25, 1LL<<25, 1LL<<16, 1LL<<16); sylvan_init_package(); - qsylvan_init_simulator(min_wgt_tablesize, max_wgt_tablesize, -1, COMP_HASHMAP, NORM_LARGEST); + qsylvan_init_simulator(min_wgt_tablesize, max_wgt_tablesize, -1, COMP_HASHMAP, NORM_MAX); qmdd_set_testing_mode(true); // turn on internal sanity tests From bac4d38068273baa9255ec57b7e078ad6a67c9e1 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Mon, 17 Jun 2024 10:58:09 +0200 Subject: [PATCH 20/37] gc protect aadds + use lace call insead of run --- src/sylvan_aadd.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/sylvan_aadd.c b/src/sylvan_aadd.c index d09ef13..a3f2a34 100644 --- a/src/sylvan_aadd.c +++ b/src/sylvan_aadd.c @@ -52,7 +52,7 @@ VOID_TASK_IMPL_1(aadd_gc_mark_rec, AADD, a) if (llmsset_mark(nodes, AADD_TARGET(a))) { aaddnode_t n = AADD_GETNODE(AADD_TARGET(a)); SPAWN(aadd_gc_mark_rec, aaddnode_getptrlow(n)); - RUN(aadd_gc_mark_rec, aaddnode_getptrhigh(n)); + CALL(aadd_gc_mark_rec, aaddnode_getptrhigh(n)); SYNC(aadd_gc_mark_rec); } } @@ -143,7 +143,7 @@ VOID_TASK_2(aadd_refs_mark_p_par, const AADD**, begin, size_t, count) } } else { SPAWN(aadd_refs_mark_p_par, begin, count / 2); - RUN(aadd_refs_mark_p_par, begin + (count / 2), count - count / 2); + CALL(aadd_refs_mark_p_par, begin + (count / 2), count - count / 2); SYNC(aadd_refs_mark_p_par); } } @@ -177,7 +177,7 @@ VOID_TASK_2(aadd_refs_mark_s_par, aadd_refs_task_t, begin, size_t, count) } else { if (!TASK_IS_STOLEN(begin->t)) return; SPAWN(aadd_refs_mark_s_par, begin, count / 2); - RUN(aadd_refs_mark_s_par, begin + (count / 2), count - count / 2); + CALL(aadd_refs_mark_s_par, begin + (count / 2), count - count / 2); SYNC(aadd_refs_mark_s_par); } } @@ -187,7 +187,7 @@ VOID_TASK_0(aadd_refs_mark_task) LOCALIZE_THREAD_LOCAL(aadd_refs_key, aadd_refs_internal_t); SPAWN(aadd_refs_mark_p_par, aadd_refs_key->pbegin, aadd_refs_key->pcur-aadd_refs_key->pbegin); SPAWN(aadd_refs_mark_r_par, aadd_refs_key->rbegin, aadd_refs_key->rcur-aadd_refs_key->rbegin); - RUN(aadd_refs_mark_s_par, aadd_refs_key->sbegin, aadd_refs_key->scur-aadd_refs_key->sbegin); + CALL(aadd_refs_mark_s_par, aadd_refs_key->sbegin, aadd_refs_key->scur-aadd_refs_key->sbegin); SYNC(aadd_refs_mark_r_par); SYNC(aadd_refs_mark_p_par); } @@ -393,7 +393,7 @@ TASK_IMPL_1(AADD, _fill_new_wgt_table, AADD, a) aaddnode_t n = AADD_GETNODE(AADD_TARGET(a)); aaddnode_getchilderen(n, &low, &high); aadd_refs_spawn(SPAWN(_fill_new_wgt_table, high)); - low = RUN(_fill_new_wgt_table, low); + low = CALL(_fill_new_wgt_table, low); aadd_refs_push(low); high = aadd_refs_sync(SYNC(_fill_new_wgt_table)); aadd_refs_pop(1); @@ -550,11 +550,15 @@ aadd_getvalue(AADD a, bool* path) } static void -aadd_do_before_mult() +aadd_do_before_mult(AADD *a, AADD *b) { // check if edge weight table needs gc if (auto_gc_wgt_table && aadd_test_gc_wgt_table()) { + aadd_protect(a); + aadd_protect(b); aadd_gc_wgt_table(); + aadd_unprotect(a); + aadd_unprotect(b); } } @@ -625,7 +629,7 @@ TASK_IMPL_2(AADD, aadd_plus, AADD, a, AADD, b) // Recursive calls down AADD low, high; aadd_refs_spawn(SPAWN(aadd_plus, high_a, high_b)); - low = RUN(aadd_plus, low_a, low_b); + low = CALL(aadd_plus, low_a, low_b); aadd_refs_push(low); high = aadd_refs_sync(SYNC(aadd_plus)); aadd_refs_pop(1); @@ -644,15 +648,15 @@ TASK_IMPL_2(AADD, aadd_plus, AADD, a, AADD, b) /* Wrapper for matrix vector multiplication. */ TASK_IMPL_3(AADD, aadd_matvec_mult, AADD, mat, AADD, vec, BDDVAR, nvars) { - aadd_do_before_mult(); - return RUN(aadd_matvec_mult_rec, mat, vec, nvars, 0); + aadd_do_before_mult(&mat, &vec); + return CALL(aadd_matvec_mult_rec, mat, vec, nvars, 0); } /* Wrapper for matrix vector multiplication. */ TASK_IMPL_3(AADD, aadd_matmat_mult, AADD, a, AADD, b, BDDVAR, nvars) { - aadd_do_before_mult(); - return RUN(aadd_matmat_mult_rec, a, b, nvars, 0); + aadd_do_before_mult(&a, &b); + return CALL(aadd_matmat_mult_rec, a, b, nvars, 0); } TASK_IMPL_4(AADD, aadd_matvec_mult_rec, AADD, mat, AADD, vec, BDDVAR, nvars, BDDVAR, nextvar) @@ -706,7 +710,7 @@ TASK_IMPL_4(AADD, aadd_matvec_mult_rec, AADD, mat, AADD, vec, BDDVAR, nvars, BDD aadd_refs_spawn(SPAWN(aadd_matvec_mult_rec, u00, vec_low, nvars, nextvar)); // 1 aadd_refs_spawn(SPAWN(aadd_matvec_mult_rec, u10, vec_low, nvars, nextvar)); // 2 aadd_refs_spawn(SPAWN(aadd_matvec_mult_rec, u01, vec_high, nvars, nextvar)); // 3 - res_high11 = RUN(aadd_matvec_mult_rec, u11, vec_high, nvars, nextvar); + res_high11 = CALL(aadd_matvec_mult_rec, u11, vec_high, nvars, nextvar); aadd_refs_push(res_high11); res_high01 = aadd_refs_sync(SYNC(aadd_matvec_mult_rec)); // 3 res_low10 = aadd_refs_sync(SYNC(aadd_matvec_mult_rec)); // 2 @@ -720,7 +724,7 @@ TASK_IMPL_4(AADD, aadd_matvec_mult_rec, AADD, mat, AADD, vec, BDDVAR, nvars, BDD res_high = aadd_makenode(nextvar, res_high01, res_high11); // 5. add resulting AADDs - res = RUN(aadd_plus, res_low, res_high); + res = CALL(aadd_plus, res_low, res_high); // Insert in cache (before multiplication w/ root weights) if (cachenow) { @@ -797,7 +801,7 @@ TASK_IMPL_4(AADD, aadd_matmat_mult_rec, AADD, a, AADD, b, BDDVAR, nvars, BDDVAR, aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a01, b10, nvars, nextvar)); // 5 aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a01, b11, nvars, nextvar)); // 6 aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a11, b10, nvars, nextvar)); // 7 - a11_b11 = RUN(aadd_matmat_mult_rec, a11, b11, nvars, nextvar); + a11_b11 = CALL(aadd_matmat_mult_rec, a11, b11, nvars, nextvar); aadd_refs_push(a11_b11); a11_b10 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 7 a01_b11 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 6 From de7072528216e78edb15c0a87bda366d0bfb71e6 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Mon, 17 Jun 2024 15:21:55 +0200 Subject: [PATCH 21/37] fix gc issue + small refactor of gc calls --- src/qsylvan_simulator.c | 16 +++----- src/sylvan_aadd.c | 86 ++++++++++++++++++++--------------------- src/sylvan_aadd_int.h | 2 +- 3 files changed, 49 insertions(+), 55 deletions(-) diff --git a/src/qsylvan_simulator.c b/src/qsylvan_simulator.c index 4f3d554..cbcd6d3 100644 --- a/src/qsylvan_simulator.c +++ b/src/qsylvan_simulator.c @@ -426,16 +426,14 @@ TASK_IMPL_3(QMDD, qmdd_gate_rec, QMDD, q, gate_id_t, gate, BDDVAR, target) high1 = aadd_bundle(AADD_TARGET(low), a_u10); high2 = aadd_bundle(AADD_TARGET(high),b_u11); aadd_refs_spawn(SPAWN(aadd_plus, high1, high2)); - low = CALL(aadd_plus, low1, low2); - aadd_refs_push(low); + low = aadd_refs_push(CALL(aadd_plus, low1, low2)); high = aadd_refs_sync(SYNC(aadd_plus)); aadd_refs_pop(1); res = aadd_makenode(target, low, high); } else { // var < target: not at target qubit yet, recursive calls down aadd_refs_spawn(SPAWN(qmdd_gate_rec, high, gate, target)); - low = CALL(qmdd_gate_rec, low, gate, target); - aadd_refs_push(low); + low = aadd_refs_push(CALL(qmdd_gate_rec, low, gate, target)); high = aadd_refs_sync(SYNC(qmdd_gate_rec)); aadd_refs_pop(1); res = aadd_makenode(var, low, high); @@ -486,15 +484,12 @@ TASK_IMPL_5(QMDD, qmdd_cgate_rec, QMDD, q, gate_id_t, gate, BDDVAR*, cs, uint32_ // If current node is (one of) the control qubit(s), // control on q_c = |1> (high edge) if (var == c) { - ci++; - high = CALL(qmdd_cgate_rec, high, gate, cs, ci, t); - ci--; + high = CALL(qmdd_cgate_rec, high, gate, cs, ci+1, t); } // Not at control qubit yet, apply to both childeren. else { aadd_refs_spawn(SPAWN(qmdd_cgate_rec, high, gate, cs, ci, t)); - low = CALL(qmdd_cgate_rec, low, gate, cs, ci, t); - aadd_refs_push(low); + low = aadd_refs_push(CALL(qmdd_cgate_rec, low, gate, cs, ci, t)); high = aadd_refs_sync(SYNC(qmdd_cgate_rec)); aadd_refs_pop(1); } @@ -558,8 +553,7 @@ TASK_IMPL_6(QMDD, qmdd_cgate_range_rec, QMDD, q, gate_id_t, gate, BDDVAR, c_firs // Not at first control qubit yet, apply to both children if (var < c_first) { aadd_refs_spawn(SPAWN(qmdd_cgate_range_rec, high, gate, c_first, c_last, t, nextvar)); - low = CALL(qmdd_cgate_range_rec, low, gate, c_first, c_last, t, var); - aadd_refs_push(low); + low = aadd_refs_push(CALL(qmdd_cgate_range_rec, low, gate, c_first, c_last, t, nextvar)); high = aadd_refs_sync(SYNC(qmdd_cgate_range_rec)); aadd_refs_pop(1); } diff --git a/src/sylvan_aadd.c b/src/sylvan_aadd.c index a3f2a34..f36706d 100644 --- a/src/sylvan_aadd.c +++ b/src/sylvan_aadd.c @@ -581,6 +581,8 @@ TASK_IMPL_2(AADD, aadd_plus, AADD, a, AADD, b) if(AADD_WEIGHT(a) == AADD_ZERO) return b; if(AADD_WEIGHT(b) == AADD_ZERO) return a; + sylvan_gc_test(); + // Get var(a) and var(b) AADD low_a, low_b, high_a, high_b, res; BDDVAR var_a = UINT32_MAX, var_b = UINT32_MAX, topvar; @@ -621,18 +623,16 @@ TASK_IMPL_2(AADD, aadd_plus, AADD, a, AADD, b) wgt_ha = wgt_mul(AADD_WEIGHT(a), AADD_WEIGHT(high_a)); wgt_lb = wgt_mul(AADD_WEIGHT(b), AADD_WEIGHT(low_b)); wgt_hb = wgt_mul(AADD_WEIGHT(b), AADD_WEIGHT(high_b)); - low_a = aadd_bundle(AADD_TARGET(low_a), wgt_la); - high_a = aadd_bundle(AADD_TARGET(high_a), wgt_ha); - low_b = aadd_bundle(AADD_TARGET(low_b), wgt_lb); - high_b = aadd_bundle(AADD_TARGET(high_b), wgt_hb); + low_a = aadd_refs_push(aadd_bundle(AADD_TARGET(low_a), wgt_la)); + high_a = aadd_refs_push(aadd_bundle(AADD_TARGET(high_a), wgt_ha)); + low_b = aadd_refs_push(aadd_bundle(AADD_TARGET(low_b), wgt_lb)); + high_b = aadd_refs_push(aadd_bundle(AADD_TARGET(high_b), wgt_hb)); // Recursive calls down - AADD low, high; aadd_refs_spawn(SPAWN(aadd_plus, high_a, high_b)); - low = CALL(aadd_plus, low_a, low_b); - aadd_refs_push(low); - high = aadd_refs_sync(SYNC(aadd_plus)); - aadd_refs_pop(1); + AADD low = aadd_refs_push(CALL(aadd_plus, low_a, low_b)); + AADD high = aadd_refs_sync(SYNC(aadd_plus)); + aadd_refs_pop(5); // Put in cache, return res = aadd_makenode(topvar, low, high); @@ -673,6 +673,8 @@ TASK_IMPL_4(AADD, aadd_matvec_mult_rec, AADD, mat, AADD, vec, BDDVAR, nvars, BDD return aadd_bundle(AADD_TERMINAL, prod); } + sylvan_gc_test(); + // Check cache AADD res; bool cachenow = ((nextvar % granularity) == 0); @@ -697,26 +699,25 @@ TASK_IMPL_4(AADD, aadd_matvec_mult_rec, AADD, mat, AADD, vec, BDDVAR, nvars, BDD aadd_get_topvar(mat_high,2*nextvar+1, &var, &u01, &u11); // 2. propagate "in-between" weights of matrix AADD - u00 = aadd_bundle(AADD_TARGET(u00), wgt_mul(AADD_WEIGHT(u00), AADD_WEIGHT(mat_low))); - u10 = aadd_bundle(AADD_TARGET(u10), wgt_mul(AADD_WEIGHT(u10), AADD_WEIGHT(mat_low))); - u01 = aadd_bundle(AADD_TARGET(u01), wgt_mul(AADD_WEIGHT(u01), AADD_WEIGHT(mat_high))); - u11 = aadd_bundle(AADD_TARGET(u11), wgt_mul(AADD_WEIGHT(u11), AADD_WEIGHT(mat_high))); + u00 = aadd_refs_push(aadd_bundle(AADD_TARGET(u00), wgt_mul(AADD_WEIGHT(u00), AADD_WEIGHT(mat_low)))); + u10 = aadd_refs_push(aadd_bundle(AADD_TARGET(u10), wgt_mul(AADD_WEIGHT(u10), AADD_WEIGHT(mat_low)))); + u01 = aadd_refs_push(aadd_bundle(AADD_TARGET(u01), wgt_mul(AADD_WEIGHT(u01), AADD_WEIGHT(mat_high)))); + u11 = aadd_refs_push(aadd_bundle(AADD_TARGET(u11), wgt_mul(AADD_WEIGHT(u11), AADD_WEIGHT(mat_high)))); + aadd_refs_push(vec_low); + aadd_refs_push(vec_high); // 3. recursive calls (4 tasks: SPAWN 3, CALL 1) // |u00 u01| |vec_low | = vec_low|u00| + vec_high|u01| // |u10 u11| |vec_high| |u10| |u11| AADD res_low00, res_low10, res_high01, res_high11; - nextvar++; - aadd_refs_spawn(SPAWN(aadd_matvec_mult_rec, u00, vec_low, nvars, nextvar)); // 1 - aadd_refs_spawn(SPAWN(aadd_matvec_mult_rec, u10, vec_low, nvars, nextvar)); // 2 - aadd_refs_spawn(SPAWN(aadd_matvec_mult_rec, u01, vec_high, nvars, nextvar)); // 3 - res_high11 = CALL(aadd_matvec_mult_rec, u11, vec_high, nvars, nextvar); - aadd_refs_push(res_high11); + aadd_refs_spawn(SPAWN(aadd_matvec_mult_rec, u00, vec_low, nvars, nextvar+1)); // 1 + aadd_refs_spawn(SPAWN(aadd_matvec_mult_rec, u10, vec_low, nvars, nextvar+1)); // 2 + aadd_refs_spawn(SPAWN(aadd_matvec_mult_rec, u01, vec_high, nvars, nextvar+1)); // 3 + res_high11 = aadd_refs_push(CALL(aadd_matvec_mult_rec, u11, vec_high, nvars, nextvar+1)); // gc called in here res_high01 = aadd_refs_sync(SYNC(aadd_matvec_mult_rec)); // 3 res_low10 = aadd_refs_sync(SYNC(aadd_matvec_mult_rec)); // 2 - res_low00 = aadd_refs_sync(SYNC(aadd_matvec_mult_rec)); // 1 - aadd_refs_pop(1); - nextvar--; + res_low00 = aadd_refs_sync(SYNC(aadd_matvec_mult_rec)); // 1 // gc called in here + aadd_refs_pop(6); // 4. gather results of multiplication AADD res_low, res_high; @@ -724,7 +725,7 @@ TASK_IMPL_4(AADD, aadd_matvec_mult_rec, AADD, mat, AADD, vec, BDDVAR, nvars, BDD res_high = aadd_makenode(nextvar, res_high01, res_high11); // 5. add resulting AADDs - res = CALL(aadd_plus, res_low, res_high); + res = CALL(aadd_plus, res_low, res_high); // gc called in here // Insert in cache (before multiplication w/ root weights) if (cachenow) { @@ -754,6 +755,8 @@ TASK_IMPL_4(AADD, aadd_matmat_mult_rec, AADD, a, AADD, b, BDDVAR, nvars, BDDVAR, return aadd_bundle(AADD_TERMINAL, prod); } + sylvan_gc_test(); + // Check cache AADD res; bool cachenow = ((nextvar % granularity) == 0); @@ -780,29 +783,27 @@ TASK_IMPL_4(AADD, aadd_matmat_mult_rec, AADD, a, AADD, b, BDDVAR, nvars, BDDVAR, aadd_get_topvar(b_high,2*nextvar+1, &var, &b01, &b11); // 2. propagate "in-between" weights down - a00 = aadd_bundle(AADD_TARGET(a00), wgt_mul(AADD_WEIGHT(a_low), AADD_WEIGHT(a00))); - a10 = aadd_bundle(AADD_TARGET(a10), wgt_mul(AADD_WEIGHT(a_low), AADD_WEIGHT(a10))); - a01 = aadd_bundle(AADD_TARGET(a01), wgt_mul(AADD_WEIGHT(a_high),AADD_WEIGHT(a01))); - a11 = aadd_bundle(AADD_TARGET(a11), wgt_mul(AADD_WEIGHT(a_high),AADD_WEIGHT(a11))); - b00 = aadd_bundle(AADD_TARGET(b00), wgt_mul(AADD_WEIGHT(b_low), AADD_WEIGHT(b00))); - b10 = aadd_bundle(AADD_TARGET(b10), wgt_mul(AADD_WEIGHT(b_low), AADD_WEIGHT(b10))); - b01 = aadd_bundle(AADD_TARGET(b01), wgt_mul(AADD_WEIGHT(b_high),AADD_WEIGHT(b01))); - b11 = aadd_bundle(AADD_TARGET(b11), wgt_mul(AADD_WEIGHT(b_high),AADD_WEIGHT(b11))); + a00 = aadd_refs_push(aadd_bundle(AADD_TARGET(a00), wgt_mul(AADD_WEIGHT(a_low), AADD_WEIGHT(a00)))); + a10 = aadd_refs_push(aadd_bundle(AADD_TARGET(a10), wgt_mul(AADD_WEIGHT(a_low), AADD_WEIGHT(a10)))); + a01 = aadd_refs_push(aadd_bundle(AADD_TARGET(a01), wgt_mul(AADD_WEIGHT(a_high),AADD_WEIGHT(a01)))); + a11 = aadd_refs_push(aadd_bundle(AADD_TARGET(a11), wgt_mul(AADD_WEIGHT(a_high),AADD_WEIGHT(a11)))); + b00 = aadd_refs_push(aadd_bundle(AADD_TARGET(b00), wgt_mul(AADD_WEIGHT(b_low), AADD_WEIGHT(b00)))); + b10 = aadd_refs_push(aadd_bundle(AADD_TARGET(b10), wgt_mul(AADD_WEIGHT(b_low), AADD_WEIGHT(b10)))); + b01 = aadd_refs_push(aadd_bundle(AADD_TARGET(b01), wgt_mul(AADD_WEIGHT(b_high),AADD_WEIGHT(b01)))); + b11 = aadd_refs_push(aadd_bundle(AADD_TARGET(b11), wgt_mul(AADD_WEIGHT(b_high),AADD_WEIGHT(b11)))); // 3. recursive calls (8 tasks: SPAWN 7, CALL 1) // |a00 a01| |b00 b01| = b00|a00| + b10|a01| , b01|a00| + b11|a01| // |a10 a11| |b10 b11| |a10| |a11| |a10| |a11| AADD a00_b00, a00_b01, a10_b00, a10_b01, a01_b10, a01_b11, a11_b10, a11_b11; - nextvar++; - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a00, b00, nvars, nextvar)); // 1 - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a00, b01, nvars, nextvar)); // 2 - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a10, b00, nvars, nextvar)); // 3 - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a10, b01, nvars, nextvar)); // 4 - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a01, b10, nvars, nextvar)); // 5 - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a01, b11, nvars, nextvar)); // 6 - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a11, b10, nvars, nextvar)); // 7 - a11_b11 = CALL(aadd_matmat_mult_rec, a11, b11, nvars, nextvar); - aadd_refs_push(a11_b11); + aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a00, b00, nvars, nextvar+1)); // 1 + aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a00, b01, nvars, nextvar+1)); // 2 + aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a10, b00, nvars, nextvar+1)); // 3 + aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a10, b01, nvars, nextvar+1)); // 4 + aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a01, b10, nvars, nextvar+1)); // 5 + aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a01, b11, nvars, nextvar+1)); // 6 + aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a11, b10, nvars, nextvar+1)); // 7 + a11_b11 = aadd_refs_push(CALL(aadd_matmat_mult_rec, a11, b11, nvars, nextvar+1)); a11_b10 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 7 a01_b11 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 6 a01_b10 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 5 @@ -810,8 +811,7 @@ TASK_IMPL_4(AADD, aadd_matmat_mult_rec, AADD, a, AADD, b, BDDVAR, nvars, BDDVAR, a10_b00 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 3 a00_b01 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 2 a00_b00 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 1 - aadd_refs_pop(1); - nextvar--; + aadd_refs_pop(9); // 4. gather results of multiplication AADD lh1, lh2, rh1, rh2; diff --git a/src/sylvan_aadd_int.h b/src/sylvan_aadd_int.h index bf741be..514aff2 100644 --- a/src/sylvan_aadd_int.h +++ b/src/sylvan_aadd_int.h @@ -278,7 +278,7 @@ _aadd_makenode(BDDVAR var, AADD_TARG low, AADD_TARG high, AADD_WGT a, AADD_WGT b int created; AADD_TARG index = llmsset_lookup(nodes, n.low, n.high, &created); if (index == 0) { - printf("auto gc of node table triggered\n"); + //printf("auto gc of node table triggered\n"); aadd_refs_push(low); aadd_refs_push(high); From 505761617fa1f6901e0eb8e43cba545804f6bfd3 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Tue, 18 Jun 2024 12:06:53 +0200 Subject: [PATCH 22/37] rename arg --- qasm/sim_qasm.c | 4 ++-- qasm/test/test_sim_qasm.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qasm/sim_qasm.c b/qasm/sim_qasm.c index 8de5854..cb08e5e 100644 --- a/qasm/sim_qasm.c +++ b/qasm/sim_qasm.c @@ -35,8 +35,8 @@ static struct argp_option options[] = {"json", 'j', "", 0, "Write stats to given filename as json", 0}, {"count-nodes", 'c', 0, 0, "Track maximum number of nodes", 0}, {"state-vector", 'v', 0, 0, "Also output the complete state vector", 0}, - {"allow-reorder", 10, 0, 0, "Reorders the qubits once such that (most) controls occur before targets in the variable order.", 0}, - {"allow-reorder-swaps", 11, 0, 0, "Reorders the qubits such that all controls occur before targets (requires inserting SWAP gates).", 0}, + {"reorder", 10, 0, 0, "Reorders the qubits once such that (most) controls occur before targets in the variable order.", 0}, + {"reorder-swaps", 11, 0, 0, "Reorders the qubits such that all controls occur before targets (requires inserting SWAP gates).", 0}, {"disable-inv-caching", 12, 0, 0, "Disable storing inverse of MUL and DIV in cache.", 0}, {0, 0, 0, 0, 0, 0} }; diff --git a/qasm/test/test_sim_qasm.py b/qasm/test/test_sim_qasm.py index 5cb6eba..3cf32f8 100644 --- a/qasm/test/test_sim_qasm.py +++ b/qasm/test/test_sim_qasm.py @@ -36,7 +36,7 @@ def get_vector(qasm_file : str, args : list): @pytest.mark.parametrize("cl_args", [['-s', 'low'], ['-s', 'max'], ['-s', 'min'], ['-s', 'l2'], - ['--allow-reorder'], ['--allow-reorder-swap']]) + ['--reorder'], ['--reorder-swap']]) class TestCircuits: """ Test sim_qasm on all given circuits, with CL arguments given above. From 047688ae01beff1eb8b1acc6a316ffb885e29351 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Wed, 19 Jun 2024 10:30:31 +0200 Subject: [PATCH 23/37] don't write json to stdout when already writing to file --- qasm/sim_qasm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qasm/sim_qasm.c b/qasm/sim_qasm.c index cb08e5e..2b6c6f0 100644 --- a/qasm/sim_qasm.c +++ b/qasm/sim_qasm.c @@ -383,11 +383,12 @@ int main(int argc, char *argv[]) simulate_circuit(circuit); - fprint_stats(stdout, circuit); if (json_outputfile != NULL) { FILE *fp = fopen(json_outputfile, "w"); fprint_stats(fp, circuit); fclose(fp); + } else { + fprint_stats(stdout, circuit); } sylvan_quit(); From 5257448c2064321a4f01dbbcf5575da22ffc4050 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Mon, 24 Jun 2024 13:53:50 +0200 Subject: [PATCH 24/37] fix reordering qubits for gates w/ multiple targets --- qasm/simple_parser.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/qasm/simple_parser.cpp b/qasm/simple_parser.cpp index 53c79a6..507f54d 100644 --- a/qasm/simple_parser.cpp +++ b/qasm/simple_parser.cpp @@ -649,7 +649,11 @@ void reverse_order(quantum_circuit_t *circuit) quantum_op_t* head = circuit->operations; while (head != NULL) { if (head->type == op_gate || head->type == op_measurement) { - head->targets[0] = (circuit->qreg_size - 1) - head->targets[0]; + for (int j = 0; j < 2; j++) { + if (head->targets[j] != -1) { + head->targets[j] = (circuit->qreg_size - 1) - head->targets[j]; + } + } for (int j = 0; j < 3; j++) { if (head->ctrls[j] != -1) { head->ctrls[j] = (circuit->qreg_size - 1) - head->ctrls[j]; From 7d92d1bec803a59c51bc5067d736df96d9e260ab Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Tue, 25 Jun 2024 15:01:08 +0200 Subject: [PATCH 25/37] fix bug: crz gate is not symmetric --- qasm/simple_parser.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qasm/simple_parser.cpp b/qasm/simple_parser.cpp index 507f54d..b20f799 100644 --- a/qasm/simple_parser.cpp +++ b/qasm/simple_parser.cpp @@ -624,13 +624,14 @@ void insert_required_swaps(quantum_circuit_t *circuit) void order_cphase_gates(quantum_circuit_t *circuit) { - // Since for any controlled phase gate (cz, cp, crz) cp(c,t) = c(t,c), + // Since for any controlled phase gate (cp, cz=cp(pi)) cp(c,t) = c(t,c), // change the order such that c < t + // Note that crz(theta) is not symmetric quantum_op_t* head = circuit->operations; while (head != NULL) { if (head->type == op_gate) { std::string name = std::string(head->name); - if (name == "cz" || name == "cp" || name == "crz") { + if (name == "cz" || name == "cp") { if (head->ctrls[0] > head->targets[0]) { int tmp = head->targets[0]; head->targets[0] = head->ctrls[0]; From b51dad4e88b85cd8167ef719ca61926cc7d38f35 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Thu, 27 Jun 2024 11:56:22 +0200 Subject: [PATCH 26/37] added circuit equivalence checking to examples --- examples/CMakeLists.txt | 25 ++-- examples/circuit_equivalence.c | 226 +++++++++++++++++++++++++++++++++ 2 files changed, 239 insertions(+), 12 deletions(-) create mode 100644 examples/circuit_equivalence.c diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 821ba2a..1ac660a 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,11 +1,3 @@ -set(SOURCES - grover_cnf.c - grover.c - random_circuit.c - shor.c - supremacy.c -) - if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # add argp library for OSX find_package(Argp REQUIRED) @@ -26,12 +18,21 @@ macro(add_example NAME SOURCE) endmacro(add_example) add_example(bell_state bell_state.c) -# target_sources(bell_state PRIVATE getrss.c getrss.h) - add_example(vqc vqc.c) +set(ALGORITHM_EXAMPLES + grover_cnf.c + grover.c + random_circuit.c + shor.c + supremacy.c +) + add_example(alg_run alg_run.c) -target_sources(alg_run PRIVATE ${SOURCES}) +target_sources(alg_run PRIVATE ${ALGORITHM_EXAMPLES}) add_example(test_algs test_algs.c) -target_sources(test_algs PRIVATE ${SOURCES}) +target_sources(test_algs PRIVATE ${ALGORITHM_EXAMPLES}) + +add_executable(circuit_equivalence circuit_equivalence.c) +target_link_libraries(circuit_equivalence qsylvan qsylvan_qasm_parser) diff --git a/examples/circuit_equivalence.c b/examples/circuit_equivalence.c new file mode 100644 index 0000000..603c6e0 --- /dev/null +++ b/examples/circuit_equivalence.c @@ -0,0 +1,226 @@ +#include +#include +#include +#include +#include +#include +#include +#include "../qasm/simple_parser.h" + +#define max(a,b) ((a > b) ? a : b) + +static int workers = 1; +static size_t min_tablesize = 1LL<<18; +static size_t max_tablesize = 1LL<<20; +static size_t min_cachesize = 1LL<<16; +static size_t max_cachesize = 1LL<<18; +static size_t wgt_tab_size = 1LL<<15; +static double tolerance = 1e-14; +static int wgt_table_type = COMP_HASHMAP; +static int wgt_norm_strat = NORM_MAX; +static int count_nodes = 1; + + +typedef struct stats_s { + bool are_equiv; + double cpu_time; + double wall_time; + size_t max_nodes_total; + size_t max_nodes_U; + size_t max_nodes_V; +} stats_t; +stats_t stats = {0}; + +quantum_circuit_t* circuit_U; +quantum_circuit_t* circuit_V; + + +void print_stats() { + // print stats in JSON format + printf("{\n"); + printf(" \"statistics\": {\n"); + printf(" \"are_equiv\" : %d,\n", (int)stats.are_equiv); + printf(" \"circuit_U\": \"%s\",\n", circuit_U->name); + printf(" \"circuit_V\": \"%s\",\n", circuit_V->name); + printf(" \"max_nodes_total\": %" PRIu64 ",\n", stats.max_nodes_total); + printf(" \"max_nodes_U\": %" PRIu64 ",\n", stats.max_nodes_U); + printf(" \"max_nodes_V\": %" PRIu64 ",\n", stats.max_nodes_V); + printf(" \"n_qubits\": %d,\n", circuit_U->qreg_size); + printf(" \"time_cpu\": %lf,\n", stats.cpu_time); + printf(" \"time_wall\": %lf,\n", stats.wall_time); + printf(" \"tolerance\": %.5e,\n", tolerance); + printf(" \"wgt_norm_strat\": %d,\n", wgt_norm_strat); + printf(" \"workers\": %d\n", workers); + printf(" }\n"); + printf("}\n"); +} + +/** + * Obtain current wallclock time + */ +static double +wctime() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (tv.tv_sec + 1E-6 * tv.tv_usec); +} + + +QMDD get_gate_matrix(quantum_op_t* gate, BDDVAR nqubits, bool dag) { + if (strcmp(gate->name, "id") == 0) { + return qmdd_create_all_identity_matrix(nqubits); + } + else if (strcmp(gate->name, "x") == 0) { + return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_X); + } + else if (strcmp(gate->name, "y") == 0) { + return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_Y); + } + else if (strcmp(gate->name, "z") == 0) { + return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_Z); + } + else if (strcmp(gate->name, "h") == 0) { + return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_H); + } + else if (strcmp(gate->name, "s") == 0) { + if (dag) return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_Sdag); + else return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_S); + } + else if (strcmp(gate->name, "sdg") == 0) { + if (dag) return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_S); + else return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_Sdag); + } + else if (strcmp(gate->name, "t") == 0) { + if (dag) return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_Tdag); + else return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_T); + } + else if (strcmp(gate->name, "tdg") == 0) { + if (dag) return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_T); + else return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_Tdag); + } + else if (strcmp(gate->name, "cx") == 0) { + return qmdd_create_controlled_gate(nqubits, gate->ctrls[0], gate->targets[0], GATEID_X); + } + else if (strcmp(gate->name, "cz") == 0) { + return qmdd_create_controlled_gate(nqubits, gate->ctrls[0], gate->targets[0], GATEID_Z); + } + else { + fprintf(stderr, "Gate '%s' currently unsupported\n", gate->name); + exit(EXIT_FAILURE); + } +} + +QMDD compute_UPUdag(quantum_circuit_t *circuit, gate_id_t P, BDDVAR k) { + BDDVAR nqubits = circuit->qreg_size; + QMDD circ_matrix = qmdd_create_single_qubit_gate(nqubits, k, P); + QMDD tmp = AADD_ZERO; + aadd_protect(&circ_matrix); + aadd_protect(&tmp); + + quantum_op_t *op = circuit->operations; + while (op != NULL) { + switch (op->type) { + case op_gate: + tmp = get_gate_matrix(op, nqubits, false); + circ_matrix = aadd_matmat_mult(tmp, circ_matrix, nqubits); + tmp = get_gate_matrix(op, nqubits, true); + circ_matrix = aadd_matmat_mult(circ_matrix, tmp, nqubits); + break; + case op_measurement: + fprintf(stderr, "ERROR: Measurments not supported\n"); + exit(EXIT_FAILURE); + break; + default: + break; + } + op = op->next; + } + + aadd_unprotect(&circ_matrix); + aadd_unprotect(&tmp); + + return circ_matrix; +} + + void circuit_equivalence_check(quantum_circuit_t *U, quantum_circuit_t *V) { + if (U->qreg_size != V->qreg_size) { + fprintf(stderr, "Circuits have different number of qubits\n"); + return; + } + + BDDVAR nqubits = U->qreg_size; + + uint64_t m = 0; + uint32_t XZ[2] = {GATEID_X, GATEID_Z}; + char XZ_str[2] = {'X', 'Z'}; + for (BDDVAR k = 0; k < nqubits; k++) { + for (int i = 0; i < 2; i++) { + QMDD qmdd_U = compute_UPUdag(U, XZ[i], k); + QMDD qmdd_V = compute_UPUdag(V, XZ[i], k); + + if (count_nodes) { + size_t nodes_U = aadd_countnodes(qmdd_U); + size_t nodes_V = aadd_countnodes(qmdd_V); + stats.max_nodes_total = max(stats.max_nodes_total,nodes_U+nodes_V); + stats.max_nodes_U = max(stats.max_nodes_U, nodes_U); + stats.max_nodes_V = max(stats.max_nodes_V, nodes_V); + } + + if (qmdd_U != qmdd_V) { + stats.are_equiv = false; + printf("U*%c_%d*U^dag != V*%c_%d*V^dag (%zu nodes)\n", + XZ_str[i], k, XZ_str[i], k, (size_t)m); + return; + } + } + } + + stats.are_equiv = true; +} + +int main(int argc, char *argv[]) { + + if (argc != 3) { + printf("Expected ./circuit_eq file1.qasm file2.qasm\n"); + exit(EXIT_FAILURE); + } + + char fileName1[200]; + char fileName2[200]; + strcpy(fileName1, argv[1]); + strcpy(fileName2, argv[2]); + + circuit_U = parse_qasm_file(fileName1); + circuit_V = parse_qasm_file(fileName2); + optimize_qubit_order(circuit_U, false); // TODO: remove + optimize_qubit_order(circuit_V, false); + // TODO: instead: make make qmdd_create_controlled_gate independent of order + // of c and t (or make it a wrapper which calls create_multi_cgate) + + // Init + lace_start(workers, 0); + sylvan_set_sizes(min_tablesize, max_tablesize, min_cachesize, max_cachesize); + sylvan_init_package(); + qsylvan_init_simulator(wgt_tab_size, wgt_tab_size, tolerance, wgt_table_type, wgt_norm_strat); + + clock_t cpu_t1 = clock(); + double wall_t1 = wctime(); + + circuit_equivalence_check(circuit_U, circuit_V); + + clock_t cpu_t2 = clock(); + double wall_t2 = wctime(); + + stats.cpu_time = (double)(cpu_t2 - cpu_t1) / CLOCKS_PER_SEC; + stats.wall_time = wall_t2 - wall_t1; + print_stats(); + + // Cleanup + sylvan_quit(); + lace_stop(); + free_quantum_circuit(circuit_U); + free_quantum_circuit(circuit_V); + + return 0; +} From c06e995d38eb7dfa67d0ed7898ee5cd7e866d9f5 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Thu, 27 Jun 2024 13:36:28 +0200 Subject: [PATCH 27/37] small refactor of create_cgate --- docs/documentation/c_interface.md | 2 +- examples/circuit_equivalence.c | 6 ++--- src/qsylvan_mtbdd_simulator.c | 2 +- src/qsylvan_simulator.c | 45 ++++++++----------------------- src/qsylvan_simulator.h | 5 +++- test/test_qmdd_matrix.c | 6 ++--- 6 files changed, 23 insertions(+), 43 deletions(-) diff --git a/docs/documentation/c_interface.md b/docs/documentation/c_interface.md index 6e34b51..75abbc6 100644 --- a/docs/documentation/c_interface.md +++ b/docs/documentation/c_interface.md @@ -9,7 +9,7 @@ NOTE: In the code we are refering to the QMDDs as QMDDs, but our QMDDs are reall * `qmdd_create_single_qubit_gate(int n, int t, gate_id_t gateid)` : Creates an n-qubit matrix QMDD which applies gate `gateid` to qubit t and I to all others. * `qmdd_create_single_qubit_gates(int n, gate_id_t *gateid)` : Creates an n-qubit matrix QMDD which applies the given list of n `gatesid`'s to n qubits. * `qmdd_create_single_qubit_gates_same(int n, gate_id_t gateid)` : Creates an n-qubit matrix QMDD which applies single qubit gate `gateid` to all qubits. -* `qmdd_create_controlled_gate(int n, int c, int t, gate_id_t gateid)` : Creates an n-qubit matrix QMDD which acts as a controlled-`gateid` gate on target qubit t with control qubit c, and I on all others. (Requires c < t.) +* `qmdd_create_cgate(int n, int c, int t, gate_id_t gateid)` : Creates an n-qubit matrix QMDD which acts as a controlled-`gateid` gate on target qubit t with control qubit c, and I on all others. (Requires c < t.) * `qmdd_create_multi_cgate(int n, int *c_options, gate_id_t gateid)` : Creates a controlled-`gateid` gate which acts on the qubits as specified in by the `c_options` array. `c_options[k]` can contain `-1` = ignore qubit k (apply I), `0` = control qubit k on |0>, `1` = control qubit k on |1>, and `2` = the target qubit. (Requires the index of the target qubit to be greater than the indices of the controls.) * `qmdd_create_all_control_phase(int n, bool *x)` : Creates an n-qubit CZ gate, controlled on all qubits. The array x specifies whether each qubit k is controlled on |0> (when x[k]=0) or on |1> (when x[k]=1). diff --git a/examples/circuit_equivalence.c b/examples/circuit_equivalence.c index 603c6e0..b0b37b3 100644 --- a/examples/circuit_equivalence.c +++ b/examples/circuit_equivalence.c @@ -100,10 +100,10 @@ QMDD get_gate_matrix(quantum_op_t* gate, BDDVAR nqubits, bool dag) { else return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_Tdag); } else if (strcmp(gate->name, "cx") == 0) { - return qmdd_create_controlled_gate(nqubits, gate->ctrls[0], gate->targets[0], GATEID_X); + return qmdd_create_cgate(nqubits, gate->ctrls[0], gate->targets[0], GATEID_X); } else if (strcmp(gate->name, "cz") == 0) { - return qmdd_create_controlled_gate(nqubits, gate->ctrls[0], gate->targets[0], GATEID_Z); + return qmdd_create_cgate(nqubits, gate->ctrls[0], gate->targets[0], GATEID_Z); } else { fprintf(stderr, "Gate '%s' currently unsupported\n", gate->name); @@ -195,7 +195,7 @@ int main(int argc, char *argv[]) { circuit_V = parse_qasm_file(fileName2); optimize_qubit_order(circuit_U, false); // TODO: remove optimize_qubit_order(circuit_V, false); - // TODO: instead: make make qmdd_create_controlled_gate independent of order + // TODO: instead: make make qmdd_create_cgate independent of order // of c and t (or make it a wrapper which calls create_multi_cgate) // Init diff --git a/src/qsylvan_mtbdd_simulator.c b/src/qsylvan_mtbdd_simulator.c index c04c0ba..6e3789d 100644 --- a/src/qsylvan_mtbdd_simulator.c +++ b/src/qsylvan_mtbdd_simulator.c @@ -222,7 +222,7 @@ qmdd_create_single_qubit_gates_same(BDDVAR n, gate_id_t gateid) } QMDD -qmdd_create_controlled_gate(BDDVAR n, BDDVAR c, BDDVAR t, gate_id_t gateid) +qmdd_create_cgate(BDDVAR n, BDDVAR c, BDDVAR t, gate_id_t gateid) { // for now, assume t > c assert(t > c); diff --git a/src/qsylvan_simulator.c b/src/qsylvan_simulator.c index cbcd6d3..eb3eb5b 100644 --- a/src/qsylvan_simulator.c +++ b/src/qsylvan_simulator.c @@ -191,33 +191,17 @@ qmdd_create_single_qubit_gates_same(BDDVAR n, gate_id_t gateid) } QMDD -qmdd_create_controlled_gate(BDDVAR n, BDDVAR c, BDDVAR t, gate_id_t gateid) +_qmdd_create_cgate(BDDVAR n, BDDVAR c1, BDDVAR c2, BDDVAR c3, BDDVAR t, gate_id_t gateid) { - // for now, assume t > c - assert(t > c); - // Start at terminal and build backwards - QMDD prev = aadd_bundle(AADD_TERMINAL, AADD_ONE); - QMDD branch0 = AADD_TERMINAL, branch1 = AADD_TERMINAL; - for (int k = n-1; k>= 0; k--) { - if ((unsigned int)k > t || (unsigned int) k < c) { - prev = qmdd_stack_matrix(prev, k, GATEID_I); - } - else if ((unsigned int) k == t) { - branch0 = qmdd_stack_matrix(prev, k, GATEID_I); - branch1 = qmdd_stack_matrix(prev, k, gateid); - } - else if ((unsigned int) k < t && (unsigned int) k > c) { - branch0 = qmdd_stack_matrix(branch0, k, GATEID_I); - branch1 = qmdd_stack_matrix(branch1, k, GATEID_I); - } - else if ((unsigned int) k == c) { - prev = qmdd_stack_control(branch0, branch1, k); - } - else { - assert("all cases should have been covered" && false); - } - } - return prev; + int *c_options = malloc(sizeof(int)*(n+1)); + for (uint32_t k = 0; k < n; k++) c_options[k] = -1; + if (c1 != AADD_INVALID_VAR && c1 < n) c_options[c1] = 1; + if (c2 != AADD_INVALID_VAR && c2 < n) c_options[c2] = 1; + if (c3 != AADD_INVALID_VAR && c3 < n) c_options[c3] = 1; + if (t != AADD_INVALID_VAR && t < n) c_options[t] = 2; + QMDD gate_matrix = qmdd_create_multi_cgate(n, c_options, gateid); + free(c_options); + return gate_matrix; } QMDD @@ -374,14 +358,7 @@ QMDD _qmdd_cgate(QMDD state, gate_id_t gate, BDDVAR c1, BDDVAR c2, BDDVAR c3, BD } else { assert(n != 0 && "ERROR: when ctrls > targ, nqubits must be passed to cgate() function."); - int *c_options = malloc(sizeof(int)*(n+1)); - for (uint32_t k = 0; k < n; k++) c_options[k] = -1; - if (c1 != AADD_INVALID_VAR && c1 < n) c_options[c1] = 1; - if (c2 != AADD_INVALID_VAR && c2 < n) c_options[c2] = 1; - if (c3 != AADD_INVALID_VAR && c3 < n) c_options[c3] = 1; - if (t != AADD_INVALID_VAR && t < n) c_options[t] = 2; - QMDD gate_matrix = qmdd_create_multi_cgate(n, c_options, gate); - free(c_options); + QMDD gate_matrix = _qmdd_create_cgate(n, c1, c2, c3, t, gate); return aadd_matvec_mult(gate_matrix, state, n); } } diff --git a/src/qsylvan_simulator.h b/src/qsylvan_simulator.h index ba344b7..7bf4bbe 100644 --- a/src/qsylvan_simulator.h +++ b/src/qsylvan_simulator.h @@ -124,7 +124,10 @@ QMDD qmdd_create_single_qubit_gates_same(BDDVAR n, gate_id_t gateid); * * @return A matrix QMDD encoding of the controlled gate on given qubits. */ -QMDD qmdd_create_controlled_gate(BDDVAR n, BDDVAR c, BDDVAR t, gate_id_t gateid); +#define qmdd_create_cgate(n, c, t, gateid) _qmdd_create_cgate(n, c, AADD_INVALID_VAR, AADD_INVALID_VAR, t, gateid) +#define qmdd_create_cgate2(n, c1, c2, t, gateid) _qmdd_create_cgate(n, c1, c2, AADD_INVALID_VAR, t, gateid) +#define qmdd_create_cgate3(n, c1, c2, c3, t, gateid) _qmdd_create_cgate(n, c1, c2, c3, t, gateid) +QMDD _qmdd_create_cgate(BDDVAR n, BDDVAR c1, BDDVAR c2, BDDVAR c3, BDDVAR t, gate_id_t gateid); /** * Creates a controlled-`gateid` gate which acts on the qubits as specified by diff --git a/test/test_qmdd_matrix.c b/test/test_qmdd_matrix.c index 8c39758..9739166 100644 --- a/test/test_qmdd_matrix.c +++ b/test/test_qmdd_matrix.c @@ -351,8 +351,8 @@ int test_cx_gate() mI = qmdd_create_all_identity_matrix(nqubits); mH0 = qmdd_create_single_qubit_gate(nqubits, 0, GATEID_H); mH1 = qmdd_create_single_qubit_gate(nqubits, 1, GATEID_H); - mCNOT = qmdd_create_controlled_gate(nqubits, 0, 1, GATEID_X); - mCZ = qmdd_create_controlled_gate(nqubits, 0, 1, GATEID_Z); + mCNOT = qmdd_create_cgate(nqubits, 0, 1, GATEID_X); + mCZ = qmdd_create_cgate(nqubits, 0, 1, GATEID_Z); // matrix-matrix mult mTemp = aadd_matmat_mult(mI, mH0, nqubits); test_assert(mTemp == mH0); @@ -432,7 +432,7 @@ int test_cz_gate() x2[1] = 0; x2[0] = 0; v0 = qmdd_create_basis_state(nqubits, x2); mH0 = qmdd_create_single_qubit_gate(nqubits, 0, GATEID_H); mH1 = qmdd_create_single_qubit_gate(nqubits, 1, GATEID_H); - mCZ = qmdd_create_controlled_gate(nqubits, 0, 1, GATEID_Z); + mCZ = qmdd_create_cgate(nqubits, 0, 1, GATEID_Z); v0 = aadd_matvec_mult(mH0, v0, nqubits); v0 = aadd_matvec_mult(mH1, v0, nqubits); From 43d51f6678a6d6fc65d53dde1e3934082d0d6dc8 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Thu, 27 Jun 2024 14:37:37 +0200 Subject: [PATCH 28/37] add counterexample to json --- examples/circuit_equivalence.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/examples/circuit_equivalence.c b/examples/circuit_equivalence.c index b0b37b3..501ce50 100644 --- a/examples/circuit_equivalence.c +++ b/examples/circuit_equivalence.c @@ -22,7 +22,8 @@ static int count_nodes = 1; typedef struct stats_s { - bool are_equiv; + bool equivalent; + char counterexample[100]; double cpu_time; double wall_time; size_t max_nodes_total; @@ -39,9 +40,10 @@ void print_stats() { // print stats in JSON format printf("{\n"); printf(" \"statistics\": {\n"); - printf(" \"are_equiv\" : %d,\n", (int)stats.are_equiv); printf(" \"circuit_U\": \"%s\",\n", circuit_U->name); printf(" \"circuit_V\": \"%s\",\n", circuit_V->name); + printf(" \"counterexample\": \"%s\",\n", stats.counterexample); + printf(" \"equivalent\" : %d,\n", (int)stats.equivalent); printf(" \"max_nodes_total\": %" PRIu64 ",\n", stats.max_nodes_total); printf(" \"max_nodes_U\": %" PRIu64 ",\n", stats.max_nodes_U); printf(" \"max_nodes_V\": %" PRIu64 ",\n", stats.max_nodes_V); @@ -151,6 +153,8 @@ QMDD compute_UPUdag(quantum_circuit_t *circuit, gate_id_t P, BDDVAR k) { BDDVAR nqubits = U->qreg_size; + stats.equivalent = true; + uint64_t m = 0; uint32_t XZ[2] = {GATEID_X, GATEID_Z}; char XZ_str[2] = {'X', 'Z'}; @@ -158,6 +162,7 @@ QMDD compute_UPUdag(quantum_circuit_t *circuit, gate_id_t P, BDDVAR k) { for (int i = 0; i < 2; i++) { QMDD qmdd_U = compute_UPUdag(U, XZ[i], k); QMDD qmdd_V = compute_UPUdag(V, XZ[i], k); + // TODO: ^ remove global phase? if (count_nodes) { size_t nodes_U = aadd_countnodes(qmdd_U); @@ -168,15 +173,13 @@ QMDD compute_UPUdag(quantum_circuit_t *circuit, gate_id_t P, BDDVAR k) { } if (qmdd_U != qmdd_V) { - stats.are_equiv = false; - printf("U*%c_%d*U^dag != V*%c_%d*V^dag (%zu nodes)\n", - XZ_str[i], k, XZ_str[i], k, (size_t)m); + stats.equivalent = false; + snprintf(stats.counterexample, sizeof(stats.counterexample), + "U*%c_%d*U^dag != V*%c_%d*V^dag", XZ_str[i], k, XZ_str[i], k); return; } } } - - stats.are_equiv = true; } int main(int argc, char *argv[]) { From 5e38bf86fa0c358656534fc39a342eb77499ef9b Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Thu, 27 Jun 2024 15:55:53 +0200 Subject: [PATCH 29/37] add argp arguments --- examples/circuit_equivalence.c | 87 ++++++++++++++++++++++++---------- qasm/sim_qasm.c | 5 +- 2 files changed, 64 insertions(+), 28 deletions(-) diff --git a/examples/circuit_equivalence.c b/examples/circuit_equivalence.c index 501ce50..fc1a2dd 100644 --- a/examples/circuit_equivalence.c +++ b/examples/circuit_equivalence.c @@ -9,16 +9,69 @@ #define max(a,b) ((a > b) ? a : b) + +/*********************************************/ + static int workers = 1; -static size_t min_tablesize = 1LL<<18; -static size_t max_tablesize = 1LL<<20; +static size_t min_tablesize = 1LL<<20; +static size_t max_tablesize = 1LL<<25; static size_t min_cachesize = 1LL<<16; static size_t max_cachesize = 1LL<<18; -static size_t wgt_tab_size = 1LL<<15; +static size_t wgt_tab_size = 1LL<<23; static double tolerance = 1e-14; static int wgt_table_type = COMP_HASHMAP; static int wgt_norm_strat = NORM_MAX; -static int count_nodes = 1; +static bool count_nodes = false; +static quantum_circuit_t* circuit_U; +static quantum_circuit_t* circuit_V; + +static struct argp_option options[] = +{ + {"workers", 'w', "", 0, "Number of workers/threads (default=1)", 0}, + {"norm-strat", 's', "", 0, "Edge weight normalization strategy (default=max)", 0}, + {"tol", 't', "", 0, "Tolerance for deciding edge weights equal (default=1e-14)", 0}, + {"count-nodes", 'c', 0, 0, "Track maximum number of nodes", 0}, + {0, 0, 0, 0, 0, 0} +}; +static error_t +parse_opt(int key, char *arg, struct argp_state *state) +{ + switch (key) { + case 'w': + workers = atoi(arg); + break; + case 's': + if (strcmp(arg, "low")==0) wgt_norm_strat = NORM_LOW; + else if (strcmp(arg, "max")==0) wgt_norm_strat = NORM_MAX; + else if (strcmp(arg, "min")==0) wgt_norm_strat = NORM_MIN; + else if (strcasecmp(arg, "l2")==0) wgt_norm_strat = NORM_L2; + else argp_usage(state); + break; + case 't': + tolerance = atof(arg); + break; + case 'c': + count_nodes = true; + break; + case ARGP_KEY_ARG: + if (state->arg_num == 0) + circuit_U = parse_qasm_file(arg); + else if (state->arg_num == 1) + circuit_V = parse_qasm_file(arg); + else + argp_usage(state); + break; + case ARGP_KEY_END: + if (state->arg_num < 1) argp_usage(state); + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} +static struct argp argp = { options, parse_opt, " ", 0, 0, 0, 0 }; + +/********************************************/ typedef struct stats_s { @@ -32,9 +85,6 @@ typedef struct stats_s { } stats_t; stats_t stats = {0}; -quantum_circuit_t* circuit_U; -quantum_circuit_t* circuit_V; - void print_stats() { // print stats in JSON format @@ -70,6 +120,8 @@ wctime() QMDD get_gate_matrix(quantum_op_t* gate, BDDVAR nqubits, bool dag) { + // TODO: move this relation between parsed quantum_op and internal gate + // somewhere else? if (strcmp(gate->name, "id") == 0) { return qmdd_create_all_identity_matrix(nqubits); } @@ -182,24 +234,9 @@ QMDD compute_UPUdag(quantum_circuit_t *circuit, gate_id_t P, BDDVAR k) { } } -int main(int argc, char *argv[]) { - - if (argc != 3) { - printf("Expected ./circuit_eq file1.qasm file2.qasm\n"); - exit(EXIT_FAILURE); - } - - char fileName1[200]; - char fileName2[200]; - strcpy(fileName1, argv[1]); - strcpy(fileName2, argv[2]); - - circuit_U = parse_qasm_file(fileName1); - circuit_V = parse_qasm_file(fileName2); - optimize_qubit_order(circuit_U, false); // TODO: remove - optimize_qubit_order(circuit_V, false); - // TODO: instead: make make qmdd_create_cgate independent of order - // of c and t (or make it a wrapper which calls create_multi_cgate) +int main(int argc, char *argv[]) +{ + argp_parse(&argp, argc, argv, 0, 0, 0); // Init lace_start(workers, 0); diff --git a/qasm/sim_qasm.c b/qasm/sim_qasm.c index 2b6c6f0..2a5d834 100644 --- a/qasm/sim_qasm.c +++ b/qasm/sim_qasm.c @@ -163,9 +163,8 @@ wctime() QMDD apply_gate(QMDD state, quantum_op_t* gate, BDDVAR nqubits) { - // This looks very ugly, but we need some way to match the name of a gate to - // the GATEID, and since this is C we don't really have easy access to - // data structures like a dictionary. + // TODO: move this relation between parsed quantum_op and internal gate + // somewhere else? stats.applied_gates++; if (strcmp(gate->name, "id") == 0) { stats.applied_gates--; From 3421478eda049670ce8ed610c9b8e2333ac2527a Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Mon, 1 Jul 2024 13:44:06 +0200 Subject: [PATCH 30/37] extend gate set for circuit eq --- examples/circuit_equivalence.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/examples/circuit_equivalence.c b/examples/circuit_equivalence.c index fc1a2dd..a0fbdf6 100644 --- a/examples/circuit_equivalence.c +++ b/examples/circuit_equivalence.c @@ -153,6 +153,18 @@ QMDD get_gate_matrix(quantum_op_t* gate, BDDVAR nqubits, bool dag) { if (dag) return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_T); else return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_Tdag); } + else if (strcmp(gate->name, "rx") == 0) { + if (dag) return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_Rx(-gate->angle[0])); + else return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_Rx(gate->angle[0])); + } + else if (strcmp(gate->name, "ry") == 0) { + if (dag) return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_Ry(-gate->angle[0])); + else return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_Ry(gate->angle[0])); + } + else if (strcmp(gate->name, "rz") == 0) { + if (dag) return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_Rz(-gate->angle[0])); + else return qmdd_create_single_qubit_gate(nqubits, gate->targets[0], GATEID_Rz(gate->angle[0])); + } else if (strcmp(gate->name, "cx") == 0) { return qmdd_create_cgate(nqubits, gate->ctrls[0], gate->targets[0], GATEID_X); } From d0ab71fcd918c8a750c7276f02ce6a52082411f6 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Mon, 1 Jul 2024 16:44:49 +0200 Subject: [PATCH 31/37] write error to json --- examples/circuit_equivalence.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/circuit_equivalence.c b/examples/circuit_equivalence.c index a0fbdf6..ac08c27 100644 --- a/examples/circuit_equivalence.c +++ b/examples/circuit_equivalence.c @@ -211,7 +211,8 @@ QMDD compute_UPUdag(quantum_circuit_t *circuit, gate_id_t P, BDDVAR k) { void circuit_equivalence_check(quantum_circuit_t *U, quantum_circuit_t *V) { if (U->qreg_size != V->qreg_size) { - fprintf(stderr, "Circuits have different number of qubits\n"); + snprintf(stats.counterexample, sizeof(stats.counterexample), + "Circuits have different number of qubits"); return; } From 69496e864cfc31a6377fa85799237e6f7027a381 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Tue, 2 Jul 2024 12:18:44 +0200 Subject: [PATCH 32/37] write error message to stderr --- src/sylvan_edge_weights_complex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sylvan_edge_weights_complex.c b/src/sylvan_edge_weights_complex.c index da2e185..fc78814 100644 --- a/src/sylvan_edge_weights_complex.c +++ b/src/sylvan_edge_weights_complex.c @@ -60,7 +60,7 @@ _weight_complex_lookup_ptr(complex_t *a, void *wgt_store) } if (!success) { - printf("Amplitude table full!\n"); + fprintf(stderr, "Amplitude table full!\n"); exit(1); } return (AADD_WGT) res; From e83a628544e916e309feb185fea4503b41d1f81e Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Tue, 2 Jul 2024 12:38:22 +0200 Subject: [PATCH 33/37] fix in circuit equivalence check --- examples/circuit_equivalence.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/circuit_equivalence.c b/examples/circuit_equivalence.c index ac08c27..ca22084 100644 --- a/examples/circuit_equivalence.c +++ b/examples/circuit_equivalence.c @@ -226,7 +226,9 @@ QMDD compute_UPUdag(quantum_circuit_t *circuit, gate_id_t P, BDDVAR k) { for (BDDVAR k = 0; k < nqubits; k++) { for (int i = 0; i < 2; i++) { QMDD qmdd_U = compute_UPUdag(U, XZ[i], k); + aadd_protect(&qmdd_U); QMDD qmdd_V = compute_UPUdag(V, XZ[i], k); + aadd_unprotect(&qmdd_U); // TODO: ^ remove global phase? if (count_nodes) { From 9c7f0ef809134c6c8d24c4beb838716159fea9cf Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Tue, 2 Jul 2024 13:41:17 +0200 Subject: [PATCH 34/37] restructure gc in matmat mult --- src/sylvan_aadd.c | 54 ++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/src/sylvan_aadd.c b/src/sylvan_aadd.c index f36706d..20969e9 100644 --- a/src/sylvan_aadd.c +++ b/src/sylvan_aadd.c @@ -783,52 +783,48 @@ TASK_IMPL_4(AADD, aadd_matmat_mult_rec, AADD, a, AADD, b, BDDVAR, nvars, BDDVAR, aadd_get_topvar(b_high,2*nextvar+1, &var, &b01, &b11); // 2. propagate "in-between" weights down - a00 = aadd_refs_push(aadd_bundle(AADD_TARGET(a00), wgt_mul(AADD_WEIGHT(a_low), AADD_WEIGHT(a00)))); - a10 = aadd_refs_push(aadd_bundle(AADD_TARGET(a10), wgt_mul(AADD_WEIGHT(a_low), AADD_WEIGHT(a10)))); - a01 = aadd_refs_push(aadd_bundle(AADD_TARGET(a01), wgt_mul(AADD_WEIGHT(a_high),AADD_WEIGHT(a01)))); - a11 = aadd_refs_push(aadd_bundle(AADD_TARGET(a11), wgt_mul(AADD_WEIGHT(a_high),AADD_WEIGHT(a11)))); - b00 = aadd_refs_push(aadd_bundle(AADD_TARGET(b00), wgt_mul(AADD_WEIGHT(b_low), AADD_WEIGHT(b00)))); - b10 = aadd_refs_push(aadd_bundle(AADD_TARGET(b10), wgt_mul(AADD_WEIGHT(b_low), AADD_WEIGHT(b10)))); - b01 = aadd_refs_push(aadd_bundle(AADD_TARGET(b01), wgt_mul(AADD_WEIGHT(b_high),AADD_WEIGHT(b01)))); - b11 = aadd_refs_push(aadd_bundle(AADD_TARGET(b11), wgt_mul(AADD_WEIGHT(b_high),AADD_WEIGHT(b11)))); + a00 = aadd_bundle(AADD_TARGET(a00), wgt_mul(AADD_WEIGHT(a_low), AADD_WEIGHT(a00))); + a10 = aadd_bundle(AADD_TARGET(a10), wgt_mul(AADD_WEIGHT(a_low), AADD_WEIGHT(a10))); + a01 = aadd_bundle(AADD_TARGET(a01), wgt_mul(AADD_WEIGHT(a_high),AADD_WEIGHT(a01))); + a11 = aadd_bundle(AADD_TARGET(a11), wgt_mul(AADD_WEIGHT(a_high),AADD_WEIGHT(a11))); + b00 = aadd_bundle(AADD_TARGET(b00), wgt_mul(AADD_WEIGHT(b_low), AADD_WEIGHT(b00))); + b10 = aadd_bundle(AADD_TARGET(b10), wgt_mul(AADD_WEIGHT(b_low), AADD_WEIGHT(b10))); + b01 = aadd_bundle(AADD_TARGET(b01), wgt_mul(AADD_WEIGHT(b_high),AADD_WEIGHT(b01))); + b11 = aadd_bundle(AADD_TARGET(b11), wgt_mul(AADD_WEIGHT(b_high),AADD_WEIGHT(b11))); // 3. recursive calls (8 tasks: SPAWN 7, CALL 1) // |a00 a01| |b00 b01| = b00|a00| + b10|a01| , b01|a00| + b11|a01| // |a10 a11| |b10 b11| |a10| |a11| |a10| |a11| AADD a00_b00, a00_b01, a10_b00, a10_b01, a01_b10, a01_b11, a11_b10, a11_b11; aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a00, b00, nvars, nextvar+1)); // 1 - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a00, b01, nvars, nextvar+1)); // 2 - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a10, b00, nvars, nextvar+1)); // 3 + aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a10, b00, nvars, nextvar+1)); // 2 + aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a00, b01, nvars, nextvar+1)); // 3 aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a10, b01, nvars, nextvar+1)); // 4 aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a01, b10, nvars, nextvar+1)); // 5 - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a01, b11, nvars, nextvar+1)); // 6 - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a11, b10, nvars, nextvar+1)); // 7 - a11_b11 = aadd_refs_push(CALL(aadd_matmat_mult_rec, a11, b11, nvars, nextvar+1)); - a11_b10 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 7 - a01_b11 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 6 + aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a11, b10, nvars, nextvar+1)); // 6 + aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a01, b11, nvars, nextvar+1)); // 7 + a11_b11 = aadd_refs_push(CALL(aadd_matmat_mult_rec, a11, b11, nvars, nextvar+1)); // 8 + a01_b11 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); aadd_refs_pop(1); // 7 + AADD rh2 = aadd_refs_push(aadd_makenode(2*nextvar+1, a01_b11, a11_b11)); + a11_b10 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 6 a01_b10 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 5 + AADD lh2 = aadd_refs_push(aadd_makenode(2*nextvar+1, a01_b10, a11_b10)); a10_b01 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 4 - a10_b00 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 3 - a00_b01 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 2 + a00_b01 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 3 + AADD rh1 = aadd_refs_push(aadd_makenode(2*nextvar+1, a00_b01, a10_b01)); + a10_b00 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 2 a00_b00 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // 1 - aadd_refs_pop(9); + AADD lh1 = aadd_refs_push(aadd_makenode(2*nextvar+1, a00_b00, a10_b00)); - // 4. gather results of multiplication - AADD lh1, lh2, rh1, rh2; - lh1 = aadd_makenode(2*nextvar+1, a00_b00, a10_b00); - lh2 = aadd_makenode(2*nextvar+1, a01_b10, a11_b10); - rh1 = aadd_makenode(2*nextvar+1, a00_b01, a10_b01); - rh2 = aadd_makenode(2*nextvar+1, a01_b11, a11_b11); - - // 5. add resulting AADDs + // 4. add resulting AADDs AADD lh, rh; aadd_refs_spawn(SPAWN(aadd_plus, lh1, lh2)); rh = CALL(aadd_plus, rh1, rh2); aadd_refs_push(rh); lh = aadd_refs_sync(SYNC(aadd_plus)); - aadd_refs_pop(1); + aadd_refs_pop(5); - // 6. put left and right halves of matix together + // 5. put left and right halves of matix together res = aadd_makenode(2*nextvar, lh, rh); // Insert in cache @@ -837,7 +833,7 @@ TASK_IMPL_4(AADD, aadd_matmat_mult_rec, AADD, a, AADD, b, BDDVAR, nvars, BDDVAR, sylvan_stats_count(AADD_MULT_CACHEDPUT); } - // 7. multiply w/ product of root weights + // 6. multiply w/ product of root weights AADD_WGT prod = wgt_mul(AADD_WEIGHT(a), AADD_WEIGHT(b)); AADD_WGT new_weight = wgt_mul(prod, AADD_WEIGHT(res)); res = aadd_bundle(AADD_TARGET(res), new_weight); From e35d373d0b171d88c247a81fbf68a81432b16f18 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Tue, 9 Jul 2024 12:41:06 +0200 Subject: [PATCH 35/37] inner product function for aadds --- src/sylvan_aadd.c | 56 +++++++++++++++++++++++++++++++++++++++-- src/sylvan_aadd.h | 5 ++++ src/sylvan_int.h | 9 ++++--- test/test_qmdd_basics.c | 33 +++++++++++++++++++++++- 4 files changed, 96 insertions(+), 7 deletions(-) diff --git a/src/sylvan_aadd.c b/src/sylvan_aadd.c index 20969e9..15ca12e 100644 --- a/src/sylvan_aadd.c +++ b/src/sylvan_aadd.c @@ -563,7 +563,7 @@ aadd_do_before_mult(AADD *a, AADD *b) } static void -norm_plus_cache_key(AADD a, AADD b, AADD *x, AADD *y) +norm_commuting_cache_key(AADD a, AADD b, AADD *x, AADD *y) { if (a < b) { *x = a; @@ -608,7 +608,7 @@ TASK_IMPL_2(AADD, aadd_plus, AADD, a, AADD, b) // Check cache AADD x, y; - norm_plus_cache_key(a, b, &x, &y); // (a+b) = (b+a) so normalize cache key + norm_commuting_cache_key(a, b, &x, &y); // (a+b) = (b+a) so normalize cache key bool cachenow = ((topvar % granularity) == 0); if (cachenow) { if (cache_get3(CACHE_AADD_PLUS, sylvan_false, x, y, &res)) { @@ -841,6 +841,58 @@ TASK_IMPL_4(AADD, aadd_matmat_mult_rec, AADD, a, AADD, b, BDDVAR, nvars, BDDVAR, return res; } +TASK_IMPL_4(AADD_WGT, aadd_inner_product, AADD, a, AADD, b, BDDVAR, nvars, BDDVAR, nextvar) +{ + if (AADD_WEIGHT(a) == AADD_ZERO) return AADD_ZERO; + if (AADD_WEIGHT(b) == AADD_ZERO) return AADD_ZERO; + + // Terminal case: currently aadd_inner_product doesn't skip variables, + // so when both point to terminal, both are scalars. + // TODO: allow for skipping variables (and multiply res w/ 2^{# skipped}) + // (requires adding some wgt_from_int() function in wgt interface) + if (nextvar == nvars) { + return wgt_mul(AADD_WEIGHT(a), AADD_WEIGHT(b)); + } + + // Get var(a) and var(b) + AADD low_a, low_b, high_a, high_b; + BDDVAR topvar; + + // For both a and b, get children of node with var=top{topvar(a),topvar(b)} + aadd_get_topvar(a, nextvar, &topvar, &low_a, &high_a); + aadd_get_topvar(b, nextvar, &topvar, &low_b, &high_b); + + // Check cache + // TODO: norm cache key? ( = ^\dagger) + AADD_WGT res; + bool cachenow = ((topvar % granularity) == 0); + if (cachenow) { + if (cache_get4(CACHE_AADD_INPROD, AADD_TARGET(a), AADD_TARGET(b), nextvar, nvars, &res)) { + res = wgt_mul(res, AADD_WEIGHT(a)); + res = wgt_mul(res, AADD_WEIGHT(b)); + return res; + } + } + + // Recursive calls + aadd_refs_spawn(SPAWN(aadd_inner_product, high_a, high_b, nvars, nextvar+1)); + AADD_WGT res_low = aadd_refs_push(CALL(aadd_inner_product, low_a, low_b, nvars, nextvar+1)); + AADD_WGT res_high = aadd_refs_sync(SYNC(aadd_inner_product)); + aadd_refs_pop(1); + + res = wgt_add(res_low, res_high); + + // Insert in cache (before multiplication w/ root weights) + if (cachenow) { + cache_put4(CACHE_AADD_INPROD, AADD_TARGET(a), AADD_TARGET(b), nextvar, nvars, res); + } + + // Multiply result with product of weights of a and b + res = wgt_mul(res, AADD_WEIGHT(a)); + res = wgt_mul(res, AADD_WEIGHT(b)); + return res; +} + AADD aadd_increase_all_vars(AADD a, int k) { diff --git a/src/sylvan_aadd.h b/src/sylvan_aadd.h index c1c3286..790d337 100644 --- a/src/sylvan_aadd.h +++ b/src/sylvan_aadd.h @@ -159,6 +159,11 @@ TASK_DECL_3(AADD, aadd_matmat_mult, AADD, AADD, BDDVAR); TASK_DECL_4(AADD, aadd_matvec_mult_rec, AADD, AADD, BDDVAR, BDDVAR); TASK_DECL_4(AADD, aadd_matmat_mult_rec, AADD, AADD, BDDVAR, BDDVAR); + +/* Computes inner product of two vectors a, b */ +#define aadd_inner_product(a,b,nvars) (RUN(aadd_inner_product,a,b,nvars,0)) +TASK_DECL_4(AADD_WGT, aadd_inner_product, AADD, AADD, BDDVAR, BDDVAR); + /** * Increases all the variable number in AADD a by k (used for tensor product) * diff --git a/src/sylvan_int.h b/src/sylvan_int.h index 0e491cd..8bd9da1 100644 --- a/src/sylvan_int.h +++ b/src/sylvan_int.h @@ -110,10 +110,11 @@ static const uint64_t CACHE_MTBDD_TENSOR = (61LL<<40); static const uint64_t CACHE_AADD_PLUS = (70LL<<40); static const uint64_t CACHE_AADD_MATVEC_MULT = (71LL<<40); static const uint64_t CACHE_AADD_MATMAT_MULT = (72LL<<40); -static const uint64_t CACHE_AADD_REPLACE_TERMINAL = (73LL<<40); -static const uint64_t CACHE_AADD_INC_VARS = (74LL<<40); -static const uint64_t CACHE_AADD_CLEAN_WGT_TABLE = (75LL<<40); -static const uint64_t CACHE_AADD_IS_ORDERED = (76LL<<40); +static const uint64_t CACHE_AADD_INPROD = (73LL<<30); +static const uint64_t CACHE_AADD_REPLACE_TERMINAL = (74LL<<40); +static const uint64_t CACHE_AADD_INC_VARS = (75LL<<40); +static const uint64_t CACHE_AADD_CLEAN_WGT_TABLE = (76LL<<40); +static const uint64_t CACHE_AADD_IS_ORDERED = (77LL<<40); // Operations on AADD edge weights static const uint64_t CACHE_WGT_ADD = (80LL<<40); diff --git a/test/test_qmdd_basics.c b/test/test_qmdd_basics.c index 37f8e42..e1da74f 100644 --- a/test/test_qmdd_basics.c +++ b/test/test_qmdd_basics.c @@ -331,7 +331,37 @@ int test_vector_addition() test_assert(q001 == q100); test_assert(!qmdd_is_unitvector(q001, 4)); - if(VERBOSE) printf("qmdd vector addition: ok\n"); + if(VERBOSE) printf("aadd vector addition: ok\n"); + return 0; +} + +int test_inner_product() +{ + QMDD q0, q1, q00, q01, q10, q11, q000, q001, q010, q100; + bool x4[] = {0, 0, 0, 0}; + BDDVAR nqubits = 4; + + // vectors from test_vector_addition + x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 0; q0 = qmdd_create_basis_state(nqubits, x4); + x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 0; q1 = qmdd_create_basis_state(nqubits, x4); + q00 = aadd_plus(q0, q0); // [0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0] + q01 = aadd_plus(q0, q1); // [0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0] + q11 = aadd_plus(q1, q1); // [0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0] + q000 = aadd_plus(q00, q0); // [0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0] + q001 = aadd_plus(q00, q1); // [0 0 2 0 0 0 0 0 0 0 0 1 0 0 0 0] + + test_assert(aadd_inner_product(q00, q00, nqubits) == complex_lookup(4.0, 0.0)); + test_assert(aadd_inner_product(q01, q01, nqubits) == complex_lookup(2.0, 0.0)); + test_assert(aadd_inner_product(q11, q11, nqubits) == complex_lookup(4.0, 0.0)); + test_assert(aadd_inner_product(q000, q000, nqubits) == complex_lookup(9.0, 0.0)); + test_assert(aadd_inner_product(q001, q001, nqubits) == complex_lookup(5.0, 0.0)); + test_assert(aadd_inner_product(q00, q01, nqubits) == complex_lookup(2.0, 0.0)); + test_assert(aadd_inner_product(q00, q000, nqubits) == complex_lookup(6.0, 0.0)); + test_assert(aadd_inner_product(q01, q000, nqubits) == complex_lookup(3.0, 0.0)); + test_assert(aadd_inner_product(q000, q001, nqubits) == complex_lookup(6.0, 0.0)); + test_assert(aadd_inner_product(q01, q001, nqubits) == complex_lookup(3.0, 0.0)); + + if (VERBOSE) printf("aadd inner product: ok\n"); return 0; } @@ -344,6 +374,7 @@ int run_qmdd_tests() if (test_complex_operations()) return 1; if (test_basis_state_creation()) return 1; if (test_vector_addition()) return 1; + if (test_inner_product()) return 1; return 0; } From 4395bc2361f67ec23d9ccabc2e261be8c88ac778 Mon Sep 17 00:00:00 2001 From: Sebastiaan Brand Date: Tue, 9 Jul 2024 16:33:48 +0200 Subject: [PATCH 36/37] compute inner product of complex vectors --- src/sylvan_aadd.c | 11 +++++++---- src/sylvan_aadd.h | 5 ++++- src/sylvan_edge_weights.c | 19 +++++++++++++++++++ src/sylvan_edge_weights.h | 3 +++ src/sylvan_edge_weights_complex.c | 6 ++++++ src/sylvan_edge_weights_complex.h | 1 + test/test_qmdd_basics.c | 9 ++++++++- 7 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/sylvan_aadd.c b/src/sylvan_aadd.c index 15ca12e..07cfb58 100644 --- a/src/sylvan_aadd.c +++ b/src/sylvan_aadd.c @@ -851,7 +851,7 @@ TASK_IMPL_4(AADD_WGT, aadd_inner_product, AADD, a, AADD, b, BDDVAR, nvars, BDDVA // TODO: allow for skipping variables (and multiply res w/ 2^{# skipped}) // (requires adding some wgt_from_int() function in wgt interface) if (nextvar == nvars) { - return wgt_mul(AADD_WEIGHT(a), AADD_WEIGHT(b)); + return wgt_mul(AADD_WEIGHT(a), wgt_conj(AADD_WEIGHT(b))); } // Get var(a) and var(b) @@ -869,7 +869,7 @@ TASK_IMPL_4(AADD_WGT, aadd_inner_product, AADD, a, AADD, b, BDDVAR, nvars, BDDVA if (cachenow) { if (cache_get4(CACHE_AADD_INPROD, AADD_TARGET(a), AADD_TARGET(b), nextvar, nvars, &res)) { res = wgt_mul(res, AADD_WEIGHT(a)); - res = wgt_mul(res, AADD_WEIGHT(b)); + res = wgt_mul(res, wgt_conj(AADD_WEIGHT(b))); return res; } } @@ -887,9 +887,12 @@ TASK_IMPL_4(AADD_WGT, aadd_inner_product, AADD, a, AADD, b, BDDVAR, nvars, BDDVA cache_put4(CACHE_AADD_INPROD, AADD_TARGET(a), AADD_TARGET(b), nextvar, nvars, res); } - // Multiply result with product of weights of a and b + // Multiply result with product of weights of a and (conjugate of) b + // (Note that we can compute the complex conjugate of |b> by taking the + // complex conjugate of all edge weights separately, since + // (w1 • w2)* = (w2* • w1*) and for scalars (w2* • w1*) = (w1* • w2*).) res = wgt_mul(res, AADD_WEIGHT(a)); - res = wgt_mul(res, AADD_WEIGHT(b)); + res = wgt_mul(res, wgt_conj(AADD_WEIGHT(b))); return res; } diff --git a/src/sylvan_aadd.h b/src/sylvan_aadd.h index 790d337..d34da44 100644 --- a/src/sylvan_aadd.h +++ b/src/sylvan_aadd.h @@ -160,7 +160,10 @@ TASK_DECL_4(AADD, aadd_matvec_mult_rec, AADD, AADD, BDDVAR, BDDVAR); TASK_DECL_4(AADD, aadd_matmat_mult_rec, AADD, AADD, BDDVAR, BDDVAR); -/* Computes inner product of two vectors a, b */ +/** + * Computes inner product of two vectors + * (Note that if b contains complex values, the complex conjugate is taken) +*/ #define aadd_inner_product(a,b,nvars) (RUN(aadd_inner_product,a,b,nvars,0)) TASK_DECL_4(AADD_WGT, aadd_inner_product, AADD, AADD, BDDVAR, BDDVAR); diff --git a/src/sylvan_edge_weights.c b/src/sylvan_edge_weights.c index c3b3a1b..6d7b34c 100644 --- a/src/sylvan_edge_weights.c +++ b/src/sylvan_edge_weights.c @@ -35,6 +35,7 @@ _weight_lookup_ptr_f _weight_lookup_ptr; init_one_zero_f init_one_zero; weight_abs_f weight_abs; weight_neg_f weight_neg; +weight_conj_f weight_conj; weight_sqr_f weight_sqr; weight_add_f weight_add; weight_sub_f weight_sub; @@ -81,6 +82,7 @@ void init_edge_weight_functions(edge_weight_type_t edge_weight_type) init_one_zero = (init_one_zero_f) &init_complex_one_zero; weight_abs = (weight_abs_f) &weight_complex_abs; weight_neg = (weight_neg_f) &weight_complex_neg; + weight_conj = (weight_conj_f) &weight_complex_conj; weight_sqr = (weight_sqr_f) &weight_complex_sqr; weight_add = (weight_add_f) &weight_complex_add; weight_sub = (weight_sub_f) &weight_complex_sub; @@ -394,6 +396,23 @@ wgt_neg(AADD_WGT a) return res; } +AADD_WGT +wgt_conj(AADD_WGT a) +{ + // special cases + if (a == AADD_ZERO || a == AADD_ONE || a == AADD_MIN_ONE) return a; + + AADD_WGT res; + + weight_t w = weight_malloc(); + weight_value(a, w); + weight_conj(w); + res = weight_lookup_ptr(w); + free(w); + + return res; +} + AADD_WGT wgt_add(AADD_WGT a, AADD_WGT b) { diff --git a/src/sylvan_edge_weights.h b/src/sylvan_edge_weights.h index 4e1c939..9a04269 100644 --- a/src/sylvan_edge_weights.h +++ b/src/sylvan_edge_weights.h @@ -71,6 +71,7 @@ typedef void (*init_one_zero_f)(void *wgt_store); /* Arithmetic operations on edge weights */ typedef void (*weight_abs_f)(weight_t a); // a <-- |a| typedef void (*weight_neg_f)(weight_t a); // a <-- -a +typedef void (*weight_conj_f)(weight_t a); // a <-- a* typedef void (*weight_sqr_f)(weight_t a); // a <-- a^2 typedef void (*weight_add_f)(weight_t a, weight_t b); // a <-- a + b typedef void (*weight_sub_f)(weight_t a, weight_t b); // a <-- a - b @@ -96,6 +97,7 @@ extern _weight_lookup_ptr_f _weight_lookup_ptr; extern init_one_zero_f init_one_zero; extern weight_abs_f weight_abs; extern weight_neg_f weight_neg; +extern weight_conj_f weight_conj; extern weight_sqr_f weight_sqr; extern weight_add_f weight_add; extern weight_sub_f weight_sub; @@ -136,6 +138,7 @@ void wgt_set_inverse_chaching(bool on); /* Arithmetic operations on AADD_WGT's */ AADD_WGT wgt_abs(AADD_WGT a); // returns |a| AADD_WGT wgt_neg(AADD_WGT a); // returns -a +AADD_WGT wgt_conj(AADD_WGT a); // returns a* AADD_WGT wgt_add(AADD_WGT a, AADD_WGT b); // returns a + b AADD_WGT wgt_sub(AADD_WGT a, AADD_WGT b); // returns a - b AADD_WGT wgt_mul(AADD_WGT a, AADD_WGT b); // returns a * b diff --git a/src/sylvan_edge_weights_complex.c b/src/sylvan_edge_weights_complex.c index fc78814..81b6aa0 100644 --- a/src/sylvan_edge_weights_complex.c +++ b/src/sylvan_edge_weights_complex.c @@ -95,6 +95,12 @@ weight_complex_neg(complex_t *a) a->i = -(a->i); } +void +weight_complex_conj(complex_t *a) +{ + a->i = -(a->i); +} + void weight_complex_sqr(complex_t *a) { diff --git a/src/sylvan_edge_weights_complex.h b/src/sylvan_edge_weights_complex.h index 78cff1c..f10f126 100644 --- a/src/sylvan_edge_weights_complex.h +++ b/src/sylvan_edge_weights_complex.h @@ -16,6 +16,7 @@ void init_complex_one_zero(void *wgt_store); void weight_complex_abs(complex_t *a); void weight_complex_neg(complex_t *a); +void weight_complex_conj(complex_t *a); void weight_complex_sqr(complex_t *a); void weight_complex_add(complex_t *a, complex_t *b); void weight_complex_sub(complex_t *a, complex_t *b); diff --git a/test/test_qmdd_basics.c b/test/test_qmdd_basics.c index e1da74f..8fd6481 100644 --- a/test/test_qmdd_basics.c +++ b/test/test_qmdd_basics.c @@ -337,7 +337,7 @@ int test_vector_addition() int test_inner_product() { - QMDD q0, q1, q00, q01, q10, q11, q000, q001, q010, q100; + QMDD q0, q1, q00, q01, q10, q11, q000, q001, q010, q100, q000i, q001i; bool x4[] = {0, 0, 0, 0}; BDDVAR nqubits = 4; @@ -349,6 +349,10 @@ int test_inner_product() q11 = aadd_plus(q1, q1); // [0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0] q000 = aadd_plus(q00, q0); // [0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0] q001 = aadd_plus(q00, q1); // [0 0 2 0 0 0 0 0 0 0 0 1 0 0 0 0] + q000i = aadd_bundle(AADD_TARGET(q000), wgt_mul(AADD_WEIGHT(q000), complex_lookup(0,1))); + // [0 0 3i 0 0 0 0 0 0 0 0 0 0 0 0 0] + q001i = aadd_bundle(AADD_TARGET(q001), wgt_mul(AADD_WEIGHT(q001), complex_lookup(0,1))); + // [0 0 2i 0 0 0 0 0 0 0 0 i 0 0 0 0] test_assert(aadd_inner_product(q00, q00, nqubits) == complex_lookup(4.0, 0.0)); test_assert(aadd_inner_product(q01, q01, nqubits) == complex_lookup(2.0, 0.0)); @@ -360,6 +364,9 @@ int test_inner_product() test_assert(aadd_inner_product(q01, q000, nqubits) == complex_lookup(3.0, 0.0)); test_assert(aadd_inner_product(q000, q001, nqubits) == complex_lookup(6.0, 0.0)); test_assert(aadd_inner_product(q01, q001, nqubits) == complex_lookup(3.0, 0.0)); + test_assert(aadd_inner_product(q000i, q000i, nqubits) == complex_lookup(9.0, 0.0)); + test_assert(aadd_inner_product(q001i, q001i, nqubits) == complex_lookup(5.0, 0.0)); + test_assert(aadd_inner_product(q000i, q001i, nqubits) == complex_lookup(6.0, 0.0)); if (VERBOSE) printf("aadd inner product: ok\n"); return 0; From b59b280ee6b0744ced0ea40210c7e59153451ce1 Mon Sep 17 00:00:00 2001 From: Richard Dijk Date: Thu, 18 Jul 2024 14:38:02 +0200 Subject: [PATCH 37/37] filenames changed --- qasm/CMakeLists.txt | 4 ++-- qasm/{sim_qasm.c => run_qasm_on_qmdd.c} | 0 src/{qsylvan_mtbdd_simulator.c => qsylvan_simulator_mtbdd.c} | 2 +- src/{qsylvan_mtbdd_simulator.h => qsylvan_simulator_mtbdd.h} | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) rename qasm/{sim_qasm.c => run_qasm_on_qmdd.c} (100%) rename src/{qsylvan_mtbdd_simulator.c => qsylvan_simulator_mtbdd.c} (99%) rename src/{qsylvan_mtbdd_simulator.h => qsylvan_simulator_mtbdd.h} (99%) diff --git a/qasm/CMakeLists.txt b/qasm/CMakeLists.txt index 341adae..050d4c1 100644 --- a/qasm/CMakeLists.txt +++ b/qasm/CMakeLists.txt @@ -17,6 +17,6 @@ target_sources(qsylvan_qasm_parser PUBLIC simple_parser.h) -add_executable(sim_qasm sim_qasm.c) -target_link_libraries(sim_qasm qsylvan qsylvan_qasm_parser) +add_executable(run_qasm_on_qmdd run_qasm_on_qmdd.c) +target_link_libraries(run_qasm_on_qmdd qsylvan qsylvan_qasm_parser) diff --git a/qasm/sim_qasm.c b/qasm/run_qasm_on_qmdd.c similarity index 100% rename from qasm/sim_qasm.c rename to qasm/run_qasm_on_qmdd.c diff --git a/src/qsylvan_mtbdd_simulator.c b/src/qsylvan_simulator_mtbdd.c similarity index 99% rename from src/qsylvan_mtbdd_simulator.c rename to src/qsylvan_simulator_mtbdd.c index 6e3789d..3ce92b6 100644 --- a/src/qsylvan_mtbdd_simulator.c +++ b/src/qsylvan_simulator_mtbdd.c @@ -19,7 +19,7 @@ // This code is copied in September 2023 from qsylvan_simulator.h/c made by Sebastian Brand // -#include +#include /* #include diff --git a/src/qsylvan_mtbdd_simulator.h b/src/qsylvan_simulator_mtbdd.h similarity index 99% rename from src/qsylvan_mtbdd_simulator.h rename to src/qsylvan_simulator_mtbdd.h index c23de57..18940fb 100644 --- a/src/qsylvan_mtbdd_simulator.h +++ b/src/qsylvan_simulator_mtbdd.h @@ -19,8 +19,8 @@ // This code is copied in September 2023 from qsylvan_simulator.h/c made by Sebastian Brand // -#ifndef QSYLVAN_MTBDD_SIMULATOR_H -#define QSYLVAN_MTBDD_SIMULATOR_H +#ifndef QSYLVAN_SIMULATOR_MTBDD_H +#define QSYLVAN_SIMULATOR_MTBDD_H #include #include