Cytnx v0.9.1
Loading...
Searching...
No Matches
UniTensor.hpp
Go to the documentation of this file.
1#ifndef _H_UniTensor_
2#define _H_UniTensor_
3
4#include "Type.hpp"
5#include "cytnx_error.hpp"
6#include "Storage.hpp"
7#include "Device.hpp"
8#include "Tensor.hpp"
9#include "Scalar.hpp"
10#include "utils/utils.hpp"
12#include <iostream>
13#include <vector>
14#include <map>
15#include <utility>
16#include <initializer_list>
17#include <fstream>
18#include <algorithm>
19#include "Symmetry.hpp"
20#include "Bond.hpp"
21// #include "linalg.hpp"
22
23// namespace cytnx{
24namespace cytnx {
25 using namespace cytnx;
27 class UniTensorType_class {
28 public:
29 enum : int {
30 Void = -99,
31 Dense = 0,
32 Sparse = 1,
33 Block = 2,
34 };
35 std::string getname(const int &ut_type);
36 };
38
54 extern UniTensorType_class UTenType;
55
57 // class DenseUniTensor;
58 // class SparseUniTensor;
59 class UniTensor_base : public intrusive_ptr_base<UniTensor_base> {
60 public:
61 int uten_type_id; // the unitensor type id.
62 bool _is_braket_form;
63 bool _is_tag;
64 bool _is_diag;
65 cytnx_int64 _rowrank;
66 std::string _name;
67 std::vector<std::string> _labels;
68 std::vector<Bond> _bonds;
69
70 bool _update_braket() {
71 if (_bonds.size() == 0) return false;
72
73 if (this->_bonds[0].type() != bondType::BD_REG) {
74 // check:
75 for (unsigned int i = 0; i < this->_bonds.size(); i++) {
76 if (i < this->_rowrank) {
77 if (this->_bonds[i].type() != bondType::BD_KET) return false;
78 } else {
79 if (this->_bonds[i].type() != bondType::BD_BRA) return false;
80 }
81 }
82 return true;
83 } else {
84 return false;
85 }
86 }
87
88 friend class UniTensor; // allow wrapper to access the private elems
89 friend class DenseUniTensor;
90 friend class SparseUniTensor;
91 friend class BlockUniTensor;
92
93
94 UniTensor_base()
95 : _is_tag(false),
96 _name(std::string("")),
97 _is_braket_form(false),
98 _rowrank(0),
99 _is_diag(false),
100 uten_type_id(UTenType.Void){};
101
102 // copy&assignment constr., use intrusive_ptr's !!
103 UniTensor_base(const UniTensor_base &rhs);
104 UniTensor_base &operator=(UniTensor_base &rhs);
105
106 cytnx_uint64 rowrank() const { return this->_rowrank; }
107 bool is_diag() const { return this->_is_diag; }
108 const bool &is_braket_form() const { return this->_is_braket_form; }
109 const bool &is_tag() const { return this->_is_tag; }
110 const std::vector<std::string> &labels() const { return this->_labels; }
117 cytnx_int64 get_index(std::string lbl) const {
118 std::vector<std::string> lbls = this->_labels;
119 for (cytnx_uint64 i = 0; i < lbls.size(); i++) {
120 if (lbls[i] == lbl) return i;
121 }
122 return -1;
123 }
124 const std::vector<Bond> &bonds() const { return this->_bonds; }
125 std::vector<Bond> &bonds() { return this->_bonds; }
126 const std::string &name() const { return this->_name; }
127 cytnx_uint64 rank() const { return this->_labels.size(); }
128 void set_name(const std::string &in) { this->_name = in; }
139 void set_label(const std::string &oldlbl, const std::string &new_label) {
140 cytnx_int64 idx;
141 auto res = std::find(this->_labels.begin(), this->_labels.end(), oldlbl);
142 cytnx_error_msg(res == this->_labels.end(), "[ERROR] label %s not exists.\n", oldlbl.c_str());
143 idx = std::distance(this->_labels.begin(), res);
144
145 cytnx_error_msg(idx >= this->_labels.size(), "[ERROR] index exceed the rank of UniTensor%s",
146 "\n");
147 // check in:
148 bool is_dup = false;
149 for (cytnx_uint64 i = 0; i < this->_labels.size(); i++) {
150 if (i == idx) continue;
151 if (new_label == this->_labels[i]) {
152 is_dup = true;
153 break;
154 }
155 }
156 cytnx_error_msg(is_dup, "[ERROR] alreay has a label that is the same as the input label%s",
157 "\n");
158 this->_labels[idx] = new_label;
159 }
160 void set_label(const cytnx_int64 &inx, const std::string &new_label) {
161 cytnx_error_msg(inx < 0 , "[ERROR] index is negative%s",
162 "\n");
163 cytnx_error_msg(inx >= this->_labels.size(), "[ERROR] index exceed the rank of UniTensor%s",
164 "\n");
165 // check in:
166 bool is_dup = false;
167 for (cytnx_uint64 i = 0; i < this->_labels.size(); i++) {
168 if (i == inx) continue;
169 if (new_label == this->_labels[i]) {
170 is_dup = true;
171 break;
172 }
173 }
174 cytnx_error_msg(is_dup, "[ERROR] alreay has a label that is the same as the input label%s",
175 "\n");
176 this->_labels[inx] = new_label;
177 }
186 void set_label(const cytnx_int64 &inx, const cytnx_int64 &new_label) {
187 set_label(inx, std::to_string(new_label));
188 }
196 void set_label(const cytnx_int64 &inx, const cytnx_int64 &_new_label, const bool &by_label) {
197 std::string new_label = std::to_string(_new_label);
198 cytnx_int64 idx;
199 if (by_label) {
200 auto res = std::find(this->_labels.begin(), this->_labels.end(), std::to_string(inx));
201 cytnx_error_msg(res == this->_labels.end(), "[ERROR] label %s not exists.\n", inx);
202 idx = std::distance(this->_labels.begin(), res);
203 } else {
204 idx = inx;
205 }
206
207 set_label(idx,new_label);
208
209 }
217 void set_labels(const std::vector<cytnx_int64> &new_labels);
218 void set_labels(const std::vector<std::string> &new_labels);
219
220
221
222 /*
223 template<class T>
224 T get_elem(const std::vector<cytnx_uint64> &locator) const{
225 if(this->is_blockform()){
226 if(this->elem_exists(locator)){
227 T aux; // [workaround] use aux to dispatch.
228 return this->at_for_sparse(locator,aux);
229 }else{
230 return 0;
231 }
232 }else{
233 return this->at<T>(locator);
234 }
235 }
236 template<class T>
237 void set_elem(const std::vector<cytnx_uint64> &locator, const T &input){
238 if(this->uten_type()==UTenType.Sparse){
239 if(this->elem_exists(locator)){
240 T aux;
241 this->at_for_sparse(locator,aux) = input;
242 }else{
243 cytnx_error_msg(true,"[ERROR][SparseUniTensor] invalid location. break qnum
244 block.%s","\n");
245 }
246 }else{
247 this->at<T>(locator) = input;
248 }
249 }
250 */
251
252 int uten_type() { return this->uten_type_id; }
253 std::string uten_type_str() { return UTenType.getname(this->uten_type_id); }
254
255
257
258 // string labels!
259 virtual void Init(const std::vector<Bond> &bonds,
260 const std::vector<std::string> &in_labels = {},
261 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
262 const int &device = Device.cpu, const bool &is_diag = false,
263 const bool &no_alloc = false, const std::string &name = "");
264
265 virtual void Init_by_Tensor(const Tensor &in, const bool &is_diag = false,
266 const cytnx_int64 &rowrank = -1, const std::string &name = "");
267 virtual std::vector<cytnx_uint64> shape() const;
268 virtual bool is_blockform() const;
269 virtual bool is_contiguous() const;
270 virtual void to_(const int &device);
271 virtual boost::intrusive_ptr<UniTensor_base> to(const int &device);
272 virtual boost::intrusive_ptr<UniTensor_base> clone() const;
273 virtual unsigned int dtype() const;
274 virtual int device() const;
275 virtual std::string dtype_str() const;
276 virtual std::string device_str() const;
277 virtual void set_rowrank(const cytnx_uint64 &new_rowrank);
278
279
280
281 virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
282 const cytnx_int64 &rowrank = -1,
283 const bool &by_label= false);
284 virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
285 const cytnx_int64 &rowrank = -1);
286 //virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
287 // const cytnx_int64 &rowrank = -1);
288
289 virtual void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank=-1,
290 const bool &by_label=false);
291 virtual void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
292 //virtual void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
293 virtual boost::intrusive_ptr<UniTensor_base> contiguous_();
294 virtual boost::intrusive_ptr<UniTensor_base> contiguous();
295 virtual void print_diagram(const bool &bond_info = false);
296 virtual void print_blocks(const bool &full_info=true) const;
297 virtual void print_block(const cytnx_int64 &idx, const bool &full_info=true) const;
298
299 virtual boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const;
300
301 virtual cytnx_uint64 Nblocks() const { return 0; };
302 virtual Tensor get_block(const cytnx_uint64 &idx = 0) const; // return a copy of block
303 virtual Tensor get_block(const std::vector<cytnx_int64> &qnum,
304 const bool &force) const; // return a copy of block
305
306 virtual const Tensor &get_block_(const cytnx_uint64 &idx = 0)
307 const; // return a share view of block, this only work for non-symm tensor.
308 virtual const Tensor &get_block_(const std::vector<cytnx_int64> &qnum,
309 const bool &force) const; // return a copy of block
310 virtual Tensor &get_block_(const cytnx_uint64 &idx = 0); // return a share view of block, this
311 // only work for non-symm tensor.
312 virtual Tensor &get_block_(const std::vector<cytnx_int64> &qnum,
313 const bool &force); // return a copy of block
314 virtual bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const;
315
316 virtual std::vector<Tensor> get_blocks() const;
317 virtual const std::vector<Tensor> &get_blocks_(const bool &) const;
318 virtual std::vector<Tensor> &get_blocks_(const bool &);
319
320 virtual void put_block(const Tensor &in, const cytnx_uint64 &idx = 0);
321 virtual void put_block_(Tensor &in, const cytnx_uint64 &idx = 0);
322 virtual void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum,
323 const bool &force);
324 virtual void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force);
325
326 // this will only work on non-symm tensor (DenseUniTensor)
327 virtual boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors);
328
329 // this will only work on non-symm tensor (DenseUniTensor)
330 virtual void set(const std::vector<Accessor> &accessors, const Tensor &rhs);
331
332 virtual void reshape_(const std::vector<cytnx_int64> &new_shape,
333 const cytnx_uint64 &rowrank = 0);
334 virtual boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
335 const cytnx_uint64 &rowrank = 0);
336 virtual boost::intrusive_ptr<UniTensor_base> to_dense();
337 virtual void to_dense_();
338 virtual void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
339 const bool &by_label);
340 virtual void combineBonds(const std::vector<std::string> &indicators,
341 const bool &force = false);
342 virtual void combineBonds(const std::vector<cytnx_int64> &indicators,
343 const bool &force = false);
344 virtual boost::intrusive_ptr<UniTensor_base> contract(
345 const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &mv_elem_self = false,
346 const bool &mv_elem_rhs = false);
347 virtual std::vector<Bond> getTotalQnums(const bool &physical = false);
348 virtual std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const;
349 virtual void Trace_(const std::string &a, const std::string &b);
350 virtual void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
351 virtual void Trace_(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label);
352 virtual boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b);
353 virtual boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b);
354 virtual boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b,
355 const bool &by_label);
356 virtual boost::intrusive_ptr<UniTensor_base> relabels(
357 const std::vector<cytnx_int64> &new_labels);
358 virtual boost::intrusive_ptr<UniTensor_base> relabels(
359 const std::vector<std::string> &new_labels);
360 virtual boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
361 const cytnx_int64 &new_label,
362 const bool &by_label);
363 virtual boost::intrusive_ptr<UniTensor_base> relabel(const std::string &inx,
364 const std::string &new_label);
365 virtual boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
366 const cytnx_int64 &new_label);
367 virtual boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
368 const std::string &new_label);
369
370 virtual std::vector<Symmetry> syms() const;
371
372 // arithmetic
373 virtual void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
374 virtual void Add_(const Scalar &rhs);
375
376 virtual void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
377 virtual void Mul_(const Scalar &rhs);
378
379 virtual void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
380 virtual void Sub_(const Scalar &rhs);
381 virtual void lSub_(const Scalar &lhs);
382
383 virtual void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
384 virtual void Div_(const Scalar &rhs);
385 virtual void lDiv_(const Scalar &lhs);
386
387 virtual Tensor Norm() const;
388 virtual boost::intrusive_ptr<UniTensor_base> normalize();
389 virtual void normalize_();
390
391 virtual boost::intrusive_ptr<UniTensor_base> Conj();
392 virtual void Conj_();
393
394 virtual boost::intrusive_ptr<UniTensor_base> Transpose();
395 virtual void Transpose_();
396
397 virtual boost::intrusive_ptr<UniTensor_base> Dagger();
398 virtual void Dagger_();
399
400 virtual void tag();
401
402 virtual void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim,
403 const bool &by_label);
404 virtual void truncate_(const std::string &bond_idx, const cytnx_uint64 &dim);
405 virtual void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim);
406
407 virtual bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
408
409 // this a workaround, as virtual function cannot template.
410 virtual Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator);
411 virtual const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const;
412
413 virtual cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
414 const cytnx_complex128 &aux);
415 virtual cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
416 const cytnx_complex64 &aux);
417 virtual cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
418 const cytnx_double &aux);
419 virtual cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
420 const cytnx_float &aux);
421 virtual cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
422 const cytnx_uint64 &aux);
423 virtual cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
424 const cytnx_int64 &aux);
425 virtual cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
426 const cytnx_uint32 &aux);
427 virtual cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
428 const cytnx_int32 &aux);
429 virtual cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
430 const cytnx_uint16 &aux);
431 virtual cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
432 const cytnx_int16 &aux);
433
434 virtual const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
435 const cytnx_complex128 &aux) const;
436 virtual const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
437 const cytnx_complex64 &aux) const;
438 virtual const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
439 const cytnx_double &aux) const;
440 virtual const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
441 const cytnx_float &aux) const;
442 virtual const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
443 const cytnx_uint64 &aux) const;
444 virtual const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
445 const cytnx_int64 &aux) const;
446 virtual const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
447 const cytnx_uint32 &aux) const;
448 virtual const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
449 const cytnx_int32 &aux) const;
450 virtual const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
451 const cytnx_uint16 &aux) const;
452 virtual const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
453 const cytnx_int16 &aux) const;
454
455 virtual void group_basis_();
456 virtual const std::vector<cytnx_uint64>& get_qindices(const cytnx_uint64 &bidx) const;
457 virtual std::vector<cytnx_uint64>& get_qindices(const cytnx_uint64 &bidx);
458 virtual const vec2d<cytnx_uint64> & get_itoi() const;
459 virtual vec2d<cytnx_uint64> & get_itoi();
460
461
462 virtual void _save_dispatch(std::fstream &f) const;
463 virtual void _load_dispatch(std::fstream &f);
464
465 virtual ~UniTensor_base(){};
466 };
468
469 //======================================================================
471 class DenseUniTensor : public UniTensor_base {
472 protected:
473 public:
474 Tensor _block;
475 std::vector<Tensor> _interface_block; // this is serves as interface for get_blocks_();
476 DenseUniTensor *clone_meta() const {
477 DenseUniTensor *tmp = new DenseUniTensor();
478 tmp->_bonds = vec_clone(this->_bonds);
479 tmp->_labels = this->_labels;
480 tmp->_is_braket_form = this->_is_braket_form;
481 tmp->_rowrank = this->_rowrank;
482 tmp->_is_diag = this->_is_diag;
483 tmp->_name = this->_name;
484 tmp->_is_tag = this->_is_tag;
485 return tmp;
486 }
487 //------------------------------------------
488
489 DenseUniTensor() { this->uten_type_id = UTenType.Dense; };
490 friend class UniTensor; // allow wrapper to access the private elems
491 // virtual functions
492
493 //void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels = {},
494 // const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
495 // const int &device = Device.cpu, const bool &is_diag = false,
496 // const bool &no_alloc = false);
497
498 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
499 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
500 const int &device = Device.cpu, const bool &is_diag = false,
501 const bool &no_alloc = false, const std::string &name = "");
502 // this only work for non-symm tensor
503 void Init_by_Tensor(const Tensor &in_tensor, const bool &is_diag = false,
504 const cytnx_int64 &rowrank = -1, const std::string &name = "");
505 std::vector<cytnx_uint64> shape() const {
506 if (this->_is_diag) {
507 std::vector<cytnx_uint64> shape = this->_block.shape();
508 shape.push_back(shape[0]);
509 return shape;
510 } else {
511 return this->_block.shape();
512 }
513 }
514 bool is_blockform() const { return false; }
515 void to_(const int &device) { this->_block.to_(device); }
516 boost::intrusive_ptr<UniTensor_base> to(const int &device) {
517 if (this->device() == device) {
518 std::vector<Tensor> _interface_block; // this is serves as interface for get_blocks_();
519 return this;
520 } else {
521 boost::intrusive_ptr<UniTensor_base> out = this->clone();
522 out->to_(device);
523 return out;
524 }
525 }
526 void set_rowrank(const cytnx_uint64 &new_rowrank) {
527 cytnx_error_msg(new_rowrank > this->_labels.size(),
528 "[ERROR] rowrank cannot exceed the rank of UniTensor.%s", "\n");
529 if(this->is_diag()){
530 cytnx_error_msg(new_rowrank != 1,
531 "[ERROR] rowrank should be [==1] when is_diag =true!.%s",
532 "\n");
533 }
534
535 this->_rowrank = new_rowrank;
536 }
537
538 boost::intrusive_ptr<UniTensor_base> clone() const {
539 DenseUniTensor *tmp = this->clone_meta();
540 tmp->_block = this->_block.clone();
541 boost::intrusive_ptr<UniTensor_base> out(tmp);
542 return out;
543 };
544 bool is_contiguous() const { return this->_block.is_contiguous(); }
545 unsigned int dtype() const { return this->_block.dtype(); }
546 int device() const { return this->_block.device(); }
547 std::string dtype_str() const { return Type.getname(this->_block.dtype()); }
548 std::string device_str() const { return Device.getname(this->_block.device()); }
559 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
560 const cytnx_int64 &rowrank=-1, const bool &by_label=false);
561 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
562 const cytnx_int64 &rowrank = -1);
563 //boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
564 // const cytnx_int64 &rowrank = -1);
574 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank=-1,
575 const bool &by_label=false);
576 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
577 //void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
578 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &new_labels);
587 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<cytnx_int64> &new_labels);
598 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
599 const cytnx_int64 &new_label,
600 const bool &by_label);
601 boost::intrusive_ptr<UniTensor_base> relabel(const std::string &inx,
602 const std::string &new_label);
603 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
604 const std::string &new_label);
605 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
606 const cytnx_int64 &new_label);
607
608 boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const {
609 DenseUniTensor *tmp = this->clone_meta();
610 tmp->_block = this->_block.astype(dtype);
611 boost::intrusive_ptr<UniTensor_base> out(tmp);
612 return tmp;
613 }
614
615 std::vector<Symmetry> syms() const {
616 cytnx_error_msg(true, "[ERROR][DenseUniTensor] dense unitensor does not have symmetry.%s",
617 "\n");
618 return std::vector<Symmetry>();
619 }
620
621 boost::intrusive_ptr<UniTensor_base> contiguous_() {
622 this->_block.contiguous_();
623 return boost::intrusive_ptr<UniTensor_base>(this);
624 }
625 boost::intrusive_ptr<UniTensor_base> contiguous() {
626 // if contiguous then return self!
627 if (this->is_contiguous()) {
628 boost::intrusive_ptr<UniTensor_base> out(this);
629 return out;
630 } else {
631 DenseUniTensor *tmp = this->clone_meta();
632 tmp->_block = this->_block.contiguous();
633 boost::intrusive_ptr<UniTensor_base> out(tmp);
634 return out;
635 }
636 }
637 void print_diagram(const bool &bond_info = false);
638 void print_blocks(const bool &full_info=true) const;
639 void print_block(const cytnx_int64 &idx, const bool &full_info=true) const;
640 Tensor get_block(const cytnx_uint64 &idx = 0) const { return this->_block.clone(); }
641
642 Tensor get_block(const std::vector<cytnx_int64> &qnum, const bool &force) const {
644 true, "[ERROR][DenseUniTensor] try to get_block() using qnum on a non-symmetry UniTensor%s",
645 "\n");
646 return Tensor();
647 }
648 // return a share view of block, this only work for non-symm tensor.
649 const Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force) const {
651 true,
652 "[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
653 "\n");
654 return this->_block;
655 }
656 Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force) {
658 true,
659 "[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
660 "\n");
661 return this->_block;
662 }
663
664 // return a share view of block, this only work for non-symm tensor.
665 Tensor &get_block_(const cytnx_uint64 &idx = 0) { return this->_block; }
666 // return a share view of block, this only work for non-symm tensor.
667 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const { return this->_block; }
668
669 cytnx_uint64 Nblocks() const { return 1; };
670 std::vector<Tensor> get_blocks() const {
671 std::vector<Tensor> out;
673 true, "[ERROR][DenseUniTensor] cannot use get_blocks(), use get_block() instead!%s", "\n");
674 return out; // this will not share memory!!
675 }
676 const std::vector<Tensor> &get_blocks_(const bool &silent = false) const {
678 true, "[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s",
679 "\n");
680 return this->_interface_block; // this will not share memory!!
681 }
682 std::vector<Tensor> &get_blocks_(const bool &silent = false) {
684 true, "[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s",
685 "\n");
686 return this->_interface_block; // this will not share memory!!
687 }
688
689 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
690 if (this->is_diag()) {
692 in.shape() != this->_block.shape(),
693 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
694 this->_block = in.clone();
695 } else {
697 in.shape() != this->shape(),
698 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
699 this->_block = in.clone();
700 }
701 }
702 // share view of the block
703 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) {
704 if (this->is_diag()) {
706 in.shape() != this->_block.shape(),
707 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
708 this->_block = in;
709 } else {
711 in.shape() != this->shape(),
712 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
713 this->_block = in;
714 }
715 }
716
717 void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force) {
719 true, "[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
720 "\n");
721 }
722 void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force) {
724 true, "[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
725 "\n");
726 }
727 // this will only work on non-symm tensor (DenseUniTensor)
728 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors) {
729 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
730 out->Init_by_Tensor(this->_block.get(accessors), false, 0); // wrapping around.
731 return out;
732 }
733 // this will only work on non-symm tensor (DenseUniTensor)
734 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
735 this->_block.set(accessors, rhs);
736 }
737
738 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0);
739 boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
740 const cytnx_uint64 &rowrank = 0);
741 boost::intrusive_ptr<UniTensor_base> to_dense();
742 void to_dense_();
752 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
753 const bool &by_label);
754 void combineBonds(const std::vector<std::string> &indicators, const bool &force = true);
755 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = true);
756 boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs,
757 const bool &mv_elem_self = false,
758 const bool &mv_elem_rhs = false);
759 std::vector<Bond> getTotalQnums(const bool &physical = false) {
760 cytnx_error_msg(true, "[ERROR][DenseUniTensor] %s",
761 "getTotalQnums can only operate on UniTensor with symmetry.\n");
762 return std::vector<Bond>();
763 }
764
765 std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const {
766 cytnx_error_msg(true, "[ERROR][DenseUniTensor] %s",
767 "get_blocks_qnums can only operate on UniTensor with symmetry.\n");
768 return std::vector<std::vector<cytnx_int64>>();
769 }
770
771 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const {
772 if (rhs->uten_type() != UTenType.Dense) return false;
773
774 return this->get_block_().same_data(rhs->get_block_());
775 }
776
777 ~DenseUniTensor(){};
778
779 // arithmetic
780 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
781 void Add_(const Scalar &rhs);
782
783 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
784 void Mul_(const Scalar &rhs);
785
786 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
787 void Sub_(const Scalar &rhs);
788 void lSub_(const Scalar &lhs);
789
790 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
791 void Div_(const Scalar &rhs);
792 void lDiv_(const Scalar &lhs);
793
794 void Conj_() { this->_block.Conj_(); };
795
796 boost::intrusive_ptr<UniTensor_base> Conj() {
797 boost::intrusive_ptr<UniTensor_base> out = this->clone();
798 out->Conj_();
799 return out;
800 }
801
802 boost::intrusive_ptr<UniTensor_base> Transpose() {
803 boost::intrusive_ptr<UniTensor_base> out = this->clone();
804 out->Transpose_();
805 return out;
806 }
807 void Transpose_();
808
809 boost::intrusive_ptr<UniTensor_base> normalize() {
810 boost::intrusive_ptr<UniTensor_base> out = this->clone();
811 out->normalize_();
812 return out;
813 }
814 void normalize_();
815
816 boost::intrusive_ptr<UniTensor_base> Dagger() {
817 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
818 out->Transpose_();
819 return out;
820 }
821 void Dagger_() {
822 this->Conj_();
823 this->Transpose_();
824 }
834 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label);
835 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
836 void Trace_(const std::string &a, const std::string &b);
837 boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b) {
838 boost::intrusive_ptr<UniTensor_base> out = this->clone();
839 out->Trace_(a, b);
840 return out;
841 }
842 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b) {
843 boost::intrusive_ptr<UniTensor_base> out = this->clone();
844 out->Trace_(a, b);
845 return out;
846 }
856 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b,
857 const bool &by_label) {
858 boost::intrusive_ptr<UniTensor_base> out = this->clone();
859 out->Trace_(a, b, by_label);
860 return out;
861 }
862
863 Tensor Norm() const;
864
865 const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const {
867 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
868 "\n");
869 // return cytnx_complex128(0,0);
870 }
871 const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
872 const cytnx_complex128 &aux) const {
874 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
875 "\n");
876 // return cytnx_complex128(0,0);
877 }
878 const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
879 const cytnx_complex64 &aux) const {
881 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
882 "\n");
883 // return cytnx_complex64(0,0);
884 }
885 const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
886 const cytnx_double &aux) const {
888 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
889 "\n");
890 // return 0;
891 }
892 const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
893 const cytnx_float &aux) const {
895 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
896 "\n");
897 // return 0;
898 }
899 const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
900 const cytnx_uint64 &aux) const {
902 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
903 "\n");
904 // return 0;
905 }
906 const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
907 const cytnx_int64 &aux) const {
909 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
910 "\n");
911 // return 0;
912 }
913 const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
914 const cytnx_uint32 &aux) const {
916 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
917 "\n");
918 // return 0;
919 }
920 const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
921 const cytnx_int32 &aux) const {
923 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
924 "\n");
925 // return 0;
926 }
927 const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
928 const cytnx_uint16 &aux) const {
930 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
931 "\n");
932 // return 0;
933 }
934 const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
935 const cytnx_int16 &aux) const {
937 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
938 "\n");
939 // return 0;
940 }
941
942 Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) {
944 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
945 "\n");
946 // return cytnx_complex128(0,0);
947 }
948 cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
949 const cytnx_complex128 &aux) {
951 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
952 "\n");
953 // return cytnx_complex128(0,0);
954 }
955 cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
956 const cytnx_complex64 &aux) {
958 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
959 "\n");
960 // return cytnx_complex64(0,0);
961 }
962 cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux) {
964 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
965 "\n");
966 // return 0;
967 }
968 cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux) {
970 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
971 "\n");
972 // return 0;
973 }
974 cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux) {
976 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
977 "\n");
978 // return 0;
979 }
980 cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux) {
982 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
983 "\n");
984 // return 0;
985 }
986 cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux) {
988 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
989 "\n");
990 // return 0;
991 }
992 cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux) {
994 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
995 "\n");
996 // return 0;
997 }
998 cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux) {
1000 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
1001 "\n");
1002 // return 0;
1003 }
1004 cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux) {
1006 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
1007 "\n");
1008 // return 0;
1009 }
1010
1011 bool elem_exists(const std::vector<cytnx_uint64> &locator) const {
1013 true, "[ERROR][DenseUniTensor] elem_exists can only be used on UniTensor with Symmetry.%s",
1014 "\n");
1015 }
1016 void tag() {
1017 if (!this->is_tag()) {
1018 for (int i = 0; i < this->_rowrank; i++) {
1019 this->_bonds[i].set_type(BD_KET);
1020 }
1021 for (int i = this->_rowrank; i < this->_bonds.size(); i++) {
1022 this->_bonds[i].set_type(BD_BRA);
1023 }
1024 this->_is_tag = true;
1025 this->_is_braket_form = this->_update_braket();
1026 }
1027 }
1037 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim, const bool &by_label);
1038 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim);
1039 void truncate_(const std::string &bond_idx, const cytnx_uint64 &dim);
1040
1041 void group_basis_(){
1042 cytnx_warning_msg(true,"[WARNING] group basis will not have any effect on DensUniTensor.%s","\n");
1043 }
1044
1045 void _save_dispatch(std::fstream &f) const;
1046 void _load_dispatch(std::fstream &f);
1047
1048 const std::vector<cytnx_uint64>& get_qindices(const cytnx_uint64 &bidx) const{
1049 cytnx_error_msg(true,"[ERROR] get_qindices can only be unsed on UniTensor with Symmetry.%s","\n");
1050
1051 }
1052 std::vector<cytnx_uint64>& get_qindices(const cytnx_uint64 &bidx){
1053 cytnx_error_msg(true,"[ERROR] get_qindices can only be unsed on UniTensor with Symmetry.%s","\n");
1054 }
1055
1056 const vec2d<cytnx_uint64> & get_itoi() const{
1057 cytnx_error_msg(true,"[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s","\n");
1058 }
1059 vec2d<cytnx_uint64> & get_itoi(){
1060 cytnx_error_msg(true,"[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s","\n");
1061 }
1062
1063
1064 // end virtual function
1065 };
1067
1068 //======================================================================
1070 class SparseUniTensor : public UniTensor_base {
1071 protected:
1072 public:
1073 cytnx_uint64 _inner_rowrank;
1074 std::vector<std::vector<cytnx_int64>> _blockqnums;
1075 std::vector<cytnx_uint64> _mapper;
1076 std::vector<cytnx_uint64> _inv_mapper;
1077 std::vector<std::vector<cytnx_uint64>> _inner2outer_row;
1078 std::vector<std::vector<cytnx_uint64>> _inner2outer_col;
1079 std::map<cytnx_uint64, std::pair<cytnx_uint64, cytnx_uint64>> _outer2inner_row;
1080 std::map<cytnx_uint64, std::pair<cytnx_uint64, cytnx_uint64>> _outer2inner_col;
1081
1082 std::vector<Tensor> _blocks;
1083
1084 bool _contiguous;
1085 void set_meta(SparseUniTensor *tmp, const bool &inner, const bool &outer) const {
1086 // outer meta
1087 if (outer) {
1088 tmp->_bonds = vec_clone(this->_bonds);
1089 tmp->_labels = this->_labels;
1090 tmp->_is_braket_form = this->_is_braket_form;
1091 tmp->_rowrank = this->_rowrank;
1092 tmp->_name = this->_name;
1093 }
1094 // comm meta
1095 tmp->_mapper = this->_mapper;
1096 tmp->_inv_mapper = this->_inv_mapper;
1097 tmp->_contiguous = this->_contiguous;
1098 tmp->_is_diag = this->_is_diag;
1099
1100 // inner meta
1101 if (inner) {
1102 tmp->_inner_rowrank = this->_inner_rowrank;
1103 tmp->_inner2outer_row = this->_inner2outer_row;
1104 tmp->_inner2outer_col = this->_inner2outer_col;
1105 tmp->_outer2inner_row = this->_outer2inner_row;
1106 tmp->_outer2inner_col = this->_outer2inner_col;
1107 tmp->_blockqnums = this->_blockqnums;
1108 }
1109 }
1110 SparseUniTensor *clone_meta(const bool &inner, const bool &outer) const {
1111 SparseUniTensor *tmp = new SparseUniTensor();
1112 this->set_meta(tmp, inner, outer);
1113 return tmp;
1114 };
1115
1116 //===================================
1117 friend class UniTensor; // allow wrapper to access the private elems
1118 SparseUniTensor() {
1119 this->uten_type_id = UTenType.Sparse;
1120 this->_is_tag = true;
1121 };
1122
1123 // virtual functions
1124 //void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels = {},
1125 // const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1126 // const int &device = Device.cpu, const bool &is_diag = false,
1127 // const bool &no_alloc = false);
1128 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1129 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1130 const int &device = Device.cpu, const bool &is_diag = false,
1131 const bool &no_alloc = false, const std::string &name = "");
1132
1133 void Init_by_Tensor(const Tensor &in_tensor, const bool &is_diag = false,
1134 const cytnx_int64 &rowrank = -1, const std::string &name = "") {
1136 true, "[ERROR][SparseUniTensor] cannot use Init_by_tensor() on a SparseUniTensor.%s", "\n");
1137 }
1138 std::vector<cytnx_uint64> shape() const {
1139 std::vector<cytnx_uint64> out(this->_bonds.size());
1140 for (cytnx_uint64 i = 0; i < out.size(); i++) {
1141 out[i] = this->_bonds[i].dim();
1142 }
1143 return out;
1144 }
1145 bool is_blockform() const { return true; }
1146 void to_(const int &device) {
1147 for (cytnx_uint64 i = 0; i < this->_blocks.size(); i++) {
1148 this->_blocks[i].to_(device);
1149 }
1150 };
1151 boost::intrusive_ptr<UniTensor_base> to(const int &device) {
1152 if (this->device() == device) {
1153 return this;
1154 } else {
1155 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1156 out->to_(device);
1157 return out;
1158 }
1159 };
1160 boost::intrusive_ptr<UniTensor_base> clone() const {
1161 SparseUniTensor *tmp = this->clone_meta(true, true);
1162 tmp->_blocks = vec_clone(this->_blocks);
1163 boost::intrusive_ptr<UniTensor_base> out(tmp);
1164 return out;
1165 };
1166
1167 bool is_contiguous() const { return this->_contiguous; };
1168 void set_rowrank(const cytnx_uint64 &new_rowrank) {
1169 cytnx_error_msg((new_rowrank < 1) || (new_rowrank >= this->rank()),
1170 "[ERROR][SparseUniTensor] rowrank should be [>=1] and [<UniTensor.rank].%s",
1171 "\n");
1172 cytnx_error_msg(new_rowrank >= this->_labels.size(),
1173 "[ERROR] rowrank cannot exceed the rank of UniTensor.%s", "\n");
1174 if (this->_inner_rowrank != new_rowrank) this->_contiguous = false;
1175
1176 this->_rowrank = new_rowrank;
1177 this->_is_braket_form = this->_update_braket();
1178 }
1187 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<cytnx_int64> &new_labels);
1188 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &new_labels);
1199 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
1200 const cytnx_int64 &new_label,
1201 const bool &by_label);
1202 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
1203 const cytnx_int64 &new_label);
1204 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
1205 const std::string &new_label);
1206 boost::intrusive_ptr<UniTensor_base> relabel(const std::string &inx,
1207 const std::string &new_label);
1208 unsigned int dtype() const {
1209#ifdef UNI_DEBUG
1210 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1211 "\n");
1212#endif
1213 return this->_blocks[0].dtype();
1214 };
1215 int device() const {
1216#ifdef UNI_DEBUG
1217 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1218 "\n");
1219#endif
1220 return this->_blocks[0].device();
1221 };
1222 std::string dtype_str() const {
1223#ifdef UNI_DEBUG
1224 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1225 "\n");
1226#endif
1227 return this->_blocks[0].dtype_str();
1228 };
1229 std::string device_str() const {
1230#ifdef UNI_DEBUG
1231 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1232 "\n");
1233#endif
1234 return this->_blocks[0].device_str();
1235 };
1236
1237 boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const {
1238 SparseUniTensor *tmp = this->clone_meta(true, true);
1239 tmp->_blocks.resize(this->_blocks.size());
1240 for (cytnx_int64 blk = 0; blk < this->_blocks.size(); blk++) {
1241 tmp->_blocks[blk] = this->_blocks[blk].astype(dtype);
1242 }
1243 boost::intrusive_ptr<UniTensor_base> out(tmp);
1244 return out;
1245 };
1246
1256 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank=-1,
1257 const bool &by_label=false);
1258 //void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
1259 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
1270 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
1271 const cytnx_int64 &rowrank=-1, const bool &by_label=false);
1272 //boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
1273 // const cytnx_int64 &rowrank = -1);
1274 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
1275 const cytnx_int64 &rowrank = -1);
1276 boost::intrusive_ptr<UniTensor_base> contiguous();
1277 boost::intrusive_ptr<UniTensor_base> contiguous_() {
1278 if (!this->_contiguous) {
1279 boost::intrusive_ptr<UniTensor_base> titr = this->contiguous();
1280 SparseUniTensor *tmp = (SparseUniTensor *)titr.get();
1281 tmp->set_meta(this, true, true);
1282 this->_blocks = tmp->_blocks;
1283 }
1284 return boost::intrusive_ptr<UniTensor_base>(this);
1285 }
1286 void print_diagram(const bool &bond_info = false);
1287 void print_blocks(const bool &full_info=true)const;
1288 void print_block(const cytnx_int64 &idx, const bool &full_info=true) const;
1289 std::vector<Symmetry> syms() const;
1290
1291 Tensor get_block(const cytnx_uint64 &idx = 0) const {
1292 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][SparseUniTensor] index out of range%s",
1293 "\n");
1294 if (this->_contiguous) {
1295 return this->_blocks[idx].clone();
1296 } else {
1297 cytnx_error_msg(true,
1298 "[Developing] get block from a non-contiguous SparseUniTensor is currently "
1299 "not support. Call contiguous()/contiguous_() first.%s",
1300 "\n");
1301 return Tensor();
1302 }
1303 };
1304 cytnx_uint64 Nblocks() const { return this->_blocks.size(); };
1305 Tensor get_block(const std::vector<cytnx_int64> &qnum, const bool &force) const {
1306 if (!force)
1308 !this->is_braket_form(),
1309 "[ERROR][Un-physical] cannot get the block by qnums when bra-ket/in-out bonds mismatch "
1310 "the row/col space.\n permute to the correct physical space first, then get block.%s",
1311 "\n");
1312 // std::cout << "get_block" <<std::endl;
1313 if (this->_contiguous) {
1314 // std::cout << "contiguous" << std::endl;
1315 // get dtype from qnum:
1316 cytnx_int64 idx = -1;
1317 for (int i = 0; i < this->_blockqnums.size(); i++) {
1318 // for(int j=0;j<this->_blockqnums[i].size();j++)
1319 // std::cout << this->_blockqnums[i][j]<< " ";
1320 // std::cout << std::endl;
1321 if (qnum == this->_blockqnums[i]) {
1322 idx = i;
1323 break;
1324 }
1325 }
1327 idx < 0,
1328 "[ERROR][SparseUniTensor] no block with [qnum] exists in the current UniTensor.%s", "\n");
1329 return this->get_block(idx);
1330 } else {
1331 cytnx_error_msg(true,
1332 "[Developing] get block from a non-contiguous SparseUniTensor is currently "
1333 "not support. Call contiguous()/contiguous_() first.%s",
1334 "\n");
1335 return Tensor();
1336 }
1337 return Tensor();
1338 };
1339
1340 // return a share view of block, this only work for symm tensor in contiguous form.
1341 Tensor &get_block_(const cytnx_uint64 &idx = 0) {
1343 this->is_contiguous() == false,
1344 "[ERROR][SparseUniTensor] cannot use get_block_() on non-contiguous UniTensor with "
1345 "symmetry.\n suggest options: \n 1) Call contiguous_()/contiguous() first, then call "
1346 "get_block_()\n 2) Try get_block()/get_blocks()%s",
1347 "\n");
1348
1349 cytnx_error_msg(idx >= this->_blocks.size(),
1350 "[ERROR][SparseUniTensor] index exceed the number of blocks.%s", "\n");
1351
1352 return this->_blocks[idx];
1353 }
1354 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const {
1356 this->is_contiguous() == false,
1357 "[ERROR][SparseUniTensor] cannot use get_block_() on non-contiguous UniTensor with "
1358 "symmetry.\n suggest options: \n 1) Call contiguous_()/contiguous() first, then call "
1359 "get_block_()\n 2) Try get_block()/get_blocks()%s",
1360 "\n");
1361
1362 cytnx_error_msg(idx >= this->_blocks.size(),
1363 "[ERROR][SparseUniTensor] index exceed the number of blocks.%s", "\n");
1364
1365 return this->_blocks[idx];
1366 }
1367
1368 Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force) {
1369 if (!force)
1371 !this->is_braket_form(),
1372 "[ERROR][Un-physical] cannot get the block by qnums when bra-ket/in-out bonds mismatch "
1373 "the row/col space.\n permute to the correct physical space first, then get block.%s",
1374 "\n");
1375
1377 this->is_contiguous() == false,
1378 "[ERROR][SparseUniTensor] cannot use get_block_() on non-contiguous UniTensor with "
1379 "symmetry.\n suggest options: \n 1) Call contiguous_()/contiguous() first, then call "
1380 "get_blocks_()\n 2) Try get_block()/get_blocks()%s",
1381 "\n");
1382
1383 // get dtype from qnum:
1384 cytnx_int64 idx = -1;
1385 for (int i = 0; i < this->_blockqnums.size(); i++) {
1386 if (qnum == this->_blockqnums[i]) {
1387 idx = i;
1388 break;
1389 }
1390 }
1392 idx < 0, "[ERROR][SparseUniTensor] no block with [qnum] exists in the current UniTensor.%s",
1393 "\n");
1394 return this->get_block_(idx);
1395 // cytnx_error_msg(true,"[Developing]%s","\n");
1396 }
1397 const Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force) const {
1398 if (!force)
1400 !this->is_braket_form(),
1401 "[ERROR][Un-physical] cannot get the block by qnums when bra-ket/in-out bonds mismatch "
1402 "the row/col space.\n permute to the correct physical space first, then get block.%s",
1403 "\n");
1404
1406 this->is_contiguous() == false,
1407 "[ERROR][SparseUniTensor] cannot use get_block_() on non-contiguous UniTensor with "
1408 "symmetry.\n suggest options: \n 1) Call contiguous_()/contiguous() first, then call "
1409 "get_blocks_()\n 2) Try get_block()/get_blocks()%s",
1410 "\n");
1411
1412 // get dtype from qnum:
1413 cytnx_int64 idx = -1;
1414 for (int i = 0; i < this->_blockqnums.size(); i++) {
1415 if (qnum == this->_blockqnums[i]) {
1416 idx = i;
1417 break;
1418 }
1419 }
1421 idx < 0, "[ERROR][SparseUniTensor] no block with [qnum] exists in the current UniTensor.%s",
1422 "\n");
1423 return this->get_block_(idx);
1424 }
1425
1426 std::vector<Tensor> get_blocks() const {
1427 if (this->_contiguous) {
1428 return vec_clone(this->_blocks);
1429 } else {
1430 // cytnx_error_msg(true,"[Developing]%s","\n");
1431 boost::intrusive_ptr<UniTensor_base> tmp = this->clone();
1432 tmp->contiguous_();
1433 SparseUniTensor *ttmp = (SparseUniTensor *)tmp.get();
1434 return ttmp->_blocks;
1435 }
1436 };
1437
1438 const std::vector<Tensor> &get_blocks_(const bool &silent = false) const {
1439 // cout << "[call this]" << endl;
1440 if (this->_contiguous) {
1441 return this->_blocks;
1442 } else {
1443 // cytnx_error_msg(true,"[Developing]%s","\n");
1444 if (!silent)
1446 true,
1447 "[WARNING][SparseUniTensor] call get_blocks_() with a non-contiguous UniTensor should "
1448 "be used with caution. \ntry: \n1) get_blocks()\n2) call contiguous/contiguous_() "
1449 "first, then get_blocks_() to get concise results%s",
1450 "\n");
1451
1452 return this->_blocks;
1453 }
1454 };
1455 std::vector<Tensor> &get_blocks_(const bool &silent = false) {
1456 // cout << "[call this]" << endl;
1457 if (this->_contiguous) {
1458 return this->_blocks;
1459 } else {
1460 if (!silent)
1462 true,
1463 "[WARNING][SparseUniTensor] call get_blocks_() with a non-contiguous UniTensor should "
1464 "be used with caution. \ntry: \n1) get_blocks()\n2) call contiguous/contiguous_() "
1465 "first, then get_blocks_() to get concise results%s",
1466 "\n");
1467
1468 return this->_blocks;
1469 }
1470 };
1471
1472 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const {
1473 if (rhs->uten_type() != UTenType.Sparse) return false;
1474 if (rhs->get_blocks_(1).size() != this->get_blocks_(1).size()) return false;
1475
1476 for (int i = 0; i < rhs->get_blocks_(1).size(); i++)
1477 if (this->get_blocks_(1)[i].same_data(rhs->get_blocks_(1)[i]) == false) return false;
1478
1479 return true;
1480 }
1481
1482 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) {
1484 this->is_contiguous() == false,
1485 "[ERROR][SparseUniTensor] cannot use put_block_() on non-contiguous UniTensor with "
1486 "symmetry.\n suggest options: \n 1) Call contiguous_()/contiguous() first, then call "
1487 "put_blocks_()\n 2) Try put_block()/put_blocks()%s",
1488 "\n");
1489
1490 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][SparseUniTensor] index out of range%s",
1491 "\n");
1492 cytnx_error_msg(in.shape() != this->_blocks[idx].shape(),
1493 "[ERROR][SparseUniTensor] the shape of input tensor does not match the shape "
1494 "of block @ idx=%d\n",
1495 idx);
1496 this->_blocks[idx] = in;
1497 };
1498 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
1499 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][SparseUniTensor] index out of range%s",
1500 "\n");
1501 if (this->_contiguous) {
1502 cytnx_error_msg(in.shape() != this->_blocks[idx].shape(),
1503 "[ERROR][SparseUniTensor] the shape of input tensor does not match the "
1504 "shape of block @ idx=%d\n",
1505 idx);
1506 this->_blocks[idx] = in.clone();
1507 } else {
1508 cytnx_error_msg(true,
1509 "[Developing] put block to a non-contiguous SparseUniTensor is currently "
1510 "not support. Call contiguous()/contiguous_() first.%s",
1511 "\n");
1512 }
1513 };
1514 void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force) {
1515 if (!force)
1517 !this->is_braket_form(),
1518 "[ERROR][Un-physical] cannot get the block by qnums when bra-ket/in-out bonds mismatch "
1519 "the row/col space.\n permute to the correct physical space first, then get block.%s",
1520 "\n");
1521
1522 // get dtype from qnum:
1523 cytnx_int64 idx = -1;
1524 for (int i = 0; i < this->_blockqnums.size(); i++) {
1525 if (qnum == this->_blockqnums[i]) {
1526 idx = i;
1527 break;
1528 }
1529 }
1531 idx < 0, "[ERROR][SparseUniTensor] no block with [qnum] exists in the current UniTensor.%s",
1532 "\n");
1533 this->put_block(in, idx);
1534 };
1535 void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force) {
1536 if (!force)
1538 !this->is_braket_form(),
1539 "[ERROR][Un-physical] cannot get the block by qnums when bra-ket/in-out bonds mismatch "
1540 "the row/col space.\n permute to the correct physical space first, then get block.%s",
1541 "\n");
1542
1543 // get dtype from qnum:
1544 cytnx_int64 idx = -1;
1545 for (int i = 0; i < this->_blockqnums.size(); i++) {
1546 if (qnum == this->_blockqnums[i]) {
1547 idx = i;
1548 break;
1549 }
1550 }
1552 idx < 0, "[ERROR][SparseUniTensor] no block with [qnum] exists in the current UniTensor.%s",
1553 "\n");
1554 this->put_block_(in, idx);
1555 };
1556
1557 // this will only work on non-symm tensor (DenseUniTensor)
1558 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors) {
1559 cytnx_error_msg(true,
1560 "[ERROR][SparseUniTensor][get] cannot use get on a UniTensor with "
1561 "Symmetry.\n suggestion: try get_block()/get_blocks() first.%s",
1562 "\n");
1563 return nullptr;
1564 }
1565 // this will only work on non-symm tensor (DenseUniTensor)
1566 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
1567 cytnx_error_msg(true,
1568 "[ERROR][SparseUniTensor][set] cannot use set on a UniTensor with "
1569 "Symmetry.\n suggestion: try get_block()/get_blocks() first.%s",
1570 "\n");
1571 }
1572 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
1573 cytnx_error_msg(true, "[ERROR] cannot reshape a UniTensor with symmetry.%s", "\n");
1574 }
1575 boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
1576 const cytnx_uint64 &rowrank = 0) {
1577 cytnx_error_msg(true, "[ERROR] cannot reshape a UniTensor with symmetry.%s", "\n");
1578 return nullptr;
1579 }
1580 boost::intrusive_ptr<UniTensor_base> to_dense() {
1581 cytnx_error_msg(true, "[ERROR] cannot to_dense a UniTensor with symmetry.%s", "\n");
1582 return nullptr;
1583 }
1584 void to_dense_() {
1585 cytnx_error_msg(true, "[ERROR] cannot to_dense_ a UniTensor with symmetry.%s", "\n");
1586 }
1596 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
1597 const bool &by_label) {
1598 cytnx_error_msg(true, "[Developing]%s", "\n");
1599 };
1600 void combineBonds(const std::vector<std::string> &indicators, const bool &force = true) {
1601 cytnx_error_msg(true, "[Developing]%s", "\n");
1602 };
1603 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = true) {
1604 cytnx_error_msg(true, "[Developing]%s", "\n");
1605 };
1606 boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs,
1607 const bool &mv_elem_self = false,
1608 const bool &mv_elem_rhs = false);
1609 std::vector<Bond> getTotalQnums(const bool &physical = false);
1610 std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const { return this->_blockqnums; }
1611 ~SparseUniTensor(){};
1612
1613 // arithmetic
1614 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1615 void Add_(const Scalar &rhs);
1616
1617 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1618 void Mul_(const Scalar &rhs);
1619
1620 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1621 void Sub_(const Scalar &rhs);
1622 void lSub_(const Scalar &lhs);
1623
1624 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1625 void Div_(const Scalar &rhs);
1626 void lDiv_(const Scalar &lhs);
1627
1628 boost::intrusive_ptr<UniTensor_base> Conj() {
1629 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1630 out->Conj_();
1631 return out;
1632 }
1633
1634 void Conj_() {
1635 for (int i = 0; i < this->_blocks.size(); i++) {
1636 this->_blocks[i].Conj_();
1637 }
1638 };
1639 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b);
1640 boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b);
1651 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b,
1652 const bool &by_label);
1653 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b) {
1654 cytnx_error_msg(true,
1655 "[ERROR] Currently SparseUniTensor does not support inplace Trace!, call "
1656 "Trace() instead!%s",
1657 "\n");
1658 }
1659 void Trace_(const std::string &a, const std::string &b) {
1660 cytnx_error_msg(true,
1661 "[ERROR] Currently SparseUniTensor does not support inplace Trace!, call "
1662 "Trace() instead!%s",
1663 "\n");
1664 }
1674 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label) {
1675 cytnx_error_msg(true,
1676 "[ERROR] Currently SparseUniTensor does not support inplace Trace!, call "
1677 "Trace() instead!%s",
1678 "\n");
1679 }
1680
1681 void Transpose_();
1682 boost::intrusive_ptr<UniTensor_base> Transpose() {
1683 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1684 out->Transpose_();
1685 return out;
1686 }
1687
1688 boost::intrusive_ptr<UniTensor_base> Dagger() {
1689 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
1690 out->Transpose_();
1691 return out;
1692 }
1693 void Dagger_() {
1694 this->Conj_();
1695 this->Transpose_();
1696 }
1697
1698 Tensor Norm() const;
1699
1700 boost::intrusive_ptr<UniTensor_base> normalize() {
1701 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
1702 out->normalize_();
1703 return out;
1704 }
1705 void normalize_(){
1706 cytnx_error_msg(true,"[ERROR] SparseUniTensor is about to deprecated.%s","\n");
1707 }
1708
1709 void tag() {
1710 // no-use!
1711 }
1721 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim, const bool &by_label);
1722 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim);
1723 void truncate_(const std::string &bond_idx, const cytnx_uint64 &dim);
1724 const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const;
1725 const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1726 const cytnx_complex128 &aux) const;
1727 const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1728 const cytnx_complex64 &aux) const;
1729 const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1730 const cytnx_double &aux) const;
1731 const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1732 const cytnx_float &aux) const;
1733 const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1734 const cytnx_uint64 &aux) const;
1735 const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1736 const cytnx_int64 &aux) const;
1737 const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1738 const cytnx_uint32 &aux) const;
1739 const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1740 const cytnx_int32 &aux) const;
1741 const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1742 const cytnx_uint16 &aux) const;
1743 const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1744 const cytnx_int16 &aux) const;
1745
1746 Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator);
1747 cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1748 const cytnx_complex128 &aux);
1749 cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1750 const cytnx_complex64 &aux);
1751 cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux);
1752 cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux);
1753 cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux);
1754 cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux);
1755 cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux);
1756 cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux);
1757 cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux);
1758 cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux);
1759
1760 void group_basis_(){
1761 cytnx_warning_msg(true,"[WARNING] group basis will not have any effect on SparseUniTensor.%s","\n");
1762 }
1763
1764 bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
1765 void _save_dispatch(std::fstream &f) const;
1766 void _load_dispatch(std::fstream &f);
1767
1768 const std::vector<cytnx_uint64>& get_qindices(const cytnx_uint64 &bidx) const{
1769 cytnx_error_msg(true,"[ERROR][SparseUniTensor] get_qindices can only be unsed on BlockUniTensor with Symmetry.%s","\n");
1770 }
1771 std::vector<cytnx_uint64>& get_qindices(const cytnx_uint64 &bidx){
1772 cytnx_error_msg(true,"[ERROR][SparseUniTensor] get_qindices can only be unsed on BlockUniTensor.%s","\n");
1773 }
1774 const vec2d<cytnx_uint64> & get_itoi() const{
1775 cytnx_error_msg(true,"[ERROR][SparseUniTensor] get_itoi can only be unsed on BlockUniTensor with Symmetry.%s","\n");
1776 }
1777 vec2d<cytnx_uint64> & get_itoi(){
1778 cytnx_error_msg(true,"[ERROR][SparseUniTensor] get_itoi can only be unsed on BlockUniTensor with Symmetry.%s","\n");
1779 }
1780
1781
1782 // end virtual func
1783
1784 };
1786
1787 //======================================================================
1789 class BlockUniTensor : public UniTensor_base {
1790 protected:
1791 public:
1792
1793 std::vector<std::vector<cytnx_uint64> > _inner_to_outer_idx;
1794 std::vector<Tensor> _blocks;
1795 Tensor NullRefTensor; // this returns when access block is not exists!
1796
1797 // given an index list [loc], get qnums from this->_bonds[loc] and return the combined qnums calculated from Symm object!
1798 // this assume 1. symmetry are the same for each bond!
1799 // 2. total_qns are feeded with size len(symmetry)
1800 void _fx_get_total_fluxs(std::vector<cytnx_uint64> &loc, const std::vector<Symmetry> &syms, std::vector<cytnx_int64> &total_qns){
1801 memset(&total_qns[0],0,sizeof(cytnx_int64)*total_qns.size());
1802
1803 for(cytnx_int32 i=0;i<syms.size();i++){
1804 if(this->_bonds[0].type() == BD_BRA)
1805 total_qns[i] = syms[0].reverse_rule(this->_bonds[0]._impl->_qnums[loc[0]][i]);
1806 else
1807 total_qns[i] = this->_bonds[0]._impl->_qnums[loc[0]][i];
1808
1809 for(auto j=1;j<loc.size();j++){
1810 if(this->_bonds[j].type() == BD_BRA)
1811 total_qns[i] = syms[i].combine_rule(total_qns[i],syms[i].reverse_rule(this->_bonds[j]._impl->_qnums[loc[j]][i]));
1812 else{
1813 total_qns[i] = syms[i].combine_rule(total_qns[i],this->_bonds[j]._impl->_qnums[loc[j]][i]);
1814 }
1815 }
1816 }
1817
1818
1819 }
1820
1821 void _fx_locate_elem(cytnx_int64 &bidx, std::vector<cytnx_uint64> &loc_in_T,const std::vector<cytnx_uint64> &locator) const;
1822
1823 // internal function, grouping all duplicate qnums in all bonds
1824 void _fx_group_duplicates(const std::vector<cytnx_uint64> &dup_bond_idxs, const std::vector<std::vector<cytnx_uint64> > &idx_mappers);
1825
1826
1827 void set_meta(BlockUniTensor *tmp, const bool &inner, const bool &outer) const {
1828 // outer meta
1829 if (outer) {
1830 tmp->_bonds = vec_clone(this->_bonds);
1831 tmp->_labels = this->_labels;
1832 tmp->_is_braket_form = this->_is_braket_form;
1833 tmp->_rowrank = this->_rowrank;
1834 tmp->_name = this->_name;
1835 }
1836
1837 tmp->_is_diag = this->_is_diag;
1838
1839 // inner meta
1840 if (inner) {
1841 tmp->_inner_to_outer_idx = this->_inner_to_outer_idx;
1842 }
1843 }
1844
1845
1846 BlockUniTensor *clone_meta(const bool &inner, const bool &outer) const {
1847 BlockUniTensor *tmp = new BlockUniTensor();
1848 this->set_meta(tmp, inner, outer);
1849 return tmp;
1850 };
1851
1852
1853
1854 friend class UniTensor;
1855 BlockUniTensor(){
1856 this->uten_type_id = UTenType.Block;
1857 this->_is_tag = true;
1858 }
1859
1860 //virtual functions:
1861 //void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels = {},
1862 // const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1863 // const int &device = Device.cpu, const bool &is_diag = false,
1864 // const bool &no_alloc = false);
1865
1866 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1867 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1868 const int &device = Device.cpu, const bool &is_diag = false,
1869 const bool &no_alloc = false, const std::string &name = "");
1870
1871 void Init_by_Tensor(const Tensor &in_tensor, const bool &is_diag = false,
1872 const cytnx_int64 &rowrank = -1, const std::string &name = "") {
1874 true, "[ERROR][BlockUniTensor] cannot use Init_by_tensor() on a BlockUniTensor.%s", "\n");
1875 }
1876
1877
1878 std::vector<cytnx_uint64> shape() const {
1879 std::vector<cytnx_uint64> out(this->_bonds.size());
1880 for (cytnx_uint64 i = 0; i < out.size(); i++) {
1881 out[i] = this->_bonds[i].dim();
1882 }
1883 return out;
1884 }
1885
1886 bool is_blockform() const { return true; }
1887 bool is_contiguous() const {
1888 bool out=true;
1889 for(int i=0;i<this->_blocks.size();i++){
1890 out &= this->_blocks[i].is_contiguous();
1891 }
1892 return out;
1893 };
1894
1895 cytnx_uint64 Nblocks() const { return this->_blocks.size(); };
1896
1897 void to_(const int &device) {
1898 for (cytnx_uint64 i = 0; i < this->_blocks.size(); i++) {
1899 this->_blocks[i].to_(device);
1900 }
1901 };
1902
1903 boost::intrusive_ptr<UniTensor_base> to(const int &device) {
1904 if (this->device() == device) {
1905 return this;
1906 } else {
1907 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1908 out->to_(device);
1909 return out;
1910 }
1911 };
1912
1913 boost::intrusive_ptr<UniTensor_base> clone() const {
1914 BlockUniTensor *tmp = this->clone_meta(true, true);
1915 tmp->_blocks = vec_clone(this->_blocks);
1916 boost::intrusive_ptr<UniTensor_base> out(tmp);
1917 return out;
1918 };
1919
1920 unsigned int dtype() const {
1921#ifdef UNI_DEBUG
1922 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1923 "\n");
1924#endif
1925 return this->_blocks[0].dtype();
1926 };
1927 int device() const {
1928#ifdef UNI_DEBUG
1929 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1930 "\n");
1931#endif
1932 return this->_blocks[0].device();
1933 };
1934 std::string dtype_str() const {
1935#ifdef UNI_DEBUG
1936 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1937 "\n");
1938#endif
1939 return this->_blocks[0].dtype_str();
1940 };
1941 std::string device_str() const {
1942#ifdef UNI_DEBUG
1943 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1944 "\n");
1945#endif
1946 return this->_blocks[0].device_str();
1947
1948 };
1949
1950 Tensor get_block(const cytnx_uint64 &idx = 0) const {
1951 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1952 "\n");
1953 return this->_blocks[idx].clone();
1954 };
1955
1956 // this one for Block will return the indicies!!
1957 Tensor get_block(const std::vector<cytnx_int64> &indices, const bool &force_return) const {
1958
1959 cytnx_error_msg(indices.size()!=this->rank(),"[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the Tensor rank (number of legs).%s","\n");
1960
1961 std::vector<cytnx_uint64> inds(indices.begin(),indices.end());
1962
1963
1964 //find if the indices specify exists!
1965 cytnx_int64 b = -1;
1966 for(cytnx_uint64 i=0;i<this->_inner_to_outer_idx.size();i++){
1967 if(inds == this->_inner_to_outer_idx[i]){
1968 b = i;
1969 break;
1970 }
1971 }
1972
1973 if(b<0){
1974 if(force_return){
1975 return NullRefTensor;
1976 }else{
1977 cytnx_error_msg(true,"[ERROR][get_block][BlockUniTensor] no avaliable block exists, force_return=false, so error throws. \n If you want to return an empty block without error when block is not avaliable, set force_return=True.%s","\n");
1978 }
1979 }else{
1980 return this->_blocks[b].clone();
1981 }
1982 }
1983
1984 const Tensor& get_block_(const cytnx_uint64 &idx = 0) const {
1985 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1986 "\n");
1987 return this->_blocks[idx];
1988 };
1989
1990 Tensor& get_block_(const cytnx_uint64 &idx = 0) {
1991 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1992 "\n");
1993 return this->_blocks[idx];
1994 };
1995
1996 const Tensor &get_block_(const std::vector<cytnx_int64> &indices, const bool &force_return) const {
1997 cytnx_error_msg(indices.size()!=this->rank(),"[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the Tensor rank (number of legs).%s","\n");
1998
1999 std::vector<cytnx_uint64> inds(indices.begin(),indices.end());
2000
2001 //find if the indices specify exists!
2002 cytnx_int64 b = -1;
2003 for(cytnx_uint64 i=0;i<this->_inner_to_outer_idx.size();i++){
2004 if(inds == this->_inner_to_outer_idx[i]){
2005 b = i;
2006 break;
2007 }
2008 }
2009
2010 if(b<0){
2011 if(force_return){
2012 return this->NullRefTensor;
2013 }else{
2014 cytnx_error_msg(true,"[ERROR][get_block][BlockUniTensor] no avaliable block exists, force_return=false, so error throws. \n If you want to return an empty block without error when block is not avaliable, set force_return=True.%s","\n");
2015 }
2016 }else{
2017 return this->_blocks[b];
2018 }
2019
2020 }
2021
2022 Tensor &get_block_(const std::vector<cytnx_int64> &indices, const bool &force_return){
2023 cytnx_error_msg(indices.size()!=this->rank(),"[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the Tensor rank (number of legs).%s","\n");
2024
2025 std::vector<cytnx_uint64> inds(indices.begin(),indices.end());
2026
2027 //find if the indices specify exists!
2028 cytnx_int64 b = -1;
2029 for(cytnx_uint64 i=0;i<this->_inner_to_outer_idx.size();i++){
2030 if(inds == this->_inner_to_outer_idx[i]){
2031 b = i;
2032 break;
2033 }
2034 }
2035
2036 if(b<0){
2037 if(force_return){
2038 return this->NullRefTensor;
2039 }else{
2040 cytnx_error_msg(true,"[ERROR][get_block][BlockUniTensor] no avaliable block exists, force_return=false, so error throws. \n If you want to return an empty block without error when block is not avaliable, set force_return=True.%s","\n");
2041 }
2042 }else{
2043 return this->_blocks[b];
2044 }
2045
2046 }
2047
2048 std::vector<Tensor> get_blocks() const{
2049 return vec_clone(this->_blocks);
2050 }
2051 const std::vector<Tensor> &get_blocks_(const bool &) const{
2052 return this->_blocks;
2053 }
2054 std::vector<Tensor> &get_blocks_(const bool &){
2055 return this->_blocks;
2056 }
2057
2058
2059
2060 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const {
2061 if (rhs->uten_type() != UTenType.Block) return false;
2062 if (rhs->get_blocks_(1).size() != this->get_blocks_(1).size()) return false;
2063
2064 for (int i = 0; i < rhs->get_blocks_(1).size(); i++)
2065 if (this->get_blocks_(1)[i].same_data(rhs->get_blocks_(1)[i]) == false) return false;
2066
2067 return true;
2068 }
2069
2070
2071
2072 void set_rowrank(const cytnx_uint64 &new_rowrank) {
2073 cytnx_error_msg(new_rowrank > this->rank(),
2074 "[ERROR][BlockUniTensor] rowrank should be [>=0] and [<=UniTensor.rank].%s",
2075 "\n");
2076 if(this->is_diag()){
2077 cytnx_error_msg(new_rowrank != 1,
2078 "[ERROR][BlockUniTensor] rowrank should be [==1] when is_diag =true!.%s",
2079 "\n");
2080 }
2081 this->_rowrank = new_rowrank;
2082 this->_is_braket_form = this->_update_braket();
2083 }
2084
2085 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
2086 const cytnx_int64 &rowrank=-1,
2087 const bool &by_label=false);
2088 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
2089 const cytnx_int64 &rowrank = -1);
2090 //boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
2091 // const cytnx_int64 &rowrank = -1);
2092
2093 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank=-1,
2094 const bool &by_label=false);
2095 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
2096 //void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
2097
2098
2099 boost::intrusive_ptr<UniTensor_base> contiguous_() {
2100 for(unsigned int b=0;b<this->_blocks.size();b++)
2101 this->_blocks[b].contiguous_();
2102 return boost::intrusive_ptr<UniTensor_base>(this);
2103 }
2104
2105 boost::intrusive_ptr<UniTensor_base> contiguous();
2106
2107
2108 void print_diagram(const bool &bond_info = false);
2109 void print_blocks(const bool &full_info=true) const;
2110 void print_block(const cytnx_int64 &idx, const bool &full_info=true) const;
2111
2112 boost::intrusive_ptr<UniTensor_base> contract(
2113 const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &mv_elem_self = false,
2114 const bool &mv_elem_rhs = false);
2115
2116
2117 boost::intrusive_ptr<UniTensor_base> relabels(
2118 const std::vector<cytnx_int64> &new_labels);
2119 boost::intrusive_ptr<UniTensor_base> relabels(
2120 const std::vector<std::string> &new_labels);
2121 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
2122 const cytnx_int64 &new_label,
2123 const bool &by_label);
2124 boost::intrusive_ptr<UniTensor_base> relabel(const std::string &inx,
2125 const std::string &new_label);
2126 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
2127 const cytnx_int64 &new_label);
2128 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
2129 const std::string &new_label);
2130
2131 std::vector<Symmetry> syms() const;
2132
2133 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
2134 cytnx_error_msg(true, "[ERROR] cannot reshape a UniTensor with symmetry.%s", "\n");
2135 }
2136 boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
2137 const cytnx_uint64 &rowrank = 0) {
2138 cytnx_error_msg(true, "[ERROR] cannot reshape a UniTensor with symmetry.%s", "\n");
2139 return nullptr;
2140 }
2141
2142 boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const {
2143 BlockUniTensor *tmp = this->clone_meta(true, true);
2144 tmp->_blocks.resize(this->_blocks.size());
2145 for (cytnx_int64 blk = 0; blk < this->_blocks.size(); blk++) {
2146 tmp->_blocks[blk] = this->_blocks[blk].astype(dtype);
2147 }
2148 boost::intrusive_ptr<UniTensor_base> out(tmp);
2149 return out;
2150 };
2151
2152 // this will only work on non-symm tensor (DenseUniTensor)
2153 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors){
2154 cytnx_error_msg(true,
2155 "[ERROR][BlockUniTensor][get] cannot use get on a UniTensor with "
2156 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
2157 "\n");
2158 return nullptr;
2159
2160 }
2161
2162 // this will only work on non-symm tensor (DenseUniTensor)
2163 void set(const std::vector<Accessor> &accessors, const Tensor &rhs){
2164 cytnx_error_msg(true,
2165 "[ERROR][BlockUniTensor][get] cannot use get on a UniTensor with "
2166 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
2167 "\n");
2168 }
2169
2170 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0){
2171 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
2172 "\n");
2173 cytnx_error_msg(in.shape() != this->_blocks[idx].shape(),
2174 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
2175 "of block @ idx=%d\n",
2176 idx);
2177
2178 this->_blocks[idx] = in.clone();
2179 }
2180 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0){
2181 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
2182 "\n");
2183 cytnx_error_msg(in.shape() != this->_blocks[idx].shape(),
2184 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
2185 "of block @ idx=%d\n",
2186 idx);
2187
2188 this->_blocks[idx] = in;
2189
2190 }
2191 void put_block(const Tensor &in, const std::vector<cytnx_int64> &indices,
2192 const bool &check){
2193
2194 cytnx_error_msg(indices.size()!=this->rank(),"[ERROR][put_block][BlockUniTensor] len(indices) must be the same as the Tensor rank (number of legs).%s","\n");
2195
2196 std::vector<cytnx_uint64> inds(indices.begin(),indices.end());
2197
2198 //find if the indices specify exists!
2199 cytnx_int64 b = -1;
2200 for(cytnx_uint64 i=0;i<this->_inner_to_outer_idx.size();i++){
2201 if(inds == this->_inner_to_outer_idx[i]){
2202 b = i;
2203 break;
2204 }
2205 }
2206
2207 if(b<0){
2208 if(check){
2209 cytnx_error_msg(true,"[ERROR][put_block][BlockUniTensor] no avaliable block exists, check=true, so error throws. \n If you want without error when block is not avaliable, set check=false.%s","\n");
2210 }
2211 }else{
2212 cytnx_error_msg(in.shape() != this->_blocks[b].shape(),
2213 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
2214 "of block @ idx=%d\n",
2215 b);
2216
2217 this->_blocks[b] = in.clone();
2218 }
2219
2220
2221 }
2222 void put_block_(Tensor &in, const std::vector<cytnx_int64> &indices, const bool &check){
2223 cytnx_error_msg(indices.size()!=this->rank(),"[ERROR][put_block][BlockUniTensor] len(indices) must be the same as the Tensor rank (number of legs).%s","\n");
2224
2225 std::vector<cytnx_uint64> inds(indices.begin(),indices.end());
2226
2227 //find if the indices specify exists!
2228 cytnx_int64 b = -1;
2229 for(cytnx_uint64 i=0;i<this->_inner_to_outer_idx.size();i++){
2230 if(inds == this->_inner_to_outer_idx[i]){
2231 b = i;
2232 break;
2233 }
2234 }
2235
2236 if(b<0){
2237 if(check){
2238 cytnx_error_msg(true,"[ERROR][put_block][BlockUniTensor] no avaliable block exists, check=true, so error throws. \n If you want without error when block is not avaliable, set check=false.%s","\n");
2239 }
2240 }else{
2241 cytnx_error_msg(in.shape() != this->_blocks[b].shape(),
2242 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
2243 "of block @ idx=%d\n",
2244 b);
2245 this->_blocks[b] = in;
2246 }
2247
2248 }
2249
2250 void tag() {
2251 // no-use!
2252 }
2253
2254
2255 boost::intrusive_ptr<UniTensor_base> Conj() {
2256 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2257 out->Conj_();
2258 return out;
2259 }
2260
2261 void Conj_() {
2262 for (int i = 0; i < this->_blocks.size(); i++) {
2263 this->_blocks[i].Conj_();
2264 }
2265 };
2266
2267 void Transpose_();
2268 boost::intrusive_ptr<UniTensor_base> Transpose() {
2269 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2270 out->Transpose_();
2271 return out;
2272 }
2273
2274 void normalize_();
2275 boost::intrusive_ptr<UniTensor_base> normalize() {
2276 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2277 out->normalize_();
2278 return out;
2279 }
2280
2281
2282 boost::intrusive_ptr<UniTensor_base> Dagger() {
2283 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
2284 out->Transpose_();
2285 return out;
2286 }
2287 void Dagger_() {
2288 this->Conj_();
2289 this->Transpose_();
2290 }
2291
2292 void Trace_(const std::string &a, const std::string &b);
2293 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
2294 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label);
2295
2296 boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b) {
2297 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2298 out->Trace_(a, b);
2299 if(out->rank()==0){
2300 DenseUniTensor *tmp = new DenseUniTensor();
2301 tmp->_block = ((BlockUniTensor*)out.get())->_blocks[0];
2302 out = boost::intrusive_ptr<UniTensor_base>(tmp);
2303 }
2304 return out;
2305 }
2306 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b) {
2307 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2308 out->Trace_(a, b);
2309 if(out->rank()==0){
2310 DenseUniTensor *tmp = new DenseUniTensor();
2311 tmp->_block = ((BlockUniTensor*)out.get())->_blocks[0];
2312 out = boost::intrusive_ptr<UniTensor_base>(tmp);
2313 }
2314 return out;
2315 }
2325 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b,
2326 const bool &by_label) {
2327 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2328 out->Trace_(a, b, by_label);
2329 if(out->rank()==0){
2330 DenseUniTensor *tmp = new DenseUniTensor();
2331 tmp->_block = ((BlockUniTensor*)out.get())->_blocks[0];
2332 out = boost::intrusive_ptr<UniTensor_base>(tmp);
2333 }
2334 return out;
2335 }
2336
2337 Tensor Norm() const;
2338
2339 bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
2340
2341 const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const;
2342 const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2343 const cytnx_complex128 &aux) const;
2344 const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2345 const cytnx_complex64 &aux) const;
2346 const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2347 const cytnx_double &aux) const;
2348 const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2349 const cytnx_float &aux) const;
2350 const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2351 const cytnx_uint64 &aux) const;
2352 const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2353 const cytnx_int64 &aux) const;
2354 const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2355 const cytnx_uint32 &aux) const;
2356 const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2357 const cytnx_int32 &aux) const;
2358 const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2359 const cytnx_uint16 &aux) const;
2360 const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2361 const cytnx_int16 &aux) const;
2362
2363 Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator);
2364 cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2365 const cytnx_complex128 &aux);
2366 cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2367 const cytnx_complex64 &aux);
2368 cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux);
2369 cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux);
2370 cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux);
2371 cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux);
2372 cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux);
2373 cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux);
2374 cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux);
2375 cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux);
2376
2377 void _save_dispatch(std::fstream &f) const;
2378 void _load_dispatch(std::fstream &f);
2379
2380 // this will remove the [q_index]-th qnum at [bond_idx]-th Bond!
2381 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &q_index,
2382 const bool &by_label);
2383 void truncate_(const std::string &bond_idx, const cytnx_uint64 &q_index);
2384 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &q_index);
2385
2386
2387 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
2388 void Add_(const Scalar &rhs){
2389 cytnx_error_msg(true, "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s \n",
2390 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do operation on the block(s).");
2391 }
2392
2393 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
2394 void Mul_(const Scalar &rhs);
2395
2396 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
2397 void Sub_(const Scalar &rhs){
2398 cytnx_error_msg(true, "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s \n",
2399 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do operation on the block(s).");
2400 }
2401 void lSub_(const Scalar &lhs){
2402 cytnx_error_msg(true, "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s \n",
2403 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do operation on the block(s).");
2404 }
2405
2406 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs){
2407 cytnx_error_msg(true, "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s \n",
2408 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do operation on the block(s).");
2409
2410 }
2411 void Div_(const Scalar &rhs);
2412 void lDiv_(const Scalar &lhs){
2413 cytnx_error_msg(true, "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s \n",
2414 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do operation on the block(s).");
2415 }
2416
2417 void group_basis_();
2418
2419 void combineBonds(const std::vector<cytnx_int64> &indicators,
2420 const bool &force = false);
2421 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
2422 const bool &by_label);
2423 void combineBonds(const std::vector<std::string> &indicators,
2424 const bool &force = false);
2425
2426 const std::vector<cytnx_uint64>& get_qindices(const cytnx_uint64 &bidx) const{
2427 cytnx_error_msg(bidx>=this->Nblocks(),"[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",this->Nblocks());
2428 return this->_inner_to_outer_idx[bidx];
2429 }
2430 std::vector<cytnx_uint64>& get_qindices(const cytnx_uint64 &bidx){
2431 cytnx_error_msg(bidx>=this->Nblocks(),"[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",this->Nblocks());
2432 return this->_inner_to_outer_idx[bidx];
2433 }
2434
2435 const vec2d<cytnx_uint64> & get_itoi() const{
2436 return this->_inner_to_outer_idx;
2437 }
2438 vec2d<cytnx_uint64> & get_itoi(){
2439 return this->_inner_to_outer_idx;
2440 }
2441
2442
2443
2444 };
2446 //======================================================================
2447
2450 public:
2452 boost::intrusive_ptr<UniTensor_base> _impl;
2453 UniTensor() : _impl(new UniTensor_base()){};
2454 UniTensor(const UniTensor &rhs) { this->_impl = rhs._impl; }
2455 UniTensor &operator=(const UniTensor &rhs) {
2456 this->_impl = rhs._impl;
2457 return *this;
2458 }
2460
2462
2488 explicit UniTensor(const Tensor &in_tensor, const bool &is_diag = false,
2489 const cytnx_int64 &rowrank = -1, const std::string &name = "")
2490 : _impl(new UniTensor_base()) {
2491 this->Init(in_tensor, is_diag, rowrank, name);
2492 }
2510 void Init(const Tensor &in_tensor, const bool &is_diag = false,
2511 const cytnx_int64 &rowrank = -1, const std::string &name = "") {
2512 //std::cout << "[entry!]" << std::endl;
2513 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
2514 out->Init_by_Tensor(in_tensor, is_diag, rowrank, name);
2515 this->_impl = out;
2516 }
2518
2520
2536 UniTensor(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
2537 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
2538 const int &device = Device.cpu, const bool &is_diag = false, const std::string &name = "")
2539 : _impl(new UniTensor_base()) {
2540#ifdef UNI_DEBUG
2542 true,
2543 "[DEBUG] message: entry for UniTensor(const std::vector<Bond> &bonds, const "
2544 "std::vector<std::string> &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int "
2545 "&dtype=Type.Double, const int &device = Device.cpu, const bool &is_diag=false)%s",
2546 "\n");
2547#endif
2548 this->Init(bonds, in_labels, rowrank, dtype, device, is_diag, name);
2549 }
2558 UniTensor(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels,
2559 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
2560 const int &device = Device.cpu, const bool &is_diag = false, const std::string &name = "")
2561 : _impl(new UniTensor_base()) {
2562#ifdef UNI_DEBUG
2564 true,
2565 "[DEBUG] message: entry for UniTensor(const std::vector<Bond> &bonds, const "
2566 "std::vector<cytnx_int64> &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int "
2567 "&dtype=Type.Double, const int &device = Device.cpu, const bool &is_diag=false)%s",
2568 "\n");
2569#endif
2570 std::vector<std::string> vs;
2571 for (int i = 0; i < (int)in_labels.size(); i++) vs.push_back(std::to_string(in_labels[i]));
2572 this->Init(bonds, vs, rowrank, dtype, device, is_diag, name);
2573 }
2597 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
2598 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
2599 const int &device = Device.cpu, const bool &is_diag = false, const std::string &name = "") {
2600 // checking type:
2601 bool is_sym = false;
2602 int sym_fver = -1;
2603
2604 for (cytnx_uint64 i = 0; i < bonds.size(); i++) {
2605 // check
2606 if (bonds[i].syms().size() != 0){
2607 is_sym = true;
2608 if(sym_fver == -1) sym_fver = bonds[i]._impl->_degs.size();
2609 else{
2610 //std::cout << sym_fver << " " <<
2611 //bonds[i]._impl->_degs.size() << std::endl;
2612 cytnx_error_msg((bool(sym_fver)^bool(bonds[i]._impl->_degs.size())), "[ERROR] All the Bond when init a UniTensor with symmetric must be in the same format!%s","\n");
2613 }
2614 }else
2616 is_sym, "[ERROR] cannot have bonds with mixing of symmetry and non-symmetry.%s", "\n");
2617 }
2618
2619 // dynamical dispatch:
2620 if (is_sym) {
2621#ifdef UNI_DEBUG
2622 cytnx_warning_msg(true, "[DEBUG] message: entry dispatch: UniTensor: symmetric%s", "\n");
2623#endif
2624 // cytnx_warning_msg(true,"[warning, still developing, some functions will display
2625 // \"[Developing]\"][SparseUniTensor]%s","\n");
2626 if(sym_fver == 0){
2627 boost::intrusive_ptr<UniTensor_base> out(new SparseUniTensor());
2628 this->_impl = out;
2629 }else if(sym_fver==-1){
2630 cytnx_error_msg(true,"[ERROR] internal error! the Bond is symmetry but the version is not properly determined!%s","\n");
2631 }else{
2632 boost::intrusive_ptr<UniTensor_base> out(new BlockUniTensor());
2633 this->_impl = out;
2634 }
2635 } else {
2636 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
2637 this->_impl = out;
2638 }
2639 this->_impl->Init(bonds, in_labels, rowrank, dtype, device, is_diag, false, name);
2640 }
2649 void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels,
2650 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
2651 const int &device = Device.cpu, const bool &is_diag = false, const std::string &name = "") {
2652 std::vector<std::string> vs;
2653 cytnx_warning_msg(true,"[Deprecated warning] specify label with integers will be depreated soon. use string instead.%s","\n");
2654 for (int i = 0; i < (int)in_labels.size(); i++) vs.push_back(std::to_string(in_labels[i]));
2655 this->Init(bonds, vs, rowrank, dtype, device, is_diag, name);
2656 }
2657
2659
2666 UniTensor &set_name(const std::string &in) {
2667 this->_impl->set_name(in);
2668 return *this;
2669 }
2678 UniTensor &set_label(const cytnx_int64 &idx, const cytnx_int64 &new_label,
2679 const bool &by_label) {
2680 this->_impl->set_label(idx, new_label, by_label);
2681 return *this;
2682 }
2683
2693 UniTensor &set_label(const cytnx_int64 &idx, const cytnx_int64 &new_label) {
2694 this->_impl->set_label(idx, new_label);
2695 return *this;
2696 }
2705 UniTensor &set_label(const cytnx_int64 &idx, const std::string &new_label) {
2706 this->_impl->set_label(idx, new_label);
2707 return *this;
2708 }
2709
2713 UniTensor &set_label(const cytnx_int64 &idx, const char* new_label){
2714 this->_impl->set_label(idx, std::string(new_label));
2715 return *this;
2716 }
2717
2726 UniTensor &set_label(const std::string &old_label, const std::string &new_label) {
2727 this->_impl->set_label(old_label, new_label);
2728 return *this;
2729 }
2730
2734 UniTensor &set_label(const char* old_label, const std::string &new_label) {
2735 this->_impl->set_label(std::string(old_label), new_label);
2736 return *this;
2737 }
2738
2742 UniTensor &set_label(const std::string &old_label, const char* new_label) {
2743 this->_impl->set_label(old_label, std::string(new_label));
2744 return *this;
2745 }
2746
2750 UniTensor &set_label(const char* old_label, const char* new_label) {
2751 this->_impl->set_label(std::string(old_label), std::string(new_label));
2752 return *this;
2753 }
2754
2755
2766 /*
2767 UniTensor& change_label(const cytnx_int64 &old_lbl, const cytnx_int64 &new_label){
2768 this->_impl->change_label(old_lbl,new_label);
2769 return *this;
2770 }
2771 */
2772
2779 UniTensor &set_labels(const std::vector<cytnx_int64> &new_labels) {
2780 this->_impl->set_labels(new_labels);
2781 return *this;
2782 }
2790 UniTensor &set_labels(const std::vector<std::string> &new_labels) {
2791 this->_impl->set_labels(new_labels);
2792 return *this;
2793 }
2798 UniTensor &set_labels(const std::initializer_list<char*> &new_labels) {
2799 std::vector<char*> new_lbls(new_labels);
2800 std::vector<std::string> vs(new_lbls.size());
2801 transform(new_lbls.begin(),new_lbls.end(), vs.begin(),[](char * x) -> std::string { return std::string(x); });
2802
2803 this->_impl->set_labels(vs);
2804 return *this;
2805 }
2806
2813 UniTensor &set_rowrank(const cytnx_uint64 &new_rowrank) {
2814 this->_impl->set_rowrank(new_rowrank);
2815 return *this;
2816 }
2817
2818 template <class T>
2819 T &item() {
2821 "[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use "
2822 "get_block()/get_blocks() first.%s",
2823 "\n");
2824
2825 DenseUniTensor *tmp = static_cast<DenseUniTensor *>(this->_impl.get());
2826 return tmp->_block.item<T>();
2827 }
2828
2829 Scalar::Sproxy item() const {
2831 "[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use "
2832 "get_block()/get_blocks() first.%s",
2833 "\n");
2834
2835 DenseUniTensor *tmp = static_cast<DenseUniTensor *>(this->_impl.get());
2836 return tmp->_block.item();
2837 }
2842 cytnx_uint64 Nblocks() const { return this->_impl->Nblocks(); }
2843
2848 cytnx_uint64 rank() const { return this->_impl->rank(); }
2849
2854 cytnx_uint64 rowrank() const { return this->_impl->rowrank(); }
2855
2861 unsigned int dtype() const { return this->_impl->dtype(); }
2862
2869 int uten_type() const { return this->_impl->uten_type(); }
2870
2876 int device() const { return this->_impl->device(); }
2877
2882 std::string name() const { return this->_impl->name(); }
2883
2889 std::string dtype_str() const { return this->_impl->dtype_str(); }
2890
2896 std::string device_str() const { return this->_impl->device_str(); }
2897
2903 std::string uten_type_str() const { return this->_impl->uten_type_str(); }
2904
2910 bool is_contiguous() const { return this->_impl->is_contiguous(); }
2911
2916 bool is_diag() const { return this->_impl->is_diag(); }
2917 bool is_tag() const { return this->_impl->is_tag(); }
2918
2924 std::vector<Symmetry> syms() const { return this->_impl->syms(); }
2925 const bool &is_braket_form() const { return this->_impl->is_braket_form(); }
2926
2931 const std::vector<std::string> &labels() const { return this->_impl->labels(); }
2938 cytnx_int64 get_index(std::string lbl) const { return this->_impl->get_index(lbl); }
2939
2944 const std::vector<Bond> &bonds() const { return this->_impl->bonds(); }
2945
2949 std::vector<Bond> &bonds() { return this->_impl->bonds(); }
2950
2955 std::vector<cytnx_uint64> shape() const { return this->_impl->shape(); }
2956 bool is_blockform() const { return this->_impl->is_blockform(); }
2957
2964 void to_(const int &device) { this->_impl->to_(device); }
2965
2975 UniTensor to(const int &device) const {
2976 UniTensor out;
2977 out._impl = this->_impl->to(device);
2978 return out;
2979 }
2980
2986 UniTensor out;
2987 out._impl = this->_impl->clone();
2988 return out;
2989 }
2990
2996 UniTensor relabels(const std::vector<cytnx_int64> &new_labels) const {
2997 UniTensor out;
2998 out._impl = this->_impl->relabels(new_labels);
2999 return out;
3000 }
3001
3006 UniTensor relabels(const std::vector<std::string> &new_labels) const {
3007 UniTensor out;
3008 out._impl = this->_impl->relabels(new_labels);
3009 return out;
3010 }
3011
3015 UniTensor relabels(const std::initializer_list<char*> &new_lbls) const{
3016 std::vector<char*> new_labels(new_lbls);
3017 std::vector<std::string> vs(new_labels.size());
3018 transform(new_labels.begin(),new_labels.end(), vs.begin(),[](char * x) -> std::string { return std::string(x); });
3019 //std::cout << new_labels.size() << std::endl;
3020 //std::cout << vs << std::endl;
3021
3022 UniTensor out;
3023 out._impl = this->_impl->relabels(vs);
3024 return out;
3025 }
3026
3032 UniTensor relabel(const cytnx_int64 &inx, const cytnx_int64 &new_label,
3033 const bool &by_label=false) const {
3034 UniTensor out;
3035 out._impl = this->_impl->relabel(inx, new_label, by_label);
3036 return out;
3037 }
3038
3044 UniTensor relabel(const cytnx_int64 &inx, const std::string &new_label) const {
3045 UniTensor out;
3046 out._impl = this->_impl->relabel(inx, new_label);
3047 return out;
3048 }
3049
3055 UniTensor relabel(const std::string &old_label, const std::string &new_label) const {
3056 UniTensor out;
3057 out._impl = this->_impl->relabel(old_label, new_label);
3058 return out;
3059 }
3060
3067 UniTensor astype(const unsigned int &dtype) const {
3068 UniTensor out;
3069 if (this->dtype() == dtype) {
3070 out._impl = this->_impl;
3071 } else {
3072 out._impl = this->_impl->astype(dtype);
3073 }
3074 return out;
3075 }
3076
3087 UniTensor permute(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank=-1,
3088 const bool &by_label=false) const {
3089 UniTensor out;
3090 out._impl = this->_impl->permute(mapper, rowrank, by_label);
3091 return out;
3092 }
3093 //UniTensor permute(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1) {
3094 // UniTensor out;
3095 // out._impl = this->_impl->permute(mapper, rowrank);
3096 // return out;
3097 //}
3098 //
3105 UniTensor permute(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1) const {
3106 UniTensor out;
3107 out._impl = this->_impl->permute(mapper, rowrank);
3108 return out;
3109 }
3110
3114 UniTensor permute( const std::initializer_list<char*> &mapper, const cytnx_int64 &rowrank= -1) const{
3115 std::vector<char*> mprs = mapper;
3116 std::vector<std::string> vs(mprs.size());
3117 transform(mprs.begin(),mprs.end(),vs.begin(),[](char * x) -> std::string { return std::string(x); });
3118
3119 return this->permute(vs,rowrank);
3120 }
3121
3131 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank=-1,
3132 const bool &by_label=false) {
3133 this->_impl->permute_(mapper, rowrank, by_label);
3134 }
3135
3142 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1) {
3143 this->_impl->permute_(mapper, rowrank);
3144 }
3145
3146 // void permute_( const std::initializer_list<char*> &mapper, const cytnx_int64 &rowrank= -1){
3147 // std::vector<char*> mprs = mapper;
3148 // std::vector<std::string> vs(mprs.size());
3149 // transform(mprs.begin(),mprs.end(),vs.begin(),[](char * x) -> std::string { return std::string(x); });
3150
3151 // this->permute_(vs,rowrank);
3152 // }
3153
3154 //void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1) {
3155 // this->_impl->permute_(mapper, rowrank);
3156 //}
3157
3163 UniTensor out;
3164 out._impl = this->_impl->contiguous();
3165 return out;
3166 }
3167
3172 void contiguous_() { this->_impl = this->_impl->contiguous_(); }
3173
3178 void print_diagram(const bool &bond_info = false) { this->_impl->print_diagram(bond_info); }
3179
3184 void print_blocks(const bool &full_info=true) const{ this->_impl->print_blocks(full_info); }
3185
3191 void print_block(const cytnx_int64 &idx, const bool &full_info=true) const{this->_impl->print_block(idx,full_info);}
3192
3194 this->_impl->group_basis_();
3195 }
3196
3198 UniTensor out = this->clone();
3199 out.group_basis_();
3200 return out;
3201 }
3202
3203
3209 template <class T>
3210 T &at(const std::vector<cytnx_uint64> &locator){
3211 // std::cout << "at " << this->is_blockform() << std::endl;
3212 if (this->uten_type() ==UTenType.Block){
3213 // [NEW] this will not check if it exists, if it is not then error will throw!
3214 T aux;
3215 return this->_impl->at_for_sparse(locator, aux);
3216
3217 }else if (this->uten_type() == UTenType.Sparse) {
3218 if (this->_impl->elem_exists(locator)) {
3219 T aux;
3220 return this->_impl->at_for_sparse(locator, aux);
3221 } else {
3222 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
3223 "\n");
3224 }
3225 } else {
3226 return this->get_block_().at<T>(locator);
3227 }
3228 }
3229
3235 template <class T>
3236 const T &at(const std::vector<cytnx_uint64> &locator) const {
3237 // std::cout << "at " << this->is_blockform() << std::endl;
3238 if (this->uten_type() ==UTenType.Block){
3239 // [NEW] this will not check if it exists, if it is not then error will throw!
3240 T aux;
3241 return this->_impl->at_for_sparse(locator, aux);
3242
3243 }else if (this->uten_type() == UTenType.Sparse) {
3244 if (this->_impl->elem_exists(locator)) {
3245 T aux; // [workaround] use aux to dispatch.
3246 return this->_impl->at_for_sparse(locator, aux);
3247 } else {
3248 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
3249 "\n");
3250 }
3251 } else {
3252 return this->get_block_().at<T>(locator);
3253 }
3254 }
3255
3256 const Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) const {
3257 if (this->uten_type() == UTenType.Block){
3258 return this->_impl->at_for_sparse(locator);
3259 }else if (this->uten_type() == UTenType.Sparse) {
3260 if (this->_impl->elem_exists(locator)) {
3261 return this->_impl->at_for_sparse(locator);
3262 } else {
3263 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
3264 "\n");
3265 }
3266 } else {
3267 return this->get_block_().at(locator);
3268 }
3269 }
3270
3271 Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) {
3272 if (this->uten_type() == UTenType.Block){
3273 return this->_impl->at_for_sparse(locator);
3274 }else if (this->uten_type() == UTenType.Sparse) {
3275 if (this->_impl->elem_exists(locator)) {
3276 return this->_impl->at_for_sparse(locator);
3277 } else {
3278 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
3279 "\n");
3280 }
3281 } else {
3282 return this->get_block_().at(locator);
3283 }
3284 }
3285
3286 // return a clone of block
3292 Tensor get_block(const cytnx_uint64 &idx = 0) const { return this->_impl->get_block(idx); };
3293 //================================
3294 // return a clone of block
3303 Tensor get_block(const std::vector<cytnx_int64> &qnum, const bool &force = false) const {
3304 return this->_impl->get_block(qnum, force);
3305 }
3306
3311 Tensor get_block(const std::initializer_list<cytnx_int64> &qnum,
3312 const bool &force = false) const {
3313 std::vector<cytnx_int64> tmp = qnum;
3314 return get_block(tmp, force);
3315 }
3316
3321 Tensor get_block(const std::vector<cytnx_uint64> &qnum, const bool &force = false) const {
3322 std::vector<cytnx_int64> iqnum(qnum.begin(),qnum.end());
3323 return this->_impl->get_block(iqnum, force);
3324 }
3325
3332 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const {
3333 return this->_impl->get_block_(idx);
3334 }
3335
3340 Tensor &get_block_(const cytnx_uint64 &idx = 0) { return this->_impl->get_block_(idx); }
3341
3351 Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force = false) {
3352 return this->_impl->get_block_(qnum, force);
3353 }
3354
3358 Tensor &get_block_(const std::initializer_list<cytnx_int64> &qnum, const bool &force = false) {
3359 std::vector<cytnx_int64> tmp = qnum;
3360 return get_block_(tmp, force);
3361 }
3362
3366 Tensor &get_block_(const std::vector<cytnx_uint64> &qnum, const bool &force = false){
3367 std::vector<cytnx_int64> iqnum(qnum.begin(),qnum.end());
3368 return get_block_(iqnum,force);
3369 }
3370 //================================
3371
3372 // this only work for non-symm tensor. return a shared view of block
3376 const Tensor &get_block_(const std::vector<cytnx_int64> &qnum,
3377 const bool &force = false) const {
3378 return this->_impl->get_block_(qnum, force);
3379 }
3380
3384 const Tensor &get_block_(const std::initializer_list<cytnx_int64> &qnum,
3385 const bool &force = false) const {
3386 std::vector<cytnx_int64> tmp = qnum;
3387 return this->_impl->get_block_(tmp, force);
3388 }
3389
3393 const Tensor &get_block_(const std::vector<cytnx_uint64> &qnum, const bool &force = false) const{
3394 std::vector<cytnx_int64> iqnum(qnum.begin(),qnum.end());
3395 return get_block_(iqnum,force);
3396 }
3397
3398 //================================
3407 //[dev]
3408 std::vector<Tensor> get_blocks() const { return this->_impl->get_blocks(); }
3409
3415 //[dev]
3416 const std::vector<Tensor> &get_blocks_(const bool &silent = false) const {
3417 return this->_impl->get_blocks_(silent);
3418 }
3419
3423 //[dev]
3424 std::vector<Tensor> &get_blocks_(const bool &silent = false) {
3425 return this->_impl->get_blocks_(silent);
3426 }
3427
3434 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
3435 this->_impl->put_block(in, idx);
3436 }
3437
3444 void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force) {
3445 this->_impl->put_block(in, qnum, force);
3446 }
3447
3453 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) { this->_impl->put_block_(in, idx); }
3454
3460 void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force) {
3461 this->_impl->put_block_(in, qnum, force);
3462 }
3463 UniTensor get(const std::vector<Accessor> &accessors) const {
3464 UniTensor out;
3465 out._impl = this->_impl->get(accessors);
3466 return out;
3467 }
3468 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
3469 this->_impl->set(accessors, rhs);
3470 }
3471
3477 UniTensor reshape(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
3478 UniTensor out;
3479 out._impl = this->_impl->reshape(new_shape, rowrank);
3480 return out;
3481 }
3482
3487 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
3488 this->_impl->reshape_(new_shape, rowrank);
3489 }
3490
3503 UniTensor out;
3504 out._impl = this->_impl->to_dense();
3505 return out;
3506 }
3507
3512 void to_dense_() { this->_impl->to_dense_(); }
3513
3519 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
3520 const bool &by_label) {
3521 this->_impl->combineBonds(indicators, force, by_label);
3522 }
3523
3532 void combineBonds(const std::vector<std::string> &indicators, const bool &force = false) {
3533 this->_impl->combineBonds(indicators, force);
3534 }
3535
3541 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = false) {
3542 this->_impl->combineBonds(indicators, force);
3543 }
3544
3565 UniTensor contract(const UniTensor &inR, const bool &mv_elem_self = false,
3566 const bool &mv_elem_rhs = false) const {
3567 UniTensor out;
3568 out._impl = this->_impl->contract(inR._impl, mv_elem_self, mv_elem_rhs);
3569 return out;
3570 }
3571
3580 std::vector<Bond> getTotalQnums(const bool physical = false) const {
3581 return this->_impl->getTotalQnums(physical);
3582 }
3583
3587 std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const {
3588 return this->_impl->get_blocks_qnums();
3589 }
3590
3591 bool same_data(const UniTensor &rhs) const {
3592 // check same type:
3593 if (this->_impl->uten_type() != rhs._impl->uten_type()) return false;
3594
3595 return this->_impl->same_data(rhs._impl);
3596 }
3597
3614 UniTensor &Add_(const UniTensor &rhs) {
3615 this->_impl->Add_(rhs._impl);
3616 return *this;
3617 }
3618
3635 UniTensor &Mul_(const UniTensor &rhs) {
3636 this->_impl->Mul_(rhs._impl);
3637 return *this;
3638 }
3639
3656 UniTensor &Sub_(const UniTensor &rhs) {
3657 this->_impl->Sub_(rhs._impl);
3658 return *this;
3659 }
3660
3677 UniTensor &Div_(const UniTensor &rhs) {
3678 this->_impl->Div_(rhs._impl);
3679 return *this;
3680 }
3681
3692 UniTensor &Add_(const Scalar &rhs) {
3693 this->_impl->Add_(rhs);
3694 return *this;
3695 }
3696
3707 UniTensor &Mul_(const Scalar &rhs) {
3708 this->_impl->Mul_(rhs);
3709 return *this;
3710 }
3711
3722 UniTensor &Sub_(const Scalar &rhs) {
3723 this->_impl->Sub_(rhs);
3724 return *this;
3725 }
3726
3737 UniTensor &Div_(const Scalar &rhs) {
3738 this->_impl->Div_(rhs);
3739 return *this;
3740 }
3741
3758 UniTensor Add(const UniTensor &rhs) const;
3759
3770 UniTensor Add(const Scalar &rhs) const;
3771
3788 UniTensor Mul(const UniTensor &rhs) const;
3789
3800 UniTensor Mul(const Scalar &rhs) const;
3801
3818 UniTensor Div(const UniTensor &rhs) const;
3819
3830 UniTensor Div(const Scalar &rhs) const;
3831
3848 UniTensor Sub(const UniTensor &rhs) const;
3849
3860 UniTensor Sub(const Scalar &rhs) const;
3861
3870 Tensor Norm() const { return this->_impl->Norm(); };
3871
3888 this->Add_(rhs);
3889 return *this;
3890 }
3891
3908 this->Sub_(rhs);
3909 return *this;
3910 }
3911
3928 this->Div_(rhs);
3929 return *this;
3930 }
3931
3948 this->Mul_(rhs);
3949 return *this;
3950 }
3951
3963 this->Add_(rhs);
3964 return *this;
3965 }
3966
3978 this->Sub_(rhs);
3979 return *this;
3980 }
3981
3993 this->Div_(rhs);
3994 return *this;
3995 }
3996
4008 this->Mul_(rhs);
4009 return *this;
4010 }
4011
4020 UniTensor out;
4021 out._impl = this->_impl->Conj();
4022 return out;
4023 }
4024
4033 this->_impl->Conj_();
4034 return *this;
4035 }
4036
4044 UniTensor out;
4045 out._impl = this->_impl->Transpose();
4046 return out;
4047 }
4048
4056 this->_impl->Transpose_();
4057 return *this;
4058 }
4059
4067 UniTensor out;
4068 out._impl = this->_impl->normalize();
4069 return out;
4070 }
4071
4079 this->_impl->normalize_();
4080 return *this;
4081 }
4082
4083
4093 UniTensor Trace(const std::string &a, const std::string &b) const {
4094 UniTensor out;
4095 out._impl = this->_impl->Trace(a, b);
4096 return out;
4097 }
4098
4108 UniTensor Trace(const cytnx_int64 &a = 0, const cytnx_int64 &b = 1) const {
4109 UniTensor out;
4110 out._impl = this->_impl->Trace(a, b);
4111 return out;
4112 }
4113
4120 UniTensor Trace(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label) const {
4121 if(by_label){
4122 return Trace(std::to_string(a),std::to_string(b));
4123 }else{
4124 return Trace(a, b);
4125 }
4126 }
4127
4137 UniTensor &Trace_(const std::string &a, const std::string &b) {
4138 this->_impl->Trace_(a, b);
4139 if(this->uten_type()==UTenType.Block){
4140 // handle if no leg left case for BlockUniTensor.
4141 if(this->rank()==0){
4142 DenseUniTensor *tmp = new DenseUniTensor();
4143 tmp->_block = this->get_blocks_(true)[0];
4144 this->_impl = boost::intrusive_ptr<UniTensor_base>(tmp);
4145 }
4146 }
4147 return *this;
4148 }
4149
4159 UniTensor &Trace_(const cytnx_int64 &a = 0, const cytnx_int64 &b = 1) {
4160 this->_impl->Trace_(a, b);
4161 if(this->uten_type()==UTenType.Block){
4162 // handle if no leg left case for BlockUniTensor.
4163 if(this->rank()==0){
4164 DenseUniTensor *tmp = new DenseUniTensor();
4165 tmp->_block = this->get_blocks_(true)[0];
4166 this->_impl = boost::intrusive_ptr<UniTensor_base>(tmp);
4167 }
4168 }
4169 return *this;
4170 }
4171
4178 UniTensor &Trace_(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label) {
4179 this->_impl->Trace_(a, b, by_label);
4180 if(this->uten_type()==UTenType.Block){
4181 // handle if no leg left case for BlockUniTensor.
4182 if(this->rank()==0){
4183 DenseUniTensor *tmp = new DenseUniTensor();
4184 tmp->_block = this->get_blocks_(true)[0];
4185 this->_impl = boost::intrusive_ptr<UniTensor_base>(tmp);
4186 }
4187 }
4188 return *this;
4189 }
4190
4198 UniTensor out;
4199 out._impl = this->_impl->Dagger();
4200 return out;
4201 }
4202
4210 this->_impl->Dagger_();
4211 return *this;
4212 }
4213
4215 this->_impl->tag();
4216 return *this;
4217 }
4218
4227 UniTensor Pow(const double &p) const;
4228
4237 UniTensor &Pow_(const double &p);
4238
4239 bool elem_exists(const std::vector<cytnx_uint64> &locator) const {
4240 return this->_impl->elem_exists(locator);
4241 }
4242
4248 template <class T>
4249 T get_elem(const std::vector<cytnx_uint64> &locator) const {
4250 return this->at<T>(locator);
4251 }
4252
4258 template <class T2>
4259 void set_elem(const std::vector<cytnx_uint64> &locator, const T2 &rc) {
4260 // cytnx_error_msg(true,"[ERROR] invalid type%s","\n");
4261 this->at(locator) = rc;
4262 }
4263
4269 void Save(const std::string &fname) const;
4270
4276 void Save(const char *fname) const;
4277
4285 static UniTensor Load(const std::string &fname);
4286
4294 static UniTensor Load(const char *fname);
4295
4306 UniTensor &truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim,
4307 const bool &by_label) {
4308 this->_impl->truncate_(bond_idx, dim, by_label);
4309 return *this;
4310 }
4311 UniTensor &truncate_(const std::string &bond_idx, const cytnx_uint64 &dim) {
4312 this->_impl->truncate_(bond_idx, dim);
4313 return *this;
4314 }
4315 UniTensor &truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim) {
4316 this->_impl->truncate_(bond_idx, dim);
4317 return *this;
4318 }
4329 UniTensor truncate(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim,
4330 const bool &by_label) const {
4331 UniTensor out = this->clone();
4332 out.truncate_(bond_idx, dim, by_label);
4333 return out;
4334 }
4335 UniTensor truncate(const std::string &bond_idx, const cytnx_uint64 &dim) const {
4336 UniTensor out = this->clone();
4337 out.truncate_(bond_idx, dim);
4338 return out;
4339 }
4340 UniTensor truncate(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim) const {
4341 UniTensor out = this->clone();
4342 out.truncate_(bond_idx, dim);
4343 return out;
4344 }
4345
4353 const std::vector<cytnx_uint64>& get_qindices(const cytnx_uint64 &bidx) const{
4354 return this->_impl->get_qindices(bidx);
4355 }
4363 std::vector<cytnx_uint64>& get_qindices(const cytnx_uint64 &bidx){
4364 return this->_impl->get_qindices(bidx);
4365 }
4366
4367
4368
4376 return this->_impl->get_itoi();
4377 }
4379 return this->_impl->get_itoi();
4380 }
4381
4382
4383
4385 void _Load(std::fstream &f);
4386 void _Save(std::fstream &f) const;
4388
4389 }; // class UniTensor
4390
4392 std::ostream &operator<<(std::ostream &os, const UniTensor &in);
4394
4407 UniTensor Contract(const UniTensor &inL, const UniTensor &inR, const bool &cacheL = false,
4408 const bool &cacheR = false);
4409
4422 UniTensor Contracts(const std::vector<UniTensor> &TNs, const std::string &order, const bool &optimal);
4423
4425 void _resolve_CT(std::vector<UniTensor> &TNlist);
4426 template <class... T>
4427 void _resolve_CT(std::vector<UniTensor> &TNlist, const UniTensor &in, const T &...args) {
4428 TNlist.push_back(in);
4429 _resolve_CT(TNlist, args...);
4430 }
4432
4444 template <class... T>
4445 UniTensor Contracts(const UniTensor &in, const T &...args, const std::string &order, const bool &optimal) {
4446 std::vector<UniTensor> TNlist;
4447 _resolve_CT(TNlist, in, args...);
4448 return Contracts(TNlist, order, optimal);
4449 }
4450
4451} // namespace cytnx
4452#endif
A class to represent a scalar.
Definition Scalar.hpp:2470
an tensor (multi-dimensional array)
Definition Tensor.hpp:345
void to_(const int &device)
move the current Tensor to the device.
Definition Tensor.hpp:869
Tensor contiguous_()
Make the Tensor contiguous by coalescing the memory (storage), inplacely.
Definition Tensor.hpp:952
unsigned int dtype() const
the dtype-id of the Tensor
Definition Tensor.hpp:768
Tensor contiguous() const
Make the Tensor contiguous by coalescing the memory (storage).
Definition Tensor.hpp:932
T & at(const std::vector< cytnx_uint64 > &locator)
[C++ only] get an element at specific location.
Definition Tensor.hpp:1101
Tensor clone() const
return a clone of the current Tensor.
Definition Tensor.hpp:820
void set(const std::vector< cytnx::Accessor > &accessors, const Tensor &rhs)
set elements with the input Tensor using Accessor (C++ API) / slices (python API)
Definition Tensor.hpp:1234
Tensor Norm() const
the Norm member function. Same as linalg::Norm(const Tensor &Tin), where Tin is the current Tensor.
Definition Tensor.cpp:1336
Tensor astype(const int &new_type) const
return a new Tensor that cast to different dtype.
Definition Tensor.hpp:1068
const bool & is_contiguous() const
Definition Tensor.hpp:871
Tensor & Conj_()
the Conj_ member function. Same as cytnx::linalg::Conj_(Tensor &Tin), where Tin is the current Tensor...
Definition Tensor.cpp:1325
int device() const
the device-id of the Tensor
Definition Tensor.hpp:775
Tensor get(const std::vector< cytnx::Accessor > &accessors) const
get elements using Accessor (C++ API) / slices (python API)
Definition Tensor.hpp:1202
const std::vector< cytnx_uint64 > & shape() const
the shape of the Tensor
Definition Tensor.hpp:795
An Enhanced tensor specifically designed for physical Tensor network simulation.
Definition UniTensor.hpp:2449
UniTensor to(const int &device) const
move the current UniTensor to the assigned device.
Definition UniTensor.hpp:2975
UniTensor & operator*=(const UniTensor &rhs)
The multiplication assignment operator of the UniTensor.
Definition UniTensor.hpp:3947
void Init(const Tensor &in_tensor, const bool &is_diag=false, const cytnx_int64 &rowrank=-1, const std::string &name="")
Initialize a UniTensor with cytnx::Tensor.
Definition UniTensor.hpp:2510
UniTensor relabels(const std::vector< cytnx_int64 > &new_labels) const
Definition UniTensor.hpp:2996
std::vector< Tensor > & get_blocks_(const bool &silent=false)
Definition UniTensor.hpp:3424
void print_block(const cytnx_int64 &idx, const bool &full_info=true) const
Given a index and print out the corresponding block of the UniTensor.
Definition UniTensor.hpp:3191
UniTensor & operator/=(const UniTensor &rhs)
The division assignment operator of the UniTensor.
Definition UniTensor.hpp:3927
T & item()
Definition UniTensor.hpp:2819
bool is_contiguous() const
To tell whether the UniTensor is contiguous.
Definition UniTensor.hpp:2910
T get_elem(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:4249
UniTensor Div(const UniTensor &rhs) const
The division function of the UniTensor.
Definition UniTensor.cpp:25
const Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:3384
UniTensor & set_label(const cytnx_int64 &idx, const cytnx_int64 &new_label)
Definition UniTensor.hpp:2693
std::vector< cytnx_uint64 > & get_qindices(const cytnx_uint64 &bidx)
get the q-indices on each leg for the [bidx]-th block
Definition UniTensor.hpp:4363
Tensor & get_block_(const std::vector< cytnx_int64 > &qnum, const bool &force=false)
Get the shared view of block for the given quantum number.
Definition UniTensor.hpp:3351
UniTensor & set_label(const cytnx_int64 &idx, const char *new_label)
Definition UniTensor.hpp:2713
UniTensor & operator+=(const UniTensor &rhs)
The addition assignment operator of the UniTensor.
Definition UniTensor.hpp:3887
void to_dense_()
Convert the UniTensor to non-diagonal form, inplacely.
Definition UniTensor.hpp:3512
UniTensor reshape(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor.
Definition UniTensor.hpp:3477
std::vector< Tensor > get_blocks() const
Get all the blocks of the UniTensor.
Definition UniTensor.hpp:3408
UniTensor permute(const std::initializer_list< char * > &mapper, const cytnx_int64 &rowrank=-1) const
Definition UniTensor.hpp:3114
bool is_tag() const
Definition UniTensor.hpp:2917
cytnx_int64 get_index(std::string lbl) const
Get the index of an desired label string.
Definition UniTensor.hpp:2938
std::string uten_type_str() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor in 'string' form.
Definition UniTensor.hpp:2903
void put_block(const Tensor &in, const std::vector< cytnx_int64 > &qnum, const bool &force)
Put the block into the UniTensor with given quantum number.
Definition UniTensor.hpp:3444
UniTensor truncate(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim, const bool &by_label) const
Definition UniTensor.hpp:4329
UniTensor(const std::vector< Bond > &bonds, const std::vector< std::string > &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const bool &is_diag=false, const std::string &name="")
Construct a UniTensor.
Definition UniTensor.hpp:2536
static UniTensor Load(const std::string &fname)
load a UniTensor from file
Definition UniTensor.cpp:158
UniTensor & tag()
Definition UniTensor.hpp:4214
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force=false)
Definition UniTensor.hpp:3541
UniTensor get(const std::vector< Accessor > &accessors) const
Definition UniTensor.hpp:3463
UniTensor & set_label(const std::string &old_label, const std::string &new_label)
set a new label for bond to replace one of the current label.
Definition UniTensor.hpp:2726
UniTensor(const Tensor &in_tensor, const bool &is_diag=false, const cytnx_int64 &rowrank=-1, const std::string &name="")
Construct a UniTensor from a cytnx::Tensor.
Definition UniTensor.hpp:2488
void Save(const std::string &fname) const
save a UniTensor to file
Definition UniTensor.cpp:138
UniTensor & operator-=(const Scalar &rhs)
The subtraction assignment operator for a given scalar.
Definition UniTensor.hpp:3977
cytnx_uint64 rowrank() const
Return the row rank of the UniTensor.
Definition UniTensor.hpp:2854
Tensor Norm() const
Return the norm of the UniTensor.
Definition UniTensor.hpp:3870
UniTensor & set_labels(const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:2798
UniTensor & Sub_(const Scalar &rhs)
The subtraction function for a given scalar.
Definition UniTensor.hpp:3722
UniTensor & operator/=(const Scalar &rhs)
The division assignment operator for a given scalar.
Definition UniTensor.hpp:3992
const bool & is_braket_form() const
Definition UniTensor.hpp:2925
void set_elem(const std::vector< cytnx_uint64 > &locator, const T2 &rc)
Definition UniTensor.hpp:4259
UniTensor relabel(const cytnx_int64 &inx, const cytnx_int64 &new_label, const bool &by_label=false) const
Definition UniTensor.hpp:3032
std::vector< cytnx_uint64 > shape() const
Get the shape of the UniTensor.
Definition UniTensor.hpp:2955
UniTensor to_dense()
Convert the UniTensor to non-diagonal form.
Definition UniTensor.hpp:3502
UniTensor relabels(const std::initializer_list< char * > &new_lbls) const
Definition UniTensor.hpp:3015
UniTensor truncate(const std::string &bond_idx, const cytnx_uint64 &dim) const
Definition UniTensor.hpp:4335
void reshape_(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor, inplacely.
Definition UniTensor.hpp:3487
const Tensor & get_block_(const std::vector< cytnx_int64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:3376
UniTensor & set_labels(const std::vector< std::string > &new_labels)
Set new labels for all the bonds.
Definition UniTensor.hpp:2790
void permute_(const std::vector< std::string > &mapper, const cytnx_int64 &rowrank=-1)
permute the lags of the UniTensor, inplacely.
Definition UniTensor.hpp:3142
std::string name() const
Return the name of the UniTensor.
Definition UniTensor.hpp:2882
void Init(const std::vector< Bond > &bonds, const std::vector< cytnx_int64 > &in_labels, const cytnx_int64 &rowrank=-1, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const bool &is_diag=false, const std::string &name="")
Definition UniTensor.hpp:2649
UniTensor & Add_(const Scalar &rhs)
The addition function for a given scalar.
Definition UniTensor.hpp:3692
UniTensor Trace(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label) const
Definition UniTensor.hpp:4120
UniTensor & Trace_(const std::string &a, const std::string &b)
Take the partial trance to the UniTensor, inplacely.
Definition UniTensor.hpp:4137
UniTensor & truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim)
Definition UniTensor.hpp:4315
std::vector< Bond > getTotalQnums(const bool physical=false) const
Get the total quantum number of the UniTensor.
Definition UniTensor.hpp:3580
Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:3271
UniTensor Trace(const std::string &a, const std::string &b) const
Take the partial trance to the UniTensor.
Definition UniTensor.hpp:4093
bool same_data(const UniTensor &rhs) const
Definition UniTensor.hpp:3591
UniTensor astype(const unsigned int &dtype) const
Return a new UniTensor that cast to different data type.
Definition UniTensor.hpp:3067
UniTensor Transpose() const
Take the transpose of the UniTensor.
Definition UniTensor.hpp:4043
Tensor & get_block_(const std::vector< cytnx_uint64 > &qnum, const bool &force=false)
Definition UniTensor.hpp:3366
UniTensor & set_label(const char *old_label, const std::string &new_label)
Definition UniTensor.hpp:2734
UniTensor & Dagger_()
Take the conjugate transpose to the UniTensor, inplacely.
Definition UniTensor.hpp:4209
void print_diagram(const bool &bond_info=false)
Plot the diagram of the UniTensor.
Definition UniTensor.hpp:3178
std::vector< Bond > & bonds()
Definition UniTensor.hpp:2949
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition UniTensor.hpp:3210
UniTensor & set_label(const cytnx_int64 &idx, const std::string &new_label)
Set a new label for bond at the assigned index.
Definition UniTensor.hpp:2705
std::vector< std::vector< cytnx_int64 > > get_blocks_qnums() const
Definition UniTensor.hpp:3587
UniTensor contiguous() const
Make the UniTensor contiguous by coalescing the memory (storage).
Definition UniTensor.hpp:3162
Tensor get_block(const cytnx_uint64 &idx=0) const
Get the block of the UniTensor for a given index.
Definition UniTensor.hpp:3292
const T & at(const std::vector< cytnx_uint64 > &locator) const
Get an element at specific location.
Definition UniTensor.hpp:3236
UniTensor & operator*=(const Scalar &rhs)
The multiplication assignment operator for a given scalar.
Definition UniTensor.hpp:4007
void contiguous_()
Make the UniTensor contiguous by coalescing the memory (storage), inplacely.
Definition UniTensor.hpp:3172
UniTensor normalize() const
normalize the current UniTensor instance with 2-norm.
Definition UniTensor.hpp:4066
UniTensor & set_labels(const std::vector< cytnx_int64 > &new_labels)
change a new label for bond with original label.
Definition UniTensor.hpp:2779
std::vector< Symmetry > syms() const
Return the symmetry type of the UniTensor.
Definition UniTensor.hpp:2924
UniTensor & Mul_(const UniTensor &rhs)
The multiplcation function of the UniTensor.
Definition UniTensor.hpp:3635
UniTensor & Trace_(const cytnx_int64 &a, const cytnx_int64 &b, const bool &by_label)
Definition UniTensor.hpp:4178
UniTensor permute(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1, const bool &by_label=false) const
permute the lags of the UniTensor
Definition UniTensor.hpp:3087
void put_block_(Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index, inplacely.
Definition UniTensor.hpp:3453
UniTensor & set_label(const cytnx_int64 &idx, const cytnx_int64 &new_label, const bool &by_label)
Definition UniTensor.hpp:2678
void combineBonds(const std::vector< std::string > &indicators, const bool &force=false)
Combine the sevral bonds of the UniTensor.
Definition UniTensor.hpp:3532
void put_block_(Tensor &in, const std::vector< cytnx_int64 > &qnum, const bool &force)
Put the block into the UniTensor with given quantum number, inplacely.
Definition UniTensor.hpp:3460
UniTensor relabel(const std::string &old_label, const std::string &new_label) const
rebable the lags in the UniTensor by a given label.
Definition UniTensor.hpp:3055
UniTensor & normalize_()
normalize the UniTensor, inplacely.
Definition UniTensor.hpp:4078
UniTensor & truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim, const bool &by_label)
Definition UniTensor.hpp:4306
bool is_diag() const
To tell whether the UniTensor is in diagonal form.
Definition UniTensor.hpp:2916
int device() const
Return the device of the UniTensor.
Definition UniTensor.hpp:2876
UniTensor & Pow_(const double &p)
Power function.
Definition UniTensor.cpp:12
void set(const std::vector< Accessor > &accessors, const Tensor &rhs)
Definition UniTensor.hpp:3468
std::string dtype_str() const
Return the data type of the UniTensor in 'string' form.
Definition UniTensor.hpp:2889
UniTensor & operator+=(const Scalar &rhs)
The addition assignment operator for a given scalar.
Definition UniTensor.hpp:3962
UniTensor & Div_(const UniTensor &rhs)
The division function of the UniTensor.
Definition UniTensor.hpp:3677
UniTensor & Div_(const Scalar &rhs)
The division function for a given scalar.
Definition UniTensor.hpp:3737
cytnx_uint64 rank() const
Return the rank of the UniTensor.
Definition UniTensor.hpp:2848
void group_basis_()
Definition UniTensor.hpp:3193
void to_(const int &device)
move the current UniTensor to the assigned device (inplace).
Definition UniTensor.hpp:2964
UniTensor & Trace_(const cytnx_int64 &a=0, const cytnx_int64 &b=1)
Take the partial trance to the UniTensor, inplacely.
Definition UniTensor.hpp:4159
UniTensor & set_name(const std::string &in)
Set the name of the UniTensor.
Definition UniTensor.hpp:2666
UniTensor Trace(const cytnx_int64 &a=0, const cytnx_int64 &b=1) const
Take the partial trance to the UniTensor.
Definition UniTensor.hpp:4108
UniTensor & Add_(const UniTensor &rhs)
The addition function of the UniTensor.
Definition UniTensor.hpp:3614
Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qnum, const bool &force=false)
Definition UniTensor.hpp:3358
UniTensor & set_label(const std::string &old_label, const char *new_label)
Definition UniTensor.hpp:2742
UniTensor permute(const std::vector< std::string > &mapper, const cytnx_int64 &rowrank=-1) const
permute the lags of the UniTensor by labels
Definition UniTensor.hpp:3105
unsigned int dtype() const
Return the data type of the UniTensor.
Definition UniTensor.hpp:2861
UniTensor Pow(const double &p) const
Power function.
Definition UniTensor.cpp:11
UniTensor & Mul_(const Scalar &rhs)
The multiplication function for a given scalar.
Definition UniTensor.hpp:3707
UniTensor & operator-=(const UniTensor &rhs)
The subtraction assignment operator of the UniTensor.
Definition UniTensor.hpp:3907
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force, const bool &by_label)
Definition UniTensor.hpp:3519
UniTensor & set_label(const char *old_label, const char *new_label)
Definition UniTensor.hpp:2750
bool is_blockform() const
Definition UniTensor.hpp:2956
UniTensor group_basis() const
Definition UniTensor.hpp:3197
UniTensor Dagger() const
Take the conjugate transpose to the UniTensor.
Definition UniTensor.hpp:4197
const std::vector< Tensor > & get_blocks_(const bool &silent=false) const
Get all the blocks of the UniTensor, inplacely.
Definition UniTensor.hpp:3416
bool elem_exists(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:4239
UniTensor(const std::vector< Bond > &bonds, const std::vector< cytnx_int64 > &in_labels, const cytnx_int64 &rowrank=-1, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const bool &is_diag=false, const std::string &name="")
Definition UniTensor.hpp:2558
UniTensor & Sub_(const UniTensor &rhs)
The subtraction function of the UniTensor.
Definition UniTensor.hpp:3656
UniTensor contract(const UniTensor &inR, const bool &mv_elem_self=false, const bool &mv_elem_rhs=false) const
Contract the UniTensor with common labels.
Definition UniTensor.hpp:3565
void put_block(const Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index.
Definition UniTensor.hpp:3434
const Tensor & get_block_(const cytnx_uint64 &idx=0) const
Get the shared view of block for the given index.
Definition UniTensor.hpp:3332
UniTensor & truncate_(const std::string &bond_idx, const cytnx_uint64 &dim)
Definition UniTensor.hpp:4311
UniTensor relabel(const cytnx_int64 &inx, const std::string &new_label) const
rebable the lags in the UniTensor by given index.
Definition UniTensor.hpp:3044
UniTensor Mul(const UniTensor &rhs) const
The multiplication function of the UniTensor.
Definition UniTensor.cpp:28
const std::vector< cytnx_uint64 > & get_qindices(const cytnx_uint64 &bidx) const
get the q-indices on each leg for the [bidx]-th block
Definition UniTensor.hpp:4353
const std::vector< std::string > & labels() const
Return the labels of the UniTensor.
Definition UniTensor.hpp:2931
Tensor get_block(const std::vector< cytnx_int64 > &qnum, const bool &force=false) const
Get the block of the UniTensor for the given quantun number.
Definition UniTensor.hpp:3303
const std::vector< Bond > & bonds() const
Get the bonds of the UniTensor.
Definition UniTensor.hpp:2944
UniTensor truncate(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim) const
Definition UniTensor.hpp:4340
UniTensor & Transpose_()
Take the transpose of the UniTensor, inplacely.
Definition UniTensor.hpp:4055
UniTensor clone() const
Clone (deep copy) the UniTensor.
Definition UniTensor.hpp:2985
vec2d< cytnx_uint64 > & get_itoi()
Definition UniTensor.hpp:4378
void print_blocks(const bool &full_info=true) const
Print all of the blocks in the UniTensor.
Definition UniTensor.hpp:3184
Scalar::Sproxy item() const
Definition UniTensor.hpp:2829
const vec2d< cytnx_uint64 > & get_itoi() const
get the q-indices on each leg for all the blocks
Definition UniTensor.hpp:4375
std::string device_str() const
Return the device of the UniTensor in 'string' form.
Definition UniTensor.hpp:2896
UniTensor relabels(const std::vector< std::string > &new_labels) const
rebables all of the labels in UniTensor.
Definition UniTensor.hpp:3006
UniTensor Sub(const UniTensor &rhs) const
The subtraction function of the UniTensor.
Definition UniTensor.cpp:22
void Init(const std::vector< Bond > &bonds, const std::vector< std::string > &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const bool &is_diag=false, const std::string &name="")
Initialize the UniTensor with the given arguments.
Definition UniTensor.hpp:2597
UniTensor & Conj_()
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:4032
cytnx_uint64 Nblocks() const
Return the blocks' number.
Definition UniTensor.hpp:2842
Tensor get_block(const std::vector< cytnx_uint64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:3321
UniTensor Conj()
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:4019
const Tensor & get_block_(const std::vector< cytnx_uint64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:3393
UniTensor Add(const UniTensor &rhs) const
The addition function of the UniTensor.
Definition UniTensor.cpp:16
UniTensor & set_rowrank(const cytnx_uint64 &new_rowrank)
Set the row rank of the UniTensor.
Definition UniTensor.hpp:2813
void permute_(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1, const bool &by_label=false)
permute the lags of the UniTensor, inplacely.
Definition UniTensor.hpp:3131
Tensor get_block(const std::initializer_list< cytnx_int64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:3311
const Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:3256
int uten_type() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor.
Definition UniTensor.hpp:2869
Tensor & get_block_(const cytnx_uint64 &idx=0)
Definition UniTensor.hpp:3340
#define cytnx_warning_msg(is_true, format,...)
Definition cytnx_error.hpp:40
#define cytnx_error_msg(is_true, format,...)
Definition cytnx_error.hpp:16
cytnx::UniTensor Trace(const cytnx::UniTensor &Tin, const cytnx_int64 &a=0, const cytnx_int64 &b=1)
Tensor Conj(const Tensor &Tin)
Conjugate all the element in Tensor.
Tensor Norm(const Tensor &Tl)
Calculate the norm of a tensor.
void Conj_(Tensor &Tin)
inplace perform Conjugate on all the element in Tensor.
Definition Accessor.hpp:12
Device_class Device
data on which devices.
Definition Device.cpp:140
double cytnx_double
Definition Type.hpp:43
UniTensorType_class UTenType
UniTensor type.
Definition UniTensor_base.cpp:24
uint32_t cytnx_uint32
Definition Type.hpp:46
std::complex< double > cytnx_complex128
Definition Type.hpp:53
float cytnx_float
Definition Type.hpp:44
std::ostream & operator<<(std::ostream &os, const Scalar &in)
The stream operator for Scalar objects.
Definition Scalar.cpp:10
int16_t cytnx_int16
Definition Type.hpp:50
std::complex< float > cytnx_complex64
Definition Type.hpp:52
int32_t cytnx_int32
Definition Type.hpp:49
UniTensor Contract(const UniTensor &inL, const UniTensor &inR, const bool &cacheL=false, const bool &cacheR=false)
Contract two UniTensor by tracing the ranks with common labels.
Definition UniTensor_base.cpp:601
uint16_t cytnx_uint16
Definition Type.hpp:47
void _resolve_CT(std::vector< UniTensor > &TNlist)
Definition UniTensor_base.cpp:607
uint64_t cytnx_uint64
Definition Type.hpp:45
int64_t cytnx_int64
Definition Type.hpp:48
std::vector< std::vector< T > > vec2d
Definition Type.hpp:40
UniTensor Contracts(const std::vector< UniTensor > &TNs, const std::string &order, const bool &optimal)
Contract multiple UniTensor by tracing the ranks with common labels with pairwise operation.
Definition UniTensor_base.cpp:608
Type_class Type
data type
Definition Type.cpp:23
tmp
Definition sp.py:8