bugfix unwind_index; Tucker works
This commit is contained in:
		
							parent
							
								
									ba58060c2d
								
							
						
					
					
						commit
						12cf5b76a5
					
				
							
								
								
									
										83
									
								
								t.cc
									
									
									
									
									
								
							
							
						
						
									
										83
									
								
								t.cc
									
									
									
									
									
								
							@ -3275,13 +3275,20 @@ if(0)
 | 
				
			|||||||
int n=5;
 | 
					int n=5;
 | 
				
			||||||
INDEXGROUP g;
 | 
					INDEXGROUP g;
 | 
				
			||||||
g.number=4;
 | 
					g.number=4;
 | 
				
			||||||
g.symmetry= -1;
 | 
					g.symmetry= 0;
 | 
				
			||||||
 | 
					//g.symmetry= 1;
 | 
				
			||||||
 | 
					//g.symmetry= -1;
 | 
				
			||||||
g.offset=0;
 | 
					g.offset=0;
 | 
				
			||||||
g.range=n;
 | 
					g.range=n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Tensor<double> e(g);
 | 
					Tensor<double> e(g);
 | 
				
			||||||
e.randomize(1.);
 | 
					e.randomize(1.);
 | 
				
			||||||
Tensor<double> eu = e.unwind_index(0,1);
 | 
					Tensor<double> eu = e.unwind_index(0,1);
 | 
				
			||||||
 | 
					Tensor<double> eu2 = e.unwind_index(0,2);
 | 
				
			||||||
 | 
					Tensor<double> eu3 = e.unwind_index(0,3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cout <<e<<endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
for(int i=0; i<n; ++i)
 | 
					for(int i=0; i<n; ++i)
 | 
				
			||||||
        for(int j=0; j<n; ++j)
 | 
					        for(int j=0; j<n; ++j)
 | 
				
			||||||
@ -3289,11 +3296,47 @@ for(int i=0; i<n; ++i)
 | 
				
			|||||||
                        for(int l=0; l<n; ++l)
 | 
					                        for(int l=0; l<n; ++l)
 | 
				
			||||||
                                {
 | 
					                                {
 | 
				
			||||||
				if(e(i,j,k,l)!=eu(j,i,k,l)) laerror("error in unwind_index");
 | 
									if(e(i,j,k,l)!=eu(j,i,k,l)) laerror("error in unwind_index");
 | 
				
			||||||
 | 
									if(e(i,j,k,l)!=eu2(k,i,j,l)) laerror("error2 in unwind_index");
 | 
				
			||||||
 | 
									if(e(i,j,k,l)!=eu3(l,i,j,k)) laerror("error3 in unwind_index");
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
cout <<e;
 | 
					 | 
				
			||||||
cout <<eu;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(0)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					int n=2;
 | 
				
			||||||
 | 
					NRVec<INDEXGROUP> g(4);
 | 
				
			||||||
 | 
					for(int i=0; i<4; ++i)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						g[i].number=1;
 | 
				
			||||||
 | 
						g[i].symmetry= 0;
 | 
				
			||||||
 | 
						g[i].offset=0;
 | 
				
			||||||
 | 
						g[i].range=n+i;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Tensor<double> e(g);
 | 
				
			||||||
 | 
					e.randomize(1.);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cout<< "E shape = "<<e.shape<<endl;
 | 
				
			||||||
 | 
					Tensor<double> eu = e.unwind_index(1,0);
 | 
				
			||||||
 | 
					cout<< "Eu shape = "<<eu.shape<<endl;
 | 
				
			||||||
 | 
					Tensor<double> eu2 = e.unwind_index(2,0);
 | 
				
			||||||
 | 
					cout<< "Eu2 shape = "<<eu2.shape<<endl;
 | 
				
			||||||
 | 
					Tensor<double> eu3 = e.unwind_index(3,0);
 | 
				
			||||||
 | 
					cout<< "Eu3 shape = "<<eu3.shape<<endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for(int i=0; i<n; ++i)
 | 
				
			||||||
 | 
					        for(int j=0; j<n+1; ++j)
 | 
				
			||||||
 | 
					                for(int k=0; k<n+2; ++k)
 | 
				
			||||||
 | 
					                        for(int l=0; l<n+3; ++l)
 | 
				
			||||||
 | 
					                                {
 | 
				
			||||||
 | 
					                                if(e(i,j,k,l)!=eu(j,i,k,l)) laerror("error in unwind_index");
 | 
				
			||||||
 | 
									if(e(i,j,k,l)!=eu2(k,i,j,l)) laerror("error2 in unwind_index");
 | 
				
			||||||
 | 
					                                if(e(i,j,k,l)!=eu3(l,i,j,k)) laerror("error3 in unwind_index");
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(0)
 | 
					if(0)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -3355,7 +3398,6 @@ for(int i=0; i<n; ++i)
 | 
				
			|||||||
//cout <<c;
 | 
					//cout <<c;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//test Tensor apply_permutation_algebra
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
//test unwind_indices
 | 
					//test unwind_indices
 | 
				
			||||||
if(0)
 | 
					if(0)
 | 
				
			||||||
@ -3390,7 +3432,8 @@ if(0)
 | 
				
			|||||||
int n=5;
 | 
					int n=5;
 | 
				
			||||||
INDEXGROUP g;
 | 
					INDEXGROUP g;
 | 
				
			||||||
g.number=2;
 | 
					g.number=2;
 | 
				
			||||||
g.symmetry= 1;
 | 
					//g.symmetry= 1;
 | 
				
			||||||
 | 
					g.symmetry= 0;
 | 
				
			||||||
g.offset=0;
 | 
					g.offset=0;
 | 
				
			||||||
g.range=n;
 | 
					g.range=n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -3557,7 +3600,7 @@ y.apply_permutation_algebra(rhsvec,b,false,1.,0.);
 | 
				
			|||||||
cout <<y;
 | 
					cout <<y;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(1)
 | 
					if(0)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
//compact SVD
 | 
					//compact SVD
 | 
				
			||||||
NRMat<double> a;
 | 
					NRMat<double> a;
 | 
				
			||||||
@ -3576,5 +3619,33 @@ cout << "Error "<<(u*sdiag*vt-abak).norm()<<endl;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(1)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					//tucker of a flat tensor
 | 
				
			||||||
 | 
					int r,n;
 | 
				
			||||||
 | 
					cin>>r>>n;
 | 
				
			||||||
 | 
					NRVec<INDEXGROUP> shape(r);
 | 
				
			||||||
 | 
					for(int i=0; i<r; ++i)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						shape[i].number=1;
 | 
				
			||||||
 | 
						shape[i].symmetry=0;
 | 
				
			||||||
 | 
						shape[i].range=n+i;
 | 
				
			||||||
 | 
						shape[i].offset=0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					Tensor<double> x(shape);
 | 
				
			||||||
 | 
					x.randomize(1.);
 | 
				
			||||||
 | 
					cout<<x;
 | 
				
			||||||
 | 
					Tensor<double> x0(x);
 | 
				
			||||||
 | 
					x0.copyonwrite();
 | 
				
			||||||
 | 
					bool inv=true;
 | 
				
			||||||
 | 
					NRVec<NRMat<double> > dec=x.Tucker(1e-12,inv);
 | 
				
			||||||
 | 
					cout<<"Tucker\n"<<x<<endl;
 | 
				
			||||||
 | 
					cout<<dec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Tensor<double> y = x.inverseTucker(dec,inv);
 | 
				
			||||||
 | 
					cout <<"invTucker\n"<<y;
 | 
				
			||||||
 | 
					cout <<"Error = "<<(x0-y).norm()<<endl;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}//main
 | 
					}//main
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										113
									
								
								tensor.cc
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								tensor.cc
									
									
									
									
									
								
							@ -34,7 +34,7 @@ int r=0;
 | 
				
			|||||||
for(int i=0; i<shape.size(); ++i)
 | 
					for(int i=0; i<shape.size(); ++i)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
	const indexgroup *sh = &(* const_cast<const NRVec<indexgroup> *>(&shape))[i];
 | 
						const indexgroup *sh = &(* const_cast<const NRVec<indexgroup> *>(&shape))[i];
 | 
				
			||||||
        if(sh->number==0) laerror("empty index group");
 | 
					        if(sh->number<=0) laerror("empty index group"); //we do not support scalar as a trivial case
 | 
				
			||||||
        r+=sh->number;
 | 
					        r+=sh->number;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
myrank=r;
 | 
					myrank=r;
 | 
				
			||||||
@ -46,6 +46,7 @@ return r;
 | 
				
			|||||||
template<typename T>
 | 
					template<typename T>
 | 
				
			||||||
LA_largeindex Tensor<T>::calcsize()
 | 
					LA_largeindex Tensor<T>::calcsize()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					if(shape.size()==0) laerror("tensor must have rank at least 1");
 | 
				
			||||||
groupsizes.resize(shape.size()); 
 | 
					groupsizes.resize(shape.size()); 
 | 
				
			||||||
cumsizes.resize(shape.size());
 | 
					cumsizes.resize(shape.size());
 | 
				
			||||||
LA_largeindex s=1;
 | 
					LA_largeindex s=1;
 | 
				
			||||||
@ -330,11 +331,11 @@ calcsize();
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<typename T>
 | 
					template<typename T>
 | 
				
			||||||
Tensor<T>::Tensor(const NRMat<T> &x)
 | 
					Tensor<T>::Tensor(const NRMat<T> &x, bool flat)
 | 
				
			||||||
: data(&x(0,0),x.nrows()*x.ncols())
 | 
					: data(&x(0,0),x.nrows()*x.ncols())
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
myrank=2;
 | 
					myrank=2;
 | 
				
			||||||
if(x.nrows()==x.ncols())
 | 
					if(x.nrows()==x.ncols() && !flat)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	shape.resize(1);
 | 
						shape.resize(1);
 | 
				
			||||||
	shape[0].number=2;
 | 
						shape[0].number=2;
 | 
				
			||||||
@ -542,7 +543,9 @@ help_t<T>->data[target] = *v;
 | 
				
			|||||||
template<typename T>
 | 
					template<typename T>
 | 
				
			||||||
Tensor<T> Tensor<T>::permute_index_groups(const NRPerm<int> &p) const
 | 
					Tensor<T> Tensor<T>::permute_index_groups(const NRPerm<int> &p) const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
NRVec<indexgroup> newshape=shape.permuted(p);
 | 
					//std::cout <<"permute_index_groups permutation = "<<p<<std::endl;
 | 
				
			||||||
 | 
					NRVec<indexgroup> newshape=shape.permuted(p,true);
 | 
				
			||||||
 | 
					//std::cout <<"permute_index_groups newshape = "<<newshape<<std::endl;
 | 
				
			||||||
Tensor<T> r(newshape);
 | 
					Tensor<T> r(newshape);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//prepare statics for the callback
 | 
					//prepare statics for the callback
 | 
				
			||||||
@ -569,12 +572,7 @@ return J;
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int flatposition(const INDEX &i, const NRVec<indexgroup> &shape) 
 | 
					int flatposition(const INDEX &i, const NRVec<indexgroup> &shape) 
 | 
				
			||||||
{
 | 
					{return flatposition(i.group,i.index,shape);}
 | 
				
			||||||
int ii=0;
 | 
					 | 
				
			||||||
for(int g=0; g<i.group; ++g) ii+= shape[g].number;
 | 
					 | 
				
			||||||
ii += i.index;
 | 
					 | 
				
			||||||
return ii;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
int flatposition(int group, int index, const NRVec<indexgroup> &shape)
 | 
					int flatposition(int group, int index, const NRVec<indexgroup> &shape)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -584,12 +582,26 @@ ii += index;
 | 
				
			|||||||
return ii;
 | 
					return ii;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INDEX indexposition(int flatindex, const NRVec<indexgroup> &shape)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					INDEX I={0,0};
 | 
				
			||||||
 | 
					if(flatindex<0) laerror("illegal index in indexposition");
 | 
				
			||||||
 | 
					for(int g=0; g<shape.size(); ++g)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						I.group=g;
 | 
				
			||||||
 | 
						if(flatindex<shape[g].number) {I.index=flatindex; return I;}
 | 
				
			||||||
 | 
						flatindex-=shape[g].number;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					laerror("flatindex out of range");
 | 
				
			||||||
 | 
					return I;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<typename T>
 | 
					template<typename T>
 | 
				
			||||||
static void unwind_callback(const SUPERINDEX &I, T *v)
 | 
					static void unwind_callback(const SUPERINDEX &I, T *v)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
FLATINDEX J = superindex2flat(I);
 | 
					FLATINDEX J = superindex2flat(I);
 | 
				
			||||||
FLATINDEX JP = J.permuted(*help_p,true);
 | 
					FLATINDEX JP = J.permuted(*help_p,false);
 | 
				
			||||||
//std::cout <<"TEST unwind_callback: from "<<JP<<" TO "<<J<<std::endl;
 | 
					//std::cout <<"TEST unwind_callback: from "<<JP<<" TO "<<J<<std::endl;
 | 
				
			||||||
*v = (*help_tt<T>)(JP); //rhs operator() generates the redundant elements for the unwinded lhs tensor
 | 
					*v = (*help_tt<T>)(JP); //rhs operator() generates the redundant elements for the unwinded lhs tensor
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -637,6 +649,8 @@ for(int i=0; i<shape.size(); ++i)
 | 
				
			|||||||
	else flatindex += shape[i].number;
 | 
						else flatindex += shape[i].number;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::cout <<"unwind new shape = "<<newshape<<std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Tensor<T> r(newshape);
 | 
					Tensor<T> r(newshape);
 | 
				
			||||||
if(r.rank()!=rank()) laerror("internal error 2 in unwind_index");
 | 
					if(r.rank()!=rank()) laerror("internal error 2 in unwind_index");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -656,6 +670,8 @@ if(!indexperm.is_valid())
 | 
				
			|||||||
	laerror("internal error 3 in unwind_index");
 | 
						laerror("internal error 3 in unwind_index");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::cout <<"unwind permutation = "<<indexperm<<std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//loop recursively and do the unwinding
 | 
					//loop recursively and do the unwinding
 | 
				
			||||||
help_tt<T> = this;
 | 
					help_tt<T> = this;
 | 
				
			||||||
help_p = &indexperm;
 | 
					help_p = &indexperm;
 | 
				
			||||||
@ -782,7 +798,7 @@ return r;
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<typename T>
 | 
					template<typename T>
 | 
				
			||||||
static void auxmatmult(int nn, int mm, int kk, T *r, T *a, T *b,  T alpha=1, T beta=0, bool conjugate=false) //R(nn,mm) = A(nn,kk) * B^T(mm,kk)
 | 
					static void auxmatmult(int nn, int mm, int kk, T *r, const T *a, const T *b,  T alpha=1, T beta=0, bool conjugate=false) //R(nn,mm) = A(nn,kk) * B^T(mm,kk)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
for(int i=0; i<nn; ++i) for(int j=0; j<mm; ++j)
 | 
					for(int i=0; i<nn; ++i) for(int j=0; j<mm; ++j)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -793,13 +809,13 @@ for(int i=0; i<nn; ++i) for(int j=0; j<mm; ++j)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<>
 | 
					template<>
 | 
				
			||||||
void auxmatmult<double>(int nn, int mm, int kk, double *r, double *a, double *b, double alpha, double beta, bool conjugate)
 | 
					void auxmatmult<double>(int nn, int mm, int kk, double *r, const double *a, const double *b, double alpha, double beta, bool conjugate)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasTrans, nn, mm, kk, alpha, a, kk, b, kk, beta, r, mm);
 | 
					cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasTrans, nn, mm, kk, alpha, a, kk, b, kk, beta, r, mm);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<>
 | 
					template<>
 | 
				
			||||||
void auxmatmult<std::complex<double> >(int nn, int mm, int kk, std::complex<double> *r, std::complex<double> *a, std::complex<double> *b,  std::complex<double> alpha,  std::complex<double> beta, bool conjugate)
 | 
					void auxmatmult<std::complex<double> >(int nn, int mm, int kk, std::complex<double> *r, const std::complex<double> *a, const std::complex<double> *b,  std::complex<double> alpha,  std::complex<double> beta, bool conjugate)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
cblas_zgemm(CblasRowMajor, CblasNoTrans, (conjugate?CblasConjTrans:CblasTrans), nn, mm, kk, &alpha, a, kk, b, kk, &beta, r, mm);
 | 
					cblas_zgemm(CblasRowMajor, CblasNoTrans, (conjugate?CblasConjTrans:CblasTrans), nn, mm, kk, &alpha, a, kk, b, kk, &beta, r, mm);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -823,9 +839,8 @@ if(rhsindex<0||rhsindex>=rhs.shape[rhsgroup].number)  laerror("wrong index numbe
 | 
				
			|||||||
if(rhs1.shape[group].offset != rhs.shape[rhsgroup].offset) laerror("incompatible index offset in contraction");
 | 
					if(rhs1.shape[group].offset != rhs.shape[rhsgroup].offset) laerror("incompatible index offset in contraction");
 | 
				
			||||||
if(rhs1.shape[group].range != rhs.shape[rhsgroup].range) laerror("incompatible index range in contraction");
 | 
					if(rhs1.shape[group].range != rhs.shape[rhsgroup].range) laerror("incompatible index range in contraction");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Tensor<T> u = rhs1.unwind_index(group,index);
 | 
					const Tensor<T> u = conjugate1? (rhs1.unwind_index(group,index)).conjugate() : rhs1.unwind_index(group,index);
 | 
				
			||||||
if(conjugate1) u.conjugateme();
 | 
					const Tensor<T> rhsu = rhs.unwind_index(rhsgroup,rhsindex);
 | 
				
			||||||
Tensor<T> rhsu = rhs.unwind_index(rhsgroup,rhsindex);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NRVec<indexgroup> newshape(u.shape.size()+rhsu.shape.size()-2);
 | 
					NRVec<indexgroup> newshape(u.shape.size()+rhsu.shape.size()-2);
 | 
				
			||||||
@ -1077,21 +1092,32 @@ return r;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<typename T> 
 | 
					template<typename T> 
 | 
				
			||||||
NRVec<NRMat<T> > Tensor<T>::Tucker(typename LA_traits<T>::normtype thr)
 | 
					NRVec<NRMat<T> > Tensor<T>::Tucker(typename LA_traits<T>::normtype thr, bool inverseorder)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
int r=rank();
 | 
					int r=rank();
 | 
				
			||||||
NRVec<NRMat<T> > ret(r);
 | 
					NRVec<NRMat<T> > ret(r);
 | 
				
			||||||
if(r<2) return ret;
 | 
					if(r<1) laerror("illegal rank in Tucker");
 | 
				
			||||||
 | 
					copyonwrite();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int rr=0;	
 | 
					if(r==1) //create an analogous output for the trivial case 
 | 
				
			||||||
for(int i=0; i<shape.size(); ++i)
 | 
					 | 
				
			||||||
	for(int j=0; j<shape[i].number; ++j) //loop over all indices
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
						ret[0]=NRMat<T>(data,data.size(),1);
 | 
				
			||||||
 | 
						shape[0].range=1;
 | 
				
			||||||
 | 
						data.resize(calcsize()); 
 | 
				
			||||||
 | 
						calcrank();
 | 
				
			||||||
 | 
						data[0]=1;
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//loop over all indices; relies on the fact tha unwinding does not change order of remaining indices
 | 
				
			||||||
 | 
					for(int i=0; i<r; ++i)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						INDEX I=indexposition(i,shape);
 | 
				
			||||||
	NRMat<T> um;
 | 
						NRMat<T> um;
 | 
				
			||||||
	NRVec<indexgroup> ushape;
 | 
						NRVec<indexgroup> ushape;
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		Tensor<T> u=unwind_index(i,j);
 | 
						Tensor<T> u=unwind_index(I);
 | 
				
			||||||
		ushape=u.shape;
 | 
						ushape=u.shape; ushape.copyonwrite();
 | 
				
			||||||
	um=u.matrix();
 | 
						um=u.matrix();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	int mini=um.nrows(); if(um.ncols()<mini) mini=um.ncols(); //compact SVD, expect descendingly sorted values
 | 
						int mini=um.nrows(); if(um.ncols()<mini) mini=um.ncols(); //compact SVD, expect descendingly sorted values
 | 
				
			||||||
@ -1110,18 +1136,55 @@ for(int i=0; i<shape.size(); ++i)
 | 
				
			|||||||
		umnew=u.submatrix(0,um.nrows()-1,0,preserve-1);
 | 
							umnew=u.submatrix(0,um.nrows()-1,0,preserve-1);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	else umnew=u;
 | 
						else umnew=u;
 | 
				
			||||||
		ret[rr++]=vt.transpose(true);
 | 
						ret[(inverseorder? r-i-1 : i)]=vt.transpose(true);
 | 
				
			||||||
	umnew.diagmultr(w);
 | 
						umnew.diagmultr(w);
 | 
				
			||||||
	//rebuild tensor of the preserved shape from matrix
 | 
						//rebuild tensor of the preserved shape from matrix
 | 
				
			||||||
	ushape[0].range=preserve;
 | 
						ushape[0].range=preserve;
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
	NRVec<T> newdata(umnew);
 | 
						NRVec<T> newdata(umnew);
 | 
				
			||||||
 | 
						umnew.resize(0,0);//deallocate
 | 
				
			||||||
	*this = Tensor(ushape,newdata);
 | 
						*this = Tensor(ushape,newdata);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					if(!is_flat()) laerror("this should not happen");
 | 
				
			||||||
 | 
					if(!inverseorder)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						NRPerm<int> p(r);
 | 
				
			||||||
 | 
						for(int i=1; i<=r; ++i) p[r-i+1]=i;
 | 
				
			||||||
 | 
						*this =  permute_index_groups(p);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
return ret;
 | 
					return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					Tensor<T> Tensor<T>::inverseTucker(const NRVec<NRMat<T> > &x, bool inverseorder) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					if(rank()!=x.size()) laerror("input of inverseTucker does not match rank");
 | 
				
			||||||
 | 
					Tensor<T> tmp(*this);
 | 
				
			||||||
 | 
					Tensor<T> r;
 | 
				
			||||||
 | 
					if(!is_flat()) laerror("inverseTucker only for flat tensors as produced by Tucker");
 | 
				
			||||||
 | 
					for(int i=0; i<rank(); ++i)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						Tensor<T> mat(x[i],true);
 | 
				
			||||||
 | 
						r= tmp.contraction(i,0,mat,0,0,(T)1,false,false);
 | 
				
			||||||
 | 
						if(i<rank()-1) 
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							tmp=r;
 | 
				
			||||||
 | 
							r.deallocate();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					if(!inverseorder)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        NRPerm<int> p(r.rank());
 | 
				
			||||||
 | 
					        for(int i=1; i<=r.rank(); ++i) p[r.rank()-i+1]=i;
 | 
				
			||||||
 | 
					        return r.permute_index_groups(p);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										17
									
								
								tensor.h
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								tensor.h
									
									
									
									
									
								
							@ -35,6 +35,7 @@
 | 
				
			|||||||
#include "vec.h"
 | 
					#include "vec.h"
 | 
				
			||||||
#include "mat.h"
 | 
					#include "mat.h"
 | 
				
			||||||
#include "smat.h"
 | 
					#include "smat.h"
 | 
				
			||||||
 | 
					#include "fourindex.h"
 | 
				
			||||||
#include "miscfunc.h"
 | 
					#include "miscfunc.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//TODO:
 | 
					//TODO:
 | 
				
			||||||
@ -44,6 +45,10 @@
 | 
				
			|||||||
//@@@ will need to store vector of INDEX to the original tensor for the result's flatindex
 | 
					//@@@ will need to store vector of INDEX to the original tensor for the result's flatindex
 | 
				
			||||||
//@@@ will not be particularly efficient
 | 
					//@@@ will not be particularly efficient
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					//@@@conversions to/from fourindex
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//@@@!!!!!!!!!!!const loopover and grouploopover
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
//@@@?general permutation of individual indices - check the indices in sym groups remain adjacent, calculate result's shape, loopover the result and permute using unwind_callback
 | 
					//@@@?general permutation of individual indices - check the indices in sym groups remain adjacent, calculate result's shape, loopover the result and permute using unwind_callback
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
@ -122,7 +127,9 @@ int index;
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
typedef NRVec<INDEX> INDEXLIST; //collection of several indices
 | 
					typedef NRVec<INDEX> INDEXLIST; //collection of several indices
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int flatposition(int group, int index, const NRVec<indexgroup> &shape);
 | 
				
			||||||
int flatposition(const INDEX &i, const NRVec<indexgroup> &shape); //position of that index in FLATINDEX
 | 
					int flatposition(const INDEX &i, const NRVec<indexgroup> &shape); //position of that index in FLATINDEX
 | 
				
			||||||
 | 
					INDEX indexposition(int flatindex, const NRVec<indexgroup> &shape); //inverse to flatposition
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FLATINDEX superindex2flat(const SUPERINDEX &I);
 | 
					FLATINDEX superindex2flat(const SUPERINDEX &I);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -150,7 +157,7 @@ public:
 | 
				
			|||||||
	Tensor(const Tensor &rhs): myrank(rhs.myrank), shape(rhs.shape), groupsizes(rhs.groupsizes), cumsizes(rhs.cumsizes), data(rhs.data) {};
 | 
						Tensor(const Tensor &rhs): myrank(rhs.myrank), shape(rhs.shape), groupsizes(rhs.groupsizes), cumsizes(rhs.cumsizes), data(rhs.data) {};
 | 
				
			||||||
	Tensor(int xrank, const NRVec<indexgroup> &xshape, const NRVec<LA_largeindex> &xgroupsizes,  const  NRVec<LA_largeindex> xcumsizes, const  NRVec<T> &xdata) :  myrank(xrank), shape(xshape), groupsizes(xgroupsizes), cumsizes(xcumsizes), data(xdata) {};
 | 
						Tensor(int xrank, const NRVec<indexgroup> &xshape, const NRVec<LA_largeindex> &xgroupsizes,  const  NRVec<LA_largeindex> xcumsizes, const  NRVec<T> &xdata) :  myrank(xrank), shape(xshape), groupsizes(xgroupsizes), cumsizes(xcumsizes), data(xdata) {};
 | 
				
			||||||
	explicit Tensor(const NRVec<T> &x);
 | 
						explicit Tensor(const NRVec<T> &x);
 | 
				
			||||||
	explicit Tensor(const NRMat<T> &x);
 | 
						explicit Tensor(const NRMat<T> &x, bool flat=false);
 | 
				
			||||||
	explicit Tensor(const NRSMat<T> &x);
 | 
						explicit Tensor(const NRSMat<T> &x);
 | 
				
			||||||
	NRMat<T> matrix() const {return NRMat<T>(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<T> matrix() const {return NRMat<T>(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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -162,6 +169,7 @@ public:
 | 
				
			|||||||
	LA_largeindex size() const {return data.size();};
 | 
						LA_largeindex size() const {return data.size();};
 | 
				
			||||||
	void copyonwrite() {shape.copyonwrite(); groupsizes.copyonwrite(); cumsizes.copyonwrite(); data.copyonwrite();};
 | 
						void copyonwrite() {shape.copyonwrite(); groupsizes.copyonwrite(); cumsizes.copyonwrite(); data.copyonwrite();};
 | 
				
			||||||
	void resize(const NRVec<indexgroup> &s) {shape=s; data.resize(calcsize()); calcrank();};
 | 
						void resize(const NRVec<indexgroup> &s) {shape=s; data.resize(calcsize()); calcrank();};
 | 
				
			||||||
 | 
						void deallocate() {data.resize(0); shape.resize(0); groupsizes.resize(0); cumsizes.resize(0);};
 | 
				
			||||||
        inline Signedpointer<T> lhs(const SUPERINDEX &I) {int sign; LA_largeindex i=index(&sign,I); return Signedpointer<T>(&data[i],sign);};
 | 
					        inline Signedpointer<T> lhs(const SUPERINDEX &I) {int sign; LA_largeindex i=index(&sign,I); return Signedpointer<T>(&data[i],sign);};
 | 
				
			||||||
	inline T operator()(const SUPERINDEX &I) const {int sign; LA_largeindex i=index(&sign,I); if(sign==0) return 0; return sign>0 ?data[i] : -data[i];};
 | 
						inline T operator()(const SUPERINDEX &I) const {int sign; LA_largeindex i=index(&sign,I); if(sign==0) return 0; return sign>0 ?data[i] : -data[i];};
 | 
				
			||||||
        inline Signedpointer<T> lhs(const FLATINDEX &I) {int sign; LA_largeindex i=index(&sign,I); return Signedpointer<T>(&data[i],sign);};
 | 
					        inline Signedpointer<T> lhs(const FLATINDEX &I) {int sign; LA_largeindex i=index(&sign,I); return Signedpointer<T>(&data[i],sign);};
 | 
				
			||||||
@ -176,6 +184,8 @@ public:
 | 
				
			|||||||
	inline Tensor& operator/=(const T &a) {data/=a; return *this;};
 | 
						inline Tensor& operator/=(const T &a) {data/=a; return *this;};
 | 
				
			||||||
	inline Tensor operator/(const T &a) const {Tensor r(*this); r /=a; return r;};
 | 
						inline Tensor operator/(const T &a) const {Tensor r(*this); r /=a; return r;};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						typename LA_traits<T>::normtype norm() const {return data.norm();};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline Tensor operator*(const Tensor &rhs) const {return Tensor(rhs.shape.concat(shape),data.otimes2vec(rhs.data));} //outer product,  rhs indices will be the less significant 
 | 
						inline Tensor operator*(const Tensor &rhs) const {return Tensor(rhs.shape.concat(shape),data.otimes2vec(rhs.data));} //outer product,  rhs indices will be the less significant 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Tensor& conjugateme() {data.conjugateme(); return *this;};
 | 
						Tensor& conjugateme() {data.conjugateme(); return *this;};
 | 
				
			||||||
@ -215,6 +225,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	Tensor permute_index_groups(const NRPerm<int> &p) const; //rearrange the tensor storage permuting index groups as a whole
 | 
						Tensor permute_index_groups(const NRPerm<int> &p) const; //rearrange the tensor storage permuting index groups as a whole
 | 
				
			||||||
	Tensor unwind_index(int group, int index) const; //separate an index from a group and expand it to full range as the least significant one (the leftmost one)
 | 
						Tensor unwind_index(int group, int index) const; //separate an index from a group and expand it to full range as the least significant one (the leftmost one)
 | 
				
			||||||
 | 
						Tensor unwind_index(const INDEX &I) const {return unwind_index(I.group,I.index);};
 | 
				
			||||||
	Tensor unwind_indices(const INDEXLIST &il) const; //the same for a list of indices
 | 
						Tensor unwind_indices(const INDEXLIST &il) const; //the same for a list of indices
 | 
				
			||||||
	void addcontraction(const Tensor &rhs1, int group, int index, const Tensor &rhs2, int rhsgroup, int rhsindex, T alpha=1, T beta=1, bool doresize=false, bool conjugate1=false, bool conjugate=false); //rhs1 will have more significant non-contracted indices in the result than rhs2
 | 
						void addcontraction(const Tensor &rhs1, int group, int index, const Tensor &rhs2, int rhsgroup, int rhsindex, T alpha=1, T beta=1, bool doresize=false, bool conjugate1=false, bool conjugate=false); //rhs1 will have more significant non-contracted indices in the result than rhs2
 | 
				
			||||||
	inline Tensor contraction(int group, int index, const Tensor &rhs, int rhsgroup, int rhsindex, T alpha=1, bool conjugate1=false, bool conjugate=false) const {Tensor<T> r; r.addcontraction(*this,group,index,rhs,rhsgroup,rhsindex,alpha,0,true, conjugate1, conjugate); return r; };
 | 
						inline Tensor contraction(int group, int index, const Tensor &rhs, int rhsgroup, int rhsindex, T alpha=1, bool conjugate1=false, bool conjugate=false) const {Tensor<T> r; r.addcontraction(*this,group,index,rhs,rhsgroup,rhsindex,alpha,0,true, conjugate1, conjugate); return r; };
 | 
				
			||||||
@ -232,8 +243,8 @@ public:
 | 
				
			|||||||
	void split_index_group(int group); //formal split of a non-symmetric index group WITHOUT the need for data reorganization
 | 
						void split_index_group(int group); //formal split of a non-symmetric index group WITHOUT the need for data reorganization
 | 
				
			||||||
	void merge_adjacent_index_groups(int groupfrom, int groupto); //formal merge of non-symmetric index groups  WITHOUT the need for data reorganization
 | 
						void merge_adjacent_index_groups(int groupfrom, int groupto); //formal merge of non-symmetric index groups  WITHOUT the need for data reorganization
 | 
				
			||||||
	Tensor merge_index_groups(const NRVec<int> &groups) const;
 | 
						Tensor merge_index_groups(const NRVec<int> &groups) const;
 | 
				
			||||||
	NRVec<NRMat<T> > Tucker(typename LA_traits<T>::normtype thr=1e-12); //HOSVD-Tucker decomposition, return core tensor in *this, flattened 
 | 
						NRVec<NRMat<T> > Tucker(typename LA_traits<T>::normtype thr=1e-12, bool inverseorder=true); //HOSVD-Tucker decomposition, return core tensor in *this, flattened 
 | 
				
			||||||
 | 
						Tensor inverseTucker(const NRVec<NRMat<T> > &x, bool inverseorder=true) const; //rebuild the original tensor from Tucker
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user