class_docstr: Represents an experiment with its trials and a store.
docstr: Runs the experiment. Typically done asynchronously.
  
  Args:
      trial_run_fn (FunctionType): This function is run for each trial (locally or remote). Make sure all imports and objects needed are defined within.
      trial_gen_fn (FunctionType): This function determines which trials are generated from the tasks found in store. Best to see documentation examples for usage.
      timeout (int, optional): Timeout in seconds for each trial run. Defaults to None.
      n_replicates (int, optional): Number of times to repeat a trial run. Defaults to 1.
      executor (Executor, optional): Executor responsible for running trials (local machine, remote docker container, etc). Defaults to None and will select local machine.
  
  Raises:
      TypeError: Invalid arguments may raise this.
  
  Returns:
      Executor: Either executor provided to call, or local machine executor.
docstr_tok: ["Runs","the","experiment",".","Typically","done","asynchronously",".","Args",":","trial_run_fn","(","FunctionType",")",":","This","function","is","run","for","each","trial","(","locally","or","remote",")",".","Make","sure","all","imports","and","objects","needed","are","defined","within",".","trial_gen_fn","(","FunctionType",")",":","This","function","determines","which","trials","are","generated","from","the","tasks","found","in","store",".","Best","to","see","documentation","examples","for","usage",".","timeout","(","int",",","optional",")",":","Timeout","in","seconds","for","each","trial","run",".","Defaults","to","None",".","n_replicates","(","int",",","optional",")",":","Number","of","times","to","repeat","a","trial","run",".","Defaults","to","1.","executor","(","Executor",",","optional",")",":","Executor","responsible","for","running","trials","(","local","machine",",","remote","docker","container",",","etc",")",".","Defaults","to","None","and","will","select","local","machine",".","Raises",":","TypeError",":","Invalid","arguments","may","raise","this",".","Returns",":","Executor",":","Either","executor","provided","to","call",",","or","local","machine","executor","."]
code: def run(
      self,
      trial_run_fn: FunctionType,
      trial_gen_fn: FunctionType,
      timeout: int = None,
      n_replicates: int = 1,
      executor: Executor = None,
  ) -> Executor:
      """Runs the experiment. Typically done asynchronously.
  
      Args:
          trial_run_fn (FunctionType): This function is run for each trial (locally or remote). Make sure all imports and objects needed are defined within.
          trial_gen_fn (FunctionType): This function determines which trials are generated from the tasks found in store. Best to see documentation examples for usage.
          timeout (int, optional): Timeout in seconds for each trial run. Defaults to None.
          n_replicates (int, optional): Number of times to repeat a trial run. Defaults to 1.
          executor (Executor, optional): Executor responsible for running trials (local machine, remote docker container, etc). Defaults to None and will select local machine.
  
      Raises:
          TypeError: Invalid arguments may raise this.
  
      Returns:
          Executor: Either executor provided to call, or local machine executor.
      """
      # Create experiment if needed
      if self._id is None:
          self._id, _ = self._store.get_or_create_experiment(
              self._name, self._description
          )
  
      # Create trials
      trial_params = []
      for task in self._store.iter_tasks():
          generated_trials = trial_gen_fn(task)
          for generated_trial in generated_trials:
              if isinstance(generated_trial, tuple):
                  # Response: (method, meta)
                  method = generated_trial[0]
                  meta = generated_trial[1]
              else:
                  # Response: method
                  method = generated_trial
                  meta = {}
              if isinstance(method, str):
                  method = Method.from_name(method)
              elif isinstance(method, Method):
                  pass
              else:
                  raise TypeError(
                      f"Cannot handle method type: {type(method)}"
                  )
              method_id, _ = self._store.get_or_create_method(
                  method.name,
                  method.description,
                  method.version,
                  method.params,
                  method.env,
              )
              method = Method(
                  method_id,
                  method.name,
                  method.description,
                  method.version,
                  method.params,
                  method.env,
              )
  
              for replicate_num in range(n_replicates):
                  trial_param = {
                      "experiment_id": self.id,
                      "task_id": task.id,
                      "method_id": method.id,
                      "replicate_num": replicate_num,
                      "meta": meta,
                  }
                  trial_params.append(trial_param)
                  self._trials.append(
                      Trial(
                          None,
                          self,
                          task,
                          method,
                          replicate_num,
                          meta,
                          [],
                      )
                  )
  
      # Save to store
      trial_ids = self._store.create_trials(trial_params)
      for _id, trial in zip(trial_ids, self._trials):
          trial._id = _id
  
      # Run trials
      if executor is None:
          executor = LocalMachine(self._store)
      executor.submit(trial_run_fn, self._trials, timeout=timeout)
      return executor
  
imports: import random
  from types import FunctionType
  import pandas
  from typing import Dict, Iterable
  from typing import Type, TypeVar
  from powerlift.bench.store import Store
  from typing import Union, Optional, List
  from dataclasses import dataclass
  from numbers import Number
  from powerlift.executors.base import Executor
  from powerlift.executors import LocalMachine
label_desc: Use image node_id 7 for calling the Experiment obj's underlying member method code with example usage: obj.run(trial_run_fn, trial_gen_fn, timeout, n_replicates, executor) and returns: executor