docs: def forward_sample(self, size=1, return_type='dataframe'):
          """
          Generates sample(s) from joint distribution of the bayesian network.
  
          Parameters
          ----------
          size: int
              size of sample to be generated
  
          return_type: string (dataframe | recarray)
              Return type for samples, either of 'dataframe' or 'recarray'.
              Defaults to 'dataframe'
  
          Returns
          -------
          sampled: A pandas.DataFrame or a numpy.recarray object depending upon return_type argument
              the generated samples
  
  
          Examples
          --------
          >>> from pgmpy.models.BayesianModel import BayesianModel
          >>> from pgmpy.factors.discrete import TabularCPD
          >>> from pgmpy.sampling import BayesianModelSampling
          >>> student = BayesianModel([('diff', 'grade'), ('intel', 'grade')])
          >>> cpd_d = TabularCPD('diff', 2, [[0.6], [0.4]])
          >>> cpd_i = TabularCPD('intel', 2, [[0.7], [0.3]])
          >>> cpd_g = TabularCPD('grade', 3, [[0.3, 0.05, 0.9, 0.5], [0.4, 0.25,
          ...                0.08, 0.3], [0.3, 0.7, 0.02, 0.2]],
          ...                ['intel', 'diff'], [2, 2])
          >>> student.add_cpds(cpd_d, cpd_i, cpd_g)
          >>> inference = BayesianModelSampling(student)
          >>> inference.forward_sample(size=2, return_type='recarray')
          rec.array([(0, 0, 1), (1, 0, 2)], dtype=
                    [('diff', '<i8'), ('intel', '<i8'), ('grade', '<i8')])
          """
          types = [(var_name, 'int') for var_name in self.topological_order]
          sampled = np.zeros(size, dtype=types).view(np.recarray)
  
          for node in self.topological_order:
              cpd = self.model.get_cpds(node)
              states = range(self.cardinality[node])
              evidence = cpd.variables[:0:-1]
              if evidence:
                  cached_values = self.pre_compute_reduce(variable=node)
                  evidence = np.vstack([sampled[i] for i in evidence])
                  weights = list(map(lambda t: cached_values[tuple(t)], evidence.T))
              else:
                  weights = cpd.values
              sampled[node] = sample_discrete(states, weights, size)
  
          return _return_samples(return_type, sampled)