Cytnx v0.9.6
Loading...
Searching...
No Matches
UniTensor.hpp
Go to the documentation of this file.
1#ifndef _H_UniTensor_
2#define _H_UniTensor_
3
4#include "Type.hpp"
5#include "cytnx_error.hpp"
6#include "Device.hpp"
7#include "Tensor.hpp"
8#include "utils/utils.hpp"
10#include <iostream>
11#include <vector>
12#include <map>
13#include <utility>
14#include <initializer_list>
15#include <fstream>
16#include <algorithm>
17#include "Symmetry.hpp"
18#include "Bond.hpp"
19#include "Generator.hpp"
20#include <random>
21
22#ifdef BACKEND_TORCH
23#else
24 #include "backend/Scalar.hpp"
25
26// namespace cytnx{
27namespace cytnx {
28 using namespace cytnx;
30 class UniTensorType_class {
31 public:
32 enum : int {
33 Void = -99,
34 Dense = 0,
35 Sparse = 1,
36 Block = 2,
37 };
38 std::string getname(const int &ut_type);
39 };
41
57 extern UniTensorType_class UTenType;
58
60 // class DenseUniTensor;
61 // class SparseUniTensor;
62 class UniTensor_base : public intrusive_ptr_base<UniTensor_base> {
63 public:
64 int uten_type_id; // the unitensor type id.
65 bool _is_braket_form;
66 bool _is_tag;
67 bool _is_diag;
68 cytnx_int64 _rowrank;
69 std::string _name;
70 std::vector<std::string> _labels;
71 std::vector<Bond> _bonds;
72
73 bool _update_braket() {
74 if (_bonds.size() == 0) return false;
75
76 if (this->_bonds[0].type() != bondType::BD_REG) {
77 // check:
78 for (unsigned int i = 0; i < this->_bonds.size(); i++) {
79 if (i < this->_rowrank) {
80 if (this->_bonds[i].type() != bondType::BD_KET) return false;
81 } else {
82 if (this->_bonds[i].type() != bondType::BD_BRA) return false;
83 }
84 }
85 return true;
86 } else {
87 return false;
88 }
89 }
90
91 friend class UniTensor; // allow wrapper to access the private elems
92 friend class DenseUniTensor;
93 // friend class SparseUniTensor;
94 friend class BlockUniTensor;
95
96 UniTensor_base()
97 : _is_tag(false),
98 _name(std::string("")),
99 _is_braket_form(false),
100 _rowrank(0),
101 _is_diag(false),
102 uten_type_id(UTenType.Void){};
103
104 // copy&assignment constr., use intrusive_ptr's !!
105 UniTensor_base(const UniTensor_base &rhs);
106 UniTensor_base &operator=(UniTensor_base &rhs);
107
108 cytnx_uint64 rowrank() const { return this->_rowrank; }
109 bool is_diag() const { return this->_is_diag; }
110 const bool &is_braket_form() const { return this->_is_braket_form; }
111 const bool &is_tag() const { return this->_is_tag; }
112 const std::vector<std::string> &labels() const { return this->_labels; }
119 cytnx_int64 get_index(std::string label) const {
120 std::vector<std::string> labels = this->_labels;
121 for (cytnx_uint64 i = 0; i < labels.size(); i++) {
122 if (labels[i] == label) return i;
123 }
124 return -1;
125 }
126 const std::vector<Bond> &bonds() const { return this->_bonds; }
127 std::vector<Bond> &bonds() { return this->_bonds; }
128
129 Bond &bond_(const cytnx_uint64 &idx) {
130 cytnx_error_msg(idx >= this->_bonds.size(), "[ERROR][bond] index %d out of bound, total %d\n",
131 idx, this->_bonds.size());
132 return this->_bonds[idx];
133 }
134
135 Bond &bond_(const std::string &label) {
136 auto res = std::find(this->_labels.begin(), this->_labels.end(), label);
137 cytnx_error_msg(res == this->_labels.end(), "[ERROR] label %s not exists.\n", label.c_str());
138 cytnx_uint64 idx = std::distance(this->_labels.begin(), res);
139
140 return this->bond_(idx);
141 }
142
143 const std::string &name() const { return this->_name; }
144 cytnx_uint64 rank() const { return this->_labels.size(); }
145 void set_name(const std::string &in) { this->_name = in; }
146
157 void set_label(const std::string &oldlabel, const std::string &new_label) {
158 cytnx_int64 idx;
159 auto res = std::find(this->_labels.begin(), this->_labels.end(), oldlabel);
160 cytnx_error_msg(res == this->_labels.end(), "[ERROR] label %s not exists.\n",
161 oldlabel.c_str());
162 idx = std::distance(this->_labels.begin(), res);
163
164 cytnx_error_msg(idx >= this->_labels.size(), "[ERROR] index exceed the rank of UniTensor%s",
165 "\n");
166 // check in:
167 bool is_dup = false;
168 for (cytnx_uint64 i = 0; i < this->_labels.size(); i++) {
169 if (i == idx) continue;
170 if (new_label == this->_labels[i]) {
171 is_dup = true;
172 break;
173 }
174 }
175 cytnx_error_msg(is_dup, "[ERROR] alreay has a label that is the same as the input label%s",
176 "\n");
177 this->_labels[idx] = new_label;
178 }
179 void set_label(const cytnx_int64 &inx, const std::string &new_label) {
180 cytnx_error_msg(inx < 0, "[ERROR] index is negative%s", "\n");
181 cytnx_error_msg(inx >= this->_labels.size(), "[ERROR] index exceed the rank of UniTensor%s",
182 "\n");
183 // check in:
184 bool is_dup = false;
185 for (cytnx_uint64 i = 0; i < this->_labels.size(); i++) {
186 if (i == inx) continue;
187 if (new_label == this->_labels[i]) {
188 is_dup = true;
189 break;
190 }
191 }
192 cytnx_error_msg(is_dup, "[ERROR] alreay has a label that is the same as the input label%s",
193 "\n");
194 this->_labels[inx] = new_label;
195 }
196
197 void set_labels(const std::vector<std::string> &new_labels);
198 void relabels_(const std::vector<std::string> &new_labels); // implemented
199 void relabels_(const std::vector<std::string> &old_labels,
200 const std::vector<std::string> &new_labels); // implemented
201 void relabel_(const std::string &old_label, const std::string &new_label) {
202 this->set_label(old_label, new_label);
203 }
204 void relabel_(const cytnx_int64 &inx, const std::string &new_label) {
205 this->set_label(inx, new_label);
206 }
207
208 int uten_type() { return this->uten_type_id; }
209 std::string uten_type_str() { return UTenType.getname(this->uten_type_id); }
210
212
213 // string labels!
214 virtual void Init(const std::vector<Bond> &bonds,
215 const std::vector<std::string> &in_labels = {},
216 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
217 const int &device = Device.cpu, const bool &is_diag = false,
218 const bool &no_alloc = false, const std::string &name = "");
219
220 virtual void Init_by_Tensor(const Tensor &in, const bool &is_diag = false,
221 const cytnx_int64 &rowrank = -1, const std::string &name = "");
222 virtual std::vector<cytnx_uint64> shape() const;
223 virtual bool is_blockform() const;
224 virtual bool is_contiguous() const;
225 virtual void to_(const int &device);
226 virtual boost::intrusive_ptr<UniTensor_base> to(const int &device);
227 virtual boost::intrusive_ptr<UniTensor_base> clone() const;
228 virtual unsigned int dtype() const;
229 virtual int device() const;
230 virtual std::string dtype_str() const;
231 virtual std::string device_str() const;
232 virtual void set_rowrank_(const cytnx_uint64 &new_rowrank);
233 virtual boost::intrusive_ptr<UniTensor_base> set_rowrank(const cytnx_uint64 &new_rowrank) const;
234
235 virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
236 const cytnx_int64 &rowrank = -1);
237 virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
238 const cytnx_int64 &rowrank = -1);
239 // virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
240 // const cytnx_int64 &rowrank = -1);
241
242 virtual void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
243 virtual void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
244
245 // virtual void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank =
246 // -1);
247 virtual boost::intrusive_ptr<UniTensor_base> contiguous_();
248 virtual boost::intrusive_ptr<UniTensor_base> contiguous();
249 virtual void print_diagram(const bool &bond_info = false);
250 virtual void print_blocks(const bool &full_info = true) const;
251 virtual void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
252
253 virtual boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const;
254
255 virtual cytnx_uint64 Nblocks() const { return 0; };
256 virtual Tensor get_block(const cytnx_uint64 &idx = 0) const; // return a copy of block
257 virtual Tensor get_block(const std::vector<cytnx_int64> &qnum,
258 const bool &force) const; // return a copy of block
259
260 virtual const Tensor &get_block_(const cytnx_uint64 &idx = 0)
261 const; // return a share view of block, this only work for non-symm tensor.
262 virtual const Tensor &get_block_(const std::vector<cytnx_int64> &qnum,
263 const bool &force) const; // return a copy of block
264 virtual Tensor &get_block_(const cytnx_uint64 &idx = 0); // return a share view of block, this
265 // only work for non-symm tensor.
266 virtual Tensor &get_block_(const std::vector<cytnx_int64> &qnum,
267 const bool &force); // return a copy of block
268 virtual bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const;
269
270 virtual std::vector<Tensor> get_blocks() const;
271 virtual const std::vector<Tensor> &get_blocks_(const bool &) const;
272 virtual std::vector<Tensor> &get_blocks_(const bool &);
273
274 virtual void put_block(const Tensor &in, const cytnx_uint64 &idx = 0);
275 virtual void put_block_(Tensor &in, const cytnx_uint64 &idx = 0);
276 virtual void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum,
277 const bool &force);
278 virtual void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force);
279
280 // this will only work on non-symm tensor (DenseUniTensor)
281 virtual boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors);
282
283 // this will only work on non-symm tensor (DenseUniTensor)
284 virtual void set(const std::vector<Accessor> &accessors, const Tensor &rhs);
285
286 virtual void reshape_(const std::vector<cytnx_int64> &new_shape,
287 const cytnx_uint64 &rowrank = 0);
288 virtual boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
289 const cytnx_uint64 &rowrank = 0);
290 virtual boost::intrusive_ptr<UniTensor_base> to_dense();
291 virtual void to_dense_();
292 virtual void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
293 const bool &by_label);
294 virtual void combineBonds(const std::vector<std::string> &indicators,
295 const bool &force = false);
296 virtual void combineBonds(const std::vector<cytnx_int64> &indicators,
297 const bool &force = false);
298 virtual boost::intrusive_ptr<UniTensor_base> contract(
299 const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &mv_elem_self = false,
300 const bool &mv_elem_rhs = false);
301 virtual std::vector<Bond> getTotalQnums(const bool &physical = false);
302 virtual std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const;
303 virtual void Trace_(const std::string &a, const std::string &b);
304 virtual void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
305
306 virtual boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b);
307 virtual boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b);
308
309 virtual boost::intrusive_ptr<UniTensor_base> relabels(
310 const std::vector<std::string> &new_labels);
311
312 virtual boost::intrusive_ptr<UniTensor_base> relabels(
313 const std::vector<std::string> &old_labels, const std::vector<std::string> &new_labels);
314
315 virtual boost::intrusive_ptr<UniTensor_base> relabel(const std::string &old_label,
316 const std::string &new_label);
317
318 virtual boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
319 const std::string &new_label);
320
321 virtual std::vector<Symmetry> syms() const;
322
323 // arithmetic
324 virtual void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
325 virtual void Add_(const Scalar &rhs);
326
327 virtual void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
328 virtual void Mul_(const Scalar &rhs);
329
330 virtual void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
331 virtual void Sub_(const Scalar &rhs);
332 virtual void lSub_(const Scalar &lhs);
333
334 virtual void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
335 virtual void Div_(const Scalar &rhs);
336 virtual void lDiv_(const Scalar &lhs);
337
338 virtual Tensor Norm() const;
339 virtual boost::intrusive_ptr<UniTensor_base> normalize();
340 virtual void normalize_();
341
342 virtual boost::intrusive_ptr<UniTensor_base> Conj();
343 virtual void Conj_();
344
345 virtual boost::intrusive_ptr<UniTensor_base> Transpose();
346 virtual void Transpose_();
347
348 virtual boost::intrusive_ptr<UniTensor_base> Dagger();
349 virtual void Dagger_();
350
351 virtual void tag();
352
353 virtual void truncate_(const std::string &bond_idx, const cytnx_uint64 &dim);
354 virtual void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim);
355
356 virtual bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
357
358 // this a workaround, as virtual function cannot template.
359 virtual Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator);
360 virtual const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const;
361
362 virtual cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
363 const cytnx_complex128 &aux);
364 virtual cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
365 const cytnx_complex64 &aux);
366 virtual cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
367 const cytnx_double &aux);
368 virtual cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
369 const cytnx_float &aux);
370 virtual cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
371 const cytnx_uint64 &aux);
372 virtual cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
373 const cytnx_int64 &aux);
374 virtual cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
375 const cytnx_uint32 &aux);
376 virtual cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
377 const cytnx_int32 &aux);
378 virtual cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
379 const cytnx_uint16 &aux);
380 virtual cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
381 const cytnx_int16 &aux);
382
383 virtual const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
384 const cytnx_complex128 &aux) const;
385 virtual const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
386 const cytnx_complex64 &aux) const;
387 virtual const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
388 const cytnx_double &aux) const;
389 virtual const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
390 const cytnx_float &aux) const;
391 virtual const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
392 const cytnx_uint64 &aux) const;
393 virtual const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
394 const cytnx_int64 &aux) const;
395 virtual const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
396 const cytnx_uint32 &aux) const;
397 virtual const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
398 const cytnx_int32 &aux) const;
399 virtual const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
400 const cytnx_uint16 &aux) const;
401 virtual const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
402 const cytnx_int16 &aux) const;
403
404 virtual void from_(const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &force);
405
406 virtual void group_basis_();
407 virtual const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const;
408 virtual std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx);
409 virtual const vec2d<cytnx_uint64> &get_itoi() const;
410 virtual vec2d<cytnx_uint64> &get_itoi();
411
412 virtual void _save_dispatch(std::fstream &f) const;
413 virtual void _load_dispatch(std::fstream &f);
414
415 virtual ~UniTensor_base(){};
416 };
418
419 //======================================================================
421 class DenseUniTensor : public UniTensor_base {
422 protected:
423 public:
424 Tensor _block;
425 std::vector<Tensor> _interface_block; // this is serves as interface for get_blocks_();
426 DenseUniTensor *clone_meta() const {
427 DenseUniTensor *tmp = new DenseUniTensor();
428 tmp->_bonds = vec_clone(this->_bonds);
429 tmp->_labels = this->_labels;
430 tmp->_is_braket_form = this->_is_braket_form;
431 tmp->_rowrank = this->_rowrank;
432 tmp->_is_diag = this->_is_diag;
433 tmp->_name = this->_name;
434 tmp->_is_tag = this->_is_tag;
435 return tmp;
436 }
437 //------------------------------------------
438
439 DenseUniTensor() { this->uten_type_id = UTenType.Dense; };
440 friend class UniTensor; // allow wrapper to access the private elems
441 // virtual functions
442
443 // void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels = {},
444 // const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
445 // const int &device = Device.cpu, const bool &is_diag = false,
446 // const bool &no_alloc = false);
447
448 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
449 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
450 const int &device = Device.cpu, const bool &is_diag = false,
451 const bool &no_alloc = false, const std::string &name = "");
452 // this only work for non-symm tensor
453 void Init_by_Tensor(const Tensor &in_tensor, const bool &is_diag = false,
454 const cytnx_int64 &rowrank = -1, const std::string &name = "");
455 std::vector<cytnx_uint64> shape() const {
456 if (this->_is_diag) {
457 std::vector<cytnx_uint64> shape = this->_block.shape();
458 shape.push_back(shape[0]);
459 return shape;
460 } else {
461 return this->_block.shape();
462 }
463 }
464 bool is_blockform() const { return false; }
465 void to_(const int &device) { this->_block.to_(device); }
466 boost::intrusive_ptr<UniTensor_base> to(const int &device) {
467 if (this->device() == device) {
468 std::vector<Tensor> _interface_block; // this is serves as interface for get_blocks_();
469 return this;
470 } else {
471 boost::intrusive_ptr<UniTensor_base> out = this->clone();
472 out->to_(device);
473 return out;
474 }
475 }
476 void set_rowrank_(const cytnx_uint64 &new_rowrank) {
477 cytnx_error_msg(new_rowrank > this->_labels.size(),
478 "[ERROR] rowrank cannot exceed the rank of UniTensor.%s", "\n");
479 if (this->is_diag()) {
480 cytnx_error_msg(new_rowrank != 1, "[ERROR] rowrank should be [==1] when is_diag =true!.%s",
481 "\n");
482 }
483
484 this->_rowrank = new_rowrank;
485 }
486
487 boost::intrusive_ptr<UniTensor_base> set_rowrank(const cytnx_uint64 &new_rowrank) const {
488 DenseUniTensor *out_raw = this->clone_meta();
489 out_raw->_block = this->_block;
490 out_raw->set_rowrank_(new_rowrank);
491 boost::intrusive_ptr<UniTensor_base> out(out_raw);
492 return out;
493 }
494
495 boost::intrusive_ptr<UniTensor_base> clone() const {
496 DenseUniTensor *tmp = this->clone_meta();
497 tmp->_block = this->_block.clone();
498 boost::intrusive_ptr<UniTensor_base> out(tmp);
499 return out;
500 };
501 bool is_contiguous() const { return this->_block.is_contiguous(); }
502 unsigned int dtype() const { return this->_block.dtype(); }
503 int device() const { return this->_block.device(); }
504 std::string dtype_str() const { return Type.getname(this->_block.dtype()); }
505 std::string device_str() const { return Device.getname(this->_block.device()); }
515 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
516 const cytnx_int64 &rowrank = -1);
517 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
518 const cytnx_int64 &rowrank = -1);
519
528 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
529 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
530
531 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &new_labels);
532
533 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &old_labels,
534 const std::vector<std::string> &new_labels);
535
546 boost::intrusive_ptr<UniTensor_base> relabel(const std::string &old_label,
547 const std::string &new_label);
548 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
549 const std::string &new_label);
550
551 boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const {
552 DenseUniTensor *tmp = this->clone_meta();
553 tmp->_block = this->_block.astype(dtype);
554 boost::intrusive_ptr<UniTensor_base> out(tmp);
555 return tmp;
556 }
557
558 std::vector<Symmetry> syms() const {
559 cytnx_error_msg(true, "[ERROR][DenseUniTensor] dense unitensor does not have symmetry.%s",
560 "\n");
561 return std::vector<Symmetry>();
562 }
563
564 boost::intrusive_ptr<UniTensor_base> contiguous_() {
565 this->_block.contiguous_();
566 return boost::intrusive_ptr<UniTensor_base>(this);
567 }
568 boost::intrusive_ptr<UniTensor_base> contiguous() {
569 // if contiguous then return self!
570 if (this->is_contiguous()) {
571 boost::intrusive_ptr<UniTensor_base> out(this);
572 return out;
573 } else {
574 DenseUniTensor *tmp = this->clone_meta();
575 tmp->_block = this->_block.contiguous();
576 boost::intrusive_ptr<UniTensor_base> out(tmp);
577 return out;
578 }
579 }
580 void print_diagram(const bool &bond_info = false);
581 void print_blocks(const bool &full_info = true) const;
582 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
583 Tensor get_block(const cytnx_uint64 &idx = 0) const { return this->_block.clone(); }
584
585 Tensor get_block(const std::vector<cytnx_int64> &qnum, const bool &force) const {
587 true, "[ERROR][DenseUniTensor] try to get_block() using qnum on a non-symmetry UniTensor%s",
588 "\n");
589 return Tensor();
590 }
591 // return a share view of block, this only work for non-symm tensor.
592 const Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force) const {
594 true,
595 "[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
596 "\n");
597 return this->_block;
598 }
599 Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force) {
601 true,
602 "[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
603 "\n");
604 return this->_block;
605 }
606
607 // return a share view of block, this only work for non-symm tensor.
608 Tensor &get_block_(const cytnx_uint64 &idx = 0) { return this->_block; }
609 // return a share view of block, this only work for non-symm tensor.
610 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const { return this->_block; }
611
612 cytnx_uint64 Nblocks() const { return 1; };
613 std::vector<Tensor> get_blocks() const {
614 std::vector<Tensor> out;
616 true, "[ERROR][DenseUniTensor] cannot use get_blocks(), use get_block() instead!%s", "\n");
617 return out; // this will not share memory!!
618 }
619 const std::vector<Tensor> &get_blocks_(const bool &silent = false) const {
621 true, "[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s",
622 "\n");
623 return this->_interface_block; // this will not share memory!!
624 }
625 std::vector<Tensor> &get_blocks_(const bool &silent = false) {
627 true, "[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s",
628 "\n");
629 return this->_interface_block; // this will not share memory!!
630 }
631
632 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
633 // We don't check the dtype for DenseUniTensor, since it'll be more convinent to change
634 // DenseUniTensor's dtype
635
636 // cytnx_error_msg(in.dtype() != this->dtype(),
637 // "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not
638 // match.%s",
639 // "\n");
640 cytnx_error_msg(in.device() != this->device(),
641 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
642 "match.%s",
643 "\n");
644 // We shouldn't check the contiguous
645 // cytnx_error_msg(!in.contiguous());
646 if (this->is_diag()) {
648 in.shape() != this->_block.shape(),
649 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
650 this->_block = in.clone();
651 } else {
653 in.shape() != this->shape(),
654 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
655 this->_block = in.clone();
656 }
657 }
658 // share view of the block
659 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) {
660 // We don't check the dtype for DenseUniTensor, since it'll be more convinent to change
661 // DenseUniTensor's dtype
662
663 // cytnx_error_msg(in.dtype() != this->dtype(),
664 // "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not
665 // match.%s",
666 // "\n");
667 cytnx_error_msg(in.device() != this->device(),
668 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
669 "match.%s",
670 "\n");
671 // We shouldn't check the contiguous
672 // cytnx_error_msg(!in.contiguous());
673 if (this->is_diag()) {
675 in.shape() != this->_block.shape(),
676 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
677 this->_block = in;
678 } else {
680 in.shape() != this->shape(),
681 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s", "\n");
682 this->_block = in;
683 }
684 }
685
686 void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force) {
688 true, "[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
689 "\n");
690 }
691 void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum, const bool &force) {
693 true, "[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
694 "\n");
695 }
696 // this will only work on non-symm tensor (DenseUniTensor)
697 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors) {
698 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
699 out->Init_by_Tensor(this->_block.get(accessors), false, 0); // wrapping around.
700 return out;
701 }
702 // this will only work on non-symm tensor (DenseUniTensor)
703 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
704 this->_block.set(accessors, rhs);
705 }
706
707 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0);
708 boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
709 const cytnx_uint64 &rowrank = 0);
710 boost::intrusive_ptr<UniTensor_base> to_dense();
711 void to_dense_();
721 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
722 const bool &by_label);
723 void combineBonds(const std::vector<std::string> &indicators, const bool &force = true);
724 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = true);
725 boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs,
726 const bool &mv_elem_self = false,
727 const bool &mv_elem_rhs = false);
728 std::vector<Bond> getTotalQnums(const bool &physical = false) {
729 cytnx_error_msg(true, "[ERROR][DenseUniTensor] %s",
730 "getTotalQnums can only operate on UniTensor with symmetry.\n");
731 return std::vector<Bond>();
732 }
733
734 std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const {
735 cytnx_error_msg(true, "[ERROR][DenseUniTensor] %s",
736 "get_blocks_qnums can only operate on UniTensor with symmetry.\n");
737 return std::vector<std::vector<cytnx_int64>>();
738 }
739
740 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const {
741 if (rhs->uten_type() != UTenType.Dense) return false;
742
743 return this->get_block_().same_data(rhs->get_block_());
744 }
745
746 ~DenseUniTensor(){};
747
748 // arithmetic
749 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
750 void Add_(const Scalar &rhs);
751
752 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
753 void Mul_(const Scalar &rhs);
754
755 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
756 void Sub_(const Scalar &rhs);
757 void lSub_(const Scalar &lhs);
758
759 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
760 void Div_(const Scalar &rhs);
761 void lDiv_(const Scalar &lhs);
762
763 void Conj_() { this->_block.Conj_(); };
764
765 boost::intrusive_ptr<UniTensor_base> Conj() {
766 boost::intrusive_ptr<UniTensor_base> out = this->clone();
767 out->Conj_();
768 return out;
769 }
770
771 boost::intrusive_ptr<UniTensor_base> Transpose() {
772 boost::intrusive_ptr<UniTensor_base> out = this->clone();
773 out->Transpose_();
774 return out;
775 }
776 void Transpose_();
777
778 boost::intrusive_ptr<UniTensor_base> normalize() {
779 boost::intrusive_ptr<UniTensor_base> out = this->clone();
780 out->normalize_();
781 return out;
782 }
783 void normalize_();
784
785 boost::intrusive_ptr<UniTensor_base> Dagger() {
786 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
787 out->Transpose_();
788 return out;
789 }
790 void Dagger_() {
791 this->Conj_();
792 this->Transpose_();
793 }
803 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
804 void Trace_(const std::string &a, const std::string &b);
805 boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b) {
806 boost::intrusive_ptr<UniTensor_base> out = this->clone();
807 out->Trace_(a, b);
808 return out;
809 }
810 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b) {
811 boost::intrusive_ptr<UniTensor_base> out = this->clone();
812 out->Trace_(a, b);
813 return out;
814 }
815
816 Tensor Norm() const;
817
818 const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const {
820 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
821 "\n");
822 return Scalar::Sproxy();
823 }
824 const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
825 const cytnx_complex128 &aux) const {
827 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
828 "\n");
829 return cytnx_complex128(0, 0);
830 }
831 const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
832 const cytnx_complex64 &aux) const {
834 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
835 "\n");
836 return cytnx_complex64(0, 0);
837 }
838 const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
839 const cytnx_double &aux) const {
841 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
842 "\n");
843 return 0;
844 }
845 const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
846 const cytnx_float &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_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
853 const cytnx_uint64 &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_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
860 const cytnx_int64 &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_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
867 const cytnx_uint32 &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_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
874 const cytnx_int32 &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_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
881 const cytnx_uint16 &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_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
888 const cytnx_int16 &aux) const {
890 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
891 "\n");
892 return 0;
893 }
894
895 Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) {
897 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
898 "\n");
899 return Scalar::Sproxy();
900 }
901 cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
902 const cytnx_complex128 &aux) {
904 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
905 "\n");
906 return *(cytnx_complex128 *)nullptr;
907 }
908 cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
909 const cytnx_complex64 &aux) {
911 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
912 "\n");
913 return *(cytnx_complex64 *)nullptr;
914 }
915 cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux) {
917 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
918 "\n");
919 return *(cytnx_double *)nullptr;
920 }
921 cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux) {
923 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
924 "\n");
925 return *(cytnx_float *)nullptr;
926 }
927 cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux) {
929 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
930 "\n");
931 return *(cytnx_uint64 *)nullptr;
932 }
933 cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux) {
935 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
936 "\n");
937 return *(cytnx_int64 *)nullptr;
938 }
939 cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux) {
941 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
942 "\n");
943 return *(cytnx_uint32 *)nullptr;
944 }
945 cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux) {
947 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
948 "\n");
949 return *(cytnx_int32 *)nullptr;
950 }
951 cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux) {
953 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
954 "\n");
955 return *(cytnx_uint16 *)nullptr;
956 }
957 cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux) {
959 true, "[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
960 "\n");
961 return *(cytnx_int16 *)nullptr;
962 }
963
964 bool elem_exists(const std::vector<cytnx_uint64> &locator) const {
966 true, "[ERROR][DenseUniTensor] elem_exists can only be used on UniTensor with Symmetry.%s",
967 "\n");
968 }
969 void tag() {
970 if (!this->is_tag()) {
971 for (int i = 0; i < this->_rowrank; i++) {
972 this->_bonds[i].set_type(BD_KET);
973 }
974 for (int i = this->_rowrank; i < this->_bonds.size(); i++) {
975 this->_bonds[i].set_type(BD_BRA);
976 }
977 this->_is_tag = true;
978 this->_is_braket_form = this->_update_braket();
979 }
980 }
990 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim);
991 void truncate_(const std::string &bond_idx, const cytnx_uint64 &dim);
992
993 void from_(const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &force);
994
995 void group_basis_() {
996 cytnx_warning_msg(true, "[WARNING] group basis will not have any effect on DensUniTensor.%s",
997 "\n");
998 }
999
1000 void _save_dispatch(std::fstream &f) const;
1001 void _load_dispatch(std::fstream &f);
1002
1003 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
1004 cytnx_error_msg(true, "[ERROR] get_qindices can only be unsed on UniTensor with Symmetry.%s",
1005 "\n");
1006 }
1007 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
1008 cytnx_error_msg(true, "[ERROR] get_qindices can only be unsed on UniTensor with Symmetry.%s",
1009 "\n");
1010 }
1011
1012 const vec2d<cytnx_uint64> &get_itoi() const {
1013 cytnx_error_msg(true, "[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s",
1014 "\n");
1015 }
1016 vec2d<cytnx_uint64> &get_itoi() {
1017 cytnx_error_msg(true, "[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s",
1018 "\n");
1019 }
1020
1021 // end virtual function
1022 };
1024
1025 //======================================================================
1027 class BlockUniTensor : public UniTensor_base {
1028 protected:
1029 public:
1030 std::vector<std::vector<cytnx_uint64>> _inner_to_outer_idx;
1031 std::vector<Tensor> _blocks;
1032 Tensor NullRefTensor; // this returns when access block is not exists!
1033
1034 // given an index list [loc], get qnums from this->_bonds[loc] and return the combined qnums
1035 // calculated from Symm object! this assume 1. symmetry are the same for each bond!
1036 // 2. total_qns are feeded with size len(symmetry)
1037 void _fx_get_total_fluxs(std::vector<cytnx_uint64> &loc, const std::vector<Symmetry> &syms,
1038 std::vector<cytnx_int64> &total_qns) {
1039 memset(&total_qns[0], 0, sizeof(cytnx_int64) * total_qns.size());
1040
1041 for (cytnx_int32 i = 0; i < syms.size(); i++) {
1042 if (this->_bonds[0].type() == BD_BRA)
1043 total_qns[i] = syms[0].reverse_rule(this->_bonds[0]._impl->_qnums[loc[0]][i]);
1044 else
1045 total_qns[i] = this->_bonds[0]._impl->_qnums[loc[0]][i];
1046
1047 for (auto j = 1; j < loc.size(); j++) {
1048 if (this->_bonds[j].type() == BD_BRA)
1049 total_qns[i] = syms[i].combine_rule(
1050 total_qns[i], syms[i].reverse_rule(this->_bonds[j]._impl->_qnums[loc[j]][i]));
1051 else {
1052 total_qns[i] =
1053 syms[i].combine_rule(total_qns[i], this->_bonds[j]._impl->_qnums[loc[j]][i]);
1054 }
1055 }
1056 }
1057 }
1058
1059 void _fx_locate_elem(cytnx_int64 &bidx, std::vector<cytnx_uint64> &loc_in_T,
1060 const std::vector<cytnx_uint64> &locator) const;
1061
1062 // internal function, grouping all duplicate qnums in all bonds
1063 void _fx_group_duplicates(const std::vector<cytnx_uint64> &dup_bond_idxs,
1064 const std::vector<std::vector<cytnx_uint64>> &idx_mappers);
1065
1066 void set_meta(BlockUniTensor *tmp, const bool &inner, const bool &outer) const {
1067 // outer meta
1068 if (outer) {
1069 tmp->_bonds = vec_clone(this->_bonds);
1070 tmp->_labels = this->_labels;
1071 tmp->_is_braket_form = this->_is_braket_form;
1072 tmp->_rowrank = this->_rowrank;
1073 tmp->_name = this->_name;
1074 }
1075
1076 tmp->_is_diag = this->_is_diag;
1077
1078 // inner meta
1079 if (inner) {
1080 tmp->_inner_to_outer_idx = this->_inner_to_outer_idx;
1081 }
1082 }
1083
1084 BlockUniTensor *clone_meta(const bool &inner, const bool &outer) const {
1085 BlockUniTensor *tmp = new BlockUniTensor();
1086 this->set_meta(tmp, inner, outer);
1087 return tmp;
1088 };
1089
1090 friend class UniTensor;
1091 BlockUniTensor() {
1092 this->uten_type_id = UTenType.Block;
1093 this->_is_tag = true;
1094 }
1095
1096 // virtual functions:
1097 // void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels = {},
1098 // const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1099 // const int &device = Device.cpu, const bool &is_diag = false,
1100 // const bool &no_alloc = false);
1101
1102 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1103 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1104 const int &device = Device.cpu, const bool &is_diag = false,
1105 const bool &no_alloc = false, const std::string &name = "");
1106
1107 void Init_by_Tensor(const Tensor &in_tensor, const bool &is_diag = false,
1108 const cytnx_int64 &rowrank = -1, const std::string &name = "") {
1110 true, "[ERROR][BlockUniTensor] cannot use Init_by_tensor() on a BlockUniTensor.%s", "\n");
1111 }
1112
1113 std::vector<cytnx_uint64> shape() const {
1114 std::vector<cytnx_uint64> out(this->_bonds.size());
1115 for (cytnx_uint64 i = 0; i < out.size(); i++) {
1116 out[i] = this->_bonds[i].dim();
1117 }
1118 return out;
1119 }
1120
1121 bool is_blockform() const { return true; }
1122 bool is_contiguous() const {
1123 bool out = true;
1124 for (int i = 0; i < this->_blocks.size(); i++) {
1125 out &= this->_blocks[i].is_contiguous();
1126 }
1127 return out;
1128 };
1129
1130 cytnx_uint64 Nblocks() const { return this->_blocks.size(); };
1131
1132 void to_(const int &device) {
1133 for (cytnx_uint64 i = 0; i < this->_blocks.size(); i++) {
1134 this->_blocks[i].to_(device);
1135 }
1136 };
1137
1138 boost::intrusive_ptr<UniTensor_base> to(const int &device) {
1139 if (this->device() == device) {
1140 return this;
1141 } else {
1142 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1143 out->to_(device);
1144 return out;
1145 }
1146 };
1147
1148 boost::intrusive_ptr<UniTensor_base> clone() const {
1149 BlockUniTensor *tmp = this->clone_meta(true, true);
1150 tmp->_blocks = vec_clone(this->_blocks);
1151 boost::intrusive_ptr<UniTensor_base> out(tmp);
1152 return out;
1153 };
1154
1155 unsigned int dtype() const {
1156 #ifdef UNI_DEBUG
1157 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1158 "\n");
1159 #endif
1160 return this->_blocks[0].dtype();
1161 };
1162 int device() const {
1163 #ifdef UNI_DEBUG
1164 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1165 "\n");
1166 #endif
1167 return this->_blocks[0].device();
1168 };
1169 std::string dtype_str() const {
1170 #ifdef UNI_DEBUG
1171 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1172 "\n");
1173 #endif
1174 return this->_blocks[0].dtype_str();
1175 };
1176 std::string device_str() const {
1177 #ifdef UNI_DEBUG
1178 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1179 "\n");
1180 #endif
1181 return this->_blocks[0].device_str();
1182 };
1183
1184 Tensor get_block(const cytnx_uint64 &idx = 0) const {
1185 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1186 "\n");
1187 return this->_blocks[idx].clone();
1188 };
1189
1190 // this one for Block will return the indicies!!
1191 Tensor get_block(const std::vector<cytnx_int64> &indices, const bool &force_return) const {
1192 cytnx_error_msg(indices.size() != this->rank(),
1193 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1194 "Tensor rank (number of legs).%s",
1195 "\n");
1196
1197 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1198
1199 // find if the indices specify exists!
1200 cytnx_int64 b = -1;
1201 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1202 if (inds == this->_inner_to_outer_idx[i]) {
1203 b = i;
1204 break;
1205 }
1206 }
1207
1208 if (b < 0) {
1209 if (force_return) {
1210 return NullRefTensor;
1211 } else {
1212 cytnx_error_msg(true,
1213 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1214 "force_return=false, so "
1215 "error throws. \n If you want to return an empty block without "
1216 "error when block is "
1217 "not avaliable, set force_return=True.%s",
1218 "\n");
1219 }
1220 } else {
1221 return this->_blocks[b].clone();
1222 }
1223 }
1224
1225 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const {
1226 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1227 "\n");
1228 return this->_blocks[idx];
1229 };
1230
1231 Tensor &get_block_(const cytnx_uint64 &idx = 0) {
1232 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1233 "\n");
1234 return this->_blocks[idx];
1235 };
1236
1237 const Tensor &get_block_(const std::vector<cytnx_int64> &indices,
1238 const bool &force_return) const {
1239 cytnx_error_msg(indices.size() != this->rank(),
1240 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1241 "Tensor rank (number of legs).%s",
1242 "\n");
1243
1244 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1245
1246 // find if the indices specify exists!
1247 cytnx_int64 b = -1;
1248 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1249 if (inds == this->_inner_to_outer_idx[i]) {
1250 b = i;
1251 break;
1252 }
1253 }
1254
1255 if (b < 0) {
1256 if (force_return) {
1257 return this->NullRefTensor;
1258 } else {
1259 cytnx_error_msg(true,
1260 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1261 "force_return=false, so "
1262 "error throws. \n If you want to return an empty block without "
1263 "error when block is "
1264 "not avaliable, set force_return=True.%s",
1265 "\n");
1266 }
1267 } else {
1268 return this->_blocks[b];
1269 }
1270 }
1271
1272 Tensor &get_block_(const std::vector<cytnx_int64> &indices, const bool &force_return) {
1273 cytnx_error_msg(indices.size() != this->rank(),
1274 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1275 "Tensor rank (number of legs).%s",
1276 "\n");
1277
1278 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1279
1280 // find if the indices specify exists!
1281 cytnx_int64 b = -1;
1282 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1283 if (inds == this->_inner_to_outer_idx[i]) {
1284 b = i;
1285 break;
1286 }
1287 }
1288
1289 if (b < 0) {
1290 if (force_return) {
1291 return this->NullRefTensor;
1292 } else {
1293 cytnx_error_msg(true,
1294 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1295 "force_return=false, so "
1296 "error throws. \n If you want to return an empty block without "
1297 "error when block is "
1298 "not avaliable, set force_return=True.%s",
1299 "\n");
1300 }
1301 } else {
1302 return this->_blocks[b];
1303 }
1304 }
1305
1306 std::vector<Tensor> get_blocks() const { return vec_clone(this->_blocks); }
1307 const std::vector<Tensor> &get_blocks_(const bool &) const { return this->_blocks; }
1308 std::vector<Tensor> &get_blocks_(const bool &) { return this->_blocks; }
1309
1310 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const {
1311 if (rhs->uten_type() != UTenType.Block) return false;
1312 if (rhs->get_blocks_(1).size() != this->get_blocks_(1).size()) return false;
1313
1314 for (int i = 0; i < rhs->get_blocks_(1).size(); i++)
1315 if (this->get_blocks_(1)[i].same_data(rhs->get_blocks_(1)[i]) == false) return false;
1316
1317 return true;
1318 }
1319
1320 void set_rowrank_(const cytnx_uint64 &new_rowrank) {
1321 cytnx_error_msg(new_rowrank > this->rank(),
1322 "[ERROR][BlockUniTensor] rowrank should be [>=0] and [<=UniTensor.rank].%s",
1323 "\n");
1324 if (this->is_diag()) {
1325 cytnx_error_msg(new_rowrank != 1,
1326 "[ERROR][BlockUniTensor] rowrank should be [==1] when is_diag =true!.%s",
1327 "\n");
1328 }
1329 this->_rowrank = new_rowrank;
1330 this->_is_braket_form = this->_update_braket();
1331 }
1332
1333 boost::intrusive_ptr<UniTensor_base> set_rowrank(const cytnx_uint64 &new_rowrank) const {
1334 BlockUniTensor *tmp = this->clone_meta(true, true);
1335 tmp->_blocks = this->_blocks;
1336 tmp->set_rowrank_(new_rowrank);
1337 boost::intrusive_ptr<UniTensor_base> out(tmp);
1338 return out;
1339 }
1340
1341 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
1342 const cytnx_int64 &rowrank = -1);
1343 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
1344 const cytnx_int64 &rowrank = -1);
1345
1346 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
1347 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
1348
1349 boost::intrusive_ptr<UniTensor_base> contiguous_() {
1350 for (unsigned int b = 0; b < this->_blocks.size(); b++) this->_blocks[b].contiguous_();
1351 return boost::intrusive_ptr<UniTensor_base>(this);
1352 }
1353
1354 boost::intrusive_ptr<UniTensor_base> contiguous();
1355
1356 void print_diagram(const bool &bond_info = false);
1357 void print_blocks(const bool &full_info = true) const;
1358 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
1359
1360 boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs,
1361 const bool &mv_elem_self = false,
1362 const bool &mv_elem_rhs = false);
1363
1364 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &new_labels);
1365
1366 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &old_labels,
1367 const std::vector<std::string> &new_labels);
1368
1369 boost::intrusive_ptr<UniTensor_base> relabel(const std::string &old_label,
1370 const std::string &new_label);
1371 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
1372 const std::string &new_label);
1373
1374 std::vector<Symmetry> syms() const;
1375
1376 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
1377 cytnx_error_msg(true, "[ERROR] cannot reshape a UniTensor with symmetry.%s", "\n");
1378 }
1379 boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
1380 const cytnx_uint64 &rowrank = 0) {
1381 cytnx_error_msg(true, "[ERROR] cannot reshape a UniTensor with symmetry.%s", "\n");
1382 return nullptr;
1383 }
1384
1385 boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const {
1386 BlockUniTensor *tmp = this->clone_meta(true, true);
1387 tmp->_blocks.resize(this->_blocks.size());
1388 for (cytnx_int64 blk = 0; blk < this->_blocks.size(); blk++) {
1389 tmp->_blocks[blk] = this->_blocks[blk].astype(dtype);
1390 }
1391 boost::intrusive_ptr<UniTensor_base> out(tmp);
1392 return out;
1393 };
1394
1395 // this will only work on non-symm tensor (DenseUniTensor)
1396 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors) {
1398 true,
1399 "[ERROR][BlockUniTensor][get] cannot use get on a UniTensor with "
1400 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
1401 "\n");
1402 return nullptr;
1403 }
1404
1405 // this will only work on non-symm tensor (DenseUniTensor)
1406 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
1408 true,
1409 "[ERROR][BlockUniTensor][get] cannot use get on a UniTensor with "
1410 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
1411 "\n");
1412 }
1413
1414 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
1415 cytnx_error_msg(in.dtype() != this->dtype(),
1416 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
1417 "\n");
1418 cytnx_error_msg(in.device() != this->device(),
1419 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
1420 "match.%s",
1421 "\n");
1422 // We shouldn't check the contiguous
1423 // cytnx_error_msg(!in.contiguous());
1424 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1425 "\n");
1426 cytnx_error_msg(in.shape() != this->_blocks[idx].shape(),
1427 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1428 "of block @ idx=%d\n",
1429 idx);
1430
1431 this->_blocks[idx] = in.clone();
1432 }
1433 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) {
1434 cytnx_error_msg(in.dtype() != this->dtype(),
1435 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
1436 "\n");
1437 cytnx_error_msg(in.device() != this->device(),
1438 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
1439 "match.%s",
1440 "\n");
1441 // We shouldn't check the contiguous
1442 // cytnx_error_msg(!in.contiguous());
1443 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1444 "\n");
1445 cytnx_error_msg(in.shape() != this->_blocks[idx].shape(),
1446 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1447 "of block @ idx=%d\n",
1448 idx);
1449
1450 this->_blocks[idx] = in;
1451 }
1452 void put_block(const Tensor &in, const std::vector<cytnx_int64> &indices, const bool &check) {
1453 cytnx_error_msg(in.dtype() != this->dtype(),
1454 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
1455 "\n");
1456 cytnx_error_msg(in.device() != this->device(),
1457 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
1458 "match.%s",
1459 "\n");
1460 // We shouldn't check the contiguous
1461 // cytnx_error_msg(!in.contiguous());
1462 cytnx_error_msg(indices.size() != this->rank(),
1463 "[ERROR][put_block][BlockUniTensor] len(indices) must be the same as the "
1464 "Tensor rank (number of legs).%s",
1465 "\n");
1466
1467 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1468
1469 // find if the indices specify exists!
1470 cytnx_int64 b = -1;
1471 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1472 if (inds == this->_inner_to_outer_idx[i]) {
1473 b = i;
1474 break;
1475 }
1476 }
1477
1478 if (b < 0) {
1479 if (check) {
1480 cytnx_error_msg(true,
1481 "[ERROR][put_block][BlockUniTensor] no avaliable block exists, "
1482 "check=true, so error throws. \n If you want without error when block "
1483 "is not avaliable, set check=false.%s",
1484 "\n");
1485 }
1486 } else {
1488 in.shape() != this->_blocks[b].shape(),
1489 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1490 "of block @ idx=%d\n",
1491 b);
1492
1493 this->_blocks[b] = in.clone();
1494 }
1495 }
1496 void put_block_(Tensor &in, const std::vector<cytnx_int64> &indices, const bool &check) {
1497 cytnx_error_msg(in.dtype() != this->dtype(),
1498 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
1499 "\n");
1500 cytnx_error_msg(in.device() != this->device(),
1501 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
1502 "match.%s",
1503 "\n");
1504 // We shouldn't check the contiguous
1505 // cytnx_error_msg(!in.contiguous());
1506 cytnx_error_msg(indices.size() != this->rank(),
1507 "[ERROR][put_block][BlockUniTensor] len(indices) must be the same as the "
1508 "Tensor rank (number of legs).%s",
1509 "\n");
1510
1511 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1512
1513 // find if the indices specify exists!
1514 cytnx_int64 b = -1;
1515 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1516 if (inds == this->_inner_to_outer_idx[i]) {
1517 b = i;
1518 break;
1519 }
1520 }
1521
1522 if (b < 0) {
1523 if (check) {
1524 cytnx_error_msg(true,
1525 "[ERROR][put_block][BlockUniTensor] no avaliable block exists, "
1526 "check=true, so error throws. \n If you want without error when block "
1527 "is not avaliable, set check=false.%s",
1528 "\n");
1529 }
1530 } else {
1532 in.shape() != this->_blocks[b].shape(),
1533 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1534 "of block @ idx=%d\n",
1535 b);
1536 this->_blocks[b] = in;
1537 }
1538 }
1539
1540 void tag() {
1541 // no-use!
1542 }
1543
1544 boost::intrusive_ptr<UniTensor_base> Conj() {
1545 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1546 out->Conj_();
1547 return out;
1548 }
1549
1550 void Conj_() {
1551 for (int i = 0; i < this->_blocks.size(); i++) {
1552 this->_blocks[i].Conj_();
1553 }
1554 };
1555
1556 void Transpose_();
1557 boost::intrusive_ptr<UniTensor_base> Transpose() {
1558 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1559 out->Transpose_();
1560 return out;
1561 }
1562
1563 void normalize_();
1564 boost::intrusive_ptr<UniTensor_base> normalize() {
1565 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1566 out->normalize_();
1567 return out;
1568 }
1569
1570 boost::intrusive_ptr<UniTensor_base> Dagger() {
1571 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
1572 out->Transpose_();
1573 return out;
1574 }
1575 void Dagger_() {
1576 this->Conj_();
1577 this->Transpose_();
1578 }
1579
1580 void Trace_(const std::string &a, const std::string &b);
1581 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
1582
1583 boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b) {
1584 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1585 out->Trace_(a, b);
1586 if (out->rank() == 0) {
1587 DenseUniTensor *tmp = new DenseUniTensor();
1588 tmp->_block = ((BlockUniTensor *)out.get())->_blocks[0];
1589 out = boost::intrusive_ptr<UniTensor_base>(tmp);
1590 }
1591 return out;
1592 }
1593 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b) {
1594 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1595 out->Trace_(a, b);
1596 if (out->rank() == 0) {
1597 DenseUniTensor *tmp = new DenseUniTensor();
1598 tmp->_block = ((BlockUniTensor *)out.get())->_blocks[0];
1599 out = boost::intrusive_ptr<UniTensor_base>(tmp);
1600 }
1601 return out;
1602 }
1603
1604 Tensor Norm() const;
1605
1606 bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
1607
1608 const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const;
1609 const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1610 const cytnx_complex128 &aux) const;
1611 const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1612 const cytnx_complex64 &aux) const;
1613 const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1614 const cytnx_double &aux) const;
1615 const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1616 const cytnx_float &aux) const;
1617 const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1618 const cytnx_uint64 &aux) const;
1619 const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1620 const cytnx_int64 &aux) const;
1621 const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1622 const cytnx_uint32 &aux) const;
1623 const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1624 const cytnx_int32 &aux) const;
1625 const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1626 const cytnx_uint16 &aux) const;
1627 const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1628 const cytnx_int16 &aux) const;
1629
1630 Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator);
1631 cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1632 const cytnx_complex128 &aux);
1633 cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1634 const cytnx_complex64 &aux);
1635 cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux);
1636 cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux);
1637 cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux);
1638 cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux);
1639 cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux);
1640 cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux);
1641 cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux);
1642 cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux);
1643
1644 void _save_dispatch(std::fstream &f) const;
1645 void _load_dispatch(std::fstream &f);
1646
1647 // this will remove the [q_index]-th qnum at [bond_idx]-th Bond!
1648 void truncate_(const std::string &bond_idx, const cytnx_uint64 &q_index);
1649 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &q_index);
1650
1651 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1652 void Add_(const Scalar &rhs) {
1654 true,
1655 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s "
1656 "\n",
1657 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1658 "operation on the block(s).");
1659 }
1660
1661 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1662 void Mul_(const Scalar &rhs);
1663
1664 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1665 void Sub_(const Scalar &rhs) {
1667 true,
1668 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s "
1669 "\n",
1670 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1671 "operation on the block(s).");
1672 }
1673 void lSub_(const Scalar &lhs) {
1675 true,
1676 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s "
1677 "\n",
1678 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1679 "operation on the block(s).");
1680 }
1681
1682 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs) {
1684 true,
1685 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s "
1686 "\n",
1687 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1688 "operation on the block(s).");
1689 }
1690 void Div_(const Scalar &rhs);
1691 void lDiv_(const Scalar &lhs) {
1693 true,
1694 "[ERROR] cannot perform elementwise arithmetic '+' btwn Scalar and BlockUniTensor.\n %s "
1695 "\n",
1696 "This operation will destroy block structure. [Suggest] using get/set_block(s) to do "
1697 "operation on the block(s).");
1698 }
1699 void from_(const boost::intrusive_ptr<UniTensor_base> &rhs, const bool &force);
1700
1701 void group_basis_();
1702
1703 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = false);
1704 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
1705 const bool &by_label);
1706 void combineBonds(const std::vector<std::string> &indicators, const bool &force = false);
1707
1708 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
1710 bidx >= this->Nblocks(),
1711 "[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
1712 this->Nblocks());
1713 return this->_inner_to_outer_idx[bidx];
1714 }
1715 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
1717 bidx >= this->Nblocks(),
1718 "[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
1719 this->Nblocks());
1720 return this->_inner_to_outer_idx[bidx];
1721 }
1722
1723 const vec2d<cytnx_uint64> &get_itoi() const { return this->_inner_to_outer_idx; }
1724 vec2d<cytnx_uint64> &get_itoi() { return this->_inner_to_outer_idx; }
1725 };
1727 //======================================================================
1728
1730 class UniTensor_options {
1731 public:
1732 bool _is_diag;
1733 int _dtype;
1734 int _device;
1735 int _rowrank;
1736
1737 UniTensor_options() {
1738 this->_is_diag = false;
1739 this->_dtype = Type.Double;
1740 this->_device = Device.cpu;
1741 this->_rowrank = -1;
1742 }
1743
1744 UniTensor_options(const UniTensor_options &rhs) {
1745 this->_is_diag = rhs._is_diag;
1746 this->_dtype = rhs._dtype;
1747 this->_device = rhs._device;
1748 this->_rowrank = rhs._rowrank;
1749 }
1750
1751 UniTensor_options &operator=(const UniTensor_options &rhs) {
1752 this->_is_diag = rhs._is_diag;
1753 this->_dtype = rhs._dtype;
1754 this->_device = rhs._device;
1755 this->_rowrank = rhs._rowrank;
1756 return *this;
1757 }
1758
1759 UniTensor_options &is_diag(const bool &in) {
1760 this->_is_diag = in;
1761 return *this;
1762 }
1763 UniTensor_options &dtype(const int &in) {
1764 this->_dtype = in;
1765 return *this;
1766 }
1767 UniTensor_options &device(const int &in) {
1768 this->_device = in;
1769 return *this;
1770 }
1771 UniTensor_options &rowrank(const int &in) {
1772 this->_rowrank = in;
1773 return *this;
1774 }
1775 };
1777
1780 public:
1782 boost::intrusive_ptr<UniTensor_base> _impl;
1783 UniTensor() : _impl(new UniTensor_base()){};
1784 UniTensor(const UniTensor &rhs) { this->_impl = rhs._impl; }
1785 UniTensor &operator=(const UniTensor &rhs) {
1786 this->_impl = rhs._impl;
1787 return *this;
1788 }
1790
1792
1818 explicit UniTensor(const Tensor &in_tensor, const bool &is_diag = false,
1819 const cytnx_int64 &rowrank = -1,
1820 const std::vector<std::string> &in_labels = {}, const std::string &name = "")
1821 : _impl(new UniTensor_base()) {
1822 this->Init(in_tensor, is_diag, rowrank, in_labels, name);
1823 }
1841 void Init(const Tensor &in_tensor, const bool &is_diag = false, const cytnx_int64 &rowrank = -1,
1842 const std::vector<std::string> &in_labels = {}, const std::string &name = "") {
1843 // std::cout << "[entry!]" << std::endl;
1844 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
1845 out->Init_by_Tensor(in_tensor, is_diag, rowrank, name);
1846 this->_impl = out;
1847 if (in_labels.size() != 0) this->set_labels(in_labels);
1848 }
1850
1852
1869 UniTensor(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1870 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1871 const int &device = Device.cpu, const bool &is_diag = false,
1872 const std::string &name = "")
1873 : _impl(new UniTensor_base()) {
1874 #ifdef UNI_DEBUG
1876 true,
1877 "[DEBUG] message: entry for UniTensor(const std::vector<Bond> &bonds, const "
1878 "std::vector<std::string> &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned "
1879 "int "
1880 "&dtype=Type.Double, const int &device = Device.cpu, const bool &is_diag=false)%s",
1881 "\n");
1882 #endif
1883 this->Init(bonds, in_labels, rowrank, dtype, device, is_diag, name);
1884 }
1885
1887 /* [developing]
1888 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1889 const UniTensor_options &UToptions = UniTensor_options(), const std::string &name =
1890 ""){ this->Init(bonds,in_labels, UToptions._rowrank, UToptions._dtype , UToptions._device ,
1891 UToptions._is_diag,
1892 name);
1893 }
1894 */
1896
1920 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1921 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1922 const int &device = Device.cpu, const bool &is_diag = false,
1923 const std::string &name = "") {
1924 // checking type:
1925 bool is_sym = false;
1926 int sym_fver = -1;
1927
1928 for (cytnx_uint64 i = 0; i < bonds.size(); i++) {
1929 // check
1930 if (bonds[i].syms().size() != 0) {
1931 is_sym = true;
1932 if (sym_fver == -1)
1933 sym_fver = bonds[i]._impl->_degs.size();
1934 else {
1935 // std::cout << sym_fver << " " <<
1936 // bonds[i]._impl->_degs.size() << std::endl;
1937 cytnx_error_msg((bool(sym_fver) ^ bool(bonds[i]._impl->_degs.size())),
1938 "[ERROR] All the Bond when init a UniTensor with symmetric must be in "
1939 "the same format!%s",
1940 "\n");
1941 }
1942 } else
1944 is_sym, "[ERROR] cannot have bonds with mixing of symmetry and non-symmetry.%s", "\n");
1945 }
1946
1947 // dynamical dispatch:
1948 if (is_sym) {
1949 #ifdef UNI_DEBUG
1950 cytnx_warning_msg(true, "[DEBUG] message: entry dispatch: UniTensor: symmetric%s", "\n");
1951 #endif
1952 // cytnx_warning_msg(true,"[warning, still developing, some functions will display
1953 // \"[Developing]\"][SparseUniTensor]%s","\n");
1954 if (sym_fver == 0) {
1955 // boost::intrusive_ptr<UniTensor_base> out(new SparseUniTensor());
1956 // this->_impl = out;
1957 cytnx_error_msg(true,
1958 "[ERROR] internal error! [legacy Sparse entry] the Bond is symmetry but "
1959 "the version is not properly determined!%s",
1960 "\n")
1961 } else if (sym_fver == -1) {
1962 cytnx_error_msg(true,
1963 "[ERROR] internal error! the Bond is symmetry but the version is not "
1964 "properly determined!%s",
1965 "\n");
1966 } else {
1967 boost::intrusive_ptr<UniTensor_base> out(new BlockUniTensor());
1968 this->_impl = out;
1969 }
1970 } else {
1971 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
1972 this->_impl = out;
1973 }
1974 this->_impl->Init(bonds, in_labels, rowrank, dtype, device, is_diag, false, name);
1975 }
1976
1983 UniTensor &set_name(const std::string &in) {
1984 this->_impl->set_name(in);
1985 return *this;
1986 }
1987
1998 UniTensor &set_label(const cytnx_int64 &idx, const std::string &new_label) {
1999 this->_impl->set_label(idx, new_label);
2000 return *this;
2001 }
2002
2007 this->_impl->set_label(idx, std::string(new_label));
2008 return *this;
2009 }
2010
2021 UniTensor &set_label(const std::string &old_label, const std::string &new_label) {
2022 this->_impl->set_label(old_label, new_label);
2023 return *this;
2024 }
2025
2029 UniTensor &set_label(const char *old_label, const std::string &new_label) {
2030 this->_impl->set_label(std::string(old_label), new_label);
2031 return *this;
2032 }
2033
2037 UniTensor &set_label(const std::string &old_label, const char *new_label) {
2038 this->_impl->set_label(old_label, std::string(new_label));
2039 return *this;
2040 }
2041
2045 UniTensor &set_label(const char *old_label, const char *new_label) {
2046 this->_impl->set_label(std::string(old_label), std::string(new_label));
2047 return *this;
2048 }
2049
2050 /*
2051 UniTensor& change_label(const cytnx_int64 &old_label, const cytnx_int64 &new_label){
2052 this->_impl->change_label(old_label,new_label);
2053 return *this;
2054 }
2055 */
2056
2066 UniTensor &set_labels(const std::vector<std::string> &new_labels) {
2067 this->_impl->set_labels(new_labels);
2068 return *this;
2069 }
2070
2075 UniTensor &set_labels(const std::initializer_list<char *> &new_labels) {
2076 std::vector<char *> new_lbls(new_labels);
2077 std::vector<std::string> vs(new_lbls.size());
2078 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2079 [](char *x) -> std::string { return std::string(x); });
2080
2081 this->_impl->set_labels(vs);
2082 return *this;
2083 }
2084
2092 this->_impl->set_rowrank_(new_rowrank);
2093 return *this;
2094 }
2095
2097 UniTensor out;
2098 out._impl = this->_impl->set_rowrank(new_rowrank);
2099 return out;
2100 }
2101
2102 template <class T>
2103 T &item() {
2105 "[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use "
2106 "get_block()/get_blocks() first.%s",
2107 "\n");
2108
2109 DenseUniTensor *tmp = static_cast<DenseUniTensor *>(this->_impl.get());
2110 return tmp->_block.item<T>();
2111 }
2112
2113 Scalar::Sproxy item() const {
2115 "[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use "
2116 "get_block()/get_blocks() first.%s",
2117 "\n");
2118
2119 DenseUniTensor *tmp = static_cast<DenseUniTensor *>(this->_impl.get());
2120 return tmp->_block.item();
2121 }
2126 cytnx_uint64 Nblocks() const { return this->_impl->Nblocks(); }
2127
2132 cytnx_uint64 rank() const { return this->_impl->rank(); }
2133
2138 cytnx_uint64 rowrank() const { return this->_impl->rowrank(); }
2139
2145 unsigned int dtype() const { return this->_impl->dtype(); }
2146
2153 int uten_type() const { return this->_impl->uten_type(); }
2154
2160 int device() const { return this->_impl->device(); }
2161
2166 std::string name() const { return this->_impl->name(); }
2167
2173 std::string dtype_str() const { return this->_impl->dtype_str(); }
2174
2180 std::string device_str() const { return this->_impl->device_str(); }
2181
2187 std::string uten_type_str() const { return this->_impl->uten_type_str(); }
2188
2194 bool is_contiguous() const { return this->_impl->is_contiguous(); }
2195
2200 bool is_diag() const { return this->_impl->is_diag(); }
2201
2207 bool is_tag() const { return this->_impl->is_tag(); }
2208
2214 std::vector<Symmetry> syms() const { return this->_impl->syms(); }
2215
2222 const bool &is_braket_form() const { return this->_impl->is_braket_form(); }
2223
2228 const std::vector<std::string> &labels() const { return this->_impl->labels(); }
2235 cytnx_int64 get_index(std::string label) const { return this->_impl->get_index(label); }
2236
2241 const std::vector<Bond> &bonds() const { return this->_impl->bonds(); }
2242
2246 std::vector<Bond> &bonds() { return this->_impl->bonds(); }
2247
2248 const Bond &bond_(const cytnx_uint64 &idx) const { return this->_impl->bond_(idx); }
2249 Bond &bond_(const cytnx_uint64 &idx) { return this->_impl->bond_(idx); }
2250
2251 const Bond &bond_(const std::string &label) const { return this->_impl->bond_(label); }
2252 Bond &bond_(const std::string &label) { return this->_impl->bond_(label); }
2253
2254 Bond bond(const cytnx_uint64 &idx) const { return this->_impl->bond_(idx).clone(); }
2255 Bond bond(const std::string &label) const { return this->_impl->bond_(label).clone(); }
2256
2261 std::vector<cytnx_uint64> shape() const { return this->_impl->shape(); }
2262
2268 bool is_blockform() const { return this->_impl->is_blockform(); }
2269
2276 void to_(const int &device) { this->_impl->to_(device); }
2277
2287 UniTensor to(const int &device) const {
2288 UniTensor out;
2289 out._impl = this->_impl->to(device);
2290 return out;
2291 }
2292
2298 UniTensor out;
2299 out._impl = this->_impl->clone();
2300 return out;
2301 }
2302
2312 UniTensor &relabels_(const std::vector<std::string> &new_labels) {
2313 this->_impl->relabels_(new_labels);
2314 return *this;
2315 }
2316
2328 UniTensor relabels(const std::vector<std::string> &new_labels) const {
2329 UniTensor out;
2330 out._impl = this->_impl->relabels(new_labels);
2331 return out;
2332 }
2333
2337 UniTensor relabels(const std::initializer_list<char *> &new_labels) const {
2338 std::vector<char *> new_lbls(new_labels);
2339 std::vector<std::string> vs(new_lbls.size());
2340 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2341 [](char *x) -> std::string { return std::string(x); });
2342
2343 UniTensor out;
2344 out._impl = this->_impl->relabels(vs);
2345 return out;
2346 }
2350 UniTensor &relabels_(const std::initializer_list<char *> &new_labels) {
2351 std::vector<char *> new_lbls(new_labels);
2352 std::vector<std::string> vs(new_lbls.size());
2353 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2354 [](char *x) -> std::string { return std::string(x); });
2355
2356 this->_impl->relabels_(vs);
2357 return *this;
2358 }
2359
2367 UniTensor relabels(const std::vector<std::string> &old_labels,
2368 const std::vector<std::string> &new_labels) const {
2369 UniTensor out;
2370 out._impl = this->_impl->relabels(old_labels, new_labels);
2371 return out;
2372 }
2373
2389 UniTensor &relabels_(const std::vector<std::string> &old_labels,
2390 const std::vector<std::string> &new_labels) {
2391 this->_impl->relabels_(old_labels, new_labels);
2392 return *this;
2393 }
2394
2399 UniTensor relabels(const std::initializer_list<char *> &old_labels,
2400 const std::initializer_list<char *> &new_labels) const {
2401 std::vector<char *> new_lbls(new_labels);
2402 std::vector<std::string> vs(new_lbls.size());
2403 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2404 [](char *x) -> std::string { return std::string(x); });
2405
2406 std::vector<char *> old_lbls(old_labels);
2407 std::vector<std::string> vs_old(old_lbls.size());
2408 transform(old_lbls.begin(), old_lbls.end(), vs_old.begin(),
2409 [](char *x) -> std::string { return std::string(x); });
2410
2411 return this->relabels(vs_old, vs);
2412 }
2413
2418 UniTensor &relabels_(const std::initializer_list<char *> &old_labels,
2419 const std::initializer_list<char *> &new_labels) {
2420 std::vector<char *> new_lbls(new_labels);
2421 std::vector<std::string> vs(new_lbls.size());
2422 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
2423 [](char *x) -> std::string { return std::string(x); });
2424
2425 std::vector<char *> old_lbls(old_labels);
2426 std::vector<std::string> vs_old(old_lbls.size());
2427 transform(old_lbls.begin(), old_lbls.end(), vs_old.begin(),
2428 [](char *x) -> std::string { return std::string(x); });
2429
2430 this->relabels_(vs_old, vs);
2431 return *this;
2432 }
2433
2448 UniTensor relabel(const cytnx_int64 &inx, const std::string &new_label) const {
2449 UniTensor out;
2450 out._impl = this->_impl->relabel(inx, new_label);
2451 return out;
2452 }
2461 UniTensor &relabel_(const cytnx_int64 &inx, const std::string &new_label) {
2462 this->_impl->relabel_(inx, new_label);
2463 return *this;
2464 }
2465
2474 UniTensor &relabel_(const std::string &old_label, const std::string &new_label) {
2475 this->_impl->relabel_(old_label, new_label);
2476 return *this;
2477 }
2478
2493 UniTensor relabel(const std::string &old_label, const std::string &new_label) const {
2494 UniTensor out;
2495 out._impl = this->_impl->relabel(old_label, new_label);
2496 return out;
2497 }
2498
2505 UniTensor astype(const unsigned int &dtype) const {
2506 UniTensor out;
2507 if (this->dtype() == dtype) {
2508 out._impl = this->_impl;
2509 } else {
2510 out._impl = this->_impl->astype(dtype);
2511 }
2512 return out;
2513 }
2514
2523 UniTensor permute(const std::vector<cytnx_int64> &mapper,
2524 const cytnx_int64 &rowrank = -1) const {
2525 UniTensor out;
2526 out._impl = this->_impl->permute(mapper, rowrank);
2527 return out;
2528 }
2529
2536 UniTensor permute(const std::vector<std::string> &mapper,
2537 const cytnx_int64 &rowrank = -1) const {
2538 UniTensor out;
2539 out._impl = this->_impl->permute(mapper, rowrank);
2540 return out;
2541 }
2542
2546 UniTensor permute(const std::initializer_list<char *> &mapper,
2547 const cytnx_int64 &rowrank = -1) const {
2548 std::vector<char *> mprs = mapper;
2549 std::vector<std::string> vs(mprs.size());
2550 transform(mprs.begin(), mprs.end(), vs.begin(),
2551 [](char *x) -> std::string { return std::string(x); });
2552
2553 return this->permute(vs, rowrank);
2554 }
2555
2564 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1) {
2565 this->_impl->permute_(mapper, rowrank);
2566 }
2567
2574 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1) {
2575 this->_impl->permute_(mapper, rowrank);
2576 }
2577
2578 // void permute_( const std::initializer_list<char*> &mapper, const cytnx_int64 &rowrank= -1){
2579 // std::vector<char*> mprs = mapper;
2580 // std::vector<std::string> vs(mprs.size());
2581 // transform(mprs.begin(),mprs.end(),vs.begin(),[](char * x) -> std::string { return
2582 // std::string(x); });
2583
2584 // this->permute_(vs,rowrank);
2585 // }
2586
2587 // void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1) {
2588 // this->_impl->permute_(mapper, rowrank);
2589 // }
2590
2596 UniTensor out;
2597 out._impl = this->_impl->contiguous();
2598 return out;
2599 }
2600
2605 void contiguous_() { this->_impl = this->_impl->contiguous_(); }
2606
2611 void print_diagram(const bool &bond_info = false) { this->_impl->print_diagram(bond_info); }
2612
2617 void print_blocks(const bool &full_info = true) const { this->_impl->print_blocks(full_info); }
2618
2624 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const {
2625 this->_impl->print_block(idx, full_info);
2626 }
2627
2634 void group_basis_() { this->_impl->group_basis_(); }
2635
2637 UniTensor out = this->clone();
2638 out.group_basis_();
2639 return out;
2640 }
2641
2647 template <class T>
2648 T &at(const std::vector<cytnx_uint64> &locator) {
2649 // std::cout << "at " << this->is_blockform() << std::endl;
2650 if (this->uten_type() == UTenType.Block) {
2651 // [NEW] this will not check if it exists, if it is not then error will throw!
2652 T aux;
2653 return this->_impl->at_for_sparse(locator, aux);
2654
2655 } else if (this->uten_type() == UTenType.Sparse) {
2656 if (this->_impl->elem_exists(locator)) {
2657 T aux;
2658 return this->_impl->at_for_sparse(locator, aux);
2659 } else {
2660 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2661 "\n");
2662 }
2663 } else {
2664 return this->get_block_().at<T>(locator);
2665 }
2666 }
2667
2673 template <class T>
2674 const T &at(const std::vector<cytnx_uint64> &locator) const {
2675 // std::cout << "at " << this->is_blockform() << std::endl;
2676 if (this->uten_type() == UTenType.Block) {
2677 // [NEW] this will not check if it exists, if it is not then error will throw!
2678 T aux;
2679 return this->_impl->at_for_sparse(locator, aux);
2680
2681 } else if (this->uten_type() == UTenType.Sparse) {
2682 if (this->_impl->elem_exists(locator)) {
2683 T aux; // [workaround] use aux to dispatch.
2684 return this->_impl->at_for_sparse(locator, aux);
2685 } else {
2686 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2687 "\n");
2688 }
2689 } else {
2690 return this->get_block_().at<T>(locator);
2691 }
2692 }
2693
2694 template <class T>
2695 const T &at(const std::vector<std::string> &labels,
2696 const std::vector<cytnx_uint64> &locator) const {
2697 // giving label <-> locator one to one corresponding, return the element:
2698 cytnx_error_msg(locator.size() != labels.size(),
2699 "[ERROR][at] length of list should be the same for label and locator.%s",
2700 "\n");
2702 labels.size() != this->rank(),
2703 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
2704 std::vector<cytnx_uint64> new_locator(this->rank());
2706 for (int i = 0; i < labels.size(); i++) {
2707 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
2708 cytnx_error_msg(res == this->_impl->_labels.end(),
2709 "[ERROR] label:%s does not exist in current UniTensor.\n",
2710 labels[i].c_str());
2711 new_loc = std::distance(this->_impl->_labels.begin(), res);
2713 }
2714 return this->at<T>(new_locator);
2715 }
2716 template <class T>
2717 T &at(const std::vector<std::string> &labels, const std::vector<cytnx_uint64> &locator) {
2718 // giving label <-> locator one to one corresponding, return the element:
2719 cytnx_error_msg(locator.size() != labels.size(),
2720 "[ERROR][at] length of list should be the same for label and locator.%s",
2721 "\n");
2723 labels.size() != this->rank(),
2724 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
2725 std::vector<cytnx_uint64> new_locator(this->rank());
2727 for (int i = 0; i < labels.size(); i++) {
2728 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
2729 cytnx_error_msg(res == this->_impl->_labels.end(),
2730 "[ERROR] label:%s does not exist in current UniTensor.\n",
2731 labels[i].c_str());
2732 new_loc = std::distance(this->_impl->_labels.begin(), res);
2734 }
2735 return this->at<T>(new_locator);
2736 }
2737
2742 const Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) const {
2743 if (this->uten_type() == UTenType.Block) {
2744 return this->_impl->at_for_sparse(locator);
2745 } else if (this->uten_type() == UTenType.Sparse) {
2746 if (this->_impl->elem_exists(locator)) {
2747 return this->_impl->at_for_sparse(locator);
2748 } else {
2749 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2750 "\n");
2751 }
2752 } else {
2753 return this->get_block_().at(locator);
2754 }
2755 }
2756
2761 Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) {
2762 if (this->uten_type() == UTenType.Block) {
2763 return this->_impl->at_for_sparse(locator);
2764 } else if (this->uten_type() == UTenType.Sparse) {
2765 if (this->_impl->elem_exists(locator)) {
2766 return this->_impl->at_for_sparse(locator);
2767 } else {
2768 cytnx_error_msg(true, "[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
2769 "\n");
2770 }
2771 } else {
2772 return this->get_block_().at(locator);
2773 }
2774 }
2775
2776 Scalar::Sproxy at(const std::vector<std::string> &labels,
2777 const std::vector<cytnx_uint64> &locator) {
2778 // giving label <-> locator one to one corresponding, return the element:
2779 cytnx_error_msg(locator.size() != labels.size(),
2780 "[ERROR][at] length of list should be the same for label and locator.%s",
2781 "\n");
2783 labels.size() != this->rank(),
2784 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
2785 std::vector<cytnx_uint64> new_locator(this->rank());
2787 for (int i = 0; i < labels.size(); i++) {
2788 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
2789 cytnx_error_msg(res == this->_impl->_labels.end(),
2790 "[ERROR] label:%s does not exist in current UniTensor.\n",
2791 labels[i].c_str());
2792 new_loc = std::distance(this->_impl->_labels.begin(), res);
2794 }
2795 return this->at(new_locator);
2796 }
2797
2798 const Scalar::Sproxy at(const std::vector<std::string> &labels,
2799 const std::vector<cytnx_uint64> &locator) const {
2800 // giving label <-> locator one to one corresponding, return the element:
2801 cytnx_error_msg(locator.size() != labels.size(),
2802 "[ERROR][at] length of list should be the same for label and locator.%s",
2803 "\n");
2805 labels.size() != this->rank(),
2806 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
2807 std::vector<cytnx_uint64> new_locator(this->rank());
2809 for (int i = 0; i < labels.size(); i++) {
2810 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
2811 cytnx_error_msg(res == this->_impl->_labels.end(),
2812 "[ERROR] label:%s does not exist in current UniTensor.\n",
2813 labels[i].c_str());
2814 new_loc = std::distance(this->_impl->_labels.begin(), res);
2816 }
2817 return this->at(new_locator);
2818 }
2819
2820 // return a clone of block
2826 Tensor get_block(const cytnx_uint64 &idx = 0) const { return this->_impl->get_block(idx); };
2827 //================================
2828 // return a clone of block
2837 Tensor get_block(const std::vector<cytnx_int64> &qidx, const bool &force = false) const {
2838 return this->_impl->get_block(qidx, force);
2839 }
2840
2841 Tensor get_block(const std::vector<std::string> &labels, const std::vector<cytnx_int64> &qidx,
2842 const bool &force = false) const {
2844 labels.size() != qidx.size(),
2845 "[ERROR][get_block] length of lists must be the same for both lables and qnidices%s", "\n");
2846 cytnx_error_msg(labels.size() != this->rank(),
2847 "[ERROR][get_block] length of lists must be the rank (# of legs)%s", "\n");
2848
2849 std::vector<cytnx_int64> loc_id(this->rank());
2850 std::vector<cytnx_int64> new_qidx(this->rank());
2851
2853 std::vector<cytnx_uint64> new_order(this->rank());
2854 for (int i = 0; i < labels.size(); i++) {
2855 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
2856 cytnx_error_msg(res == this->_impl->_labels.end(),
2857 "[ERROR][get_block] label:%s does not exists in current Tensor.\n",
2858 labels[i].c_str());
2859 new_loc = std::distance(this->_impl->_labels.begin(), res);
2860 new_qidx[new_loc] = qidx[i];
2861 new_order[i] = new_loc;
2862 }
2863 auto out = this->_impl->get_block(new_qidx, force);
2864 if (out.dtype() != Type.Void) out.permute_(new_order);
2865 return out;
2866 }
2867
2872 Tensor get_block(const std::initializer_list<cytnx_int64> &qnum,
2873 const bool &force = false) const {
2874 std::vector<cytnx_int64> tmp = qnum;
2875 return get_block(tmp, force);
2876 }
2877
2882 Tensor get_block(const std::vector<cytnx_uint64> &qnum, const bool &force = false) const {
2883 std::vector<cytnx_int64> iqnum(qnum.begin(), qnum.end());
2884 return this->_impl->get_block(iqnum, force);
2885 }
2886
2887 Tensor get_block(const std::vector<std::string> &labels, const std::vector<cytnx_uint64> &qidx,
2888 const bool &force = false) const {
2889 std::vector<cytnx_int64> iqnum(qidx.begin(), qidx.end());
2890 return this->get_block(labels, iqnum, force);
2891 }
2892
2898 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const {
2899 return this->_impl->get_block_(idx);
2900 }
2901
2906 Tensor &get_block_(const cytnx_uint64 &idx = 0) { return this->_impl->get_block_(idx); }
2907
2916 Tensor &get_block_(const std::vector<cytnx_int64> &qidx, const bool &force = false) {
2917 return this->_impl->get_block_(qidx, force);
2918 }
2919
2934 // developer note: Tensor is not the same object (Thus Tensor instead of Tensor& ),
2935 // since we permute! but they have shared data memory.
2936 Tensor get_block_(const std::vector<std::string> &labels, const std::vector<cytnx_int64> &qidx,
2937 const bool &force = false) {
2939 labels.size() != qidx.size(),
2940 "[ERROR][get_block] length of lists must be the same for both lables and qnidices%s", "\n");
2941 cytnx_error_msg(labels.size() != this->rank(),
2942 "[ERROR][get_block] length of lists must be the rank (# of legs)%s", "\n");
2943
2944 std::vector<cytnx_int64> loc_id(this->rank());
2945 std::vector<cytnx_int64> new_qidx(this->rank());
2946
2948 std::vector<cytnx_uint64> new_order(this->rank());
2949 for (int i = 0; i < labels.size(); i++) {
2950 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
2951 cytnx_error_msg(res == this->_impl->_labels.end(),
2952 "[ERROR][get_block] label:%s does not exists in current Tensor.\n",
2953 labels[i].c_str());
2954 new_loc = std::distance(this->_impl->_labels.begin(), res);
2955 new_qidx[new_loc] = qidx[i];
2956 new_order[i] = new_loc;
2957 }
2958 auto out = this->_impl->get_block_(new_qidx, force);
2959 if (out.dtype() != Type.Void) {
2960 out = out.permute(new_order);
2961 }
2962 return out;
2963 }
2964
2968 Tensor &get_block_(const std::initializer_list<cytnx_int64> &qidx, const bool &force = false) {
2969 std::vector<cytnx_int64> tmp = qidx;
2970 return get_block_(tmp, force);
2971 }
2972
2976 Tensor &get_block_(const std::vector<cytnx_uint64> &qidx, const bool &force = false) {
2977 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
2978 return get_block_(iqidx, force);
2979 }
2980
2981 Tensor get_block_(const std::vector<std::string> &labels, const std::vector<cytnx_uint64> &qidx,
2982 const bool &force = false) {
2983 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
2984 return get_block_(labels, iqidx, force);
2985 }
2986 //================================
2987
2988 // this only work for non-symm tensor. return a shared view of block
2992 const Tensor &get_block_(const std::vector<cytnx_int64> &qidx,
2993 const bool &force = false) const {
2994 return this->_impl->get_block_(qidx, force);
2995 }
2996
3000 const Tensor &get_block_(const std::initializer_list<cytnx_int64> &qidx,
3001 const bool &force = false) const {
3002 std::vector<cytnx_int64> tmp = qidx;
3003 return this->_impl->get_block_(tmp, force);
3004 }
3005
3009 const Tensor &get_block_(const std::vector<cytnx_uint64> &qidx,
3010 const bool &force = false) const {
3011 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
3012 return get_block_(iqidx, force);
3013 }
3014
3015 //================================
3024 //[dev]
3025 std::vector<Tensor> get_blocks() const { return this->_impl->get_blocks(); }
3026
3032 //[dev]
3033 const std::vector<Tensor> &get_blocks_(const bool &silent = false) const {
3034 return this->_impl->get_blocks_(silent);
3035 }
3036
3040 //[dev]
3041 std::vector<Tensor> &get_blocks_(const bool &silent = false) {
3042 return this->_impl->get_blocks_(silent);
3043 }
3044
3050 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
3051 this->_impl->put_block(in, idx);
3052 }
3053
3061 void put_block(const Tensor &in_tens, const std::vector<cytnx_int64> &qidx, const bool &force) {
3062 this->_impl->put_block(in_tens, qidx, force);
3063 }
3064
3069 void put_block(Tensor &in, const std::vector<std::string> &lbls,
3070 const std::vector<cytnx_int64> &qidx, const bool &force = false) {
3072 lbls.size() != qidx.size(),
3073 "[ERROR][put_block] length of lists must be the same for both lables and qnidices%s", "\n");
3074 cytnx_error_msg(lbls.size() != this->rank(),
3075 "[ERROR][put_block] length of lists must be the rank (# of legs)%s", "\n");
3076
3077 std::vector<cytnx_int64> loc_id(this->rank());
3078 std::vector<cytnx_int64> new_qidx(this->rank());
3079
3081 // std::vector<cytnx_uint64> new_order(this->rank());
3082 std::vector<cytnx_uint64> inv_order(this->rank());
3083 for (int i = 0; i < lbls.size(); i++) {
3084 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), lbls[i]);
3085 cytnx_error_msg(res == this->_impl->_labels.end(),
3086 "[ERROR][put_block] label:%s does not exists in current Tensor.\n",
3087 lbls[i].c_str());
3088 new_loc = std::distance(this->_impl->_labels.begin(), res);
3089 new_qidx[new_loc] = qidx[i];
3090 // new_order[i] = new_loc;
3091 inv_order[new_loc] = i;
3092 }
3093 this->_impl->put_block(in.permute(inv_order), new_qidx, force);
3094 }
3095
3101 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) { this->_impl->put_block_(in, idx); }
3102
3109 void put_block_(Tensor &in, const std::vector<cytnx_int64> &qidx, const bool &force) {
3110 this->_impl->put_block_(in, qidx, force);
3111 }
3112
3117 void put_block_(Tensor &in, const std::vector<std::string> &lbls,
3118 const std::vector<cytnx_int64> &qidx, const bool &force = false) {
3120 lbls.size() != qidx.size(),
3121 "[ERROR][put_block_] length of lists must be the same for both lables and qnidices%s",
3122 "\n");
3123 cytnx_error_msg(lbls.size() != this->rank(),
3124 "[ERROR][put_block_] length of lists must be the rank (# of legs)%s", "\n");
3125
3126 std::vector<cytnx_int64> loc_id(this->rank());
3127 std::vector<cytnx_int64> new_qidx(this->rank());
3128
3130 std::vector<cytnx_uint64> new_order(this->rank());
3131 std::vector<cytnx_uint64> inv_order(this->rank());
3132 for (int i = 0; i < lbls.size(); i++) {
3133 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), lbls[i]);
3134 cytnx_error_msg(res == this->_impl->_labels.end(),
3135 "[ERROR][put_block_] label:%s does not exists in current Tensor.\n",
3136 lbls[i].c_str());
3137 new_loc = std::distance(this->_impl->_labels.begin(), res);
3138 new_qidx[new_loc] = qidx[i];
3139 new_order[i] = new_loc;
3140 inv_order[new_loc] = i;
3141 }
3142 in.permute_(inv_order);
3143 this->_impl->put_block_(in, new_qidx, force);
3144 in.permute_(new_order);
3145 }
3146 UniTensor get(const std::vector<Accessor> &accessors) const {
3147 UniTensor out;
3148 out._impl = this->_impl->get(accessors);
3149 return out;
3150 }
3151 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
3152 this->_impl->set(accessors, rhs);
3153 }
3154 void set(const std::vector<Accessor> &accessors, const UniTensor &rhs) {
3156 rhs.uten_type() != UTenType.Dense,
3157 "[ERROR] cannot set elements from UniTensor with symmetry. Use at() instead.%s", "\n");
3158 cytnx_error_msg(this->is_diag(), "[ERROR] cannot set UniTensor with is_diag=True.%s", "\n");
3160 "[ERROR] cannot set UniTensor. incoming UniTensor is_diag=True.%s", "\n");
3161
3162 this->_impl->set(accessors, rhs.get_block());
3163 }
3171 UniTensor reshape(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
3172 UniTensor out;
3173 out._impl = this->_impl->reshape(new_shape, rowrank);
3174 return out;
3175 }
3176
3183 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
3184 this->_impl->reshape_(new_shape, rowrank);
3185 }
3186
3199 UniTensor out;
3200 out._impl = this->_impl->to_dense();
3201 return out;
3202 }
3203
3208 void to_dense_() { this->_impl->to_dense_(); }
3209
3215 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
3216 const bool &by_label) {
3217 this->_impl->combineBonds(indicators, force, by_label);
3218 }
3219
3230 void combineBonds(const std::vector<std::string> &indicators, const bool &force = false) {
3231 this->_impl->combineBonds(indicators, force);
3232 }
3233
3239 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = false) {
3240 this->_impl->combineBonds(indicators, force);
3241 }
3242
3261 UniTensor contract(const UniTensor &inR, const bool &mv_elem_self = false,
3262 const bool &mv_elem_rhs = false) const {
3263 UniTensor out;
3264 out._impl = this->_impl->contract(inR._impl, mv_elem_self, mv_elem_rhs);
3265 return out;
3266 }
3267
3269
3277 std::vector<Bond> getTotalQnums(const bool physical = false) const {
3278 return this->_impl->getTotalQnums(physical);
3279 }
3280
3284 std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const {
3285 return this->_impl->get_blocks_qnums();
3286 }
3288
3293 bool same_data(const UniTensor &rhs) const {
3294 // check same type:
3295 if (this->_impl->uten_type() != rhs._impl->uten_type()) return false;
3296
3297 return this->_impl->same_data(rhs._impl);
3298 }
3299
3317 this->_impl->Add_(rhs._impl);
3318 return *this;
3319 }
3320
3338 this->_impl->Mul_(rhs._impl);
3339 return *this;
3340 }
3341
3359 this->_impl->Sub_(rhs._impl);
3360 return *this;
3361 }
3362
3380 this->_impl->Div_(rhs._impl);
3381 return *this;
3382 }
3383
3395 this->_impl->Add_(rhs);
3396 return *this;
3397 }
3398
3410 this->_impl->Mul_(rhs);
3411 return *this;
3412 }
3413
3425 this->_impl->Sub_(rhs);
3426 return *this;
3427 }
3428
3440 this->_impl->Div_(rhs);
3441 return *this;
3442 }
3443
3461
3472 UniTensor Add(const Scalar &rhs) const;
3473
3491
3502 UniTensor Mul(const Scalar &rhs) const;
3503
3521
3532 UniTensor Div(const Scalar &rhs) const;
3533
3551
3562 UniTensor Sub(const Scalar &rhs) const;
3563
3572 Tensor Norm() const { return this->_impl->Norm(); };
3573
3590 this->Add_(rhs);
3591 return *this;
3592 }
3593
3610 this->Sub_(rhs);
3611 return *this;
3612 }
3613
3630 this->Div_(rhs);
3631 return *this;
3632 }
3633
3650 this->Mul_(rhs);
3651 return *this;
3652 }
3653
3665 this->Add_(rhs);
3666 return *this;
3667 }
3668
3680 this->Sub_(rhs);
3681 return *this;
3682 }
3683
3695 this->Div_(rhs);
3696 return *this;
3697 }
3698
3710 this->Mul_(rhs);
3711 return *this;
3712 }
3713
3721 UniTensor Conj() const {
3722 UniTensor out;
3723 out._impl = this->_impl->Conj();
3724 return out;
3725 }
3726
3735 this->_impl->Conj_();
3736 return *this;
3737 }
3738
3750 UniTensor out;
3751 out._impl = this->_impl->Transpose();
3752 return out;
3753 }
3754
3762 this->_impl->Transpose_();
3763 return *this;
3764 }
3765
3773 UniTensor out;
3774 out._impl = this->_impl->normalize();
3775 return out;
3776 }
3777
3785 this->_impl->normalize_();
3786 return *this;
3787 }
3788
3798 UniTensor Trace(const std::string &a, const std::string &b) const {
3799 UniTensor out;
3800 out._impl = this->_impl->Trace(a, b);
3801 return out;
3802 }
3803
3813 UniTensor Trace(const cytnx_int64 &a = 0, const cytnx_int64 &b = 1) const {
3814 UniTensor out;
3815 out._impl = this->_impl->Trace(a, b);
3816 return out;
3817 }
3818
3828 UniTensor &Trace_(const std::string &a, const std::string &b) {
3829 this->_impl->Trace_(a, b);
3830 if (this->uten_type() == UTenType.Block) {
3831 // handle if no leg left case for BlockUniTensor.
3832 if (this->rank() == 0) {
3833 DenseUniTensor *tmp = new DenseUniTensor();
3834 tmp->_block = this->get_blocks_(true)[0];
3835 this->_impl = boost::intrusive_ptr<UniTensor_base>(tmp);
3836 }
3837 }
3838 return *this;
3839 }
3840
3850 UniTensor &Trace_(const cytnx_int64 &a = 0, const cytnx_int64 &b = 1) {
3851 this->_impl->Trace_(a, b);
3852 if (this->uten_type() == UTenType.Block) {
3853 // handle if no leg left case for BlockUniTensor.
3854 if (this->rank() == 0) {
3855 DenseUniTensor *tmp = new DenseUniTensor();
3856 tmp->_block = this->get_blocks_(true)[0];
3857 this->_impl = boost::intrusive_ptr<UniTensor_base>(tmp);
3858 }
3859 }
3860 return *this;
3861 }
3862
3870 UniTensor out;
3871 out._impl = this->_impl->Dagger();
3872 return out;
3873 }
3874
3882 this->_impl->Dagger_();
3883 return *this;
3884 }
3885
3895 this->_impl->tag();
3896 return *this;
3897 }
3898
3907 UniTensor Pow(const double &p) const;
3908
3917 UniTensor &Pow_(const double &p);
3918
3925 bool elem_exists(const std::vector<cytnx_uint64> &locator) const {
3926 return this->_impl->elem_exists(locator);
3927 }
3928
3934 template <class T>
3935 T get_elem(const std::vector<cytnx_uint64> &locator) const {
3936 return this->at<T>(locator);
3937 }
3938
3944 template <class T2>
3945 void set_elem(const std::vector<cytnx_uint64> &locator, const T2 &rc) {
3946 // cytnx_error_msg(true,"[ERROR] invalid type%s","\n");
3947 this->at(locator) = rc;
3948 }
3949
3956 void Save(const std::string &fname) const;
3957
3964 void Save(const char *fname) const;
3965
3974 static UniTensor Load(const std::string &fname);
3975
3984 static UniTensor Load(const char *fname);
3985
3994 UniTensor &truncate_(const std::string &label, const cytnx_uint64 &dim) {
3995 this->_impl->truncate_(label, dim);
3996 return *this;
3997 }
3998
4008 this->_impl->truncate_(bond_idx, dim);
4009 return *this;
4010 }
4011
4021 UniTensor truncate(const std::string &label, const cytnx_uint64 &dim) const {
4022 UniTensor out = this->clone();
4023 out.truncate_(label, dim);
4024 return out;
4025 }
4026
4037 UniTensor out = this->clone();
4038 out.truncate_(bond_idx, dim);
4039 return out;
4040 }
4041
4049 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
4050 return this->_impl->get_qindices(bidx);
4051 }
4059 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
4060 return this->_impl->get_qindices(bidx);
4061 }
4062
4069 const vec2d<cytnx_uint64> &get_itoi() const { return this->_impl->get_itoi(); }
4070 vec2d<cytnx_uint64> &get_itoi() { return this->_impl->get_itoi(); }
4071
4073 void _Load(std::fstream &f);
4074 void _Save(std::fstream &f) const;
4076
4077 UniTensor &convert_from(const UniTensor &rhs, const bool &force = false) {
4078 this->_impl->from_(rhs._impl, force);
4079 return *this;
4080 }
4081
4082 // Generators:
4096 const std::vector<std::string> &in_labels = {},
4097 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4098 const std::string &name = "") {
4099 return UniTensor(cytnx::zeros(Nelem, dtype, device), false, -1, in_labels, name);
4100 }
4101
4115 static UniTensor zeros(const std::vector<cytnx_uint64> &shape,
4116 const std::vector<std::string> &in_labels = {},
4117 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4118 const std::string &name = "") {
4119 return UniTensor(cytnx::zeros(shape, dtype, device), false, -1, in_labels, name);
4120 }
4121
4133 static UniTensor ones(const cytnx_uint64 &Nelem, const std::vector<std::string> &in_labels = {},
4134 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4135 const std::string &name = "") {
4136 return UniTensor(cytnx::ones(Nelem, dtype, device), false, -1, in_labels, name);
4137 }
4138
4151 static UniTensor ones(const std::vector<cytnx_uint64> &shape,
4152 const std::vector<std::string> &in_labels = {},
4153 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4154 const std::string &name = "") {
4155 return UniTensor(cytnx::ones(shape, dtype, device), false, -1, in_labels, name);
4156 }
4157
4172 const std::vector<std::string> &in_labels = {},
4173 const std::string &name = "") {
4174 return UniTensor(cytnx::arange(Nelem), false, -1, in_labels, name);
4175 }
4176
4194 const cytnx_double &step = 1,
4195 const std::vector<std::string> &in_labels = {},
4196 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4197 const std::string &name = "") {
4198 return UniTensor(cytnx::arange(start, end, step, dtype, device), false, -1, in_labels, name);
4199 }
4200
4221 const cytnx_uint64 &Nelem, const bool &endpoint = true,
4222 const std::vector<std::string> &in_labels = {},
4223 const unsigned int &dtype = Type.Double,
4224 const int &device = Device.cpu, const std::string &name = "") {
4225 return UniTensor(cytnx::linspace(start, end, Nelem, endpoint, dtype, device), false, -1,
4226 in_labels, name);
4227 }
4228
4229 // Random Generators:
4248 static UniTensor normal(const cytnx_uint64 &Nelem, const double &mean, const double &std,
4249 const std::vector<std::string> &in_labels = {},
4250 const unsigned int &seed = std::random_device()(),
4251 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4252 const std::string &name = "");
4253
4272 static UniTensor normal(const std::vector<cytnx_uint64> &shape, const double &mean,
4273 const double &std, const std::vector<std::string> &in_labels = {},
4274 const unsigned int &seed = std::random_device()(),
4275 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
4276 const std::string &name = "");
4277
4296 static UniTensor uniform(const cytnx_uint64 &Nelem, const double &low, const double &high,
4297 const std::vector<std::string> &in_labels = {},
4298 const unsigned int &seed = std::random_device()(),
4299 const unsigned int &dtype = Type.Double,
4300 const int &device = Device.cpu, const std::string &name = "");
4301
4339 static UniTensor uniform(const std::vector<cytnx_uint64> &shape, const double &low,
4340 const double &high, const std::vector<std::string> &in_labels = {},
4341 const unsigned int &seed = std::random_device()(),
4342 const unsigned int &dtype = Type.Double,
4343 const int &device = Device.cpu, const std::string &name = "");
4344
4345 // Inplace Random Generators:
4358 void normal_(const double &mean, const double &std,
4359 const unsigned int &seed = std::random_device()());
4360
4373 void uniform_(const double &low = 0, const double &high = 1,
4374 const unsigned int &seed = std::random_device()());
4375
4376 }; // class UniTensor
4377
4379 std::ostream &operator<<(std::ostream &os, const UniTensor &in);
4381
4394 UniTensor Contract(const UniTensor &inL, const UniTensor &inR, const bool &cacheL = false,
4395 const bool &cacheR = false);
4396
4409 UniTensor Contracts(const std::vector<UniTensor> &TNs, const std::string &order,
4410 const bool &optimal);
4411
4413 void _resolve_CT(std::vector<UniTensor> &TNlist);
4414 template <class... T>
4415 void _resolve_CT(std::vector<UniTensor> &TNlist, const UniTensor &in, const T &...args) {
4416 TNlist.push_back(in);
4417 _resolve_CT(TNlist, args...);
4418 }
4420
4432 template <class... T>
4433 UniTensor Contracts(const UniTensor &in, const T &...args, const std::string &order,
4434 const bool &optimal) {
4435 std::vector<UniTensor> TNlist;
4436 _resolve_CT(TNlist, in, args...);
4437 return Contracts(TNlist, order, optimal);
4438 }
4439
4440} // namespace cytnx
4441
4442#endif // BACKEND_TORCH
4443
4444#endif
the object contains auxiliary properties for each Tensor rank (bond)
Definition Bond.hpp:176
Bond clone() const
return a copy of the instance Bond
Definition Bond.hpp:488
an tensor (multi-dimensional array)
Definition Tensor.hpp:41
void to_(const int &device)
move the current Tensor to the device.
Definition Tensor.hpp:615
Tensor contiguous_()
Make the Tensor contiguous by coalescing the memory (storage), inplacely.
Definition Tensor.hpp:702
unsigned int dtype() const
the dtype-id of the Tensor
Definition Tensor.hpp:514
Tensor contiguous() const
Make the Tensor contiguous by coalescing the memory (storage).
Definition Tensor.hpp:682
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition Tensor.hpp:858
Tensor clone() const
return a clone of the current Tensor.
Definition Tensor.hpp:566
void set(const std::vector< cytnx::Accessor > &accessors, const Tensor &rhs)
set elements with the input Tensor using Accessor (C++ API) / slices (python API)
Definition Tensor.hpp:993
Tensor Norm() const
the Norm member function. Same as linalg::Norm(const Tensor &Tin), where Tin is the current Tensor.
Tensor astype(const int &new_type) const
return a new Tensor that cast to different dtype.
Definition Tensor.hpp:823
const bool & is_contiguous() const
return whether the Tensor is contiguous or not.
Definition Tensor.hpp:621
Tensor & Conj_()
the Conj_ member function. Same as cytnx::linalg::Conj_(Tensor &Tin), where Tin is the current Tensor...
int device() const
the device-id of the Tensor
Definition Tensor.hpp:521
Tensor get(const std::vector< cytnx::Accessor > &accessors) const
get elements using Accessor (C++ API) / slices (python API)
Definition Tensor.hpp:961
const std::vector< cytnx_uint64 > & shape() const
the shape of the Tensor
Definition Tensor.hpp:541
An Enhanced tensor specifically designed for physical Tensor network simulation.
Definition UniTensor.hpp:1779
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:3061
UniTensor to(const int &device) const
move the current UniTensor to the assigned device.
Definition UniTensor.hpp:2287
UniTensor & operator*=(const UniTensor &rhs)
The multiplication assignment operator of the UniTensor.
Definition UniTensor.hpp:3649
Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:2968
std::vector< Tensor > & get_blocks_(const bool &silent=false)
Definition UniTensor.hpp:3041
Tensor & get_block_(const std::vector< cytnx_uint64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:2976
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:2624
UniTensor & operator/=(const UniTensor &rhs)
The division assignment operator of the UniTensor.
Definition UniTensor.hpp:3629
T & item()
Definition UniTensor.hpp:2103
bool is_contiguous() const
To tell whether the UniTensor is contiguous.
Definition UniTensor.hpp:2194
T get_elem(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:3935
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:2841
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:4059
UniTensor & set_label(const cytnx_int64 &idx, const char *new_label)
Definition UniTensor.hpp:2006
UniTensor & operator+=(const UniTensor &rhs)
The addition assignment operator of the UniTensor.
Definition UniTensor.hpp:3589
void to_dense_()
Convert the UniTensor to non-diagonal form, inplacely.
Definition UniTensor.hpp:3208
UniTensor reshape(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor.
Definition UniTensor.hpp:3171
std::vector< Tensor > get_blocks() const
Get all the blocks of the UniTensor.
Definition UniTensor.hpp:3025
UniTensor permute(const std::initializer_list< char * > &mapper, const cytnx_int64 &rowrank=-1) const
Definition UniTensor.hpp:2546
void normal_(const double &mean, const double &std, const unsigned int &seed=std::random_device()())
Generate a one-bond UniTensor with all elements are random numbers sampled from a normal (Gaussian) d...
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:2207
std::string uten_type_str() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor in 'string' form.
Definition UniTensor.hpp:2187
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:1869
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:2837
void permute_(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1)
permute the lags of the UniTensor, inplacely.
Definition UniTensor.hpp:2564
UniTensor & tag()
Set the UniTensor as a tagged UniTensor.
Definition UniTensor.hpp:3894
const Bond & bond_(const cytnx_uint64 &idx) const
Definition UniTensor.hpp:2248
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force=false)
Definition UniTensor.hpp:3239
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:2474
const T & at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:2695
UniTensor & relabels_(const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:2350
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:1818
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:2916
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:1841
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:4115
UniTensor get(const std::vector< Accessor > &accessors) const
Definition UniTensor.hpp:3146
T & at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:2717
UniTensor Conj() const
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:3721
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:2021
UniTensor set_rowrank(const cytnx_uint64 &new_rowrank) const
Definition UniTensor.hpp:2096
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:3679
cytnx_uint64 rowrank() const
Return the row rank of the UniTensor.
Definition UniTensor.hpp:2138
UniTensor & relabels_(const std::vector< std::string > &old_labels, const std::vector< std::string > &new_labels)
relables part or all of the labels in UniTensor by given new labels
Definition UniTensor.hpp:2389
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:3572
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:2075
UniTensor & Sub_(const Scalar &rhs)
The subtraction function for a given scalar.
Definition UniTensor.hpp:3424
UniTensor & relabel_(const cytnx_int64 &inx, const std::string &new_label)
rebable the lags in the UniTensor by given index.
Definition UniTensor.hpp:2461
UniTensor & operator/=(const Scalar &rhs)
The division assignment operator for a given scalar.
Definition UniTensor.hpp:3694
const bool & is_braket_form() const
Check whether the UniTensor is in braket form.
Definition UniTensor.hpp:2222
void set_elem(const std::vector< cytnx_uint64 > &locator, const T2 &rc)
Definition UniTensor.hpp:3945
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:4220
std::vector< cytnx_uint64 > shape() const
Get the shape of the UniTensor.
Definition UniTensor.hpp:2261
UniTensor to_dense()
Convert the UniTensor to non-diagonal form.
Definition UniTensor.hpp:3198
Scalar::Sproxy at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:2776
const Tensor & get_block_(const std::vector< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:2992
void reshape_(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor, inplacely.
Definition UniTensor.hpp:3183
UniTensor & set_labels(const std::vector< std::string > &new_labels)
Set new labels for all the bonds.
Definition UniTensor.hpp:2066
void permute_(const std::vector< std::string > &mapper, const cytnx_int64 &rowrank=-1)
permute the lags of the UniTensor, inplacely.
Definition UniTensor.hpp:2574
std::string name() const
Return the name of the UniTensor.
Definition UniTensor.hpp:2166
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=std::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.
const Scalar::Sproxy at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:2798
UniTensor & Add_(const Scalar &rhs)
The addition function for a given scalar.
Definition UniTensor.hpp:3394
UniTensor & Trace_(const std::string &a, const std::string &b)
Take the partial trance to the UniTensor, inplacely.
Definition UniTensor.hpp:3828
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:4007
Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition UniTensor.hpp:2761
UniTensor Trace(const std::string &a, const std::string &b) const
Take the partial trance to the UniTensor.
Definition UniTensor.hpp:3798
bool same_data(const UniTensor &rhs) const
Check whether the Blocks address are the same.
Definition UniTensor.hpp:3293
UniTensor astype(const unsigned int &dtype) const
Return a new UniTensor that cast to different data type.
Definition UniTensor.hpp:2505
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:4151
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:4021
UniTensor Transpose() const
Take the transpose of the UniTensor.
Definition UniTensor.hpp:3749
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:4193
UniTensor & set_label(const char *old_label, const std::string &new_label)
Definition UniTensor.hpp:2029
static UniTensor Load(const char *fname)
load a UniTensor from file
UniTensor & Dagger_()
Take the conjugate transpose to the UniTensor, inplacely.
Definition UniTensor.hpp:3881
void print_diagram(const bool &bond_info=false)
Plot the diagram of the UniTensor.
Definition UniTensor.hpp:2611
std::vector< Bond > & bonds()
Definition UniTensor.hpp:2246
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition UniTensor.hpp:2648
UniTensor & set_rowrank_(const cytnx_uint64 &new_rowrank)
Set the row rank of the UniTensor.
Definition UniTensor.hpp:2091
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:3069
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:1998
static UniTensor normal(const cytnx_uint64 &Nelem, const double &mean, const double &std, const std::vector< std::string > &in_labels={}, const unsigned int &seed=std::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 contiguous() const
Make the UniTensor contiguous by coalescing the memory (storage).
Definition UniTensor.hpp:2595
Tensor get_block(const cytnx_uint64 &idx=0) const
Get the block of the UniTensor for a given index.
Definition UniTensor.hpp:2826
const T & at(const std::vector< cytnx_uint64 > &locator) const
Get an element at specific location.
Definition UniTensor.hpp:2674
UniTensor & operator*=(const Scalar &rhs)
The multiplication assignment operator for a given scalar.
Definition UniTensor.hpp:3709
UniTensor relabels(const std::vector< std::string > &old_labels, const std::vector< std::string > &new_labels) const
replace part or all labels by given new labels for the bonds.
Definition UniTensor.hpp:2367
void contiguous_()
Make the UniTensor contiguous by coalescing the memory (storage), inplacely.
Definition UniTensor.hpp:2605
UniTensor normalize() const
normalize the current UniTensor instance with 2-norm.
Definition UniTensor.hpp:3772
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:4133
std::vector< Symmetry > syms() const
Return the symmetry type of the UniTensor.
Definition UniTensor.hpp:2214
UniTensor & Mul_(const UniTensor &rhs)
The multiplcation function of the UniTensor.
Definition UniTensor.hpp:3337
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:4095
void put_block_(Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index, inplacely.
Definition UniTensor.hpp:3101
void combineBonds(const std::vector< std::string > &indicators, const bool &force=false)
Combine the sevral bonds of the UniTensor.
Definition UniTensor.hpp:3230
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:2493
UniTensor & normalize_()
normalize the UniTensor, inplacely.
Definition UniTensor.hpp:3784
bool is_diag() const
To tell whether the UniTensor is in diagonal form.
Definition UniTensor.hpp:2200
int device() const
Return the device of the UniTensor.
Definition UniTensor.hpp:2160
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:3009
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:2936
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:3117
void set(const std::vector< Accessor > &accessors, const Tensor &rhs)
Definition UniTensor.hpp:3151
std::string dtype_str() const
Return the data type of the UniTensor in 'string' form.
Definition UniTensor.hpp:2173
UniTensor & operator+=(const Scalar &rhs)
The addition assignment operator for a given scalar.
Definition UniTensor.hpp:3664
UniTensor & Div_(const UniTensor &rhs)
The division function of the UniTensor.
Definition UniTensor.hpp:3379
UniTensor & Div_(const Scalar &rhs)
The division function for a given scalar.
Definition UniTensor.hpp:3439
Bond & bond_(const std::string &label)
Definition UniTensor.hpp:2252
cytnx_uint64 rank() const
Return the rank of the UniTensor.
Definition UniTensor.hpp:2132
Bond bond(const std::string &label) const
Definition UniTensor.hpp:2255
void group_basis_()
Group the same quantum number basis together.
Definition UniTensor.hpp:2634
void to_(const int &device)
move the current UniTensor to the assigned device (inplace).
Definition UniTensor.hpp:2276
UniTensor & Trace_(const cytnx_int64 &a=0, const cytnx_int64 &b=1)
Take the partial trance to the UniTensor, inplacely.
Definition UniTensor.hpp:3850
UniTensor & set_name(const std::string &in)
Set the name of the UniTensor.
Definition UniTensor.hpp:1983
UniTensor Trace(const cytnx_int64 &a=0, const cytnx_int64 &b=1) const
Take the partial trance to the UniTensor.
Definition UniTensor.hpp:3813
UniTensor & Add_(const UniTensor &rhs)
The addition function of the UniTensor.
Definition UniTensor.hpp:3316
UniTensor permute(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1) const
permute the lags of the UniTensor
Definition UniTensor.hpp:2523
UniTensor & set_label(const std::string &old_label, const char *new_label)
Definition UniTensor.hpp:2037
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:2536
unsigned int dtype() const
Return the data type of the UniTensor.
Definition UniTensor.hpp:2145
UniTensor Pow(const double &p) const
Power function.
UniTensor & Mul_(const Scalar &rhs)
The multiplication function for a given scalar.
Definition UniTensor.hpp:3409
UniTensor & operator-=(const UniTensor &rhs)
The subtraction assignment operator of the UniTensor.
Definition UniTensor.hpp:3609
Tensor get_block_(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:2981
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force, const bool &by_label)
Definition UniTensor.hpp:3215
UniTensor & set_label(const char *old_label, const char *new_label)
Definition UniTensor.hpp:2045
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:4171
bool is_blockform() const
Check whether the UniTensor is in block form.
Definition UniTensor.hpp:2268
UniTensor group_basis() const
Definition UniTensor.hpp:2636
UniTensor Dagger() const
Take the conjugate transpose to the UniTensor.
Definition UniTensor.hpp:3869
void set(const std::vector< Accessor > &accessors, const UniTensor &rhs)
Definition UniTensor.hpp:3154
const std::vector< Tensor > & get_blocks_(const bool &silent=false) const
Get all the blocks of the UniTensor, inplacely.
Definition UniTensor.hpp:3033
UniTensor & relabels_(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:2418
const Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:3000
bool elem_exists(const std::vector< cytnx_uint64 > &locator) const
Geiven the locator, check if the element exists.
Definition UniTensor.hpp:3925
UniTensor & Sub_(const UniTensor &rhs)
The subtraction function of the UniTensor.
Definition UniTensor.hpp:3358
UniTensor relabels(const std::initializer_list< char * > &new_labels) const
Definition UniTensor.hpp:2337
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:3261
void put_block(const Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index.
Definition UniTensor.hpp:3050
const Tensor & get_block_(const cytnx_uint64 &idx=0) const
Get the shared view of block for the given index.
Definition UniTensor.hpp:2898
static UniTensor Load(const std::string &fname)
load a UniTensor from file
const Bond & bond_(const std::string &label) const
Definition UniTensor.hpp:2251
Bond & bond_(const cytnx_uint64 &idx)
Definition UniTensor.hpp:2249
UniTensor relabel(const cytnx_int64 &inx, const std::string &new_label) const
rebable the lags in the UniTensor by given index.
Definition UniTensor.hpp:2448
UniTensor Mul(const UniTensor &rhs) const
The multiplication function of the UniTensor.
UniTensor relabels(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels) const
Definition UniTensor.hpp:2399
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:4049
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:2228
cytnx_int64 get_index(std::string label) const
Get the index of an desired label string.
Definition UniTensor.hpp:2235
const std::vector< Bond > & bonds() const
Get the bonds of the UniTensor.
Definition UniTensor.hpp:2241
Tensor get_block(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:2887
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:4036
UniTensor & Transpose_()
Take the transpose of the UniTensor, inplacely.
Definition UniTensor.hpp:3761
UniTensor clone() const
Clone (deep copy) the UniTensor.
Definition UniTensor.hpp:2297
vec2d< cytnx_uint64 > & get_itoi()
Definition UniTensor.hpp:4070
void print_blocks(const bool &full_info=true) const
Print all of the blocks in the UniTensor.
Definition UniTensor.hpp:2617
Scalar::Sproxy item() const
Definition UniTensor.hpp:2113
const vec2d< cytnx_uint64 > & get_itoi() const
get the q-indices on each leg for all the blocks
Definition UniTensor.hpp:4069
std::string device_str() const
Return the device of the UniTensor in 'string' form.
Definition UniTensor.hpp:2180
UniTensor & convert_from(const UniTensor &rhs, const bool &force=false)
Definition UniTensor.hpp:4077
UniTensor relabels(const std::vector< std::string > &new_labels) const
relables all of the labels in UniTensor.
Definition UniTensor.hpp:2328
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:3109
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:1920
UniTensor & Conj_()
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:3734
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=std::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...
cytnx_uint64 Nblocks() const
Return the number of blocks in the UniTensor.
Definition UniTensor.hpp:2126
Tensor get_block(const std::vector< cytnx_uint64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:2882
void Save(const char *fname) const
save a UniTensor to file
void uniform_(const double &low=0, const double &high=1, const unsigned int &seed=std::random_device()())
Generate a UniTensor with all elements are random numbers sampled from a uniform distribution,...
Bond bond(const cytnx_uint64 &idx) const
Definition UniTensor.hpp:2254
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:3994
Tensor get_block(const std::initializer_list< cytnx_int64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:2872
UniTensor & relabels_(const std::vector< std::string > &new_labels)
Set new labels for all the bonds.
Definition UniTensor.hpp:2312
const Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator) const
Get an element at specific location.
Definition UniTensor.hpp:2742
int uten_type() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor.
Definition UniTensor.hpp:2153
static UniTensor uniform(const cytnx_uint64 &Nelem, const double &low, const double &high, const std::vector< std::string > &in_labels={}, const unsigned int &seed=std::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...
Tensor & get_block_(const cytnx_uint64 &idx=0)
Definition UniTensor.hpp:2906
#define cytnx_warning_msg(is_true, format,...)
Definition cytnx_error.hpp:40
#define cytnx_error_msg(is_true, format,...)
Definition cytnx_error.hpp:16
cytnx::UniTensor Conj(const cytnx::UniTensor &UT)
Elementwise conjugate of the UniTensor.
cytnx::UniTensor Trace(const cytnx::UniTensor &Tin, const cytnx_int64 &a=0, const cytnx_int64 &b=1)
void Conj_(cytnx::UniTensor &UT)
Inplace elementwise conjugate of the UniTensor.
Tensor Norm(const Tensor &Tl)
Calculate the norm of a tensor.
Helper function to print vector with ODT:
Definition Accessor.hpp:12
Device_class Device
data on which devices.
double cytnx_double
Definition Type.hpp:53
Tensor linspace(const cytnx_double &start, const cytnx_double &end, const cytnx_uint64 &Nelem, const bool &endpoint=true, const unsigned int &dtype=Type.Double, const int &device=Device.cpu)
UniTensorType_class UTenType
UniTensor type.
uint32_t cytnx_uint32
Definition Type.hpp:56
std::complex< double > cytnx_complex128
Definition Type.hpp:63
float cytnx_float
Definition Type.hpp:54
int16_t cytnx_int16
Definition Type.hpp:60
std::complex< float > cytnx_complex64
Definition Type.hpp:62
int32_t cytnx_int32
Definition Type.hpp:59
Tensor arange(const cytnx_int64 &Nelem)
create an rank-1 Tensor with incremental unsigned integer elements start with [0,Nelem)
UniTensor Contract(const UniTensor &inL, const UniTensor &inR, const bool &cacheL=false, const bool &cacheR=false)
Contract two UniTensor by tracing the ranks with common labels.
uint16_t cytnx_uint16
Definition Type.hpp:57
Tensor ones(const cytnx_uint64 &Nelem, const unsigned int &dtype=Type.Double, const int &device=Device.cpu)
create an rank-1 Tensor with all the elements are initialized with one.
uint64_t cytnx_uint64
Definition Type.hpp:55
int64_t cytnx_int64
Definition Type.hpp:58
std::vector< std::vector< T > > vec2d
Definition Type.hpp:51
UniTensor Contracts(const std::vector< UniTensor > &TNs, const std::string &order, const bool &optimal)
Contract multiple UniTensor by tracing the ranks with common labels with pairwise operation.
Tensor zeros(const cytnx_uint64 &Nelem, const unsigned int &dtype=Type.Double, const int &device=Device.cpu)
create an rank-1 Tensor with all the elements are initialized with zero.
Type_class Type
data type
tmp
Definition sp.py:8