Skip to content

Commit

Permalink
remove sparse_autocov_csr_mat (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
j-i-l authored Oct 14, 2024
1 parent 8648a8b commit 23028c4
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 285 deletions.
7 changes: 2 additions & 5 deletions src/flowstab/FlowStability.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
USE_SPARSE_DOT_MKL,
inplace_csr_matmul_diag,
inplace_diag_matmul_csr,
sparse_autocov_csr_mat,
sparse_autocov_mat,
sparse_gram_matrix,
sparse_matmul,
Expand Down Expand Up @@ -1394,8 +1393,7 @@ def __init__(self, p1=None, p2=None,T=None, S=None,
raise ValueError("At least T or S must be provided")

if T is None:
assert isinstance(S, sparse_autocov_mat) or \
isinstance(S, sparse_autocov_csr_mat), "S must be a sparse_autocov_mat."
assert isinstance(S, sparse_autocov_mat), "S must be a sparse_autocov_mat."

# only if S provided, T will only be used to look for neighours.
# so set T to S.PT.
Expand Down Expand Up @@ -1440,8 +1438,7 @@ def __init__(self, p1=None, p2=None,T=None, S=None,
self._S = self._compute_S()

else:
if not (isinstance(S, sparse_autocov_mat) or \
isinstance(S, sparse_autocov_csr_mat)):
if not isinstance(S, sparse_autocov_mat):
raise TypeError("S must be a sparse_autocov_mat.")
assert S.shape == self.T.shape, "T and S must have the same shape."

Expand Down
280 changes: 0 additions & 280 deletions src/flowstab/SparseStochMat.py
Original file line number Diff line number Diff line change
Expand Up @@ -1171,286 +1171,6 @@ def inplace_diag_matmul_csr(A, diag_vec):
raise ValueError("A must be a csr or csc matrix")



class sparse_autocov_csr_mat:
"""Class for autocovariance matrix stored as a CSR matrix
"""

def __init__(self, PT, S, symmetric=False):

assert isspmatrix_csr(S)
assert isspmatrix_csr(PT)

self.PT = PT
self.S = S
self.size = S.shape[0]
self.PT_symmetric = symmetric

self.p1 = None
self.p2 = None

self.shape = (self.size,self.size)

self.S.sort_indices()

if not self.PT_symmetric:
#store a version of PT as csc for fast access to columns
self.Scsc = self.S.tocsc()
self.PTcsc = self.PT.tocsc()
else:
self.Scsc = self.S
self.PTcsc = self.PT

def __repr__(self):

if self.PT_symmetric:
return f"{self.size}x{self.size} sparse autocovariance matrix with symmetric S:\n" + \
self.S.__repr__()
else:
return f"{self.size}x{self.size} sparse autocovariance matrix with S:\n" + \
self.S.__repr__()


def copy(self):

return self.__class__(self.PT.copy(),
self.S.copy(),
copy(self.PT_symmetric))

def toarray(self):


return self.S.toarray()


def get_submat_sum(self, row_idx, col_idx):
"""Returns the sum of the elements of the autocov submatrix
defined by the indices in idx, i.e. S[row_idx,col_idx].sum().
"""
if USE_CYTHON:
return cython_get_submat_sum(self.S.data, self.S.indices,
self.PT.indptr,
row_idx,
col_idx)

else:

return self.S._major_index_fancy(row_idx)._minor_index_fancy(col_idx).sum()



def get_element(self, i,j):
"""Returns element (i,j)"""
# slightly more fast to directly compute location in csr data
k, = np.where(self.S.indices[self.S.indptr[i]:self.S.indptr[i+1]] == j)
if len(k) == 0:
return 0
else:
return self.PT.data[self.S.indptr[i]+k[0]]

def get_row_idx_sum(self, row, idx):
"""Return sum of elements at positions given by `idx` in row `row`.
Parameters
----------
row : int
Index of row.
idx : list
List of indices along row `row`.
Returns
-------
Autocov[row,idx].sum()
"""
if USE_CYTHON:
PTsum = cython_get_submat_sum(self.S.data, self.S.indices,
self.S.indptr,
np.array([row], dtype=np.int32),
np.array(idx, dtype=np.int32))
else:
PTrow = self.PT._major_index_fancy(row)
PTsum = PTrow.data[np.isin(PTrow.indices,idx)].sum()

return PTsum

def get_col_idx_sum(self, col, idx):
"""Return sum of elements at positions given by `idx` in col `col`.
Parameters
----------
col : int
Index of col.
idx : list
List of indices along col `col`.
Returns
-------
Autocov[idx,col].sum()
"""
if USE_CYTHON:
PTsum = cython_get_submat_sum(self.Scsc.data, self.Scsc.indices,
self.Scsc.indptr,
np.array([col], dtype=np.int32),
np.array(idx, dtype=np.int32))
else:
PTcol = self.Scsc._major_index_fancy(col)
PTsum = PTcol.data[np.isin(PTcol.indices,idx)].sum()

return PTsum



def aggregate(self, idx_list):
"""Returns a new sparse_autocol_mat where elements of
the original mat have been aggregated according to
idx_list.
Parameters
----------
idx_list : list of lists of ints
idx_list[i] and idx_list[j] contains the list of
row indices and col_indices to be aggregated to form S[i,j].
Returns
-------
new aggregated sparse_autocov_mat
"""
# convert idx_list to a single array of indices and an array of
# pointers to start/stops for each cluster.
idxs_array = np.array([i for idx in idx_list for i in idx], dtype=np.int32)
idxptr = np.cumsum([0]+[len(idx) for idx in idx_list], dtype=np.int32)



new_size = idxptr.size-1

if USE_CYTHON:
# choose the fastest version
if new_size**2 < self.S.data.size:
Sdata, Srows, Scols, new_size = cython_aggregate_csr_mat(self.S.data,
self.S.indices,
self.S.indptr,
idxs_array,
idxptr)
else:
Sdata, Srows, Scols, new_size = cython_aggregate_csr_mat_2(self.S.data,
self.S.indices,
self.S.indptr,
idxs_array,
idxptr)

if new_size**2 < self.PT.data.size:
PTdata, PTrows, PTcols, new_size = cython_aggregate_csr_mat(self.PT.data,
self.PT.indices,
self.PT.indptr,
idxs_array,
idxptr)
else:
PTdata, PTrows, PTcols, new_size = cython_aggregate_csr_mat_2(self.PT.data,
self.PT.indices,
self.PT.indptr,
idxs_array,
idxptr)
else:
# AtoB = {}
# for kb in range(new_size):
# for ka in range(idxptr[kb],idxptr[kb+1]):
# AtoB[idxs_array[ka]] = kb

# Bdata = []
# Brows = []
# Bcols = []
# # loop over values of A
# for row in range(self.S.indptr.shape[0]-1):
# for k in range(self.S.indptr[row],self.S.indptr[row+1]):
# col = self.S.indices[k]

# Bdata.append(self.S.data[k])
# Brows.append(AtoB[row])
# Bcols.append(AtoB[col])
raise NotImplementedError

newPT = coo_matrix((PTdata,(PTrows,PTcols)), shape=(new_size,new_size))
newS = coo_matrix((Sdata,(Srows,Scols)), shape=(new_size,new_size))



return self.__class__(newPT.tocsr(),
newS.tocsr(),
self.PT_symmetric)


def is_all_zeros(self):
"""Returns True of all values are equal to zero.
checks only nonzero values of self.PT
"""
self.S.eliminate_zeros()

if self.S.getnnz() == 0:
return True
else:
return False


def _compute_delta_S_moveto(self, k, idx):
"""Return the gain in stability obtained by moving node
k into the community defined by index list in idx.
"""
if USE_CYTHON:


return cython_compute_delta_PT_moveto(self.S.data,
self.S.indices,
self.S.indptr,
self.Scsc.data,
self.Scsc.indices,
self.Scsc.indptr,
k,
idx)




else:
return self.S.get_row_idx_sum(k,idx) \
+ self.S.get_col_idx_sum(k,idx) \
+ self.S.get_element(k,k)

def _compute_delta_S_moveout(self, k, idx):
"""Return the gain in stability obtained by moving node
k outside the community defined by index list in idx.
"""
if USE_CYTHON:

return cython_compute_delta_PT_moveout(self.S.data,
self.S.indices,
self.S.indptr,
self.Scsc.data,
self.Scsc.indices,
self.Scsc.indptr,
k,
np.array(idx, dtype=np.int32))



else:
return - self.S.get_row_idx_sum(k,idx) \
- self.S.get_col_idx_sum(k,idx) \
+ self.S.get_element(k,k)




class sparse_autocov_mat:
"""Class for autocovariance matrix in the form:
Expand Down

0 comments on commit 23028c4

Please sign in to comment.