code: def ensure_frozen(
      mutable: Mutable | Any,
      *,
      strict: bool = True,
      sample: Sample | None = None,
      retries: int = 1000,
  ) -> Any:
      """Ensure a mutable is frozen. Used when passing the mutable to a function which doesn't accept a mutable.
  
      If the argument is not a mutable, nothing happens.
      Otherwise, :meth:`~nni.mutable.Mutable.freeze` will be called if sample is given.
      If sample is None, :func:`ensure_frozen` will also try to fill the sample
      with the content in :class:`frozen_context`.
      Or else :meth:`~nni.mutable.Mutable.robust_default` will be called on the mutable.
  
      Parameters
      ----------
      mutable : nni.mutable.Mutable or any
          The mutable to freeze.
      strict
          Whether to raise an error if sample context is not provided and not found.
      sample
          The context to freeze the mutable with.
      retries
          Control the number of retries in case :meth:`~nni.mutable.Mutable.robust_default` is called.
  
      Examples
      --------
      >>> with frozen_context({'a': 2}):
      ...     ensure_frozen(Categorical([1, 2, 3], label='a'))
      2
      >>> ensure_frozen(Categorical([1, 2, 3]), strict=False)
      1
      >>> ensure_frozen(Categorical([1, 2, 3], label='a'), sample={'a': 2}, strict=False)
      2
      >>> ensure_frozen('anything', strict=False)
      'anything'
      """
      if not isinstance(mutable, Mutable):
          return mutable
  
      # If we're in a frozen context, just use the current.
      if sample is None:
          ctx = frozen_context.current()
          if ctx is not None:
              sample = ctx
  
      if sample is not None:
          # If we have a sample, we can just use it.
          # Use freeze here to detect potential label mismatch errors.
          try:
              return mutable.freeze(sample)
          except:
              _logger.error(
                  "Failed to freeze mutable %s with sample %s. "
                  "In NAS, please make sure to have registered it via add_mutable(). "
                  "Otherwise, please make sure you are not inside a frozen_context.",
                  mutable,
                  sample,
              )
              raise
      else:
          if retries < 0 or (_ENSURE_FROZEN_STRICT and strict):
              raise RuntimeError(
                  f"No frozen context is found for {mutable!r}. Assuming no context. "
                  "If you are using NAS, you are probably using `ensure_frozen` in forward, or outside the init of ModelSpace. "
                  "Please avoid doing this as they will lead to erroneous results."
              )
  
          # TODO: Currently only mutable parameters in NAS evaluator end up here.
          # It might cause consistency issues between multiple parameters without context.
          # I don't want to throw a warning here, but there should be a smarter way to do this.
          return mutable.robust_default(retries=retries)
  
file_path: nni/nni/mutable/frozen.py
imports: from __future__ import annotations
  import logging
  from contextlib import contextmanager
  from typing import Any, Callable
  from .mutable import Mutable, Sample
  from .utils import NoContextError, ContextStack
label_desc: Use image node_id 1 for calling a global function with example usage: ensure_frozen(mutable) and returns: mutable, mutable, mutable