22 int size = 1 << num_qubits;
24 std::uniform_real_distribution<double> dist(-1.0, 1.0);
27 for (
int i = 0; i < size; i++) {
28 state[i].real = dist(rng);
29 state[i].imag = dist(rng);
30 norm_sq += state[i].real*state[i].real + state[i].imag*state[i].imag;
33 double inv_norm = 1.0 / std::sqrt(norm_sq);
34 for (
int i = 0; i < size; i++){
35 state[i].real *= inv_norm;
36 state[i].imag *= inv_norm;
42 double real_sum = 0.0, imag_sum = 0.0;
43 for (
int i = 0; i < s1.
rows; i++) {
44 real_sum += s1[i].real*s2[i].real + s1[i].imag*s2[i].imag;
45 imag_sum += s1[i].real*s2[i].imag - s1[i].imag*s2[i].real;
47 return std::sqrt(real_sum*real_sum + imag_sum*imag_sum);
51 std::vector<std::vector<int>> combinations;
52 std::vector<bool> selector(n);
53 std::fill(selector.end() -
k, selector.end(),
true);
56 std::vector<int> combination;
57 for (
int i = 0; i <
n; ++i) {
59 combination.push_back(i);
63 std::sort(combination.begin(), combination.end());
64 combinations.push_back(combination);
65 }
while (std::next_permutation(selector.begin(), selector.end()));
68 std::sort(combinations.begin(), combinations.end());
75 const int num_qubits = 10;
78 std::cout <<
"Testing all " << k <<
"-qubit gates on " << num_qubits <<
"-qubit system..." << std::endl;
81 std::cout <<
"Total combinations to test: " << combinations.size() << std::endl;
83 int passed_regular = 0;
84 int failed_regular = 0;
88 for (
size_t combo_idx = 0; combo_idx < combinations.size(); ++combo_idx) {
89 const auto&
qubits = combinations[combo_idx];
97 memset(params.
get_data(), 0.0, params.
size() *
sizeof(double));
107 GHZ_circ_mini.
add_h(0);
109 GHZ_circ_mini.
apply_to(params, Umtx);
114 double fid =
fidelity(state, test_state);
116 if (std::abs(fid - 1.0) < 1e-10) {
120 std::cout <<
"REGULAR FAILED: Qubits {" <<
qubits[0] <<
"," <<
qubits[1]
121 <<
"} - Fidelity: " << std::fixed << std::setprecision(12) << fid << std::endl;
127 double fid_avx =
fidelity(state, test_state_avx);
129 if (std::abs(fid_avx - 1.0) < 1e-10) {
133 std::cout <<
"AVX FAILED: Qubits {" <<
qubits[0] <<
"," <<
qubits[1]
134 <<
"} - Fidelity: " << std::fixed << std::setprecision(12) << fid_avx << std::endl;
139 std::cout <<
"2-qubit gate test results:" << std::endl;
140 std::cout <<
" Regular kernel: " << passed_regular <<
" passed, " << failed_regular <<
" failed" << std::endl;
142 std::cout <<
" AVX kernel: " << passed_avx <<
" passed, " << failed_avx <<
" failed" << std::endl;
145 assert(failed_regular == 0);
147 assert(failed_avx == 0);
152 const int num_qubits = 10;
155 std::cout <<
"Testing all " << k <<
"-qubit gates on " << num_qubits <<
"-qubit system..." << std::endl;
158 std::cout <<
"Total combinations to test: " << combinations.size() << std::endl;
160 int passed_regular = 0;
161 int failed_regular = 0;
165 for (
size_t combo_idx = 0; combo_idx < combinations.size(); ++combo_idx) {
166 const auto&
qubits = combinations[combo_idx];
174 memset(params.
get_data(), 0.0, params.
size() *
sizeof(double));
185 GHZ_circ_mini.
add_h(0);
188 GHZ_circ_mini.
apply_to(params, Umtx);
193 double fid =
fidelity(state, test_state);
195 if (std::abs(fid - 1.0) < 1e-10) {
199 std::cout <<
"REGULAR FAILED: Qubits {" <<
qubits[0] <<
"," <<
qubits[1] <<
"," <<
qubits[2]
200 <<
"} - Fidelity: " << std::fixed << std::setprecision(12) << fid << std::endl;
206 double fid_avx =
fidelity(state, test_state_avx);
208 if (std::abs(fid_avx - 1.0) < 1e-10) {
212 std::cout <<
"AVX FAILED: Qubits {" <<
qubits[0] <<
"," <<
qubits[1] <<
"," <<
qubits[2]
213 <<
"} - Fidelity: " << std::fixed << std::setprecision(12) << fid_avx << std::endl;
218 std::cout <<
"3-qubit gate test results:" << std::endl;
219 std::cout <<
" Regular kernel: " << passed_regular <<
" passed, " << failed_regular <<
" failed" << std::endl;
221 std::cout <<
" AVX kernel: " << passed_avx <<
" passed, " << failed_avx <<
" failed" << std::endl;
224 assert(failed_regular == 0);
226 assert(failed_avx == 0);
231 const int num_qubits = 10;
234 std::cout <<
"Testing all " << k <<
"-qubit gates on " << num_qubits <<
"-qubit system..." << std::endl;
237 std::cout <<
"Total combinations to test: " << combinations.size() << std::endl;
239 int passed_regular = 0;
240 int failed_regular = 0;
244 for (
size_t combo_idx = 0; combo_idx < combinations.size(); ++combo_idx) {
245 const auto&
qubits = combinations[combo_idx];
253 memset(params.
get_data(), 0.0, params.
size() *
sizeof(double));
258 for (
int i = 1; i <
k; ++i) {
265 GHZ_circ_mini.
add_h(0);
266 for (
int i = 1; i <
k; ++i) {
269 GHZ_circ_mini.
apply_to(params, Umtx);
274 double fid =
fidelity(state, test_state);
276 if (std::abs(fid - 1.0) < 1e-10) {
280 std::cout <<
"REGULAR FAILED: Qubits {";
281 for (
size_t i = 0; i <
qubits.size(); ++i) {
283 if (i < qubits.size() - 1) std::cout <<
",";
285 std::cout <<
"} - Fidelity: " << std::fixed << std::setprecision(12) << fid << std::endl;
290 double fid_avx =
fidelity(state, test_state_avx);
292 if (std::abs(fid_avx - 1.0) < 1e-10) {
296 std::cout <<
"AVX FAILED: Qubits {";
297 for (
size_t i = 0; i <
qubits.size(); ++i) {
299 if (i < qubits.size() - 1) std::cout <<
",";
301 std::cout <<
"} - Fidelity: " << std::fixed << std::setprecision(12) << fid_avx << std::endl;
307 std::cout <<
"4-qubit gate test results:" << std::endl;
308 std::cout <<
" Regular kernel: " << passed_regular <<
" passed, " << failed_regular <<
" failed" << std::endl;
310 std::cout <<
" AVX kernel: " << passed_avx <<
" passed, " << failed_avx <<
" failed" << std::endl;
313 assert(failed_regular == 0);
315 assert(failed_avx == 0);
320 const int num_qubits = 10;
323 std::cout <<
"Testing all " << k <<
"-qubit gates on " << num_qubits <<
"-qubit system..." << std::endl;
326 std::cout <<
"Total combinations to test: " << combinations.size() << std::endl;
328 int passed_regular = 0;
329 int failed_regular = 0;
333 for (
size_t combo_idx = 0; combo_idx < combinations.size(); ++combo_idx) {
334 const auto&
qubits = combinations[combo_idx];
342 memset(params.
get_data(), 0.0, params.
size() *
sizeof(double));
347 for (
int i = 1; i <
k; ++i) {
354 GHZ_circ_mini.
add_h(0);
355 for (
int i = 1; i <
k; ++i) {
358 GHZ_circ_mini.
apply_to(params, Umtx);
363 double fid =
fidelity(state, test_state);
365 if (std::abs(fid - 1.0) < 1e-10) {
369 std::cout <<
"REGULAR FAILED: Qubits {";
370 for (
size_t i = 0; i <
qubits.size(); ++i) {
372 if (i < qubits.size() - 1) std::cout <<
",";
374 std::cout <<
"} - Fidelity: " << std::fixed << std::setprecision(12) << fid << std::endl;
380 double fid_avx =
fidelity(state, test_state_avx);
382 if (std::abs(fid_avx - 1.0) < 1e-10) {
386 std::cout <<
"AVX FAILED: Qubits {";
387 for (
size_t i = 0; i <
qubits.size(); ++i) {
389 if (i < qubits.size() - 1) std::cout <<
",";
391 std::cout <<
"} - Fidelity: " << std::fixed << std::setprecision(12) << fid_avx << std::endl;
398 std::cout <<
"5-qubit gate test results:" << std::endl;
399 std::cout <<
" Regular kernel: " << passed_regular <<
" passed, " << failed_regular <<
" failed" << std::endl;
401 std::cout <<
" AVX kernel: " << passed_avx <<
" passed, " << failed_avx <<
" failed" << std::endl;
404 assert(failed_regular == 0);
406 assert(failed_avx == 0);
417 std::vector<int>
qubits = {0,4,7};
419 memset(params.
get_data(), 0.0, params.
size()*
sizeof(double) );
422 GHZ_circ.
add_h(qubits[0]);
423 GHZ_circ.
add_cnot(qubits[1], qubits[0]);
424 GHZ_circ.
add_cnot(qubits[2], qubits[0]);
428 GHZ_circ_mini.
add_h(0);
432 GHZ_circ_mini.
apply_to(params,Umtx);
434 double fid =
fidelity(state, test_state);
435 std::cout << num_qubits <<
"-qubit GHZ gate fidelity: " << fid << std::endl;
436 assert(std::abs(fid - 1.0) < 1e-10);
456 circuit_inner_2->
add_cry(2, 3);
458 circuit_inner_2->
add_u3(3);
459 circuit_inner_2->
add_u3(0);
467 for (
int i = 0; i < num_params; i++) {
468 parameters[i] = (i+1) / (
M_PI*2);
475 circuit.
apply_to(parameters, state);
481 circuit.
apply_to(parameters, test_state);
483 double fid =
fidelity(state, test_state);
484 std::cout <<
"Identity circuit fidelity (should be 1.0): " << fid << std::endl;
485 assert(std::abs(fid - 1.0) < 1e-10);
496 for (
int n=2;
n<6;
n++){
498 for (
int qubit=offset;qubit<offset+
n;qubit++){
499 qubits.push_back(qubit);
515 double dedicated_kernel_AVX_time = 0.0;
516 tbb::tick_count dedicated_kernel_AVX_start = tbb::tick_count::now();
517 for (
int idx=0; idx<samples;idx++){
520 tbb::tick_count dedicated_kernel_AVX_end = tbb::tick_count::now();
522 dedicated_kernel_AVX_time = (dedicated_kernel_AVX_time + (dedicated_kernel_AVX_end-dedicated_kernel_AVX_start).seconds())/samples;
524 std::cout << qubits.size()<<
" qubit dedicated AVX kernel time "<< dedicated_kernel_AVX_time << std::endl;
537 for (
size_t combo_idx = 0; combo_idx < combinations.size(); ++combo_idx) {
538 const auto&
qubits = combinations[combo_idx];
539 std::vector<int> target_qbits = {
qubits[0]};
540 std::vector<int> control_qbits = {};
545 X_gate.
apply_to(params, test_state2);
546 double fid =
fidelity(test_state, test_state2);
547 if (std::abs(fid - 1.0) >= 1e-10) {
548 std::cout <<
"X gate FAILED: Qubit {" <<
qubits[0]
549 <<
"} - Fidelity: " << std::fixed << std::setprecision(12) << fid << std::endl;
551 assert(std::abs(fid - 1.0) < 1e-10);
556 for (
size_t combo_idx = 0; combo_idx < combinations.size(); ++combo_idx) {
557 const auto&
qubits = combinations[combo_idx];
558 std::vector<int> target_qbits = {
qubits[0]};
559 std::vector<int> control_qbits = {
qubits[1]};
564 X_gate.
apply_to(params, test_state2);
565 double fid =
fidelity(test_state, test_state2);
566 if (std::abs(fid - 1.0) >= 1e-10) {
567 std::cout <<
"2 qubit X gate FAILED: Qubits {" <<
qubits[0] <<
"," <<
qubits[1]
568 <<
"} - Fidelity: " << std::fixed << std::setprecision(12) << fid << std::endl;
571 for (
size_t combo_idx = 0; combo_idx < combinations.size(); ++combo_idx) {
572 const auto&
qubits = combinations[combo_idx];
573 std::vector<int> target_qbits = {
qubits[1]};
574 std::vector<int> control_qbits = {
qubits[0]};
579 X_gate.
apply_to(params, test_state2);
580 double fid =
fidelity(test_state, test_state2);
581 if (std::abs(fid - 1.0) >= 1e-10) {
582 std::cout <<
"2 qubit X gate FAILED: Qubits {" <<
qubits[0] <<
"," <<
qubits[1]
583 <<
"} - Fidelity: " << std::fixed << std::setprecision(12) << fid << std::endl;
589 for (
size_t combo_idx = 0; combo_idx < combinations.size(); ++combo_idx) {
590 const auto&
qubits = combinations[combo_idx];
591 std::vector<int> target_qbits = {
qubits[0]};
592 std::vector<int> control_qbits = {
qubits[1],
qubits[2]};
595 Umtx[6*8 + 6].real = 0.0;
596 Umtx[7*8 + 7].real = 0.0;
597 Umtx[6*8 + 7].real = 1.0;
598 Umtx[7*8 + 6].real = 1.0;
600 double fid =
fidelity(test_state, test_state2);
601 if (std::abs(fid - 1.0) >= 1e-10) {
603 std::cout <<
"Toffoli X gate FAILED: Qubits {" << qubits[0] <<
"," << qubits[1] <<
"," << qubits[2]
604 <<
"} - Fidelity: " << std::fixed << std::setprecision(12) << fid << std::endl;
607 std::cout <<
"Toffoli X gate failed cases: " << failed/combinations.size() << std::endl;
void testNQubitGate_Parallel_GHZ()
void add_h(int target_qbit)
Append a Hadamard gate to the list of gates.
void add_x(int target_qbit)
Append a X gate to the list of gates.
void add_gate(Gate *gate)
Append a general gate to the list of gates.
Header file for a class responsible for grouping gates into subcircuits. (Subcircuits can be nested) ...
void add_cnot(int target_qbit, int control_qbit)
Append a CNOT gate gate to the list of gates.
std::vector< std::vector< int > > generate_combinations(int n, int k)
scalar * get_data() const
Call to get the pointer to the stored data.
int rows
The number of rows.
void add_u3(int target_qbit)
Append a U3 gate to the list of gates.
Umtx
The unitary to be decomposed.
Header file of complex array storage array with automatic and thread safe reference counting...
virtual void apply_to(Matrix_real ¶meters_mtx, Matrix &input, int parallel=0) override
Call to apply the gate on the input array/matrix Gates_block*input.
void set_min_fusion(int min_fusion)
Matrix copy() const
Call to create a copy of the matrix.
Double-precision complex matrix (float64).
int size() const
Call to get the number of the allocated elements.
void add_cry(int target_qbit, int control_qbit)
Append a CRY gate to the list of gates.
A class responsible for grouping two-qubit (CNOT,CZ,CH) and one-qubit gates into layers.
double fidelity(const Matrix &s1, const Matrix &s2)
Matrix generateRandomState(int num_qubits)
Matrix create_identity(int matrix_size)
Call to create an identity matrix.
Header file for commonly used functions and wrappers to CBLAS functions.
void testNQubit_Gate_speed()
int get_parameter_num() override
Call to get the number of free parameters.
Class to store data of complex arrays and its properties.