Cytnx v0.9.7
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#include "Generator.hpp"
20#include <random>
21
22#ifdef BACKEND_TORCH
23#else
24 #include "backend/Scalar.hpp"
25
26// namespace cytnx{
27namespace cytnx {
28 namespace random {
29 extern std::random_device __static_random_device;
30 }
31
32 using namespace cytnx;
34 class UniTensorType_class {
35 public:
36 enum : int {
37 Void = -99,
38 Dense = 0,
39 Sparse = 1,
40 Block = 2,
41 };
42 std::string getname(const int &ut_type);
43 };
45
61 extern UniTensorType_class UTenType;
62
64 // class DenseUniTensor;
65 // class SparseUniTensor;
66 class UniTensor_base : public intrusive_ptr_base<UniTensor_base> {
67 public:
68 int uten_type_id; // the unitensor type id.
69 bool _is_braket_form;
70 bool _is_tag;
71 bool _is_diag;
72 cytnx_int64 _rowrank;
73 std::string _name;
74 std::vector<std::string> _labels;
75 std::vector<Bond> _bonds;
76
77 bool _update_braket() {
78 if (_bonds.size() == 0) return false;
79
80 if (this->_bonds[0].type() != bondType::BD_REG) {
81 // check:
82 for (unsigned int i = 0; i < this->_bonds.size(); i++) {
83 if (i < this->_rowrank) {
84 if (this->_bonds[i].type() != bondType::BD_KET) return false;
85 } else {
86 if (this->_bonds[i].type() != bondType::BD_BRA) return false;
87 }
88 }
89 return true;
90 } else {
91 return false;
92 }
93 }
94
95 friend class UniTensor; // allow wrapper to access the private elems
96 friend class DenseUniTensor;
97 // friend class SparseUniTensor;
98 friend class BlockUniTensor;
99
100 UniTensor_base()
101 : _is_tag(false),
102 _name(std::string("")),
103 _is_braket_form(false),
104 _rowrank(0),
105 _is_diag(false),
106 uten_type_id(UTenType.Void){};
107
108 // copy&assignment constr., use intrusive_ptr's !!
109 UniTensor_base(const UniTensor_base &rhs);
110 UniTensor_base &operator=(UniTensor_base &rhs);
111
112 cytnx_uint64 rowrank() const { return this->_rowrank; }
113 bool is_diag() const { return this->_is_diag; }
114 const bool &is_braket_form() const { return this->_is_braket_form; }
115 const bool &is_tag() const { return this->_is_tag; }
116 const std::vector<std::string> &labels() const { return this->_labels; }
123 cytnx_int64 get_index(std::string label) const {
124 std::vector<std::string> labels = this->_labels;
125 for (cytnx_uint64 i = 0; i < labels.size(); i++) {
126 if (labels[i] == label) return i;
127 }
128 return -1;
129 }
130 const std::vector<Bond> &bonds() const { return this->_bonds; }
131 std::vector<Bond> &bonds() { return this->_bonds; }
132
133 Bond &bond_(const cytnx_uint64 &idx) {
134 cytnx_error_msg(idx >= this->_bonds.size(), "[ERROR][bond] index %d out of bound, total %d\n",
135 idx, this->_bonds.size());
136 return this->_bonds[idx];
137 }
138
139 Bond &bond_(const std::string &label) {
140 auto res = std::find(this->_labels.begin(), this->_labels.end(), label);
141 cytnx_error_msg(res == this->_labels.end(), "[ERROR] label %s not exists.\n", label.c_str());
142 cytnx_uint64 idx = std::distance(this->_labels.begin(), res);
143
144 return this->bond_(idx);
145 }
146
147 const std::string &name() const { return this->_name; }
148 cytnx_uint64 rank() const { return this->_labels.size(); }
149 void set_name(const std::string &in) { this->_name = in; }
150
161 void set_label(const std::string &oldlabel, const std::string &new_label) {
162 cytnx_int64 idx;
163 auto res = std::find(this->_labels.begin(), this->_labels.end(), oldlabel);
164 cytnx_error_msg(res == this->_labels.end(), "[ERROR] label %s not exists.\n",
165 oldlabel.c_str());
166 idx = std::distance(this->_labels.begin(), res);
167
168 cytnx_error_msg(idx >= this->_labels.size(), "[ERROR] index exceed the rank of UniTensor%s",
169 "\n");
170 // check in:
171 bool is_dup = false;
172 for (cytnx_uint64 i = 0; i < this->_labels.size(); i++) {
173 if (i == idx) continue;
174 if (new_label == this->_labels[i]) {
175 is_dup = true;
176 break;
177 }
178 }
179 cytnx_error_msg(is_dup, "[ERROR] alreay has a label that is the same as the input label%s",
180 "\n");
181 this->_labels[idx] = new_label;
182 }
183 void set_label(const cytnx_int64 &inx, const std::string &new_label) {
184 cytnx_error_msg(inx < 0, "[ERROR] index is negative%s", "\n");
185 cytnx_error_msg(inx >= this->_labels.size(), "[ERROR] index exceed the rank of UniTensor%s",
186 "\n");
187 // check in:
188 bool is_dup = false;
189 for (cytnx_uint64 i = 0; i < this->_labels.size(); i++) {
190 if (i == inx) continue;
191 if (new_label == this->_labels[i]) {
192 is_dup = true;
193 break;
194 }
195 }
196 cytnx_error_msg(is_dup, "[ERROR] alreay has a label that is the same as the input label%s",
197 "\n");
198 this->_labels[inx] = new_label;
199 }
200
201 void set_labels(const std::vector<std::string> &new_labels);
202 void relabels_(const std::vector<std::string> &new_labels); // implemented
203 void relabels_(const std::vector<std::string> &old_labels,
204 const std::vector<std::string> &new_labels); // implemented
205 void relabel_(const std::string &old_label, const std::string &new_label) {
206 this->set_label(old_label, new_label);
207 }
208 void relabel_(const cytnx_int64 &inx, const std::string &new_label) {
209 this->set_label(inx, new_label);
210 }
211
212 int uten_type() { return this->uten_type_id; }
213 std::string uten_type_str() { return UTenType.getname(this->uten_type_id); }
214
216
217 // string labels!
218 virtual void Init(const std::vector<Bond> &bonds,
219 const std::vector<std::string> &in_labels = {},
220 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
221 const int &device = Device.cpu, const bool &is_diag = false,
222 const bool &no_alloc = false, const std::string &name = "");
223
224 virtual void Init_by_Tensor(const Tensor &in, const bool &is_diag = false,
225 const cytnx_int64 &rowrank = -1, const std::string &name = "");
226 virtual std::vector<cytnx_uint64> shape() const;
227 virtual bool is_blockform() const;
228 virtual bool is_contiguous() const;
229 virtual void to_(const int &device);
230 virtual boost::intrusive_ptr<UniTensor_base> to(const int &device);
231 virtual boost::intrusive_ptr<UniTensor_base> clone() const;
232 virtual unsigned int dtype() const;
233 virtual int device() const;
234 virtual std::string dtype_str() const;
235 virtual std::string device_str() const;
236 virtual void set_rowrank_(const cytnx_uint64 &new_rowrank);
237 virtual boost::intrusive_ptr<UniTensor_base> set_rowrank(const cytnx_uint64 &new_rowrank) const;
238
239 virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
240 const cytnx_int64 &rowrank = -1);
241 virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
242 const cytnx_int64 &rowrank = -1);
243 // virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
244 // const cytnx_int64 &rowrank = -1);
245
246 virtual void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
247 virtual void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
248
249 // virtual void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank =
250 // -1);
251 virtual boost::intrusive_ptr<UniTensor_base> contiguous_();
252 virtual boost::intrusive_ptr<UniTensor_base> contiguous();
253 virtual void print_diagram(const bool &bond_info = false);
254 virtual void print_blocks(const bool &full_info = true) const;
255 virtual void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
256
257 virtual boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const;
258
259 virtual cytnx_uint64 Nblocks() const { return 0; };
260 virtual Tensor get_block(const cytnx_uint64 &idx = 0) const; // return a copy of block
261 virtual Tensor get_block(const std::vector<cytnx_int64> &qnum,
262 const bool &force) const; // return a copy of block
263
264 virtual const Tensor &get_block_(const cytnx_uint64 &idx = 0)
265 const; // return a share view of block, this only work for non-symm tensor.
266 virtual const Tensor &get_block_(const std::vector<cytnx_int64> &qnum,
267 const bool &force) const; // return a copy of block
268 virtual Tensor &get_block_(const cytnx_uint64 &idx = 0); // return a share view of block, this
269 // only work for non-symm tensor.
270 virtual Tensor &get_block_(const std::vector<cytnx_int64> &qnum,
271 const bool &force); // return a copy of block
272 virtual bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const;
273
274 virtual std::vector<Tensor> get_blocks() const;
275 virtual const std::vector<Tensor> &get_blocks_(const bool &) const;
276 virtual std::vector<Tensor> &get_blocks_(const bool &);
277
278 virtual void put_block(const Tensor &in, const cytnx_uint64 &idx = 0);
279 virtual void put_block_(Tensor &in, const cytnx_uint64 &idx = 0);
280 virtual void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum,
281 const bool &force);
282 virtual void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force);
283
284 // this will only work on non-symm tensor (DenseUniTensor)
285 virtual boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors);
286
287 // this will only work on non-symm tensor (DenseUniTensor)
288 virtual void set(const std::vector<Accessor> &accessors, const Tensor &rhs);
289
290 virtual void reshape_(const std::vector<cytnx_int64> &new_shape,
291 const cytnx_uint64 &rowrank = 0);
292 virtual boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
293 const cytnx_uint64 &rowrank = 0);
294 virtual boost::intrusive_ptr<UniTensor_base> to_dense();
295 virtual void to_dense_();
296 virtual void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
297 const bool &by_label);
298 virtual void combineBonds(const std::vector<std::string> &indicators,
299 const bool &force = false);
300 virtual void combineBonds(const std::vector<cytnx_int64> &indicators,
301 const bool &force = false);
302 virtual boost::intrusive_ptr<UniTensor_base> contract(
303 const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &mv_elem_self = false,
304 const bool &mv_elem_rhs = false);
305 virtual std::vector<Bond> getTotalQnums(const bool &physical = false);
306 virtual std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const;
307 virtual void Trace_(const std::string &a, const std::string &b);
308 virtual void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
309
310 virtual boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b);
311 virtual boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b);
312
313 virtual boost::intrusive_ptr<UniTensor_base> relabels(
314 const std::vector<std::string> &new_labels);
315
316 virtual boost::intrusive_ptr<UniTensor_base> relabels(
317 const std::vector<std::string> &old_labels, const std::vector<std::string> &new_labels);
318
319 virtual boost::intrusive_ptr<UniTensor_base> relabel(const std::string &old_label,
320 const std::string &new_label);
321
322 virtual boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
323 const std::string &new_label);
324
325 virtual std::vector<Symmetry> syms() const;
326
327 // arithmetic
328 virtual void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
329 virtual void Add_(const Scalar &rhs);
330
331 virtual void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
332 virtual void Mul_(const Scalar &rhs);
333
334 virtual void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
335 virtual void Sub_(const Scalar &rhs);
336 virtual void lSub_(const Scalar &lhs);
337
338 virtual void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
339 virtual void Div_(const Scalar &rhs);
340 virtual void lDiv_(const Scalar &lhs);
341
342 virtual Tensor Norm() const;
343 virtual boost::intrusive_ptr<UniTensor_base> normalize();
344 virtual void normalize_();
345
346 virtual boost::intrusive_ptr<UniTensor_base> Conj();
347 virtual void Conj_();
348
349 virtual boost::intrusive_ptr<UniTensor_base> Transpose();
350 virtual void Transpose_();
351
352 virtual boost::intrusive_ptr<UniTensor_base> Dagger();
353 virtual void Dagger_();
354
355 virtual void tag();
356
357 virtual void truncate_(const std::string &bond_idx, const cytnx_uint64 &dim);
358 virtual void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim);
359
360 virtual bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
361
362 // this a workaround, as virtual function cannot template.
363 virtual Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator);
364 virtual const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const;
365
366 virtual cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
367 const cytnx_complex128 &aux);
368 virtual cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
369 const cytnx_complex64 &aux);
370 virtual cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
371 const cytnx_double &aux);
372 virtual cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
373 const cytnx_float &aux);
374 virtual cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
375 const cytnx_uint64 &aux);
376 virtual cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
377 const cytnx_int64 &aux);
378 virtual cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
379 const cytnx_uint32 &aux);
380 virtual cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
381 const cytnx_int32 &aux);
382 virtual cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
383 const cytnx_uint16 &aux);
384 virtual cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
385 const cytnx_int16 &aux);
386
387 virtual const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
388 const cytnx_complex128 &aux) const;
389 virtual const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
390 const cytnx_complex64 &aux) const;
391 virtual const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
392 const cytnx_double &aux) const;
393 virtual const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
394 const cytnx_float &aux) const;
395 virtual const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
396 const cytnx_uint64 &aux) const;
397 virtual const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
398 const cytnx_int64 &aux) const;
399 virtual const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
400 const cytnx_uint32 &aux) const;
401 virtual const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
402 const cytnx_int32 &aux) const;
403 virtual const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
404 const cytnx_uint16 &aux) const;
405 virtual const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
406 const cytnx_int16 &aux) const;
407
408 virtual void from_(const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &force);
409
410 virtual void group_basis_();
411 virtual const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const;
412 virtual std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx);
413 virtual const vec2d<cytnx_uint64> &get_itoi() const;
414 virtual vec2d<cytnx_uint64> &get_itoi();
415
416 virtual void _save_dispatch(std::fstream &f) const;
417 virtual void _load_dispatch(std::fstream &f);
418
419 virtual ~UniTensor_base(){};
420 };
422
423 //======================================================================
425 class DenseUniTensor : public UniTensor_base {
426 protected:
427 public:
428 Tensor _block;
429 std::vector<Tensor> _interface_block; // this is serves as interface for get_blocks_();
430 DenseUniTensor *clone_meta() const {
431 DenseUniTensor *tmp = new DenseUniTensor();
432 tmp->_bonds = vec_clone(this->_bonds);
433 tmp->_labels = this->_labels;
434 tmp->_is_braket_form = this->_is_braket_form;
435 tmp->_rowrank = this->_rowrank;
436 tmp->_is_diag = this->_is_diag;
437 tmp->_name = this->_name;
438 tmp->_is_tag = this->_is_tag;
439 return tmp;
440 }
441 //------------------------------------------
442
443 DenseUniTensor() { this->uten_type_id = UTenType.Dense; };
444 friend class UniTensor; // allow wrapper to access the private elems
445 // virtual functions
446
447 // void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels = {},
448 // const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
449 // const int &device = Device.cpu, const bool &is_diag = false,
450 // const bool &no_alloc = false);
451
452 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
453 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
454 const int &device = Device.cpu, const bool &is_diag = false,
455 const bool &no_alloc = false, const std::string &name = "");
456 // this only work for non-symm tensor
457 void Init_by_Tensor(const Tensor &in_tensor, const bool &is_diag = false,
458 const cytnx_int64 &rowrank = -1, const std::string &name = "");
459 std::vector<cytnx_uint64> shape() const {
460 if (this->_is_diag) {
461 std::vector<cytnx_uint64> shape = this->_block.shape();
462 shape.push_back(shape[0]);
463 return shape;
464 } else {
465 return this->_block.shape();
466 }
467 }
468 bool is_blockform() const { return false; }
469 void to_(const int &device) { this->_block.to_(device); }
470 boost::intrusive_ptr<UniTensor_base> to(const int &device) {
471 if (this->device() == device) {
472 std::vector<Tensor> _interface_block; // this is serves as interface for get_blocks_();
473 return this;
474 } else {
475 boost::intrusive_ptr<UniTensor_base> out = this->clone();
476 out->to_(device);
477 return out;
478 }
479 }
480 void set_rowrank_(const cytnx_uint64 &new_rowrank) {
481 cytnx_error_msg(new_rowrank > this->_labels.size(),
482 "[ERROR] rowrank cannot exceed the rank of UniTensor.%s", "\n");
483 if (this->is_diag()) {
484 cytnx_error_msg(new_rowrank != 1, "[ERROR] rowrank should be [==1] when is_diag =true!.%s",
485 "\n");
486 }
487
488 this->_rowrank = new_rowrank;
489 }
490
491 boost::intrusive_ptr<UniTensor_base> set_rowrank(const cytnx_uint64 &new_rowrank) const {
492 DenseUniTensor *out_raw = this->clone_meta();
493 out_raw->_block = this->_block;
494 out_raw->set_rowrank_(new_rowrank);
495 boost::intrusive_ptr<UniTensor_base> out(out_raw);
496 return out;
497 }
498
499 boost::intrusive_ptr<UniTensor_base> clone() const {
500 DenseUniTensor *tmp = this->clone_meta();
501 tmp->_block = this->_block.clone();
502 boost::intrusive_ptr<UniTensor_base> out(tmp);
503 return out;
504 };
505 bool is_contiguous() const { return this->_block.is_contiguous(); }
506 unsigned int dtype() const { return this->_block.dtype(); }
507 int device() const { return this->_block.device(); }
508 std::string dtype_str() const { return Type.getname(this->_block.dtype()); }
509 std::string device_str() const { return Device.getname(this->_block.device()); }
519 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
520 const cytnx_int64 &rowrank = -1);
521 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
522 const cytnx_int64 &rowrank = -1);
523
532 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
533 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
534
535 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &new_labels);
536
537 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &old_labels,
538 const std::vector<std::string> &new_labels);
539
550 boost::intrusive_ptr<UniTensor_base> relabel(const std::string &old_label,
551 const std::string &new_label);
552 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
553 const std::string &new_label);
554
555 boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const {
556 DenseUniTensor *tmp = this->clone_meta();
557 tmp->_block = this->_block.astype(dtype);
558 boost::intrusive_ptr<UniTensor_base> out(tmp);
559 return tmp;
560 }
561
562 std::vector<Symmetry> syms() const {
563 cytnx_error_msg(true, "[ERROR][DenseUniTensor] dense unitensor does not have symmetry.%s",
564 "\n");
565 return std::vector<Symmetry>();
566 }
567
568 boost::intrusive_ptr<UniTensor_base> contiguous_() {
569 this->_block.contiguous_();
570 return boost::intrusive_ptr<UniTensor_base>(this);
571 }
572 boost::intrusive_ptr<UniTensor_base> contiguous() {
573 // if contiguous then return self!
574 if (this->is_contiguous()) {
575 boost::intrusive_ptr<UniTensor_base> out(this);
576 return out;
577 } else {
578 DenseUniTensor *tmp = this->clone_meta();
579 tmp->_block = this->_block.contiguous();
580 boost::intrusive_ptr<UniTensor_base> out(tmp);
581 return out;
582 }
583 }
584 void print_diagram(const bool &bond_info = false);
585 void print_blocks(const bool &full_info = true) const;
586 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
587 Tensor get_block(const cytnx_uint64 &idx = 0) const { return this->_block.clone(); }
588
589 Tensor get_block(const std::vector<cytnx_int64> &qnum, const bool &force) const {
591 true, "[ERROR][DenseUniTensor] try to get_block() using qnum on a non-symmetry UniTensor%s",
592 "\n");
593 return Tensor();
594 }
595 // return a share view of block, this only work for non-symm tensor.
596 const Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force) const {
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 Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force) {
605 true,
606 "[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
607 "\n");
608 return this->_block;
609 }
610
611 // return a share view of block, this only work for non-symm tensor.
612 Tensor &get_block_(const cytnx_uint64 &idx = 0) { return this->_block; }
613 // return a share view of block, this only work for non-symm tensor.
614 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const { return this->_block; }
615
616 cytnx_uint64 Nblocks() const { return 1; };
617 std::vector<Tensor> get_blocks() const {
618 std::vector<Tensor> out;
620 true, "[ERROR][DenseUniTensor] cannot use get_blocks(), use get_block() instead!%s", "\n");
621 return out; // this will not share memory!!
622 }
623 const std::vector<Tensor> &get_blocks_(const bool &silent = false) const {
625 true, "[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s",
626 "\n");
627 return this->_interface_block; // this will not share memory!!
628 }
629 std::vector<Tensor> &get_blocks_(const bool &silent = false) {
631 true, "[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s",
632 "\n");
633 return this->_interface_block; // this will not share memory!!
634 }
635
636 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
637 // We don't check the dtype for DenseUniTensor, since it'll be more convinent to change
638 // DenseUniTensor's dtype
639
640 // cytnx_error_msg(in.dtype() != this->dtype(),
641 // "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not
642 // match.%s",
643 // "\n");
644 cytnx_error_msg(in.device() != this->device(),
645 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
646 "match.%s",
647 "\n");
648 // We shouldn't check the contiguous
649 // cytnx_error_msg(!in.contiguous());
650 if (this->is_diag()) {
652 in.shape() != this->_block.shape(),
653 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
654 this->_block = in.clone();
655 } else {
657 in.shape() != this->shape(),
658 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
659 this->_block = in.clone();
660 }
661 }
662 // share view of the block
663 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) {
664 // We don't check the dtype for DenseUniTensor, since it'll be more convinent to change
665 // DenseUniTensor's dtype
666
667 // cytnx_error_msg(in.dtype() != this->dtype(),
668 // "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not
669 // match.%s",
670 // "\n");
671 cytnx_error_msg(in.device() != this->device(),
672 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
673 "match.%s",
674 "\n");
675 // We shouldn't check the contiguous
676 // cytnx_error_msg(!in.contiguous());
677 if (this->is_diag()) {
679 in.shape() != this->_block.shape(),
680 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
681 this->_block = in;
682 } else {
684 in.shape() != this->shape(),
685 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
686 this->_block = in;
687 }
688 }
689
690 void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force) {
692 true, "[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
693 "\n");
694 }
695 void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force) {
697 true, "[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
698 "\n");
699 }
700 // this will only work on non-symm tensor (DenseUniTensor)
701 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors) {
702 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
703 out->Init_by_Tensor(this->_block.get(accessors), false, 0); // wrapping around.
704 return out;
705 }
706 // this will only work on non-symm tensor (DenseUniTensor)
707 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
708 this->_block.set(accessors, rhs);
709 }
710
711 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0);
712 boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
713 const cytnx_uint64 &rowrank = 0);
714 boost::intrusive_ptr<UniTensor_base> to_dense();
715 void to_dense_();
725 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
726 const bool &by_label);
727 void combineBonds(const std::vector<std::string> &indicators, const bool &force = true);
728 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = true);
729 boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs,
730 const bool &mv_elem_self = false,
731 const bool &mv_elem_rhs = false);
732 std::vector<Bond> getTotalQnums(const bool &physical = false) {
733 cytnx_error_msg(true, "[ERROR][DenseUniTensor] %s",
734 "getTotalQnums can only operate on UniTensor with symmetry.\n");
735 return std::vector<Bond>();
736 }
737
738 std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const {
739 cytnx_error_msg(true, "[ERROR][DenseUniTensor] %s",
740 "get_blocks_qnums can only operate on UniTensor with symmetry.\n");
741 return std::vector<std::vector<cytnx_int64>>();
742 }
743
744 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const {
745 if (rhs->uten_type() != UTenType.Dense) return false;
746
747 return this->get_block_().same_data(rhs->get_block_());
748 }
749
750 ~DenseUniTensor(){};
751
752 // arithmetic
753 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
754 void Add_(const Scalar &rhs);
755
756 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
757 void Mul_(const Scalar &rhs);
758
759 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
760 void Sub_(const Scalar &rhs);
761 void lSub_(const Scalar &lhs);
762
763 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
764 void Div_(const Scalar &rhs);
765 void lDiv_(const Scalar &lhs);
766
767 void Conj_() { this->_block.Conj_(); };
768
769 boost::intrusive_ptr<UniTensor_base> Conj() {
770 boost::intrusive_ptr<UniTensor_base> out = this->clone();
771 out->Conj_();
772 return out;
773 }
774
775 boost::intrusive_ptr<UniTensor_base> Transpose() {
776 boost::intrusive_ptr<UniTensor_base> out = this->clone();
777 out->Transpose_();
778 return out;
779 }
780 void Transpose_();
781
782 boost::intrusive_ptr<UniTensor_base> normalize() {
783 boost::intrusive_ptr<UniTensor_base> out = this->clone();
784 out->normalize_();
785 return out;
786 }
787 void normalize_();
788
789 boost::intrusive_ptr<UniTensor_base> Dagger() {
790 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
791 out->Transpose_();
792 return out;
793 }
794 void Dagger_() {
795 this->Conj_();
796 this->Transpose_();
797 }
807 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
808 void Trace_(const std::string &a, const std::string &b);
809 boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b) {
810 boost::intrusive_ptr<UniTensor_base> out = this->clone();
811 out->Trace_(a, b);
812 return out;
813 }
814 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b) {
815 boost::intrusive_ptr<UniTensor_base> out = this->clone();
816 out->Trace_(a, b);
817 return out;
818 }
819
820 Tensor Norm() const;
821
822 const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const {
824 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
825 "\n");
826 return Scalar::Sproxy();
827 }
828 const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
829 const cytnx_complex128 &aux) const {
831 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
832 "\n");
833 return cytnx_complex128(0, 0);
834 }
835 const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
836 const cytnx_complex64 &aux) const {
838 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
839 "\n");
840 return cytnx_complex64(0, 0);
841 }
842 const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
843 const cytnx_double &aux) const {
845 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
846 "\n");
847 return 0;
848 }
849 const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
850 const cytnx_float &aux) const {
852 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
853 "\n");
854 return 0;
855 }
856 const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
857 const cytnx_uint64 &aux) const {
859 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
860 "\n");
861 return 0;
862 }
863 const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
864 const cytnx_int64 &aux) const {
866 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
867 "\n");
868 return 0;
869 }
870 const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
871 const cytnx_uint32 &aux) const {
873 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
874 "\n");
875 return 0;
876 }
877 const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
878 const cytnx_int32 &aux) const {
880 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
881 "\n");
882 return 0;
883 }
884 const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
885 const cytnx_uint16 &aux) const {
887 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
888 "\n");
889 return 0;
890 }
891 const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
892 const cytnx_int16 &aux) const {
894 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
895 "\n");
896 return 0;
897 }
898
899 Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) {
901 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
902 "\n");
903 return Scalar::Sproxy();
904 }
905 cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
906 const cytnx_complex128 &aux) {
908 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
909 "\n");
910 return *(cytnx_complex128 *)nullptr;
911 }
912 cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
913 const cytnx_complex64 &aux) {
915 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
916 "\n");
917 return *(cytnx_complex64 *)nullptr;
918 }
919 cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux) {
921 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
922 "\n");
923 return *(cytnx_double *)nullptr;
924 }
925 cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux) {
927 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
928 "\n");
929 return *(cytnx_float *)nullptr;
930 }
931 cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux) {
933 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
934 "\n");
935 return *(cytnx_uint64 *)nullptr;
936 }
937 cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux) {
939 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
940 "\n");
941 return *(cytnx_int64 *)nullptr;
942 }
943 cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux) {
945 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
946 "\n");
947 return *(cytnx_uint32 *)nullptr;
948 }
949 cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux) {
951 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
952 "\n");
953 return *(cytnx_int32 *)nullptr;
954 }
955 cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux) {
957 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
958 "\n");
959 return *(cytnx_uint16 *)nullptr;
960 }
961 cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux) {
963 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
964 "\n");
965 return *(cytnx_int16 *)nullptr;
966 }
967
968 bool elem_exists(const std::vector<cytnx_uint64> &locator) const {
970 true, "[ERROR][DenseUniTensor] elem_exists can only be used on UniTensor with Symmetry.%s",
971 "\n");
972 }
973 void tag() {
974 if (!this->is_tag()) {
975 for (int i = 0; i < this->_rowrank; i++) {
976 this->_bonds[i].set_type(BD_KET);
977 }
978 for (int i = this->_rowrank; i < this->_bonds.size(); i++) {
979 this->_bonds[i].set_type(BD_BRA);
980 }
981 this->_is_tag = true;
982 this->_is_braket_form = this->_update_braket();
983 }
984 }
994 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim);
995 void truncate_(const std::string &bond_idx, const cytnx_uint64 &dim);
996
997 void from_(const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &force);
998
999 void group_basis_() {
1000 cytnx_warning_msg(true, "[WARNING] group basis will not have any effect on DensUniTensor.%s",
1001 "\n");
1002 }
1003
1004 void _save_dispatch(std::fstream &f) const;
1005 void _load_dispatch(std::fstream &f);
1006
1007 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
1008 cytnx_error_msg(true, "[ERROR] get_qindices can only be unsed on UniTensor with Symmetry.%s",
1009 "\n");
1010 }
1011 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
1012 cytnx_error_msg(true, "[ERROR] get_qindices can only be unsed on UniTensor with Symmetry.%s",
1013 "\n");
1014 }
1015
1016 const vec2d<cytnx_uint64> &get_itoi() const {
1017 cytnx_error_msg(true, "[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s",
1018 "\n");
1019 }
1020 vec2d<cytnx_uint64> &get_itoi() {
1021 cytnx_error_msg(true, "[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s",
1022 "\n");
1023 }
1024
1025 // end virtual function
1026 };
1028
1029 //======================================================================
1031 class BlockUniTensor : public UniTensor_base {
1032 protected:
1033 public:
1034 std::vector<std::vector<cytnx_uint64>> _inner_to_outer_idx;
1035 std::vector<Tensor> _blocks;
1036 Tensor NullRefTensor; // this returns when access block is not exists!
1037
1038 // given an index list [loc], get qnums from this->_bonds[loc] and return the combined qnums
1039 // calculated from Symm object! this assume 1. symmetry are the same for each bond!
1040 // 2. total_qns are feeded with size len(symmetry)
1041 void _fx_get_total_fluxs(std::vector<cytnx_uint64> &loc, const std::vector<Symmetry> &syms,
1042 std::vector<cytnx_int64> &total_qns) {
1043 memset(&total_qns[0], 0, sizeof(cytnx_int64) * total_qns.size());
1044
1045 for (cytnx_int32 i = 0; i < syms.size(); i++) {
1046 if (this->_bonds[0].type() == BD_BRA)
1047 total_qns[i] = syms[0].reverse_rule(this->_bonds[0]._impl->_qnums[loc[0]][i]);
1048 else
1049 total_qns[i] = this->_bonds[0]._impl->_qnums[loc[0]][i];
1050
1051 for (auto j = 1; j < loc.size(); j++) {
1052 if (this->_bonds[j].type() == BD_BRA)
1053 total_qns[i] = syms[i].combine_rule(
1054 total_qns[i], syms[i].reverse_rule(this->_bonds[j]._impl->_qnums[loc[j]][i]));
1055 else {
1056 total_qns[i] =
1057 syms[i].combine_rule(total_qns[i], this->_bonds[j]._impl->_qnums[loc[j]][i]);
1058 }
1059 }
1060 }
1061 }
1062
1063 void _fx_locate_elem(cytnx_int64 &bidx, std::vector<cytnx_uint64> &loc_in_T,
1064 const std::vector<cytnx_uint64> &locator) const;
1065
1066 // internal function, grouping all duplicate qnums in all bonds
1067 void _fx_group_duplicates(const std::vector<cytnx_uint64> &dup_bond_idxs,
1068 const std::vector<std::vector<cytnx_uint64>> &idx_mappers);
1069
1070 void set_meta(BlockUniTensor *tmp, const bool &inner, const bool &outer) const {
1071 // outer meta
1072 if (outer) {
1073 tmp->_bonds = vec_clone(this->_bonds);
1074 tmp->_labels = this->_labels;
1075 tmp->_is_braket_form = this->_is_braket_form;
1076 tmp->_rowrank = this->_rowrank;
1077 tmp->_name = this->_name;
1078 }
1079
1080 tmp->_is_diag = this->_is_diag;
1081
1082 // inner meta
1083 if (inner) {
1084 tmp->_inner_to_outer_idx = this->_inner_to_outer_idx;
1085 }
1086 }
1087
1088 BlockUniTensor *clone_meta(const bool &inner, const bool &outer) const {
1089 BlockUniTensor *tmp = new BlockUniTensor();
1090 this->set_meta(tmp, inner, outer);
1091 return tmp;
1092 };
1093
1094 friend class UniTensor;
1095 BlockUniTensor() {
1096 this->uten_type_id = UTenType.Block;
1097 this->_is_tag = true;
1098 }
1099
1100 // virtual functions:
1101 // void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels = {},
1102 // const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1103 // const int &device = Device.cpu, const bool &is_diag = false,
1104 // const bool &no_alloc = false);
1105
1106 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1107 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1108 const int &device = Device.cpu, const bool &is_diag = false,
1109 const bool &no_alloc = false, const std::string &name = "");
1110
1111 void Init_by_Tensor(const Tensor &in_tensor, const bool &is_diag = false,
1112 const cytnx_int64 &rowrank = -1, const std::string &name = "") {
1114 true, "[ERROR][BlockUniTensor] cannot use Init_by_tensor() on a BlockUniTensor.%s", "\n");
1115 }
1116
1117 std::vector<cytnx_uint64> shape() const {
1118 std::vector<cytnx_uint64> out(this->_bonds.size());
1119 for (cytnx_uint64 i = 0; i < out.size(); i++) {
1120 out[i] = this->_bonds[i].dim();
1121 }
1122 return out;
1123 }
1124
1125 bool is_blockform() const { return true; }
1126 bool is_contiguous() const {
1127 bool out = true;
1128 for (int i = 0; i < this->_blocks.size(); i++) {
1129 out &= this->_blocks[i].is_contiguous();
1130 }
1131 return out;
1132 };
1133
1134 cytnx_uint64 Nblocks() const { return this->_blocks.size(); };
1135
1136 void to_(const int &device) {
1137 for (cytnx_uint64 i = 0; i < this->_blocks.size(); i++) {
1138 this->_blocks[i].to_(device);
1139 }
1140 };
1141
1142 boost::intrusive_ptr<UniTensor_base> to(const int &device) {
1143 if (this->device() == device) {
1144 return this;
1145 } else {
1146 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1147 out->to_(device);
1148 return out;
1149 }
1150 };
1151
1152 boost::intrusive_ptr<UniTensor_base> clone() const {
1153 BlockUniTensor *tmp = this->clone_meta(true, true);
1154 tmp->_blocks = vec_clone(this->_blocks);
1155 boost::intrusive_ptr<UniTensor_base> out(tmp);
1156 return out;
1157 };
1158
1159 unsigned int dtype() const {
1160 #ifdef UNI_DEBUG
1161 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1162 "\n");
1163 #endif
1164 return this->_blocks[0].dtype();
1165 };
1166 int device() const {
1167 #ifdef UNI_DEBUG
1168 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1169 "\n");
1170 #endif
1171 return this->_blocks[0].device();
1172 };
1173 std::string dtype_str() const {
1174 #ifdef UNI_DEBUG
1175 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1176 "\n");
1177 #endif
1178 return this->_blocks[0].dtype_str();
1179 };
1180 std::string device_str() const {
1181 #ifdef UNI_DEBUG
1182 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1183 "\n");
1184 #endif
1185 return this->_blocks[0].device_str();
1186 };
1187
1188 Tensor get_block(const cytnx_uint64 &idx = 0) const {
1189 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1190 "\n");
1191 return this->_blocks[idx].clone();
1192 };
1193
1194 // this one for Block will return the indicies!!
1195 Tensor get_block(const std::vector<cytnx_int64> &indices, const bool &force_return) const {
1196 cytnx_error_msg(indices.size() != this->rank(),
1197 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1198 "Tensor rank (number of legs).%s",
1199 "\n");
1200
1201 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1202
1203 // find if the indices specify exists!
1204 cytnx_int64 b = -1;
1205 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1206 if (inds == this->_inner_to_outer_idx[i]) {
1207 b = i;
1208 break;
1209 }
1210 }
1211
1212 if (b < 0) {
1213 if (force_return) {
1214 return NullRefTensor;
1215 } else {
1216 cytnx_error_msg(true,
1217 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1218 "force_return=false, so "
1219 "error throws. \n If you want to return an empty block without "
1220 "error when block is "
1221 "not avaliable, set force_return=True.%s",
1222 "\n");
1223 }
1224 } else {
1225 return this->_blocks[b].clone();
1226 }
1227 }
1228
1229 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const {
1230 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1231 "\n");
1232 return this->_blocks[idx];
1233 };
1234
1235 Tensor &get_block_(const cytnx_uint64 &idx = 0) {
1236 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1237 "\n");
1238 return this->_blocks[idx];
1239 };
1240
1241 const Tensor &get_block_(const std::vector<cytnx_int64> &indices,
1242 const bool &force_return) const {
1243 cytnx_error_msg(indices.size() != this->rank(),
1244 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1245 "Tensor rank (number of legs).%s",
1246 "\n");
1247
1248 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1249
1250 // find if the indices specify exists!
1251 cytnx_int64 b = -1;
1252 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1253 if (inds == this->_inner_to_outer_idx[i]) {
1254 b = i;
1255 break;
1256 }
1257 }
1258
1259 if (b < 0) {
1260 if (force_return) {
1261 return this->NullRefTensor;
1262 } else {
1263 cytnx_error_msg(true,
1264 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1265 "force_return=false, so "
1266 "error throws. \n If you want to return an empty block without "
1267 "error when block is "
1268 "not avaliable, set force_return=True.%s",
1269 "\n");
1270 }
1271 } else {
1272 return this->_blocks[b];
1273 }
1274 }
1275
1276 Tensor &get_block_(const std::vector<cytnx_int64> &indices, const bool &force_return) {
1277 cytnx_error_msg(indices.size() != this->rank(),
1278 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1279 "Tensor rank (number of legs).%s",
1280 "\n");
1281
1282 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1283
1284 // find if the indices specify exists!
1285 cytnx_int64 b = -1;
1286 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1287 if (inds == this->_inner_to_outer_idx[i]) {
1288 b = i;
1289 break;
1290 }
1291 }
1292
1293 if (b < 0) {
1294 if (force_return) {
1295 return this->NullRefTensor;
1296 } else {
1297 cytnx_error_msg(true,
1298 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1299 "force_return=false, so "
1300 "error throws. \n If you want to return an empty block without "
1301 "error when block is "
1302 "not avaliable, set force_return=True.%s",
1303 "\n");
1304 }
1305 } else {
1306 return this->_blocks[b];
1307 }
1308 }
1309
1310 std::vector<Tensor> get_blocks() const { return vec_clone(this->_blocks); }
1311 const std::vector<Tensor> &get_blocks_(const bool &) const { return this->_blocks; }
1312 std::vector<Tensor> &get_blocks_(const bool &) { return this->_blocks; }
1313
1314 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const {
1315 if (rhs->uten_type() != UTenType.Block) return false;
1316 if (rhs->get_blocks_(1).size() != this->get_blocks_(1).size()) return false;
1317
1318 for (int i = 0; i < rhs->get_blocks_(1).size(); i++)
1319 if (this->get_blocks_(1)[i].same_data(rhs->get_blocks_(1)[i]) == false) return false;
1320
1321 return true;
1322 }
1323
1324 void set_rowrank_(const cytnx_uint64 &new_rowrank) {
1325 cytnx_error_msg(new_rowrank > this->rank(),
1326 "[ERROR][BlockUniTensor] rowrank should be [>=0] and [<=UniTensor.rank].%s",
1327 "\n");
1328 if (this->is_diag()) {
1329 cytnx_error_msg(new_rowrank != 1,
1330 "[ERROR][BlockUniTensor] rowrank should be [==1] when is_diag =true!.%s",
1331 "\n");
1332 }
1333 this->_rowrank = new_rowrank;
1334 this->_is_braket_form = this->_update_braket();
1335 }
1336
1337 boost::intrusive_ptr<UniTensor_base> set_rowrank(const cytnx_uint64 &new_rowrank) const {
1338 BlockUniTensor *tmp = this->clone_meta(true, true);
1339 tmp->_blocks = this->_blocks;
1340 tmp->set_rowrank_(new_rowrank);
1341 boost::intrusive_ptr<UniTensor_base> out(tmp);
1342 return out;
1343 }
1344
1345 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
1346 const cytnx_int64 &rowrank = -1);
1347 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
1348 const cytnx_int64 &rowrank = -1);
1349
1350 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
1351 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
1352
1353 boost::intrusive_ptr<UniTensor_base> contiguous_() {
1354 for (unsigned int b = 0; b < this->_blocks.size(); b++) this->_blocks[b].contiguous_();
1355 return boost::intrusive_ptr<UniTensor_base>(this);
1356 }
1357
1358 boost::intrusive_ptr<UniTensor_base> contiguous();
1359
1360 void print_diagram(const bool &bond_info = false);
1361 void print_blocks(const bool &full_info = true) const;
1362 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
1363
1364 boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs,
1365 const bool &mv_elem_self = false,
1366 const bool &mv_elem_rhs = false);
1367
1368 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &new_labels);
1369
1370 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &old_labels,
1371 const std::vector<std::string> &new_labels);
1372
1373 boost::intrusive_ptr<UniTensor_base> relabel(const std::string &old_label,
1374 const std::string &new_label);
1375 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
1376 const std::string &new_label);
1377
1378 std::vector<Symmetry> syms() const;
1379
1380 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
1381 cytnx_error_msg(true, "[ERROR] cannot reshape a UniTensor with symmetry.%s", "\n");
1382 }
1383 boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
1384 const cytnx_uint64 &rowrank = 0) {
1385 cytnx_error_msg(true, "[ERROR] cannot reshape a UniTensor with symmetry.%s", "\n");
1386 return nullptr;
1387 }
1388
1389 boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const {
1390 BlockUniTensor *tmp = this->clone_meta(true, true);
1391 tmp->_blocks.resize(this->_blocks.size());
1392 for (cytnx_int64 blk = 0; blk < this->_blocks.size(); blk++) {
1393 tmp->_blocks[blk] = this->_blocks[blk].astype(dtype);
1394 }
1395 boost::intrusive_ptr<UniTensor_base> out(tmp);
1396 return out;
1397 };
1398
1399 // this will only work on non-symm tensor (DenseUniTensor)
1400 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors) {
1402 true,
1403 "[ERROR][BlockUniTensor][get] cannot use get on a UniTensor with "
1404 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
1405 "\n");
1406 return nullptr;
1407 }
1408
1409 // this will only work on non-symm tensor (DenseUniTensor)
1410 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
1412 true,
1413 "[ERROR][BlockUniTensor][get] cannot use get on a UniTensor with "
1414 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
1415 "\n");
1416 }
1417
1418 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
1419 cytnx_error_msg(in.dtype() != this->dtype(),
1420 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
1421 "\n");
1422 cytnx_error_msg(in.device() != this->device(),
1423 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
1424 "match.%s",
1425 "\n");
1426 // We shouldn't check the contiguous
1427 // cytnx_error_msg(!in.contiguous());
1428 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1429 "\n");
1430 cytnx_error_msg(in.shape() != this->_blocks[idx].shape(),
1431 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1432 "of block @ idx=%d\n",
1433 idx);
1434
1435 this->_blocks[idx] = in.clone();
1436 }
1437 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) {
1438 cytnx_error_msg(in.dtype() != this->dtype(),
1439 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
1440 "\n");
1441 cytnx_error_msg(in.device() != this->device(),
1442 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
1443 "match.%s",
1444 "\n");
1445 // We shouldn't check the contiguous
1446 // cytnx_error_msg(!in.contiguous());
1447 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1448 "\n");
1449 cytnx_error_msg(in.shape() != this->_blocks[idx].shape(),
1450 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1451 "of block @ idx=%d\n",
1452 idx);
1453
1454 this->_blocks[idx] = in;
1455 }
1456 void put_block(const Tensor &in, const std::vector<cytnx_int64> &indices, const bool &check) {
1457 cytnx_error_msg(in.dtype() != this->dtype(),
1458 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
1459 "\n");
1460 cytnx_error_msg(in.device() != this->device(),
1461 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
1462 "match.%s",
1463 "\n");
1464 // We shouldn't check the contiguous
1465 // cytnx_error_msg(!in.contiguous());
1466 cytnx_error_msg(indices.size() != this->rank(),
1467 "[ERROR][put_block][BlockUniTensor] len(indices) must be the same as the "
1468 "Tensor rank (number of legs).%s",
1469 "\n");
1470
1471 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1472
1473 // find if the indices specify exists!
1474 cytnx_int64 b = -1;
1475 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1476 if (inds == this->_inner_to_outer_idx[i]) {
1477 b = i;
1478 break;
1479 }
1480 }
1481
1482 if (b < 0) {
1483 if (check) {
1484 cytnx_error_msg(true,
1485 "[ERROR][put_block][BlockUniTensor] no avaliable block exists, "
1486 "check=true, so error throws. \n If you want without error when block "
1487 "is not avaliable, set check=false.%s",
1488 "\n");
1489 }
1490 } else {
1492 in.shape() != this->_blocks[b].shape(),
1493 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1494 "of block @ idx=%d\n",
1495 b);
1496
1497 this->_blocks[b] = in.clone();
1498 }
1499 }
1500 void put_block_(Tensor &in, const std::vector<cytnx_int64> &indices, const bool &check) {
1501 cytnx_error_msg(in.dtype() != this->dtype(),
1502 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
1503 "\n");
1504 cytnx_error_msg(in.device() != this->device(),
1505 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
1506 "match.%s",
1507 "\n");
1508 // We shouldn't check the contiguous
1509 // cytnx_error_msg(!in.contiguous());
1510 cytnx_error_msg(indices.size() != this->rank(),
1511 "[ERROR][put_block][BlockUniTensor] len(indices) must be the same as the "
1512 "Tensor rank (number of legs).%s",
1513 "\n");
1514
1515 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1516
1517 // find if the indices specify exists!
1518 cytnx_int64 b = -1;
1519 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1520 if (inds == this->_inner_to_outer_idx[i]) {
1521 b = i;
1522 break;
1523 }
1524 }
1525
1526 if (b < 0) {
1527 if (check) {
1528 cytnx_error_msg(true,
1529 "[ERROR][put_block][BlockUniTensor] no avaliable block exists, "
1530 "check=true, so error throws. \n If you want without error when block "
1531 "is not avaliable, set check=false.%s",
1532 "\n");
1533 }
1534 } else {
1536 in.shape() != this->_blocks[b].shape(),
1537 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1538 "of block @ idx=%d\n",
1539 b);
1540 this->_blocks[b] = in;
1541 }
1542 }
1543
1544 void tag() {
1545 // no-use!
1546 }
1547
1548 boost::intrusive_ptr<UniTensor_base> Conj() {
1549 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1550 out->Conj_();
1551 return out;
1552 }
1553
1554 void Conj_() {
1555 for (int i = 0; i < this->_blocks.size(); i++) {
1556 this->_blocks[i].Conj_();
1557 }
1558 };
1559
1560 void Transpose_();
1561 boost::intrusive_ptr<UniTensor_base> Transpose() {
1562 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1563 out->Transpose_();
1564 return out;
1565 }
1566
1567 void normalize_();
1568 boost::intrusive_ptr<UniTensor_base> normalize() {
1569 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1570 out->normalize_();
1571 return out;
1572 }
1573
1574 boost::intrusive_ptr<UniTensor_base> Dagger() {
1575 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
1576 out->Transpose_();
1577 return out;
1578 }
1579 void Dagger_() {
1580 this->Conj_();
1581 this->Transpose_();
1582 }
1583
1584 void Trace_(const std::string &a, const std::string &b);
1585 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
1586
1587 boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b) {
1588 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1589 out->Trace_(a, b);
1590 if (out->rank() == 0) {
1591 DenseUniTensor *tmp = new DenseUniTensor();
1592 tmp->_block = ((BlockUniTensor *)out.get())->_blocks[0];
1593 out = boost::intrusive_ptr<UniTensor_base>(tmp);
1594 }
1595 return out;
1596 }
1597 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b) {
1598 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1599 out->Trace_(a, b);
1600 if (out->rank() == 0) {
1601 DenseUniTensor *tmp = new DenseUniTensor();
1602 tmp->_block = ((BlockUniTensor *)out.get())->_blocks[0];
1603 out = boost::intrusive_ptr<UniTensor_base>(tmp);
1604 }
1605 return out;
1606 }
1607
1608 Tensor Norm() const;
1609
1610 bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
1611
1612 const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const;
1613 const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1614 const cytnx_complex128 &aux) const;
1615 const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1616 const cytnx_complex64 &aux) const;
1617 const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1618 const cytnx_double &aux) const;
1619 const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1620 const cytnx_float &aux) const;
1621 const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1622 const cytnx_uint64 &aux) const;
1623 const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1624 const cytnx_int64 &aux) const;
1625 const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1626 const cytnx_uint32 &aux) const;
1627 const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1628 const cytnx_int32 &aux) const;
1629 const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1630 const cytnx_uint16 &aux) const;
1631 const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1632 const cytnx_int16 &aux) const;
1633
1634 Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator);
1635 cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1636 const cytnx_complex128 &aux);
1637 cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1638 const cytnx_complex64 &aux);
1639 cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux);
1640 cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux);
1641 cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux);
1642 cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux);
1643 cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux);
1644 cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux);
1645 cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux);
1646 cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux);
1647
1648 void _save_dispatch(std::fstream &f) const;
1649 void _load_dispatch(std::fstream &f);
1650
1651 // this will remove the [q_index]-th qnum at [bond_idx]-th Bond!
1652 void truncate_(const std::string &bond_idx, const cytnx_uint64 &q_index);
1653 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &q_index);
1654
1655 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1656 void Add_(const Scalar &rhs) {
1658 true,
1659 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s "
1660 "\n",
1661 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1662 "operation on the block(s).");
1663 }
1664
1665 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1666 void Mul_(const Scalar &rhs);
1667
1668 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1669 void Sub_(const Scalar &rhs) {
1671 true,
1672 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s "
1673 "\n",
1674 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1675 "operation on the block(s).");
1676 }
1677 void lSub_(const Scalar &lhs) {
1679 true,
1680 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s "
1681 "\n",
1682 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1683 "operation on the block(s).");
1684 }
1685
1686 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs) {
1688 true,
1689 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s "
1690 "\n",
1691 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1692 "operation on the block(s).");
1693 }
1694 void Div_(const Scalar &rhs);
1695 void lDiv_(const Scalar &lhs) {
1697 true,
1698 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s "
1699 "\n",
1700 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1701 "operation on the block(s).");
1702 }
1703 void from_(const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &force);
1704
1705 void group_basis_();
1706
1707 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = false);
1708 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
1709 const bool &by_label);
1710 void combineBonds(const std::vector<std::string> &indicators, const bool &force = false);
1711
1712 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
1714 bidx >= this->Nblocks(),
1715 "[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
1716 this->Nblocks());
1717 return this->_inner_to_outer_idx[bidx];
1718 }
1719 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
1721 bidx >= this->Nblocks(),
1722 "[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
1723 this->Nblocks());
1724 return this->_inner_to_outer_idx[bidx];
1725 }
1726
1727 const vec2d<cytnx_uint64> &get_itoi() const { return this->_inner_to_outer_idx; }
1728 vec2d<cytnx_uint64> &get_itoi() { return this->_inner_to_outer_idx; }
1729 };
1731 //======================================================================
1732
1734 class UniTensor_options {
1735 public:
1736 bool _is_diag;
1737 int _dtype;
1738 int _device;
1739 int _rowrank;
1740
1741 UniTensor_options() {
1742 this->_is_diag = false;
1743 this->_dtype = Type.Double;
1744 this->_device = Device.cpu;
1745 this->_rowrank = -1;
1746 }
1747
1748 UniTensor_options(const UniTensor_options &rhs) {
1749 this->_is_diag = rhs._is_diag;
1750 this->_dtype = rhs._dtype;
1751 this->_device = rhs._device;
1752 this->_rowrank = rhs._rowrank;
1753 }
1754
1755 UniTensor_options &operator=(const UniTensor_options &rhs) {
1756 this->_is_diag = rhs._is_diag;
1757 this->_dtype = rhs._dtype;
1758 this->_device = rhs._device;
1759 this->_rowrank = rhs._rowrank;
1760 return *this;
1761 }
1762
1763 UniTensor_options &is_diag(const bool &in) {
1764 this->_is_diag = in;
1765 return *this;
1766 }
1767 UniTensor_options &dtype(const int &in) {
1768 this->_dtype = in;
1769 return *this;
1770 }
1771 UniTensor_options &device(const int &in) {
1772 this->_device = in;
1773 return *this;
1774 }
1775 UniTensor_options &rowrank(const int &in) {
1776 this->_rowrank = in;
1777 return *this;
1778 }
1779 };
1781
1784 public:
1786 boost::intrusive_ptr<UniTensor_base> _impl;
1787 UniTensor() : _impl(new UniTensor_base()){};
1788 UniTensor(const UniTensor &rhs) { this->_impl = rhs._impl; }
1789 UniTensor &operator=(const UniTensor &rhs) {
1790 this->_impl = rhs._impl;
1791 return *this;
1792 }
1794
1796
1822 explicit UniTensor(const Tensor &in_tensor, const bool &is_diag = false,
1823 const cytnx_int64 &rowrank = -1,
1824 const std::vector<std::string> &in_labels = {}, const std::string &name = "")
1825 : _impl(new UniTensor_base()) {
1826 this->Init(in_tensor, is_diag, rowrank, in_labels, name);
1827 }
1845 void Init(const Tensor &in_tensor, const bool &is_diag = false, const cytnx_int64 &rowrank = -1,
1846 const std::vector<std::string> &in_labels = {}, const std::string &name = "") {
1847 // std::cout << "[entry!]" << std::endl;
1848 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
1849 out->Init_by_Tensor(in_tensor, is_diag, rowrank, name);
1850 this->_impl = out;
1851 if (in_labels.size() != 0) this->set_labels(in_labels);
1852 }
1854
1856
1873 UniTensor(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1874 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1875 const int &device = Device.cpu, const bool &is_diag = false,
1876 const std::string &name = "")
1877 : _impl(new UniTensor_base()) {
1878 #ifdef UNI_DEBUG
1880 true,
1881 "[DEBUG] message: entry for UniTensor(const std::vector<Bond> &bonds, const "
1882 "std::vector<std::string> &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned "
1883 "int "
1884 "&dtype=Type.Double, const int &device = Device.cpu, const bool &is_diag=false)%s",
1885 "\n");
1886 #endif
1887 this->Init(bonds, in_labels, rowrank, dtype, device, is_diag, name);
1888 }
1889
1891 /* [developing]
1892 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1893 const UniTensor_options &UToptions = UniTensor_options(), const std::string &name =
1894 ""){ this->Init(bonds,in_labels, UToptions._rowrank, UToptions._dtype , UToptions._device ,
1895 UToptions._is_diag,
1896 name);
1897 }
1898 */
1900
1924 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1925 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1926 const int &device = Device.cpu, const bool &is_diag = false,
1927 const std::string &name = "") {
1928 // checking type:
1929 bool is_sym = false;
1930 int sym_fver = -1;
1931
1932 for (cytnx_uint64 i = 0; i < bonds.size(); i++) {
1933 // check
1934 if (bonds[i].syms().size() != 0) {
1935 is_sym = true;
1936 if (sym_fver == -1)
1937 sym_fver = bonds[i]._impl->_degs.size();
1938 else {
1939 // std::cout << sym_fver << " " <<
1940 // bonds[i]._impl->_degs.size() << std::endl;
1941 cytnx_error_msg((bool(sym_fver) ^ bool(bonds[i]._impl->_degs.size())),
1942 "[ERROR] All the Bond when init a UniTensor with symmetric must be in "
1943 "the same format!%s",
1944 "\n");
1945 }
1946 } else
1948 is_sym, "[ERROR] cannot have bonds with mixing of symmetry and non-symmetry.%s", "\n");
1949 }
1950
1951 // dynamical dispatch:
1952 if (is_sym) {
1953 #ifdef UNI_DEBUG
1954 cytnx_warning_msg(true, "[DEBUG] message: entry dispatch: UniTensor: symmetric%s", "\n");
1955 #endif
1956 // cytnx_warning_msg(true,"[warning, still developing, some functions will display
1957 // \"[Developing]\"][SparseUniTensor]%s","\n");
1958 if (sym_fver == 0) {
1959 // boost::intrusive_ptr<UniTensor_base> out(new SparseUniTensor());
1960 // this->_impl = out;
1961 cytnx_error_msg(true,
1962 "[ERROR] internal error! [legacy Sparse entry] the Bond is symmetry but "
1963 "the version is not properly determined!%s",
1964 "\n")
1965 } else if (sym_fver == -1) {
1966 cytnx_error_msg(true,
1967 "[ERROR] internal error! the Bond is symmetry but the version is not "
1968 "properly determined!%s",
1969 "\n");
1970 } else {
1971 boost::intrusive_ptr<UniTensor_base> out(new BlockUniTensor());
1972 this->_impl = out;
1973 }
1974 } else {
1975 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
1976 this->_impl = out;
1977 }
1978 this->_impl->Init(bonds, in_labels, rowrank, dtype, device, is_diag, false, name);
1979 }
1980
1987 UniTensor &set_name(const std::string &in) {
1988 this->_impl->set_name(in);
1989 return *this;
1990 }
1991
2002 UniTensor &set_label(const cytnx_int64 &idx, const std::string &new_label) {
2003 this->_impl->set_label(idx, new_label);
2004 return *this;
2005 }
2006
2011 this->_impl->set_label(idx, std::string(new_label));
2012 return *this;
2013 }
2014
2025 UniTensor &set_label(const std::string &old_label, const std::string &new_label) {
2026 this->_impl->set_label(old_label, new_label);
2027 return *this;
2028 }
2029
2033 UniTensor &set_label(const char *old_label, const std::string &new_label) {
2034 this->_impl->set_label(std::string(old_label), new_label);
2035 return *this;
2036 }
2037
2041 UniTensor &set_label(const std::string &old_label, const char *new_label) {
2042 this->_impl->set_label(old_label, std::string(new_label));
2043 return *this;
2044 }
2045
2049 UniTensor &set_label(const char *old_label, const char *new_label) {
2050 this->_impl->set_label(std::string(old_label), std::string(new_label));
2051 return *this;
2052 }
2053
2054 /*
2055 UniTensor& change_label(const cytnx_int64 &old_label, const cytnx_int64 &new_label){
2056 this->_impl->change_label(old_label,new_label);
2057 return *this;
2058 }
2059 */
2060
2070 UniTensor &set_labels(const std::vector<std::string> &new_labels) {
2071 this->_impl->set_labels(new_labels);
2072 return *this;
2073 }
2074
2079 UniTensor &set_labels(const std::initializer_list<char *> &new_labels) {
2080 std::vector<char *> new_lbls(new_labels);
2081 std::vector<std::string> vs(new_lbls.size());
2082 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2083 [](char *x) -> std::string { return std::string(x); });
2084
2085 this->_impl->set_labels(vs);
2086 return *this;
2087 }
2088
2096 this->_impl->set_rowrank_(new_rowrank);
2097 return *this;
2098 }
2099
2101 UniTensor out;
2102 out._impl = this->_impl->set_rowrank(new_rowrank);
2103 return out;
2104 }
2105
2106 template <class T>
2107 T &item() {
2109 "[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use "
2110 "get_block()/get_blocks() first.%s",
2111 "\n");
2112
2113 DenseUniTensor *tmp = static_cast<DenseUniTensor *>(this->_impl.get());
2114 return tmp->_block.item<T>();
2115 }
2116
2117 Scalar::Sproxy item() const {
2119 "[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use "
2120 "get_block()/get_blocks() first.%s",
2121 "\n");
2122
2123 DenseUniTensor *tmp = static_cast<DenseUniTensor *>(this->_impl.get());
2124 return tmp->_block.item();
2125 }
2130 cytnx_uint64 Nblocks() const { return this->_impl->Nblocks(); }
2131
2136 cytnx_uint64 rank() const { return this->_impl->rank(); }
2137
2142 cytnx_uint64 rowrank() const { return this->_impl->rowrank(); }
2143
2149 unsigned int dtype() const { return this->_impl->dtype(); }
2150
2157 int uten_type() const { return this->_impl->uten_type(); }
2158
2164 int device() const { return this->_impl->device(); }
2165
2170 std::string name() const { return this->_impl->name(); }
2171
2177 std::string dtype_str() const { return this->_impl->dtype_str(); }
2178
2184 std::string device_str() const { return this->_impl->device_str(); }
2185
2191 std::string uten_type_str() const { return this->_impl->uten_type_str(); }
2192
2198 bool is_contiguous() const { return this->_impl->is_contiguous(); }
2199
2204 bool is_diag() const { return this->_impl->is_diag(); }
2205
2211 bool is_tag() const { return this->_impl->is_tag(); }
2212
2218 std::vector<Symmetry> syms() const { return this->_impl->syms(); }
2219
2226 const bool &is_braket_form() const { return this->_impl->is_braket_form(); }
2227
2232 const std::vector<std::string> &labels() const { return this->_impl->labels(); }
2239 cytnx_int64 get_index(std::string label) const { return this->_impl->get_index(label); }
2240
2245 const std::vector<Bond> &bonds() const { return this->_impl->bonds(); }
2246
2250 std::vector<Bond> &bonds() { return this->_impl->bonds(); }
2251
2252 const Bond &bond_(const cytnx_uint64 &idx) const { return this->_impl->bond_(idx); }
2253 Bond &bond_(const cytnx_uint64 &idx) { return this->_impl->bond_(idx); }
2254
2255 const Bond &bond_(const std::string &label) const { return this->_impl->bond_(label); }
2256 Bond &bond_(const std::string &label) { return this->_impl->bond_(label); }
2257
2258 Bond bond(const cytnx_uint64 &idx) const { return this->_impl->bond_(idx).clone(); }
2259 Bond bond(const std::string &label) const { return this->_impl->bond_(label).clone(); }
2260
2265 std::vector<cytnx_uint64> shape() const { return this->_impl->shape(); }
2266
2272 bool is_blockform() const { return this->_impl->is_blockform(); }
2273
2280 void to_(const int &device) { this->_impl->to_(device); }
2281
2291 UniTensor to(const int &device) const {
2292 UniTensor out;
2293 out._impl = this->_impl->to(device);
2294 return out;
2295 }
2296
2302 UniTensor out;
2303 out._impl = this->_impl->clone();
2304 return out;
2305 }
2306
2316 UniTensor &relabels_(const std::vector<std::string> &new_labels) {
2317 this->_impl->relabels_(new_labels);
2318 return *this;
2319 }
2320
2332 UniTensor relabels(const std::vector<std::string> &new_labels) const {
2333 UniTensor out;
2334 out._impl = this->_impl->relabels(new_labels);
2335 return out;
2336 }
2337
2341 UniTensor relabels(const std::initializer_list<char *> &new_labels) const {
2342 std::vector<char *> new_lbls(new_labels);
2343 std::vector<std::string> vs(new_lbls.size());
2344 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2345 [](char *x) -> std::string { return std::string(x); });
2346
2347 UniTensor out;
2348 out._impl = this->_impl->relabels(vs);
2349 return out;
2350 }
2354 UniTensor &relabels_(const std::initializer_list<char *> &new_labels) {
2355 std::vector<char *> new_lbls(new_labels);
2356 std::vector<std::string> vs(new_lbls.size());
2357 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2358 [](char *x) -> std::string { return std::string(x); });
2359
2360 this->_impl->relabels_(vs);
2361 return *this;
2362 }
2363
2371 UniTensor relabels(const std::vector<std::string> &old_labels,
2372 const std::vector<std::string> &new_labels) const {
2373 UniTensor out;
2374 out._impl = this->_impl->relabels(old_labels, new_labels);
2375 return out;
2376 }
2377
2393 UniTensor &relabels_(const std::vector<std::string> &old_labels,
2394 const std::vector<std::string> &new_labels) {
2395 this->_impl->relabels_(old_labels, new_labels);
2396 return *this;
2397 }
2398
2403 UniTensor relabels(const std::initializer_list<char *> &old_labels,
2404 const std::initializer_list<char *> &new_labels) const {
2405 std::vector<char *> new_lbls(new_labels);
2406 std::vector<std::string> vs(new_lbls.size());
2407 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2408 [](char *x) -> std::string { return std::string(x); });
2409
2410 std::vector<char *> old_lbls(old_labels);
2411 std::vector<std::string> vs_old(old_lbls.size());
2412 transform(old_lbls.begin(), old_lbls.end(), vs_old.begin(),
2413 [](char *x) -> std::string { return std::string(x); });
2414
2415 return this->relabels(vs_old, vs);
2416 }
2417
2422 UniTensor &relabels_(const std::initializer_list<char *> &old_labels,
2423 const std::initializer_list<char *> &new_labels) {
2424 std::vector<char *> new_lbls(new_labels);
2425 std::vector<std::string> vs(new_lbls.size());
2426 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2427 [](char *x) -> std::string { return std::string(x); });
2428
2429 std::vector<char *> old_lbls(old_labels);
2430 std::vector<std::string> vs_old(old_lbls.size());
2431 transform(old_lbls.begin(), old_lbls.end(), vs_old.begin(),
2432 [](char *x) -> std::string { return std::string(x); });
2433
2434 this->relabels_(vs_old, vs);
2435 return *this;
2436 }
2437
2452 UniTensor relabel(const cytnx_int64 &inx, const std::string &new_label) const {
2453 UniTensor out;
2454 out._impl = this->_impl->relabel(inx, new_label);
2455 return out;
2456 }
2465 UniTensor &relabel_(const cytnx_int64 &inx, const std::string &new_label) {
2466 this->_impl->relabel_(inx, new_label);
2467 return *this;
2468 }
2469
2478 UniTensor &relabel_(const std::string &old_label, const std::string &new_label) {
2479 this->_impl->relabel_(old_label, new_label);
2480 return *this;
2481 }
2482
2497 UniTensor relabel(const std::string &old_label, const std::string &new_label) const {
2498 UniTensor out;
2499 out._impl = this->_impl->relabel(old_label, new_label);
2500 return out;
2501 }
2502
2509 UniTensor astype(const unsigned int &dtype) const {
2510 UniTensor out;
2511 if (this->dtype() == dtype) {
2512 out._impl = this->_impl;
2513 } else {
2514 out._impl = this->_impl->astype(dtype);
2515 }
2516 return out;
2517 }
2518
2527 UniTensor permute(const std::vector<cytnx_int64> &mapper,
2528 const cytnx_int64 &rowrank = -1) const {
2529 UniTensor out;
2530 out._impl = this->_impl->permute(mapper, rowrank);
2531 return out;
2532 }
2533
2540 UniTensor permute(const std::vector<std::string> &mapper,
2541 const cytnx_int64 &rowrank = -1) const {
2542 UniTensor out;
2543 out._impl = this->_impl->permute(mapper, rowrank);
2544 return out;
2545 }
2546
2550 UniTensor permute(const std::initializer_list<char *> &mapper,
2551 const cytnx_int64 &rowrank = -1) const {
2552 std::vector<char *> mprs = mapper;
2553 std::vector<std::string> vs(mprs.size());
2554 transform(mprs.begin(), mprs.end(), vs.begin(),
2555 [](char *x) -> std::string { return std::string(x); });
2556
2557 return this->permute(vs, rowrank);
2558 }
2559
2568 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1) {
2569 this->_impl->permute_(mapper, rowrank);
2570 }
2571
2578 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1) {
2579 this->_impl->permute_(mapper, rowrank);
2580 }
2581
2582 // void permute_( const std::initializer_list<char*> &mapper, const cytnx_int64 &rowrank= -1){
2583 // std::vector<char*> mprs = mapper;
2584 // std::vector<std::string> vs(mprs.size());
2585 // transform(mprs.begin(),mprs.end(),vs.begin(),[](char * x) -> std::string { return
2586 // std::string(x); });
2587
2588 // this->permute_(vs,rowrank);
2589 // }
2590
2591 // void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1) {
2592 // this->_impl->permute_(mapper, rowrank);
2593 // }
2594
2600 UniTensor out;
2601 out._impl = this->_impl->contiguous();
2602 return out;
2603 }
2604
2609 void contiguous_() { this->_impl = this->_impl->contiguous_(); }
2610
2615 void print_diagram(const bool &bond_info = false) { this->_impl->print_diagram(bond_info); }
2616
2621 void print_blocks(const bool &full_info = true) const { this->_impl->print_blocks(full_info); }
2622
2628 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const {
2629 this->_impl->print_block(idx, full_info);
2630 }
2631
2638 void group_basis_() { this->_impl->group_basis_(); }
2639
2641 UniTensor out = this->clone();
2642 out.group_basis_();
2643 return out;
2644 }
2645
2651 template <class T>
2652 T &at(const std::vector<cytnx_uint64> &locator) {
2653 // std::cout << "at " << this->is_blockform() << std::endl;
2654 if (this->uten_type() == UTenType.Block) {
2655 // [NEW] this will not check if it exists, if it is not then error will throw!
2656 T aux;
2657 return this->_impl->at_for_sparse(locator, aux);
2658
2659 } else if (this->uten_type() == UTenType.Sparse) {
2660 if (this->_impl->elem_exists(locator)) {
2661 T aux;
2662 return this->_impl->at_for_sparse(locator, aux);
2663 } else {
2664 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2665 "\n");
2666 }
2667 } else {
2668 return this->get_block_().at<T>(locator);
2669 }
2670 }
2671
2677 template <class T>
2678 const T &at(const std::vector<cytnx_uint64> &locator) const {
2679 // std::cout << "at " << this->is_blockform() << std::endl;
2680 if (this->uten_type() == UTenType.Block) {
2681 // [NEW] this will not check if it exists, if it is not then error will throw!
2682 T aux;
2683 return this->_impl->at_for_sparse(locator, aux);
2684
2685 } else if (this->uten_type() == UTenType.Sparse) {
2686 if (this->_impl->elem_exists(locator)) {
2687 T aux; // [workaround] use aux to dispatch.
2688 return this->_impl->at_for_sparse(locator, aux);
2689 } else {
2690 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2691 "\n");
2692 }
2693 } else {
2694 return this->get_block_().at<T>(locator);
2695 }
2696 }
2697
2698 template <class T>
2699 const T &at(const std::vector<std::string> &labels,
2700 const std::vector<cytnx_uint64> &locator) const {
2701 // giving label <-> locator one to one corresponding, return the element:
2702 cytnx_error_msg(locator.size() != labels.size(),
2703 "[ERROR][at] length of list should be the same for label and locator.%s",
2704 "\n");
2706 labels.size() != this->rank(),
2707 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
2708 std::vector<cytnx_uint64> new_locator(this->rank());
2710 for (int i = 0; i < labels.size(); i++) {
2711 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
2712 cytnx_error_msg(res == this->_impl->_labels.end(),
2713 "[ERROR] label:%s does not exist in current UniTensor.\n",
2714 labels[i].c_str());
2715 new_loc = std::distance(this->_impl->_labels.begin(), res);
2717 }
2718 return this->at<T>(new_locator);
2719 }
2720 template <class T>
2721 T &at(const std::vector<std::string> &labels, const std::vector<cytnx_uint64> &locator) {
2722 // giving label <-> locator one to one corresponding, return the element:
2723 cytnx_error_msg(locator.size() != labels.size(),
2724 "[ERROR][at] length of list should be the same for label and locator.%s",
2725 "\n");
2727 labels.size() != this->rank(),
2728 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
2729 std::vector<cytnx_uint64> new_locator(this->rank());
2731 for (int i = 0; i < labels.size(); i++) {
2732 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
2733 cytnx_error_msg(res == this->_impl->_labels.end(),
2734 "[ERROR] label:%s does not exist in current UniTensor.\n",
2735 labels[i].c_str());
2736 new_loc = std::distance(this->_impl->_labels.begin(), res);
2738 }
2739 return this->at<T>(new_locator);
2740 }
2741
2746 const Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) const {
2747 if (this->uten_type() == UTenType.Block) {
2748 return this->_impl->at_for_sparse(locator);
2749 } else if (this->uten_type() == UTenType.Sparse) {
2750 if (this->_impl->elem_exists(locator)) {
2751 return this->_impl->at_for_sparse(locator);
2752 } else {
2753 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2754 "\n");
2755 }
2756 } else {
2757 return this->get_block_().at(locator);
2758 }
2759 }
2760
2765 Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) {
2766 if (this->uten_type() == UTenType.Block) {
2767 return this->_impl->at_for_sparse(locator);
2768 } else if (this->uten_type() == UTenType.Sparse) {
2769 if (this->_impl->elem_exists(locator)) {
2770 return this->_impl->at_for_sparse(locator);
2771 } else {
2772 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2773 "\n");
2774 }
2775 } else {
2776 return this->get_block_().at(locator);
2777 }
2778 }
2779
2780 Scalar::Sproxy at(const std::vector<std::string> &labels,
2781 const std::vector<cytnx_uint64> &locator) {
2782 // giving label <-> locator one to one corresponding, return the element:
2783 cytnx_error_msg(locator.size() != labels.size(),
2784 "[ERROR][at] length of list should be the same for label and locator.%s",
2785 "\n");
2787 labels.size() != this->rank(),
2788 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
2789 std::vector<cytnx_uint64> new_locator(this->rank());
2791 for (int i = 0; i < labels.size(); i++) {
2792 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
2793 cytnx_error_msg(res == this->_impl->_labels.end(),
2794 "[ERROR] label:%s does not exist in current UniTensor.\n",
2795 labels[i].c_str());
2796 new_loc = std::distance(this->_impl->_labels.begin(), res);
2798 }
2799 return this->at(new_locator);
2800 }
2801
2802 const Scalar::Sproxy at(const std::vector<std::string> &labels,
2803 const std::vector<cytnx_uint64> &locator) const {
2804 // giving label <-> locator one to one corresponding, return the element:
2805 cytnx_error_msg(locator.size() != labels.size(),
2806 "[ERROR][at] length of list should be the same for label and locator.%s",
2807 "\n");
2809 labels.size() != this->rank(),
2810 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
2811 std::vector<cytnx_uint64> new_locator(this->rank());
2813 for (int i = 0; i < labels.size(); i++) {
2814 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
2815 cytnx_error_msg(res == this->_impl->_labels.end(),
2816 "[ERROR] label:%s does not exist in current UniTensor.\n",
2817 labels[i].c_str());
2818 new_loc = std::distance(this->_impl->_labels.begin(), res);
2820 }
2821 return this->at(new_locator);
2822 }
2823
2824 // return a clone of block
2830 Tensor get_block(const cytnx_uint64 &idx = 0) const { return this->_impl->get_block(idx); };
2831 //================================
2832 // return a clone of block
2841 Tensor get_block(const std::vector<cytnx_int64> &qidx, const bool &force = false) const {
2842 return this->_impl->get_block(qidx, force);
2843 }
2844
2845 Tensor get_block(const std::vector<std::string> &labels, const std::vector<cytnx_int64> &qidx,
2846 const bool &force = false) const {
2848 labels.size() != qidx.size(),
2849 "[ERROR][get_block] length of lists must be the same for both lables and qnidices%s", "\n");
2850 cytnx_error_msg(labels.size() != this->rank(),
2851 "[ERROR][get_block] length of lists must be the rank (# of legs)%s", "\n");
2852
2853 std::vector<cytnx_int64> loc_id(this->rank());
2854 std::vector<cytnx_int64> new_qidx(this->rank());
2855
2857 std::vector<cytnx_uint64> new_order(this->rank());
2858 for (int i = 0; i < labels.size(); i++) {
2859 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
2860 cytnx_error_msg(res == this->_impl->_labels.end(),
2861 "[ERROR][get_block] label:%s does not exists in current Tensor.\n",
2862 labels[i].c_str());
2863 new_loc = std::distance(this->_impl->_labels.begin(), res);
2864 new_qidx[new_loc] = qidx[i];
2865 new_order[i] = new_loc;
2866 }
2867 auto out = this->_impl->get_block(new_qidx, force);
2868 if (out.dtype() != Type.Void) out.permute_(new_order);
2869 return out;
2870 }
2871
2876 Tensor get_block(const std::initializer_list<cytnx_int64> &qnum,
2877 const bool &force = false) const {
2878 std::vector<cytnx_int64> tmp = qnum;
2879 return get_block(tmp, force);
2880 }
2881
2886 Tensor get_block(const std::vector<cytnx_uint64> &qnum, const bool &force = false) const {
2887 std::vector<cytnx_int64> iqnum(qnum.begin(), qnum.end());
2888 return this->_impl->get_block(iqnum, force);
2889 }
2890
2891 Tensor get_block(const std::vector<std::string> &labels, const std::vector<cytnx_uint64> &qidx,
2892 const bool &force = false) const {
2893 std::vector<cytnx_int64> iqnum(qidx.begin(), qidx.end());
2894 return this->get_block(labels, iqnum, force);
2895 }
2896
2902 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const {
2903 return this->_impl->get_block_(idx);
2904 }
2905
2910 Tensor &get_block_(const cytnx_uint64 &idx = 0) { return this->_impl->get_block_(idx); }
2911
2920 Tensor &get_block_(const std::vector<cytnx_int64> &qidx, const bool &force = false) {
2921 return this->_impl->get_block_(qidx, force);
2922 }
2923
2938 // developer note: Tensor is not the same object (Thus Tensor instead of Tensor& ),
2939 // since we permute! but they have shared data memory.
2940 Tensor get_block_(const std::vector<std::string> &labels, const std::vector<cytnx_int64> &qidx,
2941 const bool &force = false) {
2943 labels.size() != qidx.size(),
2944 "[ERROR][get_block] length of lists must be the same for both lables and qnidices%s", "\n");
2945 cytnx_error_msg(labels.size() != this->rank(),
2946 "[ERROR][get_block] length of lists must be the rank (# of legs)%s", "\n");
2947
2948 std::vector<cytnx_int64> loc_id(this->rank());
2949 std::vector<cytnx_int64> new_qidx(this->rank());
2950
2952 std::vector<cytnx_uint64> new_order(this->rank());
2953 for (int i = 0; i < labels.size(); i++) {
2954 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
2955 cytnx_error_msg(res == this->_impl->_labels.end(),
2956 "[ERROR][get_block] label:%s does not exists in current Tensor.\n",
2957 labels[i].c_str());
2958 new_loc = std::distance(this->_impl->_labels.begin(), res);
2959 new_qidx[new_loc] = qidx[i];
2960 new_order[i] = new_loc;
2961 }
2962 auto out = this->_impl->get_block_(new_qidx, force);
2963 if (out.dtype() != Type.Void) {
2964 out = out.permute(new_order);
2965 }
2966 return out;
2967 }
2968
2972 Tensor &get_block_(const std::initializer_list<cytnx_int64> &qidx, const bool &force = false) {
2973 std::vector<cytnx_int64> tmp = qidx;
2974 return get_block_(tmp, force);
2975 }
2976
2980 Tensor &get_block_(const std::vector<cytnx_uint64> &qidx, const bool &force = false) {
2981 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
2982 return get_block_(iqidx, force);
2983 }
2984
2985 Tensor get_block_(const std::vector<std::string> &labels, const std::vector<cytnx_uint64> &qidx,
2986 const bool &force = false) {
2987 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
2988 return get_block_(labels, iqidx, force);
2989 }
2990 //================================
2991
2992 // this only work for non-symm tensor. return a shared view of block
2996 const Tensor &get_block_(const std::vector<cytnx_int64> &qidx,
2997 const bool &force = false) const {
2998 return this->_impl->get_block_(qidx, force);
2999 }
3000
3004 const Tensor &get_block_(const std::initializer_list<cytnx_int64> &qidx,
3005 const bool &force = false) const {
3006 std::vector<cytnx_int64> tmp = qidx;
3007 return this->_impl->get_block_(tmp, force);
3008 }
3009
3013 const Tensor &get_block_(const std::vector<cytnx_uint64> &qidx,
3014 const bool &force = false) const {
3015 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
3016 return get_block_(iqidx, force);
3017 }
3018
3019 //================================
3028 //[dev]
3029 std::vector<Tensor> get_blocks() const { return this->_impl->get_blocks(); }
3030
3036 //[dev]
3037 const std::vector<Tensor> &get_blocks_(const bool &silent = false) const {
3038 return this->_impl->get_blocks_(silent);
3039 }
3040
3044 //[dev]
3045 std::vector<Tensor> &get_blocks_(const bool &silent = false) {
3046 return this->_impl->get_blocks_(silent);
3047 }
3048
3054 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
3055 this->_impl->put_block(in, idx);
3056 }
3057
3065 void put_block(const Tensor &in_tens, const std::vector<cytnx_int64> &qidx, const bool &force) {
3066 this->_impl->put_block(in_tens, qidx, force);
3067 }
3068
3073 void put_block(Tensor &in, const std::vector<std::string> &lbls,
3074 const std::vector<cytnx_int64> &qidx, const bool &force = false) {
3076 lbls.size() != qidx.size(),
3077 "[ERROR][put_block] length of lists must be the same for both lables and qnidices%s", "\n");
3078 cytnx_error_msg(lbls.size() != this->rank(),
3079 "[ERROR][put_block] length of lists must be the rank (# of legs)%s", "\n");
3080
3081 std::vector<cytnx_int64> loc_id(this->rank());
3082 std::vector<cytnx_int64> new_qidx(this->rank());
3083
3085 // std::vector<cytnx_uint64> new_order(this->rank());
3086 std::vector<cytnx_uint64> inv_order(this->rank());
3087 for (int i = 0; i < lbls.size(); i++) {
3088 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), lbls[i]);
3089 cytnx_error_msg(res == this->_impl->_labels.end(),
3090 "[ERROR][put_block] label:%s does not exists in current Tensor.\n",
3091 lbls[i].c_str());
3092 new_loc = std::distance(this->_impl->_labels.begin(), res);
3093 new_qidx[new_loc] = qidx[i];
3094 // new_order[i] = new_loc;
3095 inv_order[new_loc] = i;
3096 }
3097 this->_impl->put_block(in.permute(inv_order), new_qidx, force);
3098 }
3099
3105 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) { this->_impl->put_block_(in, idx); }
3106
3113 void put_block_(Tensor &in, const std::vector<cytnx_int64> &qidx, const bool &force) {
3114 this->_impl->put_block_(in, qidx, force);
3115 }
3116
3121 void put_block_(Tensor &in, const std::vector<std::string> &lbls,
3122 const std::vector<cytnx_int64> &qidx, const bool &force = false) {
3124 lbls.size() != qidx.size(),
3125 "[ERROR][put_block_] length of lists must be the same for both lables and qnidices%s",
3126 "\n");
3127 cytnx_error_msg(lbls.size() != this->rank(),
3128 "[ERROR][put_block_] length of lists must be the rank (# of legs)%s", "\n");
3129
3130 std::vector<cytnx_int64> loc_id(this->rank());
3131 std::vector<cytnx_int64> new_qidx(this->rank());
3132
3134 std::vector<cytnx_uint64> new_order(this->rank());
3135 std::vector<cytnx_uint64> inv_order(this->rank());
3136 for (int i = 0; i < lbls.size(); i++) {
3137 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), lbls[i]);
3138 cytnx_error_msg(res == this->_impl->_labels.end(),
3139 "[ERROR][put_block_] label:%s does not exists in current Tensor.\n",
3140 lbls[i].c_str());
3141 new_loc = std::distance(this->_impl->_labels.begin(), res);
3142 new_qidx[new_loc] = qidx[i];
3143 new_order[i] = new_loc;
3144 inv_order[new_loc] = i;
3145 }
3146 in.permute_(inv_order);
3147 this->_impl->put_block_(in, new_qidx, force);
3148 in.permute_(new_order);
3149 }
3150 UniTensor get(const std::vector<Accessor> &accessors) const {
3151 UniTensor out;
3152 out._impl = this->_impl->get(accessors);
3153 return out;
3154 }
3155 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
3156 this->_impl->set(accessors, rhs);
3157 }
3158 void set(const std::vector<Accessor> &accessors, const UniTensor &rhs) {
3160 rhs.uten_type() != UTenType.Dense,
3161 "[ERROR] cannot set elements from UniTensor with symmetry. Use at() instead.%s", "\n");
3162 cytnx_error_msg(this->is_diag(), "[ERROR] cannot set UniTensor with is_diag=True.%s", "\n");
3164 "[ERROR] cannot set UniTensor. incoming UniTensor is_diag=True.%s", "\n");
3165
3166 this->_impl->set(accessors, rhs.get_block());
3167 }
3175 UniTensor reshape(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
3176 UniTensor out;
3177 out._impl = this->_impl->reshape(new_shape, rowrank);
3178 return out;
3179 }
3180
3187 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
3188 this->_impl->reshape_(new_shape, rowrank);
3189 }
3190
3203 UniTensor out;
3204 out._impl = this->_impl->to_dense();
3205 return out;
3206 }
3207
3212 void to_dense_() { this->_impl->to_dense_(); }
3213
3219 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
3220 const bool &by_label) {
3221 this->_impl->combineBonds(indicators, force, by_label);
3222 }
3223
3234 void combineBonds(const std::vector<std::string> &indicators, const bool &force = false) {
3235 this->_impl->combineBonds(indicators, force);
3236 }
3237
3243 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = false) {
3244 this->_impl->combineBonds(indicators, force);
3245 }
3246
3265 UniTensor contract(const UniTensor &inR, const bool &mv_elem_self = false,
3266 const bool &mv_elem_rhs = false) const {
3267 UniTensor out;
3268 out._impl = this->_impl->contract(inR._impl, mv_elem_self, mv_elem_rhs);
3269 return out;
3270 }
3271
3273
3281 std::vector<Bond> getTotalQnums(const bool physical = false) const {
3282 return this->_impl->getTotalQnums(physical);
3283 }
3284
3288 std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const {
3289 return this->_impl->get_blocks_qnums();
3290 }
3292
3297 bool same_data(const UniTensor &rhs) const {
3298 // check same type:
3299 if (this->_impl->uten_type() != rhs._impl->uten_type()) return false;
3300
3301 return this->_impl->same_data(rhs._impl);
3302 }
3303
3321 this->_impl->Add_(rhs._impl);
3322 return *this;
3323 }
3324
3342 this->_impl->Mul_(rhs._impl);
3343 return *this;
3344 }
3345
3363 this->_impl->Sub_(rhs._impl);
3364 return *this;
3365 }
3366
3384 this->_impl->Div_(rhs._impl);
3385 return *this;
3386 }
3387
3399 this->_impl->Add_(rhs);
3400 return *this;
3401 }
3402
3414 this->_impl->Mul_(rhs);
3415 return *this;
3416 }
3417
3429 this->_impl->Sub_(rhs);
3430 return *this;
3431 }
3432
3444 this->_impl->Div_(rhs);
3445 return *this;
3446 }
3447
3465
3476 UniTensor Add(const Scalar &rhs) const;
3477
3495
3506 UniTensor Mul(const Scalar &rhs) const;
3507
3525
3536 UniTensor Div(const Scalar &rhs) const;
3537
3555
3566 UniTensor Sub(const Scalar &rhs) const;
3567
3576 Tensor Norm() const { return this->_impl->Norm(); };
3577
3594 this->Add_(rhs);
3595 return *this;
3596 }
3597
3614 this->Sub_(rhs);
3615 return *this;
3616 }
3617
3634 this->Div_(rhs);
3635 return *this;
3636 }
3637
3654 this->Mul_(rhs);
3655 return *this;
3656 }
3657
3669 this->Add_(rhs);
3670 return *this;
3671 }
3672
3684 this->Sub_(rhs);
3685 return *this;
3686 }
3687
3699 this->Div_(rhs);
3700 return *this;
3701 }
3702
3714 this->Mul_(rhs);
3715 return *this;
3716 }
3717
3725 UniTensor Conj() const {
3726 UniTensor out;
3727 out._impl = this->_impl->Conj();
3728 return out;
3729 }
3730
3739 this->_impl->Conj_();
3740 return *this;
3741 }
3742
3754 UniTensor out;
3755 out._impl = this->_impl->Transpose();
3756 return out;
3757 }
3758
3766 this->_impl->Transpose_();
3767 return *this;
3768 }
3769
3777 UniTensor out;
3778 out._impl = this->_impl->normalize();
3779 return out;
3780 }
3781
3789 this->_impl->normalize_();
3790 return *this;
3791 }
3792
3802 UniTensor Trace(const std::string &a, const std::string &b) const {
3803 UniTensor out;
3804 out._impl = this->_impl->Trace(a, b);
3805 return out;
3806 }
3807
3817 UniTensor Trace(const cytnx_int64 &a = 0, const cytnx_int64 &b = 1) const {
3818 UniTensor out;
3819 out._impl = this->_impl->Trace(a, b);
3820 return out;
3821 }
3822
3832 UniTensor &Trace_(const std::string &a, const std::string &b) {
3833 this->_impl->Trace_(a, b);
3834 if (this->uten_type() == UTenType.Block) {
3835 // handle if no leg left case for BlockUniTensor.
3836 if (this->rank() == 0) {
3837 DenseUniTensor *tmp = new DenseUniTensor();
3838 tmp->_block = this->get_blocks_(true)[0];
3839 this->_impl = boost::intrusive_ptr<UniTensor_base>(tmp);
3840 }
3841 }
3842 return *this;
3843 }
3844
3854 UniTensor &Trace_(const cytnx_int64 &a = 0, const cytnx_int64 &b = 1) {
3855 this->_impl->Trace_(a, b);
3856 if (this->uten_type() == UTenType.Block) {
3857 // handle if no leg left case for BlockUniTensor.
3858 if (this->rank() == 0) {
3859 DenseUniTensor *tmp = new DenseUniTensor();
3860 tmp->_block = this->get_blocks_(true)[0];
3861 this->_impl = boost::intrusive_ptr<UniTensor_base>(tmp);
3862 }
3863 }
3864 return *this;
3865 }
3866
3874 UniTensor out;
3875 out._impl = this->_impl->Dagger();
3876 return out;
3877 }
3878
3886 this->_impl->Dagger_();
3887 return *this;
3888 }
3889
3899 this->_impl->tag();
3900 return *this;
3901 }
3902
3911 UniTensor Pow(const double &p) const;
3912
3921 UniTensor &Pow_(const double &p);
3922
3929 bool elem_exists(const std::vector<cytnx_uint64> &locator) const {
3930 return this->_impl->elem_exists(locator);
3931 }
3932
3938 template <class T>
3939 T get_elem(const std::vector<cytnx_uint64> &locator) const {
3940 return this->at<T>(locator);
3941 }
3942
3948 template <class T2>
3949 void set_elem(const std::vector<cytnx_uint64> &locator, const T2 &rc) {
3950 // cytnx_error_msg(true,"[ERROR] invalid type%s","\n");
3951 this->at(locator) = rc;
3952 }
3953
3960 void Save(const std::string &fname) const;
3961
3968 void Save(const char *fname) const;
3969
3978 static UniTensor Load(const std::string &fname);
3979
3988 static UniTensor Load(const char *fname);
3989
3998 UniTensor &truncate_(const std::string &label, const cytnx_uint64 &dim) {
3999 this->_impl->truncate_(label, dim);
4000 return *this;
4001 }
4002
4012 this->_impl->truncate_(bond_idx, dim);
4013 return *this;
4014 }
4015
4025 UniTensor truncate(const std::string &label, const cytnx_uint64 &dim) const {
4026 UniTensor out = this->clone();
4027 out.truncate_(label, dim);
4028 return out;
4029 }
4030
4041 UniTensor out = this->clone();
4042 out.truncate_(bond_idx, dim);
4043 return out;
4044 }
4045
4053 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
4054 return this->_impl->get_qindices(bidx);
4055 }
4063 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
4064 return this->_impl->get_qindices(bidx);
4065 }
4066
4073 const vec2d<cytnx_uint64> &get_itoi() const { return this->_impl->get_itoi(); }
4074 vec2d<cytnx_uint64> &get_itoi() { return this->_impl->get_itoi(); }
4075
4077 void _Load(std::fstream &f);
4078 void _Save(std::fstream &f) const;
4080
4081 UniTensor &convert_from(const UniTensor &rhs, const bool &force = false) {
4082 this->_impl->from_(rhs._impl, force);
4083 return *this;
4084 }
4085
4086 // Generators:
4100 const std::vector<std::string> &in_labels = {},
4101 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4102 const std::string &name = "") {
4103 return UniTensor(cytnx::zeros(Nelem, dtype, device), false, -1, in_labels, name);
4104 }
4105
4119 static UniTensor zeros(const std::vector<cytnx_uint64> &shape,
4120 const std::vector<std::string> &in_labels = {},
4121 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4122 const std::string &name = "") {
4123 return UniTensor(cytnx::zeros(shape, dtype, device), false, -1, in_labels, name);
4124 }
4125
4137 static UniTensor ones(const cytnx_uint64 &Nelem, const std::vector<std::string> &in_labels = {},
4138 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4139 const std::string &name = "") {
4140 return UniTensor(cytnx::ones(Nelem, dtype, device), false, -1, in_labels, name);
4141 }
4142
4156 const std::vector<std::string> &in_labels = {},
4157 const cytnx_bool &is_diag = false,
4158 const unsigned int &dtype = Type.Double,
4159 const int &device = Device.cpu, const std::string &name = "") {
4160 if (is_diag) {
4161 return UniTensor(cytnx::ones(dim, dtype, device), is_diag, -1, in_labels, name);
4162 } else {
4164 }
4165 }
4166
4182 static UniTensor eye(const cytnx_uint64 &dim, const std::vector<std::string> &in_labels = {},
4183 const cytnx_bool &is_diag = false, const unsigned int &dtype = Type.Double,
4184 const int &device = Device.cpu, const std::string &name = "") {
4185 return identity(dim, in_labels, is_diag, dtype, device, name);
4186 }
4187
4200 static UniTensor ones(const std::vector<cytnx_uint64> &shape,
4201 const std::vector<std::string> &in_labels = {},
4202 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4203 const std::string &name = "") {
4204 return UniTensor(cytnx::ones(shape, dtype, device), false, -1, in_labels, name);
4205 }
4206
4221 const std::vector<std::string> &in_labels = {},
4222 const std::string &name = "") {
4223 return UniTensor(cytnx::arange(Nelem), false, -1, in_labels, name);
4224 }
4225
4243 const cytnx_double &step = 1,
4244 const std::vector<std::string> &in_labels = {},
4245 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4246 const std::string &name = "") {
4247 return UniTensor(cytnx::arange(start, end, step, dtype, device), false, -1, in_labels, name);
4248 }
4249
4270 const cytnx_uint64 &Nelem, const bool &endpoint = true,
4271 const std::vector<std::string> &in_labels = {},
4272 const unsigned int &dtype = Type.Double,
4273 const int &device = Device.cpu, const std::string &name = "") {
4274 return UniTensor(cytnx::linspace(start, end, Nelem, endpoint, dtype, device), false, -1,
4275 in_labels, name);
4276 }
4277
4278 // Random Generators:
4297 static UniTensor normal(const cytnx_uint64 &Nelem, const double &mean, const double &std,
4298 const std::vector<std::string> &in_labels = {},
4299 const unsigned int &seed = cytnx::random::__static_random_device(),
4300 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4301 const std::string &name = "");
4302
4321 static UniTensor normal(const std::vector<cytnx_uint64> &shape, const double &mean,
4322 const double &std, const std::vector<std::string> &in_labels = {},
4323 const unsigned int &seed = cytnx::random::__static_random_device(),
4324 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4325 const std::string &name = "");
4326
4345 static UniTensor uniform(const cytnx_uint64 &Nelem, const double &low, const double &high,
4346 const std::vector<std::string> &in_labels = {},
4347 const unsigned int &seed = cytnx::random::__static_random_device(),
4348 const unsigned int &dtype = Type.Double,
4349 const int &device = Device.cpu, const std::string &name = "");
4350
4388 static UniTensor uniform(const std::vector<cytnx_uint64> &shape, const double &low,
4389 const double &high, const std::vector<std::string> &in_labels = {},
4390 const unsigned int &seed = cytnx::random::__static_random_device(),
4391 const unsigned int &dtype = Type.Double,
4392 const int &device = Device.cpu, const std::string &name = "");
4393
4394 // Inplace Random Generators:
4407 void normal_(const double &mean, const double &std,
4408 const unsigned int &seed = cytnx::random::__static_random_device());
4409
4422 void uniform_(const double &low = 0, const double &high = 1,
4423 const unsigned int &seed = cytnx::random::__static_random_device());
4424
4425 }; // class UniTensor
4426
4428 std::ostream &operator<<(std::ostream &os, const UniTensor &in);
4430
4443 UniTensor Contract(const UniTensor &inL, const UniTensor &inR, const bool &cacheL = false,
4444 const bool &cacheR = false);
4445
4458 UniTensor Contracts(const std::vector<UniTensor> &TNs, const std::string &order,
4459 const bool &optimal);
4460
4462 void _resolve_CT(std::vector<UniTensor> &TNlist);
4463 template <class... T>
4464 void _resolve_CT(std::vector<UniTensor> &TNlist, const UniTensor &in, const T &...args) {
4465 TNlist.push_back(in);
4466 _resolve_CT(TNlist, args...);
4467 }
4469
4481 template <class... T>
4482 UniTensor Contracts(const UniTensor &in, const T &...args, const std::string &order,
4483 const bool &optimal) {
4484 std::vector<UniTensor> TNlist;
4485 _resolve_CT(TNlist, in, args...);
4486 return Contracts(TNlist, order, optimal);
4487 }
4488
4489} // namespace cytnx
4490
4491#endif // BACKEND_TORCH
4492
4493#endif
the object contains auxiliary properties for each Tensor rank (bond)
Definition Bond.hpp:176
Bond clone() const
return a copy of the instance Bond
Definition Bond.hpp:488
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:1783
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:3065
UniTensor to(const int &device) const
move the current UniTensor to the assigned device.
Definition UniTensor.hpp:2291
UniTensor & operator*=(const UniTensor &rhs)
The multiplication assignment operator of the UniTensor.
Definition UniTensor.hpp:3653
static UniTensor eye(const cytnx_uint64 &dim, const std::vector< std::string > &in_labels={}, const cytnx_bool &is_diag=false, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a 2-bond identity UniTensor.
Definition UniTensor.hpp:4182
Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:2972
std::vector< Tensor > & get_blocks_(const bool &silent=false)
Definition UniTensor.hpp:3045
Tensor & get_block_(const std::vector< cytnx_uint64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:2980
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:2628
UniTensor & operator/=(const UniTensor &rhs)
The division assignment operator of the UniTensor.
Definition UniTensor.hpp:3633
T & item()
Definition UniTensor.hpp:2107
bool is_contiguous() const
To tell whether the UniTensor is contiguous.
Definition UniTensor.hpp:2198
T get_elem(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:3939
UniTensor Div(const UniTensor &rhs) const
The division function of the UniTensor.
Tensor get_block(const std::vector< std::string > &labels, const std::vector< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:2845
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:4063
UniTensor & set_label(const cytnx_int64 &idx, const char *new_label)
Definition UniTensor.hpp:2010
UniTensor & operator+=(const UniTensor &rhs)
The addition assignment operator of the UniTensor.
Definition UniTensor.hpp:3593
void to_dense_()
Convert the UniTensor to non-diagonal form, inplacely.
Definition UniTensor.hpp:3212
UniTensor reshape(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor.
Definition UniTensor.hpp:3175
std::vector< Tensor > get_blocks() const
Get all the blocks of the UniTensor.
Definition UniTensor.hpp:3029
UniTensor permute(const std::initializer_list< char * > &mapper, const cytnx_int64 &rowrank=-1) const
Definition UniTensor.hpp:2550
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:2211
std::string uten_type_str() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor in 'string' form.
Definition UniTensor.hpp:2191
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:1873
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:2841
void permute_(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1)
permute the lags of the UniTensor, inplacely.
Definition UniTensor.hpp:2568
UniTensor & tag()
Set the UniTensor as a tagged UniTensor.
Definition UniTensor.hpp:3898
const Bond & bond_(const cytnx_uint64 &idx) const
Definition UniTensor.hpp:2252
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force=false)
Definition UniTensor.hpp:3243
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:2478
const T & at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:2699
UniTensor & relabels_(const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:2354
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:1822
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:2920
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:1845
static UniTensor zeros(const std::vector< cytnx_uint64 > &shape, const std::vector< std::string > &in_labels={}, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a UniTensor with all elements set to zero.
Definition UniTensor.hpp:4119
UniTensor get(const std::vector< Accessor > &accessors) const
Definition UniTensor.hpp:3150
T & at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:2721
UniTensor Conj() const
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:3725
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:2025
UniTensor set_rowrank(const cytnx_uint64 &new_rowrank) const
Definition UniTensor.hpp:2100
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:3683
cytnx_uint64 rowrank() const
Return the row rank of the UniTensor.
Definition UniTensor.hpp:2142
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:2393
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:3576
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:2079
UniTensor & Sub_(const Scalar &rhs)
The subtraction function for a given scalar.
Definition UniTensor.hpp:3428
UniTensor & relabel_(const cytnx_int64 &inx, const std::string &new_label)
rebable the lags in the UniTensor by given index.
Definition UniTensor.hpp:2465
UniTensor & operator/=(const Scalar &rhs)
The division assignment operator for a given scalar.
Definition UniTensor.hpp:3698
const bool & is_braket_form() const
Check whether the UniTensor is in braket form.
Definition UniTensor.hpp:2226
void set_elem(const std::vector< cytnx_uint64 > &locator, const T2 &rc)
Definition UniTensor.hpp:3949
UniTensor Add(const Scalar &rhs) const
The addition function for a given scalar.
static UniTensor linspace(const cytnx_double &start, const cytnx_double &end, const cytnx_uint64 &Nelem, const bool &endpoint=true, const std::vector< std::string > &in_labels={}, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a one-bond UniTensor with all elements are evenly spaced numbers over a specified interval.
Definition UniTensor.hpp:4269
std::vector< cytnx_uint64 > shape() const
Get the shape of the UniTensor.
Definition UniTensor.hpp:2265
UniTensor to_dense()
Convert the UniTensor to non-diagonal form.
Definition UniTensor.hpp:3202
Scalar::Sproxy at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:2780
static UniTensor normal(const std::vector< cytnx_uint64 > &shape, const double &mean, const double &std, const std::vector< std::string > &in_labels={}, const unsigned int &seed=cytnx::random::__static_random_device(), const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a UniTensor with all elements are random numbers sampled from a normal (Gaussian) distributi...
const Tensor & get_block_(const std::vector< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:2996
void reshape_(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor, inplacely.
Definition UniTensor.hpp:3187
UniTensor & set_labels(const std::vector< std::string > &new_labels)
Set new labels for all the bonds.
Definition UniTensor.hpp:2070
void permute_(const std::vector< std::string > &mapper, const cytnx_int64 &rowrank=-1)
permute the lags of the UniTensor, inplacely.
Definition UniTensor.hpp:2578
std::string name() const
Return the name of the UniTensor.
Definition UniTensor.hpp:2170
const Scalar::Sproxy at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:2802
UniTensor & Add_(const Scalar &rhs)
The addition function for a given scalar.
Definition UniTensor.hpp:3398
UniTensor & Trace_(const std::string &a, const std::string &b)
Take the partial trance to the UniTensor, inplacely.
Definition UniTensor.hpp:3832
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:4011
Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition UniTensor.hpp:2765
UniTensor Trace(const std::string &a, const std::string &b) const
Take the partial trance to the UniTensor.
Definition UniTensor.hpp:3802
bool same_data(const UniTensor &rhs) const
Check whether the Blocks address are the same.
Definition UniTensor.hpp:3297
UniTensor astype(const unsigned int &dtype) const
Return a new UniTensor that cast to different data type.
Definition UniTensor.hpp:2509
static UniTensor ones(const std::vector< cytnx_uint64 > &shape, const std::vector< std::string > &in_labels={}, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a UniTensor with all elements set to one.
Definition UniTensor.hpp:4200
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:4025
UniTensor Transpose() const
Take the transpose of the UniTensor.
Definition UniTensor.hpp:3753
static UniTensor arange(const cytnx_double &start, const cytnx_double &end, const cytnx_double &step=1, const std::vector< std::string > &in_labels={}, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a UniTensor with all elements are arange from start to end.
Definition UniTensor.hpp:4242
UniTensor & set_label(const char *old_label, const std::string &new_label)
Definition UniTensor.hpp:2033
static UniTensor Load(const char *fname)
load a UniTensor from file
UniTensor & Dagger_()
Take the conjugate transpose to the UniTensor, inplacely.
Definition UniTensor.hpp:3885
void print_diagram(const bool &bond_info=false)
Plot the diagram of the UniTensor.
Definition UniTensor.hpp:2615
std::vector< Bond > & bonds()
Definition UniTensor.hpp:2250
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition UniTensor.hpp:2652
UniTensor & set_rowrank_(const cytnx_uint64 &new_rowrank)
Set the row rank of the UniTensor.
Definition UniTensor.hpp:2095
void put_block(Tensor &in, const std::vector< std::string > &lbls, const std::vector< cytnx_int64 > &qidx, const bool &force=false)
Put the block into the UniTensor with given quantum indices, will copy the input tensor.
Definition UniTensor.hpp:3073
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:2002
UniTensor contiguous() const
Make the UniTensor contiguous by coalescing the memory (storage).
Definition UniTensor.hpp:2599
Tensor get_block(const cytnx_uint64 &idx=0) const
Get the block of the UniTensor for a given index.
Definition UniTensor.hpp:2830
const T & at(const std::vector< cytnx_uint64 > &locator) const
Get an element at specific location.
Definition UniTensor.hpp:2678
UniTensor & operator*=(const Scalar &rhs)
The multiplication assignment operator for a given scalar.
Definition UniTensor.hpp:3713
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:2371
void contiguous_()
Make the UniTensor contiguous by coalescing the memory (storage), inplacely.
Definition UniTensor.hpp:2609
UniTensor normalize() const
normalize the current UniTensor instance with 2-norm.
Definition UniTensor.hpp:3776
static UniTensor ones(const cytnx_uint64 &Nelem, const std::vector< std::string > &in_labels={}, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a one-bond UniTensor with all elements set to one.
Definition UniTensor.hpp:4137
std::vector< Symmetry > syms() const
Return the symmetry type of the UniTensor.
Definition UniTensor.hpp:2218
UniTensor & Mul_(const UniTensor &rhs)
The multiplcation function of the UniTensor.
Definition UniTensor.hpp:3341
static UniTensor zeros(const cytnx_uint64 &Nelem, const std::vector< std::string > &in_labels={}, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a one-bond UniTensor with all elements set to zero.
Definition UniTensor.hpp:4099
void put_block_(Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index, inplacely.
Definition UniTensor.hpp:3105
void combineBonds(const std::vector< std::string > &indicators, const bool &force=false)
Combine the sevral bonds of the UniTensor.
Definition UniTensor.hpp:3234
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:2497
UniTensor & normalize_()
normalize the UniTensor, inplacely.
Definition UniTensor.hpp:3788
bool is_diag() const
To tell whether the UniTensor is in diagonal form.
Definition UniTensor.hpp:2204
int device() const
Return the device of the UniTensor.
Definition UniTensor.hpp:2164
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:3013
Tensor get_block_(const std::vector< std::string > &labels, 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:2940
void put_block_(Tensor &in, const std::vector< std::string > &lbls, const std::vector< cytnx_int64 > &qidx, const bool &force=false)
Put the block into the UniTensor with given quantum indices, inplacely.
Definition UniTensor.hpp:3121
void set(const std::vector< Accessor > &accessors, const Tensor &rhs)
Definition UniTensor.hpp:3155
std::string dtype_str() const
Return the data type of the UniTensor in 'string' form.
Definition UniTensor.hpp:2177
UniTensor & operator+=(const Scalar &rhs)
The addition assignment operator for a given scalar.
Definition UniTensor.hpp:3668
UniTensor & Div_(const UniTensor &rhs)
The division function of the UniTensor.
Definition UniTensor.hpp:3383
UniTensor & Div_(const Scalar &rhs)
The division function for a given scalar.
Definition UniTensor.hpp:3443
Bond & bond_(const std::string &label)
Definition UniTensor.hpp:2256
cytnx_uint64 rank() const
Return the rank of the UniTensor.
Definition UniTensor.hpp:2136
Bond bond(const std::string &label) const
Definition UniTensor.hpp:2259
void group_basis_()
Group the same quantum number basis together.
Definition UniTensor.hpp:2638
void to_(const int &device)
move the current UniTensor to the assigned device (inplace).
Definition UniTensor.hpp:2280
UniTensor & Trace_(const cytnx_int64 &a=0, const cytnx_int64 &b=1)
Take the partial trance to the UniTensor, inplacely.
Definition UniTensor.hpp:3854
UniTensor & set_name(const std::string &in)
Set the name of the UniTensor.
Definition UniTensor.hpp:1987
UniTensor Trace(const cytnx_int64 &a=0, const cytnx_int64 &b=1) const
Take the partial trance to the UniTensor.
Definition UniTensor.hpp:3817
UniTensor & Add_(const UniTensor &rhs)
The addition function of the UniTensor.
Definition UniTensor.hpp:3320
void normal_(const double &mean, const double &std, const unsigned int &seed=cytnx::random::__static_random_device())
Generate a one-bond UniTensor with all elements are random numbers sampled from a normal (Gaussian) d...
UniTensor permute(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1) const
permute the lags of the UniTensor
Definition UniTensor.hpp:2527
UniTensor & set_label(const std::string &old_label, const char *new_label)
Definition UniTensor.hpp:2041
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:2540
unsigned int dtype() const
Return the data type of the UniTensor.
Definition UniTensor.hpp:2149
UniTensor Pow(const double &p) const
Power function.
UniTensor & Mul_(const Scalar &rhs)
The multiplication function for a given scalar.
Definition UniTensor.hpp:3413
UniTensor & operator-=(const UniTensor &rhs)
The subtraction assignment operator of the UniTensor.
Definition UniTensor.hpp:3613
Tensor get_block_(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:2985
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force, const bool &by_label)
Definition UniTensor.hpp:3219
UniTensor & set_label(const char *old_label, const char *new_label)
Definition UniTensor.hpp:2049
static UniTensor arange(const cytnx_int64 &Nelem, const std::vector< std::string > &in_labels={}, const std::string &name="")
Generate a one-bond UniTensor with all elements are arange from 0 to Nelem-1.
Definition UniTensor.hpp:4220
bool is_blockform() const
Check whether the UniTensor is in block form.
Definition UniTensor.hpp:2272
UniTensor group_basis() const
Definition UniTensor.hpp:2640
UniTensor Dagger() const
Take the conjugate transpose to the UniTensor.
Definition UniTensor.hpp:3873
static UniTensor uniform(const std::vector< cytnx_uint64 > &shape, const double &low, const double &high, const std::vector< std::string > &in_labels={}, const unsigned int &seed=cytnx::random::__static_random_device(), const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a UniTensor with all elements are random numbers sampled from a uniform distribution.
void set(const std::vector< Accessor > &accessors, const UniTensor &rhs)
Definition UniTensor.hpp:3158
const std::vector< Tensor > & get_blocks_(const bool &silent=false) const
Get all the blocks of the UniTensor, inplacely.
Definition UniTensor.hpp:3037
UniTensor & relabels_(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:2422
const Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:3004
bool elem_exists(const std::vector< cytnx_uint64 > &locator) const
Geiven the locator, check if the element exists.
Definition UniTensor.hpp:3929
UniTensor & Sub_(const UniTensor &rhs)
The subtraction function of the UniTensor.
Definition UniTensor.hpp:3362
UniTensor relabels(const std::initializer_list< char * > &new_labels) const
Definition UniTensor.hpp:2341
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:3265
void put_block(const Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index.
Definition UniTensor.hpp:3054
const Tensor & get_block_(const cytnx_uint64 &idx=0) const
Get the shared view of block for the given index.
Definition UniTensor.hpp:2902
static UniTensor Load(const std::string &fname)
load a UniTensor from file
const Bond & bond_(const std::string &label) const
Definition UniTensor.hpp:2255
static UniTensor identity(const cytnx_uint64 &dim, const std::vector< std::string > &in_labels={}, const cytnx_bool &is_diag=false, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a identity UniTensor.
Definition UniTensor.hpp:4155
Bond & bond_(const cytnx_uint64 &idx)
Definition UniTensor.hpp:2253
static UniTensor normal(const cytnx_uint64 &Nelem, const double &mean, const double &std, const std::vector< std::string > &in_labels={}, const unsigned int &seed=cytnx::random::__static_random_device(), const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a one-bond UniTensor with all elements are random numbers sampled from a normal (Gaussian) d...
UniTensor relabel(const cytnx_int64 &inx, const std::string &new_label) const
rebable the lags in the UniTensor by given index.
Definition UniTensor.hpp:2452
UniTensor Mul(const UniTensor &rhs) const
The multiplication function of the UniTensor.
void uniform_(const double &low=0, const double &high=1, const unsigned int &seed=cytnx::random::__static_random_device())
Generate a UniTensor with all elements are random numbers sampled from a uniform distribution,...
UniTensor relabels(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels) const
Definition UniTensor.hpp:2403
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:4053
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:2232
cytnx_int64 get_index(std::string label) const
Get the index of an desired label string.
Definition UniTensor.hpp:2239
const std::vector< Bond > & bonds() const
Get the bonds of the UniTensor.
Definition UniTensor.hpp:2245
Tensor get_block(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:2891
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:4040
UniTensor & Transpose_()
Take the transpose of the UniTensor, inplacely.
Definition UniTensor.hpp:3765
static UniTensor uniform(const cytnx_uint64 &Nelem, const double &low, const double &high, const std::vector< std::string > &in_labels={}, const unsigned int &seed=cytnx::random::__static_random_device(), const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a one-bond UniTensor with all elements are random numbers sampled from a uniform distributio...
UniTensor clone() const
Clone (deep copy) the UniTensor.
Definition UniTensor.hpp:2301
vec2d< cytnx_uint64 > & get_itoi()
Definition UniTensor.hpp:4074
void print_blocks(const bool &full_info=true) const
Print all of the blocks in the UniTensor.
Definition UniTensor.hpp:2621
Scalar::Sproxy item() const
Definition UniTensor.hpp:2117
const vec2d< cytnx_uint64 > & get_itoi() const
get the q-indices on each leg for all the blocks
Definition UniTensor.hpp:4073
std::string device_str() const
Return the device of the UniTensor in 'string' form.
Definition UniTensor.hpp:2184
UniTensor & convert_from(const UniTensor &rhs, const bool &force=false)
Definition UniTensor.hpp:4081
UniTensor relabels(const std::vector< std::string > &new_labels) const
relables all of the labels in UniTensor.
Definition UniTensor.hpp:2332
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:3113
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:1924
UniTensor & Conj_()
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:3738
cytnx_uint64 Nblocks() const
Return the number of blocks in the UniTensor.
Definition UniTensor.hpp:2130
Tensor get_block(const std::vector< cytnx_uint64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:2886
void Save(const char *fname) const
save a UniTensor to file
Bond bond(const cytnx_uint64 &idx) const
Definition UniTensor.hpp:2258
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:3998
Tensor get_block(const std::initializer_list< cytnx_int64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:2876
UniTensor & relabels_(const std::vector< std::string > &new_labels)
Set new labels for all the bonds.
Definition UniTensor.hpp:2316
const Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator) const
Get an element at specific location.
Definition UniTensor.hpp:2746
int uten_type() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor.
Definition UniTensor.hpp:2157
Tensor & get_block_(const cytnx_uint64 &idx=0)
Definition UniTensor.hpp:2910
#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.
std::random_device __static_random_device
Definition UniTensor.hpp:29
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
Tensor linspace(const cytnx_double &start, const cytnx_double &end, const cytnx_uint64 &Nelem, const bool &endpoint=true, const unsigned int &dtype=Type.Double, const int &device=Device.cpu)
UniTensorType_class UTenType
UniTensor type.
uint32_t cytnx_uint32
Definition Type.hpp:56
bool cytnx_bool
Definition Type.hpp:64
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
Tensor arange(const cytnx_int64 &Nelem)
create an rank-1 Tensor with incremental unsigned integer elements start with [0,Nelem)
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
Tensor ones(const cytnx_uint64 &Nelem, const unsigned int &dtype=Type.Double, const int &device=Device.cpu)
create an rank-1 Tensor with all the elements are initialized with one.
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.
Tensor zeros(const cytnx_uint64 &Nelem, const unsigned int &dtype=Type.Double, const int &device=Device.cpu)
create an rank-1 Tensor with all the elements are initialized with zero.
Type_class Type
data type
Tensor identity(const cytnx_uint64 &Dim, const unsigned int &dtype=Type.Double, const int &device=Device.cpu)
create an square rank-2 Tensor with all diagonal to be one.
tmp
Definition sp.py:8