class_docstr: An implementation of the element-wise rational spline bijections of linear and
  quadratic order (Durkan et al., 2019; Dolatabadi et al., 2020) conditioning on
  an additional context variable.
  
  Rational splines are functions that are comprised of segments that are the ratio
  of two polynomials. For instance, for the :math:`d`-th dimension and the
  :math:`k`-th segment on the spline, the function will take the form,
  
      :math:`y_d = \frac{\alpha^{(k)}(x_d)}{\beta^{(k)}(x_d)},`
  
  where :math:`\alpha^{(k)}` and :math:`\beta^{(k)}` are two polynomials of
  order :math:`d` whose parameters are the output of a function, e.g. a NN, with
  input :math:`z\\in\\mathbb{R}^{M}` representing the context variable to
  condition on.. For :math:`d=1`, we say that the spline is linear, and for
  :math:`d=2`, quadratic. The spline is constructed on the specified bounding box,
  :math:`[-K,K]\times[-K,K]`, with the identity function used elsewhere.
  
  Rational splines offer an excellent combination of functional flexibility whilst
  maintaining a numerically stable inverse that is of the same computational and
  space complexities as the forward operation. This element-wise transform permits
  the accurate represention of complex univariate distributions.
  
  Example usage:
  
  >>> from pyro.nn.dense_nn import DenseNN
  >>> input_dim = 10
  >>> context_dim = 5
  >>> batch_size = 3
  >>> count_bins = 8
  >>> base_dist = dist.Normal(torch.zeros(input_dim), torch.ones(input_dim))
  >>> param_dims = [input_dim * count_bins, input_dim * count_bins,
  ... input_dim * (count_bins - 1), input_dim * count_bins]
  >>> hypernet = DenseNN(context_dim, [50, 50], param_dims)
  >>> transform = ConditionalSpline(hypernet, input_dim, count_bins)
  >>> z = torch.rand(batch_size, context_dim)
  >>> flow_dist = dist.ConditionalTransformedDistribution(base_dist,
  ... [transform]).condition(z)
  >>> flow_dist.sample(sample_shape=torch.Size([batch_size])) # doctest: +SKIP
  
  :param input_dim: Dimension of the input vector. This is required so we know how
      many parameters to store.
  :type input_dim: int
  :param count_bins: The number of segments comprising the spline.
  :type count_bins: int
  :param bound: The quantity :math:`K` determining the bounding box,
      :math:`[-K,K]\times[-K,K]`, of the spline.
  :type bound: float
  :param order: One of ['linear', 'quadratic'] specifying the order of the spline.
  :type order: string
  
  References:
  
  Conor Durkan, Artur Bekasov, Iain Murray, George Papamakarios. Neural
  Spline Flows. NeurIPS 2019.
  
  Hadi M. Dolatabadi, Sarah Erfani, Christopher Leckie. Invertible Generative
  Modeling using Linear Rational Splines. AISTATS 2020.
code: def __init__(
      self, nn, input_dim, count_bins, bound=3.0, order="linear"
  ):
      super().__init__()
  
      self.nn = nn
      self.input_dim = input_dim
      self.count_bins = count_bins
      self.bound = bound
      self.order = order
  
imports: from functools import partial
  import torch
  import torch.nn
  import torch.nn.functional
  from torch.distributions import Transform, constraints
  from pyro.nn import DenseNN
  from ..conditional import ConditionalTransformModule
  from ..torch_transform import TransformModule
  from ..util import copy_docs_from
label_desc: Use image node_id 1 to create a new ConditionalSpline object from inherited base classes: ConditionalTransformModule with example: obj = ConditionalSpline(nn, input_dim, count_bins, bound, order)