Method returns a generator type object whose each iteration yields a sample
        using Hamiltonian Monte Carlo

        Parameters
        ----------
        initial_pos: A 1d array like object
            Vector representing values of parameter position, the starting
            state in markov chain.

        num_samples: int
            Number of samples to be generated

        trajectory_length: int or float
            Target trajectory length, stepsize * number of steps(L),
            where L is the number of steps taken per HMC iteration,
            and stepsize is step size for splitting time method.

        stepsize: float , defaults to None
            The stepsize for proposing new values of position and momentum in simulate_dynamics
            If None, then will be choosen suitably

        Returns
        -------
        genrator: yielding a 1d numpy.array type object for a sample

        Examples
        --------
        >>> from pgmpy.sampling import HamiltonianMC as HMC, GradLogPDFGaussian as GLPG
        >>> from pgmpy.factors import GaussianDistribution as JGD
        >>> import numpy as np
        >>> mean = np.array([4, -1])
        >>> covariance = np.array([[3, 0.4], [0.4, 3]])
        >>> model = JGD(['x', 'y'], mean, covariance)
        >>> sampler = HMC(model=model, grad_log_pdf=GLPG)
        >>> gen_samples = sampler.generate_sample(np.array([-1, 1]), num_samples = 10000,
        ...                                       trajectory_length=2, stepsize=0.25)
        >>> samples_array = np.array([sample for sample in gen_samples])
        >>> samples_array
        array([[ 0.1467264 ,  0.27143857],
               [ 4.0371448 ,  0.15871274],
               [ 3.24656208, -1.03742621],
               ...,
               [ 6.45975905,  1.97941306],
               [ 4.89007171,  0.15413156],
               [ 5.9528083 ,  1.92983158]])
        >>> np.cov(samples_array.T)
        array([[ 2.95692642,  0.4379419 ],
               [ 0.4379419 ,  3.00939434]])
        >>> sampler.acceptance_rate
        0.9969

def generate_sample(self, initial_pos, num_samples, trajectory_length, stepsize=None):
        """
        Method returns a generator type object whose each iteration yields a sample
        using Hamiltonian Monte Carlo

        Parameters
        ----------
        initial_pos: A 1d array like object
            Vector representing values of parameter position, the starting
            state in markov chain.

        num_samples: int
            Number of samples to be generated

        trajectory_length: int or float
            Target trajectory length, stepsize * number of steps(L),
            where L is the number of steps taken per HMC iteration,
            and stepsize is step size for splitting time method.

        stepsize: float , defaults to None
            The stepsize for proposing new values of position and momentum in simulate_dynamics
            If None, then will be choosen suitably

        Returns
        -------
        genrator: yielding a 1d numpy.array type object for a sample

        Examples
        --------
        >>> from pgmpy.sampling import HamiltonianMC as HMC, GradLogPDFGaussian as GLPG
        >>> from pgmpy.factors import GaussianDistribution as JGD
        >>> import numpy as np
        >>> mean = np.array([4, -1])
        >>> covariance = np.array([[3, 0.4], [0.4, 3]])
        >>> model = JGD(['x', 'y'], mean, covariance)
        >>> sampler = HMC(model=model, grad_log_pdf=GLPG)
        >>> gen_samples = sampler.generate_sample(np.array([-1, 1]), num_samples = 10000,
        ...                                       trajectory_length=2, stepsize=0.25)
        >>> samples_array = np.array([sample for sample in gen_samples])
        >>> samples_array
        array([[ 0.1467264 ,  0.27143857],
               [ 4.0371448 ,  0.15871274],
               [ 3.24656208, -1.03742621],
               ...,
               [ 6.45975905,  1.97941306],
               [ 4.89007171,  0.15413156],
               [ 5.9528083 ,  1.92983158]])
        >>> np.cov(samples_array.T)
        array([[ 2.95692642,  0.4379419 ],
               [ 0.4379419 ,  3.00939434]])
        >>> sampler.acceptance_rate
        0.9969
        """

        self.accepted_proposals = 0
        initial_pos = _check_1d_array_object(initial_pos, 'initial_pos')
        _check_length_equal(initial_pos, self.model.variables, 'initial_pos', 'model.variables')

        if stepsize is None:
            stepsize = self._find_reasonable_stepsize(initial_pos)

        lsteps = int(max(1, round(trajectory_length / stepsize, 0)))
        position_m = initial_pos.copy()

        for i in range(0, num_samples):

            position_m, _ = self._sample(position_m, trajectory_length, stepsize, lsteps)

            yield position_m

        self.acceptance_rate = self.accepted_proposals / num_samples