Cytnx v1.0.0
Loading...
Searching...
No Matches
UniTensor.hpp
Go to the documentation of this file.
1#ifndef CYTNX_UNITENSOR_H_
2#define CYTNX_UNITENSOR_H_
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 relabel_(const std::vector<std::string> &new_labels); // implemented
203 void relabels_(const std::vector<std::string> &new_labels); // implemented
204 void relabel_(const std::vector<std::string> &old_labels,
205 const std::vector<std::string> &new_labels); // implemented
206 void relabels_(const std::vector<std::string> &old_labels,
207 const std::vector<std::string> &new_labels); // implemented
208 void relabel_(const std::string &old_label, const std::string &new_label) {
209 this->set_label(old_label, new_label);
210 }
211 void relabel_(const cytnx_int64 &inx, const std::string &new_label) {
212 this->set_label(inx, new_label);
213 }
214
215 int uten_type() { return this->uten_type_id; }
216 std::string uten_type_str() { return UTenType.getname(this->uten_type_id); }
217
219
220 // string labels!
221 virtual void Init(const std::vector<Bond> &bonds,
222 const std::vector<std::string> &in_labels = {},
223 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
224 const int &device = Device.cpu, const bool &is_diag = false,
225 const bool &no_alloc = false, const std::string &name = "");
226
227 virtual void Init_by_Tensor(const Tensor &in, const bool &is_diag = false,
228 const cytnx_int64 &rowrank = -1, const std::string &name = "");
229 virtual std::vector<cytnx_uint64> shape() const;
230 virtual bool is_blockform() const;
231 virtual bool is_contiguous() const;
232 virtual void to_(const int &device);
233 virtual boost::intrusive_ptr<UniTensor_base> to(const int &device);
234 virtual boost::intrusive_ptr<UniTensor_base> clone() const;
235 virtual unsigned int dtype() const;
236 virtual int device() const;
237 virtual std::string dtype_str() const;
238 virtual std::string device_str() const;
239 virtual void set_rowrank_(const cytnx_uint64 &new_rowrank);
240 virtual boost::intrusive_ptr<UniTensor_base> set_rowrank(const cytnx_uint64 &new_rowrank) const;
241
242 virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
243 const cytnx_int64 &rowrank = -1);
244 virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
245 const cytnx_int64 &rowrank = -1);
246 // virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
247 // const cytnx_int64 &rowrank = -1);
248
249 virtual void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
250 virtual void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
251
252 // virtual void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank =
253 // -1);
254 virtual boost::intrusive_ptr<UniTensor_base> contiguous_();
255 virtual boost::intrusive_ptr<UniTensor_base> contiguous();
256 virtual void print_diagram(const bool &bond_info = false);
257 virtual void print_blocks(const bool &full_info = true) const;
258 virtual void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
259
260 virtual boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const;
261
262 virtual cytnx_uint64 Nblocks() const { return 0; };
263 virtual Tensor get_block(const cytnx_uint64 &idx = 0) const; // return a copy of block
264 virtual Tensor get_block(const std::vector<cytnx_int64> &qnum,
265 const bool &force) const; // return a copy of block
266
267 virtual const Tensor &get_block_(const cytnx_uint64 &idx = 0)
268 const; // return a share view of block, this only work for non-symm tensor.
269 virtual const Tensor &get_block_(const std::vector<cytnx_int64> &qnum,
270 const bool &force) const; // return a copy of block
271 virtual Tensor &get_block_(const cytnx_uint64 &idx = 0); // return a share view of block, this
272 // only work for non-symm tensor.
273 virtual Tensor &get_block_(const std::vector<cytnx_int64> &qnum,
274 const bool &force); // return a copy of block
275 virtual bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const;
276
277 virtual std::vector<Tensor> get_blocks() const;
278 virtual const std::vector<Tensor> &get_blocks_(const bool &) const;
279 virtual std::vector<Tensor> &get_blocks_(const bool &);
280
281 virtual void put_block(const Tensor &in, const cytnx_uint64 &idx = 0);
282 virtual void put_block_(Tensor &in, const cytnx_uint64 &idx = 0);
283 virtual void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum,
284 const bool &force);
285 virtual void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force);
286
287 // this will only work on non-symm tensor (DenseUniTensor)
288 virtual boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors);
289
290 // this will only work on non-symm tensor (DenseUniTensor)
291 virtual void set(const std::vector<Accessor> &accessors, const Tensor &rhs);
292
293 virtual void reshape_(const std::vector<cytnx_int64> &new_shape,
294 const cytnx_uint64 &rowrank = 0);
295 virtual boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
296 const cytnx_uint64 &rowrank = 0);
297 virtual boost::intrusive_ptr<UniTensor_base> to_dense();
298 virtual void to_dense_();
299 virtual void combineBond(const std::vector<std::string> &indicators, const bool &force = false);
300 virtual void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
301 const bool &by_label);
302 virtual void combineBonds(const std::vector<std::string> &indicators,
303 const bool &force = false);
304 virtual void combineBonds(const std::vector<cytnx_int64> &indicators,
305 const bool &force = false);
306 virtual boost::intrusive_ptr<UniTensor_base> contract(
307 const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &mv_elem_self = false,
308 const bool &mv_elem_rhs = false);
309 virtual std::vector<Bond> getTotalQnums(const bool &physical = false);
310 virtual std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const;
311 virtual void Trace_(const std::string &a, const std::string &b);
312 virtual void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
313
314 virtual boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b);
315 virtual boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b);
316
317 virtual boost::intrusive_ptr<UniTensor_base> relabel(
318 const std::vector<std::string> &new_labels);
319 virtual boost::intrusive_ptr<UniTensor_base> relabels(
320 const std::vector<std::string> &new_labels);
321
322 virtual boost::intrusive_ptr<UniTensor_base> relabel(
323 const std::vector<std::string> &old_labels, const std::vector<std::string> &new_labels);
324 virtual boost::intrusive_ptr<UniTensor_base> relabels(
325 const std::vector<std::string> &old_labels, const std::vector<std::string> &new_labels);
326
327 virtual boost::intrusive_ptr<UniTensor_base> relabel(const std::string &old_label,
328 const std::string &new_label);
329
330 virtual boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
331 const std::string &new_label);
332
333 virtual std::vector<Symmetry> syms() const;
334
335 // arithmetic
336 virtual void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
337 virtual void Add_(const Scalar &rhs);
338
339 virtual void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
340 virtual void Mul_(const Scalar &rhs);
341
342 virtual void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
343 virtual void Sub_(const Scalar &rhs);
344 virtual void lSub_(const Scalar &lhs);
345
346 virtual void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
347 virtual void Div_(const Scalar &rhs);
348 virtual void lDiv_(const Scalar &lhs);
349
350 virtual Tensor Norm() const;
351 virtual boost::intrusive_ptr<UniTensor_base> normalize();
352 virtual void normalize_();
353
354 virtual boost::intrusive_ptr<UniTensor_base> Conj();
355 virtual void Conj_();
356
357 virtual boost::intrusive_ptr<UniTensor_base> Transpose();
358 virtual void Transpose_();
359
360 virtual boost::intrusive_ptr<UniTensor_base> Dagger();
361 virtual void Dagger_();
362
363 virtual void tag();
364
365 virtual void truncate_(const std::string &bond_idx, const cytnx_uint64 &dim);
366 virtual void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim);
367
368 virtual bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
369
370 // this a workaround, as virtual function cannot template.
371 virtual Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator);
372 virtual const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const;
373
374 virtual cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
375 const cytnx_complex128 &aux);
376 virtual cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
377 const cytnx_complex64 &aux);
378 virtual cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
379 const cytnx_double &aux);
380 virtual cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
381 const cytnx_float &aux);
382 virtual cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
383 const cytnx_uint64 &aux);
384 virtual cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
385 const cytnx_int64 &aux);
386 virtual cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
387 const cytnx_uint32 &aux);
388 virtual cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
389 const cytnx_int32 &aux);
390 virtual cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
391 const cytnx_uint16 &aux);
392 virtual cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
393 const cytnx_int16 &aux);
394
395 virtual const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
396 const cytnx_complex128 &aux) const;
397 virtual const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
398 const cytnx_complex64 &aux) const;
399 virtual const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
400 const cytnx_double &aux) const;
401 virtual const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
402 const cytnx_float &aux) const;
403 virtual const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
404 const cytnx_uint64 &aux) const;
405 virtual const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
406 const cytnx_int64 &aux) const;
407 virtual const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
408 const cytnx_uint32 &aux) const;
409 virtual const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
410 const cytnx_int32 &aux) const;
411 virtual const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
412 const cytnx_uint16 &aux) const;
413 virtual const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
414 const cytnx_int16 &aux) const;
415
416 virtual void from_(const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &force);
417
418 virtual void group_basis_();
419 virtual const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const;
420 virtual std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx);
421 virtual const vec2d<cytnx_uint64> &get_itoi() const;
422 virtual vec2d<cytnx_uint64> &get_itoi();
423
424 virtual void _save_dispatch(std::fstream &f) const;
425 virtual void _load_dispatch(std::fstream &f);
426
427 virtual ~UniTensor_base(){};
428 };
430
431 //======================================================================
433 class DenseUniTensor : public UniTensor_base {
434 protected:
435 public:
436 Tensor _block;
437 std::vector<Tensor> _interface_block; // this is serves as interface for get_blocks_();
438 DenseUniTensor *clone_meta() const {
439 DenseUniTensor *tmp = new DenseUniTensor();
440 tmp->_bonds = vec_clone(this->_bonds);
441 tmp->_labels = this->_labels;
442 tmp->_is_braket_form = this->_is_braket_form;
443 tmp->_rowrank = this->_rowrank;
444 tmp->_is_diag = this->_is_diag;
445 tmp->_name = this->_name;
446 tmp->_is_tag = this->_is_tag;
447 return tmp;
448 }
449 //------------------------------------------
450
451 DenseUniTensor() { this->uten_type_id = UTenType.Dense; };
452 friend class UniTensor; // allow wrapper to access the private elems
453 // virtual functions
454
455 // void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels = {},
456 // const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
457 // const int &device = Device.cpu, const bool &is_diag = false,
458 // const bool &no_alloc = false);
459
460 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
461 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
462 const int &device = Device.cpu, const bool &is_diag = false,
463 const bool &no_alloc = false, const std::string &name = "");
464 // this only work for non-symm tensor
465 void Init_by_Tensor(const Tensor &in_tensor, const bool &is_diag = false,
466 const cytnx_int64 &rowrank = -1, const std::string &name = "");
467 std::vector<cytnx_uint64> shape() const {
468 if (this->_is_diag) {
469 std::vector<cytnx_uint64> shape = this->_block.shape();
470 shape.push_back(shape[0]);
471 return shape;
472 } else {
473 return this->_block.shape();
474 }
475 }
476 bool is_blockform() const { return false; }
477 void to_(const int &device) { this->_block.to_(device); }
478 boost::intrusive_ptr<UniTensor_base> to(const int &device) {
479 if (this->device() == device) {
480 std::vector<Tensor> _interface_block; // this is serves as interface for get_blocks_();
481 return this;
482 } else {
483 boost::intrusive_ptr<UniTensor_base> out = this->clone();
484 out->to_(device);
485 return out;
486 }
487 }
488 void set_rowrank_(const cytnx_uint64 &new_rowrank) {
489 cytnx_error_msg(new_rowrank > this->_labels.size(),
490 "[ERROR] rowrank cannot exceed the rank of UniTensor.%s", "\n");
491 if (this->is_diag()) {
492 cytnx_error_msg(new_rowrank != 1, "[ERROR] rowrank should be [==1] when is_diag =true!.%s",
493 "\n");
494 }
495
496 this->_rowrank = new_rowrank;
497 }
498
499 boost::intrusive_ptr<UniTensor_base> set_rowrank(const cytnx_uint64 &new_rowrank) const {
500 DenseUniTensor *out_raw = this->clone_meta();
501 out_raw->_block = this->_block;
502 out_raw->set_rowrank_(new_rowrank);
503 boost::intrusive_ptr<UniTensor_base> out(out_raw);
504 return out;
505 }
506
507 boost::intrusive_ptr<UniTensor_base> clone() const {
508 DenseUniTensor *tmp = this->clone_meta();
509 tmp->_block = this->_block.clone();
510 boost::intrusive_ptr<UniTensor_base> out(tmp);
511 return out;
512 };
513 bool is_contiguous() const { return this->_block.is_contiguous(); }
514 unsigned int dtype() const { return this->_block.dtype(); }
515 int device() const { return this->_block.device(); }
516 std::string dtype_str() const { return Type.getname(this->_block.dtype()); }
517 std::string device_str() const { return Device.getname(this->_block.device()); }
527 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
528 const cytnx_int64 &rowrank = -1);
529 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
530 const cytnx_int64 &rowrank = -1);
531
540 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
541 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
542
543 boost::intrusive_ptr<UniTensor_base> relabel(const std::vector<std::string> &new_labels);
544 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &new_labels);
545
546 boost::intrusive_ptr<UniTensor_base> relabel(const std::vector<std::string> &old_labels,
547 const std::vector<std::string> &new_labels);
548 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &old_labels,
549 const std::vector<std::string> &new_labels);
550
561 boost::intrusive_ptr<UniTensor_base> relabel(const std::string &old_label,
562 const std::string &new_label);
563 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
564 const std::string &new_label);
565
566 boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const {
567 DenseUniTensor *tmp = this->clone_meta();
568 tmp->_block = this->_block.astype(dtype);
569 boost::intrusive_ptr<UniTensor_base> out(tmp);
570 return tmp;
571 }
572
573 std::vector<Symmetry> syms() const {
574 cytnx_error_msg(true, "[ERROR][DenseUniTensor] dense unitensor does not have symmetry.%s",
575 "\n");
576 return std::vector<Symmetry>();
577 }
578
579 boost::intrusive_ptr<UniTensor_base> contiguous_() {
580 this->_block.contiguous_();
581 return boost::intrusive_ptr<UniTensor_base>(this);
582 }
583 boost::intrusive_ptr<UniTensor_base> contiguous() {
584 // if contiguous then return self!
585 if (this->is_contiguous()) {
586 boost::intrusive_ptr<UniTensor_base> out(this);
587 return out;
588 } else {
589 DenseUniTensor *tmp = this->clone_meta();
590 tmp->_block = this->_block.contiguous();
591 boost::intrusive_ptr<UniTensor_base> out(tmp);
592 return out;
593 }
594 }
595 void print_diagram(const bool &bond_info = false);
596 void print_blocks(const bool &full_info = true) const;
597 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
598 Tensor get_block(const cytnx_uint64 &idx = 0) const { return this->_block.clone(); }
599
600 Tensor get_block(const std::vector<cytnx_int64> &qnum, const bool &force) const {
602 true, "[ERROR][DenseUniTensor] try to get_block() using qnum on a non-symmetry UniTensor%s",
603 "\n");
604 return Tensor();
605 }
606 // return a share view of block, this only work for non-symm tensor.
607 const Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force) const {
609 true,
610 "[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
611 "\n");
612 return this->_block;
613 }
614 Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force) {
616 true,
617 "[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
618 "\n");
619 return this->_block;
620 }
621
622 // return a share view of block, this only work for non-symm tensor.
623 Tensor &get_block_(const cytnx_uint64 &idx = 0) { return this->_block; }
624 // return a share view of block, this only work for non-symm tensor.
625 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const { return this->_block; }
626
627 cytnx_uint64 Nblocks() const { return 1; };
628 std::vector<Tensor> get_blocks() const {
629 std::vector<Tensor> out;
631 true, "[ERROR][DenseUniTensor] cannot use get_blocks(), use get_block() instead!%s", "\n");
632 return out; // this will not share memory!!
633 }
634 const std::vector<Tensor> &get_blocks_(const bool &silent = false) const {
636 true, "[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s",
637 "\n");
638 return this->_interface_block; // this will not share memory!!
639 }
640 std::vector<Tensor> &get_blocks_(const bool &silent = false) {
642 true, "[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s",
643 "\n");
644 return this->_interface_block; // this will not share memory!!
645 }
646
647 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
648 // We don't check the dtype for DenseUniTensor, since it'll be more convinent to change
649 // DenseUniTensor's dtype
650
651 // cytnx_error_msg(in.dtype() != this->dtype(),
652 // "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not
653 // match.%s",
654 // "\n");
655 cytnx_error_msg(in.device() != this->device(),
656 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
657 "match.%s",
658 "\n");
659 // We shouldn't check the contiguous
660 // cytnx_error_msg(!in.contiguous());
661 if (this->is_diag()) {
663 in.shape() != this->_block.shape(),
664 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
665 this->_block = in.clone();
666 } else {
668 in.shape() != this->shape(),
669 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
670 this->_block = in.clone();
671 }
672 }
673 // share view of the block
674 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) {
675 // We don't check the dtype for DenseUniTensor, since it'll be more convinent to change
676 // DenseUniTensor's dtype
677
678 // cytnx_error_msg(in.dtype() != this->dtype(),
679 // "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not
680 // match.%s",
681 // "\n");
682 cytnx_error_msg(in.device() != this->device(),
683 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
684 "match.%s",
685 "\n");
686 // We shouldn't check the contiguous
687 // cytnx_error_msg(!in.contiguous());
688 if (this->is_diag()) {
690 in.shape() != this->_block.shape(),
691 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
692 this->_block = in;
693 } else {
695 in.shape() != this->shape(),
696 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
697 this->_block = in;
698 }
699 }
700
701 void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force) {
703 true, "[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
704 "\n");
705 }
706 void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force) {
708 true, "[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
709 "\n");
710 }
711 // this will only work on non-symm tensor (DenseUniTensor)
712 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors) {
713 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
714 out->Init_by_Tensor(this->_block.get(accessors), false, 0); // wrapping around.
715 return out;
716 }
717 // this will only work on non-symm tensor (DenseUniTensor)
718 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
719 this->_block.set(accessors, rhs);
720 }
721
722 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0);
723 boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
724 const cytnx_uint64 &rowrank = 0);
725 boost::intrusive_ptr<UniTensor_base> to_dense();
726 void to_dense_();
727 void combineBond(const std::vector<std::string> &indicators, const bool &force = true);
728 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
729 const bool &by_label);
730 void combineBonds(const std::vector<std::string> &indicators, const bool &force = true);
731 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = true);
732 boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs,
733 const bool &mv_elem_self = false,
734 const bool &mv_elem_rhs = false);
735 std::vector<Bond> getTotalQnums(const bool &physical = false) {
736 cytnx_error_msg(true, "[ERROR][DenseUniTensor] %s",
737 "getTotalQnums can only operate on UniTensor with symmetry.\n");
738 return std::vector<Bond>();
739 }
740
741 std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const {
742 cytnx_error_msg(true, "[ERROR][DenseUniTensor] %s",
743 "get_blocks_qnums can only operate on UniTensor with symmetry.\n");
744 return std::vector<std::vector<cytnx_int64>>();
745 }
746
747 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const {
748 if (rhs->uten_type() != UTenType.Dense) return false;
749
750 return this->get_block_().same_data(rhs->get_block_());
751 }
752
753 ~DenseUniTensor(){};
754
755 // arithmetic
756 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
757 void Add_(const Scalar &rhs);
758
759 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
760 void Mul_(const Scalar &rhs);
761
762 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
763 void Sub_(const Scalar &rhs);
764 void lSub_(const Scalar &lhs);
765
766 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
767 void Div_(const Scalar &rhs);
768 void lDiv_(const Scalar &lhs);
769
770 void Conj_() { this->_block.Conj_(); };
771
772 boost::intrusive_ptr<UniTensor_base> Conj() {
773 boost::intrusive_ptr<UniTensor_base> out = this->clone();
774 out->Conj_();
775 return out;
776 }
777
778 boost::intrusive_ptr<UniTensor_base> Transpose() {
779 boost::intrusive_ptr<UniTensor_base> out = this->clone();
780 out->Transpose_();
781 return out;
782 }
783 void Transpose_();
784
785 boost::intrusive_ptr<UniTensor_base> normalize() {
786 boost::intrusive_ptr<UniTensor_base> out = this->clone();
787 out->normalize_();
788 return out;
789 }
790 void normalize_();
791
792 boost::intrusive_ptr<UniTensor_base> Dagger() {
793 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
794 out->Transpose_();
795 return out;
796 }
797 void Dagger_() {
798 this->Conj_();
799 this->Transpose_();
800 }
810 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
811 void Trace_(const std::string &a, const std::string &b);
812 boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b) {
813 boost::intrusive_ptr<UniTensor_base> out = this->clone();
814 out->Trace_(a, b);
815 return out;
816 }
817 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b) {
818 boost::intrusive_ptr<UniTensor_base> out = this->clone();
819 out->Trace_(a, b);
820 return out;
821 }
822
823 Tensor Norm() const;
824
825 const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const {
827 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
828 "\n");
829 return Scalar::Sproxy();
830 }
831 const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
832 const cytnx_complex128 &aux) const {
834 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
835 "\n");
836 return cytnx_complex128(0, 0);
837 }
838 const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
839 const cytnx_complex64 &aux) const {
841 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
842 "\n");
843 return cytnx_complex64(0, 0);
844 }
845 const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
846 const cytnx_double &aux) const {
848 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
849 "\n");
850 return 0;
851 }
852 const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
853 const cytnx_float &aux) const {
855 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
856 "\n");
857 return 0;
858 }
859 const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
860 const cytnx_uint64 &aux) const {
862 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
863 "\n");
864 return 0;
865 }
866 const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
867 const cytnx_int64 &aux) const {
869 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
870 "\n");
871 return 0;
872 }
873 const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
874 const cytnx_uint32 &aux) const {
876 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
877 "\n");
878 return 0;
879 }
880 const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
881 const cytnx_int32 &aux) const {
883 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
884 "\n");
885 return 0;
886 }
887 const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
888 const cytnx_uint16 &aux) const {
890 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
891 "\n");
892 return 0;
893 }
894 const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
895 const cytnx_int16 &aux) const {
897 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
898 "\n");
899 return 0;
900 }
901
902 Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) {
904 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
905 "\n");
906 return Scalar::Sproxy();
907 }
908 cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
909 const cytnx_complex128 &aux) {
911 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
912 "\n");
913 return *(cytnx_complex128 *)nullptr;
914 }
915 cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
916 const cytnx_complex64 &aux) {
918 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
919 "\n");
920 return *(cytnx_complex64 *)nullptr;
921 }
922 cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux) {
924 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
925 "\n");
926 return *(cytnx_double *)nullptr;
927 }
928 cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux) {
930 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
931 "\n");
932 return *(cytnx_float *)nullptr;
933 }
934 cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux) {
936 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
937 "\n");
938 return *(cytnx_uint64 *)nullptr;
939 }
940 cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux) {
942 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
943 "\n");
944 return *(cytnx_int64 *)nullptr;
945 }
946 cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux) {
948 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
949 "\n");
950 return *(cytnx_uint32 *)nullptr;
951 }
952 cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux) {
954 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
955 "\n");
956 return *(cytnx_int32 *)nullptr;
957 }
958 cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux) {
960 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
961 "\n");
962 return *(cytnx_uint16 *)nullptr;
963 }
964 cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux) {
966 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
967 "\n");
968 return *(cytnx_int16 *)nullptr;
969 }
970
971 bool elem_exists(const std::vector<cytnx_uint64> &locator) const {
973 true, "[ERROR][DenseUniTensor] elem_exists can only be used on UniTensor with Symmetry.%s",
974 "\n");
975 }
976 void tag() {
977 if (!this->is_tag()) {
978 for (int i = 0; i < this->_rowrank; i++) {
979 this->_bonds[i].set_type(BD_KET);
980 }
981 for (int i = this->_rowrank; i < this->_bonds.size(); i++) {
982 this->_bonds[i].set_type(BD_BRA);
983 }
984 this->_is_tag = true;
985 this->_is_braket_form = this->_update_braket();
986 }
987 }
997 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim);
998 void truncate_(const std::string &bond_idx, const cytnx_uint64 &dim);
999
1000 void from_(const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &force);
1001
1002 void group_basis_() {
1003 cytnx_warning_msg(true, "[WARNING] group basis will not have any effect on DensUniTensor.%s",
1004 "\n");
1005 }
1006
1007 void _save_dispatch(std::fstream &f) const;
1008 void _load_dispatch(std::fstream &f);
1009
1010 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
1011 cytnx_error_msg(true, "[ERROR] get_qindices can only be unsed on UniTensor with Symmetry.%s",
1012 "\n");
1013 }
1014 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
1015 cytnx_error_msg(true, "[ERROR] get_qindices can only be unsed on UniTensor with Symmetry.%s",
1016 "\n");
1017 }
1018
1019 const vec2d<cytnx_uint64> &get_itoi() const {
1020 cytnx_error_msg(true, "[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s",
1021 "\n");
1022 }
1023 vec2d<cytnx_uint64> &get_itoi() {
1024 cytnx_error_msg(true, "[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s",
1025 "\n");
1026 }
1027
1028 // end virtual function
1029 };
1031
1032 //======================================================================
1034 class BlockUniTensor : public UniTensor_base {
1035 protected:
1036 public:
1037 std::vector<std::vector<cytnx_uint64>> _inner_to_outer_idx;
1038 std::vector<Tensor> _blocks;
1039 Tensor NullRefTensor; // this returns when access block is not exists!
1040
1041 // given an index list [loc], get qnums from this->_bonds[loc] and return the combined qnums
1042 // calculated from Symm object! this assume 1. symmetry are the same for each bond!
1043 // 2. total_qns are feeded with size len(symmetry)
1044 void _fx_get_total_fluxs(std::vector<cytnx_uint64> &loc, const std::vector<Symmetry> &syms,
1045 std::vector<cytnx_int64> &total_qns) {
1046 memset(&total_qns[0], 0, sizeof(cytnx_int64) * total_qns.size());
1047
1048 for (cytnx_int32 i = 0; i < syms.size(); i++) {
1049 if (this->_bonds[0].type() == BD_BRA)
1050 total_qns[i] = syms[0].reverse_rule(this->_bonds[0]._impl->_qnums[loc[0]][i]);
1051 else
1052 total_qns[i] = this->_bonds[0]._impl->_qnums[loc[0]][i];
1053
1054 for (auto j = 1; j < loc.size(); j++) {
1055 if (this->_bonds[j].type() == BD_BRA)
1056 total_qns[i] = syms[i].combine_rule(
1057 total_qns[i], syms[i].reverse_rule(this->_bonds[j]._impl->_qnums[loc[j]][i]));
1058 else {
1059 total_qns[i] =
1060 syms[i].combine_rule(total_qns[i], this->_bonds[j]._impl->_qnums[loc[j]][i]);
1061 }
1062 }
1063 }
1064 }
1065
1066 void _fx_locate_elem(cytnx_int64 &bidx, std::vector<cytnx_uint64> &loc_in_T,
1067 const std::vector<cytnx_uint64> &locator) const;
1068
1069 // internal function, grouping all duplicate qnums in all bonds
1070 void _fx_group_duplicates(const std::vector<cytnx_uint64> &dup_bond_idxs,
1071 const std::vector<std::vector<cytnx_uint64>> &idx_mappers);
1072
1073 void set_meta(BlockUniTensor *tmp, const bool &inner, const bool &outer) const {
1074 // outer meta
1075 if (outer) {
1076 tmp->_bonds = vec_clone(this->_bonds);
1077 tmp->_labels = this->_labels;
1078 tmp->_is_braket_form = this->_is_braket_form;
1079 tmp->_rowrank = this->_rowrank;
1080 tmp->_name = this->_name;
1081 }
1082
1083 tmp->_is_diag = this->_is_diag;
1084
1085 // inner meta
1086 if (inner) {
1087 tmp->_inner_to_outer_idx = this->_inner_to_outer_idx;
1088 }
1089 }
1090
1091 BlockUniTensor *clone_meta(const bool &inner, const bool &outer) const {
1092 BlockUniTensor *tmp = new BlockUniTensor();
1093 this->set_meta(tmp, inner, outer);
1094 return tmp;
1095 };
1096
1097 friend class UniTensor;
1098 BlockUniTensor() {
1099 this->uten_type_id = UTenType.Block;
1100 this->_is_tag = true;
1101 }
1102
1103 // virtual functions:
1104 // void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels = {},
1105 // const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1106 // const int &device = Device.cpu, const bool &is_diag = false,
1107 // const bool &no_alloc = false);
1108
1109 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1110 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1111 const int &device = Device.cpu, const bool &is_diag = false,
1112 const bool &no_alloc = false, const std::string &name = "");
1113
1114 void Init_by_Tensor(const Tensor &in_tensor, const bool &is_diag = false,
1115 const cytnx_int64 &rowrank = -1, const std::string &name = "") {
1117 true, "[ERROR][BlockUniTensor] cannot use Init_by_tensor() on a BlockUniTensor.%s", "\n");
1118 }
1119
1120 std::vector<cytnx_uint64> shape() const {
1121 std::vector<cytnx_uint64> out(this->_bonds.size());
1122 for (cytnx_uint64 i = 0; i < out.size(); i++) {
1123 out[i] = this->_bonds[i].dim();
1124 }
1125 return out;
1126 }
1127
1128 bool is_blockform() const { return true; }
1129 bool is_contiguous() const {
1130 bool out = true;
1131 for (int i = 0; i < this->_blocks.size(); i++) {
1132 out &= this->_blocks[i].is_contiguous();
1133 }
1134 return out;
1135 };
1136
1137 cytnx_uint64 Nblocks() const { return this->_blocks.size(); };
1138
1139 void to_(const int &device) {
1140 for (cytnx_uint64 i = 0; i < this->_blocks.size(); i++) {
1141 this->_blocks[i].to_(device);
1142 }
1143 };
1144
1145 boost::intrusive_ptr<UniTensor_base> to(const int &device) {
1146 if (this->device() == device) {
1147 return this;
1148 } else {
1149 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1150 out->to_(device);
1151 return out;
1152 }
1153 };
1154
1155 boost::intrusive_ptr<UniTensor_base> clone() const {
1156 BlockUniTensor *tmp = this->clone_meta(true, true);
1157 tmp->_blocks = vec_clone(this->_blocks);
1158 boost::intrusive_ptr<UniTensor_base> out(tmp);
1159 return out;
1160 };
1161
1162 unsigned int dtype() const {
1163 //[21 Aug 2024] This is a copy from BlockUniTensor;
1164 #ifdef UNI_DEBUG
1165 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1166 "\n");
1167 #endif
1168 return this->_blocks.size() < 1 ? Type.Void : this->_blocks[0].dtype();
1169 };
1170 int device() const {
1171 //[21 Aug 2024] This is a copy from BlockUniTensor;
1172 #ifdef UNI_DEBUG
1173 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1174 "\n");
1175 #endif
1176 return this->_blocks.size() < 1 ? -404 : this->_blocks[0].device();
1177 };
1178 std::string dtype_str() const {
1179 //[21 Aug 2024] This is a copy from BlockUniTensor;
1180 #ifdef UNI_DEBUG
1181 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1182 "\n");
1183 #endif
1184 return this->_blocks.size() < 1 ? "Void, no valid blocks" : this->_blocks[0].dtype_str();
1185 };
1186 std::string device_str() const {
1187 //[21 Aug 2024] This is a copy from BlockUniTensor;
1188 #ifdef UNI_DEBUG
1189 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1190 "\n");
1191 #endif
1192 return this->_blocks.size() < 1 ? "None, no valid blocks" : this->_blocks[0].device_str();
1193 };
1194
1195 Tensor get_block(const cytnx_uint64 &idx = 0) const {
1196 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1197 "\n");
1198 return this->_blocks[idx].clone();
1199 };
1200
1201 // this one for Block will return the indicies!!
1202 Tensor get_block(const std::vector<cytnx_int64> &indices, const bool &force_return) const {
1203 cytnx_error_msg(indices.size() != this->rank(),
1204 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1205 "Tensor rank (number of legs).%s",
1206 "\n");
1207
1208 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1209
1210 // find if the indices specify exists!
1211 cytnx_int64 b = -1;
1212 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1213 if (inds == this->_inner_to_outer_idx[i]) {
1214 b = i;
1215 break;
1216 }
1217 }
1218
1219 if (b < 0) {
1220 if (force_return) {
1221 return NullRefTensor;
1222 } else {
1223 cytnx_error_msg(true,
1224 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1225 "force_return=false, so "
1226 "error throws. \n If you want to return an empty block without "
1227 "error when block is "
1228 "not avaliable, set force_return=True.%s",
1229 "\n");
1230 }
1231 } else {
1232 return this->_blocks[b].clone();
1233 }
1234 }
1235
1236 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const {
1237 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1238 "\n");
1239 return this->_blocks[idx];
1240 };
1241
1242 Tensor &get_block_(const cytnx_uint64 &idx = 0) {
1243 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1244 "\n");
1245 return this->_blocks[idx];
1246 };
1247
1248 const Tensor &get_block_(const std::vector<cytnx_int64> &indices,
1249 const bool &force_return) const {
1250 cytnx_error_msg(indices.size() != this->rank(),
1251 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1252 "Tensor rank (number of legs).%s",
1253 "\n");
1254
1255 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1256
1257 // find if the indices specify exists!
1258 cytnx_int64 b = -1;
1259 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1260 if (inds == this->_inner_to_outer_idx[i]) {
1261 b = i;
1262 break;
1263 }
1264 }
1265
1266 if (b < 0) {
1267 if (force_return) {
1268 return this->NullRefTensor;
1269 } else {
1270 cytnx_error_msg(true,
1271 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1272 "force_return=false, so "
1273 "error throws. \n If you want to return an empty block without "
1274 "error when block is "
1275 "not avaliable, set force_return=True.%s",
1276 "\n");
1277 }
1278 } else {
1279 return this->_blocks[b];
1280 }
1281 }
1282
1283 Tensor &get_block_(const std::vector<cytnx_int64> &indices, const bool &force_return) {
1284 cytnx_error_msg(indices.size() != this->rank(),
1285 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1286 "Tensor rank (number of legs).%s",
1287 "\n");
1288
1289 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1290
1291 // find if the indices specify exists!
1292 cytnx_int64 b = -1;
1293 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1294 if (inds == this->_inner_to_outer_idx[i]) {
1295 b = i;
1296 break;
1297 }
1298 }
1299
1300 if (b < 0) {
1301 if (force_return) {
1302 return this->NullRefTensor;
1303 } else {
1304 cytnx_error_msg(true,
1305 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1306 "force_return=false, so "
1307 "error throws. \n If you want to return an empty block without "
1308 "error when block is "
1309 "not avaliable, set force_return=True.%s",
1310 "\n");
1311 }
1312 } else {
1313 return this->_blocks[b];
1314 }
1315 }
1316
1317 std::vector<Tensor> get_blocks() const { return vec_clone(this->_blocks); }
1318 const std::vector<Tensor> &get_blocks_(const bool &) const { return this->_blocks; }
1319 std::vector<Tensor> &get_blocks_(const bool &) { return this->_blocks; }
1320
1321 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const {
1322 if (rhs->uten_type() != UTenType.Block) return false;
1323 if (rhs->get_blocks_(1).size() != this->get_blocks_(1).size()) return false;
1324
1325 for (int i = 0; i < rhs->get_blocks_(1).size(); i++)
1326 if (this->get_blocks_(1)[i].same_data(rhs->get_blocks_(1)[i]) == false) return false;
1327
1328 return true;
1329 }
1330
1331 void set_rowrank_(const cytnx_uint64 &new_rowrank) {
1332 cytnx_error_msg(new_rowrank > this->rank(),
1333 "[ERROR][BlockUniTensor] rowrank should be [>=0] and [<=UniTensor.rank].%s",
1334 "\n");
1335 if (this->is_diag()) {
1336 cytnx_error_msg(new_rowrank != 1,
1337 "[ERROR][BlockUniTensor] rowrank should be [==1] when is_diag =true!.%s",
1338 "\n");
1339 }
1340 this->_rowrank = new_rowrank;
1341 this->_is_braket_form = this->_update_braket();
1342 }
1343
1344 boost::intrusive_ptr<UniTensor_base> set_rowrank(const cytnx_uint64 &new_rowrank) const {
1345 BlockUniTensor *tmp = this->clone_meta(true, true);
1346 tmp->_blocks = this->_blocks;
1347 tmp->set_rowrank_(new_rowrank);
1348 boost::intrusive_ptr<UniTensor_base> out(tmp);
1349 return out;
1350 }
1351
1352 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
1353 const cytnx_int64 &rowrank = -1);
1354 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
1355 const cytnx_int64 &rowrank = -1);
1356
1357 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
1358 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
1359
1360 boost::intrusive_ptr<UniTensor_base> contiguous_() {
1361 for (unsigned int b = 0; b < this->_blocks.size(); b++) this->_blocks[b].contiguous_();
1362 return boost::intrusive_ptr<UniTensor_base>(this);
1363 }
1364
1365 boost::intrusive_ptr<UniTensor_base> contiguous();
1366
1367 void print_diagram(const bool &bond_info = false);
1368 void print_blocks(const bool &full_info = true) const;
1369 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
1370
1371 boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs,
1372 const bool &mv_elem_self = false,
1373 const bool &mv_elem_rhs = false);
1374
1375 boost::intrusive_ptr<UniTensor_base> relabel(const std::vector<std::string> &new_labels);
1376 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &new_labels);
1377
1378 boost::intrusive_ptr<UniTensor_base> relabel(const std::vector<std::string> &old_labels,
1379 const std::vector<std::string> &new_labels);
1380 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &old_labels,
1381 const std::vector<std::string> &new_labels);
1382
1383 boost::intrusive_ptr<UniTensor_base> relabel(const std::string &old_label,
1384 const std::string &new_label);
1385 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
1386 const std::string &new_label);
1387
1388 std::vector<Symmetry> syms() const;
1389
1390 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
1391 cytnx_error_msg(true, "[ERROR] cannot reshape a UniTensor with symmetry.%s", "\n");
1392 }
1393 boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
1394 const cytnx_uint64 &rowrank = 0) {
1395 cytnx_error_msg(true, "[ERROR] cannot reshape a UniTensor with symmetry.%s", "\n");
1396 return nullptr;
1397 }
1398
1399 boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const {
1400 BlockUniTensor *tmp = this->clone_meta(true, true);
1401 tmp->_blocks.resize(this->_blocks.size());
1402 for (cytnx_int64 blk = 0; blk < this->_blocks.size(); blk++) {
1403 tmp->_blocks[blk] = this->_blocks[blk].astype(dtype);
1404 }
1405 boost::intrusive_ptr<UniTensor_base> out(tmp);
1406 return out;
1407 };
1408
1409 // this will only work on non-symm tensor (DenseUniTensor)
1410 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors) {
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 return nullptr;
1417 }
1418
1419 // this will only work on non-symm tensor (DenseUniTensor)
1420 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
1422 true,
1423 "[ERROR][BlockUniTensor][get] cannot use get on a UniTensor with "
1424 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
1425 "\n");
1426 }
1427
1428 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
1429 cytnx_error_msg(in.dtype() != this->dtype(),
1430 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
1431 "\n");
1432 cytnx_error_msg(in.device() != this->device(),
1433 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
1434 "match.%s",
1435 "\n");
1436 // We shouldn't check the contiguous
1437 // cytnx_error_msg(!in.contiguous());
1438 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1439 "\n");
1440 cytnx_error_msg(in.shape() != this->_blocks[idx].shape(),
1441 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1442 "of block @ idx=%d\n",
1443 idx);
1444
1445 this->_blocks[idx] = in.clone();
1446 }
1447 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) {
1448 cytnx_error_msg(in.dtype() != this->dtype(),
1449 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
1450 "\n");
1451 cytnx_error_msg(in.device() != this->device(),
1452 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
1453 "match.%s",
1454 "\n");
1455 // We shouldn't check the contiguous
1456 // cytnx_error_msg(!in.contiguous());
1457 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1458 "\n");
1459 cytnx_error_msg(in.shape() != this->_blocks[idx].shape(),
1460 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1461 "of block @ idx=%d\n",
1462 idx);
1463
1464 this->_blocks[idx] = in;
1465 }
1466 void put_block(const Tensor &in, const std::vector<cytnx_int64> &indices, const bool &check) {
1467 cytnx_error_msg(in.dtype() != this->dtype(),
1468 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
1469 "\n");
1470 cytnx_error_msg(in.device() != this->device(),
1471 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
1472 "match.%s",
1473 "\n");
1474 // We shouldn't check the contiguous
1475 // cytnx_error_msg(!in.contiguous());
1476 cytnx_error_msg(indices.size() != this->rank(),
1477 "[ERROR][put_block][BlockUniTensor] len(indices) must be the same as the "
1478 "Tensor rank (number of legs).%s",
1479 "\n");
1480
1481 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1482
1483 // find if the indices specify exists!
1484 cytnx_int64 b = -1;
1485 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1486 if (inds == this->_inner_to_outer_idx[i]) {
1487 b = i;
1488 break;
1489 }
1490 }
1491
1492 if (b < 0) {
1493 if (check) {
1494 cytnx_error_msg(true,
1495 "[ERROR][put_block][BlockUniTensor] no avaliable block exists, "
1496 "check=true, so error throws. \n If you want without error when block "
1497 "is not avaliable, set check=false.%s",
1498 "\n");
1499 }
1500 } else {
1502 in.shape() != this->_blocks[b].shape(),
1503 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1504 "of block @ idx=%d\n",
1505 b);
1506
1507 this->_blocks[b] = in.clone();
1508 }
1509 }
1510 void put_block_(Tensor &in, const std::vector<cytnx_int64> &indices, const bool &check) {
1511 cytnx_error_msg(in.dtype() != this->dtype(),
1512 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
1513 "\n");
1514 cytnx_error_msg(in.device() != this->device(),
1515 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
1516 "match.%s",
1517 "\n");
1518 // We shouldn't check the contiguous
1519 // cytnx_error_msg(!in.contiguous());
1520 cytnx_error_msg(indices.size() != this->rank(),
1521 "[ERROR][put_block][BlockUniTensor] len(indices) must be the same as the "
1522 "Tensor rank (number of legs).%s",
1523 "\n");
1524
1525 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1526
1527 // find if the indices specify exists!
1528 cytnx_int64 b = -1;
1529 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1530 if (inds == this->_inner_to_outer_idx[i]) {
1531 b = i;
1532 break;
1533 }
1534 }
1535
1536 if (b < 0) {
1537 if (check) {
1538 cytnx_error_msg(true,
1539 "[ERROR][put_block][BlockUniTensor] no avaliable block exists, "
1540 "check=true, so error throws. \n If you want without error when block "
1541 "is not avaliable, set check=false.%s",
1542 "\n");
1543 }
1544 } else {
1546 in.shape() != this->_blocks[b].shape(),
1547 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1548 "of block @ idx=%d\n",
1549 b);
1550 this->_blocks[b] = in;
1551 }
1552 }
1553
1554 void tag() {
1555 // no-use!
1556 }
1557
1558 boost::intrusive_ptr<UniTensor_base> Conj() {
1559 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1560 out->Conj_();
1561 return out;
1562 }
1563
1564 void Conj_() {
1565 for (int i = 0; i < this->_blocks.size(); i++) {
1566 this->_blocks[i].Conj_();
1567 }
1568 };
1569
1570 void Transpose_();
1571 boost::intrusive_ptr<UniTensor_base> Transpose() {
1572 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1573 out->Transpose_();
1574 return out;
1575 }
1576
1577 void normalize_();
1578 boost::intrusive_ptr<UniTensor_base> normalize() {
1579 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1580 out->normalize_();
1581 return out;
1582 }
1583
1584 boost::intrusive_ptr<UniTensor_base> Dagger() {
1585 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
1586 out->Transpose_();
1587 return out;
1588 }
1589 void Dagger_() {
1590 this->Conj_();
1591 this->Transpose_();
1592 }
1593
1594 void Trace_(const std::string &a, const std::string &b);
1595 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
1596
1597 boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &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 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b) {
1608 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1609 out->Trace_(a, b);
1610 if (out->rank() == 0) {
1611 DenseUniTensor *tmp = new DenseUniTensor();
1612 tmp->_block = ((BlockUniTensor *)out.get())->_blocks[0];
1613 out = boost::intrusive_ptr<UniTensor_base>(tmp);
1614 }
1615 return out;
1616 }
1617
1618 Tensor Norm() const;
1619
1620 bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
1621
1622 const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const;
1623 const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1624 const cytnx_complex128 &aux) const;
1625 const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1626 const cytnx_complex64 &aux) const;
1627 const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1628 const cytnx_double &aux) const;
1629 const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1630 const cytnx_float &aux) const;
1631 const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1632 const cytnx_uint64 &aux) const;
1633 const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1634 const cytnx_int64 &aux) const;
1635 const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1636 const cytnx_uint32 &aux) const;
1637 const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1638 const cytnx_int32 &aux) const;
1639 const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1640 const cytnx_uint16 &aux) const;
1641 const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1642 const cytnx_int16 &aux) const;
1643
1644 Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator);
1645 cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1646 const cytnx_complex128 &aux);
1647 cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1648 const cytnx_complex64 &aux);
1649 cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux);
1650 cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux);
1651 cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux);
1652 cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux);
1653 cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux);
1654 cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux);
1655 cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux);
1656 cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux);
1657
1658 void _save_dispatch(std::fstream &f) const;
1659 void _load_dispatch(std::fstream &f);
1660
1661 // this will remove the [q_index]-th qnum at [bond_idx]-th Bond!
1662 void truncate_(const std::string &bond_idx, const cytnx_uint64 &q_index);
1663 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &q_index);
1664
1665 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1666 void Add_(const Scalar &rhs) {
1668 true,
1669 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s "
1670 "\n",
1671 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1672 "operation on the block(s).");
1673 }
1674
1675 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1676 void Mul_(const Scalar &rhs);
1677
1678 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1679 void Sub_(const Scalar &rhs) {
1681 true,
1682 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s "
1683 "\n",
1684 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1685 "operation on the block(s).");
1686 }
1687 void lSub_(const Scalar &lhs) {
1689 true,
1690 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s "
1691 "\n",
1692 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1693 "operation on the block(s).");
1694 }
1695
1696 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs) {
1698 true,
1699 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s "
1700 "\n",
1701 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1702 "operation on the block(s).");
1703 }
1704 void Div_(const Scalar &rhs);
1705 void lDiv_(const Scalar &lhs) {
1707 true,
1708 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s "
1709 "\n",
1710 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1711 "operation on the block(s).");
1712 }
1713 void from_(const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &force);
1714
1715 void group_basis_();
1716
1717 void combineBond(const std::vector<std::string> &indicators, const bool &force = false);
1718 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = false);
1719 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
1720 const bool &by_label);
1721 void combineBonds(const std::vector<std::string> &indicators, const bool &force = false);
1722
1723 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
1725 bidx >= this->Nblocks(),
1726 "[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
1727 this->Nblocks());
1728 return this->_inner_to_outer_idx[bidx];
1729 }
1730 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
1732 bidx >= this->Nblocks(),
1733 "[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
1734 this->Nblocks());
1735 return this->_inner_to_outer_idx[bidx];
1736 }
1737
1738 const vec2d<cytnx_uint64> &get_itoi() const { return this->_inner_to_outer_idx; }
1739 vec2d<cytnx_uint64> &get_itoi() { return this->_inner_to_outer_idx; }
1740 };
1742 //======================================================================
1743
1745 class UniTensor_options {
1746 public:
1747 bool _is_diag;
1748 int _dtype;
1749 int _device;
1750 int _rowrank;
1751
1752 UniTensor_options() {
1753 this->_is_diag = false;
1754 this->_dtype = Type.Double;
1755 this->_device = Device.cpu;
1756 this->_rowrank = -1;
1757 }
1758
1759 UniTensor_options(const UniTensor_options &rhs) {
1760 this->_is_diag = rhs._is_diag;
1761 this->_dtype = rhs._dtype;
1762 this->_device = rhs._device;
1763 this->_rowrank = rhs._rowrank;
1764 }
1765
1766 UniTensor_options &operator=(const UniTensor_options &rhs) {
1767 this->_is_diag = rhs._is_diag;
1768 this->_dtype = rhs._dtype;
1769 this->_device = rhs._device;
1770 this->_rowrank = rhs._rowrank;
1771 return *this;
1772 }
1773
1774 UniTensor_options &is_diag(const bool &in) {
1775 this->_is_diag = in;
1776 return *this;
1777 }
1778 UniTensor_options &dtype(const int &in) {
1779 this->_dtype = in;
1780 return *this;
1781 }
1782 UniTensor_options &device(const int &in) {
1783 this->_device = in;
1784 return *this;
1785 }
1786 UniTensor_options &rowrank(const int &in) {
1787 this->_rowrank = in;
1788 return *this;
1789 }
1790 };
1792
1795 public:
1797 boost::intrusive_ptr<UniTensor_base> _impl;
1798 UniTensor() : _impl(new UniTensor_base()){};
1799 UniTensor(const UniTensor &rhs) { this->_impl = rhs._impl; }
1800 UniTensor &operator=(const UniTensor &rhs) {
1801 this->_impl = rhs._impl;
1802 return *this;
1803 }
1805
1807
1833 explicit UniTensor(const Tensor &in_tensor, const bool &is_diag = false,
1834 const cytnx_int64 &rowrank = -1,
1835 const std::vector<std::string> &in_labels = {}, const std::string &name = "")
1836 : _impl(new UniTensor_base()) {
1837 this->Init(in_tensor, is_diag, rowrank, in_labels, name);
1838 }
1856 void Init(const Tensor &in_tensor, const bool &is_diag = false, const cytnx_int64 &rowrank = -1,
1857 const std::vector<std::string> &in_labels = {}, const std::string &name = "") {
1858 // std::cout << "[entry!]" << std::endl;
1859 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
1860 out->Init_by_Tensor(in_tensor, is_diag, rowrank, name);
1861 this->_impl = out;
1862 if (in_labels.size() != 0) this->set_labels(in_labels);
1863 }
1865
1867
1884 UniTensor(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1885 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1886 const int &device = Device.cpu, const bool &is_diag = false,
1887 const std::string &name = "")
1888 : _impl(new UniTensor_base()) {
1889 #ifdef UNI_DEBUG
1891 true,
1892 "[DEBUG] message: entry for UniTensor(const std::vector<Bond> &bonds, const "
1893 "std::vector<std::string> &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned "
1894 "int "
1895 "&dtype=Type.Double, const int &device = Device.cpu, const bool &is_diag=false)%s",
1896 "\n");
1897 #endif
1898 this->Init(bonds, in_labels, rowrank, dtype, device, is_diag, name);
1899 }
1900
1902 /* [developing]
1903 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1904 const UniTensor_options &UToptions = UniTensor_options(), const std::string &name =
1905 ""){ this->Init(bonds,in_labels, UToptions._rowrank, UToptions._dtype , UToptions._device ,
1906 UToptions._is_diag,
1907 name);
1908 }
1909 */
1911
1935 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1936 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1937 const int &device = Device.cpu, const bool &is_diag = false,
1938 const std::string &name = "") {
1939 // checking type:
1940 bool is_sym = false;
1941 int sym_fver = -1;
1942
1943 for (cytnx_uint64 i = 0; i < bonds.size(); i++) {
1944 // check
1945 if (bonds[i].syms().size() != 0) {
1946 is_sym = true;
1947 if (sym_fver == -1)
1948 sym_fver = bonds[i]._impl->_degs.size();
1949 else {
1950 // std::cout << sym_fver << " " <<
1951 // bonds[i]._impl->_degs.size() << std::endl;
1952 cytnx_error_msg((bool(sym_fver) ^ bool(bonds[i]._impl->_degs.size())),
1953 "[ERROR] All the Bond when init a UniTensor with symmetric must be in "
1954 "the same format!%s",
1955 "\n");
1956 }
1957 } else
1959 is_sym, "[ERROR] cannot have bonds with mixing of symmetry and non-symmetry.%s", "\n");
1960 }
1961
1962 // dynamical dispatch:
1963 if (is_sym) {
1964 #ifdef UNI_DEBUG
1965 cytnx_warning_msg(true, "[DEBUG] message: entry dispatch: UniTensor: symmetric%s", "\n");
1966 #endif
1967 // cytnx_warning_msg(true,"[warning, still developing, some functions will display
1968 // \"[Developing]\"][SparseUniTensor]%s","\n");
1969 if (sym_fver == 0) {
1970 // boost::intrusive_ptr<UniTensor_base> out(new SparseUniTensor());
1971 // this->_impl = out;
1972 cytnx_error_msg(true,
1973 "[ERROR] internal error! [legacy Sparse entry] the Bond is symmetry but "
1974 "the version is not properly determined!%s",
1975 "\n")
1976 } else if (sym_fver == -1) {
1977 cytnx_error_msg(true,
1978 "[ERROR] internal error! the Bond is symmetry but the version is not "
1979 "properly determined!%s",
1980 "\n");
1981 } else {
1982 boost::intrusive_ptr<UniTensor_base> out(new BlockUniTensor());
1983 this->_impl = out;
1984 }
1985 } else {
1986 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
1987 this->_impl = out;
1988 }
1989 this->_impl->Init(bonds, in_labels, rowrank, dtype, device, is_diag, false, name);
1990 }
1991
1998 UniTensor &set_name(const std::string &in) {
1999 this->_impl->set_name(in);
2000 return *this;
2001 }
2002
2013 UniTensor &set_label(const cytnx_int64 &idx, const std::string &new_label) {
2014 this->_impl->set_label(idx, new_label);
2015 return *this;
2016 }
2017
2022 this->_impl->set_label(idx, std::string(new_label));
2023 return *this;
2024 }
2025
2036 UniTensor &set_label(const std::string &old_label, const std::string &new_label) {
2037 this->_impl->set_label(old_label, new_label);
2038 return *this;
2039 }
2040
2044 UniTensor &set_label(const char *old_label, const std::string &new_label) {
2045 this->_impl->set_label(std::string(old_label), new_label);
2046 return *this;
2047 }
2048
2052 UniTensor &set_label(const std::string &old_label, const char *new_label) {
2053 this->_impl->set_label(old_label, std::string(new_label));
2054 return *this;
2055 }
2056
2060 UniTensor &set_label(const char *old_label, const char *new_label) {
2061 this->_impl->set_label(std::string(old_label), std::string(new_label));
2062 return *this;
2063 }
2064
2065 /*
2066 UniTensor& change_label(const cytnx_int64 &old_label, const cytnx_int64 &new_label){
2067 this->_impl->change_label(old_label,new_label);
2068 return *this;
2069 }
2070 */
2071
2081 UniTensor &set_labels(const std::vector<std::string> &new_labels) {
2082 this->_impl->set_labels(new_labels);
2083 return *this;
2084 }
2085
2090 UniTensor &set_labels(const std::initializer_list<char *> &new_labels) {
2091 std::vector<char *> new_lbls(new_labels);
2092 std::vector<std::string> vs(new_lbls.size());
2093 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2094 [](char *x) -> std::string { return std::string(x); });
2095
2096 this->_impl->set_labels(vs);
2097 return *this;
2098 }
2099
2107 this->_impl->set_rowrank_(new_rowrank);
2108 return *this;
2109 }
2110
2112 UniTensor out;
2113 out._impl = this->_impl->set_rowrank(new_rowrank);
2114 return out;
2115 }
2116
2117 template <class T>
2118 T &item() {
2120 "[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use "
2121 "get_block()/get_blocks() first.%s",
2122 "\n");
2123
2124 DenseUniTensor *tmp = static_cast<DenseUniTensor *>(this->_impl.get());
2125 return tmp->_block.item<T>();
2126 }
2127
2128 Scalar::Sproxy item() const {
2130 "[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use "
2131 "get_block()/get_blocks() first.%s",
2132 "\n");
2133
2134 DenseUniTensor *tmp = static_cast<DenseUniTensor *>(this->_impl.get());
2135 return tmp->_block.item();
2136 }
2141 cytnx_uint64 Nblocks() const { return this->_impl->Nblocks(); }
2142
2147 cytnx_uint64 rank() const { return this->_impl->rank(); }
2148
2153 cytnx_uint64 rowrank() const { return this->_impl->rowrank(); }
2154
2160 unsigned int dtype() const { return this->_impl->dtype(); }
2161
2168 int uten_type() const { return this->_impl->uten_type(); }
2169
2175 int device() const { return this->_impl->device(); }
2176
2181 std::string name() const { return this->_impl->name(); }
2182
2188 std::string dtype_str() const { return this->_impl->dtype_str(); }
2189
2195 std::string device_str() const { return this->_impl->device_str(); }
2196
2202 std::string uten_type_str() const { return this->_impl->uten_type_str(); }
2203
2209 bool is_contiguous() const { return this->_impl->is_contiguous(); }
2210
2215 bool is_diag() const { return this->_impl->is_diag(); }
2216
2222 bool is_tag() const { return this->_impl->is_tag(); }
2223
2229 std::vector<Symmetry> syms() const { return this->_impl->syms(); }
2230
2237 const bool &is_braket_form() const { return this->_impl->is_braket_form(); }
2238
2243 const std::vector<std::string> &labels() const { return this->_impl->labels(); }
2250 cytnx_int64 get_index(std::string label) const { return this->_impl->get_index(label); }
2251
2256 const std::vector<Bond> &bonds() const { return this->_impl->bonds(); }
2257
2261 std::vector<Bond> &bonds() { return this->_impl->bonds(); }
2262
2263 const Bond &bond_(const cytnx_uint64 &idx) const { return this->_impl->bond_(idx); }
2264 Bond &bond_(const cytnx_uint64 &idx) { return this->_impl->bond_(idx); }
2265
2266 const Bond &bond_(const std::string &label) const { return this->_impl->bond_(label); }
2267 Bond &bond_(const std::string &label) { return this->_impl->bond_(label); }
2268
2269 Bond bond(const cytnx_uint64 &idx) const { return this->_impl->bond_(idx).clone(); }
2270 Bond bond(const std::string &label) const { return this->_impl->bond_(label).clone(); }
2271
2276 std::vector<cytnx_uint64> shape() const { return this->_impl->shape(); }
2277
2283 bool is_blockform() const { return this->_impl->is_blockform(); }
2284
2291 void to_(const int &device) { this->_impl->to_(device); }
2292
2302 UniTensor to(const int &device) const {
2303 UniTensor out;
2304 out._impl = this->_impl->to(device);
2305 return out;
2306 }
2307
2313 UniTensor out;
2314 out._impl = this->_impl->clone();
2315 return out;
2316 }
2317
2327 UniTensor &relabel_(const std::vector<std::string> &new_labels) {
2328 this->_impl->relabel_(new_labels);
2329 return *this;
2330 }
2337 [[deprecated(
2338 "Please use "
2339 "UniTensor &relabel_(const std::vector<std::string> &old_labels, const "
2340 "std::vector<std::string> &new_labels) "
2341 "instead.")]] UniTensor &
2342 relabels_(const std::vector<std::string> &new_labels) {
2343 this->_impl->relabels_(new_labels);
2344 return *this;
2345 }
2346
2358 UniTensor relabel(const std::vector<std::string> &new_labels) const {
2359 UniTensor out;
2360 out._impl = this->_impl->relabel(new_labels);
2361 return out;
2362 }
2368 [[deprecated(
2369 "Please use "
2370 "UniTensor relabel(const std::vector<std::string> &new_labels) const "
2371 "instead.")]] UniTensor
2372 relabels(const std::vector<std::string> &new_labels) const {
2373 UniTensor out;
2374 out._impl = this->_impl->relabels(new_labels);
2375 return out;
2376 }
2377
2382 UniTensor relabel(const std::initializer_list<char *> &new_labels) const {
2383 std::vector<char *> new_lbls(new_labels);
2384 std::vector<std::string> vs(new_lbls.size());
2385 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2386 [](char *x) -> std::string { return std::string(x); });
2387
2388 UniTensor out;
2389 out._impl = this->_impl->relabel(vs);
2390 return out;
2391 }
2397 [[deprecated(
2398 "Please use "
2399 "UniTensor relabel(const std::initializer_list<char *> &new_labels) const "
2400 "instead.")]] UniTensor
2401 relabels(const std::initializer_list<char *> &new_labels) const {
2402 std::vector<char *> new_lbls(new_labels);
2403 std::vector<std::string> vs(new_lbls.size());
2404 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2405 [](char *x) -> std::string { return std::string(x); });
2406
2407 UniTensor out;
2408 out._impl = this->_impl->relabels(vs);
2409 return out;
2410 }
2414 UniTensor &relabel_(const std::initializer_list<char *> &new_labels) {
2415 std::vector<char *> new_lbls(new_labels);
2416 std::vector<std::string> vs(new_lbls.size());
2417 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2418 [](char *x) -> std::string { return std::string(x); });
2419
2420 this->_impl->relabel_(vs);
2421 return *this;
2422 }
2428 [[deprecated(
2429 "Please use "
2430 "UniTensor &relabel_(const std::initializer_list<char *> &new_labels) "
2431 "instead.")]] UniTensor &
2432 relabels_(const std::initializer_list<char *> &new_labels) {
2433 std::vector<char *> new_lbls(new_labels);
2434 std::vector<std::string> vs(new_lbls.size());
2435 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2436 [](char *x) -> std::string { return std::string(x); });
2437
2438 this->_impl->relabels_(vs);
2439 return *this;
2440 }
2441
2449 UniTensor relabel(const std::vector<std::string> &old_labels,
2450 const std::vector<std::string> &new_labels) const {
2451 UniTensor out;
2452 out._impl = this->_impl->relabel(old_labels, new_labels);
2453 return out;
2454 }
2460 [[deprecated(
2461 "Please use "
2462 "UniTensor relabel(const std::vector<std::string> &old_labels, const "
2463 "std::vector<std::string> &new_labels) const "
2464 "instead.")]] UniTensor
2465 relabels(const std::vector<std::string> &old_labels,
2466 const std::vector<std::string> &new_labels) const {
2467 UniTensor out;
2468 out._impl = this->_impl->relabels(old_labels, new_labels);
2469 return out;
2470 }
2471
2487 UniTensor &relabel_(const std::vector<std::string> &old_labels,
2488 const std::vector<std::string> &new_labels) {
2489 this->_impl->relabel_(old_labels, new_labels);
2490 return *this;
2491 }
2497 [[deprecated(
2498 "Please use "
2499 "UniTensor &relabel_(const std::vector<std::string> &old_labels, const "
2500 "std::vector<std::string> &new_labels) "
2501 "instead.")]] UniTensor &
2502 relabels_(const std::vector<std::string> &old_labels,
2503 const std::vector<std::string> &new_labels) {
2504 this->_impl->relabels_(old_labels, new_labels);
2505 return *this;
2506 }
2507
2512 UniTensor relabel(const std::initializer_list<char *> &old_labels,
2513 const std::initializer_list<char *> &new_labels) const {
2514 std::vector<char *> new_lbls(new_labels);
2515 std::vector<std::string> vs(new_lbls.size());
2516 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2517 [](char *x) -> std::string { return std::string(x); });
2518
2519 std::vector<char *> old_lbls(old_labels);
2520 std::vector<std::string> vs_old(old_lbls.size());
2521 transform(old_lbls.begin(), old_lbls.end(), vs_old.begin(),
2522 [](char *x) -> std::string { return std::string(x); });
2523
2524 return this->relabel(vs_old, vs);
2525 }
2526
2532 [[deprecated(
2533 "Please use "
2534 "UniTensor relabel(const std::initializer_list<char *> &old_labels, const "
2535 "std::initializer_list<char *> &new_labels) const "
2536 "instead.")]] UniTensor
2537 relabels(const std::initializer_list<char *> &old_labels,
2538 const std::initializer_list<char *> &new_labels) const {
2539 std::vector<char *> new_lbls(new_labels);
2540 std::vector<std::string> vs(new_lbls.size());
2541 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2542 [](char *x) -> std::string { return std::string(x); });
2543
2544 std::vector<char *> old_lbls(old_labels);
2545 std::vector<std::string> vs_old(old_lbls.size());
2546 transform(old_lbls.begin(), old_lbls.end(), vs_old.begin(),
2547 [](char *x) -> std::string { return std::string(x); });
2548
2549 return this->relabels(vs_old, vs);
2550 }
2551
2556 UniTensor &relabel_(const std::initializer_list<char *> &old_labels,
2557 const std::initializer_list<char *> &new_labels) {
2558 std::vector<char *> new_lbls(new_labels);
2559 std::vector<std::string> vs(new_lbls.size());
2560 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2561 [](char *x) -> std::string { return std::string(x); });
2562
2563 std::vector<char *> old_lbls(old_labels);
2564 std::vector<std::string> vs_old(old_lbls.size());
2565 transform(old_lbls.begin(), old_lbls.end(), vs_old.begin(),
2566 [](char *x) -> std::string { return std::string(x); });
2567
2568 this->relabel_(vs_old, vs);
2569 return *this;
2570 }
2576 [[deprecated(
2577 "Please use "
2578 "UniTensor &relabel_(const std::initializer_list<char *> &old_labels, const "
2579 "std::initializer_list<char *> &new_labels) "
2580 "instead.")]] UniTensor &
2581 relabels_(const std::initializer_list<char *> &old_labels,
2582 const std::initializer_list<char *> &new_labels) {
2583 std::vector<char *> new_lbls(new_labels);
2584 std::vector<std::string> vs(new_lbls.size());
2585 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2586 [](char *x) -> std::string { return std::string(x); });
2587
2588 std::vector<char *> old_lbls(old_labels);
2589 std::vector<std::string> vs_old(old_lbls.size());
2590 transform(old_lbls.begin(), old_lbls.end(), vs_old.begin(),
2591 [](char *x) -> std::string { return std::string(x); });
2592
2593 this->relabels_(vs_old, vs);
2594 return *this;
2595 }
2596
2611 UniTensor relabel(const cytnx_int64 &inx, const std::string &new_label) const {
2612 UniTensor out;
2613 out._impl = this->_impl->relabel(inx, new_label);
2614 return out;
2615 }
2624 UniTensor &relabel_(const cytnx_int64 &inx, const std::string &new_label) {
2625 this->_impl->relabel_(inx, new_label);
2626 return *this;
2627 }
2628
2637 UniTensor &relabel_(const std::string &old_label, const std::string &new_label) {
2638 this->_impl->relabel_(old_label, new_label);
2639 return *this;
2640 }
2641
2656 UniTensor relabel(const std::string &old_label, const std::string &new_label) const {
2657 UniTensor out;
2658 out._impl = this->_impl->relabel(old_label, new_label);
2659 return out;
2660 }
2661
2668 UniTensor astype(const unsigned int &dtype) const {
2669 UniTensor out;
2670 if (this->dtype() == dtype) {
2671 out._impl = this->_impl;
2672 } else {
2673 out._impl = this->_impl->astype(dtype);
2674 }
2675 return out;
2676 }
2677
2686 UniTensor permute(const std::vector<cytnx_int64> &mapper,
2687 const cytnx_int64 &rowrank = -1) const {
2688 UniTensor out;
2689 out._impl = this->_impl->permute(mapper, rowrank);
2690 return out;
2691 }
2692
2699 UniTensor permute(const std::vector<std::string> &mapper,
2700 const cytnx_int64 &rowrank = -1) const {
2701 UniTensor out;
2702 out._impl = this->_impl->permute(mapper, rowrank);
2703 return out;
2704 }
2705
2709 UniTensor permute(const std::initializer_list<char *> &mapper,
2710 const cytnx_int64 &rowrank = -1) const {
2711 std::vector<char *> mprs = mapper;
2712 std::vector<std::string> vs(mprs.size());
2713 transform(mprs.begin(), mprs.end(), vs.begin(),
2714 [](char *x) -> std::string { return std::string(x); });
2715
2716 return this->permute(vs, rowrank);
2717 }
2718
2728 [[deprecated(
2729 "Please use "
2730 "UniTensor &permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank) "
2731 "instead.")]] UniTensor &
2732 permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1) {
2733 this->_impl->permute_(mapper, rowrank);
2734 return *this;
2735 }
2736
2743 UniTensor &permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1) {
2744 this->_impl->permute_(mapper, rowrank);
2745 return *this;
2746 }
2747
2748 // void permute_( const std::initializer_list<char*> &mapper, const cytnx_int64 &rowrank= -1){
2749 // std::vector<char*> mprs = mapper;
2750 // std::vector<std::string> vs(mprs.size());
2751 // transform(mprs.begin(),mprs.end(),vs.begin(),[](char * x) -> std::string { return
2752 // std::string(x); });
2753
2754 // this->permute_(vs,rowrank);
2755 // }
2756
2757 // void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1) {
2758 // this->_impl->permute_(mapper, rowrank);
2759 // }
2760
2766 UniTensor out;
2767 out._impl = this->_impl->contiguous();
2768 return out;
2769 }
2770
2775 void contiguous_() { this->_impl = this->_impl->contiguous_(); }
2776
2781 void print_diagram(const bool &bond_info = false) { this->_impl->print_diagram(bond_info); }
2782
2787 void print_blocks(const bool &full_info = true) const { this->_impl->print_blocks(full_info); }
2788
2794 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const {
2795 this->_impl->print_block(idx, full_info);
2796 }
2797
2804 void group_basis_() { this->_impl->group_basis_(); }
2805
2807 UniTensor out = this->clone();
2808 out.group_basis_();
2809 return out;
2810 }
2811
2817 template <class T>
2818 T &at(const std::vector<cytnx_uint64> &locator) {
2819 // std::cout << "at " << this->is_blockform() << std::endl;
2820 if (this->uten_type() == UTenType.Block) {
2821 // [NEW] this will not check if it exists, if it is not then error will throw!
2822 T aux;
2823 return this->_impl->at_for_sparse(locator, aux);
2824
2825 } else if (this->uten_type() == UTenType.Sparse) {
2826 if (this->_impl->elem_exists(locator)) {
2827 T aux;
2828 return this->_impl->at_for_sparse(locator, aux);
2829 } else {
2830 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2831 "\n");
2832 }
2833 } else {
2834 return this->get_block_().at<T>(locator);
2835 }
2836 }
2837
2843 template <class T>
2844 const T &at(const std::vector<cytnx_uint64> &locator) const {
2845 // std::cout << "at " << this->is_blockform() << std::endl;
2846 if (this->uten_type() == UTenType.Block) {
2847 // [NEW] this will not check if it exists, if it is not then error will throw!
2848 T aux;
2849 return this->_impl->at_for_sparse(locator, aux);
2850
2851 } else if (this->uten_type() == UTenType.Sparse) {
2852 if (this->_impl->elem_exists(locator)) {
2853 T aux; // [workaround] use aux to dispatch.
2854 return this->_impl->at_for_sparse(locator, aux);
2855 } else {
2856 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2857 "\n");
2858 }
2859 } else {
2860 return this->get_block_().at<T>(locator);
2861 }
2862 }
2863
2864 template <class T>
2865 const T &at(const std::vector<std::string> &labels,
2866 const std::vector<cytnx_uint64> &locator) const {
2867 // giving label <-> locator one to one corresponding, return the element:
2868 cytnx_error_msg(locator.size() != labels.size(),
2869 "[ERROR][at] length of list should be the same for label and locator.%s",
2870 "\n");
2872 labels.size() != this->rank(),
2873 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
2874 std::vector<cytnx_uint64> new_locator(this->rank());
2876 for (int i = 0; i < labels.size(); i++) {
2877 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
2878 cytnx_error_msg(res == this->_impl->_labels.end(),
2879 "[ERROR] label:%s does not exist in current UniTensor.\n",
2880 labels[i].c_str());
2881 new_loc = std::distance(this->_impl->_labels.begin(), res);
2883 }
2884 return this->at<T>(new_locator);
2885 }
2886 template <class T>
2887 T &at(const std::vector<std::string> &labels, const std::vector<cytnx_uint64> &locator) {
2888 // giving label <-> locator one to one corresponding, return the element:
2889 cytnx_error_msg(locator.size() != labels.size(),
2890 "[ERROR][at] length of list should be the same for label and locator.%s",
2891 "\n");
2893 labels.size() != this->rank(),
2894 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
2895 std::vector<cytnx_uint64> new_locator(this->rank());
2897 for (int i = 0; i < labels.size(); i++) {
2898 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
2899 cytnx_error_msg(res == this->_impl->_labels.end(),
2900 "[ERROR] label:%s does not exist in current UniTensor.\n",
2901 labels[i].c_str());
2902 new_loc = std::distance(this->_impl->_labels.begin(), res);
2904 }
2905 return this->at<T>(new_locator);
2906 }
2907
2912 const Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) const {
2913 if (this->uten_type() == UTenType.Block) {
2914 return this->_impl->at_for_sparse(locator);
2915 } else if (this->uten_type() == UTenType.Sparse) {
2916 if (this->_impl->elem_exists(locator)) {
2917 return this->_impl->at_for_sparse(locator);
2918 } else {
2919 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2920 "\n");
2921 }
2922 } else {
2923 return this->get_block_().at(locator);
2924 }
2925 }
2926
2931 Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) {
2932 if (this->uten_type() == UTenType.Block) {
2933 return this->_impl->at_for_sparse(locator);
2934 } else if (this->uten_type() == UTenType.Sparse) {
2935 if (this->_impl->elem_exists(locator)) {
2936 return this->_impl->at_for_sparse(locator);
2937 } else {
2938 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2939 "\n");
2940 }
2941 } else {
2942 return this->get_block_().at(locator);
2943 }
2944 }
2945
2946 Scalar::Sproxy at(const std::vector<std::string> &labels,
2947 const std::vector<cytnx_uint64> &locator) {
2948 // giving label <-> locator one to one corresponding, return the element:
2949 cytnx_error_msg(locator.size() != labels.size(),
2950 "[ERROR][at] length of list should be the same for label and locator.%s",
2951 "\n");
2953 labels.size() != this->rank(),
2954 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
2955 std::vector<cytnx_uint64> new_locator(this->rank());
2957 for (int i = 0; i < labels.size(); i++) {
2958 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
2959 cytnx_error_msg(res == this->_impl->_labels.end(),
2960 "[ERROR] label:%s does not exist in current UniTensor.\n",
2961 labels[i].c_str());
2962 new_loc = std::distance(this->_impl->_labels.begin(), res);
2964 }
2965 return this->at(new_locator);
2966 }
2967
2968 const Scalar::Sproxy at(const std::vector<std::string> &labels,
2969 const std::vector<cytnx_uint64> &locator) const {
2970 // giving label <-> locator one to one corresponding, return the element:
2971 cytnx_error_msg(locator.size() != labels.size(),
2972 "[ERROR][at] length of list should be the same for label and locator.%s",
2973 "\n");
2975 labels.size() != this->rank(),
2976 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
2977 std::vector<cytnx_uint64> new_locator(this->rank());
2979 for (int i = 0; i < labels.size(); i++) {
2980 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
2981 cytnx_error_msg(res == this->_impl->_labels.end(),
2982 "[ERROR] label:%s does not exist in current UniTensor.\n",
2983 labels[i].c_str());
2984 new_loc = std::distance(this->_impl->_labels.begin(), res);
2986 }
2987 return this->at(new_locator);
2988 }
2989
2990 // return a clone of block
2996 Tensor get_block(const cytnx_uint64 &idx = 0) const { return this->_impl->get_block(idx); };
2997 //================================
2998 // return a clone of block
3007 Tensor get_block(const std::vector<cytnx_int64> &qidx, const bool &force = false) const {
3008 return this->_impl->get_block(qidx, force);
3009 }
3010
3011 Tensor get_block(const std::vector<std::string> &labels, const std::vector<cytnx_int64> &qidx,
3012 const bool &force = false) const {
3014 labels.size() != qidx.size(),
3015 "[ERROR][get_block] length of lists must be the same for both lables and qnidices%s", "\n");
3016 cytnx_error_msg(labels.size() != this->rank(),
3017 "[ERROR][get_block] length of lists must be the rank (# of legs)%s", "\n");
3018
3019 std::vector<cytnx_int64> loc_id(this->rank());
3020 std::vector<cytnx_int64> new_qidx(this->rank());
3021
3023 std::vector<cytnx_uint64> new_order(this->rank());
3024 for (int i = 0; i < labels.size(); i++) {
3025 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
3026 cytnx_error_msg(res == this->_impl->_labels.end(),
3027 "[ERROR][get_block] label:%s does not exists in current Tensor.\n",
3028 labels[i].c_str());
3029 new_loc = std::distance(this->_impl->_labels.begin(), res);
3030 new_qidx[new_loc] = qidx[i];
3031 new_order[i] = new_loc;
3032 }
3033 auto out = this->_impl->get_block(new_qidx, force);
3034 if (out.dtype() != Type.Void) out.permute_(new_order);
3035 return out;
3036 }
3037
3042 Tensor get_block(const std::initializer_list<cytnx_int64> &qnum,
3043 const bool &force = false) const {
3044 std::vector<cytnx_int64> tmp = qnum;
3045 return get_block(tmp, force);
3046 }
3047
3052 Tensor get_block(const std::vector<cytnx_uint64> &qnum, const bool &force = false) const {
3053 std::vector<cytnx_int64> iqnum(qnum.begin(), qnum.end());
3054 return this->_impl->get_block(iqnum, force);
3055 }
3056
3057 Tensor get_block(const std::vector<std::string> &labels, const std::vector<cytnx_uint64> &qidx,
3058 const bool &force = false) const {
3059 std::vector<cytnx_int64> iqnum(qidx.begin(), qidx.end());
3060 return this->get_block(labels, iqnum, force);
3061 }
3062
3068 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const {
3069 return this->_impl->get_block_(idx);
3070 }
3071
3076 Tensor &get_block_(const cytnx_uint64 &idx = 0) { return this->_impl->get_block_(idx); }
3077
3086 Tensor &get_block_(const std::vector<cytnx_int64> &qidx, const bool &force = false) {
3087 return this->_impl->get_block_(qidx, force);
3088 }
3089
3104 // developer note: Tensor is not the same object (Thus Tensor instead of Tensor& ),
3105 // since we permute! but they have shared data memory.
3106 Tensor get_block_(const std::vector<std::string> &labels, const std::vector<cytnx_int64> &qidx,
3107 const bool &force = false) {
3109 labels.size() != qidx.size(),
3110 "[ERROR][get_block] length of lists must be the same for both lables and qnidices%s", "\n");
3111 cytnx_error_msg(labels.size() != this->rank(),
3112 "[ERROR][get_block] length of lists must be the rank (# of legs)%s", "\n");
3113
3114 std::vector<cytnx_int64> loc_id(this->rank());
3115 std::vector<cytnx_int64> new_qidx(this->rank());
3116
3118 std::vector<cytnx_uint64> new_order(this->rank());
3119 for (int i = 0; i < labels.size(); i++) {
3120 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
3121 cytnx_error_msg(res == this->_impl->_labels.end(),
3122 "[ERROR][get_block] label:%s does not exists in current Tensor.\n",
3123 labels[i].c_str());
3124 new_loc = std::distance(this->_impl->_labels.begin(), res);
3125 new_qidx[new_loc] = qidx[i];
3126 new_order[i] = new_loc;
3127 }
3128 auto out = this->_impl->get_block_(new_qidx, force);
3129 if (out.dtype() != Type.Void) {
3130 out = out.permute(new_order);
3131 }
3132 return out;
3133 }
3134
3138 Tensor &get_block_(const std::initializer_list<cytnx_int64> &qidx, const bool &force = false) {
3139 std::vector<cytnx_int64> tmp = qidx;
3140 return get_block_(tmp, force);
3141 }
3142
3146 Tensor &get_block_(const std::vector<cytnx_uint64> &qidx, const bool &force = false) {
3147 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
3148 return get_block_(iqidx, force);
3149 }
3150
3151 Tensor get_block_(const std::vector<std::string> &labels, const std::vector<cytnx_uint64> &qidx,
3152 const bool &force = false) {
3153 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
3154 return get_block_(labels, iqidx, force);
3155 }
3156 //================================
3157
3158 // this only work for non-symm tensor. return a shared view of block
3162 const Tensor &get_block_(const std::vector<cytnx_int64> &qidx,
3163 const bool &force = false) const {
3164 return this->_impl->get_block_(qidx, force);
3165 }
3166
3170 const Tensor &get_block_(const std::initializer_list<cytnx_int64> &qidx,
3171 const bool &force = false) const {
3172 std::vector<cytnx_int64> tmp = qidx;
3173 return this->_impl->get_block_(tmp, force);
3174 }
3175
3179 const Tensor &get_block_(const std::vector<cytnx_uint64> &qidx,
3180 const bool &force = false) const {
3181 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
3182 return get_block_(iqidx, force);
3183 }
3184
3185 //================================
3194 //[dev]
3195 std::vector<Tensor> get_blocks() const { return this->_impl->get_blocks(); }
3196
3202 //[dev]
3203 const std::vector<Tensor> &get_blocks_(const bool &silent = false) const {
3204 return this->_impl->get_blocks_(silent);
3205 }
3206
3210 //[dev]
3211 std::vector<Tensor> &get_blocks_(const bool &silent = false) {
3212 return this->_impl->get_blocks_(silent);
3213 }
3214
3220 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
3221 this->_impl->put_block(in, idx);
3222 }
3223
3231 void put_block(const Tensor &in_tens, const std::vector<cytnx_int64> &qidx, const bool &force) {
3232 this->_impl->put_block(in_tens, qidx, force);
3233 }
3234
3239 void put_block(Tensor &in, const std::vector<std::string> &lbls,
3240 const std::vector<cytnx_int64> &qidx, const bool &force = false) {
3242 lbls.size() != qidx.size(),
3243 "[ERROR][put_block] length of lists must be the same for both lables and qnidices%s", "\n");
3244 cytnx_error_msg(lbls.size() != this->rank(),
3245 "[ERROR][put_block] length of lists must be the rank (# of legs)%s", "\n");
3246
3247 std::vector<cytnx_int64> loc_id(this->rank());
3248 std::vector<cytnx_int64> new_qidx(this->rank());
3249
3251 // std::vector<cytnx_uint64> new_order(this->rank());
3252 std::vector<cytnx_uint64> inv_order(this->rank());
3253 for (int i = 0; i < lbls.size(); i++) {
3254 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), lbls[i]);
3255 cytnx_error_msg(res == this->_impl->_labels.end(),
3256 "[ERROR][put_block] label:%s does not exists in current Tensor.\n",
3257 lbls[i].c_str());
3258 new_loc = std::distance(this->_impl->_labels.begin(), res);
3259 new_qidx[new_loc] = qidx[i];
3260 // new_order[i] = new_loc;
3261 inv_order[new_loc] = i;
3262 }
3263 this->_impl->put_block(in.permute(inv_order), new_qidx, force);
3264 }
3265
3271 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) { this->_impl->put_block_(in, idx); }
3272
3279 void put_block_(Tensor &in, const std::vector<cytnx_int64> &qidx, const bool &force) {
3280 this->_impl->put_block_(in, qidx, force);
3281 }
3282
3287 void put_block_(Tensor &in, const std::vector<std::string> &lbls,
3288 const std::vector<cytnx_int64> &qidx, const bool &force = false) {
3290 lbls.size() != qidx.size(),
3291 "[ERROR][put_block_] length of lists must be the same for both lables and qnidices%s",
3292 "\n");
3293 cytnx_error_msg(lbls.size() != this->rank(),
3294 "[ERROR][put_block_] length of lists must be the rank (# of legs)%s", "\n");
3295
3296 std::vector<cytnx_int64> loc_id(this->rank());
3297 std::vector<cytnx_int64> new_qidx(this->rank());
3298
3300 std::vector<cytnx_uint64> new_order(this->rank());
3301 std::vector<cytnx_uint64> inv_order(this->rank());
3302 for (int i = 0; i < lbls.size(); i++) {
3303 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), lbls[i]);
3304 cytnx_error_msg(res == this->_impl->_labels.end(),
3305 "[ERROR][put_block_] label:%s does not exists in current Tensor.\n",
3306 lbls[i].c_str());
3307 new_loc = std::distance(this->_impl->_labels.begin(), res);
3308 new_qidx[new_loc] = qidx[i];
3309 new_order[i] = new_loc;
3310 inv_order[new_loc] = i;
3311 }
3312 in.permute_(inv_order);
3313 this->_impl->put_block_(in, new_qidx, force);
3314 in.permute_(new_order);
3315 }
3316 UniTensor get(const std::vector<Accessor> &accessors) const {
3317 UniTensor out;
3318 out._impl = this->_impl->get(accessors);
3319 return out;
3320 }
3321 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
3322 this->_impl->set(accessors, rhs);
3323 }
3324 void set(const std::vector<Accessor> &accessors, const UniTensor &rhs) {
3326 rhs.uten_type() != UTenType.Dense,
3327 "[ERROR] cannot set elements from UniTensor with symmetry. Use at() instead.%s", "\n");
3328 cytnx_error_msg(this->is_diag(), "[ERROR] cannot set UniTensor with is_diag=True.%s", "\n");
3330 "[ERROR] cannot set UniTensor. incoming UniTensor is_diag=True.%s", "\n");
3331
3332 this->_impl->set(accessors, rhs.get_block());
3333 }
3341 UniTensor reshape(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
3342 UniTensor out;
3343 out._impl = this->_impl->reshape(new_shape, rowrank);
3344 return out;
3345 }
3346
3353 UniTensor &reshape_(const std::vector<cytnx_int64> &new_shape,
3354 const cytnx_uint64 &rowrank = 0) {
3355 this->_impl->reshape_(new_shape, rowrank);
3356 return *this;
3357 }
3358
3371 UniTensor out;
3372 out._impl = this->_impl->to_dense();
3373 return out;
3374 }
3375
3380 void to_dense_() { this->_impl->to_dense_(); }
3381
3387 [[deprecated(
3388 "Please use "
3389 "combineBond(const std::vector<std::string> &indicators, const bool &force) "
3390 "instead.")]] void
3391 combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
3392 const bool &by_label) {
3393 this->_impl->combineBonds(indicators, force, by_label);
3394 }
3395
3401 [[deprecated(
3402 "Please use "
3403 "combineBond(const std::vector<std::string> &indicators, const bool &force) "
3404 "instead.")]] void
3405 combineBonds(const std::vector<std::string> &indicators, const bool &force = false) {
3406 this->_impl->combineBonds(indicators, force);
3407 }
3408
3414 [[deprecated(
3415 "Please use "
3416 "combineBond(const std::vector<std::string> &indicators, const bool &force) "
3417 "instead.")]] void
3418 combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = false) {
3419 this->_impl->combineBonds(indicators, force);
3420 }
3421
3432 void combineBond(const std::vector<std::string> &indicators, const bool &force = false) {
3433 this->_impl->combineBond(indicators, force);
3434 }
3435
3454 UniTensor contract(const UniTensor &inR, const bool &mv_elem_self = false,
3455 const bool &mv_elem_rhs = false) const {
3456 UniTensor out;
3457 out._impl = this->_impl->contract(inR._impl, mv_elem_self, mv_elem_rhs);
3458 return out;
3459 }
3460
3462
3470 std::vector<Bond> getTotalQnums(const bool physical = false) const {
3471 return this->_impl->getTotalQnums(physical);
3472 }
3473
3477 std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const {
3478 return this->_impl->get_blocks_qnums();
3479 }
3481
3486 bool same_data(const UniTensor &rhs) const {
3487 // check same type:
3488 if (this->_impl->uten_type() != rhs._impl->uten_type()) return false;
3489
3490 return this->_impl->same_data(rhs._impl);
3491 }
3492
3510 this->_impl->Add_(rhs._impl);
3511 return *this;
3512 }
3513
3531 this->_impl->Mul_(rhs._impl);
3532 return *this;
3533 }
3534
3552 this->_impl->Sub_(rhs._impl);
3553 return *this;
3554 }
3555
3573 this->_impl->Div_(rhs._impl);
3574 return *this;
3575 }
3576
3588 this->_impl->Add_(rhs);
3589 return *this;
3590 }
3591
3603 this->_impl->Mul_(rhs);
3604 return *this;
3605 }
3606
3618 this->_impl->Sub_(rhs);
3619 return *this;
3620 }
3621
3633 this->_impl->Div_(rhs);
3634 return *this;
3635 }
3636
3654
3665 UniTensor Add(const Scalar &rhs) const;
3666
3684
3695 UniTensor Mul(const Scalar &rhs) const;
3696
3714
3725 UniTensor Div(const Scalar &rhs) const;
3726
3744
3755 UniTensor Sub(const Scalar &rhs) const;
3756
3765 Tensor Norm() const { return this->_impl->Norm(); };
3766
3783 this->Add_(rhs);
3784 return *this;
3785 }
3786
3803 this->Sub_(rhs);
3804 return *this;
3805 }
3806
3823 this->Div_(rhs);
3824 return *this;
3825 }
3826
3843 this->Mul_(rhs);
3844 return *this;
3845 }
3846
3858 this->Add_(rhs);
3859 return *this;
3860 }
3861
3873 this->Sub_(rhs);
3874 return *this;
3875 }
3876
3888 this->Div_(rhs);
3889 return *this;
3890 }
3891
3903 this->Mul_(rhs);
3904 return *this;
3905 }
3906
3914 UniTensor Conj() const {
3915 UniTensor out;
3916 out._impl = this->_impl->Conj();
3917 return out;
3918 }
3919
3928 this->_impl->Conj_();
3929 return *this;
3930 }
3931
3943 UniTensor out;
3944 out._impl = this->_impl->Transpose();
3945 return out;
3946 }
3947
3955 this->_impl->Transpose_();
3956 return *this;
3957 }
3958
3966 UniTensor out;
3967 out._impl = this->_impl->normalize();
3968 return out;
3969 }
3970
3978 this->_impl->normalize_();
3979 return *this;
3980 }
3981
3991 UniTensor Trace(const std::string &a, const std::string &b) const {
3992 UniTensor out;
3993 out._impl = this->_impl->Trace(a, b);
3994 return out;
3995 }
3996
4006 UniTensor Trace(const cytnx_int64 &a = 0, const cytnx_int64 &b = 1) const {
4007 UniTensor out;
4008 out._impl = this->_impl->Trace(a, b);
4009 return out;
4010 }
4011
4021 UniTensor &Trace_(const std::string &a, const std::string &b) {
4022 this->_impl->Trace_(a, b);
4023 if (this->uten_type() == UTenType.Block) {
4024 // handle if no leg left case for BlockUniTensor.
4025 if (this->rank() == 0) {
4026 DenseUniTensor *tmp = new DenseUniTensor();
4027 tmp->_block = this->get_blocks_(true)[0];
4028 this->_impl = boost::intrusive_ptr<UniTensor_base>(tmp);
4029 }
4030 }
4031 return *this;
4032 }
4033
4043 UniTensor &Trace_(const cytnx_int64 &a = 0, const cytnx_int64 &b = 1) {
4044 this->_impl->Trace_(a, b);
4045 if (this->uten_type() == UTenType.Block) {
4046 // handle if no leg left case for BlockUniTensor.
4047 if (this->rank() == 0) {
4048 DenseUniTensor *tmp = new DenseUniTensor();
4049 tmp->_block = this->get_blocks_(true)[0];
4050 this->_impl = boost::intrusive_ptr<UniTensor_base>(tmp);
4051 }
4052 }
4053 return *this;
4054 }
4055
4063 UniTensor out;
4064 out._impl = this->_impl->Dagger();
4065 return out;
4066 }
4067
4075 this->_impl->Dagger_();
4076 return *this;
4077 }
4078
4088 this->_impl->tag();
4089 return *this;
4090 }
4091
4100 UniTensor Pow(const double &p) const;
4101
4110 UniTensor &Pow_(const double &p);
4111
4118 bool elem_exists(const std::vector<cytnx_uint64> &locator) const {
4119 return this->_impl->elem_exists(locator);
4120 }
4121
4127 template <class T>
4128 T get_elem(const std::vector<cytnx_uint64> &locator) const {
4129 return this->at<T>(locator);
4130 }
4131
4137 template <class T2>
4138 void set_elem(const std::vector<cytnx_uint64> &locator, const T2 &rc) {
4139 // cytnx_error_msg(true,"[ERROR] invalid type%s","\n");
4140 this->at(locator) = rc;
4141 }
4142
4149 void Save(const std::string &fname) const;
4150
4157 void Save(const char *fname) const;
4158
4167 static UniTensor Load(const std::string &fname);
4168
4177 static UniTensor Load(const char *fname);
4178
4187 UniTensor &truncate_(const std::string &label, const cytnx_uint64 &dim) {
4188 this->_impl->truncate_(label, dim);
4189 return *this;
4190 }
4191
4201 this->_impl->truncate_(bond_idx, dim);
4202 return *this;
4203 }
4204
4214 UniTensor truncate(const std::string &label, const cytnx_uint64 &dim) const {
4215 UniTensor out = this->clone();
4216 out.truncate_(label, dim);
4217 return out;
4218 }
4219
4230 UniTensor out = this->clone();
4231 out.truncate_(bond_idx, dim);
4232 return out;
4233 }
4234
4242 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
4243 return this->_impl->get_qindices(bidx);
4244 }
4252 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
4253 return this->_impl->get_qindices(bidx);
4254 }
4255
4262 const vec2d<cytnx_uint64> &get_itoi() const { return this->_impl->get_itoi(); }
4263 vec2d<cytnx_uint64> &get_itoi() { return this->_impl->get_itoi(); }
4264
4266 void _Load(std::fstream &f);
4267 void _Save(std::fstream &f) const;
4269
4270 UniTensor &convert_from(const UniTensor &rhs, const bool &force = false) {
4271 this->_impl->from_(rhs._impl, force);
4272 return *this;
4273 }
4274
4275 // Generators:
4289 const std::vector<std::string> &in_labels = {},
4290 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4291 const std::string &name = "") {
4292 return UniTensor(cytnx::zeros(Nelem, dtype, device), false, -1, in_labels, name);
4293 }
4294
4308 static UniTensor zeros(const std::vector<cytnx_uint64> &shape,
4309 const std::vector<std::string> &in_labels = {},
4310 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4311 const std::string &name = "") {
4312 return UniTensor(cytnx::zeros(shape, dtype, device), false, -1, in_labels, name);
4313 }
4314
4326 static UniTensor ones(const cytnx_uint64 &Nelem, const std::vector<std::string> &in_labels = {},
4327 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4328 const std::string &name = "") {
4329 return UniTensor(cytnx::ones(Nelem, dtype, device), false, -1, in_labels, name);
4330 }
4331
4345 const std::vector<std::string> &in_labels = {},
4346 const cytnx_bool &is_diag = false,
4347 const unsigned int &dtype = Type.Double,
4348 const int &device = Device.cpu, const std::string &name = "") {
4349 if (is_diag) {
4350 return UniTensor(cytnx::ones(dim, dtype, device), is_diag, -1, in_labels, name);
4351 } else {
4353 }
4354 }
4355
4371 static UniTensor eye(const cytnx_uint64 &dim, const std::vector<std::string> &in_labels = {},
4372 const cytnx_bool &is_diag = false, const unsigned int &dtype = Type.Double,
4373 const int &device = Device.cpu, const std::string &name = "") {
4374 return identity(dim, in_labels, is_diag, dtype, device, name);
4375 }
4376
4389 static UniTensor ones(const std::vector<cytnx_uint64> &shape,
4390 const std::vector<std::string> &in_labels = {},
4391 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4392 const std::string &name = "") {
4393 return UniTensor(cytnx::ones(shape, dtype, device), false, -1, in_labels, name);
4394 }
4395
4410 const std::vector<std::string> &in_labels = {},
4411 const std::string &name = "") {
4412 return UniTensor(cytnx::arange(Nelem), false, -1, in_labels, name);
4413 }
4414
4432 const cytnx_double &step = 1,
4433 const std::vector<std::string> &in_labels = {},
4434 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4435 const std::string &name = "") {
4436 return UniTensor(cytnx::arange(start, end, step, dtype, device), false, -1, in_labels, name);
4437 }
4438
4459 const cytnx_uint64 &Nelem, const bool &endpoint = true,
4460 const std::vector<std::string> &in_labels = {},
4461 const unsigned int &dtype = Type.Double,
4462 const int &device = Device.cpu, const std::string &name = "") {
4463 return UniTensor(cytnx::linspace(start, end, Nelem, endpoint, dtype, device), false, -1,
4464 in_labels, name);
4465 }
4466
4467 // Random Generators:
4486 static UniTensor normal(const cytnx_uint64 &Nelem, const double &mean, const double &std,
4487 const std::vector<std::string> &in_labels = {},
4488 const unsigned int &seed = cytnx::random::__static_random_device(),
4489 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4490 const std::string &name = "");
4491
4510 static UniTensor normal(const std::vector<cytnx_uint64> &shape, const double &mean,
4511 const double &std, const std::vector<std::string> &in_labels = {},
4512 const unsigned int &seed = cytnx::random::__static_random_device(),
4513 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4514 const std::string &name = "");
4515
4534 static UniTensor uniform(const cytnx_uint64 &Nelem, const double &low, const double &high,
4535 const std::vector<std::string> &in_labels = {},
4536 const unsigned int &seed = cytnx::random::__static_random_device(),
4537 const unsigned int &dtype = Type.Double,
4538 const int &device = Device.cpu, const std::string &name = "");
4539
4577 static UniTensor uniform(const std::vector<cytnx_uint64> &shape, const double &low,
4578 const double &high, const std::vector<std::string> &in_labels = {},
4579 const unsigned int &seed = cytnx::random::__static_random_device(),
4580 const unsigned int &dtype = Type.Double,
4581 const int &device = Device.cpu, const std::string &name = "");
4582
4583 // Inplace Random Generators:
4596 void normal_(const double &mean, const double &std,
4597 const unsigned int &seed = cytnx::random::__static_random_device());
4598
4611 void uniform_(const double &low = 0, const double &high = 1,
4612 const unsigned int &seed = cytnx::random::__static_random_device());
4613
4614 }; // class UniTensor
4615
4617 std::ostream &operator<<(std::ostream &os, const UniTensor &in);
4619
4632 UniTensor Contract(const UniTensor &inL, const UniTensor &inR, const bool &cacheL = false,
4633 const bool &cacheR = false);
4634
4647 UniTensor Contract(const std::vector<UniTensor> &TNs, const std::string &order,
4648 const bool &optimal);
4649
4655 [[deprecated(
4656 "Please use "
4657 "UniTensor Contract(const std::vector<UniTensor> &TNs, const std::string &order, const bool "
4658 "&optimal) "
4659 "instead.")]] UniTensor
4660 Contracts(const std::vector<UniTensor> &TNs, const std::string &order, const bool &optimal);
4661
4663 void _resolve_CT(std::vector<UniTensor> &TNlist);
4664 template <class... T>
4665 void _resolve_CT(std::vector<UniTensor> &TNlist, const UniTensor &in, const T &...args) {
4666 TNlist.push_back(in);
4667 _resolve_CT(TNlist, args...);
4668 }
4670
4682 template <class... T>
4683 UniTensor Contract(const UniTensor &in, const T &...args, const std::string &order,
4684 const bool &optimal) {
4685 std::vector<UniTensor> TNlist;
4686 _resolve_CT(TNlist, in, args...);
4687 return Contract(TNlist, order, optimal);
4688 }
4689
4695 template <class... T>
4696 [[deprecated(
4697 "Please use "
4698 "UniTensor Contract(const UniTensor &in, const T &...args, const std::string &order, const "
4699 "bool &optimal) "
4700 "instead.")]] UniTensor
4701 Contracts(const UniTensor &in, const T &...args, const std::string &order,
4702 const bool &optimal) {
4703 std::vector<UniTensor> TNlist;
4704 _resolve_CT(TNlist, in, args...);
4705 return Contracts(TNlist, order, optimal);
4706 }
4707
4708} // namespace cytnx
4709
4710#endif // BACKEND_TORCH
4711
4712#endif // CYTNX_UNITENSOR_H_
constexpr Type_class Type
data type
Definition Type.hpp:426
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:671
Tensor contiguous_()
Make the Tensor contiguous by coalescing the memory (storage), inplacely.
Definition Tensor.hpp:758
unsigned int dtype() const
the dtype-id of the Tensor
Definition Tensor.hpp:570
Tensor contiguous() const
Make the Tensor contiguous by coalescing the memory (storage).
Definition Tensor.hpp:738
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition Tensor.hpp:920
Tensor clone() const
return a clone of the current Tensor.
Definition Tensor.hpp:622
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:1055
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:885
const bool & is_contiguous() const
return whether the Tensor is contiguous or not.
Definition Tensor.hpp:677
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:577
Tensor get(const std::vector< cytnx::Accessor > &accessors) const
get elements using Accessor (C++ API) / slices (python API)
Definition Tensor.hpp:1023
const std::vector< cytnx_uint64 > & shape() const
the shape of the Tensor
Definition Tensor.hpp:597
An Enhanced tensor specifically designed for physical Tensor network simulation.
Definition UniTensor.hpp:1794
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:3231
UniTensor to(const int &device) const
move the current UniTensor to the assigned device.
Definition UniTensor.hpp:2302
UniTensor & operator*=(const UniTensor &rhs)
The multiplication assignment operator of the UniTensor.
Definition UniTensor.hpp:3842
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:4371
Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:3138
std::vector< Tensor > & get_blocks_(const bool &silent=false)
Definition UniTensor.hpp:3211
Tensor & get_block_(const std::vector< cytnx_uint64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:3146
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:2794
UniTensor & operator/=(const UniTensor &rhs)
The division assignment operator of the UniTensor.
Definition UniTensor.hpp:3822
T & item()
Definition UniTensor.hpp:2118
bool is_contiguous() const
To tell whether the UniTensor is contiguous.
Definition UniTensor.hpp:2209
T get_elem(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:4128
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:3011
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:4252
UniTensor & set_label(const cytnx_int64 &idx, const char *new_label)
Definition UniTensor.hpp:2021
UniTensor & operator+=(const UniTensor &rhs)
The addition assignment operator of the UniTensor.
Definition UniTensor.hpp:3782
void to_dense_()
Convert the UniTensor to non-diagonal form, inplacely.
Definition UniTensor.hpp:3380
UniTensor reshape(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor.
Definition UniTensor.hpp:3341
std::vector< Tensor > get_blocks() const
Get all the blocks of the UniTensor.
Definition UniTensor.hpp:3195
void combineBond(const std::vector< std::string > &indicators, const bool &force=false)
Combine the sevral bonds of the UniTensor.
Definition UniTensor.hpp:3432
UniTensor permute(const std::initializer_list< char * > &mapper, const cytnx_int64 &rowrank=-1) const
Definition UniTensor.hpp:2709
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:2222
std::string uten_type_str() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor in 'string' form.
Definition UniTensor.hpp:2202
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:1884
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:3007
UniTensor & tag()
Set the UniTensor as a tagged UniTensor.
Definition UniTensor.hpp:4087
const Bond & bond_(const cytnx_uint64 &idx) const
Definition UniTensor.hpp:2263
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force=false)
Definition UniTensor.hpp:3418
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:2637
const T & at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:2865
UniTensor & relabels_(const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:2432
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:1833
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:3086
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:1856
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:4308
UniTensor get(const std::vector< Accessor > &accessors) const
Definition UniTensor.hpp:3316
T & at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:2887
UniTensor Conj() const
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:3914
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:2036
UniTensor set_rowrank(const cytnx_uint64 &new_rowrank) const
Definition UniTensor.hpp:2111
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:3872
cytnx_uint64 rowrank() const
Return the row rank of the UniTensor.
Definition UniTensor.hpp:2153
UniTensor & relabels_(const std::vector< std::string > &old_labels, const std::vector< std::string > &new_labels)
Definition UniTensor.hpp:2502
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:3765
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:2090
UniTensor & relabel_(const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:2414
UniTensor & Sub_(const Scalar &rhs)
The subtraction function for a given scalar.
Definition UniTensor.hpp:3617
UniTensor & relabel_(const cytnx_int64 &inx, const std::string &new_label)
rebable the lags in the UniTensor by given index.
Definition UniTensor.hpp:2624
UniTensor & operator/=(const Scalar &rhs)
The division assignment operator for a given scalar.
Definition UniTensor.hpp:3887
const bool & is_braket_form() const
Check whether the UniTensor is in braket form.
Definition UniTensor.hpp:2237
void set_elem(const std::vector< cytnx_uint64 > &locator, const T2 &rc)
Definition UniTensor.hpp:4138
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:4458
std::vector< cytnx_uint64 > shape() const
Get the shape of the UniTensor.
Definition UniTensor.hpp:2276
UniTensor to_dense()
Convert the UniTensor to non-diagonal form.
Definition UniTensor.hpp:3370
UniTensor & permute_(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1)
permute the lags of the UniTensor, inplacely.
Definition UniTensor.hpp:2732
Scalar::Sproxy at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:2946
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:3162
UniTensor & set_labels(const std::vector< std::string > &new_labels)
Set new labels for all the bonds.
Definition UniTensor.hpp:2081
std::string name() const
Return the name of the UniTensor.
Definition UniTensor.hpp:2181
const Scalar::Sproxy at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:2968
UniTensor & Add_(const Scalar &rhs)
The addition function for a given scalar.
Definition UniTensor.hpp:3587
UniTensor & Trace_(const std::string &a, const std::string &b)
Take the partial trance to the UniTensor, inplacely.
Definition UniTensor.hpp:4021
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:4200
Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition UniTensor.hpp:2931
UniTensor Trace(const std::string &a, const std::string &b) const
Take the partial trance to the UniTensor.
Definition UniTensor.hpp:3991
bool same_data(const UniTensor &rhs) const
Check whether the Blocks address are the same.
Definition UniTensor.hpp:3486
UniTensor astype(const unsigned int &dtype) const
Return a new UniTensor that cast to different data type.
Definition UniTensor.hpp:2668
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:4389
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:4214
UniTensor Transpose() const
Take the transpose of the UniTensor.
Definition UniTensor.hpp:3942
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:4431
UniTensor & set_label(const char *old_label, const std::string &new_label)
Definition UniTensor.hpp:2044
static UniTensor Load(const char *fname)
load a UniTensor from file
UniTensor & Dagger_()
Take the conjugate transpose to the UniTensor, inplacely.
Definition UniTensor.hpp:4074
void print_diagram(const bool &bond_info=false)
Plot the diagram of the UniTensor.
Definition UniTensor.hpp:2781
std::vector< Bond > & bonds()
Definition UniTensor.hpp:2261
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition UniTensor.hpp:2818
UniTensor & set_rowrank_(const cytnx_uint64 &new_rowrank)
Set the row rank of the UniTensor.
Definition UniTensor.hpp:2106
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:3239
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:2013
UniTensor contiguous() const
Make the UniTensor contiguous by coalescing the memory (storage).
Definition UniTensor.hpp:2765
Tensor get_block(const cytnx_uint64 &idx=0) const
Get the block of the UniTensor for a given index.
Definition UniTensor.hpp:2996
const T & at(const std::vector< cytnx_uint64 > &locator) const
Get an element at specific location.
Definition UniTensor.hpp:2844
UniTensor & operator*=(const Scalar &rhs)
The multiplication assignment operator for a given scalar.
Definition UniTensor.hpp:3902
UniTensor relabels(const std::vector< std::string > &old_labels, const std::vector< std::string > &new_labels) const
Definition UniTensor.hpp:2465
void contiguous_()
Make the UniTensor contiguous by coalescing the memory (storage), inplacely.
Definition UniTensor.hpp:2775
UniTensor normalize() const
normalize the current UniTensor instance with 2-norm.
Definition UniTensor.hpp:3965
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:4326
UniTensor & relabel_(const std::vector< std::string > &new_labels)
Set new labels for all the bonds.
Definition UniTensor.hpp:2327
std::vector< Symmetry > syms() const
Return the symmetry type of the UniTensor.
Definition UniTensor.hpp:2229
UniTensor relabel(const std::vector< std::string > &new_labels) const
relable all of the labels in UniTensor.
Definition UniTensor.hpp:2358
UniTensor & Mul_(const UniTensor &rhs)
The multiplcation function of the UniTensor.
Definition UniTensor.hpp:3530
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:4288
void put_block_(Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index, inplacely.
Definition UniTensor.hpp:3271
void combineBonds(const std::vector< std::string > &indicators, const bool &force=false)
Definition UniTensor.hpp:3405
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:2656
UniTensor & normalize_()
normalize the UniTensor, inplacely.
Definition UniTensor.hpp:3977
bool is_diag() const
To tell whether the UniTensor is in diagonal form.
Definition UniTensor.hpp:2215
int device() const
Return the device of the UniTensor.
Definition UniTensor.hpp:2175
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:3179
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:3106
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:3287
void set(const std::vector< Accessor > &accessors, const Tensor &rhs)
Definition UniTensor.hpp:3321
std::string dtype_str() const
Return the data type of the UniTensor in 'string' form.
Definition UniTensor.hpp:2188
UniTensor & operator+=(const Scalar &rhs)
The addition assignment operator for a given scalar.
Definition UniTensor.hpp:3857
UniTensor & Div_(const UniTensor &rhs)
The division function of the UniTensor.
Definition UniTensor.hpp:3572
UniTensor & Div_(const Scalar &rhs)
The division function for a given scalar.
Definition UniTensor.hpp:3632
Bond & bond_(const std::string &label)
Definition UniTensor.hpp:2267
cytnx_uint64 rank() const
Return the rank of the UniTensor.
Definition UniTensor.hpp:2147
Bond bond(const std::string &label) const
Definition UniTensor.hpp:2270
void group_basis_()
Group the same quantum number basis together.
Definition UniTensor.hpp:2804
void to_(const int &device)
move the current UniTensor to the assigned device (inplace).
Definition UniTensor.hpp:2291
UniTensor & Trace_(const cytnx_int64 &a=0, const cytnx_int64 &b=1)
Take the partial trance to the UniTensor, inplacely.
Definition UniTensor.hpp:4043
UniTensor relabel(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:2449
UniTensor & set_name(const std::string &in)
Set the name of the UniTensor.
Definition UniTensor.hpp:1998
UniTensor Trace(const cytnx_int64 &a=0, const cytnx_int64 &b=1) const
Take the partial trance to the UniTensor.
Definition UniTensor.hpp:4006
UniTensor & Add_(const UniTensor &rhs)
The addition function of the UniTensor.
Definition UniTensor.hpp:3509
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:2686
UniTensor & set_label(const std::string &old_label, const char *new_label)
Definition UniTensor.hpp:2052
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:2699
unsigned int dtype() const
Return the data type of the UniTensor.
Definition UniTensor.hpp:2160
UniTensor Pow(const double &p) const
Power function.
UniTensor & Mul_(const Scalar &rhs)
The multiplication function for a given scalar.
Definition UniTensor.hpp:3602
UniTensor & operator-=(const UniTensor &rhs)
The subtraction assignment operator of the UniTensor.
Definition UniTensor.hpp:3802
Tensor get_block_(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:3151
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force, const bool &by_label)
Definition UniTensor.hpp:3391
UniTensor & set_label(const char *old_label, const char *new_label)
Definition UniTensor.hpp:2060
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:4409
bool is_blockform() const
Check whether the UniTensor is in block form.
Definition UniTensor.hpp:2283
UniTensor group_basis() const
Definition UniTensor.hpp:2806
UniTensor Dagger() const
Take the conjugate transpose to the UniTensor.
Definition UniTensor.hpp:4062
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:3324
const std::vector< Tensor > & get_blocks_(const bool &silent=false) const
Get all the blocks of the UniTensor, inplacely.
Definition UniTensor.hpp:3203
UniTensor & relabels_(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:2581
const Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:3170
bool elem_exists(const std::vector< cytnx_uint64 > &locator) const
Geiven the locator, check if the element exists.
Definition UniTensor.hpp:4118
UniTensor & Sub_(const UniTensor &rhs)
The subtraction function of the UniTensor.
Definition UniTensor.hpp:3551
UniTensor relabels(const std::initializer_list< char * > &new_labels) const
Definition UniTensor.hpp:2401
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:3454
void put_block(const Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index.
Definition UniTensor.hpp:3220
const Tensor & get_block_(const cytnx_uint64 &idx=0) const
Get the shared view of block for the given index.
Definition UniTensor.hpp:3068
UniTensor & relabel_(const std::vector< std::string > &old_labels, const std::vector< std::string > &new_labels)
relable part or all of the labels in UniTensor by given new labels
Definition UniTensor.hpp:2487
static UniTensor Load(const std::string &fname)
load a UniTensor from file
UniTensor & permute_(const std::vector< std::string > &mapper, const cytnx_int64 &rowrank=-1)
permute the lags of the UniTensor, inplacely.
Definition UniTensor.hpp:2743
const Bond & bond_(const std::string &label) const
Definition UniTensor.hpp:2266
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:4344
Bond & bond_(const cytnx_uint64 &idx)
Definition UniTensor.hpp:2264
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:2611
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 & reshape_(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor, inplacely.
Definition UniTensor.hpp:3353
UniTensor relabels(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels) const
Definition UniTensor.hpp:2537
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:4242
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:2243
UniTensor & relabel_(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:2556
cytnx_int64 get_index(std::string label) const
Get the index of an desired label string.
Definition UniTensor.hpp:2250
const std::vector< Bond > & bonds() const
Get the bonds of the UniTensor.
Definition UniTensor.hpp:2256
Tensor get_block(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:3057
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:4229
UniTensor & Transpose_()
Take the transpose of the UniTensor, inplacely.
Definition UniTensor.hpp:3954
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:2312
vec2d< cytnx_uint64 > & get_itoi()
Definition UniTensor.hpp:4263
void print_blocks(const bool &full_info=true) const
Print all of the blocks in the UniTensor.
Definition UniTensor.hpp:2787
Scalar::Sproxy item() const
Definition UniTensor.hpp:2128
const vec2d< cytnx_uint64 > & get_itoi() const
get the q-indices on each leg for all the blocks
Definition UniTensor.hpp:4262
std::string device_str() const
Return the device of the UniTensor in 'string' form.
Definition UniTensor.hpp:2195
UniTensor & convert_from(const UniTensor &rhs, const bool &force=false)
Definition UniTensor.hpp:4270
UniTensor relabels(const std::vector< std::string > &new_labels) const
Definition UniTensor.hpp:2372
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:3279
UniTensor relabel(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels) const
Definition UniTensor.hpp:2512
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:1935
UniTensor & Conj_()
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:3927
UniTensor relabel(const std::initializer_list< char * > &new_labels) const
relables all of the labels in UniTensor.
Definition UniTensor.hpp:2382
cytnx_uint64 Nblocks() const
Return the number of blocks in the UniTensor.
Definition UniTensor.hpp:2141
Tensor get_block(const std::vector< cytnx_uint64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:3052
void Save(const char *fname) const
save a UniTensor to file
Bond bond(const cytnx_uint64 &idx) const
Definition UniTensor.hpp:2269
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:4187
Tensor get_block(const std::initializer_list< cytnx_int64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:3042
UniTensor & relabels_(const std::vector< std::string > &new_labels)
Definition UniTensor.hpp:2342
const Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator) const
Get an element at specific location.
Definition UniTensor.hpp:2912
int uten_type() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor.
Definition UniTensor.hpp:2168
Tensor & get_block_(const cytnx_uint64 &idx=0)
Definition UniTensor.hpp:3076
#define cytnx_warning_msg(is_true, format,...)
Definition cytnx_error.hpp:52
#define cytnx_error_msg(is_true, format,...)
Definition cytnx_error.hpp:18
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
Definition Accessor.hpp:12
Device_class Device
data on which devices.
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.
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.
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.
UniTensor Contracts(const std::vector< UniTensor > &TNs, const std::string &order, const bool &optimal)
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.
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.