Skip to content

Commit

Permalink
adding tests for dpa, homophily and pa
Browse files Browse the repository at this point in the history
  • Loading branch information
lisette-espin committed Sep 11, 2024
1 parent 42ff2b9 commit cce1f78
Show file tree
Hide file tree
Showing 3 changed files with 351 additions and 0 deletions.
35 changes: 35 additions & 0 deletions netin/models/tests/test_dpa.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import numpy as np

from netin.models import DPAModel

class TestDPAModel(object):
@staticmethod
def _create_model(
N=1000, d=0.005, f_m=0.1,
plo_M=2.0, plo_m=2.0,
seed=1234) -> DPAModel:
return DPAModel(
N=N, d=d, f_m=f_m, plo_M=plo_M, plo_m=plo_m, seed=seed)

def test_simulation(self):
model = TestDPAModel._create_model()
model.simulate()
graph = model.graph

assert len(graph) == model.N
assert graph.is_directed()
n_edges = graph.number_of_edges()
assert np.isclose(
n_edges / (model.N * (model.N - 1)),
model.d,
atol=1e-5)

def test_preload_graph(self):
pass

def test_no_invalid_links(self):
model = TestDPAModel._create_model()
model.simulate()
graph = model.graph
for node in graph.nodes():
assert not graph.has_edge(node, node)
175 changes: 175 additions & 0 deletions netin/models/tests/test_homophily.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
import pytest

from netin.models import HomophilyModel
from netin.utils.constants import CLASS_ATTRIBUTE
from netin.graphs.binary_class_node_vector import BinaryClassNodeVector
from netin.graphs import Graph, DiGraph

import numpy as np

class TestHomophilyModel:
@staticmethod
def _create_model(
N=1000, m=2, f_m=0.1, h_m=0.5, h_M=0.5, seed=1234
):
return HomophilyModel(
N=N, m=m, f_m=f_m, h_m=h_m, h_M=h_M, seed=seed
)

def test_simulation(self):
N = 1000
m = 2
f_m = .3

model = TestHomophilyModel._create_model(N=N, m=m, f_m=f_m)
model.simulate()

assert model.graph is not None
assert not model.graph.is_directed()
assert len(model.graph) == N
_sum_links = sum(model.graph.degree(v)\
for v in model.graph.nodes())
assert (_sum_links // 2) == (((N - m) * m) + (m * (m - 1)) // 2)

node_classes = model.graph.get_node_class(CLASS_ATTRIBUTE)
assert node_classes is not None
assert len(node_classes) == N
assert np.isclose(np.mean(node_classes), f_m, atol=0.05)

assert isinstance(node_classes, BinaryClassNodeVector)
assert np.isclose(
node_classes.get_n_minority(),
f_m * N, rtol=0.05)

def test_preload_graph(self):
N = 1000
N_pre = 10
m = 2
f_m = .3
f_m_pre = .1

model = TestHomophilyModel._create_model(N=N, f_m=f_m)
with pytest.raises(AssertionError):
model.preload_graph(DiGraph())

g_pre = Graph()
for i in range(N_pre):
g_pre.add_node(i)
g_pre.add_edge(0, 1)
g_pre.set_node_class(
CLASS_ATTRIBUTE,
BinaryClassNodeVector.from_fraction(N=N_pre, f_m=f_m_pre))
model.preload_graph(g_pre)
model.initialize_simulation()
assert len(g_pre.get_node_class(CLASS_ATTRIBUTE)) == (N_pre + N),\
"Node class not set correctly."
model.simulate()

assert len(model.graph) == (N + N_pre)
_sum_links = sum(model.graph.degree(v)\
for v in model.graph.nodes()) // 2
assert _sum_links == (1 + (N * m))
for u in range(N_pre):
for v in range(u):
if u == v:
assert not model.graph.has_edge(u, v)
elif (u == 0 and v == 1) or (v == 0 and u == 1):
assert model.graph.has_edge(u, v)
else:
assert not model.graph.has_edge(u, v)
node_classes = model.graph.get_node_class(CLASS_ATTRIBUTE)
assert node_classes is not None
assert len(node_classes) == (N + N_pre)
assert np.isclose(np.mean(node_classes), f_m, atol=0.05)

model = TestHomophilyModel._create_model(N=N, f_m=f_m)
g_pre = Graph()
for i in range(N_pre):
g_pre.add_node(i)
g_pre.set_node_class(
CLASS_ATTRIBUTE,
BinaryClassNodeVector.from_fraction(N=N_pre, f_m=f_m_pre))
model.simulate()
node_classes = model.graph.get_node_class(CLASS_ATTRIBUTE)
assert node_classes is not None
assert len(node_classes) == N
assert np.isclose(
np.sum(node_classes),
(N_pre * f_m_pre) + (N * f_m),
rtol=0.05)

def test_no_invalid_links(self):
N = 1000
m = 2
model = TestHomophilyModel._create_model(N=N, m=m)
model.simulate()
graph = model.graph

# The graph class cannot store double links
# Hence, if there are no self-links, the number of links
# must be `(N-m) * m` because each but the first `m` nodes
# create `m` links.
for u in graph.nodes():
assert not graph.has_edge(u, u)
n_links = graph.number_of_edges()
assert n_links == ((N - m) * m) + ((m * (m - 1)) // 2)

def test_heterophily_min_advantage(self):
h = 0.1

model = TestHomophilyModel._create_model(
h_m=h, h_M=h)
model.simulate()
node_classes = model.graph.get_node_class(CLASS_ATTRIBUTE)

minority_mask = node_classes.get_minority_mask()
majority_mask = node_classes.get_majority_mask()

degrees = model.graph.degrees()
degrees_min = degrees[minority_mask]
degrees_maj = degrees[majority_mask]

assert np.mean(degrees_min) > np.mean(degrees_maj)

def test_homophily_maj_advantage(self):
h = .9

model = TestHomophilyModel._create_model(
h_m=h, h_M=h)
model.simulate()
node_classes = model.graph.get_node_class(CLASS_ATTRIBUTE)

minority_mask = node_classes.get_minority_mask()
majority_mask = node_classes.get_majority_mask()

degrees = model.graph.degrees()
degrees_min = degrees[minority_mask]
degrees_maj = degrees[majority_mask]

assert np.mean(degrees_min) < np.mean(degrees_maj)

def test_seeding(self):
model1 = TestHomophilyModel._create_model(seed=1234)
model1.simulate()
graph1 = model1.graph
nc1 = graph1.get_node_class(CLASS_ATTRIBUTE)

model2 = TestHomophilyModel._create_model(seed=1234)
model2.simulate()
graph2 = model2.graph
nc2 = graph2.get_node_class(CLASS_ATTRIBUTE)

model3 = TestHomophilyModel._create_model(seed=999)
model3.simulate()
graph3 = model3.graph
nc3 = graph3.get_node_class(CLASS_ATTRIBUTE)

assert np.all(nc1 == nc2)
assert not np.all(nc1 == nc3)

_n_non_overlap = 0
for u in graph1.nodes():
assert graph1[u] == graph2[u]
if not graph1[u] == graph3[u]:
_n_non_overlap += 1
assert _n_non_overlap > 0
141 changes: 141 additions & 0 deletions netin/models/tests/test_pa.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import pytest

from netin.models import PAModel
from netin.utils.constants import CLASS_ATTRIBUTE
from netin.graphs.binary_class_node_vector import BinaryClassNodeVector
from netin.graphs import Graph, DiGraph

import numpy as np

class TestPAModel:
@staticmethod
def _create_model(
N=1000, m=2, f_m=0.1, seed=1234
):
return PAModel(
N=N, m=m, f_m=f_m, seed=seed
)

def test_simulation(self):
N = 1000
m = 2
f_m = .3

model = TestPAModel._create_model(N=N, m=m, f_m=f_m)
model.simulate()

assert model.graph is not None
assert not model.graph.is_directed()
assert len(model.graph) == N
_sum_links = sum(model.graph.degree(v)\
for v in model.graph.nodes())
assert (_sum_links // 2) == (((N - m) * m) + (m * (m - 1)) // 2)

node_classes = model.graph.get_node_class(CLASS_ATTRIBUTE)
assert node_classes is not None
assert len(node_classes) == N
assert np.isclose(np.mean(node_classes), f_m, atol=0.05)

assert isinstance(node_classes, BinaryClassNodeVector)
assert np.isclose(
node_classes.get_n_minority(),
f_m * N, rtol=0.05)

def test_preload_graph(self):
N = 1000
N_pre = 10
m = 2
f_m = .3
f_m_pre = .1

model = TestPAModel._create_model(N=N, f_m=f_m)
with pytest.raises(AssertionError):
model.preload_graph(DiGraph())

g_pre = Graph()
for i in range(N_pre):
g_pre.add_node(i)
g_pre.add_edge(0, 1)
g_pre.set_node_class(
CLASS_ATTRIBUTE,
BinaryClassNodeVector.from_fraction(N=N_pre, f_m=f_m_pre))
model.preload_graph(g_pre)
model.initialize_simulation()
assert len(g_pre.get_node_class(CLASS_ATTRIBUTE)) == (N_pre + N),\
"Node class not set correctly."
model.simulate()

assert len(model.graph) == (N + N_pre)
_sum_links = sum(model.graph.degree(v)\
for v in model.graph.nodes()) // 2
assert _sum_links == (1 + (N * m))
for u in range(N_pre):
for v in range(u):
if u == v:
assert not model.graph.has_edge(u, v)
elif (u == 0 and v == 1) or (v == 0 and u == 1):
assert model.graph.has_edge(u, v)
else:
assert not model.graph.has_edge(u, v)
node_classes = model.graph.get_node_class(CLASS_ATTRIBUTE)
assert node_classes is not None
assert len(node_classes) == (N + N_pre)
assert np.isclose(np.mean(node_classes), f_m, atol=0.05)

model = TestPAModel._create_model(N=N, f_m=f_m)
g_pre = Graph()
for i in range(N_pre):
g_pre.add_node(i)
g_pre.set_node_class(
CLASS_ATTRIBUTE,
BinaryClassNodeVector.from_fraction(N=N_pre, f_m=f_m_pre))
model.simulate()
node_classes = model.graph.get_node_class(CLASS_ATTRIBUTE)
assert node_classes is not None
assert len(node_classes) == N
assert np.isclose(
np.sum(node_classes),
(N_pre * f_m_pre) + (N * f_m),
rtol=0.05)

def test_no_invalid_links(self):
N = 1000
m = 2
model = TestPAModel._create_model(N=N, m=m)
model.simulate()
graph = model.graph

# The graph class cannot store double links
# Hence, if there are no self-links, the number of links
# must be `(N-m) * m` because each but the first `m` nodes
# create `m` links.
for u in graph.nodes():
assert not graph.has_edge(u, u)
n_links = graph.number_of_edges()
assert n_links == ((N - m) * m) + ((m * (m - 1)) // 2)

def test_seeding(self):
model1 = TestPAModel._create_model(seed=1234)
model1.simulate()
graph1 = model1.graph
nc1 = graph1.get_node_class(CLASS_ATTRIBUTE)

model2 = TestPAModel._create_model(seed=1234)
model2.simulate()
graph2 = model2.graph
nc2 = graph2.get_node_class(CLASS_ATTRIBUTE)

model3 = TestPAModel._create_model(seed=999)
model3.simulate()
graph3 = model3.graph
nc3 = graph3.get_node_class(CLASS_ATTRIBUTE)

assert np.all(nc1 == nc2)
assert not np.all(nc1 == nc3)

_n_non_overlap = 0
for u in graph1.nodes():
assert graph1[u] == graph2[u]
if not graph1[u] == graph3[u]:
_n_non_overlap += 1
assert _n_non_overlap > 0

0 comments on commit cce1f78

Please sign in to comment.