docstr: Validate a parafac2_tensor in the form (weights, factors) Return the
  rank and shape of the validated tensor.
  
  Parameters
  ----------
  parafac2_tensor
      Parafac2Tensor or (weights, factors)
  
  Returns
  -------
  (shape, rank)
      size of the full tensor and rank of the CP tensor
docstr_tok: ["Validate","a","parafac2_tensor","in","the","form","(","weights",",","factors",")","Return","the","rank","and","shape","of","the","validated","tensor",".","Parameters","--","--","--","--","--","parafac2_tensor","Parafac2Tensor","or","(","weights",",","factors",")","Returns","--","--","--","-","(","shape",",","rank",")","size","of","the","full","tensor","and","rank","of","the","CP","tensor"]
code: def validate_parafac2_tensor(parafac2_tensor):
      """Validate a parafac2_tensor in the form (weights, factors) Return the
      rank and shape of the validated tensor.
  
      Parameters
      ----------
      parafac2_tensor
          Parafac2Tensor or (weights, factors)
  
      Returns
      -------
      (shape, rank)
          size of the full tensor and rank of the CP tensor
      """
      if isinstance(parafac2_tensor, ivy.Parafac2Tensor):
          # it's already been validated at creation
          return parafac2_tensor.shape, parafac2_tensor.rank
  
      weights, factors, projections = parafac2_tensor
  
      if len(factors) != 3:
          raise ValueError(
              "A PARAFAC2 tensor should be composed of exactly three factors."
              f"However, {len(factors)} factors was given."
          )
  
      if len(projections) != factors[0].shape[0]:
          raise ValueError(
              "A PARAFAC2 tensor should have one projection matrix for each"
              f" horisontal slice. However, {len(projections)} projection matrices"
              f" was given and the first mode haslength {factors[0].shape[0]}"
          )
  
      rank = int(ivy.shape(factors[0])[1])
  
      shape = []
      for i, projection in enumerate(projections):
          current_mode_size, current_rank = ivy.shape(projection)
          if current_rank != rank:
              raise ValueError(
                  "All the projection matrices of a PARAFAC2 tensor should have the"
                  f" same number of columns as the rank. However, rank={rank} but"
                  f" projections[{i}].shape[1]={ivy.shape(projection)[1]}"
              )
  
          inner_product = ivy.dot(
              ivy.permute_dims(projection, (1, 0)), projection
          )
          if (
              ivy.max(
                  ivy.abs(
                      inner_product
                      - ivy.eye(rank, dtype=inner_product[0].dtype)
                  )
              )
              > 1e-5
          ):
              raise ValueError(
                  "All the projection matrices must be orthonormal, that is, P.T@P"
                  " = I. "
                  f"However, projection[{i}].T@projection[{i}] -"
                  " T.eye(rank)) = "
                  f"""{ivy.sqrt(ivy.sum(ivy.square(inner_product -
                                    ivy.eye(rank,dtype=inner_product[0].dtype)),
                                      axis=0))}"""
              )
  
          # Tuple unpacking to possibly support higher
          # order PARAFAC2 tensors in the future
          shape.append(
              (current_mode_size, *[f.shape[0] for f in factors[2:]])
          )
  
      # Skip first factor matrix since the rank is extracted from it.
      for i, factor in enumerate(factors[1:]):
          current_mode_size, current_rank = ivy.shape(factor)
          if current_rank != rank:
              raise ValueError(
                  "All the factors of a PARAFAC2 tensor should have the same number"
                  f" of columns.However, factors[0].shape[1]={rank} but"
                  f" factors[{i}].shape[1]={current_rank}."
              )
  
      if weights is not None and ivy.shape(weights)[0] != rank:
          raise ValueError(
              f"Given factors for a rank-{rank} PARAFAC2 tensor but"
              f" len(weights)={ivy.shape(weights)[0]}."
          )
  
      return tuple(shape), rank
  
imports: from .base import FactorizedTensor
  import ivy
  from copy import deepcopy
label_desc: Use image node_id 12 for calling the Parafac2Tensor obj's underlying member method code with example usage: obj.validate_parafac2_tensor(parafac2_tensor) and returns: tuple,  rank, parafac2_tensor,  parafac2_tensor