Source code for sknetwork.utils.format

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created in April 2019
@author: Nathan de Lara <nathan.delara@polytechnique.org>
"""
from typing import Union, Tuple, Optional

import numpy as np
from scipy import sparse

from sknetwork.linalg.sparse_lowrank import SparseLR
from sknetwork.utils.check import check_format, is_square, is_symmetric
from sknetwork.utils.values import stack_values, get_values

"""Check if input is csr or SparseLR and raise an error otherwise."""
if type(adjacency) not in [sparse.csr_matrix, SparseLR]:
raise TypeError('Input must be a scipy CSR matrix or a SparseLR object.')

weighted: bool = True) -> Union[sparse.csr_matrix, SparseLR]:
"""Adjacency matrix of the undirected graph associated with some directed graph.

The new adjacency matrix becomes either:

:math:A+A^T (default)

or

:math:\\max(A,A^T)

If the initial adjacency matrix :math:A is binary, bidirectional edges have weight 2
(first method, default) or 1 (second method).

Parameters
----------
weighted :
If True, return the sum of the weights in both directions of each edge.

Returns
-------
New adjacency matrix (same format as input).
"""
if weighted:
data_type = float
else:
data_type = int
else:
else:
if weighted:
new_tuples = [(y, x) for (x, y) in adjacency.low_rank_tuples]
else:
raise ValueError('This function only works with weighted=True for SparseLR objects.')

[docs]def bipartite2directed(biadjacency: Union[sparse.csr_matrix, SparseLR]) -> Union[sparse.csr_matrix, SparseLR]:
"""Adjacency matrix of the directed graph associated with a bipartite graph
(with edges from one part to the other).

:math:A  = \\begin{bmatrix} 0 & B \\\\ 0 & 0 \\end{bmatrix}

where :math:B is the biadjacency matrix.

Parameters
----------

Returns
-------
Adjacency matrix (same format as input).
"""
else:
new_tuples = [(np.hstack((x, np.zeros(n_col))), np.hstack((np.zeros(n_row), y)))

[docs]def bipartite2undirected(biadjacency: Union[sparse.csr_matrix, SparseLR]) -> Union[sparse.csr_matrix, SparseLR]:

:math:A  = \\begin{bmatrix} 0 & B \\\\ B^T & 0 \\end{bmatrix}

where :math:B is the biadjacency matrix of the bipartite graph.

Parameters
----------

Returns
-------
Adjacency matrix (same format as input).
"""
else:
new_tuples = []
new_tuples.append((np.hstack((x, np.zeros(n_col))), np.hstack((np.zeros(n_row), y))))
new_tuples.append((np.hstack((np.zeros(n_row), y)), np.hstack((x, np.zeros(n_col)))))

def get_adjacency(input_matrix: Union[sparse.csr_matrix, np.ndarray], allow_directed: bool = True,
force_bipartite: bool = False, force_directed: bool = False, allow_empty: bool = False)\
-> Tuple[sparse.csr_matrix, bool]:
"""Check the input matrix and return a proper adjacency matrix.
Parameters
----------
input_matrix :
allow_directed :
If True (default), allow the graph to be directed.
force_bipartite : bool
If True, return the adjacency matrix of a bipartite graph.
Otherwise (default), do it only if the input matrix is not square or not symmetric
with allow_directed=False.
force_directed :
If True return :math:A  = \\begin{bmatrix} 0 & B \\\\ 0 & 0 \\end{bmatrix}.
Otherwise (default), return :math:A  = \\begin{bmatrix} 0 & B \\\\ B^T & 0 \\end{bmatrix}.
allow_empty :
If True, allow the input matrix to be empty.
"""
input_matrix = check_format(input_matrix, allow_empty=allow_empty)
bipartite = False
if force_bipartite or not is_square(input_matrix) or not (allow_directed or is_symmetric(input_matrix)):
bipartite = True
if bipartite:
if force_directed:
else:
else:

def get_adjacency_values(input_matrix: Union[sparse.csr_matrix, np.ndarray], allow_directed: bool = True,
force_bipartite: bool = False, force_directed: bool = False,
values: Optional[Union[dict, np.ndarray]] = None,
values_row: Optional[Union[dict, np.ndarray]] = None,
values_col: Optional[Union[dict, np.ndarray]] = None,
default_value: float = -1,
which: Optional[str] = None) \
-> Tuple[sparse.csr_matrix, np.ndarray, bool]:
"""Check the input matrix and return a proper adjacency matrix and vector of values.
Parameters
----------
input_matrix :
allow_directed :
If True (default), allow the graph to be directed.
force_bipartite : bool
If True, return the adjacency matrix of a bipartite graph.
Otherwise (default), do it only if the input matrix is not square or not symmetric
with allow_directed=False.
force_directed :
If True return :math:A  = \\begin{bmatrix} 0 & B \\\\ 0 & 0 \\end{bmatrix}.
Otherwise (default), return :math:A  = \\begin{bmatrix} 0 & B \\\\ B^T & 0 \\end{bmatrix}.
values :
Values of nodes (dictionary or vector). Negative values ignored.
values_row, values_col :
Values of rows and columns for bipartite graphs. Negative values ignored.
default_value :
Default value of nodes (default = -1).
which :
Which values.
If 'probs', return a probability distribution.
If 'labels', return the values, or distinct integer values if all are the same.
"""
input_matrix = check_format(input_matrix)
if values_row is not None or values_col is not None:
force_bipartite = True
force_bipartite=force_bipartite, force_directed=force_directed)
if bipartite:
if values is None:
values = stack_values(input_matrix.shape, values_row, values_col, default_value=default_value)
else:
values = stack_values(input_matrix.shape, values, default_value=default_value)
else:
values = get_values(input_matrix.shape, values, default_value=default_value)
if which == 'probs':
if values.sum() > 0:
values /= values.sum()
elif which == 'labels':
if len(set(values[values >= 0])) == 1:
values = np.arange(len(values))