Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TCH model of Triadic Closure & Homophily without Preferential Attachment #13

Merged
merged 2 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4,646 changes: 146 additions & 4,500 deletions examples/notebooks/undirected.ipynb

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions netin/generators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
from .pah import PAH
from .patc import PATC
from .patch import PATCH
from .tch import TCH
from .tc import TriadicClosure
from .undirected import UnDiGraph
185 changes: 185 additions & 0 deletions netin/generators/tch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
from typing import Set, Union, Tuple

import numpy as np

from netin.generators.undirected import UnDiGraph
from netin.generators.h import Homophily
from netin.generators.tc import TriadicClosure
from netin.utils import constants as const


class TCH(UnDiGraph, Homophily, TriadicClosure):
"""Creates a new TCH graph. An undirected graph with homophily and triadic closure as link formation mechanisms.

Parameters
----------
n: int
number of nodes (minimum=2)

k: int
minimum degree of nodes (minimum=1)

f_m: float
fraction of minorities (minimum=1/n, maximum=(n-1)/n)

h_MM: float
homophily (similarity) between majority nodes (minimum=0, maximum=1.)

h_mm: float
homophily (similarity) between minority nodes (minimum=0, maximum=1.)

tc: float
probability of a new edge to close a triad (minimum=0, maximum=1.)

Notes
-----
The initialization is an undirected graph with n nodes and no edges.
Then, everytime a node is selected as source, it gets connected to k target nodes.
Target nodes are selected via homophily (h_**; see :class:`netin.Homophily`) [Karimi2018]_ with probability ``1-p_{TC}``,
and with probability ``p_{TC}`` via triadic closure (see :class:`netin.TriadicClosure`) [HolmeKim2002]_.

Note that this model is still work in progress and not fully implemented yet.
"""

############################################################
# Constructor
############################################################

def __init__(self, n: int, k: int, f_m: float, h_mm: float, h_MM: float, tc: float, seed: object = None):
UnDiGraph.__init__(self, n, k, f_m, seed)
Homophily.__init__(self, n=n, f_m=f_m, h_MM=h_MM, h_mm=h_mm, seed=seed)
TriadicClosure.__init__(self, n=n, f_m=f_m, tc=tc, seed=seed)

############################################################
# Init
############################################################

def _infer_model_name(self):
"""
Infers the name of the model.
"""
return self.set_model_name(const.TCH_MODEL_NAME)

############################################################
# Generation
############################################################

def get_target_probabilities(self, source: Union[None, int], target_set: Union[None, Set[int]],
special_targets: Union[None, object, iter] = None) -> Tuple[np.array, set[int]]:
"""
Returns the probabilities of nodes to be selected as target nodes.

Parameters
----------
source: int
source node id

target_set: set
set of target node ids

special_targets: dict
dictionary of special target node ids to be considered

Returns
-------
tuple
probabilities of nodes to be selected as target nodes, and set of target of nodes

"""
return TriadicClosure.get_target_probabilities(self, source, target_set, special_targets)

def get_target_probabilities_regular(self, source: Union[None, int], target_set: Union[None, Set[int]],
special_targets: Union[None, object, iter] = None) -> Tuple[
np.ndarray, set[int]]:
"""
Returns the probability of nodes to be selected as target nodes using the homophily mechanism.

Parameters
----------
source: int
source node id

target_set: set
set of target node ids

special_targets: dict
dictionary of special target node ids to be considered

Returns
-------
tuple
probabilities of nodes to be selected as target nodes, and set of target of nodes
"""
probs = np.asarray([self.get_homophily_between_source_and_target(source, target) + const.EPSILON for target in target_set])
return probs / probs.sum(), target_set

def get_special_targets(self, source: int) -> object:
"""
Returns an empty dictionary (source node ids)

Parameters
----------
source : int
Newly added node

Returns
-------
Dict
Empty dictionary
"""
return TriadicClosure.get_special_targets(self, source)

############################################################
# Calculations
############################################################

def info_params(self):
"""
Shows the (input) parameters of the graph.
"""
Homophily.info_params(self)
TriadicClosure.info_params(self)

def info_computed(self):
"""
Shows the (computed) properties of the graph.
"""
Homophily.info_computed(self)
TriadicClosure.info_computed(self)

def infer_homophily_values(self) -> Tuple[float, float]:
"""
Infers analytically the homophily values of the graph.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a @todo or a message that implementation is not yet done.


Returns
-------
tuple
homophily values of the graph (majority, minority)
"""
h_MM = None
h_mm = None
return h_MM, h_mm

def infer_triadic_closure(self) -> float:
"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a @todo or a message that implementation is not yet done.

Infers analytically the triadic closure value of the graph.

Returns
-------
float
triadic closure probability of the graph
"""
tc = None
return tc

def _makecopy(self):
"""
Makes a copy of the current object.
"""
return self.__class__(n=self.n,
k=self.k,
f_m=self.f_m,
tc=self.tc,
h_MM=self.h_MM,
h_mm=self.h_mm,
seed=self.seed)
2 changes: 2 additions & 0 deletions netin/utils/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
PATC_MODEL_NAME = 'PATC'
PATCH_MODEL_NAME = 'PATCH'

TCH_MODEL_NAME = 'TCH'

DH_MODEL_NAME = 'DH'
DPA_MODEL_NAME = 'DPA'
DPAH_MODEL_NAME = 'DPAH'
Expand Down