Quantum Gate Decomposer  v1.3
Powerful decomposition of almost any unitary into U3 and CNOT gates
CNOT.cpp
Go to the documentation of this file.
1 /*
2 Created on Fri Jun 26 14:13:26 2020
3 Copyright (C) 2020 Peter Rakyta, Ph.D.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see http://www.gnu.org/licenses/.
17 
18 @author: Peter Rakyta, Ph.D.
19 */
24 #include "qgd/CNOT.h"
25 
26 
27 using namespace std;
28 
29 
30 
31 
38 CNOT::CNOT(int qbit_num_in, int target_qbit_in, int control_qbit_in) {
39 
40  // number of qubits spanning the matrix of the operation
41  qbit_num = qbit_num_in;
42  // the size of the matrix
44  // A string describing the type of the operation
45  type = CNOT_OPERATION;
46  // The number of free parameters
47  parameter_num = 0;
48 
49  if (target_qbit_in >= qbit_num) {
50  printf("The index of the target qubit is larger than the number of qubits");
51  throw "The index of the target qubit is larger than the number of qubits";
52  }
53  // The index of the qubit on which the operation acts (target_qbit >= 0)
54  target_qbit = target_qbit_in;
55 
56 
57  if (control_qbit_in >= qbit_num) {
58  printf("The index of the control qubit is larger than the number of qubits");
59  throw "The index of the control qubit is larger than the number of qubits";
60  }
61  // The index of the qubit which acts as a control qubit (control_qbit >= 0) in controlled operations
62  control_qbit = control_qbit_in;
63 
64 
65 }
66 
71 }
72 
73 
78 Matrix
80  return composite_cnot();
81 }
82 
88 
89 
90  // preallocate array for the composite u3 operation
91  Matrix CNOT_mtx = Matrix(matrix_size, matrix_size);
92  QGD_Complex16* CNOT_mtx_data = CNOT_mtx.get_data();
93 
94  // set to zero all the elements of the matrix
95  memset(CNOT_mtx_data, 0, matrix_size*matrix_size*sizeof(QGD_Complex16) );
96 
97 
98  int target_qbit_power = Power_of_2(target_qbit);
99  int control_qbit_power = Power_of_2(control_qbit);
100 
101 
102  // setting the operation elements
103  for(int idx = 0; idx < matrix_size*matrix_size; ++idx)
104  {
105 
106  int col_idx = idx % matrix_size;
107  int row_idx = (idx-col_idx)/matrix_size;
108 
109 
110 
111  // determine the row state of the control and target qubits corresponding to the given thread
112  int target_qubit_state_row = int(row_idx / target_qbit_power) % 2;
113  int control_qubit_state_row = int(row_idx / control_qbit_power) % 2;
114  int state_row_remaining = row_idx;
115  if (target_qubit_state_row == 1) {
116  state_row_remaining = state_row_remaining - target_qbit_power;
117  }
118  if (control_qubit_state_row == 1) {
119  state_row_remaining = state_row_remaining - control_qbit_power;
120  }
121 
122 
123  // determine the col state of the control and target qubits corresponding to the given thread
124  int target_qubit_state_col = int(col_idx / target_qbit_power) % 2;
125  int control_qubit_state_col = int(col_idx / control_qbit_power) % 2;
126  int state_col_remaining = col_idx;
127  if (target_qubit_state_col == 1) {
128  state_col_remaining = state_col_remaining - target_qbit_power;
129  }
130  if (control_qubit_state_col == 1) {
131  state_col_remaining = state_col_remaining - control_qbit_power;
132  }
133 
134 
135  // setting the col_idx-th element in the row
136  if (control_qubit_state_row == 0 && control_qubit_state_col == 0 && target_qubit_state_row == target_qubit_state_col && state_row_remaining == state_col_remaining) {
137  CNOT_mtx[idx].real = 1;
138  //CNOT_mtx[idx].imag = 0;
139  }
140  /*else if (control_qubit_state_row == 0 && control_qubit_state_col == 0 && target_qubit_state_row != target_qubit_state_col && state_row_remaining == state_col_remaining) {
141  CNOT_mtx[idx].real = 0;
142  CNOT_mtx[idx].imag = 0;
143  }
144  else if (control_qubit_state_row == 1 && control_qubit_state_col == 1 && target_qubit_state_row == target_qubit_state_col && state_row_remaining == state_col_remaining) {
145  CNOT_mtx[idx].real = 0;
146  CNOT_mtx[idx].imag = 0;
147  }*/
148  else if (control_qubit_state_row == 1 && control_qubit_state_col == 1 && target_qubit_state_row != target_qubit_state_col && state_row_remaining == state_col_remaining) {
149  CNOT_mtx[idx].real = 1;
150  //CNOT_mtx[idx].imag = 0;
151  }
152  /*else {
153  CNOT_mtx[idx].real = 0;
154  CNOT_mtx[idx].imag = 0;
155  }*/
156 
157 
158  }
159 
160  return CNOT_mtx;
161 }
162 
163 
169  // setting the number of qubits
171 
172 }
173 
174 
175 
180 void CNOT::reorder_qubits( vector<int> qbit_list) {
181 
182  Operation::reorder_qubits(qbit_list);
183 
184 }
185 
186 
187 
193 
194  CNOT* ret = new CNOT( qbit_num, target_qbit, control_qbit );
195 
196  return ret;
197 
198 }
199 
200 
201 
CNOT(int qbit_num_in, int target_qbit_in, int control_qbit_in)
Constructor of the class.
Definition: CNOT.cpp:38
scalar * get_data()
Call to get the pointer to the stored data.
Definition: matrix_base.h:221
virtual void reorder_qubits(std::vector< int > qbit_list)
Call to reorder the qubits in the matrix of the operation.
Definition: Operation.cpp:118
Header file for a class representing a CNOT operation.
Matrix composite_cnot()
Calculate the matrix of a CNOT gate operation acting on the space of qbit_num qubits.
Definition: CNOT.cpp:87
matrix_size
Definition: example.py:41
void reorder_qubits(std::vector< int > qbit_list)
Call to reorder the qubits in the matrix of the operation.
Definition: CNOT.cpp:180
CNOT * clone()
Call to create a clone of the present class.
Definition: CNOT.cpp:192
Structure type representing complex numbers in the QGD package.
Definition: QGDTypes.h:39
A class representing a CNOT operation.
Definition: CNOT.h:36
void set_qbit_num(int qbit_num)
Call to set the number of qubits spanning the matrix of the operation.
Definition: CNOT.cpp:168
int Power_of_2(int n)
Calculates the n-th power of 2.
Definition: common.cpp:81
Class to store data of complex arrays and its properties.
Definition: matrix.h:12
int qbit_num
Definition: example.py:38
~CNOT()
Destructor of the class.
Definition: CNOT.cpp:70
virtual void set_qbit_num(int qbit_num_in)
Set the number of qubits spanning the matrix of the operation.
Definition: Operation.cpp:82
Matrix get_matrix()
Call to retrieve the operation matrix.
Definition: CNOT.cpp:79