docs: 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)