1#ifndef CYTNX_UNITENSOR_H_
2#define CYTNX_UNITENSOR_H_
8#include "utils/utils.hpp"
14#include <initializer_list>
22#include "backend/Scalar.hpp"
31 class UniTensorType_class {
33 enum :
int {
Void = -99, Dense = 0, Sparse = 1, Block = 2, BlockFermionic = 3 };
34 std::string getname(
const int &ut_type)
const;
58 class UniTensor_base :
public intrusive_ptr_base<UniTensor_base> {
66 std::vector<std::string> _labels;
67 std::vector<Bond> _bonds;
68 std::vector<Symmetry> syms_cache;
70 bool _update_braket() {
71 if (_bonds.size() == 0)
return false;
73 if (this->_bonds[0].type() != bondType::BD_REG) {
75 for (
unsigned int i = 0; i < this->_bonds.size(); i++) {
76 if (i < this->_rowrank) {
77 if (this->_bonds[i].type() != bondType::BD_KET)
return false;
79 if (this->_bonds[i].type() != bondType::BD_BRA)
return false;
88 friend class UniTensor;
89 friend class DenseUniTensor;
90 friend class BlockUniTensor;
91 friend class BlockFermionicUniTensor;
95 _name(std::string(
"")),
96 _is_braket_form(false),
102 UniTensor_base(
const UniTensor_base &rhs);
103 UniTensor_base &operator=(UniTensor_base &rhs);
105 cytnx_uint64 rowrank()
const {
return this->_rowrank; }
106 bool is_diag()
const {
return this->_is_diag; }
107 const bool &is_braket_form()
const {
return this->_is_braket_form; }
108 const bool &is_tag()
const {
return this->_is_tag; }
109 const std::vector<std::string> &labels()
const {
return this->_labels; }
116 cytnx_int64 get_index(std::string label)
const {
117 std::vector<std::string> labels = this->_labels;
118 for (cytnx_uint64 i = 0; i < labels.size(); i++) {
119 if (labels[i] == label)
return i;
123 const std::vector<Bond> &bonds()
const {
return this->_bonds; }
125 Bond &bond_(
const cytnx_uint64 &idx) {
126 cytnx_error_msg(idx >= this->rank(),
"[ERROR][bond] index %d out of bound, total %d\n", idx,
128 return this->_bonds[idx];
131 Bond &bond_(
const std::string &label) {
132 auto res = std::find(this->_labels.begin(), this->_labels.end(), label);
133 cytnx_error_msg(res == this->_labels.end(),
"[ERROR] label %s not exists.\n", label.c_str());
134 cytnx_uint64 idx = std::distance(this->_labels.begin(), res);
136 return this->bond_(idx);
139 const std::string &name()
const {
return this->_name; }
140 cytnx_uint64 rank()
const {
142 "[ERROR][UniTensor_base][rank] inconsistent metadata: labels.size()=%zu, "
143 "bonds.size()=%zu.%s",
144 this->_labels.size(), this->_bonds.size(),
"\n");
145 return this->_labels.size();
147 void set_name_(
const std::string &in) { this->_name = in; }
148 [[deprecated(
"Please use set_name_(const std::string &in) instead.")]]
void set_name(
149 const std::string &in) {
164 void set_label_(
const std::string &oldlabel,
const std::string &new_label) {
166 auto res = std::find(this->_labels.begin(), this->_labels.end(), oldlabel);
167 cytnx_error_msg(res == this->_labels.end(),
"[ERROR] label %s not exists.\n",
169 idx = std::distance(this->_labels.begin(), res);
171 cytnx_error_msg(idx >= this->_labels.size(),
"[ERROR] index exceed the rank of UniTensor%s",
175 for (cytnx_uint64 i = 0; i < this->_labels.size(); i++) {
176 if (i == idx)
continue;
177 if (new_label == this->_labels[i]) {
182 cytnx_error_msg(is_dup,
"[ERROR] alreay has a label that is the same as the input label%s",
184 this->_labels[idx] = new_label;
186 void set_label_(
const cytnx_int64 &inx,
const std::string &new_label) {
188 cytnx_error_msg(inx >= this->_labels.size(),
"[ERROR] index exceed the rank of UniTensor%s",
192 for (cytnx_uint64 i = 0; i < this->_labels.size(); i++) {
193 if (i == inx)
continue;
194 if (new_label == this->_labels[i]) {
199 cytnx_error_msg(is_dup,
"[ERROR] alreay has a label that is the same as the input label%s",
201 this->_labels[inx] = new_label;
204 "Please use set_label_(const std::string &oldlabel, const std::string "
205 "&new_label) instead.")]]
void
206 set_label(
const std::string &oldlabel,
const std::string &new_label) {
207 this->set_label_(oldlabel, new_label);
210 "Please use set_label_(const cytnx_int64 &inx, const std::string &new_label) "
212 set_label(
const cytnx_int64 &inx,
const std::string &new_label) {
213 this->set_label_(inx, new_label);
216 [[deprecated(
"Please use relabel_(const std::vector<std::string> &new_labels) instead.")]]
void
217 set_labels(
const std::vector<std::string> &new_labels);
218 void relabel_(
const std::vector<std::string> &new_labels);
219 [[deprecated(
"Please use relabel_(const std::vector<std::string> &new_labels) instead.")]]
void
220 relabels_(
const std::vector<std::string> &new_labels);
221 void relabel_(
const std::vector<std::string> &old_labels,
222 const std::vector<std::string> &new_labels);
224 "Please use relabel_(const std::vector<std::string> &old_labels, const "
225 "std::vector<std::string> &new_labels) instead.")]]
void
226 relabels_(
const std::vector<std::string> &old_labels,
227 const std::vector<std::string> &new_labels);
228 void relabel_(
const std::string &old_label,
const std::string &new_label) {
229 this->set_label_(old_label, new_label);
231 void relabel_(
const cytnx_int64 &inx,
const std::string &new_label) {
232 this->set_label_(inx, new_label);
235 int uten_type() {
return this->uten_type_id; }
236 std::string uten_type_str()
const {
return UTenType.getname(this->uten_type_id); }
241 virtual void Init(
const std::vector<Bond> &bonds,
242 const std::vector<std::string> &in_labels = {},
243 const cytnx_int64 &rowrank = -1,
const unsigned int &dtype =
Type.Double,
244 const int &device =
Device.cpu,
const bool &is_diag =
false,
245 const bool &no_alloc =
false,
const std::string &name =
"");
247 virtual void Init_by_Tensor(
const Tensor &in,
const bool &is_diag =
false,
248 const cytnx_int64 &rowrank = -1,
const std::string &name =
"");
249 virtual std::vector<cytnx_uint64> shape()
const;
250 virtual std::vector<bool> signflip()
const;
251 virtual bool is_blockform()
const;
252 virtual bool is_contiguous()
const;
253 virtual void to_(
const int &device);
254 virtual boost::intrusive_ptr<UniTensor_base> to(
const int &device);
255 virtual boost::intrusive_ptr<UniTensor_base> clone()
const;
256 virtual unsigned int dtype()
const;
257 virtual int device()
const;
258 virtual std::string dtype_str()
const;
259 virtual std::string device_str()
const;
260 virtual void set_rowrank_(
const cytnx_uint64 &new_rowrank);
261 virtual boost::intrusive_ptr<UniTensor_base> set_rowrank(
const cytnx_uint64 &new_rowrank)
const;
263 virtual boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<cytnx_int64> &mapper,
264 const cytnx_int64 &rowrank = -1);
265 virtual boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<std::string> &mapper,
266 const cytnx_int64 &rowrank = -1);
270 virtual void permute_(
const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank = -1);
271 virtual void permute_(
const std::vector<std::string> &mapper,
const cytnx_int64 &rowrank = -1);
273 virtual boost::intrusive_ptr<UniTensor_base> permute_nosignflip(
274 const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank = -1);
275 virtual boost::intrusive_ptr<UniTensor_base> permute_nosignflip(
276 const std::vector<std::string> &mapper,
const cytnx_int64 &rowrank = -1);
277 virtual void permute_nosignflip_(
const std::vector<cytnx_int64> &mapper,
278 const cytnx_int64 &rowrank = -1);
279 virtual void permute_nosignflip_(
const std::vector<std::string> &mapper,
280 const cytnx_int64 &rowrank = -1);
284 virtual void twist_(
const cytnx_int64 &idx);
285 virtual void twist_(
const std::string &label);
286 virtual void fermion_twists_();
288 virtual boost::intrusive_ptr<UniTensor_base> contiguous_();
289 virtual boost::intrusive_ptr<UniTensor_base> contiguous();
290 virtual boost::intrusive_ptr<UniTensor_base> apply_();
291 virtual boost::intrusive_ptr<UniTensor_base> apply();
292 virtual void print_diagram(
const bool &bond_info =
false)
const;
293 virtual void print_blocks(
const bool &full_info =
true)
const;
294 virtual void print_block(
const cytnx_int64 &idx,
const bool &full_info =
true)
const;
296 virtual boost::intrusive_ptr<UniTensor_base> astype(
const unsigned int &dtype)
const;
298 virtual cytnx_uint64 Nblocks()
const {
return 0; };
299 virtual Tensor get_block(
const cytnx_uint64 &idx = 0)
const;
302 virtual Tensor get_block(
const std::vector<cytnx_int64> &qidx,
303 const bool &force)
const;
305 virtual const Tensor &get_block_(
const cytnx_uint64 &idx = 0)
307 virtual const Tensor &get_block_(
const std::vector<cytnx_int64> &qidx,
308 const bool &force)
const;
309 virtual Tensor &get_block_(
const cytnx_uint64 &idx = 0);
311 virtual Tensor &get_block_(
const std::vector<cytnx_int64> &qidx,
313 virtual bool same_data(
const boost::intrusive_ptr<UniTensor_base> &rhs)
const;
315 virtual std::vector<Tensor> get_blocks()
const;
316 virtual const std::vector<Tensor> &get_blocks_(
const bool &)
const;
317 virtual std::vector<Tensor> &get_blocks_(
const bool &);
319 virtual void put_block(
const Tensor &in,
const cytnx_uint64 &idx = 0);
320 virtual void put_block_(Tensor &in,
const cytnx_uint64 &idx = 0);
321 virtual void put_block(
const Tensor &in,
const std::vector<cytnx_int64> &qidx);
322 virtual void put_block_(Tensor &in,
const std::vector<cytnx_int64> &qidx);
325 virtual boost::intrusive_ptr<UniTensor_base> get(
const std::vector<Accessor> &accessors);
328 virtual void set(
const std::vector<Accessor> &accessors,
const Tensor &rhs);
330 virtual void reshape_(
const std::vector<cytnx_int64> &new_shape,
331 const cytnx_uint64 &rowrank = 0);
332 virtual boost::intrusive_ptr<UniTensor_base> reshape(
const std::vector<cytnx_int64> &new_shape,
333 const cytnx_uint64 &rowrank = 0);
334 virtual boost::intrusive_ptr<UniTensor_base> to_dense();
335 virtual void to_dense_();
336 virtual void combineBond(
const std::vector<std::string> &indicators,
const bool &force =
false);
337 virtual void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &force,
338 const bool &by_label);
339 virtual void combineBonds(
const std::vector<std::string> &indicators,
340 const bool &force =
false);
341 virtual void combineBonds(
const std::vector<cytnx_int64> &indicators,
342 const bool &force =
false);
343 virtual boost::intrusive_ptr<UniTensor_base> contract(
344 const boost::intrusive_ptr<UniTensor_base> &rhs,
const bool &mv_elem_self =
false,
345 const bool &mv_elem_rhs =
false);
346 virtual std::vector<Bond> getTotalQnums(
const bool &physical =
false);
347 virtual std::vector<std::vector<cytnx_int64>> get_blocks_qnums()
const;
348 virtual void Trace_(
const std::string &a,
const std::string &b);
349 virtual void Trace_(
const cytnx_int64 &a,
const cytnx_int64 &b);
351 virtual boost::intrusive_ptr<UniTensor_base>
Trace(
const std::string &a,
const std::string &b);
352 virtual boost::intrusive_ptr<UniTensor_base>
Trace(
const cytnx_int64 &a,
const cytnx_int64 &b);
354 virtual boost::intrusive_ptr<UniTensor_base> relabel(
355 const std::vector<std::string> &new_labels);
356 virtual boost::intrusive_ptr<UniTensor_base> relabels(
357 const std::vector<std::string> &new_labels);
359 virtual boost::intrusive_ptr<UniTensor_base> relabel(
360 const std::vector<std::string> &old_labels,
const std::vector<std::string> &new_labels);
361 virtual boost::intrusive_ptr<UniTensor_base> relabels(
362 const std::vector<std::string> &old_labels,
const std::vector<std::string> &new_labels);
364 virtual boost::intrusive_ptr<UniTensor_base> relabel(
const std::string &old_label,
365 const std::string &new_label);
367 virtual boost::intrusive_ptr<UniTensor_base> relabel(
const cytnx_int64 &inx,
368 const std::string &new_label);
370 virtual std::vector<Symmetry> syms()
const;
378 virtual void Add_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
379 virtual void Add_(
const Scalar &rhs);
381 virtual void Mul_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
382 virtual void Mul_(
const Scalar &rhs);
384 virtual void Sub_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
385 virtual void Sub_(
const Scalar &rhs);
386 virtual void lSub_(
const Scalar &lhs);
388 virtual void Div_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
389 virtual void Div_(
const Scalar &rhs);
390 virtual void lDiv_(
const Scalar &lhs);
392 virtual Tensor
Norm()
const;
393 virtual boost::intrusive_ptr<UniTensor_base> normalize();
394 virtual void normalize_();
396 virtual boost::intrusive_ptr<UniTensor_base>
Conj();
397 virtual void Conj_();
399 virtual boost::intrusive_ptr<UniTensor_base> Transpose();
400 virtual void Transpose_();
402 virtual boost::intrusive_ptr<UniTensor_base> Dagger();
403 virtual void Dagger_();
407 virtual void truncate_(
const std::string &label,
const cytnx_uint64 &dim);
408 virtual void truncate_(
const cytnx_int64 &bond_idx,
const cytnx_uint64 &dim);
410 virtual bool elem_exists(
const std::vector<cytnx_uint64> &locator)
const;
413 virtual Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator);
414 virtual const Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator)
const;
416 virtual cytnx_complex128 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
417 const cytnx_complex128 &aux);
418 virtual cytnx_complex64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
419 const cytnx_complex64 &aux);
420 virtual cytnx_double &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
421 const cytnx_double &aux);
422 virtual cytnx_float &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
423 const cytnx_float &aux);
424 virtual cytnx_uint64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
425 const cytnx_uint64 &aux);
426 virtual cytnx_int64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
427 const cytnx_int64 &aux);
428 virtual cytnx_uint32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
429 const cytnx_uint32 &aux);
430 virtual cytnx_int32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
431 const cytnx_int32 &aux);
432 virtual cytnx_uint16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
433 const cytnx_uint16 &aux);
434 virtual cytnx_int16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
435 const cytnx_int16 &aux);
437 virtual const cytnx_complex128 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
438 const cytnx_complex128 &aux)
const;
439 virtual const cytnx_complex64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
440 const cytnx_complex64 &aux)
const;
441 virtual const cytnx_double &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
442 const cytnx_double &aux)
const;
443 virtual const cytnx_float &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
444 const cytnx_float &aux)
const;
445 virtual const cytnx_uint64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
446 const cytnx_uint64 &aux)
const;
447 virtual const cytnx_int64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
448 const cytnx_int64 &aux)
const;
449 virtual const cytnx_uint32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
450 const cytnx_uint32 &aux)
const;
451 virtual const cytnx_int32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
452 const cytnx_int32 &aux)
const;
453 virtual const cytnx_uint16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
454 const cytnx_uint16 &aux)
const;
455 virtual const cytnx_int16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
456 const cytnx_int16 &aux)
const;
458 virtual void from_(
const boost::intrusive_ptr<UniTensor_base> &rhs,
bool force,
459 cytnx_double tol = 0.);
461 virtual void group_basis_();
462 virtual const std::vector<cytnx_uint64> &get_qindices(
const cytnx_uint64 &bidx)
const;
463 virtual std::vector<cytnx_uint64> &get_qindices(
const cytnx_uint64 &bidx);
464 virtual const vec2d<cytnx_uint64> &get_itoi()
const;
465 virtual vec2d<cytnx_uint64> &get_itoi();
467 virtual void _save_dispatch(std::fstream &f)
const;
468 virtual void _load_dispatch(std::fstream &f,
unsigned int version);
470 virtual ~UniTensor_base(){};
476 class DenseUniTensor :
public UniTensor_base {
480 std::vector<Tensor> _interface_block;
481 boost::intrusive_ptr<DenseUniTensor> clone_meta()
const {
482 boost::intrusive_ptr<DenseUniTensor> tmp(
new DenseUniTensor());
483 tmp->_bonds = vec_clone(this->_bonds);
484 tmp->_labels = this->_labels;
485 tmp->syms_cache = vec_clone(this->syms_cache);
486 tmp->_is_braket_form = this->_is_braket_form;
487 tmp->_rowrank = this->_rowrank;
488 tmp->_is_diag = this->_is_diag;
489 tmp->_name = this->_name;
490 tmp->_is_tag = this->_is_tag;
495 DenseUniTensor() { this->uten_type_id =
UTenType.Dense; };
496 friend class UniTensor;
504 void Init(
const std::vector<Bond> &bonds,
const std::vector<std::string> &in_labels = {},
505 const cytnx_int64 &rowrank = -1,
const unsigned int &dtype =
Type.Double,
506 const int &device =
Device.cpu,
const bool &is_diag =
false,
507 const bool &no_alloc =
false,
const std::string &name =
"");
509 void Init_by_Tensor(
const Tensor &in_tensor,
const bool &is_diag =
false,
510 const cytnx_int64 &rowrank = -1,
const std::string &name =
"");
511 std::vector<cytnx_uint64> shape()
const {
512 if (this->_is_diag) {
513 std::vector<cytnx_uint64> shape = this->_block.shape();
514 shape.push_back(shape[0]);
517 return this->_block.shape();
520 bool is_blockform()
const {
return false; }
521 void to_(
const int &device) { this->_block.to_(device); }
522 boost::intrusive_ptr<UniTensor_base> to(
const int &device) {
523 if (this->device() == device) {
524 std::vector<Tensor> _interface_block;
527 boost::intrusive_ptr<UniTensor_base> out = this->clone();
532 void set_rowrank_(
const cytnx_uint64 &new_rowrank) {
534 "[ERROR] rowrank cannot exceed the rank of UniTensor.%s",
"\n");
535 if (this->is_diag()) {
536 cytnx_error_msg(new_rowrank != 1,
"[ERROR] rowrank should be [==1] when is_diag =true!.%s",
540 this->_rowrank = new_rowrank;
543 boost::intrusive_ptr<UniTensor_base> set_rowrank(
const cytnx_uint64 &new_rowrank)
const {
544 boost::intrusive_ptr<DenseUniTensor> out_raw = this->clone_meta();
545 out_raw->_block = this->_block;
546 out_raw->set_rowrank_(new_rowrank);
550 boost::intrusive_ptr<UniTensor_base> clone()
const {
551 boost::intrusive_ptr<DenseUniTensor> tmp = this->clone_meta();
552 tmp->_block = this->_block.clone();
555 bool is_contiguous()
const {
return this->_block.is_contiguous(); }
556 unsigned int dtype()
const {
return this->_block.dtype(); }
557 int device()
const {
return this->_block.device(); }
558 std::string dtype_str()
const {
return Type.getname(this->_block.dtype()); }
559 std::string device_str()
const {
return Device.getname(this->_block.device()); }
569 boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<cytnx_int64> &mapper,
570 const cytnx_int64 &rowrank = -1);
571 boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<std::string> &mapper,
572 const cytnx_int64 &rowrank = -1);
582 void permute_(
const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank = -1);
583 void permute_(
const std::vector<std::string> &mapper,
const cytnx_int64 &rowrank = -1);
585 void twist_(
const cytnx_int64 &idx)
override {
589 void twist_(
const std::string &label)
override {
594 void fermion_twists_()
override {
599 boost::intrusive_ptr<UniTensor_base> relabel(
const std::vector<std::string> &new_labels);
600 boost::intrusive_ptr<UniTensor_base> relabels(
const std::vector<std::string> &new_labels);
602 boost::intrusive_ptr<UniTensor_base> relabel(
const std::vector<std::string> &old_labels,
603 const std::vector<std::string> &new_labels);
604 boost::intrusive_ptr<UniTensor_base> relabels(
const std::vector<std::string> &old_labels,
605 const std::vector<std::string> &new_labels);
617 boost::intrusive_ptr<UniTensor_base> relabel(
const std::string &old_label,
618 const std::string &new_label);
619 boost::intrusive_ptr<UniTensor_base> relabel(
const cytnx_int64 &inx,
620 const std::string &new_label);
622 boost::intrusive_ptr<UniTensor_base> astype(
const unsigned int &dtype)
const {
623 boost::intrusive_ptr<DenseUniTensor> tmp = this->clone_meta();
624 tmp->_block = this->_block.astype(dtype);
628 std::vector<Symmetry> syms()
const {
629 cytnx_error_msg(
true,
"[ERROR][DenseUniTensor] dense unitensor does not have symmetry.%s",
631 return std::vector<Symmetry>();
634 boost::intrusive_ptr<UniTensor_base> contiguous_() {
639 this->_block = this->_block.contiguous();
640 return boost::intrusive_ptr<UniTensor_base>(
this);
642 boost::intrusive_ptr<UniTensor_base> contiguous() {
644 if (this->is_contiguous()) {
645 boost::intrusive_ptr<UniTensor_base> out(
this);
648 boost::intrusive_ptr<DenseUniTensor> tmp = this->clone_meta();
649 tmp->_block = this->_block.contiguous();
654 boost::intrusive_ptr<UniTensor_base> apply_() {
655 return boost::intrusive_ptr<UniTensor_base>(
this);
657 boost::intrusive_ptr<UniTensor_base> apply() {
659 boost::intrusive_ptr<UniTensor_base> out(
this);
663 void print_diagram(
const bool &bond_info =
false)
const;
664 void print_blocks(
const bool &full_info =
true)
const;
665 void print_block(
const cytnx_int64 &idx,
const bool &full_info =
true)
const;
666 Tensor get_block()
const {
return this->_block.clone(); }
667 Tensor get_block(
const cytnx_uint64 &idx)
const {
669 "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %llu "
670 "invalid. Use get_block(0).\n",
671 (
unsigned long long)idx);
672 return this->_block.clone();
675 Tensor get_block(
const std::vector<cytnx_int64> &qidx,
const bool &force)
const {
677 true,
"[ERROR][DenseUniTensor] try to get_block() using qidx on a non-symmetry UniTensor%s",
682 const Tensor &get_block_(
const std::vector<cytnx_int64> &qidx,
const bool &force)
const {
685 "[ERROR][DenseUniTensor] try to get_block_() using qidx on a non-symmetry UniTensor%s",
689 Tensor &get_block_(
const std::vector<cytnx_int64> &qidx,
const bool &force) {
692 "[ERROR][DenseUniTensor] try to get_block_() using qidx on a non-symmetry UniTensor%s",
698 Tensor &get_block_() {
return this->_block; }
699 Tensor &get_block_(
const cytnx_uint64 &idx) {
701 "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %llu "
702 "invalid. Use get_block_(0).\n",
703 (
unsigned long long)idx);
707 const Tensor &get_block_()
const {
return this->_block; }
708 const Tensor &get_block_(
const cytnx_uint64 &idx)
const {
710 "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %llu "
711 "invalid. Use get_block_(0).\n",
712 (
unsigned long long)idx);
716 cytnx_uint64 Nblocks()
const {
return 1; };
717 std::vector<Tensor> get_blocks()
const {
718 std::vector<Tensor> out;
720 true,
"[ERROR][DenseUniTensor] Cannot use get_blocks(), use get_block() instead!%s",
"\n");
723 const std::vector<Tensor> &get_blocks_(
const bool &silent =
false)
const {
725 true,
"[ERROR][DenseUniTensor] Cannot use get_blocks_(), use get_block_() instead!%s",
727 return this->_interface_block;
729 std::vector<Tensor> &get_blocks_(
const bool &silent =
false) {
731 true,
"[ERROR][DenseUniTensor] Cannot use get_blocks_(), use get_block_() instead!%s",
733 return this->_interface_block;
736 void put_block(
const Tensor &in) {
745 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
750 if (this->is_diag()) {
752 in.shape() != this->_block.shape(),
753 "[ERROR][DenseUniTensor][put_block] the input tensor shape does not match.%s",
"\n");
754 this->_block = in.clone();
757 in.shape() != this->shape(),
758 "[ERROR][DenseUniTensor][put_block] the input tensor shape does not match.%s",
"\n");
759 this->_block = in.clone();
762 void put_block(
const Tensor &in,
const cytnx_uint64 &idx) {
764 "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %llu "
765 "invalid. Use put_block(0).\n",
766 (
unsigned long long)idx);
770 void put_block_(Tensor &in) {
779 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
784 if (this->is_diag()) {
786 in.shape() != this->_block.shape(),
787 "[ERROR][DenseUniTensor][put_block] the input tensor shape does not match.%s",
"\n");
791 in.shape() != this->shape(),
792 "[ERROR][DenseUniTensor][put_block] the input tensor shape does not match.%s",
"\n");
796 void put_block_(Tensor &in,
const cytnx_uint64 &idx) {
798 "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %llu "
799 "invalid. Use put_block_(0).\n",
800 (
unsigned long long)idx);
804 void put_block(
const Tensor &in,
const std::vector<cytnx_int64> &qidx) {
806 true,
"[ERROR][DenseUniTensor] try to put_block using qidx on a non-symmetry UniTensor%s",
809 void put_block_(Tensor &in,
const std::vector<cytnx_int64> &qidx) {
811 true,
"[ERROR][DenseUniTensor] try to put_block using qidx on a non-symmetry UniTensor%s",
815 boost::intrusive_ptr<UniTensor_base> get(
const std::vector<Accessor> &accessors);
816 void set(
const std::vector<Accessor> &accessors,
const Tensor &rhs);
818 void reshape_(
const std::vector<cytnx_int64> &new_shape,
const cytnx_uint64 &rowrank = 0);
819 boost::intrusive_ptr<UniTensor_base> reshape(
const std::vector<cytnx_int64> &new_shape,
820 const cytnx_uint64 &rowrank = 0);
821 boost::intrusive_ptr<UniTensor_base> to_dense();
823 void combineBond(
const std::vector<std::string> &indicators,
const bool &force =
true);
824 void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &force,
825 const bool &by_label);
826 void combineBonds(
const std::vector<std::string> &indicators,
const bool &force =
true);
827 void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &force =
true);
828 boost::intrusive_ptr<UniTensor_base> contract(
const boost::intrusive_ptr<UniTensor_base> &rhs,
829 const bool &mv_elem_self =
false,
830 const bool &mv_elem_rhs =
false);
831 std::vector<Bond> getTotalQnums(
const bool &physical =
false) {
833 "getTotalQnums can only operate on UniTensor with symmetry.\n");
834 return std::vector<Bond>();
837 std::vector<std::vector<cytnx_int64>> get_blocks_qnums()
const {
839 "get_blocks_qnums can only operate on UniTensor with symmetry.\n");
840 return std::vector<std::vector<cytnx_int64>>();
843 bool same_data(
const boost::intrusive_ptr<UniTensor_base> &rhs)
const {
844 if (rhs->uten_type() !=
UTenType.Dense)
return false;
846 return this->get_block_().same_data(rhs->get_block_());
852 void Add_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
853 void Add_(
const Scalar &rhs);
855 void Mul_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
856 void Mul_(
const Scalar &rhs);
858 void Sub_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
859 void Sub_(
const Scalar &rhs);
860 void lSub_(
const Scalar &lhs);
862 void Div_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
863 void Div_(
const Scalar &rhs);
864 void lDiv_(
const Scalar &lhs);
866 void Conj_() { this->_block.Conj_(); };
868 boost::intrusive_ptr<UniTensor_base>
Conj() {
869 boost::intrusive_ptr<UniTensor_base> out = this->clone();
874 boost::intrusive_ptr<UniTensor_base> Transpose() {
875 boost::intrusive_ptr<UniTensor_base> out = this->clone();
881 boost::intrusive_ptr<UniTensor_base> normalize() {
882 boost::intrusive_ptr<UniTensor_base> out = this->clone();
888 boost::intrusive_ptr<UniTensor_base> Dagger() {
889 boost::intrusive_ptr<UniTensor_base> out = this->
Conj();
906 void Trace_(
const cytnx_int64 &a,
const cytnx_int64 &b);
907 void Trace_(
const std::string &a,
const std::string &b);
908 boost::intrusive_ptr<UniTensor_base>
Trace(
const std::string &a,
const std::string &b) {
909 boost::intrusive_ptr<UniTensor_base> out = this->clone();
913 boost::intrusive_ptr<UniTensor_base>
Trace(
const cytnx_int64 &a,
const cytnx_int64 &b) {
914 boost::intrusive_ptr<UniTensor_base> out = this->clone();
921 const Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator)
const {
923 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
925 return Scalar::Sproxy();
927 const cytnx_complex128 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
928 const cytnx_complex128 &aux)
const {
930 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
932 return cytnx_complex128(0, 0);
934 const cytnx_complex64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
935 const cytnx_complex64 &aux)
const {
937 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
939 return cytnx_complex64(0, 0);
941 const cytnx_double &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
942 const cytnx_double &aux)
const {
944 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
948 const cytnx_float &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
949 const cytnx_float &aux)
const {
951 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
955 const cytnx_uint64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
956 const cytnx_uint64 &aux)
const {
958 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
962 const cytnx_int64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
963 const cytnx_int64 &aux)
const {
965 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
969 const cytnx_uint32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
970 const cytnx_uint32 &aux)
const {
972 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
976 const cytnx_int32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
977 const cytnx_int32 &aux)
const {
979 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
983 const cytnx_uint16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
984 const cytnx_uint16 &aux)
const {
986 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
990 const cytnx_int16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
991 const cytnx_int16 &aux)
const {
993 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
998 Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator) {
1000 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
1002 return Scalar::Sproxy();
1004 cytnx_complex128 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1005 const cytnx_complex128 &aux) {
1007 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
1009 return *(cytnx_complex128 *)
nullptr;
1011 cytnx_complex64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1012 const cytnx_complex64 &aux) {
1014 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
1016 return *(cytnx_complex64 *)
nullptr;
1018 cytnx_double &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_double &aux) {
1020 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
1022 return *(cytnx_double *)
nullptr;
1024 cytnx_float &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_float &aux) {
1026 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
1028 return *(cytnx_float *)
nullptr;
1030 cytnx_uint64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint64 &aux) {
1032 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
1034 return *(cytnx_uint64 *)
nullptr;
1036 cytnx_int64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int64 &aux) {
1038 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
1040 return *(cytnx_int64 *)
nullptr;
1042 cytnx_uint32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint32 &aux) {
1044 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
1046 return *(cytnx_uint32 *)
nullptr;
1048 cytnx_int32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int32 &aux) {
1050 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
1052 return *(cytnx_int32 *)
nullptr;
1054 cytnx_uint16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint16 &aux) {
1056 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
1058 return *(cytnx_uint16 *)
nullptr;
1060 cytnx_int16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int16 &aux) {
1062 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
1064 return *(cytnx_int16 *)
nullptr;
1067 bool elem_exists(
const std::vector<cytnx_uint64> &locator)
const {
1069 true,
"[ERROR][DenseUniTensor] elem_exists can only be used on UniTensor with Symmetry.%s",
1073 if (!this->is_tag()) {
1074 for (
int i = 0; i < this->_rowrank; i++) {
1075 this->_bonds[i] = this->_bonds[i].retype(BD_KET);
1077 for (
int i = this->_rowrank; i < this->_bonds.size(); i++) {
1078 this->_bonds[i] = this->_bonds[i].retype(BD_BRA);
1080 this->_is_tag =
true;
1081 this->_is_braket_form = this->_update_braket();
1093 void truncate_(
const cytnx_int64 &bond_idx,
const cytnx_uint64 &dim);
1094 void truncate_(
const std::string &label,
const cytnx_uint64 &dim);
1096 void from_(
const boost::intrusive_ptr<UniTensor_base> &rhs,
bool force, cytnx_double tol = 0.);
1098 void group_basis_() {
1099 cytnx_warning_msg(
true,
"[WARNING] group basis will not have any effect on DensUniTensor.%s",
1103 void _save_dispatch(std::fstream &f)
const;
1104 void _load_dispatch(std::fstream &f,
unsigned int version);
1106 const std::vector<cytnx_uint64> &get_qindices(
const cytnx_uint64 &bidx)
const {
1107 cytnx_error_msg(
true,
"[ERROR] get_qindices can only be unsed on UniTensor with Symmetry.%s",
1110 std::vector<cytnx_uint64> &get_qindices(
const cytnx_uint64 &bidx) {
1111 cytnx_error_msg(
true,
"[ERROR] get_qindices can only be unsed on UniTensor with Symmetry.%s",
1115 const vec2d<cytnx_uint64> &get_itoi()
const {
1116 cytnx_error_msg(
true,
"[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s",
1119 vec2d<cytnx_uint64> &get_itoi() {
1120 cytnx_error_msg(
true,
"[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s",
1130 class BlockUniTensor :
public UniTensor_base {
1133 std::vector<std::vector<cytnx_uint64>>
1134 _inner_to_outer_idx;
1135 std::vector<Tensor> _blocks;
1136 Tensor NullRefTensor;
1141 void _fx_get_total_fluxs(std::vector<cytnx_uint64> &loc,
const std::vector<Symmetry> &syms,
1142 std::vector<cytnx_int64> &total_qns) {
1144 loc.size() != this->_bonds.size(),
1145 "[ERROR][BlockUniTensor] qnum location rank does not match the number of bonds.%s",
"\n");
1147 "[ERROR][BlockUniTensor] total_qns size does not match symmetry count.%s",
1149 std::fill(total_qns.begin(), total_qns.end(), 0);
1150 if (this->_bonds.empty())
return;
1152 for (cytnx_int32 i = 0; i < syms.size(); i++) {
1153 if (this->_bonds[0].type() == BD_BRA)
1154 total_qns[i] = syms[i].reverse_rule(this->_bonds[0]._impl->_qnums[loc[0]][i]);
1156 total_qns[i] = this->_bonds[0]._impl->_qnums[loc[0]][i];
1158 for (
auto j = 1; j < loc.size(); j++) {
1159 if (this->_bonds[j].type() == BD_BRA)
1160 total_qns[i] = syms[i].combine_rule(
1161 total_qns[i], syms[i].reverse_rule(this->_bonds[j]._impl->_qnums[loc[j]][i]));
1164 syms[i].combine_rule(total_qns[i], this->_bonds[j]._impl->_qnums[loc[j]][i]);
1170 void _fx_locate_elem(cytnx_int64 &bidx, std::vector<cytnx_uint64> &loc_in_T,
1171 const std::vector<cytnx_uint64> &locator)
const;
1174 void _fx_group_duplicates(
const std::vector<cytnx_uint64> &dup_bond_idxs,
1175 const std::vector<std::vector<cytnx_uint64>> &idx_mappers);
1177 void set_meta(BlockUniTensor *tmp,
const bool &inner,
const bool &outer)
const {
1180 tmp->_bonds = vec_clone(this->_bonds);
1181 tmp->_labels = this->_labels;
1182 tmp->syms_cache = vec_clone(this->syms_cache);
1183 tmp->_is_braket_form = this->_is_braket_form;
1184 tmp->_rowrank = this->_rowrank;
1185 tmp->_name = this->_name;
1188 tmp->_is_diag = this->_is_diag;
1192 tmp->_inner_to_outer_idx = this->_inner_to_outer_idx;
1196 boost::intrusive_ptr<BlockUniTensor> clone_meta(
const bool &inner,
const bool &outer)
const {
1197 boost::intrusive_ptr<BlockUniTensor> tmp(
new BlockUniTensor());
1198 this->set_meta(tmp.get(), inner, outer);
1202 friend class UniTensor;
1204 this->uten_type_id =
UTenType.Block;
1205 this->_is_tag =
true;
1214 void Init(
const std::vector<Bond> &bonds,
const std::vector<std::string> &in_labels = {},
1215 const cytnx_int64 &rowrank = -1,
const unsigned int &dtype =
Type.Double,
1216 const int &device =
Device.cpu,
const bool &is_diag =
false,
1217 const bool &no_alloc =
false,
const std::string &name =
"");
1219 void Init_by_Tensor(
const Tensor &in_tensor,
const bool &is_diag =
false,
1220 const cytnx_int64 &rowrank = -1,
const std::string &name =
"") {
1222 true,
"[ERROR][BlockUniTensor] Cannot use Init_by_tensor() on a BlockUniTensor.%s",
"\n");
1225 std::vector<cytnx_uint64> shape()
const {
1226 if (this->rank() == 0)
return {};
1227 std::vector<cytnx_uint64> out(this->_bonds.size());
1228 for (cytnx_uint64 i = 0; i < out.size(); i++) {
1229 out[i] = this->_bonds[i].dim();
1234 bool is_blockform()
const {
return true; }
1235 bool is_contiguous()
const {
1237 for (
int i = 0; i < this->_blocks.size(); i++) {
1238 out &= this->_blocks[i].is_contiguous();
1243 cytnx_uint64 Nblocks()
const {
return this->_blocks.size(); };
1245 void to_(
const int &device) {
1246 for (cytnx_uint64 i = 0; i < this->_blocks.size(); i++) {
1247 this->_blocks[i].to_(device);
1251 boost::intrusive_ptr<UniTensor_base> to(
const int &device) {
1252 if (this->device() == device) {
1255 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1261 boost::intrusive_ptr<UniTensor_base> clone()
const {
1262 boost::intrusive_ptr<BlockUniTensor> tmp = this->clone_meta(
true,
true);
1263 tmp->_blocks = vec_clone(this->_blocks);
1267 unsigned int dtype()
const {
1270 cytnx_error_msg(this->_blocks.size() == 0,
"[ERROR][internal] empty blocks for blockform.%s",
1273 return this->_blocks.size() < 1 ?
Type.Void : this->_blocks[0].dtype();
1275 int device()
const {
1278 cytnx_error_msg(this->_blocks.size() == 0,
"[ERROR][internal] empty blocks for blockform.%s",
1281 return this->_blocks.size() < 1 ? -404 : this->_blocks[0].device();
1283 std::string dtype_str()
const {
1286 cytnx_error_msg(this->_blocks.size() == 0,
"[ERROR][internal] empty blocks for blockform.%s",
1289 return this->_blocks.size() < 1 ?
"Void, no valid blocks" : this->_blocks[0].dtype_str();
1291 std::string device_str()
const {
1294 cytnx_error_msg(this->_blocks.size() == 0,
"[ERROR][internal] empty blocks for blockform.%s",
1297 return this->_blocks.size() < 1 ?
"None, no valid blocks" : this->_blocks[0].device_str();
1300 Tensor get_block(
const cytnx_uint64 &idx = 0)
const {
1301 cytnx_error_msg(idx >= this->_blocks.size(),
"[ERROR][BlockUniTensor] index out of range%s",
1303 return this->_blocks[idx].clone();
1307 Tensor get_block(
const std::vector<cytnx_int64> &qidx,
const bool &force_return)
const {
1308 if (this->rank() == 0) {
1310 "[ERROR][get_block][BlockUniTensor] rank-0 scalar block expects no "
1313 cytnx_error_msg(this->_blocks.empty(),
"[ERROR][BlockUniTensor] index out of range%s",
1315 return this->_blocks[0].clone();
1318 "[ERROR][get_block][BlockUniTensor] len(qidx) must be the same as the "
1319 "Tensor rank (number of legs).%s",
1322 std::vector<cytnx_uint64> inds(qidx.begin(), qidx.end());
1326 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1327 if (inds == this->_inner_to_outer_idx[i]) {
1335 return NullRefTensor;
1338 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1339 "force_return=false, so "
1340 "error throws. \n If you want to return an empty block without "
1341 "error when block is "
1342 "not avaliable, set force_return=True.%s",
1346 return this->_blocks[b].clone();
1350 const Tensor &get_block_(
const cytnx_uint64 &idx = 0)
const {
1351 cytnx_error_msg(idx >= this->_blocks.size(),
"[ERROR][BlockUniTensor] index out of range%s",
1353 return this->_blocks[idx];
1356 Tensor &get_block_(
const cytnx_uint64 &idx = 0) {
1357 cytnx_error_msg(idx >= this->_blocks.size(),
"[ERROR][BlockUniTensor] index out of range%s",
1359 return this->_blocks[idx];
1362 const Tensor &get_block_(
const std::vector<cytnx_int64> &qidx,
const bool &force_return)
const {
1363 if (this->rank() == 0) {
1365 "[ERROR][get_block][BlockUniTensor] rank-0 scalar block expects no "
1368 cytnx_error_msg(this->_blocks.empty(),
"[ERROR][BlockUniTensor] index out of range%s",
1370 return this->_blocks[0];
1373 "[ERROR][get_block][BlockUniTensor] len(qidx) must be the same as the "
1374 "Tensor rank (number of legs).%s",
1377 std::vector<cytnx_uint64> inds(qidx.begin(), qidx.end());
1381 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1382 if (inds == this->_inner_to_outer_idx[i]) {
1390 return this->NullRefTensor;
1393 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1394 "force_return=false, so "
1395 "error throws. \n If you want to return an empty block without "
1396 "error when block is "
1397 "not avaliable, set force_return=True.%s",
1401 return this->_blocks[b];
1405 Tensor &get_block_(
const std::vector<cytnx_int64> &qidx,
const bool &force_return) {
1406 if (this->rank() == 0) {
1408 "[ERROR][get_block][BlockUniTensor] rank-0 scalar block expects no "
1411 cytnx_error_msg(this->_blocks.empty(),
"[ERROR][BlockUniTensor] index out of range%s",
1413 return this->_blocks[0];
1416 "[ERROR][get_block][BlockUniTensor] len(qidx) must be the same as the "
1417 "Tensor rank (number of legs).%s",
1420 std::vector<cytnx_uint64> inds(qidx.begin(), qidx.end());
1424 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1425 if (inds == this->_inner_to_outer_idx[i]) {
1433 return this->NullRefTensor;
1436 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1437 "force_return=false, so "
1438 "error throws. \n If you want to return an empty block without "
1439 "error when block is "
1440 "not avaliable, set force_return=True.%s",
1444 return this->_blocks[b];
1448 std::vector<Tensor> get_blocks()
const {
return vec_clone(this->_blocks); }
1449 const std::vector<Tensor> &get_blocks_(
const bool &)
const {
return this->_blocks; }
1450 std::vector<Tensor> &get_blocks_(
const bool &) {
return this->_blocks; }
1452 bool same_data(
const boost::intrusive_ptr<UniTensor_base> &rhs)
const {
1453 if (rhs->uten_type() !=
UTenType.Block)
return false;
1454 if (rhs->get_blocks_(1).size() != this->get_blocks_(1).size())
return false;
1456 for (
int i = 0; i < rhs->get_blocks_(1).size(); i++)
1457 if (this->get_blocks_(1)[i].same_data(rhs->get_blocks_(1)[i]) ==
false)
return false;
1462 void set_rowrank_(
const cytnx_uint64 &new_rowrank) {
1464 "[ERROR][BlockUniTensor] rowrank should be [>=0] and [<=UniTensor.rank].%s",
1466 if (this->is_diag()) {
1468 "[ERROR][BlockUniTensor] rowrank should be [==1] when is_diag =true!.%s",
1471 this->_rowrank = new_rowrank;
1472 this->_is_braket_form = this->_update_braket();
1475 boost::intrusive_ptr<UniTensor_base> set_rowrank(
const cytnx_uint64 &new_rowrank)
const {
1476 boost::intrusive_ptr<BlockUniTensor> tmp = this->clone_meta(
true,
true);
1477 tmp->_blocks = this->_blocks;
1478 tmp->set_rowrank_(new_rowrank);
1482 boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<cytnx_int64> &mapper,
1483 const cytnx_int64 &rowrank = -1);
1484 boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<std::string> &mapper,
1485 const cytnx_int64 &rowrank = -1);
1487 void permute_(
const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank = -1);
1488 void permute_(
const std::vector<std::string> &mapper,
const cytnx_int64 &rowrank = -1);
1490 void twist_(
const cytnx_int64 &idx)
override {
1494 void fermion_twists_()
override {
1498 void twist_(
const std::string &label)
override {
1503 boost::intrusive_ptr<UniTensor_base> contiguous_() {
1508 for (
unsigned int b = 0; b < this->_blocks.size(); b++)
1509 this->_blocks[b] = this->_blocks[b].contiguous();
1510 return boost::intrusive_ptr<UniTensor_base>(
this);
1512 boost::intrusive_ptr<UniTensor_base> contiguous();
1514 boost::intrusive_ptr<UniTensor_base> apply_() {
1515 return boost::intrusive_ptr<UniTensor_base>(
this);
1517 boost::intrusive_ptr<UniTensor_base> apply() {
1519 boost::intrusive_ptr<UniTensor_base> out(
this);
1523 void print_diagram(
const bool &bond_info =
false)
const;
1524 void print_blocks(
const bool &full_info =
true)
const;
1525 void print_block(
const cytnx_int64 &idx,
const bool &full_info =
true)
const;
1527 boost::intrusive_ptr<UniTensor_base> contract(
const boost::intrusive_ptr<UniTensor_base> &rhs,
1528 const bool &mv_elem_self =
false,
1529 const bool &mv_elem_rhs =
false);
1531 boost::intrusive_ptr<UniTensor_base> relabel(
const std::vector<std::string> &new_labels);
1532 boost::intrusive_ptr<UniTensor_base> relabels(
const std::vector<std::string> &new_labels);
1534 boost::intrusive_ptr<UniTensor_base> relabel(
const std::vector<std::string> &old_labels,
1535 const std::vector<std::string> &new_labels);
1536 boost::intrusive_ptr<UniTensor_base> relabels(
const std::vector<std::string> &old_labels,
1537 const std::vector<std::string> &new_labels);
1539 boost::intrusive_ptr<UniTensor_base> relabel(
const std::string &old_label,
1540 const std::string &new_label);
1541 boost::intrusive_ptr<UniTensor_base> relabel(
const cytnx_int64 &inx,
1542 const std::string &new_label);
1544 std::vector<Symmetry> syms()
const;
1546 void reshape_(
const std::vector<cytnx_int64> &new_shape,
const cytnx_uint64 &rowrank = 0) {
1547 cytnx_error_msg(
true,
"[ERROR] Cannot reshape a UniTensor with symmetry.%s",
"\n");
1549 boost::intrusive_ptr<UniTensor_base> reshape(
const std::vector<cytnx_int64> &new_shape,
1550 const cytnx_uint64 &rowrank = 0) {
1551 cytnx_error_msg(
true,
"[ERROR] Cannot reshape a UniTensor with symmetry.%s",
"\n");
1555 boost::intrusive_ptr<UniTensor_base> to_dense();
1558 boost::intrusive_ptr<UniTensor_base> astype(
const unsigned int &dtype)
const {
1559 boost::intrusive_ptr<BlockUniTensor> tmp = this->clone_meta(
true,
true);
1560 tmp->_blocks.resize(this->_blocks.size());
1561 for (cytnx_int64 blk = 0; blk < this->_blocks.size(); blk++) {
1562 tmp->_blocks[blk] = this->_blocks[blk].astype(dtype);
1568 boost::intrusive_ptr<UniTensor_base> get(
const std::vector<Accessor> &accessors) {
1571 "[ERROR][BlockUniTensor][get] Cannot use get on a UniTensor with "
1572 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
1578 void set(
const std::vector<Accessor> &accessors,
const Tensor &rhs) {
1581 "[ERROR][BlockUniTensor][get] Cannot use get on a UniTensor with "
1582 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
1586 void put_block(
const Tensor &in,
const cytnx_uint64 &idx = 0) {
1588 "[ERROR][BlockUniTensor][put_block] The input tensor dtype does not match.%s",
1591 "[ERROR][BlockUniTensor][put_block] The input tensor device does not "
1596 cytnx_error_msg(idx >= this->_blocks.size(),
"[ERROR][BlockUniTensor] index out of range%s",
1599 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1600 "of block @ idx=%d\n",
1603 this->_blocks[idx] = in.clone();
1605 void put_block_(Tensor &in,
const cytnx_uint64 &idx = 0) {
1607 "[ERROR][BlockUniTensor][put_block] The input tensor dtype does not match.%s",
1610 "[ERROR][BlockUniTensor][put_block] The input tensor device does not "
1615 cytnx_error_msg(idx >= this->_blocks.size(),
"[ERROR][BlockUniTensor] index out of range%s",
1618 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1619 "of block @ idx=%d\n",
1622 this->_blocks[idx] = in;
1624 void put_block(
const Tensor &in,
const std::vector<cytnx_int64> &qidx) {
1626 "[ERROR][BlockUniTensor][put_block] The input tensor dtype does not match.%s",
1629 "[ERROR][BlockUniTensor][put_block] The input tensor device does not "
1635 "[ERROR][put_block][BlockUniTensor] len(qidx) must be the same as the "
1636 "Tensor rank (number of legs).%s",
1639 std::vector<cytnx_uint64> inds(qidx.begin(), qidx.end());
1643 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1644 if (inds == this->_inner_to_outer_idx[i]) {
1651 cytnx_error_msg(
true,
"[ERROR][put_block][BlockUniTensor] no avaliable block exists.%s",
1655 in.shape() != this->_blocks[b].shape(),
1656 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1657 "of block @ idx=%d\n",
1660 this->_blocks[b] = in.clone();
1663 void put_block_(Tensor &in,
const std::vector<cytnx_int64> &qidx) {
1665 "[ERROR][BlockUniTensor][put_block] The input tensor dtype does not match.%s",
1668 "[ERROR][BlockUniTensor][put_block] The input tensor device does not "
1674 "[ERROR][put_block][BlockUniTensor] len(qidx) must be the same as the "
1675 "Tensor rank (number of legs).%s",
1678 std::vector<cytnx_uint64> inds(qidx.begin(), qidx.end());
1682 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1683 if (inds == this->_inner_to_outer_idx[i]) {
1690 cytnx_error_msg(
true,
"[ERROR][put_block][BlockUniTensor] no avaliable block exists.%s",
1694 in.shape() != this->_blocks[b].shape(),
1695 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1696 "of block @ idx=%d\n",
1698 this->_blocks[b] = in;
1706 boost::intrusive_ptr<UniTensor_base>
Conj() {
1707 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1713 for (
int i = 0; i < this->_blocks.size(); i++) {
1714 this->_blocks[i].Conj_();
1719 boost::intrusive_ptr<UniTensor_base> Transpose() {
1720 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1726 boost::intrusive_ptr<UniTensor_base> normalize() {
1727 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1732 boost::intrusive_ptr<UniTensor_base> Dagger() {
1733 boost::intrusive_ptr<UniTensor_base> out = this->
Conj();
1742 void Trace_(
const std::string &a,
const std::string &b);
1743 void Trace_(
const cytnx_int64 &a,
const cytnx_int64 &b);
1745 boost::intrusive_ptr<UniTensor_base>
Trace(
const std::string &a,
const std::string &b) {
1746 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1750 boost::intrusive_ptr<UniTensor_base>
Trace(
const cytnx_int64 &a,
const cytnx_int64 &b) {
1751 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1756 Tensor
Norm()
const;
1758 bool elem_exists(
const std::vector<cytnx_uint64> &locator)
const;
1760 const Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator)
const;
1761 const cytnx_complex128 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1762 const cytnx_complex128 &aux)
const;
1763 const cytnx_complex64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1764 const cytnx_complex64 &aux)
const;
1765 const cytnx_double &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1766 const cytnx_double &aux)
const;
1767 const cytnx_float &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1768 const cytnx_float &aux)
const;
1769 const cytnx_uint64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1770 const cytnx_uint64 &aux)
const;
1771 const cytnx_int64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1772 const cytnx_int64 &aux)
const;
1773 const cytnx_uint32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1774 const cytnx_uint32 &aux)
const;
1775 const cytnx_int32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1776 const cytnx_int32 &aux)
const;
1777 const cytnx_uint16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1778 const cytnx_uint16 &aux)
const;
1779 const cytnx_int16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1780 const cytnx_int16 &aux)
const;
1782 Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator);
1783 cytnx_complex128 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1784 const cytnx_complex128 &aux);
1785 cytnx_complex64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1786 const cytnx_complex64 &aux);
1787 cytnx_double &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_double &aux);
1788 cytnx_float &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_float &aux);
1789 cytnx_uint64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint64 &aux);
1790 cytnx_int64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int64 &aux);
1791 cytnx_uint32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint32 &aux);
1792 cytnx_int32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int32 &aux);
1793 cytnx_uint16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint16 &aux);
1794 cytnx_int16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int16 &aux);
1796 void _save_dispatch(std::fstream &f)
const;
1797 void _load_dispatch(std::fstream &f,
unsigned int version);
1800 void truncate_(
const std::string &label,
const cytnx_uint64 &q_index);
1801 void truncate_(
const cytnx_int64 &bond_idx,
const cytnx_uint64 &q_index);
1803 void Add_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
1804 void Add_(
const Scalar &rhs) {
1807 "[ERROR] Cannot perform elementwise arithmetic '+' between Scalar and BlockUniTensor.\n %s "
1809 "This operation would destroy the block structure. [Suggest] Avoid or use get/put_block(s) "
1810 "to do operation on blocks.");
1813 void Mul_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
1814 void Mul_(
const Scalar &rhs);
1816 void Sub_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
1817 void Sub_(
const Scalar &rhs) {
1820 "[ERROR] Cannot perform elementwise arithmetic '-' between Scalar and BlockUniTensor.\n %s "
1822 "This operation would destroy the block structure. [Suggest] Avoid or use get/put_block(s) "
1823 "to do operation on blocks.");
1825 void lSub_(
const Scalar &lhs) {
1828 "[ERROR] Cannot perform elementwise arithmetic '-' between Scalar and BlockUniTensor.\n %s "
1830 "This operation would destroy the block structure. [Suggest] Avoid or use get/put_block(s) "
1831 "to do operation on blocks.");
1834 void Div_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
1835 void Div_(
const Scalar &rhs);
1836 void lDiv_(
const Scalar &lhs) {
1839 "[ERROR] Cannot perform elementwise arithmetic '/' between Scalar and BlockUniTensor.\n %s "
1841 "This operation would cause division by zero on non-block elements. [Suggest] Avoid or use "
1842 "get/put_block(s) to do operation on blocks.");
1844 void from_(
const boost::intrusive_ptr<UniTensor_base> &rhs,
bool force, cytnx_double tol = 0.);
1846 void group_basis_();
1848 void combineBond(
const std::vector<std::string> &indicators,
const bool &force =
false);
1849 void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &force =
false);
1850 void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &force,
1851 const bool &by_label);
1852 void combineBonds(
const std::vector<std::string> &indicators,
const bool &force =
false);
1854 const std::vector<cytnx_uint64> &get_qindices(
const cytnx_uint64 &bidx)
const {
1856 bidx >= this->Nblocks(),
1857 "[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
1859 return this->_inner_to_outer_idx[bidx];
1861 std::vector<cytnx_uint64> &get_qindices(
const cytnx_uint64 &bidx) {
1863 bidx >= this->Nblocks(),
1864 "[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
1866 return this->_inner_to_outer_idx[bidx];
1869 const vec2d<cytnx_uint64> &get_itoi()
const {
return this->_inner_to_outer_idx; }
1870 vec2d<cytnx_uint64> &get_itoi() {
return this->_inner_to_outer_idx; }
1876 class BlockFermionicUniTensor :
public UniTensor_base {
1880 std::vector<std::vector<cytnx_uint64>>
1881 _inner_to_outer_idx;
1882 std::vector<Tensor> _blocks;
1883 Tensor NullRefTensor;
1888 void _fx_get_total_fluxs(std::vector<cytnx_uint64> &loc,
const std::vector<Symmetry> &syms,
1889 std::vector<cytnx_int64> &total_qns) {
1892 loc.size() != this->_bonds.size(),
1893 "[ERROR][BlockFermionicUniTensor] qnum location rank does not match the number of bonds.%s",
1896 total_qns.size() != syms.size(),
1897 "[ERROR][BlockFermionicUniTensor] total_qns size does not match symmetry count.%s",
"\n");
1898 std::fill(total_qns.begin(), total_qns.end(), 0);
1899 if (this->_bonds.empty())
return;
1901 for (cytnx_int32 i = 0; i < syms.size(); i++) {
1902 if (this->_bonds[0].type() == BD_BRA)
1903 total_qns[i] = syms[i].reverse_rule(this->_bonds[0]._impl->_qnums[loc[0]][i]);
1905 total_qns[i] = this->_bonds[0]._impl->_qnums[loc[0]][i];
1907 for (
auto j = 1; j < loc.size(); j++) {
1908 if (this->_bonds[j].type() == BD_BRA)
1909 total_qns[i] = syms[i].combine_rule(
1910 total_qns[i], syms[i].reverse_rule(this->_bonds[j]._impl->_qnums[loc[j]][i]));
1913 syms[i].combine_rule(total_qns[i], this->_bonds[j]._impl->_qnums[loc[j]][i]);
1919 void _fx_locate_elem(cytnx_int64 &bidx, std::vector<cytnx_uint64> &loc_in_T,
1920 const std::vector<cytnx_uint64> &locator)
const;
1923 void _fx_group_duplicates(
const std::vector<cytnx_uint64> &dup_bond_idxs,
1924 const std::vector<std::vector<cytnx_uint64>> &idx_mappers);
1926 void set_meta(BlockFermionicUniTensor *tmp,
const bool &inner,
const bool &outer)
const {
1930 tmp->_bonds = vec_clone(this->_bonds);
1931 tmp->_labels = this->_labels;
1932 tmp->syms_cache = vec_clone(this->syms_cache);
1933 tmp->_is_braket_form = this->_is_braket_form;
1934 tmp->_rowrank = this->_rowrank;
1935 tmp->_name = this->_name;
1937 tmp->_signflip = this->_signflip;
1940 tmp->_is_diag = this->_is_diag;
1944 tmp->_inner_to_outer_idx = this->_inner_to_outer_idx;
1948 boost::intrusive_ptr<BlockFermionicUniTensor> clone_meta(
const bool &inner,
1949 const bool &outer)
const {
1951 boost::intrusive_ptr<BlockFermionicUniTensor> tmp(
new BlockFermionicUniTensor());
1952 this->set_meta(tmp.get(), inner, outer);
1956 friend class UniTensor;
1957 BlockFermionicUniTensor() {
1959 this->uten_type_id =
UTenType.BlockFermionic;
1960 this->_is_tag =
true;
1963 void Init(
const std::vector<Bond> &bonds,
const std::vector<std::string> &in_labels = {},
1964 const cytnx_int64 &rowrank = -1,
const unsigned int &dtype =
Type.Double,
1965 const int &device =
Device.cpu,
const bool &is_diag =
false,
1966 const bool &no_alloc =
false,
const std::string &name =
"");
1968 void Init_by_Tensor(
const Tensor &in_tensor,
const bool &is_diag =
false,
1969 const cytnx_int64 &rowrank = -1,
const std::string &name =
"") {
1971 "[ERROR][BlockFermionicUniTensor] Cannot use Init_by_tensor() on a "
1972 "BlockFermionicUniTensor.%s",
1976 std::vector<cytnx_uint64> shape()
const {
1978 if (this->rank() == 0)
return {};
1979 std::vector<cytnx_uint64> out(this->_bonds.size());
1980 for (cytnx_uint64 i = 0; i < out.size(); i++) {
1981 out[i] = this->_bonds[i].dim();
1986 bool is_blockform()
const {
1991 bool is_contiguous()
const {
1994 for (
int i = 0; i < this->_blocks.size(); i++) {
1995 out &= this->_blocks[i].is_contiguous();
2000 cytnx_uint64 Nblocks()
const {
2002 return this->_blocks.size();
2005 std::vector<bool> signflip()
const override {
return this->_signflip; };
2010 void reset_signflip_() { this->_signflip.assign(this->_blocks.size(),
false); }
2016 void erase_signflip_(
const std::vector<cytnx_uint64> &positions);
2018 void to_(
const int &device) {
2020 for (cytnx_uint64 i = 0; i < this->_blocks.size(); i++) {
2021 this->_blocks[i].to_(device);
2025 boost::intrusive_ptr<UniTensor_base> to(
const int &device) {
2027 if (this->device() == device) {
2030 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2036 boost::intrusive_ptr<UniTensor_base> clone()
const {
2039 boost::intrusive_ptr<BlockFermionicUniTensor> tmp = this->clone_meta(
true,
true);
2040 tmp->_blocks = vec_clone(this->_blocks);
2044 unsigned int dtype()
const {
2047 cytnx_error_msg(this->_blocks.size() == 0,
"[ERROR][internal] empty blocks for blockform.%s",
2050 return this->_blocks.size() < 1 ?
Type.Void : this->_blocks[0].dtype();
2052 int device()
const {
2055 cytnx_error_msg(this->_blocks.size() == 0,
"[ERROR][internal] empty blocks for blockform.%s",
2058 return this->_blocks.size() < 1 ? -404 : this->_blocks[0].device();
2060 std::string dtype_str()
const {
2063 cytnx_error_msg(this->_blocks.size() == 0,
"[ERROR][internal] empty blocks for blockform.%s",
2066 return this->_blocks.size() < 1 ?
"Void, no valid blocks" : this->_blocks[0].dtype_str();
2068 std::string device_str()
const {
2071 cytnx_error_msg(this->_blocks.size() == 0,
"[ERROR][internal] empty blocks for blockform.%s",
2074 return this->_blocks.size() < 1 ?
"None, no valid blocks" : this->_blocks[0].device_str();
2077 Tensor get_block(
const cytnx_uint64 &idx = 0)
const {
2080 "[ERROR][BlockFermionicUniTensor] index out of range%s",
"\n");
2081 return this->_blocks[idx].clone();
2085 Tensor get_block(
const std::vector<cytnx_int64> &qidx,
const bool &force_return)
const {
2087 if (this->rank() == 0) {
2089 "[ERROR][get_block][BlockFermionicUniTensor] rank-0 scalar block expects "
2090 "no qidx entries.%s",
2093 "[ERROR][BlockFermionicUniTensor] index out of range%s",
"\n");
2094 return this->_blocks[0].clone();
2097 qidx.size() != this->rank(),
2098 "[ERROR][get_block][BlockFermionicUniTensor] len(qidx) must be the same as the "
2099 "Tensor rank (number of legs).%s",
2102 std::vector<cytnx_uint64> inds(qidx.begin(), qidx.end());
2106 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
2107 if (inds == this->_inner_to_outer_idx[i]) {
2115 return NullRefTensor;
2118 "[ERROR][get_block][BlockFermionicUniTensor] no avaliable block exists, "
2119 "force_return=false, so "
2120 "error throws. \n If you want to return an empty block without "
2121 "error when block is "
2122 "not avaliable, set force_return=True.%s",
2126 return this->_blocks[b].clone();
2130 const Tensor &get_block_(
const cytnx_uint64 &idx = 0)
const {
2133 "[ERROR][BlockFermionicUniTensor] index out of range%s",
"\n");
2134 return this->_blocks[idx];
2137 Tensor &get_block_(
const cytnx_uint64 &idx = 0) {
2140 "[ERROR][BlockFermionicUniTensor] index out of range%s",
"\n");
2141 return this->_blocks[idx];
2144 const Tensor &get_block_(
const std::vector<cytnx_int64> &qidx,
const bool &force_return)
const {
2146 if (this->rank() == 0) {
2148 "[ERROR][get_block][BlockFermionicUniTensor] rank-0 scalar block expects "
2149 "no qidx entries.%s",
2152 "[ERROR][BlockFermionicUniTensor] index out of range%s",
"\n");
2153 return this->_blocks[0];
2156 qidx.size() != this->rank(),
2157 "[ERROR][get_block][BlockFermionicUniTensor] len(qidx) must be the same as the "
2158 "Tensor rank (number of legs).%s",
2161 std::vector<cytnx_uint64> inds(qidx.begin(), qidx.end());
2165 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
2166 if (inds == this->_inner_to_outer_idx[i]) {
2174 return this->NullRefTensor;
2177 "[ERROR][get_block][BlockFermionicUniTensor] no avaliable block exists, "
2178 "force_return=false, so "
2179 "error throws. \n If you want to return an empty block without "
2180 "error when block is "
2181 "not avaliable, set force_return=True.%s",
2185 return this->_blocks[b];
2189 Tensor &get_block_(
const std::vector<cytnx_int64> &qidx,
const bool &force_return) {
2191 if (this->rank() == 0) {
2193 "[ERROR][get_block][BlockFermionicUniTensor] rank-0 scalar block expects "
2194 "no qidx entries.%s",
2197 "[ERROR][BlockFermionicUniTensor] index out of range%s",
"\n");
2198 return this->_blocks[0];
2201 qidx.size() != this->rank(),
2202 "[ERROR][get_block][BlockFermionicUniTensor] len(qidx) must be the same as the "
2203 "Tensor rank (number of legs).%s",
2206 std::vector<cytnx_uint64> inds(qidx.begin(), qidx.end());
2210 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
2211 if (inds == this->_inner_to_outer_idx[i]) {
2219 return this->NullRefTensor;
2222 "[ERROR][get_block][BlockFermionicUniTensor] no avaliable block exists, "
2223 "force_return=false, so "
2224 "error throws. \n If you want to return an empty block without "
2225 "error when block is "
2226 "not avaliable, set force_return=True.%s",
2230 return this->_blocks[b];
2234 std::vector<Tensor> get_blocks()
const {
2236 return vec_clone(this->_blocks);
2238 const std::vector<Tensor> &get_blocks_(
const bool &)
const {
2240 return this->_blocks;
2242 std::vector<Tensor> &get_blocks_(
const bool &) {
2244 return this->_blocks;
2247 bool same_data(
const boost::intrusive_ptr<UniTensor_base> &rhs)
const {
2249 if (rhs->uten_type() !=
UTenType.BlockFermionic)
return false;
2250 if (rhs->get_blocks_(1).size() != this->get_blocks_(1).size())
return false;
2252 for (
int i = 0; i < rhs->get_blocks_(1).size(); i++)
2253 if (this->get_blocks_(1)[i].same_data(rhs->get_blocks_(1)[i]) ==
false)
return false;
2258 void set_rowrank_(
const cytnx_uint64 &new_rowrank) {
2261 new_rowrank > this->rank(),
2262 "[ERROR][BlockFermionicUniTensor] rowrank should be [>=0] and [<=UniTensor.rank].%s",
"\n");
2263 if (this->is_diag()) {
2266 "[ERROR][BlockFermionicUniTensor] rowrank should be [==1] when is_diag =true!.%s",
"\n");
2268 this->_rowrank = new_rowrank;
2269 this->_is_braket_form = this->_update_braket();
2272 boost::intrusive_ptr<UniTensor_base> set_rowrank(
const cytnx_uint64 &new_rowrank)
const {
2275 boost::intrusive_ptr<BlockFermionicUniTensor> tmp = this->clone_meta(
true,
true);
2276 tmp->_blocks = this->_blocks;
2277 tmp->set_rowrank_(new_rowrank);
2281 boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<cytnx_int64> &mapper,
2282 const cytnx_int64 &rowrank = -1);
2283 boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<std::string> &mapper,
2284 const cytnx_int64 &rowrank = -1);
2286 void permute_(
const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank = -1)
override;
2287 void permute_(
const std::vector<std::string> &mapper,
const cytnx_int64 &rowrank = -1)
override;
2289 boost::intrusive_ptr<UniTensor_base> permute_nosignflip(
2290 const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank = -1)
override;
2291 boost::intrusive_ptr<UniTensor_base> permute_nosignflip(
2292 const std::vector<std::string> &mapper,
const cytnx_int64 &rowrank = -1)
override;
2293 void permute_nosignflip_(
const std::vector<cytnx_int64> &mapper,
2294 const cytnx_int64 &rowrank = -1)
override;
2295 void permute_nosignflip_(
const std::vector<std::string> &mapper,
2296 const cytnx_int64 &rowrank = -1)
override;
2298 void twist_(
const cytnx_int64 &idx)
override;
2299 void twist_(
const std::string &label)
override;
2300 void fermion_twists_()
override;
2303 std::vector<bool> _swapsigns_(
const std::vector<cytnx_int64> &mapper)
const;
2304 std::vector<bool> _lhssigns_(
const std::vector<cytnx_int64> &mapper,
2305 const cytnx_int64 contrno)
const;
2306 std::vector<bool> _swapsigns_(
const std::vector<cytnx_uint64> &mapper)
const;
2307 std::vector<bool> _lhssigns_(
const std::vector<cytnx_uint64> &mapper,
2308 const cytnx_uint64 contrno)
const;
2310 boost::intrusive_ptr<UniTensor_base> contiguous_() {
2315 for (
unsigned int b = 0; b < this->_blocks.size(); b++)
2316 this->_blocks[b] = this->_blocks[b].contiguous();
2317 return boost::intrusive_ptr<UniTensor_base>(
this);
2319 boost::intrusive_ptr<UniTensor_base> contiguous();
2321 boost::intrusive_ptr<UniTensor_base> apply_();
2322 boost::intrusive_ptr<UniTensor_base> apply();
2324 void print_diagram(
const bool &bond_info =
false)
const;
2325 void print_blocks(
const bool &full_info =
true)
const;
2326 void print_block(
const cytnx_int64 &idx,
const bool &full_info =
true)
const;
2328 boost::intrusive_ptr<UniTensor_base> contract(
const boost::intrusive_ptr<UniTensor_base> &rhs,
2329 const bool &mv_elem_self =
false,
2330 const bool &mv_elem_rhs =
false);
2332 boost::intrusive_ptr<UniTensor_base> relabel(
const std::vector<std::string> &new_labels);
2333 boost::intrusive_ptr<UniTensor_base> relabels(
const std::vector<std::string> &new_labels);
2335 boost::intrusive_ptr<UniTensor_base> relabel(
const std::vector<std::string> &old_labels,
2336 const std::vector<std::string> &new_labels);
2337 boost::intrusive_ptr<UniTensor_base> relabels(
const std::vector<std::string> &old_labels,
2338 const std::vector<std::string> &new_labels);
2340 boost::intrusive_ptr<UniTensor_base> relabel(
const std::string &old_label,
2341 const std::string &new_label);
2342 boost::intrusive_ptr<UniTensor_base> relabel(
const cytnx_int64 &inx,
2343 const std::string &new_label);
2344 std::vector<Symmetry> syms()
const;
2346 void reshape_(
const std::vector<cytnx_int64> &new_shape,
const cytnx_uint64 &rowrank = 0) {
2347 cytnx_error_msg(
true,
"[ERROR] Cannot reshape a UniTensor with symmetry.%s",
"\n");
2349 boost::intrusive_ptr<UniTensor_base> reshape(
const std::vector<cytnx_int64> &new_shape,
2350 const cytnx_uint64 &rowrank = 0) {
2351 cytnx_error_msg(
true,
"[ERROR] Cannot reshape a UniTensor with symmetry.%s",
"\n");
2355 boost::intrusive_ptr<UniTensor_base> to_dense();
2358 boost::intrusive_ptr<UniTensor_base> astype(
const unsigned int &dtype)
const {
2360 boost::intrusive_ptr<BlockFermionicUniTensor> tmp = this->clone_meta(
true,
true);
2361 tmp->_blocks.resize(this->_blocks.size());
2362 for (cytnx_int64 blk = 0; blk < this->_blocks.size(); blk++) {
2363 tmp->_blocks[blk] = this->_blocks[blk].astype(dtype);
2369 boost::intrusive_ptr<UniTensor_base> get(
const std::vector<Accessor> &accessors) {
2372 "[ERROR][BlockFermionicUniTensor][get] Cannot use get on a UniTensor with "
2373 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
2379 void set(
const std::vector<Accessor> &accessors,
const Tensor &rhs) {
2383 "[ERROR][BlockFermionicUniTensor][get] Cannot use get on a UniTensor with "
2384 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
2388 void put_block(
const Tensor &in,
const cytnx_uint64 &idx = 0) {
2391 in.dtype() != this->dtype(),
2392 "[ERROR][BlockFermionicUniTensor][put_block] The input tensor dtype does not match.%s",
2395 in.device() != this->device(),
2396 "[ERROR][BlockFermionicUniTensor][put_block] The input tensor device does not "
2402 "[ERROR][BlockFermionicUniTensor] index out of range%s",
"\n");
2404 in.shape() != this->_blocks[idx].shape(),
2405 "[ERROR][BlockFermionicUniTensor] the shape of input tensor does not match the shape "
2406 "of block @ idx=%d\n",
2409 this->_blocks[idx] = in.clone();
2411 void put_block_(Tensor &in,
const cytnx_uint64 &idx = 0) {
2414 in.dtype() != this->dtype(),
2415 "[ERROR][BlockFermionicUniTensor][put_block] The input tensor dtype does not match.%s",
2418 in.device() != this->device(),
2419 "[ERROR][BlockFermionicUniTensor][put_block] The input tensor device does not "
2425 "[ERROR][BlockFermionicUniTensor] index out of range%s",
"\n");
2427 in.shape() != this->_blocks[idx].shape(),
2428 "[ERROR][BlockFermionicUniTensor] the shape of input tensor does not match the shape "
2429 "of block @ idx=%d\n",
2432 this->_blocks[idx] = in;
2434 void put_block(
const Tensor &in,
const std::vector<cytnx_int64> &qidx) {
2437 in.dtype() != this->dtype(),
2438 "[ERROR][BlockFermionicUniTensor][put_block] The input tensor dtype does not match.%s",
2441 in.device() != this->device(),
2442 "[ERROR][BlockFermionicUniTensor][put_block] The input tensor device does not "
2448 qidx.size() != this->rank(),
2449 "[ERROR][put_block][BlockFermionicUniTensor] len(qidx) must be the same as the "
2450 "Tensor rank (number of legs).%s",
2453 std::vector<cytnx_uint64> inds(qidx.begin(), qidx.end());
2457 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
2458 if (inds == this->_inner_to_outer_idx[i]) {
2466 true,
"[ERROR][put_block][BlockFermionicUniTensor] no avaliable block exists.%s",
"\n");
2469 in.shape() != this->_blocks[b].shape(),
2470 "[ERROR][BlockFermionicUniTensor] the shape of input tensor does not match the shape "
2471 "of block @ idx=%d\n",
2474 this->_blocks[b] = in.clone();
2477 void put_block_(Tensor &in,
const std::vector<cytnx_int64> &qidx) {
2480 in.dtype() != this->dtype(),
2481 "[ERROR][BlockFermionicUniTensor][put_block] The input tensor dtype does not match.%s",
2484 in.device() != this->device(),
2485 "[ERROR][BlockFermionicUniTensor][put_block] The input tensor device does not "
2491 qidx.size() != this->rank(),
2492 "[ERROR][put_block][BlockFermionicUniTensor] len(qidx) must be the same as the "
2493 "Tensor rank (number of legs).%s",
2496 std::vector<cytnx_uint64> inds(qidx.begin(), qidx.end());
2500 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
2501 if (inds == this->_inner_to_outer_idx[i]) {
2509 true,
"[ERROR][put_block][BlockFermionicUniTensor] no avaliable block exists.%s",
"\n");
2512 in.shape() != this->_blocks[b].shape(),
2513 "[ERROR][BlockFermionicUniTensor] the shape of input tensor does not match the shape "
2514 "of block @ idx=%d\n",
2516 this->_blocks[b] = in;
2524 boost::intrusive_ptr<UniTensor_base>
Conj() {
2526 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2533 for (
int i = 0; i < this->_blocks.size(); i++) {
2534 this->_blocks[i].Conj_();
2541 boost::intrusive_ptr<UniTensor_base> Transpose() {
2543 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2549 boost::intrusive_ptr<UniTensor_base> normalize() {
2551 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2556 boost::intrusive_ptr<UniTensor_base> Dagger() {
2558 boost::intrusive_ptr<UniTensor_base> out = this->
Conj();
2568 void Trace_(
const std::string &a,
const std::string &b);
2569 void Trace_(
const cytnx_int64 &a,
const cytnx_int64 &b);
2571 boost::intrusive_ptr<UniTensor_base>
Trace(
const std::string &a,
const std::string &b) {
2573 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2577 boost::intrusive_ptr<UniTensor_base>
Trace(
const cytnx_int64 &a,
const cytnx_int64 &b) {
2579 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2584 Tensor
Norm()
const;
2586 bool elem_exists(
const std::vector<cytnx_uint64> &locator)
const;
2588 const Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator)
const;
2589 const cytnx_complex128 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2590 const cytnx_complex128 &aux)
const;
2591 const cytnx_complex64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2592 const cytnx_complex64 &aux)
const;
2593 const cytnx_double &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2594 const cytnx_double &aux)
const;
2595 const cytnx_float &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2596 const cytnx_float &aux)
const;
2597 const cytnx_uint64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2598 const cytnx_uint64 &aux)
const;
2599 const cytnx_int64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2600 const cytnx_int64 &aux)
const;
2601 const cytnx_uint32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2602 const cytnx_uint32 &aux)
const;
2603 const cytnx_int32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2604 const cytnx_int32 &aux)
const;
2605 const cytnx_uint16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2606 const cytnx_uint16 &aux)
const;
2607 const cytnx_int16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2608 const cytnx_int16 &aux)
const;
2610 Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator);
2611 cytnx_complex128 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2612 const cytnx_complex128 &aux);
2613 cytnx_complex64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2614 const cytnx_complex64 &aux);
2615 cytnx_double &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_double &aux);
2616 cytnx_float &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_float &aux);
2617 cytnx_uint64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint64 &aux);
2618 cytnx_int64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int64 &aux);
2619 cytnx_uint32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint32 &aux);
2620 cytnx_int32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int32 &aux);
2621 cytnx_uint16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint16 &aux);
2622 cytnx_int16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int16 &aux);
2624 void _save_dispatch(std::fstream &f)
const;
2625 void _load_dispatch(std::fstream &f,
unsigned int version);
2628 void truncate_(
const std::string &label,
const cytnx_uint64 &q_index);
2629 void truncate_(
const cytnx_int64 &bond_idx,
const cytnx_uint64 &q_index);
2631 void Add_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
2632 void Add_(
const Scalar &rhs) {
2634 "[ERROR] Cannot perform elementwise arithmetic '+' between Scalar and "
2635 "BlockFermionicUniTensor.\n %s "
2637 "This operation would destroy the block structure. [Suggest] Avoid or use "
2638 "get/put_block(s) to do operation on blocks.");
2641 void Mul_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
2642 void Mul_(
const Scalar &rhs);
2644 void Sub_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
2645 void Sub_(
const Scalar &rhs) {
2647 "[ERROR] Cannot perform elementwise arithmetic '-' between Scalar and "
2648 "BlockFermionicUniTensor.\n %s "
2650 "This operation would destroy the block structure. [Suggest] Avoid or use "
2651 "get/put_block(s) to do operation on blocks.");
2653 void lSub_(
const Scalar &lhs) {
2655 "[ERROR] Cannot perform elementwise arithmetic '-' between Scalar and "
2656 "BlockFermionicUniTensor.\n %s "
2658 "This operation would destroy the block structure. [Suggest] Avoid or use "
2659 "get/put_block(s) to do operation on blocks.");
2662 void Div_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
2663 void Div_(
const Scalar &rhs);
2664 void lDiv_(
const Scalar &lhs) {
2666 "[ERROR] Cannot perform elementwise arithmetic '/' between Scalar and "
2667 "BlockFermionicUniTensor.\n %s "
2669 "This operation would cause division by zero on non-block elements. "
2670 "[Suggest] Avoid or use get/put_block(s) to do operation on blocks.");
2672 void from_(
const boost::intrusive_ptr<UniTensor_base> &rhs,
bool force, cytnx_double tol = 0.);
2674 void group_basis_();
2676 void combineBond(
const std::vector<std::string> &indicators,
const bool &force =
false);
2677 void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &force =
false);
2678 void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &force,
2679 const bool &by_label);
2680 void combineBonds(
const std::vector<std::string> &indicators,
const bool &force =
false);
2682 const std::vector<cytnx_uint64> &get_qindices(
const cytnx_uint64 &bidx)
const {
2685 bidx >= this->Nblocks(),
2686 "[ERROR][BlockFermionicUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
2688 return this->_inner_to_outer_idx[bidx];
2690 std::vector<cytnx_uint64> &get_qindices(
const cytnx_uint64 &bidx) {
2693 bidx >= this->Nblocks(),
2694 "[ERROR][BlockFermionicUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
2696 return this->_inner_to_outer_idx[bidx];
2699 const vec2d<cytnx_uint64> &get_itoi()
const {
2701 return this->_inner_to_outer_idx;
2703 vec2d<cytnx_uint64> &get_itoi() {
2705 return this->_inner_to_outer_idx;
2708 void beauty_print_block(std::ostream &os,
const cytnx_uint64 &Nin,
const cytnx_uint64 &Nout,
2709 const std::vector<cytnx_uint64> &qn_indices,
2710 const std::vector<Bond> &bonds,
const Tensor &block)
const;
2717 std::vector<cytnx_bool> _signflip;
2724 class UniTensor_options {
2731 UniTensor_options() {
2732 this->_is_diag =
false;
2733 this->_dtype =
Type.Double;
2734 this->_device =
Device.cpu;
2735 this->_rowrank = -1;
2738 UniTensor_options(
const UniTensor_options &rhs) {
2739 this->_is_diag = rhs._is_diag;
2740 this->_dtype = rhs._dtype;
2741 this->_device = rhs._device;
2742 this->_rowrank = rhs._rowrank;
2745 UniTensor_options &operator=(
const UniTensor_options &rhs) {
2746 this->_is_diag = rhs._is_diag;
2747 this->_dtype = rhs._dtype;
2748 this->_device = rhs._device;
2749 this->_rowrank = rhs._rowrank;
2753 UniTensor_options &is_diag(
const bool &in) {
2754 this->_is_diag = in;
2757 UniTensor_options &dtype(
const int &in) {
2761 UniTensor_options &device(
const int &in) {
2765 UniTensor_options &rowrank(
const int &in) {
2766 this->_rowrank = in;
2776 boost::intrusive_ptr<UniTensor_base>
_impl;
2780 this->_impl =
rhs._impl;
2814 const std::vector<std::string> &
in_labels = {},
const std::string &
name =
"")
2836 const std::vector<std::string> &
in_labels = {},
const std::string &
name =
"") {
2865 const std::string &
name =
"")
2870 "[DEBUG] message: entry for UniTensor(const std::vector<Bond> &bonds, const "
2871 "std::vector<std::string> &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned "
2873 "&dtype=Type.Double, const int &device = Device.cpu, const bool &is_diag=false)%s",
2912 const std::string &
name =
"") {
2926 "[ERROR] When initializing a UniTensor with symmetries, all Bonds must "
2927 "be in the same format!%s",
2938 is_sym,
"[ERROR] Cannot have bonds with mixing of symmetry and non-symmetry.%s",
"\n");
2944 cytnx_warning_msg(
true,
"[DEBUG] message: entry dispatch: UniTensor: symmetric%s",
"\n");
2948 "[ERROR] Symmetric tensor, but no degeneracies given. The UniTensor seems broken.%s",
2980 const std::string &
in) {
3052 "Please use set_label_(const cytnx_int64 &idx, const std::string &new_label) "
3062 "Please use set_label_(const cytnx_int64 &idx, const char *new_label) "
3074 "Please use set_label_(const std::string &old_label, const std::string "
3084 "Please use set_label_(const char *old_label, const std::string &new_label) "
3094 "Please use set_label_(const std::string &old_label, const char *new_label) "
3104 "Please use set_label_(const char *old_label, const char *new_label) "
3124 "UniTensor &relabel_(const std::vector<std::string> &new_labels) "
3138 "UniTensor &relabel_(const std::initializer_list<char *> &new_labels) "
3142 std::vector<std::string>
vs(
new_lbls.size());
3144 [](
char *
x) -> std::string { return std::string(x); });
3146 this->_impl->set_labels(
vs);
3172 "[ERROR] Cannot use item on a non-scalar UniTensor with Symmetry.\n suggestion: use "
3173 "get_block()/get_blocks() first.%s",
3175 return this->_impl->get_block_(0).item<
T>();
3179 return tmp->_block.item<
T>();
3186 "[ERROR] Cannot use item on a non-scalar UniTensor with Symmetry.\n suggestion: use "
3187 "get_block()/get_blocks() first.%s",
3189 return this->_impl->get_block_(0).item();
3193 return tmp->_block.item();
3218 unsigned int dtype()
const {
return this->_impl->dtype(); }
3247 if (this->
is_void())
return 0;
3263 int device()
const {
return this->_impl->device(); }
3269 std::string
name()
const {
return this->_impl->name(); }
3276 std::string
dtype_str()
const {
return this->_impl->dtype_str(); }
3283 std::string
device_str()
const {
return this->_impl->device_str(); }
3303 bool is_diag()
const {
return this->_impl->is_diag(); }
3310 bool is_tag()
const {
return this->_impl->is_tag(); }
3317 std::vector<Symmetry>
syms()
const {
return this->_impl->syms(); }
3331 const std::vector<std::string> &
labels()
const {
return this->_impl->labels(); }
3344 const std::vector<Bond> &
bonds()
const {
return this->_impl->bonds(); }
3359 std::vector<cytnx_uint64>
shape()
const {
return this->_impl->shape(); }
3367 std::vector<bool>
signflip()
const {
return this->_impl->signflip(); }
3432 "UniTensor &relabel_(const std::vector<std::string> &new_labels) "
3462 "UniTensor relabel(const std::vector<std::string> &new_labels) const "
3476 std::vector<std::string>
vs(
new_lbls.size());
3478 [](
char *
x) -> std::string { return std::string(x); });
3491 "UniTensor relabel(const std::initializer_list<char *> &new_labels) const "
3495 std::vector<std::string>
vs(
new_lbls.size());
3497 [](
char *
x) -> std::string { return std::string(x); });
3508 std::vector<std::string>
vs(
new_lbls.size());
3510 [](
char *
x) -> std::string { return std::string(x); });
3512 this->_impl->relabel_(
vs);
3522 "UniTensor &relabel_(const std::initializer_list<char *> &new_labels) "
3526 std::vector<std::string>
vs(
new_lbls.size());
3528 [](
char *
x) -> std::string { return std::string(x); });
3530 this->_impl->relabels_(
vs);
3542 const std::vector<std::string> &
new_labels)
const {
3554 "UniTensor relabel(const std::vector<std::string> &old_labels, const "
3555 "std::vector<std::string> &new_labels) const "
3558 const std::vector<std::string> &
new_labels)
const {
3580 const std::vector<std::string> &
new_labels) {
3591 "UniTensor &relabel_(const std::vector<std::string> &old_labels, const "
3592 "std::vector<std::string> &new_labels) "
3595 const std::vector<std::string> &
new_labels) {
3605 const std::initializer_list<char *> &
new_labels)
const {
3607 std::vector<std::string>
vs(
new_lbls.size());
3609 [](
char *
x) -> std::string { return std::string(x); });
3614 [](
char *
x) -> std::string { return std::string(x); });
3626 "UniTensor relabel(const std::initializer_list<char *> &old_labels, const "
3627 "std::initializer_list<char *> &new_labels) const "
3630 const std::initializer_list<char *> &
new_labels)
const {
3632 std::vector<std::string>
vs(
new_lbls.size());
3634 [](
char *
x) -> std::string { return std::string(x); });
3639 [](
char *
x) -> std::string { return std::string(x); });
3649 const std::initializer_list<char *> &
new_labels) {
3651 std::vector<std::string>
vs(
new_lbls.size());
3653 [](
char *
x) -> std::string { return std::string(x); });
3658 [](
char *
x) -> std::string { return std::string(x); });
3670 "UniTensor &relabel_(const std::initializer_list<char *> &old_labels, const "
3671 "std::initializer_list<char *> &new_labels) "
3674 const std::initializer_list<char *> &
new_labels) {
3676 std::vector<std::string>
vs(
new_lbls.size());
3678 [](
char *
x) -> std::string { return std::string(x); });
3683 [](
char *
x) -> std::string { return std::string(x); });
3762 if (this->
dtype() == dtype) {
3806 std::vector<std::string>
vs(
mprs.size());
3808 [](
char *
x) -> std::string { return std::string(x); });
3882 std::vector<std::string>
vs(
mprs.size());
3884 [](
const char *
x) -> std::string { return std::string(x); });
4039 this->_impl = this->_impl->
apply_();
4096 return this->_impl->at_for_sparse(
locator,
aux);
4097 }
else if (this->
uten_type() == UTenType.Dense) {
4101 "[ERROR] UniTensor is not initialized and of type Void.%s",
"\n");
4104 "[ERROR] SparseUniTensor is deprecated. Use BlockUniTensor or LinOp instead.%s",
"\n");
4123 return this->_impl->at_for_sparse(
locator,
aux);
4124 }
else if (this->
uten_type() == UTenType.Dense) {
4128 "[ERROR] UniTensor is not initialized and of type Void.%s",
"\n");
4131 "[ERROR] SparseUniTensor is deprecated. Use BlockUniTensor or LinOp instead.%s",
"\n");
4139 const std::vector<cytnx_uint64> &
locator)
const {
4142 "[ERROR][at] length of list should be the same for label and locator.%s",
4146 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s",
"\n");
4149 for (
int i = 0;
i <
labels.size();
i++) {
4150 auto res = std::find(this->_impl->_labels.begin(),
this->_impl->_labels.end(),
labels[
i]);
4152 "[ERROR] label:%s does not exist in current UniTensor.\n",
4154 new_loc = std::distance(this->_impl->_labels.begin(),
res);
4157 return this->
at<T>(new_locator);
4163 "[ERROR][at] length of list should be the same for label and locator.%s",
4167 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s",
"\n");
4170 for (
int i = 0;
i <
labels.size();
i++) {
4171 auto res = std::find(this->_impl->_labels.begin(),
this->_impl->_labels.end(),
labels[
i]);
4173 "[ERROR] label:%s does not exist in current UniTensor.\n",
4175 new_loc = std::distance(this->_impl->_labels.begin(),
res);
4178 return this->
at<T>(new_locator);
4188 const Scalar::Sproxy
at(
const std::vector<cytnx_uint64> &
locator)
const {
4190 return this->_impl->at_for_sparse(
locator);
4191 }
else if (this->
uten_type() == UTenType.Dense) {
4195 "[ERROR] UniTensor is not initialized and of type Void.%s",
"\n");
4198 "[ERROR] SparseUniTensor is deprecated. Use BlockUniTensor or LinOp instead.%s",
"\n");
4211 Scalar::Sproxy
at(
const std::vector<cytnx_uint64> &
locator) {
4213 return this->_impl->at_for_sparse(
locator);
4214 }
else if (this->
uten_type() == UTenType.Dense) {
4218 "[ERROR] UniTensor is not initialized and of type Void.%s",
"\n");
4221 "[ERROR] SparseUniTensor is deprecated. Use BlockUniTensor or LinOp instead.%s",
"\n");
4227 Scalar::Sproxy
at(
const std::vector<std::string> &
labels,
4228 const std::vector<cytnx_uint64> &
locator) {
4231 "[ERROR][at] length of list should be the same for label and locator.%s",
4235 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s",
"\n");
4238 for (
int i = 0;
i <
labels.size();
i++) {
4239 auto res = std::find(this->_impl->_labels.begin(),
this->_impl->_labels.end(),
labels[
i]);
4241 "[ERROR] label:%s does not exist in current UniTensor.\n",
4243 new_loc = std::distance(this->_impl->_labels.begin(),
res);
4246 return this->
at(new_locator);
4249 const Scalar::Sproxy
at(
const std::vector<std::string> &
labels,
4250 const std::vector<cytnx_uint64> &
locator)
const {
4253 "[ERROR][at] length of list should be the same for label and locator.%s",
4257 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s",
"\n");
4260 for (
int i = 0;
i <
labels.size();
i++) {
4261 auto res = std::find(this->_impl->_labels.begin(),
this->_impl->_labels.end(),
labels[
i]);
4263 "[ERROR] label:%s does not exist in current UniTensor.\n",
4265 new_loc = std::distance(this->_impl->_labels.begin(),
res);
4268 return this->
at(new_locator);
4295 return this->_impl->get_block(
qidx,
force);
4299 const bool &
force =
false)
const {
4302 "[ERROR][get_block] length of lists must be the same for both labels and qidx%s",
"\n");
4304 "[ERROR][get_block] length of lists must be the rank (# of legs)%s",
"\n");
4306 std::vector<cytnx_int64>
loc_id(this->
rank());
4311 for (
int i = 0;
i <
labels.size();
i++) {
4312 auto res = std::find(this->_impl->_labels.begin(),
this->_impl->_labels.end(),
labels[
i]);
4314 "[ERROR][get_block] label:%s does not exists in current Tensor.\n",
4316 new_loc = std::distance(this->_impl->_labels.begin(),
res);
4330 const bool &
force =
false)
const {
4331 std::vector<cytnx_int64>
tmp =
qidx;
4345 const bool &
force =
false)
const {
4359 return this->_impl->get_block_(
idx);
4380 return this->_impl->get_block_(
qidx,
force);
4402 const bool &
force =
false) {
4405 "[ERROR][get_block] length of lists must be the same for both labels and qidx%s",
"\n");
4407 "[ERROR][get_block] length of lists must be the rank (# of legs)%s",
"\n");
4409 std::vector<cytnx_int64>
loc_id(this->
rank());
4414 for (
int i = 0;
i <
labels.size();
i++) {
4415 auto res = std::find(this->_impl->_labels.begin(),
this->_impl->_labels.end(),
labels[
i]);
4417 "[ERROR][get_block] label:%s does not exists in current Tensor.\n",
4419 new_loc = std::distance(this->_impl->_labels.begin(),
res);
4424 if (
out.dtype() !=
Type.Void) {
4434 std::vector<cytnx_int64>
tmp =
qidx;
4447 const bool &
force =
false) {
4458 const bool &
force =
false)
const {
4459 return this->_impl->get_block_(
qidx,
force);
4466 const bool &
force =
false)
const {
4467 std::vector<cytnx_int64>
tmp =
qidx;
4468 return this->_impl->get_block_(
tmp,
force);
4475 const bool &
force =
false)
const {
4493 std::vector<Tensor>
get_blocks()
const {
return this->_impl->get_blocks(); }
4505 return this->_impl->get_blocks_(
silent);
4513 return this->_impl->get_blocks_(
silent);
4537 "UniTensor &put_block(const Tensor &in, const cytnx_uint64 &idx) "
4565 "UniTensor &put_block(const Tensor &in_tens, const std::vector<cytnx_int64> &qidx) "
4581 const std::vector<cytnx_int64> &
qidx) {
4584 "[ERROR][put_block] length of lists must be the same for both labels and qidx%s",
"\n");
4586 "[ERROR][put_block] length of lists must be the rank (# of legs)%s",
"\n");
4588 std::vector<cytnx_int64>
loc_id(this->
rank());
4594 for (
int i = 0;
i <
lbls.size();
i++) {
4595 auto res = std::find(this->_impl->_labels.begin(),
this->_impl->_labels.end(),
lbls[
i]);
4597 "[ERROR][put_block] label:%s does not exists in current Tensor.\n",
4599 new_loc = std::distance(this->_impl->_labels.begin(),
res);
4615 "UniTensor &put_block(Tensor &in, const std::vector<std::string> &lbls, const "
4616 "std::vector<cytnx_int64> &qidx) "
4619 const std::vector<cytnx_int64> &
qidx,
const bool &
force) {
4658 "UniTensor &put_block_(Tensor &in, const std::vector<cytnx_int64> &qidx) "
4674 const std::vector<cytnx_int64> &
qidx) {
4677 "[ERROR][put_block_] length of lists must be the same for both labels and qidx%s",
"\n");
4679 "[ERROR][put_block_] length of lists must be the rank (# of legs)%s",
"\n");
4681 std::vector<cytnx_int64>
loc_id(this->
rank());
4687 for (
int i = 0;
i <
lbls.size();
i++) {
4688 auto res = std::find(this->_impl->_labels.begin(),
this->_impl->_labels.end(),
lbls[
i]);
4690 "[ERROR][put_block_] label:%s does not exists in current Tensor.\n",
4692 new_loc = std::distance(this->_impl->_labels.begin(),
res);
4710 "UniTensor &put_block_(Tensor &in, const std::vector<std::string> &lbls, const "
4711 "std::vector<cytnx_int64> &qidx) "
4714 const std::vector<cytnx_int64> &
qidx,
const bool &
force) {
4750 return this->
get(acc_in);
4753 std::vector<cytnx::Accessor>
acc_in;
4757 return this->
get(acc_in);
4787 "[ERROR] Cannot set elements from UniTensor with symmetry. Use at() instead.%s",
"\n");
4790 "[ERROR] Cannot set UniTensor. incoming UniTensor is_diag=True.%s",
"\n");
4853 "combineBond_(const std::vector<std::string> &indicators, const bool &force) "
4867 "combineBond_(const std::vector<std::string> &indicators, const bool &force) "
4880 "combineBond_(const std::vector<std::string> &indicators, const bool &force) "
4916 const bool &
force =
false)
const {
4957 return this->_impl->getTotalQnums(
physical);
4964 return this->_impl->get_blocks_qnums();
4974 if (this->_impl->uten_type() !=
rhs._impl->uten_type())
return false;
4976 return this->_impl->same_data(
rhs._impl);
5276 [[deprecated(
"use norm() (returns Scalar) instead")]]
Tensor Norm()
const {
5277 return this->_impl->
Norm();
5493 out._impl = this->_impl->
Conj();
5505 this->_impl->
Conj_();
5657 this->_impl->
tag_();
5707 return this->_impl->elem_exists(
locator);
5716 [[deprecated(
"Use at() instead.")]]
T get_elem(
const std::vector<cytnx_uint64> &
locator)
const {
5717 return this->
at<T>(locator);
5727 const std::vector<cytnx_uint64> &
locator,
const T2 &
rc) {
5729 this->
at(locator) =
rc;
5833 return this->_impl->get_qindices(
bidx);
5843 return this->_impl->get_qindices(
bidx);
5856 void _Load(std::fstream &
f);
5857 void _Save(std::fstream &
f)
const;
5885 "Please use convert_from_(const UniTensor &rhs, bool force, cytnx_double tol) "
5906 const std::vector<std::string> &
in_labels = {},
5908 const std::string &
name =
"") {
5912 const std::vector<std::string> &
in_labels = {},
5914 const std::string &
name =
"") {
5975 const std::vector<std::string> &
in_labels = {},
5977 const std::string &
name =
"") {
5981 const std::vector<std::string> &
in_labels = {},
5983 const std::string &
name =
"") {
6002 const std::string &
name =
"") {
6024 const std::vector<std::string> &
in_labels = {},
6026 const std::string &
name =
"") {
6052 const std::string &
name =
"") {
6077 const std::vector<std::string> &
in_labels = {},
6080 const std::string &
name =
"");
6101 const double &std,
const std::vector<std::string> &
in_labels = {},
6104 const std::string &
name =
"");
6125 const std::vector<std::string> &
in_labels = {},
6127 const unsigned int &
dtype =
Type.Double,
6168 const double &
high,
const std::vector<std::string> &
in_labels = {},
6170 const unsigned int &
dtype =
Type.Double,
6207 std::ostream &operator<<(std::ostream &os,
const UniTensor &in);
6223 const bool &cacheR =
false);
6238 const bool &optimal);
6247 "UniTensor Contract(const std::vector<UniTensor> &TNs, const std::string &order, const bool "
6250 Contracts(
const std::vector<UniTensor> &TNs,
const std::string &order,
const bool &optimal);
6253 void _resolve_CT(std::vector<UniTensor> &TNlist);
6254 template <
class... T>
6255 void _resolve_CT(std::vector<UniTensor> &TNlist,
const UniTensor &in,
const T &...args) {
6256 TNlist.push_back(in);
6257 _resolve_CT(TNlist, args...);
6272 template <
class... T>
6274 const bool &optimal) {
6275 std::vector<UniTensor> TNlist;
6276 _resolve_CT(TNlist, in, args...);
6277 return Contract(TNlist, order, optimal);
6285 template <
class... T>
6288 "UniTensor Contract(const UniTensor &in, const T &...args, const std::string &order, const "
6290 "instead.")]] UniTensor
6292 const bool &optimal) {
6293 std::vector<UniTensor> TNlist;
6294 _resolve_CT(TNlist, in, args...);
6295 return Contracts(TNlist, order, optimal);
constexpr Type_class Type
data type
Definition Type.hpp:553
object that mimic the python slice to access elements in C++ [this is for c++ API only].
Definition Accessor.hpp:17
the object contains auxiliary properties for each Tensor rank (bond)
Definition Bond.hpp:178
Bond clone() const
return a copy of the instance Bond
Definition Bond.hpp:451
an tensor (multi-dimensional array)
Definition Tensor.hpp:33
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition Tensor.hpp:957
Tensor Norm() const
the Norm member function. Same as linalg::Norm(const Tensor &Tin), where Tin is the current Tensor.
An Enhanced tensor specifically designed for physical Tensor network simulation.
Definition UniTensor.hpp:2773
UniTensor to(const int &device) const
move the current UniTensor to the assigned device.
Definition UniTensor.hpp:3396
UniTensor & operator*=(const UniTensor &rhs)
The multiplication assignment operator of the UniTensor.
Definition UniTensor.hpp:5367
Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:4433
std::vector< Tensor > & get_blocks_(const bool &silent=false)
Definition UniTensor.hpp:4512
Tensor & get_block_(const std::vector< cytnx_uint64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:4441
void print_block(const cytnx_int64 &idx, const bool &full_info=true) const
Print out the block of the UniTensor with a given block index number.
Definition UniTensor.hpp:4062
UniTensor & operator/=(const UniTensor &rhs)
The division assignment operator of the UniTensor.
Definition UniTensor.hpp:5347
UniTensor & set_elem(const std::vector< cytnx_uint64 > &locator, const T2 &rc)
Definition UniTensor.hpp:5726
T & item()
Definition UniTensor.hpp:3168
UniTensor & tag_()
Set the UniTensor as a tagged UniTensor, in-place.
Definition UniTensor.hpp:5656
UniTensor & put_block_(Tensor &in, const std::vector< cytnx_int64 > &qidx)
Put the block into the UniTensor with given quantum indices, inplacely.
Definition UniTensor.hpp:4646
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, in-place.
Definition UniTensor.hpp:3017
bool is_contiguous() const
To tell whether the UniTensor is contiguous.
Definition UniTensor.hpp:3297
static UniTensor eye(cytnx_uint64 dim, const std::vector< std::string > &in_labels={}, cytnx_bool is_diag=false, unsigned int dtype=Type.Double, int device=Device.cpu, const std::string &name="")
Generate a 2-bond identity UniTensor.
Definition UniTensor.hpp:5956
T get_elem(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:5716
UniTensor Div(const UniTensor &rhs) const
The division function of the UniTensor.
UniTensor & convert_from(const UniTensor &rhs, bool force=false, cytnx_double tol=0.)
Definition UniTensor.hpp:5887
Tensor get_block(const std::vector< std::string > &labels, const std::vector< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:4298
UniTensor & put_block(const Tensor &in, const cytnx_uint64 &idx, const bool &force)
Definition UniTensor.hpp:4539
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:5842
std::vector< bool > signflip() const
Get the sign information of a fermionic UniTensor.
Definition UniTensor.hpp:3367
UniTensor & set_label_(const std::string &old_label, const char *new_label)
Definition UniTensor.hpp:3033
UniTensor & set_label(const cytnx_int64 &idx, const char *new_label)
Definition UniTensor.hpp:3064
UniTensor & operator+=(const UniTensor &rhs)
The addition assignment operator of the UniTensor.
Definition UniTensor.hpp:5307
UniTensor reshape(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor.
Definition UniTensor.hpp:4803
std::vector< Tensor > get_blocks() const
Get all the blocks of the UniTensor.
Definition UniTensor.hpp:4493
UniTensor permute(const std::initializer_list< char * > &mapper, const cytnx_int64 &rowrank=-1) const
Definition UniTensor.hpp:3803
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:3310
std::string uten_type_str() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor in 'string' form.
Definition UniTensor.hpp:3290
UniTensor permute_nosignflip(const std::vector< std::string > &mapper, const cytnx_int64 &rowrank=-1) const
permute the legs of the UniTensor by labels without sign flips
Definition UniTensor.hpp:3867
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:2862
bool is_void() const
Return whether the UniTensor is uninitialized.
Definition UniTensor.hpp:3232
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:4294
UniTensor & contiguous_()
Make the UniTensor contiguous by coalescing the memory (storage), inplacely.
Definition UniTensor.hpp:4014
UniTensor & tag()
Definition UniTensor.hpp:5664
const Bond & bond_(const cytnx_uint64 &idx) const
Definition UniTensor.hpp:3346
bool is_scalar() const
whether the UniTensor is an initialized rank-0 scalar UniTensor
Definition UniTensor.hpp:3238
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force=false)
Definition UniTensor.hpp:4882
UniTensor & set_label_(const char *old_label, const char *new_label)
Definition UniTensor.hpp:3041
UniTensor & relabel_(const std::string &old_label, const std::string &new_label)
relabel the legs in the UniTensor by a given label.
Definition UniTensor.hpp:3729
const T & at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:4138
UniTensor & relabels_(const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:3524
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:2812
Tensor & get_block_(const std::vector< cytnx_int64 > &qidx, const bool &force=false)
Get the shared view of the block for the given quantum indices.
Definition UniTensor.hpp:4379
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 from a cytnx::Tensor.
Definition UniTensor.hpp:2835
UniTensor get(const std::vector< Accessor > &accessors) const
get elements using Accessor (C++ API) / slices (python API)
Definition UniTensor.hpp:4733
UniTensor & permute_nosignflip_(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1)
permute the legs of the UniTensor without fermionic sign flips, inplacely.
Definition UniTensor.hpp:3901
T & at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:4160
UniTensor Conj() const
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:5491
UniTensor & set_label(const std::string &old_label, const std::string &new_label)
Definition UniTensor.hpp:3076
UniTensor set_rowrank(const cytnx_uint64 &new_rowrank) const
Definition UniTensor.hpp:3161
UniTensor & set(const std::vector< Accessor > &accessors, const UniTensor &rhs)
Definition UniTensor.hpp:4784
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:5397
cytnx_uint64 rowrank() const
Return the row rank of the UniTensor.
Definition UniTensor.hpp:3211
UniTensor & put_block(const Tensor &in_tens, const std::vector< cytnx_int64 > &qidx)
Put the block into the UniTensor with given quantum indices.
Definition UniTensor.hpp:4553
UniTensor & relabels_(const std::vector< std::string > &old_labels, const std::vector< std::string > &new_labels)
Definition UniTensor.hpp:3594
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:5276
UniTensor Mul(const Scalar &rhs) const
The multiplication function for a given scalar.
UniTensor & twist_(const std::string &label)
Inline version.
Definition UniTensor.hpp:3955
UniTensor twist(const std::string &label) const
Apply a twist (or braids/self-swap) operation to a given bond; No effect for bosonic tensors; for a f...
Definition UniTensor.hpp:3932
UniTensor & set_labels(const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:3140
UniTensor & relabel_(const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:3506
UniTensor & Sub_(const Scalar &rhs)
The subtraction function for a given scalar.
Definition UniTensor.hpp:5115
UniTensor & relabel_(const cytnx_int64 &inx, const std::string &new_label)
rebable the legs in the UniTensor by given index.
Definition UniTensor.hpp:3716
UniTensor & operator/=(const Scalar &rhs)
The division assignment operator for a given scalar.
Definition UniTensor.hpp:5412
const bool & is_braket_form() const
Check whether the UniTensor is in braket form.
Definition UniTensor.hpp:3325
UniTensor Add(const Scalar &rhs) const
The addition function for a given scalar.
UniTensor operator[](const std::vector< cytnx::Accessor > &accessors) const
get elements using Accessor (C++ API) / slices (python API)
Definition UniTensor.hpp:4743
UniTensor & set_label_(const char *old_label, const std::string &new_label)
Definition UniTensor.hpp:3025
std::vector< cytnx_uint64 > shape() const
Get the shape of the UniTensor.
Definition UniTensor.hpp:3359
UniTensor to_dense()
Convert the UniTensor to non-diagonal form.
Definition UniTensor.hpp:4831
UniTensor & permute_(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1)
permute the legs of the UniTensor, inplacely.
Definition UniTensor.hpp:3820
Scalar::Sproxy at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:4227
static UniTensor normal(const std::vector< cytnx_uint64 > &shape, const double &mean, const double &std, const std::vector< std::string > &in_labels={}, const unsigned int &seed=cytnx::random::__static_random_device(), const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a UniTensor with all elements are random numbers sampled from a normal (Gaussian) distributi...
const Tensor & get_block_(const std::vector< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:4457
UniTensor & set_name_(const std::string &in)
Set the name of a UniTensor, in-place.
Definition UniTensor.hpp:2971
UniTensor & set_labels(const std::vector< std::string > &new_labels)
Definition UniTensor.hpp:3126
std::string name() const
Return the name of the UniTensor.
Definition UniTensor.hpp:3269
const Scalar::Sproxy at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:4249
UniTensor & put_block(Tensor &in, const std::vector< std::string > &lbls, const std::vector< cytnx_int64 > &qidx)
Put the block into the UniTensor with given quantum indices, will copy the input tensor.
Definition UniTensor.hpp:4580
static UniTensor zeros(const std::vector< cytnx_uint64 > &shape, const std::vector< std::string > &in_labels={}, unsigned int dtype=Type.Double, int device=Device.cpu, const std::string &name="")
Generate a UniTensor with all elements set to zero.
Definition UniTensor.hpp:5905
UniTensor combineBond(const std::vector< std::string > &indicators, const bool &force=false) const
Combine the sevral bonds of the UniTensor, out-of-place.
Definition UniTensor.hpp:4915
UniTensor & Add_(const Scalar &rhs)
The addition function for a given scalar.
Definition UniTensor.hpp:5085
UniTensor & set(const std::vector< Accessor > &accessors, const Tensor &rhs)
set elements using Accessor (C++ API) / slices (python API)
Definition UniTensor.hpp:4780
UniTensor & Trace_(const std::string &a, const std::string &b)
Take the partial trace of the UniTensor, inplacely.
Definition UniTensor.hpp:5602
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:5790
UniTensor & twist_(const cytnx_int64 &idx)
Inline version.
Definition UniTensor.hpp:3964
Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator)
Get an element at a specific location.
Definition UniTensor.hpp:4211
UniTensor Trace(const std::string &a, const std::string &b) const
Take the partial trace of the UniTensor.
Definition UniTensor.hpp:5572
UniTensor & set_label_(const cytnx_int64 &idx, const char *new_label)
Definition UniTensor.hpp:3002
UniTensor & 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:2909
bool same_data(const UniTensor &rhs) const
Check whether the Blocks address are the same.
Definition UniTensor.hpp:4972
UniTensor astype(const unsigned int &dtype) const
Return a new UniTensor whose elements are casted to a different data type.
Definition UniTensor.hpp:3760
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:5804
UniTensor Transpose() const
Take the transpose of the UniTensor.
Definition UniTensor.hpp:5522
UniTensor operator[](const std::initializer_list< cytnx_int64 > &accessors) const
Definition UniTensor.hpp:4759
UniTensor & set_label(const char *old_label, const std::string &new_label)
Definition UniTensor.hpp:3086
static UniTensor Load(const char *fname)
load a UniTensor from file
static UniTensor arange(cytnx_int64 Nelem, const std::vector< std::string > &in_labels={}, const std::string &name="")
Create a rank-1 UniTensor with incremental unsigned integer elements in the range [0,...
Definition UniTensor.hpp:6001
UniTensor & Dagger_()
Take the conjugate transpose to the UniTensor, inplacely.
Definition UniTensor.hpp:5643
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at a specific location.
Definition UniTensor.hpp:4092
UniTensor & set_rowrank_(const cytnx_uint64 &new_rowrank)
Set the rowrank of the UniTensor.
Definition UniTensor.hpp:3156
UniTensor & uniform_(const double &low=0, const double &high=1, const unsigned int &seed=cytnx::random::__static_random_device())
Generate a UniTensor with all elements are random numbers sampled from a uniform distribution,...
UniTensor & normal_(const double &mean, const double &std, const unsigned int &seed=cytnx::random::__static_random_device())
Generate a one-bond UniTensor with all elements are random numbers sampled from a normal (Gaussian) d...
UniTensor operator[](const std::initializer_list< cytnx::Accessor > &accessors) const
Definition UniTensor.hpp:4748
UniTensor & put_block_(Tensor &in, const std::vector< std::string > &lbls, const std::vector< cytnx_int64 > &qidx)
Put the block into the UniTensor with given quantum indices, inplacely.
Definition UniTensor.hpp:4673
UniTensor & set_label(const cytnx_int64 &idx, const std::string &new_label)
Definition UniTensor.hpp:3054
UniTensor permute_nosignflip(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1) const
permute the legs of the UniTensor without sign flips
Definition UniTensor.hpp:3849
UniTensor & fermion_twists_()
Inline version.
Definition UniTensor.hpp:3993
UniTensor & to_dense_()
Convert the UniTensor to non-diagonal form, inplacely.
Definition UniTensor.hpp:4841
UniTensor contiguous() const
Make the UniTensor contiguous by coalescing the memory (storage).
Definition UniTensor.hpp:4004
UniTensor & put_block_(Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index, inplacely.
Definition UniTensor.hpp:4632
UniTensor & combineBond_(const std::vector< std::string > &indicators, const bool &force=false)
Combine the sevral bonds of the UniTensor, in-place.
Definition UniTensor.hpp:4898
UniTensor & apply_()
Apply fermionic signflips to the UniTensor, inplacely. Subsequently, all elements returned by signfli...
Definition UniTensor.hpp:4038
Tensor get_block(const cytnx_uint64 &idx=0) const
Get the block of the UniTensor for a given block index.
Definition UniTensor.hpp:4280
const T & at(const std::vector< cytnx_uint64 > &locator) const
Get an element at a specific location.
Definition UniTensor.hpp:4119
UniTensor & operator*=(const Scalar &rhs)
The multiplication assignment operator for a given scalar.
Definition UniTensor.hpp:5427
UniTensor relabels(const std::vector< std::string > &old_labels, const std::vector< std::string > &new_labels) const
Definition UniTensor.hpp:3557
UniTensor & convert_from_(const UniTensor &rhs, bool force=false, cytnx_double tol=0.)
Copy data from a UniTensor of different type, in-place.
Definition UniTensor.hpp:5874
UniTensor normalize() const
normalize the current UniTensor instance with 2-norm.
Definition UniTensor.hpp:5546
UniTensor & relabel_(const std::vector< std::string > &new_labels)
Set new labels for all the bonds.
Definition UniTensor.hpp:3421
std::vector< Symmetry > syms() const
Return the symmetry type of the UniTensor.
Definition UniTensor.hpp:3317
UniTensor relabel(const std::vector< std::string > &new_labels) const
relabel all of the labels in UniTensor.
Definition UniTensor.hpp:3450
UniTensor & Mul_(const UniTensor &rhs)
The multiplcation function of the UniTensor.
Definition UniTensor.hpp:5022
static UniTensor linspace(cytnx_double start, cytnx_double end, cytnx_uint64 Nelem, bool endpoint=true, const std::vector< std::string > &in_labels={}, unsigned int dtype=Type.Double, 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:6049
UniTensor & permute_nosignflip_(const std::vector< std::string > &mapper, const cytnx_int64 &rowrank=-1)
permute the legs of the UniTensor without fermionic sign flips, inplacely.
Definition UniTensor.hpp:3918
void combineBonds(const std::vector< std::string > &indicators, const bool &force=false)
Definition UniTensor.hpp:4869
UniTensor relabel(const std::string &old_label, const std::string &new_label) const
relabel the legs in the UniTensor by a given label.
Definition UniTensor.hpp:3748
UniTensor & group_basis_()
Group the same quantum number basis together.
Definition UniTensor.hpp:4072
UniTensor & normalize_()
normalize the UniTensor, inplacely.
Definition UniTensor.hpp:5558
UniTensor & Inv_(double clip=-1.)
Element-wise (pseudo-)inverse, inplacely.
bool is_diag() const
To tell whether the UniTensor is in diagonal form.
Definition UniTensor.hpp:3303
int device() const
Return the device of the UniTensor.
Definition UniTensor.hpp:3263
UniTensor & Pow_(const double &p)
Take the power p of all elements, inplacely.
const Tensor & get_block_(const std::vector< cytnx_uint64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:4474
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 the block for the given quantum indices on given labels.
Definition UniTensor.hpp:4401
std::string dtype_str() const
Return the data type of the UniTensor in 'string' form.
Definition UniTensor.hpp:3276
UniTensor & operator+=(const Scalar &rhs)
The addition assignment operator for a given scalar.
Definition UniTensor.hpp:5382
UniTensor & Div_(const UniTensor &rhs)
The division function of the UniTensor.
Definition UniTensor.hpp:5070
UniTensor & Div_(const Scalar &rhs)
The division function for a given scalar.
Definition UniTensor.hpp:5130
UniTensor & put_block_(Tensor &in, const std::vector< cytnx_int64 > &qidx, const bool &force)
Definition UniTensor.hpp:4660
Bond & bond_(const std::string &label)
Definition UniTensor.hpp:3350
cytnx_uint64 rank() const
Return the rank of the UniTensor.
Definition UniTensor.hpp:3205
Bond bond(const std::string &label) const
Definition UniTensor.hpp:3353
UniTensor permute_nosignflip(const std::initializer_list< const char * > &mapper, const cytnx_int64 &rowrank=-1) const
Definition UniTensor.hpp:3879
UniTensor fermion_twists() const
Apply twists to all right bonds (>= rowrank) with bond type BD_KET.
Definition UniTensor.hpp:3983
UniTensor & Trace_(const cytnx_int64 &a=0, const cytnx_int64 &b=1)
Take the partial trace of the UniTensor, inplacely.
Definition UniTensor.hpp:5616
UniTensor relabel(const std::vector< std::string > &old_labels, const std::vector< std::string > &new_labels) const
replace part or all labels by given new labels for the bonds.
Definition UniTensor.hpp:3541
UniTensor & put_block(const Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index.
Definition UniTensor.hpp:4525
UniTensor & put_block(const Tensor &in_tens, const std::vector< cytnx_int64 > &qidx, const bool &force)
Definition UniTensor.hpp:4567
UniTensor & set_name(const std::string &in)
Definition UniTensor.hpp:2979
UniTensor Trace(const cytnx_int64 &a=0, const cytnx_int64 &b=1) const
Take the partial trace of the UniTensor.
Definition UniTensor.hpp:5587
UniTensor & Add_(const UniTensor &rhs)
The addition function of the UniTensor.
Definition UniTensor.hpp:4998
UniTensor permute(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1) const
permute the legs of the UniTensor
Definition UniTensor.hpp:3778
UniTensor & set_label(const std::string &old_label, const char *new_label)
Definition UniTensor.hpp:3096
UniTensor permute(const std::vector< std::string > &mapper, const cytnx_int64 &rowrank=-1) const
permute the legs of the UniTensor by labels
Definition UniTensor.hpp:3791
unsigned int dtype() const
Return the data type of the UniTensor.
Definition UniTensor.hpp:3218
UniTensor & set_label_(const cytnx_int64 &idx, const std::string &new_label)
Set a new label for bond at the assigned index, in-place.
Definition UniTensor.hpp:2994
UniTensor Pow(const double &p) const
Take the power p of all elements.
UniTensor & Mul_(const Scalar &rhs)
The multiplication function for a given scalar.
Definition UniTensor.hpp:5100
UniTensor & operator-=(const UniTensor &rhs)
The subtraction assignment operator of the UniTensor.
Definition UniTensor.hpp:5327
static UniTensor ones(std::initializer_list< cytnx_uint64 > shape, const std::vector< std::string > &in_labels={}, unsigned int dtype=Type.Double, int device=Device.cpu, const std::string &name="")
Definition UniTensor.hpp:5980
Tensor get_block_(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:4446
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force, const bool &by_label)
Definition UniTensor.hpp:4855
UniTensor & set_label(const char *old_label, const char *new_label)
Definition UniTensor.hpp:3106
bool is_blockform() const
Check whether the UniTensor is in block form.
Definition UniTensor.hpp:3374
UniTensor group_basis() const
Definition UniTensor.hpp:4077
UniTensor twist(const cytnx_int64 &idx) const
Apply a twist (or braids/self-swap) operation to a given bond; No effect for bosonic tensors; for a f...
Definition UniTensor.hpp:3945
UniTensor apply() const
Apply fermionic signflips to the UniTensor, such that all elements calling signflip() on the output t...
Definition UniTensor.hpp:4027
UniTensor Dagger() const
Take the conjugate transpose to the UniTensor.
Definition UniTensor.hpp:5629
static UniTensor uniform(const std::vector< cytnx_uint64 > &shape, const double &low, const double &high, const std::vector< std::string > &in_labels={}, const unsigned int &seed=cytnx::random::__static_random_device(), const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a UniTensor with all elements are random numbers sampled from a uniform distribution.
const std::vector< Tensor > & get_blocks_(const bool &silent=false) const
Get all the blocks of the UniTensor, inplacely.
Definition UniTensor.hpp:4504
UniTensor & relabels_(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:3673
const Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:4465
bool elem_exists(const std::vector< cytnx_uint64 > &locator) const
Given the locator, check if the element exists.
Definition UniTensor.hpp:5706
UniTensor & Sub_(const UniTensor &rhs)
The subtraction function of the UniTensor.
Definition UniTensor.hpp:5046
UniTensor relabels(const std::initializer_list< char * > &new_labels) const
Definition UniTensor.hpp:3493
Scalar norm() const
Return the norm of the UniTensor.
Definition UniTensor.hpp:5290
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:4940
const Tensor & get_block_(const cytnx_uint64 &idx=0) const
Get the shared view of the block for the given block index.
Definition UniTensor.hpp:4358
UniTensor & relabel_(const std::vector< std::string > &old_labels, const std::vector< std::string > &new_labels)
relabel part or all of the labels in UniTensor by given new labels
Definition UniTensor.hpp:3579
static UniTensor identity(cytnx_uint64 dim, const std::vector< std::string > &in_labels={}, cytnx_bool is_diag=false, unsigned int dtype=Type.Double, int device=Device.cpu, const std::string &name="")
Generate an identity UniTensor with two bonds.
Definition UniTensor.hpp:5931
static UniTensor Load(const std::string &fname)
load a UniTensor from file
UniTensor & permute_(const std::vector< std::string > &mapper, const cytnx_int64 &rowrank=-1)
permute the legs of the UniTensor, inplacely.
Definition UniTensor.hpp:3831
const Bond & bond_(const std::string &label) const
Definition UniTensor.hpp:3349
Bond & bond_(const cytnx_uint64 &idx)
Definition UniTensor.hpp:3347
cytnx_uint64 size() const
Return the total number of logical elements in the UniTensor.
Definition UniTensor.hpp:3246
static UniTensor normal(const cytnx_uint64 &Nelem, const double &mean, const double &std, const std::vector< std::string > &in_labels={}, const unsigned int &seed=cytnx::random::__static_random_device(), const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a one-bond UniTensor with all elements are random numbers sampled from a normal (Gaussian) d...
UniTensor Inv(double clip=-1.) const
Element-wise (pseudo-)inverse.
UniTensor relabel(const cytnx_int64 &inx, const std::string &new_label) const
rebabel the legs in the UniTensor by given index.
Definition UniTensor.hpp:3703
UniTensor Mul(const UniTensor &rhs) const
The multiplication function of the UniTensor.
UniTensor & reshape_(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor, inplacely.
Definition UniTensor.hpp:4815
bool is_empty() const
whether the UniTensor is initialized and has no logical elements
Definition UniTensor.hpp:3256
void print_diagram(const bool &bond_info=false) const
Plot the diagram of the UniTensor.
Definition UniTensor.hpp:4047
UniTensor relabels(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels) const
Definition UniTensor.hpp:3629
Tensor get_block(const std::vector< cytnx_uint64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:4339
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:5832
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:3331
UniTensor & relabel_(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:3648
cytnx_int64 get_index(std::string label) const
Get the index of an desired label string.
Definition UniTensor.hpp:3338
UniTensor & to_(const int &device)
move the current UniTensor to the assigned device (inplace).
Definition UniTensor.hpp:3382
const std::vector< Bond > & bonds() const
Get the bonds of the UniTensor.
Definition UniTensor.hpp:3344
Tensor get_block(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:4344
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:5819
UniTensor & Transpose_()
Take the transpose of the UniTensor, inplacely.
Definition UniTensor.hpp:5535
static UniTensor uniform(const cytnx_uint64 &Nelem, const double &low, const double &high, const std::vector< std::string > &in_labels={}, const unsigned int &seed=cytnx::random::__static_random_device(), const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a one-bond UniTensor with all elements are random numbers sampled from a uniform distributio...
UniTensor & put_block(Tensor &in, const std::vector< std::string > &lbls, const std::vector< cytnx_int64 > &qidx, const bool &force)
Definition UniTensor.hpp:4618
Tensor get_block(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:4329
UniTensor clone() const
Clone (deep copy) the UniTensor.
Definition UniTensor.hpp:3406
vec2d< cytnx_uint64 > & get_itoi()
Definition UniTensor.hpp:5853
void print_blocks(const bool &full_info=true) const
Print all blocks of the UniTensor.
Definition UniTensor.hpp:4055
Scalar::Sproxy item() const
Definition UniTensor.hpp:3182
const vec2d< cytnx_uint64 > & get_itoi() const
get the q-indices on each leg for all the blocks
Definition UniTensor.hpp:5852
std::string device_str() const
Return the device of the UniTensor in 'string' form.
Definition UniTensor.hpp:3283
UniTensor & put_block_(Tensor &in, const std::vector< std::string > &lbls, const std::vector< cytnx_int64 > &qidx, const bool &force)
Definition UniTensor.hpp:4713
UniTensor relabels(const std::vector< std::string > &new_labels) const
Definition UniTensor.hpp:3464
static UniTensor ones(const std::vector< cytnx_uint64 > &shape, const std::vector< std::string > &in_labels={}, unsigned int dtype=Type.Double, int device=Device.cpu, const std::string &name="")
Generate a UniTensor with all elements set to one.
Definition UniTensor.hpp:5974
UniTensor relabel(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels) const
Definition UniTensor.hpp:3604
UniTensor Sub(const UniTensor &rhs) const
The subtraction function of the UniTensor.
UniTensor & Conj_()
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:5504
static UniTensor arange(cytnx_double start, cytnx_double end, cytnx_double step=1, const std::vector< std::string > &in_labels={}, unsigned int dtype=Type.Double, int device=Device.cpu, const std::string &name="")
Create a rank-1 UniTensor with incremental elements in the range [start,end) with given step-size ste...
Definition UniTensor.hpp:6023
UniTensor operator[](const std::vector< cytnx_int64 > &accessors) const
Definition UniTensor.hpp:4752
UniTensor relabel(const std::initializer_list< char * > &new_labels) const
relables all of the labels in UniTensor.
Definition UniTensor.hpp:3474
cytnx_uint64 Nblocks() const
Return the number of blocks in the UniTensor.
Definition UniTensor.hpp:3199
void Save(const char *fname) const
save a UniTensor to file
Bond bond(const cytnx_uint64 &idx) const
Definition UniTensor.hpp:3352
static UniTensor zeros(std::initializer_list< cytnx_uint64 > shape, const std::vector< std::string > &in_labels={}, unsigned int dtype=Type.Double, int device=Device.cpu, const std::string &name="")
Definition UniTensor.hpp:5911
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:5777
UniTensor & relabels_(const std::vector< std::string > &new_labels)
Definition UniTensor.hpp:3434
const Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator) const
Get an element at a specific location.
Definition UniTensor.hpp:4188
int uten_type() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor.
Definition UniTensor.hpp:3226
Tensor & get_block_(const cytnx_uint64 &idx=0)
Definition UniTensor.hpp:4366
#define cytnx_warning_msg(is_true, format,...)
Definition cytnx_error.hpp:125
#define cytnx_error_msg(is_true, format,...)
Definition cytnx_error.hpp:118
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)
Perform the trace over two legs of a UniTensor.
void Conj_(cytnx::UniTensor &UT)
Inplace elementwise conjugate of the UniTensor.
Tensor Norm(const Tensor &Tl)
Calculate the norm of a tensor.
std::random_device __static_random_device
Definition UniTensor.hpp:27
Definition Accessor.hpp:12
Device_class Device
data on which devices.
UniTensorType_class UTenType
UniTensor type.
@ Void
Definition Symmetry.hpp:30
Tensor zeros(const std::vector< cytnx_uint64 > &shape, unsigned int dtype=Type.Double, int device=Device.cpu)
Create a Tensor with all elements initialized to zero.
UniTensor Contract(const UniTensor &inL, const UniTensor &inR, const bool &cacheL=false, const bool &cacheR=false)
Contract two UniTensor by tracing the ranks with common labels.
Tensor linspace(cytnx_double start, cytnx_double end, cytnx_uint64 Nelem, bool endpoint=true, unsigned int dtype=Type.Double, int device=Device.cpu)
Tensor ones(const std::vector< cytnx_uint64 > &shape, unsigned int dtype=Type.Double, int device=Device.cpu)
Create a Tensor with all elements initialized to one.
UniTensor Contracts(const std::vector< UniTensor > &TNs, const std::string &order, const bool &optimal)
Tensor arange(cytnx_int64 Nelem)
Create a rank-1 Tensor with incremental unsigned integer elements in the range [0,...
Tensor identity(cytnx_uint64 Dim, unsigned int dtype=Type.Double, int device=Device.cpu)
Create a square rank-2 Tensor with the diagonal initialized to one and all other elements set to zero...