SMG2S
Sparse Matrix Generator with Given Spectrum
nilpotent.hpp
1 /*
2 MIT License
3 Copyright (c) 2019 Xinzhe WU @ Maison de la Simulation, France
4 Copyright (c) 2019-2022, Xinzhe Wu @ Simulation and Data Laboratory Quantum
5  Materials, Forschungszentrum Juelich GmbH.
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 SOFTWARE.
22 */
23 
24 #ifndef __NILPOTENT_H__
25 #define __NILPOTENT_H__
26 
27 
28 #include "utils/utils.hpp"
29 
34 
44 template<typename S>
45 class Nilpotent
46 {
47  private:
49 
54 
58  S degree;
60 
66  S offset;
68 
71  std::vector<S> indOfZeros; // a pair: index
72 
73  public:
75 
87  Nilpotent(S nbOne, S size);
89 
103  Nilpotent(S nbOne, S diag, S size);
105 
116  Nilpotent(std::vector<S> nilpvec, S size);
118 
130  Nilpotent(std::vector<S> nilpvec, S diag, S size);
132  ~Nilpotent();
134 
141  S computeDegree(std::vector<S> nilpvec);
143 
146  S getProbSize(){return probSize;};
150  S getDegree(){return degree;};
155 
159  S getOffset(){return offset;};
161 
164  std::vector<S> getIndOfZeros(){return indOfZeros;};
166 
169  void show();
170 
171 };
172 
173 
174 
175 template<typename S>
176 Nilpotent<S>::Nilpotent(S nbOne, S size){
177 
178  probSize = size;
179  offset = 1; //in the default mode, the Nilpotent is generated with the diagonal of offset 1
180  degree = nbOne + 1;
181 
182  if(nbOne > probSize - 1){
183  try{
184  throw 505;
185  }catch(...){
186  std::cout << "SMG2S]> Caught Exception: for Nilpotent, nbOne is too large" << std::endl;
187  }
188  }
189 
190  for(auto i = 0; i < probSize - 1; i++){
191  if( (i + 1) % (nbOne + 1) == 0 ){
192  indOfZeros.push_back(i);
193  }
194  }
195 }
196 
197 template<typename S>
198 Nilpotent<S>::Nilpotent(S nbOne, S diag, S size){
199 
200  probSize = size;
201  offset = diag; //in the default mode, the Nilpotent is generated with the diagonal of offset 1
202  //degree = nbOne + 1;
203 
204  if(nbOne > probSize - diag){
205  try{
206  throw 505;
207  }catch(...){
208  std::cout << "SMG2S]> Caught Exception: for Nilpotent, nbOne is too large" << std::endl;
209  }
210  }
211 
212  S length = probSize - diag;
213 
214  S cnt = 0;
215 
216  while (cnt < length){
217  S l1 = 1 + (rand() % nbOne);
218  S l2 = 1 + (rand() % nbOne);
219 
220  for(auto i = l1 + cnt; i < l1 + l2 + cnt; i++){
221  if(i < length){
222  indOfZeros.push_back(i);
223  }
224  }
225 
226  cnt += l1 + l2;
227  }
228 
229  std::vector<S> nilpvec(length);
230  std::fill(nilpvec.begin(), nilpvec.end(), 1);
231  for(auto i = 0; i < indOfZeros.size(); i++){
232  nilpvec[indOfZeros[i]] = 0;
233  }
234 
235  degree = computeDegree(nilpvec);
236 
237 }
238 
239 template<typename S>
240 Nilpotent<S>::Nilpotent(std::vector<S> nilpvec, S size){
241  probSize = size;
242  offset = 1;
243 
244  S nbOne = 0;
245  S cnt = 0;
246 
247  if(nilpvec.size() < size - 1){
248  try{
249  throw 505;
250  }catch(...){
251  std::cout << "SMG2S]> Caught Exception: for Nilpotent, nilpvec size is not enough" << std::endl;
252  }
253  }
254  for(auto i = 0; i < size - 1; i++){
255  if (nilpvec[i] != 0){
256  cnt ++;
257  }else if(nilpvec[i] == 0){
258  indOfZeros.push_back(i);
259  if (cnt > nbOne){
260  nbOne = cnt;
261  }
262  cnt = 0;
263  }
264  }
265 
266  degree = nbOne + 1;
267 }
268 
269 template<typename S>
270 Nilpotent<S>::Nilpotent(std::vector<S> nilpvec, S diag, S size){
271  probSize = size;
272  offset = diag;
273 
274  if(nilpvec.size() < size - offset){
275  try{
276  throw 505;
277  }catch(...){
278  std::cout << "SMG2S]> Caught Exception: for Nilpotent, nilpvec size is not enough" << std::endl;
279  }
280  }
281  for(auto i = 0; i < size - diag; i++){
282  if(nilpvec[i] == 0){
283  indOfZeros.push_back(i);
284  }
285  }
286 
287  std::vector<S> vec(nilpvec.begin(), nilpvec.begin() + size - offset);
288  degree = computeDegree(vec);
289 }
290 
291 template<typename S>
292 S Nilpotent<S>::computeDegree(std::vector<S> nilpvec){
293 
294  std::vector<S> vectmps(nilpvec.begin(), nilpvec.end());
295 
296  S diag_offset = offset;
297  degree = 1;
298  S maxdegree = 80;
299 
300  while (degree <= maxdegree){
301  for(auto i = 0; i < probSize - offset - diag_offset; i++){
302  vectmps[i] = nilpvec[i] * vectmps[i+offset];
303  }
304 
305  degree = degree + 1;
306 
307  bool zeros = std::all_of(vectmps.begin(), vectmps.begin() + probSize-offset - diag_offset, [](S i) { return i==0; });
308  if(zeros){
309  break;
310  }
311  diag_offset = diag_offset + offset;
312  }
313 
314  return degree;
315 }
316 
317 template<typename S>
319  std::cout << "Nilpotent: " << "Matrix Size = " << probSize << ", diag_offset = " << offset << "; degree = " << degree << std::endl;
320 }
321 
322 template<typename S>
324 
325 }
326  // end of group3
328 
329 #endif
Nilpotent::degree
S degree
nilpotency of nilpotent matrix
Definition: nilpotent.hpp:58
Nilpotent::show
void show()
Display the information of a nilpotent matrix.
Definition: nilpotent.hpp:318
Nilpotent::getDegree
S getDegree()
Get the nilpotency of nilpotent matrix.
Definition: nilpotent.hpp:151
Nilpotent
A class which determines the information of a nilpotent matrix.
Definition: nilpotent.hpp:45
Nilpotent::Nilpotent
Nilpotent(S nbOne, S size)
A constructor of class `Nilpotent`.
Definition: nilpotent.hpp:176
Nilpotent::getIndOfZeros
std::vector< S > getIndOfZeros()
Get indices of all zeros entries on the off-diagonal.
Definition: nilpotent.hpp:164
Nilpotent::computeDegree
S computeDegree(std::vector< S > nilpvec)
compute the degree of a nilpotent with its off-diagonal entries stored in a vector `nilpvec`.
Definition: nilpotent.hpp:292
Nilpotent::~Nilpotent
~Nilpotent()
A destructor of class `Nilpotent`.
Definition: nilpotent.hpp:323
Nilpotent::offset
S offset
offset of off-diagonal
Definition: nilpotent.hpp:66
Nilpotent::indOfZeros
std::vector< S > indOfZeros
indices of all zeros entries on the off-diagonal.
Definition: nilpotent.hpp:71
Nilpotent::getOffset
S getOffset()
Get off-diagonal offset of nilpotent matrix.
Definition: nilpotent.hpp:159
Nilpotent::probSize
S probSize
size of nilpotent matrix
Definition: nilpotent.hpp:52
Nilpotent::getProbSize
S getProbSize()
Get the size of nilpotent matrix.
Definition: nilpotent.hpp:146