diff --git a/cdfm/models/differentials.py b/cdfm/models/differentials.py index 6a2ed96..81c5348 100644 --- a/cdfm/models/differentials.py +++ b/cdfm/models/differentials.py @@ -3,6 +3,7 @@ """ from typing import List import numpy as np +from ..config import DTYPE def Iec_ve(cinds: List[int], Vc: np.ndarray) -> np.ndarray: @@ -29,6 +30,55 @@ def Iec_vc(eind: int, Ve: np.ndarray) -> np.ndarray: """ return Ve[eind] +def p_Iec_u(eind: int, + cinds: int, + Ve: np.ndarray, + Vc: np.ndarray, + d: np.ndarray, + ps: np.ndarray) -> np.ndarray: + """Partially differentiate p_Iec with u. + + Parameters: + eind: an index of the target entity. + cinds: indices of competitors. + Ve: a matrix of latent vectors of entities. shape (p, k). + Vc: a matrix of latent vectors of competitors. shape (p, k). + d: a proximity factors. shape (|cinds|, #factors). + ps: a probabilities of interaction occurrence. + + Returns: + res: shape (#factors, ). + """ + partial_sigmoid = np.einsum('i,ij->ij', np.multiply(ps, (DTYPE(1.) - ps)), -d) + strengths = np.dot(Vc[cinds], Ve[eind]) + return np.einsum('ij,i->j', partial_sigmoid, strengths) + +def p_Iec_ve(cinds: List[int], Vc: np.ndarray, ps: np.ndarray) -> np.ndarray: + """Partially differentiate P_Iec with ve. + + Parameters: + cinds: indices of competitors. + Vc: a matrix of latent vectors of competitors. shape (p, k). + ps: a probabilities of interaction occurrence. + + Returns: + res: shape (k, ). + """ + return np.einsum('ij,i->j', Vc.take(cinds, axis=0), ps) + +def p_Iec_vc(eind: int, Ve: np.ndarray, p: DTYPE) -> np.ndarray: + """Partially differentiate P_Iec with ve. + + Parameters: + eind: an index of the target entity. + Ve: a matrix of latent vectors of entities. shape (p, k). + p: a probability of interaction occurrence. + + Returns: + res: shape (k, ). + """ + return np.multiply(p, Ve[eind]) + def Ief_ve(x: np.ndarray, Vf: np.ndarray) -> np.ndarray: """Partially differentiate Ief with ve. diff --git a/tests/models/test_differentials.py b/tests/models/test_differentials.py index 90835bf..00cca9b 100644 --- a/tests/models/test_differentials.py +++ b/tests/models/test_differentials.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- """Testing differential functions. + +Checking result, type, dtype, and shape. """ import numpy as np from cdfm.config import DTYPE @@ -38,15 +40,52 @@ def test_Iec_ve(self): cinds = [1, 2] res = Diff.Iec_ve(cinds, self.Vc) expected = np.array([11.0, 13.0, 15.0], dtype=DTYPE) - assert (res == expected).all() + assert np.allclose(res, expected) assert isinstance(res, np.ndarray) assert res.dtype == DTYPE + assert res.shape == (3, ) def test_Iec_vc(self): + """eind: 0 + """ eind = 0 res = Diff.Iec_vc(eind, self.Ve) expected = np.array([1.0, 2.0, 3.0], dtype=DTYPE) - assert (res == expected).all() + assert np.allclose(res, expected) + assert isinstance(res, np.ndarray) + assert res.dtype == DTYPE + assert res.shape == (3, ) + + def test_p_Iec_u(self): + eind = 0 + cinds = [1, 2] + d = np.array([[1, 4], [2, 3]], dtype=DTYPE) + ps = np.array([0.3, 0.7], dtype=DTYPE) + res = Diff.p_Iec_u(eind, cinds, self.Ve, self.Vc, d, ps) + expected = np.array([-27.72, -58.38], dtype=DTYPE) + assert np.allclose(res, expected) + assert isinstance(res, np.ndarray) + assert res.dtype == DTYPE + + def test_p_Iec_ve(self): + """eind: 0, cinds: 1, 2 + """ + cinds = [1, 2] + ps = np.array([0.3, 0.7], dtype=DTYPE) + res = Diff.p_Iec_ve(cinds, self.Vc, ps) + expected = np.array([6.1, 7.1, 8.1], dtype=DTYPE) + assert np.allclose(res, expected) + assert isinstance(res, np.ndarray) + assert res.dtype == DTYPE + + def test_p_Iec_vc(self): + """eind: 0, (cind: 1), p: 0.3 (between 0 and 1) + """ + eind = 0 + p = DTYPE(0.3) + res = Diff.p_Iec_vc(eind, self.Ve, p) + expected = np.array([0.3, 0.6, 0.9]) + assert np.allclose(res, expected) assert isinstance(res, np.ndarray) assert res.dtype == DTYPE @@ -54,7 +93,7 @@ def test_Ief_ve(self): x = np.ones(4, dtype=DTYPE) res = Diff.Ief_ve(x, self.Vf) expected = np.array([22, 26, 30], dtype=DTYPE) - assert (res == expected).all() + assert np.allclose(res, expected) assert isinstance(res, np.ndarray) assert res.dtype == DTYPE @@ -68,7 +107,7 @@ def test_Ief_vf(self): [1.0, 2.0, 3.0], [1.0, 2.0, 3.0] ], dtype=DTYPE) - assert (res == expected).all() + assert np.allclose(res, expected) assert isinstance(res, np.ndarray) assert res.dtype == DTYPE @@ -81,6 +120,6 @@ def test_Iff_vf(self): [-141.0, -156., -171.0], [-56.0, -64.0, -72.0], ], dtype=DTYPE) # culculated by hand - assert (res == expected).all() + assert np.allclose(res, expected) assert isinstance(res, np.ndarray) assert res.dtype == DTYPE