class_docstr: Multivariate Geometric Brownian Motion.
  
  Represents a d-dimensional Ito process:
  
  ```None
    dX_i(t) = means_i * X_i(t) * dt + volatilities_i * X_i(t) * dW_i(t),
    1 <= i <= d
  ```
  
  where `W(t) = (W_1(t), .., W_d(t))` is a d-dimensional Brownian motion with
  a correlation matrix `corr_matrix`, `means` and `volatilities` are `Tensor`s
  that correspond to mean and volatility of a Geometric Brownian Motion `X_i`
  
  ## Example
  
  ```python
  import tensorflow as tf
  import tf_quant_finance as tff
  corr_matrix = [[1, 0.1], [0.1, 1]]
  process = tff.models.MultivariateGeometricBrownianMotion(
      dim=2,
      means=1, volatilities=[0.1, 0.2],
      corr_matrix=corr_matrix,
      dtype=tf.float64)
  times = [0.1, 0.2, 1.0]
  initial_state=[1.0, 2.0]
  # Use SOBOL sequence to draw trajectories
  samples_sobol = process.sample_paths(
      times=times,
      initial_state=initial_state,
      random_type=tff.math.random.RandomType.SOBOL,
      num_samples=100000)
  
  # You can also supply the random normal draws directly to the sampler
  normal_draws = tf.random.stateless_normal(
      [100000, 3, 2], seed=[4, 2], dtype=tf.float64)
  samples_custom = process.sample_paths(
      times=times,
      initial_state=initial_state,
      normal_draws=normal_draws)
  ```
class_docstr_tok: ["Multivariate","Geometric","Brownian","Motion",".","Represents","a","d-dimensional","Ito","process",":","``","`","None","dX_i","(","t",")","=","means_i","*","X_i","(","t",")","*","dt","+","volatilities_i","*","X_i","(","t",")","*","dW_i","(","t",")",",","1","<","=","i","<","=","d","``","`","where","`","W","(","t",")","=","(","W_1","(","t",")",",","..",",","W_d","(","t",")",")","`","is","a","d-dimensional","Brownian","motion","with","a","correlation","matrix","`","corr_matrix","`",",","`","means","`","and","`","volatilities","`","are","`","Tensor","`","s","that","correspond","to","mean","and","volatility","of","a","Geometric","Brownian","Motion","`","X_i","`","#","#","Example","``","`","python","import","tensorflow","as","tf","import","tf_quant_finance","as","tff","corr_matrix","=","[","[","1",",","0.1","]",",","[","0.1",",","1","]","]","process","=","tff.models.MultivariateGeometricBrownianMotion","(","dim=2",",","means=1",",","volatilities=","[","0.1",",","0.2","]",",","corr_matrix=corr_matrix",",","dtype=tf.float64",")","times","=","[","0.1",",","0.2",",","1.0","]","initial_state=","[","1.0",",","2.0","]","#","Use","SOBOL","sequence","to","draw","trajectories","samples_sobol","=","process.sample_paths","(","times=times",",","initial_state=initial_state",",","random_type=tff.math.random.RandomType.SOBOL",",","num_samples=100000",")","#","You","can","also","supply","the","random","normal","draws","directly","to","the","sampler","normal_draws","=","tf.random.stateless_normal","(","[","100000",",","3",",","2","]",",","seed=","[","4",",","2","]",",","dtype=tf.float64",")","samples_custom","=","process.sample_paths","(","times=times",",","initial_state=initial_state",",","normal_draws=normal_draws",")","``","`"]
docstr: Returns a sample of paths from the process.
docstr_tok: ["Returns","a","sample","of","paths","from","the","process","."]
code: def _sample_paths(
      self,
      times,
      num_requested_times,
      initial_state,
      num_samples,
      random_type,
      seed,
      skip,
      normal_draws,
  ):
      """Returns a sample of paths from the process."""
      if normal_draws is None:
          # Normal draws needed for sampling.
          # Shape [num_requested_times, num_samples, dim]
          normal_draws = utils.generate_mc_normal_draws(
              num_normal_draws=self._dim,
              num_time_steps=num_requested_times,
              num_sample_paths=num_samples,
              random_type=random_type,
              seed=seed,
              dtype=self._dtype,
              skip=skip,
          )
      else:
          # Shape [num_time_points, num_samples, dim]
          normal_draws = tf.transpose(normal_draws, [1, 0, 2])
          num_samples = tff_utils.get_shape(normal_draws)[1]
          draws_dim = tff_utils.get_shape(normal_draws)[2]
          if self._dim != draws_dim:
              raise ValueError(
                  "`dim` should be equal to `normal_draws.shape[2]` but are "
                  "{0} and {1} respectively".format(
                      self._dim, draws_dim
                  )
              )
      times = tf.concat([[0], times], -1)
      # Time increments
      # Shape [num_requested_times, 1, 1]
      dt = tf.expand_dims(
          tf.expand_dims(times[1:] - times[:-1], axis=-1), axis=-1
      )
      if self._corr_matrix is None:
          stochastic_increment = normal_draws
      else:
          cholesky = tf.linalg.cholesky(self._corr_matrix)
          stochastic_increment = tf.linalg.matvec(
              cholesky, normal_draws
          )
  
      # The logarithm of all the increments between the times.
      # Shape [num_requested_times, num_samples, dim]
      log_increments = (
          self._means - self._vols**2 / 2
      ) * dt + tf.sqrt(dt) * self._vols * stochastic_increment
  
      # Since the implementation of tf.math.cumsum is single-threaded we
      # use lower-triangular matrix multiplication instead
      once = tf.ones(
          [num_requested_times, num_requested_times], dtype=self._dtype
      )
      lower_triangular = tf.linalg.band_part(once, -1, 0)
      cumsum = tf.linalg.matvec(
          lower_triangular, tf.transpose(log_increments)
      )
      cumsum = tf.transpose(cumsum, [1, 2, 0])
      samples = initial_state * tf.math.exp(cumsum)
      return samples
  
file_path: tf-quant-finance/tf_quant_finance/models/geometric_brownian_motion/multivariate_geometric_brownian_motion.py
imports: import tensorflow.compat.v2
  from tf_quant_finance import utils
  from tf_quant_finance.math.pde import fd_solvers
  from tf_quant_finance.models import ito_process
  from tf_quant_finance.models import utils
label_desc: Use image node_id 8 for calling the MultivariateGeometricBrownianMotion obj's underlying member method code with example usage: obj._sample_paths(times, num_requested_times, initial_state, num_samples, random_type, seed, skip, normal_draws) and returns: samples