Skip to content

graph_interdependence

Bases: interdependence

A graph-based interdependence function.

This class computes the interdependence matrix using a graph structure, allowing relationships to be modeled based on nodes and edges in the graph.

Notes

Based on the graph structure, we define the graph interdependence function as:

\[
    \begin{equation}\label{equ:graph_interdependence_function}
    \xi(\mathbf{x} | G) = \mathbf{A} \in R^{m \times m'},
    \end{equation}
\]

where the output dimension \(m' = m\) by default.

Attributes:

Name Type Description
graph graph

The graph structure representing the interdependence.

node_id_index_map dict

Mapping of node IDs to their indices in the matrix.

node_index_id_map dict

Mapping of matrix indices back to their corresponding node IDs.

normalization bool

Whether to normalize the interdependence matrix.

normalization_mode str

The mode of normalization ('row', 'column', etc.).

self_dependence bool

Whether nodes are self-dependent.

Methods:

Name Description
__init__

Initializes the graph-based interdependence function.

get_node_index_id_map

Retrieves the mapping from indices to node IDs.

get_node_id_index_map

Retrieves the mapping from node IDs to indices.

calculate_A

Computes the interdependence matrix using the graph structure.

Source code in tinybig/interdependence/topological_interdependence.py
class graph_interdependence(interdependence):
    r"""
        A graph-based interdependence function.

        This class computes the interdependence matrix using a graph structure, allowing
        relationships to be modeled based on nodes and edges in the graph.

        Notes
        ----------
        Based on the graph structure, we define the graph interdependence function as:

        $$
            \begin{equation}\label{equ:graph_interdependence_function}
            \xi(\mathbf{x} | G) = \mathbf{A} \in R^{m \times m'},
            \end{equation}
        $$

        where the output dimension $m' = m$ by default.

        Attributes
        ----------
        graph : graph_structure
            The graph structure representing the interdependence.
        node_id_index_map : dict
            Mapping of node IDs to their indices in the matrix.
        node_index_id_map : dict
            Mapping of matrix indices back to their corresponding node IDs.
        normalization : bool
            Whether to normalize the interdependence matrix.
        normalization_mode : str
            The mode of normalization ('row', 'column', etc.).
        self_dependence : bool
            Whether nodes are self-dependent.

        Methods
        -------
        __init__(...)
            Initializes the graph-based interdependence function.
        get_node_index_id_map()
            Retrieves the mapping from indices to node IDs.
        get_node_id_index_map()
            Retrieves the mapping from node IDs to indices.
        calculate_A(...)
            Computes the interdependence matrix using the graph structure.
    """

    def __init__(
        self,
        b: int, m: int,
        interdependence_type: str = 'instance',
        name: str = 'graph_interdependence',
        graph: graph_structure = None,
        nodes: list = None, links: list = None, directed: bool = True,
        normalization: bool = False, normalization_mode: str = 'row',
        self_dependence: bool = False,
        require_data: bool = False, require_parameters: bool = False,
        device: str = 'cpu', *args, **kwargs
    ):
        """
            Initializes the graph-based interdependence function.

            Parameters
            ----------
            b : int
                Number of rows in the input tensor.
            m : int
                Number of columns in the input tensor.
            interdependence_type : str, optional
                Type of interdependence ('instance', 'attribute', etc.). Defaults to 'instance'.
            name : str, optional
                Name of the interdependence function. Defaults to 'graph_interdependence'.
            graph : graph_structure, optional
                Predefined graph structure. Defaults to None.
            nodes : list, optional
                List of nodes in the graph. Required if `graph` is not provided. Defaults to None.
            links : list, optional
                List of links (edges) in the graph. Required if `graph` is not provided. Defaults to None.
            directed : bool, optional
                Whether the graph is directed. Defaults to True.
            normalization : bool, optional
                Whether to normalize the interdependence matrix. Defaults to False.
            normalization_mode : str, optional
                The mode of normalization ('row', 'column', etc.). Defaults to 'row'.
            self_dependence : bool, optional
                Whether nodes are self-dependent. Defaults to False.
            require_data : bool, optional
                Whether the interdependence function requires data. Defaults to False.
            require_parameters : bool, optional
                Whether the interdependence function requires parameters. Defaults to False.
            device : str, optional
                Device for computation ('cpu', 'cuda'). Defaults to 'cpu'.
            *args : tuple
                Additional positional arguments for the parent class.
            **kwargs : dict
                Additional keyword arguments for the parent class.

            Raises
            ------
            ValueError
                If neither `graph` nor both `nodes` and `links` are provided.
        """
        super().__init__(b=b, m=m, name=name, interdependence_type=interdependence_type, require_data=require_data, require_parameters=require_parameters, device=device, *args, **kwargs)

        if graph is not None:
            self.graph = graph
        elif nodes is not None and links is not None:
            self.graph = graph_structure(nodes=nodes, links=links, directed=directed)
        else:
            raise ValueError('Either nodes or links must be provided')

        self.node_id_index_map = None
        self.node_index_id_map = None

        self.normalization = normalization
        self.normalization_mode = normalization_mode
        self.self_dependence = self_dependence

    def get_node_index_id_map(self):
        """
            Retrieves the mapping from indices to node IDs.

            Returns
            -------
            dict
                A dictionary mapping matrix indices to node IDs.

            Warnings
            --------
            If the mapping has not been assigned, a warning will be raised.
        """
        if self.node_index_id_map is None:
            warnings.warn("The mapping has not been assigned yet, please call the calculate_A method first...")
        return self.node_index_id_map

    def get_node_id_index_map(self):
        """
            Retrieves the mapping from node IDs to indices.

            Returns
            -------
            dict
                A dictionary mapping node IDs to matrix indices.

            Warnings
            --------
            If the mapping has not been assigned, a warning will be raised.
        """
        if self.node_id_index_map is None:
            warnings.warn("The mapping has not been assigned yet, please call the calculate_A method first...")
        return self.node_id_index_map

    def calculate_A(self, x: torch.Tensor = None, w: torch.nn.Parameter = None, device: str = 'cpu', *args, **kwargs):
        """
            Computes the interdependence matrix using the graph structure.

            Parameters
            ----------
            x : torch.Tensor, optional
                Input tensor of shape `(batch_size, num_features)`. Defaults to None.
            w : torch.nn.Parameter, optional
                Parameter tensor. Defaults to None.
            device : str, optional
                Device for computation ('cpu', 'cuda'). Defaults to 'cpu'.
            *args : tuple
                Additional positional arguments.
            **kwargs : dict
                Additional keyword arguments.

            Returns
            -------
            torch.Tensor
                The computed interdependence matrix.

            Raises
            ------
            AssertionError
                If the computed matrix shape is invalid.
        """
        if not self.require_data and not self.require_parameters and self.A is not None:
            return self.A
        else:
            adj, mappings = self.graph.to_matrix(self_dependence=self.self_dependence, normalization=self.normalization, normalization_mode=self.normalization_mode, device=device)

            self.node_id_index_map = mappings['node_id_index_map']
            self.node_index_id_map = mappings['node_index_id_map']

            A = self.post_process(x=adj, device=device)

            if self.interdependence_type in ['column', 'right', 'attribute', 'attribute_interdependence']:
                assert A.shape == (self.m, self.calculate_m_prime())
            elif self.interdependence_type in ['row', 'left', 'instance', 'instance_interdependence']:
                assert A.shape == (self.b, self.calculate_b_prime())

            if not self.require_data and not self.require_parameters and self.A is None:
                self.A = A
            return A

__init__(b, m, interdependence_type='instance', name='graph_interdependence', graph=None, nodes=None, links=None, directed=True, normalization=False, normalization_mode='row', self_dependence=False, require_data=False, require_parameters=False, device='cpu', *args, **kwargs)

Initializes the graph-based interdependence function.

Parameters:

Name Type Description Default
b int

Number of rows in the input tensor.

required
m int

Number of columns in the input tensor.

required
interdependence_type str

Type of interdependence ('instance', 'attribute', etc.). Defaults to 'instance'.

'instance'
name str

Name of the interdependence function. Defaults to 'graph_interdependence'.

'graph_interdependence'
graph graph

Predefined graph structure. Defaults to None.

None
nodes list

List of nodes in the graph. Required if graph is not provided. Defaults to None.

None
links list

List of links (edges) in the graph. Required if graph is not provided. Defaults to None.

None
directed bool

Whether the graph is directed. Defaults to True.

True
normalization bool

Whether to normalize the interdependence matrix. Defaults to False.

False
normalization_mode str

The mode of normalization ('row', 'column', etc.). Defaults to 'row'.

'row'
self_dependence bool

Whether nodes are self-dependent. Defaults to False.

False
require_data bool

Whether the interdependence function requires data. Defaults to False.

False
require_parameters bool

Whether the interdependence function requires parameters. Defaults to False.

False
device str

Device for computation ('cpu', 'cuda'). Defaults to 'cpu'.

'cpu'
*args tuple

Additional positional arguments for the parent class.

()
**kwargs dict

Additional keyword arguments for the parent class.

{}

Raises:

Type Description
ValueError

If neither graph nor both nodes and links are provided.

Source code in tinybig/interdependence/topological_interdependence.py
def __init__(
    self,
    b: int, m: int,
    interdependence_type: str = 'instance',
    name: str = 'graph_interdependence',
    graph: graph_structure = None,
    nodes: list = None, links: list = None, directed: bool = True,
    normalization: bool = False, normalization_mode: str = 'row',
    self_dependence: bool = False,
    require_data: bool = False, require_parameters: bool = False,
    device: str = 'cpu', *args, **kwargs
):
    """
        Initializes the graph-based interdependence function.

        Parameters
        ----------
        b : int
            Number of rows in the input tensor.
        m : int
            Number of columns in the input tensor.
        interdependence_type : str, optional
            Type of interdependence ('instance', 'attribute', etc.). Defaults to 'instance'.
        name : str, optional
            Name of the interdependence function. Defaults to 'graph_interdependence'.
        graph : graph_structure, optional
            Predefined graph structure. Defaults to None.
        nodes : list, optional
            List of nodes in the graph. Required if `graph` is not provided. Defaults to None.
        links : list, optional
            List of links (edges) in the graph. Required if `graph` is not provided. Defaults to None.
        directed : bool, optional
            Whether the graph is directed. Defaults to True.
        normalization : bool, optional
            Whether to normalize the interdependence matrix. Defaults to False.
        normalization_mode : str, optional
            The mode of normalization ('row', 'column', etc.). Defaults to 'row'.
        self_dependence : bool, optional
            Whether nodes are self-dependent. Defaults to False.
        require_data : bool, optional
            Whether the interdependence function requires data. Defaults to False.
        require_parameters : bool, optional
            Whether the interdependence function requires parameters. Defaults to False.
        device : str, optional
            Device for computation ('cpu', 'cuda'). Defaults to 'cpu'.
        *args : tuple
            Additional positional arguments for the parent class.
        **kwargs : dict
            Additional keyword arguments for the parent class.

        Raises
        ------
        ValueError
            If neither `graph` nor both `nodes` and `links` are provided.
    """
    super().__init__(b=b, m=m, name=name, interdependence_type=interdependence_type, require_data=require_data, require_parameters=require_parameters, device=device, *args, **kwargs)

    if graph is not None:
        self.graph = graph
    elif nodes is not None and links is not None:
        self.graph = graph_structure(nodes=nodes, links=links, directed=directed)
    else:
        raise ValueError('Either nodes or links must be provided')

    self.node_id_index_map = None
    self.node_index_id_map = None

    self.normalization = normalization
    self.normalization_mode = normalization_mode
    self.self_dependence = self_dependence

calculate_A(x=None, w=None, device='cpu', *args, **kwargs)

Computes the interdependence matrix using the graph structure.

Parameters:

Name Type Description Default
x Tensor

Input tensor of shape (batch_size, num_features). Defaults to None.

None
w Parameter

Parameter tensor. Defaults to None.

None
device str

Device for computation ('cpu', 'cuda'). Defaults to 'cpu'.

'cpu'
*args tuple

Additional positional arguments.

()
**kwargs dict

Additional keyword arguments.

{}

Returns:

Type Description
Tensor

The computed interdependence matrix.

Raises:

Type Description
AssertionError

If the computed matrix shape is invalid.

Source code in tinybig/interdependence/topological_interdependence.py
def calculate_A(self, x: torch.Tensor = None, w: torch.nn.Parameter = None, device: str = 'cpu', *args, **kwargs):
    """
        Computes the interdependence matrix using the graph structure.

        Parameters
        ----------
        x : torch.Tensor, optional
            Input tensor of shape `(batch_size, num_features)`. Defaults to None.
        w : torch.nn.Parameter, optional
            Parameter tensor. Defaults to None.
        device : str, optional
            Device for computation ('cpu', 'cuda'). Defaults to 'cpu'.
        *args : tuple
            Additional positional arguments.
        **kwargs : dict
            Additional keyword arguments.

        Returns
        -------
        torch.Tensor
            The computed interdependence matrix.

        Raises
        ------
        AssertionError
            If the computed matrix shape is invalid.
    """
    if not self.require_data and not self.require_parameters and self.A is not None:
        return self.A
    else:
        adj, mappings = self.graph.to_matrix(self_dependence=self.self_dependence, normalization=self.normalization, normalization_mode=self.normalization_mode, device=device)

        self.node_id_index_map = mappings['node_id_index_map']
        self.node_index_id_map = mappings['node_index_id_map']

        A = self.post_process(x=adj, device=device)

        if self.interdependence_type in ['column', 'right', 'attribute', 'attribute_interdependence']:
            assert A.shape == (self.m, self.calculate_m_prime())
        elif self.interdependence_type in ['row', 'left', 'instance', 'instance_interdependence']:
            assert A.shape == (self.b, self.calculate_b_prime())

        if not self.require_data and not self.require_parameters and self.A is None:
            self.A = A
        return A

get_node_id_index_map()

Retrieves the mapping from node IDs to indices.

Returns:

Type Description
dict

A dictionary mapping node IDs to matrix indices.

Warnings

If the mapping has not been assigned, a warning will be raised.

Source code in tinybig/interdependence/topological_interdependence.py
def get_node_id_index_map(self):
    """
        Retrieves the mapping from node IDs to indices.

        Returns
        -------
        dict
            A dictionary mapping node IDs to matrix indices.

        Warnings
        --------
        If the mapping has not been assigned, a warning will be raised.
    """
    if self.node_id_index_map is None:
        warnings.warn("The mapping has not been assigned yet, please call the calculate_A method first...")
    return self.node_id_index_map

get_node_index_id_map()

Retrieves the mapping from indices to node IDs.

Returns:

Type Description
dict

A dictionary mapping matrix indices to node IDs.

Warnings

If the mapping has not been assigned, a warning will be raised.

Source code in tinybig/interdependence/topological_interdependence.py
def get_node_index_id_map(self):
    """
        Retrieves the mapping from indices to node IDs.

        Returns
        -------
        dict
            A dictionary mapping matrix indices to node IDs.

        Warnings
        --------
        If the mapping has not been assigned, a warning will be raised.
    """
    if self.node_index_id_map is None:
        warnings.warn("The mapping has not been assigned yet, please call the calculate_A method first...")
    return self.node_index_id_map