From a342032b5867879c308b640460da0198410b4910 Mon Sep 17 00:00:00 2001 From: Jiri Pittner Date: Thu, 20 Nov 2025 16:00:53 +0100 Subject: [PATCH] simplified (inverse)Tucker for non-iverting index order --- t.cc | 31 ++++++++++++++++++++++++++++++- tensor.cc | 40 ++++++++++++++++++++++------------------ tensor.h | 6 +++--- 3 files changed, 55 insertions(+), 22 deletions(-) diff --git a/t.cc b/t.cc index 8499a53..4185717 100644 --- a/t.cc +++ b/t.cc @@ -3733,6 +3733,7 @@ INDEXGROUP shape; { shape.number=r; shape.symmetry= 1; + //shape.symmetry= -1; shape.range=n; shape.offset=0; } @@ -4392,7 +4393,7 @@ cout <<"Error = "<<(z-zzz).norm()<>r>>n>>inv; +NRVec shape(r); +for(int i=0; i x(shape); +x.randomize(1.); +cout< x0(x); +x0.copyonwrite(); +NRVec > dec=x.Tucker(1e-12,inv); +cout<<"Tucker\n"< y = x.inverseTucker(dec,inv); +cout <<"invTucker\n"< p(r); - for(int i=1; i<=r; ++i) p[r-i+1]=i; - *this = permute_index_groups(p); - } return ret; } - template Tensor Tensor::inverseTucker(const NRVec > &x, bool inverseorder) const { @@ -1784,9 +1779,11 @@ if(rank()!=x.size()) laerror("input of inverseTucker does not match rank"); Tensor tmp(*this); Tensor r; if(!is_flat()) laerror("inverseTucker only for flat tensors as produced by Tucker"); +if(inverseorder) +{ for(int i=0; i mat(x[i],true); + Tensor mat(x[i],true); //flat tensor from a matrix r= tmp.contraction(i,0,mat,0,0,(T)1,false,false); if(i=0; --i) { - NRPerm p(r.rank()); - for(int i=1; i<=r.rank(); ++i) p[r.rank()-i+1]=i; - return r.permute_index_groups(p); + Tensor mat(x[i],true); //flat tensor from a matrix + r= tmp.contraction(rank()-1,0,mat,0,0,(T)1,false,false); //the current index will be the last after previous contractions + if(i>0) + { + tmp=r; + r.deallocate(); + } } -else - return r; +} +return r; } @@ -2116,7 +2120,7 @@ NRVec > antigroups; parse_antisymmetrizer(antisymmetrizer,antigroups,antinames); //check the names make sense and fill in the possibly missing ones as separate group -if(antinames.size()>tmpnames.size()) laerror("too many indices in the antisymmetrizet"); +if(antinames.size()>tmpnames.size()) laerror("too many indices in the antisymmetrizer"); bitvector isexplicit(tmpnames.size()); isexplicit.clear(); for(int i=0; i &x); explicit Tensor(const NRMat &x, bool flat=false); explicit Tensor(const NRSMat &x); - NRMat matrix() const {return NRMat(data,data.size()/groupsizes[0],groupsizes[0],0);}; //reinterpret as matrix with column index being the tensor's leftmost index group (typically the unwound single index) + NRMat matrix() const {return NRMat(data,data.size()/groupsizes[0],groupsizes[0],0);}; //reinterpret as matrix with column index being the tensor's leftmost index group (typically the unwound single index) //@@@generalize to column index being n leftmost tensor index groups bool is_named() const {if(names.size()==0) return false; if(names.size()!=myrank) laerror("bad number of index names"); return true;}; bool is_uniquely_named() const; //no repeated names @@ -399,8 +399,8 @@ public: Tensor merge_indices(const INDEXLIST &il, int symmetry=0) const; //opposite to flatten (merging with optional symmetrization/antisymmetrization and compression) Tensor merge_indices(const NRVec &nl, int symmetry=0) const {return merge_indices(findindexlist(nl),symmetry);}; - NRVec > Tucker(typename LA_traits::normtype thr=1e-12, bool inverseorder=true); //HOSVD-Tucker decomposition, return core tensor in *this, flattened - Tensor inverseTucker(const NRVec > &x, bool inverseorder=true) const; //rebuild the original tensor from Tucker + NRVec > Tucker(typename LA_traits::normtype thr=1e-12, bool inverseorder=false); //HOSVD-Tucker decomposition, return core tensor in *this, flattened + Tensor inverseTucker(const NRVec > &x, bool inverseorder=false) const; //rebuild the original tensor from Tucker };