class_docstr: A mutator that can be dry run.
  
  :class:`StationaryMutator` invoke :class:`StationaryMutator.dry_run` to predict choice candidates,
  such that the mutator simplifies to some static choices within `simplify()`.
  This could be convenient to certain algorithms which do not want to handle dynamic samplers.
class_docstr_tok: ["A","mutator","that","can","be","dry","run",".",":","class",":","`","StationaryMutator","`","invoke",":","class",":","`","StationaryMutator.dry_run","`","to","predict","choice","candidates",",","such","that","the","mutator","simplifies","to","some","static","choices","within","`","simplify","(",")","`",".","This","could","be","convenient","to","certain","algorithms","which","do","not","want","to","handle","dynamic","samplers","."]
docstr: Dry run mutator on a model to collect choice candidates.
  
  If you invoke this method multiple times on same or different models,
  it may or may not return identical results, depending on how the subclass implements `Mutator.mutate()`.
  
  Recommended to be used in :meth:`simplify` if the mutator is static.
code: def dry_run(
      self, model: GraphModelSpace
  ) -> tuple[dict[str, Categorical], GraphModelSpace]:
      """Dry run mutator on a model to collect choice candidates.
  
      If you invoke this method multiple times on same or different models,
      it may or may not return identical results, depending on how the subclass implements `Mutator.mutate()`.
  
      Recommended to be used in :meth:`simplify` if the mutator is static.
      """
      sampler_backup = self.sampler
      recorder = _RecorderSampler()
      self.sampler = recorder
      new_model = self.apply(model)
      self.sampler = sampler_backup
  
      # Local import to avoid name conflict.
      from nni.mutable.utils import label
  
      # NOTE: This is hacky. It fakes a label object by splitting the label string.
      _label = label(self.label.split("/"))
  
      if len(recorder.recorded_candidates) != 1:
          # If the mutator is applied multiple times on the model (e.g., applied to multiple nodes)
          # choices can created with a suffix to distinguish them.
  
          with label_scope(_label):
              choices = [
                  Categorical(candidates, label=str(i))
                  for i, candidates in enumerate(
                      recorder.recorded_candidates
                  )
              ]
      else:
          # Only one choice.
          choices = [
              Categorical(recorder.recorded_candidates[0], label=_label)
          ]
      return {c.label: c for c in choices}, new_model
  
imports: from __future__ import annotations
  from contextlib import contextmanager
  from typing import Any, Callable, Iterable, List, Optional, TYPE_CHECKING, Iterator
  from numpy.random import RandomState
  from nni.mutable import LabeledMutable, MutableList, MutableDict, Categorical, Mutable, SampleValidationError, Sample, SampleMissingError, label_scope, auto_label, frozen_context
  from .space import ModelStatus
label_desc: Use image node_id 5 for calling the StationaryMutator obj's underlying member method code with example usage: obj.dry_run(model) and returns: unknown,  new_model