class_docstr: Ensemble of correlated Hull-White Models.
  
  Represents the Ito process:
  
  ```None
    dr_i(t) = (theta_i(t) - a_i(t) * r_i(t)) dt + sigma_i(t) * dW_{r_i}(t),
    1 <= i <= n,
  ```
  where `W_{r_i}` are 1D Brownian motions with a correlation matrix `Rho(t)`.
  For each `i`, `r_i` is the Hull-White process.
  `theta_i`, `a_i`, `sigma_i`, `Rho` are positive functions of time.
  `a_i` correspond to the mean-reversion rate, `sigma_i` is the volatility of
  the process, `theta_i(t)` is the function that determines long run behaviour
  of the process `r(t) = (r_1(t), ..., r_n(t))`
  and is computed to match the initial (at t=0) discount curve:
  
  ```None
  \theta_i = df_i(t) / dt + a_i * f_i(t) + 0.5 * sigma_i**2 / a_i
             * (1 - exp(-2 * a_i *t)), 1 <= i <= n
  ```
  where `f_i(t)` is the instantaneous forward rate at time `0` for a maturity
  `t` and `df_i(t)/dt` is the gradient of `f_i` with respect to the maturity.
  See Section 3.3.1 of [1] for details.
  
  The price at time `t` of a zero-coupon bond maturing at `T` is given by
  (Ref. [2]):
  
  ```None
  P(t,T) = P(0,T) / P(0,t) *
           exp(-(r(t) - f(0,t)) * G(t,T) - 0.5 * y(t) * G(t,T)^2)
  
  y(t) = int_0^t [exp(-2 int_u^t (a(s) ds)) sigma(u)^2 du]
  
  G(t,T) = int_t^T [exp(-int_t^u a(s) ds) du]
  ```
  
  If mean-reversion, `a_i`, is constant and the volatility (`sigma_i`), and
  correlation (`Rho`) are piecewise constant functions, the process is sampled
  exactly. Otherwise, Euler sampling is used.
  
  For `n=1` this class represents Hull-White Model (see
  tff.models.hull_white.HullWhiteModel1F).
  
  #### Example. Two correlated Hull-White processes.
  
  ```python
  import numpy as np
  import tensorflow as tf
  import tf_quant_finance as tff
  
  dtype = tf.float64
  # Mean-reversion is constant for the two processes. `mean_reversion(t)`
  # has shape `[dim] + t.shape`.
  mean_reversion = [0.03, 0.02]
  # Volatility is a piecewise constant function with jumps at the same locations
  # for both Hull-White processes. `volatility(t)` has shape `[dim] + t.shape`.
  volatility = tff.math.piecewise.PiecewiseConstantFunc(
      jump_locations=[[0.1, 2.], [0.1, 2.]],
      values=[[0.01, 0.02, 0.01], [0.01, 0.015, 0.01]],
      dtype=dtype)
  # Correlation matrix is constant
  corr_matrix = [[1., 0.1], [0.1, 1.]]
  initial_discount_rate_fn = lambda *args: [0.01, 0.015]
  process = tff.models.hull_white.VectorHullWhiteModel(
      dim=2, mean_reversion=mean_reversion,
      volatility=volatility,
      initial_discount_rate_fn=initial_discount_rate_fn,
      corr_matrix=corr_matrix,
      dtype=dtype)
  # Sample 10000 paths using Sobol numbers as a random type.
  times = np.linspace(0., 1.0, 10)
  num_samples = 10000  # number of trajectories
  paths = process.sample_paths(
      times,
      num_samples=num_samples,
      random_type=tff.math.random.RandomType.SOBOL,
      seed=[4, 2])
  # Compute mean for each Hull-White process at the terminal value
  tf.math.reduce_mean(paths[:, -1, :], axis=0)
  # Expected: [0.01070005, 0.01540942]
  
  # User can supply time discretization grid along with the underlying
  # normal draws directly to the sampler.
  times_grid = tf.sort(tf.concat([np.linspace(0., 1.0, 10), [0.1]], axis=-1))
  normal_draws = tf.random.stateless_normal(
      [num_samples // 2, 10, 2], seed=[4, 2], dtype=dtype)
  normal_draws = tf.concat([normal_draws, -normal_draws], axis=0)
  paths = process.sample_paths(
      times,
      num_samples=num_samples,
      times_grid = times_grid,
      normal_draws=normal_draws)
  # Compute mean for each Hull-White process at the terminal value
  tf.math.reduce_mean(paths[:, -1, :], axis=0)
  # Expected: [0.0101668 , 0.01509873]
  ```
  
  #### References:
    [1]: D. Brigo, F. Mercurio. Interest Rate Models. 2007.
    [2]: Leif B. G. Andersen and Vladimir V. Piterbarg. Interest Rate Modeling.
    Volume II: Term Structure Models.
class_docstr_tok: ["Ensemble","of","correlated","Hull-White","Models",".","Represents","the","Ito","process",":","``","`","None","dr_i","(","t",")","=","(","theta_i","(","t",")","-","a_i","(","t",")","*","r_i","(","t",")",")","dt","+","sigma_i","(","t",")","*","dW_","{","r_i","}","(","t",")",",","1","<","=","i","<","=","n",",","``","`","where","`","W_","{","r_i","}","`","are","1D","Brownian","motions","with","a","correlation","matrix","`","Rho","(","t",")","`",".","For","each","`","i","`",",","`","r_i","`","is","the","Hull-White","process",".","`","theta_i","`",",","`","a_i","`",",","`","sigma_i","`",",","`","Rho","`","are","positive","functions","of","time",".","`","a_i","`","correspond","to","the","mean-reversion","rate",",","`","sigma_i","`","is","the","volatility","of","the","process",",","`","theta_i","(","t",")","`","is","the","function","that","determines","long","run","behaviour","of","the","process","`","r","(","t",")","=","(","r_1","(","t",")",",","...",",","r_n","(","t",")",")","`","and","is","computed","to","match","the","initial","(","at","t=0",")","discount","curve",":","``","`","None","\\theta_i","=","df_i","(","t",")","\/","dt","+","a_i","*","f_i","(","t",")","+","0.5","*","sigma_i","*","*","2","\/","a_i","*","(","1","-","exp","(","-2","*","a_i","*","t",")",")",",","1","<","=","i","<","=","n","``","`","where","`","f_i","(","t",")","`","is","the","instantaneous","forward","rate","at","time","`","0","`","for","a","maturity","`","t","`","and","`","df_i","(","t",")","\/dt","`","is","the","gradient","of","`","f_i","`","with","respect","to","the","maturity",".","See","Section","3.3.1","of","[","1","]","for","details",".","The","price","at","time","`","t","`","of","a","zero-coupon","bond","maturing","at","`","T","`","is","given","by","(","Ref",".","[","2","]",")",":","``","`","None","P","(","t",",","T",")","=","P","(","0",",","T",")","\/","P","(","0",",","t",")","*","exp","(","-","(","r","(","t",")","-","f","(","0",",","t",")",")","*","G","(","t",",","T",")","-","0.5","*","y","(","t",")","*","G","(","t",",","T",")","^2",")","y","(","t",")","=","int_0^t","[","exp","(","-2","int_u^t","(","a","(","s",")","ds",")",")","sigma","(","u",")","^2","du","]","G","(","t",",","T",")","=","int_t^T","[","exp","(","-int_t^u","a","(","s",")","ds",")","du","]","``","`","If","mean-reversion",",","`","a_i","`",",","is","constant","and","the","volatility","(","`","sigma_i","`",")",",","and","correlation","(","`","Rho","`",")","are","piecewise","constant","functions",",","the","process","is","sampled","exactly",".","Otherwise",",","Euler","sampling","is","used",".","For","`","n=1","`","this","class","represents","Hull-White","Model","(","see","tff.models.hull_white.HullWhiteModel1F",")",".","#","#","#","#","Example",".","Two","correlated","Hull-White","processes",".","``","`","python","import","numpy","as","np","import","tensorflow","as","tf","import","tf_quant_finance","as","tff","dtype","=","tf.float64","#","Mean-reversion","is","constant","for","the","two","processes",".","`","mean_reversion","(","t",")","`","#","has","shape","`","[","dim","]","+","t.shape","`",".","mean_reversion","=","[","0.03",",","0.02","]","#","Volatility","is","a","piecewise","constant","function","with","jumps","at","the","same","locations","#","for","both","Hull-White","processes",".","`","volatility","(","t",")","`","has","shape","`","[","dim","]","+","t.shape","`",".","volatility","=","tff.math.piecewise.PiecewiseConstantFunc","(","jump_locations=","[","[","0.1",",","2",".","]",",","[","0.1",",","2",".","]","]",",","values=","[","[","0.01",",","0.02",",","0.01","]",",","[","0.01",",","0.015",",","0.01","]","]",",","dtype=dtype",")","#","Correlation","matrix","is","constant","corr_matrix","=","[","[","1.",",","0.1","]",",","[","0.1",",","1",".","]","]","initial_discount_rate_fn","=","lambda","*","args",":","[","0.01",",","0.015","]","process","=","tff.models.hull_white.VectorHullWhiteModel","(","dim=2",",","mean_reversion=mean_reversion",",","volatility=volatility",",","initial_discount_rate_fn=initial_discount_rate_fn",",","corr_matrix=corr_matrix",",","dtype=dtype",")","#","Sample","10000","paths","using","Sobol","numbers","as","a","random","type",".","times","=","np.linspace","(","0.",",","1.0",",","10",")","num_samples","=","10000","#","number","of","trajectories","paths","=","process.sample_paths","(","times",",","num_samples=num_samples",",","random_type=tff.math.random.RandomType.SOBOL",",","seed=","[","4",",","2","]",")","#","Compute","mean","for","each","Hull-White","process","at","the","terminal","value","tf.math.reduce_mean","(","paths","[",":",",","-1",",",":","]",",","axis=0",")","#","Expected",":","[","0.01070005",",","0.01540942","]","#","User","can","supply","time","discretization","grid","along","with","the","underlying","#","normal","draws","directly","to","the","sampler",".","times_grid","=","tf.sort","(","tf.concat","(","[","np.linspace","(","0.",",","1.0",",","10",")",",","[","0.1","]","]",",","axis=-1",")",")","normal_draws","=","tf.random.stateless_normal","(","[","num_samples","\/\/","2",",","10",",","2","]",",","seed=","[","4",",","2","]",",","dtype=dtype",")","normal_draws","=","tf.concat","(","[","normal_draws",",","-normal_draws","]",",","axis=0",")","paths","=","process.sample_paths","(","times",",","num_samples=num_samples",",","times_grid","=","times_grid",",","normal_draws=normal_draws",")","#","Compute","mean","for","each","Hull-White","process","at","the","terminal","value","tf.math.reduce_mean","(","paths","[",":",",","-1",",",":","]",",","axis=0",")","#","Expected",":","[","0.0101668",",","0.01509873","]","``","`","#","#","#","#","References",":","[","1","]",":","D.","Brigo",",","F.","Mercurio",".","Interest","Rate","Models",".","2007",".","[","2","]",":","Leif","B.","G.","Andersen","and","Vladimir","V.","Piterbarg",".","Interest","Rate","Modeling",".","Volume","II",":","Term","Structure","Models","."]
docstr: Returns a sample of simulated discount curves for the Hull-white model.
  
  ### References:
    [1]: Leif B.G. Andersen and Vladimir V. Piterbarg. Interest Rate Modeling,
    Volume II: Term Structure Models. 2010.
  
  Args:
    times: Rank 1 `Tensor` of positive real values. The times at which the
      discount curves are to be evaluated.
    curve_times: Rank 1 `Tensor` of positive real values. The maturities
      at which discount curve is computed at each simulation time.
    num_samples: Positive scalar `int`. The number of paths to draw.
    random_type: Enum value of `RandomType`. The type of (quasi)-random
      number generator to use to generate the paths.
      Default value: None which maps to the standard pseudo-random numbers.
    seed: Seed for the random number generator. The seed is
      only relevant if `random_type` is one of
      `[STATELESS, PSEUDO, HALTON_RANDOMIZED, PSEUDO_ANTITHETIC,
        STATELESS_ANTITHETIC]`. For `PSEUDO`, `PSEUDO_ANTITHETIC` and
      `HALTON_RANDOMIZED` the seed should be an Python integer. For
      `STATELESS` and  `STATELESS_ANTITHETIC` must be supplied as an integer
      `Tensor` of shape `[2]`.
      Default value: `None` which means no seed is set.
    skip: `int32` 0-d `Tensor`. The number of initial points of the Sobol or
      Halton sequence to skip. Used only when `random_type` is 'SOBOL',
      'HALTON', or 'HALTON_RANDOMIZED', otherwise ignored.
      Default value: `0`.
    time_step: Scalar real `Tensor`. Maximal distance between time grid points
      in Euler scheme. Used only when Euler scheme is applied.
    Default value: `None`.
    times_grid: An optional rank 1 `Tensor` representing time discretization
      grid. If `times` are not on the grid, then the nearest points from the
      grid are used. When supplied, `time_step` and jumps of the piecewise
      constant arguments are ignored.
      Default value: `None`, which means that the times grid is computed using
      `time_step`.  When exact sampling is used, the shape should be equal to
      `[num_time_points + 1]` where `num_time_points` is `tf.shape(times)[0]`
      plus the number of jumps of the Hull-White piecewise constant
      parameters. The grid should include the initial time point which is
      usually set to `0.0`.
    normal_draws: A `Tensor` of shape `[num_samples, num_time_points, dim]`
      and the same `dtype` as `times`. Represents random normal draws to
      compute increments `N(0, t_{n+1}) - N(0, t_n)`. When supplied,
      `num_samples` argument is ignored and the first dimensions of
      `normal_draws` is used instead. When exact sampling is used,
      `num_time_points` should be equal to `tf.shape(times)[0]` plus the
      number of jumps of the Hull-White piecewise constant parameters.
      Default value: `None` which means that the draws are generated by the
      algorithm.
    validate_args: Python `bool`. When `True` and `normal_draws` are supplied,
      checks that `tf.shape(normal_draws)[1]` is equal to the total number of
      time steps performed by the sampler.
      When `False` invalid dimension may silently render incorrect outputs.
      Default value: `False`.
    name: Str. The name to give this op.
      Default value: `sample_discount_curve_paths`.
  
  Returns:
    A tuple containing two `Tensor`s. The first element is a `Tensor` of
    shape [num_samples, m, k, dim] and contains the simulated bond curves
    where `m` is the size of `curve_times`, `k` is the size of `times` and
    `dim` is the dimension of the process. The second element is a `Tensor`
    of shape [num_samples, k, dim] and contains the simulated short rate
    paths.
  
  Raises:
    ValueError:
      (a) If `times` has rank different from `1`.
      (b) If Euler scheme is used by times is not supplied.
      (c) When neither `times_grid` nor `time_step` are supplied and Euler
        scheme is used.
      (d) If `normal_draws` is supplied and `dim` is mismatched.
    tf.errors.InvalidArgumentError: If `normal_draws` is supplied and the
      number of time steps implied by `times_grid` or `times_step` is
      mismatched.
      (e) If any of the parameters `mean_reversion`, `volatility`,
        `corr_matrix` is a generic callable.
docstr_tok: ["Returns","a","sample","of","simulated","discount","curves","for","the","Hull-white","model",".","#","#","#","References",":","[","1","]",":","Leif","B.G",".","Andersen","and","Vladimir","V.","Piterbarg",".","Interest","Rate","Modeling",",","Volume","II",":","Term","Structure","Models",".","2010",".","Args",":","times",":","Rank","1","`","Tensor","`","of","positive","real","values",".","The","times","at","which","the","discount","curves","are","to","be","evaluated",".","curve_times",":","Rank","1","`","Tensor","`","of","positive","real","values",".","The","maturities","at","which","discount","curve","is","computed","at","each","simulation","time",".","num_samples",":","Positive","scalar","`","int","`",".","The","number","of","paths","to","draw",".","random_type",":","Enum","value","of","`","RandomType","`",".","The","type","of","(","quasi",")","-random","number","generator","to","use","to","generate","the","paths",".","Default","value",":","None","which","maps","to","the","standard","pseudo-random","numbers",".","seed",":","Seed","for","the","random","number","generator",".","The","seed","is","only","relevant","if","`","random_type","`","is","one","of","`","[","STATELESS",",","PSEUDO",",","HALTON_RANDOMIZED",",","PSEUDO_ANTITHETIC",",","STATELESS_ANTITHETIC","]","`",".","For","`","PSEUDO","`",",","`","PSEUDO_ANTITHETIC","`","and","`","HALTON_RANDOMIZED","`","the","seed","should","be","an","Python","integer",".","For","`","STATELESS","`","and","`","STATELESS_ANTITHETIC","`","must","be","supplied","as","an","integer","`","Tensor","`","of","shape","`","[","2","]","`",".","Default","value",":","`","None","`","which","means","no","seed","is","set",".","skip",":","`","int32","`","0-d","`","Tensor","`",".","The","number","of","initial","points","of","the","Sobol","or","Halton","sequence","to","skip",".","Used","only","when","`","random_type","`","is","'SOBOL","'",",","'HALTON","'",",","or","'HALTON_RANDOMIZED","'",",","otherwise","ignored",".","Default","value",":","`","0","`",".","time_step",":","Scalar","real","`","Tensor","`",".","Maximal","distance","between","time","grid","points","in","Euler","scheme",".","Used","only","when","Euler","scheme","is","applied",".","Default","value",":","`","None","`",".","times_grid",":","An","optional","rank","1","`","Tensor","`","representing","time","discretization","grid",".","If","`","times","`","are","not","on","the","grid",",","then","the","nearest","points","from","the","grid","are","used",".","When","supplied",",","`","time_step","`","and","jumps","of","the","piecewise","constant","arguments","are","ignored",".","Default","value",":","`","None","`",",","which","means","that","the","times","grid","is","computed","using","`","time_step","`",".","When","exact","sampling","is","used",",","the","shape","should","be","equal","to","`","[","num_time_points","+","1","]","`","where","`","num_time_points","`","is","`","tf.shape","(","times",")","[","0","]","`","plus","the","number","of","jumps","of","the","Hull-White","piecewise","constant","parameters",".","The","grid","should","include","the","initial","time","point","which","is","usually","set","to","`","0.0","`",".","normal_draws",":","A","`","Tensor","`","of","shape","`","[","num_samples",",","num_time_points",",","dim","]","`","and","the","same","`","dtype","`","as","`","times","`",".","Represents","random","normal","draws","to","compute","increments","`","N","(","0",",","t_","{","n+1","}",")","-","N","(","0",",","t_n",")","`",".","When","supplied",",","`","num_samples","`","argument","is","ignored","and","the","first","dimensions","of","`","normal_draws","`","is","used","instead",".","When","exact","sampling","is","used",",","`","num_time_points","`","should","be","equal","to","`","tf.shape","(","times",")","[","0","]","`","plus","the","number","of","jumps","of","the","Hull-White","piecewise","constant","parameters",".","Default","value",":","`","None","`","which","means","that","the","draws","are","generated","by","the","algorithm",".","validate_args",":","Python","`","bool","`",".","When","`","True","`","and","`","normal_draws","`","are","supplied",",","checks","that","`","tf.shape","(","normal_draws",")","[","1","]","`","is","equal","to","the","total","number","of","time","steps","performed","by","the","sampler",".","When","`","False","`","invalid","dimension","may","silently","render","incorrect","outputs",".","Default","value",":","`","False","`",".","name",":","Str",".","The","name","to","give","this","op",".","Default","value",":","`","sample_discount_curve_paths","`",".","Returns",":","A","tuple","containing","two","`","Tensor","`","s",".","The","first","element","is","a","`","Tensor","`","of","shape","[","num_samples",",","m",",","k",",","dim","]","and","contains","the","simulated","bond","curves","where","`","m","`","is","the","size","of","`","curve_times","`",",","`","k","`","is","the","size","of","`","times","`","and","`","dim","`","is","the","dimension","of","the","process",".","The","second","element","is","a","`","Tensor","`","of","shape","[","num_samples",",","k",",","dim","]","and","contains","the","simulated","short","rate","paths",".","Raises",":","ValueError",":","(","a",")","If","`","times","`","has","rank","different","from","`","1","`",".","(","b",")","If","Euler","scheme","is","used","by","times","is","not","supplied",".","(","c",")","When","neither","`","times_grid","`","nor","`","time_step","`","are","supplied","and","Euler","scheme","is","used",".","(","d",")","If","`","normal_draws","`","is","supplied","and","`","dim","`","is","mismatched",".","tf.errors.InvalidArgumentError",":","If","`","normal_draws","`","is","supplied","and","the","number","of","time","steps","implied","by","`","times_grid","`","or","`","times_step","`","is","mismatched",".","(","e",")","If","any","of","the","parameters","`","mean_reversion","`",",","`","volatility","`",",","`","corr_matrix","`","is","a","generic","callable","."]
code: def sample_discount_curve_paths(
      self,
      times: types.RealTensor,
      curve_times: types.RealTensor,
      num_samples: types.IntTensor = 1,
      random_type: Optional[random.RandomType] = None,
      seed: Optional[types.IntTensor] = None,
      skip: types.IntTensor = 0,
      time_step: Optional[types.RealTensor] = None,
      times_grid: Optional[types.RealTensor] = None,
      normal_draws: Optional[types.RealTensor] = None,
      validate_args: bool = False,
      name: Optional[str] = None,
  ) -> Tuple[types.RealTensor, types.RealTensor]:
      """Returns a sample of simulated discount curves for the Hull-white model.
  
      ### References:
        [1]: Leif B.G. Andersen and Vladimir V. Piterbarg. Interest Rate Modeling,
        Volume II: Term Structure Models. 2010.
  
      Args:
        times: Rank 1 `Tensor` of positive real values. The times at which the
          discount curves are to be evaluated.
        curve_times: Rank 1 `Tensor` of positive real values. The maturities
          at which discount curve is computed at each simulation time.
        num_samples: Positive scalar `int`. The number of paths to draw.
        random_type: Enum value of `RandomType`. The type of (quasi)-random
          number generator to use to generate the paths.
          Default value: None which maps to the standard pseudo-random numbers.
        seed: Seed for the random number generator. The seed is
          only relevant if `random_type` is one of
          `[STATELESS, PSEUDO, HALTON_RANDOMIZED, PSEUDO_ANTITHETIC,
            STATELESS_ANTITHETIC]`. For `PSEUDO`, `PSEUDO_ANTITHETIC` and
          `HALTON_RANDOMIZED` the seed should be an Python integer. For
          `STATELESS` and  `STATELESS_ANTITHETIC` must be supplied as an integer
          `Tensor` of shape `[2]`.
          Default value: `None` which means no seed is set.
        skip: `int32` 0-d `Tensor`. The number of initial points of the Sobol or
          Halton sequence to skip. Used only when `random_type` is 'SOBOL',
          'HALTON', or 'HALTON_RANDOMIZED', otherwise ignored.
          Default value: `0`.
        time_step: Scalar real `Tensor`. Maximal distance between time grid points
          in Euler scheme. Used only when Euler scheme is applied.
        Default value: `None`.
        times_grid: An optional rank 1 `Tensor` representing time discretization
          grid. If `times` are not on the grid, then the nearest points from the
          grid are used. When supplied, `time_step` and jumps of the piecewise
          constant arguments are ignored.
          Default value: `None`, which means that the times grid is computed using
          `time_step`.  When exact sampling is used, the shape should be equal to
          `[num_time_points + 1]` where `num_time_points` is `tf.shape(times)[0]`
          plus the number of jumps of the Hull-White piecewise constant
          parameters. The grid should include the initial time point which is
          usually set to `0.0`.
        normal_draws: A `Tensor` of shape `[num_samples, num_time_points, dim]`
          and the same `dtype` as `times`. Represents random normal draws to
          compute increments `N(0, t_{n+1}) - N(0, t_n)`. When supplied,
          `num_samples` argument is ignored and the first dimensions of
          `normal_draws` is used instead. When exact sampling is used,
          `num_time_points` should be equal to `tf.shape(times)[0]` plus the
          number of jumps of the Hull-White piecewise constant parameters.
          Default value: `None` which means that the draws are generated by the
          algorithm.
        validate_args: Python `bool`. When `True` and `normal_draws` are supplied,
          checks that `tf.shape(normal_draws)[1]` is equal to the total number of
          time steps performed by the sampler.
          When `False` invalid dimension may silently render incorrect outputs.
          Default value: `False`.
        name: Str. The name to give this op.
          Default value: `sample_discount_curve_paths`.
  
      Returns:
        A tuple containing two `Tensor`s. The first element is a `Tensor` of
        shape [num_samples, m, k, dim] and contains the simulated bond curves
        where `m` is the size of `curve_times`, `k` is the size of `times` and
        `dim` is the dimension of the process. The second element is a `Tensor`
        of shape [num_samples, k, dim] and contains the simulated short rate
        paths.
  
      Raises:
        ValueError:
          (a) If `times` has rank different from `1`.
          (b) If Euler scheme is used by times is not supplied.
          (c) When neither `times_grid` nor `time_step` are supplied and Euler
            scheme is used.
          (d) If `normal_draws` is supplied and `dim` is mismatched.
        tf.errors.InvalidArgumentError: If `normal_draws` is supplied and the
          number of time steps implied by `times_grid` or `times_step` is
          mismatched.
          (e) If any of the parameters `mean_reversion`, `volatility`,
            `corr_matrix` is a generic callable.
      """
      # Parameters must be piecewise constants for now
      if not self._is_piecewise_constant:
          raise ValueError(
              "All paramaters `mean_reversion`, `volatility`, and "
              "`corr_matrix`must be piecewise constant functions."
          )
      name = name or self._name + "_sample_discount_curve_paths"
      with tf.name_scope(name):
          times = tf.convert_to_tensor(times, self._dtype, name="times")
          curve_times = tf.convert_to_tensor(
              curve_times, self._dtype, name="curve_times"
          )
          if times_grid is not None:
              times_grid = tf.convert_to_tensor(
                  times_grid, self._dtype, name="times_grid"
              )
          mean_reversion = self._mean_reversion(times)
          volatility = self._volatility(times)
          # Shape [dim, num_sim_times]
          y_t = self._compute_yt(times, mean_reversion, volatility)
          # Shape [num_samples, num_sim_times, dim]
          rate_paths = self.sample_paths(
              times=times,
              num_samples=num_samples,
              random_type=random_type,
              skip=skip,
              time_step=time_step,
              times_grid=times_grid,
              normal_draws=normal_draws,
              validate_args=validate_args,
              seed=seed,
          )
          short_rate = tf.expand_dims(rate_paths, axis=1)
  
          # Reshape all `Tensor`s so that they have the dimensions same as (or
          # broadcastable to) the output shape
          # [num_samples, num_curve_times, num_sim_times, dim].
          num_curve_nodes = tf.shape(curve_times)[0]  # m
          num_sim_steps = tf.shape(times)[0]  # k
          times = tf.reshape(times, (1, 1, num_sim_steps))
          curve_times = tf.reshape(curve_times, (1, num_curve_nodes, 1))
          # curve_times = tf.repeat(curve_times, self._dim, axis=-1)
  
          mean_reversion = tf.reshape(
              mean_reversion, (1, 1, self._dim, num_sim_steps)
          )
          # Transpose so the `dim` is the trailing dimension.
          mean_reversion = tf.transpose(mean_reversion, [0, 1, 3, 2])
  
          # Calculate the variable `y(t)` (described in [1], section 10.1.6.1)
          # so that we have the full Markovian state to compute the P(t,T).
          y_t = tf.reshape(
              tf.transpose(y_t), (1, 1, num_sim_steps, self._dim)
          )
          # Shape [num_samples, num_curve_times, num_sim_steps, dim]
          return (
              self._bond_reconstitution(
                  times,
                  times + curve_times,
                  mean_reversion,
                  short_rate,
                  y_t,
              ),
              rate_paths,
          )
  
imports: from typing import Callable, Union, Tuple, Optional
  import tensorflow.compat.v2
  from tf_quant_finance import types
  from tf_quant_finance import utils
  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 generic_ito_process
  from tf_quant_finance.models import utils
label_desc: Use image node_id 5 for calling the VectorHullWhiteModel obj's underlying member method code with example usage: obj.sample_discount_curve_paths(times, curve_times, num_samples, random_type, seed, skip, time_step, times_grid, normal_draws, validate_args, name) and returns: self,  rate_paths