class_docstr: Gaussian HJM model for term-structure modeling.
  
  Heath-Jarrow-Morton (HJM) model for the interest rate term-structre
  modelling specifies the dynamics of the instantaneus forward rate `f(t,T)`
  with maturity `T` at time `t` as follows:
  
  ```None
    df(t,T) = mu(t,T) dt + sum_i sigma_i(t,  T) * dW_i(t),
    1 <= i <= n,
  ```
  where `mu(t,T)` and `sigma_i(t,T)` denote the drift and volatility
  for the forward rate and `W_i` are Brownian motions with instantaneous
  correlation `Rho`. The model above represents an `n-factor` HJM model.
  The Gaussian HJM model assumes that the volatility `sigma_i(t,T)` is a
  deterministic function of time (t). Under the risk-neutral measure, the
  drift `mu(t,T)` is computed as
  
  ```
    mu(t,T) = sum_i sigma_i(t,T)  int_t^T sigma_(t,u) du
  ```
  Using the separability condition, the HJM model above can be formulated as
  the following Markovian model:
  
  ```None
    sigma(t,T) = sigma(t) * h(T)    (Separability condition)
  ```
  A common choice for the function h(t) is `h(t) = exp(-kt)`. Using the above
  parameterization of sigma(t,T), we obtain the following Markovian
  formulation of the HJM model [1]:
  
  ```None
    HJM Model
    dx_i(t) = (sum_j [y_ij(t)] - k_i * x_i(t)) dt + sigma_i(t) dW_i
    dy_ij(t) = (rho_ij * sigma_i(t)*sigma_j(t) - (k_i + k_j) * y_ij(t)) dt
    r(t) = sum_i x_i(t) + f(0, t)
  ```
  where `x` is an `n`-dimensional vector and `y` is an `nxn` dimensional
  matrix. For Gaussian HJM model, the quantity `y_ij(t)` can be computed
  analytically as follows:
  
  ```None
    y_ij(t) = rho_ij * exp(-k_i * t) * exp(-k_j * t) *
              int_0^t exp((k_i+k_j) * s) * sigma_i(s) * sigma_j(s) ds
  ```
  
  The Gaussian HJM class implements the model outlined above by simulating the
  state `x(t)` while analytically computing `y(t)`.
  
  The price at time `t` of a zero-coupon bond maturing at `T` is given by
  (Ref. [1]):
  
  ```None
  P(t,T) = P(0,T) / P(0,t) *
           exp(-x(t) * G(t,T) - 0.5 * y(t) * G(t,T)^2)
  ```
  
  The HJM model implementation supports constant mean-reversion rate `k` and
  `sigma(t)` can be an arbitrary function of `t`. We use Euler discretization
  to simulate the HJM model.
  
  #### Example. Simulate a 4-factor HJM process.
  
  ```python
  import numpy as np
  import tensorflow.compat.v2 as tf
  import tf_quant_finance as tff
  
  dtype = tf.float64
  def discount_fn(x):
    return 0.01 * tf.ones_like(x, dtype=dtype)
  
  process = tff.models.hjm.GaussianHJM(
      dim=4,
      mean_reversion=[0.03, 0.01, 0.02, 0.005],  # constant mean-reversion
      volatility=[0.01, 0.011, 0.015, 0.008],  # constant volatility
      initial_discount_rate_fn=discount_fn,
      dtype=dtype)
  times = np.array([0.1, 1.0, 2.0, 3.0])
  short_rate_paths, discount_paths, _, _ = process.sample_paths(
      times,
      num_samples=100000,
      time_step=0.1,
      random_type=tff.math.random.RandomType.STATELESS_ANTITHETIC,
      seed=[1, 2],
      skip=1000000)
  ```
  
  #### References:
    [1]: Leif B. G. Andersen and Vladimir V. Piterbarg. Interest Rate Modeling.
    Volume II: Term Structure Models.
class_docstr_tok: ["Gaussian","HJM","model","for","term-structure","modeling",".","Heath-Jarrow-Morton","(","HJM",")","model","for","the","interest","rate","term-structre","modelling","specifies","the","dynamics","of","the","instantaneus","forward","rate","`","f","(","t",",","T",")","`","with","maturity","`","T","`","at","time","`","t","`","as","follows",":","``","`","None","df","(","t",",","T",")","=","mu","(","t",",","T",")","dt","+","sum_i","sigma_i","(","t",",","T",")","*","dW_i","(","t",")",",","1","<","=","i","<","=","n",",","``","`","where","`","mu","(","t",",","T",")","`","and","`","sigma_i","(","t",",","T",")","`","denote","the","drift","and","volatility","for","the","forward","rate","and","`","W_i","`","are","Brownian","motions","with","instantaneous","correlation","`","Rho","`",".","The","model","above","represents","an","`","n-factor","`","HJM","model",".","The","Gaussian","HJM","model","assumes","that","the","volatility","`","sigma_i","(","t",",","T",")","`","is","a","deterministic","function","of","time","(","t",")",".","Under","the","risk-neutral","measure",",","the","drift","`","mu","(","t",",","T",")","`","is","computed","as","``","`","mu","(","t",",","T",")","=","sum_i","sigma_i","(","t",",","T",")","int_t^T","sigma_","(","t",",","u",")","du","``","`","Using","the","separability","condition",",","the","HJM","model","above","can","be","formulated","as","the","following","Markovian","model",":","``","`","None","sigma","(","t",",","T",")","=","sigma","(","t",")","*","h","(","T",")","(","Separability","condition",")","``","`","A","common","choice","for","the","function","h","(","t",")","is","`","h","(","t",")","=","exp","(","-kt",")","`",".","Using","the","above","parameterization","of","sigma","(","t",",","T",")",",","we","obtain","the","following","Markovian","formulation","of","the","HJM","model","[","1","]",":","``","`","None","HJM","Model","dx_i","(","t",")","=","(","sum_j","[","y_ij","(","t",")","]","-","k_i","*","x_i","(","t",")",")","dt","+","sigma_i","(","t",")","dW_i","dy_ij","(","t",")","=","(","rho_ij","*","sigma_i","(","t",")","*","sigma_j","(","t",")","-","(","k_i","+","k_j",")","*","y_ij","(","t",")",")","dt","r","(","t",")","=","sum_i","x_i","(","t",")","+","f","(","0",",","t",")","``","`","where","`","x","`","is","an","`","n","`","-dimensional","vector","and","`","y","`","is","an","`","nxn","`","dimensional","matrix",".","For","Gaussian","HJM","model",",","the","quantity","`","y_ij","(","t",")","`","can","be","computed","analytically","as","follows",":","``","`","None","y_ij","(","t",")","=","rho_ij","*","exp","(","-k_i","*","t",")","*","exp","(","-k_j","*","t",")","*","int_0^t","exp","(","(","k_i+k_j",")","*","s",")","*","sigma_i","(","s",")","*","sigma_j","(","s",")","ds","``","`","The","Gaussian","HJM","class","implements","the","model","outlined","above","by","simulating","the","state","`","x","(","t",")","`","while","analytically","computing","`","y","(","t",")","`",".","The","price","at","time","`","t","`","of","a","zero-coupon","bond","maturing","at","`","T","`","is","given","by","(","Ref",".","[","1","]",")",":","``","`","None","P","(","t",",","T",")","=","P","(","0",",","T",")","\/","P","(","0",",","t",")","*","exp","(","-x","(","t",")","*","G","(","t",",","T",")","-","0.5","*","y","(","t",")","*","G","(","t",",","T",")","^2",")","``","`","The","HJM","model","implementation","supports","constant","mean-reversion","rate","`","k","`","and","`","sigma","(","t",")","`","can","be","an","arbitrary","function","of","`","t","`",".","We","use","Euler","discretization","to","simulate","the","HJM","model",".","#","#","#","#","Example",".","Simulate","a","4-factor","HJM","process",".","``","`","python","import","numpy","as","np","import","tensorflow.compat.v2","as","tf","import","tf_quant_finance","as","tff","dtype","=","tf.float64","def","discount_fn","(","x",")",":","return","0.01","*","tf.ones_like","(","x",",","dtype=dtype",")","process","=","tff.models.hjm.GaussianHJM","(","dim=4",",","mean_reversion=","[","0.03",",","0.01",",","0.02",",","0.005","]",",","#","constant","mean-reversion","volatility=","[","0.01",",","0.011",",","0.015",",","0.008","]",",","#","constant","volatility","initial_discount_rate_fn=discount_fn",",","dtype=dtype",")","times","=","np.array","(","[","0.1",",","1.0",",","2.0",",","3.0","]",")","short_rate_paths",",","discount_paths",",","_",",","_","=","process.sample_paths","(","times",",","num_samples=100000",",","time_step=0.1",",","random_type=tff.math.random.RandomType.STATELESS_ANTITHETIC",",","seed=","[","1",",","2","]",",","skip=1000000",")","``","`","#","#","#","#","References",":","[","1","]",":","Leif","B.","G.","Andersen","and","Vladimir","V.","Piterbarg",".","Interest","Rate","Modeling",".","Volume","II",":","Term","Structure","Models","."]
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,
      time_step,
      num_time_steps,
      num_samples,
      random_type,
      skip,
      seed,
  ):
      """Returns a sample of paths from the process."""
      initial_state = tf.zeros((self._dim,), dtype=self._dtype)
      # Note that we need a finer simulation grid (determnied by `dt`) to compute
      # discount factors accurately. The `times` input might not be granular
      # enough for accurate calculations.
      time_step_internal = time_step
      if num_time_steps is not None:
          num_time_steps = tf.convert_to_tensor(
              num_time_steps, dtype=tf.int32, name="num_time_steps"
          )
          time_step_internal = times[-1] / tf.cast(
              num_time_steps, dtype=self._dtype
          )
  
      times, _, time_indices = utils.prepare_grid(
          times=times,
          time_step=time_step_internal,
          dtype=self._dtype,
          num_time_steps=num_time_steps,
      )
      # Add zeros as a starting location
      dt = times[1:] - times[:-1]
  
      # Shape = (num_samples, num_times, nfactors)
      paths = euler_sampling.sample(
          self._dim,
          self._drift_fn,
          self._volatility_fn,
          times,
          num_time_steps=num_time_steps,
          num_samples=num_samples,
          initial_state=initial_state,
          random_type=random_type,
          seed=seed,
          time_step=time_step,
          skip=skip,
      )
      y_paths = self.state_y(times)  # shape=(dim, dim, num_times)
      y_paths = tf.reshape(
          y_paths,
          tf.concat([[self._dim**2], tf.shape(times)], axis=0),
      )
  
      # shape=(num_samples, num_times, dim**2)
      y_paths = tf.repeat(
          tf.expand_dims(tf.transpose(y_paths), axis=0),
          num_samples,
          axis=0,
      )
  
      f_0_t = self._instant_forward_rate_fn(times)  # shape=(num_times,)
      rate_paths = (
          tf.math.reduce_sum(paths, axis=-1) + f_0_t
      )  # shape=(num_samples, num_times)
  
      discount_factor_paths = tf.math.exp(-rate_paths[:, :-1] * dt)
      discount_factor_paths = tf.concat(
          [
              tf.ones((num_samples, 1), dtype=self._dtype),
              discount_factor_paths,
          ],
          axis=1,
      )  # shape=(num_samples, num_times)
      discount_factor_paths = utils.cumprod_using_matvec(
          discount_factor_paths
      )
      return (
          tf.gather(rate_paths, time_indices, axis=1),
          tf.gather(discount_factor_paths, time_indices, axis=1),
          tf.gather(paths, time_indices, axis=1),
          tf.gather(y_paths, time_indices, axis=1),
      )
  
file_path: tf-quant-finance/tf_quant_finance/models/hjm/gaussian_hjm.py
imports: from typing import Callable, Union
  import tensorflow.compat.v2
  from tf_quant_finance import types
  from tf_quant_finance.math import gradient
  from tf_quant_finance.math import piecewise
  from tf_quant_finance.math import random
  from tf_quant_finance.models import euler_sampling
  from tf_quant_finance.models import utils
  from tf_quant_finance.models.hjm import quasi_gaussian_hjm
label_desc: Use image node_id 5 for calling the GaussianHJM obj's underlying member method code with example usage: obj._sample_paths(times, time_step, num_time_steps, num_samples, random_type, skip, seed) and returns: tf,  tf,  tf,  tf