--- /dev/null
+"""
+The doubly-nonnegative cone in `S^{n}` is the set of all such matrices
+that both,
+
+ a) are positive semidefinite
+
+ b) have only nonnegative entries
+
+It is represented typically by either `\mathcal{D}^{n}` or
+`\mathcal{DNN}`.
+
+"""
+
+from sage.all import *
+
+# Sage doesn't load ~/.sage/init.sage during testing (sage -t), so we
+# have to explicitly mangle our sitedir here so that "mjo.cone"
+# resolves.
+from os.path import abspath
+from site import addsitedir
+addsitedir(abspath('../../'))
+from mjo.cone.symmetric_psd import factor_psd
+
+
+
+def is_doubly_nonnegative(A):
+ """
+ Determine whether or not the matrix ``A`` is doubly-nonnegative.
+
+ INPUT:
+
+ - ``A`` - The matrix in question
+
+ OUTPUT:
+
+ Either ``True`` if ``A`` is doubly-nonnegative, or ``False``
+ otherwise.
+
+ EXAMPLES:
+
+ Every completely positive matrix is doubly-nonnegative::
+
+ sage: v = vector(map(abs, random_vector(ZZ, 10)))
+ sage: A = v.column() * v.row()
+ sage: is_doubly_nonnegative(A)
+ True
+
+ The following matrix is nonnegative but non positive semidefinite::
+
+ sage: A = matrix(ZZ, [[1, 2], [2, 1]])
+ sage: is_doubly_nonnegative(A)
+ False
+
+ """
+
+ if A.base_ring() == SR:
+ msg = 'The base ring of ``A`` cannot be the Symbolic Ring'
+ raise ValueError.new(msg)
+
+ # First make sure that ``A`` is symmetric.
+ if not A.is_symmetric():
+ return False
+
+ # Check that all of the entries of ``A`` are nonnegative.
+ if not all([ a >= 0 for a in A.list() ]):
+ return False
+
+ # If ``A`` is symmetric and non-negative, we only need to check
+ # that it is positive semidefinite. For that we can consult its
+ # minimum eigenvalue, which should be zero or greater. Since ``A``
+ # is symmetric, its eigenvalues are guaranteed to be real.
+ return min(A.eigenvalues()) >= 0
+
+
+
+def is_extreme_doubly_nonnegative(A):
+ """
+ Returns ``True`` if the given matrix is an extreme matrix of the
+ doubly-nonnegative cone, and ``False`` otherwise.
+ """
+ raise NotImplementedError()