Mentions légales du service

Skip to content
Snippets Groups Projects
Commit 3a70f2e0 authored by hhakim's avatar hhakim
Browse files

Add methods to Py wrapper: nnz(), density(), RCG(), norm() and get_nb_factors().

These methods are already in Matlab wrapper.
parent 0abc18d2
Branches
Tags
No related merge requests found
......@@ -47,94 +47,127 @@ import FaustCorePy
class Faust:
""" This class represents a dense matrix by a product of 'sparse' factors (i.e Faust)
The aim of the Faust representatio is to speed-up multiplication by this matrix
"""
def __init__(F,list_factors):
""" create a Faust from a list of factor.
Parameter
---------
list_factors : list/tuple of numpy matrices
"""
F.m_faust = FaustCorePy.FaustCore(list_factors);
F.m_transpose_flag=0;
F.shape=F.m_faust.shape(F.m_transpose_flag)
def getNbRow(F):
""" return the number of row of the current Faust. """
return F.shape[0]
def getNbCol(F):
""" return the number of column of the current Faust. """
return F.shape[1]
def transpose(F):
""" transpose the current Faust. """
F_trans=copy.copy(F)
F_trans.m_transpose_flag=not (F.m_transpose_flag)
F_trans.shape=(F.shape[1],F.shape[0])
return F_trans;
def display(F):
""" display information of the current Faust. """
print("Struct : ")
F.m_faust.display(F.m_transpose_flag);
def __mul__(F,x):
""" multiplication between the current Faust and a numpy matrix.
(overload the python operator *, return F*x)
Parameter
---------
x : 2D numpy ndarray of double scalar, must be FORTRAN contiguous
"""
return F.m_faust.multiply(x,F.m_transpose_flag)
def todense(F):
""" convert the current Faust into a numpy matrix.
return a numpy matrix """
identity=np.eye(F.getNbCol(),F.getNbCol());
F_dense=F*identity
return F_dense
def __getitem__(F,list_index):
""" Slicing : Return the value of the current Faust at index list_index.
(overload of python built-in operator F(indexRow,indexCol)
Parameter
---------
list_index : tab of length 2 with its elements must be slice, integer or Ellipsis(...)
Example of use :
F[2,3], F[0:dim1,...], F[::-1,::-1]
"""
#check if list_index has a 2 index (row and column)
if (len(list_index) != 2):
raise ValueError('list_index must contains 2 elements, the row index and the col index')
#check if the index are slice or integer or Ellipsis
for id in list_index:
if (not isinstance(id, slice)) and (not isinstance(id,int) and (id !=Ellipsis)):
raise ValueError('list_index must contains slice (1:n) or Ellipsis (...) or int (2)')
keyCol=list_index[1]
keyRow=list_index[0]
identity=np.eye(F.getNbCol(),F.getNbCol())
if(keyCol != Ellipsis): identity=identity[...,keyCol]
submatrix=F*identity
submatrix=submatrix[keyRow,:]
return submatrix
""" This class represents a dense matrix by a product of 'sparse' factors (i.e Faust)
The aim of the Faust representatio is to speed-up multiplication by this matrix
"""
def __init__(F,list_factors):
""" create a Faust from a list of factor.
Parameter
---------
list_factors : list/tuple of numpy matrices
"""
F.m_faust = FaustCorePy.FaustCore(list_factors);
F.m_transpose_flag=0;
F.shape=F.m_faust.shape(F.m_transpose_flag)
def getNbRow(F):
""" return the number of row of the current Faust. """
return F.shape[0]
def getNbCol(F):
""" return the number of column of the current Faust. """
return F.shape[1]
def transpose(F):
""" transpose the current Faust. """
F_trans=copy.copy(F)
F_trans.m_transpose_flag=not (F.m_transpose_flag)
F_trans.shape=(F.shape[1],F.shape[0])
return F_trans;
def display(F):
""" display information of the current Faust. """
print("Struct : ")
F.m_faust.display(F.m_transpose_flag);
def __mul__(F,x):
""" multiplication between the current Faust and a numpy matrix.
(overload the python operator *, return F*x)
Parameter
---------
x : 2D numpy ndarray of double scalar, must be FORTRAN contiguous
"""
return F.m_faust.multiply(x,F.m_transpose_flag)
def todense(F):
""" convert the current Faust into a numpy matrix.
return a numpy matrix """
identity=np.eye(F.getNbCol(),F.getNbCol());
F_dense=F*identity
return F_dense
def __getitem__(F,list_index):
""" Slicing : Return the value of the current Faust at index list_index.
(overload of python built-in operator F(indexRow,indexCol)
Parameter
---------
list_index : tab of length 2 with its elements must be slice, integer or Ellipsis(...)
Example of use :
F[2,3], F[0:dim1,...], F[::-1,::-1]
"""
#check if list_index has a 2 index (row and column)
if (len(list_index) != 2):
raise ValueError('list_index must contains 2 elements, the row index and the col index')
#check if the index are slice or integer or Ellipsis
for id in list_index:
if (not isinstance(id, slice)) and (not isinstance(id,int) and (id !=Ellipsis)):
raise ValueError('list_index must contains slice (1:n) or Ellipsis (...) or int (2)')
keyCol=list_index[1]
keyRow=list_index[0]
identity=np.eye(F.getNbCol(),F.getNbCol())
if(keyCol != Ellipsis): identity=identity[...,keyCol]
submatrix=F*identity
submatrix=submatrix[keyRow,:]
return submatrix
def nnz(F):
""" Gives the number of non-zero elements in the Faust.
"""
return F.m_faust.nnz()
def density(F):
""" Returns the density of the Faust which is the normalized rate of non-zero
coefficients.
"""
return float(F.nnz())/(F.shape[0]*F.shape[1])
def RCG(F):
""" Returns the Relative Complexity Gain (inverse of the density).
"""
d = F.density()
if(d > 0):
return 1/d
elif(d == 0):
return float("inf")
else:
return -1
def norm(F, typenorm=2):
"""
Returns the 2-norm of The Faust.
"""
if(typenorm != 2):
raise Exception("Only 2-norm is supported for the"
"Faust")
return F.m_faust.norm()
def get_nb_factors(F):
"""
Returns the Faust's number of factors.
"""
return F.m_faust.get_nb_factors()
......@@ -105,3 +105,8 @@ for i in range(nb_mult):
print("multiplication SPEED-UP using Faust")
print("Faust is "+str(t_dense/t_faust)+" faster than a full matrix")
print("Faust nnz: "+str(A.nnz()))
print("Faust density: "+str(A.density()))
print("Faust RCG: "+str(A.RCG()))
print("Faust norm: "+str(A.norm()))
print("Faust nb of factors: "+str(A.get_nb_factors()))
......@@ -63,8 +63,10 @@ class FaustCoreCpp
unsigned int getNbCol() const{return transform.getNbCol();}
void multiply(FPP* value_y,int nbrow_y,int nbcol_y,FPP* value_x,int nbrow_x,int nbcol_x,bool isTranspose)const;
void setOp(const bool isTransposed,unsigned int& nbRowOp, unsigned int& nbColOp)const;
unsigned long long nnz()const;
double norm() const;
double get_nb_factors() const;
private :
Faust::Transform<FPP,Cpu> transform;
};
......
......@@ -123,5 +123,26 @@ void FaustCoreCpp<FPP>::setOp(const bool isTransposed,unsigned int& nbRowOp, uns
template<typename FPP>
unsigned long long FaustCoreCpp<FPP>::nnz() const
{
return this->transform.get_total_nnz();
}
template<typename FPP>
double FaustCoreCpp<FPP>::norm() const
{
double precision = 0.001;
faust_unsigned_int nbr_iter_max = 100;
int flag; // not used yet
return this->transform.spectralNorm(nbr_iter_max, precision, flag);
}
template<typename FPP>
double FaustCoreCpp<FPP>::get_nb_factors() const
{
double nb_fact = this->transform.size();
return nb_fact;
}
......@@ -40,11 +40,14 @@
from libcpp cimport bool
cdef extern from "FaustCoreCpp.h" :
cdef cppclass FaustCoreCpp[FPP] :
FaustCoreCpp();
void Display() const;
void push_back(FPP* valueMat,unsigned int nbrow,unsigned int nbcol);
void multiply(FPP* value_y,int nbrow_y,int nbcol_y,FPP* value_x,int nbrow_x,int nbcol_x,bool isTranspose);
unsigned int getNbRow() const;
unsigned int getNbCol() const;
void setOp(const bool isTransposed,unsigned int& nbRowOp, unsigned int& nbColOp)const;
cdef cppclass FaustCoreCpp[FPP] :
FaustCoreCpp();
void Display() const;
void push_back(FPP* valueMat,unsigned int nbrow,unsigned int nbcol);
void multiply(FPP* value_y,int nbrow_y,int nbcol_y,FPP* value_x,int nbrow_x,int nbcol_x,bool isTranspose);
unsigned int getNbRow() const;
unsigned int getNbCol() const;
void setOp(const bool isTransposed,unsigned int& nbRowOp, unsigned int& nbColOp)const;
unsigned long long nnz() const;
double norm() const;
double get_nb_factors() const;
......@@ -49,124 +49,136 @@ from libc.string cimport memcpy;
from libcpp cimport bool
cdef class FaustCore:
#### ATTRIBUTE ########
# classe Cython
cdef FaustCoreCy.FaustCoreCpp[double] m_faust
#### CONSTRUCTOR ####
#def __cinit__(self,np.ndarray[double, mode="fortran", ndim=2] mat):
def __cinit__(self,list_factors):
#print 'inside cinit'
self.m_faust = FaustCoreCy.FaustCoreCpp[double]();
cdef double [:,:] data
cdef unsigned int nbrow
cdef unsigned int nbcol
#print 'longueur list'
#print len(list_factors)
#print 'avant boucle'
for factor in list_factors:
data=factor.astype(float,'F');
nbrow=factor.shape[0];
nbcol=factor.shape[1];
# print nbrow
# print nbcol
self.m_faust.push_back(&data[0,0],nbrow,nbcol);
#print(self.__dict__)
#print 'apres boucle'
#### METHOD ####
#~ def getNbRow(self):
#~ #return self.m_faust.getNbRow();
#~ (dim1,dim2)=self.shape();
#~ return dim1
#### ATTRIBUTE ########
# classe Cython
cdef FaustCoreCy.FaustCoreCpp[double] m_faust
#### CONSTRUCTOR ####
#def __cinit__(self,np.ndarray[double, mode="fortran", ndim=2] mat):
def __cinit__(self,list_factors):
#print 'inside cinit'
self.m_faust = FaustCoreCy.FaustCoreCpp[double]();
cdef double [:,:] data
cdef unsigned int nbrow
cdef unsigned int nbcol
#print 'longueur list'
#print len(list_factors)
#print 'avant boucle'
for factor in list_factors:
data=factor.astype(float,'F');
nbrow=factor.shape[0];
nbcol=factor.shape[1];
# print nbrow
# print nbcol
self.m_faust.push_back(&data[0,0],nbrow,nbcol);
#print(self.__dict__)
#print 'apres boucle'
#### METHOD ####
#~ def getNbRow(self):
#~ #return self.m_faust.getNbRow();
#~ (dim1,dim2)=self.shape();
#~ return dim1
#~ def getNbCol(self):
#~ (dim1,dim2)=self.shape();
#~ return dim2
def shape(self,transpose_flag=False):
cdef unsigned int nbrow = 0
cdef unsigned int nbcol = 0
self.m_faust.setOp(transpose_flag,nbrow,nbcol)
return (nbrow,nbcol)
#avoid using np.ndarray as input type
#because there is no distinction between row vector and column vector
#WARNING : a vector is always a Column Vector
#
# numpy.matrix is always 2-dimensional but C-style (RowMajor) stored
# not Fortran-style (ColMajor) as Faust lib use Fortran-style storage
# Left-Multiplication by a Faust F
# y=multiply(F,x) is equivalent to y=F*x
def multiply(self,x,transpose_flag):
if not isinstance(x, (np.ndarray) ):
raise NameError('input x must a numpy ndarray')
#transform into float F continous matrix
x=x.astype(float,'F')
if not x.dtype=='float':
raise NameError('input x must be double array')
if not x.flags['F_CONTIGUOUS']:
raise NameError('input x must be Fortran contiguous (Colmajor)')
ndim_x=x.ndim;
if (ndim_x > 2) | (ndim_x < 1):
raise NameError('input x invalid number of dimensions')
cdef unsigned int nbrow_x=x.shape[0]
cdef unsigned int nbcol_x #can't be assigned because we don't know yet if the input vector is 1D or 2D
dimThis=self.shape(transpose_flag)
cdef unsigned int nbRowThis=dimThis[0];
cdef unsigned int nbColThis=dimThis[1];
cdef unsigned int nbrow_y=nbRowThis
cdef unsigned int nbcol_y
cdef double[:] xview_1D
cdef double[:,:] xview_2D
if ndim_x == 1:
nbcol_x=1
xview_1D=x;
else:
nbcol_x=x.shape[1]
xview_2D=x;
if (nbrow_x != nbColThis):
raise NameError('y=F*x multiplication with Faust : invalid dimension of the input matrix x');
#void multiply(FPP* value_y,int nbrow_y,int nbcol_y,FPP* value_x,int nbrow_x,int nbcol_x,bool isTranspose);
nbcol_y = nbcol_x;
cdef y = np.zeros([nbrow_y,nbcol_y], dtype='d',order='F')
cdef double[:,:] yview=y
if ndim_x == 1:
self.m_faust.multiply(&yview[0,0],nbrow_y,nbcol_y,&xview_1D[0],nbrow_x,nbcol_x,transpose_flag);
else:
self.m_faust.multiply(&yview[0,0],nbrow_y,nbcol_y,&xview_2D[0,0],nbrow_x,nbcol_x,transpose_flag);
return y
# print information about the faust (size, number of factor, type of factor (dense/sparse) ...)
def display(self,transpose_flag):
print("Faust transposition " + str(transpose_flag))
self.m_faust.Display();
#~ (dim1,dim2)=self.shape();
#~ return dim2
def shape(self,transpose_flag=False):
cdef unsigned int nbrow = 0
cdef unsigned int nbcol = 0
self.m_faust.setOp(transpose_flag,nbrow,nbcol)
return (nbrow,nbcol)
#avoid using np.ndarray as input type
#because there is no distinction between row vector and column vector
#WARNING : a vector is always a Column Vector
#
# numpy.matrix is always 2-dimensional but C-style (RowMajor) stored
# not Fortran-style (ColMajor) as Faust lib use Fortran-style storage
# Left-Multiplication by a Faust F
# y=multiply(F,x) is equivalent to y=F*x
def multiply(self,x,transpose_flag):
if not isinstance(x, (np.ndarray) ):
raise NameError('input x must a numpy ndarray')
#transform into float F continous matrix
x=x.astype(float,'F')
if not x.dtype=='float':
raise NameError('input x must be double array')
if not x.flags['F_CONTIGUOUS']:
raise NameError('input x must be Fortran contiguous (Colmajor)')
ndim_x=x.ndim;
if (ndim_x > 2) | (ndim_x < 1):
raise NameError('input x invalid number of dimensions')
cdef unsigned int nbrow_x=x.shape[0]
cdef unsigned int nbcol_x #can't be assigned because we don't know yet if the input vector is 1D or 2D
dimThis=self.shape(transpose_flag)
cdef unsigned int nbRowThis=dimThis[0];
cdef unsigned int nbColThis=dimThis[1];
cdef unsigned int nbrow_y=nbRowThis
cdef unsigned int nbcol_y
cdef double[:] xview_1D
cdef double[:,:] xview_2D
if ndim_x == 1:
nbcol_x=1
xview_1D=x;
else:
nbcol_x=x.shape[1]
xview_2D=x;
if (nbrow_x != nbColThis):
raise NameError('y=F*x multiplication with Faust : invalid dimension of the input matrix x');
#void multiply(FPP* value_y,int nbrow_y,int nbcol_y,FPP* value_x,int nbrow_x,int nbcol_x,bool isTranspose);
nbcol_y = nbcol_x;
cdef y = np.zeros([nbrow_y,nbcol_y], dtype='d',order='F')
cdef double[:,:] yview=y
if ndim_x == 1:
self.m_faust.multiply(&yview[0,0],nbrow_y,nbcol_y,&xview_1D[0],nbrow_x,nbcol_x,transpose_flag);
else:
self.m_faust.multiply(&yview[0,0],nbrow_y,nbcol_y,&xview_2D[0,0],nbrow_x,nbcol_x,transpose_flag);
return y
# print information about the faust (size, number of factor, type of factor (dense/sparse) ...)
def display(self,transpose_flag):
print("Faust transposition " + str(transpose_flag))
self.m_faust.Display();
def nnz(self):
cdef unsigned long long nnz = 0
nnz = self.m_faust.nnz()
return nnz
def norm(self):
cdef double norm
norm = self.m_faust.norm()
return norm
def get_nb_factors(F):
cdef int nb_factors
nb_factors = int(F.m_faust.get_nb_factors())
return nb_factors
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment