def _slq_red_var_vnge(matrix, lanczos_steps, nvectors): """Approximates Von Neumann Graph Entropy (VNGE) of a given matrix. Uses the control variates method to reduce the variance of VNGE estimation. Args: matrix (sparse matrix): Input adjacency matrix of a graph. lanczos_steps (int): Number of Lanczos steps. nvectors (int): Number of random vectors for stochastic estimation. Returns: float: Approximated von Neumann graph entropy. """ functions = [lambda x: -np.where(x > 0, x * np.log(x), 0), lambda x: x] traces = slq(matrix, lanczos_steps, nvectors, functions).ravel() return traces[0] - traces[1] + 1
def _slq_red_var_netlsd(matrix, lanczos_steps, nvectors, timescales): """Computes unnormalized NetLSD signatures of a given matrix. Uses the control variates method to reduce the variance of NetLSD estimation. Args: matrix (sparse matrix): Input adjacency matrix of a graph. lanczos_steps (int): Number of Lanczos steps. nvectors (int): Number of random vectors for stochastic estimation. timescales (np.ndarray): Timescale parameter for NetLSD computation. Default value is the one used in both NetLSD and SLaQ papers. Returns: np.ndarray: Approximated NetLSD descriptors. """ functions = [np.exp, lambda x: x] traces = slq(matrix, lanczos_steps, nvectors, functions, -timescales) subee = traces[0, :] - traces[1, :] / np.exp(timescales) sub = -timescales * matrix.shape[0] / np.exp(timescales) return np.array(subee + sub)