Skip to content

Experiment

Repeated Experiment.

Source code in abses/experiment.py
def __init__(
    self,
    model_cls: Type[MainModel],
    nature_cls: Optional[Type[BaseNature]] = None,
    human_cls: Optional[Type[BaseHuman]] = None,
):
    self._n_runs = 0
    self._types: Dict[SubSystemType, Type] = {
        "model": model_cls,
        "nature": nature_cls or BaseNature,
        "human": human_cls or BaseHuman,
    }
    self._overrides: Dict[str, Any] = {}
    self._job_id: int = 0

model property

model

Model class.

outpath property

outpath

Output dir path.

overrides property writable

overrides

Overrides

job_id property

job_id

Job id. Each job means a combination of the configuration. If the experiment is running in Hydra, it will return the hydra's job id.

is_hydra_job staticmethod

is_hydra_job()

Returns True if the experiment is running in Hydra.

Source code in abses/experiment.py
@staticmethod
def is_hydra_job() -> bool:
    """Returns True if the experiment is running in Hydra."""
    return GlobalHydra().is_initialized()

run

run(cfg, repeat_id, outpath=None)

运行模型一次

Source code in abses/experiment.py
def run(
    self, cfg: DictConfig, repeat_id: int, outpath: Optional[Path] = None
) -> Tuple[Dict[str, Any], pd.DataFrame]:
    """运行模型一次"""
    cfg = self._update_log_config(cfg, repeat_id)
    # 获取日志
    model = self.model(
        parameters=cfg,
        run_id=repeat_id,
        outpath=outpath,
        experiment=self,
        nature_class=self._types["nature"],
        human_class=self._types["human"],
    )
    model.run_model()
    if model.datacollector.model_reporters:
        df = model.datacollector.get_model_vars_dataframe()
    else:
        df = pd.DataFrame()
    final_report = model.datacollector.get_final_vars_report(model)
    return final_report, df

batch_run

batch_run(cfg, repeats=None, parallels=None, display_progress=True, overrides=None)

Run the experiment multiple times.

Parameters:

Name Type Description Default
cfg Configurations

The configuration of the experiment. It can be either a string of the config file path, or a dictionary of the config. For an example: cfg='config.yaml' refers to the config file config.yaml saved in the current workspace. cfg={'exp': {'name': 'test', 'repeats': 2}} refers to the config dictionary.

required
repeats Optional[int]

The number of repeats for the experiment. If not specified, it will use the default value 1 (No repeats).

None
parallels Optional[int]

The number of processes running in parallel. If not specified, it will use the default value 1 (No parallel).

None
display_progress bool

Whether to display the progress bar, default True.

True
overrides Optional[Dict[str, str | Iterable[Number]]]

The dictionary of overrides for the experiment. If specified, the experiment will sweep all the possible values for the parameter. For examples: override = {model.key: ["cate1", "cate2"]} override = {nature.key: np.arange(10, 2)} The first override will lead to two different runs: - model.key = cate1 - model.key = cate2 The second override will lead to a series runs: - model.nature.key = 0.0 - model.nature.key = 2.0 - model.nature.key = 4.0 - model.nature.key = 6.0 - model.nature.key = 8.0

None
Example
# initialize the experiment.
exp = Experiment(MainModel)
# Loading the configuration file `config.yaml`.
exp.batch_run('config.yaml')
# A different way for initializing.
exp = Experiment.new(MainModel)
cfg = {'time': {'end': 25}}

# Nine runs with different ending ticks.
exp.batch_run(cfg=cfg, overrides={'time.end': range(10, 100, 10)})
Source code in abses/experiment.py
def batch_run(
    self,
    cfg: Configurations,
    repeats: Optional[int] = None,
    parallels: Optional[int] = None,
    display_progress: bool = True,
    overrides: Optional[Dict[str, str | Iterable[Number]]] = None,
) -> None:
    """Run the experiment multiple times.

    Parameters:
        cfg:
            The configuration of the experiment.
            It can be either a string of the config file path,
            or a dictionary of the config.
            For an example:
            `cfg='config.yaml'` refers to the config file `config.yaml` saved in the current workspace.
            `cfg={'exp': {'name': 'test', 'repeats': 2}}` refers to the config dictionary.
        repeats:
            The number of repeats for the experiment.
            If not specified, it will use the default value 1 (No repeats).
        parallels:
            The number of processes running in parallel.
            If not specified, it will use the default value 1 (No parallel).
        display_progress:
            Whether to display the progress bar, default True.
        overrides:
            The dictionary of overrides for the experiment.
            If specified, the experiment will sweep all the possible values for the parameter.
            For examples:
            override = {model.key: ["cate1", "cate2"]}
            override = {nature.key: np.arange(10, 2)}
            The first override will lead to two different runs:
            - model.key = cate1
            - model.key = cate2
            The second override will lead to a series runs:
            - model.nature.key = 0.0
            - model.nature.key = 2.0
            - model.nature.key = 4.0
            - model.nature.key = 6.0
            - model.nature.key = 8.0

    Example:
        ```Python
        # initialize the experiment.
        exp = Experiment(MainModel)
        # Loading the configuration file `config.yaml`.
        exp.batch_run('config.yaml')
        ```

        ```Python
        # A different way for initializing.
        exp = Experiment.new(MainModel)
        cfg = {'time': {'end': 25}}

        # Nine runs with different ending ticks.
        exp.batch_run(cfg=cfg, overrides={'time.end': range(10, 100, 10)})
        ```
    """
    # 如果配置是路径,则利用 Hydra API先清洗配置
    if self._is_config_path(cfg):
        config_path = self._parse_path(cast(str, cfg))
        cfg = self._load_hydra_cfg(config_path)
    # 加载配置
    repeats, parallels = self._update_config(cfg, repeats, parallels)
    # 如果没有指定覆写,则直接运行程序
    if not overrides:
        if parallels == 1 or repeats == 1:
            self._batch_run_repeats(cfg, repeats, display_progress)
        else:
            self._batch_run_multi_processes(
                cfg,
                repeats,
                parallels,
                display_progress,
            )
    # 否则,对每一个复写的配置进行重复运行
    for config, current_overrides in self._overriding_config(
        cfg, overrides
    ):
        self.overrides = current_overrides
        self.batch_run(
            cfg=config,
            repeats=repeats,
            parallels=parallels,
            display_progress=display_progress,
        )
        self._job_id += 1
    # finally, clean up the overrides now.
    self.overrides = {}

summary classmethod

summary(save=False, **kwargs)

Ending the experiment.

Source code in abses/experiment.py
@classmethod
def summary(cls, save: bool = False, **kwargs) -> None:
    """Ending the experiment."""
    df = pd.DataFrame(cls.final_vars)
    if save:
        df.to_csv(cls.folder / "summary.csv", index=False, **kwargs)
    return df

clean classmethod

clean(new_exp=False)

Clean the results.

Parameters:

Name Type Description Default
new_exp bool

Whether to create a new experiment. If True, it will delete all the current settings.

False
Source code in abses/experiment.py
@classmethod
def clean(cls, new_exp: bool = False) -> None:
    """Clean the results.

    Parameters:
        new_exp:
            Whether to create a new experiment.
            If True, it will delete all the current settings.
    """
    cls.final_vars = []
    cls.model_vars = []
    if new_exp:
        cls._instance = None
        cls.folder = Path(os.getcwd())
        cls.hydra_config = DictConfig({})
        cls.name = "ABSESpyExp"

new classmethod

new(model_cls)

Create a new experiment for the singleton class Experiment. This method will delete all currently available exp results and settings. Then, it initialize a new instance of experiment.

Parameters:

Name Type Description Default
model_cls Type[MainModel]

Using which model class to initialize the experiment.

required

Raises:

Type Description
TypeError

If the model class model_cls is not a valid ABSESpy model.

Returns:

Type Description
Experiment

An experiment.

Source code in abses/experiment.py
@classmethod
def new(cls, model_cls: Type[MainModel]) -> Experiment:
    """Create a new experiment for the singleton class `Experiment`.
    This method will delete all currently available exp results and settings.
    Then, it initialize a new instance of experiment.

    Parameters:
        model_cls:
            Using which model class to initialize the experiment.

    Raises:
        TypeError:
            If the model class `model_cls` is not a valid `ABSESpy` model.

    Returns:
        An experiment.
    """
    cls.clean(new_exp=True)
    return cls(model_cls=model_cls)

get_model_vars_dataframe classmethod

get_model_vars_dataframe()

Aggregation of model vars dataframe.

Source code in abses/experiment.py
@classmethod
def get_model_vars_dataframe(cls) -> pd.DataFrame:
    """Aggregation of model vars dataframe."""
    if cls.model_vars:
        return pd.concat(cls.model_vars, axis=0)
    raise ValueError("No model vars found.")