QNLP  v1.0
bin_into_superpos.hpp
Go to the documentation of this file.
1 
8 #ifndef QNLP_BINENCODE
9 #define QNLP_BINENCODE
10 
11 #include <cassert>
12 #include <utility>
13 #include <memory>
14 #include <cmath>
15 #include<vector>
16 #include<complex>
17 #include<iostream>
18 
19 namespace QNLP{
20 
28  #define IS_SET(byte,bit) (((byte) & (1UL << (bit))) >> (bit))
29 
35  template <class SimulatorType>
37  private:
38  using Mat2x2Type = decltype(std::declval<SimulatorType>().getGateX());
39 
40  std::unique_ptr< std::vector<Mat2x2Type> > S;
42 
43  public:
48  EncodeBinIntoSuperpos() = delete;
49 
56  EncodeBinIntoSuperpos(const std::size_t num_bin_patterns, const std::size_t len_bin_pattern_){
57  m = num_bin_patterns;
58  len_bin_pattern = len_bin_pattern_;
59 
61  };
62 
68  };
69 
75 
76  /* Preparation for binary encoding:
77  *
78  * Prepare three matrices S^1,S^2,...,S^m that are required for the implemented
79  * algorithm to encode these binary strings into a superposition state.
80  *
81  * Note the matrix indexing of the S vector of S^p matrices will be backwards:
82  * S[0] -> S^p
83  * S[1] -> S_{p-1}, and so on.
84  */
85  S.reset(new std::vector<Mat2x2Type> (m));
86  {
87  int p = m;
88  double diag, off_diag;
89 
90  for(std::size_t i = 0; i < m; i++){
91  off_diag = 1.0/sqrt((double)(p));
92  diag = off_diag * sqrt((double)(p-1));
93 
94  (*S)[i](0,0) = {diag, 0.0};
95  (*S)[i](0,1) = {off_diag, 0.0};
96  (*S)[i](1,0) = {-off_diag, 0.0};
97  (*S)[i](1,1) = {diag, 0.0};
98 
99  p--;
100  }
101  }
102  }
103 
112  void encodeBinInToSuperpos_unique(SimulatorType& qSim,
113  const std::vector<std::size_t>& reg_memory,
114  const std::vector<std::size_t>& reg_auxiliary,
115  const std::vector<std::size_t>& bin_patterns){
116  std::size_t len_reg_auxiliary = reg_auxiliary.size();
117 
118  // Require length of auxiliary register to have n+2 qubits
119  assert(reg_memory.size() + 1 < len_reg_auxiliary);
120  // Prepare state in |0...>|0...0>|01> of lengths n,n,2
121  #ifdef GATE_LOGGING
122  qSim.getGateWriter().segmentMarkerOut("Prepare state in |0...>|0...0>|01> of lengths n,n,2");
123  #endif
124  qSim.applyGateX(reg_auxiliary[len_reg_auxiliary-1]);
125  std::vector<std::size_t> sub_reg(reg_memory.begin(), reg_memory.begin () + len_bin_pattern);
126 
127  // Iteratively encode each binary pattern.
128  for(std::size_t i = 0; i < m; i++){
129 
130  // Psi0
131  // Encode inputted binary pattern.
132  #ifdef GATE_LOGGING
133  qSim.getGateWriter().segmentMarkerOut("| \\Psi_0 \\rangle");
134  #endif
135  for(std::size_t j = 0; j < len_bin_pattern; j++){
136  if(IS_SET(bin_patterns[i],j)){
137  qSim.applyGateX(reg_auxiliary[j]);
138  }
139  }
140 
141  // Psi1
142  // Copy pattern to auxiliary register of newly created state (now becoming the `active` state).
143  #ifdef GATE_LOGGING
144  qSim.getGateWriter().segmentMarkerOut("| \\Psi_1 \\rangle");
145  #endif
146  for(std::size_t j = 0; j < len_bin_pattern; j++){
147  qSim.applyGateCCX(reg_auxiliary[j], reg_auxiliary[len_reg_auxiliary-1], reg_memory[j]);
148  }
149 
150  // Psi2
151  // Set memory register to state |11..1> if it is the active state.
152  #ifdef GATE_LOGGING
153  qSim.getGateWriter().segmentMarkerOut("| \\Psi_2 \\rangle");
154  #endif
155  for(std::size_t j = 0; j < len_bin_pattern; j++){
156  qSim.applyGateCX(reg_auxiliary[j], reg_memory[j]);
157  qSim.applyGateX(reg_memory[j]);
158  }
159 
160  // Psi3
161  // Apply NCU to flip qubit in second auxiliary register (index `len_reg_auxiliary-2`).
162  #ifdef GATE_LOGGING
163  qSim.getGateWriter().segmentMarkerOut("| \\Psi_3 \\rangle");
164  #endif
165  std::vector<std::size_t> tmp_aux(reg_auxiliary.begin(), reg_auxiliary.begin() + sub_reg.size()-2 );
166  qSim.applyGateNCU(qSim.getGateX(), sub_reg, tmp_aux, reg_auxiliary[len_reg_auxiliary-2], "X");
167 
168  // Psi4
169  // Apply S^i
170  // This flips the second control bit of the new term in the position so
171  // that we get old|11> + new|01> thus breaking it off into larger and smaller chunks.
172  // The new state is now defined as the next 'newly created state'.
173  #ifdef GATE_LOGGING
174  qSim.getGateWriter().segmentMarkerOut("| \\Psi_4 \\rangle");
175  #endif
176  qSim.applyGateCU((*S)[i], reg_auxiliary[len_reg_auxiliary-2], reg_auxiliary[len_reg_auxiliary-1]);
177 
178 
179  // Psi5
180  // Uncompute NCU
181  #ifdef GATE_LOGGING
182  qSim.getGateWriter().segmentMarkerOut("| \\Psi_5 \\rangle");
183  #endif
184  qSim.applyGateNCU(qSim.getGateX(), sub_reg, tmp_aux, reg_auxiliary[len_reg_auxiliary-2], "X");
185 
186  // Psi6
187  // Uncompute setting of memory register to all 1's of active state.
188  #ifdef GATE_LOGGING
189  qSim.getGateWriter().segmentMarkerOut("| \\Psi_6 \\rangle");
190  #endif
191  for(int j = len_bin_pattern-1; j > -1; j--){
192  qSim.applyGateX(reg_memory[j]);
193  qSim.applyGateCX(reg_auxiliary[j], reg_memory[j]);
194  }
195 
196  // Psi7
197  // Uncompute encoding.
198  #ifdef GATE_LOGGING
199  qSim.getGateWriter().segmentMarkerOut("| \\Psi_7 \\rangle");
200  #endif
201  for(int j = len_bin_pattern-1; j > -1; j--){
202  qSim.applyGateCCX(reg_auxiliary[j], reg_auxiliary[len_reg_auxiliary-1], reg_memory[j]);
203  }
204 
205  // Reset the register of the new term to the state |m>|0...0>|01>.
206  #ifdef GATE_LOGGING
207  qSim.getGateWriter().segmentMarkerOut("Reset p to | 00\\ldots 0 \\rangle");
208  #endif
209  for(std::size_t j = 0; j < len_bin_pattern; j++){
210  // Check current pattern against next pattern
211  if(IS_SET(bin_patterns[i],j)){
212  qSim.applyGateX(reg_auxiliary[j]);
213  }
214  }
215  }
216  }
217  };
218 
219 };
220 #endif
EncodeBinIntoSuperpos()=delete
Construct a new object instance to encode a binary string into a superposition (disabled)
void encodeBinInToSuperpos_unique(SimulatorType &qSim, const std::vector< std::size_t > &reg_memory, const std::vector< std::size_t > &reg_auxiliary, const std::vector< std::size_t > &bin_patterns)
Encodes each element of inputted vector as a binary string in a superpostiion of states....
void initialiseMats()
Initialiser of the encoder (define the required PauliX and the unitary matrix S)
EncodeBinIntoSuperpos(const std::size_t num_bin_patterns, const std::size_t len_bin_pattern_)
Construct a new object instance to encode a binary string into a superposition.
#define IS_SET(byte, bit)
Checks if the bit'th bit of the integer byte is set.
~EncodeBinIntoSuperpos()
Destroy the Encode Bin Into Superpos object.
std::unique_ptr< std::vector< Mat2x2Type > > S
decltype(std::declval< SimulatorType >().getGateX()) Mat2x2Type
Definition of class to encode a binary string represented by an integer into a superposition of state...