Cytnx v1.0.0
Loading...
Searching...
No Matches
UniTensor.hpp
Go to the documentation of this file.
1#ifndef CYTNX_UNITENSOR_H_
2#define CYTNX_UNITENSOR_H_
3
4#include "Type.hpp"
5#include "cytnx_error.hpp"
6#include "Device.hpp"
7#include "Tensor.hpp"
8#include "utils/utils.hpp"
10#include <iostream>
11#include <vector>
12#include <map>
13#include <utility>
14#include <initializer_list>
15#include <fstream>
16#include <algorithm>
17#include "Symmetry.hpp"
18#include "Bond.hpp"
19#include "Generator.hpp"
20#include <random>
21
22#ifdef BACKEND_TORCH
23#else
24 #include "backend/Scalar.hpp"
25
26// namespace cytnx{
27namespace cytnx {
28 namespace random {
29 extern std::random_device __static_random_device;
30 }
31
33 class UniTensorType_class {
34 public:
35 enum : int { Void = -99, Dense = 0, Sparse = 1, Block = 2, BlockFermionic = 3 };
36 std::string getname(const int &ut_type) const;
37 };
39
56 extern UniTensorType_class UTenType;
57
59 // class DenseUniTensor;
60 class UniTensor_base : public intrusive_ptr_base<UniTensor_base> {
61 public:
62 int uten_type_id; // the unitensor type id.
63 bool _is_braket_form;
64 bool _is_tag;
65 bool _is_diag;
66 cytnx_int64 _rowrank;
67 std::string _name;
68 std::vector<std::string> _labels;
69 std::vector<Bond> _bonds;
70 std::vector<Symmetry> syms_cache;
71
72 bool _update_braket() {
73 if (_bonds.size() == 0) return false;
74
75 if (this->_bonds[0].type() != bondType::BD_REG) {
76 // check:
77 for (unsigned int i = 0; i < this->_bonds.size(); i++) {
78 if (i < this->_rowrank) {
79 if (this->_bonds[i].type() != bondType::BD_KET) return false;
80 } else {
81 if (this->_bonds[i].type() != bondType::BD_BRA) return false;
82 }
83 }
84 return true;
85 } else {
86 return false;
87 }
88 }
89
90 friend class UniTensor; // allow wrapper to access the private elems
91 friend class DenseUniTensor;
92 friend class BlockUniTensor;
93 friend class BlockFermionicUniTensor;
94
95 UniTensor_base()
96 : _is_tag(false),
97 _name(std::string("")),
98 _is_braket_form(false),
99 _rowrank(0),
100 _is_diag(false),
101 uten_type_id(UTenType.Void){};
102
103 // copy&assignment constr., use intrusive_ptr's !!
104 UniTensor_base(const UniTensor_base &rhs);
105 UniTensor_base &operator=(UniTensor_base &rhs);
106
107 cytnx_uint64 rowrank() const { return this->_rowrank; }
108 bool is_diag() const { return this->_is_diag; }
109 const bool &is_braket_form() const { return this->_is_braket_form; }
110 const bool &is_tag() const { return this->_is_tag; }
111 const std::vector<std::string> &labels() const { return this->_labels; }
118 cytnx_int64 get_index(std::string label) const {
119 std::vector<std::string> labels = this->_labels;
120 for (cytnx_uint64 i = 0; i < labels.size(); i++) {
121 if (labels[i] == label) return i;
122 }
123 return -1;
124 }
125 const std::vector<Bond> &bonds() const { return this->_bonds; }
126
127 Bond &bond_(const cytnx_uint64 &idx) {
128 cytnx_error_msg(idx >= this->rank(), "[ERROR][bond] index %d out of bound, total %d\n", idx,
129 this->rank());
130 return this->_bonds[idx];
131 }
132
133 Bond &bond_(const std::string &label) {
134 auto res = std::find(this->_labels.begin(), this->_labels.end(), label);
135 cytnx_error_msg(res == this->_labels.end(), "[ERROR] label %s not exists.\n", label.c_str());
136 cytnx_uint64 idx = std::distance(this->_labels.begin(), res);
137
138 return this->bond_(idx);
139 }
140
141 const std::string &name() const { return this->_name; }
142 cytnx_uint64 rank() const {
143 cytnx_error_msg(this->_labels.size() != this->_bonds.size(),
144 "[ERROR][UniTensor_base][rank] inconsistent metadata: labels.size()=%zu, "
145 "bonds.size()=%zu.%s",
146 this->_labels.size(), this->_bonds.size(), "\n");
147 return this->_labels.size();
148 }
149 void set_name_(const std::string &in) { this->_name = in; }
150 [[deprecated("Please use set_name_(const std::string &in) instead.")]] void set_name(
151 const std::string &in) {
152 this->set_name_(in);
153 }
154
166 void set_label_(const std::string &oldlabel, const std::string &new_label) {
167 cytnx_int64 idx;
168 auto res = std::find(this->_labels.begin(), this->_labels.end(), oldlabel);
169 cytnx_error_msg(res == this->_labels.end(), "[ERROR] label %s not exists.\n",
170 oldlabel.c_str());
171 idx = std::distance(this->_labels.begin(), res);
172
173 cytnx_error_msg(idx >= this->_labels.size(), "[ERROR] index exceed the rank of UniTensor%s",
174 "\n");
175 // check in:
176 bool is_dup = false;
177 for (cytnx_uint64 i = 0; i < this->_labels.size(); i++) {
178 if (i == idx) continue;
179 if (new_label == this->_labels[i]) {
180 is_dup = true;
181 break;
182 }
183 }
184 cytnx_error_msg(is_dup, "[ERROR] alreay has a label that is the same as the input label%s",
185 "\n");
186 this->_labels[idx] = new_label;
187 }
188 void set_label_(const cytnx_int64 &inx, const std::string &new_label) {
189 cytnx_error_msg(inx < 0, "[ERROR] index is negative%s", "\n");
190 cytnx_error_msg(inx >= this->_labels.size(), "[ERROR] index exceed the rank of UniTensor%s",
191 "\n");
192 // check in:
193 bool is_dup = false;
194 for (cytnx_uint64 i = 0; i < this->_labels.size(); i++) {
195 if (i == inx) continue;
196 if (new_label == this->_labels[i]) {
197 is_dup = true;
198 break;
199 }
200 }
201 cytnx_error_msg(is_dup, "[ERROR] alreay has a label that is the same as the input label%s",
202 "\n");
203 this->_labels[inx] = new_label;
204 }
205 [[deprecated(
206 "Please use set_label_(const std::string &oldlabel, const std::string "
207 "&new_label) instead.")]] void
208 set_label(const std::string &oldlabel, const std::string &new_label) {
209 this->set_label_(oldlabel, new_label);
210 }
211 [[deprecated(
212 "Please use set_label_(const cytnx_int64 &inx, const std::string &new_label) "
213 "instead.")]] void
214 set_label(const cytnx_int64 &inx, const std::string &new_label) {
215 this->set_label_(inx, new_label);
216 }
217
218 [[deprecated("Please use relabel_(const std::vector<std::string> &new_labels) instead.")]] void
219 set_labels(const std::vector<std::string> &new_labels);
220 void relabel_(const std::vector<std::string> &new_labels); // implemented
221 [[deprecated("Please use relabel_(const std::vector<std::string> &new_labels) instead.")]] void
222 relabels_(const std::vector<std::string> &new_labels); // implemented
223 void relabel_(const std::vector<std::string> &old_labels,
224 const std::vector<std::string> &new_labels); // implemented
225 [[deprecated(
226 "Please use relabel_(const std::vector<std::string> &old_labels, const "
227 "std::vector<std::string> &new_labels) instead.")]] void
228 relabels_(const std::vector<std::string> &old_labels,
229 const std::vector<std::string> &new_labels); // implemented
230 void relabel_(const std::string &old_label, const std::string &new_label) {
231 this->set_label_(old_label, new_label);
232 }
233 void relabel_(const cytnx_int64 &inx, const std::string &new_label) {
234 this->set_label_(inx, new_label);
235 }
236
237 int uten_type() { return this->uten_type_id; }
238 std::string uten_type_str() const { return UTenType.getname(this->uten_type_id); }
239
241
242 // string labels!
243 virtual void Init(const std::vector<Bond> &bonds,
244 const std::vector<std::string> &in_labels = {},
245 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
246 const int &device = Device.cpu, const bool &is_diag = false,
247 const bool &no_alloc = false, const std::string &name = "");
248
249 virtual void Init_by_Tensor(const Tensor &in, const bool &is_diag = false,
250 const cytnx_int64 &rowrank = -1, const std::string &name = "");
251 virtual std::vector<cytnx_uint64> shape() const;
252 virtual std::vector<bool> signflip() const;
253 virtual bool is_blockform() const;
254 virtual bool is_contiguous() const;
255 virtual void to_(const int &device);
256 virtual boost::intrusive_ptr<UniTensor_base> to(const int &device);
257 virtual boost::intrusive_ptr<UniTensor_base> clone() const;
258 virtual unsigned int dtype() const;
259 virtual int device() const;
260 virtual std::string dtype_str() const;
261 virtual std::string device_str() const;
262 virtual void set_rowrank_(const cytnx_uint64 &new_rowrank);
263 virtual boost::intrusive_ptr<UniTensor_base> set_rowrank(const cytnx_uint64 &new_rowrank) const;
264
265 virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
266 const cytnx_int64 &rowrank = -1);
267 virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
268 const cytnx_int64 &rowrank = -1);
269 // virtual boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
270 // const cytnx_int64 &rowrank = -1);
271
272 virtual void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
273 virtual void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
274
275 virtual boost::intrusive_ptr<UniTensor_base> permute_nosignflip(
276 const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
277 virtual boost::intrusive_ptr<UniTensor_base> permute_nosignflip(
278 const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
279 virtual void permute_nosignflip_(const std::vector<cytnx_int64> &mapper,
280 const cytnx_int64 &rowrank = -1);
281 virtual void permute_nosignflip_(const std::vector<std::string> &mapper,
282 const cytnx_int64 &rowrank = -1);
283 // virtual void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank =
284 // -1);
285
286 virtual void twist_(const cytnx_int64 &idx);
287 virtual void twist_(const std::string &label);
288 virtual void fermion_twists_();
289
290 virtual boost::intrusive_ptr<UniTensor_base> contiguous_();
291 virtual boost::intrusive_ptr<UniTensor_base> contiguous();
292 virtual boost::intrusive_ptr<UniTensor_base> apply_();
293 virtual boost::intrusive_ptr<UniTensor_base> apply();
294 virtual void print_diagram(const bool &bond_info = false) const;
295 virtual void print_blocks(const bool &full_info = true) const;
296 virtual void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
297
298 virtual boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const;
299
300 virtual cytnx_uint64 Nblocks() const { return 0; };
301 virtual Tensor get_block(const cytnx_uint64 &idx = 0) const; // return a copy of block
302 virtual Tensor get_block(const std::vector<cytnx_int64> &qnum,
303 const bool &force) const; // return a copy of block
304
305 virtual const Tensor &get_block_(const cytnx_uint64 &idx = 0)
306 const; // return a share view of block, this only work for non-symm tensor.
307 virtual const Tensor &get_block_(const std::vector<cytnx_int64> &qnum,
308 const bool &force) const; // return a copy of block
309 virtual Tensor &get_block_(const cytnx_uint64 &idx = 0); // return a share view of block, this
310 // only work for non-symm tensor.
311 virtual Tensor &get_block_(const std::vector<cytnx_int64> &qnum,
312 const bool &force); // return a copy of block
313 virtual bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const;
314
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 &);
318
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> &qnum);
322 virtual void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum);
323
324 // this will only work on non-symm tensor (DenseUniTensor)
325 virtual boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors);
326
327 // this will only work on non-symm tensor (DenseUniTensor)
328 virtual void set(const std::vector<Accessor> &accessors, const Tensor &rhs);
329
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);
350
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);
353
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);
358
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);
363
364 virtual boost::intrusive_ptr<UniTensor_base> relabel(const std::string &old_label,
365 const std::string &new_label);
366
367 virtual boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
368 const std::string &new_label);
369
370 virtual std::vector<Symmetry> syms() const;
371
372 // arithmetic
373 // internal/advanced: the UniTensor-vs-UniTensor overloads below (Add_/Mul_/Sub_/Div_
374 // taking a boost::intrusive_ptr<UniTensor_base>) are not TN operations; python surface
375 // removed per #934. See operator+(const UniTensor&, const UniTensor&) in
376 // include/linalg.hpp for the full rationale. The Scalar overloads (scalar scaling)
377 // remain fully public, including from python.
378 virtual void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
379 virtual void Add_(const Scalar &rhs);
380
381 virtual void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
382 virtual void Mul_(const Scalar &rhs);
383
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);
387
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);
391
392 virtual Tensor Norm() const;
393 virtual boost::intrusive_ptr<UniTensor_base> normalize();
394 virtual void normalize_();
395
396 virtual boost::intrusive_ptr<UniTensor_base> Conj();
397 virtual void Conj_();
398
399 virtual boost::intrusive_ptr<UniTensor_base> Transpose();
400 virtual void Transpose_();
401
402 virtual boost::intrusive_ptr<UniTensor_base> Dagger();
403 virtual void Dagger_();
404
405 virtual void tag_();
406
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);
409
410 virtual bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
411
412 // this a workaround, as virtual function cannot template.
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;
415
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);
436
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;
457
458 virtual void from_(const boost::intrusive_ptr<UniTensor_base> &rhs, bool force,
459 cytnx_double tol = 0.);
460
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();
466
467 virtual void _save_dispatch(std::fstream &f) const;
468 virtual void _load_dispatch(std::fstream &f, unsigned int version);
469
470 virtual ~UniTensor_base(){};
471 };
473
474 //======================================================================
476 class DenseUniTensor : public UniTensor_base {
477 protected:
478 public:
479 Tensor _block;
480 std::vector<Tensor> _interface_block; // this is serves as interface for get_blocks_();
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;
491 return tmp;
492 }
493 //------------------------------------------
494
495 DenseUniTensor() { this->uten_type_id = UTenType.Dense; };
496 friend class UniTensor; // allow wrapper to access the private elems
497 // virtual functions
498
499 // void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels = {},
500 // const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
501 // const int &device = Device.cpu, const bool &is_diag = false,
502 // const bool &no_alloc = false);
503
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 = "");
508 // this only work for non-symm tensor
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]);
515 return shape;
516 } else {
517 return this->_block.shape();
518 }
519 }
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; // this is serves as interface for get_blocks_();
525 return this;
526 } else {
527 boost::intrusive_ptr<UniTensor_base> out = this->clone();
528 out->to_(device);
529 return out;
530 }
531 }
532 void set_rowrank_(const cytnx_uint64 &new_rowrank) {
533 cytnx_error_msg(new_rowrank > this->_labels.size(),
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",
537 "\n");
538 }
539
540 this->_rowrank = new_rowrank;
541 }
542
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);
547 return out_raw;
548 }
549
550 boost::intrusive_ptr<UniTensor_base> clone() const {
551 boost::intrusive_ptr<DenseUniTensor> tmp = this->clone_meta();
552 tmp->_block = this->_block.clone();
553 return tmp;
554 };
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);
573
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);
584
585 void twist_(const cytnx_int64 &idx) override {
586 // do nothing for bosonic UniTensor
587 return;
588 }
589 void twist_(const std::string &label) override {
590 // do nothing for bosonic UniTensor
591 return;
592 }
593
594 void fermion_twists_() override {
595 // do nothing for bosonic UniTensor
596 return;
597 }
598
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);
601
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);
606
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);
621
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);
625 return tmp;
626 }
627
628 std::vector<Symmetry> syms() const {
629 cytnx_error_msg(true, "[ERROR][DenseUniTensor] dense unitensor does not have symmetry.%s",
630 "\n");
631 return std::vector<Symmetry>();
632 }
633
634 boost::intrusive_ptr<UniTensor_base> contiguous_() {
635 // Rebind _block to the non-mutating Tensor::contiguous() result instead of calling
636 // contiguous_() in place, so a block Tensor shared with another UniTensor (e.g. via
637 // relabel()) is not corrupted (#724). Tensor::contiguous() is cheap when the block is
638 // already contiguous (no data copy; same impl returned).
639 this->_block = this->_block.contiguous();
640 return boost::intrusive_ptr<UniTensor_base>(this);
641 }
642 boost::intrusive_ptr<UniTensor_base> contiguous() {
643 // if contiguous then return self!
644 if (this->is_contiguous()) {
645 boost::intrusive_ptr<UniTensor_base> out(this);
646 return out;
647 } else {
648 boost::intrusive_ptr<DenseUniTensor> tmp = this->clone_meta();
649 tmp->_block = this->_block.contiguous();
650 return tmp;
651 }
652 }
653
654 boost::intrusive_ptr<UniTensor_base> apply_() {
655 return boost::intrusive_ptr<UniTensor_base>(this);
656 }
657 boost::intrusive_ptr<UniTensor_base> apply() {
658 // just return self
659 boost::intrusive_ptr<UniTensor_base> out(this);
660 return out;
661 }
662
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 {
668 cytnx_error_msg(idx != 0,
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();
673 }
674
675 Tensor get_block(const std::vector<cytnx_int64> &qnum, const bool &force) const {
677 true, "[ERROR][DenseUniTensor] try to get_block() using qnum on a non-symmetry UniTensor%s",
678 "\n");
679 return Tensor();
680 }
681 // return a share view of block, this only work for non-symm tensor.
682 const Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force) const {
684 true,
685 "[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
686 "\n");
687 return this->_block;
688 }
689 Tensor &get_block_(const std::vector<cytnx_int64> &qnum, const bool &force) {
691 true,
692 "[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
693 "\n");
694 return this->_block;
695 }
696
697 // return a share view of block, this only work for non-symm tensor.
698 Tensor &get_block_() { return this->_block; }
699 Tensor &get_block_(const cytnx_uint64 &idx) {
700 cytnx_error_msg(idx != 0,
701 "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %llu "
702 "invalid. Use get_block_(0).\n",
703 (unsigned long long)idx);
704 return this->_block;
705 }
706 // return a share view of block, this only work for non-symm tensor.
707 const Tensor &get_block_() const { return this->_block; }
708 const Tensor &get_block_(const cytnx_uint64 &idx) const {
709 cytnx_error_msg(idx != 0,
710 "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %llu "
711 "invalid. Use get_block_(0).\n",
712 (unsigned long long)idx);
713 return this->_block;
714 }
715
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");
721 return out; // this will not share memory!!
722 }
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",
726 "\n");
727 return this->_interface_block; // this will not share memory!!
728 }
729 std::vector<Tensor> &get_blocks_(const bool &silent = false) {
731 true, "[ERROR][DenseUniTensor] Cannot use get_blocks_(), use get_block_() instead!%s",
732 "\n");
733 return this->_interface_block; // this will not share memory!!
734 }
735
736 void put_block(const Tensor &in) {
737 // We don't check the dtype for DenseUniTensor, since it'll be more convenient to change
738 // DenseUniTensor's dtype
739
740 // cytnx_error_msg(in.dtype() != this->dtype(),
741 // "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not
742 // match.%s",
743 // "\n");
744 cytnx_error_msg(in.device() != this->device(),
745 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
746 "match.%s",
747 "\n");
748 // We shouldn't check the contiguous
749 // cytnx_error_msg(!in.contiguous());
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();
755 } else {
757 in.shape() != this->shape(),
758 "[ERROR][DenseUniTensor][put_block] the input tensor shape does not match.%s", "\n");
759 this->_block = in.clone();
760 }
761 }
762 void put_block(const Tensor &in, const cytnx_uint64 &idx) {
763 cytnx_error_msg(idx != 0,
764 "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %llu "
765 "invalid. Use put_block(0).\n",
766 (unsigned long long)idx);
767 put_block(in);
768 }
769 // share view of the block
770 void put_block_(Tensor &in) {
771 // We don't check the dtype for DenseUniTensor, since it'll be more convenient to change
772 // DenseUniTensor's dtype
773
774 // cytnx_error_msg(in.dtype() != this->dtype(),
775 // "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not
776 // match.%s",
777 // "\n");
778 cytnx_error_msg(in.device() != this->device(),
779 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
780 "match.%s",
781 "\n");
782 // We shouldn't check the contiguous
783 // cytnx_error_msg(!in.contiguous());
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");
788 this->_block = in;
789 } else {
791 in.shape() != this->shape(),
792 "[ERROR][DenseUniTensor][put_block] the input tensor shape does not match.%s", "\n");
793 this->_block = in;
794 }
795 }
796 void put_block_(Tensor &in, const cytnx_uint64 &idx) {
797 cytnx_error_msg(idx != 0,
798 "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %llu "
799 "invalid. Use put_block_(0).\n",
800 (unsigned long long)idx);
801 put_block_(in);
802 }
803
804 void put_block(const Tensor &in, const std::vector<cytnx_int64> &qnum) {
806 true, "[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
807 "\n");
808 }
809 void put_block_(Tensor &in, const std::vector<cytnx_int64> &qnum) {
811 true, "[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
812 "\n");
813 }
814 // these two methods only work on non-symm tensor (DenseUniTensor)
815 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors);
816 void set(const std::vector<Accessor> &accessors, const Tensor &rhs);
817
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();
822 void 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) {
832 cytnx_error_msg(true, "[ERROR][DenseUniTensor] %s",
833 "getTotalQnums can only operate on UniTensor with symmetry.\n");
834 return std::vector<Bond>();
835 }
836
837 std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const {
838 cytnx_error_msg(true, "[ERROR][DenseUniTensor] %s",
839 "get_blocks_qnums can only operate on UniTensor with symmetry.\n");
840 return std::vector<std::vector<cytnx_int64>>();
841 }
842
843 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const {
844 if (rhs->uten_type() != UTenType.Dense) return false;
845
846 return this->get_block_().same_data(rhs->get_block_());
847 }
848
849 ~DenseUniTensor(){};
850
851 // arithmetic
852 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
853 void Add_(const Scalar &rhs);
854
855 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
856 void Mul_(const Scalar &rhs);
857
858 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
859 void Sub_(const Scalar &rhs);
860 void lSub_(const Scalar &lhs);
861
862 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
863 void Div_(const Scalar &rhs);
864 void lDiv_(const Scalar &lhs);
865
866 void Conj_() { this->_block.Conj_(); };
867
868 boost::intrusive_ptr<UniTensor_base> Conj() {
869 boost::intrusive_ptr<UniTensor_base> out = this->clone();
870 out->Conj_();
871 return out;
872 }
873
874 boost::intrusive_ptr<UniTensor_base> Transpose() {
875 boost::intrusive_ptr<UniTensor_base> out = this->clone();
876 out->Transpose_();
877 return out;
878 }
879 void Transpose_();
880
881 boost::intrusive_ptr<UniTensor_base> normalize() {
882 boost::intrusive_ptr<UniTensor_base> out = this->clone();
883 out->normalize_();
884 return out;
885 }
886 void normalize_();
887
888 boost::intrusive_ptr<UniTensor_base> Dagger() {
889 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
890 out->Transpose_();
891 return out;
892 }
893 void Dagger_() {
894 this->Conj_();
895 this->Transpose_();
896 }
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();
910 out->Trace_(a, b);
911 return out;
912 }
913 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b) {
914 boost::intrusive_ptr<UniTensor_base> out = this->clone();
915 out->Trace_(a, b);
916 return out;
917 }
918
919 Tensor Norm() const;
920
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",
924 "\n");
925 return Scalar::Sproxy();
926 }
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",
931 "\n");
932 return cytnx_complex128(0, 0);
933 }
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",
938 "\n");
939 return cytnx_complex64(0, 0);
940 }
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",
945 "\n");
946 return 0;
947 }
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",
952 "\n");
953 return 0;
954 }
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",
959 "\n");
960 return 0;
961 }
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",
966 "\n");
967 return 0;
968 }
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",
973 "\n");
974 return 0;
975 }
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",
980 "\n");
981 return 0;
982 }
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",
987 "\n");
988 return 0;
989 }
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",
994 "\n");
995 return 0;
996 }
997
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",
1001 "\n");
1002 return Scalar::Sproxy();
1003 }
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",
1008 "\n");
1009 return *(cytnx_complex128 *)nullptr;
1010 }
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",
1015 "\n");
1016 return *(cytnx_complex64 *)nullptr;
1017 }
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",
1021 "\n");
1022 return *(cytnx_double *)nullptr;
1023 }
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",
1027 "\n");
1028 return *(cytnx_float *)nullptr;
1029 }
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",
1033 "\n");
1034 return *(cytnx_uint64 *)nullptr;
1035 }
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",
1039 "\n");
1040 return *(cytnx_int64 *)nullptr;
1041 }
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",
1045 "\n");
1046 return *(cytnx_uint32 *)nullptr;
1047 }
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",
1051 "\n");
1052 return *(cytnx_int32 *)nullptr;
1053 }
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",
1057 "\n");
1058 return *(cytnx_uint16 *)nullptr;
1059 }
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",
1063 "\n");
1064 return *(cytnx_int16 *)nullptr;
1065 }
1066
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",
1070 "\n");
1071 }
1072 void tag_() {
1073 if (!this->is_tag()) {
1074 for (int i = 0; i < this->_rowrank; i++) {
1075 this->_bonds[i] = this->_bonds[i].retype(BD_KET);
1076 }
1077 for (int i = this->_rowrank; i < this->_bonds.size(); i++) {
1078 this->_bonds[i] = this->_bonds[i].retype(BD_BRA);
1079 }
1080 this->_is_tag = true;
1081 this->_is_braket_form = this->_update_braket();
1082 }
1083 }
1093 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim);
1094 void truncate_(const std::string &label, const cytnx_uint64 &dim);
1095
1096 void from_(const boost::intrusive_ptr<UniTensor_base> &rhs, bool force, cytnx_double tol = 0.);
1097
1098 void group_basis_() {
1099 cytnx_warning_msg(true, "[WARNING] group basis will not have any effect on DensUniTensor.%s",
1100 "\n");
1101 }
1102
1103 void _save_dispatch(std::fstream &f) const;
1104 void _load_dispatch(std::fstream &f, unsigned int version);
1105
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",
1108 "\n");
1109 }
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",
1112 "\n");
1113 }
1114
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",
1117 "\n");
1118 }
1119 vec2d<cytnx_uint64> &get_itoi() {
1120 cytnx_error_msg(true, "[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s",
1121 "\n");
1122 }
1123
1124 // end virtual function
1125 };
1127
1128 //======================================================================
1130 class BlockUniTensor : public UniTensor_base {
1131 protected:
1132 public:
1133 std::vector<std::vector<cytnx_uint64>>
1134 _inner_to_outer_idx; // stores the qindices for each block
1135 std::vector<Tensor> _blocks;
1136 Tensor NullRefTensor; // this returns when access block does not exists!
1137
1138 // given an index list [loc], get qnums from this->_bonds[loc] and return the combined qnums
1139 // calculated from Symm object! this assume 1. symmetry are the same for each bond!
1140 // 2. total_qns are feeded with size len(symmetry)
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");
1146 cytnx_error_msg(total_qns.size() != syms.size(),
1147 "[ERROR][BlockUniTensor] total_qns size does not match symmetry count.%s",
1148 "\n");
1149 std::fill(total_qns.begin(), total_qns.end(), 0);
1150 if (this->_bonds.empty()) return;
1151
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]);
1155 else
1156 total_qns[i] = this->_bonds[0]._impl->_qnums[loc[0]][i];
1157
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]));
1162 else {
1163 total_qns[i] =
1164 syms[i].combine_rule(total_qns[i], this->_bonds[j]._impl->_qnums[loc[j]][i]);
1165 }
1166 }
1167 }
1168 }
1169
1170 void _fx_locate_elem(cytnx_int64 &bidx, std::vector<cytnx_uint64> &loc_in_T,
1171 const std::vector<cytnx_uint64> &locator) const;
1172
1173 // internal function, grouping all duplicate qnums in all bonds
1174 void _fx_group_duplicates(const std::vector<cytnx_uint64> &dup_bond_idxs,
1175 const std::vector<std::vector<cytnx_uint64>> &idx_mappers);
1176
1177 void set_meta(BlockUniTensor *tmp, const bool &inner, const bool &outer) const {
1178 // outer meta
1179 if (outer) {
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;
1186 }
1187
1188 tmp->_is_diag = this->_is_diag;
1189
1190 // inner meta
1191 if (inner) {
1192 tmp->_inner_to_outer_idx = this->_inner_to_outer_idx;
1193 }
1194 }
1195
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);
1199 return tmp;
1200 };
1201
1202 friend class UniTensor;
1203 BlockUniTensor() {
1204 this->uten_type_id = UTenType.Block;
1205 this->_is_tag = true;
1206 }
1207
1208 // virtual functions:
1209 // void Init(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels = {},
1210 // const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1211 // const int &device = Device.cpu, const bool &is_diag = false,
1212 // const bool &no_alloc = false);
1213
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 = "");
1218
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");
1223 }
1224
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();
1230 }
1231 return out;
1232 }
1233
1234 bool is_blockform() const { return true; }
1235 bool is_contiguous() const {
1236 bool out = true;
1237 for (int i = 0; i < this->_blocks.size(); i++) {
1238 out &= this->_blocks[i].is_contiguous();
1239 }
1240 return out;
1241 };
1242
1243 cytnx_uint64 Nblocks() const { return this->_blocks.size(); };
1244
1245 void to_(const int &device) {
1246 for (cytnx_uint64 i = 0; i < this->_blocks.size(); i++) {
1247 this->_blocks[i].to_(device);
1248 }
1249 };
1250
1251 boost::intrusive_ptr<UniTensor_base> to(const int &device) {
1252 if (this->device() == device) {
1253 return this;
1254 } else {
1255 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1256 out->to_(device);
1257 return out;
1258 }
1259 };
1260
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);
1264 return tmp;
1265 };
1266
1267 unsigned int dtype() const {
1268 //[21 Aug 2024] This is a copy from BlockUniTensor;
1269 #ifdef UNI_DEBUG
1270 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1271 "\n");
1272 #endif
1273 return this->_blocks.size() < 1 ? Type.Void : this->_blocks[0].dtype();
1274 };
1275 int device() const {
1276 //[21 Aug 2024] This is a copy from BlockUniTensor;
1277 #ifdef UNI_DEBUG
1278 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1279 "\n");
1280 #endif
1281 return this->_blocks.size() < 1 ? -404 : this->_blocks[0].device();
1282 };
1283 std::string dtype_str() const {
1284 //[21 Aug 2024] This is a copy from BlockUniTensor;
1285 #ifdef UNI_DEBUG
1286 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1287 "\n");
1288 #endif
1289 return this->_blocks.size() < 1 ? "Void, no valid blocks" : this->_blocks[0].dtype_str();
1290 };
1291 std::string device_str() const {
1292 //[21 Aug 2024] This is a copy from BlockUniTensor;
1293 #ifdef UNI_DEBUG
1294 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
1295 "\n");
1296 #endif
1297 return this->_blocks.size() < 1 ? "None, no valid blocks" : this->_blocks[0].device_str();
1298 };
1299
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",
1302 "\n");
1303 return this->_blocks[idx].clone();
1304 };
1305
1306 // this one for Block will return the indicies!!
1307 Tensor get_block(const std::vector<cytnx_int64> &indices, const bool &force_return) const {
1308 if (this->rank() == 0) {
1309 cytnx_error_msg(!indices.empty(),
1310 "[ERROR][get_block][BlockUniTensor] rank-0 scalar block expects no "
1311 "qnum indices.%s",
1312 "\n");
1313 cytnx_error_msg(this->_blocks.empty(), "[ERROR][BlockUniTensor] index out of range%s",
1314 "\n");
1315 return this->_blocks[0].clone();
1316 }
1317 cytnx_error_msg(indices.size() != this->rank(),
1318 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1319 "Tensor rank (number of legs).%s",
1320 "\n");
1321
1322 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1323
1324 // find if the indices specify exists!
1325 cytnx_int64 b = -1;
1326 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1327 if (inds == this->_inner_to_outer_idx[i]) {
1328 b = i;
1329 break;
1330 }
1331 }
1332
1333 if (b < 0) {
1334 if (force_return) {
1335 return NullRefTensor;
1336 } else {
1337 cytnx_error_msg(true,
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",
1343 "\n");
1344 }
1345 } else {
1346 return this->_blocks[b].clone();
1347 }
1348 }
1349
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",
1352 "\n");
1353 return this->_blocks[idx];
1354 };
1355
1356 Tensor &get_block_(const cytnx_uint64 &idx = 0) {
1357 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1358 "\n");
1359 return this->_blocks[idx];
1360 };
1361
1362 const Tensor &get_block_(const std::vector<cytnx_int64> &indices,
1363 const bool &force_return) const {
1364 if (this->rank() == 0) {
1365 cytnx_error_msg(!indices.empty(),
1366 "[ERROR][get_block][BlockUniTensor] rank-0 scalar block expects no "
1367 "qnum indices.%s",
1368 "\n");
1369 cytnx_error_msg(this->_blocks.empty(), "[ERROR][BlockUniTensor] index out of range%s",
1370 "\n");
1371 return this->_blocks[0];
1372 }
1373 cytnx_error_msg(indices.size() != this->rank(),
1374 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1375 "Tensor rank (number of legs).%s",
1376 "\n");
1377
1378 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1379
1380 // find if the indices specify exists!
1381 cytnx_int64 b = -1;
1382 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1383 if (inds == this->_inner_to_outer_idx[i]) {
1384 b = i;
1385 break;
1386 }
1387 }
1388
1389 if (b < 0) {
1390 if (force_return) {
1391 return this->NullRefTensor;
1392 } else {
1393 cytnx_error_msg(true,
1394 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1395 "force_return=false, so "
1396 "error throws. \n If you want to return an empty block without "
1397 "error when block is "
1398 "not avaliable, set force_return=True.%s",
1399 "\n");
1400 }
1401 } else {
1402 return this->_blocks[b];
1403 }
1404 }
1405
1406 Tensor &get_block_(const std::vector<cytnx_int64> &indices, const bool &force_return) {
1407 if (this->rank() == 0) {
1408 cytnx_error_msg(!indices.empty(),
1409 "[ERROR][get_block][BlockUniTensor] rank-0 scalar block expects no "
1410 "qnum indices.%s",
1411 "\n");
1412 cytnx_error_msg(this->_blocks.empty(), "[ERROR][BlockUniTensor] index out of range%s",
1413 "\n");
1414 return this->_blocks[0];
1415 }
1416 cytnx_error_msg(indices.size() != this->rank(),
1417 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1418 "Tensor rank (number of legs).%s",
1419 "\n");
1420
1421 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1422
1423 // find if the indices specify exists!
1424 cytnx_int64 b = -1;
1425 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1426 if (inds == this->_inner_to_outer_idx[i]) {
1427 b = i;
1428 break;
1429 }
1430 }
1431
1432 if (b < 0) {
1433 if (force_return) {
1434 return this->NullRefTensor;
1435 } else {
1436 cytnx_error_msg(true,
1437 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1438 "force_return=false, so "
1439 "error throws. \n If you want to return an empty block without "
1440 "error when block is "
1441 "not avaliable, set force_return=True.%s",
1442 "\n");
1443 }
1444 } else {
1445 return this->_blocks[b];
1446 }
1447 }
1448
1449 std::vector<Tensor> get_blocks() const { return vec_clone(this->_blocks); }
1450 const std::vector<Tensor> &get_blocks_(const bool &) const { return this->_blocks; }
1451 std::vector<Tensor> &get_blocks_(const bool &) { return this->_blocks; }
1452
1453 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const {
1454 if (rhs->uten_type() != UTenType.Block) return false;
1455 if (rhs->get_blocks_(1).size() != this->get_blocks_(1).size()) return false;
1456
1457 for (int i = 0; i < rhs->get_blocks_(1).size(); i++)
1458 if (this->get_blocks_(1)[i].same_data(rhs->get_blocks_(1)[i]) == false) return false;
1459
1460 return true;
1461 }
1462
1463 void set_rowrank_(const cytnx_uint64 &new_rowrank) {
1464 cytnx_error_msg(new_rowrank > this->rank(),
1465 "[ERROR][BlockUniTensor] rowrank should be [>=0] and [<=UniTensor.rank].%s",
1466 "\n");
1467 if (this->is_diag()) {
1468 cytnx_error_msg(new_rowrank != 1,
1469 "[ERROR][BlockUniTensor] rowrank should be [==1] when is_diag =true!.%s",
1470 "\n");
1471 }
1472 this->_rowrank = new_rowrank;
1473 this->_is_braket_form = this->_update_braket();
1474 }
1475
1476 boost::intrusive_ptr<UniTensor_base> set_rowrank(const cytnx_uint64 &new_rowrank) const {
1477 boost::intrusive_ptr<BlockUniTensor> tmp = this->clone_meta(true, true);
1478 tmp->_blocks = this->_blocks;
1479 tmp->set_rowrank_(new_rowrank);
1480 return tmp;
1481 }
1482
1483 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
1484 const cytnx_int64 &rowrank = -1);
1485 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
1486 const cytnx_int64 &rowrank = -1);
1487
1488 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1);
1489 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1);
1490
1491 void twist_(const cytnx_int64 &idx) override {
1492 // do nothing for bosonic UniTensor
1493 return;
1494 }
1495 void fermion_twists_() override {
1496 // do nothing for bosonic UniTensor
1497 return;
1498 }
1499 void twist_(const std::string &label) override {
1500 // do nothing for bosonic UniTensor
1501 return;
1502 }
1503
1504 boost::intrusive_ptr<UniTensor_base> contiguous_() {
1505 // Rebind each block to the non-mutating Tensor::contiguous() result instead of calling
1506 // contiguous_() in place, so a block Tensor shared with another UniTensor (e.g. via
1507 // relabel()) is not corrupted (#724). Tensor::contiguous() is cheap when the block is
1508 // already contiguous (no data copy; same impl returned).
1509 for (unsigned int b = 0; b < this->_blocks.size(); b++)
1510 this->_blocks[b] = this->_blocks[b].contiguous();
1511 return boost::intrusive_ptr<UniTensor_base>(this);
1512 }
1513 boost::intrusive_ptr<UniTensor_base> contiguous();
1514
1515 boost::intrusive_ptr<UniTensor_base> apply_() {
1516 return boost::intrusive_ptr<UniTensor_base>(this);
1517 }
1518 boost::intrusive_ptr<UniTensor_base> apply() {
1519 // just return self
1520 boost::intrusive_ptr<UniTensor_base> out(this);
1521 return out;
1522 }
1523
1524 void print_diagram(const bool &bond_info = false) const;
1525 void print_blocks(const bool &full_info = true) const;
1526 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
1527
1528 boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs,
1529 const bool &mv_elem_self = false,
1530 const bool &mv_elem_rhs = false);
1531
1532 boost::intrusive_ptr<UniTensor_base> relabel(const std::vector<std::string> &new_labels);
1533 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &new_labels);
1534
1535 boost::intrusive_ptr<UniTensor_base> relabel(const std::vector<std::string> &old_labels,
1536 const std::vector<std::string> &new_labels);
1537 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &old_labels,
1538 const std::vector<std::string> &new_labels);
1539
1540 boost::intrusive_ptr<UniTensor_base> relabel(const std::string &old_label,
1541 const std::string &new_label);
1542 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
1543 const std::string &new_label);
1544
1545 std::vector<Symmetry> syms() const;
1546
1547 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
1548 cytnx_error_msg(true, "[ERROR] Cannot reshape a UniTensor with symmetry.%s", "\n");
1549 }
1550 boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
1551 const cytnx_uint64 &rowrank = 0) {
1552 cytnx_error_msg(true, "[ERROR] Cannot reshape a UniTensor with symmetry.%s", "\n");
1553 return nullptr;
1554 }
1555
1556 boost::intrusive_ptr<UniTensor_base> to_dense();
1557 void to_dense_();
1558
1559 boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const {
1560 boost::intrusive_ptr<BlockUniTensor> tmp = this->clone_meta(true, true);
1561 tmp->_blocks.resize(this->_blocks.size());
1562 for (cytnx_int64 blk = 0; blk < this->_blocks.size(); blk++) {
1563 tmp->_blocks[blk] = this->_blocks[blk].astype(dtype);
1564 }
1565 return tmp;
1566 };
1567
1568 // this will only work on non-symm tensor (DenseUniTensor)
1569 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors) {
1571 true,
1572 "[ERROR][BlockUniTensor][get] Cannot use get on a UniTensor with "
1573 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
1574 "\n");
1575 return nullptr;
1576 }
1577
1578 // this will only work on non-symm tensor (DenseUniTensor)
1579 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
1581 true,
1582 "[ERROR][BlockUniTensor][get] Cannot use get on a UniTensor with "
1583 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
1584 "\n");
1585 }
1586
1587 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
1588 cytnx_error_msg(in.dtype() != this->dtype(),
1589 "[ERROR][BlockUniTensor][put_block] The input tensor dtype does not match.%s",
1590 "\n");
1591 cytnx_error_msg(in.device() != this->device(),
1592 "[ERROR][BlockUniTensor][put_block] The input tensor device does not "
1593 "match.%s",
1594 "\n");
1595 // We shouldn't check the contiguous
1596 // cytnx_error_msg(!in.contiguous());
1597 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1598 "\n");
1599 cytnx_error_msg(in.shape() != this->_blocks[idx].shape(),
1600 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1601 "of block @ idx=%d\n",
1602 idx);
1603
1604 this->_blocks[idx] = in.clone();
1605 }
1606 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) {
1607 cytnx_error_msg(in.dtype() != this->dtype(),
1608 "[ERROR][BlockUniTensor][put_block] The input tensor dtype does not match.%s",
1609 "\n");
1610 cytnx_error_msg(in.device() != this->device(),
1611 "[ERROR][BlockUniTensor][put_block] The input tensor device does not "
1612 "match.%s",
1613 "\n");
1614 // We shouldn't check the contiguous
1615 // cytnx_error_msg(!in.contiguous());
1616 cytnx_error_msg(idx >= this->_blocks.size(), "[ERROR][BlockUniTensor] index out of range%s",
1617 "\n");
1618 cytnx_error_msg(in.shape() != this->_blocks[idx].shape(),
1619 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1620 "of block @ idx=%d\n",
1621 idx);
1622
1623 this->_blocks[idx] = in;
1624 }
1625 void put_block(const Tensor &in, const std::vector<cytnx_int64> &indices) {
1626 cytnx_error_msg(in.dtype() != this->dtype(),
1627 "[ERROR][BlockUniTensor][put_block] The input tensor dtype does not match.%s",
1628 "\n");
1629 cytnx_error_msg(in.device() != this->device(),
1630 "[ERROR][BlockUniTensor][put_block] The input tensor device does not "
1631 "match.%s",
1632 "\n");
1633 // We shouldn't check the contiguous
1634 // cytnx_error_msg(!in.contiguous());
1635 cytnx_error_msg(indices.size() != this->rank(),
1636 "[ERROR][put_block][BlockUniTensor] len(indices) must be the same as the "
1637 "Tensor rank (number of legs).%s",
1638 "\n");
1639
1640 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1641
1642 // find if the indices specify exists!
1643 cytnx_int64 b = -1;
1644 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1645 if (inds == this->_inner_to_outer_idx[i]) {
1646 b = i;
1647 break;
1648 }
1649 }
1650
1651 if (b < 0) {
1652 cytnx_error_msg(true, "[ERROR][put_block][BlockUniTensor] no avaliable block exists.%s",
1653 "\n");
1654 } else {
1656 in.shape() != this->_blocks[b].shape(),
1657 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1658 "of block @ idx=%d\n",
1659 b);
1660
1661 this->_blocks[b] = in.clone();
1662 }
1663 }
1664 void put_block_(Tensor &in, const std::vector<cytnx_int64> &indices) {
1665 cytnx_error_msg(in.dtype() != this->dtype(),
1666 "[ERROR][BlockUniTensor][put_block] The input tensor dtype does not match.%s",
1667 "\n");
1668 cytnx_error_msg(in.device() != this->device(),
1669 "[ERROR][BlockUniTensor][put_block] The input tensor device does not "
1670 "match.%s",
1671 "\n");
1672 // We shouldn't check the contiguous
1673 // cytnx_error_msg(!in.contiguous());
1674 cytnx_error_msg(indices.size() != this->rank(),
1675 "[ERROR][put_block][BlockUniTensor] len(indices) must be the same as the "
1676 "Tensor rank (number of legs).%s",
1677 "\n");
1678
1679 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1680
1681 // find if the indices specify exists!
1682 cytnx_int64 b = -1;
1683 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1684 if (inds == this->_inner_to_outer_idx[i]) {
1685 b = i;
1686 break;
1687 }
1688 }
1689
1690 if (b < 0) {
1691 cytnx_error_msg(true, "[ERROR][put_block][BlockUniTensor] no avaliable block exists.%s",
1692 "\n");
1693 } else {
1695 in.shape() != this->_blocks[b].shape(),
1696 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1697 "of block @ idx=%d\n",
1698 b);
1699 this->_blocks[b] = in;
1700 }
1701 }
1702
1703 void tag_() {
1704 // no-use!
1705 }
1706
1707 boost::intrusive_ptr<UniTensor_base> Conj() {
1708 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1709 out->Conj_();
1710 return out;
1711 }
1712
1713 void Conj_() {
1714 for (int i = 0; i < this->_blocks.size(); i++) {
1715 this->_blocks[i].Conj_();
1716 }
1717 };
1718
1719 void Transpose_();
1720 boost::intrusive_ptr<UniTensor_base> Transpose() {
1721 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1722 out->Transpose_();
1723 return out;
1724 }
1725
1726 void normalize_();
1727 boost::intrusive_ptr<UniTensor_base> normalize() {
1728 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1729 out->normalize_();
1730 return out;
1731 }
1732
1733 boost::intrusive_ptr<UniTensor_base> Dagger() {
1734 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
1735 out->Transpose_();
1736 return out;
1737 }
1738 void Dagger_() {
1739 this->Conj_();
1740 this->Transpose_();
1741 }
1742
1743 void Trace_(const std::string &a, const std::string &b);
1744 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
1745
1746 boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b) {
1747 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1748 out->Trace_(a, b);
1749 return out;
1750 }
1751 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b) {
1752 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1753 out->Trace_(a, b);
1754 return out;
1755 }
1756
1757 Tensor Norm() const;
1758
1759 bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
1760
1761 const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const;
1762 const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1763 const cytnx_complex128 &aux) const;
1764 const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1765 const cytnx_complex64 &aux) const;
1766 const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1767 const cytnx_double &aux) const;
1768 const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1769 const cytnx_float &aux) const;
1770 const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1771 const cytnx_uint64 &aux) const;
1772 const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1773 const cytnx_int64 &aux) const;
1774 const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1775 const cytnx_uint32 &aux) const;
1776 const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1777 const cytnx_int32 &aux) const;
1778 const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1779 const cytnx_uint16 &aux) const;
1780 const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1781 const cytnx_int16 &aux) const;
1782
1783 Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator);
1784 cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1785 const cytnx_complex128 &aux);
1786 cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
1787 const cytnx_complex64 &aux);
1788 cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux);
1789 cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux);
1790 cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux);
1791 cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux);
1792 cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux);
1793 cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux);
1794 cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux);
1795 cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux);
1796
1797 void _save_dispatch(std::fstream &f) const;
1798 void _load_dispatch(std::fstream &f, unsigned int version);
1799
1800 // this will remove the [q_index]-th qnum at [bond_idx]-th Bond!
1801 void truncate_(const std::string &label, const cytnx_uint64 &q_index);
1802 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &q_index);
1803
1804 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1805 void Add_(const Scalar &rhs) {
1807 true,
1808 "[ERROR] Cannot perform elementwise arithmetic '+' between Scalar and BlockUniTensor.\n %s "
1809 "\n",
1810 "This operation would destroy the block structure. [Suggest] Avoid or use get/put_block(s) "
1811 "to do operation on blocks.");
1812 }
1813
1814 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1815 void Mul_(const Scalar &rhs);
1816
1817 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1818 void Sub_(const Scalar &rhs) {
1820 true,
1821 "[ERROR] Cannot perform elementwise arithmetic '-' between Scalar and BlockUniTensor.\n %s "
1822 "\n",
1823 "This operation would destroy the block structure. [Suggest] Avoid or use get/put_block(s) "
1824 "to do operation on blocks.");
1825 }
1826 void lSub_(const Scalar &lhs) {
1828 true,
1829 "[ERROR] Cannot perform elementwise arithmetic '-' between Scalar and BlockUniTensor.\n %s "
1830 "\n",
1831 "This operation would destroy the block structure. [Suggest] Avoid or use get/put_block(s) "
1832 "to do operation on blocks.");
1833 }
1834
1835 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
1836 void Div_(const Scalar &rhs);
1837 void lDiv_(const Scalar &lhs) {
1839 true,
1840 "[ERROR] Cannot perform elementwise arithmetic '/' between Scalar and BlockUniTensor.\n %s "
1841 "\n",
1842 "This operation would cause division by zero on non-block elements. [Suggest] Avoid or use "
1843 "get/put_block(s) to do operation on blocks.");
1844 }
1845 void from_(const boost::intrusive_ptr<UniTensor_base> &rhs, bool force, cytnx_double tol = 0.);
1846
1847 void group_basis_();
1848
1849 void combineBond(const std::vector<std::string> &indicators, const bool &force = false);
1850 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = false);
1851 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
1852 const bool &by_label);
1853 void combineBonds(const std::vector<std::string> &indicators, const bool &force = false);
1854
1855 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
1857 bidx >= this->Nblocks(),
1858 "[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
1859 this->Nblocks());
1860 return this->_inner_to_outer_idx[bidx];
1861 }
1862 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
1864 bidx >= this->Nblocks(),
1865 "[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
1866 this->Nblocks());
1867 return this->_inner_to_outer_idx[bidx];
1868 }
1869
1870 const vec2d<cytnx_uint64> &get_itoi() const { return this->_inner_to_outer_idx; }
1871 vec2d<cytnx_uint64> &get_itoi() { return this->_inner_to_outer_idx; }
1872 };
1874
1875 //======================================================================
1877 class BlockFermionicUniTensor : public UniTensor_base {
1878 //[21 Aug 2024] This is a copy from BlockUniTensor; additionally sign flips are stored as
1879 //_signflip and taken care of in all the methods
1880 public:
1881 std::vector<std::vector<cytnx_uint64>>
1882 _inner_to_outer_idx; // stores the qindices for each block
1883 std::vector<Tensor> _blocks;
1884 Tensor NullRefTensor; // this returns when accessed block does not exists!
1885
1886 // given an index list [loc], get qnums from this->_bonds[loc] and return the combined qnums
1887 // calculated from Symm object! this assume 1. symmetry are the same for each bond!
1888 // 2. total_qns are feeded with size len(symmetry)
1889 void _fx_get_total_fluxs(std::vector<cytnx_uint64> &loc, const std::vector<Symmetry> &syms,
1890 std::vector<cytnx_int64> &total_qns) {
1891 //[21 Aug 2024] This is a copy from BlockUniTensor;
1893 loc.size() != this->_bonds.size(),
1894 "[ERROR][BlockFermionicUniTensor] qnum location rank does not match the number of bonds.%s",
1895 "\n");
1897 total_qns.size() != syms.size(),
1898 "[ERROR][BlockFermionicUniTensor] total_qns size does not match symmetry count.%s", "\n");
1899 std::fill(total_qns.begin(), total_qns.end(), 0);
1900 if (this->_bonds.empty()) return;
1901
1902 for (cytnx_int32 i = 0; i < syms.size(); i++) {
1903 if (this->_bonds[0].type() == BD_BRA)
1904 total_qns[i] = syms[i].reverse_rule(this->_bonds[0]._impl->_qnums[loc[0]][i]);
1905 else
1906 total_qns[i] = this->_bonds[0]._impl->_qnums[loc[0]][i];
1907
1908 for (auto j = 1; j < loc.size(); j++) {
1909 if (this->_bonds[j].type() == BD_BRA)
1910 total_qns[i] = syms[i].combine_rule(
1911 total_qns[i], syms[i].reverse_rule(this->_bonds[j]._impl->_qnums[loc[j]][i]));
1912 else {
1913 total_qns[i] =
1914 syms[i].combine_rule(total_qns[i], this->_bonds[j]._impl->_qnums[loc[j]][i]);
1915 }
1916 }
1917 }
1918 }
1919
1920 void _fx_locate_elem(cytnx_int64 &bidx, std::vector<cytnx_uint64> &loc_in_T,
1921 const std::vector<cytnx_uint64> &locator) const;
1922
1923 // internal function, grouping all duplicate qnums in all bonds
1924 void _fx_group_duplicates(const std::vector<cytnx_uint64> &dup_bond_idxs,
1925 const std::vector<std::vector<cytnx_uint64>> &idx_mappers);
1926
1927 void set_meta(BlockFermionicUniTensor *tmp, const bool &inner, const bool &outer) const {
1928 //[21 Aug 2024] This is a copy from BlockUniTensor; additionally, _signflip is set
1929 // outer meta
1930 if (outer) {
1931 tmp->_bonds = vec_clone(this->_bonds);
1932 tmp->_labels = this->_labels;
1933 tmp->syms_cache = vec_clone(this->syms_cache);
1934 tmp->_is_braket_form = this->_is_braket_form;
1935 tmp->_rowrank = this->_rowrank;
1936 tmp->_name = this->_name;
1937 // tmp->_signflip = vec_clone(this->_signflip);
1938 tmp->_signflip = this->_signflip;
1939 }
1940
1941 tmp->_is_diag = this->_is_diag;
1942
1943 // inner meta
1944 if (inner) {
1945 tmp->_inner_to_outer_idx = this->_inner_to_outer_idx;
1946 }
1947 }
1948
1949 boost::intrusive_ptr<BlockFermionicUniTensor> clone_meta(const bool &inner,
1950 const bool &outer) const {
1951 //[21 Aug 2024] This is a copy from BlockUniTensor;
1952 boost::intrusive_ptr<BlockFermionicUniTensor> tmp(new BlockFermionicUniTensor());
1953 this->set_meta(tmp.get(), inner, outer);
1954 return tmp;
1955 };
1956
1957 friend class UniTensor;
1958 BlockFermionicUniTensor() {
1959 //[21 Aug 2024] This is a copy from BlockUniTensor;
1960 this->uten_type_id = UTenType.BlockFermionic;
1961 this->_is_tag = true;
1962 }
1963
1964 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
1965 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
1966 const int &device = Device.cpu, const bool &is_diag = false,
1967 const bool &no_alloc = false, const std::string &name = "");
1968
1969 void Init_by_Tensor(const Tensor &in_tensor, const bool &is_diag = false,
1970 const cytnx_int64 &rowrank = -1, const std::string &name = "") {
1971 cytnx_error_msg(true,
1972 "[ERROR][BlockFermionicUniTensor] Cannot use Init_by_tensor() on a "
1973 "BlockFermionicUniTensor.%s",
1974 "\n");
1975 }
1976
1977 std::vector<cytnx_uint64> shape() const {
1978 //[21 Aug 2024] This is a copy from BlockUniTensor;
1979 if (this->rank() == 0) return {};
1980 std::vector<cytnx_uint64> out(this->_bonds.size());
1981 for (cytnx_uint64 i = 0; i < out.size(); i++) {
1982 out[i] = this->_bonds[i].dim();
1983 }
1984 return out;
1985 }
1986
1987 bool is_blockform() const {
1988 //[21 Aug 2024] This is a copy from BlockUniTensor;
1989 return true;
1990 }
1991
1992 bool is_contiguous() const {
1993 //[21 Aug 2024] This is a copy from BlockUniTensor;
1994 bool out = true;
1995 for (int i = 0; i < this->_blocks.size(); i++) {
1996 out &= this->_blocks[i].is_contiguous();
1997 }
1998 return out;
1999 };
2000
2001 cytnx_uint64 Nblocks() const {
2002 //[21 Aug 2024] This is a copy from BlockUniTensor;
2003 return this->_blocks.size();
2004 };
2005
2006 std::vector<bool> signflip() const override { return this->_signflip; };
2007
2011 void reset_signflip_() { this->_signflip.assign(this->_blocks.size(), false); }
2012
2017 void erase_signflip_(const std::vector<cytnx_uint64> &positions);
2018
2019 void to_(const int &device) {
2020 //[21 Aug 2024] This is a copy from BlockUniTensor;
2021 for (cytnx_uint64 i = 0; i < this->_blocks.size(); i++) {
2022 this->_blocks[i].to_(device);
2023 }
2024 };
2025
2026 boost::intrusive_ptr<UniTensor_base> to(const int &device) {
2027 //[21 Aug 2024] This is a copy from BlockUniTensor;
2028 if (this->device() == device) {
2029 return this;
2030 } else {
2031 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2032 out->to_(device);
2033 return out;
2034 }
2035 };
2036
2037 boost::intrusive_ptr<UniTensor_base> clone() const {
2038 //[21 Aug 2024] This is a copy from BlockUniTensor; changed to BlockFermionicUniTensor as
2039 // output
2040 boost::intrusive_ptr<BlockFermionicUniTensor> tmp = this->clone_meta(true, true);
2041 tmp->_blocks = vec_clone(this->_blocks);
2042 return tmp;
2043 };
2044
2045 unsigned int dtype() const {
2046 //[21 Aug 2024] This is a copy from BlockUniTensor;
2047 #ifdef UNI_DEBUG
2048 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
2049 "\n");
2050 #endif
2051 return this->_blocks.size() < 1 ? Type.Void : this->_blocks[0].dtype();
2052 };
2053 int device() const {
2054 //[21 Aug 2024] This is a copy from BlockUniTensor;
2055 #ifdef UNI_DEBUG
2056 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
2057 "\n");
2058 #endif
2059 return this->_blocks.size() < 1 ? -404 : this->_blocks[0].device();
2060 };
2061 std::string dtype_str() const {
2062 //[21 Aug 2024] This is a copy from BlockUniTensor;
2063 #ifdef UNI_DEBUG
2064 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
2065 "\n");
2066 #endif
2067 return this->_blocks.size() < 1 ? "Void, no valid blocks" : this->_blocks[0].dtype_str();
2068 };
2069 std::string device_str() const {
2070 //[21 Aug 2024] This is a copy from BlockUniTensor;
2071 #ifdef UNI_DEBUG
2072 cytnx_error_msg(this->_blocks.size() == 0, "[ERROR][internal] empty blocks for blockform.%s",
2073 "\n");
2074 #endif
2075 return this->_blocks.size() < 1 ? "None, no valid blocks" : this->_blocks[0].device_str();
2076 };
2077
2078 Tensor get_block(const cytnx_uint64 &idx = 0) const {
2079 //[21 Aug 2024] This is a copy from BlockUniTensor;
2080 cytnx_error_msg(idx >= this->_blocks.size(),
2081 "[ERROR][BlockFermionicUniTensor] index out of range%s", "\n");
2082 return this->_blocks[idx].clone();
2083 };
2084
2085 // this one for Block will return the indicies!!
2086 Tensor get_block(const std::vector<cytnx_int64> &indices, const bool &force_return) const {
2087 //[21 Aug 2024] This is a copy from BlockUniTensor;
2088 if (this->rank() == 0) {
2089 cytnx_error_msg(!indices.empty(),
2090 "[ERROR][get_block][BlockFermionicUniTensor] rank-0 scalar block expects "
2091 "no qnum indices.%s",
2092 "\n");
2093 cytnx_error_msg(this->_blocks.empty(),
2094 "[ERROR][BlockFermionicUniTensor] index out of range%s", "\n");
2095 return this->_blocks[0].clone();
2096 }
2098 indices.size() != this->rank(),
2099 "[ERROR][get_block][BlockFermionicUniTensor] len(indices) must be the same as the "
2100 "Tensor rank (number of legs).%s",
2101 "\n");
2102
2103 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
2104
2105 // find if the indices specify exists!
2106 cytnx_int64 b = -1;
2107 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
2108 if (inds == this->_inner_to_outer_idx[i]) {
2109 b = i;
2110 break;
2111 }
2112 }
2113
2114 if (b < 0) {
2115 if (force_return) {
2116 return NullRefTensor;
2117 } else {
2118 cytnx_error_msg(true,
2119 "[ERROR][get_block][BlockFermionicUniTensor] no avaliable block exists, "
2120 "force_return=false, so "
2121 "error throws. \n If you want to return an empty block without "
2122 "error when block is "
2123 "not avaliable, set force_return=True.%s",
2124 "\n");
2125 }
2126 } else {
2127 return this->_blocks[b].clone();
2128 }
2129 }
2130
2131 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const {
2132 //[21 Aug 2024] This is a copy from BlockUniTensor;
2133 cytnx_error_msg(idx >= this->_blocks.size(),
2134 "[ERROR][BlockFermionicUniTensor] index out of range%s", "\n");
2135 return this->_blocks[idx];
2136 };
2137
2138 Tensor &get_block_(const cytnx_uint64 &idx = 0) {
2139 //[21 Aug 2024] This is a copy from BlockUniTensor;
2140 cytnx_error_msg(idx >= this->_blocks.size(),
2141 "[ERROR][BlockFermionicUniTensor] index out of range%s", "\n");
2142 return this->_blocks[idx];
2143 };
2144
2145 const Tensor &get_block_(const std::vector<cytnx_int64> &indices,
2146 const bool &force_return) const {
2147 //[21 Aug 2024] This is a copy from BlockUniTensor;
2148 if (this->rank() == 0) {
2149 cytnx_error_msg(!indices.empty(),
2150 "[ERROR][get_block][BlockFermionicUniTensor] rank-0 scalar block expects "
2151 "no qnum indices.%s",
2152 "\n");
2153 cytnx_error_msg(this->_blocks.empty(),
2154 "[ERROR][BlockFermionicUniTensor] index out of range%s", "\n");
2155 return this->_blocks[0];
2156 }
2158 indices.size() != this->rank(),
2159 "[ERROR][get_block][BlockFermionicUniTensor] len(indices) must be the same as the "
2160 "Tensor rank (number of legs).%s",
2161 "\n");
2162
2163 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
2164
2165 // find if the indices specify exists!
2166 cytnx_int64 b = -1;
2167 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
2168 if (inds == this->_inner_to_outer_idx[i]) {
2169 b = i;
2170 break;
2171 }
2172 }
2173
2174 if (b < 0) {
2175 if (force_return) {
2176 return this->NullRefTensor;
2177 } else {
2178 cytnx_error_msg(true,
2179 "[ERROR][get_block][BlockFermionicUniTensor] no avaliable block exists, "
2180 "force_return=false, so "
2181 "error throws. \n If you want to return an empty block without "
2182 "error when block is "
2183 "not avaliable, set force_return=True.%s",
2184 "\n");
2185 }
2186 } else {
2187 return this->_blocks[b];
2188 }
2189 }
2190
2191 Tensor &get_block_(const std::vector<cytnx_int64> &indices, const bool &force_return) {
2192 //[21 Aug 2024] This is a copy from BlockUniTensor;
2193 if (this->rank() == 0) {
2194 cytnx_error_msg(!indices.empty(),
2195 "[ERROR][get_block][BlockFermionicUniTensor] rank-0 scalar block expects "
2196 "no qnum indices.%s",
2197 "\n");
2198 cytnx_error_msg(this->_blocks.empty(),
2199 "[ERROR][BlockFermionicUniTensor] index out of range%s", "\n");
2200 return this->_blocks[0];
2201 }
2203 indices.size() != this->rank(),
2204 "[ERROR][get_block][BlockFermionicUniTensor] len(indices) must be the same as the "
2205 "Tensor rank (number of legs).%s",
2206 "\n");
2207
2208 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
2209
2210 // find if the indices specify exists!
2211 cytnx_int64 b = -1;
2212 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
2213 if (inds == this->_inner_to_outer_idx[i]) {
2214 b = i;
2215 break;
2216 }
2217 }
2218
2219 if (b < 0) {
2220 if (force_return) {
2221 return this->NullRefTensor;
2222 } else {
2223 cytnx_error_msg(true,
2224 "[ERROR][get_block][BlockFermionicUniTensor] no avaliable block exists, "
2225 "force_return=false, so "
2226 "error throws. \n If you want to return an empty block without "
2227 "error when block is "
2228 "not avaliable, set force_return=True.%s",
2229 "\n");
2230 }
2231 } else {
2232 return this->_blocks[b];
2233 }
2234 }
2235
2236 std::vector<Tensor> get_blocks() const {
2237 //[21 Aug 2024] This is a copy from BlockUniTensor;
2238 return vec_clone(this->_blocks);
2239 }
2240 const std::vector<Tensor> &get_blocks_(const bool &) const {
2241 //[21 Aug 2024] This is a copy from BlockUniTensor;
2242 return this->_blocks;
2243 }
2244 std::vector<Tensor> &get_blocks_(const bool &) {
2245 //[21 Aug 2024] This is a copy from BlockUniTensor;
2246 return this->_blocks;
2247 }
2248
2249 bool same_data(const boost::intrusive_ptr<UniTensor_base> &rhs) const {
2250 //[21 Aug 2024] This is a copy from BlockUniTensor; changed to BlockFermionic UTenType
2251 if (rhs->uten_type() != UTenType.BlockFermionic) return false;
2252 if (rhs->get_blocks_(1).size() != this->get_blocks_(1).size()) return false;
2253
2254 for (int i = 0; i < rhs->get_blocks_(1).size(); i++)
2255 if (this->get_blocks_(1)[i].same_data(rhs->get_blocks_(1)[i]) == false) return false;
2256
2257 return true;
2258 }
2259
2260 void set_rowrank_(const cytnx_uint64 &new_rowrank) {
2261 //[21 Aug 2024] This is a copy from BlockUniTensor;
2263 new_rowrank > this->rank(),
2264 "[ERROR][BlockFermionicUniTensor] rowrank should be [>=0] and [<=UniTensor.rank].%s", "\n");
2265 if (this->is_diag()) {
2267 new_rowrank != 1,
2268 "[ERROR][BlockFermionicUniTensor] rowrank should be [==1] when is_diag =true!.%s", "\n");
2269 }
2270 this->_rowrank = new_rowrank;
2271 this->_is_braket_form = this->_update_braket();
2272 }
2273
2274 boost::intrusive_ptr<UniTensor_base> set_rowrank(const cytnx_uint64 &new_rowrank) const {
2275 //[21 Aug 2024] This is a copy from BlockUniTensor; output type changed to
2276 // BlockFermionicUniTensor
2277 boost::intrusive_ptr<BlockFermionicUniTensor> tmp = this->clone_meta(true, true);
2278 tmp->_blocks = this->_blocks;
2279 tmp->set_rowrank_(new_rowrank);
2280 return tmp;
2281 }
2282
2283 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<cytnx_int64> &mapper,
2284 const cytnx_int64 &rowrank = -1);
2285 boost::intrusive_ptr<UniTensor_base> permute(const std::vector<std::string> &mapper,
2286 const cytnx_int64 &rowrank = -1);
2287
2288 void permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1) override;
2289 void permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1) override;
2290
2291 boost::intrusive_ptr<UniTensor_base> permute_nosignflip(
2292 const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1) override;
2293 boost::intrusive_ptr<UniTensor_base> permute_nosignflip(
2294 const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1) override;
2295 void permute_nosignflip_(const std::vector<cytnx_int64> &mapper,
2296 const cytnx_int64 &rowrank = -1) override;
2297 void permute_nosignflip_(const std::vector<std::string> &mapper,
2298 const cytnx_int64 &rowrank = -1) override;
2299
2300 void twist_(const cytnx_int64 &idx) override;
2301 void twist_(const std::string &label) override;
2302 void fermion_twists_() override;
2303
2304 // Helper function; implements the sign flips when permuting indices
2305 std::vector<bool> _swapsigns_(const std::vector<cytnx_int64> &mapper) const;
2306 std::vector<bool> _lhssigns_(const std::vector<cytnx_int64> &mapper,
2307 const cytnx_int64 contrno) const;
2308 std::vector<bool> _swapsigns_(const std::vector<cytnx_uint64> &mapper) const;
2309 std::vector<bool> _lhssigns_(const std::vector<cytnx_uint64> &mapper,
2310 const cytnx_uint64 contrno) const;
2311
2312 boost::intrusive_ptr<UniTensor_base> contiguous_() {
2313 //[21 Aug 2024] This is a copy from BlockUniTensor;
2314 // Rebind each block to the non-mutating Tensor::contiguous() result instead of calling
2315 // contiguous_() in place, so a block Tensor shared with another UniTensor (e.g. via
2316 // relabel()) is not corrupted (#724).
2317 for (unsigned int b = 0; b < this->_blocks.size(); b++)
2318 this->_blocks[b] = this->_blocks[b].contiguous();
2319 return boost::intrusive_ptr<UniTensor_base>(this);
2320 }
2321 boost::intrusive_ptr<UniTensor_base> contiguous();
2322
2323 boost::intrusive_ptr<UniTensor_base> apply_();
2324 boost::intrusive_ptr<UniTensor_base> apply();
2325
2326 void print_diagram(const bool &bond_info = false) const;
2327 void print_blocks(const bool &full_info = true) const;
2328 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const;
2329
2330 boost::intrusive_ptr<UniTensor_base> contract(const boost::intrusive_ptr<UniTensor_base> &rhs,
2331 const bool &mv_elem_self = false,
2332 const bool &mv_elem_rhs = false);
2333
2334 boost::intrusive_ptr<UniTensor_base> relabel(const std::vector<std::string> &new_labels);
2335 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &new_labels);
2336
2337 boost::intrusive_ptr<UniTensor_base> relabel(const std::vector<std::string> &old_labels,
2338 const std::vector<std::string> &new_labels);
2339 boost::intrusive_ptr<UniTensor_base> relabels(const std::vector<std::string> &old_labels,
2340 const std::vector<std::string> &new_labels);
2341
2342 boost::intrusive_ptr<UniTensor_base> relabel(const std::string &old_label,
2343 const std::string &new_label);
2344 boost::intrusive_ptr<UniTensor_base> relabel(const cytnx_int64 &inx,
2345 const std::string &new_label);
2346 std::vector<Symmetry> syms() const;
2347
2348 void reshape_(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
2349 cytnx_error_msg(true, "[ERROR] Cannot reshape a UniTensor with symmetry.%s", "\n");
2350 }
2351 boost::intrusive_ptr<UniTensor_base> reshape(const std::vector<cytnx_int64> &new_shape,
2352 const cytnx_uint64 &rowrank = 0) {
2353 cytnx_error_msg(true, "[ERROR] Cannot reshape a UniTensor with symmetry.%s", "\n");
2354 return nullptr;
2355 }
2356
2357 boost::intrusive_ptr<UniTensor_base> to_dense();
2358 void to_dense_();
2359
2360 boost::intrusive_ptr<UniTensor_base> astype(const unsigned int &dtype) const {
2361 //[21 Aug 2024] This is a copy from BlockUniTensor; the tensor type was adapted
2362 boost::intrusive_ptr<BlockFermionicUniTensor> tmp = this->clone_meta(true, true);
2363 tmp->_blocks.resize(this->_blocks.size());
2364 for (cytnx_int64 blk = 0; blk < this->_blocks.size(); blk++) {
2365 tmp->_blocks[blk] = this->_blocks[blk].astype(dtype);
2366 }
2367 return tmp;
2368 };
2369
2370 // this will only work on non-symm tensor (DenseUniTensor)
2371 boost::intrusive_ptr<UniTensor_base> get(const std::vector<Accessor> &accessors) {
2373 true,
2374 "[ERROR][BlockFermionicUniTensor][get] Cannot use get on a UniTensor with "
2375 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
2376 "\n");
2377 return nullptr;
2378 }
2379
2380 // this will only work on non-symm tensor (DenseUniTensor)
2381 void set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
2382 //[21 Aug 2024] This is a copy from BlockUniTensor;
2384 true,
2385 "[ERROR][BlockFermionicUniTensor][get] Cannot use get on a UniTensor with "
2386 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
2387 "\n");
2388 }
2389
2390 void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) {
2391 //[21 Aug 2024] This is a copy from BlockUniTensor;
2393 in.dtype() != this->dtype(),
2394 "[ERROR][BlockFermionicUniTensor][put_block] The input tensor dtype does not match.%s",
2395 "\n");
2397 in.device() != this->device(),
2398 "[ERROR][BlockFermionicUniTensor][put_block] The input tensor device does not "
2399 "match.%s",
2400 "\n");
2401 // We shouldn't check the contiguous
2402 // cytnx_error_msg(!in.contiguous());
2403 cytnx_error_msg(idx >= this->_blocks.size(),
2404 "[ERROR][BlockFermionicUniTensor] index out of range%s", "\n");
2406 in.shape() != this->_blocks[idx].shape(),
2407 "[ERROR][BlockFermionicUniTensor] the shape of input tensor does not match the shape "
2408 "of block @ idx=%d\n",
2409 idx);
2410
2411 this->_blocks[idx] = in.clone();
2412 }
2413 void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) {
2414 //[21 Aug 2024] This is a copy from BlockUniTensor;
2416 in.dtype() != this->dtype(),
2417 "[ERROR][BlockFermionicUniTensor][put_block] The input tensor dtype does not match.%s",
2418 "\n");
2420 in.device() != this->device(),
2421 "[ERROR][BlockFermionicUniTensor][put_block] The input tensor device does not "
2422 "match.%s",
2423 "\n");
2424 // We shouldn't check the contiguous
2425 // cytnx_error_msg(!in.contiguous());
2426 cytnx_error_msg(idx >= this->_blocks.size(),
2427 "[ERROR][BlockFermionicUniTensor] index out of range%s", "\n");
2429 in.shape() != this->_blocks[idx].shape(),
2430 "[ERROR][BlockFermionicUniTensor] the shape of input tensor does not match the shape "
2431 "of block @ idx=%d\n",
2432 idx);
2433
2434 this->_blocks[idx] = in;
2435 }
2436 void put_block(const Tensor &in, const std::vector<cytnx_int64> &indices) {
2437 //[21 Aug 2024] This is a copy from BlockUniTensor;
2439 in.dtype() != this->dtype(),
2440 "[ERROR][BlockFermionicUniTensor][put_block] The input tensor dtype does not match.%s",
2441 "\n");
2443 in.device() != this->device(),
2444 "[ERROR][BlockFermionicUniTensor][put_block] The input tensor device does not "
2445 "match.%s",
2446 "\n");
2447 // We shouldn't check the contiguous
2448 // cytnx_error_msg(!in.contiguous());
2450 indices.size() != this->rank(),
2451 "[ERROR][put_block][BlockFermionicUniTensor] len(indices) must be the same as the "
2452 "Tensor rank (number of legs).%s",
2453 "\n");
2454
2455 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
2456
2457 // find if the indices specify exists!
2458 cytnx_int64 b = -1;
2459 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
2460 if (inds == this->_inner_to_outer_idx[i]) {
2461 b = i;
2462 break;
2463 }
2464 }
2465
2466 if (b < 0) {
2468 true, "[ERROR][put_block][BlockFermionicUniTensor] no avaliable block exists.%s", "\n");
2469 } else {
2471 in.shape() != this->_blocks[b].shape(),
2472 "[ERROR][BlockFermionicUniTensor] the shape of input tensor does not match the shape "
2473 "of block @ idx=%d\n",
2474 b);
2475
2476 this->_blocks[b] = in.clone();
2477 }
2478 }
2479 void put_block_(Tensor &in, const std::vector<cytnx_int64> &indices) {
2480 //[21 Aug 2024] This is a copy from BlockUniTensor;
2482 in.dtype() != this->dtype(),
2483 "[ERROR][BlockFermionicUniTensor][put_block] The input tensor dtype does not match.%s",
2484 "\n");
2486 in.device() != this->device(),
2487 "[ERROR][BlockFermionicUniTensor][put_block] The input tensor device does not "
2488 "match.%s",
2489 "\n");
2490 // We shouldn't check the contiguous
2491 // cytnx_error_msg(!in.contiguous());
2493 indices.size() != this->rank(),
2494 "[ERROR][put_block][BlockFermionicUniTensor] len(indices) must be the same as the "
2495 "Tensor rank (number of legs).%s",
2496 "\n");
2497
2498 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
2499
2500 // find if the indices specify exists!
2501 cytnx_int64 b = -1;
2502 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
2503 if (inds == this->_inner_to_outer_idx[i]) {
2504 b = i;
2505 break;
2506 }
2507 }
2508
2509 if (b < 0) {
2511 true, "[ERROR][put_block][BlockFermionicUniTensor] no avaliable block exists.%s", "\n");
2512 } else {
2514 in.shape() != this->_blocks[b].shape(),
2515 "[ERROR][BlockFermionicUniTensor] the shape of input tensor does not match the shape "
2516 "of block @ idx=%d\n",
2517 b);
2518 this->_blocks[b] = in;
2519 }
2520 }
2521
2522 void tag_() {
2523 // no-use!
2524 }
2525
2526 boost::intrusive_ptr<UniTensor_base> Conj() {
2527 //[21 Aug 2024] This is a copy from BlockUniTensor;
2528 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2529 out->Conj_();
2530 return out;
2531 }
2532
2533 void Conj_() {
2534 //[21 Aug 2024] This is a copy from BlockUniTensor;
2535 for (int i = 0; i < this->_blocks.size(); i++) {
2536 this->_blocks[i].Conj_();
2537 }
2538 };
2539
2540 // Transpose(_) changes the index order without sign flips and reverses the bond directions for
2541 // fermionic tensors
2542 void Transpose_();
2543 boost::intrusive_ptr<UniTensor_base> Transpose() {
2544 //[21 Aug 2024] This is a copy from BlockUniTensor;
2545 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2546 out->Transpose_();
2547 return out;
2548 }
2549
2550 void normalize_();
2551 boost::intrusive_ptr<UniTensor_base> normalize() {
2552 //[21 Aug 2024] This is a copy from BlockUniTensor;
2553 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2554 out->normalize_();
2555 return out;
2556 }
2557
2558 boost::intrusive_ptr<UniTensor_base> Dagger() {
2559 //[21 Aug 2024] This is a copy from BlockUniTensor;
2560 boost::intrusive_ptr<UniTensor_base> out = this->Conj();
2561 out->Transpose_();
2562 return out;
2563 }
2564 void Dagger_() {
2565 //[21 Aug 2024] This is a copy from BlockUniTensor;
2566 this->Conj_();
2567 this->Transpose_();
2568 }
2569
2570 void Trace_(const std::string &a, const std::string &b);
2571 void Trace_(const cytnx_int64 &a, const cytnx_int64 &b);
2572
2573 boost::intrusive_ptr<UniTensor_base> Trace(const std::string &a, const std::string &b) {
2574 //[21 Aug 2024] This is a copy from BlockUniTensor; the tensor type was adapted
2575 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2576 out->Trace_(a, b);
2577 return out;
2578 }
2579 boost::intrusive_ptr<UniTensor_base> Trace(const cytnx_int64 &a, const cytnx_int64 &b) {
2580 //[21 Aug 2024] This is a copy from BlockUniTensor; the tensor type was adapted
2581 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2582 out->Trace_(a, b);
2583 return out;
2584 }
2585
2586 Tensor Norm() const;
2587
2588 bool elem_exists(const std::vector<cytnx_uint64> &locator) const;
2589
2590 const Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator) const;
2591 const cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2592 const cytnx_complex128 &aux) const;
2593 const cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2594 const cytnx_complex64 &aux) const;
2595 const cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2596 const cytnx_double &aux) const;
2597 const cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2598 const cytnx_float &aux) const;
2599 const cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2600 const cytnx_uint64 &aux) const;
2601 const cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2602 const cytnx_int64 &aux) const;
2603 const cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2604 const cytnx_uint32 &aux) const;
2605 const cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2606 const cytnx_int32 &aux) const;
2607 const cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2608 const cytnx_uint16 &aux) const;
2609 const cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2610 const cytnx_int16 &aux) const;
2611
2612 Scalar::Sproxy at_for_sparse(const std::vector<cytnx_uint64> &locator);
2613 cytnx_complex128 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2614 const cytnx_complex128 &aux);
2615 cytnx_complex64 &at_for_sparse(const std::vector<cytnx_uint64> &locator,
2616 const cytnx_complex64 &aux);
2617 cytnx_double &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_double &aux);
2618 cytnx_float &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_float &aux);
2619 cytnx_uint64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint64 &aux);
2620 cytnx_int64 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int64 &aux);
2621 cytnx_uint32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint32 &aux);
2622 cytnx_int32 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int32 &aux);
2623 cytnx_uint16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_uint16 &aux);
2624 cytnx_int16 &at_for_sparse(const std::vector<cytnx_uint64> &locator, const cytnx_int16 &aux);
2625
2626 void _save_dispatch(std::fstream &f) const;
2627 void _load_dispatch(std::fstream &f, unsigned int version);
2628
2629 // this will remove the [q_index]-th qnum at [bond_idx]-th Bond!
2630 void truncate_(const std::string &label, const cytnx_uint64 &q_index);
2631 void truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &q_index);
2632
2633 void Add_(const boost::intrusive_ptr<UniTensor_base> &rhs);
2634 void Add_(const Scalar &rhs) {
2635 cytnx_error_msg(true,
2636 "[ERROR] Cannot perform elementwise arithmetic '+' between Scalar and "
2637 "BlockFermionicUniTensor.\n %s "
2638 "\n",
2639 "This operation would destroy the block structure. [Suggest] Avoid or use "
2640 "get/put_block(s) to do operation on blocks.");
2641 }
2642
2643 void Mul_(const boost::intrusive_ptr<UniTensor_base> &rhs);
2644 void Mul_(const Scalar &rhs);
2645
2646 void Sub_(const boost::intrusive_ptr<UniTensor_base> &rhs);
2647 void Sub_(const Scalar &rhs) {
2648 cytnx_error_msg(true,
2649 "[ERROR] Cannot perform elementwise arithmetic '-' between Scalar and "
2650 "BlockFermionicUniTensor.\n %s "
2651 "\n",
2652 "This operation would destroy the block structure. [Suggest] Avoid or use "
2653 "get/put_block(s) to do operation on blocks.");
2654 }
2655 void lSub_(const Scalar &lhs) {
2656 cytnx_error_msg(true,
2657 "[ERROR] Cannot perform elementwise arithmetic '-' between Scalar and "
2658 "BlockFermionicUniTensor.\n %s "
2659 "\n",
2660 "This operation would destroy the block structure. [Suggest] Avoid or use "
2661 "get/put_block(s) to do operation on blocks.");
2662 }
2663
2664 void Div_(const boost::intrusive_ptr<UniTensor_base> &rhs);
2665 void Div_(const Scalar &rhs);
2666 void lDiv_(const Scalar &lhs) {
2667 cytnx_error_msg(true,
2668 "[ERROR] Cannot perform elementwise arithmetic '/' between Scalar and "
2669 "BlockFermionicUniTensor.\n %s "
2670 "\n",
2671 "This operation would cause division by zero on non-block elements. "
2672 "[Suggest] Avoid or use get/put_block(s) to do operation on blocks.");
2673 }
2674 void from_(const boost::intrusive_ptr<UniTensor_base> &rhs, bool force, cytnx_double tol = 0.);
2675
2676 void group_basis_();
2677
2678 void combineBond(const std::vector<std::string> &indicators, const bool &force = false);
2679 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = false);
2680 void combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
2681 const bool &by_label);
2682 void combineBonds(const std::vector<std::string> &indicators, const bool &force = false);
2683
2684 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
2685 //[21 Aug 2024] This is a copy from BlockUniTensor;
2687 bidx >= this->Nblocks(),
2688 "[ERROR][BlockFermionicUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
2689 this->Nblocks());
2690 return this->_inner_to_outer_idx[bidx];
2691 }
2692 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
2693 //[21 Aug 2024] This is a copy from BlockUniTensor;
2695 bidx >= this->Nblocks(),
2696 "[ERROR][BlockFermionicUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
2697 this->Nblocks());
2698 return this->_inner_to_outer_idx[bidx];
2699 }
2700
2701 const vec2d<cytnx_uint64> &get_itoi() const {
2702 //[21 Aug 2024] This is a copy from BlockUniTensor;
2703 return this->_inner_to_outer_idx;
2704 }
2705 vec2d<cytnx_uint64> &get_itoi() {
2706 //[21 Aug 2024] This is a copy from BlockUniTensor;
2707 return this->_inner_to_outer_idx;
2708 }
2709
2710 void beauty_print_block(std::ostream &os, const cytnx_uint64 &Nin, const cytnx_uint64 &Nout,
2711 const std::vector<cytnx_uint64> &qn_indices,
2712 const std::vector<Bond> &bonds, const Tensor &block) const;
2713
2714 private:
2715 // additional information for fermions (#841): if true, the sign of the corresponding
2716 // block needs to be flipped. Must stay in lockstep with _blocks (one entry per block);
2717 // outside the class it can only be modified through reset_signflip_()/erase_signflip_()
2718 // above, each of which preserves that invariant.
2719 std::vector<cytnx_bool> _signflip;
2720 };
2722
2723 //======================================================================
2724
2726 class UniTensor_options {
2727 public:
2728 bool _is_diag;
2729 int _dtype;
2730 int _device;
2731 int _rowrank;
2732
2733 UniTensor_options() {
2734 this->_is_diag = false;
2735 this->_dtype = Type.Double;
2736 this->_device = Device.cpu;
2737 this->_rowrank = -1;
2738 }
2739
2740 UniTensor_options(const UniTensor_options &rhs) {
2741 this->_is_diag = rhs._is_diag;
2742 this->_dtype = rhs._dtype;
2743 this->_device = rhs._device;
2744 this->_rowrank = rhs._rowrank;
2745 }
2746
2747 UniTensor_options &operator=(const UniTensor_options &rhs) {
2748 this->_is_diag = rhs._is_diag;
2749 this->_dtype = rhs._dtype;
2750 this->_device = rhs._device;
2751 this->_rowrank = rhs._rowrank;
2752 return *this;
2753 }
2754
2755 UniTensor_options &is_diag(const bool &in) {
2756 this->_is_diag = in;
2757 return *this;
2758 }
2759 UniTensor_options &dtype(const int &in) {
2760 this->_dtype = in;
2761 return *this;
2762 }
2763 UniTensor_options &device(const int &in) {
2764 this->_device = in;
2765 return *this;
2766 }
2767 UniTensor_options &rowrank(const int &in) {
2768 this->_rowrank = in;
2769 return *this;
2770 }
2771 };
2773
2776 public:
2778 boost::intrusive_ptr<UniTensor_base> _impl;
2779 UniTensor() : _impl(new UniTensor_base()){};
2780 UniTensor(const UniTensor &rhs) { this->_impl = rhs._impl; }
2781 UniTensor &operator=(const UniTensor &rhs) {
2782 this->_impl = rhs._impl;
2783 return *this;
2784 }
2786
2788
2814 explicit UniTensor(const Tensor &in_tensor, const bool &is_diag = false,
2815 const cytnx_int64 &rowrank = -1,
2816 const std::vector<std::string> &in_labels = {}, const std::string &name = "")
2817 : _impl(new UniTensor_base()) {
2818 this->Init(in_tensor, is_diag, rowrank, in_labels, name);
2819 }
2837 void Init(const Tensor &in_tensor, const bool &is_diag = false, const cytnx_int64 &rowrank = -1,
2838 const std::vector<std::string> &in_labels = {}, const std::string &name = "") {
2839 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
2840 out->Init_by_Tensor(in_tensor, is_diag, rowrank, name);
2841 this->_impl = out;
2842 if (in_labels.size() != 0) this->set_labels(in_labels);
2843 }
2845
2847
2864 UniTensor(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
2865 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
2866 const int &device = Device.cpu, const bool &is_diag = false,
2867 const std::string &name = "")
2868 : _impl(new UniTensor_base()) {
2869 #ifdef UNI_DEBUG
2871 true,
2872 "[DEBUG] message: entry for UniTensor(const std::vector<Bond> &bonds, const "
2873 "std::vector<std::string> &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned "
2874 "int "
2875 "&dtype=Type.Double, const int &device = Device.cpu, const bool &is_diag=false)%s",
2876 "\n");
2877 #endif
2878 this->Init(bonds, in_labels, rowrank, dtype, device, is_diag, name);
2879 }
2880
2882 /* [developing]
2883 void Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
2884 const UniTensor_options &UToptions = UniTensor_options(), const std::string &name =
2885 ""){ this->Init(bonds,in_labels, UToptions._rowrank, UToptions._dtype , UToptions._device ,
2886 UToptions._is_diag,
2887 name);
2888 }
2889 */
2891
2911 UniTensor &Init(const std::vector<Bond> &bonds, const std::vector<std::string> &in_labels = {},
2912 const cytnx_int64 &rowrank = -1, const unsigned int &dtype = Type.Double,
2913 const int &device = Device.cpu, const bool &is_diag = false,
2914 const std::string &name = "") {
2915 // checking type:
2916 bool is_sym = false;
2917 int sym_fver = -1;
2918 bool fermionic = false;
2919
2920 for (cytnx_uint64 i = 0; i < bonds.size(); i++) {
2921 // check
2922 if (bonds[i].syms().size() != 0) {
2923 is_sym = true;
2924 if (sym_fver == -1)
2925 sym_fver = bonds[i]._impl->_degs.size();
2926 else {
2927 cytnx_error_msg((bool(sym_fver) ^ bool(bonds[i]._impl->_degs.size())),
2928 "[ERROR] When initializing a UniTensor with symmetries, all Bonds must "
2929 "be in the same format!%s",
2930 "\n");
2931 }
2932 if (!fermionic) {
2933 std::vector<Symmetry> symms = bonds[i].syms();
2934 for (cytnx_uint64 i = 0; i < symms.size(); i++) {
2935 if (symms[i].is_fermionic()) fermionic = true;
2936 }
2937 }
2938 } else
2940 is_sym, "[ERROR] Cannot have bonds with mixing of symmetry and non-symmetry.%s", "\n");
2941 }
2942
2943 // dynamical dispatch:
2944 if (is_sym) {
2945 #ifdef UNI_DEBUG
2946 cytnx_warning_msg(true, "[DEBUG] message: entry dispatch: UniTensor: symmetric%s", "\n");
2947 #endif
2949 sym_fver < 1,
2950 "[ERROR] Symmetric tensor, but no degeneracies given. The UniTensor seems broken.%s",
2951 "\n");
2952 if (fermionic) {
2953 boost::intrusive_ptr<UniTensor_base> out(new BlockFermionicUniTensor());
2954 this->_impl = out;
2955 } else {
2956 boost::intrusive_ptr<UniTensor_base> out(new BlockUniTensor());
2957 this->_impl = out;
2958 }
2959 } else {
2960 boost::intrusive_ptr<UniTensor_base> out(new DenseUniTensor());
2961 this->_impl = out;
2962 }
2963 this->_impl->Init(bonds, in_labels, rowrank, dtype, device, is_diag, false, name);
2964 return *this;
2965 }
2966
2973 UniTensor &set_name_(const std::string &in) {
2974 this->_impl->set_name_(in);
2975 return *this;
2976 }
2977
2981 [[deprecated("Please use set_name_(const std::string &in) instead.")]] UniTensor &set_name(
2982 const std::string &in) {
2983 return this->set_name_(in);
2984 }
2985
2996 UniTensor &set_label_(const cytnx_int64 &idx, const std::string &new_label) {
2997 this->_impl->set_label_(idx, new_label);
2998 return *this;
2999 }
3000
3005 this->_impl->set_label_(idx, std::string(new_label));
3006 return *this;
3007 }
3008
3019 UniTensor &set_label_(const std::string &old_label, const std::string &new_label) {
3020 this->_impl->set_label_(old_label, new_label);
3021 return *this;
3022 }
3023
3027 UniTensor &set_label_(const char *old_label, const std::string &new_label) {
3028 this->_impl->set_label_(std::string(old_label), new_label);
3029 return *this;
3030 }
3031
3035 UniTensor &set_label_(const std::string &old_label, const char *new_label) {
3036 this->_impl->set_label_(old_label, std::string(new_label));
3037 return *this;
3038 }
3039
3043 UniTensor &set_label_(const char *old_label, const char *new_label) {
3044 this->_impl->set_label_(std::string(old_label), std::string(new_label));
3045 return *this;
3046 }
3047
3053 [[deprecated(
3054 "Please use set_label_(const cytnx_int64 &idx, const std::string &new_label) "
3055 "instead.")]] UniTensor &
3056 set_label(const cytnx_int64 &idx, const std::string &new_label) {
3057 return this->set_label_(idx, new_label);
3058 }
3059
3063 [[deprecated(
3064 "Please use set_label_(const cytnx_int64 &idx, const char *new_label) "
3065 "instead.")]] UniTensor &
3066 set_label(const cytnx_int64 &idx, const char *new_label) {
3067 return this->set_label_(idx, new_label);
3068 }
3069
3075 [[deprecated(
3076 "Please use set_label_(const std::string &old_label, const std::string "
3077 "&new_label) instead.")]] UniTensor &
3078 set_label(const std::string &old_label, const std::string &new_label) {
3079 return this->set_label_(old_label, new_label);
3080 }
3081
3085 [[deprecated(
3086 "Please use set_label_(const char *old_label, const std::string &new_label) "
3087 "instead.")]] UniTensor &
3088 set_label(const char *old_label, const std::string &new_label) {
3089 return this->set_label_(old_label, new_label);
3090 }
3091
3095 [[deprecated(
3096 "Please use set_label_(const std::string &old_label, const char *new_label) "
3097 "instead.")]] UniTensor &
3098 set_label(const std::string &old_label, const char *new_label) {
3099 return this->set_label_(old_label, new_label);
3100 }
3101
3105 [[deprecated(
3106 "Please use set_label_(const char *old_label, const char *new_label) "
3107 "instead.")]] UniTensor &
3108 set_label(const char *old_label, const char *new_label) {
3109 return this->set_label_(old_label, new_label);
3110 }
3111
3112 /*
3113 UniTensor &change_label(const cytnx_int64 &old_label, const cytnx_int64 &new_label){
3114 this->_impl->change_label(old_label,new_label);
3115 return *this;
3116 }
3117 */
3118
3124 [[deprecated(
3125 "Please use "
3126 "UniTensor &relabel_(const std::vector<std::string> &new_labels) "
3127 "instead.")]] UniTensor &
3128 set_labels(const std::vector<std::string> &new_labels) {
3129 this->_impl->set_labels(new_labels);
3130 return *this;
3131 }
3132
3138 [[deprecated(
3139 "Please use "
3140 "UniTensor &relabel_(const std::initializer_list<char *> &new_labels) "
3141 "instead.")]] UniTensor &
3142 set_labels(const std::initializer_list<char *> &new_labels) {
3143 std::vector<char *> new_lbls(new_labels);
3144 std::vector<std::string> vs(new_lbls.size());
3145 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
3146 [](char *x) -> std::string { return std::string(x); });
3147
3148 this->_impl->set_labels(vs);
3149 return *this;
3150 }
3151
3159 this->_impl->set_rowrank_(new_rowrank);
3160 return *this;
3161 }
3162
3164 UniTensor out;
3165 out._impl = this->_impl->set_rowrank(new_rowrank);
3166 return out;
3167 }
3168
3169 template <class T>
3170 T &item() {
3171 if (this->is_blockform()) {
3173 !this->is_scalar(),
3174 "[ERROR] Cannot use item on a non-scalar UniTensor with Symmetry.\n suggestion: use "
3175 "get_block()/get_blocks() first.%s",
3176 "\n");
3177 return this->_impl->get_block_(0).item<T>();
3178 }
3179
3180 DenseUniTensor *tmp = static_cast<DenseUniTensor *>(this->_impl.get());
3181 return tmp->_block.item<T>();
3182 }
3183
3184 Scalar::Sproxy item() const {
3185 if (this->is_blockform()) {
3187 !this->is_scalar(),
3188 "[ERROR] Cannot use item on a non-scalar UniTensor with Symmetry.\n suggestion: use "
3189 "get_block()/get_blocks() first.%s",
3190 "\n");
3191 return this->_impl->get_block_(0).item();
3192 }
3193
3194 DenseUniTensor *tmp = static_cast<DenseUniTensor *>(this->_impl.get());
3195 return tmp->_block.item();
3196 }
3201 cytnx_uint64 Nblocks() const { return this->_impl->Nblocks(); }
3202
3207 cytnx_uint64 rank() const { return this->_impl->rank(); }
3208
3213 cytnx_uint64 rowrank() const { return this->_impl->rowrank(); }
3214
3220 unsigned int dtype() const { return this->_impl->dtype(); }
3221
3228 int uten_type() const { return this->_impl->uten_type(); }
3229
3234 bool is_void() const { return this->uten_type() == UTenType.Void; }
3235
3240 bool is_scalar() const { return !this->is_void() && this->rank() == 0; }
3241
3249 if (this->is_void()) return 0;
3250 cytnx_uint64 result = 1;
3251 for (const cytnx_uint64 extent : this->shape()) result *= extent;
3252 return result;
3253 }
3254
3258 bool is_empty() const { return !this->is_void() && this->size() == 0; }
3259
3265 int device() const { return this->_impl->device(); }
3266
3271 std::string name() const { return this->_impl->name(); }
3272
3278 std::string dtype_str() const { return this->_impl->dtype_str(); }
3279
3285 std::string device_str() const { return this->_impl->device_str(); }
3286
3292 std::string uten_type_str() const { return this->_impl->uten_type_str(); }
3293
3299 bool is_contiguous() const { return this->_impl->is_contiguous(); }
3300
3305 bool is_diag() const { return this->_impl->is_diag(); }
3306
3312 bool is_tag() const { return this->_impl->is_tag(); }
3313
3319 std::vector<Symmetry> syms() const { return this->_impl->syms(); }
3320
3327 const bool &is_braket_form() const { return this->_impl->is_braket_form(); }
3328
3333 const std::vector<std::string> &labels() const { return this->_impl->labels(); }
3340 cytnx_int64 get_index(std::string label) const { return this->_impl->get_index(label); }
3341
3346 const std::vector<Bond> &bonds() const { return this->_impl->bonds(); }
3347
3348 const Bond &bond_(const cytnx_uint64 &idx) const { return this->_impl->bond_(idx); }
3349 Bond &bond_(const cytnx_uint64 &idx) { return this->_impl->bond_(idx); }
3350
3351 const Bond &bond_(const std::string &label) const { return this->_impl->bond_(label); }
3352 Bond &bond_(const std::string &label) { return this->_impl->bond_(label); }
3353
3354 Bond bond(const cytnx_uint64 &idx) const { return this->_impl->bond_(idx).clone(); }
3355 Bond bond(const std::string &label) const { return this->_impl->bond_(label).clone(); }
3356
3361 std::vector<cytnx_uint64> shape() const { return this->_impl->shape(); }
3362
3369 std::vector<bool> signflip() const { return this->_impl->signflip(); }
3370
3376 bool is_blockform() const { return this->_impl->is_blockform(); }
3377
3384 UniTensor &to_(const int &device) {
3385 this->_impl->to_(device);
3386 return *this;
3387 }
3388
3398 UniTensor to(const int &device) const {
3399 UniTensor out;
3400 out._impl = this->_impl->to(device);
3401 return out;
3402 }
3403
3409 UniTensor out;
3410 out._impl = this->_impl->clone();
3411 return out;
3412 }
3413
3423 UniTensor &relabel_(const std::vector<std::string> &new_labels) {
3424 this->_impl->relabel_(new_labels);
3425 return *this;
3426 }
3432 [[deprecated(
3433 "Please use "
3434 "UniTensor &relabel_(const std::vector<std::string> &new_labels) "
3435 "instead.")]] UniTensor &
3436 relabels_(const std::vector<std::string> &new_labels) {
3437 this->_impl->relabels_(new_labels);
3438 return *this;
3439 }
3440
3452 UniTensor relabel(const std::vector<std::string> &new_labels) const {
3453 UniTensor out;
3454 out._impl = this->_impl->relabel(new_labels);
3455 return out;
3456 }
3462 [[deprecated(
3463 "Please use "
3464 "UniTensor relabel(const std::vector<std::string> &new_labels) const "
3465 "instead.")]] UniTensor
3466 relabels(const std::vector<std::string> &new_labels) const {
3467 UniTensor out;
3468 out._impl = this->_impl->relabels(new_labels);
3469 return out;
3470 }
3471
3476 UniTensor relabel(const std::initializer_list<char *> &new_labels) const {
3477 std::vector<char *> new_lbls(new_labels);
3478 std::vector<std::string> vs(new_lbls.size());
3479 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
3480 [](char *x) -> std::string { return std::string(x); });
3481
3482 UniTensor out;
3483 out._impl = this->_impl->relabel(vs);
3484 return out;
3485 }
3491 [[deprecated(
3492 "Please use "
3493 "UniTensor relabel(const std::initializer_list<char *> &new_labels) const "
3494 "instead.")]] UniTensor
3495 relabels(const std::initializer_list<char *> &new_labels) const {
3496 std::vector<char *> new_lbls(new_labels);
3497 std::vector<std::string> vs(new_lbls.size());
3498 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
3499 [](char *x) -> std::string { return std::string(x); });
3500
3501 UniTensor out;
3502 out._impl = this->_impl->relabels(vs);
3503 return out;
3504 }
3508 UniTensor &relabel_(const std::initializer_list<char *> &new_labels) {
3509 std::vector<char *> new_lbls(new_labels);
3510 std::vector<std::string> vs(new_lbls.size());
3511 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
3512 [](char *x) -> std::string { return std::string(x); });
3513
3514 this->_impl->relabel_(vs);
3515 return *this;
3516 }
3522 [[deprecated(
3523 "Please use "
3524 "UniTensor &relabel_(const std::initializer_list<char *> &new_labels) "
3525 "instead.")]] UniTensor &
3526 relabels_(const std::initializer_list<char *> &new_labels) {
3527 std::vector<char *> new_lbls(new_labels);
3528 std::vector<std::string> vs(new_lbls.size());
3529 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
3530 [](char *x) -> std::string { return std::string(x); });
3531
3532 this->_impl->relabels_(vs);
3533 return *this;
3534 }
3535
3543 UniTensor relabel(const std::vector<std::string> &old_labels,
3544 const std::vector<std::string> &new_labels) const {
3545 UniTensor out;
3546 out._impl = this->_impl->relabel(old_labels, new_labels);
3547 return out;
3548 }
3554 [[deprecated(
3555 "Please use "
3556 "UniTensor relabel(const std::vector<std::string> &old_labels, const "
3557 "std::vector<std::string> &new_labels) const "
3558 "instead.")]] UniTensor
3559 relabels(const std::vector<std::string> &old_labels,
3560 const std::vector<std::string> &new_labels) const {
3561 UniTensor out;
3562 out._impl = this->_impl->relabels(old_labels, new_labels);
3563 return out;
3564 }
3565
3581 UniTensor &relabel_(const std::vector<std::string> &old_labels,
3582 const std::vector<std::string> &new_labels) {
3583 this->_impl->relabel_(old_labels, new_labels);
3584 return *this;
3585 }
3591 [[deprecated(
3592 "Please use "
3593 "UniTensor &relabel_(const std::vector<std::string> &old_labels, const "
3594 "std::vector<std::string> &new_labels) "
3595 "instead.")]] UniTensor &
3596 relabels_(const std::vector<std::string> &old_labels,
3597 const std::vector<std::string> &new_labels) {
3598 this->_impl->relabels_(old_labels, new_labels);
3599 return *this;
3600 }
3601
3606 UniTensor relabel(const std::initializer_list<char *> &old_labels,
3607 const std::initializer_list<char *> &new_labels) const {
3608 std::vector<char *> new_lbls(new_labels);
3609 std::vector<std::string> vs(new_lbls.size());
3610 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
3611 [](char *x) -> std::string { return std::string(x); });
3612
3613 std::vector<char *> old_lbls(old_labels);
3614 std::vector<std::string> vs_old(old_lbls.size());
3615 transform(old_lbls.begin(), old_lbls.end(), vs_old.begin(),
3616 [](char *x) -> std::string { return std::string(x); });
3617
3618 return this->relabel(vs_old, vs);
3619 }
3620
3626 [[deprecated(
3627 "Please use "
3628 "UniTensor relabel(const std::initializer_list<char *> &old_labels, const "
3629 "std::initializer_list<char *> &new_labels) const "
3630 "instead.")]] UniTensor
3631 relabels(const std::initializer_list<char *> &old_labels,
3632 const std::initializer_list<char *> &new_labels) const {
3633 std::vector<char *> new_lbls(new_labels);
3634 std::vector<std::string> vs(new_lbls.size());
3635 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
3636 [](char *x) -> std::string { return std::string(x); });
3637
3638 std::vector<char *> old_lbls(old_labels);
3639 std::vector<std::string> vs_old(old_lbls.size());
3640 transform(old_lbls.begin(), old_lbls.end(), vs_old.begin(),
3641 [](char *x) -> std::string { return std::string(x); });
3642
3643 return this->relabels(vs_old, vs);
3644 }
3645
3650 UniTensor &relabel_(const std::initializer_list<char *> &old_labels,
3651 const std::initializer_list<char *> &new_labels) {
3652 std::vector<char *> new_lbls(new_labels);
3653 std::vector<std::string> vs(new_lbls.size());
3654 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
3655 [](char *x) -> std::string { return std::string(x); });
3656
3657 std::vector<char *> old_lbls(old_labels);
3658 std::vector<std::string> vs_old(old_lbls.size());
3659 transform(old_lbls.begin(), old_lbls.end(), vs_old.begin(),
3660 [](char *x) -> std::string { return std::string(x); });
3661
3662 this->relabel_(vs_old, vs);
3663 return *this;
3664 }
3670 [[deprecated(
3671 "Please use "
3672 "UniTensor &relabel_(const std::initializer_list<char *> &old_labels, const "
3673 "std::initializer_list<char *> &new_labels) "
3674 "instead.")]] UniTensor &
3675 relabels_(const std::initializer_list<char *> &old_labels,
3676 const std::initializer_list<char *> &new_labels) {
3677 std::vector<char *> new_lbls(new_labels);
3678 std::vector<std::string> vs(new_lbls.size());
3679 transform(new_lbls.begin(), new_lbls.end(), vs.begin(),
3680 [](char *x) -> std::string { return std::string(x); });
3681
3682 std::vector<char *> old_lbls(old_labels);
3683 std::vector<std::string> vs_old(old_lbls.size());
3684 transform(old_lbls.begin(), old_lbls.end(), vs_old.begin(),
3685 [](char *x) -> std::string { return std::string(x); });
3686
3687 this->relabels_(vs_old, vs);
3688 return *this;
3689 }
3690
3705 UniTensor relabel(const cytnx_int64 &inx, const std::string &new_label) const {
3706 UniTensor out;
3707 out._impl = this->_impl->relabel(inx, new_label);
3708 return out;
3709 }
3718 UniTensor &relabel_(const cytnx_int64 &inx, const std::string &new_label) {
3719 this->_impl->relabel_(inx, new_label);
3720 return *this;
3721 }
3722
3731 UniTensor &relabel_(const std::string &old_label, const std::string &new_label) {
3732 this->_impl->relabel_(old_label, new_label);
3733 return *this;
3734 }
3735
3750 UniTensor relabel(const std::string &old_label, const std::string &new_label) const {
3751 UniTensor out;
3752 out._impl = this->_impl->relabel(old_label, new_label);
3753 return out;
3754 }
3755
3762 UniTensor astype(const unsigned int &dtype) const {
3763 UniTensor out;
3764 if (this->dtype() == dtype) {
3765 out._impl = this->_impl;
3766 } else {
3767 out._impl = this->_impl->astype(dtype);
3768 }
3769 return out;
3770 }
3771
3780 UniTensor permute(const std::vector<cytnx_int64> &mapper,
3781 const cytnx_int64 &rowrank = -1) const {
3782 UniTensor out;
3783 out._impl = this->_impl->permute(mapper, rowrank);
3784 return out;
3785 }
3786
3793 UniTensor permute(const std::vector<std::string> &mapper,
3794 const cytnx_int64 &rowrank = -1) const {
3795 UniTensor out;
3796 out._impl = this->_impl->permute(mapper, rowrank);
3797 return out;
3798 }
3799
3805 UniTensor permute(const std::initializer_list<char *> &mapper,
3806 const cytnx_int64 &rowrank = -1) const {
3807 std::vector<char *> mprs = mapper;
3808 std::vector<std::string> vs(mprs.size());
3809 transform(mprs.begin(), mprs.end(), vs.begin(),
3810 [](char *x) -> std::string { return std::string(x); });
3811
3812 return this->permute(vs, rowrank);
3813 }
3814
3822 UniTensor &permute_(const std::vector<cytnx_int64> &mapper, const cytnx_int64 &rowrank = -1) {
3823 this->_impl->permute_(mapper, rowrank);
3824 return *this;
3825 }
3826
3833 UniTensor &permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank = -1) {
3834 this->_impl->permute_(mapper, rowrank);
3835 return *this;
3836 }
3837
3851 UniTensor permute_nosignflip(const std::vector<cytnx_int64> &mapper,
3852 const cytnx_int64 &rowrank = -1) const {
3853 UniTensor out;
3854 out._impl = this->_impl->permute_nosignflip(mapper, rowrank);
3855 return out;
3856 }
3857
3869 UniTensor permute_nosignflip(const std::vector<std::string> &mapper,
3870 const cytnx_int64 &rowrank = -1) const {
3871 UniTensor out;
3872 out._impl = this->_impl->permute_nosignflip(mapper, rowrank);
3873 return out;
3874 }
3875
3881 UniTensor permute_nosignflip(const std::initializer_list<char *> &mapper,
3882 const cytnx_int64 &rowrank = -1) const {
3883 std::vector<char *> mprs = mapper;
3884 std::vector<std::string> vs(mprs.size());
3885 transform(mprs.begin(), mprs.end(), vs.begin(),
3886 [](char *x) -> std::string { return std::string(x); });
3887
3888 return this->permute_nosignflip(vs, rowrank);
3889 }
3890
3903 UniTensor &permute_nosignflip_(const std::vector<cytnx_int64> &mapper,
3904 const cytnx_int64 &rowrank = -1) {
3905 this->_impl->permute_nosignflip_(mapper, rowrank);
3906 return *this;
3907 }
3908
3920 UniTensor &permute_nosignflip_(const std::vector<std::string> &mapper,
3921 const cytnx_int64 &rowrank = -1) {
3922 this->_impl->permute_nosignflip_(mapper, rowrank);
3923 return *this;
3924 }
3925
3934 UniTensor twist(const std::string &label) const {
3935 UniTensor out = this->clone();
3936 out._impl->twist_(label);
3937 return out;
3938 }
3948 UniTensor out = this->clone();
3949 out._impl->twist_(idx);
3950 return out;
3951 }
3957 UniTensor &twist_(const std::string &label) {
3958 this->_impl->twist_(label);
3959 return *this;
3960 }
3967 this->_impl->twist_(idx);
3968 return *this;
3969 }
3970
3986 UniTensor out = this->clone();
3987 out._impl->fermion_twists_();
3988 return out;
3989 }
3996 this->_impl->fermion_twists_();
3997 return *this;
3998 }
3999
4007 UniTensor out;
4008 out._impl = this->_impl->contiguous();
4009 return out;
4010 }
4011
4017 this->_impl = this->_impl->contiguous_();
4018 return *this;
4019 }
4020
4030 UniTensor out;
4031 out._impl = this->_impl->apply();
4032 return out;
4033 }
4034
4041 this->_impl = this->_impl->apply_();
4042 return *this;
4043 }
4044
4049 void print_diagram(const bool &bond_info = false) const {
4050 this->_impl->print_diagram(bond_info);
4051 }
4052
4057 void print_blocks(const bool &full_info = true) const { this->_impl->print_blocks(full_info); }
4058
4064 void print_block(const cytnx_int64 &idx, const bool &full_info = true) const {
4065 this->_impl->print_block(idx, full_info);
4066 }
4067
4075 this->_impl->group_basis_();
4076 return *this;
4077 }
4078
4080 UniTensor out = this->clone();
4081 out.group_basis_();
4082 return out;
4083 }
4084
4093 template <class T>
4094 T &at(const std::vector<cytnx_uint64> &locator) {
4095 if (this->uten_type() == UTenType.Block || this->uten_type() == UTenType.BlockFermionic) {
4096 // [NEW] this will not check if it exists, if it is not then error will throw!
4097 T aux;
4098 return this->_impl->at_for_sparse(locator, aux);
4099 } else if (this->uten_type() == UTenType.Dense) {
4100 return this->get_block_().at<T>(locator);
4101 } else {
4102 cytnx_error_msg(this->uten_type() == UTenType.Void,
4103 "[ERROR] UniTensor is not initialized and of type Void.%s", "\n");
4105 this->uten_type() == UTenType.Sparse,
4106 "[ERROR] SparseUniTensor is deprecated. Use BlockUniTensor or LinOp instead.%s", "\n");
4107 cytnx_error_msg(true, "[ERROR] UniTensor type '%s' not supported\n",
4108 this->uten_type_str().c_str());
4109 }
4110 }
4111
4120 template <class T>
4121 const T &at(const std::vector<cytnx_uint64> &locator) const {
4122 if (this->uten_type() == UTenType.Block || this->uten_type() == UTenType.BlockFermionic) {
4123 // [NEW] this will not check if it exists, if it is not then error will throw!
4124 T aux;
4125 return this->_impl->at_for_sparse(locator, aux);
4126 } else if (this->uten_type() == UTenType.Dense) {
4127 return this->get_block_().at<T>(locator);
4128 } else {
4129 cytnx_error_msg(this->uten_type() == UTenType.Void,
4130 "[ERROR] UniTensor is not initialized and of type Void.%s", "\n");
4132 this->uten_type() == UTenType.Sparse,
4133 "[ERROR] SparseUniTensor is deprecated. Use BlockUniTensor or LinOp instead.%s", "\n");
4134 cytnx_error_msg(true, "[ERROR] UniTensor type '%s' not supported\n",
4135 this->uten_type_str().c_str());
4136 }
4137 }
4138
4139 template <class T>
4140 const T &at(const std::vector<std::string> &labels,
4141 const std::vector<cytnx_uint64> &locator) const {
4142 // giving label <-> locator one to one corresponding, return the element:
4143 cytnx_error_msg(locator.size() != labels.size(),
4144 "[ERROR][at] length of list should be the same for label and locator.%s",
4145 "\n");
4147 labels.size() != this->rank(),
4148 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
4149 std::vector<cytnx_uint64> new_locator(this->rank());
4151 for (int i = 0; i < labels.size(); i++) {
4152 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
4153 cytnx_error_msg(res == this->_impl->_labels.end(),
4154 "[ERROR] label:%s does not exist in current UniTensor.\n",
4155 labels[i].c_str());
4156 new_loc = std::distance(this->_impl->_labels.begin(), res);
4158 }
4159 return this->at<T>(new_locator);
4160 }
4161 template <class T>
4162 T &at(const std::vector<std::string> &labels, const std::vector<cytnx_uint64> &locator) {
4163 // giving label <-> locator one to one corresponding, return the element:
4164 cytnx_error_msg(locator.size() != labels.size(),
4165 "[ERROR][at] length of list should be the same for label and locator.%s",
4166 "\n");
4168 labels.size() != this->rank(),
4169 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
4170 std::vector<cytnx_uint64> new_locator(this->rank());
4172 for (int i = 0; i < labels.size(); i++) {
4173 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
4174 cytnx_error_msg(res == this->_impl->_labels.end(),
4175 "[ERROR] label:%s does not exist in current UniTensor.\n",
4176 labels[i].c_str());
4177 new_loc = std::distance(this->_impl->_labels.begin(), res);
4179 }
4180 return this->at<T>(new_locator);
4181 }
4182
4190 const Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) const {
4191 if (this->uten_type() == UTenType.Block || this->uten_type() == UTenType.BlockFermionic) {
4192 return this->_impl->at_for_sparse(locator);
4193 } else if (this->uten_type() == UTenType.Dense) {
4194 return this->get_block_().at(locator);
4195 } else {
4196 cytnx_error_msg(this->uten_type() == UTenType.Void,
4197 "[ERROR] UniTensor is not initialized and of type Void.%s", "\n");
4199 this->uten_type() == UTenType.Sparse,
4200 "[ERROR] SparseUniTensor is deprecated. Use BlockUniTensor or LinOp instead.%s", "\n");
4201 cytnx_error_msg(true, "[ERROR] UniTensor type '%s' not supported\n",
4202 this->uten_type_str().c_str());
4203 }
4204 }
4205
4213 Scalar::Sproxy at(const std::vector<cytnx_uint64> &locator) {
4214 if (this->uten_type() == UTenType.Block || this->uten_type() == UTenType.BlockFermionic) {
4215 return this->_impl->at_for_sparse(locator);
4216 } else if (this->uten_type() == UTenType.Dense) {
4217 return this->get_block_().at(locator);
4218 } else {
4219 cytnx_error_msg(this->uten_type() == UTenType.Void,
4220 "[ERROR] UniTensor is not initialized and of type Void.%s", "\n");
4222 this->uten_type() == UTenType.Sparse,
4223 "[ERROR] SparseUniTensor is deprecated. Use BlockUniTensor or LinOp instead.%s", "\n");
4224 cytnx_error_msg(true, "[ERROR] UniTensor type '%s' not supported\n",
4225 this->uten_type_str().c_str());
4226 }
4227 }
4228
4229 Scalar::Sproxy at(const std::vector<std::string> &labels,
4230 const std::vector<cytnx_uint64> &locator) {
4231 // giving label <-> locator one to one corresponding, return the element:
4232 cytnx_error_msg(locator.size() != labels.size(),
4233 "[ERROR][at] length of list should be the same for label and locator.%s",
4234 "\n");
4236 labels.size() != this->rank(),
4237 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
4238 std::vector<cytnx_uint64> new_locator(this->rank());
4240 for (int i = 0; i < labels.size(); i++) {
4241 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
4242 cytnx_error_msg(res == this->_impl->_labels.end(),
4243 "[ERROR] label:%s does not exist in current UniTensor.\n",
4244 labels[i].c_str());
4245 new_loc = std::distance(this->_impl->_labels.begin(), res);
4247 }
4248 return this->at(new_locator);
4249 }
4250
4251 const Scalar::Sproxy at(const std::vector<std::string> &labels,
4252 const std::vector<cytnx_uint64> &locator) const {
4253 // giving label <-> locator one to one corresponding, return the element:
4254 cytnx_error_msg(locator.size() != labels.size(),
4255 "[ERROR][at] length of list should be the same for label and locator.%s",
4256 "\n");
4258 labels.size() != this->rank(),
4259 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s", "\n");
4260 std::vector<cytnx_uint64> new_locator(this->rank());
4262 for (int i = 0; i < labels.size(); i++) {
4263 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
4264 cytnx_error_msg(res == this->_impl->_labels.end(),
4265 "[ERROR] label:%s does not exist in current UniTensor.\n",
4266 labels[i].c_str());
4267 new_loc = std::distance(this->_impl->_labels.begin(), res);
4269 }
4270 return this->at(new_locator);
4271 }
4272
4273 // return a copy of the block with the given block index
4282 Tensor get_block(const cytnx_uint64 &idx = 0) const { return this->_impl->get_block(idx); };
4283 //================================
4284 // return a clone of block
4296 Tensor get_block(const std::vector<cytnx_int64> &qidx, const bool &force = false) const {
4297 return this->_impl->get_block(qidx, force);
4298 }
4299
4300 Tensor get_block(const std::vector<std::string> &labels, const std::vector<cytnx_int64> &qidx,
4301 const bool &force = false) const {
4303 labels.size() != qidx.size(),
4304 "[ERROR][get_block] length of lists must be the same for both lables and qnidices%s", "\n");
4305 cytnx_error_msg(labels.size() != this->rank(),
4306 "[ERROR][get_block] length of lists must be the rank (# of legs)%s", "\n");
4307
4308 std::vector<cytnx_int64> loc_id(this->rank());
4309 std::vector<cytnx_int64> new_qidx(this->rank());
4310
4312 std::vector<cytnx_uint64> new_order(this->rank());
4313 for (int i = 0; i < labels.size(); i++) {
4314 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
4315 cytnx_error_msg(res == this->_impl->_labels.end(),
4316 "[ERROR][get_block] label:%s does not exists in current Tensor.\n",
4317 labels[i].c_str());
4318 new_loc = std::distance(this->_impl->_labels.begin(), res);
4319 new_qidx[new_loc] = qidx[i];
4320 new_order[i] = new_loc;
4321 }
4322 auto out = this->_impl->get_block(new_qidx, force);
4323 if (out.dtype() != Type.Void) out.permute_(new_order);
4324 return out;
4325 }
4326
4331 Tensor get_block(const std::initializer_list<cytnx_int64> &qnum,
4332 const bool &force = false) const {
4333 std::vector<cytnx_int64> tmp = qnum;
4334 return get_block(tmp, force);
4335 }
4336
4341 Tensor get_block(const std::vector<cytnx_uint64> &qnum, const bool &force = false) const {
4342 std::vector<cytnx_int64> iqnum(qnum.begin(), qnum.end());
4343 return this->_impl->get_block(iqnum, force);
4344 }
4345
4346 Tensor get_block(const std::vector<std::string> &labels, const std::vector<cytnx_uint64> &qidx,
4347 const bool &force = false) const {
4348 std::vector<cytnx_int64> iqnum(qidx.begin(), qidx.end());
4349 return this->get_block(labels, iqnum, force);
4350 }
4351
4360 const Tensor &get_block_(const cytnx_uint64 &idx = 0) const {
4361 return this->_impl->get_block_(idx);
4362 }
4363
4368 Tensor &get_block_(const cytnx_uint64 &idx = 0) { return this->_impl->get_block_(idx); }
4369
4381 Tensor &get_block_(const std::vector<cytnx_int64> &qidx, const bool &force = false) {
4382 return this->_impl->get_block_(qidx, force);
4383 }
4384
4401 // developer note: Tensor is not the same object (Thus Tensor instead of Tensor& ),
4402 // since we permute! but they have shared data memory.
4403 Tensor get_block_(const std::vector<std::string> &labels, const std::vector<cytnx_int64> &qidx,
4404 const bool &force = false) {
4406 labels.size() != qidx.size(),
4407 "[ERROR][get_block] length of lists must be the same for both lables and qnidices%s", "\n");
4408 cytnx_error_msg(labels.size() != this->rank(),
4409 "[ERROR][get_block] length of lists must be the rank (# of legs)%s", "\n");
4410
4411 std::vector<cytnx_int64> loc_id(this->rank());
4412 std::vector<cytnx_int64> new_qidx(this->rank());
4413
4415 std::vector<cytnx_uint64> new_order(this->rank());
4416 for (int i = 0; i < labels.size(); i++) {
4417 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), labels[i]);
4418 cytnx_error_msg(res == this->_impl->_labels.end(),
4419 "[ERROR][get_block] label:%s does not exists in current Tensor.\n",
4420 labels[i].c_str());
4421 new_loc = std::distance(this->_impl->_labels.begin(), res);
4422 new_qidx[new_loc] = qidx[i];
4423 new_order[i] = new_loc;
4424 }
4425 auto out = this->_impl->get_block_(new_qidx, force);
4426 if (out.dtype() != Type.Void) {
4427 out = out.permute(new_order);
4428 }
4429 return out;
4430 }
4431
4435 Tensor &get_block_(const std::initializer_list<cytnx_int64> &qidx, const bool &force = false) {
4436 std::vector<cytnx_int64> tmp = qidx;
4437 return get_block_(tmp, force);
4438 }
4439
4443 Tensor &get_block_(const std::vector<cytnx_uint64> &qidx, const bool &force = false) {
4444 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
4445 return get_block_(iqidx, force);
4446 }
4447
4448 Tensor get_block_(const std::vector<std::string> &labels, const std::vector<cytnx_uint64> &qidx,
4449 const bool &force = false) {
4450 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
4451 return get_block_(labels, iqidx, force);
4452 }
4453 //================================
4454
4455 // this only work for non-symm tensor. return a shared view of block
4459 const Tensor &get_block_(const std::vector<cytnx_int64> &qidx,
4460 const bool &force = false) const {
4461 return this->_impl->get_block_(qidx, force);
4462 }
4463
4467 const Tensor &get_block_(const std::initializer_list<cytnx_int64> &qidx,
4468 const bool &force = false) const {
4469 std::vector<cytnx_int64> tmp = qidx;
4470 return this->_impl->get_block_(tmp, force);
4471 }
4472
4476 const Tensor &get_block_(const std::vector<cytnx_uint64> &qidx,
4477 const bool &force = false) const {
4478 std::vector<cytnx_int64> iqidx(qidx.begin(), qidx.end());
4479 return get_block_(iqidx, force);
4480 }
4481
4482 //================================
4494 //[dev]
4495 std::vector<Tensor> get_blocks() const { return this->_impl->get_blocks(); }
4496
4505 //[dev]
4506 const std::vector<Tensor> &get_blocks_(const bool &silent = false) const {
4507 return this->_impl->get_blocks_(silent);
4508 }
4509
4513 //[dev]
4514 std::vector<Tensor> &get_blocks_(const bool &silent = false) {
4515 return this->_impl->get_blocks_(silent);
4516 }
4517
4528 this->_impl->put_block(in, idx);
4529 return *this;
4530 }
4531
4537 [[deprecated(
4538 "Please use "
4539 "UniTensor &put_block(const Tensor &in, const cytnx_uint64 &idx) "
4540 "instead.")]] UniTensor &
4541 put_block(const Tensor &in, const cytnx_uint64 &idx, const bool &force) {
4542 this->_impl->put_block(in, idx);
4543 return *this;
4544 }
4545
4555 UniTensor &put_block(const Tensor &in_tens, const std::vector<cytnx_int64> &qidx) {
4556 this->_impl->put_block(in_tens, qidx);
4557 return *this;
4558 }
4559
4565 [[deprecated(
4566 "Please use "
4567 "UniTensor &put_block(const Tensor &in_tens, const std::vector<cytnx_int64> &qidx) "
4568 "instead.")]] UniTensor &
4569 put_block(const Tensor &in_tens, const std::vector<cytnx_int64> &qidx, const bool &force) {
4570 this->_impl->put_block(in_tens, qidx);
4571 return *this;
4572 }
4573
4582 UniTensor &put_block(Tensor &in, const std::vector<std::string> &lbls,
4583 const std::vector<cytnx_int64> &qidx) {
4585 lbls.size() != qidx.size(),
4586 "[ERROR][put_block] length of lists must be the same for both lables and qnidices%s", "\n");
4587 cytnx_error_msg(lbls.size() != this->rank(),
4588 "[ERROR][put_block] length of lists must be the rank (# of legs)%s", "\n");
4589
4590 std::vector<cytnx_int64> loc_id(this->rank());
4591 std::vector<cytnx_int64> new_qidx(this->rank());
4592
4594 // std::vector<cytnx_uint64> new_order(this->rank());
4595 std::vector<cytnx_uint64> inv_order(this->rank());
4596 for (int i = 0; i < lbls.size(); i++) {
4597 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), lbls[i]);
4598 cytnx_error_msg(res == this->_impl->_labels.end(),
4599 "[ERROR][put_block] label:%s does not exists in current Tensor.\n",
4600 lbls[i].c_str());
4601 new_loc = std::distance(this->_impl->_labels.begin(), res);
4602 new_qidx[new_loc] = qidx[i];
4603 // new_order[i] = new_loc;
4604 inv_order[new_loc] = i;
4605 }
4606 this->_impl->put_block(in.permute(inv_order), new_qidx);
4607 return *this;
4608 }
4609
4615 [[deprecated(
4616 "Please use "
4617 "UniTensor &put_block(Tensor &in, const std::vector<std::string> &lbls, const "
4618 "std::vector<cytnx_int64> &qidx) "
4619 "instead.")]] UniTensor &
4620 put_block(Tensor &in, const std::vector<std::string> &lbls,
4621 const std::vector<cytnx_int64> &qidx, const bool &force) {
4622 return put_block(in, lbls, qidx);
4623 }
4624
4635 this->_impl->put_block_(in, idx);
4636 return *this;
4637 }
4638
4648 UniTensor &put_block_(Tensor &in, const std::vector<cytnx_int64> &qidx) {
4649 this->_impl->put_block_(in, qidx);
4650 return *this;
4651 }
4652
4658 [[deprecated(
4659 "Please use "
4660 "UniTensor &put_block_(Tensor &in, const std::vector<cytnx_int64> &qidx) "
4661 "instead.")]] UniTensor &
4662 put_block_(Tensor &in, const std::vector<cytnx_int64> &qidx, const bool &force) {
4663 this->_impl->put_block_(in, qidx);
4664 return *this;
4665 }
4666
4675 UniTensor &put_block_(Tensor &in, const std::vector<std::string> &lbls,
4676 const std::vector<cytnx_int64> &qidx) {
4678 lbls.size() != qidx.size(),
4679 "[ERROR][put_block_] length of lists must be the same for both lables and qnidices%s",
4680 "\n");
4681 cytnx_error_msg(lbls.size() != this->rank(),
4682 "[ERROR][put_block_] length of lists must be the rank (# of legs)%s", "\n");
4683
4684 std::vector<cytnx_int64> loc_id(this->rank());
4685 std::vector<cytnx_int64> new_qidx(this->rank());
4686
4688 std::vector<cytnx_uint64> new_order(this->rank());
4689 std::vector<cytnx_uint64> inv_order(this->rank());
4690 for (int i = 0; i < lbls.size(); i++) {
4691 auto res = std::find(this->_impl->_labels.begin(), this->_impl->_labels.end(), lbls[i]);
4692 cytnx_error_msg(res == this->_impl->_labels.end(),
4693 "[ERROR][put_block_] label:%s does not exists in current Tensor.\n",
4694 lbls[i].c_str());
4695 new_loc = std::distance(this->_impl->_labels.begin(), res);
4696 new_qidx[new_loc] = qidx[i];
4697 new_order[i] = new_loc;
4698 inv_order[new_loc] = i;
4699 }
4700 in.permute_(inv_order);
4701 this->_impl->put_block_(in, new_qidx);
4702 in.permute_(new_order);
4703 return *this;
4704 }
4705
4711 [[deprecated(
4712 "Please use "
4713 "UniTensor &put_block_(Tensor &in, const std::vector<std::string> &lbls, const "
4714 "std::vector<cytnx_int64> &qidx) "
4715 "instead.")]] UniTensor &
4716 put_block_(Tensor &in, const std::vector<std::string> &lbls,
4717 const std::vector<cytnx_int64> &qidx, const bool &force) {
4718 return put_block_(in, lbls, qidx);
4719 }
4720
4736 UniTensor get(const std::vector<Accessor> &accessors) const {
4737 UniTensor out;
4738 out._impl = this->_impl->get(accessors);
4739 return out;
4740 }
4741
4746 UniTensor operator[](const std::vector<cytnx::Accessor> &accessors) const {
4747 UniTensor out;
4748 out._impl = this->_impl->get(accessors);
4749 return out;
4750 }
4751 UniTensor operator[](const std::initializer_list<cytnx::Accessor> &accessors) const {
4752 std::vector<cytnx::Accessor> acc_in = accessors;
4753 return this->get(acc_in);
4754 }
4755 UniTensor operator[](const std::vector<cytnx_int64> &accessors) const {
4756 std::vector<cytnx::Accessor> acc_in;
4757 for (cytnx_int64 i = 0; i < accessors.size(); i++) {
4758 acc_in.push_back(cytnx::Accessor(accessors[i]));
4759 }
4760 return this->get(acc_in);
4761 }
4762 UniTensor operator[](const std::initializer_list<cytnx_int64> &accessors) const {
4763 std::vector<cytnx_int64> acc_in = accessors;
4764 return (*this)[acc_in];
4765 }
4766
4783 UniTensor &set(const std::vector<Accessor> &accessors, const Tensor &rhs) {
4784 this->_impl->set(accessors, rhs);
4785 return *this;
4786 }
4787 UniTensor &set(const std::vector<Accessor> &accessors, const UniTensor &rhs) {
4789 rhs.uten_type() != UTenType.Dense,
4790 "[ERROR] Cannot set elements from UniTensor with symmetry. Use at() instead.%s", "\n");
4791 cytnx_error_msg(this->is_diag(), "[ERROR] Cannot set UniTensor with is_diag=True.%s", "\n");
4793 "[ERROR] Cannot set UniTensor. incoming UniTensor is_diag=True.%s", "\n");
4794
4795 this->_impl->set(accessors, rhs.get_block());
4796 return *this;
4797 }
4798
4806 UniTensor reshape(const std::vector<cytnx_int64> &new_shape, const cytnx_uint64 &rowrank = 0) {
4807 UniTensor out;
4808 out._impl = this->_impl->reshape(new_shape, rowrank);
4809 return out;
4810 }
4811
4818 UniTensor &reshape_(const std::vector<cytnx_int64> &new_shape,
4819 const cytnx_uint64 &rowrank = 0) {
4820 this->_impl->reshape_(new_shape, rowrank);
4821 return *this;
4822 }
4823
4835 UniTensor out;
4836 out._impl = this->_impl->to_dense();
4837 return out;
4838 }
4839
4845 this->_impl->to_dense_();
4846 return *this;
4847 }
4848
4854 [[deprecated(
4855 "Please use "
4856 "combineBond_(const std::vector<std::string> &indicators, const bool &force) "
4857 "instead.")]] void
4858 combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force,
4859 const bool &by_label) {
4860 this->_impl->combineBonds(indicators, force, by_label);
4861 }
4862
4868 [[deprecated(
4869 "Please use "
4870 "combineBond_(const std::vector<std::string> &indicators, const bool &force) "
4871 "instead.")]] void
4872 combineBonds(const std::vector<std::string> &indicators, const bool &force = false) {
4873 this->_impl->combineBonds(indicators, force);
4874 }
4875
4881 [[deprecated(
4882 "Please use "
4883 "combineBond_(const std::vector<std::string> &indicators, const bool &force) "
4884 "instead.")]] void
4885 combineBonds(const std::vector<cytnx_int64> &indicators, const bool &force = false) {
4886 this->_impl->combineBonds(indicators, force);
4887 }
4888
4901 UniTensor &combineBond_(const std::vector<std::string> &indicators, const bool &force = false) {
4902 this->_impl->combineBond(indicators, force);
4903 return *this;
4904 }
4905
4918 UniTensor combineBond(const std::vector<std::string> &indicators,
4919 const bool &force = false) const {
4920 UniTensor out = this->clone();
4922 return out;
4923 }
4924
4943 UniTensor contract(const UniTensor &inR, const bool &mv_elem_self = false,
4944 const bool &mv_elem_rhs = false) const {
4945 UniTensor out;
4946 out._impl = this->_impl->contract(inR._impl, mv_elem_self, mv_elem_rhs);
4947 return out;
4948 }
4949
4951
4959 std::vector<Bond> getTotalQnums(const bool physical = false) const {
4960 return this->_impl->getTotalQnums(physical);
4961 }
4962
4966 std::vector<std::vector<cytnx_int64>> get_blocks_qnums() const {
4967 return this->_impl->get_blocks_qnums();
4968 }
4970
4975 bool same_data(const UniTensor &rhs) const {
4976 // check same type:
4977 if (this->_impl->uten_type() != rhs._impl->uten_type()) return false;
4978
4979 return this->_impl->same_data(rhs._impl);
4980 }
4981
5002 this->_impl->Add_(rhs._impl);
5003 return *this;
5004 }
5005
5026 this->_impl->Mul_(rhs._impl);
5027 return *this;
5028 }
5029
5050 this->_impl->Sub_(rhs._impl);
5051 return *this;
5052 }
5053
5074 this->_impl->Div_(rhs._impl);
5075 return *this;
5076 }
5077
5089 this->_impl->Add_(rhs);
5090 return *this;
5091 }
5092
5104 this->_impl->Mul_(rhs);
5105 return *this;
5106 }
5107
5119 this->_impl->Sub_(rhs);
5120 return *this;
5121 }
5122
5134 this->_impl->Div_(rhs);
5135 return *this;
5136 }
5137
5158
5169 UniTensor Add(const Scalar &rhs) const;
5170
5191
5202 UniTensor Mul(const Scalar &rhs) const;
5203
5224
5235 UniTensor Div(const Scalar &rhs) const;
5236
5257
5268 UniTensor Sub(const Scalar &rhs) const;
5269
5279 [[deprecated("use norm() (returns Scalar) instead")]] Tensor Norm() const {
5280 return this->_impl->Norm();
5281 };
5282
5293 Scalar norm() const { return this->_impl->Norm().item(); };
5294
5311 this->Add_(rhs);
5312 return *this;
5313 }
5314
5331 this->Sub_(rhs);
5332 return *this;
5333 }
5334
5351 this->Div_(rhs);
5352 return *this;
5353 }
5354
5371 this->Mul_(rhs);
5372 return *this;
5373 }
5374
5386 this->Add_(rhs);
5387 return *this;
5388 }
5389
5401 this->Sub_(rhs);
5402 return *this;
5403 }
5404
5416 this->Div_(rhs);
5417 return *this;
5418 }
5419
5431 this->Mul_(rhs);
5432 return *this;
5433 }
5434
5459 UniTensor Inv(double clip = -1.) const;
5460
5485 UniTensor &Inv_(double clip = -1.);
5486
5494 UniTensor Conj() const {
5495 UniTensor out;
5496 out._impl = this->_impl->Conj();
5497 return out;
5498 }
5499
5508 this->_impl->Conj_();
5509 return *this;
5510 }
5511
5526 UniTensor out;
5527 out._impl = this->_impl->Transpose();
5528 return out;
5529 }
5530
5539 this->_impl->Transpose_();
5540 return *this;
5541 }
5542
5550 UniTensor out;
5551 out._impl = this->_impl->normalize();
5552 return out;
5553 }
5554
5562 this->_impl->normalize_();
5563 return *this;
5564 }
5565
5575 UniTensor Trace(const std::string &a, const std::string &b) const {
5576 UniTensor out;
5577 out._impl = this->_impl->Trace(a, b);
5578 return out;
5579 }
5580
5590 UniTensor Trace(const cytnx_int64 &a = 0, const cytnx_int64 &b = 1) const {
5591 UniTensor out;
5592 out._impl = this->_impl->Trace(a, b);
5593 return out;
5594 }
5595
5605 UniTensor &Trace_(const std::string &a, const std::string &b) {
5606 this->_impl->Trace_(a, b);
5607 return *this;
5608 }
5609
5619 UniTensor &Trace_(const cytnx_int64 &a = 0, const cytnx_int64 &b = 1) {
5620 this->_impl->Trace_(a, b);
5621 return *this;
5622 }
5623
5633 UniTensor out;
5634 out._impl = this->_impl->Dagger();
5635 return out;
5636 }
5637
5647 this->_impl->Dagger_();
5648 return *this;
5649 }
5650
5660 this->_impl->tag_();
5661 return *this;
5662 }
5663
5667 [[deprecated("Please use tag_() instead.")]] UniTensor &tag() { return this->tag_(); }
5668
5684 UniTensor Pow(const double &p) const;
5685
5701 UniTensor &Pow_(const double &p);
5702
5709 bool elem_exists(const std::vector<cytnx_uint64> &locator) const {
5710 return this->_impl->elem_exists(locator);
5711 }
5712
5718 template <class T>
5719 [[deprecated("Use at() instead.")]] T get_elem(const std::vector<cytnx_uint64> &locator) const {
5720 return this->at<T>(locator);
5721 }
5722
5728 template <class T2>
5729 [[deprecated("Use at() instead.")]] UniTensor &set_elem(
5730 const std::vector<cytnx_uint64> &locator, const T2 &rc) {
5731 // cytnx_error_msg(true,"[ERROR] invalid type%s","\n");
5732 this->at(locator) = rc;
5733 return *this;
5734 }
5735
5742 void Save(const std::string &fname) const;
5743
5750 void Save(const char *fname) const;
5751
5760 static UniTensor Load(const std::string &fname);
5761
5770 static UniTensor Load(const char *fname);
5771
5780 UniTensor &truncate_(const std::string &label, const cytnx_uint64 &dim) {
5781 this->_impl->truncate_(label, dim);
5782 return *this;
5783 }
5784
5794 this->_impl->truncate_(bond_idx, dim);
5795 return *this;
5796 }
5797
5807 UniTensor truncate(const std::string &label, const cytnx_uint64 &dim) const {
5808 UniTensor out = this->clone();
5809 out.truncate_(label, dim);
5810 return out;
5811 }
5812
5823 UniTensor out = this->clone();
5824 out.truncate_(bond_idx, dim);
5825 return out;
5826 }
5827
5835 const std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) const {
5836 return this->_impl->get_qindices(bidx);
5837 }
5845 std::vector<cytnx_uint64> &get_qindices(const cytnx_uint64 &bidx) {
5846 return this->_impl->get_qindices(bidx);
5847 }
5848
5855 const vec2d<cytnx_uint64> &get_itoi() const { return this->_impl->get_itoi(); }
5856 vec2d<cytnx_uint64> &get_itoi() { return this->_impl->get_itoi(); }
5857
5859 void _Load(std::fstream &f);
5860 void _Save(std::fstream &f) const;
5862
5878 this->_impl->from_(rhs._impl, force, tol);
5879 return *this;
5880 }
5881
5887 [[deprecated(
5888 "Please use convert_from_(const UniTensor &rhs, bool force, cytnx_double tol) "
5889 "instead.")]] UniTensor &
5890 convert_from(const UniTensor &rhs, bool force = false, cytnx_double tol = 0.) {
5891 return this->convert_from_(rhs, force, tol);
5892 }
5893
5894 // Generators:
5908 static UniTensor zeros(const std::vector<cytnx_uint64> &shape,
5909 const std::vector<std::string> &in_labels = {},
5910 unsigned int dtype = Type.Double, int device = Device.cpu,
5911 const std::string &name = "") {
5912 return UniTensor(cytnx::zeros(shape, dtype, device), false, -1, in_labels, name);
5913 }
5914 static UniTensor zeros(std::initializer_list<cytnx_uint64> shape,
5915 const std::vector<std::string> &in_labels = {},
5916 unsigned int dtype = Type.Double, int device = Device.cpu,
5917 const std::string &name = "") {
5918 return zeros(std::vector<cytnx_uint64>(shape), in_labels, dtype, device, name);
5919 }
5920
5934 static UniTensor identity(cytnx_uint64 dim, const std::vector<std::string> &in_labels = {},
5935 cytnx_bool is_diag = false, unsigned int dtype = Type.Double,
5936 int device = Device.cpu, const std::string &name = "") {
5937 if (is_diag) {
5938 return UniTensor(cytnx::ones({dim}, dtype, device), is_diag, -1, in_labels, name);
5939 } else {
5941 }
5942 }
5943
5959 static UniTensor eye(cytnx_uint64 dim, const std::vector<std::string> &in_labels = {},
5960 cytnx_bool is_diag = false, unsigned int dtype = Type.Double,
5961 int device = Device.cpu, const std::string &name = "") {
5962 return identity(dim, in_labels, is_diag, dtype, device, name);
5963 }
5964
5977 static UniTensor ones(const std::vector<cytnx_uint64> &shape,
5978 const std::vector<std::string> &in_labels = {},
5979 unsigned int dtype = Type.Double, int device = Device.cpu,
5980 const std::string &name = "") {
5981 return UniTensor(cytnx::ones(shape, dtype, device), false, -1, in_labels, name);
5982 }
5983 static UniTensor ones(std::initializer_list<cytnx_uint64> shape,
5984 const std::vector<std::string> &in_labels = {},
5985 unsigned int dtype = Type.Double, int device = Device.cpu,
5986 const std::string &name = "") {
5987 return ones(std::vector<cytnx_uint64>(shape), in_labels, dtype, device, name);
5988 }
5989
6004 static UniTensor arange(cytnx_int64 Nelem, const std::vector<std::string> &in_labels = {},
6005 const std::string &name = "") {
6006 return UniTensor(cytnx::arange(Nelem), false, -1, in_labels, name);
6007 }
6008
6027 const std::vector<std::string> &in_labels = {},
6028 unsigned int dtype = Type.Double, int device = Device.cpu,
6029 const std::string &name = "") {
6030 return UniTensor(cytnx::arange(start, end, step, dtype, device), false, -1, in_labels, name);
6031 }
6032
6053 bool endpoint = true, const std::vector<std::string> &in_labels = {},
6054 unsigned int dtype = Type.Double, int device = Device.cpu,
6055 const std::string &name = "") {
6056 return UniTensor(cytnx::linspace(start, end, Nelem, endpoint, dtype, device), false, -1,
6057 in_labels, name);
6058 }
6059
6060 // Random Generators:
6079 static UniTensor normal(const cytnx_uint64 &Nelem, const double &mean, const double &std,
6080 const std::vector<std::string> &in_labels = {},
6081 const unsigned int &seed = cytnx::random::__static_random_device(),
6082 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
6083 const std::string &name = "");
6084
6103 static UniTensor normal(const std::vector<cytnx_uint64> &shape, const double &mean,
6104 const double &std, const std::vector<std::string> &in_labels = {},
6105 const unsigned int &seed = cytnx::random::__static_random_device(),
6106 const unsigned int &dtype = Type.Double, const int &device = Device.cpu,
6107 const std::string &name = "");
6108
6127 static UniTensor uniform(const cytnx_uint64 &Nelem, const double &low, const double &high,
6128 const std::vector<std::string> &in_labels = {},
6129 const unsigned int &seed = cytnx::random::__static_random_device(),
6130 const unsigned int &dtype = Type.Double,
6131 const int &device = Device.cpu, const std::string &name = "");
6132
6170 static UniTensor uniform(const std::vector<cytnx_uint64> &shape, const double &low,
6171 const double &high, const std::vector<std::string> &in_labels = {},
6172 const unsigned int &seed = cytnx::random::__static_random_device(),
6173 const unsigned int &dtype = Type.Double,
6174 const int &device = Device.cpu, const std::string &name = "");
6175
6176 // Inplace Random Generators:
6189 UniTensor &normal_(const double &mean, const double &std,
6190 const unsigned int &seed = cytnx::random::__static_random_device());
6191
6204 UniTensor &uniform_(const double &low = 0, const double &high = 1,
6205 const unsigned int &seed = cytnx::random::__static_random_device());
6206
6207 }; // class UniTensor
6208
6210 std::ostream &operator<<(std::ostream &os, const UniTensor &in);
6212
6225 UniTensor Contract(const UniTensor &inL, const UniTensor &inR, const bool &cacheL = false,
6226 const bool &cacheR = false);
6227
6240 UniTensor Contract(const std::vector<UniTensor> &TNs, const std::string &order,
6241 const bool &optimal);
6242
6248 [[deprecated(
6249 "Please use "
6250 "UniTensor Contract(const std::vector<UniTensor> &TNs, const std::string &order, const bool "
6251 "&optimal) "
6252 "instead.")]] UniTensor
6253 Contracts(const std::vector<UniTensor> &TNs, const std::string &order, const bool &optimal);
6254
6256 void _resolve_CT(std::vector<UniTensor> &TNlist);
6257 template <class... T>
6258 void _resolve_CT(std::vector<UniTensor> &TNlist, const UniTensor &in, const T &...args) {
6259 TNlist.push_back(in);
6260 _resolve_CT(TNlist, args...);
6261 }
6263
6275 template <class... T>
6276 UniTensor Contract(const UniTensor &in, const T &...args, const std::string &order,
6277 const bool &optimal) {
6278 std::vector<UniTensor> TNlist;
6279 _resolve_CT(TNlist, in, args...);
6280 return Contract(TNlist, order, optimal);
6281 }
6282
6288 template <class... T>
6289 [[deprecated(
6290 "Please use "
6291 "UniTensor Contract(const UniTensor &in, const T &...args, const std::string &order, const "
6292 "bool &optimal) "
6293 "instead.")]] UniTensor
6294 Contracts(const UniTensor &in, const T &...args, const std::string &order,
6295 const bool &optimal) {
6296 std::vector<UniTensor> TNlist;
6297 _resolve_CT(TNlist, in, args...);
6298 return Contracts(TNlist, order, optimal);
6299 }
6300
6301} // namespace cytnx
6302
6303#endif // BACKEND_TORCH
6304
6305#endif // CYTNX_UNITENSOR_H_
constexpr Type_class Type
data type
Definition Type.hpp:555
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:41
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition Tensor.hpp:965
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:2775
UniTensor to(const int &device) const
move the current UniTensor to the assigned device.
Definition UniTensor.hpp:3398
UniTensor & operator*=(const UniTensor &rhs)
The multiplication assignment operator of the UniTensor.
Definition UniTensor.hpp:5370
Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:4435
std::vector< Tensor > & get_blocks_(const bool &silent=false)
Definition UniTensor.hpp:4514
Tensor & get_block_(const std::vector< cytnx_uint64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:4443
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:4064
UniTensor & operator/=(const UniTensor &rhs)
The division assignment operator of the UniTensor.
Definition UniTensor.hpp:5350
UniTensor & set_elem(const std::vector< cytnx_uint64 > &locator, const T2 &rc)
Definition UniTensor.hpp:5729
T & item()
Definition UniTensor.hpp:3170
UniTensor & tag_()
Set the UniTensor as a tagged UniTensor, in-place.
Definition UniTensor.hpp:5659
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:4648
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:3019
bool is_contiguous() const
To tell whether the UniTensor is contiguous.
Definition UniTensor.hpp:3299
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:5959
T get_elem(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:5719
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:5890
Tensor get_block(const std::vector< std::string > &labels, const std::vector< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:4300
UniTensor & put_block(const Tensor &in, const cytnx_uint64 &idx, const bool &force)
Definition UniTensor.hpp:4541
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:5845
std::vector< bool > signflip() const
Get the sign information of a fermionic UniTensor.
Definition UniTensor.hpp:3369
UniTensor & set_label_(const std::string &old_label, const char *new_label)
Definition UniTensor.hpp:3035
UniTensor & set_label(const cytnx_int64 &idx, const char *new_label)
Definition UniTensor.hpp:3066
UniTensor & operator+=(const UniTensor &rhs)
The addition assignment operator of the UniTensor.
Definition UniTensor.hpp:5310
UniTensor reshape(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor.
Definition UniTensor.hpp:4806
std::vector< Tensor > get_blocks() const
Get all the blocks of the UniTensor.
Definition UniTensor.hpp:4495
UniTensor permute(const std::initializer_list< char * > &mapper, const cytnx_int64 &rowrank=-1) const
Definition UniTensor.hpp:3805
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:3312
std::string uten_type_str() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor in 'string' form.
Definition UniTensor.hpp:3292
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:3869
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:2864
bool is_void() const
Return whether the UniTensor is uninitialized.
Definition UniTensor.hpp:3234
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:4296
UniTensor & contiguous_()
Make the UniTensor contiguous by coalescing the memory (storage), inplacely.
Definition UniTensor.hpp:4016
UniTensor & tag()
Definition UniTensor.hpp:5667
const Bond & bond_(const cytnx_uint64 &idx) const
Definition UniTensor.hpp:3348
bool is_scalar() const
whether the UniTensor is an initialized rank-0 scalar UniTensor
Definition UniTensor.hpp:3240
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force=false)
Definition UniTensor.hpp:4885
UniTensor & set_label_(const char *old_label, const char *new_label)
Definition UniTensor.hpp:3043
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:3731
const T & at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:4140
UniTensor & relabels_(const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:3526
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:2814
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:4381
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:2837
UniTensor get(const std::vector< Accessor > &accessors) const
get elements using Accessor (C++ API) / slices (python API)
Definition UniTensor.hpp:4736
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:3903
T & at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:4162
UniTensor Conj() const
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:5494
UniTensor & set_label(const std::string &old_label, const std::string &new_label)
Definition UniTensor.hpp:3078
UniTensor set_rowrank(const cytnx_uint64 &new_rowrank) const
Definition UniTensor.hpp:3163
UniTensor & set(const std::vector< Accessor > &accessors, const UniTensor &rhs)
Definition UniTensor.hpp:4787
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:5400
cytnx_uint64 rowrank() const
Return the row rank of the UniTensor.
Definition UniTensor.hpp:3213
UniTensor & put_block(const Tensor &in_tens, const std::vector< cytnx_int64 > &qidx)
Put the block into the UniTensor with given quantum number.
Definition UniTensor.hpp:4555
UniTensor & relabels_(const std::vector< std::string > &old_labels, const std::vector< std::string > &new_labels)
Definition UniTensor.hpp:3596
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:5279
UniTensor Mul(const Scalar &rhs) const
The multiplication function for a given scalar.
UniTensor & twist_(const std::string &label)
Inline version.
Definition UniTensor.hpp:3957
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:3934
UniTensor & set_labels(const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:3142
UniTensor & relabel_(const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:3508
UniTensor & Sub_(const Scalar &rhs)
The subtraction function for a given scalar.
Definition UniTensor.hpp:5118
UniTensor & relabel_(const cytnx_int64 &inx, const std::string &new_label)
rebable the legs in the UniTensor by given index.
Definition UniTensor.hpp:3718
UniTensor & operator/=(const Scalar &rhs)
The division assignment operator for a given scalar.
Definition UniTensor.hpp:5415
const bool & is_braket_form() const
Check whether the UniTensor is in braket form.
Definition UniTensor.hpp:3327
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:4746
UniTensor & set_label_(const char *old_label, const std::string &new_label)
Definition UniTensor.hpp:3027
std::vector< cytnx_uint64 > shape() const
Get the shape of the UniTensor.
Definition UniTensor.hpp:3361
UniTensor to_dense()
Convert the UniTensor to non-diagonal form.
Definition UniTensor.hpp:4834
UniTensor & permute_(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1)
permute the legs of the UniTensor, inplacely.
Definition UniTensor.hpp:3822
Scalar::Sproxy at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:4229
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:4459
UniTensor & set_name_(const std::string &in)
Set the name of a UniTensor, in-place.
Definition UniTensor.hpp:2973
UniTensor & set_labels(const std::vector< std::string > &new_labels)
Definition UniTensor.hpp:3128
std::string name() const
Return the name of the UniTensor.
Definition UniTensor.hpp:3271
const Scalar::Sproxy at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:4251
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:4582
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:5908
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:4918
UniTensor & Add_(const Scalar &rhs)
The addition function for a given scalar.
Definition UniTensor.hpp:5088
UniTensor & set(const std::vector< Accessor > &accessors, const Tensor &rhs)
set elements using Accessor (C++ API) / slices (python API)
Definition UniTensor.hpp:4783
UniTensor & Trace_(const std::string &a, const std::string &b)
Take the partial trace of the UniTensor, inplacely.
Definition UniTensor.hpp:5605
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:5793
UniTensor & twist_(const cytnx_int64 &idx)
Inline version.
Definition UniTensor.hpp:3966
Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator)
Get an element at a specific location.
Definition UniTensor.hpp:4213
UniTensor Trace(const std::string &a, const std::string &b) const
Take the partial trace of the UniTensor.
Definition UniTensor.hpp:5575
UniTensor & set_label_(const cytnx_int64 &idx, const char *new_label)
Definition UniTensor.hpp:3004
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:2911
bool same_data(const UniTensor &rhs) const
Check whether the Blocks address are the same.
Definition UniTensor.hpp:4975
UniTensor astype(const unsigned int &dtype) const
Return a new UniTensor whose elements are casted to a different data type.
Definition UniTensor.hpp:3762
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:5807
UniTensor Transpose() const
Take the transpose of the UniTensor.
Definition UniTensor.hpp:5525
UniTensor operator[](const std::initializer_list< cytnx_int64 > &accessors) const
Definition UniTensor.hpp:4762
UniTensor & set_label(const char *old_label, const std::string &new_label)
Definition UniTensor.hpp:3088
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:6004
UniTensor & Dagger_()
Take the conjugate transpose to the UniTensor, inplacely.
Definition UniTensor.hpp:5646
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at a specific location.
Definition UniTensor.hpp:4094
UniTensor & set_rowrank_(const cytnx_uint64 &new_rowrank)
Set the rowrank of the UniTensor.
Definition UniTensor.hpp:3158
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:4751
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:4675
UniTensor & set_label(const cytnx_int64 &idx, const std::string &new_label)
Definition UniTensor.hpp:3056
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:3851
UniTensor & fermion_twists_()
Inline version.
Definition UniTensor.hpp:3995
UniTensor & to_dense_()
Convert the UniTensor to non-diagonal form, inplacely.
Definition UniTensor.hpp:4844
UniTensor contiguous() const
Make the UniTensor contiguous by coalescing the memory (storage).
Definition UniTensor.hpp:4006
UniTensor & put_block_(Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index, inplacely.
Definition UniTensor.hpp:4634
UniTensor & combineBond_(const std::vector< std::string > &indicators, const bool &force=false)
Combine the sevral bonds of the UniTensor, in-place.
Definition UniTensor.hpp:4901
UniTensor & apply_()
Apply fermionic signflips to the UniTensor, inplacely. Subsequently, all elements returned by signfli...
Definition UniTensor.hpp:4040
Tensor get_block(const cytnx_uint64 &idx=0) const
Get the block of the UniTensor for a given block index.
Definition UniTensor.hpp:4282
const T & at(const std::vector< cytnx_uint64 > &locator) const
Get an element at a specific location.
Definition UniTensor.hpp:4121
UniTensor & operator*=(const Scalar &rhs)
The multiplication assignment operator for a given scalar.
Definition UniTensor.hpp:5430
UniTensor relabels(const std::vector< std::string > &old_labels, const std::vector< std::string > &new_labels) const
Definition UniTensor.hpp:3559
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:5877
UniTensor normalize() const
normalize the current UniTensor instance with 2-norm.
Definition UniTensor.hpp:5549
UniTensor & relabel_(const std::vector< std::string > &new_labels)
Set new labels for all the bonds.
Definition UniTensor.hpp:3423
std::vector< Symmetry > syms() const
Return the symmetry type of the UniTensor.
Definition UniTensor.hpp:3319
UniTensor relabel(const std::vector< std::string > &new_labels) const
relabel all of the labels in UniTensor.
Definition UniTensor.hpp:3452
UniTensor & Mul_(const UniTensor &rhs)
The multiplcation function of the UniTensor.
Definition UniTensor.hpp:5025
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:6052
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:3920
void combineBonds(const std::vector< std::string > &indicators, const bool &force=false)
Definition UniTensor.hpp:4872
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:3750
UniTensor & group_basis_()
Group the same quantum number basis together.
Definition UniTensor.hpp:4074
UniTensor & normalize_()
normalize the UniTensor, inplacely.
Definition UniTensor.hpp:5561
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:3305
int device() const
Return the device of the UniTensor.
Definition UniTensor.hpp:3265
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:4476
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:4403
std::string dtype_str() const
Return the data type of the UniTensor in 'string' form.
Definition UniTensor.hpp:3278
UniTensor & operator+=(const Scalar &rhs)
The addition assignment operator for a given scalar.
Definition UniTensor.hpp:5385
UniTensor & Div_(const UniTensor &rhs)
The division function of the UniTensor.
Definition UniTensor.hpp:5073
UniTensor & Div_(const Scalar &rhs)
The division function for a given scalar.
Definition UniTensor.hpp:5133
UniTensor & put_block_(Tensor &in, const std::vector< cytnx_int64 > &qidx, const bool &force)
Definition UniTensor.hpp:4662
Bond & bond_(const std::string &label)
Definition UniTensor.hpp:3352
cytnx_uint64 rank() const
Return the rank of the UniTensor.
Definition UniTensor.hpp:3207
Bond bond(const std::string &label) const
Definition UniTensor.hpp:3355
UniTensor fermion_twists() const
Apply twists to all right bonds (>= rowrank) with bond type BD_KET.
Definition UniTensor.hpp:3985
UniTensor permute_nosignflip(const std::initializer_list< char * > &mapper, const cytnx_int64 &rowrank=-1) const
Definition UniTensor.hpp:3881
UniTensor & Trace_(const cytnx_int64 &a=0, const cytnx_int64 &b=1)
Take the partial trace of the UniTensor, inplacely.
Definition UniTensor.hpp:5619
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:3543
UniTensor & put_block(const Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index.
Definition UniTensor.hpp:4527
UniTensor & put_block(const Tensor &in_tens, const std::vector< cytnx_int64 > &qidx, const bool &force)
Definition UniTensor.hpp:4569
UniTensor & set_name(const std::string &in)
Definition UniTensor.hpp:2981
UniTensor Trace(const cytnx_int64 &a=0, const cytnx_int64 &b=1) const
Take the partial trace of the UniTensor.
Definition UniTensor.hpp:5590
UniTensor & Add_(const UniTensor &rhs)
The addition function of the UniTensor.
Definition UniTensor.hpp:5001
UniTensor permute(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1) const
permute the legs of the UniTensor
Definition UniTensor.hpp:3780
UniTensor & set_label(const std::string &old_label, const char *new_label)
Definition UniTensor.hpp:3098
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:3793
unsigned int dtype() const
Return the data type of the UniTensor.
Definition UniTensor.hpp:3220
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:2996
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:5103
UniTensor & operator-=(const UniTensor &rhs)
The subtraction assignment operator of the UniTensor.
Definition UniTensor.hpp:5330
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:5983
Tensor get_block_(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:4448
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force, const bool &by_label)
Definition UniTensor.hpp:4858
UniTensor & set_label(const char *old_label, const char *new_label)
Definition UniTensor.hpp:3108
bool is_blockform() const
Check whether the UniTensor is in block form.
Definition UniTensor.hpp:3376
UniTensor group_basis() const
Definition UniTensor.hpp:4079
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:3947
UniTensor apply() const
Apply fermionic signflips to the UniTensor, such that all elements calling signflip() on the output t...
Definition UniTensor.hpp:4029
UniTensor Dagger() const
Take the conjugate transpose to the UniTensor.
Definition UniTensor.hpp:5632
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:4506
UniTensor & relabels_(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:3675
const Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:4467
bool elem_exists(const std::vector< cytnx_uint64 > &locator) const
Given the locator, check if the element exists.
Definition UniTensor.hpp:5709
UniTensor & Sub_(const UniTensor &rhs)
The subtraction function of the UniTensor.
Definition UniTensor.hpp:5049
UniTensor relabels(const std::initializer_list< char * > &new_labels) const
Definition UniTensor.hpp:3495
Scalar norm() const
Return the norm of the UniTensor.
Definition UniTensor.hpp:5293
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:4943
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:4360
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:3581
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:5934
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:3833
const Bond & bond_(const std::string &label) const
Definition UniTensor.hpp:3351
Bond & bond_(const cytnx_uint64 &idx)
Definition UniTensor.hpp:3349
cytnx_uint64 size() const
Return the total number of logical elements in the UniTensor.
Definition UniTensor.hpp:3248
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:3705
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:4818
bool is_empty() const
whether the UniTensor is initialized and has no logical elements
Definition UniTensor.hpp:3258
void print_diagram(const bool &bond_info=false) const
Plot the diagram of the UniTensor.
Definition UniTensor.hpp:4049
UniTensor relabels(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels) const
Definition UniTensor.hpp:3631
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:5835
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:3333
UniTensor & relabel_(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:3650
cytnx_int64 get_index(std::string label) const
Get the index of an desired label string.
Definition UniTensor.hpp:3340
UniTensor & to_(const int &device)
move the current UniTensor to the assigned device (inplace).
Definition UniTensor.hpp:3384
const std::vector< Bond > & bonds() const
Get the bonds of the UniTensor.
Definition UniTensor.hpp:3346
Tensor get_block(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:4346
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:5822
UniTensor & Transpose_()
Take the transpose of the UniTensor, inplacely.
Definition UniTensor.hpp:5538
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:4620
UniTensor clone() const
Clone (deep copy) the UniTensor.
Definition UniTensor.hpp:3408
vec2d< cytnx_uint64 > & get_itoi()
Definition UniTensor.hpp:5856
void print_blocks(const bool &full_info=true) const
Print all blocks of the UniTensor.
Definition UniTensor.hpp:4057
Scalar::Sproxy item() const
Definition UniTensor.hpp:3184
const vec2d< cytnx_uint64 > & get_itoi() const
get the q-indices on each leg for all the blocks
Definition UniTensor.hpp:5855
std::string device_str() const
Return the device of the UniTensor in 'string' form.
Definition UniTensor.hpp:3285
UniTensor & put_block_(Tensor &in, const std::vector< std::string > &lbls, const std::vector< cytnx_int64 > &qidx, const bool &force)
Definition UniTensor.hpp:4716
UniTensor relabels(const std::vector< std::string > &new_labels) const
Definition UniTensor.hpp:3466
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:5977
UniTensor relabel(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels) const
Definition UniTensor.hpp:3606
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:5507
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:6026
UniTensor operator[](const std::vector< cytnx_int64 > &accessors) const
Definition UniTensor.hpp:4755
UniTensor relabel(const std::initializer_list< char * > &new_labels) const
relables all of the labels in UniTensor.
Definition UniTensor.hpp:3476
cytnx_uint64 Nblocks() const
Return the number of blocks in the UniTensor.
Definition UniTensor.hpp:3201
Tensor get_block(const std::vector< cytnx_uint64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:4341
void Save(const char *fname) const
save a UniTensor to file
Bond bond(const cytnx_uint64 &idx) const
Definition UniTensor.hpp:3354
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:5914
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:5780
Tensor get_block(const std::initializer_list< cytnx_int64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:4331
UniTensor & relabels_(const std::vector< std::string > &new_labels)
Definition UniTensor.hpp:3436
const Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator) const
Get an element at a specific location.
Definition UniTensor.hpp:4190
int uten_type() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor.
Definition UniTensor.hpp:3228
Tensor & get_block_(const cytnx_uint64 &idx=0)
Definition UniTensor.hpp:4368
#define cytnx_warning_msg(is_true, format,...)
Definition cytnx_error.hpp:122
#define cytnx_error_msg(is_true, format,...)
Definition cytnx_error.hpp:115
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:29
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...