Cytnx v0.9.4
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 "Device.hpp"
7#include "Tensor.hpp"
8#include "utils/utils.hpp"
10#include <iostream>
11#include <vector>
12#include <map>
13#include <utility>
14#include <initializer_list>
15#include <fstream>
16#include <algorithm>
17#include "Symmetry.hpp"
18#include "Bond.hpp"
19
20#ifdef BACKEND_TORCH
21#else
22 #include "backend/Scalar.hpp"
23
24// namespace cytnx{
25namespace cytnx {
26 using namespace cytnx;
28 class UniTensorType_class {
29 public:
30 enum : int {
31 Void = -99,
32 Dense = 0,
33 Sparse = 1,
34 Block = 2,
35 };
36 std::string getname(const int &ut_type);
37 };
39
55 extern UniTensorType_class UTenType;
56
58 // class DenseUniTensor;
59 // class SparseUniTensor;
60 class UniTensor_base : public intrusive_ptr_base<UniTensor_base> {
61 public:
62 int uten_type_id; // the unitensor type id.
63 bool _is_braket_form;
64 bool _is_tag;
65 bool _is_diag;
66 cytnx_int64 _rowrank;
67 std::string _name;
68 std::vector<std::string> _labels;
69 std::vector<Bond> _bonds;
70
71 bool _update_braket() {
72 if (_bonds.size() == 0) return false;
73
74 if (this->_bonds[0].type() != bondType::BD_REG) {
75 // check:
76 for (unsigned int i = 0; i < this->_bonds.size(); i++) {
77 if (i < this->_rowrank) {
78 if (this->_bonds[i].type() != bondType::BD_KET) return false;
79 } else {
80 if (this->_bonds[i].type() != bondType::BD_BRA) return false;
81 }
82 }
83 return true;
84 } else {
85 return false;
86 }
87 }
88
89 friend class UniTensor; // allow wrapper to access the private elems
90 friend class DenseUniTensor;
91 // friend class SparseUniTensor;
92 friend class BlockUniTensor;
93
94 UniTensor_base()
95 : _is_tag(false),
96 _name(std::string("")),
97 _is_braket_form(false),
98 _rowrank(0),
99 _is_diag(false),
100 uten_type_id(UTenType.Void){};
101
102 // copy&assignment constr., use intrusive_ptr's !!
103 UniTensor_base(const UniTensor_base &rhs);
104 UniTensor_base &operator=(UniTensor_base &rhs);
105
106 cytnx_uint64 rowrank() const { return this->_rowrank; }
107 bool is_diag() const { return this->_is_diag; }
108 const bool &is_braket_form() const { return this->_is_braket_form; }
109 const bool &is_tag() const { return this->_is_tag; }
110 const std::vector<std::string> &labels() const { return this->_labels; }
117 cytnx_int64 get_index(std::string lbl) const {
118 std::vector<std::string> lbls = this->_labels;
119 for (cytnx_uint64 i = 0; i < lbls.size(); i++) {
120 if (lbls[i] == lbl) return i;
121 }
122 return -1;
123 }
124 const std::vector<Bond> &bonds() const { return this->_bonds; }
125 std::vector<Bond> &bonds() { return this->_bonds; }
126
127 Bond &bond_(const cytnx_uint64 &idx) {
128 cytnx_error_msg(idx >= this->_bonds.size(), "[ERROR][bond] index %d out of bound, total %d\n",
129 idx, this->_bonds.size());
130 return this->_bonds[idx];
131 }
132
133 Bond &bond_(const std::string &lbl) {
134 auto res = std::find(this->_labels.begin(), this->_labels.end(), lbl);
135 cytnx_error_msg(res == this->_labels.end(), "[ERROR] label %s not exists.\n", lbl.c_str());
136 cytnx_uint64 idx = std::distance(this->_labels.begin(), res);
137
138 return this->bond_(idx);
139 }
140
141 const std::string &name() const { return this->_name; }
142 cytnx_uint64 rank() const { return this->_labels.size(); }
143 void set_name(const std::string &in) { this->_name = in; }
144
155 void set_label(const std::string &oldlbl, const std::string &new_label) {
156 cytnx_int64 idx;
157 auto res = std::find(this->_labels.begin(), this->_labels.end(), oldlbl);
158 cytnx_error_msg(res == this->_labels.end(), "[ERROR] label %s not exists.\n", oldlbl.c_str());
159 idx = std::distance(this->_labels.begin(), res);
160
161 cytnx_error_msg(idx >= 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 == idx) 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[idx] = new_label;
175 }
176 void set_label(const cytnx_int64 &inx, const std::string &new_label) {
177 cytnx_error_msg(inx < 0, "[ERROR] index is negative%s", "\n");
178 cytnx_error_msg(inx >= this->_labels.size(), "[ERROR] index exceed the rank of UniTensor%s",
179 "\n");
180 // check in:
181 bool is_dup = false;
182 for (cytnx_uint64 i = 0; i < this->_labels.size(); i++) {
183 if (i == inx) continue;
184 if (new_label == this->_labels[i]) {
185 is_dup = true;
186 break;
187 }
188 }
189 cytnx_error_msg(is_dup, "[ERROR] alreay has a label that is the same as the input label%s",
190 "\n");
191 this->_labels[inx] = new_label;
192 }
193
194 void set_labels(const std::vector<std::string> &new_labels);
195 void relabels_(const std::vector<std::string> &new_labels); // implemented
196 void relabels_(const std::vector<std::string> &old_labels,
197 const std::vector<std::string> &new_labels); // implemented
198 void relabel_(const std::string &old_label, const std::string &new_label) {
199 this->set_label(old_label, new_label);
200 }
201 void relabel_(const cytnx_int64 &inx, const std::string &new_label) {
202 this->set_label(inx, new_label);
203 }
204
205 int uten_type() { return this->uten_type_id; }
206 std::string uten_type_str() { return UTenType.getname(this->uten_type_id); }
207
209
210 // string labels!
211 virtual void Init(const std::vector<Bond> &bonds,
212 const std::vector<std::string> &in_labels = {},
213 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
214 const int &device = Device.cpu, const bool &is_diag = false,
215 const bool &no_alloc = false, const std::string &name = "");
216
217 virtual void Init_by_Tensor(const Tensor &in, const bool &is_diag = false,
218 const cytnx_int64 &rowrank = -1, const std::string &name = "");
219 virtual std::vector<cytnx_uint64> shape() const;
220 virtual bool is_blockform() const;
221 virtual bool is_contiguous() const;
222 virtual void to_(const int &device);
223 virtual boost::intrusive_ptr<UniTensor_base> to(const int &device);
224 virtual boost::intrusive_ptr<UniTensor_base> clone() const;
225 virtual unsigned int dtype() const;
226 virtual int device() const;
227 virtual std::string dtype_str() const;
228 virtual std::string device_str() const;
229 virtual void set_rowrank_(const cytnx_uint64 &new_rowrank);
230 virtual boost::intrusive_ptr<UniTensor_base> set_rowrank(const cytnx_uint64 &new_rowrank) const;
231
232 virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
233 const cytnx_int64 &rowrank = -1);
234 virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
235 const cytnx_int64 &rowrank = -1);
236 // virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
237 // const cytnx_int64 &rowrank = -1);
238
239 virtual void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
240 virtual void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
241
242 // virtual void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank =
243 // -1);
244 virtual boost::intrusive_ptr<UniTensor_base> contiguous_();
245 virtual boost::intrusive_ptr<UniTensor_base> contiguous();
246 virtual void print_diagram(const bool &bond_info = false);
247 virtual void print_blocks(const bool &full_info = true) const;
248 virtual void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
249
250 virtual boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const;
251
252 virtual cytnx_uint64 Nblocks() const { return 0; };
253 virtual Tensor get_block(const cytnx_uint64 &idx = 0) const; // return a copy of block
254 virtual Tensor get_block(const std::vector<cytnx_int64> &qnum,
255 const bool &force) const; // return a copy of block
256
257 virtual const Tensor &get_block_(const cytnx_uint64 &idx = 0)
258 const; // return a share view of block, this only work for non-symm tensor.
259 virtual const Tensor &get_block_(const std::vector<cytnx_int64> &qnum,
260 const bool &force) const; // return a copy of block
261 virtual Tensor &get_block_(const cytnx_uint64 &idx = 0); // return a share view of block, this
262 // only work for non-symm tensor.
263 virtual Tensor &get_block_(const std::vector<cytnx_int64> &qnum,
264 const bool &force); // return a copy of block
265 virtual bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const;
266
267 virtual std::vector<Tensor> get_blocks() const;
268 virtual const std::vector<Tensor> &get_blocks_(const bool &) const;
269 virtual std::vector<Tensor> &get_blocks_(const bool &);
270
271 virtual void put_block(const Tensor &in, const cytnx_uint64 &idx = 0);
272 virtual void put_block_(Tensor &in, const cytnx_uint64 &idx = 0);
273 virtual void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum,
274 const bool &force);
275 virtual void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force);
276
277 // this will only work on non-symm tensor (DenseUniTensor)
278 virtual boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors);
279
280 // this will only work on non-symm tensor (DenseUniTensor)
281 virtual void set(const std::vector<Accessor> &accessors, const Tensor &rhs);
282
283 virtual void reshape_(const std::vector<cytnx_int64> &new_shape,
284 const cytnx_uint64 &rowrank = 0);
285 virtual boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
286 const cytnx_uint64 &rowrank = 0);
287 virtual boost::intrusive_ptr<UniTensor_base> to_dense();
288 virtual void to_dense_();
289 virtual void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
290 const bool &by_label);
291 virtual void combineBonds(const std::vector<std::string> &indicators,
292 const bool &force = false);
293 virtual void combineBonds(const std::vector<cytnx_int64> &indicators,
294 const bool &force = false);
295 virtual boost::intrusive_ptr<UniTensor_base> contract(
296 const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &mv_elem_self = false,
297 const bool &mv_elem_rhs = false);
298 virtual std::vector<Bond> getTotalQnums(const bool &physical = false);
299 virtual std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const;
300 virtual void Trace_(const std::string &a, const std::string &b);
301 virtual void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
302
303 virtual boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b);
304 virtual boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b);
305
306 virtual boost::intrusive_ptr<UniTensor_base> relabels(
307 const std::vector<std::string> &new_labels);
308
309 virtual boost::intrusive_ptr<UniTensor_base> relabels(
310 const std::vector<std::string> &old_labels, const std::vector<std::string> &new_labels);
311
312 virtual boost::intrusive_ptr<UniTensor_base> relabel(const std::string &inx,
313 const std::string &new_label);
314
315 virtual boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
316 const std::string &new_label);
317
318 virtual std::vector<Symmetry> syms() const;
319
320 // arithmetic
321 virtual void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
322 virtual void Add_(const Scalar &rhs);
323
324 virtual void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
325 virtual void Mul_(const Scalar &rhs);
326
327 virtual void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
328 virtual void Sub_(const Scalar &rhs);
329 virtual void lSub_(const Scalar &lhs);
330
331 virtual void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
332 virtual void Div_(const Scalar &rhs);
333 virtual void lDiv_(const Scalar &lhs);
334
335 virtual Tensor Norm() const;
336 virtual boost::intrusive_ptr<UniTensor_base> normalize();
337 virtual void normalize_();
338
339 virtual boost::intrusive_ptr<UniTensor_base> Conj();
340 virtual void Conj_();
341
342 virtual boost::intrusive_ptr<UniTensor_base> Transpose();
343 virtual void Transpose_();
344
345 virtual boost::intrusive_ptr<UniTensor_base> Dagger();
346 virtual void Dagger_();
347
348 virtual void tag();
349
350 virtual void truncate_(const std::string &bond_idx, const cytnx_uint64 &dim);
351 virtual void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim);
352
353 virtual bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
354
355 // this a workaround, as virtual function cannot template.
356 virtual Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator);
357 virtual const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const;
358
359 virtual cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
360 const cytnx_complex128 &aux);
361 virtual cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
362 const cytnx_complex64 &aux);
363 virtual cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
364 const cytnx_double &aux);
365 virtual cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
366 const cytnx_float &aux);
367 virtual cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
368 const cytnx_uint64 &aux);
369 virtual cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
370 const cytnx_int64 &aux);
371 virtual cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
372 const cytnx_uint32 &aux);
373 virtual cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
374 const cytnx_int32 &aux);
375 virtual cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
376 const cytnx_uint16 &aux);
377 virtual cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
378 const cytnx_int16 &aux);
379
380 virtual const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
381 const cytnx_complex128 &aux) const;
382 virtual const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
383 const cytnx_complex64 &aux) const;
384 virtual const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
385 const cytnx_double &aux) const;
386 virtual const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
387 const cytnx_float &aux) const;
388 virtual const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
389 const cytnx_uint64 &aux) const;
390 virtual const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
391 const cytnx_int64 &aux) const;
392 virtual const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
393 const cytnx_uint32 &aux) const;
394 virtual const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
395 const cytnx_int32 &aux) const;
396 virtual const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
397 const cytnx_uint16 &aux) const;
398 virtual const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
399 const cytnx_int16 &aux) const;
400
401 virtual void from_(const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &force);
402
403 virtual void group_basis_();
404 virtual const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const;
405 virtual std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx);
406 virtual const vec2d<cytnx_uint64> &get_itoi() const;
407 virtual vec2d<cytnx_uint64> &get_itoi();
408
409 virtual void _save_dispatch(std::fstream &f) const;
410 virtual void _load_dispatch(std::fstream &f);
411
412 virtual ~UniTensor_base(){};
413 };
415
416 //======================================================================
418 class DenseUniTensor : public UniTensor_base {
419 protected:
420 public:
421 Tensor _block;
422 std::vector<Tensor> _interface_block; // this is serves as interface for get_blocks_();
423 DenseUniTensor *clone_meta() const {
424 DenseUniTensor *tmp = new DenseUniTensor();
425 tmp->_bonds = vec_clone(this->_bonds);
426 tmp->_labels = this->_labels;
427 tmp->_is_braket_form = this->_is_braket_form;
428 tmp->_rowrank = this->_rowrank;
429 tmp->_is_diag = this->_is_diag;
430 tmp->_name = this->_name;
431 tmp->_is_tag = this->_is_tag;
432 return tmp;
433 }
434 //------------------------------------------
435
436 DenseUniTensor() { this->uten_type_id = UTenType.Dense; };
437 friend class UniTensor; // allow wrapper to access the private elems
438 // virtual functions
439
440 // void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels = {},
441 // const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
442 // const int &device = Device.cpu, const bool &is_diag = false,
443 // const bool &no_alloc = false);
444
445 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
446 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
447 const int &device = Device.cpu, const bool &is_diag = false,
448 const bool &no_alloc = false, const std::string &name = "");
449 // this only work for non-symm tensor
450 void Init_by_Tensor(const Tensor &in_tensor, const bool &is_diag = false,
451 const cytnx_int64 &rowrank = -1, const std::string &name = "");
452 std::vector<cytnx_uint64> shape() const {
453 if (this->_is_diag) {
454 std::vector<cytnx_uint64> shape = this->_block.shape();
455 shape.push_back(shape[0]);
456 return shape;
457 } else {
458 return this->_block.shape();
459 }
460 }
461 bool is_blockform() const { return false; }
462 void to_(const int &device) { this->_block.to_(device); }
463 boost::intrusive_ptr<UniTensor_base> to(const int &device) {
464 if (this->device() == device) {
465 std::vector<Tensor> _interface_block; // this is serves as interface for get_blocks_();
466 return this;
467 } else {
468 boost::intrusive_ptr<UniTensor_base> out = this->clone();
469 out->to_(device);
470 return out;
471 }
472 }
473 void set_rowrank_(const cytnx_uint64 &new_rowrank) {
474 cytnx_error_msg(new_rowrank > this->_labels.size(),
475 "[ERROR] rowrank cannot exceed the rank of UniTensor.%s", "\n");
476 if (this->is_diag()) {
477 cytnx_error_msg(new_rowrank != 1, "[ERROR] rowrank should be [==1] when is_diag =true!.%s",
478 "\n");
479 }
480
481 this->_rowrank = new_rowrank;
482 }
483
484 boost::intrusive_ptr<UniTensor_base> set_rowrank(const cytnx_uint64 &new_rowrank) const {
485 DenseUniTensor *out_raw = this->clone_meta();
486 out_raw->_block = this->_block;
487 out_raw->set_rowrank_(new_rowrank);
488 boost::intrusive_ptr<UniTensor_base> out(out_raw);
489 return out;
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
530 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &old_labels,
531 const std::vector<std::string> &new_labels);
532
543 boost::intrusive_ptr<UniTensor_base> relabel(const std::string &old_label,
544 const std::string &new_label);
545 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
546 const std::string &new_label);
547
548 boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const {
549 DenseUniTensor *tmp = this->clone_meta();
550 tmp->_block = this->_block.astype(dtype);
551 boost::intrusive_ptr<UniTensor_base> out(tmp);
552 return tmp;
553 }
554
555 std::vector<Symmetry> syms() const {
556 cytnx_error_msg(true, "[ERROR][DenseUniTensor] dense unitensor does not have symmetry.%s",
557 "\n");
558 return std::vector<Symmetry>();
559 }
560
561 boost::intrusive_ptr<UniTensor_base> contiguous_() {
562 this->_block.contiguous_();
563 return boost::intrusive_ptr<UniTensor_base>(this);
564 }
565 boost::intrusive_ptr<UniTensor_base> contiguous() {
566 // if contiguous then return self!
567 if (this->is_contiguous()) {
568 boost::intrusive_ptr<UniTensor_base> out(this);
569 return out;
570 } else {
571 DenseUniTensor *tmp = this->clone_meta();
572 tmp->_block = this->_block.contiguous();
573 boost::intrusive_ptr<UniTensor_base> out(tmp);
574 return out;
575 }
576 }
577 void print_diagram(const bool &bond_info = false);
578 void print_blocks(const bool &full_info = true) const;
579 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
580 Tensor get_block(const cytnx_uint64 &idx = 0) const { return this->_block.clone(); }
581
582 Tensor get_block(const std::vector<cytnx_int64> &qnum, const bool &force) const {
584 true, "[ERROR][DenseUniTensor] try to get_block() using qnum on a non-symmetry UniTensor%s",
585 "\n");
586 return Tensor();
587 }
588 // return a share view of block, this only work for non-symm tensor.
589 const Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force) const {
591 true,
592 "[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
593 "\n");
594 return this->_block;
595 }
596 Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force) {
598 true,
599 "[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
600 "\n");
601 return this->_block;
602 }
603
604 // return a share view of block, this only work for non-symm tensor.
605 Tensor &get_block_(const cytnx_uint64 &idx = 0) { return this->_block; }
606 // return a share view of block, this only work for non-symm tensor.
607 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const { return this->_block; }
608
609 cytnx_uint64 Nblocks() const { return 1; };
610 std::vector<Tensor> get_blocks() const {
611 std::vector<Tensor> out;
613 true, "[ERROR][DenseUniTensor] cannot use get_blocks(), use get_block() instead!%s", "\n");
614 return out; // this will not share memory!!
615 }
616 const std::vector<Tensor> &get_blocks_(const bool &silent = false) const {
618 true, "[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s",
619 "\n");
620 return this->_interface_block; // this will not share memory!!
621 }
622 std::vector<Tensor> &get_blocks_(const bool &silent = false) {
624 true, "[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s",
625 "\n");
626 return this->_interface_block; // this will not share memory!!
627 }
628
629 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
630 if (this->is_diag()) {
632 in.shape() != this->_block.shape(),
633 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
634 this->_block = in.clone();
635 } else {
637 in.shape() != this->shape(),
638 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
639 this->_block = in.clone();
640 }
641 }
642 // share view of the block
643 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) {
644 if (this->is_diag()) {
646 in.shape() != this->_block.shape(),
647 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
648 this->_block = in;
649 } else {
651 in.shape() != this->shape(),
652 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
653 this->_block = in;
654 }
655 }
656
657 void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force) {
659 true, "[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
660 "\n");
661 }
662 void put_block_(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 // this will only work on non-symm tensor (DenseUniTensor)
668 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors) {
669 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
670 out->Init_by_Tensor(this->_block.get(accessors), false, 0); // wrapping around.
671 return out;
672 }
673 // this will only work on non-symm tensor (DenseUniTensor)
674 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
675 this->_block.set(accessors, rhs);
676 }
677
678 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0);
679 boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
680 const cytnx_uint64 &rowrank = 0);
681 boost::intrusive_ptr<UniTensor_base> to_dense();
682 void to_dense_();
692 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
693 const bool &by_label);
694 void combineBonds(const std::vector<std::string> &indicators, const bool &force = true);
695 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = true);
696 boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs,
697 const bool &mv_elem_self = false,
698 const bool &mv_elem_rhs = false);
699 std::vector<Bond> getTotalQnums(const bool &physical = false) {
700 cytnx_error_msg(true, "[ERROR][DenseUniTensor] %s",
701 "getTotalQnums can only operate on UniTensor with symmetry.\n");
702 return std::vector<Bond>();
703 }
704
705 std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const {
706 cytnx_error_msg(true, "[ERROR][DenseUniTensor] %s",
707 "get_blocks_qnums can only operate on UniTensor with symmetry.\n");
708 return std::vector<std::vector<cytnx_int64>>();
709 }
710
711 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const {
712 if (rhs->uten_type() != UTenType.Dense) return false;
713
714 return this->get_block_().same_data(rhs->get_block_());
715 }
716
717 ~DenseUniTensor(){};
718
719 // arithmetic
720 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
721 void Add_(const Scalar &rhs);
722
723 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
724 void Mul_(const Scalar &rhs);
725
726 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
727 void Sub_(const Scalar &rhs);
728 void lSub_(const Scalar &lhs);
729
730 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
731 void Div_(const Scalar &rhs);
732 void lDiv_(const Scalar &lhs);
733
734 void Conj_() { this->_block.Conj_(); };
735
736 boost::intrusive_ptr<UniTensor_base> Conj() {
737 boost::intrusive_ptr<UniTensor_base> out = this->clone();
738 out->Conj_();
739 return out;
740 }
741
742 boost::intrusive_ptr<UniTensor_base> Transpose() {
743 boost::intrusive_ptr<UniTensor_base> out = this->clone();
744 out->Transpose_();
745 return out;
746 }
747 void Transpose_();
748
749 boost::intrusive_ptr<UniTensor_base> normalize() {
750 boost::intrusive_ptr<UniTensor_base> out = this->clone();
751 out->normalize_();
752 return out;
753 }
754 void normalize_();
755
756 boost::intrusive_ptr<UniTensor_base> Dagger() {
757 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
758 out->Transpose_();
759 return out;
760 }
761 void Dagger_() {
762 this->Conj_();
763 this->Transpose_();
764 }
774 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
775 void Trace_(const std::string &a, const std::string &b);
776 boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b) {
777 boost::intrusive_ptr<UniTensor_base> out = this->clone();
778 out->Trace_(a, b);
779 return out;
780 }
781 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b) {
782 boost::intrusive_ptr<UniTensor_base> out = this->clone();
783 out->Trace_(a, b);
784 return out;
785 }
786
787 Tensor Norm() const;
788
789 const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const {
791 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
792 "\n");
793 return Scalar::Sproxy();
794 }
795 const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
796 const cytnx_complex128 &aux) const {
798 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
799 "\n");
800 return cytnx_complex128(0, 0);
801 }
802 const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
803 const cytnx_complex64 &aux) const {
805 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
806 "\n");
807 return cytnx_complex64(0, 0);
808 }
809 const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
810 const cytnx_double &aux) const {
812 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
813 "\n");
814 return 0;
815 }
816 const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
817 const cytnx_float &aux) const {
819 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
820 "\n");
821 return 0;
822 }
823 const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
824 const cytnx_uint64 &aux) const {
826 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
827 "\n");
828 return 0;
829 }
830 const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
831 const cytnx_int64 &aux) const {
833 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
834 "\n");
835 return 0;
836 }
837 const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
838 const cytnx_uint32 &aux) const {
840 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
841 "\n");
842 return 0;
843 }
844 const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
845 const cytnx_int32 &aux) const {
847 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
848 "\n");
849 return 0;
850 }
851 const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
852 const cytnx_uint16 &aux) const {
854 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
855 "\n");
856 return 0;
857 }
858 const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
859 const cytnx_int16 &aux) const {
861 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
862 "\n");
863 return 0;
864 }
865
866 Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) {
868 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
869 "\n");
870 return Scalar::Sproxy();
871 }
872 cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
873 const cytnx_complex128 &aux) {
875 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
876 "\n");
877 return *(cytnx_complex128 *)nullptr;
878 }
879 cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
880 const cytnx_complex64 &aux) {
882 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
883 "\n");
884 return *(cytnx_complex64 *)nullptr;
885 }
886 cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux) {
888 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
889 "\n");
890 return *(cytnx_double *)nullptr;
891 }
892 cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux) {
894 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
895 "\n");
896 return *(cytnx_float *)nullptr;
897 }
898 cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux) {
900 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
901 "\n");
902 return *(cytnx_uint64 *)nullptr;
903 }
904 cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux) {
906 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
907 "\n");
908 return *(cytnx_int64 *)nullptr;
909 }
910 cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux) {
912 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
913 "\n");
914 return *(cytnx_uint32 *)nullptr;
915 }
916 cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux) {
918 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
919 "\n");
920 return *(cytnx_int32 *)nullptr;
921 }
922 cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux) {
924 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
925 "\n");
926 return *(cytnx_uint16 *)nullptr;
927 }
928 cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux) {
930 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
931 "\n");
932 return *(cytnx_int16 *)nullptr;
933 }
934
935 bool elem_exists(const std::vector<cytnx_uint64> &locator) const {
937 true, "[ERROR][DenseUniTensor] elem_exists can only be used on UniTensor with Symmetry.%s",
938 "\n");
939 }
940 void tag() {
941 if (!this->is_tag()) {
942 for (int i = 0; i < this->_rowrank; i++) {
943 this->_bonds[i].set_type(BD_KET);
944 }
945 for (int i = this->_rowrank; i < this->_bonds.size(); i++) {
946 this->_bonds[i].set_type(BD_BRA);
947 }
948 this->_is_tag = true;
949 this->_is_braket_form = this->_update_braket();
950 }
951 }
961 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim);
962 void truncate_(const std::string &bond_idx, const cytnx_uint64 &dim);
963
964 void from_(const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &force);
965
966 void group_basis_() {
967 cytnx_warning_msg(true, "[WARNING] group basis will not have any effect on DensUniTensor.%s",
968 "\n");
969 }
970
971 void _save_dispatch(std::fstream &f) const;
972 void _load_dispatch(std::fstream &f);
973
974 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
975 cytnx_error_msg(true, "[ERROR] get_qindices can only be unsed on UniTensor with Symmetry.%s",
976 "\n");
977 }
978 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
979 cytnx_error_msg(true, "[ERROR] get_qindices can only be unsed on UniTensor with Symmetry.%s",
980 "\n");
981 }
982
983 const vec2d<cytnx_uint64> &get_itoi() const {
984 cytnx_error_msg(true, "[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s",
985 "\n");
986 }
987 vec2d<cytnx_uint64> &get_itoi() {
988 cytnx_error_msg(true, "[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s",
989 "\n");
990 }
991
992 // end virtual function
993 };
995
996 //======================================================================
998 class BlockUniTensor : public UniTensor_base {
999 protected:
1000 public:
1001 std::vector<std::vector<cytnx_uint64>> _inner_to_outer_idx;
1002 std::vector<Tensor> _blocks;
1003 Tensor NullRefTensor; // this returns when access block is not exists!
1004
1005 // given an index list [loc], get qnums from this->_bonds[loc] and return the combined qnums
1006 // calculated from Symm object! this assume 1. symmetry are the same for each bond!
1007 // 2. total_qns are feeded with size len(symmetry)
1008 void _fx_get_total_fluxs(std::vector<cytnx_uint64> &loc, const std::vector<Symmetry> &syms,
1009 std::vector<cytnx_int64> &total_qns) {
1010 memset(&total_qns[0], 0, sizeof(cytnx_int64) * total_qns.size());
1011
1012 for (cytnx_int32 i = 0; i < syms.size(); i++) {
1013 if (this->_bonds[0].type() == BD_BRA)
1014 total_qns[i] = syms[0].reverse_rule(this->_bonds[0]._impl->_qnums[loc[0]][i]);
1015 else
1016 total_qns[i] = this->_bonds[0]._impl->_qnums[loc[0]][i];
1017
1018 for (auto j = 1; j < loc.size(); j++) {
1019 if (this->_bonds[j].type() == BD_BRA)
1020 total_qns[i] = syms[i].combine_rule(
1021 total_qns[i], syms[i].reverse_rule(this->_bonds[j]._impl->_qnums[loc[j]][i]));
1022 else {
1023 total_qns[i] =
1024 syms[i].combine_rule(total_qns[i], this->_bonds[j]._impl->_qnums[loc[j]][i]);
1025 }
1026 }
1027 }
1028 }
1029
1030 void _fx_locate_elem(cytnx_int64 &bidx, std::vector<cytnx_uint64> &loc_in_T,
1031 const std::vector<cytnx_uint64> &locator) const;
1032
1033 // internal function, grouping all duplicate qnums in all bonds
1034 void _fx_group_duplicates(const std::vector<cytnx_uint64> &dup_bond_idxs,
1035 const std::vector<std::vector<cytnx_uint64>> &idx_mappers);
1036
1037 void set_meta(BlockUniTensor *tmp, const bool &inner, const bool &outer) const {
1038 // outer meta
1039 if (outer) {
1040 tmp->_bonds = vec_clone(this->_bonds);
1041 tmp->_labels = this->_labels;
1042 tmp->_is_braket_form = this->_is_braket_form;
1043 tmp->_rowrank = this->_rowrank;
1044 tmp->_name = this->_name;
1045 }
1046
1047 tmp->_is_diag = this->_is_diag;
1048
1049 // inner meta
1050 if (inner) {
1051 tmp->_inner_to_outer_idx = this->_inner_to_outer_idx;
1052 }
1053 }
1054
1055 BlockUniTensor *clone_meta(const bool &inner, const bool &outer) const {
1056 BlockUniTensor *tmp = new BlockUniTensor();
1057 this->set_meta(tmp, inner, outer);
1058 return tmp;
1059 };
1060
1061 friend class UniTensor;
1062 BlockUniTensor() {
1063 this->uten_type_id = UTenType.Block;
1064 this->_is_tag = true;
1065 }
1066
1067 // virtual functions:
1068 // void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels = {},
1069 // const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1070 // const int &device = Device.cpu, const bool &is_diag = false,
1071 // const bool &no_alloc = false);
1072
1073 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1074 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1075 const int &device = Device.cpu, const bool &is_diag = false,
1076 const bool &no_alloc = false, const std::string &name = "");
1077
1078 void Init_by_Tensor(const Tensor &in_tensor, const bool &is_diag = false,
1079 const cytnx_int64 &rowrank = -1, const std::string &name = "") {
1081 true, "[ERROR][BlockUniTensor] cannot use Init_by_tensor() on a BlockUniTensor.%s", "\n");
1082 }
1083
1084 std::vector<cytnx_uint64> shape() const {
1085 std::vector<cytnx_uint64> out(this->_bonds.size());
1086 for (cytnx_uint64 i = 0; i < out.size(); i++) {
1087 out[i] = this->_bonds[i].dim();
1088 }
1089 return out;
1090 }
1091
1092 bool is_blockform() const { return true; }
1093 bool is_contiguous() const {
1094 bool out = true;
1095 for (int i = 0; i < this->_blocks.size(); i++) {
1096 out &= this->_blocks[i].is_contiguous();
1097 }
1098 return out;
1099 };
1100
1101 cytnx_uint64 Nblocks() const { return this->_blocks.size(); };
1102
1103 void to_(const int &device) {
1104 for (cytnx_uint64 i = 0; i < this->_blocks.size(); i++) {
1105 this->_blocks[i].to_(device);
1106 }
1107 };
1108
1109 boost::intrusive_ptr<UniTensor_base> to(const int &device) {
1110 if (this->device() == device) {
1111 return this;
1112 } else {
1113 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1114 out->to_(device);
1115 return out;
1116 }
1117 };
1118
1119 boost::intrusive_ptr<UniTensor_base> clone() const {
1120 BlockUniTensor *tmp = this->clone_meta(true, true);
1121 tmp->_blocks = vec_clone(this->_blocks);
1122 boost::intrusive_ptr<UniTensor_base> out(tmp);
1123 return out;
1124 };
1125
1126 unsigned int dtype() const {
1127 #ifdef UNI_DEBUG
1128 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1129 "\n");
1130 #endif
1131 return this->_blocks[0].dtype();
1132 };
1133 int device() const {
1134 #ifdef UNI_DEBUG
1135 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1136 "\n");
1137 #endif
1138 return this->_blocks[0].device();
1139 };
1140 std::string dtype_str() const {
1141 #ifdef UNI_DEBUG
1142 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1143 "\n");
1144 #endif
1145 return this->_blocks[0].dtype_str();
1146 };
1147 std::string device_str() const {
1148 #ifdef UNI_DEBUG
1149 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1150 "\n");
1151 #endif
1152 return this->_blocks[0].device_str();
1153 };
1154
1155 Tensor get_block(const cytnx_uint64 &idx = 0) const {
1156 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1157 "\n");
1158 return this->_blocks[idx].clone();
1159 };
1160
1161 // this one for Block will return the indicies!!
1162 Tensor get_block(const std::vector<cytnx_int64> &indices, const bool &force_return) const {
1163 cytnx_error_msg(indices.size() != this->rank(),
1164 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1165 "Tensor rank (number of legs).%s",
1166 "\n");
1167
1168 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1169
1170 // find if the indices specify exists!
1171 cytnx_int64 b = -1;
1172 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1173 if (inds == this->_inner_to_outer_idx[i]) {
1174 b = i;
1175 break;
1176 }
1177 }
1178
1179 if (b < 0) {
1180 if (force_return) {
1181 return NullRefTensor;
1182 } else {
1184 true,
1185 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, force_return=false, so "
1186 "error throws. \n If you want to return an empty block without error when block is "
1187 "not avaliable, set force_return=True.%s",
1188 "\n");
1189 }
1190 } else {
1191 return this->_blocks[b].clone();
1192 }
1193 }
1194
1195 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const {
1196 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1197 "\n");
1198 return this->_blocks[idx];
1199 };
1200
1201 Tensor &get_block_(const cytnx_uint64 &idx = 0) {
1202 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1203 "\n");
1204 return this->_blocks[idx];
1205 };
1206
1207 const Tensor &get_block_(const std::vector<cytnx_int64> &indices,
1208 const bool &force_return) const {
1209 cytnx_error_msg(indices.size() != this->rank(),
1210 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1211 "Tensor rank (number of legs).%s",
1212 "\n");
1213
1214 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1215
1216 // find if the indices specify exists!
1217 cytnx_int64 b = -1;
1218 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1219 if (inds == this->_inner_to_outer_idx[i]) {
1220 b = i;
1221 break;
1222 }
1223 }
1224
1225 if (b < 0) {
1226 if (force_return) {
1227 return this->NullRefTensor;
1228 } else {
1230 true,
1231 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, force_return=false, so "
1232 "error throws. \n If you want to return an empty block without error when block is "
1233 "not avaliable, set force_return=True.%s",
1234 "\n");
1235 }
1236 } else {
1237 return this->_blocks[b];
1238 }
1239 }
1240
1241 Tensor &get_block_(const std::vector<cytnx_int64> &indices, const bool &force_return) {
1242 cytnx_error_msg(indices.size() != this->rank(),
1243 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1244 "Tensor rank (number of legs).%s",
1245 "\n");
1246
1247 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1248
1249 // find if the indices specify exists!
1250 cytnx_int64 b = -1;
1251 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1252 if (inds == this->_inner_to_outer_idx[i]) {
1253 b = i;
1254 break;
1255 }
1256 }
1257
1258 if (b < 0) {
1259 if (force_return) {
1260 return this->NullRefTensor;
1261 } else {
1263 true,
1264 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, force_return=false, so "
1265 "error throws. \n If you want to return an empty block without error when block is "
1266 "not avaliable, set force_return=True.%s",
1267 "\n");
1268 }
1269 } else {
1270 return this->_blocks[b];
1271 }
1272 }
1273
1274 std::vector<Tensor> get_blocks() const { return vec_clone(this->_blocks); }
1275 const std::vector<Tensor> &get_blocks_(const bool &) const { return this->_blocks; }
1276 std::vector<Tensor> &get_blocks_(const bool &) { return this->_blocks; }
1277
1278 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const {
1279 if (rhs->uten_type() != UTenType.Block) return false;
1280 if (rhs->get_blocks_(1).size() != this->get_blocks_(1).size()) return false;
1281
1282 for (int i = 0; i < rhs->get_blocks_(1).size(); i++)
1283 if (this->get_blocks_(1)[i].same_data(rhs->get_blocks_(1)[i]) == false) return false;
1284
1285 return true;
1286 }
1287
1288 void set_rowrank_(const cytnx_uint64 &new_rowrank) {
1289 cytnx_error_msg(new_rowrank > this->rank(),
1290 "[ERROR][BlockUniTensor] rowrank should be [>=0] and [<=UniTensor.rank].%s",
1291 "\n");
1292 if (this->is_diag()) {
1293 cytnx_error_msg(new_rowrank != 1,
1294 "[ERROR][BlockUniTensor] rowrank should be [==1] when is_diag =true!.%s",
1295 "\n");
1296 }
1297 this->_rowrank = new_rowrank;
1298 this->_is_braket_form = this->_update_braket();
1299 }
1300
1301 boost::intrusive_ptr<UniTensor_base> set_rowrank(const cytnx_uint64 &new_rowrank) const {
1302 BlockUniTensor *tmp = this->clone_meta(true, true);
1303 tmp->_blocks = this->_blocks;
1304 tmp->set_rowrank_(new_rowrank);
1305 boost::intrusive_ptr<UniTensor_base> out(tmp);
1306 return out;
1307 }
1308
1309 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
1310 const cytnx_int64 &rowrank = -1);
1311 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
1312 const cytnx_int64 &rowrank = -1);
1313
1314 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
1315 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
1316
1317 boost::intrusive_ptr<UniTensor_base> contiguous_() {
1318 for (unsigned int b = 0; b < this->_blocks.size(); b++) this->_blocks[b].contiguous_();
1319 return boost::intrusive_ptr<UniTensor_base>(this);
1320 }
1321
1322 boost::intrusive_ptr<UniTensor_base> contiguous();
1323
1324 void print_diagram(const bool &bond_info = false);
1325 void print_blocks(const bool &full_info = true) const;
1326 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
1327
1328 boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs,
1329 const bool &mv_elem_self = false,
1330 const bool &mv_elem_rhs = false);
1331
1332 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &new_labels);
1333
1334 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &old_labels,
1335 const std::vector<std::string> &new_labels);
1336
1337 boost::intrusive_ptr<UniTensor_base> relabel(const std::string &old_label,
1338 const std::string &new_label);
1339 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
1340 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 void from_(const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &force);
1627
1628 void group_basis_();
1629
1630 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = false);
1631 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
1632 const bool &by_label);
1633 void combineBonds(const std::vector<std::string> &indicators, const bool &force = false);
1634
1635 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
1637 bidx >= this->Nblocks(),
1638 "[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
1639 this->Nblocks());
1640 return this->_inner_to_outer_idx[bidx];
1641 }
1642 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
1644 bidx >= this->Nblocks(),
1645 "[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
1646 this->Nblocks());
1647 return this->_inner_to_outer_idx[bidx];
1648 }
1649
1650 const vec2d<cytnx_uint64> &get_itoi() const { return this->_inner_to_outer_idx; }
1651 vec2d<cytnx_uint64> &get_itoi() { return this->_inner_to_outer_idx; }
1652 };
1654 //======================================================================
1655
1657 class UniTensor_options {
1658 public:
1659 bool _is_diag;
1660 int _dtype;
1661 int _device;
1662 int _rowrank;
1663
1664 UniTensor_options() {
1665 this->_is_diag = false;
1666 this->_dtype = Type.Double;
1667 this->_device = Device.cpu;
1668 this->_rowrank = -1;
1669 }
1670
1671 UniTensor_options(const UniTensor_options &rhs) {
1672 this->_is_diag = rhs._is_diag;
1673 this->_dtype = rhs._dtype;
1674 this->_device = rhs._device;
1675 this->_rowrank = rhs._rowrank;
1676 }
1677
1678 UniTensor_options &operator=(const UniTensor_options &rhs) {
1679 this->_is_diag = rhs._is_diag;
1680 this->_dtype = rhs._dtype;
1681 this->_device = rhs._device;
1682 this->_rowrank = rhs._rowrank;
1683 return *this;
1684 }
1685
1686 UniTensor_options &is_diag(const bool &in) {
1687 this->_is_diag = in;
1688 return *this;
1689 }
1690 UniTensor_options &dtype(const int &in) {
1691 this->_dtype = in;
1692 return *this;
1693 }
1694 UniTensor_options &device(const int &in) {
1695 this->_device = in;
1696 return *this;
1697 }
1698 UniTensor_options &rowrank(const int &in) {
1699 this->_rowrank = in;
1700 return *this;
1701 }
1702 };
1704
1707 public:
1709 boost::intrusive_ptr<UniTensor_base> _impl;
1710 UniTensor() : _impl(new UniTensor_base()){};
1711 UniTensor(const UniTensor &rhs) { this->_impl = rhs._impl; }
1712 UniTensor &operator=(const UniTensor &rhs) {
1713 this->_impl = rhs._impl;
1714 return *this;
1715 }
1717
1719
1745 explicit UniTensor(const Tensor &in_tensor, const bool &is_diag = false,
1746 const cytnx_int64 &rowrank = -1,
1747 const std::vector<std::string> &in_labels = {}, const std::string &name = "")
1748 : _impl(new UniTensor_base()) {
1749 this->Init(in_tensor, is_diag, rowrank, in_labels, name);
1750 }
1768 void Init(const Tensor &in_tensor, const bool &is_diag = false, const cytnx_int64 &rowrank = -1,
1769 const std::vector<std::string> &in_labels = {}, const std::string &name = "") {
1770 // std::cout << "[entry!]" << std::endl;
1771 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
1772 out->Init_by_Tensor(in_tensor, is_diag, rowrank, name);
1773 this->_impl = out;
1774 if (in_labels.size() != 0) this->set_labels(in_labels);
1775 }
1777
1779
1796 UniTensor(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1797 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1798 const int &device = Device.cpu, const bool &is_diag = false,
1799 const std::string &name = "")
1800 : _impl(new UniTensor_base()) {
1801 #ifdef UNI_DEBUG
1803 true,
1804 "[DEBUG] message: entry for UniTensor(const std::vector<Bond> &bonds, const "
1805 "std::vector<std::string> &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int "
1806 "&dtype=Type.Double, const int &device = Device.cpu, const bool &is_diag=false)%s",
1807 "\n");
1808 #endif
1809 this->Init(bonds, in_labels, rowrank, dtype, device, is_diag, name);
1810 }
1811
1813 /* [developing]
1814 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1815 const UniTensor_options &UToptions = UniTensor_options(), const std::string &name =
1816 ""){ this->Init(bonds,in_labels, UToptions._rowrank, UToptions._dtype , UToptions._device ,
1817 UToptions._is_diag,
1818 name);
1819 }
1820 */
1822
1846 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1847 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1848 const int &device = Device.cpu, const bool &is_diag = false,
1849 const std::string &name = "") {
1850 // checking type:
1851 bool is_sym = false;
1852 int sym_fver = -1;
1853
1854 for (cytnx_uint64 i = 0; i < bonds.size(); i++) {
1855 // check
1856 if (bonds[i].syms().size() != 0) {
1857 is_sym = true;
1858 if (sym_fver == -1)
1859 sym_fver = bonds[i]._impl->_degs.size();
1860 else {
1861 // std::cout << sym_fver << " " <<
1862 // bonds[i]._impl->_degs.size() << std::endl;
1863 cytnx_error_msg((bool(sym_fver) ^ bool(bonds[i]._impl->_degs.size())),
1864 "[ERROR] All the Bond when init a UniTensor with symmetric must be in "
1865 "the same format!%s",
1866 "\n");
1867 }
1868 } else
1870 is_sym, "[ERROR] cannot have bonds with mixing of symmetry and non-symmetry.%s", "\n");
1871 }
1872
1873 // dynamical dispatch:
1874 if (is_sym) {
1875 #ifdef UNI_DEBUG
1876 cytnx_warning_msg(true, "[DEBUG] message: entry dispatch: UniTensor: symmetric%s", "\n");
1877 #endif
1878 // cytnx_warning_msg(true,"[warning, still developing, some functions will display
1879 // \"[Developing]\"][SparseUniTensor]%s","\n");
1880 if (sym_fver == 0) {
1881 // boost::intrusive_ptr<UniTensor_base> out(new SparseUniTensor());
1882 // this->_impl = out;
1883 cytnx_error_msg(true,
1884 "[ERROR] internal error! [legacy Sparse entry] the Bond is symmetry but "
1885 "the version is not properly determined!%s",
1886 "\n")
1887 } else if (sym_fver == -1) {
1888 cytnx_error_msg(true,
1889 "[ERROR] internal error! the Bond is symmetry but the version is not "
1890 "properly determined!%s",
1891 "\n");
1892 } else {
1893 boost::intrusive_ptr<UniTensor_base> out(new BlockUniTensor());
1894 this->_impl = out;
1895 }
1896 } else {
1897 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
1898 this->_impl = out;
1899 }
1900 this->_impl->Init(bonds, in_labels, rowrank, dtype, device, is_diag, false, name);
1901 }
1902
1909 UniTensor &set_name(const std::string &in) {
1910 this->_impl->set_name(in);
1911 return *this;
1912 }
1913
1924 UniTensor &set_label(const cytnx_int64 &idx, const std::string &new_label) {
1925 this->_impl->set_label(idx, new_label);
1926 return *this;
1927 }
1928
1933 this->_impl->set_label(idx, std::string(new_label));
1934 return *this;
1935 }
1936
1947 UniTensor &set_label(const std::string &old_label, const std::string &new_label) {
1948 this->_impl->set_label(old_label, new_label);
1949 return *this;
1950 }
1951
1955 UniTensor &set_label(const char *old_label, const std::string &new_label) {
1956 this->_impl->set_label(std::string(old_label), new_label);
1957 return *this;
1958 }
1959
1963 UniTensor &set_label(const std::string &old_label, const char *new_label) {
1964 this->_impl->set_label(old_label, std::string(new_label));
1965 return *this;
1966 }
1967
1971 UniTensor &set_label(const char *old_label, const char *new_label) {
1972 this->_impl->set_label(std::string(old_label), std::string(new_label));
1973 return *this;
1974 }
1975
1976 /*
1977 UniTensor& change_label(const cytnx_int64 &old_lbl, const cytnx_int64 &new_label){
1978 this->_impl->change_label(old_lbl,new_label);
1979 return *this;
1980 }
1981 */
1982
1992 UniTensor &set_labels(const std::vector<std::string> &new_labels) {
1993 this->_impl->set_labels(new_labels);
1994 return *this;
1995 }
1996
2001 UniTensor &set_labels(const std::initializer_list<char *> &new_labels) {
2002 std::vector<char *> new_lbls(new_labels);
2003 std::vector<std::string> vs(new_lbls.size());
2004 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2005 [](char *x) -> std::string { return std::string(x); });
2006
2007 this->_impl->set_labels(vs);
2008 return *this;
2009 }
2010
2018 this->_impl->set_rowrank_(new_rowrank);
2019 return *this;
2020 }
2021
2023 UniTensor out;
2024 out._impl = this->_impl->set_rowrank(new_rowrank);
2025 return out;
2026 }
2027
2028 template <class T>
2029 T &item() {
2031 "[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use "
2032 "get_block()/get_blocks() first.%s",
2033 "\n");
2034
2035 DenseUniTensor *tmp = static_cast<DenseUniTensor *>(this->_impl.get());
2036 return tmp->_block.item<T>();
2037 }
2038
2039 Scalar::Sproxy item() const {
2041 "[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use "
2042 "get_block()/get_blocks() first.%s",
2043 "\n");
2044
2045 DenseUniTensor *tmp = static_cast<DenseUniTensor *>(this->_impl.get());
2046 return tmp->_block.item();
2047 }
2052 cytnx_uint64 Nblocks() const { return this->_impl->Nblocks(); }
2053
2058 cytnx_uint64 rank() const { return this->_impl->rank(); }
2059
2064 cytnx_uint64 rowrank() const { return this->_impl->rowrank(); }
2065
2071 unsigned int dtype() const { return this->_impl->dtype(); }
2072
2079 int uten_type() const { return this->_impl->uten_type(); }
2080
2086 int device() const { return this->_impl->device(); }
2087
2092 std::string name() const { return this->_impl->name(); }
2093
2099 std::string dtype_str() const { return this->_impl->dtype_str(); }
2100
2106 std::string device_str() const { return this->_impl->device_str(); }
2107
2113 std::string uten_type_str() const { return this->_impl->uten_type_str(); }
2114
2120 bool is_contiguous() const { return this->_impl->is_contiguous(); }
2121
2126 bool is_diag() const { return this->_impl->is_diag(); }
2127
2133 bool is_tag() const { return this->_impl->is_tag(); }
2134
2140 std::vector<Symmetry> syms() const { return this->_impl->syms(); }
2141
2148 const bool &is_braket_form() const { return this->_impl->is_braket_form(); }
2149
2154 const std::vector<std::string> &labels() const { return this->_impl->labels(); }
2161 cytnx_int64 get_index(std::string lbl) const { return this->_impl->get_index(lbl); }
2162
2167 const std::vector<Bond> &bonds() const { return this->_impl->bonds(); }
2168
2172 std::vector<Bond> &bonds() { return this->_impl->bonds(); }
2173
2174 const Bond &bond_(const cytnx_uint64 &idx) const { return this->_impl->bond_(idx); }
2175 Bond &bond_(const cytnx_uint64 &idx) { return this->_impl->bond_(idx); }
2176
2177 const Bond &bond_(const std::string &lbl) const { return this->_impl->bond_(lbl); }
2178 Bond &bond_(const std::string &lbl) { return this->_impl->bond_(lbl); }
2179
2180 Bond bond(const cytnx_uint64 &idx) const { return this->_impl->bond_(idx).clone(); }
2181 Bond bond(const std::string &lbl) const { return this->_impl->bond_(lbl).clone(); }
2182
2187 std::vector<cytnx_uint64> shape() const { return this->_impl->shape(); }
2188
2194 bool is_blockform() const { return this->_impl->is_blockform(); }
2195
2202 void to_(const int &device) { this->_impl->to_(device); }
2203
2213 UniTensor to(const int &device) const {
2214 UniTensor out;
2215 out._impl = this->_impl->to(device);
2216 return out;
2217 }
2218
2224 UniTensor out;
2225 out._impl = this->_impl->clone();
2226 return out;
2227 }
2228
2238 UniTensor &relabels_(const std::vector<std::string> &new_labels) {
2239 this->_impl->relabels_(new_labels);
2240 return *this;
2241 }
2242
2254 UniTensor relabels(const std::vector<std::string> &new_labels) const {
2255 UniTensor out;
2256 out._impl = this->_impl->relabels(new_labels);
2257 return out;
2258 }
2259
2263 UniTensor relabels(const std::initializer_list<char *> &new_lbls) const {
2264 std::vector<char *> new_labels(new_lbls);
2265 std::vector<std::string> vs(new_labels.size());
2266 transform(new_labels.begin(), new_labels.end(), vs.begin(),
2267 [](char *x) -> std::string { return std::string(x); });
2268
2269 UniTensor out;
2270 out._impl = this->_impl->relabels(vs);
2271 return out;
2272 }
2276 UniTensor &relabels_(const std::initializer_list<char *> &new_lbls) {
2277 std::vector<char *> new_labels(new_lbls);
2278 std::vector<std::string> vs(new_labels.size());
2279 transform(new_labels.begin(), new_labels.end(), vs.begin(),
2280 [](char *x) -> std::string { return std::string(x); });
2281
2282 this->_impl->relabels_(vs);
2283 return *this;
2284 }
2285
2293 UniTensor relabels(const std::vector<std::string> &old_labels,
2294 const std::vector<std::string> &new_labels) const {
2295 UniTensor out;
2296 out._impl = this->_impl->relabels(old_labels, new_labels);
2297 return out;
2298 }
2299
2315 UniTensor &relabels_(const std::vector<std::string> &old_labels,
2316 const std::vector<std::string> &new_labels) {
2317 this->_impl->relabels_(old_labels, new_labels);
2318 return *this;
2319 }
2320
2325 UniTensor relabels(const std::initializer_list<char *> &old_lbls,
2326 const std::initializer_list<char *> &new_lbls) const {
2327 std::vector<char *> new_labels(new_lbls);
2328 std::vector<std::string> vs(new_labels.size());
2329 transform(new_labels.begin(), new_labels.end(), vs.begin(),
2330 [](char *x) -> std::string { return std::string(x); });
2331
2332 std::vector<char *> old_labels(old_lbls);
2333 std::vector<std::string> vs_old(old_labels.size());
2334 transform(old_labels.begin(), old_labels.end(), vs_old.begin(),
2335 [](char *x) -> std::string { return std::string(x); });
2336
2337 return this->relabels(vs_old, vs);
2338 }
2339
2344 UniTensor &relabels_(const std::initializer_list<char *> &old_lbls,
2345 const std::initializer_list<char *> &new_lbls) {
2346 std::vector<char *> new_labels(new_lbls);
2347 std::vector<std::string> vs(new_labels.size());
2348 transform(new_labels.begin(), new_labels.end(), vs.begin(),
2349 [](char *x) -> std::string { return std::string(x); });
2350
2351 std::vector<char *> old_labels(old_lbls);
2352 std::vector<std::string> vs_old(old_labels.size());
2353 transform(old_labels.begin(), old_labels.end(), vs_old.begin(),
2354 [](char *x) -> std::string { return std::string(x); });
2355
2356 this->relabels_(vs_old, vs);
2357 return *this;
2358 }
2359
2374 UniTensor relabel(const cytnx_int64 &inx, const std::string &new_label) const {
2375 UniTensor out;
2376 out._impl = this->_impl->relabel(inx, new_label);
2377 return out;
2378 }
2387 UniTensor &relabel_(const cytnx_int64 &inx, const std::string &new_label) {
2388 this->_impl->relabel_(inx, new_label);
2389 return *this;
2390 }
2391
2400 UniTensor &relabel_(const std::string &old_label, const std::string &new_label) {
2401 this->_impl->relabel_(old_label, new_label);
2402 return *this;
2403 }
2404
2419 UniTensor relabel(const std::string &old_label, const std::string &new_label) const {
2420 UniTensor out;
2421 out._impl = this->_impl->relabel(old_label, new_label);
2422 return out;
2423 }
2424
2431 UniTensor astype(const unsigned int &dtype) const {
2432 UniTensor out;
2433 if (this->dtype() == dtype) {
2434 out._impl = this->_impl;
2435 } else {
2436 out._impl = this->_impl->astype(dtype);
2437 }
2438 return out;
2439 }
2440
2449 UniTensor permute(const std::vector<cytnx_int64> &mapper,
2450 const cytnx_int64 &rowrank = -1) const {
2451 UniTensor out;
2452 out._impl = this->_impl->permute(mapper, rowrank);
2453 return out;
2454 }
2455
2462 UniTensor permute(const std::vector<std::string> &mapper,
2463 const cytnx_int64 &rowrank = -1) const {
2464 UniTensor out;
2465 out._impl = this->_impl->permute(mapper, rowrank);
2466 return out;
2467 }
2468
2472 UniTensor permute(const std::initializer_list<char *> &mapper,
2473 const cytnx_int64 &rowrank = -1) const {
2474 std::vector<char *> mprs = mapper;
2475 std::vector<std::string> vs(mprs.size());
2476 transform(mprs.begin(), mprs.end(), vs.begin(),
2477 [](char *x) -> std::string { return std::string(x); });
2478
2479 return this->permute(vs, rowrank);
2480 }
2481
2490 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1) {
2491 this->_impl->permute_(mapper, rowrank);
2492 }
2493
2500 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1) {
2501 this->_impl->permute_(mapper, rowrank);
2502 }
2503
2504 // void permute_( const std::initializer_list<char*> &mapper, const cytnx_int64 &rowrank= -1){
2505 // std::vector<char*> mprs = mapper;
2506 // std::vector<std::string> vs(mprs.size());
2507 // transform(mprs.begin(),mprs.end(),vs.begin(),[](char * x) -> std::string { return
2508 // std::string(x); });
2509
2510 // this->permute_(vs,rowrank);
2511 // }
2512
2513 // void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1) {
2514 // this->_impl->permute_(mapper, rowrank);
2515 // }
2516
2522 UniTensor out;
2523 out._impl = this->_impl->contiguous();
2524 return out;
2525 }
2526
2531 void contiguous_() { this->_impl = this->_impl->contiguous_(); }
2532
2537 void print_diagram(const bool &bond_info = false) { this->_impl->print_diagram(bond_info); }
2538
2543 void print_blocks(const bool &full_info = true) const { this->_impl->print_blocks(full_info); }
2544
2550 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const {
2551 this->_impl->print_block(idx, full_info);
2552 }
2553
2560 void group_basis_() { this->_impl->group_basis_(); }
2561
2563 UniTensor out = this->clone();
2564 out.group_basis_();
2565 return out;
2566 }
2567
2573 template <class T>
2574 T &at(const std::vector<cytnx_uint64> &locator) {
2575 // std::cout << "at " << this->is_blockform() << std::endl;
2576 if (this->uten_type() == UTenType.Block) {
2577 // [NEW] this will not check if it exists, if it is not then error will throw!
2578 T aux;
2579 return this->_impl->at_for_sparse(locator, aux);
2580
2581 } else if (this->uten_type() == UTenType.Sparse) {
2582 if (this->_impl->elem_exists(locator)) {
2583 T aux;
2584 return this->_impl->at_for_sparse(locator, aux);
2585 } else {
2586 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2587 "\n");
2588 }
2589 } else {
2590 return this->get_block_().at<T>(locator);
2591 }
2592 }
2593
2599 template <class T>
2600 const T &at(const std::vector<cytnx_uint64> &locator) const {
2601 // std::cout << "at " << this->is_blockform() << std::endl;
2602 if (this->uten_type() == UTenType.Block) {
2603 // [NEW] this will not check if it exists, if it is not then error will throw!
2604 T aux;
2605 return this->_impl->at_for_sparse(locator, aux);
2606
2607 } else if (this->uten_type() == UTenType.Sparse) {
2608 if (this->_impl->elem_exists(locator)) {
2609 T aux; // [workaround] use aux to dispatch.
2610 return this->_impl->at_for_sparse(locator, aux);
2611 } else {
2612 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2613 "\n");
2614 }
2615 } else {
2616 return this->get_block_().at<T>(locator);
2617 }
2618 }
2619
2620 template <class T>
2621 const T &at(const std::vector<std::string> &lbls,
2622 const std::vector<cytnx_uint64> &locator) const {
2623 // giving label <-> locator one to one corresponding, return the element:
2624 cytnx_error_msg(locator.size() != lbls.size(),
2625 "[ERROR][at] length of list should be the same for label and locator.%s",
2626 "\n");
2628 lbls.size() != this->rank(),
2629 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
2630 std::vector<cytnx_uint64> new_locator(this->rank());
2632 for (int i = 0; i < lbls.size(); i++) {
2633 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), lbls[i]);
2634 cytnx_error_msg(res == this->_impl->_labels.end(),
2635 "[ERROR] lbl:%s does not exist in current UniTensor.\n", lbls[i].c_str());
2636 new_loc = std::distance(this->_impl->_labels.begin(), res);
2638 }
2639 return this->at<T>(new_locator);
2640 }
2641 template <class T>
2642 T &at(const std::vector<std::string> &lbls, const std::vector<cytnx_uint64> &locator) {
2643 // giving label <-> locator one to one corresponding, return the element:
2644 cytnx_error_msg(locator.size() != lbls.size(),
2645 "[ERROR][at] length of list should be the same for label and locator.%s",
2646 "\n");
2648 lbls.size() != this->rank(),
2649 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
2650 std::vector<cytnx_uint64> new_locator(this->rank());
2652 for (int i = 0; i < lbls.size(); i++) {
2653 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), lbls[i]);
2654 cytnx_error_msg(res == this->_impl->_labels.end(),
2655 "[ERROR] lbl:%s does not exist in current UniTensor.\n", lbls[i].c_str());
2656 new_loc = std::distance(this->_impl->_labels.begin(), res);
2658 }
2659 return this->at<T>(new_locator);
2660 }
2661
2666 const Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) const {
2667 if (this->uten_type() == UTenType.Block) {
2668 return this->_impl->at_for_sparse(locator);
2669 } else if (this->uten_type() == UTenType.Sparse) {
2670 if (this->_impl->elem_exists(locator)) {
2671 return this->_impl->at_for_sparse(locator);
2672 } else {
2673 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2674 "\n");
2675 }
2676 } else {
2677 return this->get_block_().at(locator);
2678 }
2679 }
2680
2685 Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) {
2686 if (this->uten_type() == UTenType.Block) {
2687 return this->_impl->at_for_sparse(locator);
2688 } else if (this->uten_type() == UTenType.Sparse) {
2689 if (this->_impl->elem_exists(locator)) {
2690 return this->_impl->at_for_sparse(locator);
2691 } else {
2692 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2693 "\n");
2694 }
2695 } else {
2696 return this->get_block_().at(locator);
2697 }
2698 }
2699
2700 Scalar::Sproxy at(const std::vector<std::string> &lbls,
2701 const std::vector<cytnx_uint64> &locator) {
2702 // giving label <-> locator one to one corresponding, return the element:
2703 cytnx_error_msg(locator.size() != lbls.size(),
2704 "[ERROR][at] length of list should be the same for label and locator.%s",
2705 "\n");
2707 lbls.size() != this->rank(),
2708 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
2709 std::vector<cytnx_uint64> new_locator(this->rank());
2711 for (int i = 0; i < lbls.size(); i++) {
2712 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), lbls[i]);
2713 cytnx_error_msg(res == this->_impl->_labels.end(),
2714 "[ERROR] lbl:%s does not exist in current UniTensor.\n", lbls[i].c_str());
2715 new_loc = std::distance(this->_impl->_labels.begin(), res);
2717 }
2718 return this->at(new_locator);
2719 }
2720
2721 const Scalar::Sproxy at(const std::vector<std::string> &lbls,
2722 const std::vector<cytnx_uint64> &locator) const {
2723 // giving label <-> locator one to one corresponding, return the element:
2724 cytnx_error_msg(locator.size() != lbls.size(),
2725 "[ERROR][at] length of list should be the same for label and locator.%s",
2726 "\n");
2728 lbls.size() != this->rank(),
2729 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
2730 std::vector<cytnx_uint64> new_locator(this->rank());
2732 for (int i = 0; i < lbls.size(); i++) {
2733 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), lbls[i]);
2734 cytnx_error_msg(res == this->_impl->_labels.end(),
2735 "[ERROR] lbl:%s does not exist in current UniTensor.\n", lbls[i].c_str());
2736 new_loc = std::distance(this->_impl->_labels.begin(), res);
2738 }
2739 return this->at(new_locator);
2740 }
2741
2742 // return a clone of block
2748 Tensor get_block(const cytnx_uint64 &idx = 0) const { return this->_impl->get_block(idx); };
2749 //================================
2750 // return a clone of block
2759 Tensor get_block(const std::vector<cytnx_int64> &qidx, const bool &force = false) const {
2760 return this->_impl->get_block(qidx, force);
2761 }
2762
2763 Tensor get_block(const std::vector<std::string> &lbls, const std::vector<cytnx_int64> &qidx,
2764 const bool &force = false) const {
2766 lbls.size() != qidx.size(),
2767 "[ERROR][get_block] length of lists must be the same for both lables and qnidices%s", "\n");
2768 cytnx_error_msg(lbls.size() != this->rank(),
2769 "[ERROR][get_block] length of lists must be the rank (# of legs)%s", "\n");
2770
2771 std::vector<cytnx_int64> loc_id(this->rank());
2772 std::vector<cytnx_int64> new_qidx(this->rank());
2773
2775 std::vector<cytnx_uint64> new_order(this->rank());
2776 for (int i = 0; i < lbls.size(); i++) {
2777 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), lbls[i]);
2778 cytnx_error_msg(res == this->_impl->_labels.end(),
2779 "[ERROR][get_block] label:%s does not exists in current Tensor.\n",
2780 lbls[i].c_str());
2781 new_loc = std::distance(this->_impl->_labels.begin(), res);
2782 new_qidx[new_loc] = qidx[i];
2783 new_order[i] = new_loc;
2784 }
2785 auto out = this->_impl->get_block(new_qidx, force);
2786 if (out.dtype() != Type.Void) out.permute_(new_order);
2787 return out;
2788 }
2789
2794 Tensor get_block(const std::initializer_list<cytnx_int64> &qnum,
2795 const bool &force = false) const {
2796 std::vector<cytnx_int64> tmp = qnum;
2797 return get_block(tmp, force);
2798 }
2799
2804 Tensor get_block(const std::vector<cytnx_uint64> &qnum, const bool &force = false) const {
2805 std::vector<cytnx_int64> iqnum(qnum.begin(), qnum.end());
2806 return this->_impl->get_block(iqnum, force);
2807 }
2808
2809 Tensor get_block(const std::vector<std::string> &lbls, const std::vector<cytnx_uint64> &qidx,
2810 const bool &force = false) const {
2811 std::vector<cytnx_int64> iqnum(qidx.begin(), qidx.end());
2812 return this->get_block(lbls, iqnum, force);
2813 }
2814
2820 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const {
2821 return this->_impl->get_block_(idx);
2822 }
2823
2828 Tensor &get_block_(const cytnx_uint64 &idx = 0) { return this->_impl->get_block_(idx); }
2829
2838 Tensor &get_block_(const std::vector<cytnx_int64> &qidx, const bool &force = false) {
2839 return this->_impl->get_block_(qidx, force);
2840 }
2841
2855 // developer note: Tensor is not the same object (Thus Tensor instead of Tensor& ),
2856 // since we permute! but they have shared data memory.
2857 Tensor get_block_(const std::vector<std::string> &lbls, const std::vector<cytnx_int64> &qidx,
2858 const bool &force = false) {
2860 lbls.size() != qidx.size(),
2861 "[ERROR][get_block] length of lists must be the same for both lables and qnidices%s", "\n");
2862 cytnx_error_msg(lbls.size() != this->rank(),
2863 "[ERROR][get_block] length of lists must be the rank (# of legs)%s", "\n");
2864
2865 std::vector<cytnx_int64> loc_id(this->rank());
2866 std::vector<cytnx_int64> new_qidx(this->rank());
2867
2869 std::vector<cytnx_uint64> new_order(this->rank());
2870 for (int i = 0; i < lbls.size(); i++) {
2871 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), lbls[i]);
2872 cytnx_error_msg(res == this->_impl->_labels.end(),
2873 "[ERROR][get_block] label:%s does not exists in current Tensor.\n",
2874 lbls[i].c_str());
2875 new_loc = std::distance(this->_impl->_labels.begin(), res);
2876 new_qidx[new_loc] = qidx[i];
2877 new_order[i] = new_loc;
2878 }
2879 auto out = this->_impl->get_block_(new_qidx, force);
2880 if (out.dtype() != Type.Void) {
2881 out = out.permute(new_order);
2882 }
2883 return out;
2884 }
2885
2889 Tensor &get_block_(const std::initializer_list<cytnx_int64> &qidx, const bool &force = false) {
2890 std::vector<cytnx_int64> tmp = qidx;
2891 return get_block_(tmp, force);
2892 }
2893
2897 Tensor &get_block_(const std::vector<cytnx_uint64> &qidx, const bool &force = false) {
2898 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
2899 return get_block_(iqidx, force);
2900 }
2901
2902 Tensor get_block_(const std::vector<std::string> &lbls, const std::vector<cytnx_uint64> &qidx,
2903 const bool &force = false) {
2904 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
2905 return get_block_(lbls, iqidx, force);
2906 }
2907 //================================
2908
2909 // this only work for non-symm tensor. return a shared view of block
2913 const Tensor &get_block_(const std::vector<cytnx_int64> &qidx,
2914 const bool &force = false) const {
2915 return this->_impl->get_block_(qidx, force);
2916 }
2917
2921 const Tensor &get_block_(const std::initializer_list<cytnx_int64> &qidx,
2922 const bool &force = false) const {
2923 std::vector<cytnx_int64> tmp = qidx;
2924 return this->_impl->get_block_(tmp, force);
2925 }
2926
2930 const Tensor &get_block_(const std::vector<cytnx_uint64> &qidx,
2931 const bool &force = false) const {
2932 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
2933 return get_block_(iqidx, force);
2934 }
2935
2936 //================================
2945 //[dev]
2946 std::vector<Tensor> get_blocks() const { return this->_impl->get_blocks(); }
2947
2953 //[dev]
2954 const std::vector<Tensor> &get_blocks_(const bool &silent = false) const {
2955 return this->_impl->get_blocks_(silent);
2956 }
2957
2961 //[dev]
2962 std::vector<Tensor> &get_blocks_(const bool &silent = false) {
2963 return this->_impl->get_blocks_(silent);
2964 }
2965
2972 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
2973 this->_impl->put_block(in, idx);
2974 }
2975
2984 void put_block(const Tensor &in_tens, const std::vector<cytnx_int64> &qidx, const bool &force) {
2985 this->_impl->put_block(in_tens, qidx, force);
2986 }
2987
2993 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) { this->_impl->put_block_(in, idx); }
2994
3001 void put_block_(Tensor &in, const std::vector<cytnx_int64> &qidx, const bool &force) {
3002 this->_impl->put_block_(in, qidx, force);
3003 }
3004 UniTensor get(const std::vector<Accessor> &accessors) const {
3005 UniTensor out;
3006 out._impl = this->_impl->get(accessors);
3007 return out;
3008 }
3009 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
3010 this->_impl->set(accessors, rhs);
3011 }
3012
3020 UniTensor reshape(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
3021 UniTensor out;
3022 out._impl = this->_impl->reshape(new_shape, rowrank);
3023 return out;
3024 }
3025
3032 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
3033 this->_impl->reshape_(new_shape, rowrank);
3034 }
3035
3048 UniTensor out;
3049 out._impl = this->_impl->to_dense();
3050 return out;
3051 }
3052
3057 void to_dense_() { this->_impl->to_dense_(); }
3058
3064 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
3065 const bool &by_label) {
3066 this->_impl->combineBonds(indicators, force, by_label);
3067 }
3068
3079 void combineBonds(const std::vector<std::string> &indicators, const bool &force = false) {
3080 this->_impl->combineBonds(indicators, force);
3081 }
3082
3088 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = false) {
3089 this->_impl->combineBonds(indicators, force);
3090 }
3091
3110 UniTensor contract(const UniTensor &inR, const bool &mv_elem_self = false,
3111 const bool &mv_elem_rhs = false) const {
3112 UniTensor out;
3113 out._impl = this->_impl->contract(inR._impl, mv_elem_self, mv_elem_rhs);
3114 return out;
3115 }
3116
3118
3126 std::vector<Bond> getTotalQnums(const bool physical = false) const {
3127 return this->_impl->getTotalQnums(physical);
3128 }
3129
3133 std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const {
3134 return this->_impl->get_blocks_qnums();
3135 }
3137
3142 bool same_data(const UniTensor &rhs) const {
3143 // check same type:
3144 if (this->_impl->uten_type() != rhs._impl->uten_type()) return false;
3145
3146 return this->_impl->same_data(rhs._impl);
3147 }
3148
3166 this->_impl->Add_(rhs._impl);
3167 return *this;
3168 }
3169
3187 this->_impl->Mul_(rhs._impl);
3188 return *this;
3189 }
3190
3208 this->_impl->Sub_(rhs._impl);
3209 return *this;
3210 }
3211
3229 this->_impl->Div_(rhs._impl);
3230 return *this;
3231 }
3232
3244 this->_impl->Add_(rhs);
3245 return *this;
3246 }
3247
3259 this->_impl->Mul_(rhs);
3260 return *this;
3261 }
3262
3274 this->_impl->Sub_(rhs);
3275 return *this;
3276 }
3277
3289 this->_impl->Div_(rhs);
3290 return *this;
3291 }
3292
3310
3321 UniTensor Add(const Scalar &rhs) const;
3322
3340
3351 UniTensor Mul(const Scalar &rhs) const;
3352
3370
3381 UniTensor Div(const Scalar &rhs) const;
3382
3400
3411 UniTensor Sub(const Scalar &rhs) const;
3412
3421 Tensor Norm() const { return this->_impl->Norm(); };
3422
3439 this->Add_(rhs);
3440 return *this;
3441 }
3442
3459 this->Sub_(rhs);
3460 return *this;
3461 }
3462
3479 this->Div_(rhs);
3480 return *this;
3481 }
3482
3499 this->Mul_(rhs);
3500 return *this;
3501 }
3502
3514 this->Add_(rhs);
3515 return *this;
3516 }
3517
3529 this->Sub_(rhs);
3530 return *this;
3531 }
3532
3544 this->Div_(rhs);
3545 return *this;
3546 }
3547
3559 this->Mul_(rhs);
3560 return *this;
3561 }
3562
3570 UniTensor Conj() const {
3571 UniTensor out;
3572 out._impl = this->_impl->Conj();
3573 return out;
3574 }
3575
3584 this->_impl->Conj_();
3585 return *this;
3586 }
3587
3599 UniTensor out;
3600 out._impl = this->_impl->Transpose();
3601 return out;
3602 }
3603
3611 this->_impl->Transpose_();
3612 return *this;
3613 }
3614
3622 UniTensor out;
3623 out._impl = this->_impl->normalize();
3624 return out;
3625 }
3626
3634 this->_impl->normalize_();
3635 return *this;
3636 }
3637
3647 UniTensor Trace(const std::string &a, const std::string &b) const {
3648 UniTensor out;
3649 out._impl = this->_impl->Trace(a, b);
3650 return out;
3651 }
3652
3662 UniTensor Trace(const cytnx_int64 &a = 0, const cytnx_int64 &b = 1) const {
3663 UniTensor out;
3664 out._impl = this->_impl->Trace(a, b);
3665 return out;
3666 }
3667
3677 UniTensor &Trace_(const std::string &a, const std::string &b) {
3678 this->_impl->Trace_(a, b);
3679 if (this->uten_type() == UTenType.Block) {
3680 // handle if no leg left case for BlockUniTensor.
3681 if (this->rank() == 0) {
3682 DenseUniTensor *tmp = new DenseUniTensor();
3683 tmp->_block = this->get_blocks_(true)[0];
3684 this->_impl = boost::intrusive_ptr<UniTensor_base>(tmp);
3685 }
3686 }
3687 return *this;
3688 }
3689
3699 UniTensor &Trace_(const cytnx_int64 &a = 0, const cytnx_int64 &b = 1) {
3700 this->_impl->Trace_(a, b);
3701 if (this->uten_type() == UTenType.Block) {
3702 // handle if no leg left case for BlockUniTensor.
3703 if (this->rank() == 0) {
3704 DenseUniTensor *tmp = new DenseUniTensor();
3705 tmp->_block = this->get_blocks_(true)[0];
3706 this->_impl = boost::intrusive_ptr<UniTensor_base>(tmp);
3707 }
3708 }
3709 return *this;
3710 }
3711
3719 UniTensor out;
3720 out._impl = this->_impl->Dagger();
3721 return out;
3722 }
3723
3731 this->_impl->Dagger_();
3732 return *this;
3733 }
3734
3743 this->_impl->tag();
3744 return *this;
3745 }
3746
3755 UniTensor Pow(const double &p) const;
3756
3765 UniTensor &Pow_(const double &p);
3766
3773 bool elem_exists(const std::vector<cytnx_uint64> &locator) const {
3774 return this->_impl->elem_exists(locator);
3775 }
3776
3782 template <class T>
3783 T get_elem(const std::vector<cytnx_uint64> &locator) const {
3784 return this->at<T>(locator);
3785 }
3786
3792 template <class T2>
3793 void set_elem(const std::vector<cytnx_uint64> &locator, const T2 &rc) {
3794 // cytnx_error_msg(true,"[ERROR] invalid type%s","\n");
3795 this->at(locator) = rc;
3796 }
3797
3804 void Save(const std::string &fname) const;
3805
3812 void Save(const char *fname) const;
3813
3822 static UniTensor Load(const std::string &fname);
3823
3832 static UniTensor Load(const char *fname);
3833
3842 UniTensor &truncate_(const std::string &label, const cytnx_uint64 &dim) {
3843 this->_impl->truncate_(label, dim);
3844 return *this;
3845 }
3846
3856 this->_impl->truncate_(bond_idx, dim);
3857 return *this;
3858 }
3859
3869 UniTensor truncate(const std::string &label, const cytnx_uint64 &dim) const {
3870 UniTensor out = this->clone();
3871 out.truncate_(label, dim);
3872 return out;
3873 }
3874
3885 UniTensor out = this->clone();
3886 out.truncate_(bond_idx, dim);
3887 return out;
3888 }
3889
3897 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
3898 return this->_impl->get_qindices(bidx);
3899 }
3907 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
3908 return this->_impl->get_qindices(bidx);
3909 }
3910
3917 const vec2d<cytnx_uint64> &get_itoi() const { return this->_impl->get_itoi(); }
3918 vec2d<cytnx_uint64> &get_itoi() { return this->_impl->get_itoi(); }
3919
3921 void _Load(std::fstream &f);
3922 void _Save(std::fstream &f) const;
3924
3925 UniTensor &from(const UniTensor &rhs, const bool &force = false) {
3926 this->_impl->from_(rhs._impl, force);
3927 return *this;
3928 }
3929
3930 }; // class UniTensor
3931
3933 std::ostream &operator<<(std::ostream &os, const UniTensor &in);
3935
3948 UniTensor Contract(const UniTensor &inL, const UniTensor &inR, const bool &cacheL = false,
3949 const bool &cacheR = false);
3950
3963 UniTensor Contracts(const std::vector<UniTensor> &TNs, const std::string &order,
3964 const bool &optimal);
3965
3967 void _resolve_CT(std::vector<UniTensor> &TNlist);
3968 template <class... T>
3969 void _resolve_CT(std::vector<UniTensor> &TNlist, const UniTensor &in, const T &...args) {
3970 TNlist.push_back(in);
3971 _resolve_CT(TNlist, args...);
3972 }
3974
3986 template <class... T>
3987 UniTensor Contracts(const UniTensor &in, const T &...args, const std::string &order,
3988 const bool &optimal) {
3989 std::vector<UniTensor> TNlist;
3990 _resolve_CT(TNlist, in, args...);
3991 return Contracts(TNlist, order, optimal);
3992 }
3993
3994} // namespace cytnx
3995
3996#endif // BACKEND_TORCH
3997
3998#endif
the object contains auxiliary properties for each Tensor rank (bond)
Definition Bond.hpp:178
Bond clone() const
return a copy of the instance Bond
Definition Bond.hpp:490
an tensor (multi-dimensional array)
Definition Tensor.hpp:41
void to_(const int &device)
move the current Tensor to the device.
Definition Tensor.hpp:615
Tensor contiguous_()
Make the Tensor contiguous by coalescing the memory (storage), inplacely.
Definition Tensor.hpp:702
unsigned int dtype() const
the dtype-id of the Tensor
Definition Tensor.hpp:514
Tensor contiguous() const
Make the Tensor contiguous by coalescing the memory (storage).
Definition Tensor.hpp:682
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition Tensor.hpp:858
Tensor clone() const
return a clone of the current Tensor.
Definition Tensor.hpp:566
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:993
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:823
const bool & is_contiguous() const
return whether the Tensor is contiguous or not.
Definition Tensor.hpp:621
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:521
Tensor get(const std::vector< cytnx::Accessor > &accessors) const
get elements using Accessor (C++ API) / slices (python API)
Definition Tensor.hpp:961
const std::vector< cytnx_uint64 > & shape() const
the shape of the Tensor
Definition Tensor.hpp:541
An Enhanced tensor specifically designed for physical Tensor network simulation.
Definition UniTensor.hpp:1706
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:2984
UniTensor to(const int &device) const
move the current UniTensor to the assigned device.
Definition UniTensor.hpp:2213
UniTensor & operator*=(const UniTensor &rhs)
The multiplication assignment operator of the UniTensor.
Definition UniTensor.hpp:3498
Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:2889
std::vector< Tensor > & get_blocks_(const bool &silent=false)
Definition UniTensor.hpp:2962
Tensor & get_block_(const std::vector< cytnx_uint64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:2897
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:2550
UniTensor & operator/=(const UniTensor &rhs)
The division assignment operator of the UniTensor.
Definition UniTensor.hpp:3478
T & item()
Definition UniTensor.hpp:2029
bool is_contiguous() const
To tell whether the UniTensor is contiguous.
Definition UniTensor.hpp:2120
T get_elem(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:3783
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:3907
UniTensor & set_label(const cytnx_int64 &idx, const char *new_label)
Definition UniTensor.hpp:1932
UniTensor & operator+=(const UniTensor &rhs)
The addition assignment operator of the UniTensor.
Definition UniTensor.hpp:3438
void to_dense_()
Convert the UniTensor to non-diagonal form, inplacely.
Definition UniTensor.hpp:3057
UniTensor reshape(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor.
Definition UniTensor.hpp:3020
std::vector< Tensor > get_blocks() const
Get all the blocks of the UniTensor.
Definition UniTensor.hpp:2946
UniTensor permute(const std::initializer_list< char * > &mapper, const cytnx_int64 &rowrank=-1) const
Definition UniTensor.hpp:2472
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:2133
cytnx_int64 get_index(std::string lbl) const
Get the index of an desired label string.
Definition UniTensor.hpp:2161
std::string uten_type_str() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor in 'string' form.
Definition UniTensor.hpp:2113
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:1796
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:2759
void permute_(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1)
permute the lags of the UniTensor, inplacely.
Definition UniTensor.hpp:2490
UniTensor & tag()
Set the UniTensor as a tagged UniTensor.
Definition UniTensor.hpp:3742
const Bond & bond_(const cytnx_uint64 &idx) const
Definition UniTensor.hpp:2174
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force=false)
Definition UniTensor.hpp:3088
UniTensor & relabel_(const std::string &old_label, const std::string &new_label)
relabel the lags in the UniTensor by a given label.
Definition UniTensor.hpp:2400
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:1745
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:2838
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:1768
UniTensor get(const std::vector< Accessor > &accessors) const
Definition UniTensor.hpp:3004
UniTensor relabels(const std::initializer_list< char * > &old_lbls, const std::initializer_list< char * > &new_lbls) const
Definition UniTensor.hpp:2325
UniTensor Conj() const
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:3570
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:1947
UniTensor set_rowrank(const cytnx_uint64 &new_rowrank) const
Definition UniTensor.hpp:2022
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:3528
cytnx_uint64 rowrank() const
Return the row rank of the UniTensor.
Definition UniTensor.hpp:2064
UniTensor & relabels_(const std::vector< std::string > &old_labels, const std::vector< std::string > &new_labels)
relables part or all of the labels in UniTensor by given new labels
Definition UniTensor.hpp:2315
const T & at(const std::vector< std::string > &lbls, const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:2621
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:3421
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:2001
UniTensor & Sub_(const Scalar &rhs)
The subtraction function for a given scalar.
Definition UniTensor.hpp:3273
UniTensor & relabel_(const cytnx_int64 &inx, const std::string &new_label)
rebable the lags in the UniTensor by given index.
Definition UniTensor.hpp:2387
UniTensor & operator/=(const Scalar &rhs)
The division assignment operator for a given scalar.
Definition UniTensor.hpp:3543
const bool & is_braket_form() const
Check whether the UniTensor is in braket form.
Definition UniTensor.hpp:2148
void set_elem(const std::vector< cytnx_uint64 > &locator, const T2 &rc)
Definition UniTensor.hpp:3793
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:2187
UniTensor to_dense()
Convert the UniTensor to non-diagonal form.
Definition UniTensor.hpp:3047
UniTensor relabels(const std::initializer_list< char * > &new_lbls) const
Definition UniTensor.hpp:2263
const Tensor & get_block_(const std::vector< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:2913
void reshape_(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor, inplacely.
Definition UniTensor.hpp:3032
UniTensor & set_labels(const std::vector< std::string > &new_labels)
Set new labels for all the bonds.
Definition UniTensor.hpp:1992
void permute_(const std::vector< std::string > &mapper, const cytnx_int64 &rowrank=-1)
permute the lags of the UniTensor, inplacely.
Definition UniTensor.hpp:2500
std::string name() const
Return the name of the UniTensor.
Definition UniTensor.hpp:2092
UniTensor & Add_(const Scalar &rhs)
The addition function for a given scalar.
Definition UniTensor.hpp:3243
UniTensor & Trace_(const std::string &a, const std::string &b)
Take the partial trance to the UniTensor, inplacely.
Definition UniTensor.hpp:3677
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:3855
Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition UniTensor.hpp:2685
UniTensor Trace(const std::string &a, const std::string &b) const
Take the partial trance to the UniTensor.
Definition UniTensor.hpp:3647
Tensor get_block(const std::vector< std::string > &lbls, const std::vector< cytnx_uint64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:2809
bool same_data(const UniTensor &rhs) const
Check whether the Blocks address are the same.
Definition UniTensor.hpp:3142
UniTensor astype(const unsigned int &dtype) const
Return a new UniTensor that cast to different data type.
Definition UniTensor.hpp:2431
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:3869
UniTensor Transpose() const
Take the transpose of the UniTensor.
Definition UniTensor.hpp:3598
UniTensor & set_label(const char *old_label, const std::string &new_label)
Definition UniTensor.hpp:1955
static UniTensor Load(const char *fname)
load a UniTensor from file
UniTensor & Dagger_()
Take the conjugate transpose to the UniTensor, inplacely.
Definition UniTensor.hpp:3730
void print_diagram(const bool &bond_info=false)
Plot the diagram of the UniTensor.
Definition UniTensor.hpp:2537
std::vector< Bond > & bonds()
Definition UniTensor.hpp:2172
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition UniTensor.hpp:2574
UniTensor & set_rowrank_(const cytnx_uint64 &new_rowrank)
Set the row rank of the UniTensor.
Definition UniTensor.hpp:2017
Bond bond(const std::string &lbl) const
Definition UniTensor.hpp:2181
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:1924
UniTensor & from(const UniTensor &rhs, const bool &force=false)
Definition UniTensor.hpp:3925
Bond & bond_(const std::string &lbl)
Definition UniTensor.hpp:2178
UniTensor contiguous() const
Make the UniTensor contiguous by coalescing the memory (storage).
Definition UniTensor.hpp:2521
UniTensor & relabels_(const std::initializer_list< char * > &new_lbls)
Definition UniTensor.hpp:2276
Tensor get_block(const cytnx_uint64 &idx=0) const
Get the block of the UniTensor for a given index.
Definition UniTensor.hpp:2748
const T & at(const std::vector< cytnx_uint64 > &locator) const
Get an element at specific location.
Definition UniTensor.hpp:2600
UniTensor & operator*=(const Scalar &rhs)
The multiplication assignment operator for a given scalar.
Definition UniTensor.hpp:3558
UniTensor relabels(const std::vector< std::string > &old_labels, const std::vector< std::string > &new_labels) const
replace part or all labels by given new labels for the bonds.
Definition UniTensor.hpp:2293
void contiguous_()
Make the UniTensor contiguous by coalescing the memory (storage), inplacely.
Definition UniTensor.hpp:2531
UniTensor normalize() const
normalize the current UniTensor instance with 2-norm.
Definition UniTensor.hpp:3621
std::vector< Symmetry > syms() const
Return the symmetry type of the UniTensor.
Definition UniTensor.hpp:2140
UniTensor & Mul_(const UniTensor &rhs)
The multiplcation function of the UniTensor.
Definition UniTensor.hpp:3186
void put_block_(Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index, inplacely.
Definition UniTensor.hpp:2993
void combineBonds(const std::vector< std::string > &indicators, const bool &force=false)
Combine the sevral bonds of the UniTensor.
Definition UniTensor.hpp:3079
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:2419
UniTensor & normalize_()
normalize the UniTensor, inplacely.
Definition UniTensor.hpp:3633
bool is_diag() const
To tell whether the UniTensor is in diagonal form.
Definition UniTensor.hpp:2126
int device() const
Return the device of the UniTensor.
Definition UniTensor.hpp:2086
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:2930
void set(const std::vector< Accessor > &accessors, const Tensor &rhs)
Definition UniTensor.hpp:3009
std::string dtype_str() const
Return the data type of the UniTensor in 'string' form.
Definition UniTensor.hpp:2099
UniTensor & operator+=(const Scalar &rhs)
The addition assignment operator for a given scalar.
Definition UniTensor.hpp:3513
UniTensor & Div_(const UniTensor &rhs)
The division function of the UniTensor.
Definition UniTensor.hpp:3228
UniTensor & Div_(const Scalar &rhs)
The division function for a given scalar.
Definition UniTensor.hpp:3288
cytnx_uint64 rank() const
Return the rank of the UniTensor.
Definition UniTensor.hpp:2058
void group_basis_()
Group the same quantum number basis together.
Definition UniTensor.hpp:2560
void to_(const int &device)
move the current UniTensor to the assigned device (inplace).
Definition UniTensor.hpp:2202
UniTensor & Trace_(const cytnx_int64 &a=0, const cytnx_int64 &b=1)
Take the partial trance to the UniTensor, inplacely.
Definition UniTensor.hpp:3699
Tensor get_block_(const std::vector< std::string > &lbls, const std::vector< cytnx_int64 > &qidx, const bool &force=false)
Get the shared (data) view of block for the given quantum indices on given labels.
Definition UniTensor.hpp:2857
UniTensor & set_name(const std::string &in)
Set the name of the UniTensor.
Definition UniTensor.hpp:1909
UniTensor Trace(const cytnx_int64 &a=0, const cytnx_int64 &b=1) const
Take the partial trance to the UniTensor.
Definition UniTensor.hpp:3662
UniTensor & Add_(const UniTensor &rhs)
The addition function of the UniTensor.
Definition UniTensor.hpp:3165
UniTensor permute(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1) const
permute the lags of the UniTensor
Definition UniTensor.hpp:2449
UniTensor & set_label(const std::string &old_label, const char *new_label)
Definition UniTensor.hpp:1963
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:2462
unsigned int dtype() const
Return the data type of the UniTensor.
Definition UniTensor.hpp:2071
UniTensor Pow(const double &p) const
Power function.
UniTensor & Mul_(const Scalar &rhs)
The multiplication function for a given scalar.
Definition UniTensor.hpp:3258
UniTensor & operator-=(const UniTensor &rhs)
The subtraction assignment operator of the UniTensor.
Definition UniTensor.hpp:3458
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force, const bool &by_label)
Definition UniTensor.hpp:3064
UniTensor & set_label(const char *old_label, const char *new_label)
Definition UniTensor.hpp:1971
bool is_blockform() const
Check whether the UniTensor is in block form.
Definition UniTensor.hpp:2194
UniTensor group_basis() const
Definition UniTensor.hpp:2562
Scalar::Sproxy at(const std::vector< std::string > &lbls, const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:2700
UniTensor Dagger() const
Take the conjugate transpose to the UniTensor.
Definition UniTensor.hpp:3718
T & at(const std::vector< std::string > &lbls, const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:2642
const std::vector< Tensor > & get_blocks_(const bool &silent=false) const
Get all the blocks of the UniTensor, inplacely.
Definition UniTensor.hpp:2954
const Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:2921
bool elem_exists(const std::vector< cytnx_uint64 > &locator) const
Geiven the locator, check if the element exists.
Definition UniTensor.hpp:3773
UniTensor & Sub_(const UniTensor &rhs)
The subtraction function of the UniTensor.
Definition UniTensor.hpp:3207
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:3110
void put_block(const Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index.
Definition UniTensor.hpp:2972
const Tensor & get_block_(const cytnx_uint64 &idx=0) const
Get the shared view of block for the given index.
Definition UniTensor.hpp:2820
static UniTensor Load(const std::string &fname)
load a UniTensor from file
const Bond & bond_(const std::string &lbl) const
Definition UniTensor.hpp:2177
Bond & bond_(const cytnx_uint64 &idx)
Definition UniTensor.hpp:2175
UniTensor relabel(const cytnx_int64 &inx, const std::string &new_label) const
rebable the lags in the UniTensor by given index.
Definition UniTensor.hpp:2374
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:3897
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:2154
UniTensor & relabels_(const std::initializer_list< char * > &old_lbls, const std::initializer_list< char * > &new_lbls)
Definition UniTensor.hpp:2344
const std::vector< Bond > & bonds() const
Get the bonds of the UniTensor.
Definition UniTensor.hpp:2167
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:3884
UniTensor & Transpose_()
Take the transpose of the UniTensor, inplacely.
Definition UniTensor.hpp:3610
UniTensor clone() const
Clone (deep copy) the UniTensor.
Definition UniTensor.hpp:2223
vec2d< cytnx_uint64 > & get_itoi()
Definition UniTensor.hpp:3918
void print_blocks(const bool &full_info=true) const
Print all of the blocks in the UniTensor.
Definition UniTensor.hpp:2543
Scalar::Sproxy item() const
Definition UniTensor.hpp:2039
const vec2d< cytnx_uint64 > & get_itoi() const
get the q-indices on each leg for all the blocks
Definition UniTensor.hpp:3917
std::string device_str() const
Return the device of the UniTensor in 'string' form.
Definition UniTensor.hpp:2106
const Scalar::Sproxy at(const std::vector< std::string > &lbls, const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:2721
UniTensor relabels(const std::vector< std::string > &new_labels) const
relables all of the labels in UniTensor.
Definition UniTensor.hpp:2254
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:3001
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:1846
UniTensor & Conj_()
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:3583
cytnx_uint64 Nblocks() const
Return the number of blocks in the UniTensor.
Definition UniTensor.hpp:2052
Tensor get_block(const std::vector< cytnx_uint64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:2804
void Save(const char *fname) const
save a UniTensor to file
Tensor get_block_(const std::vector< std::string > &lbls, const std::vector< cytnx_uint64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:2902
Bond bond(const cytnx_uint64 &idx) const
Definition UniTensor.hpp:2180
Tensor get_block(const std::vector< std::string > &lbls, const std::vector< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:2763
UniTensor Add(const UniTensor &rhs) const
The addition function of the UniTensor.
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:3842
Tensor get_block(const std::initializer_list< cytnx_int64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:2794
UniTensor & relabels_(const std::vector< std::string > &new_labels)
Set new labels for all the bonds.
Definition UniTensor.hpp:2238
const Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator) const
Get an element at specific location.
Definition UniTensor.hpp:2666
int uten_type() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor.
Definition UniTensor.hpp:2079
Tensor & get_block_(const cytnx_uint64 &idx=0)
Definition UniTensor.hpp:2828
#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 Conj(const cytnx::UniTensor &UT)
Elementwise conjugate of the UniTensor.
cytnx::UniTensor Trace(const cytnx::UniTensor &Tin, const cytnx_int64 &a=0, const cytnx_int64 &b=1)
void Conj_(cytnx::UniTensor &UT)
Inplace elementwise conjugate of the UniTensor.
Tensor Norm(const Tensor &Tl)
Calculate the norm of a tensor.
Helper function to print vector with ODT:
Definition Accessor.hpp:12
Device_class Device
data on which devices.
double cytnx_double
Definition Type.hpp:53
UniTensorType_class UTenType
UniTensor type.
uint32_t cytnx_uint32
Definition Type.hpp:56
std::complex< double > cytnx_complex128
Definition Type.hpp:63
float cytnx_float
Definition Type.hpp:54
int16_t cytnx_int16
Definition Type.hpp:60
std::complex< float > cytnx_complex64
Definition Type.hpp:62
int32_t cytnx_int32
Definition Type.hpp:59
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:57
uint64_t cytnx_uint64
Definition Type.hpp:55
int64_t cytnx_int64
Definition Type.hpp:58
std::vector< std::vector< T > > vec2d
Definition Type.hpp:51
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