class_docstr: Base class for NAS strategies.
  
  To explore a space with a strategy, use::
  
      strategy = MyStrategy()
      strategy(model_space, engine)
  
  The strategy has a :meth:`run` method, that defines the process of exploring a NAS space.
  
  Strategy is stateful. It might store information of the current :meth:`initialize` and :meth:`run` as member attributes.
  We do not allow :meth:`run` a strategy twice with same, or different model spaces.
  
  Subclass should override :meth:`_initialize` and :meth:`_run`,
  as well as :meth:`state_dict` and :meth:`load_state_dict` for checkpointing.
class_docstr_tok: ["Base","class","for","NAS","strategies",".","To","explore","a","space","with","a","strategy",",","use",":",":","strategy","=","MyStrategy","(",")","strategy","(","model_space",",","engine",")","The","strategy","has","a",":","meth",":","`","run","`","method",",","that","defines","the","process","of","exploring","a","NAS","space",".","Strategy","is","stateful",".","It","might","store","information","of","the","current",":","meth",":","`","initialize","`","and",":","meth",":","`","run","`","as","member","attributes",".","We","do","not","allow",":","meth",":","`","run","`","a","strategy","twice","with","same",",","or","different","model","spaces",".","Subclass","should","override",":","meth",":","`","_initialize","`","and",":","meth",":","`","_run","`",",","as","well","as",":","meth",":","`","state_dict","`","and",":","meth",":","`","load_state_dict","`","for","checkpointing","."]
docstr: Explore the model space.
  
  This should be the main part of a NAS experiment.
  Strategies decide how to explore the model space.
  They can submit models to :attr:`engine` for training and evaluation.
  
  The strategy doesn't have to wait for all the models it submits to finish training.
  
  The caller of :meth:`run` is responsible of setting the :attr:`engine` and :attr:`model_space` before calling :meth:`run`.
  
  Subclass override :meth:`_run` instead of this method.
docstr_tok: ["Explore","the","model","space",".","This","should","be","the","main","part","of","a","NAS","experiment",".","Strategies","decide","how","to","explore","the","model","space",".","They","can","submit","models","to",":","attr",":","`","engine","`","for","training","and","evaluation",".","The","strategy","does","n't","have","to","wait","for","all","the","models","it","submits","to","finish","training",".","The","caller","of",":","meth",":","`","run","`","is","responsible","of","setting","the",":","attr",":","`","engine","`","and",":","attr",":","`","model_space","`","before","calling",":","meth",":","`","run","`",".","Subclass","override",":","meth",":","`","_run","`","instead","of","this","method","."]
code: def run(self) -> None:
      """Explore the model space.
  
      This should be the main part of a NAS experiment.
      Strategies decide how to explore the model space.
      They can submit models to :attr:`engine` for training and evaluation.
  
      The strategy doesn't have to wait for all the models it submits to finish training.
  
      The caller of :meth:`run` is responsible of setting the :attr:`engine` and :attr:`model_space` before calling :meth:`run`.
  
      Subclass override :meth:`_run` instead of this method.
      """
      try:
          if self._status == StrategyStatus.RUNNING:
              raise RuntimeError("Strategy is already running.")
  
          if self._status == StrategyStatus.INTERRUPTED:
              raise RuntimeError(
                  "Strategy is interrupted. Please resume by creating a new strategy and load_state_dict."
              )
  
          if self._status != StrategyStatus.INITIALIZED:
              raise RuntimeError("Strategy should not be called twice.")
  
          self._status = StrategyStatus.RUNNING
  
          # Explore the model space.
          self._run()
          # Strategy doesn't wait for the models it submitted.
  
          _logger.debug("Strategy has successfully finished.")
          self._status = StrategyStatus.SUCCEEDED
      except KeyboardInterrupt:
          _logger.warning("Strategy is interrupted.")
          self._status = StrategyStatus.INTERRUPTED
          raise
      except:
          _logger.error("Strategy failed to execute.")
          self._status = StrategyStatus.FAILED
          raise
      finally:
          try:
              self._cleanup()
          except:
              _logger.exception(
                  "Exception raised during strategy cleanup. Ignore."
              )
  
imports: from __future__ import annotations
  import logging
  import time
  from enum import Enum
  from typing import Iterator, cast
  from nni.nas.execution import ExecutionEngine
  from nni.nas.space import ExecutableModelSpace, ModelStatus
  from nni.typehint import TrialMetric
label_desc: Use image node_id 9 for calling the Strategy obj's underlying member method code with example usage: obj.run() without return types