Repository: statsmodels/statsmodels

Issue:
slogdet positive-definite check is wrong
See https://github.com/scipy/scipy/pull/4135



Discussion:

Resolving patch:
diff --git a/statsmodels/tools/linalg.py b/statsmodels/tools/linalg.py
--- a/statsmodels/tools/linalg.py
+++ b/statsmodels/tools/linalg.py
@@ -192,12 +192,34 @@ def pinv2(a, cond=None, rcond=None):
     return transpose(conjugate(dot(dot(u,psigma),vh)))
 
 
+def logdet_symm(m, check_symm=False):
+    """
+    Return log(det(m)) asserting positive definiteness of m.
+
+    Parameters
+    ----------
+    m : array-like
+        2d array that is positive-definite (and symmetric)
+
+    Returns
+    -------
+    logdet : float
+        The log-determinant of m.
+    """
+    from scipy import linalg
+    if check_symm:
+        if not np.all(m == m.T):  # would be nice to short-circuit check
+            raise ValueError("m is not symmetric.")
+    c, _ = linalg.cho_factor(m, lower=True)
+    return 2*np.sum(np.log(c.diagonal()))
+
+
 if __name__ == '__main__':
     #for checking only,
     #Note on Windows32:
     #    linalg doesn't always produce the same results in each call
     a0 = np.random.randn(100,10)
-    b0 = a0.sum(1)[:,None] + np.random.randn(100,3)
+    b0 = a0.sum(1)[:, None] + np.random.randn(100,3)
     lstsq(a0,b0)
     pinv(a0)
     pinv2(a0)
diff --git a/statsmodels/tsa/vector_ar/util.py b/statsmodels/tsa/vector_ar/util.py
--- a/statsmodels/tsa/vector_ar/util.py
+++ b/statsmodels/tsa/vector_ar/util.py
@@ -159,18 +159,18 @@ def parse_lutkepohl_data(path): # pragma: no cover
 
     return data, date_range
 
+
 def get_logdet(m):
-    from numpy.linalg import slogdet
-    logdet = slogdet(m)
+    from statsmodels.tools.linalg import logdet_symm
+    return logdet_symm(m)
+
 
-    if logdet[0] == -1: # pragma: no cover
-        raise ValueError("Matrix is not positive definite")
-    elif logdet[0] == 0: # pragma: no cover
-        raise ValueError("Matrix is singular")
-    else:
-        logdet = logdet[1]
+get_logdet = np.deprecate(get_logdet,
+                          "statsmodels.tsa.vector_ar.util.get_logdet",
+                          "statsmodels.tools.linalg.logdet_symm",
+                          "get_logdet is deprecated and will be removed in "
+                          "0.8.0")
 
-    return logdet
 
 def norm_signif_level(alpha=0.05):
     return stats.norm.ppf(1 - alpha / 2)
diff --git a/statsmodels/tsa/vector_ar/var_model.py b/statsmodels/tsa/vector_ar/var_model.py
--- a/statsmodels/tsa/vector_ar/var_model.py
+++ b/statsmodels/tsa/vector_ar/var_model.py
@@ -20,6 +20,7 @@
 
 from statsmodels.tools.decorators import cache_readonly
 from statsmodels.tools.tools import chain_dot
+from statsmodels.tools.linalg import logdet_symm
 from statsmodels.tsa.tsatools import vec, unvec
 
 from statsmodels.tsa.vector_ar.irf import IRAnalysis
@@ -263,7 +264,7 @@ def var_loglike(resid, omega, nobs):
         -\left(\frac{T}{2}\right)
         \left(\ln\left|\Omega\right|-K\ln\left(2\pi\right)-K\right)
     """
-    logdet = util.get_logdet(np.asarray(omega))
+    logdet = logdet_symm(np.asarray(omega))
     neqs = len(omega)
     part1 = - (nobs * neqs / 2) * np.log(2 * np.pi)
     part2 = - (nobs / 2) * (logdet + neqs)
@@ -1464,7 +1465,7 @@ def info_criteria(self):
         lag_order = self.k_ar
         free_params = lag_order * neqs ** 2 + neqs * self.k_trend
 
-        ld = util.get_logdet(self.sigma_u_mle)
+        ld = logdet_symm(self.sigma_u_mle)
 
         # See Lutkepohl pp. 146-150
 


Test patch: