code: def non_negative_tucker(
      tensor,
      rank,
      n_iter_max=10,
      init="svd",
      tol=10e-5,
      random_state=None,
      verbose=False,
      return_errors=False,
      normalize_factors=False,
  ):
      """Non-negative Tucker decomposition
  
          Iterative multiplicative update, see [2]_
  
      Parameters
      ----------
      tensor : ``ndarray``
      rank : None, int or int list
          size of the core tensor, ``(len(ranks) == tensor.ndim)``
          if int, the same rank is used for all modes
      n_iter_max : int
          maximum number of iteration
      init : {'svd', 'random'}
      random_state : {None, int, np.random.RandomState}
      verbose : int , optional
          level of verbosity
      return_errors : boolean
          Indicates whether the algorithm should return all reconstruction errors
          and computation time of each iteration or not
          Default: False
      normalize_factors : if True, aggregates the norms of the factors in the core.
  
      Returns
      -------
      core : ndarray
              positive core of the Tucker decomposition
              has shape `ranks`
      factors : ndarray list
              list of factors of the CP decomposition
              element `i` is of shape ``(tensor.shape[i], rank)``
  
      References
      ----------
      .. [2] Yong-Deok Kim and Seungjin Choi,
         "Non-negative tucker decomposition",
         IEEE Conference on Computer Vision and Pattern Recognition s(CVPR),
         pp 1-8, 2007
      """
      rank = validate_tucker_rank(tl.shape(tensor), rank=rank)
  
      epsilon = 10e-12
  
      # Initialisation
      nn_core, nn_factors = initialize_tucker(
          tensor,
          rank,
          range(tl.ndim(tensor)),
          init=init,
          random_state=random_state,
          non_negative=True,
      )
  
      norm_tensor = tl.norm(tensor, 2)
      rec_errors = []
  
      for iteration in range(n_iter_max):
          for mode in range(tl.ndim(tensor)):
              B = tucker_to_tensor(
                  (nn_core, nn_factors), skip_factor=mode
              )
              B = tl.transpose(unfold(B, mode))
  
              numerator = tl.dot(unfold(tensor, mode), B)
              numerator = tl.clip(numerator, a_min=epsilon, a_max=None)
              denominator = tl.dot(
                  nn_factors[mode], tl.dot(tl.transpose(B), B)
              )
              denominator = tl.clip(
                  denominator, a_min=epsilon, a_max=None
              )
              nn_factors[mode] *= numerator / denominator
  
          numerator = tucker_to_tensor(
              (tensor, nn_factors), transpose_factors=True
          )
          numerator = tl.clip(numerator, a_min=epsilon, a_max=None)
          for i, f in enumerate(nn_factors):
              if i:
                  denominator = mode_dot(
                      denominator, tl.dot(tl.transpose(f), f), i
                  )
              else:
                  denominator = mode_dot(
                      nn_core, tl.dot(tl.transpose(f), f), i
                  )
          denominator = tl.clip(denominator, a_min=epsilon, a_max=None)
          nn_core *= numerator / denominator
  
          rec_error = (
              tl.norm(
                  tensor - tucker_to_tensor((nn_core, nn_factors)), 2
              )
              / norm_tensor
          )
          rec_errors.append(rec_error)
          if iteration > 1 and verbose:
              print(
                  f"reconstruction error={rec_errors[-1]}, variation={rec_errors[-2] - rec_errors[-1]}."
              )
  
          if (
              iteration > 1
              and abs(rec_errors[-2] - rec_errors[-1]) < tol
          ):
              if verbose:
                  print(f"converged in {iteration} iterations.")
              break
          if normalize_factors:
              nn_core, nn_factors = tucker_normalize(
                  (nn_core, nn_factors)
              )
      tensor = TuckerTensor((nn_core, nn_factors))
      if return_errors:
          return tensor, rec_errors
      else:
          return tensor
  
imports: import tensorly
  from ._base_decomposition import DecompositionMixin
  from ..base import unfold
  from ..tenalg import multi_mode_dot, mode_dot
  from ..tucker_tensor import tucker_to_tensor, TuckerTensor, validate_tucker_rank, tucker_normalize
  from ..tenalg.proximal import hals_nnls, active_set_nnls, fista
  from math import sqrt
  import warnings
  from collections.abc import Iterable
  from ..tenalg.svd import svd_interface
label_desc: Use image node_id 4 for calling a global function with example usage: non_negative_tucker(tensor, rank, n_iter_max, init, tol, random_state, verbose, return_errors, normalize_factors) and returns: tensor,  rec_errors, tensor