16#include <initializer_list>
25 using namespace cytnx;
27 class UniTensorType_class{
34 std::string getname(
const int &ut_type);
42 class UniTensor_base:
public intrusive_ptr_base<UniTensor_base>{
51 std::vector<cytnx_int64> _labels;
52 std::vector< Bond > _bonds;
56 bool _update_braket(){
57 if(_bonds.size()==0)
return false;
59 if(this->_bonds[0].type()!= bondType::BD_REG){
61 for(
unsigned int i=0;i<this->_bonds.size();i++){
63 if(this->_bonds[i].type()!=bondType::BD_KET)
return false;
65 if(this->_bonds[i].type()!=bondType::BD_BRA)
return false;
75 friend class DenseUniTensor;
76 friend class SparseUniTensor;
78 UniTensor_base(): _is_tag(false), _name(std::string(
"")), _is_braket_form(false), _rowrank(-1), _is_diag(false), uten_type_id(
UTenType.Void){};
81 UniTensor_base(
const UniTensor_base &rhs);
82 UniTensor_base& operator=(UniTensor_base &rhs);
85 bool is_diag()
const{
return this->_is_diag; }
86 const bool& is_braket_form()
const{
87 return this->_is_braket_form;
89 const bool& is_tag()
const{
92 const std::vector<cytnx_int64>& labels()
const{
return this->_labels;}
93 const std::vector<Bond> &bonds()
const {
return this->_bonds;}
94 std::vector<Bond> &bonds(){
return this->_bonds;}
95 const std::string& name()
const {
return this->_name;}
97 void set_name(
const std::string &in){ this->_name = in;}
101 auto res = std::find(this->_labels.begin(),this->_labels.end(),inx);
102 cytnx_error_msg(res==this->_labels.end(),
"[ERROR] label %d not exists.\n",inx);
103 idx = std::distance(this->_labels.begin(), res);
108 cytnx_error_msg(idx>=this->_labels.size(),
"[ERROR] index exceed the rank of UniTensor%s",
"\n");
113 if(new_label == this->_labels[i]){is_dup =
true;
break;}
115 cytnx_error_msg(is_dup,
"[ERROR] alreay has a label that is the same as the input label%s",
"\n");
116 this->_labels[idx] = new_label;
119 void set_labels(
const std::vector<cytnx_int64> &new_labels);
155 return this->uten_type_id;
157 std::string uten_type_str(){
158 return UTenType.getname(this->uten_type_id);
164 virtual void Init(
const std::vector<Bond> &bonds,
const std::vector<cytnx_int64> &in_labels={},
const cytnx_int64 &rowrank=-1,
const unsigned int &dtype=
Type.Double,
const int &device =
Device.cpu,
const bool &is_diag=
false,
const bool &no_alloc=
false);
165 virtual void Init_by_Tensor(
const Tensor& in,
const cytnx_uint64 &rowrank,
const bool &is_diag=
false);
166 virtual std::vector<cytnx_uint64> shape()
const;
167 virtual bool is_blockform()
const ;
168 virtual bool is_contiguous()
const;
169 virtual void to_(
const int &device);
170 virtual boost::intrusive_ptr<UniTensor_base> to(
const int &device);
171 virtual boost::intrusive_ptr<UniTensor_base> clone()
const;
172 virtual unsigned int dtype()
const;
173 virtual int device()
const;
174 virtual std::string dtype_str()
const;
175 virtual std::string device_str()
const;
176 virtual void set_rowrank(
const cytnx_uint64 &new_rowrank);
177 virtual boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank=-1,
const bool &by_label=
false);
178 virtual void permute_(
const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank=-1,
const bool &by_label=
false);
179 virtual boost::intrusive_ptr<UniTensor_base> contiguous_();
180 virtual boost::intrusive_ptr<UniTensor_base> contiguous();
181 virtual void print_diagram(
const bool &bond_info=
false);
183 virtual boost::intrusive_ptr<UniTensor_base> astype(
const unsigned int &dtype)
const;
187 virtual Tensor get_block(
const std::vector<cytnx_int64> &qnum,
const bool &force)
const;
190 virtual const Tensor& get_block_(
const std::vector<cytnx_int64> &qnum,
const bool &force)
const;
192 virtual Tensor& get_block_(
const std::vector<cytnx_int64> &qnum,
const bool &force);
193 virtual bool same_data(
const boost::intrusive_ptr<UniTensor_base> &rhs)
const;
195 virtual std::vector<Tensor> get_blocks()
const;
196 virtual const std::vector<Tensor>& get_blocks_(
const bool &)
const;
197 virtual std::vector<Tensor>& get_blocks_(
const bool &);
201 virtual void put_block(
const Tensor &in,
const std::vector<cytnx_int64> &qnum,
const bool &force);
202 virtual void put_block_(
Tensor &in,
const std::vector<cytnx_int64> &qnum,
const bool &force);
205 virtual boost::intrusive_ptr<UniTensor_base> get(
const std::vector<Accessor> &accessors);
208 virtual void set(
const std::vector<Accessor> &accessors,
const Tensor &rhs);
210 virtual void reshape_(
const std::vector<cytnx_int64> &new_shape,
const cytnx_uint64 &rowrank=0);
211 virtual boost::intrusive_ptr<UniTensor_base> reshape(
const std::vector<cytnx_int64> &new_shape,
const cytnx_uint64 &rowrank=0);
212 virtual boost::intrusive_ptr<UniTensor_base> to_dense();
213 virtual void to_dense_();
214 virtual void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &permute_back=
false,
const bool &by_label=
true);
215 virtual boost::intrusive_ptr<UniTensor_base> contract(
const boost::intrusive_ptr<UniTensor_base> &rhs,
const bool &mv_elem_self=
false,
const bool &mv_elem_rhs=
false);
216 virtual std::vector<Bond> getTotalQnums(
const bool &physical=
false);
217 virtual std::vector<std::vector<cytnx_int64> > get_blocks_qnums()
const;
220 virtual boost::intrusive_ptr<UniTensor_base> relabels(
const std::vector<cytnx_int64> &new_labels);
221 virtual boost::intrusive_ptr<UniTensor_base> relabel(
const cytnx_int64 &inx,
const cytnx_int64 &new_label,
const bool &by_label=
false);
224 virtual std::vector<Symmetry> syms()
const;
227 virtual void Add_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
228 virtual void Add_(
const Scalar &rhs);
230 virtual void Mul_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
231 virtual void Mul_(
const Scalar &rhs);
233 virtual void Sub_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
234 virtual void Sub_(
const Scalar &rhs);
235 virtual void lSub_(
const Scalar &lhs);
237 virtual void Div_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
238 virtual void Div_(
const Scalar &rhs);
239 virtual void lDiv_(
const Scalar &lhs);
246 virtual boost::intrusive_ptr<UniTensor_base>
Conj();
247 virtual void Conj_();
249 virtual boost::intrusive_ptr<UniTensor_base> Transpose();
250 virtual void Transpose_();
252 virtual boost::intrusive_ptr<UniTensor_base> Dagger();
253 virtual void Dagger_();
259 virtual bool elem_exists(
const std::vector<cytnx_uint64> &locator)
const;
262 virtual Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator);
263 virtual const Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator)
const;
279 virtual const cytnx_float& at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_float &aux)
const;
281 virtual const cytnx_int64& at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int64 &aux)
const;
283 virtual const cytnx_int32& at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int32 &aux)
const;
285 virtual const cytnx_int16& at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int16 &aux)
const;
287 virtual void _save_dispatch(std::fstream &f)
const;
288 virtual void _load_dispatch(std::fstream &f);
290 virtual ~UniTensor_base(){};
296 class DenseUniTensor:
public UniTensor_base{
300 std::vector<Tensor> _interface_block;
301 DenseUniTensor* clone_meta()
const{
302 DenseUniTensor* tmp =
new DenseUniTensor();
303 tmp->_bonds = vec_clone(this->_bonds);
304 tmp->_labels = this->_labels;
305 tmp->_is_braket_form = this->_is_braket_form;
306 tmp->_rowrank = this->_rowrank;
307 tmp->_is_diag = this->_is_diag;
308 tmp->_name = this->_name;
309 tmp->_is_tag = this->_is_tag;
314 DenseUniTensor(){this->uten_type_id =
UTenType.Dense;};
317 void Init(
const std::vector<Bond> &bonds,
const std::vector<cytnx_int64> &in_labels={},
const cytnx_int64 &rowrank=-1,
const unsigned int &dtype=
Type.Double,
const int &device =
Device.cpu,
const bool &is_diag=
false,
const bool &no_alloc=
false);
319 void Init_by_Tensor(
const Tensor& in_tensor,
const cytnx_uint64 &rowrank,
const bool &is_diag=
false);
320 std::vector<cytnx_uint64> shape()
const{
322 std::vector<cytnx_uint64> shape = this->_block.
shape();
323 shape.push_back(shape[0]);
326 return this->_block.
shape();
329 bool is_blockform()
const{
return false;}
330 void to_(
const int &device){
331 this->_block.
to_(device);
333 boost::intrusive_ptr<UniTensor_base> to(
const int &device){
334 if(this->device() == device){
337 boost::intrusive_ptr<UniTensor_base> out = this->clone();
343 cytnx_error_msg(new_rowrank > this->_labels.size(),
"[ERROR] rowrank cannot exceed the rank of UniTensor.%s",
"\n");
344 this->_rowrank = new_rowrank;
347 boost::intrusive_ptr<UniTensor_base> clone()
const{
348 DenseUniTensor* tmp = this->clone_meta();
349 tmp->_block = this->_block.
clone();
350 boost::intrusive_ptr<UniTensor_base> out(tmp);
353 bool is_contiguous()
const{
return this->_block.
is_contiguous();}
354 unsigned int dtype()
const{
return this->_block.
dtype();}
355 int device()
const{
return this->_block.
device();}
356 std::string dtype_str()
const{
return Type.getname(this->_block.
dtype());}
357 std::string device_str()
const{
return Device.getname(this->_block.
device());}
358 boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank=-1,
const bool &by_label=
false);
359 void permute_(
const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank=-1,
const bool &by_label=
false);
360 boost::intrusive_ptr<UniTensor_base> relabels(
const std::vector<cytnx_int64> &new_labels);
361 boost::intrusive_ptr<UniTensor_base> relabel(
const cytnx_int64 &inx,
const cytnx_int64 &new_label,
const bool &by_label=
false);
363 boost::intrusive_ptr<UniTensor_base> astype(
const unsigned int &dtype)
const{
364 DenseUniTensor* tmp = this->clone_meta();
365 tmp->_block = this->_block.
astype(dtype);
366 boost::intrusive_ptr<UniTensor_base> out(tmp);
370 std::vector<Symmetry> syms()
const{
371 cytnx_error_msg(
true,
"[ERROR][DenseUniTensor] dense unitensor does not have symmetry.%s",
"\n");
372 return std::vector<Symmetry>();
375 boost::intrusive_ptr<UniTensor_base> contiguous_(){this->_block.
contiguous_();
return boost::intrusive_ptr<UniTensor_base>(
this);}
376 boost::intrusive_ptr<UniTensor_base> contiguous(){
378 if(this->is_contiguous()){
379 boost::intrusive_ptr<UniTensor_base> out(
this);
382 DenseUniTensor* tmp = this->clone_meta();
384 boost::intrusive_ptr<UniTensor_base> out(tmp);
388 void print_diagram(
const bool &bond_info=
false);
391 Tensor get_block(
const std::vector<cytnx_int64> &qnum,
const bool &force)
const{
cytnx_error_msg(
true,
"[ERROR][DenseUniTensor] try to get_block() using qnum on a non-symmetry UniTensor%s",
"\n");
return Tensor();}
393 const Tensor& get_block_(
const std::vector<cytnx_int64> &qnum,
const bool &force)
const{
cytnx_error_msg(
true,
"[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
"\n");
return this->_block;}
394 Tensor& get_block_(
const std::vector<cytnx_int64> &qnum,
const bool &force){
cytnx_error_msg(
true,
"[ERROR][DenseUniTensor] try to get_block_() using qnum on a non-symmetry UniTensor%s",
"\n");
return this->_block;}
406 std::vector<Tensor> get_blocks()
const {
407 std::vector<Tensor> out;
408 cytnx_error_msg(
true,
"[ERROR][DenseUniTensor] cannot use get_blocks(), use get_block() instead!%s",
"\n");
411 const std::vector<Tensor>& get_blocks_(
const bool &silent=
false)
const {
412 cytnx_error_msg(
true,
"[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s",
"\n");
413 return this->_interface_block;
415 std::vector<Tensor>& get_blocks_(
const bool &silent=
false){
416 cytnx_error_msg(
true,
"[ERROR][DenseUniTensor] cannot use get_blocks_(), use get_block_() instead!%s",
"\n");
417 return this->_interface_block;
422 cytnx_error_msg(in.
shape() != this->_block.shape(),
"[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s",
"\n");
423 this->_block = in.
clone();
425 cytnx_error_msg(in.
shape() != this->shape(),
"[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s",
"\n");
426 this->_block = in.
clone();
432 cytnx_error_msg(in.
shape() != this->_block.shape(),
"[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s",
"\n");
435 cytnx_error_msg(in.
shape() != this->shape(),
"[ERROR][DenseUniTensor] put_block, the input tensor shape does not match.%s",
"\n");
440 void put_block(
const Tensor &in,
const std::vector<cytnx_int64> &qnum,
const bool &force){
441 cytnx_error_msg(
true,
"[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
"\n");
443 void put_block_(
Tensor &in,
const std::vector<cytnx_int64> &qnum,
const bool &force){
444 cytnx_error_msg(
true,
"[ERROR][DenseUniTensor] try to put_block using qnum on a non-symmetry UniTensor%s",
"\n");
447 boost::intrusive_ptr<UniTensor_base> get(
const std::vector<Accessor> &accessors){
448 boost::intrusive_ptr<UniTensor_base> out(
new DenseUniTensor());
449 out->Init_by_Tensor(this->_block.
get(accessors),0);
453 void set(
const std::vector<Accessor> &accessors,
const Tensor &rhs){
454 this->_block.
set(accessors,rhs);
457 void reshape_(
const std::vector<cytnx_int64> &new_shape,
const cytnx_uint64 &rowrank=0);
458 boost::intrusive_ptr<UniTensor_base> reshape(
const std::vector<cytnx_int64> &new_shape,
const cytnx_uint64 &rowrank=0);
459 boost::intrusive_ptr<UniTensor_base> to_dense();
462 void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &permute_back=
true,
const bool &by_label=
true);
463 boost::intrusive_ptr<UniTensor_base> contract(
const boost::intrusive_ptr<UniTensor_base> &rhs,
const bool &mv_elem_self=
false,
const bool &mv_elem_rhs=
false);
464 std::vector<Bond> getTotalQnums(
const bool &physical=
false){
465 cytnx_error_msg(
true,
"[ERROR][DenseUniTensor] %s",
"getTotalQnums can only operate on UniTensor with symmetry.\n");
466 return std::vector<Bond>();
470 std::vector<std::vector<cytnx_int64> > get_blocks_qnums()
const{
471 cytnx_error_msg(
true,
"[ERROR][DenseUniTensor] %s",
"get_blocks_qnums can only operate on UniTensor with symmetry.\n");
472 return std::vector<std::vector<cytnx_int64> >();
475 bool same_data(
const boost::intrusive_ptr<UniTensor_base> &rhs)
const{
476 if(rhs->uten_type()!=
UTenType.Dense)
return false;
478 return this->get_block_().same_data(rhs->get_block_());
487 void Add_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
488 void Add_(
const Scalar &rhs);
490 void Mul_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
491 void Mul_(
const Scalar &rhs);
493 void Sub_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
494 void Sub_(
const Scalar &rhs);
495 void lSub_(
const Scalar &lhs);
497 void Div_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
498 void Div_(
const Scalar &rhs);
499 void lDiv_(
const Scalar &lhs);
503 this->_block.
Conj_();
506 boost::intrusive_ptr<UniTensor_base>
Conj(){
507 boost::intrusive_ptr<UniTensor_base> out = this->clone();
512 boost::intrusive_ptr<UniTensor_base> Transpose(){
513 boost::intrusive_ptr<UniTensor_base> out = this->clone();
519 boost::intrusive_ptr<UniTensor_base> Dagger(){
520 boost::intrusive_ptr<UniTensor_base> out = this->
Conj();
532 boost::intrusive_ptr<UniTensor_base> out = this->clone();
533 out->Trace_(a,b,by_label);
539 const Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator)
const {
540 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
544 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
548 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
552 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
556 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
560 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
564 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
568 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
572 const cytnx_int32& at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int32 &aux)
const {
573 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
577 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
581 const cytnx_int16& at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int16 &aux)
const {
582 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
586 Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator){
587 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
591 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
595 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
599 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
603 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
607 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
611 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
615 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
620 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
624 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
629 cytnx_error_msg(
true,
"[ERROR][Internal] This shouldn't be called by DenseUniTensor, something wrong.%s",
"\n");
634 bool elem_exists(
const std::vector<cytnx_uint64> &locator)
const{
635 cytnx_error_msg(
true,
"[ERROR][DenseUniTensor] elem_exists can only be used on UniTensor with Symmetry.%s",
"\n");
639 for(
int i=0;i<this->_rowrank;i++){
640 this->_bonds[i].set_type(BD_KET);
642 for(
int i=this->_rowrank;i<this->_bonds.size();i++){
643 this->_bonds[i].set_type(BD_BRA);
645 this->_is_tag =
true;
646 this->_is_braket_form = this->_update_braket();
651 void _save_dispatch(std::fstream &f)
const;
652 void _load_dispatch(std::fstream &f);
663 class SparseUniTensor:
public UniTensor_base{
669 std::vector<std::vector<cytnx_int64> > _blockqnums;
670 std::vector<cytnx_uint64> _mapper;
671 std::vector<cytnx_uint64> _inv_mapper;
672 std::vector<std::vector<cytnx_uint64> > _inner2outer_row;
673 std::vector<std::vector<cytnx_uint64> > _inner2outer_col;
674 std::map<cytnx_uint64,std::pair<cytnx_uint64,cytnx_uint64> > _outer2inner_row;
675 std::map<cytnx_uint64, std::pair<cytnx_uint64,cytnx_uint64> > _outer2inner_col;
677 std::vector<Tensor> _blocks;
680 void set_meta(SparseUniTensor *tmp,
const bool &inner,
const bool &outer)
const{
683 tmp->_bonds = vec_clone(this->_bonds);
684 tmp->_labels = this->_labels;
685 tmp->_is_braket_form = this->_is_braket_form;
686 tmp->_rowrank = this->_rowrank;
687 tmp->_name = this->_name;
690 tmp->_mapper = this->_mapper;
691 tmp->_inv_mapper = this->_inv_mapper;
692 tmp->_contiguous = this->_contiguous;
693 tmp->_is_diag = this->_is_diag;
697 tmp->_inner_rowrank = this->_inner_rowrank;
698 tmp->_inner2outer_row = this->_inner2outer_row;
699 tmp->_inner2outer_col = this->_inner2outer_col;
700 tmp->_outer2inner_row = this->_outer2inner_row;
701 tmp->_outer2inner_col = this->_outer2inner_col;
702 tmp->_blockqnums = this->_blockqnums;
706 SparseUniTensor* clone_meta(
const bool &inner,
const bool &outer)
const{
707 SparseUniTensor* tmp =
new SparseUniTensor();
708 this->set_meta(tmp,inner,outer);
718 this->uten_type_id =
UTenType.Sparse;
719 this->_is_tag =
true;
723 void Init(
const std::vector<Bond> &bonds,
const std::vector<cytnx_int64> &in_labels={},
const cytnx_int64 &rowrank=-1,
const unsigned int &dtype=
Type.Double,
const int &device =
Device.cpu,
const bool &is_diag=
false,
const bool &no_alloc=
false);
724 void Init_by_Tensor(
const Tensor& in_tensor,
const cytnx_uint64 &rowrank,
const bool &is_diag=
false){
725 cytnx_error_msg(
true,
"[ERROR][SparseUniTensor] cannot use Init_by_tensor() on a SparseUniTensor.%s",
"\n");
727 std::vector<cytnx_uint64> shape()
const{
728 std::vector<cytnx_uint64> out(this->_bonds.size());
730 out[i] = this->_bonds[i].dim();
734 bool is_blockform()
const{
return true;}
735 void to_(
const int &device){
737 this->_blocks[i].to_(device);
740 boost::intrusive_ptr<UniTensor_base> to(
const int &device){
741 if(this->device() == device){
744 boost::intrusive_ptr<UniTensor_base> out = this->clone();
749 boost::intrusive_ptr<UniTensor_base> clone()
const{
750 SparseUniTensor* tmp = this->clone_meta(
true,
true);
751 tmp->_blocks = vec_clone(this->_blocks);
752 boost::intrusive_ptr<UniTensor_base> out(tmp);
756 bool is_contiguous()
const{
757 return this->_contiguous;
760 cytnx_error_msg((new_rowrank < 1) || (new_rowrank>= this->rank()),
"[ERROR][SparseUniTensor] rowrank should be [>=1] and [<UniTensor.rank].%s",
"\n");
761 cytnx_error_msg(new_rowrank >= this->_labels.size(),
"[ERROR] rowrank cannot exceed the rank of UniTensor.%s",
"\n");
762 if(this->_inner_rowrank!= new_rowrank)
763 this->_contiguous =
false;
765 this->_rowrank = new_rowrank;
766 this->_is_braket_form = this->_update_braket();
768 boost::intrusive_ptr<UniTensor_base> relabels(
const std::vector<cytnx_int64> &new_labels);
769 boost::intrusive_ptr<UniTensor_base> relabel(
const cytnx_int64 &inx,
const cytnx_int64 &new_label,
const bool &by_label=
false);
771 unsigned int dtype()
const{
773 cytnx_error_msg(this->_blocks.size()==0,
"[ERROR][internal] empty blocks for blockform.%s",
"\n");
775 return this->_blocks[0].dtype();
779 cytnx_error_msg(this->_blocks.size()==0,
"[ERROR][internal] empty blocks for blockform.%s",
"\n");
781 return this->_blocks[0].device();
783 std::string dtype_str()
const{
785 cytnx_error_msg(this->_blocks.size()==0,
"[ERROR][internal] empty blocks for blockform.%s",
"\n");
787 return this->_blocks[0].dtype_str();
789 std::string device_str()
const{
791 cytnx_error_msg(this->_blocks.size()==0,
"[ERROR][internal] empty blocks for blockform.%s",
"\n");
793 return this->_blocks[0].device_str();
796 boost::intrusive_ptr<UniTensor_base> astype(
const unsigned int &dtype)
const{
797 SparseUniTensor* tmp = this->clone_meta(
true,
true);
798 tmp->_blocks.resize(this->_blocks.size());
799 for(
cytnx_int64 blk=0;blk<this->_blocks.size();blk++){
800 tmp->_blocks[blk] = this->_blocks[blk].astype(dtype);
802 boost::intrusive_ptr<UniTensor_base> out(tmp);
806 void permute_(
const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank=-1,
const bool &by_label=
false);
807 boost::intrusive_ptr<UniTensor_base> permute(
const std::vector<cytnx_int64> &mapper,
const cytnx_int64 &rowrank=-1,
const bool &by_label=
false);
808 boost::intrusive_ptr<UniTensor_base> contiguous();
809 boost::intrusive_ptr<UniTensor_base> contiguous_(){
810 if(!this->_contiguous){
811 boost::intrusive_ptr<UniTensor_base> titr = this->contiguous();
812 SparseUniTensor *tmp = (SparseUniTensor*)titr.get();
813 tmp->set_meta(
this,
true,
true);
814 this->_blocks = tmp->_blocks;
817 return boost::intrusive_ptr<UniTensor_base>(
this);
820 void print_diagram(
const bool &bond_info=
false);
823 std::vector<Symmetry> syms()
const;
826 cytnx_error_msg(idx>=this->_blocks.size(),
"[ERROR][SparseUniTensor] index out of range%s",
"\n");
827 if(this->_contiguous){
828 return this->_blocks[idx].clone();
830 cytnx_error_msg(
true,
"[Developing] get block from a non-contiguous SparseUniTensor is currently not support. Call contiguous()/contiguous_() first.%s",
"\n");
834 cytnx_uint64 Nblocks()
const{
return this->_blocks.size();};
835 Tensor get_block(
const std::vector<cytnx_int64> &qnum,
const bool &force)
const{
837 cytnx_error_msg(!this->is_braket_form(),
"[ERROR][Un-physical] cannot get the block by qnums when bra-ket/in-out bonds mismatch the row/col space.\n permute to the correct physical space first, then get block.%s",
"\n");
839 if(this->_contiguous){
843 for(
int i=0;i<this->_blockqnums.size();i++){
847 if(qnum==this->_blockqnums[i]){idx=i;
break;}
849 cytnx_error_msg(idx<0,
"[ERROR][SparseUniTensor] no block with [qnum] exists in the current UniTensor.%s",
"\n");
850 return this->get_block(idx);
852 cytnx_error_msg(
true,
"[Developing] get block from a non-contiguous SparseUniTensor is currently not support. Call contiguous()/contiguous_() first.%s",
"\n");
860 cytnx_error_msg(this->is_contiguous()==
false,
"[ERROR][SparseUniTensor] cannot use get_block_() on non-contiguous UniTensor with symmetry.\n suggest options: \n 1) Call contiguous_()/contiguous() first, then call get_block_()\n 2) Try get_block()/get_blocks()%s",
"\n");
862 cytnx_error_msg(idx >= this->_blocks.size(),
"[ERROR][SparseUniTensor] index exceed the number of blocks.%s",
"\n");
864 return this->_blocks[idx];
867 cytnx_error_msg(this->is_contiguous()==
false,
"[ERROR][SparseUniTensor] cannot use get_block_() on non-contiguous UniTensor with symmetry.\n suggest options: \n 1) Call contiguous_()/contiguous() first, then call get_block_()\n 2) Try get_block()/get_blocks()%s",
"\n");
869 cytnx_error_msg(idx >= this->_blocks.size(),
"[ERROR][SparseUniTensor] index exceed the number of blocks.%s",
"\n");
871 return this->_blocks[idx];
874 Tensor& get_block_(
const std::vector<cytnx_int64> &qnum,
const bool &force){
876 cytnx_error_msg(!this->is_braket_form(),
"[ERROR][Un-physical] cannot get the block by qnums when bra-ket/in-out bonds mismatch the row/col space.\n permute to the correct physical space first, then get block.%s",
"\n");
878 cytnx_error_msg(this->is_contiguous()==
false,
"[ERROR][SparseUniTensor] cannot use get_block_() on non-contiguous UniTensor with symmetry.\n suggest options: \n 1) Call contiguous_()/contiguous() first, then call get_blocks_()\n 2) Try get_block()/get_blocks()%s",
"\n");
882 for(
int i=0;i<this->_blockqnums.size();i++){
883 if(qnum==this->_blockqnums[i]){idx=i;
break;}
885 cytnx_error_msg(idx<0,
"[ERROR][SparseUniTensor] no block with [qnum] exists in the current UniTensor.%s",
"\n");
886 return this->get_block_(idx);
889 const Tensor& get_block_(
const std::vector<cytnx_int64> &qnum,
const bool &force)
const{
891 cytnx_error_msg(!this->is_braket_form(),
"[ERROR][Un-physical] cannot get the block by qnums when bra-ket/in-out bonds mismatch the row/col space.\n permute to the correct physical space first, then get block.%s",
"\n");
893 cytnx_error_msg(this->is_contiguous()==
false,
"[ERROR][SparseUniTensor] cannot use get_block_() on non-contiguous UniTensor with symmetry.\n suggest options: \n 1) Call contiguous_()/contiguous() first, then call get_blocks_()\n 2) Try get_block()/get_blocks()%s",
"\n");
897 for(
int i=0;i<this->_blockqnums.size();i++){
898 if(qnum==this->_blockqnums[i]){idx=i;
break;}
900 cytnx_error_msg(idx<0,
"[ERROR][SparseUniTensor] no block with [qnum] exists in the current UniTensor.%s",
"\n");
901 return this->get_block_(idx);
904 std::vector<Tensor> get_blocks()
const {
905 if(this->_contiguous){
906 return vec_clone(this->_blocks);
909 boost::intrusive_ptr<UniTensor_base> tmp = this->clone();
911 SparseUniTensor *ttmp = (SparseUniTensor*)tmp.get();
912 return ttmp->_blocks;
916 const std::vector<Tensor>& get_blocks_(
const bool &silent=
false)
const {
918 if(this->_contiguous){
919 return this->_blocks;
923 cytnx_warning_msg(
true,
"[WARNING][SparseUniTensor] call get_blocks_() with a non-contiguous UniTensor should be used with caution. \ntry: \n1) get_blocks()\n2) call contiguous/contiguous_() first, then get_blocks_() to get concise results%s",
"\n");
925 return this->_blocks;
928 std::vector<Tensor>& get_blocks_(
const bool &silent=
false){
930 if(this->_contiguous){
931 return this->_blocks;
934 cytnx_warning_msg(
true,
"[WARNING][SparseUniTensor] call get_blocks_() with a non-contiguous UniTensor should be used with caution. \ntry: \n1) get_blocks()\n2) call contiguous/contiguous_() first, then get_blocks_() to get concise results%s",
"\n");
936 return this->_blocks;
940 bool same_data(
const boost::intrusive_ptr<UniTensor_base> &rhs)
const{
941 if(rhs->uten_type()!=
UTenType.Sparse)
return false;
942 if(rhs->get_blocks_(1).size() != this->get_blocks_(1).size())
return false;
944 for(
int i=0;i<rhs->get_blocks_(1).size();i++)
945 if(this->get_blocks_(1)[i].same_data(rhs->get_blocks_(1)[i])==
false)
return false;
954 cytnx_error_msg(this->is_contiguous()==
false,
"[ERROR][SparseUniTensor] cannot use put_block_() on non-contiguous UniTensor with symmetry.\n suggest options: \n 1) Call contiguous_()/contiguous() first, then call put_blocks_()\n 2) Try put_block()/put_blocks()%s",
"\n");
956 cytnx_error_msg(idx>=this->_blocks.size(),
"[ERROR][SparseUniTensor] index out of range%s",
"\n");
957 cytnx_error_msg(in.
shape()!=this->_blocks[idx].shape(),
"[ERROR][SparseUniTensor] the shape of input tensor does not match the shape of block @ idx=%d\n",idx);
958 this->_blocks[idx] = in;
961 cytnx_error_msg(idx>=this->_blocks.size(),
"[ERROR][SparseUniTensor] index out of range%s",
"\n");
962 if(this->_contiguous){
963 cytnx_error_msg(in.
shape()!=this->_blocks[idx].shape(),
"[ERROR][SparseUniTensor] the shape of input tensor does not match the shape of block @ idx=%d\n",idx);
964 this->_blocks[idx] = in.
clone();
966 cytnx_error_msg(
true,
"[Developing] put block to a non-contiguous SparseUniTensor is currently not support. Call contiguous()/contiguous_() first.%s",
"\n");
969 void put_block(
const Tensor &in,
const std::vector<cytnx_int64> &qnum,
const bool &force){
971 cytnx_error_msg(!this->is_braket_form(),
"[ERROR][Un-physical] cannot get the block by qnums when bra-ket/in-out bonds mismatch the row/col space.\n permute to the correct physical space first, then get block.%s",
"\n");
975 for(
int i=0;i<this->_blockqnums.size();i++){
976 if(qnum==this->_blockqnums[i]){idx=i;
break;}
978 cytnx_error_msg(idx<0,
"[ERROR][SparseUniTensor] no block with [qnum] exists in the current UniTensor.%s",
"\n");
979 this->put_block(in,idx);
982 void put_block_(
Tensor &in,
const std::vector<cytnx_int64> &qnum,
const bool &force){
984 cytnx_error_msg(!this->is_braket_form(),
"[ERROR][Un-physical] cannot get the block by qnums when bra-ket/in-out bonds mismatch the row/col space.\n permute to the correct physical space first, then get block.%s",
"\n");
988 for(
int i=0;i<this->_blockqnums.size();i++){
989 if(qnum==this->_blockqnums[i]){idx=i;
break;}
991 cytnx_error_msg(idx<0,
"[ERROR][SparseUniTensor] no block with [qnum] exists in the current UniTensor.%s",
"\n");
992 this->put_block_(in,idx);
996 boost::intrusive_ptr<UniTensor_base> get(
const std::vector<Accessor> &accessors){
997 cytnx_error_msg(
true,
"[ERROR][SparseUniTensor][get] cannot use get on a UniTensor with Symmetry.\n suggestion: try get_block()/get_blocks() first.%s",
"\n");
1001 void set(
const std::vector<Accessor> &accessors,
const Tensor &rhs){
1002 cytnx_error_msg(
true,
"[ERROR][SparseUniTensor][set] cannot use set on a UniTensor with Symmetry.\n suggestion: try get_block()/get_blocks() first.%s",
"\n");
1004 void reshape_(
const std::vector<cytnx_int64> &new_shape,
const cytnx_uint64 &rowrank=0){
1005 cytnx_error_msg(
true,
"[ERROR] cannot reshape a UniTensor with symmetry.%s",
"\n");
1007 boost::intrusive_ptr<UniTensor_base> reshape(
const std::vector<cytnx_int64> &new_shape,
const cytnx_uint64 &rowrank=0){
1008 cytnx_error_msg(
true,
"[ERROR] cannot reshape a UniTensor with symmetry.%s",
"\n");
1011 boost::intrusive_ptr<UniTensor_base> to_dense(){
1012 cytnx_error_msg(
true,
"[ERROR] cannot to_dense a UniTensor with symmetry.%s",
"\n");
1016 cytnx_error_msg(
true,
"[ERROR] cannot to_dense_ a UniTensor with symmetry.%s",
"\n");
1018 void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &permute_back=
true,
const bool &by_label=
true){
1021 boost::intrusive_ptr<UniTensor_base> contract(
const boost::intrusive_ptr<UniTensor_base> &rhs,
const bool &mv_elem_self=
false,
const bool &mv_elem_rhs=
false);
1022 std::vector<Bond> getTotalQnums(
const bool &physical=
false);
1023 std::vector<std::vector<cytnx_int64> > get_blocks_qnums()
const{
1024 return this->_blockqnums;
1026 ~SparseUniTensor(){};
1030 void Add_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
1031 void Add_(
const Scalar &rhs);
1033 void Mul_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
1034 void Mul_(
const Scalar &rhs);
1036 void Sub_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
1037 void Sub_(
const Scalar &rhs);
1038 void lSub_(
const Scalar &lhs);
1040 void Div_(
const boost::intrusive_ptr<UniTensor_base> &rhs);
1041 void Div_(
const Scalar &rhs);
1042 void lDiv_(
const Scalar &lhs);
1045 boost::intrusive_ptr<UniTensor_base>
Conj(){
1046 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1052 for(
int i=0;i<this->_blocks.size();i++){
1053 this->_blocks[i].Conj_();
1058 cytnx_error_msg(
true,
"[ERROR] Currently SparseUniTensor does not support inplace Trace!, call Trace() instead!%s",
"\n");
1062 boost::intrusive_ptr<UniTensor_base> Transpose(){
1063 boost::intrusive_ptr<UniTensor_base> out = this->clone();
1068 boost::intrusive_ptr<UniTensor_base> Dagger(){
1069 boost::intrusive_ptr<UniTensor_base> out = this->
Conj();
1085 const Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator)
const;
1089 const cytnx_float& at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_float &aux)
const;
1091 const cytnx_int64& at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int64 &aux)
const;
1093 const cytnx_int32& at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int32 &aux)
const;
1095 const cytnx_int16& at_for_sparse(
const std::vector<cytnx_uint64> &locator,
const cytnx_int16 &aux)
const;
1098 Scalar::Sproxy at_for_sparse(
const std::vector<cytnx_uint64> &locator);
1110 bool elem_exists(
const std::vector<cytnx_uint64> &locator)
const;
1111 void _save_dispatch(std::fstream &f)
const;
1112 void _load_dispatch(std::fstream &f);
1127 boost::intrusive_ptr<UniTensor_base> _impl;
1128 UniTensor(): _impl(
new UniTensor_base()){};
1130 this->_impl = rhs._impl;
1133 this->_impl = rhs._impl;
1164 boost::intrusive_ptr<UniTensor_base> out(
new DenseUniTensor());
1189 cytnx_warning_msg(
true,
"[DEBUG] message: entry for UniTensor(const std::vector<Bond> &bonds, const std::vector<cytnx_int64> &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int &dtype=Type.Double, const int &device = Device.cpu, const bool &is_diag=false)%s",
"\n");
1196 bool is_sym =
false;
1199 if(
bonds[i].
syms().size() != 0) is_sym =
true;
1200 else cytnx_error_msg(is_sym,
"[ERROR] cannot have bonds with mixing of symmetry and non-symmetry.%s",
"\n");
1206 cytnx_warning_msg(
true,
"[DEBUG] message: entry dispatch: UniTensor: symmetric%s",
"\n");
1209 boost::intrusive_ptr<UniTensor_base> out(
new SparseUniTensor());
1212 boost::intrusive_ptr<UniTensor_base> out(
new DenseUniTensor());
1239 this->_impl->
set_label(idx,new_label,by_label);
1281 cytnx_error_msg(this->
is_blockform(),
"[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use get_block()/get_blocks() first.%s",
"\n");
1283 DenseUniTensor* tmp =
static_cast<DenseUniTensor*
>(this->_impl.get());
1284 return tmp->_block.item<T>();
1289 cytnx_error_msg(this->
is_blockform(),
"[ERROR] cannot use item on UniTensor with Symmetry.\n suggestion: use get_block()/get_blocks() first.%s",
"\n");
1291 DenseUniTensor* tmp =
static_cast<DenseUniTensor*
>(this->_impl.get());
1292 return tmp->_block.item();
1299 unsigned int dtype()
const{
return this->_impl->dtype(); }
1301 int device()
const{
return this->_impl->device(); }
1302 std::string
name()
const {
return this->_impl->name();}
1303 std::string
dtype_str()
const{
return this->_impl->dtype_str();}
1304 std::string
device_str()
const{
return this->_impl->device_str();}
1307 bool is_diag()
const{
return this->_impl->is_diag(); }
1308 bool is_tag()
const {
return this->_impl->is_tag();}
1309 std::vector<Symmetry>
syms()
const{
1310 return this->_impl->syms();
1313 return this->_impl->is_braket_form();
1315 const std::vector<cytnx_int64>&
labels()
const{
return this->_impl->labels();}
1316 const std::vector<Bond> &
bonds()
const {
return this->_impl->bonds();}
1317 std::vector<Bond> &
bonds() {
return this->_impl->bonds();}
1318 std::vector<cytnx_uint64>
shape()
const{
return this->_impl->shape();}
1324 out._impl = this->_impl->
to(
device);
1329 out._impl = this->_impl->
clone();
1334 out._impl = this->_impl->
relabels(new_labels);
1339 out._impl = this->_impl->
relabel(inx,new_label,by_label);
1345 if(this->
dtype()==dtype){
1346 out._impl = this->_impl;
1355 this->_impl->permute_(mapper,
rowrank,by_label);
1363 this->_impl = this->_impl->contiguous_();
1366 this->_impl->print_diagram(bond_info);
1370 T&
at(
const std::vector<cytnx_uint64> &locator){
1373 if(this->_impl->elem_exists(locator)){
1375 return this->_impl->at_for_sparse(locator,aux);
1377 cytnx_error_msg(
true,
"[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
"\n");
1386 const T&
at(
const std::vector<cytnx_uint64> &locator)
const{
1389 if(this->_impl->elem_exists(locator)){
1391 return this->_impl->at_for_sparse(locator,aux);
1393 cytnx_error_msg(
true,
"[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
"\n");
1401 const Scalar::Sproxy
at(
const std::vector<cytnx_uint64> &locator)
const{
1403 if(this->_impl->elem_exists(locator)){
1404 return this->_impl->at_for_sparse(locator);
1406 cytnx_error_msg(
true,
"[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
"\n");
1413 Scalar::Sproxy
at(
const std::vector<cytnx_uint64> &locator){
1415 if(this->_impl->elem_exists(locator)){
1416 return this->_impl->at_for_sparse(locator);
1418 cytnx_error_msg(
true,
"[ERROR][SparseUniTensor] invalid location. break qnum block.%s",
"\n");
1430 return this->_impl->get_block(idx);
1435 return this->_impl->get_block(qnum,force);
1437 Tensor get_block(
const std::initializer_list<cytnx_int64> &qnum,
const bool &force=
false)
const{
1438 std::vector<cytnx_int64> tmp = qnum;
1444 return this->_impl->get_block_(idx);
1449 return this->_impl->get_block_(idx);
1454 return this->_impl->get_block_(qnum,force);
1457 std::vector<cytnx_int64> tmp = qnum;
1464 return this->_impl->get_block_(qnum,force);
1466 const Tensor&
get_block_(
const std::initializer_list<cytnx_int64> &qnum,
const bool &force=
false)
const{
1467 std::vector<cytnx_int64> tmp = qnum;
1468 return this->_impl->get_block_(tmp,force);
1474 return this->_impl->get_blocks();
1478 const std::vector<Tensor>&
get_blocks_(
const bool &silent=
false)
const {
1479 return this->_impl->get_blocks_(silent);
1483 return this->_impl->get_blocks_(silent);
1488 this->_impl->put_block(in,idx);
1491 void put_block(
const Tensor &in,
const std::vector<cytnx_int64> &qnum,
const bool &force){
1492 this->_impl->put_block(in,qnum, force);
1496 this->_impl->put_block_(in,idx);
1500 this->_impl->put_block_(in,qnum,force);
1504 out._impl = this->_impl->
get(accessors);
1507 void set(
const std::vector<Accessor> &accessors,
const Tensor &rhs){
1508 this->_impl->set(accessors, rhs);
1516 this->_impl->reshape_(new_shape,
rowrank);
1520 out._impl = this->_impl->
to_dense();
1524 this->_impl->to_dense_();
1526 void combineBonds(
const std::vector<cytnx_int64> &indicators,
const bool &permute_back=
true,
const bool &by_label=
true){
1527 this->_impl->combineBonds(indicators,permute_back,by_label);
1531 out._impl = this->_impl->
contract(inR._impl,mv_elem_self,mv_elem_rhs);
1535 return this->_impl->getTotalQnums(physical);
1538 return this->_impl->get_blocks_qnums();
1544 if(this->_impl->uten_type() != rhs._impl->
uten_type())
1549 return this->_impl->same_data(rhs._impl);
1553 this->_impl->
Add_(rhs._impl);
1558 this->_impl->
Mul_(rhs._impl);
1563 this->_impl->
Sub_(rhs._impl);
1568 this->_impl->
Div_(rhs._impl);
1573 this->_impl->
Add_(rhs);
1578 this->_impl->
Mul_(rhs);
1583 this->_impl->
Sub_(rhs);
1588 this->_impl->
Div_(rhs);
1602 return this->_impl->
Norm();
1642 out._impl = this->_impl->
Conj();
1647 this->_impl->
Conj_();
1664 out._impl = this->_impl->
Trace(a,b,by_label);
1669 this->_impl->
Trace_(a,b,by_label);
1675 out._impl = this->_impl->
Dagger();
1697 return this->_impl->elem_exists(locator);
1702 T
get_elem(
const std::vector<cytnx_uint64> &locator)
const{
1703 return this->at<T>(locator);
1708 void set_elem(
const std::vector<cytnx_uint64> &locator,
const T2&rc){
1710 this->
at(locator) = rc;
1715 void Save(
const std::string &fname)
const;
1716 void Save(
const char* fname)
const;
1721 this->_impl->
truncate_(bond_idx,dim,by_label);
1732 void _Load(std::fstream &f);
1733 void _Save(std::fstream &f)
const;
1775 template<
class ... T>
1777 TNlist.push_back(in);
1792 template<
class ... T>
1794 std::vector<UniTensor> TNlist;
Definition Scalar.hpp:1751
an tensor (multi-dimensional array)
Definition Tensor.hpp:344
void to_(const int &device)
move the current Tensor to the device.
Definition Tensor.hpp:836
Tensor contiguous_()
Make the Tensor contiguous by coalescing the memory (storage), inplacely.
Definition Tensor.hpp:923
unsigned int dtype() const
the dtype-id of the Tensor
Definition Tensor.hpp:729
Tensor contiguous() const
Make the Tensor contiguous by coalescing the memory (storage).
Definition Tensor.hpp:902
T & at(const std::vector< cytnx_uint64 > &locator)
[C++ only] get an element at specific location.
Definition Tensor.hpp:1057
Tensor clone() const
return a clone of the current Tensor.
Definition Tensor.hpp:787
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:1185
Tensor Norm() const
Definition Tensor.cpp:1195
Tensor astype(const int &new_type) const
return a new Tensor that cast to different dtype.
Definition Tensor.hpp:1025
const bool & is_contiguous() const
Definition Tensor.hpp:840
Tensor & Conj_()
Definition Tensor.cpp:1180
int device() const
the device-id of the Tensor
Definition Tensor.hpp:736
Tensor get(const std::vector< cytnx::Accessor > &accessors) const
get elements using Accessor (C++ API) / slices (python API)
Definition Tensor.hpp:1152
const std::vector< cytnx_uint64 > & shape() const
the shape of the Tensor
Definition Tensor.hpp:757
An Enhanced tensor specifically designed for physical Tensor network simulation.
Definition UniTensor.hpp:1122
UniTensor to(const int &device) const
Definition UniTensor.hpp:1322
UniTensor & operator*=(const UniTensor &rhs)
Definition UniTensor.hpp:1617
UniTensor relabels(const std::vector< cytnx_int64 > &new_labels) const
Definition UniTensor.hpp:1332
std::vector< Tensor > & get_blocks_(const bool &silent=false)
Definition UniTensor.hpp:1482
UniTensor & operator/=(const UniTensor &rhs)
Definition UniTensor.hpp:1613
T & item()
Definition UniTensor.hpp:1279
void combineBonds(const std::vector< cytnx_int64 > &indicators, const bool &permute_back=true, const bool &by_label=true)
Definition UniTensor.hpp:1526
bool is_contiguous() const
Definition UniTensor.hpp:1306
T get_elem(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:1702
UniTensor Div(const UniTensor &rhs) const
Definition UniTensor.cpp:32
const Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:1466
const std::vector< cytnx_int64 > & labels() const
Definition UniTensor.hpp:1315
Tensor & get_block_(const std::vector< cytnx_int64 > &qnum, const bool &force=false)
Definition UniTensor.hpp:1453
UniTensor & operator+=(const UniTensor &rhs)
Definition UniTensor.hpp:1605
void to_dense_()
Definition UniTensor.hpp:1523
UniTensor reshape(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Definition UniTensor.hpp:1510
std::vector< Tensor > get_blocks() const
Definition UniTensor.hpp:1473
bool is_tag() const
Definition UniTensor.hpp:1308
std::string uten_type_str() const
Definition UniTensor.hpp:1305
UniTensor permute(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1, const bool &by_label=false)
Definition UniTensor.hpp:1353
void put_block(const Tensor &in, const std::vector< cytnx_int64 > &qnum, const bool &force)
Definition UniTensor.hpp:1491
static UniTensor Load(const std::string &fname)
Definition UniTensor.cpp:158
UniTensor & tag()
Definition UniTensor.hpp:1684
UniTensor get(const std::vector< Accessor > &accessors) const
Definition UniTensor.hpp:1502
void Save(const std::string &fname) const
Definition UniTensor.cpp:137
UniTensor & operator-=(const Scalar &rhs)
Definition UniTensor.hpp:1625
cytnx_uint64 rowrank() const
Definition UniTensor.hpp:1298
Tensor Norm() const
Definition UniTensor.hpp:1601
void Init(const std::vector< Bond > &bonds, const std::vector< cytnx_int64 > &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const bool &is_diag=false)
Definition UniTensor.hpp:1193
UniTensor & Sub_(const Scalar &rhs)
Definition UniTensor.hpp:1582
UniTensor & operator/=(const Scalar &rhs)
Definition UniTensor.hpp:1629
const bool & is_braket_form() const
Definition UniTensor.hpp:1312
void set_elem(const std::vector< cytnx_uint64 > &locator, const T2 &rc)
Definition UniTensor.hpp:1708
UniTensor relabel(const cytnx_int64 &inx, const cytnx_int64 &new_label, const bool &by_label=false) const
Definition UniTensor.hpp:1337
UniTensor(const std::vector< Bond > &bonds, const std::vector< cytnx_int64 > &in_labels={}, const cytnx_int64 &rowrank=-1, const unsigned int &dtype=Type.Double, const int &device=Device.cpu, const bool &is_diag=false)
Initialize a UniTensor.
Definition UniTensor.hpp:1187
std::vector< cytnx_uint64 > shape() const
Definition UniTensor.hpp:1318
UniTensor to_dense()
Definition UniTensor.hpp:1518
void reshape_(const std::vector< cytnx_int64 > &new_shape, const cytnx_uint64 &rowrank=0)
Definition UniTensor.hpp:1515
const Tensor & get_block_(const std::vector< cytnx_int64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:1463
std::string name() const
Definition UniTensor.hpp:1302
UniTensor & Add_(const Scalar &rhs)
Definition UniTensor.hpp:1572
std::vector< Bond > getTotalQnums(const bool physical=false) const
Definition UniTensor.hpp:1534
Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:1413
bool same_data(const UniTensor &rhs) const
Definition UniTensor.hpp:1541
UniTensor astype(const unsigned int &dtype) const
Definition UniTensor.hpp:1343
UniTensor Transpose() const
Definition UniTensor.hpp:1652
UniTensor & Dagger_()
Definition UniTensor.hpp:1679
void print_diagram(const bool &bond_info=false)
Definition UniTensor.hpp:1365
std::vector< Bond > & bonds()
Definition UniTensor.hpp:1317
T & at(const std::vector< cytnx_uint64 > &locator)
Definition UniTensor.hpp:1370
UniTensor & truncate_(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim, const bool &by_label=false)
Definition UniTensor.hpp:1720
UniTensor & set_label(const cytnx_int64 &idx, const cytnx_int64 &new_label, const bool &by_label=false)
set a new label for bond at the assigned index.
Definition UniTensor.hpp:1238
std::vector< std::vector< cytnx_int64 > > get_blocks_qnums() const
Definition UniTensor.hpp:1537
UniTensor Trace(const cytnx_int64 &a=0, const cytnx_int64 &b=1, const bool &by_label=false) const
Definition UniTensor.hpp:1662
UniTensor contiguous() const
Definition UniTensor.hpp:1357
Tensor get_block(const cytnx_uint64 &idx=0) const
Definition UniTensor.hpp:1429
const T & at(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:1386
UniTensor & operator*=(const Scalar &rhs)
Definition UniTensor.hpp:1633
void contiguous_()
Definition UniTensor.hpp:1362
UniTensor & set_labels(const std::vector< cytnx_int64 > &new_labels)
change a new label for bond with original label.
Definition UniTensor.hpp:1269
std::vector< Symmetry > syms() const
Definition UniTensor.hpp:1309
UniTensor & Mul_(const UniTensor &rhs)
Definition UniTensor.hpp:1557
void put_block_(Tensor &in, const cytnx_uint64 &idx=0)
Definition UniTensor.hpp:1495
void put_block_(Tensor &in, const std::vector< cytnx_int64 > &qnum, const bool &force)
Definition UniTensor.hpp:1499
bool is_diag() const
Definition UniTensor.hpp:1307
int device() const
Definition UniTensor.hpp:1301
UniTensor & Pow_(const double &p)
Definition UniTensor.cpp:14
void set(const std::vector< Accessor > &accessors, const Tensor &rhs)
Definition UniTensor.hpp:1507
std::string dtype_str() const
Definition UniTensor.hpp:1303
UniTensor & operator+=(const Scalar &rhs)
Definition UniTensor.hpp:1621
UniTensor & Div_(const UniTensor &rhs)
Definition UniTensor.hpp:1567
UniTensor & Div_(const Scalar &rhs)
Definition UniTensor.hpp:1587
cytnx_uint64 rank() const
Definition UniTensor.hpp:1297
void to_(const int &device)
Definition UniTensor.hpp:1321
UniTensor & set_name(const std::string &in)
set the name of the UniTensor
Definition UniTensor.hpp:1224
UniTensor & Add_(const UniTensor &rhs)
Definition UniTensor.hpp:1552
Tensor & get_block_(const std::initializer_list< cytnx_int64 > &qnum, const bool &force=false)
Definition UniTensor.hpp:1456
unsigned int dtype() const
Definition UniTensor.hpp:1299
UniTensor Pow(const double &p) const
Definition UniTensor.cpp:11
UniTensor & Mul_(const Scalar &rhs)
Definition UniTensor.hpp:1577
UniTensor & operator-=(const UniTensor &rhs)
Definition UniTensor.hpp:1609
bool is_blockform() const
Definition UniTensor.hpp:1319
UniTensor Dagger() const
Definition UniTensor.hpp:1673
const std::vector< Tensor > & get_blocks_(const bool &silent=false) const
Definition UniTensor.hpp:1478
bool elem_exists(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:1696
UniTensor & Sub_(const UniTensor &rhs)
Definition UniTensor.hpp:1562
UniTensor contract(const UniTensor &inR, const bool &mv_elem_self=false, const bool &mv_elem_rhs=false) const
Definition UniTensor.hpp:1529
void put_block(const Tensor &in, const cytnx_uint64 &idx=0)
Definition UniTensor.hpp:1487
const Tensor & get_block_(const cytnx_uint64 &idx=0) const
Definition UniTensor.hpp:1443
UniTensor Mul(const UniTensor &rhs) const
Definition UniTensor.cpp:39
UniTensor & Trace_(const cytnx_int64 &a=0, const cytnx_int64 &b=1, const bool &by_label=false)
Definition UniTensor.hpp:1668
Tensor get_block(const std::vector< cytnx_int64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:1434
const std::vector< Bond > & bonds() const
Definition UniTensor.hpp:1316
UniTensor & Transpose_()
Definition UniTensor.hpp:1657
UniTensor clone() const
Definition UniTensor.hpp:1327
Scalar::Sproxy item() const
Definition UniTensor.hpp:1288
UniTensor truncate(const cytnx_int64 &bond_idx, const cytnx_uint64 &dim, const bool &by_label=false) const
Definition UniTensor.hpp:1724
void Init(const Tensor &in_tensor, const cytnx_uint64 &rowrank, const bool &is_diag=false)
Definition UniTensor.hpp:1163
std::string device_str() const
Definition UniTensor.hpp:1304
UniTensor Sub(const UniTensor &rhs) const
Definition UniTensor.cpp:25
UniTensor & Conj_()
Definition UniTensor.hpp:1646
cytnx_uint64 Nblocks() const
Definition UniTensor.hpp:1296
UniTensor Conj()
Definition UniTensor.hpp:1640
UniTensor Add(const UniTensor &rhs) const
Definition UniTensor.cpp:18
UniTensor & set_rowrank(const cytnx_uint64 &new_rowrank)
Definition UniTensor.hpp:1273
void permute_(const std::vector< cytnx_int64 > &mapper, const cytnx_int64 &rowrank=-1, const bool &by_label=false)
Definition UniTensor.hpp:1354
UniTensor(const Tensor &in_tensor, const cytnx_uint64 &rowrank, const bool &is_diag=false)
Initialize a UniTensor with cytnx::Tensor.
Definition UniTensor.hpp:1160
Tensor get_block(const std::initializer_list< cytnx_int64 > &qnum, const bool &force=false) const
Definition UniTensor.hpp:1437
const Scalar::Sproxy at(const std::vector< cytnx_uint64 > &locator) const
Definition UniTensor.hpp:1401
int uten_type() const
Definition UniTensor.hpp:1300
Tensor & get_block_(const cytnx_uint64 &idx=0)
Definition UniTensor.hpp:1448
#define cytnx_warning_msg(is_true, format,...)
Definition cytnx_error.hpp:37
#define cytnx_error_msg(is_true, format,...)
Definition cytnx_error.hpp:18
Tensor Conj(const Tensor &Tin)
Conjugate all the element in Tensor.
Tensor Norm(const Tensor &Tl)
calculate the norm of a tensor.
cytnx::UniTensor Trace(const cytnx::UniTensor &Tin, const cytnx_int64 &a=0, const cytnx_int64 &b=1, const bool &by_label=false)
void Conj_(Tensor &Tin)
inplace perform Conjugate on all the element in Tensor.
Definition Accessor.hpp:12
Device_class Device
Definition Device.cpp:105
double cytnx_double
Definition Type.hpp:20
UniTensorType_class UTenType
Definition UniTensor_base.cpp:21
uint32_t cytnx_uint32
Definition Type.hpp:23
std::complex< double > cytnx_complex128
Definition Type.hpp:30
float cytnx_float
Definition Type.hpp:21
std::ostream & operator<<(std::ostream &os, const Scalar &in)
Definition Scalar.cpp:14
int16_t cytnx_int16
Definition Type.hpp:27
std::complex< float > cytnx_complex64
Definition Type.hpp:29
int32_t cytnx_int32
Definition Type.hpp:26
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.
Definition UniTensor_base.cpp:379
uint16_t cytnx_uint16
Definition Type.hpp:24
void _resolve_CT(std::vector< UniTensor > &TNlist)
Definition UniTensor_base.cpp:383
uint64_t cytnx_uint64
Definition Type.hpp:22
int64_t cytnx_int64
Definition Type.hpp:25
Type_class Type
Definition Type.cpp:143
UniTensor Contracts(const std::vector< UniTensor > &TNs)
Contract multiple UniTensor by tracing the ranks with common labels with pairwise operation.
Definition UniTensor_base.cpp:384