class_docstr: Map X to [0, 1]^d for RangeParameter of type float and not log scale.
  
  Uses bounds l <= x <= u, sets x_tilde_i = (x_i - l_i) / (u_i - l_i).
  Constraints wTx <= b are converted to gTx_tilde <= h, where
  g_i = w_i (u_i - l_i) and h = b - wTl.
  
  Transform is done in-place.
class_docstr_tok: ["Map","X","to","[","0",",","1","]","^d","for","RangeParameter","of","type","float","and","not","log","scale",".","Uses","bounds","l","<","=","x","<","=","u",",","sets","x_tilde_i","=","(","x_i","-","l_i",")","\/","(","u_i","-","l_i",")",".","Constraints","wTx","<","=","b","are","converted","to","gTx_tilde","<","=","h",",","where","g_i","=","w_i","(","u_i","-","l_i",")","and","h","=","b","-","wTl",".","Transform","is","done","in-place","."]
docstr: Transform a multivariate distribution in-place.
docstr_tok: ["Transform","a","multivariate","distribution","in-place","."]
code: def _transform_multivariate_distribution(
      self, distribution: ParameterDistribution, is_environmental: bool
  ) -> None:
      r"""Transform a multivariate distribution in-place."""
      # Ignore if the ranges of all parameters are same as the target range.
      if (
          all(
              self.bounds[p_name][1] - self.bounds[p_name][0]
              == self.target_range
              for p_name in distribution.parameters
          )
          and not is_environmental
      ):
          return
      if distribution.distribution_class == "multivariate_normal":
          # If S is cov and A is the diagonal scale matrix,
          # the new cov will be ASA.
          n_dist_params = len(distribution.parameters)
          scale_vec = np.zeros(len(distribution.parameters))
          for i, p in enumerate(distribution.parameters):
              bounds = self.bounds[p]
              p_range = bounds[1] - bounds[0]
              scale_vec[i] = self.target_range / p_range
          cov = np.asarray(
              distribution.distribution_parameters.get("cov")
          )
          if cov.shape != (n_dist_params, n_dist_params):
              raise UserInputError(
                  "Expected `cov` to be a square matrix of size equal to "
                  "number of parameters. Received `cov` with shape "
                  f"{cov.shape} for the distribution of {n_dist_params} "
                  "parameters."
              )
          # Same as np.diag(scale_vec) @ cov @ np.diag(scale_vec) but faster.
          distribution.distribution_parameters["cov"] = (
              scale_vec[..., None] * cov * scale_vec[..., None, :]
          )
          mean = np.asarray(
              distribution.distribution_parameters.get("mean", 0.0)
          )
          if not np.all(mean == 0):
              if mean.shape != (n_dist_params,):
                  raise UserInputError(
                      "Expected `mean` to be an array of shape "
                      f"{(n_dist_params,)}, but received {mean}."
                  )
              # Mean would simply be AM as long as it is not environmental.
              # If environmental, we need to first subtract the lower bounds
              # then add the target lb.
              if is_environmental:
                  lbs = np.array(
                      [
                          self.bounds[p][0]
                          for p in distribution.parameters
                      ]
                  )
                  new_mean = scale_vec * (mean - lbs) + self.target_lb
                  distribution.distribution_parameters[
                      "mean"
                  ] = new_mean
              else:
                  distribution.distribution_parameters["mean"] = (
                      scale_vec * mean
                  )
      else:
          raise UnsupportedError(
              f"{self.__class__.__name__} transform of multivariate "
              "distributions, other than `multivariate_normal`, is not "
              "supported. Consider manually normalizing the parameter "
              "and the corresponding distribution."
          )
  
imports: from typing import Dict, List, Optional, Tuple, TYPE_CHECKING
  import numpy
  from ax.core.observation import Observation, ObservationFeatures
  from ax.core.parameter import ParameterType, RangeParameter
  from ax.core.parameter_constraint import ParameterConstraint
  from ax.core.parameter_distribution import ParameterDistribution
  from ax.core.search_space import RobustSearchSpace, SearchSpace
  from ax.exceptions.core import UnsupportedError, UserInputError
  from ax.modelbridge.transforms.base import Transform
  from ax.models.types import TConfig
label_desc: Use image node_id 7 for calling the UnitX obj's underlying member method code with example usage: obj._transform_multivariate_distribution(distribution, is_environmental) without return types