def fit(self, biadjacency: Union[sparse.csr_matrix, np.ndarray]) -> 'BiLouvain': """Apply the Louvain algorithm to the corresponding directed graph, with adjacency matrix: :math:`A = \\begin{bmatrix} 0 & B \\\\ 0 & 0 \\end{bmatrix}` where :math:`B` is the input (biadjacency matrix). Parameters ---------- biadjacency: Biadjacency matrix of the graph. Returns ------- self: :class:`BiLouvain` """ louvain = Louvain(resolution=self.resolution, modularity=self.modularity, tol_aggregation=self.tol_aggregation, n_aggregations=self.n_aggregations, shuffle_nodes=self.shuffle_nodes, sort_clusters=self.sort_clusters, return_membership=self.return_membership, return_aggregate=False, random_state=self.random_state, verbose=self.log.verbose) biadjacency = check_format(biadjacency) n_row, _ = biadjacency.shape if self.modularity == 'dugue': adjacency = bipartite2directed(biadjacency) else: adjacency = bipartite2undirected(biadjacency) louvain.fit(adjacency) self.labels_ = louvain.labels_ self._split_vars(n_row) self._secondary_outputs(biadjacency) return self
def bimodularity(biadjacency: Union[sparse.csr_matrix, np.ndarray], labels: np.ndarray, labels_col: np.ndarray, weights: Union[str, np.ndarray] = 'degree', weights_col: Union[str, np.ndarray] = 'degree', resolution: float = 1, return_all: bool = False) -> Union[float, Tuple[float, float, float]]: """Bimodularity of a clustering (node partition). * Bigraphs The bimodularity of a clustering is :math:`Q = \\sum_{i}\\sum_{j}\\left(\\dfrac{B_{ij}}{w} - \\gamma \\dfrac{w_{1,i}w_{2,j}}{w^2}\\right) \\delta_{c_{1,i},c_{2,j}}` where * :math:`c_{1,i}, c_{2,j}` are the clusters of nodes :math:`i` (row) and :math:`j` (column),\n * :math:`w_{1,i}, w_{2,j}` are the weights of nodes :math:`i` (row) and :math:`j` (column),\n * :math:`w = 1^TB1` is the total weight,\n * :math:`\\delta` is the Kronecker symbol,\n * :math:`\\gamma \\ge 0` is the resolution parameter. Parameters ---------- biadjacency : Biadjacency matrix of the graph (shape :math:`n_1 \\times n_2`). labels : Labels of rows, vector of size :math:`n_1`. labels_col: Labels of columns, vector of size :math:`n_2`. weights : Weights of nodes. ``'degree'`` (default), ``'uniform'`` or custom weights. weights_col : Weights of columns. ``'degree'`` (default), ``'uniform'`` or custom weights. resolution: Resolution parameter (default = 1). return_all: If ``True``, return modularity, fit, diversity. Returns ------- modularity : float fit: float, optional diversity: float, optional Example ------- >>> from sknetwork.clustering import bimodularity >>> from sknetwork.data import star_wars >>> biadjacency = star_wars() >>> labels = np.array([1, 1, 0, 0]) >>> labels_col = np.array([1, 0, 0]) >>> np.round(bimodularity(biadjacency, labels, labels_col), 2) 0.22 """ biadjacency = check_format(biadjacency).astype(float) n_row, n_col = biadjacency.shape if len(labels) != n_row: raise ValueError('Dimension mismatch between labels and biadjacency matrix.') if len(labels_col) != n_col: raise ValueError('Dimension mismatch between labels_col and biadjacency matrix.') adjacency = bipartite2directed(biadjacency) weights_ = check_probs(weights, biadjacency) weights_ = np.hstack((weights_, np.zeros(n_col))) weights_col_ = check_probs(weights_col, biadjacency.T) weights_col_ = np.hstack((np.zeros(n_row), weights_col_)) labels_ = np.hstack((labels, labels_col)) return modularity(adjacency, labels_, weights_, weights_col_, resolution, return_all)