1#ifndef CYTNX_UNITENSOR_H_
2#define CYTNX_UNITENSOR_H_
8#include "utils/utils.hpp"
14#include <initializer_list>
24 #include "backend/Scalar.hpp"
32 using namespace cytnx;
34 class UniTensorType_class {
36 enum :
int {
Void = -99, Dense = 0, Sparse = 1, Block = 2, BlockFermionic = 3 };
37 std::string getname(
const int &ut_type)
const;
62 class UniTensor_base :
public intrusive_ptr_base<UniTensor_base> {
70 std::vector<std::string> _labels;
71 std::vector<Bond> _bonds;
73 bool _update_braket() {
74 if (_bonds.size() == 0)
return false;
76 if (this->_bonds[0].type() != bondType::BD_REG) {
78 for (
unsigned int i = 0; i < this->_bonds.size(); i++) {
79 if (i < this->_rowrank) {
80 if (this->_bonds[i].type() != bondType::BD_KET)
return false;
82 if (this->_bonds[i].type() != bondType::BD_BRA)
return false;
92 friend class DenseUniTensor;
94 friend class BlockUniTensor;
95 friend class BlockFermionicUniTensor;
99 _name(std::string(
"")),
100 _is_braket_form(false),
106 UniTensor_base(
const UniTensor_base &rhs);
107 UniTensor_base &operator=(UniTensor_base &rhs);
109 cytnx_uint64 rowrank()
const {
return this->_rowrank; }
110 bool is_diag()
const {
return this->_is_diag; }
111 const bool &is_braket_form()
const {
return this->_is_braket_form; }
112 const bool &is_tag()
const {
return this->_is_tag; }
113 const std::vector<std::string> &labels()
const {
return this->_labels; }
120 cytnx_int64 get_index(std::string label)
const {
121 std::vector<std::string> labels = this->_labels;
122 for (cytnx_uint64 i = 0; i < labels.size(); i++) {
123 if (labels[i] == label)
return i;
127 const std::vector<Bond> &bonds()
const {
return this->_bonds; }
128 std::vector<Bond> &bonds() {
return this->_bonds; }
130 Bond &bond_(
const cytnx_uint64 &idx) {
131 cytnx_error_msg(idx >= this->_bonds.size(),
"[ERROR][bond] index %d out of bound, total %d\n",
132 idx, this->_bonds.size());
133 return this->_bonds[idx];
136 Bond &bond_(
const std::string &label) {
137 auto res = std::find(this->_labels.begin(), this->_labels.end(), label);
138 cytnx_error_msg(res == this->_labels.end(),
"[ERROR] label %s not exists.\n", label.c_str());
139 cytnx_uint64 idx = std::distance(this->_labels.begin(), res);
141 return this->bond_(idx);
144 const std::string &name()
const {
return this->_name; }
145 cytnx_uint64 rank()
const {
return this->_labels.size(); }
146 void set_name(
const std::string &in) { this->_name = in; }
159 void set_label(
const std::string &oldlabel,
const std::string &new_label) {
161 auto res = std::find(this->_labels.begin(), this->_labels.end(), oldlabel);
162 cytnx_error_msg(res == this->_labels.end(),
"[ERROR] label %s not exists.\n",
164 idx = std::distance(this->_labels.begin(), res);
166 cytnx_error_msg(idx >= this->_labels.size(),
"[ERROR] index exceed the rank of UniTensor%s",
170 for (cytnx_uint64 i = 0; i < this->_labels.size(); i++) {
171 if (i == idx)
continue;
172 if (new_label == this->_labels[i]) {
177 cytnx_error_msg(is_dup,
"[ERROR] alreay has a label that is the same as the input label%s",
179 this->_labels[idx] = new_label;
181 void set_label(
const cytnx_int64 &inx,
const std::string &new_label) {
183 cytnx_error_msg(inx >= this->_labels.size(),
"[ERROR] index exceed the rank of UniTensor%s",
187 for (cytnx_uint64 i = 0; i < this->_labels.size(); i++) {
188 if (i == inx)
continue;
189 if (new_label == this->_labels[i]) {
194 cytnx_error_msg(is_dup,
"[ERROR] alreay has a label that is the same as the input label%s",
196 this->_labels[inx] = new_label;
199 void set_labels(
const std::vector<std::string> &new_labels);
200 void relabel_(
const std::vector<std::string> &new_labels);
201 void relabels_(
const std::vector<std::string> &new_labels);
202 void relabel_(
const std::vector<std::string> &old_labels,
203 const std::vector<std::string> &new_labels);
204 void relabels_(
const std::vector<std::string> &old_labels,
205 const std::vector<std::string> &new_labels);
206 void relabel_(
const std::string &old_label,
const std::string &new_label) {
207 this->set_label(old_label, new_label);
209 void relabel_(
const cytnx_int64 &inx,
const std::string &new_label) {
210 this->set_label(inx, new_label);
213 int uten_type() {
return this->uten_type_id; }
214 std::string uten_type_str()
const {
return UTenType.getname(this->uten_type_id); }
219 virtual void Init(
const std::vector<Bond> &bonds,
220 const std::vector<std::string> &in_labels = {},
221 const cytnx_int64 &rowrank = -1,
const unsigned int &dtype =
Type.Double,
222 const int &device =
Device.cpu,
const bool &is_diag =
false,
223 const bool &no_alloc =
false,
const std::string &name =
"");
225 virtual void Init_by_Tensor(
const Tensor &in,
const bool &is_diag =
false,
226 const cytnx_int64 &rowrank = -1,
const std::string &name =
"");
227 virtual std::vector<cytnx_uint64> shape()
const;
228 virtual std::vector<bool> signflip()
const;
229 virtual std::vector<bool> &signflip_();
230 virtual bool is_blockform()
const;
231 virtual bool is_contiguous()
const;
232 virtual void to_(
const int &device);
233 virtual boost::intrusive_ptr<UniTensor_base> to(
const int &device);
234 virtual boost::intrusive_ptr<UniTensor_base> clone()
const;
235 virtual unsigned int dtype()
const;
236 virtual int device()
const;
237 virtual std::string dtype_str()
const;
238 virtual std::string device_str()
const;
239 virtual void set_rowrank_(
const cytnx_uint64 &new_rowrank);
240 virtual boost::intrusive_ptr<UniTensor_base> set_rowrank(
const cytnx_uint64 &new_rowrank)
const;
242 virtual boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<cytnx_int64> &mapper,
243 const cytnx_int64 &rowrank = -1);
244 virtual boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<std::string> &mapper,
245 const cytnx_int64 &rowrank = -1);
249 virtual void permute_(
const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank = -1);
250 virtual void permute_(
const std::vector<std::string> &mapper,
const cytnx_int64 &rowrank = -1);
252 virtual boost::intrusive_ptr<UniTensor_base> permute_nosignflip(
253 const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank = -1);
254 virtual boost::intrusive_ptr<UniTensor_base> permute_nosignflip(
255 const std::vector<std::string> &mapper,
const cytnx_int64 &rowrank = -1);
256 virtual void permute_nosignflip_(
const std::vector<cytnx_int64> &mapper,
257 const cytnx_int64 &rowrank = -1);
258 virtual void permute_nosignflip_(
const std::vector<std::string> &mapper,
259 const cytnx_int64 &rowrank = -1);
263 virtual boost::intrusive_ptr<UniTensor_base> contiguous_();
264 virtual boost::intrusive_ptr<UniTensor_base> contiguous();
265 virtual void print_diagram(
const bool &bond_info =
false)
const;
266 virtual void print_blocks(
const bool &full_info =
true)
const;
267 virtual void print_block(
const cytnx_int64 &idx,
const bool &full_info =
true)
const;
269 virtual boost::intrusive_ptr<UniTensor_base> astype(
const unsigned int &dtype)
const;
271 virtual cytnx_uint64 Nblocks()
const {
return 0; };
272 virtual Tensor get_block(
const cytnx_uint64 &idx = 0)
const;
273 virtual Tensor get_block(
const std::vector<cytnx_int64> &qnum,
274 const bool &force)
const;
276 virtual const Tensor &get_block_(
const cytnx_uint64 &idx = 0)
278 virtual const Tensor &get_block_(
const std::vector<cytnx_int64> &qnum,
279 const bool &force)
const;
280 virtual Tensor &get_block_(
const cytnx_uint64 &idx = 0);
282 virtual Tensor &get_block_(
const std::vector<cytnx_int64> &qnum,
284 virtual bool same_data(
const boost::intrusive_ptr<UniTensor_base> &rhs)
const;
286 virtual std::vector<Tensor> get_blocks()
const;
287 virtual const std::vector<Tensor> &get_blocks_(
const bool &)
const;
288 virtual std::vector<Tensor> &get_blocks_(
const bool &);
290 virtual void put_block(
const Tensor &in,
const cytnx_uint64 &idx = 0);
291 virtual void put_block_(
Tensor &in,
const cytnx_uint64 &idx = 0);
292 virtual void put_block(
const Tensor &in,
const std::vector<cytnx_int64> &qnum,
294 virtual void put_block_(
Tensor &in,
const std::vector<cytnx_int64> &qnum,
const bool &force);
297 virtual boost::intrusive_ptr<UniTensor_base> get(
const std::vector<Accessor> &accessors);
300 virtual void set(
const std::vector<Accessor> &accessors,
const Tensor &rhs);
302 virtual void reshape_(
const std::vector<cytnx_int64> &new_shape,
303 const cytnx_uint64 &rowrank = 0);
304 virtual boost::intrusive_ptr<UniTensor_base> reshape(
const std::vector<cytnx_int64> &new_shape,
305 const cytnx_uint64 &rowrank = 0);
306 virtual boost::intrusive_ptr<UniTensor_base> to_dense();
307 virtual void to_dense_();
308 virtual void combineBond(
const std::vector<std::string> &indicators,
const bool &force =
false);
309 virtual void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &force,
310 const bool &by_label);
311 virtual void combineBonds(
const std::vector<std::string> &indicators,
312 const bool &force =
false);
313 virtual void combineBonds(
const std::vector<cytnx_int64> &indicators,
314 const bool &force =
false);
315 virtual boost::intrusive_ptr<UniTensor_base> contract(
316 const boost::intrusive_ptr<UniTensor_base> &rhs,
const bool &mv_elem_self =
false,
317 const bool &mv_elem_rhs =
false);
318 virtual std::vector<Bond> getTotalQnums(
const bool &physical =
false);
319 virtual std::vector<std::vector<cytnx_int64>> get_blocks_qnums()
const;
320 virtual void Trace_(
const std::string &a,
const std::string &b);
321 virtual void Trace_(
const cytnx_int64 &a,
const cytnx_int64 &b);
323 virtual boost::intrusive_ptr<UniTensor_base>
Trace(
const std::string &a,
const std::string &b);
324 virtual boost::intrusive_ptr<UniTensor_base>
Trace(
const cytnx_int64 &a,
const cytnx_int64 &b);
326 virtual boost::intrusive_ptr<UniTensor_base> relabel(
327 const std::vector<std::string> &new_labels);
328 virtual boost::intrusive_ptr<UniTensor_base> relabels(
329 const std::vector<std::string> &new_labels);
331 virtual boost::intrusive_ptr<UniTensor_base> relabel(
332 const std::vector<std::string> &old_labels,
const std::vector<std::string> &new_labels);
333 virtual boost::intrusive_ptr<UniTensor_base> relabels(
334 const std::vector<std::string> &old_labels,
const std::vector<std::string> &new_labels);
336 virtual boost::intrusive_ptr<UniTensor_base> relabel(
const std::string &old_label,
337 const std::string &new_label);
339 virtual boost::intrusive_ptr<UniTensor_base> relabel(
const cytnx_int64 &inx,
340 const std::string &new_label);
342 virtual std::vector<Symmetry> syms()
const;
345 virtual void Add_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
346 virtual void Add_(
const Scalar &rhs);
348 virtual void Mul_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
349 virtual void Mul_(
const Scalar &rhs);
351 virtual void Sub_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
352 virtual void Sub_(
const Scalar &rhs);
353 virtual void lSub_(
const Scalar &lhs);
355 virtual void Div_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
356 virtual void Div_(
const Scalar &rhs);
357 virtual void lDiv_(
const Scalar &lhs);
360 virtual boost::intrusive_ptr<UniTensor_base> normalize();
361 virtual void normalize_();
363 virtual boost::intrusive_ptr<UniTensor_base>
Conj();
364 virtual void Conj_();
366 virtual boost::intrusive_ptr<UniTensor_base> Transpose();
367 virtual void Transpose_();
369 virtual boost::intrusive_ptr<UniTensor_base> Dagger();
370 virtual void Dagger_();
374 virtual void truncate_(
const std::string &label,
const cytnx_uint64 &dim);
375 virtual void truncate_(
const cytnx_int64 &bond_idx,
const cytnx_uint64 &dim);
377 virtual bool elem_exists(
const std::vector<cytnx_uint64> &locator)
const;
380 virtual Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator);
381 virtual const Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator)
const;
383 virtual cytnx_complex128 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
384 const cytnx_complex128 &aux);
385 virtual cytnx_complex64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
386 const cytnx_complex64 &aux);
387 virtual cytnx_double &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
388 const cytnx_double &aux);
389 virtual cytnx_float &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
390 const cytnx_float &aux);
391 virtual cytnx_uint64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
392 const cytnx_uint64 &aux);
393 virtual cytnx_int64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
394 const cytnx_int64 &aux);
395 virtual cytnx_uint32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
396 const cytnx_uint32 &aux);
397 virtual cytnx_int32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
398 const cytnx_int32 &aux);
399 virtual cytnx_uint16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
400 const cytnx_uint16 &aux);
401 virtual cytnx_int16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
402 const cytnx_int16 &aux);
404 virtual const cytnx_complex128 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
405 const cytnx_complex128 &aux)
const;
406 virtual const cytnx_complex64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
407 const cytnx_complex64 &aux)
const;
408 virtual const cytnx_double &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
409 const cytnx_double &aux)
const;
410 virtual const cytnx_float &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
411 const cytnx_float &aux)
const;
412 virtual const cytnx_uint64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
413 const cytnx_uint64 &aux)
const;
414 virtual const cytnx_int64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
415 const cytnx_int64 &aux)
const;
416 virtual const cytnx_uint32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
417 const cytnx_uint32 &aux)
const;
418 virtual const cytnx_int32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
419 const cytnx_int32 &aux)
const;
420 virtual const cytnx_uint16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
421 const cytnx_uint16 &aux)
const;
422 virtual const cytnx_int16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
423 const cytnx_int16 &aux)
const;
425 virtual void from_(
const boost::intrusive_ptr<UniTensor_base> &rhs,
const bool &force,
426 const cytnx_double &tol);
427 virtual void from_(
const boost::intrusive_ptr<UniTensor_base> &rhs,
const bool &force);
429 virtual void group_basis_();
430 virtual const std::vector<cytnx_uint64> &get_qindices(
const cytnx_uint64 &bidx)
const;
431 virtual std::vector<cytnx_uint64> &get_qindices(
const cytnx_uint64 &bidx);
432 virtual const vec2d<cytnx_uint64> &get_itoi()
const;
433 virtual vec2d<cytnx_uint64> &get_itoi();
435 virtual void _save_dispatch(std::fstream &f)
const;
436 virtual void _load_dispatch(std::fstream &f);
438 virtual ~UniTensor_base(){};
444 class DenseUniTensor :
public UniTensor_base {
448 std::vector<Tensor> _interface_block;
449 DenseUniTensor *clone_meta()
const {
450 DenseUniTensor *tmp =
new DenseUniTensor();
451 tmp->_bonds = vec_clone(this->_bonds);
452 tmp->_labels = this->_labels;
453 tmp->_is_braket_form = this->_is_braket_form;
454 tmp->_rowrank = this->_rowrank;
455 tmp->_is_diag = this->_is_diag;
456 tmp->_name = this->_name;
457 tmp->_is_tag = this->_is_tag;
462 DenseUniTensor() { this->uten_type_id =
UTenType.Dense; };
471 void Init(
const std::vector<Bond> &bonds,
const std::vector<std::string> &in_labels = {},
472 const cytnx_int64 &rowrank = -1,
const unsigned int &dtype =
Type.Double,
473 const int &device =
Device.cpu,
const bool &is_diag =
false,
474 const bool &no_alloc =
false,
const std::string &name =
"");
476 void Init_by_Tensor(
const Tensor &in_tensor,
const bool &is_diag =
false,
477 const cytnx_int64 &rowrank = -1,
const std::string &name =
"");
478 std::vector<cytnx_uint64> shape()
const {
479 if (this->_is_diag) {
480 std::vector<cytnx_uint64> shape = this->_block.
shape();
481 shape.push_back(shape[0]);
484 return this->_block.
shape();
487 bool is_blockform()
const {
return false; }
488 void to_(
const int &device) { this->_block.
to_(device); }
489 boost::intrusive_ptr<UniTensor_base> to(
const int &device) {
490 if (this->device() == device) {
491 std::vector<Tensor> _interface_block;
494 boost::intrusive_ptr<UniTensor_base> out = this->clone();
499 void set_rowrank_(
const cytnx_uint64 &new_rowrank) {
501 "[ERROR] rowrank cannot exceed the rank of UniTensor.%s",
"\n");
502 if (this->is_diag()) {
503 cytnx_error_msg(new_rowrank != 1,
"[ERROR] rowrank should be [==1] when is_diag =true!.%s",
507 this->_rowrank = new_rowrank;
510 boost::intrusive_ptr<UniTensor_base> set_rowrank(
const cytnx_uint64 &new_rowrank)
const {
511 DenseUniTensor *out_raw = this->clone_meta();
512 out_raw->_block = this->_block;
513 out_raw->set_rowrank_(new_rowrank);
514 boost::intrusive_ptr<UniTensor_base> out(out_raw);
518 boost::intrusive_ptr<UniTensor_base> clone()
const {
519 DenseUniTensor *tmp = this->clone_meta();
520 tmp->_block = this->_block.
clone();
521 boost::intrusive_ptr<UniTensor_base> out(tmp);
524 bool is_contiguous()
const {
return this->_block.
is_contiguous(); }
525 unsigned int dtype()
const {
return this->_block.
dtype(); }
526 int device()
const {
return this->_block.
device(); }
527 std::string dtype_str()
const {
return Type.getname(this->_block.
dtype()); }
528 std::string device_str()
const {
return Device.getname(this->_block.
device()); }
538 boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<cytnx_int64> &mapper,
539 const cytnx_int64 &rowrank = -1);
540 boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<std::string> &mapper,
541 const cytnx_int64 &rowrank = -1);
551 void permute_(
const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank = -1);
552 void permute_(
const std::vector<std::string> &mapper,
const cytnx_int64 &rowrank = -1);
554 boost::intrusive_ptr<UniTensor_base> relabel(
const std::vector<std::string> &new_labels);
555 boost::intrusive_ptr<UniTensor_base> relabels(
const std::vector<std::string> &new_labels);
557 boost::intrusive_ptr<UniTensor_base> relabel(
const std::vector<std::string> &old_labels,
558 const std::vector<std::string> &new_labels);
559 boost::intrusive_ptr<UniTensor_base> relabels(
const std::vector<std::string> &old_labels,
560 const std::vector<std::string> &new_labels);
572 boost::intrusive_ptr<UniTensor_base> relabel(
const std::string &old_label,
573 const std::string &new_label);
574 boost::intrusive_ptr<UniTensor_base> relabel(
const cytnx_int64 &inx,
575 const std::string &new_label);
577 boost::intrusive_ptr<UniTensor_base> astype(
const unsigned int &dtype)
const {
578 DenseUniTensor *tmp = this->clone_meta();
579 tmp->_block = this->_block.
astype(dtype);
580 boost::intrusive_ptr<UniTensor_base> out(tmp);
584 std::vector<Symmetry> syms()
const {
585 cytnx_error_msg(
true,
"[ERROR][DenseUniTensor] dense unitensor does not have symmetry.%s",
587 return std::vector<Symmetry>();
590 boost::intrusive_ptr<UniTensor_base> contiguous_() {
592 return boost::intrusive_ptr<UniTensor_base>(
this);
594 boost::intrusive_ptr<UniTensor_base> contiguous() {
596 if (this->is_contiguous()) {
597 boost::intrusive_ptr<UniTensor_base> out(
this);
600 DenseUniTensor *tmp = this->clone_meta();
602 boost::intrusive_ptr<UniTensor_base> out(tmp);
606 void print_diagram(
const bool &bond_info =
false)
const;
607 void print_blocks(
const bool &full_info =
true)
const;
608 void print_block(
const cytnx_int64 &idx,
const bool &full_info =
true)
const;
609 Tensor get_block(
const cytnx_uint64 &idx = 0)
const {
return this->_block.
clone(); }
611 Tensor get_block(
const std::vector<cytnx_int64> &qnum,
const bool &force)
const {
613 true,
"[ERROR][DenseUniTensor] try to get_block() using qnum on a non-symmetry UniTensor%s",
618 const Tensor &get_block_(
const std::vector<cytnx_int64> &qnum,
const bool &force)
const {
621 "[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
625 Tensor &get_block_(
const std::vector<cytnx_int64> &qnum,
const bool &force) {
628 "[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
634 Tensor &get_block_(
const cytnx_uint64 &idx = 0) {
return this->_block; }
636 const Tensor &get_block_(
const cytnx_uint64 &idx = 0)
const {
return this->_block; }
638 cytnx_uint64 Nblocks()
const {
return 1; };
639 std::vector<Tensor> get_blocks()
const {
640 std::vector<Tensor> out;
642 true,
"[ERROR][DenseUniTensor] cannot use get_blocks(), use get_block() instead!%s",
"\n");
645 const std::vector<Tensor> &get_blocks_(
const bool &silent =
false)
const {
647 true,
"[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s",
649 return this->_interface_block;
651 std::vector<Tensor> &get_blocks_(
const bool &silent =
false) {
653 true,
"[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s",
655 return this->_interface_block;
658 void put_block(
const Tensor &in,
const cytnx_uint64 &idx = 0) {
667 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
672 if (this->is_diag()) {
674 in.
shape() != this->_block.shape(),
675 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s",
"\n");
676 this->_block = in.
clone();
679 in.
shape() != this->shape(),
680 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s",
"\n");
681 this->_block = in.
clone();
685 void put_block_(
Tensor &in,
const cytnx_uint64 &idx = 0) {
694 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
699 if (this->is_diag()) {
701 in.
shape() != this->_block.shape(),
702 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s",
"\n");
706 in.
shape() != this->shape(),
707 "[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s",
"\n");
712 void put_block(
const Tensor &in,
const std::vector<cytnx_int64> &qnum,
const bool &force) {
714 true,
"[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
717 void put_block_(
Tensor &in,
const std::vector<cytnx_int64> &qnum,
const bool &force) {
719 true,
"[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
723 boost::intrusive_ptr<UniTensor_base> get(
const std::vector<Accessor> &accessors) {
724 boost::intrusive_ptr<UniTensor_base> out(
new DenseUniTensor());
725 out->Init_by_Tensor(this->_block.
get(accessors),
false, 0);
729 void set(
const std::vector<Accessor> &accessors,
const Tensor &rhs) {
730 this->_block.
set(accessors, rhs);
733 void reshape_(
const std::vector<cytnx_int64> &new_shape,
const cytnx_uint64 &rowrank = 0);
734 boost::intrusive_ptr<UniTensor_base> reshape(
const std::vector<cytnx_int64> &new_shape,
735 const cytnx_uint64 &rowrank = 0);
736 boost::intrusive_ptr<UniTensor_base> to_dense();
738 void combineBond(
const std::vector<std::string> &indicators,
const bool &force =
true);
739 void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &force,
740 const bool &by_label);
741 void combineBonds(
const std::vector<std::string> &indicators,
const bool &force =
true);
742 void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &force =
true);
743 boost::intrusive_ptr<UniTensor_base> contract(
const boost::intrusive_ptr<UniTensor_base> &rhs,
744 const bool &mv_elem_self =
false,
745 const bool &mv_elem_rhs =
false);
746 std::vector<Bond> getTotalQnums(
const bool &physical =
false) {
748 "getTotalQnums can only operate on UniTensor with symmetry.\n");
749 return std::vector<Bond>();
752 std::vector<std::vector<cytnx_int64>> get_blocks_qnums()
const {
754 "get_blocks_qnums can only operate on UniTensor with symmetry.\n");
755 return std::vector<std::vector<cytnx_int64>>();
758 bool same_data(
const boost::intrusive_ptr<UniTensor_base> &rhs)
const {
759 if (rhs->uten_type() !=
UTenType.Dense)
return false;
761 return this->get_block_().same_data(rhs->get_block_());
767 void Add_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
768 void Add_(
const Scalar &rhs);
770 void Mul_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
771 void Mul_(
const Scalar &rhs);
773 void Sub_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
774 void Sub_(
const Scalar &rhs);
775 void lSub_(
const Scalar &lhs);
777 void Div_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
778 void Div_(
const Scalar &rhs);
779 void lDiv_(
const Scalar &lhs);
783 boost::intrusive_ptr<UniTensor_base>
Conj() {
784 boost::intrusive_ptr<UniTensor_base> out = this->clone();
789 boost::intrusive_ptr<UniTensor_base> Transpose() {
790 boost::intrusive_ptr<UniTensor_base> out = this->clone();
796 boost::intrusive_ptr<UniTensor_base> normalize() {
797 boost::intrusive_ptr<UniTensor_base> out = this->clone();
803 boost::intrusive_ptr<UniTensor_base> Dagger() {
804 boost::intrusive_ptr<UniTensor_base> out = this->
Conj();
821 void Trace_(
const cytnx_int64 &a,
const cytnx_int64 &b);
822 void Trace_(
const std::string &a,
const std::string &b);
823 boost::intrusive_ptr<UniTensor_base>
Trace(
const std::string &a,
const std::string &b) {
824 boost::intrusive_ptr<UniTensor_base> out = this->clone();
828 boost::intrusive_ptr<UniTensor_base>
Trace(
const cytnx_int64 &a,
const cytnx_int64 &b) {
829 boost::intrusive_ptr<UniTensor_base> out = this->clone();
836 const Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator)
const {
838 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
840 return Scalar::Sproxy();
842 const cytnx_complex128 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
843 const cytnx_complex128 &aux)
const {
845 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
847 return cytnx_complex128(0, 0);
849 const cytnx_complex64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
850 const cytnx_complex64 &aux)
const {
852 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
854 return cytnx_complex64(0, 0);
856 const cytnx_double &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
857 const cytnx_double &aux)
const {
859 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
863 const cytnx_float &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
864 const cytnx_float &aux)
const {
866 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
870 const cytnx_uint64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
871 const cytnx_uint64 &aux)
const {
873 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
877 const cytnx_int64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
878 const cytnx_int64 &aux)
const {
880 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
884 const cytnx_uint32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
885 const cytnx_uint32 &aux)
const {
887 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
891 const cytnx_int32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
892 const cytnx_int32 &aux)
const {
894 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
898 const cytnx_uint16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
899 const cytnx_uint16 &aux)
const {
901 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
905 const cytnx_int16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
906 const cytnx_int16 &aux)
const {
908 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
913 Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator) {
915 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
917 return Scalar::Sproxy();
919 cytnx_complex128 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
920 const cytnx_complex128 &aux) {
922 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
924 return *(cytnx_complex128 *)
nullptr;
926 cytnx_complex64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
927 const cytnx_complex64 &aux) {
929 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
931 return *(cytnx_complex64 *)
nullptr;
933 cytnx_double &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_double &aux) {
935 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
937 return *(cytnx_double *)
nullptr;
939 cytnx_float &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_float &aux) {
941 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
943 return *(cytnx_float *)
nullptr;
945 cytnx_uint64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint64 &aux) {
947 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
949 return *(cytnx_uint64 *)
nullptr;
951 cytnx_int64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int64 &aux) {
953 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
955 return *(cytnx_int64 *)
nullptr;
957 cytnx_uint32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint32 &aux) {
959 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
961 return *(cytnx_uint32 *)
nullptr;
963 cytnx_int32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int32 &aux) {
965 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
967 return *(cytnx_int32 *)
nullptr;
969 cytnx_uint16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint16 &aux) {
971 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
973 return *(cytnx_uint16 *)
nullptr;
975 cytnx_int16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int16 &aux) {
977 true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
979 return *(cytnx_int16 *)
nullptr;
982 bool elem_exists(
const std::vector<cytnx_uint64> &locator)
const {
984 true,
"[ERROR][DenseUniTensor] elem_exists can only be used on UniTensor with Symmetry.%s",
988 if (!this->is_tag()) {
989 for (
int i = 0; i < this->_rowrank; i++) {
990 this->_bonds[i].set_type(BD_KET);
992 for (
int i = this->_rowrank; i < this->_bonds.size(); i++) {
993 this->_bonds[i].set_type(BD_BRA);
995 this->_is_tag =
true;
996 this->_is_braket_form = this->_update_braket();
1008 void truncate_(
const cytnx_int64 &bond_idx,
const cytnx_uint64 &dim);
1009 void truncate_(
const std::string &label,
const cytnx_uint64 &dim);
1011 void from_(
const boost::intrusive_ptr<UniTensor_base> &rhs,
const bool &force);
1013 void group_basis_() {
1014 cytnx_warning_msg(
true,
"[WARNING] group basis will not have any effect on DensUniTensor.%s",
1018 void _save_dispatch(std::fstream &f)
const;
1019 void _load_dispatch(std::fstream &f);
1021 const std::vector<cytnx_uint64> &get_qindices(
const cytnx_uint64 &bidx)
const {
1022 cytnx_error_msg(
true,
"[ERROR] get_qindices can only be unsed on UniTensor with Symmetry.%s",
1025 std::vector<cytnx_uint64> &get_qindices(
const cytnx_uint64 &bidx) {
1026 cytnx_error_msg(
true,
"[ERROR] get_qindices can only be unsed on UniTensor with Symmetry.%s",
1030 const vec2d<cytnx_uint64> &get_itoi()
const {
1031 cytnx_error_msg(
true,
"[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s",
1034 vec2d<cytnx_uint64> &get_itoi() {
1035 cytnx_error_msg(
true,
"[ERROR] get_itoi can only be unsed on UniTensor with Symmetry.%s",
1045 class BlockUniTensor :
public UniTensor_base {
1048 std::vector<std::vector<cytnx_uint64>>
1049 _inner_to_outer_idx;
1050 std::vector<Tensor> _blocks;
1056 void _fx_get_total_fluxs(std::vector<cytnx_uint64> &loc,
const std::vector<Symmetry> &syms,
1057 std::vector<cytnx_int64> &total_qns) {
1058 memset(&total_qns[0], 0,
sizeof(cytnx_int64) * total_qns.size());
1060 for (cytnx_int32 i = 0; i < syms.size(); i++) {
1061 if (this->_bonds[0].type() == BD_BRA)
1062 total_qns[i] = syms[0].reverse_rule(this->_bonds[0]._impl->_qnums[loc[0]][i]);
1064 total_qns[i] = this->_bonds[0]._impl->_qnums[loc[0]][i];
1066 for (
auto j = 1; j < loc.size(); j++) {
1067 if (this->_bonds[j].type() == BD_BRA)
1068 total_qns[i] = syms[i].combine_rule(
1069 total_qns[i], syms[i].reverse_rule(this->_bonds[j]._impl->_qnums[loc[j]][i]));
1072 syms[i].combine_rule(total_qns[i], this->_bonds[j]._impl->_qnums[loc[j]][i]);
1078 void _fx_locate_elem(cytnx_int64 &bidx, std::vector<cytnx_uint64> &loc_in_T,
1079 const std::vector<cytnx_uint64> &locator)
const;
1082 void _fx_group_duplicates(
const std::vector<cytnx_uint64> &dup_bond_idxs,
1083 const std::vector<std::vector<cytnx_uint64>> &idx_mappers);
1085 void set_meta(BlockUniTensor *tmp,
const bool &inner,
const bool &outer)
const {
1088 tmp->_bonds = vec_clone(this->_bonds);
1089 tmp->_labels = this->_labels;
1090 tmp->_is_braket_form = this->_is_braket_form;
1091 tmp->_rowrank = this->_rowrank;
1092 tmp->_name = this->_name;
1095 tmp->_is_diag = this->_is_diag;
1099 tmp->_inner_to_outer_idx = this->_inner_to_outer_idx;
1103 BlockUniTensor *clone_meta(
const bool &inner,
const bool &outer)
const {
1104 BlockUniTensor *tmp =
new BlockUniTensor();
1105 this->set_meta(tmp, inner, outer);
1111 this->uten_type_id =
UTenType.Block;
1112 this->_is_tag =
true;
1121 void Init(
const std::vector<Bond> &bonds,
const std::vector<std::string> &in_labels = {},
1122 const cytnx_int64 &rowrank = -1,
const unsigned int &dtype =
Type.Double,
1123 const int &device =
Device.cpu,
const bool &is_diag =
false,
1124 const bool &no_alloc =
false,
const std::string &name =
"");
1126 void Init_by_Tensor(
const Tensor &in_tensor,
const bool &is_diag =
false,
1127 const cytnx_int64 &rowrank = -1,
const std::string &name =
"") {
1129 true,
"[ERROR][BlockUniTensor] cannot use Init_by_tensor() on a BlockUniTensor.%s",
"\n");
1132 std::vector<cytnx_uint64> shape()
const {
1133 std::vector<cytnx_uint64> out(this->_bonds.size());
1134 for (cytnx_uint64 i = 0; i < out.size(); i++) {
1135 out[i] = this->_bonds[i].dim();
1140 bool is_blockform()
const {
return true; }
1141 bool is_contiguous()
const {
1143 for (
int i = 0; i < this->_blocks.size(); i++) {
1144 out &= this->_blocks[i].is_contiguous();
1149 cytnx_uint64 Nblocks()
const {
return this->_blocks.size(); };
1151 void to_(
const int &device) {
1152 for (cytnx_uint64 i = 0; i < this->_blocks.size(); i++) {
1153 this->_blocks[i].to_(device);
1157 boost::intrusive_ptr<UniTensor_base> to(
const int &device) {
1158 if (this->device() == device) {
1161 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1167 boost::intrusive_ptr<UniTensor_base> clone()
const {
1168 BlockUniTensor *tmp = this->clone_meta(
true,
true);
1169 tmp->_blocks = vec_clone(this->_blocks);
1170 boost::intrusive_ptr<UniTensor_base> out(tmp);
1174 unsigned int dtype()
const {
1177 cytnx_error_msg(this->_blocks.size() == 0,
"[ERROR][internal] empty blocks for blockform.%s",
1180 return this->_blocks.size() < 1 ?
Type.Void : this->_blocks[0].dtype();
1182 int device()
const {
1185 cytnx_error_msg(this->_blocks.size() == 0,
"[ERROR][internal] empty blocks for blockform.%s",
1188 return this->_blocks.size() < 1 ? -404 : this->_blocks[0].device();
1190 std::string dtype_str()
const {
1193 cytnx_error_msg(this->_blocks.size() == 0,
"[ERROR][internal] empty blocks for blockform.%s",
1196 return this->_blocks.size() < 1 ?
"Void, no valid blocks" : this->_blocks[0].dtype_str();
1198 std::string device_str()
const {
1201 cytnx_error_msg(this->_blocks.size() == 0,
"[ERROR][internal] empty blocks for blockform.%s",
1204 return this->_blocks.size() < 1 ?
"None, no valid blocks" : this->_blocks[0].device_str();
1207 Tensor get_block(
const cytnx_uint64 &idx = 0)
const {
1208 cytnx_error_msg(idx >= this->_blocks.size(),
"[ERROR][BlockUniTensor] index out of range%s",
1210 return this->_blocks[idx].clone();
1214 Tensor get_block(
const std::vector<cytnx_int64> &indices,
const bool &force_return)
const {
1216 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1217 "Tensor rank (number of legs).%s",
1220 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1224 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1225 if (inds == this->_inner_to_outer_idx[i]) {
1233 return NullRefTensor;
1236 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1237 "force_return=false, so "
1238 "error throws. \n If you want to return an empty block without "
1239 "error when block is "
1240 "not avaliable, set force_return=True.%s",
1244 return this->_blocks[b].clone();
1248 const Tensor &get_block_(
const cytnx_uint64 &idx = 0)
const {
1249 cytnx_error_msg(idx >= this->_blocks.size(),
"[ERROR][BlockUniTensor] index out of range%s",
1251 return this->_blocks[idx];
1254 Tensor &get_block_(
const cytnx_uint64 &idx = 0) {
1255 cytnx_error_msg(idx >= this->_blocks.size(),
"[ERROR][BlockUniTensor] index out of range%s",
1257 return this->_blocks[idx];
1260 const Tensor &get_block_(
const std::vector<cytnx_int64> &indices,
1261 const bool &force_return)
const {
1263 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1264 "Tensor rank (number of legs).%s",
1267 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1271 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1272 if (inds == this->_inner_to_outer_idx[i]) {
1280 return this->NullRefTensor;
1283 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1284 "force_return=false, so "
1285 "error throws. \n If you want to return an empty block without "
1286 "error when block is "
1287 "not avaliable, set force_return=True.%s",
1291 return this->_blocks[b];
1295 Tensor &get_block_(
const std::vector<cytnx_int64> &indices,
const bool &force_return) {
1297 "[ERROR][get_block][BlockUniTensor] len(indices) must be the same as the "
1298 "Tensor rank (number of legs).%s",
1301 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1305 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1306 if (inds == this->_inner_to_outer_idx[i]) {
1314 return this->NullRefTensor;
1317 "[ERROR][get_block][BlockUniTensor] no avaliable block exists, "
1318 "force_return=false, so "
1319 "error throws. \n If you want to return an empty block without "
1320 "error when block is "
1321 "not avaliable, set force_return=True.%s",
1325 return this->_blocks[b];
1329 std::vector<Tensor> get_blocks()
const {
return vec_clone(this->_blocks); }
1330 const std::vector<Tensor> &get_blocks_(
const bool &)
const {
return this->_blocks; }
1331 std::vector<Tensor> &get_blocks_(
const bool &) {
return this->_blocks; }
1333 bool same_data(
const boost::intrusive_ptr<UniTensor_base> &rhs)
const {
1334 if (rhs->uten_type() !=
UTenType.Block)
return false;
1335 if (rhs->get_blocks_(1).size() != this->get_blocks_(1).size())
return false;
1337 for (
int i = 0; i < rhs->get_blocks_(1).size(); i++)
1338 if (this->get_blocks_(1)[i].same_data(rhs->get_blocks_(1)[i]) ==
false)
return false;
1343 void set_rowrank_(
const cytnx_uint64 &new_rowrank) {
1345 "[ERROR][BlockUniTensor] rowrank should be [>=0] and [<=UniTensor.rank].%s",
1347 if (this->is_diag()) {
1349 "[ERROR][BlockUniTensor] rowrank should be [==1] when is_diag =true!.%s",
1352 this->_rowrank = new_rowrank;
1353 this->_is_braket_form = this->_update_braket();
1356 boost::intrusive_ptr<UniTensor_base> set_rowrank(
const cytnx_uint64 &new_rowrank)
const {
1357 BlockUniTensor *tmp = this->clone_meta(
true,
true);
1358 tmp->_blocks = this->_blocks;
1359 tmp->set_rowrank_(new_rowrank);
1360 boost::intrusive_ptr<UniTensor_base> out(tmp);
1364 boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<cytnx_int64> &mapper,
1365 const cytnx_int64 &rowrank = -1);
1366 boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<std::string> &mapper,
1367 const cytnx_int64 &rowrank = -1);
1369 void permute_(
const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank = -1);
1370 void permute_(
const std::vector<std::string> &mapper,
const cytnx_int64 &rowrank = -1);
1372 boost::intrusive_ptr<UniTensor_base> contiguous_() {
1373 for (
unsigned int b = 0; b < this->_blocks.size(); b++) this->_blocks[b].contiguous_();
1374 return boost::intrusive_ptr<UniTensor_base>(
this);
1377 boost::intrusive_ptr<UniTensor_base> contiguous();
1379 void print_diagram(
const bool &bond_info =
false)
const;
1380 void print_blocks(
const bool &full_info =
true)
const;
1381 void print_block(
const cytnx_int64 &idx,
const bool &full_info =
true)
const;
1383 boost::intrusive_ptr<UniTensor_base> contract(
const boost::intrusive_ptr<UniTensor_base> &rhs,
1384 const bool &mv_elem_self =
false,
1385 const bool &mv_elem_rhs =
false);
1387 boost::intrusive_ptr<UniTensor_base> relabel(
const std::vector<std::string> &new_labels);
1388 boost::intrusive_ptr<UniTensor_base> relabels(
const std::vector<std::string> &new_labels);
1390 boost::intrusive_ptr<UniTensor_base> relabel(
const std::vector<std::string> &old_labels,
1391 const std::vector<std::string> &new_labels);
1392 boost::intrusive_ptr<UniTensor_base> relabels(
const std::vector<std::string> &old_labels,
1393 const std::vector<std::string> &new_labels);
1395 boost::intrusive_ptr<UniTensor_base> relabel(
const std::string &old_label,
1396 const std::string &new_label);
1397 boost::intrusive_ptr<UniTensor_base> relabel(
const cytnx_int64 &inx,
1398 const std::string &new_label);
1400 std::vector<Symmetry> syms()
const;
1402 void reshape_(
const std::vector<cytnx_int64> &new_shape,
const cytnx_uint64 &rowrank = 0) {
1403 cytnx_error_msg(
true,
"[ERROR] cannot reshape a UniTensor with symmetry.%s",
"\n");
1405 boost::intrusive_ptr<UniTensor_base> reshape(
const std::vector<cytnx_int64> &new_shape,
1406 const cytnx_uint64 &rowrank = 0) {
1407 cytnx_error_msg(
true,
"[ERROR] cannot reshape a UniTensor with symmetry.%s",
"\n");
1411 boost::intrusive_ptr<UniTensor_base> astype(
const unsigned int &dtype)
const {
1412 BlockUniTensor *tmp = this->clone_meta(
true,
true);
1413 tmp->_blocks.resize(this->_blocks.size());
1414 for (cytnx_int64 blk = 0; blk < this->_blocks.size(); blk++) {
1415 tmp->_blocks[blk] = this->_blocks[blk].astype(dtype);
1417 boost::intrusive_ptr<UniTensor_base> out(tmp);
1422 boost::intrusive_ptr<UniTensor_base> get(
const std::vector<Accessor> &accessors) {
1425 "[ERROR][BlockUniTensor][get] cannot use get on a UniTensor with "
1426 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
1432 void set(
const std::vector<Accessor> &accessors,
const Tensor &rhs) {
1435 "[ERROR][BlockUniTensor][get] cannot use get on a UniTensor with "
1436 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
1440 void put_block(
const Tensor &in,
const cytnx_uint64 &idx = 0) {
1442 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
1445 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
1450 cytnx_error_msg(idx >= this->_blocks.size(),
"[ERROR][BlockUniTensor] index out of range%s",
1453 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1454 "of block @ idx=%d\n",
1457 this->_blocks[idx] = in.
clone();
1459 void put_block_(
Tensor &in,
const cytnx_uint64 &idx = 0) {
1461 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
1464 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
1469 cytnx_error_msg(idx >= this->_blocks.size(),
"[ERROR][BlockUniTensor] index out of range%s",
1472 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1473 "of block @ idx=%d\n",
1476 this->_blocks[idx] = in;
1478 void put_block(
const Tensor &in,
const std::vector<cytnx_int64> &indices,
const bool &check) {
1480 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
1483 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
1489 "[ERROR][put_block][BlockUniTensor] len(indices) must be the same as the "
1490 "Tensor rank (number of legs).%s",
1493 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1497 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1498 if (inds == this->_inner_to_outer_idx[i]) {
1507 "[ERROR][put_block][BlockUniTensor] no avaliable block exists, "
1508 "check=true, so error throws. \n If you want without error when block "
1509 "is not avaliable, set check=false.%s",
1514 in.
shape() != this->_blocks[b].shape(),
1515 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1516 "of block @ idx=%d\n",
1519 this->_blocks[b] = in.
clone();
1522 void put_block_(
Tensor &in,
const std::vector<cytnx_int64> &indices,
const bool &check) {
1524 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
1527 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
1533 "[ERROR][put_block][BlockUniTensor] len(indices) must be the same as the "
1534 "Tensor rank (number of legs).%s",
1537 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1541 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1542 if (inds == this->_inner_to_outer_idx[i]) {
1551 "[ERROR][put_block][BlockUniTensor] no avaliable block exists, "
1552 "check=true, so error throws. \n If you want without error when block "
1553 "is not avaliable, set check=false.%s",
1558 in.
shape() != this->_blocks[b].shape(),
1559 "[ERROR][BlockUniTensor] the shape of input tensor does not match the shape "
1560 "of block @ idx=%d\n",
1562 this->_blocks[b] = in;
1570 boost::intrusive_ptr<UniTensor_base>
Conj() {
1571 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1577 for (
int i = 0; i < this->_blocks.size(); i++) {
1578 this->_blocks[i].Conj_();
1583 boost::intrusive_ptr<UniTensor_base> Transpose() {
1584 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1590 boost::intrusive_ptr<UniTensor_base> normalize() {
1591 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1596 boost::intrusive_ptr<UniTensor_base> Dagger() {
1597 boost::intrusive_ptr<UniTensor_base> out = this->
Conj();
1606 void Trace_(
const std::string &a,
const std::string &b);
1607 void Trace_(
const cytnx_int64 &a,
const cytnx_int64 &b);
1609 boost::intrusive_ptr<UniTensor_base>
Trace(
const std::string &a,
const std::string &b) {
1610 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1612 if (out->rank() == 0) {
1613 DenseUniTensor *tmp =
new DenseUniTensor();
1614 tmp->_block = ((BlockUniTensor *)out.get())->_blocks[0];
1615 out = boost::intrusive_ptr<UniTensor_base>(tmp);
1619 boost::intrusive_ptr<UniTensor_base>
Trace(
const cytnx_int64 &a,
const cytnx_int64 &b) {
1620 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1622 if (out->rank() == 0) {
1623 DenseUniTensor *tmp =
new DenseUniTensor();
1624 tmp->_block = ((BlockUniTensor *)out.get())->_blocks[0];
1625 out = boost::intrusive_ptr<UniTensor_base>(tmp);
1632 bool elem_exists(
const std::vector<cytnx_uint64> &locator)
const;
1634 const Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator)
const;
1635 const cytnx_complex128 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1636 const cytnx_complex128 &aux)
const;
1637 const cytnx_complex64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1638 const cytnx_complex64 &aux)
const;
1639 const cytnx_double &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1640 const cytnx_double &aux)
const;
1641 const cytnx_float &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1642 const cytnx_float &aux)
const;
1643 const cytnx_uint64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1644 const cytnx_uint64 &aux)
const;
1645 const cytnx_int64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1646 const cytnx_int64 &aux)
const;
1647 const cytnx_uint32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1648 const cytnx_uint32 &aux)
const;
1649 const cytnx_int32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1650 const cytnx_int32 &aux)
const;
1651 const cytnx_uint16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1652 const cytnx_uint16 &aux)
const;
1653 const cytnx_int16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1654 const cytnx_int16 &aux)
const;
1656 Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator);
1657 cytnx_complex128 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1658 const cytnx_complex128 &aux);
1659 cytnx_complex64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
1660 const cytnx_complex64 &aux);
1661 cytnx_double &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_double &aux);
1662 cytnx_float &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_float &aux);
1663 cytnx_uint64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint64 &aux);
1664 cytnx_int64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int64 &aux);
1665 cytnx_uint32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint32 &aux);
1666 cytnx_int32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int32 &aux);
1667 cytnx_uint16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint16 &aux);
1668 cytnx_int16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int16 &aux);
1670 void _save_dispatch(std::fstream &f)
const;
1671 void _load_dispatch(std::fstream &f);
1674 void truncate_(
const std::string &label,
const cytnx_uint64 &q_index);
1675 void truncate_(
const cytnx_int64 &bond_idx,
const cytnx_uint64 &q_index);
1677 void Add_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
1678 void Add_(
const Scalar &rhs) {
1681 "[ERROR] cannot perform elementwise arithmetic '+' between Scalar and BlockUniTensor.\n %s "
1683 "This operation would destroy the block structure. [Suggest] Avoid or use get/set_block(s) "
1684 "to do operation on blocks.");
1687 void Mul_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
1688 void Mul_(
const Scalar &rhs);
1690 void Sub_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
1691 void Sub_(
const Scalar &rhs) {
1694 "[ERROR] cannot perform elementwise arithmetic '-' between Scalar and BlockUniTensor.\n %s "
1696 "This operation would destroy the block structure. [Suggest] Avoid or use get/set_block(s) "
1697 "to do operation on blocks.");
1699 void lSub_(
const Scalar &lhs) {
1702 "[ERROR] cannot perform elementwise arithmetic '-' between Scalar and BlockUniTensor.\n %s "
1704 "This operation would destroy the block structure. [Suggest] Avoid or use get/set_block(s) "
1705 "to do operation on blocks.");
1708 void Div_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
1709 void Div_(
const Scalar &rhs);
1710 void lDiv_(
const Scalar &lhs) {
1713 "[ERROR] cannot perform elementwise arithmetic '/' between Scalar and BlockUniTensor.\n %s "
1715 "This operation would cause division by zero on non-block elements. [Suggest] Avoid or use "
1716 "get/set_block(s) to do operation on blocks.");
1718 void from_(
const boost::intrusive_ptr<UniTensor_base> &rhs,
const bool &force,
1719 const cytnx_double &tol);
1721 void group_basis_();
1723 void combineBond(
const std::vector<std::string> &indicators,
const bool &force =
false);
1724 void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &force =
false);
1725 void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &force,
1726 const bool &by_label);
1727 void combineBonds(
const std::vector<std::string> &indicators,
const bool &force =
false);
1729 const std::vector<cytnx_uint64> &get_qindices(
const cytnx_uint64 &bidx)
const {
1731 bidx >= this->Nblocks(),
1732 "[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
1734 return this->_inner_to_outer_idx[bidx];
1736 std::vector<cytnx_uint64> &get_qindices(
const cytnx_uint64 &bidx) {
1738 bidx >= this->Nblocks(),
1739 "[ERROR][BlockUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
1741 return this->_inner_to_outer_idx[bidx];
1744 const vec2d<cytnx_uint64> &get_itoi()
const {
return this->_inner_to_outer_idx; }
1745 vec2d<cytnx_uint64> &get_itoi() {
return this->_inner_to_outer_idx; }
1751 class BlockFermionicUniTensor :
public UniTensor_base {
1755 std::vector<std::vector<cytnx_uint64>>
1756 _inner_to_outer_idx;
1757 std::vector<Tensor> _blocks;
1760 std::vector<cytnx_bool>
1766 void _fx_get_total_fluxs(std::vector<cytnx_uint64> &loc,
const std::vector<Symmetry> &syms,
1767 std::vector<cytnx_int64> &total_qns) {
1769 memset(&total_qns[0], 0,
sizeof(cytnx_int64) * total_qns.size());
1771 for (cytnx_int32 i = 0; i < syms.size(); i++) {
1772 if (this->_bonds[0].type() == BD_BRA)
1773 total_qns[i] = syms[0].reverse_rule(this->_bonds[0]._impl->_qnums[loc[0]][i]);
1775 total_qns[i] = this->_bonds[0]._impl->_qnums[loc[0]][i];
1777 for (
auto j = 1; j < loc.size(); j++) {
1778 if (this->_bonds[j].type() == BD_BRA)
1779 total_qns[i] = syms[i].combine_rule(
1780 total_qns[i], syms[i].reverse_rule(this->_bonds[j]._impl->_qnums[loc[j]][i]));
1783 syms[i].combine_rule(total_qns[i], this->_bonds[j]._impl->_qnums[loc[j]][i]);
1789 void _fx_locate_elem(cytnx_int64 &bidx, std::vector<cytnx_uint64> &loc_in_T,
1790 const std::vector<cytnx_uint64> &locator)
const;
1793 void _fx_group_duplicates(
const std::vector<cytnx_uint64> &dup_bond_idxs,
1794 const std::vector<std::vector<cytnx_uint64>> &idx_mappers);
1796 void set_meta(BlockFermionicUniTensor *tmp,
const bool &inner,
const bool &outer)
const {
1800 tmp->_bonds = vec_clone(this->_bonds);
1801 tmp->_labels = this->_labels;
1802 tmp->_is_braket_form = this->_is_braket_form;
1803 tmp->_rowrank = this->_rowrank;
1804 tmp->_name = this->_name;
1806 tmp->_signflip = this->_signflip;
1809 tmp->_is_diag = this->_is_diag;
1813 tmp->_inner_to_outer_idx = this->_inner_to_outer_idx;
1817 BlockFermionicUniTensor *clone_meta(
const bool &inner,
const bool &outer)
const {
1819 BlockFermionicUniTensor *tmp =
new BlockFermionicUniTensor();
1820 this->set_meta(tmp, inner, outer);
1825 BlockFermionicUniTensor() {
1827 this->uten_type_id =
UTenType.BlockFermionic;
1828 this->_is_tag =
true;
1831 void Init(
const std::vector<Bond> &bonds,
const std::vector<std::string> &in_labels = {},
1832 const cytnx_int64 &rowrank = -1,
const unsigned int &dtype =
Type.Double,
1833 const int &device =
Device.cpu,
const bool &is_diag =
false,
1834 const bool &no_alloc =
false,
const std::string &name =
"");
1836 void Init_by_Tensor(
const Tensor &in_tensor,
const bool &is_diag =
false,
1837 const cytnx_int64 &rowrank = -1,
const std::string &name =
"") {
1839 "[ERROR][BlockFermionicUniTensor] cannot use Init_by_tensor() on a "
1840 "BlockFermionicUniTensor.%s",
1844 std::vector<cytnx_uint64> shape()
const {
1846 std::vector<cytnx_uint64> out(this->_bonds.size());
1847 for (cytnx_uint64 i = 0; i < out.size(); i++) {
1848 out[i] = this->_bonds[i].dim();
1853 bool is_blockform()
const {
1858 bool is_contiguous()
const {
1861 for (
int i = 0; i < this->_blocks.size(); i++) {
1862 out &= this->_blocks[i].is_contiguous();
1867 cytnx_uint64 Nblocks()
const {
1869 return this->_blocks.size();
1872 std::vector<bool> signflip()
const override {
return this->_signflip; };
1873 std::vector<bool> &signflip_()
override {
return this->_signflip; };
1875 void to_(
const int &device) {
1877 for (cytnx_uint64 i = 0; i < this->_blocks.size(); i++) {
1878 this->_blocks[i].to_(device);
1882 boost::intrusive_ptr<UniTensor_base> to(
const int &device) {
1884 if (this->device() == device) {
1887 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1893 boost::intrusive_ptr<UniTensor_base> clone()
const {
1896 BlockFermionicUniTensor *tmp = this->clone_meta(
true,
true);
1897 tmp->_blocks = vec_clone(this->_blocks);
1898 boost::intrusive_ptr<UniTensor_base> out(tmp);
1902 unsigned int dtype()
const {
1905 cytnx_error_msg(this->_blocks.size() == 0,
"[ERROR][internal] empty blocks for blockform.%s",
1908 return this->_blocks.size() < 1 ?
Type.Void : this->_blocks[0].dtype();
1910 int device()
const {
1913 cytnx_error_msg(this->_blocks.size() == 0,
"[ERROR][internal] empty blocks for blockform.%s",
1916 return this->_blocks.size() < 1 ? -404 : this->_blocks[0].device();
1918 std::string dtype_str()
const {
1921 cytnx_error_msg(this->_blocks.size() == 0,
"[ERROR][internal] empty blocks for blockform.%s",
1924 return this->_blocks.size() < 1 ?
"Void, no valid blocks" : this->_blocks[0].dtype_str();
1926 std::string device_str()
const {
1929 cytnx_error_msg(this->_blocks.size() == 0,
"[ERROR][internal] empty blocks for blockform.%s",
1932 return this->_blocks.size() < 1 ?
"None, no valid blocks" : this->_blocks[0].device_str();
1935 Tensor get_block(
const cytnx_uint64 &idx = 0)
const {
1938 "[ERROR][BlockFermionicUniTensor] index out of range%s",
"\n");
1939 return this->_blocks[idx].clone();
1943 Tensor get_block(
const std::vector<cytnx_int64> &indices,
const bool &force_return)
const {
1946 indices.size() != this->rank(),
1947 "[ERROR][get_block][BlockFermionicUniTensor] len(indices) must be the same as the "
1948 "Tensor rank (number of legs).%s",
1951 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
1955 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
1956 if (inds == this->_inner_to_outer_idx[i]) {
1964 return NullRefTensor;
1967 "[ERROR][get_block][BlockFermionicUniTensor] no avaliable block exists, "
1968 "force_return=false, so "
1969 "error throws. \n If you want to return an empty block without "
1970 "error when block is "
1971 "not avaliable, set force_return=True.%s",
1975 return this->_blocks[b].clone();
1979 const Tensor &get_block_(
const cytnx_uint64 &idx = 0)
const {
1982 "[ERROR][BlockFermionicUniTensor] index out of range%s",
"\n");
1983 return this->_blocks[idx];
1986 Tensor &get_block_(
const cytnx_uint64 &idx = 0) {
1989 "[ERROR][BlockFermionicUniTensor] index out of range%s",
"\n");
1990 return this->_blocks[idx];
1993 const Tensor &get_block_(
const std::vector<cytnx_int64> &indices,
1994 const bool &force_return)
const {
1997 indices.size() != this->rank(),
1998 "[ERROR][get_block][BlockFermionicUniTensor] len(indices) must be the same as the "
1999 "Tensor rank (number of legs).%s",
2002 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
2006 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
2007 if (inds == this->_inner_to_outer_idx[i]) {
2015 return this->NullRefTensor;
2018 "[ERROR][get_block][BlockFermionicUniTensor] no avaliable block exists, "
2019 "force_return=false, so "
2020 "error throws. \n If you want to return an empty block without "
2021 "error when block is "
2022 "not avaliable, set force_return=True.%s",
2026 return this->_blocks[b];
2030 Tensor &get_block_(
const std::vector<cytnx_int64> &indices,
const bool &force_return) {
2033 indices.size() != this->rank(),
2034 "[ERROR][get_block][BlockFermionicUniTensor] len(indices) must be the same as the "
2035 "Tensor rank (number of legs).%s",
2038 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
2042 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
2043 if (inds == this->_inner_to_outer_idx[i]) {
2051 return this->NullRefTensor;
2054 "[ERROR][get_block][BlockFermionicUniTensor] no avaliable block exists, "
2055 "force_return=false, so "
2056 "error throws. \n If you want to return an empty block without "
2057 "error when block is "
2058 "not avaliable, set force_return=True.%s",
2062 return this->_blocks[b];
2066 std::vector<Tensor> get_blocks()
const {
2068 return vec_clone(this->_blocks);
2070 const std::vector<Tensor> &get_blocks_(
const bool &)
const {
2072 return this->_blocks;
2074 std::vector<Tensor> &get_blocks_(
const bool &) {
2076 return this->_blocks;
2079 bool same_data(
const boost::intrusive_ptr<UniTensor_base> &rhs)
const {
2081 if (rhs->uten_type() !=
UTenType.BlockFermionic)
return false;
2082 if (rhs->get_blocks_(1).size() != this->get_blocks_(1).size())
return false;
2084 for (
int i = 0; i < rhs->get_blocks_(1).size(); i++)
2085 if (this->get_blocks_(1)[i].same_data(rhs->get_blocks_(1)[i]) ==
false)
return false;
2090 void set_rowrank_(
const cytnx_uint64 &new_rowrank) {
2093 new_rowrank > this->rank(),
2094 "[ERROR][BlockFermionicUniTensor] rowrank should be [>=0] and [<=UniTensor.rank].%s",
"\n");
2095 if (this->is_diag()) {
2098 "[ERROR][BlockFermionicUniTensor] rowrank should be [==1] when is_diag =true!.%s",
"\n");
2100 this->_rowrank = new_rowrank;
2101 this->_is_braket_form = this->_update_braket();
2104 boost::intrusive_ptr<UniTensor_base> set_rowrank(
const cytnx_uint64 &new_rowrank)
const {
2107 BlockFermionicUniTensor *tmp = this->clone_meta(
true,
true);
2108 tmp->_blocks = this->_blocks;
2109 tmp->set_rowrank_(new_rowrank);
2110 boost::intrusive_ptr<UniTensor_base> out(tmp);
2114 boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<cytnx_int64> &mapper,
2115 const cytnx_int64 &rowrank = -1);
2116 boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<std::string> &mapper,
2117 const cytnx_int64 &rowrank = -1);
2119 void permute_(
const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank = -1);
2120 void permute_(
const std::vector<std::string> &mapper,
const cytnx_int64 &rowrank = -1);
2122 boost::intrusive_ptr<UniTensor_base> permute_nosignflip(
const std::vector<cytnx_int64> &mapper,
2123 const cytnx_int64 &rowrank = -1);
2124 boost::intrusive_ptr<UniTensor_base> permute_nosignflip(
const std::vector<std::string> &mapper,
2125 const cytnx_int64 &rowrank = -1);
2126 void permute_nosignflip_(
const std::vector<cytnx_int64> &mapper,
2127 const cytnx_int64 &rowrank = -1);
2128 void permute_nosignflip_(
const std::vector<std::string> &mapper,
2129 const cytnx_int64 &rowrank = -1);
2132 std::vector<bool> _swapsigns_(
const std::vector<cytnx_int64> &mapper)
const;
2133 std::vector<bool> _lhssigns_(
const std::vector<cytnx_int64> &mapper,
2134 const cytnx_int64 contrno)
const;
2135 std::vector<bool> _swapsigns_(
const std::vector<cytnx_uint64> &mapper)
const;
2136 std::vector<bool> _lhssigns_(
const std::vector<cytnx_uint64> &mapper,
2137 const cytnx_uint64 contrno)
const;
2139 boost::intrusive_ptr<UniTensor_base> contiguous_() {
2141 for (
unsigned int b = 0; b < this->_blocks.size(); b++) this->_blocks[b].contiguous_();
2142 return boost::intrusive_ptr<UniTensor_base>(
this);
2145 boost::intrusive_ptr<UniTensor_base> contiguous();
2147 void print_diagram(
const bool &bond_info =
false)
const;
2148 void print_blocks(
const bool &full_info =
true)
const;
2149 void print_block(
const cytnx_int64 &idx,
const bool &full_info =
true)
const;
2151 boost::intrusive_ptr<UniTensor_base> contract(
const boost::intrusive_ptr<UniTensor_base> &rhs,
2152 const bool &mv_elem_self =
false,
2153 const bool &mv_elem_rhs =
false);
2155 boost::intrusive_ptr<UniTensor_base> relabel(
const std::vector<std::string> &new_labels);
2156 boost::intrusive_ptr<UniTensor_base> relabels(
const std::vector<std::string> &new_labels);
2158 boost::intrusive_ptr<UniTensor_base> relabel(
const std::vector<std::string> &old_labels,
2159 const std::vector<std::string> &new_labels);
2160 boost::intrusive_ptr<UniTensor_base> relabels(
const std::vector<std::string> &old_labels,
2161 const std::vector<std::string> &new_labels);
2163 boost::intrusive_ptr<UniTensor_base> relabel(
const std::string &old_label,
2164 const std::string &new_label);
2165 boost::intrusive_ptr<UniTensor_base> relabel(
const cytnx_int64 &inx,
2166 const std::string &new_label);
2167 std::vector<Symmetry> syms()
const;
2169 void reshape_(
const std::vector<cytnx_int64> &new_shape,
const cytnx_uint64 &rowrank = 0) {
2170 cytnx_error_msg(
true,
"[ERROR] cannot reshape a UniTensor with symmetry.%s",
"\n");
2172 boost::intrusive_ptr<UniTensor_base> reshape(
const std::vector<cytnx_int64> &new_shape,
2173 const cytnx_uint64 &rowrank = 0) {
2174 cytnx_error_msg(
true,
"[ERROR] cannot reshape a UniTensor with symmetry.%s",
"\n");
2178 boost::intrusive_ptr<UniTensor_base> astype(
const unsigned int &dtype)
const {
2180 BlockFermionicUniTensor *tmp = this->clone_meta(
true,
true);
2181 tmp->_blocks.resize(this->_blocks.size());
2182 for (cytnx_int64 blk = 0; blk < this->_blocks.size(); blk++) {
2183 tmp->_blocks[blk] = this->_blocks[blk].astype(dtype);
2185 boost::intrusive_ptr<UniTensor_base> out(tmp);
2190 boost::intrusive_ptr<UniTensor_base> get(
const std::vector<Accessor> &accessors) {
2193 "[ERROR][BlockFermionicUniTensor][get] cannot use get on a UniTensor with "
2194 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
2200 void set(
const std::vector<Accessor> &accessors,
const Tensor &rhs) {
2204 "[ERROR][BlockFermionicUniTensor][get] cannot use get on a UniTensor with "
2205 "Symmetry.\n suggestion: try get_block/get_block_/get_blocks/get_blocks_ first.%s",
2209 void put_block(
const Tensor &in,
const cytnx_uint64 &idx = 0) {
2212 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
2215 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
2221 "[ERROR][BlockFermionicUniTensor] index out of range%s",
"\n");
2223 in.
shape() != this->_blocks[idx].shape(),
2224 "[ERROR][BlockFermionicUniTensor] the shape of input tensor does not match the shape "
2225 "of block @ idx=%d\n",
2228 this->_blocks[idx] = in.
clone();
2230 void put_block_(
Tensor &in,
const cytnx_uint64 &idx = 0) {
2233 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
2236 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
2242 "[ERROR][BlockFermionicUniTensor] index out of range%s",
"\n");
2244 in.
shape() != this->_blocks[idx].shape(),
2245 "[ERROR][BlockFermionicUniTensor] the shape of input tensor does not match the shape "
2246 "of block @ idx=%d\n",
2249 this->_blocks[idx] = in;
2251 void put_block(
const Tensor &in,
const std::vector<cytnx_int64> &indices,
const bool &check) {
2254 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
2257 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
2263 indices.size() != this->rank(),
2264 "[ERROR][put_block][BlockFermionicUniTensor] len(indices) must be the same as the "
2265 "Tensor rank (number of legs).%s",
2268 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
2272 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
2273 if (inds == this->_inner_to_outer_idx[i]) {
2282 "[ERROR][put_block][BlockFermionicUniTensor] no avaliable block exists, "
2283 "check=true, so error throws. \n If you want without error when block "
2284 "is not avaliable, set check=false.%s",
2289 in.
shape() != this->_blocks[b].shape(),
2290 "[ERROR][BlockFermionicUniTensor] the shape of input tensor does not match the shape "
2291 "of block @ idx=%d\n",
2294 this->_blocks[b] = in.
clone();
2297 void put_block_(
Tensor &in,
const std::vector<cytnx_int64> &indices,
const bool &check) {
2300 "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not match.%s",
2303 "[ERROR][DenseUniTensor][put_block] The input tensor device does not "
2309 indices.size() != this->rank(),
2310 "[ERROR][put_block][BlockFermionicUniTensor] len(indices) must be the same as the "
2311 "Tensor rank (number of legs).%s",
2314 std::vector<cytnx_uint64> inds(indices.begin(), indices.end());
2318 for (cytnx_uint64 i = 0; i < this->_inner_to_outer_idx.size(); i++) {
2319 if (inds == this->_inner_to_outer_idx[i]) {
2328 "[ERROR][put_block][BlockFermionicUniTensor] no avaliable block exists, "
2329 "check=true, so error throws. \n If you want without error when block "
2330 "is not avaliable, set check=false.%s",
2335 in.
shape() != this->_blocks[b].shape(),
2336 "[ERROR][BlockFermionicUniTensor] the shape of input tensor does not match the shape "
2337 "of block @ idx=%d\n",
2339 this->_blocks[b] = in;
2347 boost::intrusive_ptr<UniTensor_base>
Conj() {
2349 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2356 for (
int i = 0; i < this->_blocks.size(); i++) {
2357 this->_blocks[i].Conj_();
2364 boost::intrusive_ptr<UniTensor_base> Transpose() {
2366 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2372 boost::intrusive_ptr<UniTensor_base> normalize() {
2374 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2379 boost::intrusive_ptr<UniTensor_base> Dagger() {
2381 boost::intrusive_ptr<UniTensor_base> out = this->
Conj();
2391 void Trace_(
const std::string &a,
const std::string &b);
2392 void Trace_(
const cytnx_int64 &a,
const cytnx_int64 &b);
2394 boost::intrusive_ptr<UniTensor_base>
Trace(
const std::string &a,
const std::string &b) {
2396 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2398 if (out->rank() == 0) {
2399 DenseUniTensor *tmp =
new DenseUniTensor();
2400 tmp->_block = ((BlockFermionicUniTensor *)out.get())->_blocks[0];
2401 out = boost::intrusive_ptr<UniTensor_base>(tmp);
2405 boost::intrusive_ptr<UniTensor_base>
Trace(
const cytnx_int64 &a,
const cytnx_int64 &b) {
2407 boost::intrusive_ptr<UniTensor_base> out = this->clone();
2409 if (out->rank() == 0) {
2410 DenseUniTensor *tmp =
new DenseUniTensor();
2411 tmp->_block = ((BlockFermionicUniTensor *)out.get())->_blocks[0];
2412 out = boost::intrusive_ptr<UniTensor_base>(tmp);
2419 bool elem_exists(
const std::vector<cytnx_uint64> &locator)
const;
2421 const Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator)
const;
2422 const cytnx_complex128 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2423 const cytnx_complex128 &aux)
const;
2424 const cytnx_complex64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2425 const cytnx_complex64 &aux)
const;
2426 const cytnx_double &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2427 const cytnx_double &aux)
const;
2428 const cytnx_float &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2429 const cytnx_float &aux)
const;
2430 const cytnx_uint64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2431 const cytnx_uint64 &aux)
const;
2432 const cytnx_int64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2433 const cytnx_int64 &aux)
const;
2434 const cytnx_uint32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2435 const cytnx_uint32 &aux)
const;
2436 const cytnx_int32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2437 const cytnx_int32 &aux)
const;
2438 const cytnx_uint16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2439 const cytnx_uint16 &aux)
const;
2440 const cytnx_int16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2441 const cytnx_int16 &aux)
const;
2443 Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator);
2444 cytnx_complex128 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2445 const cytnx_complex128 &aux);
2446 cytnx_complex64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
2447 const cytnx_complex64 &aux);
2448 cytnx_double &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_double &aux);
2449 cytnx_float &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_float &aux);
2450 cytnx_uint64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint64 &aux);
2451 cytnx_int64 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int64 &aux);
2452 cytnx_uint32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint32 &aux);
2453 cytnx_int32 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int32 &aux);
2454 cytnx_uint16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_uint16 &aux);
2455 cytnx_int16 &at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int16 &aux);
2457 void _save_dispatch(std::fstream &f)
const;
2458 void _load_dispatch(std::fstream &f);
2461 void truncate_(
const std::string &label,
const cytnx_uint64 &q_index);
2462 void truncate_(
const cytnx_int64 &bond_idx,
const cytnx_uint64 &q_index);
2464 void Add_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
2465 void Add_(
const Scalar &rhs) {
2467 "[ERROR] cannot perform elementwise arithmetic '+' between Scalar and "
2468 "BlockFermionicUniTensor.\n %s "
2470 "This operation would destroy the block structure. [Suggest] Avoid or use "
2471 "get/set_block(s) to do operation on blocks.");
2474 void Mul_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
2475 void Mul_(
const Scalar &rhs);
2477 void Sub_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
2478 void Sub_(
const Scalar &rhs) {
2480 "[ERROR] cannot perform elementwise arithmetic '-' between Scalar and "
2481 "BlockFermionicUniTensor.\n %s "
2483 "This operation would destroy the block structure. [Suggest] Avoid or use "
2484 "get/set_block(s) to do operation on blocks.");
2486 void lSub_(
const Scalar &lhs) {
2488 "[ERROR] cannot perform elementwise arithmetic '-' between Scalar and "
2489 "BlockFermionicUniTensor.\n %s "
2491 "This operation would destroy the block structure. [Suggest] Avoid or use "
2492 "get/set_block(s) to do operation on blocks.");
2495 void Div_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
2496 void Div_(
const Scalar &rhs);
2497 void lDiv_(
const Scalar &lhs) {
2499 "[ERROR] cannot perform elementwise arithmetic '/' between Scalar and "
2500 "BlockFermionicUniTensor.\n %s "
2502 "This operation would cause division by zero on non-block elements. "
2503 "[Suggest] Avoid or use get/set_block(s) to do operation on blocks.");
2505 void from_(
const boost::intrusive_ptr<UniTensor_base> &rhs,
const bool &force);
2507 void group_basis_();
2509 void combineBond(
const std::vector<std::string> &indicators,
const bool &force =
false);
2510 void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &force =
false);
2511 void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &force,
2512 const bool &by_label);
2513 void combineBonds(
const std::vector<std::string> &indicators,
const bool &force =
false);
2515 const std::vector<cytnx_uint64> &get_qindices(
const cytnx_uint64 &bidx)
const {
2518 bidx >= this->Nblocks(),
2519 "[ERROR][BlockFermionicUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
2521 return this->_inner_to_outer_idx[bidx];
2523 std::vector<cytnx_uint64> &get_qindices(
const cytnx_uint64 &bidx) {
2526 bidx >= this->Nblocks(),
2527 "[ERROR][BlockFermionicUniTensor] bidx out of bound! only %d blocks in current UTen.\n",
2529 return this->_inner_to_outer_idx[bidx];
2532 const vec2d<cytnx_uint64> &get_itoi()
const {
2534 return this->_inner_to_outer_idx;
2536 vec2d<cytnx_uint64> &get_itoi() {
2538 return this->_inner_to_outer_idx;
2541 void beauty_print_block(std::ostream &os,
const cytnx_uint64 &Nin,
const cytnx_uint64 &Nout,
2542 const std::vector<cytnx_uint64> &qn_indices,
2543 const std::vector<Bond> &bonds,
const Tensor &block)
const;
2550 class UniTensor_options {
2557 UniTensor_options() {
2558 this->_is_diag =
false;
2559 this->_dtype =
Type.Double;
2560 this->_device =
Device.cpu;
2561 this->_rowrank = -1;
2564 UniTensor_options(
const UniTensor_options &rhs) {
2565 this->_is_diag = rhs._is_diag;
2566 this->_dtype = rhs._dtype;
2567 this->_device = rhs._device;
2568 this->_rowrank = rhs._rowrank;
2571 UniTensor_options &operator=(
const UniTensor_options &rhs) {
2572 this->_is_diag = rhs._is_diag;
2573 this->_dtype = rhs._dtype;
2574 this->_device = rhs._device;
2575 this->_rowrank = rhs._rowrank;
2579 UniTensor_options &is_diag(
const bool &in) {
2580 this->_is_diag = in;
2583 UniTensor_options &dtype(
const int &in) {
2587 UniTensor_options &device(
const int &in) {
2591 UniTensor_options &rowrank(
const int &in) {
2592 this->_rowrank = in;
2602 boost::intrusive_ptr<UniTensor_base>
_impl;
2606 this->_impl =
rhs._impl;
2640 const std::vector<std::string> &
in_labels = {},
const std::string &
name =
"")
2662 const std::vector<std::string> &
in_labels = {},
const std::string &
name =
"") {
2692 const std::string &
name =
"")
2697 "[DEBUG] message: entry for UniTensor(const std::vector<Bond> &bonds, const "
2698 "std::vector<std::string> &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned "
2700 "&dtype=Type.Double, const int &device = Device.cpu, const bool &is_diag=false)%s",
2743 const std::string &
name =
"") {
2759 "[ERROR] When initializing a UniTensor with symmetries, all Bonds must "
2760 "be in the same format!%s",
2771 is_sym,
"[ERROR] cannot have bonds with mixing of symmetry and non-symmetry.%s",
"\n");
2777 cytnx_warning_msg(
true,
"[DEBUG] message: entry dispatch: UniTensor: symmetric%s",
"\n");
2785 "[ERROR] internal error! [legacy Sparse entry] the Bond is symmetry but "
2786 "the version is not properly determined!%s",
2790 "[ERROR] internal error! the Bond is symmetry but the version is not "
2791 "properly determined!%s",
2909 std::vector<std::string>
vs(
new_lbls.size());
2911 [](
char *
x) -> std::string { return std::string(x); });
2913 this->_impl->set_labels(
vs);
2937 "[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use "
2938 "get_block()/get_blocks() first.%s",
2942 return tmp->_block.item<
T>();
2947 "[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use "
2948 "get_block()/get_blocks() first.%s",
2952 return tmp->_block.item();
2977 unsigned int dtype()
const {
return this->_impl->dtype(); }
2992 int device()
const {
return this->_impl->device(); }
2998 std::string
name()
const {
return this->_impl->name(); }
3005 std::string
dtype_str()
const {
return this->_impl->dtype_str(); }
3012 std::string
device_str()
const {
return this->_impl->device_str(); }
3032 bool is_diag()
const {
return this->_impl->is_diag(); }
3039 bool is_tag()
const {
return this->_impl->is_tag(); }
3046 std::vector<Symmetry>
syms()
const {
return this->_impl->syms(); }
3060 const std::vector<std::string> &
labels()
const {
return this->_impl->labels(); }
3073 const std::vector<Bond> &
bonds()
const {
return this->_impl->bonds(); }
3078 std::vector<Bond> &
bonds() {
return this->_impl->bonds(); }
3093 std::vector<cytnx_uint64>
shape()
const {
return this->_impl->shape(); }
3101 std::vector<bool>
signflip()
const {
return this->_impl->signflip(); }
3111 std::vector<bool> &
signflip_() {
return this->_impl->signflip_(); }
3174 "UniTensor &relabel_(const std::vector<std::string> &old_labels, const "
3175 "std::vector<std::string> &new_labels) "
3205 "UniTensor relabel(const std::vector<std::string> &new_labels) const "
3219 std::vector<std::string>
vs(
new_lbls.size());
3221 [](
char *
x) -> std::string { return std::string(x); });
3234 "UniTensor relabel(const std::initializer_list<char *> &new_labels) const "
3238 std::vector<std::string>
vs(
new_lbls.size());
3240 [](
char *
x) -> std::string { return std::string(x); });
3251 std::vector<std::string>
vs(
new_lbls.size());
3253 [](
char *
x) -> std::string { return std::string(x); });
3255 this->_impl->relabel_(
vs);
3265 "UniTensor &relabel_(const std::initializer_list<char *> &new_labels) "
3269 std::vector<std::string>
vs(
new_lbls.size());
3271 [](
char *
x) -> std::string { return std::string(x); });
3273 this->_impl->relabels_(
vs);
3285 const std::vector<std::string> &
new_labels)
const {
3297 "UniTensor relabel(const std::vector<std::string> &old_labels, const "
3298 "std::vector<std::string> &new_labels) const "
3301 const std::vector<std::string> &
new_labels)
const {
3323 const std::vector<std::string> &
new_labels) {
3334 "UniTensor &relabel_(const std::vector<std::string> &old_labels, const "
3335 "std::vector<std::string> &new_labels) "
3338 const std::vector<std::string> &
new_labels) {
3348 const std::initializer_list<char *> &
new_labels)
const {
3350 std::vector<std::string>
vs(
new_lbls.size());
3352 [](
char *
x) -> std::string { return std::string(x); });
3357 [](
char *
x) -> std::string { return std::string(x); });
3369 "UniTensor relabel(const std::initializer_list<char *> &old_labels, const "
3370 "std::initializer_list<char *> &new_labels) const "
3373 const std::initializer_list<char *> &
new_labels)
const {
3375 std::vector<std::string>
vs(
new_lbls.size());
3377 [](
char *
x) -> std::string { return std::string(x); });
3382 [](
char *
x) -> std::string { return std::string(x); });
3392 const std::initializer_list<char *> &
new_labels) {
3394 std::vector<std::string>
vs(
new_lbls.size());
3396 [](
char *
x) -> std::string { return std::string(x); });
3401 [](
char *
x) -> std::string { return std::string(x); });
3413 "UniTensor &relabel_(const std::initializer_list<char *> &old_labels, const "
3414 "std::initializer_list<char *> &new_labels) "
3417 const std::initializer_list<char *> &
new_labels) {
3419 std::vector<std::string>
vs(
new_lbls.size());
3421 [](
char *
x) -> std::string { return std::string(x); });
3426 [](
char *
x) -> std::string { return std::string(x); });
3505 if (this->
dtype() == dtype) {
3547 std::vector<std::string>
vs(
mprs.size());
3549 [](
char *
x) -> std::string { return std::string(x); });
3565 "UniTensor &permute_(const std::vector<std::string> &mapper, const cytnx_int64 &rowrank) "
3624 std::vector<std::string>
vs(
mprs.size());
3626 [](
char *
x) -> std::string { return std::string(x); });
3738 return this->_impl->at_for_sparse(
locator,
aux);
3740 }
else if (this->
uten_type() == UTenType.Sparse) {
3741 if (this->_impl->elem_exists(
locator)) {
3743 return this->_impl->at_for_sparse(
locator,
aux);
3745 cytnx_error_msg(
true,
"[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
3764 return this->_impl->at_for_sparse(
locator,
aux);
3766 }
else if (this->
uten_type() == UTenType.Sparse) {
3767 if (this->_impl->elem_exists(
locator)) {
3769 return this->_impl->at_for_sparse(
locator,
aux);
3771 cytnx_error_msg(
true,
"[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
3781 const std::vector<cytnx_uint64> &
locator)
const {
3784 "[ERROR][at] length of list should be the same for label and locator.%s",
3788 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s",
"\n");
3791 for (
int i = 0;
i <
labels.size();
i++) {
3792 auto res = std::find(this->_impl->_labels.begin(),
this->_impl->_labels.end(),
labels[
i]);
3794 "[ERROR] label:%s does not exist in current UniTensor.\n",
3796 new_loc = std::distance(this->_impl->_labels.begin(),
res);
3799 return this->
at<T>(new_locator);
3805 "[ERROR][at] length of list should be the same for label and locator.%s",
3809 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s",
"\n");
3812 for (
int i = 0;
i <
labels.size();
i++) {
3813 auto res = std::find(this->_impl->_labels.begin(),
this->_impl->_labels.end(),
labels[
i]);
3815 "[ERROR] label:%s does not exist in current UniTensor.\n",
3817 new_loc = std::distance(this->_impl->_labels.begin(),
res);
3820 return this->
at<T>(new_locator);
3827 const Scalar::Sproxy
at(
const std::vector<cytnx_uint64> &
locator)
const {
3829 return this->_impl->at_for_sparse(
locator);
3830 }
else if (this->
uten_type() == UTenType.Sparse) {
3831 if (this->_impl->elem_exists(
locator)) {
3832 return this->_impl->at_for_sparse(
locator);
3834 cytnx_error_msg(
true,
"[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
3846 Scalar::Sproxy
at(
const std::vector<cytnx_uint64> &
locator) {
3848 return this->_impl->at_for_sparse(
locator);
3849 }
else if (this->
uten_type() == UTenType.Sparse) {
3850 if (this->_impl->elem_exists(
locator)) {
3851 return this->_impl->at_for_sparse(
locator);
3853 cytnx_error_msg(
true,
"[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
3861 Scalar::Sproxy
at(
const std::vector<std::string> &
labels,
3862 const std::vector<cytnx_uint64> &
locator) {
3865 "[ERROR][at] length of list should be the same for label and locator.%s",
3869 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s",
"\n");
3872 for (
int i = 0;
i <
labels.size();
i++) {
3873 auto res = std::find(this->_impl->_labels.begin(),
this->_impl->_labels.end(),
labels[
i]);
3875 "[ERROR] label:%s does not exist in current UniTensor.\n",
3877 new_loc = std::distance(this->_impl->_labels.begin(),
res);
3880 return this->
at(new_locator);
3883 const Scalar::Sproxy
at(
const std::vector<std::string> &
labels,
3884 const std::vector<cytnx_uint64> &
locator)
const {
3887 "[ERROR][at] length of list should be the same for label and locator.%s",
3891 "[ERROR][at] length of lists must be the same as UniTensor.rank (# of legs)%s",
"\n");
3894 for (
int i = 0;
i <
labels.size();
i++) {
3895 auto res = std::find(this->_impl->_labels.begin(),
this->_impl->_labels.end(),
labels[
i]);
3897 "[ERROR] label:%s does not exist in current UniTensor.\n",
3899 new_loc = std::distance(this->_impl->_labels.begin(),
res);
3902 return this->
at(new_locator);
3923 return this->_impl->get_block(
qidx,
force);
3927 const bool &
force =
false)
const {
3930 "[ERROR][get_block] length of lists must be the same for both lables and qnidices%s",
"\n");
3932 "[ERROR][get_block] length of lists must be the rank (# of legs)%s",
"\n");
3934 std::vector<cytnx_int64>
loc_id(this->
rank());
3939 for (
int i = 0;
i <
labels.size();
i++) {
3940 auto res = std::find(this->_impl->_labels.begin(),
this->_impl->_labels.end(),
labels[
i]);
3942 "[ERROR][get_block] label:%s does not exists in current Tensor.\n",
3944 new_loc = std::distance(this->_impl->_labels.begin(),
res);
3958 const bool &
force =
false)
const {
3959 std::vector<cytnx_int64>
tmp =
qnum;
3973 const bool &
force =
false)
const {
3984 return this->_impl->get_block_(
idx);
4002 return this->_impl->get_block_(
qidx,
force);
4022 const bool &
force =
false) {
4025 "[ERROR][get_block] length of lists must be the same for both lables and qnidices%s",
"\n");
4027 "[ERROR][get_block] length of lists must be the rank (# of legs)%s",
"\n");
4029 std::vector<cytnx_int64>
loc_id(this->
rank());
4034 for (
int i = 0;
i <
labels.size();
i++) {
4035 auto res = std::find(this->_impl->_labels.begin(),
this->_impl->_labels.end(),
labels[
i]);
4037 "[ERROR][get_block] label:%s does not exists in current Tensor.\n",
4039 new_loc = std::distance(this->_impl->_labels.begin(),
res);
4044 if (
out.dtype() !=
Type.Void) {
4054 std::vector<cytnx_int64>
tmp =
qidx;
4067 const bool &
force =
false) {
4078 const bool &
force =
false)
const {
4079 return this->_impl->get_block_(
qidx,
force);
4086 const bool &
force =
false)
const {
4087 std::vector<cytnx_int64>
tmp =
qidx;
4088 return this->_impl->get_block_(
tmp,
force);
4095 const bool &
force =
false)
const {
4110 std::vector<Tensor>
get_blocks()
const {
return this->_impl->get_blocks(); }
4119 return this->_impl->get_blocks_(
silent);
4127 return this->_impl->get_blocks_(
silent);
4136 this->_impl->put_block(
in,
idx);
4155 const std::vector<cytnx_int64> &
qidx,
const bool &
force =
false) {
4158 "[ERROR][put_block] length of lists must be the same for both lables and qnidices%s",
"\n");
4160 "[ERROR][put_block] length of lists must be the rank (# of legs)%s",
"\n");
4162 std::vector<cytnx_int64>
loc_id(this->
rank());
4168 for (
int i = 0;
i <
lbls.size();
i++) {
4169 auto res = std::find(this->_impl->_labels.begin(),
this->_impl->_labels.end(),
lbls[
i]);
4171 "[ERROR][put_block] label:%s does not exists in current Tensor.\n",
4173 new_loc = std::distance(this->_impl->_labels.begin(),
res);
4203 const std::vector<cytnx_int64> &
qidx,
const bool &
force =
false) {
4206 "[ERROR][put_block_] length of lists must be the same for both lables and qnidices%s",
4209 "[ERROR][put_block_] length of lists must be the rank (# of legs)%s",
"\n");
4211 std::vector<cytnx_int64>
loc_id(this->
rank());
4217 for (
int i = 0;
i <
lbls.size();
i++) {
4218 auto res = std::find(this->_impl->_labels.begin(),
this->_impl->_labels.end(),
lbls[
i]);
4220 "[ERROR][put_block_] label:%s does not exists in current Tensor.\n",
4222 new_loc = std::distance(this->_impl->_labels.begin(),
res);
4242 "[ERROR] cannot set elements from UniTensor with symmetry. Use at() instead.%s",
"\n");
4245 "[ERROR] cannot set UniTensor. incoming UniTensor is_diag=True.%s",
"\n");
4304 "combineBond(const std::vector<std::string> &indicators, const bool &force) "
4318 "combineBond(const std::vector<std::string> &indicators, const bool &force) "
4331 "combineBond(const std::vector<std::string> &indicators, const bool &force) "
4386 return this->_impl->getTotalQnums(
physical);
4393 return this->_impl->get_blocks_qnums();
4403 if (this->_impl->uten_type() !=
rhs._impl->uten_type())
return false;
4405 return this->_impl->same_data(
rhs._impl);
4831 out._impl = this->_impl->
Conj();
4843 this->_impl->
Conj_();
4942 if (this->
rank() == 0) {
4945 this->_impl = boost::intrusive_ptr<UniTensor_base>(
tmp);
4964 if (this->
rank() == 0) {
4967 this->_impl = boost::intrusive_ptr<UniTensor_base>(
tmp);
5036 return this->_impl->elem_exists(
locator);
5046 return this->
at<T>(locator);
5057 this->
at(locator) =
rc;
5160 return this->_impl->get_qindices(
bidx);
5170 return this->_impl->get_qindices(
bidx);
5183 void _Load(std::fstream &
f);
5184 void _Save(std::fstream &
f)
const;
5207 const std::vector<std::string> &
in_labels = {},
5209 const std::string &
name =
"") {
5227 const std::vector<std::string> &
in_labels = {},
5229 const std::string &
name =
"") {
5246 const std::string &
name =
"") {
5263 const std::vector<std::string> &
in_labels = {},
5265 const unsigned int &
dtype =
Type.Double,
5308 const std::vector<std::string> &
in_labels = {},
5310 const std::string &
name =
"") {
5328 const std::vector<std::string> &
in_labels = {},
5329 const std::string &
name =
"") {
5351 const std::vector<std::string> &
in_labels = {},
5353 const std::string &
name =
"") {
5378 const std::vector<std::string> &
in_labels = {},
5379 const unsigned int &
dtype =
Type.Double,
5405 const std::vector<std::string> &
in_labels = {},
5408 const std::string &
name =
"");
5429 const double &
std,
const std::vector<std::string> &
in_labels = {},
5432 const std::string &
name =
"");
5453 const std::vector<std::string> &
in_labels = {},
5455 const unsigned int &
dtype =
Type.Double,
5496 const double &
high,
const std::vector<std::string> &
in_labels = {},
5498 const unsigned int &
dtype =
Type.Double,
5535 std::ostream &operator<<(std::ostream &os,
const UniTensor &in);
5551 const bool &cacheR =
false);
5566 const bool &optimal);
5575 "UniTensor Contract(const std::vector<UniTensor> &TNs, const std::string &order, const bool "
5578 Contracts(
const std::vector<UniTensor> &TNs,
const std::string &order,
const bool &optimal);
5581 void _resolve_CT(std::vector<UniTensor> &TNlist);
5582 template <
class... T>
5583 void _resolve_CT(std::vector<UniTensor> &TNlist,
const UniTensor &in,
const T &...args) {
5584 TNlist.push_back(in);
5585 _resolve_CT(TNlist, args...);
5600 template <
class... T>
5602 const bool &optimal) {
5603 std::vector<UniTensor> TNlist;
5604 _resolve_CT(TNlist, in, args...);
5605 return Contract(TNlist, order, optimal);
5613 template <
class... T>
5616 "UniTensor Contract(const UniTensor &in, const T &...args, const std::string &order, const "
5620 const bool &optimal) {
5621 std::vector<UniTensor> TNlist;
5622 _resolve_CT(TNlist, in, args...);
5623 return Contracts(TNlist, order, optimal);
constexpr Type_class Type
data type
Definition Type.hpp:426
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:490
an tensor (multi-dimensional array)
Definition Tensor.hpp:41
void to_(const int &device)
move the current Tensor to the device.
Definition Tensor.hpp:675
Tensor contiguous_()
Make the Tensor contiguous by coalescing the memory (storage), inplacely.
Definition Tensor.hpp:762
unsigned int dtype() const
the dtype-id of the Tensor
Definition Tensor.hpp:574
Tensor contiguous() const
Make the Tensor contiguous by coalescing the memory (storage).
Definition Tensor.hpp:742
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition Tensor.hpp:924
Tensor clone() const
return a clone of the current Tensor.
Definition Tensor.hpp:626
void set(const std::vector< cytnx::Accessor > &accessors, const Tensor &rhs)
set elements with the input Tensor using Accessor (C++ API) / slices (python API)
Definition Tensor.hpp:1059
Tensor Norm() const
the Norm member function. Same as linalg::Norm(const Tensor &Tin), where Tin is the current Tensor.
Tensor astype(const int &new_type) const
return a new Tensor that cast to different dtype.
Definition Tensor.hpp:889
const bool & is_contiguous() const
return whether the Tensor is contiguous or not.
Definition Tensor.hpp:681
Tensor & Conj_()
the Conj_ member function. Same as cytnx::linalg::Conj_(Tensor &Tin), where Tin is the current Tensor...
int device() const
the device-id of the Tensor
Definition Tensor.hpp:581
Tensor get(const std::vector< cytnx::Accessor > &accessors) const
get elements using Accessor (C++ API) / slices (python API)
Definition Tensor.hpp:1027
const std::vector< cytnx_uint64 > & shape() const
the shape of the Tensor
Definition Tensor.hpp:601
An Enhanced tensor specifically designed for physical Tensor network simulation.
Definition UniTensor.hpp:2599
void put_block(const Tensor &in_tens, const std::vector< cytnx_int64 > &qidx, const bool &force)
Put the block into the UniTensor with given quantum number.
Definition UniTensor.hpp:4146
UniTensor to(const int &device) const
move the current UniTensor to the assigned device.
Definition UniTensor.hpp:3137
UniTensor & operator*=(const UniTensor &rhs)
The multiplication assignment operator of the UniTensor.
Definition UniTensor.hpp:4757
static UniTensor eye(const cytnx_uint64 &dim, const std::vector< std::string > &in_labels={}, const cytnx_bool &is_diag=false, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a 2-bond identity UniTensor.
Definition UniTensor.hpp:5289
Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:4053
std::vector< Tensor > & get_blocks_(const bool &silent=false)
Definition UniTensor.hpp:4126
Tensor & get_block_(const std::vector< cytnx_uint64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:4061
void print_block(const cytnx_int64 &idx, const bool &full_info=true) const
Given a index and print out the corresponding block of the UniTensor.
Definition UniTensor.hpp:3709
UniTensor & operator/=(const UniTensor &rhs)
The division assignment operator of the UniTensor.
Definition UniTensor.hpp:4737
T & item()
Definition UniTensor.hpp:2935
bool is_contiguous() const
To tell whether the UniTensor is contiguous.
Definition UniTensor.hpp:3026
T get_elem(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:5045
UniTensor Div(const UniTensor &rhs) const
The division function of the UniTensor.
Tensor get_block(const std::vector< std::string > &labels, const std::vector< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:3926
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:5169
std::vector< bool > signflip() const
Get the sign information of a fermionic UniTensor.
Definition UniTensor.hpp:3101
UniTensor & set_label(const cytnx_int64 &idx, const char *new_label)
Definition UniTensor.hpp:2838
UniTensor & operator+=(const UniTensor &rhs)
The addition assignment operator of the UniTensor.
Definition UniTensor.hpp:4697
void to_dense_()
Convert the UniTensor to non-diagonal form, inplacely.
Definition UniTensor.hpp:4295
UniTensor reshape(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor.
Definition UniTensor.hpp:4256
std::vector< Tensor > get_blocks() const
Get all the blocks of the UniTensor.
Definition UniTensor.hpp:4110
void combineBond(const std::vector< std::string > &indicators, const bool &force=false)
Combine the sevral bonds of the UniTensor.
Definition UniTensor.hpp:4347
UniTensor permute(const std::initializer_list< char * > &mapper, const cytnx_int64 &rowrank=-1) const
Definition UniTensor.hpp:3544
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:3039
std::string uten_type_str() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor in 'string' form.
Definition UniTensor.hpp:3019
void 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:3642
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:3610
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:2689
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:3922
UniTensor & tag()
Set the UniTensor as a tagged UniTensor.
Definition UniTensor.hpp:5004
const Bond & bond_(const cytnx_uint64 &idx) const
Definition UniTensor.hpp:3080
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force=false)
Definition UniTensor.hpp:4333
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:3472
const T & at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:3780
UniTensor & relabels_(const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:3267
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:2638
Tensor & get_block_(const std::vector< cytnx_int64 > &qidx, const bool &force=false)
Get the shared view of block for the given quantum indices.
Definition UniTensor.hpp:4001
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:2661
static UniTensor zeros(const std::vector< cytnx_uint64 > &shape, const std::vector< std::string > &in_labels={}, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a UniTensor with all elements set to zero.
Definition UniTensor.hpp:5226
UniTensor get(const std::vector< Accessor > &accessors) const
Definition UniTensor.hpp:4231
T & at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:3802
UniTensor Conj() const
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:4829
UniTensor & set_label(const std::string &old_label, const std::string &new_label)
set a new label for bond to replace one of the current label.
Definition UniTensor.hpp:2853
UniTensor set_rowrank(const cytnx_uint64 &new_rowrank) const
Definition UniTensor.hpp:2928
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:4787
cytnx_uint64 rowrank() const
Return the row rank of the UniTensor.
Definition UniTensor.hpp:2970
UniTensor & relabels_(const std::vector< std::string > &old_labels, const std::vector< std::string > &new_labels)
Definition UniTensor.hpp:3337
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:4680
UniTensor Mul(const Scalar &rhs) const
The multiplication function for a given scalar.
UniTensor & set_labels(const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:2907
UniTensor & relabel_(const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:3249
UniTensor & Sub_(const Scalar &rhs)
The subtraction function for a given scalar.
Definition UniTensor.hpp:4532
UniTensor & relabel_(const cytnx_int64 &inx, const std::string &new_label)
rebable the legs in the UniTensor by given index.
Definition UniTensor.hpp:3459
UniTensor & operator/=(const Scalar &rhs)
The division assignment operator for a given scalar.
Definition UniTensor.hpp:4802
const bool & is_braket_form() const
Check whether the UniTensor is in braket form.
Definition UniTensor.hpp:3054
void set_elem(const std::vector< cytnx_uint64 > &locator, const T2 &rc)
Definition UniTensor.hpp:5055
UniTensor Add(const Scalar &rhs) const
The addition function for a given scalar.
static UniTensor linspace(const cytnx_double &start, const cytnx_double &end, const cytnx_uint64 &Nelem, const bool &endpoint=true, const std::vector< std::string > &in_labels={}, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a one-bond UniTensor with all elements are evenly spaced numbers over a specified interval.
Definition UniTensor.hpp:5376
std::vector< cytnx_uint64 > shape() const
Get the shape of the UniTensor.
Definition UniTensor.hpp:3093
UniTensor to_dense()
Convert the UniTensor to non-diagonal form.
Definition UniTensor.hpp:4285
UniTensor & permute_(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1)
permute the lags of the UniTensor, inplacely.
Definition UniTensor.hpp:3567
Scalar::Sproxy at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:3861
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:4077
UniTensor & set_labels(const std::vector< std::string > &new_labels)
Set new labels for all the bonds.
Definition UniTensor.hpp:2898
std::string name() const
Return the name of the UniTensor.
Definition UniTensor.hpp:2998
const Scalar::Sproxy at(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:3883
UniTensor & Add_(const Scalar &rhs)
The addition function for a given scalar.
Definition UniTensor.hpp:4502
UniTensor & Trace_(const std::string &a, const std::string &b)
Take the partial trace of the UniTensor, inplacely.
Definition UniTensor.hpp:4938
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:5117
Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition UniTensor.hpp:3846
UniTensor Trace(const std::string &a, const std::string &b) const
Take the partial trace of the UniTensor.
Definition UniTensor.hpp:4908
bool same_data(const UniTensor &rhs) const
Check whether the Blocks address are the same.
Definition UniTensor.hpp:4401
UniTensor astype(const unsigned int &dtype) const
Return a new UniTensor that cast to different data type.
Definition UniTensor.hpp:3503
static UniTensor ones(const std::vector< cytnx_uint64 > &shape, const std::vector< std::string > &in_labels={}, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a UniTensor with all elements set to one.
Definition UniTensor.hpp:5307
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:5131
UniTensor Transpose() const
Take the transpose of the UniTensor.
Definition UniTensor.hpp:4859
static UniTensor arange(const cytnx_double &start, const cytnx_double &end, const cytnx_double &step=1, const std::vector< std::string > &in_labels={}, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a UniTensor with all elements are arange from start to end.
Definition UniTensor.hpp:5349
UniTensor & set_label(const char *old_label, const std::string &new_label)
Definition UniTensor.hpp:2861
static UniTensor Load(const char *fname)
load a UniTensor from file
UniTensor & Dagger_()
Take the conjugate transpose to the UniTensor, inplacely.
Definition UniTensor.hpp:4991
std::vector< Bond > & bonds()
Definition UniTensor.hpp:3078
T & at(const std::vector< cytnx_uint64 > &locator)
Get an element at specific location.
Definition UniTensor.hpp:3733
UniTensor & set_rowrank_(const cytnx_uint64 &new_rowrank)
Set the rowrank of the UniTensor.
Definition UniTensor.hpp:2923
void put_block(Tensor &in, const std::vector< std::string > &lbls, const std::vector< cytnx_int64 > &qidx, const bool &force=false)
Put the block into the UniTensor with given quantum indices, will copy the input tensor.
Definition UniTensor.hpp:4154
void 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:3656
UniTensor & set_label(const cytnx_int64 &idx, const std::string &new_label)
Set a new label for bond at the assigned index.
Definition UniTensor.hpp:2830
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:3594
UniTensor contiguous() const
Make the UniTensor contiguous by coalescing the memory (storage).
Definition UniTensor.hpp:3678
Tensor get_block(const cytnx_uint64 &idx=0) const
Get the block of the UniTensor for a given index.
Definition UniTensor.hpp:3911
const T & at(const std::vector< cytnx_uint64 > &locator) const
Get an element at specific location.
Definition UniTensor.hpp:3759
UniTensor & operator*=(const Scalar &rhs)
The multiplication assignment operator for a given scalar.
Definition UniTensor.hpp:4817
UniTensor relabels(const std::vector< std::string > &old_labels, const std::vector< std::string > &new_labels) const
Definition UniTensor.hpp:3300
void contiguous_()
Make the UniTensor contiguous by coalescing the memory (storage), inplacely.
Definition UniTensor.hpp:3688
UniTensor normalize() const
normalize the current UniTensor instance with 2-norm.
Definition UniTensor.hpp:4882
static UniTensor ones(const cytnx_uint64 &Nelem, const std::vector< std::string > &in_labels={}, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a one-bond UniTensor with all elements set to one.
Definition UniTensor.hpp:5244
UniTensor & relabel_(const std::vector< std::string > &new_labels)
Set new labels for all the bonds.
Definition UniTensor.hpp:3162
std::vector< Symmetry > syms() const
Return the symmetry type of the UniTensor.
Definition UniTensor.hpp:3046
UniTensor relabel(const std::vector< std::string > &new_labels) const
relabel all of the labels in UniTensor.
Definition UniTensor.hpp:3193
UniTensor & Mul_(const UniTensor &rhs)
The multiplcation function of the UniTensor.
Definition UniTensor.hpp:4445
static UniTensor zeros(const cytnx_uint64 &Nelem, const std::vector< std::string > &in_labels={}, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a one-bond UniTensor with all elements set to zero.
Definition UniTensor.hpp:5206
void put_block_(Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index, inplacely.
Definition UniTensor.hpp:4186
void combineBonds(const std::vector< std::string > &indicators, const bool &force=false)
Definition UniTensor.hpp:4320
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:3491
UniTensor & normalize_()
normalize the UniTensor, inplacely.
Definition UniTensor.hpp:4894
bool is_diag() const
To tell whether the UniTensor is in diagonal form.
Definition UniTensor.hpp:3032
int device() const
Return the device of the UniTensor.
Definition UniTensor.hpp:2992
UniTensor & Pow_(const double &p)
Power function.
const Tensor & get_block_(const std::vector< cytnx_uint64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:4094
Tensor get_block_(const std::vector< std::string > &labels, const std::vector< cytnx_int64 > &qidx, const bool &force=false)
Get the shared (data) view of block for the given quantum indices on given labels.
Definition UniTensor.hpp:4021
void put_block_(Tensor &in, const std::vector< std::string > &lbls, const std::vector< cytnx_int64 > &qidx, const bool &force=false)
Put the block into the UniTensor with given quantum indices, inplacely.
Definition UniTensor.hpp:4202
void set(const std::vector< Accessor > &accessors, const Tensor &rhs)
Definition UniTensor.hpp:4236
std::string dtype_str() const
Return the data type of the UniTensor in 'string' form.
Definition UniTensor.hpp:3005
UniTensor & operator+=(const Scalar &rhs)
The addition assignment operator for a given scalar.
Definition UniTensor.hpp:4772
UniTensor & Div_(const UniTensor &rhs)
The division function of the UniTensor.
Definition UniTensor.hpp:4487
UniTensor & Div_(const Scalar &rhs)
The division function for a given scalar.
Definition UniTensor.hpp:4547
Bond & bond_(const std::string &label)
Definition UniTensor.hpp:3084
cytnx_uint64 rank() const
Return the rank of the UniTensor.
Definition UniTensor.hpp:2964
Bond bond(const std::string &label) const
Definition UniTensor.hpp:3087
std::vector< bool > & signflip_()
Get reference to the sign information of a fermionic UniTensor.
Definition UniTensor.hpp:3111
void group_basis_()
Group the same quantum number basis together.
Definition UniTensor.hpp:3719
UniTensor permute_nosignflip(const std::initializer_list< char * > &mapper, const cytnx_int64 &rowrank=-1) const
Definition UniTensor.hpp:3621
void to_(const int &device)
move the current UniTensor to the assigned device (inplace).
Definition UniTensor.hpp:3126
UniTensor & Trace_(const cytnx_int64 &a=0, const cytnx_int64 &b=1)
Take the partial trace of the UniTensor, inplacely.
Definition UniTensor.hpp:4960
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:3284
UniTensor & set_name(const std::string &in)
Set the name of a UniTensor.
Definition UniTensor.hpp:2815
UniTensor Trace(const cytnx_int64 &a=0, const cytnx_int64 &b=1) const
Take the partial trace of the UniTensor.
Definition UniTensor.hpp:4923
UniTensor & Add_(const UniTensor &rhs)
The addition function of the UniTensor.
Definition UniTensor.hpp:4424
void normal_(const double &mean, const double &std, const unsigned int &seed=cytnx::random::__static_random_device())
Generate a one-bond UniTensor with all elements are random numbers sampled from a normal (Gaussian) d...
UniTensor permute(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1) const
permute the legs of the UniTensor
Definition UniTensor.hpp:3521
UniTensor & set_label(const std::string &old_label, const char *new_label)
Definition UniTensor.hpp:2869
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:3534
unsigned int dtype() const
Return the data type of the UniTensor.
Definition UniTensor.hpp:2977
UniTensor Pow(const double &p) const
Power function.
UniTensor & Mul_(const Scalar &rhs)
The multiplication function for a given scalar.
Definition UniTensor.hpp:4517
UniTensor & operator-=(const UniTensor &rhs)
The subtraction assignment operator of the UniTensor.
Definition UniTensor.hpp:4717
Tensor get_block_(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &qidx, const bool &force=false)
Definition UniTensor.hpp:4066
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &force, const bool &by_label)
Definition UniTensor.hpp:4306
UniTensor & set_label(const char *old_label, const char *new_label)
Definition UniTensor.hpp:2877
static UniTensor arange(const cytnx_int64 &Nelem, const std::vector< std::string > &in_labels={}, const std::string &name="")
Generate a one-bond UniTensor with all elements are arange from 0 to Nelem-1.
Definition UniTensor.hpp:5327
bool is_blockform() const
Check whether the UniTensor is in block form.
Definition UniTensor.hpp:3118
UniTensor group_basis() const
Definition UniTensor.hpp:3721
UniTensor Dagger() const
Take the conjugate transpose to the UniTensor.
Definition UniTensor.hpp:4979
static UniTensor uniform(const std::vector< cytnx_uint64 > &shape, const double &low, const double &high, const std::vector< std::string > &in_labels={}, const unsigned int &seed=cytnx::random::__static_random_device(), const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a UniTensor with all elements are random numbers sampled from a uniform distribution.
void set(const std::vector< Accessor > &accessors, const UniTensor &rhs)
Definition UniTensor.hpp:4239
const std::vector< Tensor > & get_blocks_(const bool &silent=false) const
Get all the blocks of the UniTensor, inplacely.
Definition UniTensor.hpp:4118
UniTensor & relabels_(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:3416
const Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:4085
bool elem_exists(const std::vector< cytnx_uint64 > &locator) const
Geiven the locator, check if the element exists.
Definition UniTensor.hpp:5035
UniTensor & Sub_(const UniTensor &rhs)
The subtraction function of the UniTensor.
Definition UniTensor.hpp:4466
UniTensor relabels(const std::initializer_list< char * > &new_labels) const
Definition UniTensor.hpp:3236
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:4369
void put_block(const Tensor &in, const cytnx_uint64 &idx=0)
Put the block into the UniTensor with given index.
Definition UniTensor.hpp:4135
const Tensor & get_block_(const cytnx_uint64 &idx=0) const
Get the shared view of block for the given index.
Definition UniTensor.hpp:3983
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:3322
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:3578
const Bond & bond_(const std::string &label) const
Definition UniTensor.hpp:3083
static UniTensor identity(const cytnx_uint64 &dim, const std::vector< std::string > &in_labels={}, const cytnx_bool &is_diag=false, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a identity UniTensor.
Definition UniTensor.hpp:5262
Bond & bond_(const cytnx_uint64 &idx)
Definition UniTensor.hpp:3081
static UniTensor normal(const cytnx_uint64 &Nelem, const double &mean, const double &std, const std::vector< std::string > &in_labels={}, const unsigned int &seed=cytnx::random::__static_random_device(), const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a one-bond UniTensor with all elements are random numbers sampled from a normal (Gaussian) d...
UniTensor relabel(const cytnx_int64 &inx, const std::string &new_label) const
rebabel the legs in the UniTensor by given index.
Definition UniTensor.hpp:3446
UniTensor Mul(const UniTensor &rhs) const
The multiplication function of the UniTensor.
void uniform_(const double &low=0, const double &high=1, const unsigned int &seed=cytnx::random::__static_random_device())
Generate a UniTensor with all elements are random numbers sampled from a uniform distribution,...
UniTensor & reshape_(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Reshape the UniTensor, inplacely.
Definition UniTensor.hpp:4268
void print_diagram(const bool &bond_info=false) const
Plot the diagram of the UniTensor.
Definition UniTensor.hpp:3694
UniTensor relabels(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels) const
Definition UniTensor.hpp:3372
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:5159
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:3060
UniTensor & relabel_(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels)
Definition UniTensor.hpp:3391
cytnx_int64 get_index(std::string label) const
Get the index of an desired label string.
Definition UniTensor.hpp:3067
const std::vector< Bond > & bonds() const
Get the bonds of the UniTensor.
Definition UniTensor.hpp:3073
Tensor get_block(const std::vector< std::string > &labels, const std::vector< cytnx_uint64 > &qidx, const bool &force=false) const
Definition UniTensor.hpp:3972
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:5146
UniTensor & Transpose_()
Take the transpose of the UniTensor, inplacely.
Definition UniTensor.hpp:4871
static UniTensor uniform(const cytnx_uint64 &Nelem, const double &low, const double &high, const std::vector< std::string > &in_labels={}, const unsigned int &seed=cytnx::random::__static_random_device(), const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const std::string &name="")
Generate a one-bond UniTensor with all elements are random numbers sampled from a uniform distributio...
UniTensor clone() const
Clone (deep copy) the UniTensor.
Definition UniTensor.hpp:3147
vec2d< cytnx_uint64 > & get_itoi()
Definition UniTensor.hpp:5180
void print_blocks(const bool &full_info=true) const
Print all of the blocks in the UniTensor.
Definition UniTensor.hpp:3702
Scalar::Sproxy item() const
Definition UniTensor.hpp:2945
UniTensor & convert_from(const UniTensor &rhs, const bool &force=false, const cytnx_double &tol=1e-14)
Definition UniTensor.hpp:5187
const vec2d< cytnx_uint64 > & get_itoi() const
get the q-indices on each leg for all the blocks
Definition UniTensor.hpp:5179
std::string device_str() const
Return the device of the UniTensor in 'string' form.
Definition UniTensor.hpp:3012
UniTensor relabels(const std::vector< std::string > &new_labels) const
Definition UniTensor.hpp:3207
void put_block_(Tensor &in, const std::vector< cytnx_int64 > &qidx, const bool &force)
Put the block into the UniTensor with given quantum indices, inplacely.
Definition UniTensor.hpp:4194
UniTensor relabel(const std::initializer_list< char * > &old_labels, const std::initializer_list< char * > &new_labels) const
Definition UniTensor.hpp:3347
UniTensor Sub(const UniTensor &rhs) const
The subtraction function of the UniTensor.
void Init(const std::vector< Bond > &bonds, const std::vector< std::string > &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const bool &is_diag=false, const std::string &name="")
Initialize the UniTensor with the given arguments.
Definition UniTensor.hpp:2740
UniTensor & Conj_()
Apply complex conjugate on each entry of the UniTensor.
Definition UniTensor.hpp:4842
UniTensor relabel(const std::initializer_list< char * > &new_labels) const
relables all of the labels in UniTensor.
Definition UniTensor.hpp:3217
cytnx_uint64 Nblocks() const
Return the number of blocks in the UniTensor.
Definition UniTensor.hpp:2958
Tensor get_block(const std::vector< cytnx_uint64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:3967
void Save(const char *fname) const
save a UniTensor to file
Bond bond(const cytnx_uint64 &idx) const
Definition UniTensor.hpp:3086
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:5104
Tensor get_block(const std::initializer_list< cytnx_int64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:3957
UniTensor & relabels_(const std::vector< std::string > &new_labels)
Definition UniTensor.hpp:3177
const Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator) const
Get an element at specific location.
Definition UniTensor.hpp:3827
int uten_type() const
Return the UniTensor type (cytnx::UTenType) of the UniTensor.
Definition UniTensor.hpp:2985
Tensor & get_block_(const cytnx_uint64 &idx=0)
Definition UniTensor.hpp:3991
#define cytnx_warning_msg(is_true, format,...)
Definition cytnx_error.hpp:52
#define cytnx_error_msg(is_true, format,...)
Definition cytnx_error.hpp:18
cytnx::UniTensor Conj(const cytnx::UniTensor &UT)
Elementwise conjugate of the UniTensor.
cytnx::UniTensor Trace(const cytnx::UniTensor &Tin, const cytnx_int64 &a=0, const cytnx_int64 &b=1)
void Conj_(cytnx::UniTensor &UT)
Inplace elementwise conjugate of the UniTensor.
Tensor Norm(const Tensor &Tl)
Calculate the norm of a tensor.
std::random_device __static_random_device
Definition UniTensor.hpp:29
Definition Accessor.hpp:12
Device_class Device
data on which devices.
Tensor linspace(const cytnx_double &start, const cytnx_double &end, const cytnx_uint64 &Nelem, const bool &endpoint=true, const unsigned int &dtype=Type.Double, const int &device=Device.cpu)
UniTensorType_class UTenType
UniTensor type.
@ Void
Definition Symmetry.hpp:32
Tensor arange(const cytnx_int64 &Nelem)
create an rank-1 Tensor with incremental unsigned integer elements start with [0,Nelem)
UniTensor Contract(const UniTensor &inL, const UniTensor &inR, const bool &cacheL=false, const bool &cacheR=false)
Contract two UniTensor by tracing the ranks with common labels.
Tensor ones(const cytnx_uint64 &Nelem, const unsigned int &dtype=Type.Double, const int &device=Device.cpu)
create an rank-1 Tensor with all the elements are initialized with one.
UniTensor Contracts(const std::vector< UniTensor > &TNs, const std::string &order, const bool &optimal)
Tensor zeros(const cytnx_uint64 &Nelem, const unsigned int &dtype=Type.Double, const int &device=Device.cpu)
create an rank-1 Tensor with all the elements are initialized with zero.
Tensor identity(const cytnx_uint64 &Dim, const unsigned int &dtype=Type.Double, const int &device=Device.cpu)
create an square rank-2 Tensor with all diagonal to be one.