docstr: Return the rank of a TT Decomposition.
  
  Parameters
  ----------
  tensor_shape
      shape of the tensor to decompose
  rank
      way to determine the rank, by default 'same'
      if 'same': rank is computed to keep the number of parameters (at most) the same
      if float, computes a rank so as to keep rank percent of the original number of parameters
      if int or tuple, just returns rank
  constant_rank
      if True, the *same* rank will be chosen for each modes
      if False (default), the rank of each mode will be
      proportional to the corresponding tensor_shape
      used only if rank == 'same' or 0 < rank <= 1*
  
  rounding
      Mode for rounding
      One of ["round", "floor", "ceil"]
  
  allow_overparametrization
      if False, the rank must be realizable through iterative application of SVD
  
  Returns
  -------
  rank
      rank of the decomposition
docstr_tok: ["Return","the","rank","of","a","TT","Decomposition",".","Parameters","--","--","--","--","--","tensor_shape","shape","of","the","tensor","to","decompose","rank","way","to","determine","the","rank",",","by","default","'same'","if","'same","'",":","rank","is","computed","to","keep","the","number","of","parameters","(","at","most",")","the","same","if","float",",","computes","a","rank","so","as","to","keep","rank","percent","of","the","original","number","of","parameters","if","int","or","tuple",",","just","returns","rank","constant_rank","if","True",",","the","*","same","*","rank","will","be","chosen","for","each","modes","if","False","(","default",")",",","the","rank","of","each","mode","will","be","proportional","to","the","corresponding","tensor_shape","used","only","if","rank","==","'same","'","or","0","<","rank","<","=","1","*","rounding","Mode","for","rounding","One","of","[","``","round","''",",","``","floor","''",",","``","ceil","''","]","allow_overparametrization","if","False",",","the","rank","must","be","realizable","through","iterative","application","of","SVD","Returns","--","--","--","-","rank","rank","of","the","decomposition"]
code: def validate_tt_rank(
      tensor_shape,
      rank="same",
      constant_rank=False,
      rounding="round",
      allow_overparametrization=True,
  ):
      """Return the rank of a TT Decomposition.
  
      Parameters
      ----------
      tensor_shape
          shape of the tensor to decompose
      rank
          way to determine the rank, by default 'same'
          if 'same': rank is computed to keep the number of parameters (at most) the same
          if float, computes a rank so as to keep rank percent of the original number of parameters
          if int or tuple, just returns rank
      constant_rank
          if True, the *same* rank will be chosen for each modes
          if False (default), the rank of each mode will be
          proportional to the corresponding tensor_shape
          used only if rank == 'same' or 0 < rank <= 1*
  
      rounding
          Mode for rounding
          One of ["round", "floor", "ceil"]
  
      allow_overparametrization
          if False, the rank must be realizable through iterative application of SVD
  
      Returns
      -------
      rank
          rank of the decomposition
      """  # noqa: E501
      if rounding == "ceil":
          rounding_fn = ivy.ceil
      elif rounding == "floor":
          rounding_fn = ivy.floor
      elif rounding == "round":
          rounding_fn = ivy.round
      else:
          raise ValueError(
              f"Rounding should be round, floor or ceil, but got {rounding}"
          )
  
      if rank == "same":
          rank = float(1)
  
      if isinstance(rank, float) and constant_rank:
          n_param_tensor = ivy.prod(tensor_shape) * rank
          order = len(tensor_shape)
  
          if order == 2:
              rank = (
                  1,
                  n_param_tensor / (tensor_shape[0] + tensor_shape[1]),
                  1,
              )
              warnings.warn(
                  "Determining the tt-rank for the trivial case of a matrix (order 2"
                  f" tensor) of shape {tensor_shape}, not a higher-order tensor."
              )
  
          a = ivy.sum(tensor_shape[1:-1])
          b = ivy.sum(tensor_shape[0] + tensor_shape[-1])
          c = -n_param_tensor
          delta = ivy.sqrt(b**2 - 4 * a * c)
          solution = int(rounding_fn((-b + delta) / (2 * a)))
          rank = rank = (1,) + (solution,) * (order - 1) + (1,)
  
      elif isinstance(rank, float):
          order = len(tensor_shape)
          avg_dim = [
              (tensor_shape[i] + tensor_shape[i + 1]) / 2
              for i in range(order - 1)
          ]
          if len(avg_dim) > 1:
              a = sum(
                  avg_dim[i - 1] * tensor_shape[i] * avg_dim[i]
                  for i in range(1, order - 1)
              )
          else:
              warnings.warn(
                  "Determining the tt-rank for the trivial case of a matrix (order 2"
                  f" tensor) of shape {tensor_shape}, not a higher-order tensor."
              )
              a = avg_dim[0] ** 2 * tensor_shape[0]
          b = (
              tensor_shape[0] * avg_dim[0]
              + tensor_shape[-1] * avg_dim[-1]
          )
          c = -ivy.prod(tensor_shape) * rank
          delta = ivy.sqrt(b**2 - 4 * a * c)
  
          fraction_param = (-b + delta) / (2 * a)
          rank = tuple(
              max(int(rounding_fn(d * fraction_param)), 1)
              for d in avg_dim
          )
          rank = (1,) + rank + (1,)
  
      else:
          n_dim = len(tensor_shape)
          if isinstance(rank, int):
              rank = [1] + [rank] * (n_dim - 1) + [1]
          elif n_dim + 1 != len(rank):
              message = (
                  "Provided incorrect number of ranks. Should verify len(rank) =="
                  f" len(ivy.shape(tensor)) + 1, but len(rank) = {len(rank)} while"
                  f" len(ivy.shape(tensor)) + 1  = {n_dim+1}"
              )
              raise (ValueError(message))
  
          if rank[0] != 1:
              message = (
                  f"Provided rank[0] == {rank[0]} but boundary conditions dictate"
                  " rank[0] == rank[-1] == 1."
              )
              raise ValueError(message)
          if rank[-1] != 1:
              message = (
                  f"Provided rank[-1] == {rank[-1]} but boundary conditions dictate"
                  " rank[0] == rank[-1] == 1."
              )
              raise ValueError(message)
  
      if allow_overparametrization:
          return list(rank)
      else:
          validated_rank = [1]
          for i, s in enumerate(tensor_shape[:-1]):
              n_row = int(rank[i] * s)
              n_column = ivy.prod(tensor_shape[(i + 1) :])
              validated_rank.append(min(n_row, n_column, rank[i + 1]))
          validated_rank.append(1)
  
          return validated_rank
  
imports: from .base import FactorizedTensor
  import ivy
  import warnings
label_desc: Use image node_id 16 for calling the TTTensor obj's underlying member method code with example usage: obj.validate_tt_rank(tensor_shape, rank, constant_rank, rounding, allow_overparametrization) and returns: list, validated_rank