def copy(self):
        """
        Returns a copy of the factor.

        Returns
        -------
        DiscreteFactor: copy of the factor

        Examples
        --------
        >>> import numpy as np
        >>> from pgmpy.factors.discrete import DiscreteFactor
        >>> phi = DiscreteFactor(['x1', 'x2', 'x3'], [2, 3, 3], np.arange(18))
        >>> phi_copy = phi.copy()
        >>> phi_copy.variables
        ['x1', 'x2', 'x3']
        >>> phi_copy.cardinality
        array([2, 3, 3])
        >>> phi_copy.values
        array([[[ 0,  1,  2],
                [ 3,  4,  5],
                [ 6,  7,  8]],

               [[ 9, 10, 11],
                [12, 13, 14],
                [15, 16, 17]]])
        """
        # not creating a new copy of self.values and self.cardinality
        # because __init__ methods does that.
        return DiscreteFactor(self.scope(), self.cardinality, self.values, state_names=self.state_names)