diff --git a/README.md b/README.md index dcc9c6c..d45ddc0 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![CI testing](https://github.com/sebastiaanbrand/q-sylvan/actions/workflows/cmake.yml/badge.svg)](https://github.com/sebastiaanbrand/q-sylvan/actions/workflows/cmake.yml) -Q-Sylvan extends the parallel decision diagram library [Sylvan](https://github.com/trolando/sylvan) (v1.8.0) with QMDDs (i.e. multiplicative AADDs), as well as functionality to simulate quantum circuits. This is currently still a beta version. +Q-Sylvan extends the parallel decision diagram library [Sylvan](https://github.com/trolando/sylvan) (v1.8.0) with QMDDs (i.e. factored EVBDDs with complex edge weights), as well as functionality to simulate quantum circuits. This is currently still a beta version. ## Installation diff --git a/docs/documentation/c_interface.md b/docs/documentation/c_interface.md index 75abbc6..7a32291 100644 --- a/docs/documentation/c_interface.md +++ b/docs/documentation/c_interface.md @@ -19,10 +19,10 @@ NOTE: In the code we are refering to the QMDDs as QMDDs, but our QMDDs are reall * `qmdd_cgate2(QMDD qmdd, gate_id_t gateid, int c1, int c2, int t)` : As above but with two controls (c1 < c2 < t). * `qmdd_cgate3(QMDD qmdd, gate_id_t gateid, int c1, int c2, int c3, int t)` : As above but with three controls (c1 < c2 < c3 < t). * `qmdd_cgate_range(QMDD qmdd, gate_id_t gateid , int c_first, int c_last, int t)` : Applies controlled-`gateid` to (t)arget, with all qubits between (and including) c_first and c_last as controls (c_first < c_last < t). -* `aadd_matvec_mult(QMDD mat, QMDD vec, int n)` : Computes mat|vec> for an 2^n vector and a 2^n x 2^n matrix. -* `aadd_matmat_mult(QMDD a, QMDD b, int)` : Computes a*b for two 2^n x 2^n matrices. -* `aadd_vec_tensor_prod(QMDD a, QMDD b, int nqubits_a)` : Computes a \tensor b for two vector QMDDs. -* `aadd_mat_tensor_prod(QMDD a, QMDD b, QMDD nqubits_a)` : Computes a \tensor b for two matrix QMDDs. +* `evbdd_matvec_mult(QMDD mat, QMDD vec, int n)` : Computes mat|vec> for an 2^n vector and a 2^n x 2^n matrix. +* `evbdd_matmat_mult(QMDD a, QMDD b, int)` : Computes a*b for two 2^n x 2^n matrices. +* `evbdd_vec_tensor_prod(QMDD a, QMDD b, int nqubits_a)` : Computes a \tensor b for two vector QMDDs. +* `evbdd_mat_tensor_prod(QMDD a, QMDD b, QMDD nqubits_a)` : Computes a \tensor b for two matrix QMDDs. ## Measurements and related Note: For measurements, the post-measurement state is the return value of the measurement function, while the input qmdd is unaffected. @@ -52,5 +52,5 @@ Note: For measurements, the post-measurement state is the return value of the me ## Other -* `aadd_countnodes(QMDD qmdd)` Counts the number of nodes in the given QMDD. -* `aadd_fprintdot(FILE *out, QMDD qmdd, bool draw_zeroes)` Writes a .dot representation of the given QMDD to the given file. +* `evbdd_countnodes(QMDD qmdd)` Counts the number of nodes in the given QMDD. +* `evbdd_fprintdot(FILE *out, QMDD qmdd, bool draw_zeroes)` Writes a .dot representation of the given QMDD to the given file. diff --git a/examples/alg_run.c b/examples/alg_run.c index 49bea8b..67badef 100644 --- a/examples/alg_run.c +++ b/examples/alg_run.c @@ -208,8 +208,8 @@ run_grover() // Sanity checks on final state // 1. Check flag probability (marginalize ancilla qubit out) - flag[qubits] = 0; AADD_WGT amp0 = aadd_getvalue(stats.final_qmdd, flag); - flag[qubits] = 1; AADD_WGT amp1 = aadd_getvalue(stats.final_qmdd, flag); + flag[qubits] = 0; EVBDD_WGT amp0 = evbdd_getvalue(stats.final_qmdd, flag); + flag[qubits] = 1; EVBDD_WGT amp1 = evbdd_getvalue(stats.final_qmdd, flag); double flag_prob = qmdd_amp_to_prob(amp0) + qmdd_amp_to_prob(amp1); INFO("Measure Grover flag with prob %lf\n", flag_prob); @@ -306,7 +306,7 @@ int main(int argc, char **argv) /* Some stats */ stats.final_magnitude = qmdd_get_magnitude(stats.final_qmdd, stats.nqubits); INFO("Magnitude of final state: %.05lf\n", stats.final_magnitude); - stats.final_nodecount = aadd_countnodes(stats.final_qmdd); + stats.final_nodecount = evbdd_countnodes(stats.final_qmdd); INFO("Final Nodecount: %" PRIu64 "\n", stats.final_nodecount); if (csv_outputfile != NULL) { INFO("Writing csv output to %s\n", csv_outputfile); diff --git a/examples/circuit_equivalence.c b/examples/circuit_equivalence.c index 59997b5..c5b48ae 100644 --- a/examples/circuit_equivalence.c +++ b/examples/circuit_equivalence.c @@ -189,18 +189,18 @@ QMDD get_gate_matrix(quantum_op_t* gate, BDDVAR nqubits, bool dag) { 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); + QMDD tmp = EVBDD_ZERO; + evbdd_protect(&circ_matrix); + evbdd_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); + circ_matrix = evbdd_matmat_mult(tmp, circ_matrix, nqubits); tmp = get_gate_matrix(op, nqubits, true); - circ_matrix = aadd_matmat_mult(circ_matrix, tmp, nqubits); + circ_matrix = evbdd_matmat_mult(circ_matrix, tmp, nqubits); break; case op_measurement: fprintf(stderr, "ERROR: Measurments not supported\n"); @@ -212,8 +212,8 @@ QMDD compute_UPUdag(quantum_circuit_t *circuit, gate_id_t P, BDDVAR k) { op = op->next; } - aadd_unprotect(&circ_matrix); - aadd_unprotect(&tmp); + evbdd_unprotect(&circ_matrix); + evbdd_unprotect(&tmp); return circ_matrix; } @@ -236,13 +236,13 @@ 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); + evbdd_protect(&qmdd_U); QMDD qmdd_V = compute_UPUdag(V, XZ[i], k); - aadd_unprotect(&qmdd_U); + evbdd_unprotect(&qmdd_U); if (count_nodes) { - size_t nodes_U = aadd_countnodes(qmdd_U); - size_t nodes_V = aadd_countnodes(qmdd_V); + size_t nodes_U = evbdd_countnodes(qmdd_U); + size_t nodes_V = evbdd_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); diff --git a/examples/grover.c b/examples/grover.c index fb3a777..3dd2dd1 100644 --- a/examples/grover.c +++ b/examples/grover.c @@ -115,63 +115,63 @@ QMDD qmdd_grover_matrix_multi_its(BDDVAR n, bool *flag, int t, QMDD *matrix) // H on all qubits all_H = qmdd_create_single_qubit_gates_same(nqubits, GATEID_H); - aadd_protect(&all_H); + evbdd_protect(&all_H); // H on first n qubits (all qubits except ancilla) for (BDDVAR k = 0; k < n; k++) gate_list[k] = GATEID_H; gate_list[n] = GATEID_I; first_n_H = qmdd_create_single_qubit_gates(nqubits, gate_list); - aadd_protect(&first_n_H); + evbdd_protect(&first_n_H); // oracle for (BDDVAR k = 0; k < n; k++) cgate_options[k] = flag[k]; cgate_options[n] = 2; // ancilla qubit is target qubit of this multi-cgate oracle = qmdd_create_multi_cgate(nqubits, cgate_options, GATEID_X); - aadd_protect(&oracle); + evbdd_protect(&oracle); // X on first n qubits (all qubits except ancilla) for (BDDVAR k = 0; k < n; k++) gate_list[k] = GATEID_X; gate_list[n] = GATEID_I; first_n_X = qmdd_create_single_qubit_gates(nqubits, gate_list); - aadd_protect(&first_n_X); + evbdd_protect(&first_n_X); // CZ gate on all qubits except ancilla for (BDDVAR k = 0; k < n-1; k++) cgate_options[k] = 1; // controls" cgate_options[n-1] = 2; // target last qubit before ancilla cgate_options[n] = -1; // do nothing to ancilla first_n_CZ = qmdd_create_multi_cgate(nqubits, cgate_options, GATEID_Z); - aadd_protect(&first_n_CZ); + evbdd_protect(&first_n_CZ); // Grover iteration = oracle + mean inversion grov_it = oracle; - aadd_protect(&grov_it); - grov_it = aadd_matmat_mult(first_n_H, grov_it, nqubits); - grov_it = aadd_matmat_mult(first_n_X, grov_it, nqubits); - grov_it = aadd_matmat_mult(first_n_CZ, grov_it, nqubits); - grov_it = aadd_matmat_mult(first_n_X, grov_it, nqubits); - grov_it = aadd_matmat_mult(first_n_H, grov_it, nqubits); + evbdd_protect(&grov_it); + grov_it = evbdd_matmat_mult(first_n_H, grov_it, nqubits); + grov_it = evbdd_matmat_mult(first_n_X, grov_it, nqubits); + grov_it = evbdd_matmat_mult(first_n_CZ, grov_it, nqubits); + grov_it = evbdd_matmat_mult(first_n_X, grov_it, nqubits); + grov_it = evbdd_matmat_mult(first_n_H, grov_it, nqubits); // Compute grov_it^t (by squaring if t is a power of 2) grov_its = grov_it; - aadd_protect(&grov_its); + evbdd_protect(&grov_its); if (EXP_BY_SQUARING && ((t & (t - 1)) == 0)) { for (int i = 0; i < log2l(t); i++) { - grov_its = aadd_matmat_mult(grov_its, grov_its, nqubits); + grov_its = evbdd_matmat_mult(grov_its, grov_its, nqubits); } } else { for (int i = 1; i < t; i++) { - grov_its = aadd_matmat_mult(grov_its, grov_it, nqubits); + grov_its = evbdd_matmat_mult(grov_its, grov_it, nqubits); } } R = R / t; *matrix = grov_its; // return for nodecount in bench - aadd_unprotect(&first_n_H); - aadd_unprotect(&first_n_X); - aadd_unprotect(&first_n_CZ); - aadd_unprotect(&oracle); - aadd_unprotect(&grov_it); + evbdd_unprotect(&first_n_H); + evbdd_unprotect(&first_n_X); + evbdd_unprotect(&first_n_CZ); + evbdd_unprotect(&oracle); + evbdd_unprotect(&grov_it); // Now, actually apply the circuit: // 1. Start with all zero state + ancilla: |000...0>|1> @@ -179,11 +179,11 @@ QMDD qmdd_grover_matrix_multi_its(BDDVAR n, bool *flag, int t, QMDD *matrix) for (BDDVAR k = 0; k < n; k++) init[k] = 0; init[n] = 1; state = qmdd_create_basis_state(nqubits, init); - aadd_protect(&state); + evbdd_protect(&state); // 2. H on all qubits - state = aadd_matvec_mult(all_H, state, nqubits); - aadd_unprotect(&all_H); + state = evbdd_matvec_mult(all_H, state, nqubits); + evbdd_unprotect(&all_H); // 3. Grover iterations if (VERBOSE) { @@ -198,19 +198,19 @@ QMDD qmdd_grover_matrix_multi_its(BDDVAR n, bool *flag, int t, QMDD *matrix) } // gc edge wegith table - aadd_gc_wgt_table(); + evbdd_gc_wgt_table(); // gc node table sylvan_gc(); } - state = aadd_matvec_mult(grov_its, state, nqubits); + state = evbdd_matvec_mult(grov_its, state, nqubits); } if (VERBOSE) { printf("\rGrover progress %lf%%\n", 100.); } - aadd_unprotect(&grov_its); - aadd_unprotect(&state); + evbdd_unprotect(&grov_its); + evbdd_unprotect(&state); free(init); free(gate_list); diff --git a/examples/shor.c b/examples/shor.c index 5c0913b..4f700af 100644 --- a/examples/shor.c +++ b/examples/shor.c @@ -98,7 +98,7 @@ qmdd_phi_add_mod(QMDD qmdd, BDDVAR c1, BDDVAR c2, uint64_t a, uint64_t N) // are not parameterized on a) sylvan_clear_cache(); shor_set_globals(a, N); // set bitvalues of a/N (N says the same though) - BDDVAR nc = AADD_INVALID_VAR; // no control + BDDVAR nc = EVBDD_INVALID_VAR; // no control // 1. controlled(c1,c2) phi_add(a) qmdd = qmdd_phi_add(qmdd, shor_wires.targ_first, shor_wires.targ_last, c1, c2, shor_bits_a); @@ -141,7 +141,7 @@ qmdd_phi_add_mod_inv(QMDD qmdd, BDDVAR c1, BDDVAR c2, uint64_t a, uint64_t N) // are not parameterized on a) sylvan_clear_cache(); shor_set_globals(a, N); // set bitvalues of a/N (N says the same though) - BDDVAR nc = AADD_INVALID_VAR; // no control + BDDVAR nc = EVBDD_INVALID_VAR; // no control // 13. controlled(c1,c2) phi_add_inv(a) qmdd = qmdd_phi_add_inv(qmdd, shor_wires.targ_first, shor_wires.targ_last, c1, c2, shor_bits_a); @@ -187,7 +187,7 @@ qmdd_cmult(QMDD qmdd, uint64_t a, uint64_t N) // 2. loop over k = {0, n-1} uint64_t t = a; - //BDDVAR cs[] = {shor_wires.top, AADD_INVALID_VAR, AADD_INVALID_VAR}; + //BDDVAR cs[] = {shor_wires.top, EVBDD_INVALID_VAR, EVBDD_INVALID_VAR}; for (BDDVAR c2 = shor_wires.ctrl_last; c2 >= shor_wires.ctrl_first; c2--) { // 2a. double controlled phi_add_mod(a* 2^k) qmdd = qmdd_phi_add_mod(qmdd, shor_wires.top, c2, t, N); diff --git a/examples/test_algs.c b/examples/test_algs.c index 92cb19a..83aebfc 100644 --- a/examples/test_algs.c +++ b/examples/test_algs.c @@ -30,11 +30,11 @@ int test_grover() prob = 0; for (int k = 0; k < (1<<(nbits+1)); k++) { bool *x = int_to_bitarray(k, nbits+1, true); - a = aadd_getvalue(grov, x); + a = evbdd_getvalue(grov, x); if (x[0] == flag2[0] && x[1] == flag2[1]) prob += qmdd_amp_to_prob(a); else - test_assert(a == AADD_ZERO); + test_assert(a == EVBDD_ZERO); free(x); // int_to_bitarray mallocs } test_assert(fabs(prob - 1) < TOLERANCE); @@ -52,7 +52,7 @@ int test_grover() prob = 0; for (int k = 0; k < (1<<(nbits+1)); k++) { bool *x = int_to_bitarray(k, nbits+1, true); - a = aadd_getvalue(grov, x); + a = evbdd_getvalue(grov, x); if (x[0] == flag3[0] && x[1] == flag3[1] && x[2] == flag3[2]) prob += qmdd_amp_to_prob(a); else @@ -75,7 +75,7 @@ int test_grover() prob = 0; for (int k = 0; k < (1<<(nbits+1)); k++) { bool *x = int_to_bitarray(k, nbits+1, true); - a = aadd_getvalue(grov, x); + a = evbdd_getvalue(grov, x); if (x[0] == flag10[0] && x[1] == flag10[1] && x[2] == flag10[2] && x[3] == flag10[3] && x[4] == flag10[4] && x[5] == flag10[5] && @@ -94,7 +94,7 @@ int test_grover() int test_grover_matrix() { - aadd_set_auto_gc_wgt_table(false); // no auto gc of ctable yet for mult operations + evbdd_set_auto_gc_wgt_table(false); // no auto gc of ctable yet for mult operations BDDVAR nbits; AMP a; @@ -111,11 +111,11 @@ int test_grover_matrix() prob = 0; for (int k = 0; k < (1<<(nbits+1)); k++) { bool *x = int_to_bitarray(k, nbits+1, true); - a = aadd_getvalue(grov, x); + a = evbdd_getvalue(grov, x); if (x[0] == flag2[0] && x[1] == flag2[1]) prob += qmdd_amp_to_prob(a); else - test_assert(a == AADD_ZERO); + test_assert(a == EVBDD_ZERO); free(x); // int_to_bitarray mallocs } test_assert(fabs(prob - 1) < TOLERANCE); @@ -133,7 +133,7 @@ int test_grover_matrix() prob = 0; for (int k = 0; k < (1<<(nbits+1)); k++) { bool *x = int_to_bitarray(k, nbits+1, true); - a = aadd_getvalue(grov, x); + a = evbdd_getvalue(grov, x); if (x[0] == flag3[0] && x[1] == flag3[1] && x[2] == flag3[2]) prob += qmdd_amp_to_prob(a); else @@ -157,7 +157,7 @@ int test_grover_matrix() prob = 0; for (int k = 0; k < (1<<(nbits+1)); k++) { bool *x = int_to_bitarray(k, nbits+1, true); - a = aadd_getvalue(grov, x); + a = evbdd_getvalue(grov, x); if (x[0] == flag10[0] && x[1] == flag10[1] && x[2] == flag10[2] && x[3] == flag10[3] && x[4] == flag10[4] && x[5] == flag10[5] && @@ -173,7 +173,7 @@ int test_grover_matrix() if(VERBOSE) printf("matrix qmdd %2d-qubit Grover: ok (Pr(flag) = %lf)\n", nbits+1, prob); return 0; - aadd_set_auto_gc_wgt_table(true); + evbdd_set_auto_gc_wgt_table(true); return 0; } @@ -201,7 +201,7 @@ int test_grover_cnf() prob = 0; for (int k = 0; k < (1<<(nqubits+1+clauses)); k++) { bool *x = int_to_bitarray(k, nqubits+1+clauses, true); - a = aadd_getvalue(grov, x); + a = evbdd_getvalue(grov, x); if (x[0] == ans3[0] && x[1] == ans3[1]) prob += qmdd_amp_to_prob(a); free(x); // int_to_bitarray mallocs @@ -224,7 +224,7 @@ int test_grover_cnf() prob = 0; for (int k = 0; k < (1<<(nqubits+1+clauses)); k++) { bool *x = int_to_bitarray(k, nqubits+1+clauses, true); - a = aadd_getvalue(grov, x); + a = evbdd_getvalue(grov, x); if (x[0] == ans4[0] && x[1] == ans4[1] && x[2] == ans4[2] && x[3] == ans4[3]) prob += qmdd_amp_to_prob(a); free(x); // int_to_bitarray mallocs @@ -247,7 +247,7 @@ int test_shor() // // Test inversion // (no controls) - BDDVAR nc = AADD_INVALID_VAR; + BDDVAR nc = EVBDD_INVALID_VAR; q = qmdd_create_basis_state(3, x3); q = qmdd_gate(q, GATEID_H, 0); q = qmdd_gate(q, GATEID_H, 1); @@ -255,8 +255,8 @@ int test_shor() qref = q; q = qmdd_phi_add(q, 0, 2, nc, nc, as); q = qmdd_phi_add_inv(q, 0, 2, nc, nc, as); - test_assert(aadd_equivalent(q, qref, 3, false, false)); - test_assert(aadd_equivalent(q, qref, 3, true, false)); + test_assert(evbdd_equivalent(q, qref, 3, false, false)); + test_assert(evbdd_equivalent(q, qref, 3, true, false)); test_assert(q == qref); // Test addition in Fourier space (be mindful about endianness here!) @@ -267,14 +267,14 @@ int test_shor() q = qmdd_circuit(q, CIRCID_QFT, 0, 2); // QFT|x> = |phi(x)> q = qmdd_phi_add(q, 0, 2, nc, nc, as); // addition in Fourier space gives |phi(x+a)> q = qmdd_circuit(q, CIRCID_QFT_inv, 0, 2); // expected out = |3> = |011> (MSB first) - x3[0]=0; x3[1]=0; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=0; x3[1]=0; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=0; x3[1]=1; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=0; x3[1]=1; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ONE); - x3[0]=1; x3[1]=0; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=1; x3[1]=0; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=1; x3[1]=1; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=1; x3[1]=1; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); + x3[0]=0; x3[1]=0; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=0; x3[1]=0; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=0; x3[1]=1; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=0; x3[1]=1; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ONE); + x3[0]=1; x3[1]=0; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=1; x3[1]=0; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=1; x3[1]=1; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=1; x3[1]=1; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); // 2 + 2 (carry, should go the the left) x3[0] = 0; x3[1] = 1; x3[2] = 0; // x = 010 = 2 (MSB first) @@ -283,14 +283,14 @@ int test_shor() q = qmdd_circuit(q, CIRCID_QFT, 0, 2); // QFT|x> = |phi(x)> q = qmdd_phi_add(q, 0, 2, nc, nc, as); // addition in Fourier space gives |phi(x+a)> q = qmdd_circuit(q, CIRCID_QFT_inv, 0, 2); // expected out = |4> = |100> (MSB first) - x3[0]=0; x3[1]=0; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=0; x3[1]=0; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=0; x3[1]=1; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=0; x3[1]=1; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=1; x3[1]=0; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ONE); - x3[0]=1; x3[1]=0; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=1; x3[1]=1; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=1; x3[1]=1; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); + x3[0]=0; x3[1]=0; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=0; x3[1]=0; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=0; x3[1]=1; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=0; x3[1]=1; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=1; x3[1]=0; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ONE); + x3[0]=1; x3[1]=0; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=1; x3[1]=1; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=1; x3[1]=1; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); // 2 + 3 (carry, should go the the left) x3[0] = 0; x3[1] = 1; x3[2] = 0; // x = 010 = 2 (MSB first) @@ -299,14 +299,14 @@ int test_shor() q = qmdd_circuit(q, CIRCID_QFT, 0, 2); // QFT|x> = |phi(x)> q = qmdd_phi_add(q, 0, 2, nc, nc, as); // addition in Fourier space gives |phi(x+a)> q = qmdd_circuit(q, CIRCID_QFT_inv, 0, 2); // expected out = |5> = |101> (MSB first) - x3[0]=0; x3[1]=0; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=0; x3[1]=0; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=0; x3[1]=1; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=0; x3[1]=1; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=1; x3[1]=0; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=1; x3[1]=0; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ONE); - x3[0]=1; x3[1]=1; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=1; x3[1]=1; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); + x3[0]=0; x3[1]=0; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=0; x3[1]=0; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=0; x3[1]=1; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=0; x3[1]=1; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=1; x3[1]=0; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=1; x3[1]=0; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ONE); + x3[0]=1; x3[1]=1; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=1; x3[1]=1; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); // 3 + 2 (carry, should go the the left) x3[0] = 0; x3[1] = 1; x3[2] = 1; // x = 011 = 3 (MSB first) @@ -315,14 +315,14 @@ int test_shor() q = qmdd_circuit(q, CIRCID_QFT, 0, 2); // QFT|x> = |phi(x)> q = qmdd_phi_add(q, 0, 2, nc, nc, as); // addition in Fourier space gives |phi(x+a)> q = qmdd_circuit(q, CIRCID_QFT_inv, 0, 2); // expected out = |5> = |101> (MSB first) - x3[0]=0; x3[1]=0; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=0; x3[1]=0; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=0; x3[1]=1; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=0; x3[1]=1; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=1; x3[1]=0; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=1; x3[1]=0; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ONE); - x3[0]=1; x3[1]=1; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=1; x3[1]=1; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); + x3[0]=0; x3[1]=0; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=0; x3[1]=0; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=0; x3[1]=1; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=0; x3[1]=1; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=1; x3[1]=0; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=1; x3[1]=0; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ONE); + x3[0]=1; x3[1]=1; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=1; x3[1]=1; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); // 3 + 3 (carry, should go the the left) x3[0] = 0; x3[1] = 1; x3[2] = 1; // x = 011 = 3 (MSB first) @@ -331,14 +331,14 @@ int test_shor() q = qmdd_circuit(q, CIRCID_QFT, 0, 2); // QFT|x> = |phi(x)> q = qmdd_phi_add(q, 0, 2, nc, nc, as); // addition in Fourier space gives |phi(x+a)> q = qmdd_circuit(q, CIRCID_QFT_inv, 0, 2); // expected out = |6> = |110> (MSB first) - x3[0]=0; x3[1]=0; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=0; x3[1]=0; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=0; x3[1]=1; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=0; x3[1]=1; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=1; x3[1]=0; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=1; x3[1]=0; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[0]=1; x3[1]=1; x3[2]=0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ONE); - x3[0]=1; x3[1]=1; x3[2]=1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); + x3[0]=0; x3[1]=0; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=0; x3[1]=0; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=0; x3[1]=1; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=0; x3[1]=1; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=1; x3[1]=0; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=1; x3[1]=0; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[0]=1; x3[1]=1; x3[2]=0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ONE); + x3[0]=1; x3[1]=1; x3[2]=1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); // if(VERBOSE) printf("qmdd fourier addition: ok\n"); diff --git a/examples/vqc.c b/examples/vqc.c index 24256ff..f136795 100644 --- a/examples/vqc.c +++ b/examples/vqc.c @@ -4,7 +4,7 @@ void ry_cz_ansatz(int nqubits, int depth) { QMDD state = qmdd_create_all_zero_state(nqubits); - aadd_protect(&state); + evbdd_protect(&state); for (int d = 0; d < depth; d++) { // Ry rotations @@ -30,7 +30,7 @@ void ry_cz_ansatz(int nqubits, int depth) printf("> (with prob %lf)\n", prob); free(outcome); - aadd_unprotect(&state); + evbdd_unprotect(&state); } int main() diff --git a/qasm/qsylvan_qasm.c b/qasm/qsylvan_qasm.c index 45b280a..b6d4259 100644 --- a/qasm/qsylvan_qasm.c +++ b/qasm/qsylvan_qasm.c @@ -86,7 +86,7 @@ QMDD apply_controlled_gate(QMDD qmdd, Gate gate, BDDVAR i, BDDVAR n) // Create controlled gate qmdd QMDD qmdd_column = handle_control_matrix(gate, i, n); // multiply with vector - qmdd = aadd_matvec_mult(qmdd_column, qmdd, n); + qmdd = evbdd_matvec_mult(qmdd_column, qmdd, n); return qmdd; } @@ -143,10 +143,10 @@ QMDD handle_control_matrix(Gate gate, BDDVAR k, BDDVAR n) c_options[k] = 2; // Create the gate QMDD qmdd_next = qmdd_create_multi_cgate_rec(n, c_options, gate_id, 0); - qmdd = aadd_matmat_mult(qmdd_next, qmdd, n); + qmdd = evbdd_matmat_mult(qmdd_next, qmdd, n); if (!sorted) { qmdd_next = circuit_swap_matrix(temp, k, n); - qmdd = aadd_matmat_mult(qmdd_next, qmdd, n); + qmdd = evbdd_matmat_mult(qmdd_next, qmdd, n); temp = k; k = gate.control[index]; gate.control[index] = temp; @@ -168,13 +168,13 @@ QMDD circuit_swap_matrix(BDDVAR qubit1, BDDVAR qubit2, BDDVAR n) // Perform swap qmdd = qmdd_create_multi_cgate_rec(n, c_options, GATEID_X, 0); qmdd_next = qmdd_create_single_qubit_gate(n, qubit1, GATEID_H); - qmdd = aadd_matmat_mult(qmdd_next, qmdd, n); + qmdd = evbdd_matmat_mult(qmdd_next, qmdd, n); qmdd_next = qmdd_create_multi_cgate_rec(n, c_options, GATEID_Z, 0); - qmdd = aadd_matmat_mult(qmdd_next, qmdd, n); + qmdd = evbdd_matmat_mult(qmdd_next, qmdd, n); qmdd_next = qmdd_create_single_qubit_gate(n, qubit1, GATEID_H); - qmdd = aadd_matmat_mult(qmdd_next, qmdd, n); + qmdd = evbdd_matmat_mult(qmdd_next, qmdd, n); qmdd_next = qmdd_create_multi_cgate_rec(n, c_options, GATEID_X, 0); - qmdd = aadd_matmat_mult(qmdd_next, qmdd, n); + qmdd = evbdd_matmat_mult(qmdd_next, qmdd, n); return qmdd; } @@ -275,7 +275,7 @@ QMDD greedy(C_struct c_s, QMDD prev_qmdd, BDDVAR* column, int* measurements, boo BDDVAR* progress = malloc(c_s.qubits * sizeof(BDDVAR)); for (BDDVAR i = 0; i < c_s.qubits; i++) progress[i] = *column; if (experiments) { - best_nodecount = aadd_countnodes(prev_qmdd); + best_nodecount = evbdd_countnodes(prev_qmdd); printf("nodecount vec: %d at %d\n", best_nodecount, *n_gates); } for (BDDVAR i = 0; i < c_s.qubits; i++) { @@ -307,7 +307,7 @@ QMDD greedy(C_struct c_s, QMDD prev_qmdd, BDDVAR* column, int* measurements, boo } else curr_qmdd = apply_gate(prev_qmdd, gate, i, c_s.qubits); - curr_nodecount = aadd_countnodes(curr_qmdd); + curr_nodecount = evbdd_countnodes(curr_qmdd); if (curr_nodecount < best_nodecount) { best_nodecount = curr_nodecount; best_qmdd = curr_qmdd; @@ -335,7 +335,7 @@ QMDD greedy(C_struct c_s, QMDD prev_qmdd, BDDVAR* column, int* measurements, boo loop = true; } } - best_nodecount = aadd_countnodes(prev_qmdd); + best_nodecount = evbdd_countnodes(prev_qmdd); if (experiments) printf("nodecount vec: %d at %d\n", best_nodecount, *n_gates); *column = progress[0]; @@ -352,12 +352,12 @@ QMDD matmat(C_struct c_s, QMDD vec, BDDVAR* column, int* measurements, bool* res qmdd = qmdd_create_single_qubit_gates_same(c_s.qubits, GATEID_I); qmdd_column = qmdd; - aadd_protect(&qmdd); - aadd_protect(&qmdd_column); + evbdd_protect(&qmdd); + evbdd_protect(&qmdd_column); if (experiments) { - nodecount = aadd_countnodes(qmdd); + nodecount = evbdd_countnodes(qmdd); printf("nodecount mat: %d at %d\n", nodecount, *n_gates); - nodecount = aadd_countnodes(vec); + nodecount = evbdd_countnodes(vec); printf("nodecount vec: %d at %d\n", nodecount, *n_gates); } // Loop over all places in the circuit @@ -385,9 +385,9 @@ QMDD matmat(C_struct c_s, QMDD vec, BDDVAR* column, int* measurements, bool* res else { // Multiply everything currently already in the column qmdd_column = qmdd_create_single_qubit_gates(c_s.qubits, gateids); - qmdd = aadd_matmat_mult(qmdd_column, qmdd, c_s.qubits); + qmdd = evbdd_matmat_mult(qmdd_column, qmdd, c_s.qubits); // Multiply with the vector and measure - vec = aadd_matvec_mult(qmdd, vec, c_s.qubits); + vec = evbdd_matvec_mult(qmdd, vec, c_s.qubits); vec = measure(vec, i, c_s.qubits, &results[gate.control[0]]); // Reset qmdd and gateids qmdd = qmdd_create_single_qubit_gates_same(c_s.qubits, GATEID_I); @@ -399,7 +399,7 @@ QMDD matmat(C_struct c_s, QMDD vec, BDDVAR* column, int* measurements, bool* res else if (gate.controlSize != 0) { qmdd_column = handle_control_matrix(gate, i, c_s.qubits); // Separately multiply with gate QMDD (not together with column) - qmdd = aadd_matmat_mult(qmdd_column, qmdd, c_s.qubits); + qmdd = evbdd_matmat_mult(qmdd_column, qmdd, c_s.qubits); } // Set single gate in gateids else @@ -413,14 +413,14 @@ QMDD matmat(C_struct c_s, QMDD vec, BDDVAR* column, int* measurements, bool* res // Create gate QMDD out of current column (gateids) qmdd_column = qmdd_create_single_qubit_gates(c_s.qubits, gateids); // Multiply with previous columns - qmdd = aadd_matmat_mult(qmdd_column, qmdd, c_s.qubits); + qmdd = evbdd_matmat_mult(qmdd_column, qmdd, c_s.qubits); } // Keep track of the all time highest node count in the matrices - nodecount = aadd_countnodes(qmdd); + nodecount = evbdd_countnodes(qmdd); // If nodecount of column QMDD is over limit... if (limit > 0 && nodecount > (BDDVAR)limit) { // Multiply with statevector QMDD and reset column QMDD - vec = aadd_matvec_mult(qmdd, vec, c_s.qubits); + vec = evbdd_matvec_mult(qmdd, vec, c_s.qubits); qmdd = qmdd_create_single_qubit_gates_same(c_s.qubits, GATEID_I); } else if (experiments) @@ -428,18 +428,18 @@ QMDD matmat(C_struct c_s, QMDD vec, BDDVAR* column, int* measurements, bool* res } *column = j+1; // Final multiply with statevector QMDD - vec = aadd_matvec_mult(qmdd, vec, c_s.qubits); + vec = evbdd_matvec_mult(qmdd, vec, c_s.qubits); qmdd = qmdd_create_single_qubit_gates_same(c_s.qubits, GATEID_I); if (experiments) { - nodecount = aadd_countnodes(qmdd); + nodecount = evbdd_countnodes(qmdd); printf("nodecount mat: %d at %d\n", nodecount, *n_gates); - nodecount = aadd_countnodes(vec); + nodecount = evbdd_countnodes(vec); printf("nodecount vec: %d at %d\n", nodecount, *n_gates); } // Free variables free(gateids); - aadd_unprotect(&qmdd); - aadd_unprotect(&qmdd_column); + evbdd_unprotect(&qmdd); + evbdd_unprotect(&qmdd_column); return vec; } @@ -451,7 +451,7 @@ QMDD run_circuit_balance(C_struct c_s, int* measurements, bool* results, int lim BDDVAR n_gates = 0, column = 0; QMDD vec = qmdd_create_all_zero_state(c_s.qubits); - aadd_protect(&vec); + evbdd_protect(&vec); while (column < c_s.depth) { vec = greedy(c_s, vec, &column, measurements, results, experiments, &n_gates); if (experiments) @@ -461,7 +461,7 @@ QMDD run_circuit_balance(C_struct c_s, int* measurements, bool* results, int lim if (experiments && column < c_s.depth) printf("palindrome end at: %d\n", n_gates); } - aadd_unprotect(&vec); + evbdd_unprotect(&vec); return vec; } @@ -479,7 +479,7 @@ QMDD greedy_run_circuit(C_struct c_s, int* measurements, bool* results, bool exp BDDVAR* progress = malloc(c_s.qubits * sizeof(BDDVAR)); for (BDDVAR i = 0; i < c_s.qubits; i++) progress[i] = 0; if (experiments) { - best_nodecount = aadd_countnodes(prev_qmdd); + best_nodecount = evbdd_countnodes(prev_qmdd); printf("nodecount: %d\n", best_nodecount); } for (BDDVAR i = 0; i < c_s.qubits; i++) { @@ -509,7 +509,7 @@ QMDD greedy_run_circuit(C_struct c_s, int* measurements, bool* results, bool exp } else curr_qmdd = apply_gate(prev_qmdd, gate, i, c_s.qubits); - curr_nodecount = aadd_countnodes(curr_qmdd); + curr_nodecount = evbdd_countnodes(curr_qmdd); if (curr_nodecount < best_nodecount) { best_nodecount = curr_nodecount; best_qmdd = curr_qmdd; @@ -552,14 +552,14 @@ QMDD run_circuit_matrix(C_struct c_s, int* measurements, bool* results, int limi qmdd = qmdd_create_single_qubit_gates_same(c_s.qubits, GATEID_I); qmdd_column = qmdd; - aadd_protect(&vec); - aadd_protect(&qmdd); - aadd_protect(&qmdd_column); + evbdd_protect(&vec); + evbdd_protect(&qmdd); + evbdd_protect(&qmdd_column); if (experiments) { - nodecount = aadd_countnodes(qmdd); + nodecount = evbdd_countnodes(qmdd); printf("nodecount mat: %d at %d\n", nodecount, n_gates); - nodecount = aadd_countnodes(vec); + nodecount = evbdd_countnodes(vec); printf("nodecount vec: %d at %d\n", nodecount, n_gates); } // Loop over all places in the circuit @@ -588,9 +588,9 @@ QMDD run_circuit_matrix(C_struct c_s, int* measurements, bool* results, int limi else { // Multiply everything currently already in the column qmdd_column = qmdd_create_single_qubit_gates(c_s.qubits, gateids); - qmdd = aadd_matmat_mult(qmdd_column, qmdd, c_s.qubits); + qmdd = evbdd_matmat_mult(qmdd_column, qmdd, c_s.qubits); // Multiply with the vector and measure - vec = aadd_matvec_mult(qmdd, vec, c_s.qubits); + vec = evbdd_matvec_mult(qmdd, vec, c_s.qubits); vec = measure(vec, i, c_s.qubits, &results[gate.control[0]]); // Reset qmdd and gateids qmdd = qmdd_create_single_qubit_gates_same(c_s.qubits, GATEID_I); @@ -602,7 +602,7 @@ QMDD run_circuit_matrix(C_struct c_s, int* measurements, bool* results, int limi else if (gate.controlSize != 0) { qmdd_column = handle_control_matrix(gate, i, c_s.qubits); // Separately multiply with gate QMDD (not together with column) - qmdd = aadd_matmat_mult(qmdd_column, qmdd, c_s.qubits); + qmdd = evbdd_matmat_mult(qmdd_column, qmdd, c_s.qubits); } // Set single gate in gateids else { @@ -624,36 +624,36 @@ QMDD run_circuit_matrix(C_struct c_s, int* measurements, bool* results, int limi // Create gate QMDD out of current column (gateids) qmdd_column = qmdd_create_single_qubit_gates(c_s.qubits, gateids); // Multiply with previous columns - qmdd = aadd_matmat_mult(qmdd_column, qmdd, c_s.qubits); + qmdd = evbdd_matmat_mult(qmdd_column, qmdd, c_s.qubits); } // Keep track of the all time highest node count in the matrices // If nodecount of column QMDD is over limit... if (limit > 0) { - nodecount = aadd_countnodes(qmdd); + nodecount = evbdd_countnodes(qmdd); if (nodecount > (BDDVAR)limit) { // Multiply with statevector QMDD and reset column QMDD - vec = aadd_matvec_mult(qmdd, vec, c_s.qubits); + vec = evbdd_matvec_mult(qmdd, vec, c_s.qubits); qmdd = qmdd_create_single_qubit_gates_same(c_s.qubits, GATEID_I); } } if (experiments) { - nodecount = aadd_countnodes(qmdd); + nodecount = evbdd_countnodes(qmdd); printf("nodecount mat: %d at %d\n", nodecount, n_gates); - nodecount = aadd_countnodes(vec); + nodecount = evbdd_countnodes(vec); printf("nodecount vec: %d at %d\n", nodecount, n_gates); } } // Final multiply with statevector QMDD - vec = aadd_matvec_mult(qmdd, vec, c_s.qubits); + vec = evbdd_matvec_mult(qmdd, vec, c_s.qubits); if (experiments) { - nodecount = aadd_countnodes(vec); + nodecount = evbdd_countnodes(vec); printf("nodecount vec: %d at %d\n", nodecount, n_gates); } // Free variables free(gateids); - aadd_unprotect(&vec); - aadd_unprotect(&qmdd); - aadd_unprotect(&qmdd_column); + evbdd_unprotect(&vec); + evbdd_unprotect(&qmdd); + evbdd_unprotect(&qmdd_column); return vec; } @@ -668,10 +668,10 @@ QMDD run_c_struct(C_struct c_s, int* measurements, bool* results, bool experimen for (BDDVAR i = 0; i < c_s.bits; i++) results[i] = 0; for (BDDVAR i = 0; i < c_s.qubits; i++) measurements[i] = -1; QMDD qmdd = qmdd_create_all_zero_state(c_s.qubits); - aadd_protect(&qmdd); + evbdd_protect(&qmdd); if (experiments) { - nodecount = aadd_countnodes(qmdd); + nodecount = evbdd_countnodes(qmdd); printf("nodecount: %d\n", nodecount); } // Loop over all places in the circuit @@ -702,12 +702,12 @@ QMDD run_c_struct(C_struct c_s, int* measurements, bool* results, bool experimen else qmdd = apply_gate(qmdd, gate, i, c_s.qubits); if (experiments) { - nodecount = aadd_countnodes(qmdd); + nodecount = evbdd_countnodes(qmdd); printf("nodecount: %d\n", nodecount); } } } - aadd_unprotect(&qmdd); + evbdd_unprotect(&qmdd); return qmdd; } @@ -752,7 +752,7 @@ int main(int argc, char *argv[]) int experiments = 0; bool intermediate_experiments; char *csv_outputfile = NULL; - QMDD qmdd = AADD_TERMINAL; + QMDD qmdd = EVBDD_TERMINAL; uint64_t res; poptContext con; @@ -889,7 +889,7 @@ int main(int argc, char *argv[]) } } - uint64_t final_nodecount = aadd_countnodes(qmdd); + uint64_t final_nodecount = evbdd_countnodes(qmdd); double final_magnitude = qmdd_get_magnitude(qmdd, c_s.qubits); INFO("Nodecount of final state: %" PRIu64 "\n", final_nodecount); INFO("Magnitude of final state: %.05lf\n", final_magnitude); diff --git a/qasm/run_qasm_on_qmdd.c b/qasm/run_qasm_on_qmdd.c index a7cc78f..1928ded 100644 --- a/qasm/run_qasm_on_qmdd.c +++ b/qasm/run_qasm_on_qmdd.c @@ -387,7 +387,7 @@ void simulate_circuit(quantum_circuit_t* circuit) } } if (count_nodes) { - uint64_t count = aadd_countnodes(state); + uint64_t count = evbdd_countnodes(state); if (count > stats.max_nodes) stats.max_nodes = count; } op = op->next; @@ -395,7 +395,7 @@ void simulate_circuit(quantum_circuit_t* circuit) stats.simulation_time = wctime() - t_start; stats.final_state = state; stats.shots = 1; - stats.final_nodes = aadd_countnodes(state); + stats.final_nodes = evbdd_countnodes(state); stats.norm = qmdd_get_norm(state, circuit->qreg_size); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c54dc46..7e70636 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,7 +8,7 @@ target_sources(qsylvan qsylvan_gates_mtbdd_mpc.c qsylvan_simulator.c qsylvan_simulator_mtbdd.c - sylvan_aadd.c + sylvan_evbdd.c sylvan_bdd.c sylvan_cache.c sylvan_common.c @@ -32,8 +32,8 @@ target_sources(qsylvan qsylvan_gates_mtbdd_mpc.h qsylvan_simulator.h qsylvan_simulator_mtbdd.h - sylvan_aadd.h - sylvan_aadd_int.h + sylvan_evbdd.h + sylvan_evbdd_int.h sylvan_bdd.h sylvan_cache.h sylvan_config.h diff --git a/src/qsylvan.h b/src/qsylvan.h index 49b432b..7be10b1 100644 --- a/src/qsylvan.h +++ b/src/qsylvan.h @@ -1,5 +1,5 @@ #include -#include +#include #include #include diff --git a/src/qsylvan_gates.c b/src/qsylvan_gates.c index 26d69fe..21076bb 100644 --- a/src/qsylvan_gates.c +++ b/src/qsylvan_gates.c @@ -128,48 +128,48 @@ qmdd_gates_init() uint32_t k; k = GATEID_I; - gates[k][0] = AADD_ONE; gates[k][1] = AADD_ZERO; - gates[k][2] = AADD_ZERO; gates[k][3] = AADD_ONE; + gates[k][0] = EVBDD_ONE; gates[k][1] = EVBDD_ZERO; + gates[k][2] = EVBDD_ZERO; gates[k][3] = EVBDD_ONE; k = GATEID_proj0; - gates[k][0] = AADD_ONE; gates[k][1] = AADD_ZERO; - gates[k][2] = AADD_ZERO; gates[k][3] = AADD_ZERO; + gates[k][0] = EVBDD_ONE; gates[k][1] = EVBDD_ZERO; + gates[k][2] = EVBDD_ZERO; gates[k][3] = EVBDD_ZERO; k = GATEID_proj1; - gates[k][0] = AADD_ZERO; gates[k][1] = AADD_ZERO; - gates[k][2] = AADD_ZERO; gates[k][3] = AADD_ONE; + gates[k][0] = EVBDD_ZERO; gates[k][1] = EVBDD_ZERO; + gates[k][2] = EVBDD_ZERO; gates[k][3] = EVBDD_ONE; k = GATEID_X; - gates[k][0] = AADD_ZERO; gates[k][1] = AADD_ONE; - gates[k][2] = AADD_ONE; gates[k][3] = AADD_ZERO; + gates[k][0] = EVBDD_ZERO; gates[k][1] = EVBDD_ONE; + gates[k][2] = EVBDD_ONE; gates[k][3] = EVBDD_ZERO; k = GATEID_Y; - gates[k][0] = AADD_ZERO; gates[k][1] = complex_lookup(0.0, -1.0); - gates[k][2] = complex_lookup(0.0, 1.0); gates[k][3] = AADD_ZERO; + gates[k][0] = EVBDD_ZERO; gates[k][1] = complex_lookup(0.0, -1.0); + gates[k][2] = complex_lookup(0.0, 1.0); gates[k][3] = EVBDD_ZERO; k = GATEID_Z; - gates[k][0] = AADD_ONE; gates[k][1] = AADD_ZERO; - gates[k][2] = AADD_ZERO; gates[k][3] = AADD_MIN_ONE; + gates[k][0] = EVBDD_ONE; gates[k][1] = EVBDD_ZERO; + gates[k][2] = EVBDD_ZERO; gates[k][3] = EVBDD_MIN_ONE; k = GATEID_H; gates[k][0] = gates[k][1] = gates[k][2] = complex_lookup(1.0/flt_sqrt(2.0),0); gates[k][3] = complex_lookup(-1.0/flt_sqrt(2.0),0); k = GATEID_S; - gates[k][0] = AADD_ONE; gates[k][1] = AADD_ZERO; - gates[k][2] = AADD_ZERO; gates[k][3] = complex_lookup(0.0, 1.0); + gates[k][0] = EVBDD_ONE; gates[k][1] = EVBDD_ZERO; + gates[k][2] = EVBDD_ZERO; gates[k][3] = complex_lookup(0.0, 1.0); k = GATEID_Sdag; - gates[k][0] = AADD_ONE; gates[k][1] = AADD_ZERO; - gates[k][2] = AADD_ZERO; gates[k][3] = complex_lookup(0.0, -1.0); + gates[k][0] = EVBDD_ONE; gates[k][1] = EVBDD_ZERO; + gates[k][2] = EVBDD_ZERO; gates[k][3] = complex_lookup(0.0, -1.0); k = GATEID_T; - gates[k][0] = AADD_ONE; gates[k][1] = AADD_ZERO; - gates[k][2] = AADD_ZERO; gates[k][3] = complex_lookup(1.0/flt_sqrt(2.0), 1.0/flt_sqrt(2.0)); + gates[k][0] = EVBDD_ONE; gates[k][1] = EVBDD_ZERO; + gates[k][2] = EVBDD_ZERO; gates[k][3] = complex_lookup(1.0/flt_sqrt(2.0), 1.0/flt_sqrt(2.0)); k = GATEID_Tdag; - gates[k][0] = AADD_ONE; gates[k][1] = AADD_ZERO; - gates[k][2] = AADD_ZERO; gates[k][3] = complex_lookup(1.0/flt_sqrt(2.0), -1.0/flt_sqrt(2.0)); + gates[k][0] = EVBDD_ONE; gates[k][1] = EVBDD_ZERO; + gates[k][2] = EVBDD_ZERO; gates[k][3] = complex_lookup(1.0/flt_sqrt(2.0), -1.0/flt_sqrt(2.0)); k = GATEID_sqrtX; gates[k][0] = complex_lookup(0.5, 0.5); gates[k][1] = complex_lookup(0.5,-0.5); @@ -211,14 +211,14 @@ qmdd_phase_gates_init(int n) angle = 2*Pi / (fl_t)(1< #include -typedef uint64_t AMP; // TODO: replace with AADD_WGT? +typedef uint64_t AMP; // TODO: replace with EVBDD_WGT? // GATE_ID's (gates are initialized in qmdd_gates_init) // currently 24 bits available for this number (see GATE_OPID) diff --git a/src/qsylvan_gates_mtbdd_mpc.c b/src/qsylvan_gates_mtbdd_mpc.c index 3ad08f5..34a699e 100644 --- a/src/qsylvan_gates_mtbdd_mpc.c +++ b/src/qsylvan_gates_mtbdd_mpc.c @@ -702,15 +702,15 @@ mtbdd_phase_gates_init(int n) cartesian = cmake_angle(angle, 1); gate_id = GATEID_Rk(k); - gates[gate_id][0] = AADD_ONE; gates[gate_id][1] = AADD_ZERO; - gates[gate_id][2] = AADD_ZERO; gates[gate_id][3] = weight_lookup(&cartesian); + gates[gate_id][0] = EVBDD_ONE; gates[gate_id][1] = EVBDD_ZERO; + gates[gate_id][2] = EVBDD_ZERO; gates[gate_id][3] = weight_lookup(&cartesian); // backward rotation angle = -2*Pi / (fl_t)(1<= 0; k--) { if (x[k] == 0) { - low = aadd_bundle(AADD_TARGET(prev), AADD_ONE); - high = aadd_bundle(AADD_TERMINAL, AADD_ZERO); + low = evbdd_bundle(EVBDD_TARGET(prev), EVBDD_ONE); + high = evbdd_bundle(EVBDD_TERMINAL, EVBDD_ZERO); } else if (x[k] == 1) { - low = aadd_bundle(AADD_TERMINAL, AADD_ZERO); - high = aadd_bundle(AADD_TARGET(prev), AADD_ONE); + low = evbdd_bundle(EVBDD_TERMINAL, EVBDD_ZERO); + high = evbdd_bundle(EVBDD_TARGET(prev), EVBDD_ONE); } // add node to unique table - prev = aadd_makenode(k, low, high); + prev = evbdd_makenode(k, low, high); } return prev; } @@ -122,17 +122,17 @@ qmdd_stack_matrix(QMDD below, BDDVAR k, gate_id_t gateid) // Matrix U = [u00 u01 // u10 u11] endoded in a small tree - u00 = aadd_bundle(AADD_TARGET(below), gates[gateid][0]); - u10 = aadd_bundle(AADD_TARGET(below), gates[gateid][2]); - u01 = aadd_bundle(AADD_TARGET(below), gates[gateid][1]); - u11 = aadd_bundle(AADD_TARGET(below), gates[gateid][3]); - low = aadd_makenode(t, u00, u10); - high = aadd_makenode(t, u01, u11); - res = aadd_makenode(s, low, high); + u00 = evbdd_bundle(EVBDD_TARGET(below), gates[gateid][0]); + u10 = evbdd_bundle(EVBDD_TARGET(below), gates[gateid][2]); + u01 = evbdd_bundle(EVBDD_TARGET(below), gates[gateid][1]); + u11 = evbdd_bundle(EVBDD_TARGET(below), gates[gateid][3]); + low = evbdd_makenode(t, u00, u10); + high = evbdd_makenode(t, u01, u11); + res = evbdd_makenode(s, low, high); // Propagate common factor on previous root amp to new root amp - AMP new_root_amp = wgt_mul(AADD_WEIGHT(below), AADD_WEIGHT(res)); - res = aadd_bundle(AADD_TARGET(res), new_root_amp); + AMP new_root_amp = wgt_mul(EVBDD_WEIGHT(below), EVBDD_WEIGHT(res)); + res = evbdd_bundle(EVBDD_TARGET(res), new_root_amp); return res; } @@ -147,14 +147,14 @@ qmdd_stack_control(QMDD case0, QMDD case1, BDDVAR k) t = s + 1; u00 = case0; - u10 = aadd_bundle(AADD_TERMINAL, AADD_ZERO); - u01 = aadd_bundle(AADD_TERMINAL, AADD_ZERO); + u10 = evbdd_bundle(EVBDD_TERMINAL, EVBDD_ZERO); + u01 = evbdd_bundle(EVBDD_TERMINAL, EVBDD_ZERO); u11 = case1; - low = aadd_makenode(t, u00, u10); - high = aadd_makenode(t, u01, u11); - res = aadd_makenode(s, low, high); + low = evbdd_makenode(t, u00, u10); + high = evbdd_makenode(t, u01, u11); + res = evbdd_makenode(s, low, high); - // Weights of case0/case1 already dealt with by aadd_makenode + // Weights of case0/case1 already dealt with by evbdd_makenode return res; } @@ -162,7 +162,7 @@ QMDD qmdd_create_all_identity_matrix(BDDVAR n) { // Start at terminal and build backwards - QMDD prev = aadd_bundle(AADD_TERMINAL, AADD_ONE); + QMDD prev = evbdd_bundle(EVBDD_TERMINAL, EVBDD_ONE); for (int k = n-1; k >= 0; k--) { prev = qmdd_stack_matrix(prev, k, GATEID_I); } @@ -173,7 +173,7 @@ QMDD qmdd_create_single_qubit_gate(BDDVAR n, BDDVAR t, gate_id_t gateid) { // Start at terminal and build backwards - QMDD prev = aadd_bundle(AADD_TERMINAL, AADD_ONE); + QMDD prev = evbdd_bundle(EVBDD_TERMINAL, EVBDD_ONE); for (int k = n-1; k >= 0; k--) { if ((unsigned int)k == t) prev = qmdd_stack_matrix(prev, k, gateid); @@ -187,7 +187,7 @@ QMDD qmdd_create_single_qubit_gates(BDDVAR n, gate_id_t *gateids) { // Start at terminal and build backwards - QMDD prev = aadd_bundle(AADD_TERMINAL, AADD_ONE); + QMDD prev = evbdd_bundle(EVBDD_TERMINAL, EVBDD_ONE); for (int k = n-1; k >= 0; k--) { prev = qmdd_stack_matrix(prev, k, gateids[k]); } @@ -198,7 +198,7 @@ QMDD qmdd_create_single_qubit_gates_same(BDDVAR n, gate_id_t gateid) { // Start at terminal and build backwards - QMDD prev = aadd_bundle(AADD_TERMINAL, AADD_ONE); + QMDD prev = evbdd_bundle(EVBDD_TERMINAL, EVBDD_ONE); for (int k = n-1; k >= 0; k--) { prev = qmdd_stack_matrix(prev, k, gateid); } @@ -210,10 +210,10 @@ _qmdd_create_cgate(BDDVAR n, BDDVAR c1, BDDVAR c2, BDDVAR c3, BDDVAR t, gate_id_ { 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; + if (c1 != EVBDD_INVALID_VAR && c1 < n) c_options[c1] = 1; + if (c2 != EVBDD_INVALID_VAR && c2 < n) c_options[c2] = 1; + if (c3 != EVBDD_INVALID_VAR && c3 < n) c_options[c3] = 1; + if (t != EVBDD_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; @@ -232,8 +232,8 @@ qmdd_create_multi_cgate(BDDVAR n, int *c_options, gate_id_t gateid) // -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 U_proj = evbdd_bundle(EVBDD_TERMINAL, EVBDD_ONE); + QMDD proj = evbdd_bundle(EVBDD_TERMINAL, EVBDD_ONE); QMDD I = qmdd_create_all_identity_matrix(n); for (int k = n-1; k >= 0; k--) { @@ -264,16 +264,16 @@ qmdd_create_multi_cgate(BDDVAR n, int *c_options, gate_id_t gateid) } // multiply root edge of proj with -1 - proj = aadd_bundle(AADD_TARGET(proj), wgt_neg(AADD_WEIGHT(proj))); + proj = evbdd_bundle(EVBDD_TARGET(proj), wgt_neg(EVBDD_WEIGHT(proj))); - return aadd_plus(U_proj, aadd_plus(I, proj)); + return evbdd_plus(U_proj, evbdd_plus(I, proj)); } QMDD qmdd_create_all_control_phase(BDDVAR n, bool *x) { - QMDD identity = aadd_bundle(AADD_TERMINAL, AADD_ONE); - QMDD ccphase = aadd_bundle(AADD_TERMINAL, AADD_ONE); + QMDD identity = evbdd_bundle(EVBDD_TERMINAL, EVBDD_ONE); + QMDD ccphase = evbdd_bundle(EVBDD_TERMINAL, EVBDD_ONE); // Start with (-1)Z gate on last qubit. Z if control on 1 and -Z if 0. if (x[n-1] == 1) { @@ -281,7 +281,7 @@ qmdd_create_all_control_phase(BDDVAR n, bool *x) } else if (x[n-1] == 0) { ccphase = qmdd_stack_matrix(ccphase, n-1, GATEID_Z); - ccphase = aadd_bundle(AADD_TARGET(ccphase), wgt_neg(AADD_WEIGHT(ccphase))); + ccphase = evbdd_bundle(EVBDD_TARGET(ccphase), wgt_neg(EVBDD_WEIGHT(ccphase))); } // Stack remaining controls @@ -314,18 +314,18 @@ static void qmdd_do_before_gate(QMDD* qmdd) { // check if ctable needs gc - if (aadd_test_gc_wgt_table()) { - aadd_protect(qmdd); - aadd_gc_wgt_table(); - aadd_unprotect(qmdd); + if (evbdd_test_gc_wgt_table()) { + evbdd_protect(qmdd); + evbdd_gc_wgt_table(); + evbdd_unprotect(qmdd); } if (periodic_gc_nodetable) { gate_counter++; if (gate_counter % periodic_gc_nodetable == 0) { - aadd_protect(qmdd); + evbdd_protect(qmdd); sylvan_gc(); - aadd_unprotect(qmdd); + evbdd_unprotect(qmdd); } } @@ -349,9 +349,9 @@ check_ctrls_before_targ(BDDVAR *c1, BDDVAR *c2, BDDVAR *c3, BDDVAR t) 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; + if (*c1 != EVBDD_INVALID_VAR && *c1 > t) return false; + if (*c2 != EVBDD_INVALID_VAR && *c2 > t) return false; + if (*c3 != EVBDD_INVALID_VAR && *c3 > t) return false; return true; } @@ -359,9 +359,9 @@ check_ctrls_before_targ(BDDVAR *c1, BDDVAR *c2, BDDVAR *c3, BDDVAR t) TASK_IMPL_3(QMDD, qmdd_gate, QMDD, qmdd, gate_id_t, gate, BDDVAR, target) { qmdd_do_before_gate(&qmdd); - aadd_refs_push(qmdd); + evbdd_refs_push(qmdd); QMDD res = qmdd_gate_rec(qmdd, gate, target); - aadd_refs_pop(1); + evbdd_refs_pop(1); return res; } @@ -369,21 +369,21 @@ TASK_IMPL_3(QMDD, qmdd_gate, QMDD, qmdd, gate_id_t, gate, BDDVAR, target) QMDD _qmdd_cgate(QMDD state, gate_id_t gate, BDDVAR c1, BDDVAR c2, BDDVAR c3, BDDVAR t, BDDVAR n) { if (check_ctrls_before_targ(&c1, &c2, &c3, t)) { - BDDVAR cs[4] = {c1, c2, c3, AADD_INVALID_VAR}; // last pos is to mark end + BDDVAR cs[4] = {c1, c2, c3, EVBDD_INVALID_VAR}; // last pos is to mark end return RUN(qmdd_cgate, state, gate, cs, t);//qmdd_cgate_rec(state, gate, cs, t); } else { assert(n != 0 && "ERROR: when ctrls > targ, nqubits must be passed to cgate() function."); QMDD gate_matrix = _qmdd_create_cgate(n, c1, c2, c3, t, gate); - return aadd_matvec_mult(gate_matrix, state, n); + return evbdd_matvec_mult(gate_matrix, state, n); } } TASK_IMPL_4(QMDD, qmdd_cgate, QMDD, state, gate_id_t, gate, BDDVAR*, cs, BDDVAR, t) { qmdd_do_before_gate(&state); - aadd_refs_push(state); + evbdd_refs_push(state); QMDD res = qmdd_cgate_rec(state, gate, cs, t); - aadd_refs_pop(1); + evbdd_refs_pop(1); return res; } @@ -397,57 +397,57 @@ TASK_IMPL_5(QMDD, qmdd_cgate_range, QMDD, qmdd, gate_id_t, gate, BDDVAR, c_first TASK_IMPL_3(QMDD, qmdd_gate_rec, QMDD, q, gate_id_t, gate, BDDVAR, target) { // Trivial cases - if (AADD_WEIGHT(q) == AADD_ZERO) return q; + if (EVBDD_WEIGHT(q) == EVBDD_ZERO) return q; BDDVAR var; QMDD res, low, high; - aadd_get_topvar(q, target, &var, &low, &high); + evbdd_get_topvar(q, target, &var, &low, &high); assert(var <= target); // Check cache bool cachenow = ((var % granularity) == 0); if (cachenow) { - if (cache_get3(CACHE_QMDD_GATE, sylvan_false, AADD_TARGET(q), GATE_OPID_40(gate, target, 0), &res)) { + if (cache_get3(CACHE_QMDD_GATE, sylvan_false, EVBDD_TARGET(q), GATE_OPID_40(gate, target, 0), &res)) { sylvan_stats_count(QMDD_GATE_CACHED); // Multiply root of res with root of input qmdd - AMP new_root_amp = wgt_mul(AADD_WEIGHT(q), AADD_WEIGHT(res)); - res = aadd_bundle(AADD_TARGET(res), new_root_amp); + AMP new_root_amp = wgt_mul(EVBDD_WEIGHT(q), EVBDD_WEIGHT(res)); + res = evbdd_bundle(EVBDD_TARGET(res), new_root_amp); return res; } } if (var == target) { - AMP a_u00 = wgt_mul(AADD_WEIGHT(low), gates[gate][0]); - AMP a_u10 = wgt_mul(AADD_WEIGHT(low), gates[gate][2]); - AMP b_u01 = wgt_mul(AADD_WEIGHT(high), gates[gate][1]); - AMP b_u11 = wgt_mul(AADD_WEIGHT(high), gates[gate][3]); + AMP a_u00 = wgt_mul(EVBDD_WEIGHT(low), gates[gate][0]); + AMP a_u10 = wgt_mul(EVBDD_WEIGHT(low), gates[gate][2]); + AMP b_u01 = wgt_mul(EVBDD_WEIGHT(high), gates[gate][1]); + AMP b_u11 = wgt_mul(EVBDD_WEIGHT(high), gates[gate][3]); QMDD low1, low2, high1, high2; - low1 = aadd_bundle(AADD_TARGET(low), a_u00); - low2 = aadd_bundle(AADD_TARGET(high),b_u01); - 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 = 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); + low1 = evbdd_bundle(EVBDD_TARGET(low), a_u00); + low2 = evbdd_bundle(EVBDD_TARGET(high),b_u01); + high1 = evbdd_bundle(EVBDD_TARGET(low), a_u10); + high2 = evbdd_bundle(EVBDD_TARGET(high),b_u11); + evbdd_refs_spawn(SPAWN(evbdd_plus, high1, high2)); + low = evbdd_refs_push(CALL(evbdd_plus, low1, low2)); + high = evbdd_refs_sync(SYNC(evbdd_plus)); + evbdd_refs_pop(1); + res = evbdd_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 = 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); + evbdd_refs_spawn(SPAWN(qmdd_gate_rec, high, gate, target)); + low = evbdd_refs_push(CALL(qmdd_gate_rec, low, gate, target)); + high = evbdd_refs_sync(SYNC(qmdd_gate_rec)); + evbdd_refs_pop(1); + res = evbdd_makenode(var, low, high); } // Store not yet "root normalized" result in cache if (cachenow) { - if (cache_put3(CACHE_QMDD_GATE, sylvan_false, AADD_TARGET(q), GATE_OPID_40(gate, target, 0), res)) + if (cache_put3(CACHE_QMDD_GATE, sylvan_false, EVBDD_TARGET(q), GATE_OPID_40(gate, target, 0), res)) sylvan_stats_count(QMDD_GATE_CACHEDPUT); } // Multiply amp res with amp of input qmdd - AMP new_root_amp = wgt_mul(AADD_WEIGHT(q), AADD_WEIGHT(res)); - res = aadd_bundle(AADD_TARGET(res), new_root_amp); + AMP new_root_amp = wgt_mul(EVBDD_WEIGHT(q), EVBDD_WEIGHT(res)); + res = evbdd_bundle(EVBDD_TARGET(res), new_root_amp); return res; } @@ -455,7 +455,7 @@ TASK_IMPL_5(QMDD, qmdd_cgate_rec, QMDD, q, gate_id_t, gate, BDDVAR*, cs, uint32_ { // Get current control qubit. If no more control qubits, apply gate here BDDVAR c = cs[ci]; - if (c == AADD_INVALID_VAR || ci > MAX_CONTROLS) { + if (c == EVBDD_INVALID_VAR || ci > MAX_CONTROLS) { return CALL(qmdd_gate_rec, q, gate, t); } @@ -465,19 +465,19 @@ TASK_IMPL_5(QMDD, qmdd_cgate_rec, QMDD, q, gate_id_t, gate, BDDVAR*, cs, uint32_ BDDVAR var; QMDD res, low, high; - aadd_get_topvar(q, c, &var, &low, &high); + evbdd_get_topvar(q, c, &var, &low, &high); assert(var <= c); // Check cache bool cachenow = ((var % granularity) == 0); if (cachenow) { - if (cache_get3(CACHE_QMDD_CGATE, sylvan_false, AADD_TARGET(q), + if (cache_get3(CACHE_QMDD_CGATE, sylvan_false, EVBDD_TARGET(q), GATE_OPID_64(gate, ci, cs[0], cs[1], cs[2], t), &res)) { sylvan_stats_count(QMDD_CGATE_CACHED); // Multiply root amp of res with input root amp - AMP new_root_amp = wgt_mul(AADD_WEIGHT(q), AADD_WEIGHT(res)); - res = aadd_bundle(AADD_TARGET(res), new_root_amp); + AMP new_root_amp = wgt_mul(EVBDD_WEIGHT(q), EVBDD_WEIGHT(res)); + res = evbdd_bundle(EVBDD_TARGET(res), new_root_amp); return res; } } @@ -489,24 +489,24 @@ TASK_IMPL_5(QMDD, qmdd_cgate_rec, QMDD, q, gate_id_t, gate, BDDVAR*, cs, uint32_ } // Not at control qubit yet, apply to both childeren. else { - aadd_refs_spawn(SPAWN(qmdd_cgate_rec, high, gate, cs, ci, t)); - 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); + evbdd_refs_spawn(SPAWN(qmdd_cgate_rec, high, gate, cs, ci, t)); + low = evbdd_refs_push(CALL(qmdd_cgate_rec, low, gate, cs, ci, t)); + high = evbdd_refs_sync(SYNC(qmdd_cgate_rec)); + evbdd_refs_pop(1); } - res = aadd_makenode(var, low, high); + res = evbdd_makenode(var, low, high); // Store not yet "root normalized" result in cache if (cachenow) { - if (cache_put3(CACHE_QMDD_CGATE, sylvan_false, AADD_TARGET(q), + if (cache_put3(CACHE_QMDD_CGATE, sylvan_false, EVBDD_TARGET(q), GATE_OPID_64(gate, ci, cs[0], cs[1], cs[2], t), res)) { sylvan_stats_count(QMDD_CGATE_CACHEDPUT); } } // Multiply root amp of res with input root amp - AMP new_root_amp = wgt_mul(AADD_WEIGHT(q), AADD_WEIGHT(res)); - res = aadd_bundle(AADD_TARGET(res), new_root_amp); + AMP new_root_amp = wgt_mul(EVBDD_WEIGHT(q), EVBDD_WEIGHT(res)); + res = evbdd_bundle(EVBDD_TARGET(res), new_root_amp); return res; } @@ -524,13 +524,13 @@ TASK_IMPL_6(QMDD, qmdd_cgate_range_rec, QMDD, q, gate_id_t, gate, BDDVAR, c_firs QMDD res; bool cachenow = ((k % granularity) == 0); if (cachenow) { - if (cache_get3(CACHE_QMDD_CGATE_RANGE, sylvan_false, AADD_TARGET(q), + if (cache_get3(CACHE_QMDD_CGATE_RANGE, sylvan_false, EVBDD_TARGET(q), GATE_OPID_64(gate, c_first, c_last, k, t, 0), &res)) { sylvan_stats_count(QMDD_CGATE_CACHED); // Multiply root amp of result with the input root amp - AMP new_root_amp = wgt_mul(AADD_WEIGHT(q), AADD_WEIGHT(res)); - res = aadd_bundle(AADD_TARGET(res), new_root_amp); + AMP new_root_amp = wgt_mul(EVBDD_WEIGHT(q), EVBDD_WEIGHT(res)); + res = evbdd_bundle(EVBDD_TARGET(res), new_root_amp); return res; } } @@ -540,41 +540,41 @@ TASK_IMPL_6(QMDD, qmdd_cgate_range_rec, QMDD, q, gate_id_t, gate, BDDVAR, c_firs QMDD low, high; if (k < c_first) { // possibly skip to c_first if we are before c_first - aadd_get_topvar(q, c_first, &var, &low, &high); + evbdd_get_topvar(q, c_first, &var, &low, &high); assert(var <= c_first); } else { // k is a control qubit, so get node with var = k (insert if skipped) assert(c_first <= k && k <= c_last); - aadd_get_topvar(q, k, &var, &low, &high); + evbdd_get_topvar(q, k, &var, &low, &high); assert(var == k); } nextvar = var + 1; // 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 = 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); + evbdd_refs_spawn(SPAWN(qmdd_cgate_range_rec, high, gate, c_first, c_last, t, nextvar)); + low = evbdd_refs_push(CALL(qmdd_cgate_range_rec, low, gate, c_first, c_last, t, nextvar)); + high = evbdd_refs_sync(SYNC(qmdd_cgate_range_rec)); + evbdd_refs_pop(1); } // Current var is a control qubit, control on q_k = |1> (high edge) else { high = CALL(qmdd_cgate_range_rec, high, gate, c_first, c_last, t, nextvar); } - res = aadd_makenode(var, low, high); + res = evbdd_makenode(var, low, high); // Store not yet "root normalized" result in cache if (cachenow) { - if (cache_put3(CACHE_QMDD_CGATE_RANGE, sylvan_false, AADD_TARGET(q), + if (cache_put3(CACHE_QMDD_CGATE_RANGE, sylvan_false, EVBDD_TARGET(q), GATE_OPID_64(gate, c_first, c_last, k, t, 0), res)) { sylvan_stats_count(QMDD_CGATE_CACHEDPUT); } } // Multiply root amp of result with the input root amp - AMP new_root_amp = wgt_mul(AADD_WEIGHT(q), AADD_WEIGHT(res)); - res = aadd_bundle(AADD_TARGET(res), new_root_amp); + AMP new_root_amp = wgt_mul(EVBDD_WEIGHT(q), EVBDD_WEIGHT(res)); + res = evbdd_bundle(EVBDD_TARGET(res), new_root_amp); return res; } @@ -681,7 +681,7 @@ qmdd_circuit(QMDD qmdd, circuit_id_t circ_id, BDDVAR t1, BDDVAR t2) case CIRCID_QFT_inv : return qmdd_circuit_QFT_inv(qmdd, t1, t2); default : assert ("Invalid circuit ID" && false); - return AADD_TERMINAL; + return EVBDD_TERMINAL; } } @@ -702,7 +702,7 @@ TASK_IMPL_6(QMDD, qmdd_ccircuit, QMDD, qmdd, circuit_id_t, circ_id, BDDVAR*, cs, BDDVAR c = cs[ci]; // If no more control qubits, apply sub-circ here - if (c == AADD_INVALID_VAR || ci > MAX_CONTROLS) { + if (c == EVBDD_INVALID_VAR || ci > MAX_CONTROLS) { res = qmdd_circuit(qmdd, circ_id, t1, t2); // the gates in qmdd_circuit already took care of multiplying the input // root amp with normalization, so no need to do that here again @@ -710,7 +710,7 @@ TASK_IMPL_6(QMDD, qmdd_ccircuit, QMDD, qmdd, circuit_id_t, circ_id, BDDVAR*, cs, else { BDDVAR var; QMDD low, high; - aadd_get_topvar(qmdd, c, &var, &low, &high); + evbdd_get_topvar(qmdd, c, &var, &low, &high); assert(var <= c); if (var == c) { @@ -720,16 +720,16 @@ TASK_IMPL_6(QMDD, qmdd_ccircuit, QMDD, qmdd, circuit_id_t, circ_id, BDDVAR*, cs, } else { // recursive call to both children - aadd_refs_spawn(SPAWN(qmdd_ccircuit, high, circ_id, cs, ci, t1, t2)); + evbdd_refs_spawn(SPAWN(qmdd_ccircuit, high, circ_id, cs, ci, t1, t2)); low = CALL(qmdd_ccircuit, low, circ_id, cs, ci, t1, t2); - aadd_refs_push(low); - high = aadd_refs_sync(SYNC(qmdd_ccircuit)); - aadd_refs_pop(1); + evbdd_refs_push(low); + high = evbdd_refs_sync(SYNC(qmdd_ccircuit)); + evbdd_refs_pop(1); } - res = aadd_makenode(var, low, high); + res = evbdd_makenode(var, low, high); // Multiply root amp of sum with input root amp - AMP new_root_amp = wgt_mul(AADD_WEIGHT(qmdd), AADD_WEIGHT(res)); - res = aadd_bundle(AADD_TARGET(res), new_root_amp); + AMP new_root_amp = wgt_mul(EVBDD_WEIGHT(qmdd), EVBDD_WEIGHT(res)); + res = evbdd_bundle(EVBDD_TARGET(res), new_root_amp); } // Add to cache, return @@ -747,13 +747,13 @@ qmdd_all_control_phase_rec(QMDD qmdd, BDDVAR k, BDDVAR n, bool *x) assert(k < n); bool skipped_k = false; - aaddnode_t node; - if (AADD_TARGET(qmdd) == AADD_TERMINAL) { + evbddnode_t node; + if (EVBDD_TARGET(qmdd) == EVBDD_TERMINAL) { skipped_k = true; } else { - node = AADD_GETNODE(AADD_TARGET(qmdd)); - BDDVAR var = aaddnode_getvar(node); + node = EVBDD_GETNODE(EVBDD_TARGET(qmdd)); + BDDVAR var = evbddnode_getvar(node); if(var > k) { skipped_k = true; } @@ -762,23 +762,23 @@ qmdd_all_control_phase_rec(QMDD qmdd, BDDVAR k, BDDVAR n, bool *x) QMDD low, high; if (skipped_k) { // insert skipped node - low = aadd_bundle(AADD_TARGET(qmdd), AADD_ONE); - high = aadd_bundle(AADD_TARGET(qmdd), AADD_ONE); + low = evbdd_bundle(EVBDD_TARGET(qmdd), EVBDD_ONE); + high = evbdd_bundle(EVBDD_TARGET(qmdd), EVBDD_ONE); } else { // case var == k (var < k shouldn't happen) - aaddnode_getchilderen(node, &low, &high); + evbddnode_getchilderen(node, &low, &high); } // terminal case, apply phase depending on x[k] (control k on 0 or 1) if (k == (n-1)) { if (x[k] == 1) { - AMP new_amp = wgt_mul(AADD_WEIGHT(high), AADD_MIN_ONE); - high = aadd_bundle(AADD_TARGET(high), new_amp); + AMP new_amp = wgt_mul(EVBDD_WEIGHT(high), EVBDD_MIN_ONE); + high = evbdd_bundle(EVBDD_TARGET(high), new_amp); } else { - AMP new_amp = wgt_mul(AADD_WEIGHT(low), AADD_MIN_ONE); - low = aadd_bundle(AADD_TARGET(low), new_amp); + AMP new_amp = wgt_mul(EVBDD_WEIGHT(low), EVBDD_MIN_ONE); + low = evbdd_bundle(EVBDD_TARGET(low), new_amp); } } // non terminal case, choose low/high depending on x[k] (control k on 0 or 1) @@ -795,11 +795,11 @@ qmdd_all_control_phase_rec(QMDD qmdd, BDDVAR k, BDDVAR n, bool *x) } } - QMDD res = aadd_makenode(k, low, high); + QMDD res = evbdd_makenode(k, low, high); // multiply by existing edge weight on qmdd - AMP new_root_amp = wgt_mul(AADD_WEIGHT(qmdd), AADD_WEIGHT(res)); - res = aadd_bundle(AADD_TARGET(res), new_root_amp); + AMP new_root_amp = wgt_mul(EVBDD_WEIGHT(qmdd), EVBDD_WEIGHT(res)); + res = evbdd_bundle(EVBDD_TARGET(res), new_root_amp); return res; } @@ -835,7 +835,7 @@ qmdd_measure_q0(QMDD qmdd, BDDVAR nvars, int *m, double *p) QMDD low, high; BDDVAR var; - aadd_get_topvar(qmdd, 0, &var, &low, &high); + evbdd_get_topvar(qmdd, 0, &var, &low, &high); if (testing_mode) assert(qmdd_is_unitvector(qmdd, nvars)); @@ -843,7 +843,7 @@ qmdd_measure_q0(QMDD qmdd, BDDVAR nvars, int *m, double *p) // (e.g. by using AMPs) prob_low = qmdd_unnormed_prob(low, 1, nvars); prob_high = qmdd_unnormed_prob(high, 1, nvars); - prob_root = qmdd_amp_to_prob(AADD_WEIGHT(qmdd)); + prob_root = qmdd_amp_to_prob(EVBDD_WEIGHT(qmdd)); prob_low *= prob_root; prob_high *= prob_root; if (fabs(prob_low + prob_high - 1.0) > 1e-6) { @@ -858,20 +858,20 @@ qmdd_measure_q0(QMDD qmdd, BDDVAR nvars, int *m, double *p) // produce post-measurement state AMP norm; if (*m == 0) { - high = aadd_bundle(AADD_TERMINAL, AADD_ZERO); + high = evbdd_bundle(EVBDD_TERMINAL, EVBDD_ZERO); norm = qmdd_amp_from_prob(prob_low); } else { - low = aadd_bundle(AADD_TERMINAL, AADD_ZERO); + low = evbdd_bundle(EVBDD_TERMINAL, EVBDD_ZERO); norm = qmdd_amp_from_prob(prob_high); } - QMDD res = aadd_makenode(0, low, high); + QMDD res = evbdd_makenode(0, low, high); - AMP new_root_amp = wgt_mul(AADD_WEIGHT(qmdd), AADD_WEIGHT(res)); + AMP new_root_amp = wgt_mul(EVBDD_WEIGHT(qmdd), EVBDD_WEIGHT(res)); new_root_amp = wgt_div(new_root_amp, norm); - res = aadd_bundle(AADD_TARGET(res), new_root_amp); + res = evbdd_bundle(EVBDD_TARGET(res), new_root_amp); res = qmdd_remove_global_phase(res); return res; } @@ -879,7 +879,7 @@ qmdd_measure_q0(QMDD qmdd, BDDVAR nvars, int *m, double *p) QMDD qmdd_measure_all(QMDD qmdd, BDDVAR n, bool* ms, double *p) { - aaddnode_t node; + evbddnode_t node; bool skipped; BDDVAR var; double prob_low, prob_high, prob_path = 1.0, prob_roots = 1.0; @@ -887,28 +887,28 @@ qmdd_measure_all(QMDD qmdd, BDDVAR n, bool* ms, double *p) for (BDDVAR k=0; k < n; k++) { // find relevant node (assuming it should be the next one) skipped = false; - if (AADD_TARGET(qmdd) == AADD_TERMINAL) { + if (EVBDD_TARGET(qmdd) == EVBDD_TERMINAL) { skipped = true; } else { - node = AADD_GETNODE(AADD_TARGET(qmdd)); - var = aaddnode_getvar(node); + node = EVBDD_GETNODE(EVBDD_TARGET(qmdd)); + var = evbddnode_getvar(node); assert(var >= k); if (var > k) skipped = true; } QMDD low, high; if (skipped) { // if skipped q0 is a don't care, treat separately? - low = aadd_bundle(AADD_TARGET(qmdd), AADD_ONE); - high = aadd_bundle(AADD_TARGET(qmdd), AADD_ONE); + low = evbdd_bundle(EVBDD_TARGET(qmdd), EVBDD_ONE); + high = evbdd_bundle(EVBDD_TARGET(qmdd), EVBDD_ONE); } else { - aaddnode_getchilderen(node, &low, &high); + evbddnode_getchilderen(node, &low, &high); } prob_low = qmdd_unnormed_prob(low, k+1, n); prob_high = qmdd_unnormed_prob(high, k+1, n); - prob_roots *= qmdd_amp_to_prob(AADD_WEIGHT(qmdd)); + prob_roots *= qmdd_amp_to_prob(EVBDD_WEIGHT(qmdd)); prob_high = prob_high * prob_roots / prob_path; prob_low = prob_low * prob_roots / prob_path; @@ -928,19 +928,19 @@ qmdd_measure_all(QMDD qmdd, BDDVAR n, bool* ms, double *p) *p = prob_path; //TODO: replace below ith "return qmdd_create_basis_state(n, ms);"" - QMDD low, high, prev = AADD_TERMINAL; + QMDD low, high, prev = EVBDD_TERMINAL; for (int k = n-1; k >= 0; k--) { if (ms[k] == 0) { - low = aadd_bundle(AADD_TARGET(prev), AADD_ONE); - high = aadd_bundle(AADD_TERMINAL, AADD_ZERO); + low = evbdd_bundle(EVBDD_TARGET(prev), EVBDD_ONE); + high = evbdd_bundle(EVBDD_TERMINAL, EVBDD_ZERO); } else if (ms[k] == 1) { - low = aadd_bundle(AADD_TERMINAL, AADD_ZERO); - high = aadd_bundle(AADD_TARGET(prev), AADD_ONE); + low = evbdd_bundle(EVBDD_TERMINAL, EVBDD_ZERO); + high = evbdd_bundle(EVBDD_TARGET(prev), EVBDD_ONE); } // add node to unique table - prev = aadd_makenode(k, low, high); + prev = evbdd_makenode(k, low, high); } return prev; } @@ -957,8 +957,8 @@ TASK_IMPL_3(double, qmdd_unnormed_prob, QMDD, qmdd, BDDVAR, topvar, BDDVAR, nvar assert(topvar <= nvars); if (topvar == nvars) { - assert(AADD_TARGET(qmdd) == AADD_TERMINAL); - return qmdd_amp_to_prob(AADD_WEIGHT(qmdd)); + assert(EVBDD_TARGET(qmdd) == EVBDD_TERMINAL); + return qmdd_amp_to_prob(EVBDD_WEIGHT(qmdd)); } // Look in cache @@ -975,7 +975,7 @@ TASK_IMPL_3(double, qmdd_unnormed_prob, QMDD, qmdd, BDDVAR, topvar, BDDVAR, nvar // Check if the node we want is being skipped BDDVAR var; QMDD low, high; - aadd_get_topvar(qmdd, topvar, &var, &low, &high); + evbdd_get_topvar(qmdd, topvar, &var, &low, &high); double prob_low, prob_high, prob_root, prob_res; // "prob" = absolute amps squared BDDVAR nextvar = topvar + 1; @@ -983,7 +983,7 @@ TASK_IMPL_3(double, qmdd_unnormed_prob, QMDD, qmdd, BDDVAR, topvar, BDDVAR, nvar SPAWN(qmdd_unnormed_prob, high, nextvar, nvars); prob_low = CALL(qmdd_unnormed_prob, low, nextvar, nvars); prob_high = SYNC(qmdd_unnormed_prob); - prob_root = qmdd_amp_to_prob(AADD_WEIGHT(qmdd)); + prob_root = qmdd_amp_to_prob(EVBDD_WEIGHT(qmdd)); prob_res = prob_root * (prob_low + prob_high); // Put in cache and return @@ -1002,7 +1002,7 @@ qmdd_get_amplitude(QMDD q, bool *x, BDDVAR nqubits) // so we temporarily reverse x. reverse_bit_array(x, nqubits); complex_t res; - weight_value(aadd_getvalue(q, x), &res); + weight_value(evbdd_getvalue(q, x), &res); reverse_bit_array(x, nqubits); return res; } @@ -1028,7 +1028,7 @@ qmdd_amp_from_prob(double a) double qmdd_fidelity(QMDD a, QMDD b, BDDVAR nvars) { // c = - AMP prod = aadd_inner_product(a, b, nvars); + AMP prod = evbdd_inner_product(a, b, nvars); complex_t c; weight_value(prod, &c); @@ -1049,8 +1049,8 @@ QMDD qmdd_remove_global_phase(QMDD qmdd) { // Remove global phase by replacing amp of qmdd with absolute value of amp - AMP abs = wgt_abs(AADD_WEIGHT(qmdd)); - QMDD res = aadd_bundle(AADD_TARGET(qmdd), abs); + AMP abs = wgt_abs(EVBDD_WEIGHT(qmdd)); + QMDD res = evbdd_bundle(EVBDD_TARGET(qmdd), abs); return res; } @@ -1105,7 +1105,7 @@ qmdd_stats_log(QMDD qmdd) if (logtrycounter++ % statslog_granularity != 0) return; // Insert info - uint64_t num_nodes = aadd_countnodes(qmdd); + uint64_t num_nodes = evbdd_countnodes(qmdd); uint64_t num_amps = sylvan_edge_weights_count_entries(); fprintf(qmdd_logfile, "%" PRIu64 ",%" PRIu64 "\n", num_nodes, num_amps); logcounter++; @@ -1178,7 +1178,7 @@ qmdd_is_close_to_unitvector(QMDD qmdd, BDDVAR n, double tol) double sum_abs_squares = 0.0; while(has_next){ - a = aadd_getvalue(qmdd, x); + a = evbdd_getvalue(qmdd, x); sum_abs_squares += qmdd_amp_to_prob(a); has_next = _next_bitstring(x, n); } @@ -1187,7 +1187,7 @@ qmdd_is_close_to_unitvector(QMDD qmdd, BDDVAR n, double tol) if (WRITE_TO_FILE) { FILE *fp; fp = fopen("is_unitvector_true.dot", "w"); - aadd_fprintdot(fp, qmdd, false); + evbdd_fprintdot(fp, qmdd, false); fclose(fp); } return true; @@ -1197,7 +1197,7 @@ qmdd_is_close_to_unitvector(QMDD qmdd, BDDVAR n, double tol) if (WRITE_TO_FILE) { FILE *fp; fp = fopen("is_unitvector_false.dot", "w"); - aadd_fprintdot(fp, qmdd, false); + evbdd_fprintdot(fp, qmdd, false); fclose(fp); } return false; diff --git a/src/qsylvan_simulator.h b/src/qsylvan_simulator.h index 2e6ca63..47aef02 100644 --- a/src/qsylvan_simulator.h +++ b/src/qsylvan_simulator.h @@ -28,9 +28,9 @@ #include #include -typedef AADD QMDD; // QMDD edge (contains AMP and PTR) -typedef AADD_WGT AMP; // edge weight index -typedef AADD_TARG PTR; // node index +typedef EVBDD QMDD; // QMDD edge (contains AMP and PTR) +typedef EVBDD_WGT AMP; // edge weight index +typedef EVBDD_TARG PTR; // node index #ifdef __cplusplus extern "C" { @@ -139,8 +139,8 @@ 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. */ -#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_cgate(n, c, t, gateid) _qmdd_create_cgate(n, c, EVBDD_INVALID_VAR, EVBDD_INVALID_VAR, t, gateid) +#define qmdd_create_cgate2(n, c1, c2, t, gateid) _qmdd_create_cgate(n, c1, c2, EVBDD_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); @@ -268,8 +268,8 @@ TASK_DECL_3(QMDD, qmdd_gate, QMDD, gate_id_t, 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_cgate(state,gate,c,t,...) _qmdd_cgate(state,gate,c,EVBDD_INVALID_VAR,EVBDD_INVALID_VAR,t,(0, ##__VA_ARGS__)) +#define qmdd_cgate2(state,gate,c1,c2,t,...) (_qmdd_cgate(state,gate,c1,c2,EVBDD_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); TASK_DECL_4(QMDD, qmdd_cgate, QMDD, gate_id_t, BDDVAR*, BDDVAR); @@ -344,7 +344,7 @@ QMDD qmdd_circuit(QMDD qmdd, circuit_id_t circ_id, BDDVAR t1, BDDVAR t2); * functions defined here. * @param circ_id CIRCID_something * @param cs BDDVAR[] of control qubits. Needs to be length 3. If using fewer - * controls use e.g. cs = [c1, c2, AADD_INVALID_VAR] + * controls use e.g. cs = [c1, c2, EVBDD_INVALID_VAR] * @param t1 BDDVAR. Parameter 1 for given circuit. * @param t2 BDDVAR. Parameter 2 for given circuit. * diff --git a/src/qsylvan_simulator_mtbdd.c b/src/qsylvan_simulator_mtbdd.c index 6c79108..9b2ced4 100644 --- a/src/qsylvan_simulator_mtbdd.c +++ b/src/qsylvan_simulator_mtbdd.c @@ -282,8 +282,8 @@ mtbdd_stack_matrix(BDDVAR k, gate_id_t gateid) res = mtbdd_makenode(s, low, high); // Propagate common factor on previous root amp to new root amp - // AMP new_root_amp = wgt_mul(AADD_WEIGHT(below), AADD_WEIGHT(res)); - // res = aadd_bundle(AADD_TARGET(res), new_root_amp); + // AMP new_root_amp = wgt_mul(EVBDD_WEIGHT(below), EVBDD_WEIGHT(res)); + // res = evbdd_bundle(EVBDD_TARGET(res), new_root_amp); return res; } */ diff --git a/src/sylvan.h b/src/sylvan.h index 693502a..564fdd7 100644 --- a/src/sylvan.h +++ b/src/sylvan.h @@ -61,7 +61,7 @@ namespace sylvan { #include #ifndef __cplusplus -#include // (need this here but issue w/ including in C++) +#include // (need this here but issue w/ including in C++) #endif #include diff --git a/src/sylvan_aadd.c b/src/sylvan_aadd.c deleted file mode 100644 index 53a51bd..0000000 --- a/src/sylvan_aadd.c +++ /dev/null @@ -1,1329 +0,0 @@ -/* - * Copyright 2011-2016 Formal Methods and Tools, University of Twente - * Copyright 2016-2017 Tom van Dijk, Johannes Kepler University Linz - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include -#include -#include - -static int granularity = 1; // operation cache access granularity - - -bool larger_wgt_indices; -int weight_norm_strat; -AADD_WGT (*normalize_weights)(AADD_WGT *, AADD_WGT *); - -/*************************************/ - -/** - * Most of this gc code is copy-paste from sylvan_mtbdd.c, however because the - * bit structure of BDDs and AADDs are a bit different we can't use the mtbdd - * code directly. Since the way sylvan_mtbdd/sylvan_common/sylvan_table are - * structured we need to copy-paste a few more functions/variables than we - * actually change. - */ - -/* - * Recursively mark AADD nodes as 'in use'. - * This is really the only gc function which is different for AADDs vs MTBDDs. - */ -VOID_TASK_IMPL_1(aadd_gc_mark_rec, AADD, a) -{ - if (AADD_TARGET(a) == AADD_TERMINAL) return; - - if (llmsset_mark(nodes, AADD_TARGET(a))) { - aaddnode_t n = AADD_GETNODE(AADD_TARGET(a)); - SPAWN(aadd_gc_mark_rec, aaddnode_getptrlow(n)); - CALL(aadd_gc_mark_rec, aaddnode_getptrhigh(n)); - SYNC(aadd_gc_mark_rec); - } -} - -/** - * External references - */ -refs_table_t aadd_refs; -refs_table_t aadd_protected; -static int aadd_protected_created = 0; - -void -aadd_protect(AADD *a) -{ - if (!aadd_protected_created) { - // In C++, sometimes mtbdd_protect is called before Sylvan is initialized. Just create a table. - protect_create(&aadd_protected, 4096); - aadd_protected_created = 1; - } - protect_up(&aadd_protected, (size_t)a); -} - -void -aadd_unprotect(AADD *a) -{ - if (aadd_protected.refs_table != NULL) protect_down(&aadd_protected, (size_t)a); -} - -size_t -aadd_count_protected() -{ - return protect_count(&aadd_protected); -} - -/* Called during garbage collection */ -VOID_TASK_0(aadd_gc_mark_external_refs) -{ - // iterate through refs hash table, mark all found - size_t count=0; - uint64_t *it = refs_iter(&aadd_refs, 0, aadd_refs.refs_size); - while (it != NULL) { - SPAWN(aadd_gc_mark_rec, refs_next(&aadd_refs, &it, aadd_refs.refs_size)); - count++; - } - while (count--) { - SYNC(aadd_gc_mark_rec); - } -} - -/* Called during garbage collection */ -VOID_TASK_0(aadd_gc_mark_protected) -{ - // iterate through refs hash table, mark all found - size_t count=0; - uint64_t *it = protect_iter(&aadd_protected, 0, aadd_protected.refs_size); - while (it != NULL) { - AADD *to_mark = (AADD*)protect_next(&aadd_protected, &it, aadd_protected.refs_size); - SPAWN(aadd_gc_mark_rec, *to_mark); - count++; - } - while (count--) { - SYNC(aadd_gc_mark_rec); - } -} - -/* Infrastructure for internal markings */ -typedef struct aadd_refs_task -{ - Task *t; - void *f; -} *aadd_refs_task_t; - -typedef struct aadd_refs_internal -{ - const AADD **pbegin, **pend, **pcur; - AADD *rbegin, *rend, *rcur; - aadd_refs_task_t sbegin, send, scur; -} *aadd_refs_internal_t; - -DECLARE_THREAD_LOCAL(aadd_refs_key, aadd_refs_internal_t); - -VOID_TASK_2(aadd_refs_mark_p_par, const AADD**, begin, size_t, count) -{ - if (count < 32) { - while (count) { - aadd_gc_mark_rec(**(begin++)); - count--; - } - } else { - SPAWN(aadd_refs_mark_p_par, begin, count / 2); - CALL(aadd_refs_mark_p_par, begin + (count / 2), count - count / 2); - SYNC(aadd_refs_mark_p_par); - } -} - -VOID_TASK_2(aadd_refs_mark_r_par, AADD*, begin, size_t, count) -{ - if (count < 32) { - while (count) { - aadd_gc_mark_rec(*begin++); - count--; - } - } else { - SPAWN(aadd_refs_mark_r_par, begin, count / 2); - CALL(aadd_refs_mark_r_par, begin + (count / 2), count - count / 2); - SYNC(aadd_refs_mark_r_par); - } -} - -VOID_TASK_2(aadd_refs_mark_s_par, aadd_refs_task_t, begin, size_t, count) -{ - if (count < 32) { - while (count > 0) { - Task *t = begin->t; - if (!TASK_IS_STOLEN(t)) return; - if (t->f == begin->f && TASK_IS_COMPLETED(t)) { - aadd_gc_mark_rec(*(AADD*)TASK_RESULT(t)); - } - begin += 1; - count -= 1; - } - } else { - if (!TASK_IS_STOLEN(begin->t)) return; - SPAWN(aadd_refs_mark_s_par, begin, count / 2); - CALL(aadd_refs_mark_s_par, begin + (count / 2), count - count / 2); - SYNC(aadd_refs_mark_s_par); - } -} - -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); - 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); -} - -/* Called during garbage collection */ -VOID_TASK_0(aadd_refs_mark) -{ - TOGETHER(aadd_refs_mark_task); -} - -VOID_TASK_0(aadd_refs_init_task) -{ - aadd_refs_internal_t s = (aadd_refs_internal_t)malloc(sizeof(struct aadd_refs_internal)); - s->pcur = s->pbegin = (const AADD**)malloc(sizeof(AADD*) * 1024); - s->pend = s->pbegin + 1024; - s->rcur = s->rbegin = (AADD*)malloc(sizeof(AADD) * 1024); - s->rend = s->rbegin + 1024; - s->scur = s->sbegin = (aadd_refs_task_t)malloc(sizeof(struct aadd_refs_task) * 1024); - s->send = s->sbegin + 1024; - SET_THREAD_LOCAL(aadd_refs_key, s); -} - -VOID_TASK_0(aadd_refs_init) -{ - INIT_THREAD_LOCAL(aadd_refs_key); - TOGETHER(aadd_refs_init_task); - sylvan_gc_add_mark(TASK(aadd_refs_mark)); -} - -VOID_TASK_0(aadd_refs_cleanup_task) -{ - LOCALIZE_THREAD_LOCAL(aadd_refs_key, aadd_refs_internal_t); - free(aadd_refs_key->pbegin); - free(aadd_refs_key->rbegin); - free(aadd_refs_key->sbegin); - free(aadd_refs_key); -} - -/** - * Called by aadd_quit. Cleans up the (thread local) malloc'ed aadd_refs_key. - * - * NOTE: this cleanup isn't done in sylvan_mtbdd.c, but not doing this causes - * memory leaks when calling initializing and quiting Sylvan multiple times - * during the same program run. - */ -VOID_TASK_0(aadd_refs_cleanup) -{ - TOGETHER(aadd_refs_cleanup_task); -} - -void -aadd_refs_ptrs_up(aadd_refs_internal_t aadd_refs_key) -{ - size_t cur = aadd_refs_key->pcur - aadd_refs_key->pbegin; - size_t size = aadd_refs_key->pend - aadd_refs_key->pbegin; - aadd_refs_key->pbegin = (const AADD**)realloc(aadd_refs_key->pbegin, sizeof(AADD*) * size * 2); - aadd_refs_key->pcur = aadd_refs_key->pbegin + cur; - aadd_refs_key->pend = aadd_refs_key->pbegin + (size * 2); -} - -AADD __attribute__((noinline)) -aadd_refs_refs_up(aadd_refs_internal_t aadd_refs_key, AADD res) -{ - long size = aadd_refs_key->rend - aadd_refs_key->rbegin; - aadd_refs_key->rbegin = (AADD*)realloc(aadd_refs_key->rbegin, sizeof(AADD) * size * 2); - aadd_refs_key->rcur = aadd_refs_key->rbegin + size; - aadd_refs_key->rend = aadd_refs_key->rbegin + (size * 2); - return res; -} - -void __attribute__((noinline)) -aadd_refs_tasks_up(aadd_refs_internal_t aadd_refs_key) -{ - long size = aadd_refs_key->send - aadd_refs_key->sbegin; - aadd_refs_key->sbegin = (aadd_refs_task_t)realloc(aadd_refs_key->sbegin, sizeof(struct aadd_refs_task) * size * 2); - aadd_refs_key->scur = aadd_refs_key->sbegin + size; - aadd_refs_key->send = aadd_refs_key->sbegin + (size * 2); -} - -void __attribute__((unused)) -aadd_refs_pushptr(const AADD *ptr) -{ - LOCALIZE_THREAD_LOCAL(aadd_refs_key, aadd_refs_internal_t); - *aadd_refs_key->pcur++ = ptr; - if (aadd_refs_key->pcur == aadd_refs_key->pend) aadd_refs_ptrs_up(aadd_refs_key); -} - -void __attribute__((unused)) -aadd_refs_popptr(size_t amount) -{ - LOCALIZE_THREAD_LOCAL(aadd_refs_key, aadd_refs_internal_t); - aadd_refs_key->pcur -= amount; -} - -AADD __attribute__((unused)) -aadd_refs_push(AADD a) -{ - LOCALIZE_THREAD_LOCAL(aadd_refs_key, aadd_refs_internal_t); - *(aadd_refs_key->rcur++) = a; - if (aadd_refs_key->rcur == aadd_refs_key->rend) return aadd_refs_refs_up(aadd_refs_key, a); - else return a; -} - -void __attribute__((unused)) -aadd_refs_pop(long amount) -{ - LOCALIZE_THREAD_LOCAL(aadd_refs_key, aadd_refs_internal_t); - aadd_refs_key->rcur -= amount; -} - -void -aadd_refs_spawn(Task *t) -{ - LOCALIZE_THREAD_LOCAL(aadd_refs_key, aadd_refs_internal_t); - aadd_refs_key->scur->t = t; - aadd_refs_key->scur->f = t->f; - aadd_refs_key->scur += 1; - if (aadd_refs_key->scur == aadd_refs_key->send) aadd_refs_tasks_up(aadd_refs_key); -} - -AADD -aadd_refs_sync(AADD result) -{ - LOCALIZE_THREAD_LOCAL(aadd_refs_key, aadd_refs_internal_t); - aadd_refs_key->scur -= 1; - return result; -} - -/************************************/ - - - - - -/**************************************************/ - -static int auto_gc_wgt_table = 1; -static double wgt_table_gc_thres = 0.5; - -void -aadd_set_auto_gc_wgt_table(bool enabled) -{ - auto_gc_wgt_table = enabled; -} - -void -aadd_set_gc_wgt_table_thres(double fraction_filled) -{ - wgt_table_gc_thres = fraction_filled; -} - -double -aadd_get_gc_wgt_table_thres() -{ - return wgt_table_gc_thres; -} - - -void -aadd_gc_wgt_table() -{ - // gc edge weight table and keep wgts of protected AADDs (and update those) - // 1. Create new edge weight table table - wgt_table_gc_init_new(init_wgt_table_entries); - - // 2. Fill new table with wgts in protected AADDs and update those AADDs - uint64_t *it = protect_iter(&aadd_protected, 0, aadd_protected.refs_size); - while (it != NULL) { - AADD *to_protect_wgts = (AADD*)protect_next(&aadd_protected, &it, aadd_protected.refs_size); - if (to_protect_wgts != NULL) { - *to_protect_wgts = _fill_new_wgt_table(*to_protect_wgts); - } - } - - // 3. Delete old edge weight table - wgt_table_gc_delete_old(); - - // 4. Any cache we migh have is now invalid because the same edge weights - // might now have different indices in the edge weight table - sylvan_clear_cache(); -} - -TASK_IMPL_1(AADD, _fill_new_wgt_table, AADD, a) -{ - // Check cache - AADD res; - bool cachenow = 1; - if (cachenow) { - if (cache_get3(CACHE_AADD_CLEAN_WGT_TABLE, 0LL, a, 0LL, &res)) { - return res; - } - } - - // Move weight from old to new table, get new index - AADD_WGT new_wgt = wgt_table_gc_keep(AADD_WEIGHT(a)); - a = aadd_bundle(AADD_TARGET(a), new_wgt); - - // If terminal, return - if (AADD_TARGET(a) == AADD_TERMINAL) return a; - - // Recursive for children - AADD low, high; - aaddnode_t n = AADD_GETNODE(AADD_TARGET(a)); - aaddnode_getchilderen(n, &low, &high); - aadd_refs_spawn(SPAWN(_fill_new_wgt_table, high)); - low = CALL(_fill_new_wgt_table, low); - aadd_refs_push(low); - high = aadd_refs_sync(SYNC(_fill_new_wgt_table)); - aadd_refs_pop(1); - - // We don't need to use the 'aadd_makenode()' function which normalizes the - // weights, because the AADD doesn't actually change, only the WGT indices, - // but none of the actual values. - AADD_TARG ptr = _aadd_makenode(aaddnode_getvar(n), AADD_TARGET(low), AADD_TARGET(high), AADD_WEIGHT(low), AADD_WEIGHT(high)); - - // Put in cache, return - res = aadd_bundle(ptr, new_wgt); - if (cachenow) cache_put3(CACHE_AADD_CLEAN_WGT_TABLE, 0LL, a, 0LL, res); - return res; -} - -bool -aadd_test_gc_wgt_table() -{ - uint64_t entries = wgt_table_entries_estimate(); - uint64_t size = sylvan_get_edge_weight_table_size(); - return ( ((double)entries / (double)size) > wgt_table_gc_thres ); -} - -/*************************************************/ - - - - - -/**************************************************************/ - -/** - * Initialize and quit functions - */ -static int aadd_initialized = 0; - -static void -aadd_quit() -{ - refs_free(&aadd_refs); - if (aadd_protected_created) { - protect_free(&aadd_protected); - aadd_protected_created = 0; - } - RUN(aadd_refs_cleanup); - aadd_initialized = 0; - sylvan_edge_weights_free(); -} - -void -sylvan_init_aadd(size_t min_wgt_tablesize, size_t max_wgt_tablesize, - double wgt_tab_tolerance, int edge_weigth_backend, - int norm_strat, void *init_wgt_tab_entries) -{ - if (aadd_initialized) return; - aadd_initialized = 1; - - int index_size = (int) ceil(log2(max_wgt_tablesize)); - if (edge_weigth_backend == REAL_TUPLES_HASHMAP || edge_weigth_backend == REAL_TREE) - index_size = index_size*2; - if (index_size > 33) { - fprintf(stderr,"max edge weight storage size is 2^33 (2^16 when using storing r and i seperately)\n"); - exit(1); - } - if (index_size > 23) larger_wgt_indices = true; - else larger_wgt_indices = false; - - sylvan_register_quit(aadd_quit); - sylvan_gc_add_mark(TASK(aadd_gc_mark_external_refs)); - sylvan_gc_add_mark(TASK(aadd_gc_mark_protected)); - - refs_create(&aadd_refs, 1024); - if (!aadd_protected_created) { - protect_create(&aadd_protected, 4096); - aadd_protected_created = 1; - } - - // TODO: pass edge weight type to sylvan_init_aadd - if (min_wgt_tablesize > max_wgt_tablesize) min_wgt_tablesize = max_wgt_tablesize; - sylvan_init_edge_weights(min_wgt_tablesize, max_wgt_tablesize, - wgt_tab_tolerance, WGT_COMPLEX_128, - edge_weigth_backend); - - init_wgt_table_entries = init_wgt_tab_entries; - if (init_wgt_table_entries != NULL) { - init_wgt_table_entries(); - } - - weight_norm_strat = norm_strat; - switch (norm_strat) - { - 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; - default: - printf("Edge weight normalization strategy not recognized\n"); - exit(1); - break; - } - - RUN(aadd_refs_init); -} - -void -sylvan_init_aadd_defaults(size_t min_wgt_tablesize, size_t max_wgt_tablesize) -{ - sylvan_init_aadd(min_wgt_tablesize, max_wgt_tablesize, -1, COMP_HASHMAP, NORM_LOW, NULL); -} - - -void -aadd_set_caching_granularity(int g) -{ - granularity = g; -} - -/*************************************************************/ - - - - - -/****************************************************/ - -AADD_WGT -aadd_getvalue(AADD a, bool* path) -{ - AADD_WGT res = AADD_ONE; - AADD low, high; - for (;;) { - res = wgt_mul(res, AADD_WEIGHT(a)); - - // if the current edge is pointing to the terminal, we're done. - if (AADD_TARGET(a) == AADD_TERMINAL) break; - - // now we need to choose low or high edge of next node - aaddnode_t node = AADD_GETNODE(AADD_TARGET(a)); - BDDVAR var = aaddnode_getvar(node); - aaddnode_getchilderen(node, &low, &high); - - // Condition low/high choice on basis state vector[var] - a = (path[var] == 0) ? low : high; - } - - return res; -} - -static void -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); - } -} - -static void -norm_commuting_cache_key(AADD a, AADD b, AADD *x, AADD *y) -{ - if (a < b) { - *x = a; - *y = b; - } - else { - *x = b; - *y = a; - } -} - -TASK_IMPL_2(AADD, aadd_plus, AADD, a, AADD, b) -{ - // Trivial cases - 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; - if (AADD_TARGET(a) != AADD_TERMINAL) { - aaddnode_t node = AADD_GETNODE(AADD_TARGET(a)); - var_a = aaddnode_getvar(node); - } - if (AADD_TARGET(b) != AADD_TERMINAL) { - aaddnode_t node = AADD_GETNODE(AADD_TARGET(b)); - var_b = aaddnode_getvar(node); - } - - // For both a and b, get children of node with var=top{topvar(a),topvar(b)} - aadd_get_topvar(a, var_b, &topvar, &low_a, &high_a); - aadd_get_topvar(b, var_a, &topvar, &low_b, &high_b); - - // Base/terminal case: same target and same variable - if(AADD_TARGET(a) == AADD_TARGET(b) && var_a == var_b){ - AADD_WGT sum = wgt_add(AADD_WEIGHT(a), AADD_WEIGHT(b)); - res = aadd_bundle(AADD_TARGET(a), sum); - return res; - } - - // Check cache - AADD x, y; - 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)) { - sylvan_stats_count(AADD_PLUS_CACHED); - return res; - } - } - - // If not base/terminal case, pass edge weight of current edge down - AADD_WGT wgt_la, wgt_ha, wgt_lb, wgt_hb; - wgt_la = wgt_mul(AADD_WEIGHT(a), AADD_WEIGHT(low_a)); - 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_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_refs_spawn(SPAWN(aadd_plus, high_a, high_b)); - 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); - if (cachenow) { - if (cache_put3(CACHE_AADD_PLUS, sylvan_false, x, y, res)) - sylvan_stats_count(AADD_PLUS_CACHEDPUT); - } - return res; -} - - - -/* Wrapper for matrix vector multiplication. */ -TASK_IMPL_3(AADD, aadd_matvec_mult, AADD, mat, AADD, vec, BDDVAR, nvars) -{ - aadd_do_before_mult(&mat, &vec); - aadd_refs_push(mat); aadd_refs_push(vec); - AADD res = CALL(aadd_matvec_mult_rec, mat, vec, nvars, 0); - aadd_refs_pop(2); - return res; -} - -/* Wrapper for matrix vector multiplication. */ -TASK_IMPL_3(AADD, aadd_matmat_mult, AADD, a, AADD, b, BDDVAR, nvars) -{ - aadd_do_before_mult(&a, &b); - aadd_refs_push(a); aadd_refs_push(b); - AADD res = CALL(aadd_matmat_mult_rec, a, b, nvars, 0); - aadd_refs_pop(2); - return res; -} - -TASK_IMPL_4(AADD, aadd_matvec_mult_rec, AADD, mat, AADD, vec, BDDVAR, nvars, BDDVAR, nextvar) -{ - // Trivial case: either one is all 0 - if (AADD_WEIGHT(mat) == AADD_ZERO || AADD_WEIGHT(vec) == AADD_ZERO) - return aadd_bundle(AADD_TERMINAL, AADD_ZERO); - - // Terminal case: past last variable - if (nextvar == nvars) { - assert(AADD_TARGET(mat) == AADD_TERMINAL); - assert(AADD_TARGET(vec) == AADD_TERMINAL); - AADD_WGT prod = wgt_mul(AADD_WEIGHT(mat), AADD_WEIGHT(vec)); - return aadd_bundle(AADD_TERMINAL, prod); - } - - sylvan_gc_test(); - - // Check cache - AADD res; - bool cachenow = ((nextvar % granularity) == 0); - if (cachenow) { - if (cache_get3(CACHE_AADD_MATVEC_MULT, nextvar, AADD_TARGET(mat), AADD_TARGET(vec), &res)) { - sylvan_stats_count(AADD_MULT_CACHED); - // 6. multiply w/ product of root weights - AADD_WGT prod = wgt_mul(AADD_WEIGHT(mat), AADD_WEIGHT(vec)); - AADD_WGT new_weight = wgt_mul(prod, AADD_WEIGHT(res)); - res = aadd_bundle(AADD_TARGET(res), new_weight); - return res; - } - } - - // Recursive multiplication - // 1. get relevant nodes for both AADDs - BDDVAR var; - AADD vec_low, vec_high, mat_low, mat_high, u00, u10, u01, u11; - aadd_get_topvar(vec, nextvar, &var, &vec_low, &vec_high); - aadd_get_topvar(mat, 2*nextvar, &var, &mat_low, &mat_high); - aadd_get_topvar(mat_low, 2*nextvar+1, &var, &u00, &u10); - 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))); - - // 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; // [GC refs stack] - aadd_refs_spawn(SPAWN(aadd_matvec_mult_rec, u00, vec_low, nvars, nextvar+1)); // fork 1 - aadd_refs_spawn(SPAWN(aadd_matvec_mult_rec, u10, vec_low, nvars, nextvar+1)); // fork 2 - aadd_refs_spawn(SPAWN(aadd_matvec_mult_rec, u01, vec_high, nvars, nextvar+1)); // fork 3 - res_high11 = aadd_refs_push(CALL(aadd_matvec_mult_rec, u11, vec_high, nvars, nextvar+1));// [res_high11] - res_high01 = aadd_refs_sync(SYNC(aadd_matvec_mult_rec)); // join 3 [res_high11] - aadd_refs_pop(1); // [] - AADD res_high = aadd_refs_push(aadd_makenode(nextvar, res_high01, res_high11)); // [res_high] - res_low10 = aadd_refs_push(aadd_refs_sync(SYNC(aadd_matvec_mult_rec))); // join 2 [res_low10,res_high] - res_low00 = aadd_refs_sync(SYNC(aadd_matvec_mult_rec)); // join 1 [res_low10,res_high] - aadd_refs_pop(1); // [res_high] - AADD res_low = aadd_refs_push(aadd_makenode(nextvar, res_low00, res_low10)); // [res_low,res_high] - - // 4. add resulting AADDs - res = CALL(aadd_plus, res_low, res_high); // [res_low,res_high] - aadd_refs_pop(2); // [] - - // Insert in cache (before multiplication w/ root weights) - if (cachenow) { - if (cache_put3(CACHE_AADD_MATVEC_MULT, nextvar, AADD_TARGET(mat), AADD_TARGET(vec), res)) - sylvan_stats_count(AADD_MULT_CACHEDPUT); - } - - // 5. multiply w/ product of root weights - AADD_WGT prod = wgt_mul(AADD_WEIGHT(mat), AADD_WEIGHT(vec)); - AADD_WGT new_weight = wgt_mul(prod, AADD_WEIGHT(res)); - res = aadd_bundle(AADD_TARGET(res), new_weight); - - return res; -} - -TASK_IMPL_4(AADD, aadd_matmat_mult_rec, AADD, a, AADD, b, BDDVAR, nvars, BDDVAR, nextvar) -{ - // Trivial case: either one is all 0 - if (AADD_WEIGHT(a) == AADD_ZERO || AADD_WEIGHT(b) == AADD_ZERO) - return aadd_bundle(AADD_TERMINAL, AADD_ZERO); - - // Terminal case: past last variable - if (nextvar == nvars) { - assert(AADD_TARGET(a) == AADD_TERMINAL); - assert(AADD_TARGET(b) == AADD_TERMINAL); - AADD_WGT prod = wgt_mul(AADD_WEIGHT(a), AADD_WEIGHT(b)); - return aadd_bundle(AADD_TERMINAL, prod); - } - - sylvan_gc_test(); - - // Check cache - AADD res; - bool cachenow = ((nextvar % granularity) == 0); - if (cachenow) { - if (cache_get3(CACHE_AADD_MATMAT_MULT, nextvar, AADD_TARGET(a), AADD_TARGET(b), &res)) { - sylvan_stats_count(AADD_MULT_CACHED); - // 7. 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); - return res; - } - } - - // Recursive multiplication - // 1. get relevant nodes for both AADDs - BDDVAR var; - AADD a_low, a_high, a00, a10, a01, a11, b_low, b_high, b00, b10, b01, b11; - aadd_get_topvar(a, 2*nextvar, &var, &a_low, &a_high); - aadd_get_topvar(b, 2*nextvar, &var, &b_low, &b_high); - aadd_get_topvar(a_low, 2*nextvar+1, &var, &a00, &a10); - aadd_get_topvar(a_high,2*nextvar+1, &var, &a01, &a11); - aadd_get_topvar(b_low, 2*nextvar+1, &var, &b00, &b10); - 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))); - - // 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; // [GC refs stack] - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a00, b00, nvars, nextvar+1)); // fork 1 - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a10, b00, nvars, nextvar+1)); // fork 2 - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a00, b01, nvars, nextvar+1)); // fork 3 - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a10, b01, nvars, nextvar+1)); // fork 4 - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a01, b10, nvars, nextvar+1)); // fork 5 - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a11, b10, nvars, nextvar+1)); // fork 6 - aadd_refs_spawn(SPAWN(aadd_matmat_mult_rec, a01, b11, nvars, nextvar+1)); // fork 7 - a11_b11 = aadd_refs_push(CALL(aadd_matmat_mult_rec, a11, b11, nvars, nextvar+1)); // [a11_b11] - a01_b11 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // join 7 [a11_b11] - aadd_refs_pop(1); // [] - AADD rh2 = aadd_refs_push(aadd_makenode(2*nextvar+1, a01_b11, a11_b11)); // [rh2] - a11_b10 = aadd_refs_push(aadd_refs_sync(SYNC(aadd_matmat_mult_rec))); // join 6 [a11_b10,rh2] - a01_b10 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // join 5 [a11_b10,rh2] - aadd_refs_pop(1); // [rh2] - AADD lh2 = aadd_refs_push(aadd_makenode(2*nextvar+1, a01_b10, a11_b10)); // [lh2,rh2] - a10_b01 = aadd_refs_push(aadd_refs_sync(SYNC(aadd_matmat_mult_rec))); // join 4 [b10_b01,lh2,rh2] - a00_b01 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // join 3 [b10_b01,lh2,rh2] - aadd_refs_pop(1); // [lh2,rh2] - AADD rh1 = aadd_refs_push(aadd_makenode(2*nextvar+1, a00_b01, a10_b01)); // [rh1,lh2,rh2] - a10_b00 = aadd_refs_push(aadd_refs_sync(SYNC(aadd_matmat_mult_rec))); // join 2 [b10_b00,rh1,lh2,rh2] - a00_b00 = aadd_refs_sync(SYNC(aadd_matmat_mult_rec)); // join 1 [b10_b00,rh1,lh2,rh2] - aadd_refs_pop(1); // [rh1,lh2,rh2] - AADD lh1 = aadd_refs_push(aadd_makenode(2*nextvar+1, a00_b00, a10_b00)); // [lh1,rh1,lh2,rh2] - - // 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); // [rh,lh1,rh1,lh2,rh2] - lh = aadd_refs_sync(SYNC(aadd_plus)); // [rh,lh1,rh1,lh2,rh2] - aadd_refs_pop(5); // [] - - // 5. put left and right halves of matix together - res = aadd_makenode(2*nextvar, lh, rh); - - // Insert in cache - if (cachenow) { - if (cache_put3(CACHE_AADD_MATMAT_MULT, nextvar, AADD_TARGET(a), AADD_TARGET(b), res)) - sylvan_stats_count(AADD_MULT_CACHEDPUT); - } - - // 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); - - 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), wgt_conj(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, wgt_conj(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 (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, wgt_conj(AADD_WEIGHT(b))); - return res; -} - -AADD -aadd_increase_all_vars(AADD a, int k) -{ - if (AADD_TARGET(a) == AADD_TERMINAL) { - return a; - } - - // Check cache - AADD res; - if (cache_get3(CACHE_AADD_INC_VARS, AADD_TARGET(a), k, 0, &res)) { - return aadd_bundle(res, AADD_WEIGHT(a)); - } - - // Get node info - AADD low, high; - aaddnode_t node = AADD_GETNODE(AADD_TARGET(a)); - aaddnode_getchilderen(node, &low, &high); - BDDVAR curvar = aaddnode_getvar(node); - - // Recursive apply to children (TODO: lace?) - low = aadd_increase_all_vars(low, k); - high = aadd_increase_all_vars(high, k); - res = aadd_makenode(curvar+k, low, high); - - // We assume the input AADDs are already normalized in terms of edge weights - // so we expect no normalization is needed - assert(AADD_WEIGHT(res) == AADD_ONE); - - // Put res (ptr) in cache and return - cache_put3(CACHE_AADD_INC_VARS, AADD_TARGET(a), k, 0, AADD_TARGET(res)); - return aadd_bundle(AADD_TARGET(res), AADD_WEIGHT(a)); -} - -AADD -aadd_replace_terminal(AADD a, AADD_TARG b) -{ - if (AADD_TARGET(a) == AADD_TERMINAL) { - return aadd_bundle(b, AADD_WEIGHT(a)); - } - - // Check cache - AADD res; - if (cache_get3(CACHE_AADD_REPLACE_TERMINAL, AADD_TARGET(a), b, 0, &res)) { - return aadd_bundle(res, AADD_WEIGHT(a)); - } - - // Get node info - AADD low, high; - aaddnode_t node = AADD_GETNODE(AADD_TARGET(a)); - aaddnode_getchilderen(node, &low, &high); - BDDVAR var = aaddnode_getvar(node); - - // Recursive apply to children and makenode (TODO: lace?) - low = aadd_replace_terminal(low, b); - high = aadd_replace_terminal(high, b); - res = aadd_makenode(var, low, high); - - // We assume the input AADDs are already normalized in terms of edge weights - // so we expect no normalization is needed - assert(AADD_WEIGHT(res) == AADD_ONE); - - // Put res (ptr) in cache and return - cache_put3(CACHE_AADD_REPLACE_TERMINAL, AADD_TARGET(a), b, 0, AADD_TARGET(res)); - return aadd_bundle(AADD_TARGET(res), AADD_WEIGHT(a)); -} - -AADD -aadd_tensor_prod(AADD a, AADD b, BDDVAR nvars_a) -{ - // Shift all vars of 'b' by 'nvars_a' - b = aadd_increase_all_vars(b, nvars_a); - - // Stack 'a' on top of 'b' (and multiply root edge of 'a' with that of 'b') - AADD res = aadd_replace_terminal(a, AADD_TARGET(b)); - AADD_WGT new_weight = wgt_mul(AADD_WEIGHT(res), AADD_WEIGHT(b)); - res = aadd_bundle(AADD_TARGET(res), new_weight); - - return res; -} - -/***************************************************/ - - - - - -/******************************************************/ - - -/** - * Helper function for recursive unmarking - */ -static void -aadd_unmark_rec(AADD a) -{ - if (AADD_TARGET(a) == AADD_TERMINAL) return; - aaddnode_t n = AADD_GETNODE(AADD_TARGET(a)); - if (!aaddnode_getmark(n)) return; - aaddnode_setmark(n, 0); - aadd_unmark_rec(aaddnode_getptrlow(n)); - aadd_unmark_rec(aaddnode_getptrhigh(n)); -} - -/** - * Counts nodes in the AADD by marking them. - */ -static uint64_t -aadd_nodecount_mark(AADD a) -{ - if (AADD_TARGET(a) == AADD_TERMINAL) return 0; // don't (repeat) count terminal - aaddnode_t n = AADD_GETNODE(AADD_TARGET(a)); - if (aaddnode_getmark(n)) return 0; - aaddnode_setmark(n, 1); - return 1 + aadd_nodecount_mark(aaddnode_getptrlow(n)) + aadd_nodecount_mark(aaddnode_getptrhigh(n)); -} - -uint64_t -aadd_countnodes(AADD a) -{ - uint64_t res = aadd_nodecount_mark(a) + 1; // (+ 1 for terminal "node") - aadd_unmark_rec(a); - return res; -} - -/*****************************************************/ - - - - - -/*****************************************************/ - -/** - * Pretty prints the information contained in `n`. - */ -static void aaddnode_pprint(aaddnode_t n) -{ - BDDVAR var = aaddnode_getvar(n); - AADD low, high; - aaddnode_getchilderen(n, &low, &high); - printf("[var=%d, low=%" PRIu64 ", high=%" PRIu64 ", ", - var, - AADD_TARGET(low), - AADD_TARGET(high)); - if(AADD_WEIGHT(low) == AADD_ZERO) printf("a=AADD_ZERO, "); - else if(AADD_WEIGHT(high) == AADD_ONE) printf("a=AADD_ONE, "); - else { - printf("a=%" PRIu64 ", ", AADD_WEIGHT(low)); - printf("("); wgt_fprint(stdout, AADD_WEIGHT(low)); printf(")"); - } - if(AADD_WEIGHT(high) == AADD_ZERO) printf("b=AADD_ZERO "); - else if(AADD_WEIGHT(high) == AADD_ONE) printf("b=AADD_ONE, "); - else { - printf("b=%" PRIu64, AADD_WEIGHT(high)); - printf("("); wgt_fprint(stdout, AADD_WEIGHT(high)); printf(")"); - } - printf("]\n"); -} - -void -_print_aadd(AADD a) -{ - if(AADD_TARGET(a) != AADD_TERMINAL){ - aaddnode_t node = AADD_GETNODE(AADD_TARGET(a)); - if(!aaddnode_getmark(node)){ - aaddnode_setmark(node, 1); - printf("%" PRIu64 "\t", AADD_TARGET(a)); - aaddnode_pprint(node); - AADD low, high; - aaddnode_getchilderen(node, &low, &high); - _print_aadd(low); - _print_aadd(high); - } - } -} - -void -aadd_printnodes(AADD a) -{ - printf("root edge: %" PRIu64 ", %" PRIu64 " = ",AADD_TARGET(a), AADD_WEIGHT(a)); - wgt_fprint(stdout, AADD_WEIGHT(a)); - printf("\n"); - _print_aadd(a); - aadd_unmark_rec(a); -} - -static void -aadd_fprintdot_edge_label(FILE *out, AADD_WGT w) -{ - fprintf(out, ", label=\""); - if (w == AADD_ONE) {} - else if (w == AADD_ZERO) { fprintf(out, "0"); } - else if (w == AADD_MIN_ONE) { fprintf(out, "-1"); } - else { wgt_fprint(out, w); } - fprintf(out, "\""); -} - -static void -aadd_fprintdot_rec(FILE *out, AADD a, bool draw_zeros) -{ - // terminal node - if(AADD_TARGET(a) == AADD_TERMINAL) return; - - aaddnode_t n = AADD_GETNODE(AADD_TARGET(a)); - if (aaddnode_getmark(n)) return; - aaddnode_setmark(n, 1); - - // add this node - fprintf(out, "%" PRIu64 " [label=\"%" PRIu32 "\"];\n", - AADD_TARGET(a), aaddnode_getvar(n)); - - - // children of this node - AADD low, high; - aaddnode_getchilderen(n, &low, &high); - aadd_fprintdot_rec(out, low, draw_zeros); - aadd_fprintdot_rec(out, high, draw_zeros); - - // add edge from this node to each child (unless weight 0) - if (draw_zeros || AADD_WEIGHT(low) != AADD_ZERO) { - fprintf(out, "%" PRIu64 " -> %" PRIu64 " [style=dashed", - AADD_TARGET(a), AADD_TARGET(low)); - aadd_fprintdot_edge_label(out, AADD_WEIGHT(low)); - fprintf(out, "];\n"); - } - if (draw_zeros || AADD_WEIGHT(high) != AADD_ZERO) { - fprintf(out, "%" PRIu64 " -> %" PRIu64 " [style=solid", - AADD_TARGET(a), AADD_TARGET(high)); - aadd_fprintdot_edge_label(out, AADD_WEIGHT(high)); - fprintf(out, "];\n"); - } -} - -void -aadd_fprintdot(FILE *out, AADD a, bool draw_zeros) -{ - fprintf(out, "digraph \"DD\" {\n"); - fprintf(out, "center = true;\n"); - fprintf(out, "edge [dir=forward];\n"); - fprintf(out, "root [style=invis];\n"); - fprintf(out, "root -> %" PRIu64 " [style=solid", AADD_TARGET(a)); - aadd_fprintdot_edge_label(out, AADD_WEIGHT(a)); - fprintf(out, "];\n"); - - // terminal node - fprintf(out, "%" PRIu64 " [shape=box, label=\"T\"];\n", AADD_TERMINAL); - - // recursively add nodes - aadd_fprintdot_rec(out, a, draw_zeros); - aadd_unmark_rec(a); - - fprintf(out, "}\n"); -} - -/****************************************************/ - - - - - -/*****************************************************************/ - -bool -aadd_equivalent(AADD a, AADD b, int n, bool exact, bool verbose) -{ - bool has_next = true; - AADD_WGT wgt_a, wgt_b; - bool x[n]; - for(int k=0; k= nvars || var < nextvar) return false; - - // Check cache - uint64_t res; - bool cachenow = ((var % granularity) == 0); - if (cachenow) { - if (cache_get3(CACHE_AADD_IS_ORDERED, AADD_TARGET(a), 0, 0, &res)) { - return (bool) res; - } - } - - // Recursive calls - bool res_low, res_high; - var++; - res_low = aadd_is_ordered_rec(low, var, nvars); - res_high = aadd_is_ordered_rec(high, var, nvars); - var--; - res = (res_low && res_high); - - // Put res in cache and return - if (cachenow) cache_put3(CACHE_AADD_IS_ORDERED, AADD_TARGET(a), 0, 0, res); - return res; -} - -bool -_next_bitstring(bool *x, int n) -{ - // binary add 1 - bool success = false; - for(int k=0; k=0; k--) printf("%d", x[k]); - else - for(int k=0; k= 0; i--) { - if (x[i] == 1) res |= k; - k = k<<1; - } - } - else { - for (int i = 0; i < n; i++) { - if (x[i] == 1) res |= k; - k = k<<1; - } - } - return res; -} - -bool * -int_to_bitarray(uint64_t n, int length, bool MSB_first) -{ - if (length <= 0) length = (int) ceil(log2(n)); - bool *res = malloc(sizeof(bool) * length); - if (MSB_first) { - for (int i = length-1; i >= 0; i--) { - res[i] = (n & 1LL); - n = n>>1; - } - } - else { - for (int i = 0; i < length; i++) { - res[i] = (n & 1LL); - n = n>>1; - } - } - return res; -} - -bool -bit_from_int(uint64_t a, uint8_t index) -{ - // assumes index=0 is the LSB - uint64_t mask = 1<>index; - return (bool) res; -} - -void -reverse_bit_array(bool *x, int length) -{ - bool tmp; - for(int i = 0; i<(length/2); i++){ - tmp = x[i]; - x[i] = x[length-i-1]; - x[length-i-1] = tmp; - } -} - -/****************************************************************/ diff --git a/src/sylvan_aadd.h b/src/sylvan_aadd.h deleted file mode 100644 index d34da44..0000000 --- a/src/sylvan_aadd.h +++ /dev/null @@ -1,281 +0,0 @@ -#ifndef SYLVAN_AADD_H -#define SYLVAN_AADD_H - -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -typedef uint64_t AADD; -typedef uint64_t AADD_WGT; // Edge weight -typedef uint64_t AADD_TARG; // Edge target - -static const AADD_TARG AADD_TERMINAL = 1; -static const BDDVAR AADD_INVALID_VAR = UINT8_MAX; - -typedef enum weight_norm_strategy { - NORM_LOW, - NORM_MAX, - NORM_MIN, - NORM_L2, - n_norm_strategies -} weight_norm_strategy_t; - - -/*************************************/ - -VOID_TASK_DECL_1(aadd_gc_mark_rec, AADD); -#define aadd_gc_mark_rec(a) RUN(aadd_gc_mark_rec, a) - -/** - * Store the pointer in the pointers table. - */ -void aadd_protect(AADD* a); - -/** - * Delete the pointer from the pointers table. - */ -void aadd_unprotect(AADD* a); - -/** - * Compute the number of pointers in the pointers table. - */ -size_t aadd_count_protected(void); - -/** - * Push an AADD variable to the pointer reference stack. - * During gc the variable will be inspected and the contents will be marked. - */ -void aadd_refs_pushptr(const AADD *a); - -/** - * Pop the last AADD variables from the pointer reference stack. - */ -void aadd_refs_popptr(size_t amount); - -/** - * Push an AADD to the values reference stack. - * During garbage collection the references AADD will be marked. - */ -AADD aadd_refs_push(AADD a); - -/** - * Pop the last AADDs from the values reference stack. - */ -void aadd_refs_pop(long amount); - -/** - * Push a Task that returns an AADD to the tasks reference stack. - * Usage: aadd_refs_spawn(SPAWN(function, ...)); - */ -void aadd_refs_spawn(Task *t); - -/** - * Pop a Task from the task reference stack. - * Usage: AADD result = aadd_refs_sync(SYNC(function)); - */ -AADD aadd_refs_sync(AADD a); - -/************************************/ - - - - - -/**************************************************/ - -/* enabled by default */ -void aadd_set_auto_gc_wgt_table(bool enabled); -/* default 0.5 */ -void aadd_set_gc_wgt_table_thres(double fraction_filled); -double aadd_get_gc_wgt_table_thres(); -void aadd_gc_wgt_table(); -bool aadd_test_gc_wgt_table(); - -/** - * Recursive function for moving weights from old to new edge weight table. - */ -#define _fill_new_wgt_table(a) (RUN(_fill_new_wgt_table, a)) -TASK_DECL_1(AADD, _fill_new_wgt_table, AADD); - -/*************************************************/ - - - - - -/**************************************************************/ - -/** - * Similar initialization as for MTBDDs + edge weight table init. - * Setting tolerance to -1 uses default tolerance. - * real table: stores 2 real values per edge weight, instead of 1 tuple - * NOTE: this function doesn't currently check if the combination of table - * sizes (edge weight table + node table) works in combination with using - * a real-table or complex-table. - * - init_wgt_tab_entries() is a pointer to a function which is called after gc - * of edge table. This can be used to reinitialize edge weight table values - * outside of any AADD. Can be NULL. - */ -void sylvan_init_aadd(size_t min_wgt_tablesize, size_t max_wgt_tablesize, double wgt_tab_tolerance, int edge_weigth_backend, int norm_strat, void *init_wgt_tab_entries); -void sylvan_init_aadd_defaults(size_t min_wgt_tablesize, size_t max_wgt_tablesize); -void aadd_set_caching_granularity(int granularity); - -/*************************************************************/ - - - - - -/****************************************************/ - -/** - * Get the AADD value corresponding to the given (bool array of length - * nvars(a)). - */ -AADD_WGT aadd_getvalue(AADD a, bool* path); - -/** - * Recursive implementation of vector addition. - */ -#define aadd_plus(a,b) (RUN(aadd_plus,a,b)) -TASK_DECL_2(AADD, aadd_plus, AADD, AADD); - - -/* Computes Mat * |vec> (Wrapper function) */ -#define aadd_matvec_mult(mat,vec,nvars) (RUN(aadd_matvec_mult,mat,vec,nvars)) -TASK_DECL_3(AADD, aadd_matvec_mult, AADD, AADD, BDDVAR); - -/* Computes A*B (note generally AB != BA) (Wrapper function) */ -#define aadd_matmat_mult(a,b,nvars) (RUN(aadd_matmat_mult,a,b,nvars)) -TASK_DECL_3(AADD, aadd_matmat_mult, AADD, AADD, BDDVAR); - -/** - * Recursive implementation of matrix-vector mult and matrix-matrix mult. - */ -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 - * (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); - -/** - * Increases all the variable number in AADD a by k (used for tensor product) - * - * @param a AADD over n vars {j, j+1, ..., j+n-1} (generally j=0) - * - * @return AADD over n vars {j+k, j+k+1, ..., j+k+n-1} - */ -AADD aadd_increase_all_vars(AADD a, int k); - -/* Replace the terminal node in a with b (effectively stacks a and b) -* (used for tensor product) -*/ -AADD aadd_replace_terminal(AADD a, AADD_TARG b); - -/** - * @param a AADD over vars 0...n-1 (n = nvars_a) - * @param b AADD over vars 0...m-1 - * @param nvars_a number of vars of AADD a - * - * @return AADD over vars 0...n-1...(n+m)-1, representing a (tensor) b - */ -AADD aadd_tensor_prod(AADD a, AADD b, BDDVAR nvars_a); - -/** - * Computes the tensor product of vec (tensor) vec - * - * @param a AADD over vars 0...n-1 (n = nvars_a) - * @param b AADD over vars 0...m-1 - * @param nvars_a number of vars of AADD a - * - * @return AADD over vars 0...n-1...(n+m)-1, representing a (tensor) b - */ -#define aadd_vec_tensor_prod(a, b, nvars_a) aadd_tensor_prod(a,b,nvars_a) - -/** - * Computes the tensor product of mat (tensor) mat - * - * @param a AADD over vars 0...2n-1 (n = nvars_a) - * @param b AADD over vars 0...2m-1 - * @param nvars_a number of vars of AADD a (counting only unprimed) - * - * @return AADD over vars 0...2n-1...(2n+2m)-1, representing a (tensor) b - */ -#define aadd_mat_tensor_prod(a, b, nvars_a) aadd_tensor_prod(a,b,2*nvars_a) - -/***************************************************/ - - - - - -/******************************************************/ - -/** - * Count the number of AADD nodes. - */ -uint64_t aadd_countnodes(AADD a); - -/*****************************************************/ - - - - - -/*****************************************************/ - -/** - * Write a .dot representation of a given AADD - */ -void aadd_fprintdot(FILE *out, AADD a, bool draw_zeros); - -/****************************************************/ - - - - - -/*****************************************************************/ - -/** - * Checks if the vectors encoded by two AADDs are the same. In principle the - * root edges of two identical AADDs should always be the same, so this is - * mostly a debug/testing function. - * - * @param n Number of variables - * @param exact If true, vec(a) should equal vec(b) exactly (float equal), - * otherwise allow for preset float equivalence margin. - * - * @returns True iff vec(a) == vec(b). - */ -bool aadd_equivalent(AADD a, AADD b, int n, bool exact, bool verbose); - -/** Sanity check to see if the AADD variables are ordered and < nvars. */ -#define aadd_is_ordered(a, nvars) aadd_is_ordered_rec(a, 0, nvars) -bool aadd_is_ordered_rec(AADD a, BDD nextvar, BDD nvars); - -void aadd_printnodes(AADD a); -bool _next_bitstring(bool *x, int n); -void _print_bitstring(bool *x, int n, bool backwards); -uint64_t bitarray_to_int(bool *x, int n, bool MSB_first); -bool * int_to_bitarray(uint64_t n, int length, bool MSB_first); -bool bit_from_int(uint64_t a, uint8_t index); -void reverse_bit_array(bool *x, int length); - -/****************************************************************/ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif diff --git a/src/sylvan_aadd_int.h b/src/sylvan_aadd_int.h deleted file mode 100644 index 514aff2..0000000 --- a/src/sylvan_aadd_int.h +++ /dev/null @@ -1,357 +0,0 @@ - -/* Do not include this file directly. Instead, include sylvan_int.h */ - -/** - * Internals for AADDs - */ - -#ifndef SYLVAN_AADD_INT_H -#define SYLVAN_AADD_INT_H - -#include - -/** - * These golbal variables control some of the AADD behavior, and are set in - * sylvan_init_aadd(). - * TODO: Maybe handle this in a cleaner way than with global variables? - */ -// 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 *); - - -/*********************************/ - -/** - * When edge weight table <= 2^23 (larger_wgt_indices = false) - * ----------------------------------------------------------------------------- - * 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) - * (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: 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 - * 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 - -static const AADD aadd_marked_mask = 0x8000000000000000LL; -static const AADD aadd_var_mask_low = 0x7f80000000000000LL; -static const AADD aadd_wgt_pos_mask = 0x0040000000000000LL; -static const AADD aadd_wgt_val_mask = 0x0020000000000000LL; -static const AADD aadd_wgt_mask_23 = 0x7fffff0000000000LL; -static const AADD aadd_wgt_mask_33 = 0x7fffffffc0000000LL; -static const AADD aadd_ptr_mask_30 = 0x000000003fffffffLL; -static const AADD aadd_ptr_mask_40 = 0x000000ffffffffffLL; - - -/** - * Gets only the AADD_WGT information of an AADD edge. - */ -static inline AADD_WGT -AADD_WEIGHT(AADD a) -{ - if (larger_wgt_indices) { - return (a & aadd_wgt_mask_33) >> 30; // 33 bits - } - else { - return (a & aadd_wgt_mask_23) >> 40; // 23 bits - } -} - -/** - * Gets only the TARGET information of an AADD edge. - */ -static inline AADD_TARG -AADD_TARGET(AADD a) -{ - if (larger_wgt_indices) { - return a & aadd_ptr_mask_30; // 30 bits - } - else { - return a & aadd_ptr_mask_40; // 40 bits - } -} - -/** - * Gets the variable number of a given node `n`. - */ -static inline BDDVAR -aaddnode_getvar(aaddnode_t n) -{ - return (BDDVAR) ((n->low & aadd_var_mask_low) >> 55 ); // 8 bits -} - -/** - * Gets only the AADD_TARG of the low edge of . - */ -static inline AADD_TARG -aaddnode_getptrlow(aaddnode_t n) -{ - return (AADD_TARG) AADD_TARGET(n->low); -} - -/** - * Gets only the AADD_TARG of the high edge of . - */ -static inline AADD_TARG -aaddnode_getptrhigh(aaddnode_t n) -{ - return (AADD_TARG) AADD_TARGET(n->high); -} - -/** - * Gets the value of the "marked" flag. - */ -static inline bool -aaddnode_getmark(aaddnode_t n) -{ - return n->high & aadd_marked_mask ? 1 : 0; -} - -/** - * Sets the value of the "marked" flag to `mark`. - */ -static inline void -aaddnode_setmark(aaddnode_t n, bool mark) -{ - if (mark) n->high |= aadd_marked_mask; // set 1st bit from left to 1 - else n->high &= ~aadd_marked_mask; // set 1st bit from left to 0 -} - -/** - * Gets the node

is pointing to. - * TODO (?) return special node for when p == AADD_TERMINAL - */ -static inline aaddnode_t -AADD_GETNODE(AADD_TARG p) -{ - return (aaddnode_t) llmsset_index_to_ptr(nodes, p); -} - -/** - * Packs a AADD_TARG and AADD_WGT into a single 64 bit AADD. - */ -static inline AADD -aadd_bundle(AADD_TARG p, AADD_WGT a) -{ - if (larger_wgt_indices) { - assert (p <= 0x000000003ffffffe); // avoid clash with sylvan_invalid - assert (a <= (1LL<<33)); - return (a << 30 | p); - }else { - assert (p <= 0x000000fffffffffe); // avoid clash with sylvan_invalid - assert (a <= (1<<23)); - return (a << 40 | p); - } -} - -static void __attribute__((unused)) -aaddnode_unpack(aaddnode_t n, AADD_TARG *low, AADD_TARG *high, AADD_WGT *a, AADD_WGT *b) -{ - *low = aaddnode_getptrlow(n); - *high = aaddnode_getptrhigh(n); - bool norm_pos = (n->low & aadd_wgt_pos_mask) >> 54; - bool norm_val = (n->low & aadd_wgt_val_mask) >> 53; - - if (weight_norm_strat == NORM_L2) { - *b = AADD_WEIGHT(n->high); - *a = wgt_get_low_L2normed(*b); - } - else { - if (norm_pos == 0) { // low WGT is AADD_ZERO or AADD_ONE, high WGT in table - *a = (norm_val == 0) ? AADD_ZERO : AADD_ONE; - *b = AADD_WEIGHT(n->high); - } - else { // high WGT is AADD_ZERO or AADD_ONE, low WGT in table - *b = (norm_val == 0) ? AADD_ZERO : AADD_ONE; - *a = AADD_WEIGHT(n->high); - } - } -} - -static void __attribute__((unused)) -aaddnode_getchilderen(aaddnode_t n, AADD *low, AADD *high) -{ - AADD_TARG l, h; - AADD_WGT a, b; - aaddnode_unpack(n, &l, &h, &a, &b); - *low = aadd_bundle(l, a); - *high = aadd_bundle(h, b); -} - -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_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 - // outside of {0, 1}, but under the constraint that |low|^2 + |high|^2 = 1, - // (or both are 0) and that |low| \in R+, we only need to store high, and - // can derive low. - - // these will be set depending on the normalization strategy - // (retrieval of edge weights is also dependent on normalization strategy) - AADD_WGT wgt_high; - bool norm_pos; - bool norm_val; - - if (weight_norm_strat == NORM_L2) { - assert(!(a == AADD_ZERO && b == AADD_ZERO)); // redundant node (caught before) - norm_pos = 0; - norm_val = 0; - wgt_high = b; // we can derive a from b - } - else { - /// 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) { - norm_val = (a == AADD_ZERO) ? 0 : 1; - wgt_high = b; - } - else { - norm_val = (b == AADD_ZERO) ? 0 : 1; - wgt_high = a; - } - } - - // organize the bit structure of low and high - n->low = ((uint64_t)var)<<55 | ((uint64_t)norm_pos)<<54 | ((uint64_t)norm_val)<<53 | low; - if (larger_wgt_indices) { - n->high = wgt_high<<30 | high; - } - else { - n->high = wgt_high<<40 | high; - } -} - -static AADD_TARG __attribute__((unused)) -_aadd_makenode(BDDVAR var, AADD_TARG low, AADD_TARG high, AADD_WGT a, AADD_WGT b) -{ - struct aaddnode n; - - aaddnode_pack(&n, var, low, high, a, b); - - AADD_TARG result; - int created; - AADD_TARG index = llmsset_lookup(nodes, n.low, n.high, &created); - if (index == 0) { - //printf("auto gc of node table triggered\n"); - - aadd_refs_push(low); - aadd_refs_push(high); - sylvan_gc(); - aadd_refs_pop(2); - - index = llmsset_lookup(nodes, n.low, n.high, &created); - if (index == 0) { - fprintf(stderr, "AADD/BDD Unique table full, %zu of %zu buckets filled!\n", llmsset_count_marked(nodes), llmsset_get_size(nodes)); - exit(1); - } - } - - if (created) sylvan_stats_count(AADD_NODES_CREATED); - else sylvan_stats_count(AADD_NODES_REUSED); - - result = index; - //return mark ? result | aadd_marked_mask : result; - return result; -} - -static AADD __attribute__((unused)) -aadd_makenode(BDDVAR var, AADD low, AADD high) -{ - AADD_TARG low_trg = AADD_TARGET(low); - AADD_WGT low_wgt = AADD_WEIGHT(low); - AADD_TARG high_trg = AADD_TARGET(high); - AADD_WGT high_wgt = AADD_WEIGHT(high); - - // Edges with weight 0 should point straight to terminal. - if (low_wgt == AADD_ZERO) low_trg = AADD_TERMINAL; - if (high_wgt == AADD_ZERO) high_trg = AADD_TERMINAL; - - // If both low and high are the same (both TARG and WGT) return low - if (low == high) return low; - else { - // If the edges are not the same - AADD_WGT norm = (*normalize_weights)(&low_wgt, &high_wgt); - AADD_TARG res = _aadd_makenode(var, low_trg, high_trg, low_wgt, high_wgt); - return aadd_bundle(res, norm); - } -} - -/********************************/ - - -/** - * Gets either the top node of the AADD, or the node with var 't' if this - * variable would otherwise be skipped. The "node" is returned as - * (*topvar, *low, *high). - */ -static void __attribute__((unused)) -aadd_get_topvar(AADD a, BDDVAR t, BDDVAR *topvar, AADD *low, AADD *high) -{ - bool skipped = false; - if(AADD_TARGET(a) == AADD_TERMINAL) { - skipped = true; - } - else { - aaddnode_t node = AADD_GETNODE(AADD_TARGET(a)); - *topvar = aaddnode_getvar(node); - if (*topvar > t) skipped = true; - } - - if (skipped) { - *low = aadd_bundle(AADD_TARGET(a), AADD_ONE); - *high = aadd_bundle(AADD_TARGET(a), AADD_ONE); - *topvar = t; - } - else { - aaddnode_t node = AADD_GETNODE(AADD_TARGET(a)); - aaddnode_getchilderen(node, low, high); - } -} - -#endif \ No newline at end of file diff --git a/src/sylvan_edge_weights.c b/src/sylvan_edge_weights.c index 6d7b34c..9ea48f1 100644 --- a/src/sylvan_edge_weights.c +++ b/src/sylvan_edge_weights.c @@ -9,17 +9,17 @@ void *wgt_storage; // TODO: move to source file? void *wgt_storage_new; -AADD_WGT AADD_ZERO; -AADD_WGT AADD_ONE; -AADD_WGT AADD_MIN_ONE; -AADD_WGT AADD_IMG; -AADD_WGT AADD_MIN_IMG; -AADD_WGT AADD_SQRT_TWO; +EVBDD_WGT EVBDD_ZERO; +EVBDD_WGT EVBDD_ONE; +EVBDD_WGT EVBDD_MIN_ONE; +EVBDD_WGT EVBDD_IMG; +EVBDD_WGT EVBDD_MIN_IMG; +EVBDD_WGT EVBDD_SQRT_TWO; void sylvan_init_edge_weights(size_t min_tablesize, size_t max_tablesize, double tol, edge_weight_type_t edge_weight_type, wgt_storage_backend_t backend); void init_edge_weight_functions(edge_weight_type_t edge_weight_type); void init_edge_weight_storage(size_t size, double tol, wgt_storage_backend_t backend, void **wgt_store); -void (*init_wgt_table_entries)(); // set by sylvan_init_aadd +void (*init_wgt_table_entries)(); // set by sylvan_init_evbdd uint64_t sylvan_get_edge_weight_table_size(); double sylvan_edge_weights_tolerance(); uint64_t sylvan_edge_weights_count_entries(); @@ -115,7 +115,7 @@ init_edge_weight_storage(size_t size, double tol, wgt_storage_backend_t backend, // create actual table *wgt_store = wgt_store_create(table_size, tolerance); - // Set AADD_WGT values for 1, 0 (and -1) + // Set EVBDD_WGT values for 1, 0 (and -1) init_one_zero(*wgt_store); } @@ -222,13 +222,13 @@ wgt_table_gc_delete_old() wgt_storage = wgt_storage_new; } -AADD_WGT -wgt_table_gc_keep(AADD_WGT a) +EVBDD_WGT +wgt_table_gc_keep(EVBDD_WGT a) { // move from current (old) to new weight_t wa = weight_malloc(); _weight_value(wgt_storage, a, wa); - AADD_WGT res = _weight_lookup_ptr(wa, wgt_storage_new); + EVBDD_WGT res = _weight_lookup_ptr(wa, wgt_storage_new); free(wa); return res; } @@ -251,16 +251,16 @@ wgt_set_inverse_chaching(bool on) } static void -order_inputs(AADD_WGT *a, AADD_WGT *b) +order_inputs(EVBDD_WGT *a, EVBDD_WGT *b) { - AADD_WGT x = (*a > *b) ? *a : *b; - AADD_WGT y = (*a > *b) ? *b : *a; + EVBDD_WGT x = (*a > *b) ? *a : *b; + EVBDD_WGT y = (*a > *b) ? *b : *a; *a = x; *b = y; } static bool -cache_get_add(AADD_WGT a, AADD_WGT b, AADD_WGT *res) +cache_get_add(EVBDD_WGT a, EVBDD_WGT b, EVBDD_WGT *res) { order_inputs(&a, &b); if (cache_get3(CACHE_WGT_ADD, a, b, sylvan_false, res)) { @@ -271,7 +271,7 @@ cache_get_add(AADD_WGT a, AADD_WGT b, AADD_WGT *res) } static void -cache_put_add(AADD_WGT a, AADD_WGT b, AADD_WGT res) +cache_put_add(EVBDD_WGT a, EVBDD_WGT b, EVBDD_WGT res) { order_inputs(&a, &b); if (cache_put3(CACHE_WGT_ADD, a, b, sylvan_false, res)) { @@ -280,7 +280,7 @@ cache_put_add(AADD_WGT a, AADD_WGT b, AADD_WGT res) } static void -cache_put_sub(AADD_WGT a, AADD_WGT b, AADD_WGT res) +cache_put_sub(EVBDD_WGT a, EVBDD_WGT b, EVBDD_WGT res) { if (cache_put3(CACHE_WGT_SUB, a, b, sylvan_false, res)) { sylvan_stats_count(WGT_SUB_CACHEDPUT); @@ -288,7 +288,7 @@ cache_put_sub(AADD_WGT a, AADD_WGT b, AADD_WGT res) } static bool -cache_get_sub(AADD_WGT a, AADD_WGT b, AADD_WGT *res) +cache_get_sub(EVBDD_WGT a, EVBDD_WGT b, EVBDD_WGT *res) { if (cache_get3(CACHE_WGT_SUB, a, b, sylvan_false, res)) { sylvan_stats_count(WGT_SUB_CACHED); @@ -298,7 +298,7 @@ cache_get_sub(AADD_WGT a, AADD_WGT b, AADD_WGT *res) } static void -cache_put_mul(AADD_WGT a, AADD_WGT b, AADD_WGT res) +cache_put_mul(EVBDD_WGT a, EVBDD_WGT b, EVBDD_WGT res) { order_inputs(&a, &b); if (cache_put3(CACHE_WGT_MUL, a, b, sylvan_false, res)) { @@ -316,7 +316,7 @@ cache_put_mul(AADD_WGT a, AADD_WGT b, AADD_WGT res) } static bool -cache_get_mul(AADD_WGT a, AADD_WGT b, AADD_WGT *res) +cache_get_mul(EVBDD_WGT a, EVBDD_WGT b, EVBDD_WGT *res) { order_inputs(&a, &b); if (cache_get3(CACHE_WGT_MUL, a, b, sylvan_false, res)) { @@ -327,7 +327,7 @@ cache_get_mul(AADD_WGT a, AADD_WGT b, AADD_WGT *res) } static void -cache_put_div(AADD_WGT a, AADD_WGT b, AADD_WGT res) +cache_put_div(EVBDD_WGT a, EVBDD_WGT b, EVBDD_WGT res) { if (cache_put3(CACHE_WGT_DIV, a, b, sylvan_false, res)) { sylvan_stats_count(WGT_DIV_CACHEDPUT); @@ -342,7 +342,7 @@ cache_put_div(AADD_WGT a, AADD_WGT b, AADD_WGT res) } static bool -cache_get_div(AADD_WGT a, AADD_WGT b, AADD_WGT *res) +cache_get_div(EVBDD_WGT a, EVBDD_WGT b, EVBDD_WGT *res) { if (cache_get3(CACHE_WGT_DIV, a, b, sylvan_false, res)) { sylvan_stats_count(WGT_DIV_CACHED); @@ -357,16 +357,16 @@ cache_get_div(AADD_WGT a, AADD_WGT b, AADD_WGT *res) -/******************************************/ +/******************************************/ -AADD_WGT -wgt_abs(AADD_WGT a) +EVBDD_WGT +wgt_abs(EVBDD_WGT a) { // special cases - if (a == AADD_ZERO || a == AADD_ONE) return a; - if (a == AADD_MIN_ONE) return AADD_ONE; + if (a == EVBDD_ZERO || a == EVBDD_ONE) return a; + if (a == EVBDD_MIN_ONE) return EVBDD_ONE; - AADD_WGT res; + EVBDD_WGT res; weight_t w = weight_malloc(); weight_value(a, w); @@ -377,15 +377,15 @@ wgt_abs(AADD_WGT a) return res; } -AADD_WGT -wgt_neg(AADD_WGT a) +EVBDD_WGT +wgt_neg(EVBDD_WGT a) { // special cases - if (a == AADD_ZERO) return AADD_ZERO; - if (a == AADD_ONE) return AADD_MIN_ONE; - if (a == AADD_MIN_ONE) return AADD_ONE; + if (a == EVBDD_ZERO) return EVBDD_ZERO; + if (a == EVBDD_ONE) return EVBDD_MIN_ONE; + if (a == EVBDD_MIN_ONE) return EVBDD_ONE; - AADD_WGT res; + EVBDD_WGT res; weight_t w = weight_malloc(); weight_value(a, w); @@ -396,13 +396,13 @@ wgt_neg(AADD_WGT a) return res; } -AADD_WGT -wgt_conj(AADD_WGT a) +EVBDD_WGT +wgt_conj(EVBDD_WGT a) { // special cases - if (a == AADD_ZERO || a == AADD_ONE || a == AADD_MIN_ONE) return a; + if (a == EVBDD_ZERO || a == EVBDD_ONE || a == EVBDD_MIN_ONE) return a; - AADD_WGT res; + EVBDD_WGT res; weight_t w = weight_malloc(); weight_value(a, w); @@ -413,15 +413,15 @@ wgt_conj(AADD_WGT a) return res; } -AADD_WGT -wgt_add(AADD_WGT a, AADD_WGT b) +EVBDD_WGT +wgt_add(EVBDD_WGT a, EVBDD_WGT b) { // special cases - if (a == AADD_ZERO) return b; - if (b == AADD_ZERO) return a; + if (a == EVBDD_ZERO) return b; + if (b == EVBDD_ZERO) return a; // check cache - AADD_WGT res; + EVBDD_WGT res; if (CACHE_WGT_OPS) { if (cache_get_add(a, b, &res)) return res; } @@ -443,15 +443,15 @@ wgt_add(AADD_WGT a, AADD_WGT b) return res; } -AADD_WGT -wgt_sub(AADD_WGT a, AADD_WGT b) +EVBDD_WGT +wgt_sub(EVBDD_WGT a, EVBDD_WGT b) { // special cases - if (b == AADD_ZERO) return a; - if (a == AADD_ZERO) return wgt_neg(b); + if (b == EVBDD_ZERO) return a; + if (a == EVBDD_ZERO) return wgt_neg(b); // check cache - AADD_WGT res; + EVBDD_WGT res; if (CACHE_WGT_OPS) { if (cache_get_sub(a, b, &res)) return res; } @@ -473,16 +473,16 @@ wgt_sub(AADD_WGT a, AADD_WGT b) return res; } -AADD_WGT -wgt_mul(AADD_WGT a, AADD_WGT b) +EVBDD_WGT +wgt_mul(EVBDD_WGT a, EVBDD_WGT b) { // special cases - if (a == AADD_ONE) return b; - if (b == AADD_ONE) return a; - if (a == AADD_ZERO || b == AADD_ZERO) return AADD_ZERO; + if (a == EVBDD_ONE) return b; + if (b == EVBDD_ONE) return a; + if (a == EVBDD_ZERO || b == EVBDD_ZERO) return EVBDD_ZERO; // check cache - AADD_WGT res; + EVBDD_WGT res; if (CACHE_WGT_OPS) { if (cache_get_mul(a, b, &res)) return res; } @@ -504,16 +504,16 @@ wgt_mul(AADD_WGT a, AADD_WGT b) return res; } -AADD_WGT -wgt_div(AADD_WGT a, AADD_WGT b) +EVBDD_WGT +wgt_div(EVBDD_WGT a, EVBDD_WGT b) { // special cases - if (a == b) return AADD_ONE; - if (a == AADD_ZERO) return AADD_ZERO; - if (b == AADD_ONE) return a; + if (a == b) return EVBDD_ONE; + if (a == EVBDD_ZERO) return EVBDD_ZERO; + if (b == EVBDD_ONE) return a; // check cache - AADD_WGT res; + EVBDD_WGT res; if (CACHE_WGT_OPS) { if (cache_get_div(a, b, &res)) return res; } @@ -535,16 +535,16 @@ wgt_div(AADD_WGT a, AADD_WGT b) return res; } -/*****************************************/ +/*****************************************/ -/***************************************************/ +/***************************************************/ bool -wgt_eq(AADD_WGT a, AADD_WGT b) +wgt_eq(EVBDD_WGT a, EVBDD_WGT b) { weight_t wa = weight_malloc(); weight_t wb = weight_malloc(); @@ -560,7 +560,7 @@ wgt_eq(AADD_WGT a, AADD_WGT b) } bool -wgt_eps_close(AADD_WGT a, AADD_WGT b, double eps) +wgt_eps_close(EVBDD_WGT a, EVBDD_WGT b, double eps) { weight_t wa = weight_malloc(); weight_t wb = weight_malloc(); @@ -576,12 +576,12 @@ wgt_eps_close(AADD_WGT a, AADD_WGT b, double eps) } bool -wgt_approx_eq(AADD_WGT a, AADD_WGT b) +wgt_approx_eq(EVBDD_WGT a, EVBDD_WGT b) { return wgt_eps_close(a, b, wgt_store_get_tol()); } -/**************************************************/ +/**************************************************/ @@ -589,31 +589,31 @@ wgt_approx_eq(AADD_WGT a, AADD_WGT b) /***************************************************/ -AADD_WGT -wgt_norm_low(AADD_WGT *low, AADD_WGT *high) +EVBDD_WGT +wgt_norm_low(EVBDD_WGT *low, EVBDD_WGT *high) { // Normalize using low if low != 0 - AADD_WGT norm; - if(*low != AADD_ZERO){ + EVBDD_WGT norm; + if(*low != EVBDD_ZERO){ *high = wgt_div(*high, *low); norm = *low; - *low = AADD_ONE; + *low = EVBDD_ONE; } else { norm = *high; - *high = AADD_ONE; + *high = EVBDD_ONE; } return norm; } -AADD_WGT -wgt_norm_max(AADD_WGT *low, AADD_WGT *high) +EVBDD_WGT +wgt_norm_max(EVBDD_WGT *low, EVBDD_WGT *high) { - AADD_WGT norm; + EVBDD_WGT norm; if (*low == *high) { norm = *low; - *low = AADD_ONE; - *high = AADD_ONE; + *low = EVBDD_ONE; + *high = EVBDD_ONE; return norm; } @@ -627,13 +627,13 @@ wgt_norm_max(AADD_WGT *low, AADD_WGT *high) // high greater than low, divide both by high *low = wgt_div(*low, *high); norm = *high; - *high = AADD_ONE; + *high = EVBDD_ONE; } else { // low greater than high (or equal magnitude), divide both by low *high = wgt_div(*high, *low); norm = *low; - *low = AADD_ONE; + *low = EVBDD_ONE; } free(wl); @@ -641,25 +641,25 @@ wgt_norm_max(AADD_WGT *low, AADD_WGT *high) return norm; } -AADD_WGT -wgt_norm_min(AADD_WGT *low, AADD_WGT *high) +EVBDD_WGT +wgt_norm_min(EVBDD_WGT *low, EVBDD_WGT *high) { - AADD_WGT norm; + EVBDD_WGT norm; if (*low == *high) { norm = *low; - *low = AADD_ONE; - *high = AADD_ONE; + *low = EVBDD_ONE; + *high = EVBDD_ONE; return norm; } // Since min(a, b) could be 0, norm using non-zero to avoid dividing by 0 - if (*low == AADD_ZERO) { + if (*low == EVBDD_ZERO) { norm = *high; - *high = AADD_ONE; + *high = EVBDD_ONE; return norm; } - if (*high == AADD_ZERO) { + if (*high == EVBDD_ZERO) { norm = *low; - *low = AADD_ONE; + *low = EVBDD_ONE; return norm; } @@ -681,19 +681,19 @@ wgt_norm_min(AADD_WGT *low, AADD_WGT *high) // |low| ~= |high|, divide by low *high = wgt_div(*high, *low); norm = *low; - *low = AADD_ONE; + *low = EVBDD_ONE; } else if (weight_greater(wl, wh)) { // |high| < |low|, divide both by high *low = wgt_div(*low, *high); norm = *high; - *high = AADD_ONE; + *high = EVBDD_ONE; } else { // |low| < |high|, divide both by low *high = wgt_div(*high, *low); norm = *low; - *low = AADD_ONE; + *low = EVBDD_ONE; } free(wl); @@ -711,7 +711,7 @@ wgt_norm_min(AADD_WGT *low, AADD_WGT *high) /************************************************/ -void wgt_fprint(FILE *stream, AADD_WGT a) +void wgt_fprint(FILE *stream, EVBDD_WGT a) { weight_t w = weight_malloc(); weight_value(a, w); diff --git a/src/sylvan_edge_weights.h b/src/sylvan_edge_weights.h index 9a04269..07acbbc 100644 --- a/src/sylvan_edge_weights.h +++ b/src/sylvan_edge_weights.h @@ -5,11 +5,11 @@ #include #include -typedef uint64_t AADD_WGT; // AADD edge weights (indices to table entries) +typedef uint64_t EVBDD_WGT; // EVBDD edge weights (indices to table entries) -extern AADD_WGT AADD_ONE; -extern AADD_WGT AADD_ZERO; -extern AADD_WGT AADD_MIN_ONE; +extern EVBDD_WGT EVBDD_ONE; +extern EVBDD_WGT EVBDD_ZERO; +extern EVBDD_WGT EVBDD_MIN_ONE; typedef void *weight_t; @@ -31,7 +31,7 @@ extern void *wgt_storage_new; extern void sylvan_init_edge_weights(size_t min_tablesize, size_t max_tablesize, double tol, edge_weight_type_t edge_weight_type, wgt_storage_backend_t backend); extern void init_edge_weight_functions(edge_weight_type_t edge_weight_type); extern void init_edge_weight_storage(size_t size, double tol, wgt_storage_backend_t backend, void **wgt_store); -extern void (*init_wgt_table_entries)(); // set by sylvan_init_aadd +extern void (*init_wgt_table_entries)(); // set by sylvan_init_evbdd extern uint64_t sylvan_get_edge_weight_table_size(); extern double sylvan_edge_weights_tolerance(); @@ -51,7 +51,7 @@ extern uint64_t wgt_table_entries_estimate(); extern void wgt_table_gc_inc_entries_estimate(); extern void wgt_table_gc_init_new(void (*init_wgt_table_entries)()); extern void wgt_table_gc_delete_old(); -extern AADD_WGT wgt_table_gc_keep(AADD_WGT a); +extern EVBDD_WGT wgt_table_gc_keep(EVBDD_WGT a); /****************************************************/ @@ -62,9 +62,9 @@ extern AADD_WGT wgt_table_gc_keep(AADD_WGT a); /***********************************/ typedef weight_t (*weight_malloc_f)(); -typedef void (*_weight_value_f)(void *wgt_store, AADD_WGT a, weight_t res); -typedef AADD_WGT (*weight_lookup_f)(weight_t a); -typedef AADD_WGT (*_weight_lookup_ptr_f)(weight_t a, void *wgt_store); +typedef void (*_weight_value_f)(void *wgt_store, EVBDD_WGT a, weight_t res); +typedef EVBDD_WGT (*weight_lookup_f)(weight_t a); +typedef EVBDD_WGT (*_weight_lookup_ptr_f)(weight_t a, void *wgt_store); typedef void (*init_one_zero_f)(void *wgt_store); @@ -82,8 +82,8 @@ typedef bool (*weight_eps_close_f)(weight_t a, weight_t b, double eps); // retur 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); -typedef AADD_WGT (*wgt_get_low_L2normed_f)(AADD_WGT high); +typedef EVBDD_WGT (*wgt_norm_L2_f)(EVBDD_WGT *low, EVBDD_WGT *high); +typedef EVBDD_WGT (*wgt_get_low_L2normed_f)(EVBDD_WGT high); typedef void (*weight_fprint_f)(FILE *stream, weight_t a); @@ -133,30 +133,30 @@ 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 -AADD_WGT wgt_div(AADD_WGT a, AADD_WGT b); // returns a / b +/* Arithmetic operations on EVBDD_WGT's */ +EVBDD_WGT wgt_abs(EVBDD_WGT a); // returns |a| +EVBDD_WGT wgt_neg(EVBDD_WGT a); // returns -a +EVBDD_WGT wgt_conj(EVBDD_WGT a); // returns a* +EVBDD_WGT wgt_add(EVBDD_WGT a, EVBDD_WGT b); // returns a + b +EVBDD_WGT wgt_sub(EVBDD_WGT a, EVBDD_WGT b); // returns a - b +EVBDD_WGT wgt_mul(EVBDD_WGT a, EVBDD_WGT b); // returns a * b +EVBDD_WGT wgt_div(EVBDD_WGT a, EVBDD_WGT b); // returns a / b -/*****************************************/ +/*****************************************/ -/***************************************************/ +/***************************************************/ -bool wgt_eq(AADD_WGT a, AADD_WGT b); -bool wgt_eps_close(AADD_WGT a, AADD_WGT b, double eps); -bool wgt_approx_eq(AADD_WGT a, AADD_WGT b); +bool wgt_eq(EVBDD_WGT a, EVBDD_WGT b); +bool wgt_eps_close(EVBDD_WGT a, EVBDD_WGT b, double eps); +bool wgt_approx_eq(EVBDD_WGT a, EVBDD_WGT b); -/**************************************************/ +/**************************************************/ @@ -164,9 +164,9 @@ 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_max(AADD_WGT *low, AADD_WGT *high); -AADD_WGT wgt_norm_min(AADD_WGT *low, AADD_WGT *high); +EVBDD_WGT wgt_norm_low(EVBDD_WGT *low, EVBDD_WGT *high); +EVBDD_WGT wgt_norm_max(EVBDD_WGT *low, EVBDD_WGT *high); +EVBDD_WGT wgt_norm_min(EVBDD_WGT *low, EVBDD_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. @@ -178,7 +178,7 @@ AADD_WGT wgt_norm_min(AADD_WGT *low, AADD_WGT *high); /************************************************/ -void wgt_fprint(FILE *stream, AADD_WGT a); +void wgt_fprint(FILE *stream, EVBDD_WGT a); /************************************************/ diff --git a/src/sylvan_edge_weights_complex.c b/src/sylvan_edge_weights_complex.c index 81b6aa0..9b2fe51 100644 --- a/src/sylvan_edge_weights_complex.c +++ b/src/sylvan_edge_weights_complex.c @@ -34,15 +34,15 @@ weight_complex_malloc() } void -_weight_complex_value(void *wgt_store, AADD_WGT a, complex_t *res) +_weight_complex_value(void *wgt_store, EVBDD_WGT a, complex_t *res) { - if (a == AADD_ZERO) *res = czero(); - else if (a == AADD_ONE) *res = cone(); - else if (a == AADD_MIN_ONE) *res = cmone(); + if (a == EVBDD_ZERO) *res = czero(); + else if (a == EVBDD_ONE) *res = cone(); + else if (a == EVBDD_MIN_ONE) *res = cmone(); *res = wgt_store_get(wgt_store, a); } -AADD_WGT +EVBDD_WGT _weight_complex_lookup_ptr(complex_t *a, void *wgt_store) { // TODO: catch czero() / cone() here? @@ -63,10 +63,10 @@ _weight_complex_lookup_ptr(complex_t *a, void *wgt_store) fprintf(stderr, "Amplitude table full!\n"); exit(1); } - return (AADD_WGT) res; + return (EVBDD_WGT) res; } -AADD_WGT +EVBDD_WGT weight_complex_lookup(complex_t *a) { return _weight_complex_lookup_ptr(a, wgt_storage); @@ -76,9 +76,9 @@ void init_complex_one_zero(void *wgt_store) { complex_t a; - a = cone(); AADD_ONE = _weight_complex_lookup_ptr(&a, wgt_store); - a = czero(); AADD_ZERO = _weight_complex_lookup_ptr(&a, wgt_store); - a = cmone(); AADD_MIN_ONE = _weight_complex_lookup_ptr(&a, wgt_store); + a = cone(); EVBDD_ONE = _weight_complex_lookup_ptr(&a, wgt_store); + a = czero(); EVBDD_ZERO = _weight_complex_lookup_ptr(&a, wgt_store); + a = cmone(); EVBDD_MIN_ONE = _weight_complex_lookup_ptr(&a, wgt_store); } void @@ -166,20 +166,20 @@ weight_complex_greater(complex_t *a, complex_t *b) return ( (a->r*a->r + a->i*a->i) > (b->r*b->r + b->i*b->i) ); } -AADD_WGT -wgt_complex_norm_L2(AADD_WGT *low, AADD_WGT *high) +EVBDD_WGT +wgt_complex_norm_L2(EVBDD_WGT *low, EVBDD_WGT *high) { // normalize such that |low|^2 + |high|^2 = 1, and low in R+ // Deal with cases where one weight is 0 (both 0 shouldn't end up here) - if (*low == AADD_ZERO) { - AADD_WGT res = *high; - *high = AADD_ONE; + if (*low == EVBDD_ZERO) { + EVBDD_WGT res = *high; + *high = EVBDD_ONE; return res; } - else if (*high == AADD_ZERO){ - AADD_WGT res = *low; - *low = AADD_ONE; + else if (*high == EVBDD_ZERO){ + EVBDD_WGT res = *low; + *low = EVBDD_ONE; return res; } @@ -214,13 +214,13 @@ wgt_complex_norm_L2(AADD_WGT *low, AADD_WGT *high) return weight_complex_lookup(&c_norm); } -AADD_WGT -wgt_complex_get_low_L2normed(AADD_WGT high) +EVBDD_WGT +wgt_complex_get_low_L2normed(EVBDD_WGT high) { // Get low from high, assuming |low|^2 + |high|^2 = 1, and low \in R+: // a = sqrt(1 - |b|^2) - if (high == AADD_ZERO) return AADD_ONE; - if (high == AADD_ONE || high == AADD_MIN_ONE) return AADD_ZERO; + if (high == EVBDD_ZERO) return EVBDD_ONE; + if (high == EVBDD_ONE || high == EVBDD_MIN_ONE) return EVBDD_ZERO; complex_t b; weight_value(high, &b); diff --git a/src/sylvan_edge_weights_complex.h b/src/sylvan_edge_weights_complex.h index f10f126..d506e24 100644 --- a/src/sylvan_edge_weights_complex.h +++ b/src/sylvan_edge_weights_complex.h @@ -8,9 +8,9 @@ /************************************/ complex_t *weight_complex_malloc(); -void _weight_complex_value(void *wgt_store, AADD_WGT a, complex_t *res); -AADD_WGT weight_complex_lookup(complex_t *a); -AADD_WGT _weight_complex_lookup_ptr(complex_t *a, void *wgt_store); +void _weight_complex_value(void *wgt_store, EVBDD_WGT a, complex_t *res); +EVBDD_WGT weight_complex_lookup(complex_t *a); +EVBDD_WGT _weight_complex_lookup_ptr(complex_t *a, void *wgt_store); void init_complex_one_zero(void *wgt_store); @@ -26,20 +26,20 @@ bool weight_complex_eq(complex_t *a, complex_t *b); bool weight_complex_eps_close(complex_t *a, complex_t *b, double eps); bool weight_complex_greater(complex_t *a, complex_t *b); -AADD_WGT wgt_complex_norm_L2(AADD_WGT *low, AADD_WGT *high); -AADD_WGT wgt_complex_get_low_L2normed(AADD_WGT high); +EVBDD_WGT wgt_complex_norm_L2(EVBDD_WGT *low, EVBDD_WGT *high); +EVBDD_WGT wgt_complex_get_low_L2normed(EVBDD_WGT high); void weight_complex_fprint(FILE *stream, complex_t *a); -static inline AADD_WGT +static inline EVBDD_WGT complex_lookup_angle(fl_t theta, fl_t mag) { complex_t c = cmake_angle(theta, mag); return weight_lookup(&c); } -static inline AADD_WGT +static inline EVBDD_WGT complex_lookup(fl_t r, fl_t i) { complex_t c = cmake(r, i); diff --git a/src/sylvan_evbdd.c b/src/sylvan_evbdd.c new file mode 100644 index 0000000..e89e7e7 --- /dev/null +++ b/src/sylvan_evbdd.c @@ -0,0 +1,1329 @@ +/* + * Copyright 2011-2016 Formal Methods and Tools, University of Twente + * Copyright 2016-2017 Tom van Dijk, Johannes Kepler University Linz + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include +#include + +static int granularity = 1; // operation cache access granularity + + +bool larger_wgt_indices; +int weight_norm_strat; +EVBDD_WGT (*normalize_weights)(EVBDD_WGT *, EVBDD_WGT *); + +/*************************************/ + +/** + * Most of this gc code is copy-paste from sylvan_mtbdd.c, however because the + * bit structure of BDDs and EVBDDs are a bit different we can't use the mtbdd + * code directly. Since the way sylvan_mtbdd/sylvan_common/sylvan_table are + * structured we need to copy-paste a few more functions/variables than we + * actually change. + */ + +/* + * Recursively mark EVBDD nodes as 'in use'. + * This is really the only gc function which is different for EVBDDs vs MTBDDs. + */ +VOID_TASK_IMPL_1(evbdd_gc_mark_rec, EVBDD, a) +{ + if (EVBDD_TARGET(a) == EVBDD_TERMINAL) return; + + if (llmsset_mark(nodes, EVBDD_TARGET(a))) { + evbddnode_t n = EVBDD_GETNODE(EVBDD_TARGET(a)); + SPAWN(evbdd_gc_mark_rec, evbddnode_getptrlow(n)); + CALL(evbdd_gc_mark_rec, evbddnode_getptrhigh(n)); + SYNC(evbdd_gc_mark_rec); + } +} + +/** + * External references + */ +refs_table_t evbdd_refs; +refs_table_t evbdd_protected; +static int evbdd_protected_created = 0; + +void +evbdd_protect(EVBDD *a) +{ + if (!evbdd_protected_created) { + // In C++, sometimes mtbdd_protect is called before Sylvan is initialized. Just create a table. + protect_create(&evbdd_protected, 4096); + evbdd_protected_created = 1; + } + protect_up(&evbdd_protected, (size_t)a); +} + +void +evbdd_unprotect(EVBDD *a) +{ + if (evbdd_protected.refs_table != NULL) protect_down(&evbdd_protected, (size_t)a); +} + +size_t +evbdd_count_protected() +{ + return protect_count(&evbdd_protected); +} + +/* Called during garbage collection */ +VOID_TASK_0(evbdd_gc_mark_external_refs) +{ + // iterate through refs hash table, mark all found + size_t count=0; + uint64_t *it = refs_iter(&evbdd_refs, 0, evbdd_refs.refs_size); + while (it != NULL) { + SPAWN(evbdd_gc_mark_rec, refs_next(&evbdd_refs, &it, evbdd_refs.refs_size)); + count++; + } + while (count--) { + SYNC(evbdd_gc_mark_rec); + } +} + +/* Called during garbage collection */ +VOID_TASK_0(evbdd_gc_mark_protected) +{ + // iterate through refs hash table, mark all found + size_t count=0; + uint64_t *it = protect_iter(&evbdd_protected, 0, evbdd_protected.refs_size); + while (it != NULL) { + EVBDD *to_mark = (EVBDD*)protect_next(&evbdd_protected, &it, evbdd_protected.refs_size); + SPAWN(evbdd_gc_mark_rec, *to_mark); + count++; + } + while (count--) { + SYNC(evbdd_gc_mark_rec); + } +} + +/* Infrastructure for internal markings */ +typedef struct evbdd_refs_task +{ + Task *t; + void *f; +} *evbdd_refs_task_t; + +typedef struct evbdd_refs_internal +{ + const EVBDD **pbegin, **pend, **pcur; + EVBDD *rbegin, *rend, *rcur; + evbdd_refs_task_t sbegin, send, scur; +} *evbdd_refs_internal_t; + +DECLARE_THREAD_LOCAL(evbdd_refs_key, evbdd_refs_internal_t); + +VOID_TASK_2(evbdd_refs_mark_p_par, const EVBDD**, begin, size_t, count) +{ + if (count < 32) { + while (count) { + evbdd_gc_mark_rec(**(begin++)); + count--; + } + } else { + SPAWN(evbdd_refs_mark_p_par, begin, count / 2); + CALL(evbdd_refs_mark_p_par, begin + (count / 2), count - count / 2); + SYNC(evbdd_refs_mark_p_par); + } +} + +VOID_TASK_2(evbdd_refs_mark_r_par, EVBDD*, begin, size_t, count) +{ + if (count < 32) { + while (count) { + evbdd_gc_mark_rec(*begin++); + count--; + } + } else { + SPAWN(evbdd_refs_mark_r_par, begin, count / 2); + CALL(evbdd_refs_mark_r_par, begin + (count / 2), count - count / 2); + SYNC(evbdd_refs_mark_r_par); + } +} + +VOID_TASK_2(evbdd_refs_mark_s_par, evbdd_refs_task_t, begin, size_t, count) +{ + if (count < 32) { + while (count > 0) { + Task *t = begin->t; + if (!TASK_IS_STOLEN(t)) return; + if (t->f == begin->f && TASK_IS_COMPLETED(t)) { + evbdd_gc_mark_rec(*(EVBDD*)TASK_RESULT(t)); + } + begin += 1; + count -= 1; + } + } else { + if (!TASK_IS_STOLEN(begin->t)) return; + SPAWN(evbdd_refs_mark_s_par, begin, count / 2); + CALL(evbdd_refs_mark_s_par, begin + (count / 2), count - count / 2); + SYNC(evbdd_refs_mark_s_par); + } +} + +VOID_TASK_0(evbdd_refs_mark_task) +{ + LOCALIZE_THREAD_LOCAL(evbdd_refs_key, evbdd_refs_internal_t); + SPAWN(evbdd_refs_mark_p_par, evbdd_refs_key->pbegin, evbdd_refs_key->pcur-evbdd_refs_key->pbegin); + SPAWN(evbdd_refs_mark_r_par, evbdd_refs_key->rbegin, evbdd_refs_key->rcur-evbdd_refs_key->rbegin); + CALL(evbdd_refs_mark_s_par, evbdd_refs_key->sbegin, evbdd_refs_key->scur-evbdd_refs_key->sbegin); + SYNC(evbdd_refs_mark_r_par); + SYNC(evbdd_refs_mark_p_par); +} + +/* Called during garbage collection */ +VOID_TASK_0(evbdd_refs_mark) +{ + TOGETHER(evbdd_refs_mark_task); +} + +VOID_TASK_0(evbdd_refs_init_task) +{ + evbdd_refs_internal_t s = (evbdd_refs_internal_t)malloc(sizeof(struct evbdd_refs_internal)); + s->pcur = s->pbegin = (const EVBDD**)malloc(sizeof(EVBDD*) * 1024); + s->pend = s->pbegin + 1024; + s->rcur = s->rbegin = (EVBDD*)malloc(sizeof(EVBDD) * 1024); + s->rend = s->rbegin + 1024; + s->scur = s->sbegin = (evbdd_refs_task_t)malloc(sizeof(struct evbdd_refs_task) * 1024); + s->send = s->sbegin + 1024; + SET_THREAD_LOCAL(evbdd_refs_key, s); +} + +VOID_TASK_0(evbdd_refs_init) +{ + INIT_THREAD_LOCAL(evbdd_refs_key); + TOGETHER(evbdd_refs_init_task); + sylvan_gc_add_mark(TASK(evbdd_refs_mark)); +} + +VOID_TASK_0(evbdd_refs_cleanup_task) +{ + LOCALIZE_THREAD_LOCAL(evbdd_refs_key, evbdd_refs_internal_t); + free(evbdd_refs_key->pbegin); + free(evbdd_refs_key->rbegin); + free(evbdd_refs_key->sbegin); + free(evbdd_refs_key); +} + +/** + * Called by evbdd_quit. Cleans up the (thread local) malloc'ed evbdd_refs_key. + * + * NOTE: this cleanup isn't done in sylvan_mtbdd.c, but not doing this causes + * memory leaks when calling initializing and quiting Sylvan multiple times + * during the same program run. + */ +VOID_TASK_0(evbdd_refs_cleanup) +{ + TOGETHER(evbdd_refs_cleanup_task); +} + +void +evbdd_refs_ptrs_up(evbdd_refs_internal_t evbdd_refs_key) +{ + size_t cur = evbdd_refs_key->pcur - evbdd_refs_key->pbegin; + size_t size = evbdd_refs_key->pend - evbdd_refs_key->pbegin; + evbdd_refs_key->pbegin = (const EVBDD**)realloc(evbdd_refs_key->pbegin, sizeof(EVBDD*) * size * 2); + evbdd_refs_key->pcur = evbdd_refs_key->pbegin + cur; + evbdd_refs_key->pend = evbdd_refs_key->pbegin + (size * 2); +} + +EVBDD __attribute__((noinline)) +evbdd_refs_refs_up(evbdd_refs_internal_t evbdd_refs_key, EVBDD res) +{ + long size = evbdd_refs_key->rend - evbdd_refs_key->rbegin; + evbdd_refs_key->rbegin = (EVBDD*)realloc(evbdd_refs_key->rbegin, sizeof(EVBDD) * size * 2); + evbdd_refs_key->rcur = evbdd_refs_key->rbegin + size; + evbdd_refs_key->rend = evbdd_refs_key->rbegin + (size * 2); + return res; +} + +void __attribute__((noinline)) +evbdd_refs_tasks_up(evbdd_refs_internal_t evbdd_refs_key) +{ + long size = evbdd_refs_key->send - evbdd_refs_key->sbegin; + evbdd_refs_key->sbegin = (evbdd_refs_task_t)realloc(evbdd_refs_key->sbegin, sizeof(struct evbdd_refs_task) * size * 2); + evbdd_refs_key->scur = evbdd_refs_key->sbegin + size; + evbdd_refs_key->send = evbdd_refs_key->sbegin + (size * 2); +} + +void __attribute__((unused)) +evbdd_refs_pushptr(const EVBDD *ptr) +{ + LOCALIZE_THREAD_LOCAL(evbdd_refs_key, evbdd_refs_internal_t); + *evbdd_refs_key->pcur++ = ptr; + if (evbdd_refs_key->pcur == evbdd_refs_key->pend) evbdd_refs_ptrs_up(evbdd_refs_key); +} + +void __attribute__((unused)) +evbdd_refs_popptr(size_t amount) +{ + LOCALIZE_THREAD_LOCAL(evbdd_refs_key, evbdd_refs_internal_t); + evbdd_refs_key->pcur -= amount; +} + +EVBDD __attribute__((unused)) +evbdd_refs_push(EVBDD a) +{ + LOCALIZE_THREAD_LOCAL(evbdd_refs_key, evbdd_refs_internal_t); + *(evbdd_refs_key->rcur++) = a; + if (evbdd_refs_key->rcur == evbdd_refs_key->rend) return evbdd_refs_refs_up(evbdd_refs_key, a); + else return a; +} + +void __attribute__((unused)) +evbdd_refs_pop(long amount) +{ + LOCALIZE_THREAD_LOCAL(evbdd_refs_key, evbdd_refs_internal_t); + evbdd_refs_key->rcur -= amount; +} + +void +evbdd_refs_spawn(Task *t) +{ + LOCALIZE_THREAD_LOCAL(evbdd_refs_key, evbdd_refs_internal_t); + evbdd_refs_key->scur->t = t; + evbdd_refs_key->scur->f = t->f; + evbdd_refs_key->scur += 1; + if (evbdd_refs_key->scur == evbdd_refs_key->send) evbdd_refs_tasks_up(evbdd_refs_key); +} + +EVBDD +evbdd_refs_sync(EVBDD result) +{ + LOCALIZE_THREAD_LOCAL(evbdd_refs_key, evbdd_refs_internal_t); + evbdd_refs_key->scur -= 1; + return result; +} + +/************************************/ + + + + + +/**************************************************/ + +static int auto_gc_wgt_table = 1; +static double wgt_table_gc_thres = 0.5; + +void +evbdd_set_auto_gc_wgt_table(bool enabled) +{ + auto_gc_wgt_table = enabled; +} + +void +evbdd_set_gc_wgt_table_thres(double fraction_filled) +{ + wgt_table_gc_thres = fraction_filled; +} + +double +evbdd_get_gc_wgt_table_thres() +{ + return wgt_table_gc_thres; +} + + +void +evbdd_gc_wgt_table() +{ + // gc edge weight table and keep wgts of protected EVBDDs (and update those) + // 1. Create new edge weight table table + wgt_table_gc_init_new(init_wgt_table_entries); + + // 2. Fill new table with wgts in protected EVBDDs and update those EVBDDs + uint64_t *it = protect_iter(&evbdd_protected, 0, evbdd_protected.refs_size); + while (it != NULL) { + EVBDD *to_protect_wgts = (EVBDD*)protect_next(&evbdd_protected, &it, evbdd_protected.refs_size); + if (to_protect_wgts != NULL) { + *to_protect_wgts = _fill_new_wgt_table(*to_protect_wgts); + } + } + + // 3. Delete old edge weight table + wgt_table_gc_delete_old(); + + // 4. Any cache we migh have is now invalid because the same edge weights + // might now have different indices in the edge weight table + sylvan_clear_cache(); +} + +TASK_IMPL_1(EVBDD, _fill_new_wgt_table, EVBDD, a) +{ + // Check cache + EVBDD res; + bool cachenow = 1; + if (cachenow) { + if (cache_get3(CACHE_EVBDD_CLEAN_WGT_TABLE, 0LL, a, 0LL, &res)) { + return res; + } + } + + // Move weight from old to new table, get new index + EVBDD_WGT new_wgt = wgt_table_gc_keep(EVBDD_WEIGHT(a)); + a = evbdd_bundle(EVBDD_TARGET(a), new_wgt); + + // If terminal, return + if (EVBDD_TARGET(a) == EVBDD_TERMINAL) return a; + + // Recursive for children + EVBDD low, high; + evbddnode_t n = EVBDD_GETNODE(EVBDD_TARGET(a)); + evbddnode_getchilderen(n, &low, &high); + evbdd_refs_spawn(SPAWN(_fill_new_wgt_table, high)); + low = CALL(_fill_new_wgt_table, low); + evbdd_refs_push(low); + high = evbdd_refs_sync(SYNC(_fill_new_wgt_table)); + evbdd_refs_pop(1); + + // We don't need to use the 'evbdd_makenode()' function which normalizes the + // weights, because the EVBDD doesn't actually change, only the WGT indices, + // but none of the actual values. + EVBDD_TARG ptr = _evbdd_makenode(evbddnode_getvar(n), EVBDD_TARGET(low), EVBDD_TARGET(high), EVBDD_WEIGHT(low), EVBDD_WEIGHT(high)); + + // Put in cache, return + res = evbdd_bundle(ptr, new_wgt); + if (cachenow) cache_put3(CACHE_EVBDD_CLEAN_WGT_TABLE, 0LL, a, 0LL, res); + return res; +} + +bool +evbdd_test_gc_wgt_table() +{ + uint64_t entries = wgt_table_entries_estimate(); + uint64_t size = sylvan_get_edge_weight_table_size(); + return ( ((double)entries / (double)size) > wgt_table_gc_thres ); +} + +/*************************************************/ + + + + + +/**************************************************************/ + +/** + * Initialize and quit functions + */ +static int evbdd_initialized = 0; + +static void +evbdd_quit() +{ + refs_free(&evbdd_refs); + if (evbdd_protected_created) { + protect_free(&evbdd_protected); + evbdd_protected_created = 0; + } + RUN(evbdd_refs_cleanup); + evbdd_initialized = 0; + sylvan_edge_weights_free(); +} + +void +sylvan_init_evbdd(size_t min_wgt_tablesize, size_t max_wgt_tablesize, + double wgt_tab_tolerance, int edge_weigth_backend, + int norm_strat, void *init_wgt_tab_entries) +{ + if (evbdd_initialized) return; + evbdd_initialized = 1; + + int index_size = (int) ceil(log2(max_wgt_tablesize)); + if (edge_weigth_backend == REAL_TUPLES_HASHMAP || edge_weigth_backend == REAL_TREE) + index_size = index_size*2; + if (index_size > 33) { + fprintf(stderr,"max edge weight storage size is 2^33 (2^16 when using storing r and i seperately)\n"); + exit(1); + } + if (index_size > 23) larger_wgt_indices = true; + else larger_wgt_indices = false; + + sylvan_register_quit(evbdd_quit); + sylvan_gc_add_mark(TASK(evbdd_gc_mark_external_refs)); + sylvan_gc_add_mark(TASK(evbdd_gc_mark_protected)); + + refs_create(&evbdd_refs, 1024); + if (!evbdd_protected_created) { + protect_create(&evbdd_protected, 4096); + evbdd_protected_created = 1; + } + + // TODO: pass edge weight type to sylvan_init_evbdd + if (min_wgt_tablesize > max_wgt_tablesize) min_wgt_tablesize = max_wgt_tablesize; + sylvan_init_edge_weights(min_wgt_tablesize, max_wgt_tablesize, + wgt_tab_tolerance, WGT_COMPLEX_128, + edge_weigth_backend); + + init_wgt_table_entries = init_wgt_tab_entries; + if (init_wgt_table_entries != NULL) { + init_wgt_table_entries(); + } + + weight_norm_strat = norm_strat; + switch (norm_strat) + { + 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; + default: + printf("Edge weight normalization strategy not recognized\n"); + exit(1); + break; + } + + RUN(evbdd_refs_init); +} + +void +sylvan_init_evbdd_defaults(size_t min_wgt_tablesize, size_t max_wgt_tablesize) +{ + sylvan_init_evbdd(min_wgt_tablesize, max_wgt_tablesize, -1, COMP_HASHMAP, NORM_LOW, NULL); +} + + +void +evbdd_set_caching_granularity(int g) +{ + granularity = g; +} + +/*************************************************************/ + + + + + +/****************************************************/ + +EVBDD_WGT +evbdd_getvalue(EVBDD a, bool* path) +{ + EVBDD_WGT res = EVBDD_ONE; + EVBDD low, high; + for (;;) { + res = wgt_mul(res, EVBDD_WEIGHT(a)); + + // if the current edge is pointing to the terminal, we're done. + if (EVBDD_TARGET(a) == EVBDD_TERMINAL) break; + + // now we need to choose low or high edge of next node + evbddnode_t node = EVBDD_GETNODE(EVBDD_TARGET(a)); + BDDVAR var = evbddnode_getvar(node); + evbddnode_getchilderen(node, &low, &high); + + // Condition low/high choice on basis state vector[var] + a = (path[var] == 0) ? low : high; + } + + return res; +} + +static void +evbdd_do_before_mult(EVBDD *a, EVBDD *b) +{ + // check if edge weight table needs gc + if (auto_gc_wgt_table && evbdd_test_gc_wgt_table()) { + evbdd_protect(a); + evbdd_protect(b); + evbdd_gc_wgt_table(); + evbdd_unprotect(a); + evbdd_unprotect(b); + } +} + +static void +norm_commuting_cache_key(EVBDD a, EVBDD b, EVBDD *x, EVBDD *y) +{ + if (a < b) { + *x = a; + *y = b; + } + else { + *x = b; + *y = a; + } +} + +TASK_IMPL_2(EVBDD, evbdd_plus, EVBDD, a, EVBDD, b) +{ + // Trivial cases + if(EVBDD_WEIGHT(a) == EVBDD_ZERO) return b; + if(EVBDD_WEIGHT(b) == EVBDD_ZERO) return a; + + sylvan_gc_test(); + + // Get var(a) and var(b) + EVBDD low_a, low_b, high_a, high_b, res; + BDDVAR var_a = UINT32_MAX, var_b = UINT32_MAX, topvar; + if (EVBDD_TARGET(a) != EVBDD_TERMINAL) { + evbddnode_t node = EVBDD_GETNODE(EVBDD_TARGET(a)); + var_a = evbddnode_getvar(node); + } + if (EVBDD_TARGET(b) != EVBDD_TERMINAL) { + evbddnode_t node = EVBDD_GETNODE(EVBDD_TARGET(b)); + var_b = evbddnode_getvar(node); + } + + // For both a and b, get children of node with var=top{topvar(a),topvar(b)} + evbdd_get_topvar(a, var_b, &topvar, &low_a, &high_a); + evbdd_get_topvar(b, var_a, &topvar, &low_b, &high_b); + + // Base/terminal case: same target and same variable + if(EVBDD_TARGET(a) == EVBDD_TARGET(b) && var_a == var_b){ + EVBDD_WGT sum = wgt_add(EVBDD_WEIGHT(a), EVBDD_WEIGHT(b)); + res = evbdd_bundle(EVBDD_TARGET(a), sum); + return res; + } + + // Check cache + EVBDD x, y; + 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_EVBDD_PLUS, sylvan_false, x, y, &res)) { + sylvan_stats_count(EVBDD_PLUS_CACHED); + return res; + } + } + + // If not base/terminal case, pass edge weight of current edge down + EVBDD_WGT wgt_la, wgt_ha, wgt_lb, wgt_hb; + wgt_la = wgt_mul(EVBDD_WEIGHT(a), EVBDD_WEIGHT(low_a)); + wgt_ha = wgt_mul(EVBDD_WEIGHT(a), EVBDD_WEIGHT(high_a)); + wgt_lb = wgt_mul(EVBDD_WEIGHT(b), EVBDD_WEIGHT(low_b)); + wgt_hb = wgt_mul(EVBDD_WEIGHT(b), EVBDD_WEIGHT(high_b)); + low_a = evbdd_refs_push(evbdd_bundle(EVBDD_TARGET(low_a), wgt_la)); + high_a = evbdd_refs_push(evbdd_bundle(EVBDD_TARGET(high_a), wgt_ha)); + low_b = evbdd_refs_push(evbdd_bundle(EVBDD_TARGET(low_b), wgt_lb)); + high_b = evbdd_refs_push(evbdd_bundle(EVBDD_TARGET(high_b), wgt_hb)); + + // Recursive calls down + evbdd_refs_spawn(SPAWN(evbdd_plus, high_a, high_b)); + EVBDD low = evbdd_refs_push(CALL(evbdd_plus, low_a, low_b)); + EVBDD high = evbdd_refs_sync(SYNC(evbdd_plus)); + evbdd_refs_pop(5); + + // Put in cache, return + res = evbdd_makenode(topvar, low, high); + if (cachenow) { + if (cache_put3(CACHE_EVBDD_PLUS, sylvan_false, x, y, res)) + sylvan_stats_count(EVBDD_PLUS_CACHEDPUT); + } + return res; +} + + + +/* Wrapper for matrix vector multiplication. */ +TASK_IMPL_3(EVBDD, evbdd_matvec_mult, EVBDD, mat, EVBDD, vec, BDDVAR, nvars) +{ + evbdd_do_before_mult(&mat, &vec); + evbdd_refs_push(mat); evbdd_refs_push(vec); + EVBDD res = CALL(evbdd_matvec_mult_rec, mat, vec, nvars, 0); + evbdd_refs_pop(2); + return res; +} + +/* Wrapper for matrix vector multiplication. */ +TASK_IMPL_3(EVBDD, evbdd_matmat_mult, EVBDD, a, EVBDD, b, BDDVAR, nvars) +{ + evbdd_do_before_mult(&a, &b); + evbdd_refs_push(a); evbdd_refs_push(b); + EVBDD res = CALL(evbdd_matmat_mult_rec, a, b, nvars, 0); + evbdd_refs_pop(2); + return res; +} + +TASK_IMPL_4(EVBDD, evbdd_matvec_mult_rec, EVBDD, mat, EVBDD, vec, BDDVAR, nvars, BDDVAR, nextvar) +{ + // Trivial case: either one is all 0 + if (EVBDD_WEIGHT(mat) == EVBDD_ZERO || EVBDD_WEIGHT(vec) == EVBDD_ZERO) + return evbdd_bundle(EVBDD_TERMINAL, EVBDD_ZERO); + + // Terminal case: past last variable + if (nextvar == nvars) { + assert(EVBDD_TARGET(mat) == EVBDD_TERMINAL); + assert(EVBDD_TARGET(vec) == EVBDD_TERMINAL); + EVBDD_WGT prod = wgt_mul(EVBDD_WEIGHT(mat), EVBDD_WEIGHT(vec)); + return evbdd_bundle(EVBDD_TERMINAL, prod); + } + + sylvan_gc_test(); + + // Check cache + EVBDD res; + bool cachenow = ((nextvar % granularity) == 0); + if (cachenow) { + if (cache_get3(CACHE_EVBDD_MATVEC_MULT, nextvar, EVBDD_TARGET(mat), EVBDD_TARGET(vec), &res)) { + sylvan_stats_count(EVBDD_MULT_CACHED); + // 6. multiply w/ product of root weights + EVBDD_WGT prod = wgt_mul(EVBDD_WEIGHT(mat), EVBDD_WEIGHT(vec)); + EVBDD_WGT new_weight = wgt_mul(prod, EVBDD_WEIGHT(res)); + res = evbdd_bundle(EVBDD_TARGET(res), new_weight); + return res; + } + } + + // Recursive multiplication + // 1. get relevant nodes for both EVBDDs + BDDVAR var; + EVBDD vec_low, vec_high, mat_low, mat_high, u00, u10, u01, u11; + evbdd_get_topvar(vec, nextvar, &var, &vec_low, &vec_high); + evbdd_get_topvar(mat, 2*nextvar, &var, &mat_low, &mat_high); + evbdd_get_topvar(mat_low, 2*nextvar+1, &var, &u00, &u10); + evbdd_get_topvar(mat_high,2*nextvar+1, &var, &u01, &u11); + + // 2. propagate "in-between" weights of matrix EVBDD + u00 = evbdd_bundle(EVBDD_TARGET(u00), wgt_mul(EVBDD_WEIGHT(u00), EVBDD_WEIGHT(mat_low))); + u10 = evbdd_bundle(EVBDD_TARGET(u10), wgt_mul(EVBDD_WEIGHT(u10), EVBDD_WEIGHT(mat_low))); + u01 = evbdd_bundle(EVBDD_TARGET(u01), wgt_mul(EVBDD_WEIGHT(u01), EVBDD_WEIGHT(mat_high))); + u11 = evbdd_bundle(EVBDD_TARGET(u11), wgt_mul(EVBDD_WEIGHT(u11), EVBDD_WEIGHT(mat_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| + EVBDD res_low00, res_low10, res_high01, res_high11; // [GC refs stack] + evbdd_refs_spawn(SPAWN(evbdd_matvec_mult_rec, u00, vec_low, nvars, nextvar+1)); // fork 1 + evbdd_refs_spawn(SPAWN(evbdd_matvec_mult_rec, u10, vec_low, nvars, nextvar+1)); // fork 2 + evbdd_refs_spawn(SPAWN(evbdd_matvec_mult_rec, u01, vec_high, nvars, nextvar+1)); // fork 3 + res_high11 = evbdd_refs_push(CALL(evbdd_matvec_mult_rec, u11, vec_high, nvars, nextvar+1));// [res_high11] + res_high01 = evbdd_refs_sync(SYNC(evbdd_matvec_mult_rec)); // join 3 [res_high11] + evbdd_refs_pop(1); // [] + EVBDD res_high = evbdd_refs_push(evbdd_makenode(nextvar, res_high01, res_high11)); // [res_high] + res_low10 = evbdd_refs_push(evbdd_refs_sync(SYNC(evbdd_matvec_mult_rec))); // join 2 [res_low10,res_high] + res_low00 = evbdd_refs_sync(SYNC(evbdd_matvec_mult_rec)); // join 1 [res_low10,res_high] + evbdd_refs_pop(1); // [res_high] + EVBDD res_low = evbdd_refs_push(evbdd_makenode(nextvar, res_low00, res_low10)); // [res_low,res_high] + + // 4. add resulting EVBDDs + res = CALL(evbdd_plus, res_low, res_high); // [res_low,res_high] + evbdd_refs_pop(2); // [] + + // Insert in cache (before multiplication w/ root weights) + if (cachenow) { + if (cache_put3(CACHE_EVBDD_MATVEC_MULT, nextvar, EVBDD_TARGET(mat), EVBDD_TARGET(vec), res)) + sylvan_stats_count(EVBDD_MULT_CACHEDPUT); + } + + // 5. multiply w/ product of root weights + EVBDD_WGT prod = wgt_mul(EVBDD_WEIGHT(mat), EVBDD_WEIGHT(vec)); + EVBDD_WGT new_weight = wgt_mul(prod, EVBDD_WEIGHT(res)); + res = evbdd_bundle(EVBDD_TARGET(res), new_weight); + + return res; +} + +TASK_IMPL_4(EVBDD, evbdd_matmat_mult_rec, EVBDD, a, EVBDD, b, BDDVAR, nvars, BDDVAR, nextvar) +{ + // Trivial case: either one is all 0 + if (EVBDD_WEIGHT(a) == EVBDD_ZERO || EVBDD_WEIGHT(b) == EVBDD_ZERO) + return evbdd_bundle(EVBDD_TERMINAL, EVBDD_ZERO); + + // Terminal case: past last variable + if (nextvar == nvars) { + assert(EVBDD_TARGET(a) == EVBDD_TERMINAL); + assert(EVBDD_TARGET(b) == EVBDD_TERMINAL); + EVBDD_WGT prod = wgt_mul(EVBDD_WEIGHT(a), EVBDD_WEIGHT(b)); + return evbdd_bundle(EVBDD_TERMINAL, prod); + } + + sylvan_gc_test(); + + // Check cache + EVBDD res; + bool cachenow = ((nextvar % granularity) == 0); + if (cachenow) { + if (cache_get3(CACHE_EVBDD_MATMAT_MULT, nextvar, EVBDD_TARGET(a), EVBDD_TARGET(b), &res)) { + sylvan_stats_count(EVBDD_MULT_CACHED); + // 7. multiply w/ product of root weights + EVBDD_WGT prod = wgt_mul(EVBDD_WEIGHT(a), EVBDD_WEIGHT(b)); + EVBDD_WGT new_weight = wgt_mul(prod, EVBDD_WEIGHT(res)); + res = evbdd_bundle(EVBDD_TARGET(res), new_weight); + return res; + } + } + + // Recursive multiplication + // 1. get relevant nodes for both EVBDDs + BDDVAR var; + EVBDD a_low, a_high, a00, a10, a01, a11, b_low, b_high, b00, b10, b01, b11; + evbdd_get_topvar(a, 2*nextvar, &var, &a_low, &a_high); + evbdd_get_topvar(b, 2*nextvar, &var, &b_low, &b_high); + evbdd_get_topvar(a_low, 2*nextvar+1, &var, &a00, &a10); + evbdd_get_topvar(a_high,2*nextvar+1, &var, &a01, &a11); + evbdd_get_topvar(b_low, 2*nextvar+1, &var, &b00, &b10); + evbdd_get_topvar(b_high,2*nextvar+1, &var, &b01, &b11); + + // 2. propagate "in-between" weights down + a00 = evbdd_bundle(EVBDD_TARGET(a00), wgt_mul(EVBDD_WEIGHT(a_low), EVBDD_WEIGHT(a00))); + a10 = evbdd_bundle(EVBDD_TARGET(a10), wgt_mul(EVBDD_WEIGHT(a_low), EVBDD_WEIGHT(a10))); + a01 = evbdd_bundle(EVBDD_TARGET(a01), wgt_mul(EVBDD_WEIGHT(a_high),EVBDD_WEIGHT(a01))); + a11 = evbdd_bundle(EVBDD_TARGET(a11), wgt_mul(EVBDD_WEIGHT(a_high),EVBDD_WEIGHT(a11))); + b00 = evbdd_bundle(EVBDD_TARGET(b00), wgt_mul(EVBDD_WEIGHT(b_low), EVBDD_WEIGHT(b00))); + b10 = evbdd_bundle(EVBDD_TARGET(b10), wgt_mul(EVBDD_WEIGHT(b_low), EVBDD_WEIGHT(b10))); + b01 = evbdd_bundle(EVBDD_TARGET(b01), wgt_mul(EVBDD_WEIGHT(b_high),EVBDD_WEIGHT(b01))); + b11 = evbdd_bundle(EVBDD_TARGET(b11), wgt_mul(EVBDD_WEIGHT(b_high),EVBDD_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| + EVBDD a00_b00, a00_b01, a10_b00, a10_b01, a01_b10, a01_b11, a11_b10, a11_b11; // [GC refs stack] + evbdd_refs_spawn(SPAWN(evbdd_matmat_mult_rec, a00, b00, nvars, nextvar+1)); // fork 1 + evbdd_refs_spawn(SPAWN(evbdd_matmat_mult_rec, a10, b00, nvars, nextvar+1)); // fork 2 + evbdd_refs_spawn(SPAWN(evbdd_matmat_mult_rec, a00, b01, nvars, nextvar+1)); // fork 3 + evbdd_refs_spawn(SPAWN(evbdd_matmat_mult_rec, a10, b01, nvars, nextvar+1)); // fork 4 + evbdd_refs_spawn(SPAWN(evbdd_matmat_mult_rec, a01, b10, nvars, nextvar+1)); // fork 5 + evbdd_refs_spawn(SPAWN(evbdd_matmat_mult_rec, a11, b10, nvars, nextvar+1)); // fork 6 + evbdd_refs_spawn(SPAWN(evbdd_matmat_mult_rec, a01, b11, nvars, nextvar+1)); // fork 7 + a11_b11 = evbdd_refs_push(CALL(evbdd_matmat_mult_rec, a11, b11, nvars, nextvar+1)); // [a11_b11] + a01_b11 = evbdd_refs_sync(SYNC(evbdd_matmat_mult_rec)); // join 7 [a11_b11] + evbdd_refs_pop(1); // [] + EVBDD rh2 = evbdd_refs_push(evbdd_makenode(2*nextvar+1, a01_b11, a11_b11)); // [rh2] + a11_b10 = evbdd_refs_push(evbdd_refs_sync(SYNC(evbdd_matmat_mult_rec))); // join 6 [a11_b10,rh2] + a01_b10 = evbdd_refs_sync(SYNC(evbdd_matmat_mult_rec)); // join 5 [a11_b10,rh2] + evbdd_refs_pop(1); // [rh2] + EVBDD lh2 = evbdd_refs_push(evbdd_makenode(2*nextvar+1, a01_b10, a11_b10)); // [lh2,rh2] + a10_b01 = evbdd_refs_push(evbdd_refs_sync(SYNC(evbdd_matmat_mult_rec))); // join 4 [b10_b01,lh2,rh2] + a00_b01 = evbdd_refs_sync(SYNC(evbdd_matmat_mult_rec)); // join 3 [b10_b01,lh2,rh2] + evbdd_refs_pop(1); // [lh2,rh2] + EVBDD rh1 = evbdd_refs_push(evbdd_makenode(2*nextvar+1, a00_b01, a10_b01)); // [rh1,lh2,rh2] + a10_b00 = evbdd_refs_push(evbdd_refs_sync(SYNC(evbdd_matmat_mult_rec))); // join 2 [b10_b00,rh1,lh2,rh2] + a00_b00 = evbdd_refs_sync(SYNC(evbdd_matmat_mult_rec)); // join 1 [b10_b00,rh1,lh2,rh2] + evbdd_refs_pop(1); // [rh1,lh2,rh2] + EVBDD lh1 = evbdd_refs_push(evbdd_makenode(2*nextvar+1, a00_b00, a10_b00)); // [lh1,rh1,lh2,rh2] + + // 4. add resulting EVBDDs + EVBDD lh, rh; + evbdd_refs_spawn(SPAWN(evbdd_plus, lh1, lh2)); + rh = CALL(evbdd_plus, rh1, rh2); + evbdd_refs_push(rh); // [rh,lh1,rh1,lh2,rh2] + lh = evbdd_refs_sync(SYNC(evbdd_plus)); // [rh,lh1,rh1,lh2,rh2] + evbdd_refs_pop(5); // [] + + // 5. put left and right halves of matix together + res = evbdd_makenode(2*nextvar, lh, rh); + + // Insert in cache + if (cachenow) { + if (cache_put3(CACHE_EVBDD_MATMAT_MULT, nextvar, EVBDD_TARGET(a), EVBDD_TARGET(b), res)) + sylvan_stats_count(EVBDD_MULT_CACHEDPUT); + } + + // 6. multiply w/ product of root weights + EVBDD_WGT prod = wgt_mul(EVBDD_WEIGHT(a), EVBDD_WEIGHT(b)); + EVBDD_WGT new_weight = wgt_mul(prod, EVBDD_WEIGHT(res)); + res = evbdd_bundle(EVBDD_TARGET(res), new_weight); + + return res; +} + +TASK_IMPL_4(EVBDD_WGT, evbdd_inner_product, EVBDD, a, EVBDD, b, BDDVAR, nvars, BDDVAR, nextvar) +{ + if (EVBDD_WEIGHT(a) == EVBDD_ZERO) return EVBDD_ZERO; + if (EVBDD_WEIGHT(b) == EVBDD_ZERO) return EVBDD_ZERO; + + // Terminal case: currently evbdd_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(EVBDD_WEIGHT(a), wgt_conj(EVBDD_WEIGHT(b))); + } + + // Get var(a) and var(b) + EVBDD 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)} + evbdd_get_topvar(a, nextvar, &topvar, &low_a, &high_a); + evbdd_get_topvar(b, nextvar, &topvar, &low_b, &high_b); + + // Check cache + // TODO: norm cache key? ( = ^\dagger) + EVBDD_WGT res; + bool cachenow = ((topvar % granularity) == 0); + if (cachenow) { + if (cache_get4(CACHE_EVBDD_INPROD, EVBDD_TARGET(a), EVBDD_TARGET(b), nextvar, nvars, &res)) { + res = wgt_mul(res, EVBDD_WEIGHT(a)); + res = wgt_mul(res, wgt_conj(EVBDD_WEIGHT(b))); + return res; + } + } + + // Recursive calls + evbdd_refs_spawn(SPAWN(evbdd_inner_product, high_a, high_b, nvars, nextvar+1)); + EVBDD_WGT res_low = evbdd_refs_push(CALL(evbdd_inner_product, low_a, low_b, nvars, nextvar+1)); + EVBDD_WGT res_high = evbdd_refs_sync(SYNC(evbdd_inner_product)); + evbdd_refs_pop(1); + + res = wgt_add(res_low, res_high); + + // Insert in cache (before multiplication w/ root weights) + if (cachenow) { + cache_put4(CACHE_EVBDD_INPROD, EVBDD_TARGET(a), EVBDD_TARGET(b), nextvar, nvars, res); + } + + // 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, EVBDD_WEIGHT(a)); + res = wgt_mul(res, wgt_conj(EVBDD_WEIGHT(b))); + return res; +} + +EVBDD +evbdd_increase_all_vars(EVBDD a, int k) +{ + if (EVBDD_TARGET(a) == EVBDD_TERMINAL) { + return a; + } + + // Check cache + EVBDD res; + if (cache_get3(CACHE_EVBDD_INC_VARS, EVBDD_TARGET(a), k, 0, &res)) { + return evbdd_bundle(res, EVBDD_WEIGHT(a)); + } + + // Get node info + EVBDD low, high; + evbddnode_t node = EVBDD_GETNODE(EVBDD_TARGET(a)); + evbddnode_getchilderen(node, &low, &high); + BDDVAR curvar = evbddnode_getvar(node); + + // Recursive apply to children (TODO: lace?) + low = evbdd_increase_all_vars(low, k); + high = evbdd_increase_all_vars(high, k); + res = evbdd_makenode(curvar+k, low, high); + + // We assume the input EVBDDs are already normalized in terms of edge weights + // so we expect no normalization is needed + assert(EVBDD_WEIGHT(res) == EVBDD_ONE); + + // Put res (ptr) in cache and return + cache_put3(CACHE_EVBDD_INC_VARS, EVBDD_TARGET(a), k, 0, EVBDD_TARGET(res)); + return evbdd_bundle(EVBDD_TARGET(res), EVBDD_WEIGHT(a)); +} + +EVBDD +evbdd_replace_terminal(EVBDD a, EVBDD_TARG b) +{ + if (EVBDD_TARGET(a) == EVBDD_TERMINAL) { + return evbdd_bundle(b, EVBDD_WEIGHT(a)); + } + + // Check cache + EVBDD res; + if (cache_get3(CACHE_EVBDD_REPLACE_TERMINAL, EVBDD_TARGET(a), b, 0, &res)) { + return evbdd_bundle(res, EVBDD_WEIGHT(a)); + } + + // Get node info + EVBDD low, high; + evbddnode_t node = EVBDD_GETNODE(EVBDD_TARGET(a)); + evbddnode_getchilderen(node, &low, &high); + BDDVAR var = evbddnode_getvar(node); + + // Recursive apply to children and makenode (TODO: lace?) + low = evbdd_replace_terminal(low, b); + high = evbdd_replace_terminal(high, b); + res = evbdd_makenode(var, low, high); + + // We assume the input EVBDDs are already normalized in terms of edge weights + // so we expect no normalization is needed + assert(EVBDD_WEIGHT(res) == EVBDD_ONE); + + // Put res (ptr) in cache and return + cache_put3(CACHE_EVBDD_REPLACE_TERMINAL, EVBDD_TARGET(a), b, 0, EVBDD_TARGET(res)); + return evbdd_bundle(EVBDD_TARGET(res), EVBDD_WEIGHT(a)); +} + +EVBDD +evbdd_tensor_prod(EVBDD a, EVBDD b, BDDVAR nvars_a) +{ + // Shift all vars of 'b' by 'nvars_a' + b = evbdd_increase_all_vars(b, nvars_a); + + // Stack 'a' on top of 'b' (and multiply root edge of 'a' with that of 'b') + EVBDD res = evbdd_replace_terminal(a, EVBDD_TARGET(b)); + EVBDD_WGT new_weight = wgt_mul(EVBDD_WEIGHT(res), EVBDD_WEIGHT(b)); + res = evbdd_bundle(EVBDD_TARGET(res), new_weight); + + return res; +} + +/***************************************************/ + + + + + +/******************************************************/ + + +/** + * Helper function for recursive unmarking + */ +static void +evbdd_unmark_rec(EVBDD a) +{ + if (EVBDD_TARGET(a) == EVBDD_TERMINAL) return; + evbddnode_t n = EVBDD_GETNODE(EVBDD_TARGET(a)); + if (!evbddnode_getmark(n)) return; + evbddnode_setmark(n, 0); + evbdd_unmark_rec(evbddnode_getptrlow(n)); + evbdd_unmark_rec(evbddnode_getptrhigh(n)); +} + +/** + * Counts nodes in the EVBDD by marking them. + */ +static uint64_t +evbdd_nodecount_mark(EVBDD a) +{ + if (EVBDD_TARGET(a) == EVBDD_TERMINAL) return 0; // don't (repeat) count terminal + evbddnode_t n = EVBDD_GETNODE(EVBDD_TARGET(a)); + if (evbddnode_getmark(n)) return 0; + evbddnode_setmark(n, 1); + return 1 + evbdd_nodecount_mark(evbddnode_getptrlow(n)) + evbdd_nodecount_mark(evbddnode_getptrhigh(n)); +} + +uint64_t +evbdd_countnodes(EVBDD a) +{ + uint64_t res = evbdd_nodecount_mark(a) + 1; // (+ 1 for terminal "node") + evbdd_unmark_rec(a); + return res; +} + +/*****************************************************/ + + + + + +/*****************************************************/ + +/** + * Pretty prints the information contained in `n`. + */ +static void evbddnode_pprint(evbddnode_t n) +{ + BDDVAR var = evbddnode_getvar(n); + EVBDD low, high; + evbddnode_getchilderen(n, &low, &high); + printf("[var=%d, low=%" PRIu64 ", high=%" PRIu64 ", ", + var, + EVBDD_TARGET(low), + EVBDD_TARGET(high)); + if(EVBDD_WEIGHT(low) == EVBDD_ZERO) printf("a=EVBDD_ZERO, "); + else if(EVBDD_WEIGHT(high) == EVBDD_ONE) printf("a=EVBDD_ONE, "); + else { + printf("a=%" PRIu64 ", ", EVBDD_WEIGHT(low)); + printf("("); wgt_fprint(stdout, EVBDD_WEIGHT(low)); printf(")"); + } + if(EVBDD_WEIGHT(high) == EVBDD_ZERO) printf("b=EVBDD_ZERO "); + else if(EVBDD_WEIGHT(high) == EVBDD_ONE) printf("b=EVBDD_ONE, "); + else { + printf("b=%" PRIu64, EVBDD_WEIGHT(high)); + printf("("); wgt_fprint(stdout, EVBDD_WEIGHT(high)); printf(")"); + } + printf("]\n"); +} + +void +_print_evbdd(EVBDD a) +{ + if(EVBDD_TARGET(a) != EVBDD_TERMINAL){ + evbddnode_t node = EVBDD_GETNODE(EVBDD_TARGET(a)); + if(!evbddnode_getmark(node)){ + evbddnode_setmark(node, 1); + printf("%" PRIu64 "\t", EVBDD_TARGET(a)); + evbddnode_pprint(node); + EVBDD low, high; + evbddnode_getchilderen(node, &low, &high); + _print_evbdd(low); + _print_evbdd(high); + } + } +} + +void +evbdd_printnodes(EVBDD a) +{ + printf("root edge: %" PRIu64 ", %" PRIu64 " = ",EVBDD_TARGET(a), EVBDD_WEIGHT(a)); + wgt_fprint(stdout, EVBDD_WEIGHT(a)); + printf("\n"); + _print_evbdd(a); + evbdd_unmark_rec(a); +} + +static void +evbdd_fprintdot_edge_label(FILE *out, EVBDD_WGT w) +{ + fprintf(out, ", label=\""); + if (w == EVBDD_ONE) {} + else if (w == EVBDD_ZERO) { fprintf(out, "0"); } + else if (w == EVBDD_MIN_ONE) { fprintf(out, "-1"); } + else { wgt_fprint(out, w); } + fprintf(out, "\""); +} + +static void +evbdd_fprintdot_rec(FILE *out, EVBDD a, bool draw_zeros) +{ + // terminal node + if(EVBDD_TARGET(a) == EVBDD_TERMINAL) return; + + evbddnode_t n = EVBDD_GETNODE(EVBDD_TARGET(a)); + if (evbddnode_getmark(n)) return; + evbddnode_setmark(n, 1); + + // add this node + fprintf(out, "%" PRIu64 " [label=\"%" PRIu32 "\"];\n", + EVBDD_TARGET(a), evbddnode_getvar(n)); + + + // children of this node + EVBDD low, high; + evbddnode_getchilderen(n, &low, &high); + evbdd_fprintdot_rec(out, low, draw_zeros); + evbdd_fprintdot_rec(out, high, draw_zeros); + + // add edge from this node to each child (unless weight 0) + if (draw_zeros || EVBDD_WEIGHT(low) != EVBDD_ZERO) { + fprintf(out, "%" PRIu64 " -> %" PRIu64 " [style=dashed", + EVBDD_TARGET(a), EVBDD_TARGET(low)); + evbdd_fprintdot_edge_label(out, EVBDD_WEIGHT(low)); + fprintf(out, "];\n"); + } + if (draw_zeros || EVBDD_WEIGHT(high) != EVBDD_ZERO) { + fprintf(out, "%" PRIu64 " -> %" PRIu64 " [style=solid", + EVBDD_TARGET(a), EVBDD_TARGET(high)); + evbdd_fprintdot_edge_label(out, EVBDD_WEIGHT(high)); + fprintf(out, "];\n"); + } +} + +void +evbdd_fprintdot(FILE *out, EVBDD a, bool draw_zeros) +{ + fprintf(out, "digraph \"DD\" {\n"); + fprintf(out, "center = true;\n"); + fprintf(out, "edge [dir=forward];\n"); + fprintf(out, "root [style=invis];\n"); + fprintf(out, "root -> %" PRIu64 " [style=solid", EVBDD_TARGET(a)); + evbdd_fprintdot_edge_label(out, EVBDD_WEIGHT(a)); + fprintf(out, "];\n"); + + // terminal node + fprintf(out, "%" PRIu64 " [shape=box, label=\"T\"];\n", EVBDD_TERMINAL); + + // recursively add nodes + evbdd_fprintdot_rec(out, a, draw_zeros); + evbdd_unmark_rec(a); + + fprintf(out, "}\n"); +} + +/****************************************************/ + + + + + +/*****************************************************************/ + +bool +evbdd_equivalent(EVBDD a, EVBDD b, int n, bool exact, bool verbose) +{ + bool has_next = true; + EVBDD_WGT wgt_a, wgt_b; + bool x[n]; + for(int k=0; k= nvars || var < nextvar) return false; + + // Check cache + uint64_t res; + bool cachenow = ((var % granularity) == 0); + if (cachenow) { + if (cache_get3(CACHE_EVBDD_IS_ORDERED, EVBDD_TARGET(a), 0, 0, &res)) { + return (bool) res; + } + } + + // Recursive calls + bool res_low, res_high; + var++; + res_low = evbdd_is_ordered_rec(low, var, nvars); + res_high = evbdd_is_ordered_rec(high, var, nvars); + var--; + res = (res_low && res_high); + + // Put res in cache and return + if (cachenow) cache_put3(CACHE_EVBDD_IS_ORDERED, EVBDD_TARGET(a), 0, 0, res); + return res; +} + +bool +_next_bitstring(bool *x, int n) +{ + // binary add 1 + bool success = false; + for(int k=0; k=0; k--) printf("%d", x[k]); + else + for(int k=0; k= 0; i--) { + if (x[i] == 1) res |= k; + k = k<<1; + } + } + else { + for (int i = 0; i < n; i++) { + if (x[i] == 1) res |= k; + k = k<<1; + } + } + return res; +} + +bool * +int_to_bitarray(uint64_t n, int length, bool MSB_first) +{ + if (length <= 0) length = (int) ceil(log2(n)); + bool *res = malloc(sizeof(bool) * length); + if (MSB_first) { + for (int i = length-1; i >= 0; i--) { + res[i] = (n & 1LL); + n = n>>1; + } + } + else { + for (int i = 0; i < length; i++) { + res[i] = (n & 1LL); + n = n>>1; + } + } + return res; +} + +bool +bit_from_int(uint64_t a, uint8_t index) +{ + // assumes index=0 is the LSB + uint64_t mask = 1<>index; + return (bool) res; +} + +void +reverse_bit_array(bool *x, int length) +{ + bool tmp; + for(int i = 0; i<(length/2); i++){ + tmp = x[i]; + x[i] = x[length-i-1]; + x[length-i-1] = tmp; + } +} + +/****************************************************************/ diff --git a/src/sylvan_evbdd.h b/src/sylvan_evbdd.h new file mode 100644 index 0000000..34af9ec --- /dev/null +++ b/src/sylvan_evbdd.h @@ -0,0 +1,281 @@ +#ifndef SYLVAN_EVBDD_H +#define SYLVAN_EVBDD_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef uint64_t EVBDD; +typedef uint64_t EVBDD_WGT; // Edge weight +typedef uint64_t EVBDD_TARG; // Edge target + +static const EVBDD_TARG EVBDD_TERMINAL = 1; +static const BDDVAR EVBDD_INVALID_VAR = UINT8_MAX; + +typedef enum weight_norm_strategy { + NORM_LOW, + NORM_MAX, + NORM_MIN, + NORM_L2, + n_norm_strategies +} weight_norm_strategy_t; + + +/*************************************/ + +VOID_TASK_DECL_1(evbdd_gc_mark_rec, EVBDD); +#define evbdd_gc_mark_rec(a) RUN(evbdd_gc_mark_rec, a) + +/** + * Store the pointer in the pointers table. + */ +void evbdd_protect(EVBDD* a); + +/** + * Delete the pointer from the pointers table. + */ +void evbdd_unprotect(EVBDD* a); + +/** + * Compute the number of pointers in the pointers table. + */ +size_t evbdd_count_protected(void); + +/** + * Push an EVBDD variable to the pointer reference stack. + * During gc the variable will be inspected and the contents will be marked. + */ +void evbdd_refs_pushptr(const EVBDD *a); + +/** + * Pop the last EVBDD variables from the pointer reference stack. + */ +void evbdd_refs_popptr(size_t amount); + +/** + * Push an EVBDD to the values reference stack. + * During garbage collection the references EVBDD will be marked. + */ +EVBDD evbdd_refs_push(EVBDD a); + +/** + * Pop the last EVBDDs from the values reference stack. + */ +void evbdd_refs_pop(long amount); + +/** + * Push a Task that returns an EVBDD to the tasks reference stack. + * Usage: evbdd_refs_spawn(SPAWN(function, ...)); + */ +void evbdd_refs_spawn(Task *t); + +/** + * Pop a Task from the task reference stack. + * Usage: EVBDD result = evbdd_refs_sync(SYNC(function)); + */ +EVBDD evbdd_refs_sync(EVBDD a); + +/************************************/ + + + + + +/**************************************************/ + +/* enabled by default */ +void evbdd_set_auto_gc_wgt_table(bool enabled); +/* default 0.5 */ +void evbdd_set_gc_wgt_table_thres(double fraction_filled); +double evbdd_get_gc_wgt_table_thres(); +void evbdd_gc_wgt_table(); +bool evbdd_test_gc_wgt_table(); + +/** + * Recursive function for moving weights from old to new edge weight table. + */ +#define _fill_new_wgt_table(a) (RUN(_fill_new_wgt_table, a)) +TASK_DECL_1(EVBDD, _fill_new_wgt_table, EVBDD); + +/*************************************************/ + + + + + +/**************************************************************/ + +/** + * Similar initialization as for MTBDDs + edge weight table init. + * Setting tolerance to -1 uses default tolerance. + * real table: stores 2 real values per edge weight, instead of 1 tuple + * NOTE: this function doesn't currently check if the combination of table + * sizes (edge weight table + node table) works in combination with using + * a real-table or complex-table. + * - init_wgt_tab_entries() is a pointer to a function which is called after gc + * of edge table. This can be used to reinitialize edge weight table values + * outside of any EVBDD. Can be NULL. + */ +void sylvan_init_evbdd(size_t min_wgt_tablesize, size_t max_wgt_tablesize, double wgt_tab_tolerance, int edge_weigth_backend, int norm_strat, void *init_wgt_tab_entries); +void sylvan_init_evbdd_defaults(size_t min_wgt_tablesize, size_t max_wgt_tablesize); +void evbdd_set_caching_granularity(int granularity); + +/*************************************************************/ + + + + + +/****************************************************/ + +/** + * Get the EVBDD value corresponding to the given (bool array of length + * nvars(a)). + */ +EVBDD_WGT evbdd_getvalue(EVBDD a, bool* path); + +/** + * Recursive implementation of vector addition. + */ +#define evbdd_plus(a,b) (RUN(evbdd_plus,a,b)) +TASK_DECL_2(EVBDD, evbdd_plus, EVBDD, EVBDD); + + +/* Computes Mat * |vec> (Wrapper function) */ +#define evbdd_matvec_mult(mat,vec,nvars) (RUN(evbdd_matvec_mult,mat,vec,nvars)) +TASK_DECL_3(EVBDD, evbdd_matvec_mult, EVBDD, EVBDD, BDDVAR); + +/* Computes A*B (note generally AB != BA) (Wrapper function) */ +#define evbdd_matmat_mult(a,b,nvars) (RUN(evbdd_matmat_mult,a,b,nvars)) +TASK_DECL_3(EVBDD, evbdd_matmat_mult, EVBDD, EVBDD, BDDVAR); + +/** + * Recursive implementation of matrix-vector mult and matrix-matrix mult. + */ +TASK_DECL_4(EVBDD, evbdd_matvec_mult_rec, EVBDD, EVBDD, BDDVAR, BDDVAR); +TASK_DECL_4(EVBDD, evbdd_matmat_mult_rec, EVBDD, EVBDD, BDDVAR, BDDVAR); + + +/** + * Computes inner product of two vectors + * (Note that if b contains complex values, the complex conjugate is taken) +*/ +#define evbdd_inner_product(a,b,nvars) (RUN(evbdd_inner_product,a,b,nvars,0)) +TASK_DECL_4(EVBDD_WGT, evbdd_inner_product, EVBDD, EVBDD, BDDVAR, BDDVAR); + +/** + * Increases all the variable number in EVBDD a by k (used for tensor product) + * + * @param a EVBDD over n vars {j, j+1, ..., j+n-1} (generally j=0) + * + * @return EVBDD over n vars {j+k, j+k+1, ..., j+k+n-1} + */ +EVBDD evbdd_increase_all_vars(EVBDD a, int k); + +/* Replace the terminal node in a with b (effectively stacks a and b) +* (used for tensor product) +*/ +EVBDD evbdd_replace_terminal(EVBDD a, EVBDD_TARG b); + +/** + * @param a EVBDD over vars 0...n-1 (n = nvars_a) + * @param b EVBDD over vars 0...m-1 + * @param nvars_a number of vars of EVBDD a + * + * @return EVBDD over vars 0...n-1...(n+m)-1, representing a (tensor) b + */ +EVBDD evbdd_tensor_prod(EVBDD a, EVBDD b, BDDVAR nvars_a); + +/** + * Computes the tensor product of vec (tensor) vec + * + * @param a EVBDD over vars 0...n-1 (n = nvars_a) + * @param b EVBDD over vars 0...m-1 + * @param nvars_a number of vars of EVBDD a + * + * @return EVBDD over vars 0...n-1...(n+m)-1, representing a (tensor) b + */ +#define evbdd_vec_tensor_prod(a, b, nvars_a) evbdd_tensor_prod(a,b,nvars_a) + +/** + * Computes the tensor product of mat (tensor) mat + * + * @param a EVBDD over vars 0...2n-1 (n = nvars_a) + * @param b EVBDD over vars 0...2m-1 + * @param nvars_a number of vars of EVBDD a (counting only unprimed) + * + * @return EVBDD over vars 0...2n-1...(2n+2m)-1, representing a (tensor) b + */ +#define evbdd_mat_tensor_prod(a, b, nvars_a) evbdd_tensor_prod(a,b,2*nvars_a) + +/***************************************************/ + + + + + +/******************************************************/ + +/** + * Count the number of EVBDD nodes. + */ +uint64_t evbdd_countnodes(EVBDD a); + +/*****************************************************/ + + + + + +/*****************************************************/ + +/** + * Write a .dot representation of a given EVBDD + */ +void evbdd_fprintdot(FILE *out, EVBDD a, bool draw_zeros); + +/****************************************************/ + + + + + +/*****************************************************************/ + +/** + * Checks if the vectors encoded by two EVBDDs are the same. In principle the + * root edges of two identical EVBDDs should always be the same, so this is + * mostly a debug/testing function. + * + * @param n Number of variables + * @param exact If true, vec(a) should equal vec(b) exactly (float equal), + * otherwise allow for preset float equivalence margin. + * + * @returns True iff vec(a) == vec(b). + */ +bool evbdd_equivalent(EVBDD a, EVBDD b, int n, bool exact, bool verbose); + +/** Sanity check to see if the EVBDD variables are ordered and < nvars. */ +#define evbdd_is_ordered(a, nvars) evbdd_is_ordered_rec(a, 0, nvars) +bool evbdd_is_ordered_rec(EVBDD a, BDD nextvar, BDD nvars); + +void evbdd_printnodes(EVBDD a); +bool _next_bitstring(bool *x, int n); +void _print_bitstring(bool *x, int n, bool backwards); +uint64_t bitarray_to_int(bool *x, int n, bool MSB_first); +bool * int_to_bitarray(uint64_t n, int length, bool MSB_first); +bool bit_from_int(uint64_t a, uint8_t index); +void reverse_bit_array(bool *x, int length); + +/****************************************************************/ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/src/sylvan_evbdd_int.h b/src/sylvan_evbdd_int.h new file mode 100644 index 0000000..f8dbca8 --- /dev/null +++ b/src/sylvan_evbdd_int.h @@ -0,0 +1,357 @@ + +/* Do not include this file directly. Instead, include sylvan_int.h */ + +/** + * Internals for EVBDDs + */ + +#ifndef SYLVAN_EVBDD_INT_H +#define SYLVAN_EVBDD_INT_H + +#include + +/** + * These golbal variables control some of the EVBDD behavior, and are set in + * sylvan_init_evbdd(). + * TODO: Maybe handle this in a cleaner way than with global variables? + */ +// using [wgts,ptr] [33,30] bits if set to true (default [23,40]) +extern bool larger_wgt_indices; +extern int weight_norm_strat; +extern EVBDD_WGT (*normalize_weights)(EVBDD_WGT *, EVBDD_WGT *); + + +/*********************************/ + +/** + * When edge weight table <= 2^23 (larger_wgt_indices = false) + * ----------------------------------------------------------------------------- + * EVBDD edge structure (64 bits) + * 1 bit: unused + * 23 bits: index of edge weight in weight table (EVBDD_WGT) + * 40 bits: index of next node in node table (EVBDD_TARG) + * + * EVBDD 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: 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 EVBDD_ZERO (EVBDD_ONE) + * 13 bits: unused + * 40 bits: low edge pointer to next node (EVBDD_TARG) + * 64 bits high: + * 1 bit: marked/unmarked flag + * 23 bits: index of edge weight of high edge in ctable (EVBDD_WGT) + * 40 bits: high edge pointer to next node (EVBDD_TARG) + * ----------------------------------------------------------------------------- + * + * + * When edge weight table > 2^23 (larger_wgt_indices = true) + * ----------------------------------------------------------------------------- + * EVBDD edge structure (64 bits) + * 1 bit: unused + * 23 bits: index of edge weight in weight table (EVBDD_WGT) + * 40 bits: index of next node in node table (EVBDD_TARG) + * + * EVBDD 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 EVBDD_ZERO (EVBDD_ONE) + * 23 bits: unused + * 30 bits: low edge pointer to next node (EVBDD_TARG) + * 64 bits high: + * 1 bit: marked/unmarked flag + * 33 bits: index of edge weight of high edge in ctable (EVBDD_WGT) + * 30 bits: high edge pointer to next node (EVBDD_TARG) + * ----------------------------------------------------------------------------- + */ +typedef struct __attribute__((packed)) evbddnode { + EVBDD low, high; +} *evbddnode_t; // 16 bytes + +static const EVBDD evbdd_marked_mask = 0x8000000000000000LL; +static const EVBDD evbdd_var_mask_low = 0x7f80000000000000LL; +static const EVBDD evbdd_wgt_pos_mask = 0x0040000000000000LL; +static const EVBDD evbdd_wgt_val_mask = 0x0020000000000000LL; +static const EVBDD evbdd_wgt_mask_23 = 0x7fffff0000000000LL; +static const EVBDD evbdd_wgt_mask_33 = 0x7fffffffc0000000LL; +static const EVBDD evbdd_ptr_mask_30 = 0x000000003fffffffLL; +static const EVBDD evbdd_ptr_mask_40 = 0x000000ffffffffffLL; + + +/** + * Gets only the EVBDD_WGT information of an EVBDD edge. + */ +static inline EVBDD_WGT +EVBDD_WEIGHT(EVBDD a) +{ + if (larger_wgt_indices) { + return (a & evbdd_wgt_mask_33) >> 30; // 33 bits + } + else { + return (a & evbdd_wgt_mask_23) >> 40; // 23 bits + } +} + +/** + * Gets only the TARGET information of an EVBDD edge. + */ +static inline EVBDD_TARG +EVBDD_TARGET(EVBDD a) +{ + if (larger_wgt_indices) { + return a & evbdd_ptr_mask_30; // 30 bits + } + else { + return a & evbdd_ptr_mask_40; // 40 bits + } +} + +/** + * Gets the variable number of a given node `n`. + */ +static inline BDDVAR +evbddnode_getvar(evbddnode_t n) +{ + return (BDDVAR) ((n->low & evbdd_var_mask_low) >> 55 ); // 8 bits +} + +/** + * Gets only the EVBDD_TARG of the low edge of . + */ +static inline EVBDD_TARG +evbddnode_getptrlow(evbddnode_t n) +{ + return (EVBDD_TARG) EVBDD_TARGET(n->low); +} + +/** + * Gets only the EVBDD_TARG of the high edge of . + */ +static inline EVBDD_TARG +evbddnode_getptrhigh(evbddnode_t n) +{ + return (EVBDD_TARG) EVBDD_TARGET(n->high); +} + +/** + * Gets the value of the "marked" flag. + */ +static inline bool +evbddnode_getmark(evbddnode_t n) +{ + return n->high & evbdd_marked_mask ? 1 : 0; +} + +/** + * Sets the value of the "marked" flag to `mark`. + */ +static inline void +evbddnode_setmark(evbddnode_t n, bool mark) +{ + if (mark) n->high |= evbdd_marked_mask; // set 1st bit from left to 1 + else n->high &= ~evbdd_marked_mask; // set 1st bit from left to 0 +} + +/** + * Gets the node

is pointing to. + * TODO (?) return special node for when p == EVBDD_TERMINAL + */ +static inline evbddnode_t +EVBDD_GETNODE(EVBDD_TARG p) +{ + return (evbddnode_t) llmsset_index_to_ptr(nodes, p); +} + +/** + * Packs a EVBDD_TARG and EVBDD_WGT into a single 64 bit EVBDD. + */ +static inline EVBDD +evbdd_bundle(EVBDD_TARG p, EVBDD_WGT a) +{ + if (larger_wgt_indices) { + assert (p <= 0x000000003ffffffe); // avoid clash with sylvan_invalid + assert (a <= (1LL<<33)); + return (a << 30 | p); + }else { + assert (p <= 0x000000fffffffffe); // avoid clash with sylvan_invalid + assert (a <= (1<<23)); + return (a << 40 | p); + } +} + +static void __attribute__((unused)) +evbddnode_unpack(evbddnode_t n, EVBDD_TARG *low, EVBDD_TARG *high, EVBDD_WGT *a, EVBDD_WGT *b) +{ + *low = evbddnode_getptrlow(n); + *high = evbddnode_getptrhigh(n); + bool norm_pos = (n->low & evbdd_wgt_pos_mask) >> 54; + bool norm_val = (n->low & evbdd_wgt_val_mask) >> 53; + + if (weight_norm_strat == NORM_L2) { + *b = EVBDD_WEIGHT(n->high); + *a = wgt_get_low_L2normed(*b); + } + else { + if (norm_pos == 0) { // low WGT is EVBDD_ZERO or EVBDD_ONE, high WGT in table + *a = (norm_val == 0) ? EVBDD_ZERO : EVBDD_ONE; + *b = EVBDD_WEIGHT(n->high); + } + else { // high WGT is EVBDD_ZERO or EVBDD_ONE, low WGT in table + *b = (norm_val == 0) ? EVBDD_ZERO : EVBDD_ONE; + *a = EVBDD_WEIGHT(n->high); + } + } +} + +static void __attribute__((unused)) +evbddnode_getchilderen(evbddnode_t n, EVBDD *low, EVBDD *high) +{ + EVBDD_TARG l, h; + EVBDD_WGT a, b; + evbddnode_unpack(n, &l, &h, &a, &b); + *low = evbdd_bundle(l, a); + *high = evbdd_bundle(h, b); +} + +static void __attribute__((unused)) +evbddnode_pack(evbddnode_t n, BDDVAR var, EVBDD_TARG low, EVBDD_TARG high, EVBDD_WGT a, EVBDD_WGT b) +{ + // We only want to store 1 edge weight per node (which has 2 outgoing + // 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 + // outside of {0, 1}, but under the constraint that |low|^2 + |high|^2 = 1, + // (or both are 0) and that |low| \in R+, we only need to store high, and + // can derive low. + + // these will be set depending on the normalization strategy + // (retrieval of edge weights is also dependent on normalization strategy) + EVBDD_WGT wgt_high; + bool norm_pos; + bool norm_val; + + if (weight_norm_strat == NORM_L2) { + assert(!(a == EVBDD_ZERO && b == EVBDD_ZERO)); // redundant node (caught before) + norm_pos = 0; + norm_val = 0; + wgt_high = b; // we can derive a from b + } + else { + /// weight_norm_strat == NORM_LOW or NORM_MAX or NORM_MIN + assert(a == EVBDD_ZERO || a == EVBDD_ONE || b == EVBDD_ZERO || b == EVBDD_ONE); + norm_pos = (a == EVBDD_ZERO || a == EVBDD_ONE) ? 0 : 1; + if (norm_pos == 0) { + norm_val = (a == EVBDD_ZERO) ? 0 : 1; + wgt_high = b; + } + else { + norm_val = (b == EVBDD_ZERO) ? 0 : 1; + wgt_high = a; + } + } + + // organize the bit structure of low and high + n->low = ((uint64_t)var)<<55 | ((uint64_t)norm_pos)<<54 | ((uint64_t)norm_val)<<53 | low; + if (larger_wgt_indices) { + n->high = wgt_high<<30 | high; + } + else { + n->high = wgt_high<<40 | high; + } +} + +static EVBDD_TARG __attribute__((unused)) +_evbdd_makenode(BDDVAR var, EVBDD_TARG low, EVBDD_TARG high, EVBDD_WGT a, EVBDD_WGT b) +{ + struct evbddnode n; + + evbddnode_pack(&n, var, low, high, a, b); + + EVBDD_TARG result; + int created; + EVBDD_TARG index = llmsset_lookup(nodes, n.low, n.high, &created); + if (index == 0) { + //printf("auto gc of node table triggered\n"); + + evbdd_refs_push(low); + evbdd_refs_push(high); + sylvan_gc(); + evbdd_refs_pop(2); + + index = llmsset_lookup(nodes, n.low, n.high, &created); + if (index == 0) { + fprintf(stderr, "EVBDD/BDD Unique table full, %zu of %zu buckets filled!\n", llmsset_count_marked(nodes), llmsset_get_size(nodes)); + exit(1); + } + } + + if (created) sylvan_stats_count(EVBDD_NODES_CREATED); + else sylvan_stats_count(EVBDD_NODES_REUSED); + + result = index; + //return mark ? result | evbdd_marked_mask : result; + return result; +} + +static EVBDD __attribute__((unused)) +evbdd_makenode(BDDVAR var, EVBDD low, EVBDD high) +{ + EVBDD_TARG low_trg = EVBDD_TARGET(low); + EVBDD_WGT low_wgt = EVBDD_WEIGHT(low); + EVBDD_TARG high_trg = EVBDD_TARGET(high); + EVBDD_WGT high_wgt = EVBDD_WEIGHT(high); + + // Edges with weight 0 should point straight to terminal. + if (low_wgt == EVBDD_ZERO) low_trg = EVBDD_TERMINAL; + if (high_wgt == EVBDD_ZERO) high_trg = EVBDD_TERMINAL; + + // If both low and high are the same (both TARG and WGT) return low + if (low == high) return low; + else { + // If the edges are not the same + EVBDD_WGT norm = (*normalize_weights)(&low_wgt, &high_wgt); + EVBDD_TARG res = _evbdd_makenode(var, low_trg, high_trg, low_wgt, high_wgt); + return evbdd_bundle(res, norm); + } +} + +/********************************/ + + +/** + * Gets either the top node of the EVBDD, or the node with var 't' if this + * variable would otherwise be skipped. The "node" is returned as + * (*topvar, *low, *high). + */ +static void __attribute__((unused)) +evbdd_get_topvar(EVBDD a, BDDVAR t, BDDVAR *topvar, EVBDD *low, EVBDD *high) +{ + bool skipped = false; + if(EVBDD_TARGET(a) == EVBDD_TERMINAL) { + skipped = true; + } + else { + evbddnode_t node = EVBDD_GETNODE(EVBDD_TARGET(a)); + *topvar = evbddnode_getvar(node); + if (*topvar > t) skipped = true; + } + + if (skipped) { + *low = evbdd_bundle(EVBDD_TARGET(a), EVBDD_ONE); + *high = evbdd_bundle(EVBDD_TARGET(a), EVBDD_ONE); + *topvar = t; + } + else { + evbddnode_t node = EVBDD_GETNODE(EVBDD_TARGET(a)); + evbddnode_getchilderen(node, low, high); + } +} + +#endif \ No newline at end of file diff --git a/src/sylvan_int.h b/src/sylvan_int.h index 8bd9da1..e00d469 100644 --- a/src/sylvan_int.h +++ b/src/sylvan_int.h @@ -106,17 +106,17 @@ static const uint64_t CACHE_MTBDD_RENUMBER_VARS = (59LL<<40); static const uint64_t CACHE_MTBDD_TOPVAR = (60LL<<40); static const uint64_t CACHE_MTBDD_TENSOR = (61LL<<40); -// AADD operations -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_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 +// EVBDD operations +static const uint64_t CACHE_EVBDD_PLUS = (70LL<<40); +static const uint64_t CACHE_EVBDD_MATVEC_MULT = (71LL<<40); +static const uint64_t CACHE_EVBDD_MATMAT_MULT = (72LL<<40); +static const uint64_t CACHE_EVBDD_INPROD = (73LL<<30); +static const uint64_t CACHE_EVBDD_REPLACE_TERMINAL = (74LL<<40); +static const uint64_t CACHE_EVBDD_INC_VARS = (75LL<<40); +static const uint64_t CACHE_EVBDD_CLEAN_WGT_TABLE = (76LL<<40); +static const uint64_t CACHE_EVBDD_IS_ORDERED = (77LL<<40); + +// Operations on EVBDD edge weights static const uint64_t CACHE_WGT_ADD = (80LL<<40); static const uint64_t CACHE_WGT_SUB = (81LL<<40); static const uint64_t CACHE_WGT_MUL = (82LL<<40); @@ -151,7 +151,7 @@ static const uint64_t CACHE_ZDD_COVER_TO_BDD = (113LL<<40); } #endif /* __cplusplus */ -#include +#include #include #include #include diff --git a/src/sylvan_stats.h b/src/sylvan_stats.h index 33d2a46..0788e74 100644 --- a/src/sylvan_stats.h +++ b/src/sylvan_stats.h @@ -32,8 +32,8 @@ typedef enum { BDD_NODES_REUSED, LDD_NODES_CREATED, LDD_NODES_REUSED, - AADD_NODES_CREATED, - AADD_NODES_REUSED, + EVBDD_NODES_CREATED, + EVBDD_NODES_REUSED, ZDD_NODES_CREATED, ZDD_NODES_REUSED, @@ -89,9 +89,9 @@ typedef enum { OPCOUNTER(LDD_RELPROD_UNION), OPCOUNTER(LDD_PROJECT_MINUS), - /* AADD operations */ - OPCOUNTER(AADD_PLUS), - OPCOUNTER(AADD_MULT), + /* EVBDD operations */ + OPCOUNTER(EVBDD_PLUS), + OPCOUNTER(EVBDD_MULT), /* QMDD operations */ OPCOUNTER(QMDD_GATE), diff --git a/test/test_qmdd_basics.c b/test/test_qmdd_basics.c index 8fd6481..eabe442 100644 --- a/test/test_qmdd_basics.c +++ b/test/test_qmdd_basics.c @@ -3,7 +3,7 @@ #include "qsylvan.h" #include -#include +#include #include #include @@ -35,19 +35,19 @@ int test_complex_operations() // No influence on DD test_assert(weight_approx_eq(&ref1, &ref2)); test_assert(weight_eq(&ref1, &ref2)); - // test AADD_ZERO + // test EVBDD_ZERO ref1 = cmake(0.0, 0.0); index1 = weight_lookup(&ref1); ref2 = cmake(0.0, 0.0); index2 = weight_lookup(&ref2); ref3 = czero(); index3 = weight_lookup(&ref3); test_assert(index1 == index2); test_assert(index1 == index3); - test_assert(index1 == AADD_ZERO); + test_assert(index1 == EVBDD_ZERO); - // test AADD_ONE + // test EVBDD_ONE ref1 = cmake(1.0, 0.0); index1 = weight_lookup(&ref1); ref2 = cmake(1.0, 0.0); index2 = weight_lookup(&ref2); test_assert(index1 == index2); - test_assert(index1 == AADD_ONE); + test_assert(index1 == EVBDD_ONE); // Clookup, Cvalue ref1 = cmake(0.5, 0.0); index1 = weight_lookup(&ref1); weight_value(index1, &val1); @@ -117,55 +117,55 @@ int test_basis_state_creation() x[0] = 0; q0 = qmdd_create_basis_state(1, x); // |0> x[0] = 1; q1 = qmdd_create_basis_state(1, x); // |1> - test_assert(aadd_countnodes(q0) == 2); // Only AADD - test_assert(aadd_countnodes(q1) == 2); + test_assert(evbdd_countnodes(q0) == 2); // Only EVBDD + test_assert(evbdd_countnodes(q1) == 2); test_assert(qmdd_is_unitvector(q0, 1)); test_assert(qmdd_is_unitvector(q1, 1)); - test_assert(aadd_is_ordered(q0, 1)); - test_assert(aadd_is_ordered(q1, 1)); + test_assert(evbdd_is_ordered(q0, 1)); + test_assert(evbdd_is_ordered(q1, 1)); test_assert(fabs(qmdd_get_norm(q0, 1) - 1.0) < 1e-14); test_assert(qmdd_get_norm(q0, 1) == 1.0); AMP a; // Index to edge weight - x[0] = 0; a = aadd_getvalue(q0, x); test_assert(a == AADD_ONE); - x[0] = 1; a = aadd_getvalue(q0, x); test_assert(a == AADD_ZERO); - x[0] = 0; a = aadd_getvalue(q1, x); test_assert(a == AADD_ZERO); - x[0] = 1; a = aadd_getvalue(q1, x); test_assert(a == AADD_ONE); + x[0] = 0; a = evbdd_getvalue(q0, x); test_assert(a == EVBDD_ONE); + x[0] = 1; a = evbdd_getvalue(q0, x); test_assert(a == EVBDD_ZERO); + x[0] = 0; a = evbdd_getvalue(q1, x); test_assert(a == EVBDD_ZERO); + x[0] = 1; a = evbdd_getvalue(q1, x); test_assert(a == EVBDD_ONE); QMDD q2, q3; // Test on 3 qubits + terminal node = 4 in number bool x3[] = {0, 0, 0}; x3[2] = 0; x3[1] = 0; x3[0] = 0; q2 = qmdd_create_basis_state(3, x3); // |000> x3[2] = 1; x3[1] = 0; x3[0] = 1; q3 = qmdd_create_basis_state(3, x3); // |101> - test_assert(aadd_countnodes(q2) == 4); - test_assert(aadd_countnodes(q3) == 4); + test_assert(evbdd_countnodes(q2) == 4); + test_assert(evbdd_countnodes(q3) == 4); test_assert(qmdd_is_unitvector(q2, 3)); test_assert(qmdd_is_unitvector(q3, 3)); - test_assert(aadd_is_ordered(q2, 3)); - test_assert(aadd_is_ordered(q3, 3)); + test_assert(evbdd_is_ordered(q2, 3)); + test_assert(evbdd_is_ordered(q3, 3)); test_assert(fabs(qmdd_get_norm(q2, 3) - 1.0) < 1e-14); test_assert(qmdd_get_norm(q2, 3) == 1.0); test_assert(fabs(qmdd_get_norm(q3, 3) - 1.0) < 1e-14); test_assert(qmdd_get_norm(q3, 3) == 1.0); - x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q2, x3); test_assert(a == AADD_ONE); - x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q2, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q2, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q2, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q2, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q2, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q2, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q2, x3); test_assert(a == AADD_ZERO); - - x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q3, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q3, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q3, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q3, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q3, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q3, x3); test_assert(a == AADD_ONE); // |101> -> 2^2*1 + 2^1*0 + 2^0*1 = index 5, starts with 0 - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q3, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q3, x3); test_assert(a == AADD_ZERO); - - printf("basis state creation aadd: ok\n"); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q2, x3); test_assert(a == EVBDD_ONE); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q2, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q2, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q2, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q2, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q2, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q2, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q2, x3); test_assert(a == EVBDD_ZERO); + + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == EVBDD_ONE); // |101> -> 2^2*1 + 2^1*0 + 2^0*1 = index 5, starts with 0 + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == EVBDD_ZERO); + + printf("basis state creation evbdd: ok\n"); return 0; } @@ -180,34 +180,34 @@ int test_vector_addition() // Single qubit test x[0] = 0; q0 = qmdd_create_basis_state(1, x); x[0] = 1; q1 = qmdd_create_basis_state(1, x); - q00 = aadd_plus(q0, q0); - q01 = aadd_plus(q0, q1); - q10 = aadd_plus(q1, q0); - q11 = aadd_plus(q1, q1); - q000 = aadd_plus(q00, q0); - q001 = aadd_plus(q00, q1); - q010 = aadd_plus(q01, q0); - q100 = aadd_plus(q10, q0); - - x[0] = 0; a = aadd_getvalue(q00, x); test_assert(a == complex_lookup(2.0, 0.0)); - x[0] = 1; a = aadd_getvalue(q00, x); test_assert(a == AADD_ZERO); - x[0] = 0; a = aadd_getvalue(q01, x); test_assert(a == AADD_ONE); - x[0] = 1; a = aadd_getvalue(q01, x); test_assert(a == AADD_ONE); - x[0] = 0; a = aadd_getvalue(q10, x); test_assert(a == AADD_ONE); - x[0] = 1; a = aadd_getvalue(q10, x); test_assert(a == AADD_ONE); - x[0] = 0; a = aadd_getvalue(q11, x); test_assert(a == AADD_ZERO); - x[0] = 1; a = aadd_getvalue(q11, x); test_assert(a == complex_lookup(2.0, 0.0)); + q00 = evbdd_plus(q0, q0); + q01 = evbdd_plus(q0, q1); + q10 = evbdd_plus(q1, q0); + q11 = evbdd_plus(q1, q1); + q000 = evbdd_plus(q00, q0); + q001 = evbdd_plus(q00, q1); + q010 = evbdd_plus(q01, q0); + q100 = evbdd_plus(q10, q0); + + x[0] = 0; a = evbdd_getvalue(q00, x); test_assert(a == complex_lookup(2.0, 0.0)); + x[0] = 1; a = evbdd_getvalue(q00, x); test_assert(a == EVBDD_ZERO); + x[0] = 0; a = evbdd_getvalue(q01, x); test_assert(a == EVBDD_ONE); + x[0] = 1; a = evbdd_getvalue(q01, x); test_assert(a == EVBDD_ONE); + x[0] = 0; a = evbdd_getvalue(q10, x); test_assert(a == EVBDD_ONE); + x[0] = 1; a = evbdd_getvalue(q10, x); test_assert(a == EVBDD_ONE); + x[0] = 0; a = evbdd_getvalue(q11, x); test_assert(a == EVBDD_ZERO); + x[0] = 1; a = evbdd_getvalue(q11, x); test_assert(a == complex_lookup(2.0, 0.0)); test_assert(q01 == q10); test_assert(!qmdd_is_unitvector(q01, 1)); - x[0] = 0; a = aadd_getvalue(q000, x); test_assert(a == complex_lookup(3.0, 0.0)); - x[0] = 1; a = aadd_getvalue(q000, x); test_assert(a == AADD_ZERO); - x[0] = 0; a = aadd_getvalue(q001, x); test_assert(a == complex_lookup(2.0, 0.0)); - x[0] = 1; a = aadd_getvalue(q001, x); test_assert(a == AADD_ONE); - x[0] = 0; a = aadd_getvalue(q010, x); test_assert(a == complex_lookup(2.0, 0.0)); - x[0] = 1; a = aadd_getvalue(q010, x); test_assert(a == AADD_ONE); - x[0] = 0; a = aadd_getvalue(q100, x); test_assert(a == complex_lookup(2.0, 0.0)); - x[0] = 1; a = aadd_getvalue(q100, x); test_assert(a == AADD_ONE); + x[0] = 0; a = evbdd_getvalue(q000, x); test_assert(a == complex_lookup(3.0, 0.0)); + x[0] = 1; a = evbdd_getvalue(q000, x); test_assert(a == EVBDD_ZERO); + x[0] = 0; a = evbdd_getvalue(q001, x); test_assert(a == complex_lookup(2.0, 0.0)); + x[0] = 1; a = evbdd_getvalue(q001, x); test_assert(a == EVBDD_ONE); + x[0] = 0; a = evbdd_getvalue(q010, x); test_assert(a == complex_lookup(2.0, 0.0)); + x[0] = 1; a = evbdd_getvalue(q010, x); test_assert(a == EVBDD_ONE); + x[0] = 0; a = evbdd_getvalue(q100, x); test_assert(a == complex_lookup(2.0, 0.0)); + x[0] = 1; a = evbdd_getvalue(q100, x); test_assert(a == EVBDD_ONE); test_assert(q001 == q010); test_assert(q001 == q100); test_assert(!qmdd_is_unitvector(q001, 1)); @@ -218,120 +218,120 @@ int test_vector_addition() nqubits = 4; 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); - q01 = aadd_plus(q0, q1); - q10 = aadd_plus(q1, q0); - q11 = aadd_plus(q1, q1); - q000 = aadd_plus(q00, q0); - q001 = aadd_plus(q00, q1); - q010 = aadd_plus(q01, q0); - q100 = aadd_plus(q10, q0); - test_assert(aadd_is_ordered(q000, nqubits)); - test_assert(aadd_is_ordered(q001, nqubits)); - test_assert(aadd_is_ordered(q010, nqubits)); - test_assert(aadd_is_ordered(q100, nqubits)); + q00 = evbdd_plus(q0, q0); + q01 = evbdd_plus(q0, q1); + q10 = evbdd_plus(q1, q0); + q11 = evbdd_plus(q1, q1); + q000 = evbdd_plus(q00, q0); + q001 = evbdd_plus(q00, q1); + q010 = evbdd_plus(q01, q0); + q100 = evbdd_plus(q10, q0); + test_assert(evbdd_is_ordered(q000, nqubits)); + test_assert(evbdd_is_ordered(q001, nqubits)); + test_assert(evbdd_is_ordered(q010, nqubits)); + test_assert(evbdd_is_ordered(q100, nqubits)); // TODO: better way to assert "all others 0" --> creating function which // returns array x from int will help // q0 + q0 - x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q00, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q00, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q00, x4); test_assert(a == complex_lookup(2.0, 0.0)); - x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q00, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q00, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q00, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q00, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q00, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q00, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q00, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q00, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q00, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q00, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q00, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q00, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q00, x4); test_assert(a == AADD_ZERO); + x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q00, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q00, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q00, x4); test_assert(a == complex_lookup(2.0, 0.0)); + x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q00, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q00, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q00, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q00, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q00, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q00, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q00, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q00, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q00, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q00, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q00, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q00, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q00, x4); test_assert(a == EVBDD_ZERO); test_assert(!qmdd_is_unitvector(q00, 4)); // q0 + q1 / q1 + q0 - x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q01, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q01, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q01, x4); test_assert(a == AADD_ONE); - x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q01, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q01, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q01, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q01, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q01, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q01, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q01, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q01, x4); test_assert(a == AADD_ONE); - x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q01, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q01, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q01, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q01, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q01, x4); test_assert(a == AADD_ZERO); + x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q01, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q01, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q01, x4); test_assert(a == EVBDD_ONE); + x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q01, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q01, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q01, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q01, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q01, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q01, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q01, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q01, x4); test_assert(a == EVBDD_ONE); + x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q01, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q01, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q01, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q01, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q01, x4); test_assert(a == EVBDD_ZERO); test_assert(q01 == q10); test_assert(!qmdd_is_unitvector(q01, 4)); // q1 + q1 - x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q11, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q11, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q11, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q11, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q11, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q11, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q11, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q11, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q11, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q11, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q11, x4); test_assert(a == complex_lookup(2.0, 0.0)); - x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q11, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q11, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q11, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q11, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q11, x4); test_assert(a == AADD_ZERO); + x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q11, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q11, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q11, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q11, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q11, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q11, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q11, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q11, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q11, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q11, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q11, x4); test_assert(a == complex_lookup(2.0, 0.0)); + x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q11, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q11, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q11, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q11, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q11, x4); test_assert(a == EVBDD_ZERO); test_assert(!qmdd_is_unitvector(q11, 4)); // q0 + q0 + q0 - x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q000, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q000, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q000, x4); test_assert(a == complex_lookup(3.0, 0.0)); - x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q000, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q000, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q000, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q000, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q000, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q000, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q000, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q000, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q000, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q000, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q000, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q000, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q000, x4); test_assert(a == AADD_ZERO); + x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q000, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q000, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q000, x4); test_assert(a == complex_lookup(3.0, 0.0)); + x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q000, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q000, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q000, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q000, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q000, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q000, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q000, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q000, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q000, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q000, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q000, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q000, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q000, x4); test_assert(a == EVBDD_ZERO); test_assert(!qmdd_is_unitvector(q000, 4)); // q0 + q0 + q1 / q0 + q1 + q0 / q1 + q0 + q0 - x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q001, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q001, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q001, x4); test_assert(a == complex_lookup(2.0, 0.0)); - x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q001, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q001, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q001, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q001, x4); test_assert(a == AADD_ZERO); - x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q001, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q001, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q001, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q001, x4); test_assert(a == AADD_ONE); - x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q001, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = aadd_getvalue(q001, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = aadd_getvalue(q001, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = aadd_getvalue(q001, x4); test_assert(a == AADD_ZERO); - x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = aadd_getvalue(q001, x4); test_assert(a == AADD_ZERO); + x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q001, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q001, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q001, x4); test_assert(a == complex_lookup(2.0, 0.0)); + x4[3] = 0; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q001, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q001, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q001, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q001, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 0; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q001, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q001, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q001, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q001, x4); test_assert(a == EVBDD_ONE); + x4[3] = 1; x4[2] = 0; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q001, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 0; a = evbdd_getvalue(q001, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 0; x4[0] = 1; a = evbdd_getvalue(q001, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 0; a = evbdd_getvalue(q001, x4); test_assert(a == EVBDD_ZERO); + x4[3] = 1; x4[2] = 1; x4[1] = 1; x4[0] = 1; a = evbdd_getvalue(q001, x4); test_assert(a == EVBDD_ZERO); test_assert(q001 == q010); test_assert(q001 == q100); test_assert(!qmdd_is_unitvector(q001, 4)); - if(VERBOSE) printf("aadd vector addition: ok\n"); + if(VERBOSE) printf("evbdd vector addition: ok\n"); return 0; } @@ -344,31 +344,31 @@ int test_inner_product() // 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] - q000i = aadd_bundle(AADD_TARGET(q000), wgt_mul(AADD_WEIGHT(q000), complex_lookup(0,1))); + q00 = evbdd_plus(q0, q0); // [0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0] + q01 = evbdd_plus(q0, q1); // [0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0] + q11 = evbdd_plus(q1, q1); // [0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0] + q000 = evbdd_plus(q00, q0); // [0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0] + q001 = evbdd_plus(q00, q1); // [0 0 2 0 0 0 0 0 0 0 0 1 0 0 0 0] + q000i = evbdd_bundle(EVBDD_TARGET(q000), wgt_mul(EVBDD_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))); + q001i = evbdd_bundle(EVBDD_TARGET(q001), wgt_mul(EVBDD_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)); - 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)); - 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"); + test_assert(evbdd_inner_product(q00, q00, nqubits) == complex_lookup(4.0, 0.0)); + test_assert(evbdd_inner_product(q01, q01, nqubits) == complex_lookup(2.0, 0.0)); + test_assert(evbdd_inner_product(q11, q11, nqubits) == complex_lookup(4.0, 0.0)); + test_assert(evbdd_inner_product(q000, q000, nqubits) == complex_lookup(9.0, 0.0)); + test_assert(evbdd_inner_product(q001, q001, nqubits) == complex_lookup(5.0, 0.0)); + test_assert(evbdd_inner_product(q00, q01, nqubits) == complex_lookup(2.0, 0.0)); + test_assert(evbdd_inner_product(q00, q000, nqubits) == complex_lookup(6.0, 0.0)); + test_assert(evbdd_inner_product(q01, q000, nqubits) == complex_lookup(3.0, 0.0)); + test_assert(evbdd_inner_product(q000, q001, nqubits) == complex_lookup(6.0, 0.0)); + test_assert(evbdd_inner_product(q01, q001, nqubits) == complex_lookup(3.0, 0.0)); + test_assert(evbdd_inner_product(q000i, q000i, nqubits) == complex_lookup(9.0, 0.0)); + test_assert(evbdd_inner_product(q001i, q001i, nqubits) == complex_lookup(5.0, 0.0)); + test_assert(evbdd_inner_product(q000i, q001i, nqubits) == complex_lookup(6.0, 0.0)); + + if (VERBOSE) printf("evbdd inner product: ok\n"); return 0; } diff --git a/test/test_qmdd_circuits.c b/test/test_qmdd_circuits.c index bbd5d9e..2ec139a 100644 --- a/test/test_qmdd_circuits.c +++ b/test/test_qmdd_circuits.c @@ -16,37 +16,37 @@ int test_swap_circuit() q = qmdd_create_basis_state(3, x3); q = qmdd_gate(q, GATEID_X, 2); - x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ONE); - x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - test_assert(aadd_is_ordered(q, 3)); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ONE); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + test_assert(evbdd_is_ordered(q, 3)); q = qmdd_circuit_swap(q, 0, 2); - x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ONE); - x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - test_assert(aadd_is_ordered(q, 3)); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ONE); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + test_assert(evbdd_is_ordered(q, 3)); q = qmdd_circuit_swap(q, 0, 1); - x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ONE); - x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - test_assert(aadd_is_ordered(q, 3)); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ONE); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + test_assert(evbdd_is_ordered(q, 3)); // TODO: more tests @@ -61,96 +61,96 @@ int test_cswap_circuit() AMP a; uint32_t cs[3]; - cs[0] = 0; cs[1] = AADD_INVALID_VAR; cs[2] = AADD_INVALID_VAR; // control only on q0 + cs[0] = 0; cs[1] = EVBDD_INVALID_VAR; cs[2] = EVBDD_INVALID_VAR; // control only on q0 x3[2]=1; x3[1]=0; x3[0]=0; q = qmdd_create_basis_state(3, x3); q = qmdd_ccircuit(q, CIRCID_swap, cs, 1, 2); // control is |0>, nothing should happen - x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ONE); - x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ONE); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); x3[2]=1; x3[1]=0; x3[0]=1; q = qmdd_create_basis_state(3, x3); q = qmdd_ccircuit(q, CIRCID_swap, cs, 1, 2); // control is |1>, should swap q1 and q2 - x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ONE); - x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ONE); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); x3[2]=1; x3[1]=0; x3[0]=0; q = qmdd_create_basis_state(3, x3); q = qmdd_gate(q, GATEID_H, 0); // input state: |10+> = 1/sqrt(2)(|100> + |101>) - x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); q = qmdd_ccircuit(q, CIRCID_swap, cs, 1, 2); // control is |+>, expected output: 1/sqrt(2)(|100> + |011>) - x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); x3[2]=1; x3[1]=0; x3[0]=0; q = qmdd_create_basis_state(3, x3); q = qmdd_gate(q, GATEID_H, 0); q = qmdd_gate(q, GATEID_Z, 0); // input state: |10-> = 1/sqrt(2)(|100> - |101>) - x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == complex_lookup(-1.0/flt_sqrt(2.0),0)); - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == complex_lookup(-1.0/flt_sqrt(2.0),0)); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); q = qmdd_ccircuit(q, CIRCID_swap, cs, 1, 2); // control is |->, expected output: 1/sqrt(2)(|100> - |011>) - x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == complex_lookup(-1.0/flt_sqrt(2.0),0)); - x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == complex_lookup(-1.0/flt_sqrt(2.0),0)); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); x3[2]=1; x3[1]=0; x3[0]=0; q = qmdd_create_basis_state(3, x3); q = qmdd_gate(q, GATEID_H, 0); q = qmdd_gate(q, GATEID_S, 0); // input state: |10>|+i> = 1/sqrt(2)(|100> + i|101>) - x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == complex_lookup(0,1.0/flt_sqrt(2.0))); - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == complex_lookup(0,1.0/flt_sqrt(2.0))); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); q = qmdd_ccircuit(q, CIRCID_swap, cs, 1, 2); // control is |+i>, expected output: 1/sqrt(2)(|100> + i|011>) - x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == complex_lookup(0,1.0/flt_sqrt(2.0))); - x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q, x3); test_assert(a == AADD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == complex_lookup(0,1.0/flt_sqrt(2.0))); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q, x3); test_assert(a == EVBDD_ZERO); // TODO: more tests ? @@ -168,25 +168,25 @@ int test_tensor_product() q0 = qmdd_create_basis_state(3, x3); q1 = qmdd_create_basis_state(2, x2); - test_assert(aadd_countnodes(q0) == 4); - test_assert(aadd_countnodes(q1) == 3); + test_assert(evbdd_countnodes(q0) == 4); + test_assert(evbdd_countnodes(q1) == 3); // q0 (tensor) q1 - qTest = aadd_vec_tensor_prod(q0, q1, 3); + qTest = evbdd_vec_tensor_prod(q0, q1, 3); qRef = qmdd_create_basis_state(5, x3_2); - test_assert(aadd_is_ordered(qTest, 5)); - test_assert(aadd_countnodes(qTest) == 6); - test_assert(aadd_equivalent(qTest, qRef, 5, false, true)); - test_assert(aadd_equivalent(qTest, qRef, 5, true, true)); + test_assert(evbdd_is_ordered(qTest, 5)); + test_assert(evbdd_countnodes(qTest) == 6); + test_assert(evbdd_equivalent(qTest, qRef, 5, false, true)); + test_assert(evbdd_equivalent(qTest, qRef, 5, true, true)); test_assert(qTest == qRef); // q1 (tensor) q0 - qTest = aadd_vec_tensor_prod(q1, q0, 2); + qTest = evbdd_vec_tensor_prod(q1, q0, 2); qRef = qmdd_create_basis_state(5, x2_3); - test_assert(aadd_is_ordered(qTest, 5)); - test_assert(aadd_countnodes(qTest) == 6); - test_assert(aadd_equivalent(qTest, qRef, 5, false, true)); - test_assert(aadd_equivalent(qTest, qRef, 5, true, true)); + test_assert(evbdd_is_ordered(qTest, 5)); + test_assert(evbdd_countnodes(qTest) == 6); + test_assert(evbdd_equivalent(qTest, qRef, 5, false, true)); + test_assert(evbdd_equivalent(qTest, qRef, 5, true, true)); test_assert(qTest == qRef); @@ -203,18 +203,18 @@ int test_measure_random_state(QMDD qmdd, BDDVAR nvars) QMDD qm; int m; double p; - test_assert(aadd_is_ordered(qmdd, nvars)); + test_assert(evbdd_is_ordered(qmdd, nvars)); test_assert(qmdd_is_unitvector(qmdd, nvars)); qm = qmdd_measure_q0(qmdd, nvars, &m, &p); - test_assert(aadd_is_ordered(qmdd, nvars)); + test_assert(evbdd_is_ordered(qmdd, nvars)); test_assert(qmdd_is_unitvector(qm, nvars)); if ((flt_abs(p - 1.0) < cmap_get_tolerance()) || (flt_abs(p - 0.0) < cmap_get_tolerance())){ qmdd = qmdd_remove_global_phase(qmdd); // measurement removes global phase - test_assert(aadd_equivalent(qmdd, qm, nvars, false, false)); - test_assert(aadd_equivalent(qmdd, qm, nvars, true, false)); + test_assert(evbdd_equivalent(qmdd, qm, nvars, false, false)); + test_assert(evbdd_equivalent(qmdd, qm, nvars, true, false)); test_assert(qm == qmdd); } else { - test_assert(aadd_countnodes(qm) < aadd_countnodes(qmdd)); + test_assert(evbdd_countnodes(qm) < evbdd_countnodes(qmdd)); } return 0; @@ -239,8 +239,8 @@ int test_measurements() qPM = qmdd_measure_qubit(q, 0, 3, &m, &prob); test_assert(m == 0); test_assert(prob == 1.0); - test_assert(aadd_equivalent(q, qPM, 3, false, false)); - test_assert(aadd_equivalent(q, qPM, 3, true, false)); + test_assert(evbdd_equivalent(q, qPM, 3, false, false)); + test_assert(evbdd_equivalent(q, qPM, 3, true, false)); test_assert(q == qPM); // |010> @@ -249,8 +249,8 @@ int test_measurements() qPM = qmdd_measure_qubit(q, 0, 3, &m, &prob); test_assert(m == 0); test_assert(prob == 1.0); - test_assert(aadd_equivalent(q, qPM, 3, false, false)); - test_assert(aadd_equivalent(q, qPM, 3, true, false)); + test_assert(evbdd_equivalent(q, qPM, 3, false, false)); + test_assert(evbdd_equivalent(q, qPM, 3, true, false)); test_assert(q == qPM); // |011> @@ -259,8 +259,8 @@ int test_measurements() qPM = qmdd_measure_qubit(q, 0, 3, &m, &prob); test_assert(m == 1); test_assert(prob == 0.0); - test_assert(aadd_equivalent(q, qPM, 3, false, false)); - test_assert(aadd_equivalent(q, qPM, 3, true, false)); + test_assert(evbdd_equivalent(q, qPM, 3, false, false)); + test_assert(evbdd_equivalent(q, qPM, 3, true, false)); test_assert(q == qPM); // |00+> @@ -271,8 +271,8 @@ int test_measurements() test_assert(flt_abs(prob - 0.5) < cmap_get_tolerance()); x3[2]=0; x3[1]=0; x3[0]=m; // either |000> or |001> depending on m q = qmdd_create_basis_state(3, x3); - test_assert(aadd_equivalent(q, qPM, 3, false, true)); - test_assert(aadd_equivalent(q, qPM, 3, true, false)); + test_assert(evbdd_equivalent(q, qPM, 3, false, true)); + test_assert(evbdd_equivalent(q, qPM, 3, true, false)); test_assert(q == qPM); // |0+0> @@ -283,8 +283,8 @@ int test_measurements() test_assert(flt_abs(prob - 0.5) < cmap_get_tolerance()); x3[2]=0; x3[1]=m; x3[0]=0; // either |000> or |010> depending on m q = qmdd_create_basis_state(3, x3); - test_assert(aadd_equivalent(q, qPM, 3, false, true)); - test_assert(aadd_equivalent(q, qPM, 3, true, false)); + test_assert(evbdd_equivalent(q, qPM, 3, false, true)); + test_assert(evbdd_equivalent(q, qPM, 3, true, false)); test_assert(q == qPM); // |+00> @@ -295,8 +295,8 @@ int test_measurements() test_assert(flt_abs(prob - 0.5) < cmap_get_tolerance()); x3[2]=m; x3[1]=0; x3[0]=0; // either |000> or |100> depending on m q = qmdd_create_basis_state(3, x3); - test_assert(aadd_equivalent(q, qPM, 3, false, true)); - test_assert(aadd_equivalent(q, qPM, 3, true, false)); + test_assert(evbdd_equivalent(q, qPM, 3, false, true)); + test_assert(evbdd_equivalent(q, qPM, 3, true, false)); test_assert(q == qPM); // |00-> @@ -307,8 +307,8 @@ int test_measurements() test_assert(flt_abs(prob - 0.5) < cmap_get_tolerance()); x3[2]=0; x3[1]=0; x3[0]=m; // either |000> or |001> depending on m q = qmdd_create_basis_state(3, x3); - test_assert(aadd_equivalent(q, qPM, 3, false, true)); - test_assert(aadd_equivalent(q, qPM, 3, true, false)); + test_assert(evbdd_equivalent(q, qPM, 3, false, true)); + test_assert(evbdd_equivalent(q, qPM, 3, true, false)); test_assert(q == qPM); // |+++>, measure q0 @@ -323,8 +323,8 @@ int test_measurements() q = qmdd_create_basis_state(3, x3); q = qmdd_gate(q, GATEID_H, 1); q = qmdd_gate(q, GATEID_H, 2); - test_assert(aadd_equivalent(q, qPM, 3, false, true)); - test_assert(aadd_equivalent(q, qPM, 3, true, false)); + test_assert(evbdd_equivalent(q, qPM, 3, false, true)); + test_assert(evbdd_equivalent(q, qPM, 3, true, false)); test_assert(q == qPM); // |+++>, measure q1 @@ -339,8 +339,8 @@ int test_measurements() q = qmdd_create_basis_state(3, x3); q = qmdd_gate(q, GATEID_H, 0); q = qmdd_gate(q, GATEID_H, 2); - test_assert(aadd_equivalent(q, qPM, 3, false, true)); - test_assert(aadd_equivalent(q, qPM, 3, true, false)); + test_assert(evbdd_equivalent(q, qPM, 3, false, true)); + test_assert(evbdd_equivalent(q, qPM, 3, true, false)); test_assert(q == qPM); // [1/2, 1/2, 1/2, -1/2] = 1/2(|00> + |01> + |10> - |11>)_(q1, q0) @@ -349,23 +349,23 @@ int test_measurements() q = qmdd_gate(q, GATEID_H, 0); q = qmdd_gate(q, GATEID_H, 1); q = qmdd_cgate(q,GATEID_Z, 0, 1); - x2[1]=0; x2[0]=0; a = aadd_getvalue(q, x2); test_assert(a == complex_lookup(0.5,0)); - x2[1]=0; x2[0]=1; a = aadd_getvalue(q, x2); test_assert(a == complex_lookup(0.5,0)); - x2[1]=1; x2[0]=0; a = aadd_getvalue(q, x2); test_assert(a == complex_lookup(0.5,0)); - x2[1]=1; x2[0]=1; a = aadd_getvalue(q, x2); test_assert(a == complex_lookup(-0.5,0)); + x2[1]=0; x2[0]=0; a = evbdd_getvalue(q, x2); test_assert(a == complex_lookup(0.5,0)); + x2[1]=0; x2[0]=1; a = evbdd_getvalue(q, x2); test_assert(a == complex_lookup(0.5,0)); + x2[1]=1; x2[0]=0; a = evbdd_getvalue(q, x2); test_assert(a == complex_lookup(0.5,0)); + x2[1]=1; x2[0]=1; a = evbdd_getvalue(q, x2); test_assert(a == complex_lookup(-0.5,0)); qPM = qmdd_measure_qubit(q, 0, 2, &m, &prob); test_assert(flt_abs(prob - 0.5) < cmap_get_tolerance()); if (m == 0) { // expect 1/sqrt(2)(|00> + |10>) - x2[1]=0; x2[0]=0; a = aadd_getvalue(qPM, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1]=0; x2[0]=1; a = aadd_getvalue(qPM, x2); test_assert(a == AADD_ZERO); - x2[1]=1; x2[0]=0; a = aadd_getvalue(qPM, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1]=1; x2[0]=1; a = aadd_getvalue(qPM, x2); test_assert(a == AADD_ZERO); + x2[1]=0; x2[0]=0; a = evbdd_getvalue(qPM, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1]=0; x2[0]=1; a = evbdd_getvalue(qPM, x2); test_assert(a == EVBDD_ZERO); + x2[1]=1; x2[0]=0; a = evbdd_getvalue(qPM, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1]=1; x2[0]=1; a = evbdd_getvalue(qPM, x2); test_assert(a == EVBDD_ZERO); } if (m == 1) { // expect 1/sqrt(2)(|01> - |11>) - x2[1]=0; x2[0]=0; a = aadd_getvalue(qPM, x2); test_assert(a == AADD_ZERO); - x2[1]=0; x2[0]=1; a = aadd_getvalue(qPM, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1]=1; x2[0]=0; a = aadd_getvalue(qPM, x2); test_assert(a == AADD_ZERO); - x2[1]=1; x2[0]=1; a = aadd_getvalue(qPM, x2); test_assert(a == complex_lookup(-1.0/flt_sqrt(2.0),0)); + x2[1]=0; x2[0]=0; a = evbdd_getvalue(qPM, x2); test_assert(a == EVBDD_ZERO); + x2[1]=0; x2[0]=1; a = evbdd_getvalue(qPM, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1]=1; x2[0]=0; a = evbdd_getvalue(qPM, x2); test_assert(a == EVBDD_ZERO); + x2[1]=1; x2[0]=1; a = evbdd_getvalue(qPM, x2); test_assert(a == complex_lookup(-1.0/flt_sqrt(2.0),0)); } } @@ -382,8 +382,8 @@ int test_measurements() test_assert(ms[1] == 0); test_assert(ms[2] == 0); test_assert(prob == 1.0); - test_assert(aadd_equivalent(q, qPM, 3, false, false)); - test_assert(aadd_equivalent(q, qPM, 3, true, false)); + test_assert(evbdd_equivalent(q, qPM, 3, false, false)); + test_assert(evbdd_equivalent(q, qPM, 3, true, false)); test_assert(q == qPM); // |010> @@ -394,8 +394,8 @@ int test_measurements() test_assert(ms[1] == 1); test_assert(ms[2] == 0); test_assert(prob == 1.0); - test_assert(aadd_equivalent(q, qPM, 3, false, false)); - test_assert(aadd_equivalent(q, qPM, 3, true, false)); + test_assert(evbdd_equivalent(q, qPM, 3, false, false)); + test_assert(evbdd_equivalent(q, qPM, 3, true, false)); test_assert(q == qPM); // |011> @@ -406,8 +406,8 @@ int test_measurements() test_assert(ms[1] == 1); test_assert(ms[2] == 0); test_assert(prob == 1.0); - test_assert(aadd_equivalent(q, qPM, 3, false, false)); - test_assert(aadd_equivalent(q, qPM, 3, true, false)); + test_assert(evbdd_equivalent(q, qPM, 3, false, false)); + test_assert(evbdd_equivalent(q, qPM, 3, true, false)); test_assert(q == qPM); // |00+> @@ -418,8 +418,8 @@ int test_measurements() test_assert(flt_abs(prob - 0.5) < cmap_get_tolerance()); x3[2]=0; x3[1]=0; x3[0]=ms[0]; // either |000> or |001> depending on m q = qmdd_create_basis_state(3, x3); - test_assert(aadd_equivalent(q, qPM, 3, false, true)); - test_assert(aadd_equivalent(q, qPM, 3, true, false)); + test_assert(evbdd_equivalent(q, qPM, 3, false, true)); + test_assert(evbdd_equivalent(q, qPM, 3, true, false)); test_assert(q == qPM); if (ms[0] == 0) m_zer[0] += 1; @@ -431,8 +431,8 @@ int test_measurements() test_assert(flt_abs(prob - 0.5) < cmap_get_tolerance()); x3[2]=0; x3[1]=ms[1]; x3[0]=0; // either |000> or |010> depending on m q = qmdd_create_basis_state(3, x3); - test_assert(aadd_equivalent(q, qPM, 3, false, true)); - test_assert(aadd_equivalent(q, qPM, 3, true, false)); + test_assert(evbdd_equivalent(q, qPM, 3, false, true)); + test_assert(evbdd_equivalent(q, qPM, 3, true, false)); test_assert(q == qPM); if (ms[1] == 0) m_zer[1] += 1; @@ -444,8 +444,8 @@ int test_measurements() test_assert(flt_abs(prob - 0.5) < cmap_get_tolerance()); x3[2]=ms[2]; x3[1]=0; x3[0]=0; // either |000> or |100> depending on m q = qmdd_create_basis_state(3, x3); - test_assert(aadd_equivalent(q, qPM, 3, false, true)); - test_assert(aadd_equivalent(q, qPM, 3, true, false)); + test_assert(evbdd_equivalent(q, qPM, 3, false, true)); + test_assert(evbdd_equivalent(q, qPM, 3, true, false)); test_assert(q == qPM); if (ms[2] == 0) m_zer[2] += 1; } @@ -470,23 +470,23 @@ int test_QFT() q3 = qmdd_circuit(q3, CIRCID_reverse_range, 0, 2); // check approx equal against output from qiskit - x3[2]=0; x3[1]=0; x3[0]=0; a = aadd_getvalue(q3, x3); weight_value(a, &c); cref = cmake(3.5355339059327384e-01,-8.6595605623549353e-17); test_assert(weight_approx_eq(&c, &cref)); - x3[2]=0; x3[1]=0; x3[0]=1; a = aadd_getvalue(q3, x3); weight_value(a, &c); cref = cmake(-3.5355339059327384e-01,8.6595605623549353e-17); test_assert(weight_approx_eq(&c, &cref)); - x3[2]=0; x3[1]=1; x3[0]=0; a = aadd_getvalue(q3, x3); weight_value(a, &c); cref = cmake(-1.0824450702943669e-16,-3.5355339059327384e-01); test_assert(weight_approx_eq(&c, &cref)); - x3[2]=0; x3[1]=1; x3[0]=1; a = aadd_getvalue(q3, x3); weight_value(a, &c); cref = cmake(1.0824450702943669e-16,3.5355339059327384e-01); test_assert(weight_approx_eq(&c, &cref)); - x3[2]=1; x3[1]=0; x3[0]=0; a = aadd_getvalue(q3, x3); weight_value(a, &c); cref = cmake(-2.5000000000000000e-01,2.5000000000000017e-01); test_assert(weight_approx_eq(&c, &cref)); - x3[2]=1; x3[1]=0; x3[0]=1; a = aadd_getvalue(q3, x3); weight_value(a, &c); cref = cmake(2.5000000000000000e-01,-2.5000000000000017e-01); test_assert(weight_approx_eq(&c, &cref)); - x3[2]=1; x3[1]=1; x3[0]=0; a = aadd_getvalue(q3, x3); weight_value(a, &c); cref = cmake(2.5000000000000017e-01,2.5000000000000000e-01); test_assert(weight_approx_eq(&c, &cref)); - x3[2]=1; x3[1]=1; x3[0]=1; a = aadd_getvalue(q3, x3); weight_value(a, &c); cref = cmake(-2.5000000000000017e-01,-2.5000000000000000e-01); test_assert(weight_approx_eq(&c, &cref)); + x3[2]=0; x3[1]=0; x3[0]=0; a = evbdd_getvalue(q3, x3); weight_value(a, &c); cref = cmake(3.5355339059327384e-01,-8.6595605623549353e-17); test_assert(weight_approx_eq(&c, &cref)); + x3[2]=0; x3[1]=0; x3[0]=1; a = evbdd_getvalue(q3, x3); weight_value(a, &c); cref = cmake(-3.5355339059327384e-01,8.6595605623549353e-17); test_assert(weight_approx_eq(&c, &cref)); + x3[2]=0; x3[1]=1; x3[0]=0; a = evbdd_getvalue(q3, x3); weight_value(a, &c); cref = cmake(-1.0824450702943669e-16,-3.5355339059327384e-01); test_assert(weight_approx_eq(&c, &cref)); + x3[2]=0; x3[1]=1; x3[0]=1; a = evbdd_getvalue(q3, x3); weight_value(a, &c); cref = cmake(1.0824450702943669e-16,3.5355339059327384e-01); test_assert(weight_approx_eq(&c, &cref)); + x3[2]=1; x3[1]=0; x3[0]=0; a = evbdd_getvalue(q3, x3); weight_value(a, &c); cref = cmake(-2.5000000000000000e-01,2.5000000000000017e-01); test_assert(weight_approx_eq(&c, &cref)); + x3[2]=1; x3[1]=0; x3[0]=1; a = evbdd_getvalue(q3, x3); weight_value(a, &c); cref = cmake(2.5000000000000000e-01,-2.5000000000000017e-01); test_assert(weight_approx_eq(&c, &cref)); + x3[2]=1; x3[1]=1; x3[0]=0; a = evbdd_getvalue(q3, x3); weight_value(a, &c); cref = cmake(2.5000000000000017e-01,2.5000000000000000e-01); test_assert(weight_approx_eq(&c, &cref)); + x3[2]=1; x3[1]=1; x3[0]=1; a = evbdd_getvalue(q3, x3); weight_value(a, &c); cref = cmake(-2.5000000000000017e-01,-2.5000000000000000e-01); test_assert(weight_approx_eq(&c, &cref)); test_assert(qmdd_is_unitvector(q3, 3)); - test_assert(aadd_is_ordered(q3, 3)); + test_assert(evbdd_is_ordered(q3, 3)); test_assert(fabs(qmdd_get_norm(q3, 3) - 1.0) < 1e-14); // inverse QFT q3 = qmdd_circuit(q3, CIRCID_reverse_range, 0, 2); q3 = qmdd_circuit(q3, CIRCID_QFT_inv, 0, 2); - test_assert(aadd_equivalent(q3, qref3, 3, false, false)); - test_assert(aadd_equivalent(q3, qref3, 3, true, false)); + test_assert(evbdd_equivalent(q3, qref3, 3, false, false)); + test_assert(evbdd_equivalent(q3, qref3, 3, true, false)); test_assert(q3 == qref3); test_assert(fabs(qmdd_get_norm(q3, 3) - 1.0) < 1e-14); @@ -496,49 +496,49 @@ int test_QFT() qref5 = qmdd_create_basis_state(5, x5); q5 = qmdd_circuit(q5, CIRCID_QFT, 0, 4); q5 = qmdd_circuit(q5, CIRCID_reverse_range, 0, 4); - test_assert(aadd_is_ordered(q5, 5)); + test_assert(evbdd_is_ordered(q5, 5)); // check approx equal against output from qiskit - x5[4]=0; x5[3]=0; x5[2]=0; x5[1]=0; x5[0]=0; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.7677669529663692e-01,-6.4946704217662027e-17); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=0; x5[3]=0; x5[2]=0; x5[1]=0; x5[0]=1; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.7677669529663692e-01,6.4946704217662027e-17); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=0; x5[3]=0; x5[2]=0; x5[1]=1; x5[0]=0; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(7.5771154920605696e-17,1.7677669529663692e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=0; x5[3]=0; x5[2]=0; x5[1]=1; x5[0]=1; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-7.5771154920605696e-17,-1.7677669529663692e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=0; x5[3]=0; x5[2]=1; x5[1]=0; x5[0]=0; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.2500000000000011e-01,-1.2499999999999999e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=0; x5[3]=0; x5[2]=1; x5[1]=0; x5[0]=1; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.2500000000000011e-01,1.2499999999999999e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=0; x5[3]=0; x5[2]=1; x5[1]=1; x5[0]=0; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.2499999999999999e-01,-1.2500000000000011e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=0; x5[3]=0; x5[2]=1; x5[1]=1; x5[0]=1; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.2499999999999999e-01,1.2500000000000011e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=0; x5[3]=1; x5[2]=0; x5[1]=0; x5[0]=0; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(6.7649512518274585e-02,-1.6332037060954713e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=0; x5[3]=1; x5[2]=0; x5[1]=0; x5[0]=1; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-6.7649512518274585e-02,1.6332037060954713e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=0; x5[3]=1; x5[2]=0; x5[1]=1; x5[0]=0; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.6332037060954713e-01,6.7649512518274571e-02); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=0; x5[3]=1; x5[2]=0; x5[1]=1; x5[0]=1; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.6332037060954713e-01,-6.7649512518274571e-02); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=0; x5[3]=1; x5[2]=1; x5[1]=0; x5[0]=0; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.6332037060954710e-01,6.7649512518274696e-02); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=0; x5[3]=1; x5[2]=1; x5[1]=0; x5[0]=1; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.6332037060954710e-01,-6.7649512518274696e-02); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=0; x5[3]=1; x5[2]=1; x5[1]=1; x5[0]=0; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-6.7649512518274710e-02,-1.6332037060954710e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=0; x5[3]=1; x5[2]=1; x5[1]=1; x5[0]=1; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(6.7649512518274710e-02,1.6332037060954710e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=1; x5[3]=0; x5[2]=0; x5[1]=0; x5[0]=0; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.4698445030241986e-01,9.8211869798387877e-02); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=1; x5[3]=0; x5[2]=0; x5[1]=0; x5[0]=1; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.4698445030241986e-01,-9.8211869798387877e-02); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=1; x5[3]=0; x5[2]=0; x5[1]=1; x5[0]=0; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-9.8211869798387877e-02,-1.4698445030241986e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=1; x5[3]=0; x5[2]=0; x5[1]=1; x5[0]=1; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(9.8211869798387877e-02,1.4698445030241986e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=1; x5[3]=0; x5[2]=1; x5[1]=0; x5[0]=0; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.7337998066526852e-01,3.4487422410367806e-02); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=1; x5[3]=0; x5[2]=1; x5[1]=0; x5[0]=1; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.7337998066526852e-01,-3.4487422410367806e-02); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=1; x5[3]=0; x5[2]=1; x5[1]=1; x5[0]=0; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-3.4487422410367799e-02,1.7337998066526852e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=1; x5[3]=0; x5[2]=1; x5[1]=1; x5[0]=1; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(3.4487422410367799e-02,-1.7337998066526852e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=1; x5[3]=1; x5[2]=0; x5[1]=0; x5[0]=0; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(3.4487422410367972e-02,1.7337998066526850e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=1; x5[3]=1; x5[2]=0; x5[1]=0; x5[0]=1; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-3.4487422410367972e-02,-1.7337998066526850e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=1; x5[3]=1; x5[2]=0; x5[1]=1; x5[0]=0; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.7337998066526850e-01,3.4487422410367986e-02); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=1; x5[3]=1; x5[2]=0; x5[1]=1; x5[0]=1; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.7337998066526850e-01,-3.4487422410367986e-02); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=1; x5[3]=1; x5[2]=1; x5[1]=0; x5[0]=0; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(9.8211869798387752e-02,-1.4698445030241994e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=1; x5[3]=1; x5[2]=1; x5[1]=0; x5[0]=1; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-9.8211869798387752e-02,1.4698445030241994e-01); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=1; x5[3]=1; x5[2]=1; x5[1]=1; x5[0]=0; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.4698445030241994e-01,9.8211869798387752e-02); test_assert(weight_approx_eq(&c, &cref)); - x5[4]=1; x5[3]=1; x5[2]=1; x5[1]=1; x5[0]=1; a = aadd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.4698445030241994e-01,-9.8211869798387752e-02); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=0; x5[3]=0; x5[2]=0; x5[1]=0; x5[0]=0; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.7677669529663692e-01,-6.4946704217662027e-17); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=0; x5[3]=0; x5[2]=0; x5[1]=0; x5[0]=1; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.7677669529663692e-01,6.4946704217662027e-17); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=0; x5[3]=0; x5[2]=0; x5[1]=1; x5[0]=0; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(7.5771154920605696e-17,1.7677669529663692e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=0; x5[3]=0; x5[2]=0; x5[1]=1; x5[0]=1; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-7.5771154920605696e-17,-1.7677669529663692e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=0; x5[3]=0; x5[2]=1; x5[1]=0; x5[0]=0; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.2500000000000011e-01,-1.2499999999999999e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=0; x5[3]=0; x5[2]=1; x5[1]=0; x5[0]=1; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.2500000000000011e-01,1.2499999999999999e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=0; x5[3]=0; x5[2]=1; x5[1]=1; x5[0]=0; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.2499999999999999e-01,-1.2500000000000011e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=0; x5[3]=0; x5[2]=1; x5[1]=1; x5[0]=1; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.2499999999999999e-01,1.2500000000000011e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=0; x5[3]=1; x5[2]=0; x5[1]=0; x5[0]=0; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(6.7649512518274585e-02,-1.6332037060954713e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=0; x5[3]=1; x5[2]=0; x5[1]=0; x5[0]=1; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-6.7649512518274585e-02,1.6332037060954713e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=0; x5[3]=1; x5[2]=0; x5[1]=1; x5[0]=0; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.6332037060954713e-01,6.7649512518274571e-02); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=0; x5[3]=1; x5[2]=0; x5[1]=1; x5[0]=1; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.6332037060954713e-01,-6.7649512518274571e-02); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=0; x5[3]=1; x5[2]=1; x5[1]=0; x5[0]=0; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.6332037060954710e-01,6.7649512518274696e-02); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=0; x5[3]=1; x5[2]=1; x5[1]=0; x5[0]=1; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.6332037060954710e-01,-6.7649512518274696e-02); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=0; x5[3]=1; x5[2]=1; x5[1]=1; x5[0]=0; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-6.7649512518274710e-02,-1.6332037060954710e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=0; x5[3]=1; x5[2]=1; x5[1]=1; x5[0]=1; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(6.7649512518274710e-02,1.6332037060954710e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=1; x5[3]=0; x5[2]=0; x5[1]=0; x5[0]=0; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.4698445030241986e-01,9.8211869798387877e-02); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=1; x5[3]=0; x5[2]=0; x5[1]=0; x5[0]=1; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.4698445030241986e-01,-9.8211869798387877e-02); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=1; x5[3]=0; x5[2]=0; x5[1]=1; x5[0]=0; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-9.8211869798387877e-02,-1.4698445030241986e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=1; x5[3]=0; x5[2]=0; x5[1]=1; x5[0]=1; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(9.8211869798387877e-02,1.4698445030241986e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=1; x5[3]=0; x5[2]=1; x5[1]=0; x5[0]=0; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.7337998066526852e-01,3.4487422410367806e-02); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=1; x5[3]=0; x5[2]=1; x5[1]=0; x5[0]=1; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.7337998066526852e-01,-3.4487422410367806e-02); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=1; x5[3]=0; x5[2]=1; x5[1]=1; x5[0]=0; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-3.4487422410367799e-02,1.7337998066526852e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=1; x5[3]=0; x5[2]=1; x5[1]=1; x5[0]=1; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(3.4487422410367799e-02,-1.7337998066526852e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=1; x5[3]=1; x5[2]=0; x5[1]=0; x5[0]=0; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(3.4487422410367972e-02,1.7337998066526850e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=1; x5[3]=1; x5[2]=0; x5[1]=0; x5[0]=1; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-3.4487422410367972e-02,-1.7337998066526850e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=1; x5[3]=1; x5[2]=0; x5[1]=1; x5[0]=0; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.7337998066526850e-01,3.4487422410367986e-02); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=1; x5[3]=1; x5[2]=0; x5[1]=1; x5[0]=1; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.7337998066526850e-01,-3.4487422410367986e-02); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=1; x5[3]=1; x5[2]=1; x5[1]=0; x5[0]=0; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(9.8211869798387752e-02,-1.4698445030241994e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=1; x5[3]=1; x5[2]=1; x5[1]=0; x5[0]=1; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-9.8211869798387752e-02,1.4698445030241994e-01); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=1; x5[3]=1; x5[2]=1; x5[1]=1; x5[0]=0; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(1.4698445030241994e-01,9.8211869798387752e-02); test_assert(weight_approx_eq(&c, &cref)); + x5[4]=1; x5[3]=1; x5[2]=1; x5[1]=1; x5[0]=1; a = evbdd_getvalue(q5, x5); weight_value(a, &c); cref = cmake(-1.4698445030241994e-01,-9.8211869798387752e-02); test_assert(weight_approx_eq(&c, &cref)); test_assert(qmdd_is_unitvector(q5, 5)); test_assert(fabs(qmdd_get_norm(q5, 5) - 1.0) < 1e-14); // inverse QFT q5 = qmdd_circuit(q5, CIRCID_reverse_range, 0, 4); q5 = qmdd_circuit(q5, CIRCID_QFT_inv, 0, 4); - test_assert(aadd_equivalent(q5, qref5, 5, false, false)); - test_assert(aadd_equivalent(q5, qref5, 5, true, false)); + test_assert(evbdd_equivalent(q5, qref5, 5, false, false)); + test_assert(evbdd_equivalent(q5, qref5, 5, true, false)); test_assert(q5 == qref5); test_assert(fabs(qmdd_get_norm(q5, 5) - 1.0) < 1e-14); @@ -578,7 +578,7 @@ int test_5qubit_circuit() q = qmdd_cgate(q, GATEID_Z, 0, 4); q = qmdd_gate(q, GATEID_H, 1); test_assert(qmdd_is_unitvector(q, 5)); q = qmdd_gate(q, GATEID_H, 3); q = qmdd_gate(q, GATEID_X, 1); test_assert(qmdd_is_unitvector(q, 5)); q = qmdd_cgate(q, GATEID_Z, 1, 2); q = qmdd_gate(q, GATEID_Z, 1); test_assert(qmdd_is_unitvector(q, 5)); - node_count = aadd_countnodes(q); + node_count = evbdd_countnodes(q); if (test_measure_random_state(q, n_qubits)) return 1; test_assert(fabs(qmdd_get_norm(q, n_qubits) - 1.0) < 1e-14); @@ -600,12 +600,12 @@ int test_5qubit_circuit() q = qmdd_cgate(q, GATEID_X, 1, 3); q = qmdd_cgate(q, GATEID_Z, 3, 4); test_assert(qmdd_is_unitvector(q, 5)); q = qmdd_gate(q, GATEID_X, 2); q = qmdd_cgate(q, GATEID_Z, 1, 2); test_assert(qmdd_is_unitvector(q, 5)); - test_assert(aadd_equivalent(q, qref, n_qubits, false, VERBOSE)); // check approx equiv - test_assert(aadd_equivalent(q, qref, n_qubits, true, VERBOSE)); // check exact equiv + test_assert(evbdd_equivalent(q, qref, n_qubits, false, VERBOSE)); // check approx equiv + test_assert(evbdd_equivalent(q, qref, n_qubits, true, VERBOSE)); // check exact equiv test_assert(q == qref); fp = fopen("5_qubit_res.dot", "w"); - aadd_fprintdot(fp, q, true); + evbdd_fprintdot(fp, q, true); fclose(fp); if(VERBOSE) printf("qmdd 5 qubit circuit: ok (%" PRIu64 " nodes)\n", node_count); @@ -640,7 +640,7 @@ int test_10qubit_circuit() q = qmdd_cgate(q, GATEID_Z, 7, 8); q = qmdd_gate(q, GATEID_X, 7); test_assert(qmdd_is_unitvector(q, 10)); q = qmdd_gate(q, GATEID_Z, 2); q = qmdd_gate(q, GATEID_Z, 7); test_assert(qmdd_is_unitvector(q, 10)); q = qmdd_gate(q, GATEID_X, 6); q = qmdd_gate(q, GATEID_X, 1); test_assert(qmdd_is_unitvector(q, 10)); - node_count = aadd_countnodes(q); + node_count = evbdd_countnodes(q); if (test_measure_random_state(q, 10)) return 1; test_assert(fabs(qmdd_get_norm(q, 10) - 1.0) < 1e-14); @@ -661,8 +661,8 @@ int test_10qubit_circuit() q = qmdd_cgate(q, GATEID_X, 6, 9); q = qmdd_gate(q, GATEID_X, 6); test_assert(qmdd_is_unitvector(q, 10)); q = qmdd_gate(q, GATEID_H, 0); q = qmdd_cgate(q, GATEID_X, 1, 3); test_assert(qmdd_is_unitvector(q, 10)); - test_assert(aadd_equivalent(q, qref, 10, false, VERBOSE)); // check approx equiv - test_assert(aadd_equivalent(q, qref, 10, true, VERBOSE)); // check exact equiv + test_assert(evbdd_equivalent(q, qref, 10, false, VERBOSE)); // check approx equiv + test_assert(evbdd_equivalent(q, qref, 10, true, VERBOSE)); // check exact equiv test_assert(q == qref); if(VERBOSE) printf("qmdd 10 qubit circuit: ok (%" PRIu64 " nodes)\n", node_count); @@ -707,7 +707,7 @@ int test_20qubit_circuit() q = qmdd_cgate(q, GATEID_X, 5, 11); q = qmdd_cgate(q, GATEID_X, 9, 17); q = qmdd_gate(q, GATEID_Z, 3); q = qmdd_cgate(q, GATEID_X, 11, 18); q = qmdd_cgate(q, GATEID_Z, 5, 15); q = qmdd_cgate(q, GATEID_X, 0, 15); q = qmdd_cgate(q, GATEID_X, 1, 6); q = qmdd_cgate(q, GATEID_X, 8, 16); q = qmdd_cgate(q, GATEID_X, 5, 19); q = qmdd_cgate(q, GATEID_Z, 3, 18); q = qmdd_cgate(q, GATEID_X, 5, 8); q = qmdd_cgate(q, GATEID_Z, 14, 18); - node_count = aadd_countnodes(q); + node_count = evbdd_countnodes(q); if (test_measure_random_state(q, 20)) return 1; test_assert(fabs(qmdd_get_norm(q, 20) - 1.0) < 1e-14); @@ -738,8 +738,8 @@ int test_20qubit_circuit() q = qmdd_cgate(q, GATEID_Z, 13, 16); q = qmdd_cgate(q, GATEID_Z, 1, 16); q = qmdd_cgate(q, GATEID_Z, 0, 4); q = qmdd_cgate(q, GATEID_Z, 9, 10); q = qmdd_gate(q, GATEID_Z, 4); q = qmdd_cgate(q, GATEID_X, 1, 12); q = qmdd_gate(q, GATEID_H, 16); q = qmdd_cgate(q, GATEID_Z, 4, 18); - test_assert(aadd_equivalent(q, qref, 20, false, VERBOSE)); // check approx equiv - test_assert(aadd_equivalent(q, qref, 20, true, VERBOSE)); // check exact equiv + test_assert(evbdd_equivalent(q, qref, 20, false, VERBOSE)); // check approx equiv + test_assert(evbdd_equivalent(q, qref, 20, true, VERBOSE)); // check exact equiv test_assert(q == qref); if(VERBOSE) printf("qmdd 20 qubit circuit: ok (%" PRIu64 " nodes)\n", node_count); diff --git a/test/test_qmdd_gates.c b/test/test_qmdd_gates.c index f0032c7..e0a049c 100644 --- a/test/test_qmdd_gates.c +++ b/test/test_qmdd_gates.c @@ -29,21 +29,21 @@ int test_x_gate() x3[2] = 0; x3[1] = 0; x3[0] = 0; q3 = qmdd_create_basis_state(nqubits, x3); x3[2] = 0; x3[1] = 1; x3[0] = 0; q4 = qmdd_create_basis_state(nqubits, x3); x3[2] = 0; x3[1] = 1; x3[0] = 1; q5 = qmdd_create_basis_state(nqubits, x3); - test_assert(aadd_countnodes(q3) == 4); - test_assert(aadd_countnodes(q4) == 4); - test_assert(aadd_countnodes(q5) == 4); - test_assert(aadd_is_ordered(q3, nqubits)); - test_assert(aadd_is_ordered(q4, nqubits)); - test_assert(aadd_is_ordered(q5, nqubits)); + test_assert(evbdd_countnodes(q3) == 4); + test_assert(evbdd_countnodes(q4) == 4); + test_assert(evbdd_countnodes(q5) == 4); + test_assert(evbdd_is_ordered(q3, nqubits)); + test_assert(evbdd_is_ordered(q4, nqubits)); + test_assert(evbdd_is_ordered(q5, nqubits)); q3 = qmdd_gate(q3, GATEID_X, 1); test_assert(q3 == q4); q3 = qmdd_gate(q3, GATEID_X, 0); test_assert(q3 == q5); - test_assert(aadd_countnodes(q3) == 4); - test_assert(aadd_countnodes(q4) == 4); - test_assert(aadd_countnodes(q5) == 4); - test_assert(aadd_is_ordered(q3, nqubits)); - test_assert(aadd_is_ordered(q4, nqubits)); - test_assert(aadd_is_ordered(q5, nqubits)); + test_assert(evbdd_countnodes(q3) == 4); + test_assert(evbdd_countnodes(q4) == 4); + test_assert(evbdd_countnodes(q5) == 4); + test_assert(evbdd_is_ordered(q3, nqubits)); + test_assert(evbdd_is_ordered(q4, nqubits)); + test_assert(evbdd_is_ordered(q5, nqubits)); // Same 3 qubit test with sqrt(X) x3[2] = 0; x3[1] = 0; x3[0] = 0; q3 = qmdd_create_basis_state(nqubits, x3); @@ -58,12 +58,12 @@ int test_x_gate() q3 = qmdd_gate(q3, GATEID_sqrtX, 0); test_assert(qmdd_is_unitvector(q3, nqubits)); test_assert(q3 == q5); - test_assert(aadd_countnodes(q3) == 4); - test_assert(aadd_countnodes(q4) == 4); - test_assert(aadd_countnodes(q5) == 4); - test_assert(aadd_is_ordered(q3, nqubits)); - test_assert(aadd_is_ordered(q4, nqubits)); - test_assert(aadd_is_ordered(q5, nqubits)); + test_assert(evbdd_countnodes(q3) == 4); + test_assert(evbdd_countnodes(q4) == 4); + test_assert(evbdd_countnodes(q5) == 4); + test_assert(evbdd_is_ordered(q3, nqubits)); + test_assert(evbdd_is_ordered(q4, nqubits)); + test_assert(evbdd_is_ordered(q5, nqubits)); // Same 3 qubit test with sqrt(X)^dag x3[2] = 0; x3[1] = 0; x3[0] = 0; q3 = qmdd_create_basis_state(nqubits, x3); @@ -78,12 +78,12 @@ int test_x_gate() q3 = qmdd_gate(q3, GATEID_sqrtXdag, 0); test_assert(qmdd_is_unitvector(q3, nqubits)); test_assert(q3 == q5); - test_assert(aadd_countnodes(q3) == 4); - test_assert(aadd_countnodes(q4) == 4); - test_assert(aadd_countnodes(q5) == 4); - test_assert(aadd_is_ordered(q3, nqubits)); - test_assert(aadd_is_ordered(q4, nqubits)); - test_assert(aadd_is_ordered(q5, nqubits)); + test_assert(evbdd_countnodes(q3) == 4); + test_assert(evbdd_countnodes(q4) == 4); + test_assert(evbdd_countnodes(q5) == 4); + test_assert(evbdd_is_ordered(q3, nqubits)); + test_assert(evbdd_is_ordered(q4, nqubits)); + test_assert(evbdd_is_ordered(q5, nqubits)); // Test sqrt(X) sqrt(X)^dag gives I x3[2] = 0; x3[1] = 0; x3[0] = 0; q3 = qmdd_create_basis_state(nqubits, x3); @@ -117,10 +117,10 @@ int test_h_gate() q0 = qmdd_gate(q0, GATEID_H, 0); q1 = qmdd_gate(q1, GATEID_H, 0); - x[0] = 0; a = aadd_getvalue(q0, x); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x[0] = 1; a = aadd_getvalue(q0, x); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x[0] = 0; a = aadd_getvalue(q1, x); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x[0] = 1; a = aadd_getvalue(q1, x); test_assert(a == complex_lookup(-1.0/flt_sqrt(2.0),0)); + x[0] = 0; a = evbdd_getvalue(q0, x); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x[0] = 1; a = evbdd_getvalue(q0, x); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x[0] = 0; a = evbdd_getvalue(q1, x); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x[0] = 1; a = evbdd_getvalue(q1, x); test_assert(a == complex_lookup(-1.0/flt_sqrt(2.0),0)); // Two qubit test @@ -134,38 +134,38 @@ int test_h_gate() q4 = qmdd_gate(q4, GATEID_H, 1); // q4 = |+0> q5 = qmdd_gate(q5, GATEID_H, 0); q5 = qmdd_gate(q5, GATEID_H, 1); // q5 = |++> - test_assert(aadd_is_ordered(q2, nqubits)); - test_assert(aadd_is_ordered(q3, nqubits)); - test_assert(aadd_is_ordered(q4, nqubits)); - test_assert(aadd_is_ordered(q5, nqubits)); + test_assert(evbdd_is_ordered(q2, nqubits)); + test_assert(evbdd_is_ordered(q3, nqubits)); + test_assert(evbdd_is_ordered(q4, nqubits)); + test_assert(evbdd_is_ordered(q5, nqubits)); // q2 = |0+> - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(q2, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(q2, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(q2, x2); test_assert(a == AADD_ZERO); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(q2, x2); test_assert(a == AADD_ZERO); - test_assert(aadd_countnodes(q2) == 2); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(q2, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(q2, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(q2, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(q2, x2); test_assert(a == EVBDD_ZERO); + test_assert(evbdd_countnodes(q2) == 2); // q3 = |0-> - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(q3, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(q3, x2); test_assert(a == complex_lookup(-1.0/flt_sqrt(2.0),0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(q3, x2); test_assert(a == AADD_ZERO); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(q3, x2); test_assert(a == AADD_ZERO); - test_assert(aadd_countnodes(q3) == 3); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(q3, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(q3, x2); test_assert(a == complex_lookup(-1.0/flt_sqrt(2.0),0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(q3, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(q3, x2); test_assert(a == EVBDD_ZERO); + test_assert(evbdd_countnodes(q3) == 3); // q4 = |+0> - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(q4, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(q4, x2); test_assert(a == AADD_ZERO); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(q4, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(q4, x2); test_assert(a == AADD_ZERO); - test_assert(aadd_countnodes(q4) == 2); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(q4, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(q4, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(q4, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(q4, x2); test_assert(a == EVBDD_ZERO); + test_assert(evbdd_countnodes(q4) == 2); // q5 = |++> - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(q5, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(q5, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(q5, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(q5, x2); test_assert(a == complex_lookup(0.5, 0)); - test_assert(aadd_countnodes(q5) == 1); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(q5, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(q5, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(q5, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(q5, x2); test_assert(a == complex_lookup(0.5, 0)); + test_assert(evbdd_countnodes(q5) == 1); if(VERBOSE) printf("qmdd h gates: ok\n"); return 0; @@ -203,38 +203,38 @@ int test_phase_gates() test_assert(q0 == qTTdag); test_assert(q0 == qTdagT); - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); - test_assert(aadd_countnodes(q0) == 1); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); + test_assert(evbdd_countnodes(q0) == 1); q0 = qmdd_gate(q0, GATEID_Z, 0); - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); - test_assert(aadd_countnodes(q0) == 2); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); + test_assert(evbdd_countnodes(q0) == 2); q0 = qmdd_gate(q0, GATEID_Z, 0); q0 = qmdd_gate(q0, GATEID_Z, 1); - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); - test_assert(aadd_countnodes(q0) == 2); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); + test_assert(evbdd_countnodes(q0) == 2); q0 = qmdd_gate(q0, GATEID_Z, 1); q0 = qmdd_gate(q0, GATEID_S, 0); q0 = qmdd_gate(q0, GATEID_S, 0); - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); - test_assert(aadd_countnodes(q0) == 2); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); + test_assert(evbdd_countnodes(q0) == 2); q0 = qmdd_gate(q0, GATEID_Z, 0); q0 = qmdd_gate(q0, GATEID_T, 1); @@ -242,11 +242,11 @@ int test_phase_gates() q0 = qmdd_gate(q0, GATEID_T, 1); q0 = qmdd_gate(q0, GATEID_T, 1); - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); - test_assert(aadd_countnodes(q0) == 2); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); + test_assert(evbdd_countnodes(q0) == 2); q0 = qmdd_gate(q0, GATEID_Z, 1); q0 = qmdd_gate(q0, GATEID_Tdag, 1); @@ -254,21 +254,21 @@ int test_phase_gates() q0 = qmdd_gate(q0, GATEID_Tdag, 1); q0 = qmdd_gate(q0, GATEID_Tdag, 1); - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); - test_assert(aadd_countnodes(q0) == 2); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); + test_assert(evbdd_countnodes(q0) == 2); q0 = qmdd_gate(q0, GATEID_Z, 1); q0 = qmdd_gate(q0, GATEID_Sdag, 1); q0 = qmdd_gate(q0, GATEID_Sdag, 1); - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); - test_assert(aadd_countnodes(q0) == 2); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(q0, x2); test_assert(a == complex_lookup(-0.5,0)); + test_assert(evbdd_countnodes(q0) == 2); // check R_k gates test_assert(gates[GATEID_Rk(0)][3] == gates[GATEID_I][3]); @@ -300,32 +300,32 @@ int test_pauli_rotation_gates() qRef = qmdd_gate(qInit, GATEID_I, t); qTest = qmdd_gate(qInit, GATEID_Rz(2.0*pi), t); qTest = qmdd_remove_global_phase(qTest); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // Z gate qRef = qmdd_gate(qInit, GATEID_Z, t); qTest = qmdd_gate(qInit, GATEID_Rz(pi), t); qTest = qmdd_remove_global_phase(qTest); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // S gate qRef = qmdd_gate(qInit, GATEID_S, t); qTest = qmdd_gate(qInit, GATEID_Rz(pi/2.0), t); qTest = qmdd_remove_global_phase(qTest); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // T gate qRef = qmdd_gate(qInit, GATEID_T, t); qTest = qmdd_gate(qInit, GATEID_Rz(pi/4.0), t); qTest = qmdd_remove_global_phase(qTest); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); @@ -337,29 +337,29 @@ int test_pauli_rotation_gates() // I gate qRef = qmdd_gate(qInit, GATEID_I, t); qTest = qmdd_gate(qInit, GATEID_Phase(2.0*pi), t); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // Z gate qRef = qmdd_gate(qInit, GATEID_Z, t); qTest = qmdd_gate(qInit, GATEID_Phase(pi), t); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // S gate qRef = qmdd_gate(qInit, GATEID_S, t); qTest = qmdd_gate(qInit, GATEID_Phase(pi/2.0), t); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // T gate qRef = qmdd_gate(qInit, GATEID_T, t); qTest = qmdd_gate(qInit, GATEID_Phase(pi/4.0), t); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); @@ -371,16 +371,16 @@ int test_pauli_rotation_gates() qRef = qmdd_gate(qInit, GATEID_I, t); qTest = qmdd_gate(qInit, GATEID_Rx(2.0*pi), t); qTest = qmdd_remove_global_phase(qTest); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // X gate qRef = qmdd_gate(qInit, GATEID_X, t); qTest = qmdd_gate(qInit, GATEID_Rx(pi), t); qTest = qmdd_remove_global_phase(qTest); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // sqrt(X) gate @@ -388,22 +388,22 @@ int test_pauli_rotation_gates() qTest = qmdd_gate(qInit, GATEID_Rx(pi/2.0), t); qRef = qmdd_remove_global_phase(qRef); qTest = qmdd_remove_global_phase(qTest); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // U(theta,-pi/2,pi/2) == Rx(theta) qRef = qmdd_gate(qInit, GATEID_Rx(pi/2.0), t); qTest = qmdd_gate(qInit, GATEID_U(pi/2.0, -pi/2.0, pi/2.0), t); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // U(theta,-pi/2,pi/2) == Rx(theta) qRef = qmdd_gate(qInit, GATEID_Rx(1.42), t); qTest = qmdd_gate(qInit, GATEID_U(1.42, -pi/2.0, pi/2.0), t); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); @@ -416,8 +416,8 @@ int test_pauli_rotation_gates() qRef = qmdd_gate(qInit, GATEID_I, t); qTest = qmdd_gate(qInit, GATEID_Ry(2.0*pi), t); qTest = qmdd_remove_global_phase(qTest); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // Y gate @@ -425,8 +425,8 @@ int test_pauli_rotation_gates() qTest = qmdd_gate(qInit, GATEID_Ry(pi), t); qRef = qmdd_remove_global_phase(qRef); qTest = qmdd_remove_global_phase(qTest); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // sqrt(Y) gate @@ -434,8 +434,8 @@ int test_pauli_rotation_gates() qTest = qmdd_gate(qInit, GATEID_Ry(pi/2.0), t); qRef = qmdd_remove_global_phase(qRef); qTest = qmdd_remove_global_phase(qTest); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // sqrt(Y)^dag gate @@ -443,8 +443,8 @@ int test_pauli_rotation_gates() qTest = qmdd_gate(qInit, GATEID_Ry(-pi/2.0), t); qRef = qmdd_remove_global_phase(qRef); qTest = qmdd_remove_global_phase(qTest); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // U(theta,0,0) == Ry(theta) @@ -452,8 +452,8 @@ int test_pauli_rotation_gates() qTest = qmdd_gate(qInit, GATEID_U(pi/2.0, 0, 0), t); qRef = qmdd_remove_global_phase(qRef); qTest = qmdd_remove_global_phase(qTest); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // U(theta,0,0) == Ry(theta) @@ -461,8 +461,8 @@ int test_pauli_rotation_gates() qTest = qmdd_gate(qInit, GATEID_U(0.66, 0, 0), t); qRef = qmdd_remove_global_phase(qRef); qTest = qmdd_remove_global_phase(qTest); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, false)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); @@ -481,35 +481,35 @@ int test_cx_gate() 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)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(qBell, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - 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 == AADD_ZERO); - test_assert(aadd_countnodes(qBell) == 2); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(qBell, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(qBell, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(qBell, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(qBell, x2); test_assert(a == EVBDD_ZERO); + test_assert(evbdd_countnodes(qBell) == 2); qBell = qmdd_cgate(qBell, GATEID_X, 0, 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 == 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)); - test_assert(aadd_countnodes(qBell) == 4); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(qBell, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(qBell, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(qBell, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(qBell, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + test_assert(evbdd_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); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(qBell, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(qBell, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(qBell, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(qBell, x2); test_assert(a == EVBDD_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)); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(qBell, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(qBell, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(qBell, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(qBell, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); // TODO: more tests @@ -529,38 +529,38 @@ int test_cz_gate() 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); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + test_assert(evbdd_countnodes(qGraph) == 1); qGraph = qmdd_cgate(qGraph, GATEID_Z, 0, 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) == 3); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(qGraph, x2); test_assert(a == complex_lookup(-0.5,0)); + test_assert(evbdd_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); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + test_assert(evbdd_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); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(qGraph, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(qGraph, x2); test_assert(a == complex_lookup(-0.5,0)); + test_assert(evbdd_countnodes(qGraph) == 3); if(VERBOSE) printf("qmdd CZ gates: ok\n"); return 0; @@ -580,18 +580,18 @@ int test_ccz_gate() 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] = 0; x3[1] = 0; x3[0] = 0; aRef = evbdd_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); - 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 == wgt_mul(aRef,weight_lookup(&mone))); - 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 == aRef); - test_assert(aadd_is_ordered(q3, 3)); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == wgt_mul(aRef,weight_lookup(&mone))); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + test_assert(evbdd_is_ordered(q3, 3)); // Test CCZ using qmdd_cgate2() q3 = qmdd_create_all_zero_state(nqubits); @@ -599,18 +599,18 @@ int test_ccz_gate() 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] = 0; x3[1] = 0; x3[0] = 0; aRef = evbdd_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)); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == wgt_mul(aRef,weight_lookup(&mone))); + test_assert(evbdd_is_ordered(q3, 3)); // Test CCZ using qmdd_cgate2() with target between controls q3 = qmdd_create_all_zero_state(nqubits); @@ -618,18 +618,18 @@ int test_ccz_gate() 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] = 0; x3[1] = 0; x3[0] = 0; aRef = evbdd_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)); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == wgt_mul(aRef,weight_lookup(&mone))); + test_assert(evbdd_is_ordered(q3, 3)); // TODO: more tests? @@ -648,24 +648,24 @@ int test_controlled_range_gate() BDDVAR nqubits = 10; q10 = qmdd_create_basis_state(10, x10); for (BDDVAR k = 0; k < nqubits; k++) q10 = qmdd_gate(q10, GATEID_H, k); - aRef = aadd_getvalue(q10, x10); + aRef = evbdd_getvalue(q10, x10); aRefMin = wgt_mul(aRef, weight_lookup(&mone)); // assert |++..+> state - test_assert(aadd_is_ordered(q10, nqubits)); + test_assert(evbdd_is_ordered(q10, nqubits)); for (uint64_t x = 0; x < (1UL< we should have a phase flip if (x_bits[0] && x_bits[1] && x_bits[2] && x_bits[3] && x_bits[7]) { test_assert(a == aRefMin); @@ -679,10 +679,10 @@ int test_controlled_range_gate() // CZ gate on c=2,3,4,5 t=8 qres = qmdd_cgate_range(q10, GATEID_Z, 2, 5, 8); - test_assert(aadd_is_ordered(qres, nqubits)); + test_assert(evbdd_is_ordered(qres, nqubits)); for (uint64_t x = 0; x < (1UL< we should have a phase flip if (x_bits[2] && x_bits[3] && x_bits[4] && x_bits[5] && x_bits[8]) { test_assert(a == aRefMin); diff --git a/test/test_qmdd_gc.c b/test/test_qmdd_gc.c index 7608cc7..ae3b3d1 100644 --- a/test/test_qmdd_gc.c +++ b/test/test_qmdd_gc.c @@ -17,8 +17,8 @@ int test_grover_gc() QMDD qmdd = qmdd_grover(qubits, flag); // Sanity checks on final state - flag[qubits] = 0; AADD_WGT amp0 = aadd_getvalue(qmdd, flag); - flag[qubits] = 1; AADD_WGT amp1 = aadd_getvalue(qmdd, flag); + flag[qubits] = 0; EVBDD_WGT amp0 = evbdd_getvalue(qmdd, flag); + flag[qubits] = 1; EVBDD_WGT amp1 = evbdd_getvalue(qmdd, flag); double flag_prob = qmdd_amp_to_prob(amp0) + qmdd_amp_to_prob(amp1); free(flag); @@ -56,7 +56,7 @@ int test_table_size_increase() uint64_t wgt_tablesize = min_wgt_tablesize; for (int i = 0; i < 10; i++) { test_assert(sylvan_get_edge_weight_table_size() == wgt_tablesize); - aadd_gc_wgt_table(); + evbdd_gc_wgt_table(); wgt_tablesize = 2*wgt_tablesize; if (wgt_tablesize > max_wgt_tablesize) { wgt_tablesize = max_wgt_tablesize; @@ -95,46 +95,46 @@ int test_custom_gate_gc_protection() // apply the same custom gate twice (w/o gc) qRef = qmdd_gate(qInit, GATEID_U(pi/2.0, -pi/2.0, pi/4.0), t); qTest = qmdd_gate(qInit, GATEID_U(pi/2.0, -pi/2.0, pi/4.0), t); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, true)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, true)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // apply the same custom gate twice, but with gc of node table between them - aadd_protect(&qRef); - aadd_protect(&qTest); + evbdd_protect(&qRef); + evbdd_protect(&qTest); qRef = qmdd_gate(qInit, GATEID_U(pi/2.0, -pi/2.0, pi/4.0), t); sylvan_gc(); qTest = qmdd_gate(qInit, GATEID_U(pi/2.0, -pi/2.0, pi/4.0), t); - aadd_unprotect(&qRef); - aadd_unprotect(&qTest); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, true)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + evbdd_unprotect(&qRef); + evbdd_unprotect(&qTest); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, true)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // trigger gc of node table after defining temp gate, but before applying it - aadd_protect(&qRef); - aadd_protect(&qTest); + evbdd_protect(&qRef); + evbdd_protect(&qTest); tmp_gateid = GATEID_U(pi/2.0, -pi/2.0, pi/4.0); qRef = qmdd_gate(qInit, tmp_gateid, t); sylvan_gc(); qTest = qmdd_gate(qInit, tmp_gateid, t); - aadd_unprotect(&qRef); - aadd_unprotect(&qTest); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, true)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + evbdd_unprotect(&qRef); + evbdd_unprotect(&qTest); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, true)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); // trigger gc of edge wgt table after defining temp gate, but before applying it - aadd_protect(&qRef); - aadd_protect(&qTest); + evbdd_protect(&qRef); + evbdd_protect(&qTest); tmp_gateid = GATEID_U(pi/2.0, -pi/2.0, pi/4.0); qRef = qmdd_gate(qInit, tmp_gateid, t); - aadd_gc_wgt_table(); + evbdd_gc_wgt_table(); qTest = qmdd_gate(qInit, tmp_gateid, t); - aadd_unprotect(&qRef); - aadd_unprotect(&qTest); - test_assert(aadd_equivalent(qRef, qTest, nqubits, false, true)); - test_assert(aadd_equivalent(qRef, qTest, nqubits, true, false)); + evbdd_unprotect(&qRef); + evbdd_unprotect(&qTest); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, true)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); diff --git a/test/test_qmdd_matrix.c b/test/test_qmdd_matrix.c index 9739166..f45a2ad 100644 --- a/test/test_qmdd_matrix.c +++ b/test/test_qmdd_matrix.c @@ -28,17 +28,17 @@ int test_x_gate() mSqrtXdag = qmdd_create_single_qubit_gate(nqubits, 0, GATEID_sqrtXdag); // matrix-vector mult - v0 = aadd_matvec_mult(mX, v0, nqubits); test_assert(v0 == v1); - v0 = aadd_matvec_mult(mX, v0, nqubits); test_assert(v0 == v2); + v0 = evbdd_matvec_mult(mX, v0, nqubits); test_assert(v0 == v1); + v0 = evbdd_matvec_mult(mX, v0, nqubits); test_assert(v0 == v2); // matrix-matrix mult - mTemp = aadd_matmat_mult(mI, mX, nqubits); test_assert(mTemp == mX); - mTemp = aadd_matmat_mult(mX, mI, nqubits); test_assert(mTemp == mX); - mTemp = aadd_matmat_mult(mX, mX, nqubits); test_assert(mTemp == mI); - mTemp = aadd_matmat_mult(mSqrtX, mSqrtX, nqubits); test_assert(mTemp == mX); - mTemp = aadd_matmat_mult(mSqrtXdag, mSqrtXdag, nqubits); test_assert(mTemp == mX); - mTemp = aadd_matmat_mult(mSqrtX, mSqrtXdag, nqubits); test_assert(mTemp == mI); - mTemp = aadd_matmat_mult(mSqrtXdag, mSqrtX, nqubits); test_assert(mTemp == mI); + mTemp = evbdd_matmat_mult(mI, mX, nqubits); test_assert(mTemp == mX); + mTemp = evbdd_matmat_mult(mX, mI, nqubits); test_assert(mTemp == mX); + mTemp = evbdd_matmat_mult(mX, mX, nqubits); test_assert(mTemp == mI); + mTemp = evbdd_matmat_mult(mSqrtX, mSqrtX, nqubits); test_assert(mTemp == mX); + mTemp = evbdd_matmat_mult(mSqrtXdag, mSqrtXdag, nqubits); test_assert(mTemp == mX); + mTemp = evbdd_matmat_mult(mSqrtX, mSqrtXdag, nqubits); test_assert(mTemp == mI); + mTemp = evbdd_matmat_mult(mSqrtXdag, mSqrtX, nqubits); test_assert(mTemp == mI); // 3 qubit test @@ -51,33 +51,33 @@ int test_x_gate() mX0 = qmdd_create_single_qubit_gate(nqubits, 0, GATEID_X); // X gate on q0 uint32_t gateids[] = {GATEID_X, GATEID_X, GATEID_I}; // X on q0 and q1, I on q2 mXXI = qmdd_create_single_qubit_gates(nqubits, gateids); - test_assert(aadd_countnodes(v3) == 4); - test_assert(aadd_countnodes(v4) == 4); - test_assert(aadd_countnodes(v5) == 4); + test_assert(evbdd_countnodes(v3) == 4); + test_assert(evbdd_countnodes(v4) == 4); + test_assert(evbdd_countnodes(v5) == 4); // matrix-vector mult - v3 = aadd_matvec_mult(mX1, v3, nqubits); test_assert(v3 == v4); - v3 = aadd_matvec_mult(mX0, v3, nqubits); test_assert(v3 == v5); - test_assert(aadd_countnodes(v3) == 4); - test_assert(aadd_countnodes(v4) == 4); - test_assert(aadd_countnodes(v5) == 4); + v3 = evbdd_matvec_mult(mX1, v3, nqubits); test_assert(v3 == v4); + v3 = evbdd_matvec_mult(mX0, v3, nqubits); test_assert(v3 == v5); + test_assert(evbdd_countnodes(v3) == 4); + test_assert(evbdd_countnodes(v4) == 4); + test_assert(evbdd_countnodes(v5) == 4); // matrix-matrix mult - mTemp = aadd_matmat_mult(mI, mX0, nqubits); test_assert(mTemp == mX0); - mTemp = aadd_matmat_mult(mI, mX1, nqubits); test_assert(mTemp == mX1); - mTemp = aadd_matmat_mult(mX0, mI, nqubits); test_assert(mTemp == mX0); - mTemp = aadd_matmat_mult(mX1, mI, nqubits); test_assert(mTemp == mX1); - mTemp = aadd_matmat_mult(mX0,mX0, nqubits); test_assert(mTemp == mI); - mTemp = aadd_matmat_mult(mX1,mX1, nqubits); test_assert(mTemp == mI); - mTemp = aadd_matmat_mult(mX0,mX1, nqubits); test_assert(mTemp == mXXI); - mTemp = aadd_matmat_mult(mX1,mX0, nqubits); test_assert(mTemp == mXXI); + mTemp = evbdd_matmat_mult(mI, mX0, nqubits); test_assert(mTemp == mX0); + mTemp = evbdd_matmat_mult(mI, mX1, nqubits); test_assert(mTemp == mX1); + mTemp = evbdd_matmat_mult(mX0, mI, nqubits); test_assert(mTemp == mX0); + mTemp = evbdd_matmat_mult(mX1, mI, nqubits); test_assert(mTemp == mX1); + mTemp = evbdd_matmat_mult(mX0,mX0, nqubits); test_assert(mTemp == mI); + mTemp = evbdd_matmat_mult(mX1,mX1, nqubits); test_assert(mTemp == mI); + mTemp = evbdd_matmat_mult(mX0,mX1, nqubits); test_assert(mTemp == mXXI); + mTemp = evbdd_matmat_mult(mX1,mX0, nqubits); test_assert(mTemp == mXXI); // calculate (X0 X1)|00> by multiplying X0 and X1 first - mTemp = aadd_matmat_mult(mX0, mX1, nqubits); + mTemp = evbdd_matmat_mult(mX0, mX1, nqubits); v3 = qmdd_create_all_zero_state(nqubits); - v3 = aadd_matvec_mult(mTemp, v3, nqubits); + v3 = evbdd_matvec_mult(mTemp, v3, nqubits); test_assert(v3 == v5); - test_assert(aadd_countnodes(v5) == 4); + test_assert(evbdd_countnodes(v5) == 4); if(VERBOSE) printf("matrix qmdd x gates: ok\n"); @@ -103,29 +103,29 @@ int test_h_gate() mZ = qmdd_create_single_qubit_gate(nqubits, 0, GATEID_Z); // matrix-vector mult - v0 = aadd_matvec_mult(mH, v0, nqubits); - v1 = aadd_matvec_mult(mH, v1, nqubits); + v0 = evbdd_matvec_mult(mH, v0, nqubits); + v1 = evbdd_matvec_mult(mH, v1, nqubits); - x[0] = 1; a = aadd_getvalue(v0, x); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x[0] = 0; a = aadd_getvalue(v0, x); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x[0] = 0; a = aadd_getvalue(v1, x); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x[0] = 1; a = aadd_getvalue(v1, x); test_assert(a == complex_lookup(-1.0/flt_sqrt(2.0),0)); + x[0] = 1; a = evbdd_getvalue(v0, x); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x[0] = 0; a = evbdd_getvalue(v0, x); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x[0] = 0; a = evbdd_getvalue(v1, x); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x[0] = 1; a = evbdd_getvalue(v1, x); test_assert(a == complex_lookup(-1.0/flt_sqrt(2.0),0)); // matrix-matrix mult - mTemp = aadd_matmat_mult(mI, mH, nqubits); test_assert(mTemp == mH); - mTemp = aadd_matmat_mult(mH, mI, nqubits); test_assert(mTemp == mH); - mTemp = aadd_matmat_mult(mH, mH, nqubits); test_assert(mTemp == mI); + mTemp = evbdd_matmat_mult(mI, mH, nqubits); test_assert(mTemp == mH); + mTemp = evbdd_matmat_mult(mH, mI, nqubits); test_assert(mTemp == mH); + mTemp = evbdd_matmat_mult(mH, mH, nqubits); test_assert(mTemp == mI); // HXH = Z mTemp = mH; - mTemp = aadd_matmat_mult(mTemp, mX, nqubits); - mTemp = aadd_matmat_mult(mTemp, mH, nqubits); + mTemp = evbdd_matmat_mult(mTemp, mX, nqubits); + mTemp = evbdd_matmat_mult(mTemp, mH, nqubits); test_assert(mTemp == mZ); // HZH = X mTemp = mH; - mTemp = aadd_matmat_mult(mTemp, mZ, nqubits); - mTemp = aadd_matmat_mult(mTemp, mH, nqubits); + mTemp = evbdd_matmat_mult(mTemp, mZ, nqubits); + mTemp = evbdd_matmat_mult(mTemp, mH, nqubits); test_assert(mTemp == mX); // Two qubit test @@ -141,63 +141,63 @@ int test_h_gate() mHH = qmdd_create_single_qubit_gates_same(nqubits, GATEID_H); // matrix-vector mult - v2 = aadd_matvec_mult(mHI, v2, nqubits); // v2 = |0+> - v3 = aadd_matvec_mult(mHI, v3, nqubits); // v3 = |0-> - v4 = aadd_matvec_mult(mIH, v4, nqubits); // v4 = |+0> - v5 = aadd_matvec_mult(mHI, v5, nqubits); - v5 = aadd_matvec_mult(mIH, v5, nqubits); // v5 = |++> - v6 = aadd_matvec_mult(mHH, v6, nqubits); // v6 = |-+> + v2 = evbdd_matvec_mult(mHI, v2, nqubits); // v2 = |0+> + v3 = evbdd_matvec_mult(mHI, v3, nqubits); // v3 = |0-> + v4 = evbdd_matvec_mult(mIH, v4, nqubits); // v4 = |+0> + v5 = evbdd_matvec_mult(mHI, v5, nqubits); + v5 = evbdd_matvec_mult(mIH, v5, nqubits); // v5 = |++> + v6 = evbdd_matvec_mult(mHH, v6, nqubits); // v6 = |-+> // v2 = |0+> - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v2, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v2, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v2, x2); test_assert(a == AADD_ZERO); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v2, x2); test_assert(a == AADD_ZERO); - test_assert(aadd_countnodes(v2) == 2); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v2, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v2, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v2, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v2, x2); test_assert(a == EVBDD_ZERO); + test_assert(evbdd_countnodes(v2) == 2); // v3 = |0-> - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v3, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v3, x2); test_assert(a == complex_lookup(-1.0/flt_sqrt(2.0),0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v3, x2); test_assert(a == AADD_ZERO); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v3, x2); test_assert(a == AADD_ZERO); - test_assert(aadd_countnodes(v3) == 3); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v3, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v3, x2); test_assert(a == complex_lookup(-1.0/flt_sqrt(2.0),0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v3, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v3, x2); test_assert(a == EVBDD_ZERO); + test_assert(evbdd_countnodes(v3) == 3); // v4 = |+0> - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v4, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v4, x2); test_assert(a == AADD_ZERO); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v4, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v4, x2); test_assert(a == AADD_ZERO); - test_assert(aadd_countnodes(v4) == 2); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v4, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v4, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v4, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v4, x2); test_assert(a == EVBDD_ZERO); + test_assert(evbdd_countnodes(v4) == 2); // v5 = |++> - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v5, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v5, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v5, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v5, x2); test_assert(a == complex_lookup(0.5, 0)); - test_assert(aadd_countnodes(v5) == 1); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v5, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v5, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v5, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v5, x2); test_assert(a == complex_lookup(0.5, 0)); + test_assert(evbdd_countnodes(v5) == 1); // v6 = |-+> - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v6, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v6, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v6, x2); test_assert(a == complex_lookup(-0.5, 0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v6, x2); test_assert(a == complex_lookup(-0.5, 0)); - test_assert(aadd_countnodes(v6) == 2); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v6, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v6, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v6, x2); test_assert(a == complex_lookup(-0.5, 0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v6, x2); test_assert(a == complex_lookup(-0.5, 0)); + test_assert(evbdd_countnodes(v6) == 2); // matrix-matrix mult - mTemp = aadd_matmat_mult(mII, mHI, nqubits); test_assert(mTemp == mHI); - mTemp = aadd_matmat_mult(mII, mIH, nqubits); test_assert(mTemp == mIH); - mTemp = aadd_matmat_mult(mHI, mII, nqubits); test_assert(mTemp == mHI); - mTemp = aadd_matmat_mult(mIH, mII, nqubits); test_assert(mTemp == mIH); - mTemp = aadd_matmat_mult(mHI, mHI, nqubits); test_assert(mTemp == mII); - mTemp = aadd_matmat_mult(mIH, mIH, nqubits); test_assert(mTemp == mII); - mTemp = aadd_matmat_mult(mHI, mIH, nqubits); test_assert(mTemp == mHH); - mTemp = aadd_matmat_mult(mIH, mHI, nqubits); test_assert(mTemp == mHH); - mTemp = aadd_matmat_mult(mHH, mHH, nqubits); test_assert(mTemp == mII); + mTemp = evbdd_matmat_mult(mII, mHI, nqubits); test_assert(mTemp == mHI); + mTemp = evbdd_matmat_mult(mII, mIH, nqubits); test_assert(mTemp == mIH); + mTemp = evbdd_matmat_mult(mHI, mII, nqubits); test_assert(mTemp == mHI); + mTemp = evbdd_matmat_mult(mIH, mII, nqubits); test_assert(mTemp == mIH); + mTemp = evbdd_matmat_mult(mHI, mHI, nqubits); test_assert(mTemp == mII); + mTemp = evbdd_matmat_mult(mIH, mIH, nqubits); test_assert(mTemp == mII); + mTemp = evbdd_matmat_mult(mHI, mIH, nqubits); test_assert(mTemp == mHH); + mTemp = evbdd_matmat_mult(mIH, mHI, nqubits); test_assert(mTemp == mHH); + mTemp = evbdd_matmat_mult(mHH, mHH, nqubits); test_assert(mTemp == mII); // calculate (H0 H1)|00> by multiplying H0 and H1 first - mTemp = aadd_matmat_mult(mHI, mIH, nqubits); + mTemp = evbdd_matmat_mult(mHI, mIH, nqubits); v6 = qmdd_create_all_zero_state(nqubits); - v6 = aadd_matvec_mult(mTemp, v6, nqubits); + v6 = evbdd_matvec_mult(mTemp, v6, nqubits); test_assert(v6 == v5); @@ -228,21 +228,21 @@ int test_phase_gates() mT1 = qmdd_create_single_qubit_gate(nqubits, 1, GATEID_T); mTdag0 = qmdd_create_single_qubit_gate(nqubits, 0, GATEID_Tdag); mTdag1 = qmdd_create_single_qubit_gate(nqubits, 1, GATEID_Tdag); - v0 = aadd_matvec_mult(mH0, v0, nqubits); - v0 = aadd_matvec_mult(mH1, v0, nqubits); // start with v0 = |++> + v0 = evbdd_matvec_mult(mH0, v0, nqubits); + v0 = evbdd_matvec_mult(mH1, v0, nqubits); // start with v0 = |++> // matrix-vector mult - vZ = aadd_matvec_mult(mZ0, v0, nqubits); - vS = aadd_matvec_mult(mS0, v0, nqubits); - vSS = aadd_matvec_mult(mS0, vS, nqubits); - vT = aadd_matvec_mult(mT0, v0, nqubits); - vTT = aadd_matvec_mult(mT0, vT, nqubits); - vTTTT = aadd_matvec_mult(mT0, vTT, nqubits); - vTTTT = aadd_matvec_mult(mT0, vTTTT, nqubits); - vTTdag = aadd_matvec_mult(mT0, v0, nqubits); - vTTdag = aadd_matvec_mult(mTdag0, vTTdag, nqubits); - vTdagT = aadd_matvec_mult(mTdag0, v0, nqubits); - vTdagT = aadd_matvec_mult(mT0, vTdagT, nqubits); + vZ = evbdd_matvec_mult(mZ0, v0, nqubits); + vS = evbdd_matvec_mult(mS0, v0, nqubits); + vSS = evbdd_matvec_mult(mS0, vS, nqubits); + vT = evbdd_matvec_mult(mT0, v0, nqubits); + vTT = evbdd_matvec_mult(mT0, vT, nqubits); + vTTTT = evbdd_matvec_mult(mT0, vTT, nqubits); + vTTTT = evbdd_matvec_mult(mT0, vTTTT, nqubits); + vTTdag = evbdd_matvec_mult(mT0, v0, nqubits); + vTTdag = evbdd_matvec_mult(mTdag0, vTTdag, nqubits); + vTdagT = evbdd_matvec_mult(mTdag0, v0, nqubits); + vTdagT = evbdd_matvec_mult(mT0, vTdagT, nqubits); test_assert(vZ == vSS); test_assert(vS == vTT); test_assert(vZ == vTTTT); @@ -250,87 +250,87 @@ int test_phase_gates() test_assert(v0 == vTdagT); // matrix-matrix mult - mTemp = aadd_matmat_mult(mI, mZ0, nqubits); test_assert(mTemp == mZ0); - mTemp = aadd_matmat_mult(mZ0, mI, nqubits); test_assert(mTemp == mZ0); - mTemp = aadd_matmat_mult(mI, mZ1, nqubits); test_assert(mTemp == mZ1); - mTemp = aadd_matmat_mult(mZ1, mI, nqubits); test_assert(mTemp == mZ1); - mTemp = aadd_matmat_mult(mI, mS0, nqubits); test_assert(mTemp == mS0); - mTemp = aadd_matmat_mult(mS0, mI, nqubits); test_assert(mTemp == mS0); - mTemp = aadd_matmat_mult(mI, mT0, nqubits); test_assert(mTemp == mT0); - mTemp = aadd_matmat_mult(mT0, mI, nqubits); test_assert(mTemp == mT0); - mTemp = aadd_matmat_mult(mS0, mS0, nqubits); test_assert(mTemp == mZ0); - mTemp = aadd_matmat_mult(mS0, mSdag0, nqubits); test_assert(mTemp == mI); - mTemp = aadd_matmat_mult(mSdag0, mS0, nqubits); test_assert(mTemp == mI); - mTemp = aadd_matmat_mult(mSdag0, mSdag0, nqubits); test_assert(mTemp == mZ0); - mTemp = aadd_matmat_mult(mT0, mT0, nqubits); test_assert(mTemp == mS0); - mTemp = aadd_matmat_mult(mT1, mTdag1, nqubits); test_assert(mTemp == mI); - mTemp = aadd_matmat_mult(mTdag1, mT1, nqubits); test_assert(mTemp == mI); - mTemp = aadd_matmat_mult(mTdag0, mTdag0, nqubits); test_assert(mTemp == mSdag0); + mTemp = evbdd_matmat_mult(mI, mZ0, nqubits); test_assert(mTemp == mZ0); + mTemp = evbdd_matmat_mult(mZ0, mI, nqubits); test_assert(mTemp == mZ0); + mTemp = evbdd_matmat_mult(mI, mZ1, nqubits); test_assert(mTemp == mZ1); + mTemp = evbdd_matmat_mult(mZ1, mI, nqubits); test_assert(mTemp == mZ1); + mTemp = evbdd_matmat_mult(mI, mS0, nqubits); test_assert(mTemp == mS0); + mTemp = evbdd_matmat_mult(mS0, mI, nqubits); test_assert(mTemp == mS0); + mTemp = evbdd_matmat_mult(mI, mT0, nqubits); test_assert(mTemp == mT0); + mTemp = evbdd_matmat_mult(mT0, mI, nqubits); test_assert(mTemp == mT0); + mTemp = evbdd_matmat_mult(mS0, mS0, nqubits); test_assert(mTemp == mZ0); + mTemp = evbdd_matmat_mult(mS0, mSdag0, nqubits); test_assert(mTemp == mI); + mTemp = evbdd_matmat_mult(mSdag0, mS0, nqubits); test_assert(mTemp == mI); + mTemp = evbdd_matmat_mult(mSdag0, mSdag0, nqubits); test_assert(mTemp == mZ0); + mTemp = evbdd_matmat_mult(mT0, mT0, nqubits); test_assert(mTemp == mS0); + mTemp = evbdd_matmat_mult(mT1, mTdag1, nqubits); test_assert(mTemp == mI); + mTemp = evbdd_matmat_mult(mTdag1, mT1, nqubits); test_assert(mTemp == mI); + mTemp = evbdd_matmat_mult(mTdag0, mTdag0, nqubits); test_assert(mTemp == mSdag0); // T^7 == Tdag mTemp = qmdd_create_all_identity_matrix(nqubits); for (int k = 0; k < 7; k++) - mTemp = aadd_matmat_mult(mTemp, mT0, nqubits); + mTemp = evbdd_matmat_mult(mTemp, mT0, nqubits); test_assert(mTemp == mTdag0); // more matrix-vector mult - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - test_assert(aadd_countnodes(v0) == 1); - - v0 = aadd_matvec_mult(mZ0, v0, nqubits); - - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); - test_assert(aadd_countnodes(v0) == 2); - - v0 = aadd_matvec_mult(mZ0, v0, nqubits); - v0 = aadd_matvec_mult(mZ1, v0, nqubits); - - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); - test_assert(aadd_countnodes(v0) == 2); - - v0 = aadd_matvec_mult(mZ1, v0, nqubits); - v0 = aadd_matvec_mult(mS0, v0, nqubits); - v0 = aadd_matvec_mult(mS0, v0, nqubits); - - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); - test_assert(aadd_countnodes(v0) == 2); - - v0 = aadd_matvec_mult(mZ0, v0, nqubits); - v0 = aadd_matvec_mult(mT1, v0, nqubits); - v0 = aadd_matvec_mult(mT1, v0, nqubits); - v0 = aadd_matvec_mult(mT1, v0, nqubits); - v0 = aadd_matvec_mult(mT1, v0, nqubits); - - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); - test_assert(aadd_countnodes(v0) == 2); - - v0 = aadd_matvec_mult(mZ1, v0, nqubits); - v0 = aadd_matvec_mult(mTdag1, v0, nqubits); - v0 = aadd_matvec_mult(mTdag1, v0, nqubits); - v0 = aadd_matvec_mult(mTdag1, v0, nqubits); - v0 = aadd_matvec_mult(mTdag1, v0, nqubits); - - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); - test_assert(aadd_countnodes(v0) == 2); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + test_assert(evbdd_countnodes(v0) == 1); + + v0 = evbdd_matvec_mult(mZ0, v0, nqubits); + + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); + test_assert(evbdd_countnodes(v0) == 2); + + v0 = evbdd_matvec_mult(mZ0, v0, nqubits); + v0 = evbdd_matvec_mult(mZ1, v0, nqubits); + + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); + test_assert(evbdd_countnodes(v0) == 2); + + v0 = evbdd_matvec_mult(mZ1, v0, nqubits); + v0 = evbdd_matvec_mult(mS0, v0, nqubits); + v0 = evbdd_matvec_mult(mS0, v0, nqubits); + + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); + test_assert(evbdd_countnodes(v0) == 2); + + v0 = evbdd_matvec_mult(mZ0, v0, nqubits); + v0 = evbdd_matvec_mult(mT1, v0, nqubits); + v0 = evbdd_matvec_mult(mT1, v0, nqubits); + v0 = evbdd_matvec_mult(mT1, v0, nqubits); + v0 = evbdd_matvec_mult(mT1, v0, nqubits); + + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); + test_assert(evbdd_countnodes(v0) == 2); + + v0 = evbdd_matvec_mult(mZ1, v0, nqubits); + v0 = evbdd_matvec_mult(mTdag1, v0, nqubits); + v0 = evbdd_matvec_mult(mTdag1, v0, nqubits); + v0 = evbdd_matvec_mult(mTdag1, v0, nqubits); + v0 = evbdd_matvec_mult(mTdag1, v0, nqubits); + + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); + test_assert(evbdd_countnodes(v0) == 2); if(VERBOSE) printf("matrix qmdd phase gates: ok\n"); @@ -355,62 +355,62 @@ int test_cx_gate() mCZ = qmdd_create_cgate(nqubits, 0, 1, GATEID_Z); // matrix-matrix mult - mTemp = aadd_matmat_mult(mI, mH0, nqubits); test_assert(mTemp == mH0); - mTemp = aadd_matmat_mult(mH0, mH0, nqubits); test_assert(mTemp == mI); - mTemp = aadd_matmat_mult(mI, mCNOT, nqubits); test_assert(mTemp == mCNOT); - mTemp = aadd_matmat_mult(mCNOT, mI, nqubits); test_assert(mTemp == mCNOT); - mTemp = aadd_matmat_mult(mCNOT, mCNOT, nqubits); test_assert(mTemp == mI); + mTemp = evbdd_matmat_mult(mI, mH0, nqubits); test_assert(mTemp == mH0); + mTemp = evbdd_matmat_mult(mH0, mH0, nqubits); test_assert(mTemp == mI); + mTemp = evbdd_matmat_mult(mI, mCNOT, nqubits); test_assert(mTemp == mCNOT); + mTemp = evbdd_matmat_mult(mCNOT, mI, nqubits); test_assert(mTemp == mCNOT); + mTemp = evbdd_matmat_mult(mCNOT, mCNOT, nqubits); test_assert(mTemp == mI); // H1 CNOT(0,1) H1 = CZ(0,1) mTemp = mH1; - mTemp = aadd_matmat_mult(mTemp, mCNOT, nqubits); - mTemp = aadd_matmat_mult(mTemp, mH1, nqubits); + mTemp = evbdd_matmat_mult(mTemp, mCNOT, nqubits); + mTemp = evbdd_matmat_mult(mTemp, mH1, nqubits); test_assert(mTemp == mCZ); // H1 CZ(0,1) H1 = CNOT(0,1) mTemp = mH1; - mTemp = aadd_matmat_mult(mTemp, mCZ, nqubits); - mTemp = aadd_matmat_mult(mTemp, mH1, nqubits); + mTemp = evbdd_matmat_mult(mTemp, mCZ, nqubits); + mTemp = evbdd_matmat_mult(mTemp, mH1, nqubits); test_assert(mTemp == mCNOT); // matrix-vector mult - v0 = aadd_matvec_mult(mH0, v0, nqubits); - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == AADD_ZERO); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == AADD_ZERO); - test_assert(aadd_countnodes(v0) == 2); - - v0 = aadd_matvec_mult(mCNOT, v0, nqubits); - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == AADD_ZERO); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == AADD_ZERO); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - test_assert(aadd_countnodes(v0) == 4); + v0 = evbdd_matvec_mult(mH0, v0, nqubits); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == EVBDD_ZERO); + test_assert(evbdd_countnodes(v0) == 2); + + v0 = evbdd_matvec_mult(mCNOT, v0, nqubits); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + test_assert(evbdd_countnodes(v0) == 4); // same as above but multiplies H CNOT first before applying to the state // note that we apply the H first, so it is on the right: CNOT H0 |00> - mTemp = aadd_matmat_mult(mCNOT, mH0, nqubits); + mTemp = evbdd_matmat_mult(mCNOT, mH0, nqubits); v0 = qmdd_create_all_zero_state(nqubits); - v0 = aadd_matvec_mult(mTemp, v0, nqubits); - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == AADD_ZERO); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == AADD_ZERO); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - test_assert(aadd_countnodes(v0) == 4); + v0 = evbdd_matvec_mult(mTemp, v0, nqubits); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + test_assert(evbdd_countnodes(v0) == 4); // If we did H0 CNOT |00> instead then the CNOT would not have an effect, // and we'd just be left with H on qubit 0. This is also an example where // computing the circuit matrix first does a bunch of extra work if we // apply it on a state which is unaffected by (some of) the circuit. - mTemp = aadd_matmat_mult(mH0, mCNOT, nqubits); + mTemp = evbdd_matmat_mult(mH0, mCNOT, nqubits); v0 = qmdd_create_all_zero_state(nqubits); - v0 = aadd_matvec_mult(mTemp, v0, nqubits); - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == AADD_ZERO); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == AADD_ZERO); - test_assert(aadd_countnodes(v0) == 2); + v0 = evbdd_matvec_mult(mTemp, v0, nqubits); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(1.0/flt_sqrt(2.0),0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == EVBDD_ZERO); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == EVBDD_ZERO); + test_assert(evbdd_countnodes(v0) == 2); // TODO: test with slightly more qubits @@ -434,22 +434,22 @@ int test_cz_gate() mH1 = qmdd_create_single_qubit_gate(nqubits, 1, GATEID_H); mCZ = qmdd_create_cgate(nqubits, 0, 1, GATEID_Z); - v0 = aadd_matvec_mult(mH0, v0, nqubits); - v0 = aadd_matvec_mult(mH1, v0, nqubits); + v0 = evbdd_matvec_mult(mH0, v0, nqubits); + v0 = evbdd_matvec_mult(mH1, v0, nqubits); - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - test_assert(aadd_countnodes(v0) == 1); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + test_assert(evbdd_countnodes(v0) == 1); - v0 = aadd_matvec_mult(mCZ, v0, nqubits); + v0 = evbdd_matvec_mult(mCZ, v0, nqubits); - x2[1] = 0; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 0; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 0; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); - x2[1] = 1; x2[0] = 1; a = aadd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); - test_assert(aadd_countnodes(v0) == 3); + x2[1] = 0; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 0; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 0; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(0.5, 0)); + x2[1] = 1; x2[0] = 1; a = evbdd_getvalue(v0, x2); test_assert(a == complex_lookup(-0.5,0)); + test_assert(evbdd_countnodes(v0) == 3); // TODO: test with slightly more qubits @@ -472,47 +472,47 @@ int test_ccz_gate() mH1 = qmdd_create_single_qubit_gate(nqubits, 1, GATEID_H); mH2 = qmdd_create_single_qubit_gate(nqubits, 2, GATEID_H); - v3 = aadd_matvec_mult(mH0, v3, nqubits); - v3 = aadd_matvec_mult(mH1, v3, nqubits); - v3 = aadd_matvec_mult(mH2, v3, nqubits); - aRef = aadd_getvalue(v3, x3); + v3 = evbdd_matvec_mult(mH0, v3, nqubits); + v3 = evbdd_matvec_mult(mH1, v3, nqubits); + v3 = evbdd_matvec_mult(mH2, v3, nqubits); + aRef = evbdd_getvalue(v3, x3); test_assert(qmdd_is_unitvector(v3, nqubits)); x3[2]=1; x3[1]=1; x3[0]=1; mCCZ = qmdd_create_all_control_phase(nqubits, x3); - vTemp = aadd_matvec_mult(mCCZ, v3, nqubits); - x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(vTemp, x3); test_assert(a == wgt_neg(aRef)); + vTemp = evbdd_matvec_mult(mCCZ, v3, nqubits); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(vTemp, x3); test_assert(a == wgt_neg(aRef)); x3[2]=0; x3[1]=1; x3[0]=1; mCCZ = qmdd_create_all_control_phase(nqubits, x3); - vTemp = aadd_matvec_mult(mCCZ, v3, nqubits); - x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(vTemp, x3); test_assert(a == wgt_neg(aRef)); - x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); + vTemp = evbdd_matvec_mult(mCCZ, v3, nqubits); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(vTemp, x3); test_assert(a == wgt_neg(aRef)); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); x3[2]=0; x3[1]=1; x3[0]=0; mCCZ = qmdd_create_all_control_phase(nqubits, x3); - vTemp = aadd_matvec_mult(mCCZ, v3, nqubits); - x3[2] = 0; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 0; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 0; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(vTemp, x3); test_assert(a == wgt_neg(aRef)); - x3[2] = 0; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 1; x3[1] = 0; x3[0] = 0; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 1; x3[1] = 0; x3[0] = 1; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(vTemp, x3); test_assert(a == aRef); + vTemp = evbdd_matvec_mult(mCCZ, v3, nqubits); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(vTemp, x3); test_assert(a == wgt_neg(aRef)); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(vTemp, x3); test_assert(a == aRef); if(VERBOSE) printf("matrix qmdd all-control z: ok\n"); @@ -536,9 +536,9 @@ int test_multi_cgate() int c_options[] = {-1,2,-1}; qRef = qmdd_gate(qInit, test_gates[i], 1); 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)); + qTest = evbdd_matvec_mult(matrix, qInit, nqubits); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); } for (uint32_t i = 0; i < len(test_gates); i++) { @@ -546,9 +546,9 @@ int test_multi_cgate() int c_options[] = {2,-1,-1}; qRef = qmdd_gate(qInit, test_gates[i], 0); 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)); + qTest = evbdd_matvec_mult(matrix, qInit, nqubits); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); } @@ -561,9 +561,9 @@ int test_multi_cgate() int c_options[] = {-1, 1, 2, -1, -1}; qRef = qmdd_cgate(qInit, test_gates[i], 1, 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)); + qTest = evbdd_matvec_mult(matrix, qInit, nqubits); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); } for (uint32_t i = 0; i < len(test_gates); i++) { @@ -571,9 +571,9 @@ int test_multi_cgate() int c_options[] = {-1, 1, -1, 2, -1}; qRef = qmdd_cgate(qInit, test_gates[i], 1, 3); 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)); + qTest = evbdd_matvec_mult(matrix, qInit, nqubits); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); } @@ -587,9 +587,9 @@ int test_multi_cgate() int c_options[] = {1, -1, 1, -1, -1, 2}; qRef = qmdd_cgate2(qInit, test_gates[i], 0, 2, 5); 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)); + qTest = evbdd_matvec_mult(matrix, qInit, nqubits); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); } for (uint32_t i = 0; i < len(test_gates); i++) { @@ -599,9 +599,9 @@ int test_multi_cgate() qRef = qmdd_cgate2(qRef, test_gates[i], 0, 2, 5); qRef = qmdd_gate(qRef, GATEID_X, 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)); + qTest = evbdd_matvec_mult(matrix, qInit, nqubits); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); } @@ -618,9 +618,9 @@ int test_multi_cgate() 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)); + qTest = evbdd_matvec_mult(matrix, qInit, nqubits); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, false, false)); + test_assert(evbdd_equivalent(qRef, qTest, nqubits, true, false)); test_assert(qTest == qRef); } @@ -645,28 +645,28 @@ int test_tensor_product() // H (x) H mRef = qmdd_create_single_qubit_gates_same(2, GATEID_H); - mTest = aadd_mat_tensor_prod(mH, mH, 1); - test_assert(aadd_is_ordered(mTest, 4)); // 2*n because of primed and unprimed + mTest = evbdd_mat_tensor_prod(mH, mH, 1); + test_assert(evbdd_is_ordered(mTest, 4)); // 2*n because of primed and unprimed test_assert(mTest == mRef); // X (x) Y mRef = qmdd_create_single_qubit_gates(2, gateid_XY); - mTest = aadd_mat_tensor_prod(mX, mY, 1); - test_assert(aadd_is_ordered(mTest, 4)); + mTest = evbdd_mat_tensor_prod(mX, mY, 1); + test_assert(evbdd_is_ordered(mTest, 4)); test_assert(mTest == mRef); // X (x) (Y (x) Z) mRef = qmdd_create_single_qubit_gates(3, gateid_XYZ); - mTest = aadd_mat_tensor_prod(mY, mZ, 1); - mTest = aadd_mat_tensor_prod(mX, mTest, 1); - test_assert(aadd_is_ordered(mTest, 6)); + mTest = evbdd_mat_tensor_prod(mY, mZ, 1); + mTest = evbdd_mat_tensor_prod(mX, mTest, 1); + test_assert(evbdd_is_ordered(mTest, 6)); test_assert(mTest == mRef); // (X (x) Y) (x) Z mRef = qmdd_create_single_qubit_gates(3, gateid_XYZ); - mTest = aadd_mat_tensor_prod(mX, mY, 1); - mTest = aadd_mat_tensor_prod(mTest, mZ, 2); - test_assert(aadd_is_ordered(mTest, 6)); + mTest = evbdd_mat_tensor_prod(mX, mY, 1); + mTest = evbdd_mat_tensor_prod(mTest, mZ, 2); + test_assert(evbdd_is_ordered(mTest, 6)); test_assert(mTest == mRef); // TODO: tests with bigger matrices @@ -707,7 +707,7 @@ int test_with(int wgt_backend, int norm_strat, int wgt_indx_bits) qsylvan_init_simulator(1LL< -> 2^2*1 + 2^1*0 + 2^0*1 = index 5, starts with 0 - x3[2] = 1; x3[1] = 1; x3[0] = 0; a = aadd_getvalue(q3, x3); test_assert(a == AADD_ZERO); - x3[2] = 1; x3[1] = 1; x3[0] = 1; a = aadd_getvalue(q3, x3); test_assert(a == AADD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q2, x3); test_assert(a == EVBDD_ONE); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q2, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q2, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q2, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q2, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q2, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q2, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q2, x3); test_assert(a == EVBDD_ZERO); + + x3[2] = 0; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 0; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 0; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == EVBDD_ONE); // |101> -> 2^2*1 + 2^1*0 + 2^0*1 = index 5, starts with 0 + x3[2] = 1; x3[1] = 1; x3[0] = 0; a = evbdd_getvalue(q3, x3); test_assert(a == EVBDD_ZERO); + x3[2] = 1; x3[1] = 1; x3[0] = 1; a = evbdd_getvalue(q3, x3); test_assert(a == EVBDD_ZERO); printf("basis state creation mtrdd 2: ok\n"); return 0;