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
22// namespace cytnx{
23namespace cytnx {
24 using namespace cytnx;
26 class UniTensorType_class {
27 public:
28 enum : int {
29 Void = -99,
30 Dense = 0,
31 Sparse = 1,
32 Block = 2,
33 };
34 std::string getname(const int &ut_type);
35 };
37
53 extern UniTensorType_class UTenType;
54
56 // class DenseUniTensor;
57 // class SparseUniTensor;
58 class UniTensor_base : public intrusive_ptr_base<UniTensor_base> {
59 public:
60 int uten_type_id; // the unitensor type id.
61 bool _is_braket_form;
62 bool _is_tag;
63 bool _is_diag;
64 cytnx_int64 _rowrank;
65 std::string _name;
66 std::vector<std::string> _labels;
67 std::vector<Bond> _bonds;
68
69 bool _update_braket() {
70 if (_bonds.size() == 0) return false;
71
72 if (this->_bonds[0].type() != bondType::BD_REG) {
73 // check:
74 for (unsigned int i = 0; i < this->_bonds.size(); i++) {
75 if (i < this->_rowrank) {
76 if (this->_bonds[i].type() != bondType::BD_KET) return false;
77 } else {
78 if (this->_bonds[i].type() != bondType::BD_BRA) return false;
79 }
80 }
81 return true;
82 } else {
83 return false;
84 }
85 }
86
87 friend class UniTensor; // allow wrapper to access the private elems
88 friend class DenseUniTensor;
89 // friend class SparseUniTensor;
90 friend class BlockUniTensor;
91
92 UniTensor_base()
93 : _is_tag(false),
94 _name(std::string("")),
95 _is_braket_form(false),
96 _rowrank(0),
97 _is_diag(false),
98 uten_type_id(UTenType.Void){};
99
100 // copy&assignment constr., use intrusive_ptr's !!
101 UniTensor_base(const UniTensor_base &rhs);
102 UniTensor_base &operator=(UniTensor_base &rhs);
103
104 cytnx_uint64 rowrank() const { return this->_rowrank; }
105 bool is_diag() const { return this->_is_diag; }
106 const bool &is_braket_form() const { return this->_is_braket_form; }
107 const bool &is_tag() const { return this->_is_tag; }
108 const std::vector<std::string> &labels() const { return this->_labels; }
115 cytnx_int64 get_index(std::string lbl) const {
116 std::vector<std::string> lbls = this->_labels;
117 for (cytnx_uint64 i = 0; i < lbls.size(); i++) {
118 if (lbls[i] == lbl) return i;
119 }
120 return -1;
121 }
122 const std::vector<Bond> &bonds() const { return this->_bonds; }
123 std::vector<Bond> &bonds() { return this->_bonds; }
124 const std::string &name() const { return this->_name; }
125 cytnx_uint64 rank() const { return this->_labels.size(); }
126 void set_name(const std::string &in) { this->_name = in; }
127
138 void set_label(const std::string &oldlbl, const std::string &new_label) {
139 cytnx_int64 idx;
140 auto res = std::find(this->_labels.begin(), this->_labels.end(), oldlbl);
141 cytnx_error_msg(res == this->_labels.end(), "[ERROR] label %s not exists.\n", oldlbl.c_str());
142 idx = std::distance(this->_labels.begin(), res);
143
144 cytnx_error_msg(idx >= this->_labels.size(), "[ERROR] index exceed the rank of UniTensor%s",
145 "\n");
146 // check in:
147 bool is_dup = false;
148 for (cytnx_uint64 i = 0; i < this->_labels.size(); i++) {
149 if (i == idx) continue;
150 if (new_label == this->_labels[i]) {
151 is_dup = true;
152 break;
153 }
154 }
155 cytnx_error_msg(is_dup, "[ERROR] alreay has a label that is the same as the input label%s",
156 "\n");
157 this->_labels[idx] = new_label;
158 }
159 void set_label(const cytnx_int64 &inx, const std::string &new_label) {
160 cytnx_error_msg(inx < 0, "[ERROR] index is negative%s", "\n");
161 cytnx_error_msg(inx >= this->_labels.size(), "[ERROR] index exceed the rank of UniTensor%s",
162 "\n");
163 // check in:
164 bool is_dup = false;
165 for (cytnx_uint64 i = 0; i < this->_labels.size(); i++) {
166 if (i == inx) continue;
167 if (new_label == this->_labels[i]) {
168 is_dup = true;
169 break;
170 }
171 }
172 cytnx_error_msg(is_dup, "[ERROR] alreay has a label that is the same as the input label%s",
173 "\n");
174 this->_labels[inx] = new_label;
175 }
176
177 void set_labels(const std::vector<std::string> &new_labels);
178
179 /*
180 template<class T>
181 T get_elem(const std::vector<cytnx_uint64> &locator) const{
182 if(this->is_blockform()){
183 if(this->elem_exists(locator)){
184 T aux; // [workaround] use aux to dispatch.
185 return this->at_for_sparse(locator,aux);
186 }else{
187 return 0;
188 }
189 }else{
190 return this->at<T>(locator);
191 }
192 }
193 template<class T>
194 void set_elem(const std::vector<cytnx_uint64> &locator, const T &input){
195 if(this->uten_type()==UTenType.Sparse){
196 if(this->elem_exists(locator)){
197 T aux;
198 this->at_for_sparse(locator,aux) = input;
199 }else{
200 cytnx_error_msg(true,"[ERROR][SparseUniTensor] invalid location. break qnum
201 block.%s","\n");
202 }
203 }else{
204 this->at<T>(locator) = input;
205 }
206 }
207 */
208
209 int uten_type() { return this->uten_type_id; }
210 std::string uten_type_str() { return UTenType.getname(this->uten_type_id); }
211
213
214 // string labels!
215 virtual void Init(const std::vector<Bond> &bonds,
216 const std::vector<std::string> &in_labels = {},
217 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
218 const int &device = Device.cpu, const bool &is_diag = false,
219 const bool &no_alloc = false, const std::string &name = "");
220
221 virtual void Init_by_Tensor(const Tensor &in, const bool &is_diag = false,
222 const cytnx_int64 &rowrank = -1, const std::string &name = "");
223 virtual std::vector<cytnx_uint64> shape() const;
224 virtual bool is_blockform() const;
225 virtual bool is_contiguous() const;
226 virtual void to_(const int &device);
227 virtual boost::intrusive_ptr<UniTensor_base> to(const int &device);
228 virtual boost::intrusive_ptr<UniTensor_base> clone() const;
229 virtual unsigned int dtype() const;
230 virtual int device() const;
231 virtual std::string dtype_str() const;
232 virtual std::string device_str() const;
233 virtual void set_rowrank(const cytnx_uint64 &new_rowrank);
234
235 virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
236 const cytnx_int64 &rowrank = -1);
237 virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
238 const cytnx_int64 &rowrank = -1);
239 // virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
240 // const cytnx_int64 &rowrank = -1);
241
242 virtual void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
243 virtual void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
244
245 // virtual void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank =
246 // -1);
247 virtual boost::intrusive_ptr<UniTensor_base> contiguous_();
248 virtual boost::intrusive_ptr<UniTensor_base> contiguous();
249 virtual void print_diagram(const bool &bond_info = false);
250 virtual void print_blocks(const bool &full_info = true) const;
251 virtual void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
252
253 virtual boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const;
254
255 virtual cytnx_uint64 Nblocks() const { return 0; };
256 virtual Tensor get_block(const cytnx_uint64 &idx = 0) const; // return a copy of block
257 virtual Tensor get_block(const std::vector<cytnx_int64> &qnum,
258 const bool &force) const; // return a copy of block
259
260 virtual const Tensor &get_block_(const cytnx_uint64 &idx = 0)
261 const; // return a share view of block, this only work for non-symm tensor.
262 virtual const Tensor &get_block_(const std::vector<cytnx_int64> &qnum,
263 const bool &force) const; // return a copy of block
264 virtual Tensor &get_block_(const cytnx_uint64 &idx = 0); // return a share view of block, this
265 // only work for non-symm tensor.
266 virtual Tensor &get_block_(const std::vector<cytnx_int64> &qnum,
267 const bool &force); // return a copy of block
268 virtual bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const;
269
270 virtual std::vector<Tensor> get_blocks() const;
271 virtual const std::vector<Tensor> &get_blocks_(const bool &) const;
272 virtual std::vector<Tensor> &get_blocks_(const bool &);
273
274 virtual void put_block(const Tensor &in, const cytnx_uint64 &idx = 0);
275 virtual void put_block_(Tensor &in, const cytnx_uint64 &idx = 0);
276 virtual void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum,
277 const bool &force);
278 virtual void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force);
279
280 // this will only work on non-symm tensor (DenseUniTensor)
281 virtual boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors);
282
283 // this will only work on non-symm tensor (DenseUniTensor)
284 virtual void set(const std::vector<Accessor> &accessors, const Tensor &rhs);
285
286 virtual void reshape_(const std::vector<cytnx_int64> &new_shape,
287 const cytnx_uint64 &rowrank = 0);
288 virtual boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
289 const cytnx_uint64 &rowrank = 0);
290 virtual boost::intrusive_ptr<UniTensor_base> to_dense();
291 virtual void to_dense_();
292 virtual void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
293 const bool &by_label);
294 virtual void combineBonds(const std::vector<std::string> &indicators,
295 const bool &force = false);
296 virtual void combineBonds(const std::vector<cytnx_int64> &indicators,
297 const bool &force = false);
298 virtual boost::intrusive_ptr<UniTensor_base> contract(
299 const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &mv_elem_self = false,
300 const bool &mv_elem_rhs = false);
301 virtual std::vector<Bond> getTotalQnums(const bool &physical = false);
302 virtual std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const;
303 virtual void Trace_(const std::string &a, const std::string &b);
304 virtual void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
305
306 virtual boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b);
307 virtual boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b);
308
309 virtual boost::intrusive_ptr<UniTensor_base> relabels(
310 const std::vector<std::string> &new_labels);
311 virtual void relabels_(const std::vector<std::string> &new_labels);
312
313 // virtual boost::intrusive_ptr<UniTensor_base> relabels(
314 // const std::vector<std::string> &old_labels, const std::vector<std::string> &new_labels);
315
316 // virtual void relabels_(
317 // const std::vector<std::string> &old_labels, const std::vector<std::string> &new_labels);
318
319 virtual boost::intrusive_ptr<UniTensor_base> relabel(const std::string &inx,
320 const std::string &new_label);
321
322 virtual boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
323 const std::string &new_label);
324
325 virtual void relabel_(const std::string &inx, const std::string &new_label);
326 virtual void relabel_(const cytnx_int64 &inx, const std::string &new_label);
327
328 virtual std::vector<Symmetry> syms() const;
329
330 // arithmetic
331 virtual void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
332 virtual void Add_(const Scalar &rhs);
333
334 virtual void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
335 virtual void Mul_(const Scalar &rhs);
336
337 virtual void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
338 virtual void Sub_(const Scalar &rhs);
339 virtual void lSub_(const Scalar &lhs);
340
341 virtual void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
342 virtual void Div_(const Scalar &rhs);
343 virtual void lDiv_(const Scalar &lhs);
344
345 virtual Tensor Norm() const;
346 virtual boost::intrusive_ptr<UniTensor_base> normalize();
347 virtual void normalize_();
348
349 virtual boost::intrusive_ptr<UniTensor_base> Conj();
350 virtual void Conj_();
351
352 virtual boost::intrusive_ptr<UniTensor_base> Transpose();
353 virtual void Transpose_();
354
355 virtual boost::intrusive_ptr<UniTensor_base> Dagger();
356 virtual void Dagger_();
357
358 virtual void tag();
359
360 virtual void truncate_(const std::string &bond_idx, const cytnx_uint64 &dim);
361 virtual void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim);
362
363 virtual bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
364
365 // this a workaround, as virtual function cannot template.
366 virtual Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator);
367 virtual const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const;
368
369 virtual cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
370 const cytnx_complex128 &aux);
371 virtual cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
372 const cytnx_complex64 &aux);
373 virtual cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
374 const cytnx_double &aux);
375 virtual cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
376 const cytnx_float &aux);
377 virtual cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
378 const cytnx_uint64 &aux);
379 virtual cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
380 const cytnx_int64 &aux);
381 virtual cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
382 const cytnx_uint32 &aux);
383 virtual cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
384 const cytnx_int32 &aux);
385 virtual cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
386 const cytnx_uint16 &aux);
387 virtual cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
388 const cytnx_int16 &aux);
389
390 virtual const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
391 const cytnx_complex128 &aux) const;
392 virtual const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
393 const cytnx_complex64 &aux) const;
394 virtual const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
395 const cytnx_double &aux) const;
396 virtual const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
397 const cytnx_float &aux) const;
398 virtual const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
399 const cytnx_uint64 &aux) const;
400 virtual const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
401 const cytnx_int64 &aux) const;
402 virtual const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
403 const cytnx_uint32 &aux) const;
404 virtual const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
405 const cytnx_int32 &aux) const;
406 virtual const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
407 const cytnx_uint16 &aux) const;
408 virtual const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
409 const cytnx_int16 &aux) const;
410
411 virtual void group_basis_();
412 virtual const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const;
413 virtual std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx);
414 virtual const vec2d<cytnx_uint64> &get_itoi() const;
415 virtual vec2d<cytnx_uint64> &get_itoi();
416
417 virtual void _save_dispatch(std::fstream &f) const;
418 virtual void _load_dispatch(std::fstream &f);
419
420 virtual ~UniTensor_base(){};
421 };
423
424 //======================================================================
426 class DenseUniTensor : public UniTensor_base {
427 protected:
428 public:
429 Tensor _block;
430 std::vector<Tensor> _interface_block; // this is serves as interface for get_blocks_();
431 DenseUniTensor *clone_meta() const {
432 DenseUniTensor *tmp = new DenseUniTensor();
433 tmp->_bonds = vec_clone(this->_bonds);
434 tmp->_labels = this->_labels;
435 tmp->_is_braket_form = this->_is_braket_form;
436 tmp->_rowrank = this->_rowrank;
437 tmp->_is_diag = this->_is_diag;
438 tmp->_name = this->_name;
439 tmp->_is_tag = this->_is_tag;
440 return tmp;
441 }
442 //------------------------------------------
443
444 DenseUniTensor() { this->uten_type_id = UTenType.Dense; };
445 friend class UniTensor; // allow wrapper to access the private elems
446 // virtual functions
447
448 // void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels = {},
449 // const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
450 // const int &device = Device.cpu, const bool &is_diag = false,
451 // const bool &no_alloc = false);
452
453 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
454 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
455 const int &device = Device.cpu, const bool &is_diag = false,
456 const bool &no_alloc = false, const std::string &name = "");
457 // this only work for non-symm tensor
458 void Init_by_Tensor(const Tensor &in_tensor, const bool &is_diag = false,
459 const cytnx_int64 &rowrank = -1, const std::string &name = "");
460 std::vector<cytnx_uint64> shape() const {
461 if (this->_is_diag) {
462 std::vector<cytnx_uint64> shape = this->_block.shape();
463 shape.push_back(shape[0]);
464 return shape;
465 } else {
466 return this->_block.shape();
467 }
468 }
469 bool is_blockform() const { return false; }
470 void to_(const int &device) { this->_block.to_(device); }
471 boost::intrusive_ptr<UniTensor_base> to(const int &device) {
472 if (this->device() == device) {
473 std::vector<Tensor> _interface_block; // this is serves as interface for get_blocks_();
474 return this;
475 } else {
476 boost::intrusive_ptr<UniTensor_base> out = this->clone();
477 out->to_(device);
478 return out;
479 }
480 }
481 void set_rowrank(const cytnx_uint64 &new_rowrank) {
482 cytnx_error_msg(new_rowrank > this->_labels.size(),
483 "[ERROR] rowrank cannot exceed the rank of UniTensor.%s", "\n");
484 if (this->is_diag()) {
485 cytnx_error_msg(new_rowrank != 1, "[ERROR] rowrank should be [==1] when is_diag =true!.%s",
486 "\n");
487 }
488
489 this->_rowrank = new_rowrank;
490 }
491
492 boost::intrusive_ptr<UniTensor_base> clone() const {
493 DenseUniTensor *tmp = this->clone_meta();
494 tmp->_block = this->_block.clone();
495 boost::intrusive_ptr<UniTensor_base> out(tmp);
496 return out;
497 };
498 bool is_contiguous() const { return this->_block.is_contiguous(); }
499 unsigned int dtype() const { return this->_block.dtype(); }
500 int device() const { return this->_block.device(); }
501 std::string dtype_str() const { return Type.getname(this->_block.dtype()); }
502 std::string device_str() const { return Device.getname(this->_block.device()); }
512 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
513 const cytnx_int64 &rowrank = -1);
514 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
515 const cytnx_int64 &rowrank = -1);
516
525 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
526 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
527
528 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &new_labels);
529 void relabels_(const std::vector<std::string> &new_labels);
530
531 // boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &old_labels,
532 // const std::vector<std::string> &new_labels); void relabels_(const std::vector<std::string>
533 // &old_labels, const std::vector<std::string> &new_labels);
534
545 boost::intrusive_ptr<UniTensor_base> relabel(const std::string &old_label,
546 const std::string &new_label);
547 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
548 const std::string &new_label);
549
550 void relabel_(const std::string &old_label, const std::string &new_label);
551 void relabel_(const cytnx_int64 &inx, const std::string &new_label);
552
553 boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const {
554 DenseUniTensor *tmp = this->clone_meta();
555 tmp->_block = this->_block.astype(dtype);
556 boost::intrusive_ptr<UniTensor_base> out(tmp);
557 return tmp;
558 }
559
560 std::vector<Symmetry> syms() const {
561 cytnx_error_msg(true, "[ERROR][DenseUniTensor] dense unitensor does not have symmetry.%s",
562 "\n");
563 return std::vector<Symmetry>();
564 }
565
566 boost::intrusive_ptr<UniTensor_base> contiguous_() {
567 this->_block.contiguous_();
568 return boost::intrusive_ptr<UniTensor_base>(this);
569 }
570 boost::intrusive_ptr<UniTensor_base> contiguous() {
571 // if contiguous then return self!
572 if (this->is_contiguous()) {
573 boost::intrusive_ptr<UniTensor_base> out(this);
574 return out;
575 } else {
576 DenseUniTensor *tmp = this->clone_meta();
577 tmp->_block = this->_block.contiguous();
578 boost::intrusive_ptr<UniTensor_base> out(tmp);
579 return out;
580 }
581 }
582 void print_diagram(const bool &bond_info = false);
583 void print_blocks(const bool &full_info = true) const;
584 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
585 Tensor get_block(const cytnx_uint64 &idx = 0) const { return this->_block.clone(); }
586
587 Tensor get_block(const std::vector<cytnx_int64> &qnum, const bool &force) const {
589 true, "[ERROR][DenseUniTensor] try to get_block() using qnum on a non-symmetry UniTensor%s",
590 "\n");
591 return Tensor();
592 }
593 // return a share view of block, this only work for non-symm tensor.
594 const Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force) const {
596 true,
597 "[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
598 "\n");
599 return this->_block;
600 }
601 Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force) {
603 true,
604 "[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
605 "\n");
606 return this->_block;
607 }
608
609 // return a share view of block, this only work for non-symm tensor.
610 Tensor &get_block_(const cytnx_uint64 &idx = 0) { return this->_block; }
611 // return a share view of block, this only work for non-symm tensor.
612 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const { return this->_block; }
613
614 cytnx_uint64 Nblocks() const { return 1; };
615 std::vector<Tensor> get_blocks() const {
616 std::vector<Tensor> out;
618 true, "[ERROR][DenseUniTensor] cannot use get_blocks(), use get_block() instead!%s", "\n");
619 return out; // this will not share memory!!
620 }
621 const std::vector<Tensor> &get_blocks_(const bool &silent = false) const {
623 true, "[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s",
624 "\n");
625 return this->_interface_block; // this will not share memory!!
626 }
627 std::vector<Tensor> &get_blocks_(const bool &silent = false) {
629 true, "[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s",
630 "\n");
631 return this->_interface_block; // this will not share memory!!
632 }
633
634 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
635 if (this->is_diag()) {
637 in.shape() != this->_block.shape(),
638 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
639 this->_block = in.clone();
640 } else {
642 in.shape() != this->shape(),
643 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
644 this->_block = in.clone();
645 }
646 }
647 // share view of the block
648 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) {
649 if (this->is_diag()) {
651 in.shape() != this->_block.shape(),
652 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
653 this->_block = in;
654 } else {
656 in.shape() != this->shape(),
657 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
658 this->_block = in;
659 }
660 }
661
662 void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force) {
664 true, "[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
665 "\n");
666 }
667 void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force) {
669 true, "[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
670 "\n");
671 }
672 // this will only work on non-symm tensor (DenseUniTensor)
673 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors) {
674 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
675 out->Init_by_Tensor(this->_block.get(accessors), false, 0); // wrapping around.
676 return out;
677 }
678 // this will only work on non-symm tensor (DenseUniTensor)
679 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
680 this->_block.set(accessors, rhs);
681 }
682
683 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0);
684 boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
685 const cytnx_uint64 &rowrank = 0);
686 boost::intrusive_ptr<UniTensor_base> to_dense();
687 void to_dense_();
697 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
698 const bool &by_label);
699 void combineBonds(const std::vector<std::string> &indicators, const bool &force = true);
700 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = true);
701 boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs,
702 const bool &mv_elem_self = false,
703 const bool &mv_elem_rhs = false);
704 std::vector<Bond> getTotalQnums(const bool &physical = false) {
705 cytnx_error_msg(true, "[ERROR][DenseUniTensor] %s",
706 "getTotalQnums can only operate on UniTensor with symmetry.\n");
707 return std::vector<Bond>();
708 }
709
710 std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const {
711 cytnx_error_msg(true, "[ERROR][DenseUniTensor] %s",
712 "get_blocks_qnums can only operate on UniTensor with symmetry.\n");
713 return std::vector<std::vector<cytnx_int64>>();
714 }
715
716 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const {
717 if (rhs->uten_type() != UTenType.Dense) return false;
718
719 return this->get_block_().same_data(rhs->get_block_());
720 }
721
722 ~DenseUniTensor(){};
723
724 // arithmetic
725 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
726 void Add_(const Scalar &rhs);
727
728 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
729 void Mul_(const Scalar &rhs);
730
731 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
732 void Sub_(const Scalar &rhs);
733 void lSub_(const Scalar &lhs);
734
735 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
736 void Div_(const Scalar &rhs);
737 void lDiv_(const Scalar &lhs);
738
739 void Conj_() { this->_block.Conj_(); };
740
741 boost::intrusive_ptr<UniTensor_base> Conj() {
742 boost::intrusive_ptr<UniTensor_base> out = this->clone();
743 out->Conj_();
744 return out;
745 }
746
747 boost::intrusive_ptr<UniTensor_base> Transpose() {
748 boost::intrusive_ptr<UniTensor_base> out = this->clone();
749 out->Transpose_();
750 return out;
751 }
752 void Transpose_();
753
754 boost::intrusive_ptr<UniTensor_base> normalize() {
755 boost::intrusive_ptr<UniTensor_base> out = this->clone();
756 out->normalize_();
757 return out;
758 }
759 void normalize_();
760
761 boost::intrusive_ptr<UniTensor_base> Dagger() {
762 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
763 out->Transpose_();
764 return out;
765 }
766 void Dagger_() {
767 this->Conj_();
768 this->Transpose_();
769 }
779 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
780 void Trace_(const std::string &a, const std::string &b);
781 boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b) {
782 boost::intrusive_ptr<UniTensor_base> out = this->clone();
783 out->Trace_(a, b);
784 return out;
785 }
786 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b) {
787 boost::intrusive_ptr<UniTensor_base> out = this->clone();
788 out->Trace_(a, b);
789 return out;
790 }
791
792 Tensor Norm() const;
793
794 const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const {
796 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
797 "\n");
798 return Scalar::Sproxy();
799 }
800 const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
801 const cytnx_complex128 &aux) const {
803 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
804 "\n");
805 return cytnx_complex128(0, 0);
806 }
807 const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
808 const cytnx_complex64 &aux) const {
810 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
811 "\n");
812 return cytnx_complex64(0, 0);
813 }
814 const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
815 const cytnx_double &aux) const {
817 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
818 "\n");
819 return 0;
820 }
821 const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
822 const cytnx_float &aux) const {
824 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
825 "\n");
826 return 0;
827 }
828 const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
829 const cytnx_uint64 &aux) const {
831 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
832 "\n");
833 return 0;
834 }
835 const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
836 const cytnx_int64 &aux) const {
838 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
839 "\n");
840 return 0;
841 }
842 const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
843 const cytnx_uint32 &aux) const {
845 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
846 "\n");
847 return 0;
848 }
849 const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
850 const cytnx_int32 &aux) const {
852 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
853 "\n");
854 return 0;
855 }
856 const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
857 const cytnx_uint16 &aux) const {
859 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
860 "\n");
861 return 0;
862 }
863 const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
864 const cytnx_int16 &aux) const {
866 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
867 "\n");
868 return 0;
869 }
870
871 Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) {
873 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
874 "\n");
875 return Scalar::Sproxy();
876 }
877 cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
878 const cytnx_complex128 &aux) {
880 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
881 "\n");
882 return *(cytnx_complex128 *)nullptr;
883 }
884 cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
885 const cytnx_complex64 &aux) {
887 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
888 "\n");
889 return *(cytnx_complex64 *)nullptr;
890 }
891 cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux) {
893 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
894 "\n");
895 return *(cytnx_double *)nullptr;
896 }
897 cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux) {
899 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
900 "\n");
901 return *(cytnx_float *)nullptr;
902 }
903 cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux) {
905 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
906 "\n");
907 return *(cytnx_uint64 *)nullptr;
908 }
909 cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux) {
911 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
912 "\n");
913 return *(cytnx_int64 *)nullptr;
914 }
915 cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux) {
917 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
918 "\n");
919 return *(cytnx_uint32 *)nullptr;
920 }
921 cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux) {
923 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
924 "\n");
925 return *(cytnx_int32 *)nullptr;
926 }
927 cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux) {
929 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
930 "\n");
931 return *(cytnx_uint16 *)nullptr;
932 }
933 cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux) {
935 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
936 "\n");
937 return *(cytnx_int16 *)nullptr;
938 }
939
940 bool elem_exists(const std::vector<cytnx_uint64> &locator) const {
942 true, "[ERROR][DenseUniTensor] elem_exists can only be used on UniTensor with Symmetry.%s",
943 "\n");
944 }
945 void tag() {
946 if (!this->is_tag()) {
947 for (int i = 0; i < this->_rowrank; i++) {
948 this->_bonds[i].set_type(BD_KET);
949 }
950 for (int i = this->_rowrank; i < this->_bonds.size(); i++) {
951 this->_bonds[i].set_type(BD_BRA);
952 }
953 this->_is_tag = true;
954 this->_is_braket_form = this->_update_braket();
955 }
956 }
966 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim);
967 void truncate_(const std::string &bond_idx, const cytnx_uint64 &dim);
968
969 void group_basis_() {
970 cytnx_warning_msg(true, "[WARNING] group basis will not have any effect on DensUniTensor.%s",
971 "\n");
972 }
973
974 void _save_dispatch(std::fstream &f) const;
975 void _load_dispatch(std::fstream &f);
976
977 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
978 cytnx_error_msg(true, "[ERROR] get_qindices can only be unsed on UniTensor with Symmetry.%s",
979 "\n");
980 }
981 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
982 cytnx_error_msg(true, "[ERROR] get_qindices can only be unsed on UniTensor with Symmetry.%s",
983 "\n");
984 }
985
986 const vec2d<cytnx_uint64> &get_itoi() const {
987 cytnx_error_msg(true, "[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s",
988 "\n");
989 }
990 vec2d<cytnx_uint64> &get_itoi() {
991 cytnx_error_msg(true, "[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s",
992 "\n");
993 }
994
995 // end virtual function
996 };
998
999 //======================================================================
1001 class BlockUniTensor : public UniTensor_base {
1002 protected:
1003 public:
1004 std::vector<std::vector<cytnx_uint64>> _inner_to_outer_idx;
1005 std::vector<Tensor> _blocks;
1006 Tensor NullRefTensor; // this returns when access block is not exists!
1007
1008 // given an index list [loc], get qnums from this->_bonds[loc] and return the combined qnums
1009 // calculated from Symm object! this assume 1. symmetry are the same for each bond!
1010 // 2. total_qns are feeded with size len(symmetry)
1011 void _fx_get_total_fluxs(std::vector<cytnx_uint64> &loc, const std::vector<Symmetry> &syms,
1012 std::vector<cytnx_int64> &total_qns) {
1013 memset(&total_qns[0], 0, sizeof(cytnx_int64) * total_qns.size());
1014
1015 for (cytnx_int32 i = 0; i < syms.size(); i++) {
1016 if (this->_bonds[0].type() == BD_BRA)
1017 total_qns[i] = syms[0].reverse_rule(this->_bonds[0]._impl->_qnums[loc[0]][i]);
1018 else
1019 total_qns[i] = this->_bonds[0]._impl->_qnums[loc[0]][i];
1020
1021 for (auto j = 1; j < loc.size(); j++) {
1022 if (this->_bonds[j].type() == BD_BRA)
1023 total_qns[i] = syms[i].combine_rule(
1024 total_qns[i], syms[i].reverse_rule(this->_bonds[j]._impl->_qnums[loc[j]][i]));
1025 else {
1026 total_qns[i] =
1027 syms[i].combine_rule(total_qns[i], this->_bonds[j]._impl->_qnums[loc[j]][i]);
1028 }
1029 }
1030 }
1031 }
1032
1033 void _fx_locate_elem(cytnx_int64 &bidx, std::vector<cytnx_uint64> &loc_in_T,
1034 const std::vector<cytnx_uint64> &locator) const;
1035
1036 // internal function, grouping all duplicate qnums in all bonds
1037 void _fx_group_duplicates(const std::vector<cytnx_uint64> &dup_bond_idxs,
1038 const std::vector<std::vector<cytnx_uint64>> &idx_mappers);
1039
1040 void set_meta(BlockUniTensor *tmp, const bool &inner, const bool &outer) const {
1041 // outer meta
1042 if (outer) {
1043 tmp->_bonds = vec_clone(this->_bonds);
1044 tmp->_labels = this->_labels;
1045 tmp->_is_braket_form = this->_is_braket_form;
1046 tmp->_rowrank = this->_rowrank;
1047 tmp->_name = this->_name;
1048 }
1049
1050 tmp->_is_diag = this->_is_diag;
1051
1052 // inner meta
1053 if (inner) {
1054 tmp->_inner_to_outer_idx = this->_inner_to_outer_idx;
1055 }
1056 }
1057
1058 BlockUniTensor *clone_meta(const bool &inner, const bool &outer) const {
1059 BlockUniTensor *tmp = new BlockUniTensor();
1060 this->set_meta(tmp, inner, outer);
1061 return tmp;
1062 };
1063
1064 friend class UniTensor;
1065 BlockUniTensor() {
1066 this->uten_type_id = UTenType.Block;
1067 this->_is_tag = true;
1068 }
1069
1070 // virtual functions:
1071 // void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels = {},
1072 // const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1073 // const int &device = Device.cpu, const bool &is_diag = false,
1074 // const bool &no_alloc = false);
1075
1076 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1077 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1078 const int &device = Device.cpu, const bool &is_diag = false,
1079 const bool &no_alloc = false, const std::string &name = "");
1080
1081 void Init_by_Tensor(const Tensor &in_tensor, const bool &is_diag = false,
1082 const cytnx_int64 &rowrank = -1, const std::string &name = "") {
1084 true, "[ERROR][BlockUniTensor] cannot use Init_by_tensor() on a BlockUniTensor.%s", "\n");
1085 }
1086
1087 std::vector<cytnx_uint64> shape() const {
1088 std::vector<cytnx_uint64> out(this->_bonds.size());
1089 for (cytnx_uint64 i = 0; i < out.size(); i++) {
1090 out[i] = this->_bonds[i].dim();
1091 }
1092 return out;
1093 }
1094
1095 bool is_blockform() const { return true; }
1096 bool is_contiguous() const {
1097 bool out = true;
1098 for (int i = 0; i < this->_blocks.size(); i++) {
1099 out &= this->_blocks[i].is_contiguous();
1100 }
1101 return out;
1102 };
1103
1104 cytnx_uint64 Nblocks() const { return this->_blocks.size(); };
1105
1106 void to_(const int &device) {
1107 for (cytnx_uint64 i = 0; i < this->_blocks.size(); i++) {
1108 this->_blocks[i].to_(device);
1109 }
1110 };
1111
1112 boost::intrusive_ptr<UniTensor_base> to(const int &device) {
1113 if (this->device() == device) {
1114 return this;
1115 } else {
1116 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1117 out->to_(device);
1118 return out;
1119 }
1120 };
1121
1122 boost::intrusive_ptr<UniTensor_base> clone() const {
1123 BlockUniTensor *tmp = this->clone_meta(true, true);
1124 tmp->_blocks = vec_clone(this->_blocks);
1125 boost::intrusive_ptr<UniTensor_base> out(tmp);
1126 return out;
1127 };
1128
1129 unsigned int dtype() const {
1130#ifdef UNI_DEBUG
1131 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1132 "\n");
1133#endif
1134 return this->_blocks[0].dtype();
1135 };
1136 int device() const {
1137#ifdef UNI_DEBUG
1138 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1139 "\n");
1140#endif
1141 return this->_blocks[0].device();
1142 };
1143 std::string dtype_str() const {
1144#ifdef UNI_DEBUG
1145 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1146 "\n");
1147#endif
1148 return this->_blocks[0].dtype_str();
1149 };
1150 std::string device_str() const {
1151#ifdef UNI_DEBUG
1152 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1153 "\n");
1154#endif
1155 return this->_blocks[0].device_str();
1156 };
1157
1158 Tensor get_block(const cytnx_uint64 &idx = 0) const {
1159 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1160 "\n");
1161 return this->_blocks[idx].clone();
1162 };
1163
1164 // this one for Block will return the indicies!!
1165 Tensor get_block(const std::vector<cytnx_int64> &indices, const bool &force_return) const {
1166 cytnx_error_msg(indices.size() != this->rank(),
1167 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1168 "Tensor rank (number of legs).%s",
1169 "\n");
1170
1171 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1172
1173 // find if the indices specify exists!
1174 cytnx_int64 b = -1;
1175 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1176 if (inds == this->_inner_to_outer_idx[i]) {
1177 b = i;
1178 break;
1179 }
1180 }
1181
1182 if (b < 0) {
1183 if (force_return) {
1184 return NullRefTensor;
1185 } else {
1187 true,
1188 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, force_return=false, so "
1189 "error throws. \n If you want to return an empty block without error when block is "
1190 "not avaliable, set force_return=True.%s",
1191 "\n");
1192 }
1193 } else {
1194 return this->_blocks[b].clone();
1195 }
1196 }
1197
1198 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const {
1199 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1200 "\n");
1201 return this->_blocks[idx];
1202 };
1203
1204 Tensor &get_block_(const cytnx_uint64 &idx = 0) {
1205 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1206 "\n");
1207 return this->_blocks[idx];
1208 };
1209
1210 const Tensor &get_block_(const std::vector<cytnx_int64> &indices,
1211 const bool &force_return) const {
1212 cytnx_error_msg(indices.size() != this->rank(),
1213 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1214 "Tensor rank (number of legs).%s",
1215 "\n");
1216
1217 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1218
1219 // find if the indices specify exists!
1220 cytnx_int64 b = -1;
1221 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1222 if (inds == this->_inner_to_outer_idx[i]) {
1223 b = i;
1224 break;
1225 }
1226 }
1227
1228 if (b < 0) {
1229 if (force_return) {
1230 return this->NullRefTensor;
1231 } else {
1233 true,
1234 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, force_return=false, so "
1235 "error throws. \n If you want to return an empty block without error when block is "
1236 "not avaliable, set force_return=True.%s",
1237 "\n");
1238 }
1239 } else {
1240 return this->_blocks[b];
1241 }
1242 }
1243
1244 Tensor &get_block_(const std::vector<cytnx_int64> &indices, const bool &force_return) {
1245 cytnx_error_msg(indices.size() != this->rank(),
1246 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1247 "Tensor rank (number of legs).%s",
1248 "\n");
1249
1250 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1251
1252 // find if the indices specify exists!
1253 cytnx_int64 b = -1;
1254 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1255 if (inds == this->_inner_to_outer_idx[i]) {
1256 b = i;
1257 break;
1258 }
1259 }
1260
1261 if (b < 0) {
1262 if (force_return) {
1263 return this->NullRefTensor;
1264 } else {
1266 true,
1267 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, force_return=false, so "
1268 "error throws. \n If you want to return an empty block without error when block is "
1269 "not avaliable, set force_return=True.%s",
1270 "\n");
1271 }
1272 } else {
1273 return this->_blocks[b];
1274 }
1275 }
1276
1277 std::vector<Tensor> get_blocks() const { return vec_clone(this->_blocks); }
1278 const std::vector<Tensor> &get_blocks_(const bool &) const { return this->_blocks; }
1279 std::vector<Tensor> &get_blocks_(const bool &) { return this->_blocks; }
1280
1281 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const {
1282 if (rhs->uten_type() != UTenType.Block) return false;
1283 if (rhs->get_blocks_(1).size() != this->get_blocks_(1).size()) return false;
1284
1285 for (int i = 0; i < rhs->get_blocks_(1).size(); i++)
1286 if (this->get_blocks_(1)[i].same_data(rhs->get_blocks_(1)[i]) == false) return false;
1287
1288 return true;
1289 }
1290
1291 void set_rowrank(const cytnx_uint64 &new_rowrank) {
1292 cytnx_error_msg(new_rowrank > this->rank(),
1293 "[ERROR][BlockUniTensor] rowrank should be [>=0] and [<=UniTensor.rank].%s",
1294 "\n");
1295 if (this->is_diag()) {
1296 cytnx_error_msg(new_rowrank != 1,
1297 "[ERROR][BlockUniTensor] rowrank should be [==1] when is_diag =true!.%s",
1298 "\n");
1299 }
1300 this->_rowrank = new_rowrank;
1301 this->_is_braket_form = this->_update_braket();
1302 }
1303
1304 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
1305 const cytnx_int64 &rowrank = -1);
1306 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
1307 const cytnx_int64 &rowrank = -1);
1308
1309 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
1310 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
1311
1312 boost::intrusive_ptr<UniTensor_base> contiguous_() {
1313 for (unsigned int b = 0; b < this->_blocks.size(); b++) this->_blocks[b].contiguous_();
1314 return boost::intrusive_ptr<UniTensor_base>(this);
1315 }
1316
1317 boost::intrusive_ptr<UniTensor_base> contiguous();
1318
1319 void print_diagram(const bool &bond_info = false);
1320 void print_blocks(const bool &full_info = true) const;
1321 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
1322
1323 boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs,
1324 const bool &mv_elem_self = false,
1325 const bool &mv_elem_rhs = false);
1326
1327 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &new_labels);
1328 void relabels_(const std::vector<std::string> &new_labels);
1329
1330 // boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &old_labels,
1331 // const std::vector<std::string> &new_labels); void relabels_(const std::vector<std::string>
1332 // &old_labels, const std::vector<std::string> &new_labels);
1333
1334 boost::intrusive_ptr<UniTensor_base> relabel(const std::string &old_label,
1335 const std::string &new_label);
1336 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
1337 const std::string &new_label);
1338
1339 void relabel_(const std::string &old_label, const std::string &new_label);
1340 void relabel_(const cytnx_int64 &inx, const std::string &new_label);
1341
1342 std::vector<Symmetry> syms() const;
1343
1344 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
1345 cytnx_error_msg(true, "[ERROR] cannot reshape a UniTensor with symmetry.%s", "\n");
1346 }
1347 boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
1348 const cytnx_uint64 &rowrank = 0) {
1349 cytnx_error_msg(true, "[ERROR] cannot reshape a UniTensor with symmetry.%s", "\n");
1350 return nullptr;
1351 }
1352
1353 boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const {
1354 BlockUniTensor *tmp = this->clone_meta(true, true);
1355 tmp->_blocks.resize(this->_blocks.size());
1356 for (cytnx_int64 blk = 0; blk < this->_blocks.size(); blk++) {
1357 tmp->_blocks[blk] = this->_blocks[blk].astype(dtype);
1358 }
1359 boost::intrusive_ptr<UniTensor_base> out(tmp);
1360 return out;
1361 };
1362
1363 // this will only work on non-symm tensor (DenseUniTensor)
1364 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors) {
1366 true,
1367 "[ERROR][BlockUniTensor][get] cannot use get on a UniTensor with "
1368 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
1369 "\n");
1370 return nullptr;
1371 }
1372
1373 // this will only work on non-symm tensor (DenseUniTensor)
1374 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
1376 true,
1377 "[ERROR][BlockUniTensor][get] cannot use get on a UniTensor with "
1378 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
1379 "\n");
1380 }
1381
1382 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
1383 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1384 "\n");
1385 cytnx_error_msg(in.shape() != this->_blocks[idx].shape(),
1386 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1387 "of block @ idx=%d\n",
1388 idx);
1389
1390 this->_blocks[idx] = in.clone();
1391 }
1392 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) {
1393 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1394 "\n");
1395 cytnx_error_msg(in.shape() != this->_blocks[idx].shape(),
1396 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1397 "of block @ idx=%d\n",
1398 idx);
1399
1400 this->_blocks[idx] = in;
1401 }
1402 void put_block(const Tensor &in, const std::vector<cytnx_int64> &indices, const bool &check) {
1403 cytnx_error_msg(indices.size() != this->rank(),
1404 "[ERROR][put_block][BlockUniTensor] len(indices) must be the same as the "
1405 "Tensor rank (number of legs).%s",
1406 "\n");
1407
1408 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1409
1410 // find if the indices specify exists!
1411 cytnx_int64 b = -1;
1412 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1413 if (inds == this->_inner_to_outer_idx[i]) {
1414 b = i;
1415 break;
1416 }
1417 }
1418
1419 if (b < 0) {
1420 if (check) {
1421 cytnx_error_msg(true,
1422 "[ERROR][put_block][BlockUniTensor] no avaliable block exists, "
1423 "check=true, so error throws. \n If you want without error when block "
1424 "is not avaliable, set check=false.%s",
1425 "\n");
1426 }
1427 } else {
1429 in.shape() != this->_blocks[b].shape(),
1430 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1431 "of block @ idx=%d\n",
1432 b);
1433
1434 this->_blocks[b] = in.clone();
1435 }
1436 }
1437 void put_block_(Tensor &in, const std::vector<cytnx_int64> &indices, const bool &check) {
1438 cytnx_error_msg(indices.size() != this->rank(),
1439 "[ERROR][put_block][BlockUniTensor] len(indices) must be the same as the "
1440 "Tensor rank (number of legs).%s",
1441 "\n");
1442
1443 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1444
1445 // find if the indices specify exists!
1446 cytnx_int64 b = -1;
1447 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1448 if (inds == this->_inner_to_outer_idx[i]) {
1449 b = i;
1450 break;
1451 }
1452 }
1453
1454 if (b < 0) {
1455 if (check) {
1456 cytnx_error_msg(true,
1457 "[ERROR][put_block][BlockUniTensor] no avaliable block exists, "
1458 "check=true, so error throws. \n If you want without error when block "
1459 "is not avaliable, set check=false.%s",
1460 "\n");
1461 }
1462 } else {
1464 in.shape() != this->_blocks[b].shape(),
1465 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1466 "of block @ idx=%d\n",
1467 b);
1468 this->_blocks[b] = in;
1469 }
1470 }
1471
1472 void tag() {
1473 // no-use!
1474 }
1475
1476 boost::intrusive_ptr<UniTensor_base> Conj() {
1477 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1478 out->Conj_();
1479 return out;
1480 }
1481
1482 void Conj_() {
1483 for (int i = 0; i < this->_blocks.size(); i++) {
1484 this->_blocks[i].Conj_();
1485 }
1486 };
1487
1488 void Transpose_();
1489 boost::intrusive_ptr<UniTensor_base> Transpose() {
1490 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1491 out->Transpose_();
1492 return out;
1493 }
1494
1495 void normalize_();
1496 boost::intrusive_ptr<UniTensor_base> normalize() {
1497 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1498 out->normalize_();
1499 return out;
1500 }
1501
1502 boost::intrusive_ptr<UniTensor_base> Dagger() {
1503 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
1504 out->Transpose_();
1505 return out;
1506 }
1507 void Dagger_() {
1508 this->Conj_();
1509 this->Transpose_();
1510 }
1511
1512 void Trace_(const std::string &a, const std::string &b);
1513 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
1514
1515 boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b) {
1516 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1517 out->Trace_(a, b);
1518 if (out->rank() == 0) {
1519 DenseUniTensor *tmp = new DenseUniTensor();
1520 tmp->_block = ((BlockUniTensor *)out.get())->_blocks[0];
1521 out = boost::intrusive_ptr<UniTensor_base>(tmp);
1522 }
1523 return out;
1524 }
1525 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b) {
1526 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1527 out->Trace_(a, b);
1528 if (out->rank() == 0) {
1529 DenseUniTensor *tmp = new DenseUniTensor();
1530 tmp->_block = ((BlockUniTensor *)out.get())->_blocks[0];
1531 out = boost::intrusive_ptr<UniTensor_base>(tmp);
1532 }
1533 return out;
1534 }
1535
1536 Tensor Norm() const;
1537
1538 bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
1539
1540 const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const;
1541 const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1542 const cytnx_complex128 &aux) const;
1543 const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1544 const cytnx_complex64 &aux) const;
1545 const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1546 const cytnx_double &aux) const;
1547 const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1548 const cytnx_float &aux) const;
1549 const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1550 const cytnx_uint64 &aux) const;
1551 const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1552 const cytnx_int64 &aux) const;
1553 const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1554 const cytnx_uint32 &aux) const;
1555 const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1556 const cytnx_int32 &aux) const;
1557 const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1558 const cytnx_uint16 &aux) const;
1559 const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1560 const cytnx_int16 &aux) const;
1561
1562 Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator);
1563 cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1564 const cytnx_complex128 &aux);
1565 cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1566 const cytnx_complex64 &aux);
1567 cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux);
1568 cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux);
1569 cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux);
1570 cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux);
1571 cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux);
1572 cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux);
1573 cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux);
1574 cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux);
1575
1576 void _save_dispatch(std::fstream &f) const;
1577 void _load_dispatch(std::fstream &f);
1578
1579 // this will remove the [q_index]-th qnum at [bond_idx]-th Bond!
1580 void truncate_(const std::string &bond_idx, const cytnx_uint64 &q_index);
1581 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &q_index);
1582
1583 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1584 void Add_(const Scalar &rhs) {
1586 true,
1587 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s \n",
1588 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1589 "operation on the block(s).");
1590 }
1591
1592 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1593 void Mul_(const Scalar &rhs);
1594
1595 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1596 void Sub_(const Scalar &rhs) {
1598 true,
1599 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s \n",
1600 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1601 "operation on the block(s).");
1602 }
1603 void lSub_(const Scalar &lhs) {
1605 true,
1606 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s \n",
1607 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1608 "operation on the block(s).");
1609 }
1610
1611 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs) {
1613 true,
1614 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s \n",
1615 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1616 "operation on the block(s).");
1617 }
1618 void Div_(const Scalar &rhs);
1619 void lDiv_(const Scalar &lhs) {
1621 true,
1622 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s \n",
1623 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1624 "operation on the block(s).");
1625 }
1626
1627 void group_basis_();
1628
1629 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = false);
1630 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
1631 const bool &by_label);
1632 void combineBonds(const std::vector<std::string> &indicators, const bool &force = false);
1633
1634 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
1636 bidx >= this->Nblocks(),
1637 "[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
1638 this->Nblocks());
1639 return this->_inner_to_outer_idx[bidx];
1640 }
1641 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
1643 bidx >= this->Nblocks(),
1644 "[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
1645 this->Nblocks());
1646 return this->_inner_to_outer_idx[bidx];
1647 }
1648
1649 const vec2d<cytnx_uint64> &get_itoi() const { return this->_inner_to_outer_idx; }
1650 vec2d<cytnx_uint64> &get_itoi() { return this->_inner_to_outer_idx; }
1651 };
1653 //======================================================================
1654
1656 class UniTensor_options {
1657 public:
1658 bool _is_diag;
1659 int _dtype;
1660 int _device;
1661 int _rowrank;
1662
1663 UniTensor_options() {
1664 this->_is_diag = false;
1665 this->_dtype = Type.Double;
1666 this->_device = Device.cpu;
1667 this->_rowrank = -1;
1668 }
1669
1670 UniTensor_options(const UniTensor_options &rhs) {
1671 this->_is_diag = rhs._is_diag;
1672 this->_dtype = rhs._dtype;
1673 this->_device = rhs._device;
1674 this->_rowrank = rhs._rowrank;
1675 }
1676
1677 UniTensor_options &operator=(const UniTensor_options &rhs) {
1678 this->_is_diag = rhs._is_diag;
1679 this->_dtype = rhs._dtype;
1680 this->_device = rhs._device;
1681 this->_rowrank = rhs._rowrank;
1682 return *this;
1683 }
1684
1685 UniTensor_options &is_diag(const bool &in) {
1686 this->_is_diag = in;
1687 return *this;
1688 }
1689 UniTensor_options &dtype(const int &in) {
1690 this->_dtype = in;
1691 return *this;
1692 }
1693 UniTensor_options &device(const int &in) {
1694 this->_device = in;
1695 return *this;
1696 }
1697 UniTensor_options &rowrank(const int &in) {
1698 this->_rowrank = in;
1699 return *this;
1700 }
1701 };
1703
1706 public:
1708 boost::intrusive_ptr<UniTensor_base> _impl;
1709 UniTensor() : _impl(new UniTensor_base()){};
1710 UniTensor(const UniTensor &rhs) { this->_impl = rhs._impl; }
1711 UniTensor &operator=(const UniTensor &rhs) {
1712 this->_impl = rhs._impl;
1713 return *this;
1714 }
1716
1718
1744 explicit UniTensor(const Tensor &in_tensor, const bool &is_diag = false,
1745 const cytnx_int64 &rowrank = -1,
1746 const std::vector<std::string> &in_labels = {}, const std::string &name = "")
1747 : _impl(new UniTensor_base()) {
1748 this->Init(in_tensor, is_diag, rowrank, in_labels, name);
1749 }
1767 void Init(const Tensor &in_tensor, const bool &is_diag = false, const cytnx_int64 &rowrank = -1,
1768 const std::vector<std::string> &in_labels = {}, const std::string &name = "") {
1769 // std::cout << "[entry!]" << std::endl;
1770 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
1771 out->Init_by_Tensor(in_tensor, is_diag, rowrank, name);
1772 this->_impl = out;
1773 if (in_labels.size() != 0) this->set_labels(in_labels);
1774 }
1776
1778
1795 UniTensor(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1796 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1797 const int &device = Device.cpu, const bool &is_diag = false,
1798 const std::string &name = "")
1799 : _impl(new UniTensor_base()) {
1800#ifdef UNI_DEBUG
1802 true,
1803 "[DEBUG] message: entry for UniTensor(const std::vector<Bond> &bonds, const "
1804 "std::vector<std::string> &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int "
1805 "&dtype=Type.Double, const int &device = Device.cpu, const bool &is_diag=false)%s",
1806 "\n");
1807#endif
1808 this->Init(bonds, in_labels, rowrank, dtype, device, is_diag, name);
1809 }
1810
1812 /* [developing]
1813 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1814 const UniTensor_options &UToptions = UniTensor_options(), const std::string &name =
1815 ""){ this->Init(bonds,in_labels, UToptions._rowrank, UToptions._dtype , UToptions._device ,
1816 UToptions._is_diag,
1817 name);
1818 }
1819 */
1821
1845 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1846 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1847 const int &device = Device.cpu, const bool &is_diag = false,
1848 const std::string &name = "") {
1849 // checking type:
1850 bool is_sym = false;
1851 int sym_fver = -1;
1852
1853 for (cytnx_uint64 i = 0; i < bonds.size(); i++) {
1854 // check
1855 if (bonds[i].syms().size() != 0) {
1856 is_sym = true;
1857 if (sym_fver == -1)
1858 sym_fver = bonds[i]._impl->_degs.size();
1859 else {
1860 // std::cout << sym_fver << " " <<
1861 // bonds[i]._impl->_degs.size() << std::endl;
1862 cytnx_error_msg((bool(sym_fver) ^ bool(bonds[i]._impl->_degs.size())),
1863 "[ERROR] All the Bond when init a UniTensor with symmetric must be in "
1864 "the same format!%s",
1865 "\n");
1866 }
1867 } else
1869 is_sym, "[ERROR] cannot have bonds with mixing of symmetry and non-symmetry.%s", "\n");
1870 }
1871
1872 // dynamical dispatch:
1873 if (is_sym) {
1874#ifdef UNI_DEBUG
1875 cytnx_warning_msg(true, "[DEBUG] message: entry dispatch: UniTensor: symmetric%s", "\n");
1876#endif
1877 // cytnx_warning_msg(true,"[warning, still developing, some functions will display
1878 // \"[Developing]\"][SparseUniTensor]%s","\n");
1879 if (sym_fver == 0) {
1880 // boost::intrusive_ptr<UniTensor_base> out(new SparseUniTensor());
1881 // this->_impl = out;
1882 cytnx_error_msg(true,
1883 "[ERROR] internal error! [legacy Sparse entry] the Bond is symmetry but "
1884 "the version is not properly determined!%s",
1885 "\n")
1886 } else if (sym_fver == -1) {
1887 cytnx_error_msg(true,
1888 "[ERROR] internal error! the Bond is symmetry but the version is not "
1889 "properly determined!%s",
1890 "\n");
1891 } else {
1892 boost::intrusive_ptr<UniTensor_base> out(new BlockUniTensor());
1893 this->_impl = out;
1894 }
1895 } else {
1896 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
1897 this->_impl = out;
1898 }
1899 this->_impl->Init(bonds, in_labels, rowrank, dtype, device, is_diag, false, name);
1900 }
1901
1908 UniTensor &set_name(const std::string &in) {
1909 this->_impl->set_name(in);
1910 return *this;
1911 }
1912
1923 UniTensor &set_label(const cytnx_int64 &idx, const std::string &new_label) {
1924 this->_impl->set_label(idx, new_label);
1925 return *this;
1926 }
1927
1931 UniTensor &set_label(const cytnx_int64 &idx, const char *new_label) {
1932 this->_impl->set_label(idx, std::string(new_label));
1933 return *this;
1934 }
1935
1946 UniTensor &set_label(const std::string &old_label, const std::string &new_label) {
1947 this->_impl->set_label(old_label, new_label);
1948 return *this;
1949 }
1950
1954 UniTensor &set_label(const char *old_label, const std::string &new_label) {
1955 this->_impl->set_label(std::string(old_label), new_label);
1956 return *this;
1957 }
1958
1962 UniTensor &set_label(const std::string &old_label, const char *new_label) {
1963 this->_impl->set_label(old_label, std::string(new_label));
1964 return *this;
1965 }
1966
1970 UniTensor &set_label(const char *old_label, const char *new_label) {
1971 this->_impl->set_label(std::string(old_label), std::string(new_label));
1972 return *this;
1973 }
1974
1975 /*
1976 UniTensor& change_label(const cytnx_int64 &old_lbl, const cytnx_int64 &new_label){
1977 this->_impl->change_label(old_lbl,new_label);
1978 return *this;
1979 }
1980 */
1981
1991 UniTensor &set_labels(const std::vector<std::string> &new_labels) {
1992 this->_impl->set_labels(new_labels);
1993 return *this;
1994 }
1995
2000 UniTensor &set_labels(const std::initializer_list<char *> &new_labels) {
2001 std::vector<char *> new_lbls(new_labels);
2002 std::vector<std::string> vs(new_lbls.size());
2003 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2004 [](char *x) -> std::string { return std::string(x); });
2005
2006 this->_impl->set_labels(vs);
2007 return *this;
2008 }
2009
2016 UniTensor &set_rowrank(const cytnx_uint64 &new_rowrank) {
2017 this->_impl->set_rowrank(new_rowrank);
2018 return *this;
2019 }
2020
2021 template <class T>
2022 T &item() {
2024 "[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use "
2025 "get_block()/get_blocks() first.%s",
2026 "\n");
2027
2028 DenseUniTensor *tmp = static_cast<DenseUniTensor *>(this->_impl.get());
2029 return tmp->_block.item<T>();
2030 }
2031
2032 Scalar::Sproxy item() const {
2034 "[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use "
2035 "get_block()/get_blocks() first.%s",
2036 "\n");
2037
2038 DenseUniTensor *tmp = static_cast<DenseUniTensor *>(this->_impl.get());
2039 return tmp->_block.item();
2040 }
2045 cytnx_uint64 Nblocks() const { return this->_impl->Nblocks(); }
2046
2051 cytnx_uint64 rank() const { return this->_impl->rank(); }
2052
2057 cytnx_uint64 rowrank() const { return this->_impl->rowrank(); }
2058
2064 unsigned int dtype() const { return this->_impl->dtype(); }
2065
2072 int uten_type() const { return this->_impl->uten_type(); }
2073
2079 int device() const { return this->_impl->device(); }
2080
2085 std::string name() const { return this->_impl->name(); }
2086
2092 std::string dtype_str() const { return this->_impl->dtype_str(); }
2093
2099 std::string device_str() const { return this->_impl->device_str(); }
2100
2106 std::string uten_type_str() const { return this->_impl->uten_type_str(); }
2107
2113 bool is_contiguous() const { return this->_impl->is_contiguous(); }
2114
2119 bool is_diag() const { return this->_impl->is_diag(); }
2120
2126 bool is_tag() const { return this->_impl->is_tag(); }
2127
2133 std::vector<Symmetry> syms() const { return this->_impl->syms(); }
2134
2141 const bool &is_braket_form() const { return this->_impl->is_braket_form(); }
2142
2147 const std::vector<std::string> &labels() const { return this->_impl->labels(); }
2154 cytnx_int64 get_index(std::string lbl) const { return this->_impl->get_index(lbl); }
2155
2160 const std::vector<Bond> &bonds() const { return this->_impl->bonds(); }
2161
2165 std::vector<Bond> &bonds() { return this->_impl->bonds(); }
2166
2171 std::vector<cytnx_uint64> shape() const { return this->_impl->shape(); }
2172
2178 bool is_blockform() const { return this->_impl->is_blockform(); }
2179
2186 void to_(const int &device) { this->_impl->to_(device); }
2187
2197 UniTensor to(const int &device) const {
2198 UniTensor out;
2199 out._impl = this->_impl->to(device);
2200 return out;
2201 }
2202
2208 UniTensor out;
2209 out._impl = this->_impl->clone();
2210 return out;
2211 }
2212
2222 void relabels_(const std::vector<std::string> &new_labels) const {
2223 this->_impl->relabels(new_labels);
2224 }
2232 UniTensor relabels(const std::vector<std::string> &new_labels) const {
2233 UniTensor out;
2234 out._impl = this->_impl->relabels(new_labels);
2235 return out;
2236 }
2237
2241 UniTensor relabels(const std::initializer_list<char *> &new_lbls) const {
2242 std::vector<char *> new_labels(new_lbls);
2243 std::vector<std::string> vs(new_labels.size());
2244 transform(new_labels.begin(), new_labels.end(), vs.begin(),
2245 [](char *x) -> std::string { return std::string(x); });
2246 // std::cout << new_labels.size() << std::endl;
2247 // std::cout << vs << std::endl;
2248
2249 UniTensor out;
2250 out._impl = this->_impl->relabels(vs);
2251 return out;
2252 }
2256 void relabels_(const std::initializer_list<char *> &new_lbls) {
2257 std::vector<char *> new_labels(new_lbls);
2258 std::vector<std::string> vs(new_labels.size());
2259 transform(new_labels.begin(), new_labels.end(), vs.begin(),
2260 [](char *x) -> std::string { return std::string(x); });
2261 // std::cout << new_labels.size() << std::endl;
2262 // std::cout << vs << std::endl;
2263
2264 this->_impl->relabels_(vs);
2265 }
2266
2281 UniTensor relabel(const cytnx_int64 &inx, const std::string &new_label) const {
2282 UniTensor out;
2283 out._impl = this->_impl->relabel(inx, new_label);
2284 return out;
2285 }
2294 void relabel_(const cytnx_int64 &inx, const std::string &new_label) const {
2295 this->_impl->relabel_(inx, new_label);
2296 }
2297
2306 void relabel_(const std::string &old_label, const std::string &new_label) const {
2307 this->_impl->relabel_(old_label, new_label);
2308 }
2309
2324 UniTensor relabel(const std::string &old_label, const std::string &new_label) const {
2325 UniTensor out;
2326 out._impl = this->_impl->relabel(old_label, new_label);
2327 return out;
2328 }
2329
2336 UniTensor astype(const unsigned int &dtype) const {
2337 UniTensor out;
2338 if (this->dtype() == dtype) {
2339 out._impl = this->_impl;
2340 } else {
2341 out._impl = this->_impl->astype(dtype);
2342 }
2343 return out;
2344 }
2345
2354 UniTensor permute(const std::vector<cytnx_int64> &mapper,
2355 const cytnx_int64 &rowrank = -1) const {
2356 UniTensor out;
2357 out._impl = this->_impl->permute(mapper, rowrank);
2358 return out;
2359 }
2360
2367 UniTensor permute(const std::vector<std::string> &mapper,
2368 const cytnx_int64 &rowrank = -1) const {
2369 UniTensor out;
2370 out._impl = this->_impl->permute(mapper, rowrank);
2371 return out;
2372 }
2373
2377 UniTensor permute(const std::initializer_list<char *> &mapper,
2378 const cytnx_int64 &rowrank = -1) const {
2379 std::vector<char *> mprs = mapper;
2380 std::vector<std::string> vs(mprs.size());
2381 transform(mprs.begin(), mprs.end(), vs.begin(),
2382 [](char *x) -> std::string { return std::string(x); });
2383
2384 return this->permute(vs, rowrank);
2385 }
2386
2395 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1) {
2396 this->_impl->permute_(mapper, rowrank);
2397 }
2398
2405 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1) {
2406 this->_impl->permute_(mapper, rowrank);
2407 }
2408
2409 // void permute_( const std::initializer_list<char*> &mapper, const cytnx_int64 &rowrank= -1){
2410 // std::vector<char*> mprs = mapper;
2411 // std::vector<std::string> vs(mprs.size());
2412 // transform(mprs.begin(),mprs.end(),vs.begin(),[](char * x) -> std::string { return
2413 // std::string(x); });
2414
2415 // this->permute_(vs,rowrank);
2416 // }
2417
2418 // void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1) {
2419 // this->_impl->permute_(mapper, rowrank);
2420 // }
2421
2427 UniTensor out;
2428 out._impl = this->_impl->contiguous();
2429 return out;
2430 }
2431
2436 void contiguous_() { this->_impl = this->_impl->contiguous_(); }
2437
2442 void print_diagram(const bool &bond_info = false) { this->_impl->print_diagram(bond_info); }
2443
2448 void print_blocks(const bool &full_info = true) const { this->_impl->print_blocks(full_info); }
2449
2455 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const {
2456 this->_impl->print_block(idx, full_info);
2457 }
2458
2465 void group_basis_() { this->_impl->group_basis_(); }
2466
2468 UniTensor out = this->clone();
2469 out.group_basis_();
2470 return out;
2471 }
2472
2478 template <class T>
2479 T &at(const std::vector<cytnx_uint64> &locator) {
2480 // std::cout << "at " << this->is_blockform() << std::endl;
2481 if (this->uten_type() == UTenType.Block) {
2482 // [NEW] this will not check if it exists, if it is not then error will throw!
2483 T aux;
2484 return this->_impl->at_for_sparse(locator, aux);
2485
2486 } else if (this->uten_type() == UTenType.Sparse) {
2487 if (this->_impl->elem_exists(locator)) {
2488 T aux;
2489 return this->_impl->at_for_sparse(locator, aux);
2490 } else {
2491 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2492 "\n");
2493 }
2494 } else {
2495 return this->get_block_().at<T>(locator);
2496 }
2497 }
2498
2504 template <class T>
2505 const T &at(const std::vector<cytnx_uint64> &locator) const {
2506 // std::cout << "at " << this->is_blockform() << std::endl;
2507 if (this->uten_type() == UTenType.Block) {
2508 // [NEW] this will not check if it exists, if it is not then error will throw!
2509 T aux;
2510 return this->_impl->at_for_sparse(locator, aux);
2511
2512 } else if (this->uten_type() == UTenType.Sparse) {
2513 if (this->_impl->elem_exists(locator)) {
2514 T aux; // [workaround] use aux to dispatch.
2515 return this->_impl->at_for_sparse(locator, aux);
2516 } else {
2517 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2518 "\n");
2519 }
2520 } else {
2521 return this->get_block_().at<T>(locator);
2522 }
2523 }
2524
2529 const Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) const {
2530 if (this->uten_type() == UTenType.Block) {
2531 return this->_impl->at_for_sparse(locator);
2532 } else if (this->uten_type() == UTenType.Sparse) {
2533 if (this->_impl->elem_exists(locator)) {
2534 return this->_impl->at_for_sparse(locator);
2535 } else {
2536 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2537 "\n");
2538 }
2539 } else {
2540 return this->get_block_().at(locator);
2541 }
2542 }
2543
2548 Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) {
2549 if (this->uten_type() == UTenType.Block) {
2550 return this->_impl->at_for_sparse(locator);
2551 } else if (this->uten_type() == UTenType.Sparse) {
2552 if (this->_impl->elem_exists(locator)) {
2553 return this->_impl->at_for_sparse(locator);
2554 } else {
2555 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2556 "\n");
2557 }
2558 } else {
2559 return this->get_block_().at(locator);
2560 }
2561 }
2562
2563 // return a clone of block
2569 Tensor get_block(const cytnx_uint64 &idx = 0) const { return this->_impl->get_block(idx); };
2570 //================================
2571 // return a clone of block
2580 Tensor get_block(const std::vector<cytnx_int64> &qidx, const bool &force = false) const {
2581 return this->_impl->get_block(qidx, force);
2582 }
2583
2588 Tensor get_block(const std::initializer_list<cytnx_int64> &qnum,
2589 const bool &force = false) const {
2590 std::vector<cytnx_int64> tmp = qnum;
2591 return get_block(tmp, force);
2592 }
2593
2598 Tensor get_block(const std::vector<cytnx_uint64> &qnum, const bool &force = false) const {
2599 std::vector<cytnx_int64> iqnum(qnum.begin(), qnum.end());
2600 return this->_impl->get_block(iqnum, force);
2601 }
2602
2608 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const {
2609 return this->_impl->get_block_(idx);
2610 }
2611
2616 Tensor &get_block_(const cytnx_uint64 &idx = 0) { return this->_impl->get_block_(idx); }
2617
2626 Tensor &get_block_(const std::vector<cytnx_int64> &qidx, const bool &force = false) {
2627 return this->_impl->get_block_(qidx, force);
2628 }
2629
2633 Tensor &get_block_(const std::initializer_list<cytnx_int64> &qidx, const bool &force = false) {
2634 std::vector<cytnx_int64> tmp = qidx;
2635 return get_block_(tmp, force);
2636 }
2637
2641 Tensor &get_block_(const std::vector<cytnx_uint64> &qidx, const bool &force = false) {
2642 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
2643 return get_block_(iqidx, force);
2644 }
2645 //================================
2646
2647 // this only work for non-symm tensor. return a shared view of block
2651 const Tensor &get_block_(const std::vector<cytnx_int64> &qidx,
2652 const bool &force = false) const {
2653 return this->_impl->get_block_(qidx, force);
2654 }
2655
2659 const Tensor &get_block_(const std::initializer_list<cytnx_int64> &qidx,
2660 const bool &force = false) const {
2661 std::vector<cytnx_int64> tmp = qidx;
2662 return this->_impl->get_block_(tmp, force);
2663 }
2664
2668 const Tensor &get_block_(const std::vector<cytnx_uint64> &qidx,
2669 const bool &force = false) const {
2670 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
2671 return get_block_(iqidx, force);
2672 }
2673
2674 //================================
2683 //[dev]
2684 std::vector<Tensor> get_blocks() const { return this->_impl->get_blocks(); }
2685
2691 //[dev]
2692 const std::vector<Tensor> &get_blocks_(const bool &silent = false) const {
2693 return this->_impl->get_blocks_(silent);
2694 }
2695
2699 //[dev]
2700 std::vector<Tensor> &get_blocks_(const bool &silent = false) {
2701 return this->_impl->get_blocks_(silent);
2702 }
2703
2710 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
2711 this->_impl->put_block(in, idx);
2712 }
2713
2722 void put_block(const Tensor &in_tens, const std::vector<cytnx_int64> &qidx, const bool &force) {
2723 this->_impl->put_block(in_tens, qidx, force);
2724 }
2725
2731 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) { this->_impl->put_block_(in, idx); }
2732
2739 void put_block_(Tensor &in, const std::vector<cytnx_int64> &qidx, const bool &force) {
2740 this->_impl->put_block_(in, qidx, force);
2741 }
2742 UniTensor get(const std::vector<Accessor> &accessors) const {
2743 UniTensor out;
2744 out._impl = this->_impl->get(accessors);
2745 return out;
2746 }
2747 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
2748 this->_impl->set(accessors, rhs);
2749 }
2750
2758 UniTensor reshape(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
2759 UniTensor out;
2760 out._impl = this->_impl->reshape(new_shape, rowrank);
2761 return out;
2762 }
2763
2770 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
2771 this->_impl->reshape_(new_shape, rowrank);
2772 }
2773
2786 UniTensor out;
2787 out._impl = this->_impl->to_dense();
2788 return out;
2789 }
2790
2795 void to_dense_() { this->_impl->to_dense_(); }
2796
2802 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
2803 const bool &by_label) {
2804 this->_impl->combineBonds(indicators, force, by_label);
2805 }
2806
2817 void combineBonds(const std::vector<std::string> &indicators, const bool &force = false) {
2818 this->_impl->combineBonds(indicators, force);
2819 }
2820
2826 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = false) {
2827 this->_impl->combineBonds(indicators, force);
2828 }
2829
2848 UniTensor contract(const UniTensor &inR, const bool &mv_elem_self = false,
2849 const bool &mv_elem_rhs = false) const {
2850 UniTensor out;
2851 out._impl = this->_impl->contract(inR._impl, mv_elem_self, mv_elem_rhs);
2852 return out;
2853 }
2854
2856
2864 std::vector<Bond> getTotalQnums(const bool physical = false) const {
2865 return this->_impl->getTotalQnums(physical);
2866 }
2867
2871 std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const {
2872 return this->_impl->get_blocks_qnums();
2873 }
2875
2880 bool same_data(const UniTensor &rhs) const {
2881 // check same type:
2882 if (this->_impl->uten_type() != rhs._impl->uten_type()) return false;
2883
2884 return this->_impl->same_data(rhs._impl);
2885 }
2886
2903 UniTensor &Add_(const UniTensor &rhs) {
2904 this->_impl->Add_(rhs._impl);
2905 return *this;
2906 }
2907
2924 UniTensor &Mul_(const UniTensor &rhs) {
2925 this->_impl->Mul_(rhs._impl);
2926 return *this;
2927 }
2928
2945 UniTensor &Sub_(const UniTensor &rhs) {
2946 this->_impl->Sub_(rhs._impl);
2947 return *this;
2948 }
2949
2966 UniTensor &Div_(const UniTensor &rhs) {
2967 this->_impl->Div_(rhs._impl);
2968 return *this;
2969 }
2970
2981 UniTensor &Add_(const Scalar &rhs) {
2982 this->_impl->Add_(rhs);
2983 return *this;
2984 }
2985
2996 UniTensor &Mul_(const Scalar &rhs) {
2997 this->_impl->Mul_(rhs);
2998 return *this;
2999 }
3000
3011 UniTensor &Sub_(const Scalar &rhs) {
3012 this->_impl->Sub_(rhs);
3013 return *this;
3014 }
3015
3026 UniTensor &Div_(const Scalar &rhs) {
3027 this->_impl->Div_(rhs);
3028 return *this;
3029 }
3030
3047 UniTensor Add(const UniTensor &rhs) const;
3048
3059 UniTensor Add(const Scalar &rhs) const;
3060
3077 UniTensor Mul(const UniTensor &rhs) const;
3078
3089 UniTensor Mul(const Scalar &rhs) const;
3090
3107 UniTensor Div(const UniTensor &rhs) const;
3108
3119 UniTensor Div(const Scalar &rhs) const;
3120
3137 UniTensor Sub(const UniTensor &rhs) const;
3138
3149 UniTensor Sub(const Scalar &rhs) const;
3150
3159 Tensor Norm() const { return this->_impl->Norm(); };
3160
3177 this->Add_(rhs);
3178 return *this;
3179 }
3180
3197 this->Sub_(rhs);
3198 return *this;
3199 }
3200
3217 this->Div_(rhs);
3218 return *this;
3219 }
3220
3237 this->Mul_(rhs);
3238 return *this;
3239 }
3240
3252 this->Add_(rhs);
3253 return *this;
3254 }
3255
3267 this->Sub_(rhs);
3268 return *this;
3269 }
3270
3282 this->Div_(rhs);
3283 return *this;
3284 }
3285
3297 this->Mul_(rhs);
3298 return *this;
3299 }
3300
3309 UniTensor out;
3310 out._impl = this->_impl->Conj();
3311 return out;
3312 }
3313
3322 this->_impl->Conj_();
3323 return *this;
3324 }
3325
3337 UniTensor out;
3338 out._impl = this->_impl->Transpose();
3339 return out;
3340 }
3341
3349 this->_impl->Transpose_();
3350 return *this;
3351 }
3352
3360 UniTensor out;
3361 out._impl = this->_impl->normalize();
3362 return out;
3363 }
3364
3372 this->_impl->normalize_();
3373 return *this;
3374 }
3375
3385 UniTensor Trace(const std::string &a, const std::string &b) const {
3386 UniTensor out;
3387 out._impl = this->_impl->Trace(a, b);
3388 return out;
3389 }
3390
3400 UniTensor Trace(const cytnx_int64 &a = 0, const cytnx_int64 &b = 1) const {
3401 UniTensor out;
3402 out._impl = this->_impl->Trace(a, b);
3403 return out;
3404 }
3405
3415 UniTensor &Trace_(const std::string &a, const std::string &b) {
3416 this->_impl->Trace_(a, b);
3417 if (this->uten_type() == UTenType.Block) {
3418 // handle if no leg left case for BlockUniTensor.
3419 if (this->rank() == 0) {
3420 DenseUniTensor *tmp = new DenseUniTensor();
3421 tmp->_block = this->get_blocks_(true)[0];
3422 this->_impl = boost::intrusive_ptr<UniTensor_base>(tmp);
3423 }
3424 }
3425 return *this;
3426 }
3427
3437 UniTensor &Trace_(const cytnx_int64 &a = 0, const cytnx_int64 &b = 1) {
3438 this->_impl->Trace_(a, b);
3439 if (this->uten_type() == UTenType.Block) {
3440 // handle if no leg left case for BlockUniTensor.
3441 if (this->rank() == 0) {
3442 DenseUniTensor *tmp = new DenseUniTensor();
3443 tmp->_block = this->get_blocks_(true)[0];
3444 this->_impl = boost::intrusive_ptr<UniTensor_base>(tmp);
3445 }
3446 }
3447 return *this;
3448 }
3449
3457 UniTensor out;
3458 out._impl = this->_impl->Dagger();
3459 return out;
3460 }
3461
3469 this->_impl->Dagger_();
3470 return *this;
3471 }
3472
3481 this->_impl->tag();
3482 return *this;
3483 }
3484
3493 UniTensor Pow(const double &p) const;
3494
3503 UniTensor &Pow_(const double &p);
3504
3511 bool elem_exists(const std::vector<cytnx_uint64> &locator) const {
3512 return this->_impl->elem_exists(locator);
3513 }
3514
3520 template <class T>
3521 T get_elem(const std::vector<cytnx_uint64> &locator) const {
3522 return this->at<T>(locator);
3523 }
3524
3530 template <class T2>
3531 void set_elem(const std::vector<cytnx_uint64> &locator, const T2 &rc) {
3532 // cytnx_error_msg(true,"[ERROR] invalid type%s","\n");
3533 this->at(locator) = rc;
3534 }
3535
3542 void Save(const std::string &fname) const;
3543
3550 void Save(const char *fname) const;
3551
3560 static UniTensor Load(const std::string &fname);
3561
3570 static UniTensor Load(const char *fname);
3571
3580 UniTensor &truncate_(const std::string &label, const cytnx_uint64 &dim) {
3581 this->_impl->truncate_(label, dim);
3582 return *this;
3583 }
3584
3593 UniTensor &truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim) {
3594 this->_impl->truncate_(bond_idx, dim);
3595 return *this;
3596 }
3597
3607 UniTensor truncate(const std::string &label, const cytnx_uint64 &dim) const {
3608 UniTensor out = this->clone();
3609 out.truncate_(label, dim);
3610 return out;
3611 }
3612
3622 UniTensor truncate(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim) const {
3623 UniTensor out = this->clone();
3624 out.truncate_(bond_idx, dim);
3625 return out;
3626 }
3627
3635 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
3636 return this->_impl->get_qindices(bidx);
3637 }
3645 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
3646 return this->_impl->get_qindices(bidx);
3647 }
3648
3655 const vec2d<cytnx_uint64> &get_itoi() const { return this->_impl->get_itoi(); }
3656 vec2d<cytnx_uint64> &get_itoi() { return this->_impl->get_itoi(); }
3657
3659 void _Load(std::fstream &f);
3660 void _Save(std::fstream &f) const;
3662
3663 }; // class UniTensor
3664
3666 std::ostream &operator<<(std::ostream &os, const UniTensor &in);
3668
3681 UniTensor Contract(const UniTensor &inL, const UniTensor &inR, const bool &cacheL = false,
3682 const bool &cacheR = false);
3683
3696 UniTensor Contracts(const std::vector<UniTensor> &TNs, const std::string &order,
3697 const bool &optimal);
3698
3700 void _resolve_CT(std::vector<UniTensor> &TNlist);
3701 template <class... T>
3702 void _resolve_CT(std::vector<UniTensor> &TNlist, const UniTensor &in, const T &...args) {
3703 TNlist.push_back(in);
3704 _resolve_CT(TNlist, args...);
3705 }
3707
3719 template <class... T>
3720 UniTensor Contracts(const UniTensor &in, const T &...args, const std::string &order,
3721 const bool &optimal) {
3722 std::vector<UniTensor> TNlist;
3723 _resolve_CT(TNlist, in, args...);
3724 return Contracts(TNlist, order, optimal);
3725 }
3726
3727} // namespace cytnx
3728#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:912
Tensor contiguous_()
Make the Tensor contiguous by coalescing the memory (storage), inplacely.
Definition Tensor.hpp:999
unsigned int dtype() const
the dtype-id of the Tensor
Definition Tensor.hpp:811
Tensor contiguous() const
Make the Tensor contiguous by coalescing the memory (storage).
Definition Tensor.hpp:979
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition Tensor.hpp:1155
Tensor clone() const
return a clone of the current Tensor.
Definition Tensor.hpp:863
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:1290
Tensor Norm() const
the Norm member function. Same as linalg::Norm(const Tensor &Tin), where Tin is the current Tensor.
Tensor astype(const int &new_type) const
return a new Tensor that cast to different dtype.
Definition Tensor.hpp:1120
const bool & is_contiguous() const
return whether the Tensor is contiguous or not.
Definition Tensor.hpp:918
Tensor & Conj_()
the Conj_ member function. Same as cytnx::linalg::Conj_(Tensor &Tin), where Tin is the current Tensor...
int device() const
the device-id of the Tensor
Definition Tensor.hpp:818
Tensor get(const std::vector< cytnx::Accessor > &accessors) const
get elements using Accessor (C++ API) / slices (python API)
Definition Tensor.hpp:1258
const std::vector< cytnx_uint64 > & shape() const
the shape of the Tensor
Definition Tensor.hpp:838
An Enhanced tensor specifically designed for physical Tensor network simulation.
Definition UniTensor.hpp:1705
void put_block(const Tensor &in_tens, const std::vector< cytnx_int64 > &qidx, const bool &force)
Put the block into the UniTensor with given quantum number.
Definition UniTensor.hpp:2722
UniTensor to(const int &device) const
move the current UniTensor to the assigned device.
Definition UniTensor.hpp:2197
UniTensor & operator*=(const UniTensor &rhs)
The multiplication assignment operator of the UniTensor.
Definition UniTensor.hpp:3236
Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:2633
std::vector< Tensor > & get_blocks_(const bool &silent=false)
Definition UniTensor.hpp:2700
Tensor & get_block_(const std::vector< cytnx_uint64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:2641
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:2455
UniTensor & operator/=(const UniTensor &rhs)
The division assignment operator of the UniTensor.
Definition UniTensor.hpp:3216
T & item()
Definition UniTensor.hpp:2022
bool is_contiguous() const
To tell whether the UniTensor is contiguous.
Definition UniTensor.hpp:2113
T get_elem(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:3521
UniTensor Div(const UniTensor &rhs) const
The division function of the UniTensor.
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:3645
UniTensor & set_label(const cytnx_int64 &idx, const char *new_label)
Definition UniTensor.hpp:1931
UniTensor & operator+=(const UniTensor &rhs)
The addition assignment operator of the UniTensor.
Definition UniTensor.hpp:3176
void to_dense_()
Convert the UniTensor to non-diagonal form, inplacely.
Definition UniTensor.hpp:2795
UniTensor reshape(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor.
Definition UniTensor.hpp:2758
std::vector< Tensor > get_blocks() const
Get all the blocks of the UniTensor.
Definition UniTensor.hpp:2684
UniTensor permute(const std::initializer_list< char * > &mapper, const cytnx_int64 &rowrank=-1) const
Definition UniTensor.hpp:2377
void relabel_(const cytnx_int64 &inx, const std::string &new_label) const
rebable the lags in the UniTensor by given index.
Definition UniTensor.hpp:2294
bool is_tag() const
To tell whether the UniTensor is tagged. That is, all of the Bond in the UniTensor is directional (al...
Definition UniTensor.hpp:2126
cytnx_int64 get_index(std::string lbl) const
Get the index of an desired label string.
Definition UniTensor.hpp:2154
std::string uten_type_str() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor in 'string' form.
Definition UniTensor.hpp:2106
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:1795
Tensor get_block(const std::vector< cytnx_int64 > &qidx, const bool &force=false) const
Get the block of the UniTensor for the given quantun indices.
Definition UniTensor.hpp:2580
void permute_(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1)
permute the lags of the UniTensor, inplacely.
Definition UniTensor.hpp:2395
UniTensor & tag()
Set the UniTensor as a tagged UniTensor.
Definition UniTensor.hpp:3480
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force=false)
Definition UniTensor.hpp:2826
UniTensor(const Tensor &in_tensor, const bool &is_diag=false, const cytnx_int64 &rowrank=-1, const std::vector< std::string > &in_labels={}, const std::string &name="")
Construct a UniTensor from a cytnx::Tensor.
Definition UniTensor.hpp:1744
Tensor & get_block_(const std::vector< cytnx_int64 > &qidx, const bool &force=false)
Get the shared view of block for the given quantum indices.
Definition UniTensor.hpp:2626
void Init(const Tensor &in_tensor, const bool &is_diag=false, const cytnx_int64 &rowrank=-1, const std::vector< std::string > &in_labels={}, const std::string &name="")
Initialize a UniTensor with cytnx::Tensor.
Definition UniTensor.hpp:1767
UniTensor get(const std::vector< Accessor > &accessors) const
Definition UniTensor.hpp:2742
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:1946
void Save(const std::string &fname) const
save a UniTensor to file
UniTensor & operator-=(const Scalar &rhs)
The subtraction assignment operator for a given scalar.
Definition UniTensor.hpp:3266
cytnx_uint64 rowrank() const
Return the row rank of the UniTensor.
Definition UniTensor.hpp:2057
UniTensor Sub(const Scalar &rhs) const
The subtraction function for a given scalar.
Tensor Norm() const
Return the norm of the UniTensor.
Definition UniTensor.hpp:3159
UniTensor Mul(const Scalar &rhs) const
The multiplication function for a given scalar.
UniTensor & set_labels(const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:2000
UniTensor & Sub_(const Scalar &rhs)
The subtraction function for a given scalar.
Definition UniTensor.hpp:3011
UniTensor & operator/=(const Scalar &rhs)
The division assignment operator for a given scalar.
Definition UniTensor.hpp:3281
const bool & is_braket_form() const
Check whether the UniTensor is in braket form.
Definition UniTensor.hpp:2141
void set_elem(const std::vector< cytnx_uint64 > &locator, const T2 &rc)
Definition UniTensor.hpp:3531
UniTensor Add(const Scalar &rhs) const
The addition function for a given scalar.
std::vector< cytnx_uint64 > shape() const
Get the shape of the UniTensor.
Definition UniTensor.hpp:2171
UniTensor to_dense()
Convert the UniTensor to non-diagonal form.
Definition UniTensor.hpp:2785
UniTensor relabels(const std::initializer_list< char * > &new_lbls) const
Definition UniTensor.hpp:2241
const Tensor & get_block_(const std::vector< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:2651
void reshape_(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor, inplacely.
Definition UniTensor.hpp:2770
UniTensor & set_labels(const std::vector< std::string > &new_labels)
Set new labels for all the bonds.
Definition UniTensor.hpp:1991
void permute_(const std::vector< std::string > &mapper, const cytnx_int64 &rowrank=-1)
permute the lags of the UniTensor, inplacely.
Definition UniTensor.hpp:2405
std::string name() const
Return the name of the UniTensor.
Definition UniTensor.hpp:2085
UniTensor & Add_(const Scalar &rhs)
The addition function for a given scalar.
Definition UniTensor.hpp:2981
UniTensor & Trace_(const std::string &a, const std::string &b)
Take the partial trance to the UniTensor, inplacely.
Definition UniTensor.hpp:3415
UniTensor & truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim)
truncate bond dimension of the UniTensor by the given bond index and dimension.
Definition UniTensor.hpp:3593
Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition UniTensor.hpp:2548
UniTensor Trace(const std::string &a, const std::string &b) const
Take the partial trance to the UniTensor.
Definition UniTensor.hpp:3385
bool same_data(const UniTensor &rhs) const
Check whether the Blocks address are the same.
Definition UniTensor.hpp:2880
UniTensor astype(const unsigned int &dtype) const
Return a new UniTensor that cast to different data type.
Definition UniTensor.hpp:2336
UniTensor truncate(const std::string &label, const cytnx_uint64 &dim) const
truncate bond dimension of the UniTensor by the given bond label and dimension.
Definition UniTensor.hpp:3607
UniTensor Transpose() const
Take the transpose of the UniTensor.
Definition UniTensor.hpp:3336
UniTensor & set_label(const char *old_label, const std::string &new_label)
Definition UniTensor.hpp:1954
static UniTensor Load(const char *fname)
load a UniTensor from file
UniTensor & Dagger_()
Take the conjugate transpose to the UniTensor, inplacely.
Definition UniTensor.hpp:3468
void print_diagram(const bool &bond_info=false)
Plot the diagram of the UniTensor.
Definition UniTensor.hpp:2442
std::vector< Bond > & bonds()
Definition UniTensor.hpp:2165
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition UniTensor.hpp:2479
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:1923
UniTensor contiguous() const
Make the UniTensor contiguous by coalescing the memory (storage).
Definition UniTensor.hpp:2426
Tensor get_block(const cytnx_uint64 &idx=0) const
Get the block of the UniTensor for a given index.
Definition UniTensor.hpp:2569
const T & at(const std::vector< cytnx_uint64 > &locator) const
Get an element at specific location.
Definition UniTensor.hpp:2505
UniTensor & operator*=(const Scalar &rhs)
The multiplication assignment operator for a given scalar.
Definition UniTensor.hpp:3296
void contiguous_()
Make the UniTensor contiguous by coalescing the memory (storage), inplacely.
Definition UniTensor.hpp:2436
UniTensor normalize() const
normalize the current UniTensor instance with 2-norm.
Definition UniTensor.hpp:3359
std::vector< Symmetry > syms() const
Return the symmetry type of the UniTensor.
Definition UniTensor.hpp:2133
UniTensor & Mul_(const UniTensor &rhs)
The multiplcation function of the UniTensor.
Definition UniTensor.hpp:2924
void put_block_(Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index, inplacely.
Definition UniTensor.hpp:2731
void combineBonds(const std::vector< std::string > &indicators, const bool &force=false)
Combine the sevral bonds of the UniTensor.
Definition UniTensor.hpp:2817
UniTensor relabel(const std::string &old_label, const std::string &new_label) const
relabel the lags in the UniTensor by a given label.
Definition UniTensor.hpp:2324
UniTensor & normalize_()
normalize the UniTensor, inplacely.
Definition UniTensor.hpp:3371
bool is_diag() const
To tell whether the UniTensor is in diagonal form.
Definition UniTensor.hpp:2119
int device() const
Return the device of the UniTensor.
Definition UniTensor.hpp:2079
UniTensor & Pow_(const double &p)
Power function.
const Tensor & get_block_(const std::vector< cytnx_uint64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:2668
void set(const std::vector< Accessor > &accessors, const Tensor &rhs)
Definition UniTensor.hpp:2747
std::string dtype_str() const
Return the data type of the UniTensor in 'string' form.
Definition UniTensor.hpp:2092
UniTensor & operator+=(const Scalar &rhs)
The addition assignment operator for a given scalar.
Definition UniTensor.hpp:3251
UniTensor & Div_(const UniTensor &rhs)
The division function of the UniTensor.
Definition UniTensor.hpp:2966
UniTensor & Div_(const Scalar &rhs)
The division function for a given scalar.
Definition UniTensor.hpp:3026
cytnx_uint64 rank() const
Return the rank of the UniTensor.
Definition UniTensor.hpp:2051
void group_basis_()
Group the same quantum number basis together.
Definition UniTensor.hpp:2465
void to_(const int &device)
move the current UniTensor to the assigned device (inplace).
Definition UniTensor.hpp:2186
UniTensor & Trace_(const cytnx_int64 &a=0, const cytnx_int64 &b=1)
Take the partial trance to the UniTensor, inplacely.
Definition UniTensor.hpp:3437
UniTensor & set_name(const std::string &in)
Set the name of the UniTensor.
Definition UniTensor.hpp:1908
UniTensor Trace(const cytnx_int64 &a=0, const cytnx_int64 &b=1) const
Take the partial trance to the UniTensor.
Definition UniTensor.hpp:3400
UniTensor & Add_(const UniTensor &rhs)
The addition function of the UniTensor.
Definition UniTensor.hpp:2903
UniTensor permute(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1) const
permute the lags of the UniTensor
Definition UniTensor.hpp:2354
UniTensor & set_label(const std::string &old_label, const char *new_label)
Definition UniTensor.hpp:1962
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:2367
unsigned int dtype() const
Return the data type of the UniTensor.
Definition UniTensor.hpp:2064
UniTensor Pow(const double &p) const
Power function.
UniTensor & Mul_(const Scalar &rhs)
The multiplication function for a given scalar.
Definition UniTensor.hpp:2996
UniTensor & operator-=(const UniTensor &rhs)
The subtraction assignment operator of the UniTensor.
Definition UniTensor.hpp:3196
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force, const bool &by_label)
Definition UniTensor.hpp:2802
UniTensor & set_label(const char *old_label, const char *new_label)
Definition UniTensor.hpp:1970
bool is_blockform() const
Check whether the UniTensor is in block form.
Definition UniTensor.hpp:2178
UniTensor group_basis() const
Definition UniTensor.hpp:2467
UniTensor Dagger() const
Take the conjugate transpose to the UniTensor.
Definition UniTensor.hpp:3456
const std::vector< Tensor > & get_blocks_(const bool &silent=false) const
Get all the blocks of the UniTensor, inplacely.
Definition UniTensor.hpp:2692
const Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:2659
bool elem_exists(const std::vector< cytnx_uint64 > &locator) const
Geiven the locator, check if the element exists.
Definition UniTensor.hpp:3511
UniTensor & Sub_(const UniTensor &rhs)
The subtraction function of the UniTensor.
Definition UniTensor.hpp:2945
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:2848
void put_block(const Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index.
Definition UniTensor.hpp:2710
const Tensor & get_block_(const cytnx_uint64 &idx=0) const
Get the shared view of block for the given index.
Definition UniTensor.hpp:2608
static UniTensor Load(const std::string &fname)
load a UniTensor from file
UniTensor relabel(const cytnx_int64 &inx, const std::string &new_label) const
rebable the lags in the UniTensor by given index.
Definition UniTensor.hpp:2281
UniTensor Mul(const UniTensor &rhs) const
The multiplication function of the UniTensor.
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:3635
UniTensor Div(const Scalar &rhs) const
The division function for a given scalar.
const std::vector< std::string > & labels() const
Return the labels of the UniTensor.
Definition UniTensor.hpp:2147
const std::vector< Bond > & bonds() const
Get the bonds of the UniTensor.
Definition UniTensor.hpp:2160
UniTensor truncate(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim) const
truncate bond dimension of the UniTensor by the given bond index and dimension.
Definition UniTensor.hpp:3622
UniTensor & Transpose_()
Take the transpose of the UniTensor, inplacely.
Definition UniTensor.hpp:3348
UniTensor clone() const
Clone (deep copy) the UniTensor.
Definition UniTensor.hpp:2207
vec2d< cytnx_uint64 > & get_itoi()
Definition UniTensor.hpp:3656
void print_blocks(const bool &full_info=true) const
Print all of the blocks in the UniTensor.
Definition UniTensor.hpp:2448
void relabel_(const std::string &old_label, const std::string &new_label) const
relabel the lags in the UniTensor by a given label.
Definition UniTensor.hpp:2306
Scalar::Sproxy item() const
Definition UniTensor.hpp:2032
const vec2d< cytnx_uint64 > & get_itoi() const
get the q-indices on each leg for all the blocks
Definition UniTensor.hpp:3655
std::string device_str() const
Return the device of the UniTensor in 'string' form.
Definition UniTensor.hpp:2099
UniTensor relabels(const std::vector< std::string > &new_labels) const
rebables all of the labels in UniTensor.
Definition UniTensor.hpp:2232
void put_block_(Tensor &in, const std::vector< cytnx_int64 > &qidx, const bool &force)
Put the block into the UniTensor with given quantum indices, inplacely.
Definition UniTensor.hpp:2739
void relabels_(const std::initializer_list< char * > &new_lbls)
Definition UniTensor.hpp:2256
void relabels_(const std::vector< std::string > &new_labels) const
Set new labels for all the bonds.
Definition UniTensor.hpp:2222
UniTensor Sub(const UniTensor &rhs) const
The subtraction function of the UniTensor.
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:1845
UniTensor & Conj_()
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:3321
cytnx_uint64 Nblocks() const
Return the number of blocks in the UniTensor.
Definition UniTensor.hpp:2045
Tensor get_block(const std::vector< cytnx_uint64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:2598
void Save(const char *fname) const
save a UniTensor to file
UniTensor Conj()
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:3308
UniTensor Add(const UniTensor &rhs) const
The addition function of the UniTensor.
UniTensor & set_rowrank(const cytnx_uint64 &new_rowrank)
Set the row rank of the UniTensor.
Definition UniTensor.hpp:2016
UniTensor & truncate_(const std::string &label, const cytnx_uint64 &dim)
truncate bond dimension of the UniTensor by the given bond label and dimension.
Definition UniTensor.hpp:3580
Tensor get_block(const std::initializer_list< cytnx_int64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:2588
const Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator) const
Get an element at specific location.
Definition UniTensor.hpp:2529
int uten_type() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor.
Definition UniTensor.hpp:2072
Tensor & get_block_(const cytnx_uint64 &idx=0)
Definition UniTensor.hpp:2616
#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.
double cytnx_double
Definition Type.hpp:43
UniTensorType_class UTenType
UniTensor type.
uint32_t cytnx_uint32
Definition Type.hpp:46
std::complex< double > cytnx_complex128
Definition Type.hpp:53
float cytnx_float
Definition Type.hpp:44
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.
uint16_t cytnx_uint16
Definition Type.hpp:47
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:41
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.
Type_class Type
data type
tmp
Definition sp.py:8