Skip to content

Commit

Permalink
added model_loglikelihood method and test
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoloval committed Mar 30, 2021
1 parent 0761568 commit a1bb7a6
Show file tree
Hide file tree
Showing 2 changed files with 211 additions and 35 deletions.
93 changes: 58 additions & 35 deletions src/NEMtropy/graph_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ def __init__(
self.relative_error_strength = None
self.full_return = False
self.last_model = None
self.solution_array

# function
self.args = None
Expand Down Expand Up @@ -334,16 +335,16 @@ def _solve_problem(

def _set_solved_problem_cm(self, solution):
if self.full_return:
self.r_xy = solution[0]
self.solution_array = solution[0]
self.comput_time = solution[1]
self.n_steps = solution[2]
self.norm_seq = solution[3]
self.diff_seq = solution[4]
self.alfa_seq = solution[5]
else:
self.r_xy = solution
self.solution_array = solution

self.r_x = self.r_xy
self.r_x = self.solution_array
if self.last_model == "cm":
self.x = self.r_x[self.r_invert_dseq]
elif self.last_model == "cm_exp":
Expand Down Expand Up @@ -903,23 +904,25 @@ def _set_solved_problem_crema_undirected(self, solution):
else:
self.beta = solution

self.solution_array = self.beta

def _set_solved_problem_ecm(self, solution):
if self.full_return:
self.r_xy = solution[0]
self.solution_array = solution[0]
self.comput_time = solution[1]
self.n_steps = solution[2]
self.norm_seq = solution[3]
self.diff_seq = solution[4]
self.alfa_seq = solution[5]
else:
self.r_xy = solution
self.solution_array = solution

if self.last_model == "ecm":
self.x = self.r_xy[: self.n_nodes]
self.y = self.r_xy[self.n_nodes:]
self.x = self.solution_array[: self.n_nodes]
self.y = self.solution_array[self.n_nodes:]
elif self.last_model == "ecm_exp":
self.x = np.exp(-self.r_xy[:self.n_nodes])
self.y = np.exp(-self.r_xy[self.n_nodes:])
self.x = np.exp(-self.solution_array[:self.n_nodes])
self.y = np.exp(-self.solution_array[self.n_nodes:])

def solve_tool(
self,
Expand Down Expand Up @@ -1120,6 +1123,12 @@ def ensemble_sampler(self, n, cpu_n=1, output_dir="sample/", seed=None):
else:
raise ValueError("insert a model")

def model_loglikelihood(self):
"""Returns the loglikelihood of the solution of last model executed.
"""
return self.step_fun(self.solution_array)



class DirectedGraph:
"""Directed graph instance can be initialised with
Expand Down Expand Up @@ -1188,7 +1197,7 @@ def __init__(
# reduced solutions
self.r_x = None
self.r_y = None
self.r_xy = None
self.solution_array = None
# Problem (reduced) residuals
self.residuals = None
self.final_result = None
Expand Down Expand Up @@ -1478,73 +1487,73 @@ def _solve_problem(

def _set_solved_problem_dcm(self, solution):
if self.full_return:
self.r_xy = solution[0]
self.solution_array = solution[0]
self.comput_time = solution[1]
self.n_steps = solution[2]
self.norm_seq = solution[3]
self.diff_seq = solution[4]
self.alfa_seq = solution[5]
else:
self.r_xy = solution
self.solution_array = solution

self.r_x = self.r_xy[: self.rnz_n_out]
self.r_y = self.r_xy[self.rnz_n_out:]
self.r_x = self.solution_array[: self.rnz_n_out]
self.r_y = self.solution_array[self.rnz_n_out:]

self.x = self.r_x[self.r_invert_dseq]
self.y = self.r_y[self.r_invert_dseq]

def _set_solved_problem_dcm_exp(self, solution):
if self.full_return:
# conversion from theta to x
self.r_xy = np.exp(-solution[0])
self.solution_array = np.exp(-solution[0])
self.comput_time = solution[1]
self.n_steps = solution[2]
self.norm_seq = solution[3]
self.diff_seq = solution[4]
self.alfa_seq = solution[5]
else:
# conversion from theta to x
self.r_xy = np.exp(-solution)
self.solution_array = np.exp(-solution)

self.r_x = self.r_xy[: self.rnz_n_out]
self.r_y = self.r_xy[self.rnz_n_out:]
self.r_x = self.solution_array[: self.rnz_n_out]
self.r_y = self.solution_array[self.rnz_n_out:]

self.x = self.r_x[self.r_invert_dseq]
self.y = self.r_y[self.r_invert_dseq]

def _set_solved_problem_decm(self, solution):
if self.full_return:
self.r_xy = solution[0]
self.solution_array = solution[0]
self.comput_time = solution[1]
self.n_steps = solution[2]
self.norm_seq = solution[3]
self.diff_seq = solution[4]
self.alfa_seq = solution[5]
else:
self.r_xy = solution
self.solution_array = solution

self.x = self.r_xy[: self.n_nodes]
self.y = self.r_xy[self.n_nodes: 2 * self.n_nodes]
self.b_out = self.r_xy[2 * self.n_nodes: 3 * self.n_nodes]
self.b_in = self.r_xy[3 * self.n_nodes:]
self.x = self.solution_array[: self.n_nodes]
self.y = self.solution_array[self.n_nodes: 2 * self.n_nodes]
self.b_out = self.solution_array[2 * self.n_nodes: 3 * self.n_nodes]
self.b_in = self.solution_array[3 * self.n_nodes:]

def _set_solved_problem_decm_exp(self, solution):
if self.full_return:
# conversion from theta to x
self.r_xy = np.exp(-solution[0])
self.solution_array = np.exp(-solution[0])
self.comput_time = solution[1]
self.n_steps = solution[2]
self.norm_seq = solution[3]
self.diff_seq = solution[4]
self.alfa_seq = solution[5]
else:
# conversion from theta to x
self.r_xy = np.exp(-solution)
self.solution_array = np.exp(-solution)

self.x = self.r_xy[: self.n_nodes]
self.y = self.r_xy[self.n_nodes: 2 * self.n_nodes]
self.b_out = self.r_xy[2 * self.n_nodes: 3 * self.n_nodes]
self.b_in = self.r_xy[3 * self.n_nodes:]
self.x = self.solution_array[: self.n_nodes]
self.y = self.solution_array[self.n_nodes: 2 * self.n_nodes]
self.b_out = self.solution_array[2 * self.n_nodes: 3 * self.n_nodes]
self.b_in = self.solution_array[3 * self.n_nodes:]

def _set_solved_problem(self, solution):
model = self.last_model
Expand Down Expand Up @@ -2376,6 +2385,8 @@ def _set_solved_problem_crema_directed(self, solution):
self.b_out = solution[: self.n_nodes]
self.b_in = solution[self.n_nodes:]

self.solution_array = solution

def solve_tool(
self,
model,
Expand Down Expand Up @@ -2579,6 +2590,11 @@ def ensemble_sampler(self, n, cpu_n=1, output_dir="sample/", seed=None):
else:
raise ValueError("insert a model")

def model_loglikelihood(self):
"""Returns the loglikelihood of the solution of last model executed.
"""
return self.step_fun(self.solution_array)


class BipartiteGraph:
"""Bipartite Graph class for undirected binary bipartite networks.
Expand Down Expand Up @@ -2639,7 +2655,7 @@ def __init__(self, biadjacency=None, adjacency_list=None, edgelist=None, degree_
self.y = None
self.r_x = None
self.r_y = None
self.r_xy = None
self.solution_array = None
self.dict_x = None
self.dict_y = None
self.theta_x = None
Expand Down Expand Up @@ -2681,6 +2697,7 @@ def __init__(self, biadjacency=None, adjacency_list=None, edgelist=None, degree_
self.full_rows_num = None
self.full_rows_num = None
self.solution_converged = None
self.solution_array = None

def _initialize_graph(self, biadjacency=None, adjacency_list=None, edgelist=None, degree_sequences=None):
"""
Expand Down Expand Up @@ -3137,15 +3154,15 @@ def _set_solved_problem(self, solution):
self.r_theta_xy = solution
self.r_theta_x = self.r_theta_xy[:self.r_n_rows]
self.r_theta_y = self.r_theta_xy[self.r_n_rows:]
self.r_xy = np.exp(- self.r_theta_xy)
self.solution_array = np.exp(- self.r_theta_xy)
self.r_x = np.exp(- self.r_theta_x)
self.r_y = np.exp(- self.r_theta_y)
self.theta_x[self.nonfixed_rows] = self.r_theta_x[self.r_invert_rows_deg]
self.theta_y[self.nonfixed_cols] = self.r_theta_y[self.r_invert_cols_deg]
else:
self.r_xy = solution
self.r_x = self.r_xy[:self.r_n_rows]
self.r_y = self.r_xy[self.r_n_rows:]
self.solution_array = solution
self.r_x = self.solution_array[:self.r_n_rows]
self.r_y = self.solution_array[self.r_n_rows:]
if self.x is None:
self.x = np.zeros(self.n_rows)
if self.y is None:
Expand Down Expand Up @@ -3686,3 +3703,9 @@ def clean_edges(self):
self.rows_deg = None
self.cols_deg = None
self.is_initialized = False


def model_loglikelihood(self):
"""Returns the loglikelihood of the solution of last model executed.
"""
return self.step_fun(self.solution_array)
153 changes: 153 additions & 0 deletions tests/test_model_loglikelihood.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import sys

sys.path.append("../")
import NEMtropy.graph_classes as sample
import numpy as np
import unittest # test tool
import NEMtropy.matrix_generator as mg
import NEMtropy.models_functions as mof


class MyTest(unittest.TestCase):
def setUp(self):
pass

def test_dcm(self):
"""test with 3 classes of cardinality 1
and no zero degrees
"""
A = np.array(
[
[0, 1, 1],
[1, 0, 0],
[0, 1, 0],
]
)

g = sample.DirectedGraph(A)

g.solve_tool(
model="dcm",
max_steps=200,
verbose=False,
)
l = -mof.loglikelihood_dcm(g.solution_array, g.args)

# g._solution_error()
# debug
# print(g.r_dseq_out)
# print(g.r_dseq_in)
# print(g.rnz_dseq_out)
# print(g.rnz_dseq_in)
# print('\ntest 0: error = {}'.format(g.error))

# test result
self.assertTrue(l == g.model_loglikelihood())

def test_dcm_new(self):
"""test with 3 classes of cardinality 1
and no zero degrees
"""
A = np.array(
[
[0, 1, 1],
[1, 0, 0],
[0, 1, 0],
]
)

g = sample.DirectedGraph(A)

g.solve_tool(
model="dcm_exp",
method="quasinewton",
initial_guess="uniform",
max_steps=200,
verbose=False,
)
l = -mof.loglikelihood_dcm_exp(g.solution_array, g.args)

# g._solution_error()
# debug
# print(g.r_dseq_out)
# print(g.r_dseq_in)
# print(g.rnz_dseq_out)
# print(g.rnz_dseq_in)
# print('\ntest 0: error = {}'.format(g.error))
# print(l)
# print(g.model_loglikelihood())

# test result
self.assertTrue(l == g.model_loglikelihood())

@unittest.skip("")
def test_decm(self):
"""test with 3 classes of cardinality 1
and no zero degrees
"""

n, s = (4, 25)

A = mg.random_weighted_matrix_generator_dense(
n, sup_ext=10, sym=False, seed=s, intweights=True
)

g = sample.DirectedGraph(A)

g.solve_tool(
model="decm",
method="quasinewton",
initial_guess="uniform",
max_steps=200,
verbose=False,
)

l = -mof.loglikelihood_decm(g.solution_array, g.args)

# g._solution_error()
# debug
# print(g.r_dseq_out)
# print(g.r_dseq_in)
# print(g.rnz_dseq_out)
# print(g.rnz_dseq_in)
# print('\ntest 0: error = {}'.format(g.error))

# test result
self.assertTrue(l == g.model_loglikelihood())

def test_decm_new(self):
"""test with 3 classes of cardinality 1
and no zero degrees
"""

n, s = (10, 25)

A = mg.random_weighted_matrix_generator_dense(
n, sup_ext=10, sym=False, seed=s, intweights=True
)

g = sample.DirectedGraph(A)

g.solve_tool(
model="decm_exp",
method="quasinewton",
initial_guess="uniform",
max_steps=200,
verbose=False,
)
l = -mof.loglikelihood_decm_exp(g.solution_array, g.args)

# g._solution_error()
# debug
# print(g.r_dseq_out)
# print(g.r_dseq_in)
# print(g.rnz_dseq_out)
# print(g.rnz_dseq_in)
# print('\ntest 0: error = {}'.format(g.error))

# test result
self.assertTrue(l == g.model_loglikelihood())


if __name__ == "__main__":
unittest.main()

0 comments on commit a1bb7a6

Please sign in to comment.