code: def build_model_for_gibbs_fitting(
      observed_time_series,
      design_matrix,
      weights_prior,
      level_variance_prior,
      observation_noise_variance_prior,
      slope_variance_prior=None,
      initial_level_prior=None,
      sparse_weights_nonzero_prob=None,
      seasonal_components=None,
  ):
      """Builds a StructuralTimeSeries model instance that supports Gibbs sampling.
  
      To support Gibbs sampling, a model must have have conjugate priors on all
      scale and weight parameters, and must be constructed so that
      `model.parameters` matches the parameters and ordering specified by the
      `GibbsSamplerState` namedtuple. Currently, this includes (only) models
      consisting of the sum of a LocalLevel or LocalLinearTrend component with
      (optionally) a LinearRegression or SpikeAndSlabSparseLinearRegression
      component.
  
      Args:
        observed_time_series: optional `float` `Tensor` of shape [..., T, 1]`
          (omitting the trailing unit dimension is also supported when `T > 1`),
          specifying an observed time series. May optionally be an instance of
          `tfp.sts.MaskedTimeSeries`, which includes a mask `Tensor` to specify
          timesteps with missing observations.
        design_matrix: Optional float `Tensor` of shape `concat([batch_shape,
          [num_timesteps, num_features]])`. This may also optionally be an instance
          of `tf.linalg.LinearOperator`. If None, no regression is done.
        weights_prior: Optional distribution instance specifying a normal prior on
          weights. This may be a multivariate normal instance with event shape
          `[num_features]`, or a scalar normal distribution with event shape `[]`.
          In either case, the batch shape must broadcast to the batch shape of
          `observed_time_series`. If a `sparse_weights_nonzero_prob` is specified,
          requesting sparse regression, then the `weights_prior` mean is ignored
          (because nonzero means are not currently implemented by the spike-and-slab
          sampler). In this case, `weights_prior=None` is also valid, and will use
          the default prior of the spike-and-slab sampler.
        level_variance_prior: An instance of `tfd.InverseGamma` representing a prior
          on the level variance (`level_scale**2`) of a local level model. May have
          batch shape broadcastable to the batch shape of `observed_time_series`.
        observation_noise_variance_prior: An instance of `tfd.InverseGamma`
          representing a prior on the observation noise variance (
          `observation_noise_scale**2`). May have batch shape broadcastable to the
          batch shape of `observed_time_series`.
        slope_variance_prior: Optional instance of `tfd.InverseGamma` representing a
          prior on slope variance (`slope_scale**2`) of a local linear trend model.
          May have batch shape broadcastable to the batch shape of
          `observed_time_series`. If specified, a local linear trend model is used
          rather than a local level model.
          Default value: `None`.
        initial_level_prior: optional `tfd.Distribution` instance specifying a
          prior on the initial level. If `None`, a heuristic default prior is
          constructed based on the provided `observed_time_series`.
          Default value: `None`.
        sparse_weights_nonzero_prob: Optional scalar float `Tensor` prior
          probability that any given feature has nonzero weight. If specified, this
          triggers a sparse regression with a spike-and-slab prior, where
          `sparse_weights_nonzero_prob` is the prior probability of the 'slab'
          component.
          Default value: `None`.
        seasonal_components: An (optional) list of Seasonal components to include
          in the model. There are restrictions about what priors may be specified
          (InverseGamma drift scale prior).
  
      Returns:
        model: A `tfp.sts.StructuralTimeSeries` model instance.
      """
      if design_matrix is None:
          if sparse_weights_nonzero_prob is not None:
              raise ValueError(
                  "Design matrix is None thus sparse_weights_nonzero_prob should "
                  "not be defined, as it will not be used."
              )
          if weights_prior is not None:
              raise ValueError(
                  "Design matrix is None thus weights_prior should not be defined, "
                  "as it will not be used."
              )
  
      if isinstance(weights_prior, normal.Normal):
          # Canonicalize scalar normal priors as diagonal MVNs.
          # design_matrix must be defined, otherwise we threw an exception earlier.
          if isinstance(design_matrix, tf.linalg.LinearOperator):
              num_features = design_matrix.shape_tensor()[-1]
          else:
              num_features = prefer_static.dimension_size(
                  design_matrix, -1
              )
          weights_prior = _tile_normal_to_mvn_diag(
              weights_prior, num_features
          )
      elif weights_prior is not None and not _is_multivariate_normal(
          weights_prior
      ):
          raise ValueError(
              "Weights prior must be a normal distribution or `None`."
          )
      if not isinstance(
          level_variance_prior, inverse_gamma.InverseGamma
      ):
          raise ValueError(
              "Level variance prior must be an inverse gamma distribution."
          )
      if slope_variance_prior is not None and not isinstance(
          slope_variance_prior, inverse_gamma.InverseGamma
      ):
          raise ValueError(
              "Slope variance prior must be an inverse gamma distribution; got: {}.".format(
                  slope_variance_prior
              )
          )
      if not isinstance(
          observation_noise_variance_prior, inverse_gamma.InverseGamma
      ):
          raise ValueError(
              "Observation noise variance prior must be an inverse "
              "gamma distribution."
          )
      if seasonal_components is None:
          seasonal_components = []
      for seasonal_component in seasonal_components:
          if not seasonal_component.allow_drift:
              raise NotImplementedError(
                  "Only seasonality with drift is supported by Gibbs sampling."
              )
          prior = seasonal_component.get_parameter("drift_scale").prior
          # TODO(kloveless): Create a helper function to help with this verification,
          # to be shared with seasonal.py.
          if not (
              isinstance(
                  prior,
                  transformed_distribution.TransformedDistribution,
              )
              and isinstance(prior.bijector, invert.Invert)
              and isinstance(prior.bijector.bijector, square.Square)
              and isinstance(
                  prior.distribution, inverse_gamma.InverseGamma
              )
          ):
              raise NotImplementedError(
                  "Seasonal components drift scale must be the square root of an "
                  "inverse gamma distribution; got {}".format(prior)
              )
  
      sqrt = invert.Invert(
          square.Square()
      )  # Converts variance priors to scale priors.
      components = []
  
      # Level or trend component.
      if slope_variance_prior:
          components.append(
              local_linear_trend.LocalLinearTrend(
                  observed_time_series=observed_time_series,
                  level_scale_prior=sqrt(level_variance_prior),
                  slope_scale_prior=sqrt(slope_variance_prior),
                  initial_level_prior=initial_level_prior,
                  name="local_linear_trend",
              )
          )
      else:
          components.append(
              local_level.LocalLevel(
                  observed_time_series=observed_time_series,
                  level_scale_prior=sqrt(level_variance_prior),
                  initial_level_prior=initial_level_prior,
                  name="local_level",
              )
          )
  
      # Regression component.
      if design_matrix is None:
          pass
      elif sparse_weights_nonzero_prob is not None:
          components.append(
              SpikeAndSlabSparseLinearRegression(
                  design_matrix=design_matrix,
                  weights_prior=weights_prior,
                  sparse_weights_nonzero_prob=sparse_weights_nonzero_prob,
                  name="sparse_regression",
              )
          )
      else:
          components.append(
              regression.LinearRegression(
                  design_matrix=design_matrix,
                  weights_prior=weights_prior,
                  name="regression",
              )
          )
      model = sum_lib.Sum(
          components + seasonal_components,
          observed_time_series=observed_time_series,
          observation_noise_scale_prior=sqrt(
              observation_noise_variance_prior
          ),
          # The Gibbs sampling steps in this file do not account for an
          # offset to the observed series. Instead, we assume the
          # observed series has already been centered and
          # scale-normalized.
          constant_offset=0.0,
      )
      model.supports_gibbs_sampling = True
      return model
  
imports: import collections
  import itertools
  import numpy
  import six
  import tensorflow.compat.v2
  from tensorflow_probability.python.bijectors import identity
  from tensorflow_probability.python.bijectors import invert
  from tensorflow_probability.python.bijectors import square
  from tensorflow_probability.python.distributions import categorical
  from tensorflow_probability.python.distributions import distribution
  from tensorflow_probability.python.distributions import gamma
  from tensorflow_probability.python.distributions import inverse_gamma
  from tensorflow_probability.python.distributions import mixture_same_family
  from tensorflow_probability.python.distributions import mvn_diag
  from tensorflow_probability.python.distributions import mvn_linear_operator
  from tensorflow_probability.python.distributions import normal
  from tensorflow_probability.python.distributions import normal_conjugate_posteriors
  from tensorflow_probability.python.distributions import transformed_distribution
  from tensorflow_probability.python.experimental.distributions import mvn_precision_factor_linop
  from tensorflow_probability.python.experimental.sts_gibbs import dynamic_spike_and_slab
  from tensorflow_probability.python.experimental.sts_gibbs import sample_parameters
  from tensorflow_probability.python.experimental.sts_gibbs import spike_and_slab
  from tensorflow_probability.python.internal import distribution_util
  from tensorflow_probability.python.internal import dtype_util
  from tensorflow_probability.python.internal import prefer_static
  from tensorflow_probability.python.internal import reparameterization
  from tensorflow_probability.python.internal import samplers
  from tensorflow_probability.python.sts.components import local_level
  from tensorflow_probability.python.sts.components import local_linear_trend
  from tensorflow_probability.python.sts.components import regression
  from tensorflow_probability.python.sts.components import seasonal
  from tensorflow_probability.python.sts.components import sum
  from tensorflow_probability.python.sts.internal import util
label_desc: Use image node_id 3 for calling a global function with example usage: build_model_for_gibbs_fitting(observed_time_series, design_matrix, weights_prior, level_variance_prior, observation_noise_variance_prior, slope_variance_prior, initial_level_prior, sparse_weights_nonzero_prob, seasonal_components) and returns: model