From 6ad705359fd65aedcc12a68eb38bb047c7d524d9 Mon Sep 17 00:00:00 2001 From: faux66 Date: Tue, 7 Oct 2025 15:27:04 +0300 Subject: [PATCH 01/17] fix: remove unused flake8 im pre-commit --- .pre-commit-config.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c135076..6516923 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,12 +1,6 @@ # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks repos: - - repo: https://github.com/pycqa/flake8 - rev: "7.1.1" - hooks: - - id: flake8 - additional_dependencies: [Flake8-pyproject] - # stages: [push] - repo: https://github.com/pre-commit/mirrors-mypy rev: "v1.13.0" From 9646113fc615e8c8d9a0fad3e8144e0bb4d86f2d Mon Sep 17 00:00:00 2001 From: faux66 Date: Tue, 7 Oct 2025 20:02:27 +0300 Subject: [PATCH 02/17] refactor: cli validation in configure commands --- .../configure/executor_type/executor_type.py | 30 +++++++++++---- .../experiment_type/experiment_type.py | 33 +++++++++++----- .../generator_type/generator_type.py | 29 +++++++++++--- .../configure/hypothesis/hypothesis.py | 38 +++++++++++++------ .../report_builder_type.py | 28 +++++++++++--- .../configure/report_mode/report_mode.py | 32 ++++++++++------ .../commands/configure/run_mode/run_mode.py | 30 ++++++++++----- .../cli/commands/create/create.py | 2 +- 8 files changed, 158 insertions(+), 64 deletions(-) diff --git a/pysatl_experiment/cli/commands/configure/executor_type/executor_type.py b/pysatl_experiment/cli/commands/configure/executor_type/executor_type.py index d83a3e0..8b19c5a 100644 --- a/pysatl_experiment/cli/commands/configure/executor_type/executor_type.py +++ b/pysatl_experiment/cli/commands/configure/executor_type/executor_type.py @@ -1,8 +1,8 @@ -from click import Context, argument, echo, pass_context +from click import BadParameter, Context, argument, echo, pass_context from pysatl_experiment.cli.commands.common.common import get_experiment_name_and_config, save_experiment_config from pysatl_experiment.cli.commands.configure.configure import configure -from pysatl_experiment.validation.cli.commands.configure.step_type.step_type import validate_step_type +from pysatl_experiment.configuration.model.step_type.step_type import StepType @configure.command() @@ -10,13 +10,27 @@ @pass_context def executor_type(ctx: Context, exec_type: str) -> None: """ - Configure experiment executor type. - - :param ctx: context. - :param exec_type: executor type. + Set the executor type for the current experiment. + + This command configures which executor will be used for the experiment's + execution step. The type must be one of the predefined values in `StepType`. + It updates the experiment's configuration file with the provided value. + + Example: + experiment configure EXPERIMENT_NAME executor-type standard + Args: + ctx: The Click context object, passed automatically. + exec_type: The desired executor type (e.g., 'standard'). The value is + case-insensitive. """ - - validate_step_type(exec_type, "executor") + try: + validated_step = StepType(exec_type.lower()) + except ValueError: + valid_options = [e.value for e in StepType] + raise BadParameter(f"Type of '{exec_type}' is not valid.\nPossible values are: {valid_options}.") + + if validated_step == StepType.CUSTOM: + raise BadParameter("Custom type is not supported yet.\nPlease, choose standard one") experiment_name, experiment_config = get_experiment_name_and_config(ctx) diff --git a/pysatl_experiment/cli/commands/configure/experiment_type/experiment_type.py b/pysatl_experiment/cli/commands/configure/experiment_type/experiment_type.py index d9e46a2..d785803 100644 --- a/pysatl_experiment/cli/commands/configure/experiment_type/experiment_type.py +++ b/pysatl_experiment/cli/commands/configure/experiment_type/experiment_type.py @@ -1,8 +1,8 @@ -from click import Context, argument, echo, pass_context +from click import BadParameter, Context, argument, echo, pass_context from pysatl_experiment.cli.commands.common.common import get_experiment_name_and_config, save_experiment_config from pysatl_experiment.cli.commands.configure.configure import configure -from pysatl_experiment.validation.cli.commands.configure.experiment_type.experiment_type import validate_experiment_type +from pysatl_experiment.configuration.model.experiment_type.experiment_type import ExperimentType @configure.command() @@ -10,19 +10,32 @@ @pass_context def experiment_type(ctx: Context, exp_type: str) -> None: """ - Configure experiment type. + Set the type for the current experiment. - :param ctx: context. - :param exp_type: experiment type. - """ + This command configures the main objective of the experiment, such as + 'power' for power analysis or 'critical_value' for calculating critical + values. The chosen type affects which other configuration parameters are + valid and required. - validate_experiment_type(exp_type) + Example: + experiment configure MyPowerAnalysis experiment-type power + Args: + ctx: The Click context object, passed automatically. + exp_type: The desired experiment type (e.g., 'power', 'time_complexity'). + The value must match one of the predefined types in `ExperimentType` + and is case-insensitive. + """ experiment_name, experiment_config = get_experiment_name_and_config(ctx) - exp_type_lower = exp_type.lower() - experiment_config["experiment_type"] = exp_type_lower + try: + validated_experiment_type = ExperimentType(exp_type.lower()) + except ValueError: + valid_options = [e.value for e in ExperimentType] + raise BadParameter(f"Type of '{exp_type}' is not valid.\nPossible values are: {valid_options}.") + + experiment_config["experiment_type"] = validated_experiment_type.value save_experiment_config(ctx, experiment_name, experiment_config) - echo(f"Type of the experiment '{experiment_name}' is set to '{exp_type_lower}'.") + echo(f"Type of the experiment '{experiment_name}' is set to '{validated_experiment_type.value}'.") diff --git a/pysatl_experiment/cli/commands/configure/generator_type/generator_type.py b/pysatl_experiment/cli/commands/configure/generator_type/generator_type.py index 03f657f..b0a366e 100644 --- a/pysatl_experiment/cli/commands/configure/generator_type/generator_type.py +++ b/pysatl_experiment/cli/commands/configure/generator_type/generator_type.py @@ -1,8 +1,8 @@ -from click import Context, argument, echo, pass_context +from click import BadParameter, Context, argument, echo, pass_context from pysatl_experiment.cli.commands.common.common import get_experiment_name_and_config, save_experiment_config from pysatl_experiment.cli.commands.configure.configure import configure -from pysatl_experiment.validation.cli.commands.configure.step_type.step_type import validate_step_type +from pysatl_experiment.configuration.model.step_type.step_type import StepType @configure.command() @@ -10,13 +10,30 @@ @pass_context def generator_type(ctx: Context, gen_type: str) -> None: """ - Configure experiment generator type. + Set the generator type for the current experiment. - :param ctx: context. - :param gen_type: generator type. + This command configures which data generator will be used to create the + datasets for the experiment. The type must be one of the predefined values + in `StepType`. It updates the experiment's configuration file with the + selected type. + + Example: + experiment configure MySimulation generator-type standard + + Args: + ctx: The Click context object, passed automatically. + gen_type: The desired generator type (e.g., 'standard'). The value is + case-insensitive. """ - validate_step_type(gen_type, "generator") + try: + validated_step = StepType(gen_type.lower()) + except ValueError: + valid_options = [e.value for e in StepType] + raise BadParameter(f"Type of '{gen_type}' is not valid.\nPossible values are: {valid_options}.") + + if validated_step == StepType.CUSTOM: + raise BadParameter("Custom type is not supported yet.\nPlease, choose standard one") experiment_name, experiment_config = get_experiment_name_and_config(ctx) diff --git a/pysatl_experiment/cli/commands/configure/hypothesis/hypothesis.py b/pysatl_experiment/cli/commands/configure/hypothesis/hypothesis.py index 7683a0b..fdf7090 100644 --- a/pysatl_experiment/cli/commands/configure/hypothesis/hypothesis.py +++ b/pysatl_experiment/cli/commands/configure/hypothesis/hypothesis.py @@ -1,4 +1,4 @@ -from click import Context, argument, echo, pass_context +from click import BadParameter, Context, argument, echo, pass_context from pysatl_experiment.cli.commands.common.common import ( criteria_from_codes, @@ -7,7 +7,7 @@ save_experiment_config, ) from pysatl_experiment.cli.commands.configure.configure import configure -from pysatl_experiment.validation.cli.commands.configure.hypothesis.hypothesis import validate_hypothesis +from pysatl_experiment.configuration.model.hypothesis.hypothesis import Hypothesis @configure.command() @@ -15,26 +15,40 @@ @pass_context def hypothesis(ctx: Context, hyp: str) -> None: """ - Configure experiment hypothesis. + Set the statistical hypothesis for the current experiment. - :param ctx: context. - :param hyp: hypothesis. - """ + This command configures the main statistical hypothesis to be tested, + such as 'normal'. + + IMPORTANT: Setting a hypothesis will automatically overwrite the existing + list of criteria with all criteria compatible with that hypothesis. - validate_hypothesis(hyp) - hyp_lower = hyp.lower() + Example: + experiment configure MyNormalTest hypothesis normal + Args: + ctx: The Click context object, passed automatically. + hyp: The desired hypothesis (e.g., 'normal'). The value must + match one of the predefined types in `Hypothesis` and is + case-insensitive. + """ experiment_name, experiment_config = get_experiment_name_and_config(ctx) - experiment_config["hypothesis"] = hyp_lower + try: + validated_hypothesis = Hypothesis(hyp.lower()) + except ValueError: + valid_options = [e.value for e in Hypothesis] + raise BadParameter(f"Type of '{hyp}' is not valid.\nPossible values are: {valid_options}.") + + experiment_config["hypothesis"] = validated_hypothesis.value - criteria_for_hypothesis = get_statistics_short_codes_for_hypothesis(hyp_lower) + criteria_for_hypothesis = get_statistics_short_codes_for_hypothesis(validated_hypothesis.value) criteria_data = criteria_from_codes(criteria_for_hypothesis) experiment_config["criteria"] = criteria_data save_experiment_config(ctx, experiment_name, experiment_config) echo( - f"Hypothesis of the experiment '{experiment_name}' is set to '{hyp_lower}'.\n" - f"Likewise, all criteria for the hypothesis '{hyp_lower}' are set." + f"Hypothesis of the experiment '{experiment_name}' is set to '{validated_hypothesis}'.\n" + f"Likewise, all criteria for the hypothesis '{validated_hypothesis.value}' are set." ) diff --git a/pysatl_experiment/cli/commands/configure/report_builder_type/report_builder_type.py b/pysatl_experiment/cli/commands/configure/report_builder_type/report_builder_type.py index 4edab83..e7296f6 100644 --- a/pysatl_experiment/cli/commands/configure/report_builder_type/report_builder_type.py +++ b/pysatl_experiment/cli/commands/configure/report_builder_type/report_builder_type.py @@ -1,8 +1,8 @@ -from click import Context, argument, echo, pass_context +from click import BadParameter, Context, argument, echo, pass_context from pysatl_experiment.cli.commands.common.common import get_experiment_name_and_config, save_experiment_config from pysatl_experiment.cli.commands.configure.configure import configure -from pysatl_experiment.validation.cli.commands.configure.step_type.step_type import validate_step_type +from pysatl_experiment.configuration.model.step_type.step_type import StepType @configure.command() @@ -10,13 +10,29 @@ @pass_context def report_builder_type(ctx: Context, report_build_type: str) -> None: """ - Configure experiment report builder type. + Set the report builder type for the current experiment. - :param ctx: context. - :param report_build_type: report builder type. + This command configures which report builder will be used to generate the + final output and artifacts of the experiment. The type must be one of the + predefined values in `StepType`. + + Example: + experiment configure MyReportTest report-builder-type standard + + Args: + ctx: The Click context object, passed automatically. + report_build_type: The desired report builder type (e.g., 'standard'). + The value is case-insensitive. """ - validate_step_type(report_build_type, "report builder") + try: + validated_step = StepType(report_build_type.lower()) + except ValueError: + valid_options = [e.value for e in StepType] + raise BadParameter(f"Type of '{report_build_type}' is not valid.\nPossible values are: {valid_options}.") + + if validated_step == StepType.CUSTOM: + raise BadParameter("Custom type is not supported yet.\nPlease, choose standard one") experiment_name, experiment_config = get_experiment_name_and_config(ctx) diff --git a/pysatl_experiment/cli/commands/configure/report_mode/report_mode.py b/pysatl_experiment/cli/commands/configure/report_mode/report_mode.py index 6328bef..de9c7cd 100644 --- a/pysatl_experiment/cli/commands/configure/report_mode/report_mode.py +++ b/pysatl_experiment/cli/commands/configure/report_mode/report_mode.py @@ -1,28 +1,38 @@ -from click import Context, argument, echo, pass_context +from click import BadParameter, Context, argument, echo, pass_context from pysatl_experiment.cli.commands.common.common import get_experiment_name_and_config, save_experiment_config from pysatl_experiment.cli.commands.configure.configure import configure -from pysatl_experiment.validation.cli.commands.configure.report_mode.report_mode import validate_report_mode +from pysatl_experiment.configuration.model.report_mode.report_mode import ReportMode @configure.command() @argument("mode") @pass_context def report_mode(ctx: Context, mode: str) -> None: - """ - Configure experiment report mode. + """Set the report generation mode for the current experiment. - :param ctx: context. - :param mode: report mode. - """ + This command configures the style of the final report. + The mode must be one of the predefined values in `ReportMode`. - validate_report_mode(mode) - mode_lower = mode.lower() + Example: + experiment configure MyAnalysis report-mode with-chart + + Args: + ctx: The Click context object, passed automatically. + mode: The desired report mode (e.g., 'standard'). The value is + case-insensitive. + """ experiment_name, experiment_config = get_experiment_name_and_config(ctx) - experiment_config["report_mode"] = mode_lower + try: + validated_report_mode = ReportMode(mode.lower()) + except ValueError: + valid_options = [e.value for e in ReportMode] + raise BadParameter(f"Type of '{mode}' is not valid.\nPossible values are: {valid_options}.") + + experiment_config["report_mode"] = validated_report_mode.value save_experiment_config(ctx, experiment_name, experiment_config) - echo(f"Report mode of the experiment '{experiment_name}' is set to '{mode_lower}'.") + echo(f"Report mode of the experiment '{experiment_name}' is set to '{validated_report_mode.value}'.") diff --git a/pysatl_experiment/cli/commands/configure/run_mode/run_mode.py b/pysatl_experiment/cli/commands/configure/run_mode/run_mode.py index ed06214..3e6a923 100644 --- a/pysatl_experiment/cli/commands/configure/run_mode/run_mode.py +++ b/pysatl_experiment/cli/commands/configure/run_mode/run_mode.py @@ -1,8 +1,8 @@ -from click import Context, argument, echo, pass_context +from click import BadParameter, Context, argument, echo, pass_context from pysatl_experiment.cli.commands.common.common import get_experiment_name_and_config, save_experiment_config from pysatl_experiment.cli.commands.configure.configure import configure -from pysatl_experiment.validation.cli.commands.configure.run_mode.run_mode import validate_run_mode +from pysatl_experiment.configuration.model.run_mode.run_mode import RunMode @configure.command() @@ -10,19 +10,29 @@ @pass_context def run_mode(ctx: Context, mode: str) -> None: """ - Configure experiment run mode. + Defines the behavior for handling pre-existing experiment data. - :param ctx: context. - :param mode: run mode. - """ + This enumeration controls whether an experiment should use previously + generated or executed data found in the database or start fresh by + overwriting any existing results for the same configuration. - validate_run_mode(mode) - mode_lower = mode.lower() + Example: + experiment configure MyLocalRun run-mode reuse + Args: + ctx: The Click context object, passed automatically. + mode: The desired run mode (e.g., 'reuse'). The value is + case-insensitive. + """ experiment_name, experiment_config = get_experiment_name_and_config(ctx) - experiment_config["run_mode"] = mode_lower + try: + validated_run_mode = RunMode(mode.lower()) + except ValueError: + valid_options = [e.value for e in RunMode] + raise BadParameter(f"Type of '{mode}' is not valid.\nPossible values are: {valid_options}.") + experiment_config["run_mode"] = validated_run_mode.value save_experiment_config(ctx, experiment_name, experiment_config) - echo(f"Run mode of the experiment '{experiment_name}' is set to '{mode_lower}'.") + echo(f"Run mode of the experiment '{experiment_name}' is set to '{validated_run_mode.value}'.") diff --git a/pysatl_experiment/cli/commands/create/create.py b/pysatl_experiment/cli/commands/create/create.py index 4b2c680..27deeec 100644 --- a/pysatl_experiment/cli/commands/create/create.py +++ b/pysatl_experiment/cli/commands/create/create.py @@ -30,4 +30,4 @@ def create(name: str) -> None: save_experiment_data(name, experiment_data) - echo(f"Experiment with name {name} was created successfully.") + echo(f"Experiment with name '{name}' was created successfully.") From 6d2485da440dc068e50dbe854cc27fa7ca2e6a92 Mon Sep 17 00:00:00 2001 From: faux66 Date: Tue, 7 Oct 2025 20:23:43 +0300 Subject: [PATCH 03/17] feat: move validation to pydantic --- pyproject.toml | 1 + .../commands/build_and_run/build_and_run.py | 27 +- .../commands/configure/criteria/criteria.py | 40 ++- pysatl_experiment/validation/cli/__init__.py | 0 .../build_and_run/build_and_run_new.py | 259 ++++++++++++++++++ .../commands/configure/criteria/criteria.py | 2 +- .../validation/cli/schemas/__init__.py | 0 .../validation/cli/schemas/alternative.py | 99 +++++++ .../validation/cli/schemas/criteria.py | 67 +++++ .../validation/cli/schemas/experiment.py | 167 +++++++++++ 10 files changed, 628 insertions(+), 34 deletions(-) create mode 100644 pysatl_experiment/validation/cli/__init__.py create mode 100644 pysatl_experiment/validation/cli/commands/build_and_run/build_and_run_new.py create mode 100644 pysatl_experiment/validation/cli/schemas/__init__.py create mode 100644 pysatl_experiment/validation/cli/schemas/alternative.py create mode 100644 pysatl_experiment/validation/cli/schemas/criteria.py create mode 100644 pysatl_experiment/validation/cli/schemas/experiment.py diff --git a/pyproject.toml b/pyproject.toml index 167b138..01ccd24 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,6 +25,7 @@ rich = "==13.9.4" click = ">=8.2.1" dacite = "==1.9.2" line_profiler = "5.0.0" +pydantic = "^2.11.9" pysatl-criterion = {path = "./pysatl_criterion"} [tool.poetry.group.dev.dependencies] diff --git a/pysatl_experiment/cli/commands/build_and_run/build_and_run.py b/pysatl_experiment/cli/commands/build_and_run/build_and_run.py index b8a9e64..b083090 100644 --- a/pysatl_experiment/cli/commands/build_and_run/build_and_run.py +++ b/pysatl_experiment/cli/commands/build_and_run/build_and_run.py @@ -1,14 +1,13 @@ from click import BadParameter, argument, command -from pysatl_experiment.cli.commands.common.common import get_experiment_config, read_experiment_data -from pysatl_experiment.configuration.experiment_config.experiment_config import ExperimentConfig +from pysatl_experiment.cli.commands.common.common import read_experiment_data from pysatl_experiment.configuration.experiment_data.experiment_data import ExperimentData from pysatl_experiment.experiment_new.experiment.experiment import Experiment from pysatl_experiment.experiment_new.experiment_steps.experiment_steps import ExperimentSteps from pysatl_experiment.factory.critical_value.critical_value import CriticalValueExperimentFactory from pysatl_experiment.factory.power.power import PowerExperimentFactory from pysatl_experiment.factory.time_complexity.time_complexity import TimeComplexityExperimentFactory -from pysatl_experiment.validation.cli.commands.build_and_run.build_and_run import validate_build_and_run +from pysatl_experiment.validation.cli.commands.build_and_run.build_and_run_new import validate_build_and_run from pysatl_experiment.validation.cli.commands.common.common import if_experiment_exists @@ -20,42 +19,34 @@ def build_and_run(name: str) -> None: :param name: name of the experiment. """ - experiment_exists = if_experiment_exists(name) if not experiment_exists: raise BadParameter(f"Experiment with name {name} does not exists.") experiment_data_dict = read_experiment_data(name) - experiment_config = get_experiment_config(experiment_data_dict) - experiment_data = validate_build_and_run(experiment_data_dict) - - experiment_type = experiment_config["experiment_type"] - - experiment_steps = _build_experiment(experiment_data, experiment_type) + experiment_steps = _build_experiment(experiment_data) experiment = Experiment(experiment_steps) - experiment.run_experiment() -def _build_experiment(experiment_data: ExperimentData[ExperimentConfig], experiment_type: str) -> ExperimentSteps: +def _build_experiment(experiment_data: ExperimentData) -> ExperimentSteps: """ - Build experiment. - - :param experiment_data: experiment data. - :param experiment_type: experiment type. + Build experiment from validated ExperimentData object. + :param experiment_data: validated experiment data. :return: experiment steps. """ - experiment_type_to_factory = { "power": PowerExperimentFactory, "critical_value": CriticalValueExperimentFactory, "time_complexity": TimeComplexityExperimentFactory, } - experiment_factory = experiment_type_to_factory[experiment_type] + experiment_type_str = experiment_data.config.experiment_type.value + + experiment_factory = experiment_type_to_factory[experiment_type_str] experiment_steps = experiment_factory(experiment_data).create_experiment_steps() diff --git a/pysatl_experiment/cli/commands/configure/criteria/criteria.py b/pysatl_experiment/cli/commands/configure/criteria/criteria.py index e6be792..cf95cb8 100644 --- a/pysatl_experiment/cli/commands/configure/criteria/criteria.py +++ b/pysatl_experiment/cli/commands/configure/criteria/criteria.py @@ -1,25 +1,24 @@ -from click import ClickException, Context, argument, echo, pass_context +from click import BadParameter, ClickException, Context, argument, echo, pass_context +from pydantic import ValidationError -from pysatl_experiment.cli.commands.common.common import ( - criteria_from_codes, - get_experiment_name_and_config, - save_experiment_config, -) +from pysatl_experiment.cli.commands.common.common import get_experiment_name_and_config, save_experiment_config from pysatl_experiment.cli.commands.configure.configure import configure -from pysatl_experiment.validation.cli.commands.configure.criteria.criteria import validate_criteria +from pysatl_experiment.validation.cli.schemas.criteria import CriteriaConfig @configure.command() -@argument("criteria_codes", nargs=-1) +@argument("criteria_codes", nargs=-1, required=True) @pass_context def criteria(ctx: Context, criteria_codes: tuple[str, ...]) -> None: """ Configure experiment criteria. + Validates that the provided criteria are compatible with the + already configured experiment hypothesis. + :param ctx: context. - :param criteria_codes: criteria codes. + :param criteria_codes: A list of criteria short codes (e.g., "KS", "AD"). """ - experiment_name, experiment_config = get_experiment_name_and_config(ctx) experiment_hypothesis = experiment_config.get("hypothesis") @@ -30,13 +29,24 @@ def criteria(ctx: Context, criteria_codes: tuple[str, ...]) -> None: f"'experiment configure {experiment_name} hypothesis '." ) - criteria_codes_upper = [code.upper() for code in criteria_codes] - validate_criteria(criteria_codes_upper, experiment_hypothesis) + criteria_as_dicts = [{"criterion_code": code} for code in criteria_codes] + data_to_validate = { + "hypothesis": experiment_hypothesis, + "criteria": criteria_as_dicts, + } + + try: + config = CriteriaConfig.model_validate(data_to_validate) - criteria_data = criteria_from_codes(criteria_codes_upper) + except ValidationError as e: + error_messages = [error["msg"] for error in e.errors()] + combined_message = "\n".join(error_messages) + raise BadParameter(combined_message) - experiment_config["criteria"] = criteria_data + validated_criteria_list = [c.model_dump() for c in config.criteria] + experiment_config["criteria"] = validated_criteria_list save_experiment_config(ctx, experiment_name, experiment_config) - echo(f"Criteria of the experiment '{experiment_name}' are set to {criteria_codes_upper}.") + validated_codes = [c.criterion_code for c in config.criteria] + echo(f"Criteria for experiment '{experiment_name}' successfully set: {validated_codes}.") diff --git a/pysatl_experiment/validation/cli/__init__.py b/pysatl_experiment/validation/cli/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run_new.py b/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run_new.py new file mode 100644 index 0000000..6cc4cf4 --- /dev/null +++ b/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run_new.py @@ -0,0 +1,259 @@ +from enum import Enum +from typing import cast + +from click import ClickException +from dacite import Config, from_dict +from pydantic import ValidationError + +from pysatl_experiment.cli.commands.common.common import create_result_path +from pysatl_experiment.configuration.experiment_config.critical_value.critical_value import ( + CriticalValueExperimentConfig as LegacyCriticalValueExperimentConfig, +) +from pysatl_experiment.configuration.experiment_config.experiment_config import ExperimentConfig +from pysatl_experiment.configuration.experiment_config.power.power import ( + PowerExperimentConfig as LegacyPowerExperimentConfig, +) +from pysatl_experiment.configuration.experiment_config.time_complexity.time_complexity import ( + TimeComplexityExperimentConfig as LegacyTimeComplexityExperimentConfig, +) +from pysatl_experiment.configuration.experiment_data.common.steps_done.steps_done import StepsDone +from pysatl_experiment.configuration.experiment_data.experiment_data import ExperimentData +from pysatl_experiment.configuration.model.experiment_type.experiment_type import ExperimentType +from pysatl_experiment.configuration.model.hypothesis.hypothesis import Hypothesis +from pysatl_experiment.configuration.model.run_mode.run_mode import RunMode +from pysatl_experiment.configuration.model.step_type.step_type import StepType +from pysatl_experiment.persistence.experiment.sqlite.sqlite import SQLiteExperimentStorage +from pysatl_experiment.persistence.model.experiment.experiment import ( + ExperimentModel, + ExperimentQuery, + IExperimentStorage, +) +from pysatl_experiment.validation.cli.schemas.experiment import BaseExperimentConfig as PydanticBaseExperiment +from pysatl_experiment.validation.cli.schemas.experiment import CriticalValueConfig as PydanticCriticalValueConfig +from pysatl_experiment.validation.cli.schemas.experiment import ExperimentConfig as ExperimentInputSchema +from pysatl_experiment.validation.cli.schemas.experiment import PowerConfig as PydanticPowerConfig +from pysatl_experiment.validation.cli.schemas.experiment import TimeComplexityConfig as PydanticTimeComplexityConfig + + +def validate_build_and_run(experiment_data_dict: dict) -> ExperimentData: + """ + Validates input, initializes, and builds the experiment data object. + + This function performs the following steps: + 1. Validates the raw input dictionary against Pydantic schemas. + 2. Adapts the modern Pydantic models to legacy dataclass configurations. + 3. Initializes the SQLite storage backend. + 4. Checks if an identical experiment already exists in storage to resume it. + 5. If not, it saves the new experiment configuration. + 6. Creates a results path for experiment artifacts. + 7. Returns a complete `ExperimentData` object to be used by the runner. + + Args: + experiment_data_dict: A dictionary containing the raw experiment configuration. + + Raises: + ClickException: If validation fails or if the experiment has already + been completed. + + Returns: + An `ExperimentData` object ready for the experiment execution pipeline. + """ + try: + validated_data = ExperimentInputSchema.model_validate(experiment_data_dict) + except ValidationError as e: + raise ClickException(str(e)) + + experiment_name = validated_data.name + pydantic_config = validated_data.config + + legacy_dataclass_config = _adapt_pydantic_to_dataclass(pydantic_config) + steps_done = StepsDone( + is_generation_step_done=False, + is_execution_step_done=False, + is_report_building_step_done=False, + ) + + experiment_storage = SQLiteExperimentStorage(legacy_dataclass_config.storage_connection) + experiment_storage.init() + + experiment_config_from_storage = _get_experiment_config_from_storage( + config=legacy_dataclass_config, + storage=experiment_storage, + ) + if experiment_config_from_storage is not None: + steps_done = _check_if_experiment_finished(experiment_config_from_storage) + else: + _save_experiment_config_to_storage( + config=legacy_dataclass_config, + storage=experiment_storage, + ) + + result_path = create_result_path() + + experiment_data = ExperimentData( + name=experiment_name, + config=legacy_dataclass_config, + steps_done=steps_done, + results_path=result_path, + ) + + return experiment_data + + +def _get_experiment_config_from_storage( + config: ExperimentConfig, storage: IExperimentStorage +) -> ExperimentModel | None: + """ + Get experiment config from database. + + :param config: experiment config dataclass. + + :return: experiment config from db. + """ + + experiment_type = config.experiment_type + criteria = {criterion.criterion_code: criterion.parameters for criterion in config.criteria} + + significance_levels = [] + alternatives = {} + if experiment_type == ExperimentType.CRITICAL_VALUE: + critical_value_config = cast(LegacyCriticalValueExperimentConfig, config) + significance_levels = critical_value_config.significance_levels + elif experiment_type == ExperimentType.POWER: + power_config = cast(LegacyPowerExperimentConfig, config) + significance_levels = power_config.significance_levels + alternatives = {alternative.generator_name: alternative.parameters for alternative in power_config.alternatives} + + query = ExperimentQuery( + experiment_type=experiment_type.value, + storage_connection=config.storage_connection, + run_mode=config.run_mode.value, + report_mode=config.report_mode.value, + hypothesis=config.hypothesis.value, + generator_type=config.generator_type.value, + executor_type=config.executor_type.value, + report_builder_type=config.report_builder_type.value, + sample_sizes=config.sample_sizes, + monte_carlo_count=config.monte_carlo_count, + criteria=criteria, + significance_levels=significance_levels, + alternatives=alternatives, + ) + + experiment_config_from_db = storage.get_data(query) + + return experiment_config_from_db + + +def _save_experiment_config_to_storage(config: ExperimentConfig, storage: IExperimentStorage) -> None: + """ + Save experiment config to database. + + :param config: experiment config dataclass. + :param storage: experiment storage. + """ + + experiment_type = config.experiment_type + criteria = {criterion.criterion_code: criterion.parameters for criterion in config.criteria} + + significance_levels = [] + alternatives = {} + if experiment_type == ExperimentType.CRITICAL_VALUE: + critical_value_config = cast(LegacyCriticalValueExperimentConfig, config) + significance_levels = critical_value_config.significance_levels + elif experiment_type == ExperimentType.POWER: + power_config = cast(LegacyPowerExperimentConfig, config) + significance_levels = power_config.significance_levels + alternatives = {alternative.generator_name: alternative.parameters for alternative in power_config.alternatives} + + query = ExperimentModel( + experiment_type=experiment_type.value, + storage_connection=config.storage_connection, + run_mode=config.run_mode.value, + report_mode=config.report_mode.value, + hypothesis=config.hypothesis.value, + generator_type=config.generator_type.value, + executor_type=config.executor_type.value, + report_builder_type=config.report_builder_type.value, + sample_sizes=config.sample_sizes, + monte_carlo_count=config.monte_carlo_count, + criteria=criteria, + significance_levels=significance_levels, + alternatives=alternatives, + is_generation_done=False, + is_execution_done=False, + is_report_building_done=False, + ) + + storage.insert_data(query) + + +def _check_if_experiment_finished(experiment_config_from_db: ExperimentModel) -> StepsDone: + """ + Check if experiment is finished. + + :param experiment_config_from_db: experiment config from db. + """ + + is_generation_done = experiment_config_from_db.is_generation_done + is_execution_done = experiment_config_from_db.is_execution_done + is_report_building_done = experiment_config_from_db.is_report_building_done + + if is_generation_done and is_execution_done and is_report_building_done: + raise ClickException("Experiment is already finished.") + + steps_done = StepsDone( + is_generation_step_done=is_generation_done, + is_execution_step_done=is_execution_done, + is_report_building_step_done=is_report_building_done, + ) + + return steps_done + + +# Maps modern Pydantic config classes to their legacy dataclass counterparts. +PYDANTIC_TO_LEGACY_MAP = { + PydanticPowerConfig: LegacyPowerExperimentConfig, + PydanticCriticalValueConfig: LegacyCriticalValueExperimentConfig, + PydanticTimeComplexityConfig: LegacyTimeComplexityExperimentConfig, +} + + +def _adapt_pydantic_to_dataclass(pydantic_config: PydanticBaseExperiment) -> ExperimentConfig: + """ + Converts a Pydantic configuration model to a legacy dataclass model. + + This adapter function is necessary for compatibility between the new + Pydantic-based validation layer and the older, dataclass-based core + logic. It uses `dacite` for flexible conversion. + + Args: + pydantic_config: The validated Pydantic configuration object. + + Raises: + TypeError: If the Pydantic config type has no corresponding legacy class + in the `PYDANTIC_TO_LEGACY_MAP`. + + Returns: + The equivalent legacy `ExperimentConfig` dataclass instance. + """ + legacy_dataclass_type = PYDANTIC_TO_LEGACY_MAP.get(type(pydantic_config)) + if legacy_dataclass_type is None: + raise TypeError(f"No match for Pydantic type: {type(pydantic_config)}") + + config_dict = pydantic_config.model_dump(mode="json") + + enum_mapping = { + ExperimentType: lambda x: ExperimentType(x), + RunMode: lambda x: RunMode(x), + Hypothesis: lambda x: Hypothesis(x), + StepType: lambda x: StepType(x), + } + + legacy_config = from_dict( + data_class=legacy_dataclass_type, + data=config_dict, + config=Config(type_hooks=enum_mapping, cast=[Enum]), + ) + + return legacy_config diff --git a/pysatl_experiment/validation/cli/commands/configure/criteria/criteria.py b/pysatl_experiment/validation/cli/commands/configure/criteria/criteria.py index d49bab7..c049e93 100644 --- a/pysatl_experiment/validation/cli/commands/configure/criteria/criteria.py +++ b/pysatl_experiment/validation/cli/commands/configure/criteria/criteria.py @@ -11,7 +11,7 @@ def validate_criteria(criteria_codes: list[str], hypothesis: str) -> None: :param hypothesis: hypothesis. """ - valid_criteria_codes = get_statistics_short_codes_for_hypothesis(hypothesis) + valid_criteria_codes = get_statistics_short_codes_for_hypothesis(hypothesis) # type: ignore for code in criteria_codes: if code not in valid_criteria_codes: diff --git a/pysatl_experiment/validation/cli/schemas/__init__.py b/pysatl_experiment/validation/cli/schemas/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pysatl_experiment/validation/cli/schemas/alternative.py b/pysatl_experiment/validation/cli/schemas/alternative.py new file mode 100644 index 0000000..3549c66 --- /dev/null +++ b/pysatl_experiment/validation/cli/schemas/alternative.py @@ -0,0 +1,99 @@ +# TODO +import inspect +from typing import Any + +from pydantic import BaseModel, Field, model_validator + +from pysatl_experiment.configuration.model.experiment_type.experiment_type import ExperimentType +from pysatl_experiment.experiment.generator import AbstractRVSGenerator + + +class Alternative(BaseModel): + """ + Specifies an alternative hypothesis generator and its parameters. + + This model supports instantiation from a space-separated string + (e.g., passing "MyGenerator 1.0 5.5" instead of a dictionary). + + During validation, it dynamically checks if the `generator_name` exists + among subclasses of `AbstractRVSGenerator`. It also introspects the + generator's `__init__` method to ensure the count of provided `parameters` + matches the required unique arguments of that generator. + + Attributes: + generator_name (str): The name of the generator class (case-insensitive). + parameters (list[float]): A list of numerical parameters required by + the generator's constructor. + """ + + generator_name: str + parameters: list[float] + + @model_validator(mode="before") + @classmethod + def parse_from_string(cls, data: Any) -> Any: + if not isinstance(data, str): + return data + + parts = data.split() + if not parts: + raise ValueError("Alternative string cannot be empty.") + + generator_name = parts[0] + try: + parameters = [float(p) for p in parts[1:]] + except ValueError: + raise ValueError(f"All parameters for generator '{generator_name}' must be numbers.") + + return {"generator_name": generator_name, "parameters": parameters} + + @model_validator(mode="after") + def validate_generator_logic(self): + generator_by_name: dict[str, type[AbstractRVSGenerator]] = { + gen_cls.__name__.upper(): gen_cls for gen_cls in AbstractRVSGenerator.__subclasses__() + } + + generator_cls = generator_by_name.get(self.generator_name.upper()) + if not generator_cls: + available_generators = ", ".join(generator_by_name.keys()) + raise ValueError( + f"Generator '{self.generator_name}' is not found. Available generators are: [{available_generators}]" + ) + + base_params = set(inspect.signature(AbstractRVSGenerator.__init__).parameters.keys()) + + sig = inspect.signature(generator_cls.__init__) + + unique_param_names = [p.name for p in sig.parameters.values() if p.name not in base_params and p.name != "self"] + + if len(self.parameters) != len(unique_param_names): + expected_params = ", ".join(unique_param_names) + raise ValueError( + f"Generator '{self.generator_name}' expects {len(unique_param_names)} " + f"unique parameters ({expected_params}), " + f"but received {len(self.parameters)}." + ) + return self + + +class AlternativesConfig(BaseModel): + """ + Configuration container for a list of alternatives. + + Ensures that alternatives are only defined for experiment types that + support them (e.g., POWER analysis). + + Attributes: + experiment_type (ExperimentType): The context of the current experiment. + alternatives (list[Alternative]): The list of defined alternatives. + Must be empty if `experiment_type` is not POWER. + """ + + experiment_type: ExperimentType + alternatives: list[Alternative] = Field(default_factory=list) + + @model_validator(mode="after") + def check_alternatives_are_allowed(self): + if self.experiment_type != ExperimentType.POWER and self.alternatives: + raise ValueError(f"Alternatives are not supported for the experiment type '{self.experiment_type.value}'.") + return self diff --git a/pysatl_experiment/validation/cli/schemas/criteria.py b/pysatl_experiment/validation/cli/schemas/criteria.py new file mode 100644 index 0000000..a339fa3 --- /dev/null +++ b/pysatl_experiment/validation/cli/schemas/criteria.py @@ -0,0 +1,67 @@ +from pydantic import BaseModel, Field, ValidationInfo, field_validator + +from pysatl_experiment.cli.commands.common.common import get_statistics_short_codes_for_hypothesis +from pysatl_experiment.configuration.model.hypothesis.hypothesis import Hypothesis + + +class Criterion(BaseModel): + """ + Represents a single statistical criterion. + + A criterion is defined by its unique code (which is automatically + converted to uppercase) and an optional list of parameters. + + Attributes: + criterion_code (str): The short code identifying the criterion (e.g., "KS", "AD"). + parameters (list): An optional list of parameters for the criterion. + """ + + criterion_code: str + parameters: list = Field(default_factory=list) + + @field_validator("criterion_code", mode="before") + @classmethod + def code_to_upper(cls, v: str) -> str: + return v.upper() + + +class CriteriaConfig(BaseModel): + """ + A configuration container for a list of criteria. + + This model validates that all specified criteria are compatible with the + given statistical hypothesis. It dynamically fetches the allowed + criterion codes for the hypothesis and raises an error if any of the + provided criteria are not in the allowed list. + + Attributes: + hypothesis (Hypothesis): The hypothesis against which the criteria are tested. + criteria (list[Criterion]): A list of criteria to be used in the experiment. + """ + + hypothesis: Hypothesis + criteria: list[Criterion] + + @field_validator("criteria") + @classmethod + def criteria_must_be_compatible_with_hypothesis( + cls, criteria_list: list[Criterion], info: ValidationInfo + ) -> list[Criterion]: + if "hypothesis" not in info.data: + return criteria_list + + hypothesis = info.data["hypothesis"] + valid_codes = get_statistics_short_codes_for_hypothesis(hypothesis.value) + + if not valid_codes: + raise ValueError(f"No matching values were found for hypothesis '{hypothesis.value}'.") + + invalid_codes = [crit.criterion_code for crit in criteria_list if crit.criterion_code not in valid_codes] + + if invalid_codes: + raise ValueError( + f"Criteria '{', '.join(invalid_codes)}' are incompatible with hypothesis '{hypothesis.value}'.\n" + f"Valid codes: {', '.join(valid_codes)}" + ) + + return criteria_list diff --git a/pysatl_experiment/validation/cli/schemas/experiment.py b/pysatl_experiment/validation/cli/schemas/experiment.py new file mode 100644 index 0000000..42a1cb9 --- /dev/null +++ b/pysatl_experiment/validation/cli/schemas/experiment.py @@ -0,0 +1,167 @@ +from typing import Literal, Union + +from pydantic import BaseModel, Field, field_validator + +from pysatl_experiment.configuration.model.criterion.criterion import Criterion +from pysatl_experiment.configuration.model.hypothesis.hypothesis import Hypothesis +from pysatl_experiment.configuration.model.report_mode.report_mode import ReportMode +from pysatl_experiment.configuration.model.run_mode.run_mode import RunMode +from pysatl_experiment.configuration.model.step_type.step_type import StepType +from pysatl_experiment.validation.cli.schemas.alternative import Alternative + + +class BaseExperimentConfig(BaseModel): + """Base configuration for all experiment types. + + This class defines the common set of parameters that are required for any + type of experiment. + + Attributes: + hypothesis (Hypothesis): The statistical hypothesis to be tested. + run_mode (RunMode): The mode in which the experiment will be run + report_mode (ReportMode): The mode for generating reports. + generator_type (StepType): The type of the data generator step. + executor_type (StepType): The type of the execution step. + report_builder_type (StepType): The type of the report builder step. + criteria (list[Criterion]): A list of criteria for the experiment. + storage_connection (str): The connection string or path for data storage. + sample_sizes (list[int]): A list of sample sizes to be used in the experiment. + monte_carlo_count (int): The number of Monte Carlo simulations to run. + """ + + hypothesis: Hypothesis + run_mode: RunMode + report_mode: ReportMode + generator_type: StepType + executor_type: StepType + report_builder_type: StepType + criteria: list[Criterion] + storage_connection: str + sample_sizes: list[int] + monte_carlo_count: int + + @field_validator("generator_type", "executor_type", "report_builder_type") + @classmethod + def check_custom_step(cls, value): + if value == StepType.CUSTOM: + raise ValueError(f"Type of '{value}' is not valid.\nPossible value are: Standard") + return value + + @field_validator("sample_sizes") + @classmethod + def check_sample_sizes(cls, value): + if any(size < 10 for size in value): + raise ValueError("Sample sizes must be greater than 10.") + return value + + @field_validator("monte_carlo_count") + @classmethod + def check_monte_carlo(cls, value): + if value <= 100: + raise ValueError("Monte Carlo count must be greater than 100.") + return value + + +class PowerConfig(BaseExperimentConfig): + """ + Configuration specific to a power analysis experiment. + + This extends the base configuration with parameters required for + calculating statistical power. + + Attributes: + experiment_type (Literal["power"]): The type of the experiment. + alternatives (list[Alternative]): A list of alternative hypotheses. + significance_levels (list[float]): A list of significance levels (alpha). + """ + + experiment_type: Literal["power"] + alternatives: list[Alternative] + significance_levels: list[float] + + +class CriticalValueConfig(BaseExperimentConfig): + """ + Configuration specific to a critical value computation experiment. + + This extends the base configuration with parameters needed for + determining critical values. + + Attributes: + experiment_type (Literal["critical_value"]): The type of the experiment. + significance_levels (list[float]): A list of significance levels (alpha). + """ + + experiment_type: Literal["critical_value"] + significance_levels: list[float] + + +class TimeComplexityConfig(BaseExperimentConfig): + """ + Configuration for a time complexity analysis experiment. + + This extends the base configuration for experiments focused on measuring + computational time complexity. + + Attributes: + experiment_type (Literal["time_complexity"]): The type of the experiment. + """ + + experiment_type: Literal["time_complexity"] + pass + + +Experiment = Union[PowerConfig, CriticalValueConfig, TimeComplexityConfig] + + +class ExperimentConfig(BaseModel): + """ + The main container for an experiment's configuration. + + This model holds the name of the experiment and a specific configuration + object, which can be one of the defined experiment types. + + Attributes: + name (str): The name of the experiment. + config (Experiment): The specific configuration for the experiment, + discriminated by `experiment_type`. + """ + + name: str + config: Experiment = Field(discriminator="experiment_type") + + @field_validator("name") + @classmethod + def check_experiment_name(cls, value) -> str: + bad_names = [ + "CON", + "AUX", + "COM1", + "COM2", + "COM3", + "COM4", + "LPT1", + "LPT2", + "LPT3", + "PRN", + "NUL", + ] + if value.upper() in bad_names: + raise ValueError(f"The name mustn't be: {bad_names}") + + bad_chars = ["\\", "/", "\\0", ":", "*", "?", "<", ">", "|", "' '"] + if any(char in value for char in bad_chars): + found_bad_chars = [char for char in bad_chars if char in value] + raise ValueError(f"Name '{value}' contain invalid characters: {', '.join(found_bad_chars)}") + + if not value.strip(): + raise ValueError("Name cannot be empty or consist only of whitespace.") + + return value + + @field_validator("config") + @classmethod + def check_config(cls, value): + if value is None: + raise ValueError("Missing config") + return value From aa59ce50140302e8052a5881286525c8dbbb4f84 Mon Sep 17 00:00:00 2001 From: faux66 Date: Wed, 8 Oct 2025 14:20:47 +0300 Subject: [PATCH 04/17] feat: add pydantic alternatives validation --- .../commands/build_and_run/build_and_run.py | 2 +- .../configure/alternatives/alternatives.py | 38 +++- .../commands/build_and_run/build_and_run.py | 202 ++++++++---------- .../validation/cli/schemas/alternative.py | 27 ++- 4 files changed, 151 insertions(+), 118 deletions(-) diff --git a/pysatl_experiment/cli/commands/build_and_run/build_and_run.py b/pysatl_experiment/cli/commands/build_and_run/build_and_run.py index b083090..e193b4e 100644 --- a/pysatl_experiment/cli/commands/build_and_run/build_and_run.py +++ b/pysatl_experiment/cli/commands/build_and_run/build_and_run.py @@ -7,7 +7,7 @@ from pysatl_experiment.factory.critical_value.critical_value import CriticalValueExperimentFactory from pysatl_experiment.factory.power.power import PowerExperimentFactory from pysatl_experiment.factory.time_complexity.time_complexity import TimeComplexityExperimentFactory -from pysatl_experiment.validation.cli.commands.build_and_run.build_and_run_new import validate_build_and_run +from pysatl_experiment.validation.cli.commands.build_and_run.build_and_run import validate_build_and_run from pysatl_experiment.validation.cli.commands.common.common import if_experiment_exists diff --git a/pysatl_experiment/cli/commands/configure/alternatives/alternatives.py b/pysatl_experiment/cli/commands/configure/alternatives/alternatives.py index f1042a1..c91e859 100644 --- a/pysatl_experiment/cli/commands/configure/alternatives/alternatives.py +++ b/pysatl_experiment/cli/commands/configure/alternatives/alternatives.py @@ -1,8 +1,9 @@ from click import ClickException, Context, echo, option, pass_context +from pydantic import ValidationError from pysatl_experiment.cli.commands.common.common import get_experiment_name_and_config, save_experiment_config from pysatl_experiment.cli.commands.configure.configure import configure -from pysatl_experiment.validation.cli.commands.configure.alternatives.alternatives import validate_alternatives +from pysatl_experiment.validation.cli.schemas.alternative import AlternativesConfig @configure.command() @@ -10,12 +11,23 @@ @pass_context def alternatives(ctx: Context, alt: tuple[str]) -> None: """ - Configure experiment alternatives. + Set the alternative hypotheses for the current experiment. - :param ctx: context. - :param alt: alternatives. - """ + This command configures one or more alternative hypotheses, which are + necessary for 'power' experiments. It requires the experiment type to be + set beforehand and will raise an error if alternatives are provided for an + incompatible experiment type. + + Each alternative must be provided with a separate `--alt` option. + Example: + experiment configure MyPowerAnalysis alternatives --alt "Normal 1.0 0.5" --alt "Cauchy 0 2" + + Args: + ctx: The Click context object, passed automatically. + alt: A tuple of strings, where each string defines one alternative + in the format "generator_name param1 param2 ...". + """ experiment_name, experiment_config = get_experiment_name_and_config(ctx) experiment_type = experiment_config.get("experiment_type") @@ -26,9 +38,21 @@ def alternatives(ctx: Context, alt: tuple[str]) -> None: f"'experiment configure {experiment_name} experiment-type '." ) - alternatives_data = validate_alternatives(alt, experiment_type) + try: + validated_config = AlternativesConfig(experiment_type=experiment_type, alternatives=list(alt)) + + alternatives_data = validated_config.model_dump().get("alternatives", []) + + except ValidationError as e: + raise ClickException(str(e)) + experiment_config["alternatives"] = alternatives_data save_experiment_config(ctx, experiment_name, experiment_config) - echo(f"Alternatives of the experiment '{experiment_name}' are successfully set to {alternatives_data}.") + echo(f"Alternatives of the experiment '{experiment_name}' are successfully set.") + if alternatives_data: + echo("Configured alternatives:") + for alt_item in alternatives_data: + params_str = " ".join(map(str, alt_item.get("parameters", []))) + echo(f" - {alt_item.get('generator_name')} {params_str}") diff --git a/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run.py b/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run.py index 5dbab04..6cc4cf4 100644 --- a/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run.py +++ b/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run.py @@ -3,15 +3,18 @@ from click import ClickException from dacite import Config, from_dict +from pydantic import ValidationError from pysatl_experiment.cli.commands.common.common import create_result_path from pysatl_experiment.configuration.experiment_config.critical_value.critical_value import ( - CriticalValueExperimentConfig, + CriticalValueExperimentConfig as LegacyCriticalValueExperimentConfig, ) from pysatl_experiment.configuration.experiment_config.experiment_config import ExperimentConfig -from pysatl_experiment.configuration.experiment_config.power.power import PowerExperimentConfig +from pysatl_experiment.configuration.experiment_config.power.power import ( + PowerExperimentConfig as LegacyPowerExperimentConfig, +) from pysatl_experiment.configuration.experiment_config.time_complexity.time_complexity import ( - TimeComplexityExperimentConfig, + TimeComplexityExperimentConfig as LegacyTimeComplexityExperimentConfig, ) from pysatl_experiment.configuration.experiment_data.common.steps_done.steps_done import StepsDone from pysatl_experiment.configuration.experiment_data.experiment_data import ExperimentData @@ -25,63 +28,63 @@ ExperimentQuery, IExperimentStorage, ) +from pysatl_experiment.validation.cli.schemas.experiment import BaseExperimentConfig as PydanticBaseExperiment +from pysatl_experiment.validation.cli.schemas.experiment import CriticalValueConfig as PydanticCriticalValueConfig +from pysatl_experiment.validation.cli.schemas.experiment import ExperimentConfig as ExperimentInputSchema +from pysatl_experiment.validation.cli.schemas.experiment import PowerConfig as PydanticPowerConfig +from pysatl_experiment.validation.cli.schemas.experiment import TimeComplexityConfig as PydanticTimeComplexityConfig def validate_build_and_run(experiment_data_dict: dict) -> ExperimentData: """ - Validate build and run command. - - :param experiment_data_dict: experiment data dictionary. + Validates input, initializes, and builds the experiment data object. + + This function performs the following steps: + 1. Validates the raw input dictionary against Pydantic schemas. + 2. Adapts the modern Pydantic models to legacy dataclass configurations. + 3. Initializes the SQLite storage backend. + 4. Checks if an identical experiment already exists in storage to resume it. + 5. If not, it saves the new experiment configuration. + 6. Creates a results path for experiment artifacts. + 7. Returns a complete `ExperimentData` object to be used by the runner. + + Args: + experiment_data_dict: A dictionary containing the raw experiment configuration. + + Raises: + ClickException: If validation fails or if the experiment has already + been completed. + + Returns: + An `ExperimentData` object ready for the experiment execution pipeline. """ + try: + validated_data = ExperimentInputSchema.model_validate(experiment_data_dict) + except ValidationError as e: + raise ClickException(str(e)) - experiment_name = experiment_data_dict.get("name") - if experiment_name is None: - raise ClickException("Missing experiment_name") - - experiment_config = experiment_data_dict.get("config") - if experiment_config is None: - raise ClickException("Missing config") - - base_required_parameters = [ - "experiment_type", - "storage_connection", - "hypothesis", - "sample_sizes", - "monte_carlo_count", - ] - _check_required_parameters(experiment_config, base_required_parameters) - - experiment_type = experiment_config.get("experiment_type") - if experiment_type == "power": - power_required_parameters = ["significance_levels", "alternatives"] - _check_required_parameters(experiment_config, power_required_parameters) - elif experiment_type == "critical_value": - critical_value_required_parameters = ["significance_levels"] - _check_required_parameters(experiment_config, critical_value_required_parameters) - - experiment_config_dataclass = _create_experiment_config_from_dict( - experiment_config_dict=experiment_config, - experiment_type=experiment_type, - ) + experiment_name = validated_data.name + pydantic_config = validated_data.config + legacy_dataclass_config = _adapt_pydantic_to_dataclass(pydantic_config) steps_done = StepsDone( is_generation_step_done=False, is_execution_step_done=False, is_report_building_step_done=False, ) - experiment_storage = SQLiteExperimentStorage(experiment_config_dataclass.storage_connection) + experiment_storage = SQLiteExperimentStorage(legacy_dataclass_config.storage_connection) experiment_storage.init() experiment_config_from_storage = _get_experiment_config_from_storage( - config=experiment_config_dataclass, + config=legacy_dataclass_config, storage=experiment_storage, ) if experiment_config_from_storage is not None: steps_done = _check_if_experiment_finished(experiment_config_from_storage) else: _save_experiment_config_to_storage( - config=experiment_config_dataclass, + config=legacy_dataclass_config, storage=experiment_storage, ) @@ -89,7 +92,7 @@ def validate_build_and_run(experiment_data_dict: dict) -> ExperimentData: experiment_data = ExperimentData( name=experiment_name, - config=experiment_config_dataclass, + config=legacy_dataclass_config, steps_done=steps_done, results_path=result_path, ) @@ -97,71 +100,6 @@ def validate_build_and_run(experiment_data_dict: dict) -> ExperimentData: return experiment_data -def _check_required_parameters(experiment_config: dict, required_parameters: list[str]) -> None: - """ - Check if experiment configuration contains all required parameters. - - :param experiment_config: experiment configuration. - :param required_parameters: required parameters. - """ - - missing_parameters = [] - - for parameter in required_parameters: - if parameter not in experiment_config: - missing_parameters.append(parameter) - - is_need_to_configure = len(missing_parameters) > 0 - if is_need_to_configure: - _raise_missing_parameters_exception(missing_parameters) - - -def _raise_missing_parameters_exception(missing_parameters: list[str]) -> None: - """ - Raise exception with missing parameters. - - :param missing_parameters: missing parameters. - """ - raise ClickException(f"Experiment configuration is missing required parameters: {missing_parameters}.") - - -def _create_experiment_config_from_dict( - experiment_config_dict: dict, - experiment_type: str, -) -> ExperimentConfig: - """ - Create experiment data from dictionary. - - :param experiment_config_dict: experiment configuration dictionary. - :param experiment_type: experiment type. - - :return: experiment config. - """ - - experiment_type_str_to_class = { - "power": PowerExperimentConfig, - "critical_value": CriticalValueExperimentConfig, - "time_complexity": TimeComplexityExperimentConfig, - } - - enum_mapping = { - ExperimentType: lambda x: ExperimentType(x), - RunMode: lambda x: RunMode(x), - Hypothesis: lambda x: Hypothesis(x), - StepType: lambda x: StepType(x), - } - - experiment_config_type = experiment_type_str_to_class[experiment_type] - - experiment_config: ExperimentConfig = from_dict( - data_class=experiment_config_type, - data=experiment_config_dict, - config=Config(type_hooks=enum_mapping, cast=[Enum]), - ) - - return experiment_config - - def _get_experiment_config_from_storage( config: ExperimentConfig, storage: IExperimentStorage ) -> ExperimentModel | None: @@ -179,10 +117,10 @@ def _get_experiment_config_from_storage( significance_levels = [] alternatives = {} if experiment_type == ExperimentType.CRITICAL_VALUE: - critical_value_config = cast(PowerExperimentConfig, config) + critical_value_config = cast(LegacyCriticalValueExperimentConfig, config) significance_levels = critical_value_config.significance_levels elif experiment_type == ExperimentType.POWER: - power_config = cast(PowerExperimentConfig, config) + power_config = cast(LegacyPowerExperimentConfig, config) significance_levels = power_config.significance_levels alternatives = {alternative.generator_name: alternative.parameters for alternative in power_config.alternatives} @@ -221,10 +159,10 @@ def _save_experiment_config_to_storage(config: ExperimentConfig, storage: IExper significance_levels = [] alternatives = {} if experiment_type == ExperimentType.CRITICAL_VALUE: - critical_value_config = cast(PowerExperimentConfig, config) + critical_value_config = cast(LegacyCriticalValueExperimentConfig, config) significance_levels = critical_value_config.significance_levels elif experiment_type == ExperimentType.POWER: - power_config = cast(PowerExperimentConfig, config) + power_config = cast(LegacyPowerExperimentConfig, config) significance_levels = power_config.significance_levels alternatives = {alternative.generator_name: alternative.parameters for alternative in power_config.alternatives} @@ -271,3 +209,51 @@ def _check_if_experiment_finished(experiment_config_from_db: ExperimentModel) -> ) return steps_done + + +# Maps modern Pydantic config classes to their legacy dataclass counterparts. +PYDANTIC_TO_LEGACY_MAP = { + PydanticPowerConfig: LegacyPowerExperimentConfig, + PydanticCriticalValueConfig: LegacyCriticalValueExperimentConfig, + PydanticTimeComplexityConfig: LegacyTimeComplexityExperimentConfig, +} + + +def _adapt_pydantic_to_dataclass(pydantic_config: PydanticBaseExperiment) -> ExperimentConfig: + """ + Converts a Pydantic configuration model to a legacy dataclass model. + + This adapter function is necessary for compatibility between the new + Pydantic-based validation layer and the older, dataclass-based core + logic. It uses `dacite` for flexible conversion. + + Args: + pydantic_config: The validated Pydantic configuration object. + + Raises: + TypeError: If the Pydantic config type has no corresponding legacy class + in the `PYDANTIC_TO_LEGACY_MAP`. + + Returns: + The equivalent legacy `ExperimentConfig` dataclass instance. + """ + legacy_dataclass_type = PYDANTIC_TO_LEGACY_MAP.get(type(pydantic_config)) + if legacy_dataclass_type is None: + raise TypeError(f"No match for Pydantic type: {type(pydantic_config)}") + + config_dict = pydantic_config.model_dump(mode="json") + + enum_mapping = { + ExperimentType: lambda x: ExperimentType(x), + RunMode: lambda x: RunMode(x), + Hypothesis: lambda x: Hypothesis(x), + StepType: lambda x: StepType(x), + } + + legacy_config = from_dict( + data_class=legacy_dataclass_type, + data=config_dict, + config=Config(type_hooks=enum_mapping, cast=[Enum]), + ) + + return legacy_config diff --git a/pysatl_experiment/validation/cli/schemas/alternative.py b/pysatl_experiment/validation/cli/schemas/alternative.py index 3549c66..7e3a27f 100644 --- a/pysatl_experiment/validation/cli/schemas/alternative.py +++ b/pysatl_experiment/validation/cli/schemas/alternative.py @@ -1,8 +1,7 @@ -# TODO import inspect from typing import Any -from pydantic import BaseModel, Field, model_validator +from pydantic import BaseModel, Field, field_validator, model_validator from pysatl_experiment.configuration.model.experiment_type.experiment_type import ExperimentType from pysatl_experiment.experiment.generator import AbstractRVSGenerator @@ -29,6 +28,30 @@ class Alternative(BaseModel): generator_name: str parameters: list[float] + @field_validator("generator_name") + @classmethod + def normalize_and_resolve_generator_name(cls, value): + available_generators: list[str] = [ + gen_cls.__name__.upper() for gen_cls in AbstractRVSGenerator.__subclasses__() + ] + + user_prefix = value.upper() + + matches = [full_name for full_name in available_generators if full_name.startswith(user_prefix)] + + if len(matches) == 1: + return matches[0] + + if not matches: + raise ValueError( + f"Generator prefix '{value}' did not match any available generators. " + f"Available are: [{', '.join(available_generators)}]" + ) + else: + raise ValueError( + f"Generator prefix '{value}' is ambiguous. It matches: [{', '.join(matches)}]. Please be more specific." + ) + @model_validator(mode="before") @classmethod def parse_from_string(cls, data: Any) -> Any: From e010473675947372734688cfe5c9c6c46518c493 Mon Sep 17 00:00:00 2001 From: faux66 Date: Wed, 8 Oct 2025 14:22:31 +0300 Subject: [PATCH 05/17] refactor: drup unused --- .../build_and_run/build_and_run_new.py | 259 ------------------ .../configure/alternatives/alternatives.py | 74 ----- .../commands/configure/criteria/criteria.py | 21 -- .../experiment_type/experiment_type.py | 19 -- .../configure/hypothesis/hypothesis.py | 16 -- .../configure/report_mode/report_mode.py | 16 -- .../commands/configure/run_mode/run_mode.py | 16 -- .../commands/configure/step_type/step_type.py | 21 -- 8 files changed, 442 deletions(-) delete mode 100644 pysatl_experiment/validation/cli/commands/build_and_run/build_and_run_new.py delete mode 100644 pysatl_experiment/validation/cli/commands/configure/alternatives/alternatives.py delete mode 100644 pysatl_experiment/validation/cli/commands/configure/criteria/criteria.py delete mode 100644 pysatl_experiment/validation/cli/commands/configure/experiment_type/experiment_type.py delete mode 100644 pysatl_experiment/validation/cli/commands/configure/hypothesis/hypothesis.py delete mode 100644 pysatl_experiment/validation/cli/commands/configure/report_mode/report_mode.py delete mode 100644 pysatl_experiment/validation/cli/commands/configure/run_mode/run_mode.py delete mode 100644 pysatl_experiment/validation/cli/commands/configure/step_type/step_type.py diff --git a/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run_new.py b/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run_new.py deleted file mode 100644 index 6cc4cf4..0000000 --- a/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run_new.py +++ /dev/null @@ -1,259 +0,0 @@ -from enum import Enum -from typing import cast - -from click import ClickException -from dacite import Config, from_dict -from pydantic import ValidationError - -from pysatl_experiment.cli.commands.common.common import create_result_path -from pysatl_experiment.configuration.experiment_config.critical_value.critical_value import ( - CriticalValueExperimentConfig as LegacyCriticalValueExperimentConfig, -) -from pysatl_experiment.configuration.experiment_config.experiment_config import ExperimentConfig -from pysatl_experiment.configuration.experiment_config.power.power import ( - PowerExperimentConfig as LegacyPowerExperimentConfig, -) -from pysatl_experiment.configuration.experiment_config.time_complexity.time_complexity import ( - TimeComplexityExperimentConfig as LegacyTimeComplexityExperimentConfig, -) -from pysatl_experiment.configuration.experiment_data.common.steps_done.steps_done import StepsDone -from pysatl_experiment.configuration.experiment_data.experiment_data import ExperimentData -from pysatl_experiment.configuration.model.experiment_type.experiment_type import ExperimentType -from pysatl_experiment.configuration.model.hypothesis.hypothesis import Hypothesis -from pysatl_experiment.configuration.model.run_mode.run_mode import RunMode -from pysatl_experiment.configuration.model.step_type.step_type import StepType -from pysatl_experiment.persistence.experiment.sqlite.sqlite import SQLiteExperimentStorage -from pysatl_experiment.persistence.model.experiment.experiment import ( - ExperimentModel, - ExperimentQuery, - IExperimentStorage, -) -from pysatl_experiment.validation.cli.schemas.experiment import BaseExperimentConfig as PydanticBaseExperiment -from pysatl_experiment.validation.cli.schemas.experiment import CriticalValueConfig as PydanticCriticalValueConfig -from pysatl_experiment.validation.cli.schemas.experiment import ExperimentConfig as ExperimentInputSchema -from pysatl_experiment.validation.cli.schemas.experiment import PowerConfig as PydanticPowerConfig -from pysatl_experiment.validation.cli.schemas.experiment import TimeComplexityConfig as PydanticTimeComplexityConfig - - -def validate_build_and_run(experiment_data_dict: dict) -> ExperimentData: - """ - Validates input, initializes, and builds the experiment data object. - - This function performs the following steps: - 1. Validates the raw input dictionary against Pydantic schemas. - 2. Adapts the modern Pydantic models to legacy dataclass configurations. - 3. Initializes the SQLite storage backend. - 4. Checks if an identical experiment already exists in storage to resume it. - 5. If not, it saves the new experiment configuration. - 6. Creates a results path for experiment artifacts. - 7. Returns a complete `ExperimentData` object to be used by the runner. - - Args: - experiment_data_dict: A dictionary containing the raw experiment configuration. - - Raises: - ClickException: If validation fails or if the experiment has already - been completed. - - Returns: - An `ExperimentData` object ready for the experiment execution pipeline. - """ - try: - validated_data = ExperimentInputSchema.model_validate(experiment_data_dict) - except ValidationError as e: - raise ClickException(str(e)) - - experiment_name = validated_data.name - pydantic_config = validated_data.config - - legacy_dataclass_config = _adapt_pydantic_to_dataclass(pydantic_config) - steps_done = StepsDone( - is_generation_step_done=False, - is_execution_step_done=False, - is_report_building_step_done=False, - ) - - experiment_storage = SQLiteExperimentStorage(legacy_dataclass_config.storage_connection) - experiment_storage.init() - - experiment_config_from_storage = _get_experiment_config_from_storage( - config=legacy_dataclass_config, - storage=experiment_storage, - ) - if experiment_config_from_storage is not None: - steps_done = _check_if_experiment_finished(experiment_config_from_storage) - else: - _save_experiment_config_to_storage( - config=legacy_dataclass_config, - storage=experiment_storage, - ) - - result_path = create_result_path() - - experiment_data = ExperimentData( - name=experiment_name, - config=legacy_dataclass_config, - steps_done=steps_done, - results_path=result_path, - ) - - return experiment_data - - -def _get_experiment_config_from_storage( - config: ExperimentConfig, storage: IExperimentStorage -) -> ExperimentModel | None: - """ - Get experiment config from database. - - :param config: experiment config dataclass. - - :return: experiment config from db. - """ - - experiment_type = config.experiment_type - criteria = {criterion.criterion_code: criterion.parameters for criterion in config.criteria} - - significance_levels = [] - alternatives = {} - if experiment_type == ExperimentType.CRITICAL_VALUE: - critical_value_config = cast(LegacyCriticalValueExperimentConfig, config) - significance_levels = critical_value_config.significance_levels - elif experiment_type == ExperimentType.POWER: - power_config = cast(LegacyPowerExperimentConfig, config) - significance_levels = power_config.significance_levels - alternatives = {alternative.generator_name: alternative.parameters for alternative in power_config.alternatives} - - query = ExperimentQuery( - experiment_type=experiment_type.value, - storage_connection=config.storage_connection, - run_mode=config.run_mode.value, - report_mode=config.report_mode.value, - hypothesis=config.hypothesis.value, - generator_type=config.generator_type.value, - executor_type=config.executor_type.value, - report_builder_type=config.report_builder_type.value, - sample_sizes=config.sample_sizes, - monte_carlo_count=config.monte_carlo_count, - criteria=criteria, - significance_levels=significance_levels, - alternatives=alternatives, - ) - - experiment_config_from_db = storage.get_data(query) - - return experiment_config_from_db - - -def _save_experiment_config_to_storage(config: ExperimentConfig, storage: IExperimentStorage) -> None: - """ - Save experiment config to database. - - :param config: experiment config dataclass. - :param storage: experiment storage. - """ - - experiment_type = config.experiment_type - criteria = {criterion.criterion_code: criterion.parameters for criterion in config.criteria} - - significance_levels = [] - alternatives = {} - if experiment_type == ExperimentType.CRITICAL_VALUE: - critical_value_config = cast(LegacyCriticalValueExperimentConfig, config) - significance_levels = critical_value_config.significance_levels - elif experiment_type == ExperimentType.POWER: - power_config = cast(LegacyPowerExperimentConfig, config) - significance_levels = power_config.significance_levels - alternatives = {alternative.generator_name: alternative.parameters for alternative in power_config.alternatives} - - query = ExperimentModel( - experiment_type=experiment_type.value, - storage_connection=config.storage_connection, - run_mode=config.run_mode.value, - report_mode=config.report_mode.value, - hypothesis=config.hypothesis.value, - generator_type=config.generator_type.value, - executor_type=config.executor_type.value, - report_builder_type=config.report_builder_type.value, - sample_sizes=config.sample_sizes, - monte_carlo_count=config.monte_carlo_count, - criteria=criteria, - significance_levels=significance_levels, - alternatives=alternatives, - is_generation_done=False, - is_execution_done=False, - is_report_building_done=False, - ) - - storage.insert_data(query) - - -def _check_if_experiment_finished(experiment_config_from_db: ExperimentModel) -> StepsDone: - """ - Check if experiment is finished. - - :param experiment_config_from_db: experiment config from db. - """ - - is_generation_done = experiment_config_from_db.is_generation_done - is_execution_done = experiment_config_from_db.is_execution_done - is_report_building_done = experiment_config_from_db.is_report_building_done - - if is_generation_done and is_execution_done and is_report_building_done: - raise ClickException("Experiment is already finished.") - - steps_done = StepsDone( - is_generation_step_done=is_generation_done, - is_execution_step_done=is_execution_done, - is_report_building_step_done=is_report_building_done, - ) - - return steps_done - - -# Maps modern Pydantic config classes to their legacy dataclass counterparts. -PYDANTIC_TO_LEGACY_MAP = { - PydanticPowerConfig: LegacyPowerExperimentConfig, - PydanticCriticalValueConfig: LegacyCriticalValueExperimentConfig, - PydanticTimeComplexityConfig: LegacyTimeComplexityExperimentConfig, -} - - -def _adapt_pydantic_to_dataclass(pydantic_config: PydanticBaseExperiment) -> ExperimentConfig: - """ - Converts a Pydantic configuration model to a legacy dataclass model. - - This adapter function is necessary for compatibility between the new - Pydantic-based validation layer and the older, dataclass-based core - logic. It uses `dacite` for flexible conversion. - - Args: - pydantic_config: The validated Pydantic configuration object. - - Raises: - TypeError: If the Pydantic config type has no corresponding legacy class - in the `PYDANTIC_TO_LEGACY_MAP`. - - Returns: - The equivalent legacy `ExperimentConfig` dataclass instance. - """ - legacy_dataclass_type = PYDANTIC_TO_LEGACY_MAP.get(type(pydantic_config)) - if legacy_dataclass_type is None: - raise TypeError(f"No match for Pydantic type: {type(pydantic_config)}") - - config_dict = pydantic_config.model_dump(mode="json") - - enum_mapping = { - ExperimentType: lambda x: ExperimentType(x), - RunMode: lambda x: RunMode(x), - Hypothesis: lambda x: Hypothesis(x), - StepType: lambda x: StepType(x), - } - - legacy_config = from_dict( - data_class=legacy_dataclass_type, - data=config_dict, - config=Config(type_hooks=enum_mapping, cast=[Enum]), - ) - - return legacy_config diff --git a/pysatl_experiment/validation/cli/commands/configure/alternatives/alternatives.py b/pysatl_experiment/validation/cli/commands/configure/alternatives/alternatives.py deleted file mode 100644 index cfc8ee0..0000000 --- a/pysatl_experiment/validation/cli/commands/configure/alternatives/alternatives.py +++ /dev/null @@ -1,74 +0,0 @@ -import inspect - -from click import BadParameter - -from pysatl_experiment.experiment.generator import AbstractRVSGenerator - - -def validate_alternatives(alternatives: tuple[str], experiment_type: str) -> list[dict]: - """ - Validate experiment alternatives. - - :param alternatives: alternatives. - :param experiment_type: experiment type. - """ - if experiment_type != "power": - raise BadParameter(f"Alternatives are not supported for the experiment type '{experiment_type}'.") - - parsed = [] - - generator_by_name = {cls.__name__.upper(): cls for cls in AbstractRVSGenerator.__subclasses__()} - - for alt_str in alternatives: - generator_name, parameters = _parse_alternative(alt_str) - generator_name_upper = generator_name.upper() - - param_names, param_count = _get_generator_parameter_names_and_count(generator_name, generator_by_name) - - if len(parameters) != param_count: - raise BadParameter(f"Generator '{generator_name}' needs {param_count} parameters, got {len(parameters)}.") - - alternative_data = {"generator_name": generator_name_upper, "parameters": parameters} - - parsed.append(alternative_data) - - return parsed - - -def _parse_alternative(alternative: str) -> tuple[str, list[float]]: - """ - Parse alternative. - - :param alternative: alternative. - """ - - parts = alternative.split() - generator_name = parts[0].upper() - - try: - parameters = [float(v) for v in parts[1:]] - except ValueError: - raise BadParameter(f"Parameters for generator '{generator_name}' must be floats.") - - return generator_name, parameters - - -def _get_generator_parameter_names_and_count( - generator_name: str, generator_by_name: dict[str, type[AbstractRVSGenerator]] -) -> tuple[list[str], int]: - """ - Get generator parameter names and count. - - :param generator_name: generator name. - :param generator_by_name: generator by name dictionary. - """ - - cls = generator_by_name.get(generator_name) - if not cls: - raise BadParameter(f"Generator '{generator_name}' is not found.") - - sig = inspect.signature(cls.__init__) - param_names = [p.name for p in sig.parameters.values() if p.name != "self" and p.kind == p.POSITIONAL_OR_KEYWORD] - param_count = len(param_names) - - return param_names, param_count diff --git a/pysatl_experiment/validation/cli/commands/configure/criteria/criteria.py b/pysatl_experiment/validation/cli/commands/configure/criteria/criteria.py deleted file mode 100644 index c049e93..0000000 --- a/pysatl_experiment/validation/cli/commands/configure/criteria/criteria.py +++ /dev/null @@ -1,21 +0,0 @@ -from click import BadParameter - -from pysatl_experiment.cli.commands.common.common import get_statistics_short_codes_for_hypothesis - - -def validate_criteria(criteria_codes: list[str], hypothesis: str) -> None: - """ - Validate experiment criteria. - - :param criteria_codes: criteria codes. - :param hypothesis: hypothesis. - """ - - valid_criteria_codes = get_statistics_short_codes_for_hypothesis(hypothesis) # type: ignore - - for code in criteria_codes: - if code not in valid_criteria_codes: - raise BadParameter( - f"Criterion '{code}' is not allowed for hypothesis '{hypothesis}'.\n" - f"Possible values are: {', '.join(valid_criteria_codes)}" - ) diff --git a/pysatl_experiment/validation/cli/commands/configure/experiment_type/experiment_type.py b/pysatl_experiment/validation/cli/commands/configure/experiment_type/experiment_type.py deleted file mode 100644 index b236b7d..0000000 --- a/pysatl_experiment/validation/cli/commands/configure/experiment_type/experiment_type.py +++ /dev/null @@ -1,19 +0,0 @@ -from click import BadParameter - -from pysatl_experiment.cli.commands.common.common import list_possible_parameter_values -from pysatl_experiment.configuration.model.experiment_type.experiment_type import ExperimentType - - -def validate_experiment_type(experiment_type: str) -> None: - """ - Check if experiment type is valid. - - :param experiment_type: experiment type. - """ - - experiment_type_lower = experiment_type.lower() - if experiment_type_lower not in (item.value for item in ExperimentType): - possible_values = list_possible_parameter_values(ExperimentType) - raise BadParameter( - f"Experiment type '{experiment_type}' is not valid.\nPossible values are: {possible_values}." - ) diff --git a/pysatl_experiment/validation/cli/commands/configure/hypothesis/hypothesis.py b/pysatl_experiment/validation/cli/commands/configure/hypothesis/hypothesis.py deleted file mode 100644 index 5eac1be..0000000 --- a/pysatl_experiment/validation/cli/commands/configure/hypothesis/hypothesis.py +++ /dev/null @@ -1,16 +0,0 @@ -from click import BadParameter - -from pysatl_experiment.cli.commands.common.common import list_possible_parameter_values -from pysatl_experiment.configuration.model.hypothesis.hypothesis import Hypothesis - - -def validate_hypothesis(hypothesis: str) -> None: - """ - Check if hypothesis is valid. - - :param hypothesis: hypothesis. - """ - hypothesis_lower = hypothesis.lower() - if hypothesis_lower not in (item.value for item in Hypothesis): - possible_values = list_possible_parameter_values(Hypothesis) - raise BadParameter(f"Hypothesis '{hypothesis}' is not valid.\nPossible values are: {possible_values}.") diff --git a/pysatl_experiment/validation/cli/commands/configure/report_mode/report_mode.py b/pysatl_experiment/validation/cli/commands/configure/report_mode/report_mode.py deleted file mode 100644 index 1c29876..0000000 --- a/pysatl_experiment/validation/cli/commands/configure/report_mode/report_mode.py +++ /dev/null @@ -1,16 +0,0 @@ -from click import BadParameter - -from pysatl_experiment.cli.commands.common.common import list_possible_parameter_values -from pysatl_experiment.configuration.model.report_mode.report_mode import ReportMode - - -def validate_report_mode(report_mode: str) -> None: - """ - Check if report mode is valid. - - :param report_mode: report mode string. - """ - report_mode_lower = report_mode.lower() - if report_mode_lower not in (item.value for item in ReportMode): - possible_values = list_possible_parameter_values(ReportMode) - raise BadParameter(f"Run mode '{report_mode}' is not valid.\nPossible values are: {possible_values}.") diff --git a/pysatl_experiment/validation/cli/commands/configure/run_mode/run_mode.py b/pysatl_experiment/validation/cli/commands/configure/run_mode/run_mode.py deleted file mode 100644 index 4f2e2ce..0000000 --- a/pysatl_experiment/validation/cli/commands/configure/run_mode/run_mode.py +++ /dev/null @@ -1,16 +0,0 @@ -from click import BadParameter - -from pysatl_experiment.cli.commands.common.common import list_possible_parameter_values -from pysatl_experiment.configuration.model.run_mode.run_mode import RunMode - - -def validate_run_mode(run_mode: str) -> None: - """ - Check if run mode is valid. - - :param run_mode: run mode. - """ - run_mode_lower = run_mode.lower() - if run_mode_lower not in (item.value for item in RunMode): - possible_values = list_possible_parameter_values(RunMode) - raise BadParameter(f"Run mode '{run_mode}' is not valid.\nPossible values are: {possible_values}.") diff --git a/pysatl_experiment/validation/cli/commands/configure/step_type/step_type.py b/pysatl_experiment/validation/cli/commands/configure/step_type/step_type.py deleted file mode 100644 index 338eac2..0000000 --- a/pysatl_experiment/validation/cli/commands/configure/step_type/step_type.py +++ /dev/null @@ -1,21 +0,0 @@ -from click import BadParameter - -from pysatl_experiment.cli.commands.common.common import list_possible_parameter_values -from pysatl_experiment.configuration.model.step_type.step_type import StepType - - -def validate_step_type(step_type: str, step: str) -> None: - """ - Check if step type is valid. - - :param step_type: step type. - :param step: step. - """ - - step_type_lower = step_type.lower() - if step_type_lower not in (item.value for item in StepType): - possible_values = list_possible_parameter_values(StepType) - raise BadParameter(f"Type of {step} '{step_type}' is not valid.\nPossible values are: {possible_values}.") - - if step_type_lower == "custom": - raise BadParameter(f"Custom {step} type is not supported yet.\nPlease, choose standard one.") From ab62f39734f00e8c3523c9860d264ca01f8a477c Mon Sep 17 00:00:00 2001 From: faux66 Date: Wed, 8 Oct 2025 17:54:45 +0300 Subject: [PATCH 06/17] fix: criteria check --- .../validation/cli/schemas/experiment.py | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/pysatl_experiment/validation/cli/schemas/experiment.py b/pysatl_experiment/validation/cli/schemas/experiment.py index 42a1cb9..e2bb50c 100644 --- a/pysatl_experiment/validation/cli/schemas/experiment.py +++ b/pysatl_experiment/validation/cli/schemas/experiment.py @@ -1,13 +1,13 @@ from typing import Literal, Union -from pydantic import BaseModel, Field, field_validator +from pydantic import BaseModel, Field, ValidationError, field_validator, model_validator -from pysatl_experiment.configuration.model.criterion.criterion import Criterion from pysatl_experiment.configuration.model.hypothesis.hypothesis import Hypothesis from pysatl_experiment.configuration.model.report_mode.report_mode import ReportMode from pysatl_experiment.configuration.model.run_mode.run_mode import RunMode from pysatl_experiment.configuration.model.step_type.step_type import StepType from pysatl_experiment.validation.cli.schemas.alternative import Alternative +from pysatl_experiment.validation.cli.schemas.criteria import CriteriaConfig, Criterion class BaseExperimentConfig(BaseModel): @@ -57,10 +57,25 @@ def check_sample_sizes(cls, value): @field_validator("monte_carlo_count") @classmethod def check_monte_carlo(cls, value): - if value <= 100: + if value < 100: raise ValueError("Monte Carlo count must be greater than 100.") return value + @model_validator(mode="after") + def validate_using_criteria_config(self) -> "BaseExperimentConfig": + try: + data_to_validate = { + "hypothesis": self.hypothesis, + "criteria": self.criteria, + } + CriteriaConfig.model_validate(data_to_validate) + + except ValidationError as e: + error_message = e.errors()[0]["msg"] + raise ValueError(error_message) + + return self + class PowerConfig(BaseExperimentConfig): """ From a1ab0dc7551dda4ed4447b1a5fdb76f20ad27f7d Mon Sep 17 00:00:00 2001 From: faux66 Date: Wed, 8 Oct 2025 18:00:40 +0300 Subject: [PATCH 07/17] feat: add error handling --- .../configure/alternatives/alternatives.py | 20 ++++++++++++++++--- .../commands/build_and_run/build_and_run.py | 13 ++++++++++-- .../validation/cli/schemas/alternative.py | 4 ++-- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/pysatl_experiment/cli/commands/configure/alternatives/alternatives.py b/pysatl_experiment/cli/commands/configure/alternatives/alternatives.py index c91e859..360a851 100644 --- a/pysatl_experiment/cli/commands/configure/alternatives/alternatives.py +++ b/pysatl_experiment/cli/commands/configure/alternatives/alternatives.py @@ -42,11 +42,25 @@ def alternatives(ctx: Context, alt: tuple[str]) -> None: validated_config = AlternativesConfig(experiment_type=experiment_type, alternatives=list(alt)) alternatives_data = validated_config.model_dump().get("alternatives", []) - except ValidationError as e: - raise ClickException(str(e)) + error_messages = [] + + for error in e.errors(): + if error["loc"] and error["loc"][0] == "alternatives": + if len(error["loc"]) > 1: + index = error["loc"][1] + user_input = alt[index] + msg = f"For alternative #{index + 1} ('{user_input}'): {error['msg']}" + error_messages.append(msg) + else: + error_messages.append(f"- {error['msg']}") + else: + field = " -> ".join(map(str, error["loc"])) + error_messages.append(f"In field '{field}': {error['msg']}") + + final_message = "\n" + "\n".join(error_messages) - experiment_config["alternatives"] = alternatives_data + raise ClickException(final_message) save_experiment_config(ctx, experiment_name, experiment_config) diff --git a/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run.py b/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run.py index 6cc4cf4..e18b87a 100644 --- a/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run.py +++ b/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run.py @@ -61,8 +61,17 @@ def validate_build_and_run(experiment_data_dict: dict) -> ExperimentData: try: validated_data = ExperimentInputSchema.model_validate(experiment_data_dict) except ValidationError as e: - raise ClickException(str(e)) - + error_messages = [] + for error in e.errors(): + if error["type"] == "missing": + field_path = ".".join(map(str, error["loc"])) + error_messages.append(f"A required parameter is missing: '{field_path}'") + else: + field_path = ".".join(map(str, error["loc"])) + error_messages.append(f"Error in the field '{field_path}': {error['msg']}") + + final_error_message = "\n".join(error_messages) + raise ClickException(final_error_message) experiment_name = validated_data.name pydantic_config = validated_data.config diff --git a/pysatl_experiment/validation/cli/schemas/alternative.py b/pysatl_experiment/validation/cli/schemas/alternative.py index 7e3a27f..5f33035 100644 --- a/pysatl_experiment/validation/cli/schemas/alternative.py +++ b/pysatl_experiment/validation/cli/schemas/alternative.py @@ -44,7 +44,7 @@ def normalize_and_resolve_generator_name(cls, value): if not matches: raise ValueError( - f"Generator prefix '{value}' did not match any available generators. " + f"Generator prefix '{value}' did not match any available generators.\n" f"Available are: [{', '.join(available_generators)}]" ) else: @@ -80,7 +80,7 @@ def validate_generator_logic(self): if not generator_cls: available_generators = ", ".join(generator_by_name.keys()) raise ValueError( - f"Generator '{self.generator_name}' is not found. Available generators are: [{available_generators}]" + f"Generator '{self.generator_name}' is not found.\n Available generators are: [{available_generators}]" ) base_params = set(inspect.signature(AbstractRVSGenerator.__init__).parameters.keys()) From 89bcc5175c073caa1d5a037cf8f092eaf6128967 Mon Sep 17 00:00:00 2001 From: faux66 Date: Thu, 9 Oct 2025 14:53:14 +0300 Subject: [PATCH 08/17] fix: power report --- .../step/report_building/power/power.py | 6 +++- pysatl_experiment/report/power/power.py | 28 +++++++++++-------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/pysatl_experiment/experiment_new/step/report_building/power/power.py b/pysatl_experiment/experiment_new/step/report_building/power/power.py index 23f0e1e..272eeb0 100644 --- a/pysatl_experiment/experiment_new/step/report_building/power/power.py +++ b/pysatl_experiment/experiment_new/step/report_building/power/power.py @@ -73,7 +73,11 @@ def _collect_statistics(self) -> dict[str, dict[tuple[str, float], dict[int, lis significance_level=significance_level, ) key = (alternative.generator_name, significance_level) - power_data[criterion_config.criterion_code][key][sample_size] = result + + level1_dict = power_data.setdefault(criterion_config.criterion_code, {}) + level2_dict = level1_dict.setdefault(key, {}) + level2_dict[sample_size] = result + return power_data def _get_power_result_from_storage( diff --git a/pysatl_experiment/report/power/power.py b/pysatl_experiment/report/power/power.py index 16ffefe..9f7a372 100644 --- a/pysatl_experiment/report/power/power.py +++ b/pysatl_experiment/report/power/power.py @@ -82,7 +82,7 @@ def _generate_html(self, charts_dir: Path) -> str: } ) - html = self.template_env.get_template("power_report.html").render( + html = self.template_env.get_template("power_template.html").render( tables=tables, criteria=get_criterion_names(self.criteria_config), sample_sizes=self.sample_sizes, @@ -94,25 +94,30 @@ def _generate_table_data( self, alternative: Alternative, significance_level: float, - ) -> list[dict]: + ) -> dict[int, dict[str, float]]: """ - Generate table for one (alternative, alpha) pair. + Generate data for the power table. - :param alternative: alternative to generate tables for. - :param significance_level: significance level. - - :return: list of dictionaries. + :param alternative: The alternative for which to generate the table. + :param significance_level: The significance level for which to generate the table. + :return: A dictionary with table data, where keys are sample sizes + and values are dictionaries of power for each criterion. """ - table_data = [] + table_data = {} for size in self.sample_sizes: - data: dict[str, object] = {"size": size} + row_data: dict[str, float] = {} + for config in self.criteria_config: key = (alternative.generator_name, significance_level) results = self.power_result[config.criterion_code].get(key, {}).get(size, []) power = np.mean(results) if results else 0.0 - data[config.criterion_code.partition("_")[0]] = round(power, 3) - table_data.append(data) + + short_criterion_name = config.criterion_code.partition("_")[0] + row_data[short_criterion_name] = round(power, 3) + + table_data[size] = row_data + return table_data def _generate_chart_data( @@ -130,6 +135,7 @@ def _generate_chart_data( :return: path to chart file. """ + charts_dir.mkdir(parents=True, exist_ok=True) chart_path = charts_dir / f"{alternative.generator_name}_{significance_level}.png" From f887fa5ad67eedb55e1ac04f77fc6dd20f0ad592 Mon Sep 17 00:00:00 2001 From: faux66 Date: Thu, 9 Oct 2025 14:55:33 +0300 Subject: [PATCH 09/17] fix: alternative command --- .../cli/commands/configure/alternatives/alternatives.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pysatl_experiment/cli/commands/configure/alternatives/alternatives.py b/pysatl_experiment/cli/commands/configure/alternatives/alternatives.py index 360a851..1966319 100644 --- a/pysatl_experiment/cli/commands/configure/alternatives/alternatives.py +++ b/pysatl_experiment/cli/commands/configure/alternatives/alternatives.py @@ -62,6 +62,8 @@ def alternatives(ctx: Context, alt: tuple[str]) -> None: raise ClickException(final_message) + experiment_config["alternatives"] = alternatives_data + save_experiment_config(ctx, experiment_name, experiment_config) echo(f"Alternatives of the experiment '{experiment_name}' are successfully set.") From 211271ff4038d84d0edae2f267eb24ff0508678e Mon Sep 17 00:00:00 2001 From: faux66 Date: Thu, 9 Oct 2025 15:30:53 +0300 Subject: [PATCH 10/17] feat: add validation for cv data dependency --- .../commands/build_and_run/build_and_run.py | 42 +++++++--- .../validation/cli/commands/common/checker.py | 76 +++++++++++++++++++ .../validation/cli/schemas/experiment.py | 46 ++++++++++- 3 files changed, 153 insertions(+), 11 deletions(-) create mode 100644 pysatl_experiment/validation/cli/commands/common/checker.py diff --git a/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run.py b/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run.py index e18b87a..93a5db8 100644 --- a/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run.py +++ b/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run.py @@ -28,6 +28,7 @@ ExperimentQuery, IExperimentStorage, ) +from pysatl_experiment.validation.cli.commands.common.checker import SQLiteCriticalValueChecker from pysatl_experiment.validation.cli.schemas.experiment import BaseExperimentConfig as PydanticBaseExperiment from pysatl_experiment.validation.cli.schemas.experiment import CriticalValueConfig as PydanticCriticalValueConfig from pysatl_experiment.validation.cli.schemas.experiment import ExperimentConfig as ExperimentInputSchema @@ -40,30 +41,50 @@ def validate_build_and_run(experiment_data_dict: dict) -> ExperimentData: Validates input, initializes, and builds the experiment data object. This function performs the following steps: - 1. Validates the raw input dictionary against Pydantic schemas. - 2. Adapts the modern Pydantic models to legacy dataclass configurations. - 3. Initializes the SQLite storage backend. - 4. Checks if an identical experiment already exists in storage to resume it. - 5. If not, it saves the new experiment configuration. - 6. Creates a results path for experiment artifacts. - 7. Returns a complete `ExperimentData` object to be used by the runner. + 1. Conditionally creates a database checker if the experiment is a 'power' + analysis. + 2. Validates the raw input dictionary against Pydantic schemas, passing the + database checker in the context to allow for stateful validation (e.g., + ensuring required critical values exist). + 3. Adapts the validated Pydantic models to legacy dataclass configurations. + 4. Initializes the SQLite storage backend. + 5. Checks if an identical experiment already exists in storage to resume it. + 6. If not, it saves the new experiment configuration to the database. + 7. Creates a results path for experiment artifacts. + 8. Returns a complete `ExperimentData` object to be used by the runner. Args: experiment_data_dict: A dictionary containing the raw experiment configuration. Raises: - ClickException: If validation fails or if the experiment has already + ClickException: If validation fails (with detailed, user-friendly error + messages for each invalid field) or if the experiment has already been completed. Returns: An `ExperimentData` object ready for the experiment execution pipeline. """ try: - validated_data = ExperimentInputSchema.model_validate(experiment_data_dict) + checker = None + config_dict = experiment_data_dict.get("config", {}) + + if config_dict.get("experiment_type") == "power": + connection_str = config_dict.get("storage_connection") + if not connection_str: + pass + else: + checker = SQLiteCriticalValueChecker(connection_string=connection_str) + + validation_context = {"critical_value_checker": checker} if checker else {} + + validated_data = ExperimentInputSchema.model_validate(experiment_data_dict, context=validation_context) + except ValidationError as e: error_messages = [] for error in e.errors(): - if error["type"] == "missing": + if error["type"] == "value_error": + error_messages.append(error["msg"]) + elif error["type"] == "missing": field_path = ".".join(map(str, error["loc"])) error_messages.append(f"A required parameter is missing: '{field_path}'") else: @@ -72,6 +93,7 @@ def validate_build_and_run(experiment_data_dict: dict) -> ExperimentData: final_error_message = "\n".join(error_messages) raise ClickException(final_error_message) + experiment_name = validated_data.name pydantic_config = validated_data.config diff --git a/pysatl_experiment/validation/cli/commands/common/checker.py b/pysatl_experiment/validation/cli/commands/common/checker.py new file mode 100644 index 0000000..cadf977 --- /dev/null +++ b/pysatl_experiment/validation/cli/commands/common/checker.py @@ -0,0 +1,76 @@ +import sqlite3 + + +class SQLiteCriticalValueChecker: + """ + A utility class to check for the existence of pre-calculated + critical values in an SQLite database. + + This class connects to a specific SQLite database and provides a method + to query if a result for a given hypothesis, criterion, and sample size + has already been stored. + """ + + def __init__(self, connection_string: str): + """ + Initializes the checker and connects to the SQLite database. + + Args: + connection_string (str): The file path or connection string for the + SQLite database. + + Raises: + ConnectionError: If the connection to the database fails. + """ + self.connection_string = connection_string + self.connection = None + try: + self.connection = sqlite3.connect(self.connection_string) + except sqlite3.Error as e: + raise ConnectionError(f"Failed to connect to the database '{self.connection_string}': {e}") + + def check_exists(self, hypothesis: str, criterion_code: str, sample_size: int) -> bool: + """ + Checks if a critical value for a specific parameter set exists in the DB. + + Args: + hypothesis (str): The statistical hypothesis (e.g., "NORMAL"). + criterion_code (str): The short code for the statistical criterion (e.g., "KS"). + sample_size (int): The sample size used for the calculation. + + Returns: + bool: True if a matching record exists, False otherwise. + + Raises: + sqlite3.Error: If a critical error occurs during the SQL query execution. + """ + if self.connection is None: + return False + + sql_query = """ + SELECT EXISTS ( + SELECT 1 + FROM limit_distributions ld + JOIN experiments e ON ld.experiment_id = e.id + WHERE UPPER(e.hypothesis) = ? + AND ld.criterion_code = ? + AND ld.sample_size = ? + ) + """ + params = (hypothesis.upper(), criterion_code, sample_size) + + try: + cursor = self.connection.cursor() + cursor.execute(sql_query, params) + row = cursor.fetchone() + if row: + return row[0] == 1 + return False + except sqlite3.Error as e: + print(f"A critical error occurred during SQL execution in check_exists: {e}") + raise + + def close(self): + """Closes the connection to the database.""" + if self.connection: + self.connection.close() diff --git a/pysatl_experiment/validation/cli/schemas/experiment.py b/pysatl_experiment/validation/cli/schemas/experiment.py index e2bb50c..e130400 100644 --- a/pysatl_experiment/validation/cli/schemas/experiment.py +++ b/pysatl_experiment/validation/cli/schemas/experiment.py @@ -1,11 +1,12 @@ from typing import Literal, Union -from pydantic import BaseModel, Field, ValidationError, field_validator, model_validator +from pydantic import BaseModel, Field, ValidationError, ValidationInfo, field_validator, model_validator from pysatl_experiment.configuration.model.hypothesis.hypothesis import Hypothesis from pysatl_experiment.configuration.model.report_mode.report_mode import ReportMode from pysatl_experiment.configuration.model.run_mode.run_mode import RunMode from pysatl_experiment.configuration.model.step_type.step_type import StepType +from pysatl_experiment.validation.cli.commands.common.checker import SQLiteCriticalValueChecker from pysatl_experiment.validation.cli.schemas.alternative import Alternative from pysatl_experiment.validation.cli.schemas.criteria import CriteriaConfig, Criterion @@ -94,6 +95,49 @@ class PowerConfig(BaseExperimentConfig): alternatives: list[Alternative] significance_levels: list[float] + @model_validator(mode="after") + def validate_dependencies_on_critical_values(self, info: ValidationInfo) -> "PowerConfig": + if not info.context or "critical_value_checker" not in info.context: + raise ValueError("CriticalValueChecker must be provided in the validation context.") + + checker: SQLiteCriticalValueChecker = info.context["critical_value_checker"] + missing_combinations = [] + + hypothesis_name_map = { + "NORMAL": "NORMALITY", + "EXPONENTIAL": "EXPONENTIALITY", + "WEIBULL": "WEIBULL", + } + family_part = "GOODNESS_OF_FIT" + hypothesis_part = hypothesis_name_map.get(self.hypothesis.name) + + if not hypothesis_part: + raise ValueError(f"Unknown hypothesis '{self.hypothesis.name}' for constructing criterion name.") + + for criterion in self.criteria: + for size in self.sample_sizes: + full_name_to_check = f"{criterion.criterion_code.upper()}_{hypothesis_part}_{family_part}" + + if not checker.check_exists(self.hypothesis.name, full_name_to_check, size): + for alpha in self.significance_levels: + missing_combinations.append( + f" - Hypothesis: {self.hypothesis.name}, " + f"Criterion: {criterion.criterion_code}, " + f"Sample Size: {size}, " + f"Significance: {alpha}" + ) + + if missing_combinations: + unique_missing = sorted(list(set(missing_combinations))) + error_message = ( + "Power experiment cannot be run because the following critical values are missing.\n" + "Please run a 'critical_value' experiment for them first:\n" + ) + error_message += "\n".join(unique_missing) + raise ValueError(error_message) + + return self + class CriticalValueConfig(BaseExperimentConfig): """ From 1d18718ea92477b1642c771aa820aaff27a727e1 Mon Sep 17 00:00:00 2001 From: faux66 Date: Thu, 9 Oct 2025 18:18:37 +0300 Subject: [PATCH 11/17] add tests --- .../configure/hypothesis/hypothesis.py | 4 +- .../validation/configure/test_alternative.py | 176 ++++++++++++++++++ tests/validation/configure/test_criteria.py | 120 ++++++++++++ .../configure/test_executor_type.py | 108 +++++++++++ .../configure/test_experiment_type.py | 82 ++++++++ .../configure/test_generator_type.py | 108 +++++++++++ tests/validation/configure/test_hypothesis.py | 102 ++++++++++ .../configure/test_report_builder_type.py | 114 ++++++++++++ .../validation/configure/test_report_mode.py | 87 +++++++++ tests/validation/configure/test_run_mode.py | 84 +++++++++ 10 files changed, 983 insertions(+), 2 deletions(-) create mode 100644 tests/validation/configure/test_alternative.py create mode 100644 tests/validation/configure/test_criteria.py create mode 100644 tests/validation/configure/test_executor_type.py create mode 100644 tests/validation/configure/test_experiment_type.py create mode 100644 tests/validation/configure/test_generator_type.py create mode 100644 tests/validation/configure/test_hypothesis.py create mode 100644 tests/validation/configure/test_report_builder_type.py create mode 100644 tests/validation/configure/test_report_mode.py create mode 100644 tests/validation/configure/test_run_mode.py diff --git a/pysatl_experiment/cli/commands/configure/hypothesis/hypothesis.py b/pysatl_experiment/cli/commands/configure/hypothesis/hypothesis.py index fdf7090..b61e7d9 100644 --- a/pysatl_experiment/cli/commands/configure/hypothesis/hypothesis.py +++ b/pysatl_experiment/cli/commands/configure/hypothesis/hypothesis.py @@ -28,7 +28,7 @@ def hypothesis(ctx: Context, hyp: str) -> None: Args: ctx: The Click context object, passed automatically. - hyp: The desired hypothesis (e.g., 'normal'). The value must + hyp: The desired hypothesis (e.g., 'normal'). The value must match one of the predefined types in `Hypothesis` and is case-insensitive. """ @@ -49,6 +49,6 @@ def hypothesis(ctx: Context, hyp: str) -> None: save_experiment_config(ctx, experiment_name, experiment_config) echo( - f"Hypothesis of the experiment '{experiment_name}' is set to '{validated_hypothesis}'.\n" + f"Hypothesis of the experiment '{experiment_name}' is set to '{validated_hypothesis.value}'.\n" f"Likewise, all criteria for the hypothesis '{validated_hypothesis.value}' are set." ) diff --git a/tests/validation/configure/test_alternative.py b/tests/validation/configure/test_alternative.py new file mode 100644 index 0000000..ecd77b4 --- /dev/null +++ b/tests/validation/configure/test_alternative.py @@ -0,0 +1,176 @@ +from unittest.mock import MagicMock, patch + +import pytest +from click.testing import CliRunner + +from pysatl_experiment.cli.commands.configure.alternatives.alternatives import alternatives +from pysatl_experiment.configuration.model.experiment_type.experiment_type import ExperimentType +from pysatl_experiment.experiment.generator import AbstractRVSGenerator + + +class NormalGenerator(AbstractRVSGenerator): + def __init__(self, loc: float, scale: float, **kwargs): + super().__init__(**kwargs) + self.loc = loc + self.scale = scale + + +class CauchyGenerator(AbstractRVSGenerator): + def __init__(self, x0: float, gamma: float, **kwargs): + super().__init__(**kwargs) + self.x0 = x0 + self.gamma = gamma + + +class NormalDistribution(AbstractRVSGenerator): + def __init__(self, mean: float, std: float, **kwargs): + super().__init__(**kwargs) + self.mean = mean + self.std = std + + +@pytest.fixture +def runner() -> CliRunner: + """Fixture to create a CliRunner instance.""" + return CliRunner() + + +@patch("pysatl_experiment.cli.commands.configure.alternatives.alternatives.save_experiment_config") +@patch("pysatl_experiment.cli.commands.configure.alternatives.alternatives.get_experiment_name_and_config") +def test_alternatives_fails_if_experiment_type_not_set( + mock_get_config: MagicMock, mock_save_config: MagicMock, runner: CliRunner +) -> None: + experiment_name = "my-exp" + mock_get_config.return_value = (experiment_name, {}) + + result = runner.invoke(alternatives, ["--alt", "Normal 1 1"]) + + assert result.exit_code != 0 + assert isinstance(result.exception, SystemExit) + assert "Experiment type is not configured" in result.output + mock_save_config.assert_not_called() + + +@patch( + "pysatl_experiment.validation.cli.schemas.alternative.AbstractRVSGenerator.__subclasses__", + return_value=[NormalGenerator], +) +@patch("pysatl_experiment.cli.commands.configure.alternatives.alternatives.save_experiment_config") +@patch("pysatl_experiment.cli.commands.configure.alternatives.alternatives.get_experiment_name_and_config") +def test_alternatives_fails_for_unsupported_experiment_type( + mock_get_config: MagicMock, mock_save_config: MagicMock, mock_subclasses: MagicMock, runner: CliRunner +) -> None: + """ + Tests that the command fails if alternatives are provided for a non-POWER experiment. + """ + mock_get_config.return_value = ("my-exp", {"experiment_type": ExperimentType.CRITICAL_VALUE.value}) + + result = runner.invoke(alternatives, ["--alt", "Normal 1 1"]) + + assert result.exit_code != 0 + assert "Alternatives are not supported for the experiment type 'critical_value'" in result.output + mock_save_config.assert_not_called() + + +@patch( + "pysatl_experiment.validation.cli.schemas.alternative.AbstractRVSGenerator.__subclasses__", + return_value=[NormalGenerator], +) +@patch("pysatl_experiment.cli.commands.configure.alternatives.alternatives.save_experiment_config") +@patch("pysatl_experiment.cli.commands.configure.alternatives.alternatives.get_experiment_name_and_config") +def test_alternatives_fails_with_wrong_parameter_count( + mock_get_config: MagicMock, mock_save_config: MagicMock, mock_subclasses: MagicMock, runner: CliRunner +) -> None: + mock_get_config.return_value = ("my-exp", {"experiment_type": "power"}) + result = runner.invoke(alternatives, ["--alt", "Normal 1.0"]) + + assert result.exit_code != 0 + expected_error = ( + "For alternative #1 ('Normal 1.0'): Value error, " + "Generator 'NORMALGENERATOR' expects 2 unique parameters (loc, scale), but received 1." + ) + assert expected_error in result.output + mock_save_config.assert_not_called() + + +@patch( + "pysatl_experiment.validation.cli.schemas.alternative.AbstractRVSGenerator.__subclasses__", + return_value=[NormalGenerator], +) +@patch("pysatl_experiment.cli.commands.configure.alternatives.alternatives.save_experiment_config") +@patch("pysatl_experiment.cli.commands.configure.alternatives.alternatives.get_experiment_name_and_config") +def test_alternatives_fails_with_non_numeric_parameters( + mock_get_config: MagicMock, mock_save_config: MagicMock, mock_subclasses: MagicMock, runner: CliRunner +) -> None: + mock_get_config.return_value = ("my-exp", {"experiment_type": "power"}) + result = runner.invoke(alternatives, ["--alt", "Normal 1.0 abc"]) + + assert result.exit_code != 0 + expected_error = ( + "For alternative #1 ('Normal 1.0 abc'): Value error, All parameters for generator 'Normal' must be numbers." + ) + assert expected_error in result.output + mock_save_config.assert_not_called() + + +@patch( + "pysatl_experiment.validation.cli.schemas.alternative.AbstractRVSGenerator.__subclasses__", + return_value=[NormalGenerator, NormalDistribution], # type: ignore +) +@patch("pysatl_experiment.cli.commands.configure.alternatives.alternatives.save_experiment_config") +@patch("pysatl_experiment.cli.commands.configure.alternatives.alternatives.get_experiment_name_and_config") +def test_alternatives_fails_with_ambiguous_generator_name( + mock_get_config: MagicMock, mock_save_config: MagicMock, mock_subclasses: MagicMock, runner: CliRunner +) -> None: + """ + Tests failure when a generator prefix matches multiple available generators. + """ + mock_get_config.return_value = ("my-exp", {"experiment_type": "power"}) + result = runner.invoke(alternatives, ["--alt", "Normal 1 2"]) + + assert result.exit_code != 0 + + output = result.output + + assert "For alternative #1 ('Normal 1 2')" in output + assert "Generator prefix 'Normal' is ambiguous" in output + assert "NORMALGENERATOR" in output + assert "NORMALDISTRIBUTION" in output + assert "Please be more specific" in output + + mock_save_config.assert_not_called() + + +@patch( + "pysatl_experiment.validation.cli.schemas.alternative.AbstractRVSGenerator.__subclasses__", + return_value=[NormalGenerator, CauchyGenerator], # type: ignore +) +@patch("pysatl_experiment.cli.commands.configure.alternatives.alternatives.save_experiment_config") +@patch("pysatl_experiment.cli.commands.configure.alternatives.alternatives.get_experiment_name_and_config") +def test_alternatives_success_with_valid_inputs( + mock_get_config: MagicMock, mock_save_config: MagicMock, mock_subclasses: MagicMock, runner: CliRunner +) -> None: + experiment_name = "my-power-exp" + initial_config = {"experiment_type": "power"} + mock_get_config.return_value = (experiment_name, initial_config.copy()) + + result = runner.invoke(alternatives, ["--alt", "NormalG 1.0 0.5", "--alt", "cauchy 0 2"]) + + assert result.exit_code == 0 + assert result.exception is None + + mock_save_config.assert_called_once() + + saved_config = mock_save_config.call_args[0][2] + + assert "alternatives" in saved_config + assert len(saved_config["alternatives"]) == 2 + assert saved_config["alternatives"][0]["generator_name"] == "NORMALGENERATOR" + assert saved_config["alternatives"][0]["parameters"] == [1.0, 0.5] + assert saved_config["alternatives"][1]["generator_name"] == "CAUCHYGENERATOR" + assert saved_config["alternatives"][1]["parameters"] == [0.0, 2.0] + + assert f"Alternatives of the experiment '{experiment_name}' are successfully set." in result.output + assert "Configured alternatives:" in result.output + assert " - NORMALGENERATOR 1.0 0.5" in result.output + assert " - CAUCHYGENERATOR 0.0 2.0" in result.output diff --git a/tests/validation/configure/test_criteria.py b/tests/validation/configure/test_criteria.py new file mode 100644 index 0000000..642d0fe --- /dev/null +++ b/tests/validation/configure/test_criteria.py @@ -0,0 +1,120 @@ +from unittest.mock import MagicMock, patch + +import pytest +from click.testing import CliRunner + +from pysatl_experiment.cli.commands.configure.criteria.criteria import criteria +from pysatl_experiment.configuration.model.hypothesis.hypothesis import Hypothesis + + +@pytest.fixture +def runner() -> CliRunner: + """Fixture to create a CliRunner instance.""" + return CliRunner() + + +@patch("pysatl_experiment.cli.commands.configure.criteria.criteria.save_experiment_config") +@patch("pysatl_experiment.cli.commands.configure.criteria.criteria.get_experiment_name_and_config") +def test_criteria_fails_if_hypothesis_not_set( + mock_get_config: MagicMock, mock_save_config: MagicMock, runner: CliRunner +) -> None: + """ + Tests that the `criteria` command fails if the hypothesis is not yet configured. + + This test verifies the initial precondition check within the command by: + 1. Simulating a configuration that lacks a 'hypothesis' key. + 2. Asserting that the command exits with a non-zero code. + 3. Confirming that a `ClickException` is raised with the correct instructional message. + 4. Ensuring that no attempt is made to save the configuration. + """ + experiment_name = "my-exp" + mock_get_config.return_value = (experiment_name, {}) + + result = runner.invoke(criteria, ["KS", "AD"]) + + assert result.exit_code != 0 + assert isinstance(result.exception, SystemExit) + + assert "Hypothesis is not configured" in result.output + assert f"experiment configure {experiment_name} hypothesis " in result.output + mock_save_config.assert_not_called() + + +@patch("pysatl_experiment.validation.cli.schemas.criteria.get_statistics_short_codes_for_hypothesis") +@patch("pysatl_experiment.cli.commands.configure.criteria.criteria.save_experiment_config") +@patch("pysatl_experiment.cli.commands.configure.criteria.criteria.get_experiment_name_and_config") +def test_criteria_fails_with_incompatible_codes( + mock_get_config: MagicMock, mock_save_config: MagicMock, mock_get_valid_codes: MagicMock, runner: CliRunner +) -> None: + """ + Tests that the command fails when provided criteria are incompatible with the hypothesis. + + This test verifies the integration with the `CriteriaConfig` Pydantic model by: + 1. Providing a configuration with a set hypothesis. + 2. Mocking the helper function to return a list of allowed criteria codes. + 3. Invoking the command with a mix of valid and invalid codes. + 4. Asserting that the `ValidationError` from Pydantic is caught and converted + into a user-friendly `BadParameter` error message. + 5. Ensuring that the configuration is not saved. + """ + hypothesis = Hypothesis.NORMAL + mock_get_config.return_value = ("my-exp", {"hypothesis": hypothesis.value}) + mock_get_valid_codes.return_value = ["KS", "AD"] + + result = runner.invoke(criteria, ["KS", "CVM"]) + + assert result.exit_code != 0 + assert isinstance(result.exception, SystemExit) + + assert f"Criteria 'CVM' are incompatible with hypothesis '{hypothesis.value}'" in result.output + assert "Valid codes: KS, AD" in result.output + + mock_save_config.assert_not_called() + + +@patch("pysatl_experiment.validation.cli.schemas.criteria.get_statistics_short_codes_for_hypothesis") +@patch("pysatl_experiment.cli.commands.configure.criteria.criteria.save_experiment_config") +@patch("pysatl_experiment.cli.commands.configure.criteria.criteria.get_experiment_name_and_config") +def test_criteria_success_with_valid_codes( + mock_get_config: MagicMock, mock_save_config: MagicMock, mock_get_valid_codes: MagicMock, runner: CliRunner +) -> None: + """ + Tests the successful execution of the `criteria` command with valid codes. + + This test verifies the "happy path" by: + 1. Providing a configuration with a set hypothesis. + 2. Mocking the helper to return codes that match the input. + 3. Invoking the command with valid codes (using lowercase to test normalization). + 4. Asserting that the command exits with a success code. + 5. Verifying that the configuration to be saved is correctly updated with the + validated and normalized (uppercased) criteria list. + 6. Checking for the correct success message in the output. + """ + experiment_name = "my-exp" + hypothesis = Hypothesis.NORMAL + initial_config = {"hypothesis": hypothesis.value} + mock_get_config.return_value = (experiment_name, initial_config.copy()) + + valid_codes_for_hypothesis = ["KS", "AD", "SW"] + mock_get_valid_codes.return_value = valid_codes_for_hypothesis + + input_codes = ["ad", "ks"] + result = runner.invoke(criteria, input_codes) + + assert result.exit_code == 0 + assert result.exception is None + + mock_get_valid_codes.assert_called_once_with(hypothesis.value) + + mock_save_config.assert_called_once() + + saved_config = mock_save_config.call_args[0][2] + + assert "criteria" in saved_config + assert len(saved_config["criteria"]) == 2 + + saved_codes = [c["criterion_code"] for c in saved_config["criteria"]] + assert "AD" in saved_codes + assert "KS" in saved_codes + + assert f"Criteria for experiment '{experiment_name}' successfully set: ['AD', 'KS']" in result.output diff --git a/tests/validation/configure/test_executor_type.py b/tests/validation/configure/test_executor_type.py new file mode 100644 index 0000000..8a57cdd --- /dev/null +++ b/tests/validation/configure/test_executor_type.py @@ -0,0 +1,108 @@ +from unittest.mock import ANY, MagicMock, patch + +import pytest +from click.testing import CliRunner + +from pysatl_experiment.cli.commands.configure.executor_type.executor_type import executor_type +from pysatl_experiment.configuration.model.step_type.step_type import StepType + + +@pytest.fixture +def runner() -> CliRunner: + """Fixture to create a CliRunner instance.""" + return CliRunner() + + +@patch("pysatl_experiment.cli.commands.configure.executor_type.executor_type.get_experiment_name_and_config") +@patch("pysatl_experiment.cli.commands.configure.executor_type.executor_type.save_experiment_config") +def test_executor_type_with_invalid_type( + mock_save_config: MagicMock, mock_get_config: MagicMock, runner: CliRunner +) -> None: + """ + Tests the `executor_type` command with a completely invalid type string. + + This test verifies that when the command is invoked with a string + that does not correspond to any valid `StepType` enum value, it behaves + correctly by: + 1. Exiting with a non-zero status code. + 2. Printing an error message that includes the invalid input and lists + the valid options. + 3. Not attempting to get or save the experiment configuration, as the + error occurs during initial validation. + """ + invalid_type = "this-is-not-a-valid-type" + + result = runner.invoke(executor_type, [invalid_type]) + + assert result.exit_code != 0 + assert isinstance(result.exception, SystemExit) + + output = result.output + assert f"Type of '{invalid_type}' is not valid." in output + valid_options = [e.value for e in StepType] + assert f"Possible values are: {valid_options}" in output + + mock_get_config.assert_not_called() + mock_save_config.assert_not_called() + + +@patch("pysatl_experiment.cli.commands.configure.executor_type.executor_type.get_experiment_name_and_config") +@patch("pysatl_experiment.cli.commands.configure.executor_type.executor_type.save_experiment_config") +def test_executor_type_with_unsupported_custom_type( + mock_save_config: MagicMock, mock_get_config: MagicMock, runner: CliRunner +) -> None: + """ + Tests the `executor_type` command with the 'custom' type, which is unsupported. + + This test verifies that the specific logic check preventing the use of the + `StepType.CUSTOM` value works correctly by: + 1. Exiting with a non-zero status code. + 2. Printing the specific error message for the unsupported 'custom' type. + 3. Not attempting to get or save the experiment configuration. + """ + custom_type = StepType.CUSTOM.value + + result = runner.invoke(executor_type, [custom_type]) + + assert result.exit_code != 0 + assert isinstance(result.exception, SystemExit) + + assert "Custom type is not supported yet." in result.output + + mock_get_config.assert_not_called() + mock_save_config.assert_not_called() + + +@patch("pysatl_experiment.cli.commands.configure.executor_type.executor_type.get_experiment_name_and_config") +@patch("pysatl_experiment.cli.commands.configure.executor_type.executor_type.save_experiment_config") +@pytest.mark.parametrize("valid_type", [e for e in StepType if e != StepType.CUSTOM]) +def test_executor_type_with_valid_supported_type( + mock_save_config: MagicMock, mock_get_config: MagicMock, runner: CliRunner, valid_type: StepType +) -> None: + """ + Tests the `executor_type` command logic with all valid and supported arguments. + + This test verifies that when the command is invoked with any supported `StepType` + enum value, it behaves correctly by: + 1. Exiting with a zero status code for success. + 2. Calling the functions to get and save the configuration exactly once. + 3. Updating the configuration dictionary with the correct key and value. + 4. Printing a confirmation message to the user. + """ + experiment_name = "my-test-experiment" + initial_config = {"some_key": "some_value"} + mock_get_config.return_value = (experiment_name, initial_config.copy()) + + result = runner.invoke(executor_type, [valid_type.value]) + + assert result.exit_code == 0 + assert result.exception is None + + mock_get_config.assert_called_once() + + expected_config = initial_config.copy() + expected_config["executor_type"] = valid_type.value + mock_save_config.assert_called_once_with(ANY, experiment_name, expected_config) + + expected_output = f"Executor type of the experiment '{experiment_name}' is set to '{valid_type.value}'.\n" + assert result.output == expected_output diff --git a/tests/validation/configure/test_experiment_type.py b/tests/validation/configure/test_experiment_type.py new file mode 100644 index 0000000..4ccc3e4 --- /dev/null +++ b/tests/validation/configure/test_experiment_type.py @@ -0,0 +1,82 @@ +from unittest.mock import ANY, MagicMock, patch + +import pytest +from click.testing import CliRunner + +from pysatl_experiment.cli.commands.configure.experiment_type.experiment_type import experiment_type +from pysatl_experiment.configuration.model.experiment_type.experiment_type import ExperimentType + + +@pytest.fixture +def runner() -> CliRunner: + """Fixture to create a CliRunner instance.""" + return CliRunner() + + +@patch("pysatl_experiment.cli.commands.configure.experiment_type.experiment_type.get_experiment_name_and_config") +@patch("pysatl_experiment.cli.commands.configure.experiment_type.experiment_type.save_experiment_config") +def test_experiment_type_with_invalid_type( + mock_save_config: MagicMock, mock_get_config: MagicMock, runner: CliRunner +) -> None: + """ + Tests the `experiment_type` command with an invalid type string. + + This test verifies that when the command is invoked with a string that + does not correspond to any valid `ExperimentType` enum value, it behaves + correctly by: + 1. Exiting with a non-zero status code. + 2. Printing an error message that includes the invalid input and lists + the valid options. + 3. Not calling the function to save the configuration. + """ + invalid_type = "this-is-not-a-valid-type" + mock_get_config.return_value = ("my-experiment", {}) + + result = runner.invoke(experiment_type, [invalid_type]) + + mock_get_config.assert_called_once() + + assert result.exit_code != 0 + assert isinstance(result.exception, SystemExit) + + output = result.output + assert f"Type of '{invalid_type}' is not valid." in output + valid_options = [e.value for e in ExperimentType] + assert f"Possible values are: {valid_options}" in output + + mock_save_config.assert_not_called() + + +@patch("pysatl_experiment.cli.commands.configure.experiment_type.experiment_type.get_experiment_name_and_config") +@patch("pysatl_experiment.cli.commands.configure.experiment_type.experiment_type.save_experiment_config") +@pytest.mark.parametrize("valid_type", [e for e in ExperimentType]) +def test_experiment_type_with_valid_type( + mock_save_config: MagicMock, mock_get_config: MagicMock, runner: CliRunner, valid_type: ExperimentType +) -> None: + """ + Tests the `experiment_type` command logic with all valid arguments. + + This test verifies that when the command is invoked with any valid + `ExperimentType` enum value, it behaves correctly by: + 1. Exiting with a zero status code for success. + 2. Calling the functions to get and save the configuration exactly once. + 3. Updating the configuration dictionary with the correct key and value. + 4. Printing a confirmation message to the user. + """ + experiment_name = "my-test-experiment" + initial_config = {"some_key": "some_value"} + mock_get_config.return_value = (experiment_name, initial_config.copy()) + + result = runner.invoke(experiment_type, [valid_type.value]) + + assert result.exit_code == 0 + assert result.exception is None + + mock_get_config.assert_called_once() + + expected_config = initial_config.copy() + expected_config["experiment_type"] = valid_type.value + mock_save_config.assert_called_once_with(ANY, experiment_name, expected_config) + + expected_output = f"Type of the experiment '{experiment_name}' is set to '{valid_type.value}'.\n" + assert result.output == expected_output diff --git a/tests/validation/configure/test_generator_type.py b/tests/validation/configure/test_generator_type.py new file mode 100644 index 0000000..e5f9d4d --- /dev/null +++ b/tests/validation/configure/test_generator_type.py @@ -0,0 +1,108 @@ +from unittest.mock import ANY, MagicMock, patch + +import pytest +from click.testing import CliRunner + +from pysatl_experiment.cli.commands.configure.generator_type.generator_type import generator_type +from pysatl_experiment.configuration.model.step_type.step_type import StepType + + +@pytest.fixture +def runner() -> CliRunner: + """Fixture to create a CliRunner instance.""" + return CliRunner() + + +@patch("pysatl_experiment.cli.commands.configure.generator_type.generator_type.get_experiment_name_and_config") +@patch("pysatl_experiment.cli.commands.configure.generator_type.generator_type.save_experiment_config") +def test_generator_type_with_invalid_type( + mock_save_config: MagicMock, mock_get_config: MagicMock, runner: CliRunner +) -> None: + """ + Tests the `generator_type` command with a completely invalid type string. + + This test verifies that when the command is invoked with a string + that does not correspond to any valid `StepType` enum value, it behaves + correctly by: + 1. Exiting with a non-zero status code. + 2. Printing an error message that includes the invalid input and lists + the valid options. + 3. Not attempting to get or save the experiment configuration, as the + error occurs during initial validation. + """ + invalid_type = "this-is-not-a-valid-type" + + result = runner.invoke(generator_type, [invalid_type]) + + assert result.exit_code != 0 + assert isinstance(result.exception, SystemExit) + + output = result.output + assert f"Type of '{invalid_type}' is not valid." in output + valid_options = [e.value for e in StepType] + assert f"Possible values are: {valid_options}" in output + + mock_get_config.assert_not_called() + mock_save_config.assert_not_called() + + +@patch("pysatl_experiment.cli.commands.configure.generator_type.generator_type.get_experiment_name_and_config") +@patch("pysatl_experiment.cli.commands.configure.generator_type.generator_type.save_experiment_config") +def test_generator_type_with_unsupported_custom_type( + mock_save_config: MagicMock, mock_get_config: MagicMock, runner: CliRunner +) -> None: + """ + Tests the `generator_type` command with the 'custom' type, which is unsupported. + + This test verifies that the specific logic check preventing the use of the + `StepType.CUSTOM` value works correctly by: + 1. Exiting with a non-zero status code. + 2. Printing the specific error message for the unsupported 'custom' type. + 3. Not attempting to get or save the experiment configuration. + """ + custom_type = StepType.CUSTOM.value + + result = runner.invoke(generator_type, [custom_type]) + + assert result.exit_code != 0 + assert isinstance(result.exception, SystemExit) + + assert "Custom type is not supported yet." in result.output + + mock_get_config.assert_not_called() + mock_save_config.assert_not_called() + + +@patch("pysatl_experiment.cli.commands.configure.generator_type.generator_type.get_experiment_name_and_config") +@patch("pysatl_experiment.cli.commands.configure.generator_type.generator_type.save_experiment_config") +@pytest.mark.parametrize("valid_type", [e for e in StepType if e != StepType.CUSTOM]) +def test_generator_type_with_valid_supported_type( + mock_save_config: MagicMock, mock_get_config: MagicMock, runner: CliRunner, valid_type: StepType +) -> None: + """ + Tests the `generator_type` command logic with all valid and supported arguments. + + This test verifies that when the command is invoked with any supported `StepType` + enum value, it behaves correctly by: + 1. Exiting with a zero status code for success. + 2. Calling the functions to get and save the configuration exactly once. + 3. Updating the configuration dictionary with the correct key and value. + 4. Printing a confirmation message to the user. + """ + experiment_name = "my-test-experiment" + initial_config = {"some_key": "some_value"} + mock_get_config.return_value = (experiment_name, initial_config.copy()) + + result = runner.invoke(generator_type, [valid_type.value]) + + assert result.exit_code == 0 + assert result.exception is None + + mock_get_config.assert_called_once() + + expected_config = initial_config.copy() + expected_config["generator_type"] = valid_type.value + mock_save_config.assert_called_once_with(ANY, experiment_name, expected_config) + + expected_output = f"Generator type of the experiment '{experiment_name}' is set to '{valid_type.value}'.\n" + assert result.output == expected_output diff --git a/tests/validation/configure/test_hypothesis.py b/tests/validation/configure/test_hypothesis.py new file mode 100644 index 0000000..7333799 --- /dev/null +++ b/tests/validation/configure/test_hypothesis.py @@ -0,0 +1,102 @@ +from unittest.mock import MagicMock, patch + +import pytest +from click.testing import CliRunner + +from pysatl_experiment.cli.commands.configure.hypothesis.hypothesis import hypothesis +from pysatl_experiment.configuration.model.hypothesis.hypothesis import Hypothesis + + +@pytest.fixture +def runner() -> CliRunner: + """Fixture to create a CliRunner instance.""" + return CliRunner() + + +@patch("pysatl_experiment.cli.commands.configure.hypothesis.hypothesis.get_experiment_name_and_config") +@patch("pysatl_experiment.cli.commands.configure.hypothesis.hypothesis.save_experiment_config") +def test_hypothesis_with_invalid_hyp( + mock_save_config: MagicMock, mock_get_config: MagicMock, runner: CliRunner +) -> None: + """ + Tests the `hypothesis` command logic with an invalid hypothesis string. + + This test verifies that when the command is invoked with a string that + does not correspond to any valid `Hypothesis` enum value, it behaves correctly by: + 1. Calling the function to get the configuration (as it happens before validation). + 2. Exiting with a non-zero status code upon validation failure. + 3. Printing an error message that includes the invalid input and lists + the valid options. + 4. Not calling the function to save the configuration, thus preventing + any side effects. + """ + invalid_hyp = "this-is-not-a-valid-hypothesis" + mock_get_config.return_value = ("my-experiment", {}) + + result = runner.invoke(hypothesis, [invalid_hyp]) + + mock_get_config.assert_called_once() + + assert result.exit_code != 0 + assert isinstance(result.exception, SystemExit) + + output = result.output + assert f"Type of '{invalid_hyp}' is not valid." in output + valid_options = [e.value for e in Hypothesis] + assert f"Possible values are: {valid_options}" in output + + mock_save_config.assert_not_called() + + +@patch("pysatl_experiment.cli.commands.configure.hypothesis.hypothesis.criteria_from_codes") +@patch("pysatl_experiment.cli.commands.configure.hypothesis.hypothesis.get_statistics_short_codes_for_hypothesis") +@patch("pysatl_experiment.cli.commands.configure.hypothesis.hypothesis.save_experiment_config") +@patch("pysatl_experiment.cli.commands.configure.hypothesis.hypothesis.get_experiment_name_and_config") +@pytest.mark.parametrize("valid_hyp", [h for h in Hypothesis]) +def test_hypothesis_with_valid_hyp( + mock_get_config: MagicMock, + mock_save_config: MagicMock, + mock_get_codes: MagicMock, + mock_criteria_from_codes: MagicMock, + runner: CliRunner, + valid_hyp: Hypothesis, +) -> None: + """ + Tests the `hypothesis` command logic with a valid hypothesis. + + This test verifies that when the command is invoked with a valid `Hypothesis` + value, it correctly performs all its intended side effects: + 1. Fetches the initial experiment configuration. + 2. Updates the 'hypothesis' key in the configuration. + 3. Calls helper functions to get the appropriate statistical criteria. + 4. Updates the 'criteria' key in the configuration with the new data. + 5. Saves the fully updated configuration. + 6. Exits with a zero status code and prints a success message. + """ + experiment_name = "my-test-experiment" + initial_config = {"some_key": "some_value"} + mock_get_config.return_value = (experiment_name, initial_config.copy()) + + mock_codes = ["code1", "code2"] + mock_criteria_data = [{"name": "Criteria 1"}, {"name": "Criteria 2"}] + mock_get_codes.return_value = mock_codes + mock_criteria_from_codes.return_value = mock_criteria_data + + result = runner.invoke(hypothesis, [valid_hyp.value]) + + assert result.exit_code == 0 + assert result.exception is None + + mock_get_config.assert_called_once() + mock_get_codes.assert_called_once_with(valid_hyp.value) + mock_criteria_from_codes.assert_called_once_with(mock_codes) + + mock_save_config.assert_called_once() + + saved_config = mock_save_config.call_args[0][2] + + assert saved_config["hypothesis"] == valid_hyp.value + assert saved_config["criteria"] == mock_criteria_data + + assert f"Hypothesis of the experiment '{experiment_name}' is set to '{valid_hyp.value}'" in result.output + assert f"all criteria for the hypothesis '{valid_hyp.value}' are set" in result.output diff --git a/tests/validation/configure/test_report_builder_type.py b/tests/validation/configure/test_report_builder_type.py new file mode 100644 index 0000000..bae33fa --- /dev/null +++ b/tests/validation/configure/test_report_builder_type.py @@ -0,0 +1,114 @@ +from unittest.mock import ANY, MagicMock, patch + +import pytest +from click.testing import CliRunner + +from pysatl_experiment.cli.commands.configure.report_builder_type.report_builder_type import report_builder_type +from pysatl_experiment.configuration.model.step_type.step_type import StepType + + +@pytest.fixture +def runner() -> CliRunner: + """Fixture to create a CliRunner instance.""" + return CliRunner() + + +@patch( + "pysatl_experiment.cli.commands.configure.report_builder_type.report_builder_type.get_experiment_name_and_config" +) +@patch("pysatl_experiment.cli.commands.configure.report_builder_type.report_builder_type.save_experiment_config") +def test_report_builder_type_with_invalid_type( + mock_save_config: MagicMock, mock_get_config: MagicMock, runner: CliRunner +) -> None: + """ + Tests the `report_builder_type` command with a completely invalid type string. + + This test verifies that when the command is invoked with a string + that does not correspond to any valid `StepType` enum value, it behaves + correctly by: + 1. Exiting with a non-zero status code. + 2. Printing an error message that includes the invalid input and lists + the valid options. + 3. Not attempting to get or save the experiment configuration, as the + error occurs during initial validation. + """ + invalid_type = "this-is-not-a-valid-type" + + result = runner.invoke(report_builder_type, [invalid_type]) + + assert result.exit_code != 0 + assert isinstance(result.exception, SystemExit) + + output = result.output + assert f"Type of '{invalid_type}' is not valid." in output + valid_options = [e.value for e in StepType] + assert f"Possible values are: {valid_options}" in output + + mock_get_config.assert_not_called() + mock_save_config.assert_not_called() + + +@patch( + "pysatl_experiment.cli.commands.configure.report_builder_type.report_builder_type.get_experiment_name_and_config" +) +@patch("pysatl_experiment.cli.commands.configure.report_builder_type.report_builder_type.save_experiment_config") +def test_report_builder_type_with_unsupported_custom_type( + mock_save_config: MagicMock, mock_get_config: MagicMock, runner: CliRunner +) -> None: + """ + Tests the `report_builder_type` command with the 'custom' type, which is unsupported. + + This test verifies that the specific logic check preventing the use of the + `StepType.CUSTOM` value works correctly by: + 1. Exiting with a non-zero status code. + 2. Printing the specific error message for the unsupported 'custom' type. + 3. Not attempting to get or save the experiment configuration. + """ + custom_type = StepType.CUSTOM.value + + result = runner.invoke(report_builder_type, [custom_type]) + + assert result.exit_code != 0 + assert isinstance(result.exception, SystemExit) + + assert "Custom type is not supported yet." in result.output + + mock_get_config.assert_not_called() + mock_save_config.assert_not_called() + + +@patch( + "pysatl_experiment.cli.commands.configure.report_builder_type.report_builder_type.get_experiment_name_and_config" +) +@patch("pysatl_experiment.cli.commands.configure.report_builder_type.report_builder_type.save_experiment_config") +@pytest.mark.parametrize("valid_type", [e for e in StepType if e != StepType.CUSTOM]) +def test_report_builder_type_with_valid_supported_type( + mock_save_config: MagicMock, mock_get_config: MagicMock, runner: CliRunner, valid_type: StepType +) -> None: + """ + Tests the `report_builder_type` command logic with all valid and supported arguments. + + This test verifies that when the command is invoked with any supported `StepType` + enum value, it behaves correctly by: + 1. Exiting with a zero status code for success. + 2. Calling the functions to get and save the configuration exactly once. + 3. Updating the configuration dictionary with the correct key and value. + 4. Printing a confirmation message to the user. + """ + experiment_name = "my-test-experiment" + initial_config = {"some_key": "some_value"} + mock_get_config.return_value = (experiment_name, initial_config.copy()) + + result = runner.invoke(report_builder_type, [valid_type.value]) + + assert result.exit_code == 0 + assert result.exception is None + + mock_get_config.assert_called_once() + + expected_config = initial_config.copy() + expected_config["report_builder_type"] = valid_type.value + mock_save_config.assert_called_once_with(ANY, experiment_name, expected_config) + + expected_output = f"Report builder type of the experiment '{experiment_name}' is set to '{valid_type.value}'.\n" + assert result.output == expected_output diff --git a/tests/validation/configure/test_report_mode.py b/tests/validation/configure/test_report_mode.py new file mode 100644 index 0000000..456c628 --- /dev/null +++ b/tests/validation/configure/test_report_mode.py @@ -0,0 +1,87 @@ +from unittest.mock import ANY, MagicMock, patch + +import pytest +from click.testing import CliRunner + +from pysatl_experiment.cli.commands.configure.report_mode.report_mode import report_mode +from pysatl_experiment.configuration.model.report_mode.report_mode import ReportMode + + +@pytest.fixture +def runner() -> CliRunner: + """Fixture to create a CliRunner instance.""" + return CliRunner() + + +@patch("pysatl_experiment.cli.commands.configure.report_mode.report_mode.get_experiment_name_and_config") +@patch("pysatl_experiment.cli.commands.configure.report_mode.report_mode.save_experiment_config") +def test_report_mode_with_invalid_mode( + mock_save_config: MagicMock, mock_get_config: MagicMock, runner: CliRunner +) -> None: + """ + Tests the `report_mode` command logic in isolation with an invalid argument. + + This test verifies that when the `report_mode` command is invoked with a string + that does not correspond to any valid `ReportMode` enum value, it behaves + correctly by: + 1. Exiting with a non-zero status code to indicate failure. + 2. Printing a user-friendly error message that includes the invalid input. + 3. Suggesting the list of valid options to the user. + 4. Not calling the function to save the configuration, thus preventing + any side effects. + """ + invalid_mode = "this-is-not-a-valid-mode" + experiment_name = "my-test-experiment" + mock_get_config.return_value = (experiment_name, {"some_key": "some_value"}) + + result = runner.invoke(report_mode, [invalid_mode]) + + mock_get_config.assert_called_once() + + assert result.exit_code != 0 + assert isinstance(result.exception, SystemExit) + + output = result.output + expected_error_fragment = f"Type of '{invalid_mode}' is not valid." + assert expected_error_fragment in output + + valid_options = [e.value for e in ReportMode] + assert f"Possible values are: {valid_options}" in output + + mock_save_config.assert_not_called() + + +@patch("pysatl_experiment.cli.commands.configure.report_mode.report_mode.get_experiment_name_and_config") +@patch("pysatl_experiment.cli.commands.configure.report_mode.report_mode.save_experiment_config") +@pytest.mark.parametrize("valid_mode", [e for e in ReportMode]) +def test_report_mode_with_valid_mode( + mock_save_config: MagicMock, mock_get_config: MagicMock, runner: CliRunner, valid_mode: ReportMode +) -> None: + """ + Tests the `report_mode` command logic in isolation with valid arguments. + + This test verifies that when the command is invoked with any valid `ReportMode` + enum value, it behaves correctly by: + 1. Exiting with a zero status code to indicate success. + 2. Calling the configuration saving function exactly once. + 3. Updating the configuration dictionary with the correct key and value. + 4. Printing a confirmation message to the user. + """ + experiment_name = "my-test-experiment" + initial_config = {"some_key": "some_value"} + + mock_get_config.return_value = (experiment_name, initial_config.copy()) + + result = runner.invoke(report_mode, [valid_mode.value]) + + mock_get_config.assert_called_once() + + assert result.exit_code == 0 + assert result.exception is None + + expected_config = initial_config.copy() + expected_config["report_mode"] = valid_mode.value + mock_save_config.assert_called_once_with(ANY, experiment_name, expected_config) + + expected_output = f"Report mode of the experiment '{experiment_name}' is set to '{valid_mode.value}'.\n" + assert result.output == expected_output diff --git a/tests/validation/configure/test_run_mode.py b/tests/validation/configure/test_run_mode.py new file mode 100644 index 0000000..f570544 --- /dev/null +++ b/tests/validation/configure/test_run_mode.py @@ -0,0 +1,84 @@ +from unittest.mock import ANY, MagicMock, patch + +import pytest +from click.testing import CliRunner + +from pysatl_experiment.cli.commands.configure.run_mode.run_mode import run_mode +from pysatl_experiment.configuration.model.run_mode.run_mode import RunMode + + +@pytest.fixture +def runner() -> CliRunner: + """Fixture to create a CliRunner instance.""" + return CliRunner() + + +@patch("pysatl_experiment.cli.commands.configure.run_mode.run_mode.get_experiment_name_and_config") +@patch("pysatl_experiment.cli.commands.configure.run_mode.run_mode.save_experiment_config") +def test_run_mode_with_invalid_mode(mock_save_config: MagicMock, mock_get_config: MagicMock, runner: CliRunner) -> None: + """ + Tests the `run_mode` command logic in isolation with an invalid argument. + + This test verifies that when the `run_mode` command is invoked with a string + that does not correspond to any valid `RunMode` enum value, it behaves + correctly by: + 1. Exiting with a non-zero status code to indicate failure. + 2. Printing a user-friendly error message that includes the invalid input. + 3. Suggesting the list of valid options to the user. + 4. Not calling the function to save the configuration, thus preventing + any side effects. + """ + invalid_mode = "this-is-not-a-valid-mode" + experiment_name = "my-test-experiment" + mock_get_config.return_value = (experiment_name, {"some_key": "some_value"}) + + result = runner.invoke(run_mode, [invalid_mode]) + + mock_get_config.assert_called_once() + + assert result.exit_code != 0 + assert isinstance(result.exception, SystemExit) + + output = result.output + expected_error_fragment = f"Type of '{invalid_mode}' is not valid." + assert expected_error_fragment in output + + valid_options = [e.value for e in RunMode] + assert f"Possible values are: {valid_options}" in output + + mock_save_config.assert_not_called() + + +@patch("pysatl_experiment.cli.commands.configure.run_mode.run_mode.get_experiment_name_and_config") +@patch("pysatl_experiment.cli.commands.configure.run_mode.run_mode.save_experiment_config") +@pytest.mark.parametrize("valid_mode", [e for e in RunMode]) +def test_run_mode_with_valid_mode( + mock_save_config: MagicMock, mock_get_config: MagicMock, runner: CliRunner, valid_mode: RunMode +) -> None: + """ + Tests the `run_mode` command logic in isolation with valid arguments. + + This test verifies that when the command is invoked with any valid `RunMode` + enum value, it behaves correctly by: + 1. Exiting with a zero status code to indicate success. + 2. Calling the configuration saving function exactly once. + 3. Updating the configuration dictionary with the correct key and value. + 4. Printing a confirmation message to the user. + """ + experiment_name = "my-test-experiment" + initial_config = {"some_key": "some_value"} + mock_get_config.return_value = (experiment_name, initial_config.copy()) + + result = runner.invoke(run_mode, [valid_mode.value]) + + mock_get_config.assert_called_once() + + assert result.exit_code == 0 + assert result.exception is None + + expected_config = initial_config.copy() + expected_config["run_mode"] = valid_mode.value + mock_save_config.assert_called_once_with(ANY, experiment_name, expected_config) + + expected_output = f"Run mode of the experiment '{experiment_name}' is set to '{valid_mode.value}'.\n" + assert result.output == expected_output From 4ebb967ce4f6a2f8981346bce3dccdd6f19b1524 Mon Sep 17 00:00:00 2001 From: faux66 Date: Thu, 9 Oct 2025 22:17:48 +0300 Subject: [PATCH 12/17] feat: Add 3-step experiment workflow example --- experiment_example/README.md | 136 ++++++++++++++++++ .../configs/1_calculate_critical_values.json | 36 +++++ .../configs/2_evaluate_power.json | 45 ++++++ .../configs/3_measure_time_complexity.json | 36 +++++ .../reports/critical_values_report.pdf | Bin 0 -> 154083 bytes experiment_example/reports/power_report.pdf | Bin 0 -> 124514 bytes .../reports/time_complexity_report.pdf | Bin 0 -> 116361 bytes 7 files changed, 253 insertions(+) create mode 100644 experiment_example/README.md create mode 100644 experiment_example/configs/1_calculate_critical_values.json create mode 100644 experiment_example/configs/2_evaluate_power.json create mode 100644 experiment_example/configs/3_measure_time_complexity.json create mode 100644 experiment_example/reports/critical_values_report.pdf create mode 100644 experiment_example/reports/power_report.pdf create mode 100644 experiment_example/reports/time_complexity_report.pdf diff --git a/experiment_example/README.md b/experiment_example/README.md new file mode 100644 index 0000000..0e37a5b --- /dev/null +++ b/experiment_example/README.md @@ -0,0 +1,136 @@ +# Quick-Start Template: A 3-Step Experimental Workflow + +This directory provides a set of template configuration files for the `pysatl-experiment` framework. It is designed to serve as a starting point for conducting a robust, three-step comparison of statistical goodness-of-fit tests. + +The goal of this workflow is to help you make a data-driven decision about which statistical test is best suited for your specific hypothesis and potential alternatives. + +## The 3-Step Workflow + +This template follows a complete research cycle. Each step answers a different question, and they are designed to be run in sequence. + +--- + +### Step 1: Calibration +File: `1_calculate_critical_values.json` + +**The Question:** What are the correct decision thresholds for my chosen tests? + +**The Purpose:** Before you can use any statistical test, you must establish its baseline critical values. These values depend on your null hypothesis (the distribution you are testing for), the sample sizes, and the desired significance levels (alpha). This step calibrates your "measurement tools." + +**The Command:** +```bash +poetry run experiment build-and-run 1_calculate_critical_values +``` +--- +### Step 2: Evaluation +File: `2_evaluate_power.json` + +**The Question:** How effective are these tests at detecting the specific deviations I care about? + +**The Purpose:** This is the core scientific evaluation. You measure the **statistical power** of each test against one or more alternative hypotheses. A test with high power is very good at correctly rejecting the null hypothesis when it is indeed false. This step tells you which test is most effective for your specific problem. + +*This experiment requires the critical values generated in Step 1.* + +**The Command:** +```bash +poetry run experiment build-and-run 2_evaluate_power +``` + +--- + +### Step 3: Performance Analysis +File: `3_measure_time_complexity.json` + +**The Question:** What is the computational cost of using each test? + +**The Purpose:** This is the practical, engineering evaluation. If two tests show similar power, the faster one may be preferable, especially in data-intensive applications. This experiment measures the execution time of each test, helping you understand the trade-offs between effectiveness and performance. + +**The Command:** +```bash +poetry run experiment build-and-run 3_measure_time_complexity +``` + +--- + +## How to Adapt This Template for Your Own Research + +To use these files for your own experiment, copy this directory and modify the JSON configurations. The key is to ensure your parameters are consistent across the files. +#### 1. Define Your Null Hypothesis + +In all three files (`1_...`, `2_...`, `3_...`), change the `hypothesis` object to match the distribution you want to test for. + +**Example: Changing from `Normal` to `Weibull`** +```json + "hypothesis": "normal" +to + "hypothesis": "weibull" +``` + +#### 2. Choose the Criteria to Compare + +In all three files, update the `criteria` list to include the tests you want to evaluate. + +**Example: Comparing `Liliefos` and `Chi-Squared`** +```json + "criteria": [ + { + "criterion_code": "LILLIE", + "parameters": [] + }, + { + "criterion_code": "CHI2", + "parameters": [] + } + ], +``` +#### 3. Define the Alternative Hypothesis + +In `2_evaluate_power.json`, modify the `alternatives` array. This is the specific deviation you want your tests to be able to detect. + +**Example: Checking if tests for `Weibull` can detect an `Exponential` distribution** +```json +"alternatives": [ + { + "generator_name": "EXPONENTIALGENERATOR", + "parameters": [ + 0.5, + ] + } + ] +``` +#### 4. Adjust Experiment Parameters + +You can also change `sample_sizes`, `monte_carlo_count`, and `significance_levels` to fit the scope of your research. Just ensure the `sample_sizes` and `significance_levels` are consistent between the `critical_value` and `power` experiments. + +By following this structured, three-step approach, you can systematically evaluate and select the best statistical test for any given problem. + +--- + +## How to Run This Example Workflow + +The `pysatl-experiment` command-line tool is designed to look for experiment configurations in a dedicated `.experiment` directory at the root of the project. + +Therefore, to run these examples, you must first copy the JSON template files into that location. + +**1. Copy the configuration files:** + +Firstly you need create files +```bash +poerty run experiment create <1_calculate_critical_values> +``` + +**2. Run the experiments in sequence:** + +Once the files are in the `.experiment` directory, you can execute the workflow steps in order. Make sure you are in the project's root directory. +### First, run the calibration step +``` +poetry run experiment build-and-run 1_calculate_critical_values +``` +### Second, run the power evaluation +``` +poetry run experiment build-and-run 2_evaluate_power +``` +### Finally, run the performance analysis +``` +poetry run experiment build-and-run 3_measure_time_complexity +``` diff --git a/experiment_example/configs/1_calculate_critical_values.json b/experiment_example/configs/1_calculate_critical_values.json new file mode 100644 index 0000000..88c93f1 --- /dev/null +++ b/experiment_example/configs/1_calculate_critical_values.json @@ -0,0 +1,36 @@ +{ + "config": { + "name": "1_calculate_critical_values", + "experiment_type": "critical_value", + "hypothesis": "normal", + "criteria": [ + { + "criterion_code": "KS", + "parameters": [] + }, + { + "criterion_code": "AD", + "parameters": [] + } + ], + "executor_type": "standard", + "generator_type": "standard", + "report_builder_type": "standard", + "report_mode": "with-chart", + "run_mode": "reuse", + "monte_carlo_count": 1000, + "sample_sizes": [ + 200, + 400, + 600, + 800, + 1000 + ], + "significance_levels": [ + 0.01, + 0.05, + 0.1 + ], + "storage_connection": "/home/moveton/projects/prog/pysatl-experiment/.storage/result.sqlite" + } +} \ No newline at end of file diff --git a/experiment_example/configs/2_evaluate_power.json b/experiment_example/configs/2_evaluate_power.json new file mode 100644 index 0000000..56432f9 --- /dev/null +++ b/experiment_example/configs/2_evaluate_power.json @@ -0,0 +1,45 @@ +{ + "config": { + "name": "2_evaluate_power", + "experiment_type": "power", + "hypothesis": "normal", + "alternatives": [ + { + "generator_name": "NORMALGENERATOR", + "parameters": [ + 0.5, + 1 + ] + } + ], + "criteria": [ + { + "criterion_code": "KS", + "parameters": [] + }, + { + "criterion_code": "AD", + "parameters": [] + } + ], + "executor_type": "standard", + "generator_type": "standard", + "report_builder_type": "standard", + "report_mode": "with-chart", + "run_mode": "reuse", + "monte_carlo_count": 1000, + "sample_sizes": [ + 200, + 400, + 600, + 800, + 1000 + ], + "significance_levels": [ + 0.01, + 0.05, + 0.1 + ], + "storage_connection": "/home/moveton/projects/prog/pysatl-experiment/.storage/result.sqlite" + } +} \ No newline at end of file diff --git a/experiment_example/configs/3_measure_time_complexity.json b/experiment_example/configs/3_measure_time_complexity.json new file mode 100644 index 0000000..daee575 --- /dev/null +++ b/experiment_example/configs/3_measure_time_complexity.json @@ -0,0 +1,36 @@ +{ + "config": { + "name": "3_measure_time_complexity", + "experiment_type": "time_complexity", + "hypothesis": "normal", + "criteria": [ + { + "criterion_code": "KS", + "parameters": [] + }, + { + "criterion_code": "AD", + "parameters": [] + } + ], + "executor_type": "standard", + "generator_type": "standard", + "report_builder_type": "standard", + "report_mode": "with-chart", + "run_mode": "reuse", + "monte_carlo_count": 1000, + "sample_sizes": [ + 200, + 400, + 600, + 800, + 1000 + ], + "significance_levels": [ + 0.01, + 0.05, + 0.1 + ], + "storage_connection": "/home/moveton/projects/prog/pysatl-experiment/.storage/result.sqlite" + } +} \ No newline at end of file diff --git a/experiment_example/reports/critical_values_report.pdf b/experiment_example/reports/critical_values_report.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b95c04399270a6069c8b950a7e1a795d4ffdc0a8 GIT binary patch literal 154083 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

9u;A)Q8$Oh3mF2UU0gJa-gSfRv|sfG zdEMRM`0pdwV4xhx9Cw{gGl3t2G2k6DtL`hKtks8U(9lOKQM=BV#H zoQjkkXPA9v(fX~XiwrXAJ#1po>4&?cW3bCjbQv7VN_8as&sFADy0!`gEyD+v9r3G| z@yKh!r#-Z*$FDMnQl&}=uDn*-!1zAh_=YHVE9JooI;>JVJ##t0_bO(Q9*5Jd?q;&J z_B+Hq^RQIUHB(C^w$5GXVz#n^3m~PNiM@RiH?oX}vq0V2FBr_;4kY{L5o}SeA9n}}=T~SzEyvMnQ5q3lqc1G^=M`Uf4#Md)osU-3RJ(2g2|4JF2b&Cz z);qg}J7MHMgol+DW27CT^Zt7Ub=U2ke-6@BjCS@+b-xke{x(JTzo>>+Kj+svGgx&= z0Iu3px7V(JrdbOIGf(nxK(gzB&9WsILU+Eu#P06el=8)*4WNlHVw6|qH`OZ_3av`! zy*ixeigNC9m*WiSx1Z&*qrS(d__z)rb2TJxul$~p{I6rB;vkjwC2JKQ(2_srGy7L@ zua>Jlnf3AyZ8j<9IF=G}DR&vd$#EE$3)2)>z6*&c81+e-aaro{jQD*%3QQP40@;P|Yrc+41jH%R{W9U@U~BG-1T<3Z9rYymwl) zb7>|QCpsFfs@?%aJdd+~_PgCTWzA~phf}$LybaJ6EP$PIIV(b?2C;#{KI(p&o~L|m^4$L5*LeO_hohdcgHqMDal#wTnb4*#nS0;bXFjIP60YMj zez2NJ&qd)*!d=ct#LiSNJ5v~8bfy^y{O`}HpFI2{oEl}4p# zRDy?j8L&TAz6y1jrXpe=I$yK$OOTaJP(w}^&=nZ3hwHqfzGh+xx)0g`PM?swz8Ko} z?Zy^F@AGADi)Mm}IPJeNy@4w&PT#$Mc`rUPY-hz=JKB87ZLWczsg_YC;sK_8!EdKA zU!S{73&3w5c5_#+KEBFCz1f-rTka}kTYNLKpWL&Z)$_R~@bSxsy|pj}f6CxmarfDU zdWv?V#$cQMwVLl>+}D@sW$eeJHfPs;z3{}7?7g1c==XVBj(Um;y`JK2*}L_8sg`G^-&2D*`749i6(NYt|M!B`&&#(IX)4+L{SL2V ztM2qWQ)9``tL5JK$r}Lft>zvdH7vBk)>ZueAnQnX`4h!%rD4 z_kEC*j%DtVlyrgkuN#l(

9oYRsbJZdZplbiBG7a`9BqKRpT;@JWgg-Bzqsdkh;CHI(PeXs%3%pvZKA71Hv z9ITyOEnn1VKHd-XUYVFL&lUiUvKqU7!XePtkQnFW3!>dH$lW4RB81 z$177ATEX)05?TkTjvlJQAxk-{P#=a-KF{oT*xDkoO=FViZ3ngtDRyT!Sm{7s3(p9UwhRMJCtEtW(PeE_p8|$t1 z?{yd#U9*pSADt2MnN3VIsmZsAjBiSyydyXe>PKM%@f>u_&ZMi)6A&o>VVphg7q=1n z95pVVBK0W_G*?8WIsmY0omuv|&nbVQ~3Ub4`_Y7w^2bpjOy&IC)fn`~zW{px|hH)NH_C*)z=F_t{tc zJK>MYQkXtLA`t~!?sqA4_T`KRdV)&1DBSDkOeWLGij8{9Uq$49hjx__z#zIx7~TDK zqe2gx-XzEG8_l|?$Yn7Tw&B9R+2{N1+jV+Bwi7^~gZgbaLmR&{Jk|whz|ZjJ?^n0) z;>fBnRed?nSs)S}F9zk%FP+Wh{(hZ!dTyyn`=K7ipGa4jgAjAatBk<1uRtBIox7lKg4*e0)gVJdqRU(v zzn!Vr7W()T7mpOrFUo1=#SJ{3MK(4MAJsAcr%X?Z^_r~>9JMo;;1LQ?u$faK3($%! zjapVzZoawGR@hgI7Z7VZ=x#|DB9&cootZ$y z9ay%)mp^!~I{^iy{;a$*zQ27CwDeYmHXOQQMI9u?)r!0AmmPy}TNGcpFA;(tUy~b- z62uf>?x8`dw<}||e`*!p6n(Q^y!sb=>*I}<*??FdQ3^V++M+Y*Qnj~ZgU|NO!H^Xq z$n4GaR<&c6nFnqw_uVo09UDE;(i?T7qGbw~JT~_E$N2zBxi~<}APRg#DlB*U;4T7G zL9_pD%rkT0obHSa7G?*d)8|q7+M{jAjtYaf)avvKQ15t~hfYttoRxZ)_txc%zT&r( z+qaf4y)ms*W{LXSJ&^f ztA!&xyKdP6ua&A6;r(7IH<2qPcMq9GtDE_K)(uvD%!9J3*NmhWj*!$E7Q3acg<4KM zlT%%K_@9$e4_gG3m_F{Gi8my*&n55XW(A@7nVhkVK}3kC&5nJqo6#~D{VM#nAi7=^!D`gy-@vXJ|s8n$iAGn zrQG>?%!S<5F@*N&$poBMLm00WZJ+Q#=fWzq+1k%zd$nu2lc0gz9wo^eGqoR@bo8-V z2%l4^M1Pm+A3*a=dvc@N(VBNlnRPZWM>0*`g@2Z#PP}IdfwD2=6d=r z^Q$H&7#nn#)42x#&qsHL&xg|rWPVZF$|=UDlwZRYMxknu@t&GkS?S)U>4CnFub=#) zMS@Cc-<|fTwWipXXR7{(rZFip#&ji2&2CO(3AhunN*j2>_4oipcCN#9nC&EN z5gCXC1JL@tOpJ4eUVTkn4%aTT!l}ItXa}NyQ#r(O^U*Wx%%nIwWawFOVB<>* zoH)A@(h>tOZ*v)~v1nH(@Tig_280!j1*FRIv#fN_Vj9;A*;$^G^NGRfB$?e>qa1xA z4pq9c)uxPVZYSeH$=|f^JK0Pct$v!P{gwj@aYTFQjocOs%&@u};}vgMyIXj@I)Ik- zSo<@#xHzp!t8W_;QO0SS3BLt?KPv65OOR?|sqW zBGjM*Hc@TtHk4!c)E=wbZ|V26zcC>gP;9qv~1y)x9~N!Uhr{ z`;w32G<0!pg*5;3N$q(}aoshaMqd*bS;RoU65>qcd$l~))?cFl)Ju4SB*3~0@AHV6 zW5sEk6r-khhhB``EyZ+`-Ij3+qP zEgJ$cH7;3At^dB?o?Mm_b$a(Io}=1&2<`jMdMM#oUl;3nr5F#q^){>}-%nq0E&O+` z+>S)Tn42edqd2RXO7P3?U*wKI_VtC^%%`$|||%Z884N zG~>KV^3!Tl*OoI&C-XsH)yM|K&L7@jcMoPCVDwG+K_stdn(Ah&!t-uW5KM)0$LAXi zx(o8hz0n_azI>UrGM=A0PGN!1uH*IR6sdwkPp`ixSj-%Ab4hZ|R{xg%+@cA{c!+|N z+;DDD#m-c@HTR}gI6K#3mCeEY@6}gx5PyrnbTMk*hu0bl4)_QCm^AoZ^^~d9*k>jF z^VIv^Pv0kx$EomeIy;rEG(W9|Fj})=eozKOX1#K?p&-jgfW@6=pc;AaJMq+$|DcQ- zR*95)eYHQILq*XifnEUnVUffW(?5_Nab~B#>vxBpQMoz+sz=&bTe+F}9UI#yI9K(> zq@Omks{UmZAbECjI?~ML_N%3_9~Ie5=augGGgSt~g`&$;wEsItzO9gXb4elw~+{0a&| zi}^D?mYTA4y6$ITxxs7myfo9!`OkewV6%GfsZ#|L*sRnY-cKpo>%a=Qnad1xao*|Q zENtO@#^kPHgTp(lh!?lm6mOG{5w+)LaTa~XKt>7l-OW!izVWOY0mS8eLn{X-8+8$_ zYG)Ttt`|)9->mT36H2tqM1VXP*h;vwe5m+wP`(2xy=O>yFOr)Dv<`3N?-Lad&0}S- zQkOG<;y_52A0;rSDeV}sVbtS6$Gmy&*{s_`r~OiZN_{##x9HYffs?(th5>$5l0- zt?bJv1MuYCQGHgyL#(DsmN`shOaH&7(=x+=ZoTO{jF~pr&pWxmB+WcQ&*~#c{`f&{ zHXFtK49nFAb>i^+{@8mTZw>4;%V^kTJC)86h~?CK{k`Xx_^7t+oQfy~UE_aEz~O6{ zR0&^g&Y-GlvezFusVbp5OkXHUR-8R}L-MogK>1USSQ>b{y0vOT5mYjOiM@ejvd#DV zvN-6Gm4$@-vxppQEG-ZRVpEx{SHGFY9&-L+TOAy?(?<>&Drt?vpU!|&q9 z$#uQEGeggNSXuKNQ>S0p+&kZ&J8Xw$>Wx+`WxcIiECHUrz|^3QjP2T&I{VPo7FExJ zC}UX3I0e1la7Nbga9m&|zsnNXD*Hat(cOInIHBJwm#f*kPO~H9Q0nH-a)N^1>t|-X zhy34pPBmX+s*ZZ=5E6?e$y{XGAxPlVl93NW>O zXQVx3Z1nx7I~@)`6XM02FSi)=ba2vvDK@>Mp<-un%^#)nl^5` z=8wBR)H$-a!jW2NwvLD-&rVqcCz51wy1!YtVNmt$?4x{F!Nq&+F8i;%{u!^rIFpCg z-N1P_5_LB9<8p;9TSGl&7x~rpbU2>6wLuSl_-f~);{B|n74`xSUiKmmz2+fIFueFMocJ?4w;w$Gl$M!$dl-W*6muC)dCpFjSC!-BeSY&)Q8?OY5bo2QRKiPeC{(P?T;G6gBucY}4 zA!^8X^2}jzTJT44+C|Y>JOtJfIWn=~|;kE!mw z7aL$88(FO<$LC`YWXLGdukW8(4k#r)rv?6PB3Tx(V>bm(ct+^=_ExhfVs+n!r2u1)fC&G-WDHa2=sI1LwAR?V%2+%hg6RgJ*?anx$< zO2)3Ywe47My9=#dLvg>o5-8yzT?jKKZ%${sp$G5vseq$1oR#jm^}S9H9-m}1uwE=H zED#sr4ii*5PCXYPNC_Ieq3#Rk;G34fj=im9(Knp5s$mv_>NF_fM$78=^(<`vK65B= zmRFyLpZNIXuE5ZPW8res7c%>DxM_Q98xTE{pl_xV(<01ne)L++LA2IyTL&UO^whGq zj;Hf7X4ZUv^Wy4c?raC9pY~cc8d)Zj0d_5n_~|G9n*wQN2Ak`8#@oe+f0$(_KcDUs z_;7T}_4-l4CrYCzcAKkQ`5Ih8wL$4M=GPkgf5uc(i1$DHZIPj>+vm7tn|K4XSj92Z zZ5hwkiBL7yY;We%%0FwY)~dpLhf*<2oCkVLoLn%d`OBtDoWY#NSFyqLKom?Au+#^ymYRB<$| zW9?4w)*un$xBYP^k1!@gVO_42;#W2!06E~$;~V-gQn-|QFC)x6()0JA;Qk${DDLZK zan`MW8vj(>cxBTwVzjlxD3Ryy-F|wg2$v+Ne}?`d?w$0VvhFNAHqRg0-Ec_uISdu3 z@B6Wsp-<<$JelL1%E7j}*l18oyPBDRFSk&(|01RtMga zfQ|=e%zb5(bzUZdFB><)%K2aMGnkZjAn_Xl>gRM*bLl>a%VmD&SYoHzyv-kIp?)^Ta2$L_{o{QY(!@U`f8wuF#cQA-D@_xdDOCS2er#`nA zY_EiE-RnOy?oM2+^>S)n^5qzttY+4A9C~sSgx`nHaWTrThiJ_Mp$0)_)eITkqU;Q2 zHQfF8@M&~@QUz`0I6byd$hr3SWw*D7cG^_N<>4XO3n_gHLk`x6XOKM)Y5;BcJ7fGP zrDvol=Ef+Ntrw~iE=VX=R?I#7znPmWH_Rz6AMhSEk8)8F%{4%=ngN)OPdJ-zG4v^!dAWoX~HvF-EWb88SO$V;}n|NVl1JbPHmlZj}sd zQtt7GsLqb}u(oqX9Zyf2&EUt~-!B{1+!#(!#q#ja>$sU+X;pBD9-6%BY?BmJtfO&% z1RvTz`Oc36VW}2+a7d^5y;{BH{BqjZSkqlr*h_9NN{P#MH|zN}u1@pITd(tbJ&v!; zK9UoQ8TBoEQ(vrudu!kPjgVfCe_$W~Gp#N2Z*5&q4{ddeMz#184r+_1jM33iKmP!+ zi@}8HfD+HG1IJDBAobiLD&|MrdBphnitT>T8iYby)dT5CvMW)ZUaz=3(G&}=fJ6OIM>hrQpRYRuGDWW#DvF;8!)>fiuB-N^kX;Mr z?LO!7vw2GHoIP=?fI8jJ5Enve@6Nq{g;4*j#US%ynly4??Fo)uK8w9-PG~mxL(TAM^6=37+mL|zp8HVaM_!xv(udJ zD2dR~+$_=G&)^+R$?4=crfMO$!tii5BGW8cGvmR3UapGjwUR}a-tj0R>Khe#J!HoA z?O;~6q%jFf^~cP~%j^BaDa+mY1w9}7!iqn}?jf~j#_BoY&E;|p!sHXWd@S@lSg{Jl z+qJ($M^UyrqCl!>J^5}!k&5AkYsm!q$;lH;bUm~Nsu&239@GClbTrW>VLR4}QE|_; zQJX3?YI$LDK0!=ZjKbGsYk7ryh9mbo z=S#WY<7#z*HVHHUo%LlzcAHG$SpJHXfc3LEPwiLcL!2u7KR=R8UbnLVFCA;+B{A)m z*fC4K0AgZ|87g{@n^Lh~S?3OzI()#3xPW#$Sd^^<<%V1JhfbI~%bVkex(u~EKeYpk z$S2i%t=xzUM@ITl=}VsizQQd8H1l2NKYwooWhT}jqj|BAVIQClf3B(~mnNSPUj9Pu zM^`QLjrrM}&YcGzC%uAI2mPCUL+TEZ#cuswMM9P54@ZMTd46FxY9_)AdM6Ry=>G#be!_X&&9_t5n#>~{EP5TN6>+E)L0&H8qiDTV~L zIhBYOVDY9^;62ar2;BaUbXVZb@4oQFRxorcgG}jj> z71HP8GT3)AoBC|eoV^w7{NvicZh-&>=1&Z~jQ;$=VuB!5%>AkeeS0!#f~RW1`RPd9 zfG}{ObkzZBY#ZrSck5#bq^|ov+M)eOdf}~T!B&Qy9?>a~+vGSq)ztRJ^Jbv&e*!rx)F;Z)mbr9Axk z`r7>6=C&-I{`*w!lCYDf5)5C8p)`IX!7&eT9q;=l%EEUsDdk zdT6`vt26uAfeToRr`)33y^Y`W*=W9fp_?4) z--Yt$_Aa^ETjy&|&V*NP0b^ej+IPTbc!gW($oDG;)UaRpWHF7-?71Xu7SPq8e#Nu2 zE{?!P^f>^X*z0Te(z+)1$KJX{-6t*k`kztQ|AurdRwj#7PpRcHNkczuUo(^L57}3s zz2~p2lA>MaSk7sm*M;96f6LP`>q)xs?L?A)@#=+~7dXRz2c98ZN*Q(q5bsn`V1COk zl!-YAdAv4bK)Ows8K3{vEGaS4=lLS9SIO|9`Klsb)@NnXui#?)vlh^2W9JNt5UE(D zV4yfZ=r3AjH?|Nv59Gh$3>XgRRn+1}ney*4ocCA@FMJnjsk-04?}f3~+@iRgem<34 z8yw?F6nh3-Fq4V*=hQ;Thx-@2kGXEfUEBRbzcysQ(WU?1_0x~}_M=`oF(WU*{g(tTt>T>5OP3uZegX!s}T0bTp-gUoxGomh)T5re=UlDTuJC-NFYk z4`K&0U=6nI^^dy+x1$Z<#NI7*7&|$4)GBEuR%`-zm3_vS=MGE+7gX4ngzmvWvoL!b zG-_UzVaoYvVb)X<>6$VH3&zFaIXK;1%=Ma|W$Pn{<{1(KTae`xl&7A6{?-;0TfHmU z^WjAw6nw2eg50(=+p~jtuu*>b{l1nv(c$!X%o&f3{LCGZ6fgOu)AzsWB8HmbPznT+ zS9X10yG(x4YrtAYl^%7gd*&>C?ULJGW91|3gK%Rww2pf2D4R=g6+|H%Va%(g@`X~{ zM!Xve<6KQ-!^Hg4yEeM@&y7kyMpRJzQ*Vp~By? z>mtz&tJpz#H27tUCm&(JmFg`)<+Em?ntY3!7}h?%j@L(R_edjkhzbZp2#PR=?bv_p z>QE5s0UV-41FbS$_lOSr$xr$aiwQW=!^gJ_cKP0lRi6WzFt=-k|^-L22B@u2Dqi%Eb-DoI@-|LPD zT-`yR2k?$|Z_XS4`|VEThpoq>7bNkoc*T8Jy-rVHKK2T0L1(tgrHb6>+oC?PPM8`z~o`hr)h-9NRZN)6o_sjF?OgUr=2QaN`RD?9PgPo!GX3;c&!JnNw*V-H8z_&Q+Ak?=6+*`G5^pf-pRJp6 zr#Ykn*!|yiishH}b+dXp#QSg$UEo=PtBCw)b)lot?cI$pv?4juHb%Cy(9ULu+G9Bw zoSMA}Z6@t z>-iFn`cIvF(YoYe`Im{LmHF#gEDbacSw@FJc-a|+BV}!mY#FWG`J(vXdSdauT})^| zY39!4aqf1uvmBShWwsMo!)&2bXadSeP`qKLPR=LgphZ^|<{*g-f)tJkGvz+K2Azu$ z=#_cNVvxq%v-_sZWKT6gjE1%g^GUP&=pgJc6Ym@s<|H*>`8d} z447{vHhN^gy!sKY`))KaRs8iw&EdWf)s&*b_KH#NAYwhG`yL2S$uwukbc-DIWL_N7 zgxagDUSomfrl%`+!+#8DqRN;3TfGqCBD7BX4p$7_wi;-W`$C_KlB!4y!{xR=@BS!G zzO~|f5Wcd%;gB4?I|hp1`}|@o=XCF0{MvavjbS{sQT(t8$~v(ql)A}M^Ag5ogQ=y2 z4%Nuyhj;nD^qg7c9bwPYdmawV{HnZrnW2$#f&0DqY=b^S{k8x2_DA@5Sgj4nbrs>X zO4`W14wXffaM`;bEXH{mdk7uas(%@cA9VucvzB23cl0ul!6x zY-3$k-ppp-7^1D7(m(7fhLq^M0}?HCH%`;Axf8V^?Y1W!SEav)*5B`$)7N%e2Y#_B zDhdxolMHeYP4=P|7pG z0^_mi-s!NO<=*ppUmccOmArYyiU8#@-k0jyBc`1V6tS!kIu9p~m6PrZyAG&Qq1!Ce zD_IzCw5wE)*Yl`z1LVhL4H}u{t&w%sY}!i1k{>tTUY``c7e)oeY2%q+RO$trY&7K4 zO__!t61ng?`fZ%0-a|RBW&0_{@6sKXsWRESr+WWe+2xO=e;?Y$j{vIWH4yeBuw^GLDC ze=_mUpfeaq>wLFvu6PP{D*iSq4_sb2_`YH)K{ax#_v@Ri<-x}X1 zi@cv%(i%7U^}b9nofmz~e$XiVS?~;*3e^|tuBhG5b}JjX3A&ThKqmHs+E^Z`2ap8y zGc&cFK>;ar zcG1%j59R6|Zyhd!9lC>V{hyV>UVInJ)NX2(E)7srtUJRJp^yi?NECzAV8TPBU3MQ- zleJrBM(xb?-1~fiRZ>?|Sxg=*QxmP3#_vYzx3+eum5}D%GfaWG$gqiLI9Om>WRF=mwziL;S63-YdU{jI=(BTor|b6JbemOsth=H9q= z{_6ApaiepM!ML36pUJ)3O7tHs#D3prp}V=@Lo-e|2%D{QWk4n z8YdGWv*y42=2WRVzy7yj1QgLfZP)H)KGTrDTzOb4SpN*$nN7`5#_B(aBpj!($s|9W z7}TMJe;K9xev7FRz4!k@AN8gTaG@KwN&LIq8K(zkd*Q=v(zpT5qBC4|MU+LX+93 z_oSzlseigBJ7}+S5L8OYzW45;)ge;+R9qE>^zykc?@Dre(YZrP#cxre_H7@Ga;XW8 z>D?IgTB}<-xR!^@l49c59G>3pXEsylL%pydriZ_7pCp$?)tmaVXD#(d)K&ibi>zje zsjBj42K74sSUUf)Zj|*Y%+Tb)Zr{0shU&jAg}-@|xo;W`E2k0;;zN*(NUe1A`(O;d zq8ifJz4F}ApWn^D7RKnkSmgfmum657;g+3CdbhT3m-YBux*i9C-Va(~i^N)XevLj);KBOb7SUz`{giKmjydDhp^abA6f-`x zNw!sb?hz%!O`1TnxTkUn*L9=*D+#xmr#1qe(cBqjTkaJn_cKaq7I~yzpgi%`LFU_D z(>)N2`fWA9%jRsVzoqWdPKdBcA2*Fdo8RZ0E^glYMa00gTQTqv1llxv*8?<89}4$= zmln2^7VfT@9{4@S#c$U>bkLmih2;SOCF{=pZ%X z**|VRKj$x`DEpb_z<03iIXi!SS6Ues-G^#lNbIBF z>2+%zHllELznpkf=jFkOFJ1T;+il3>vUuVoT<}!G<7x}r<)1VEoUE&x*ChFHlq5W) z+(Z@MQF5&J6!!YWDk*kQ&~IkS*m9B4m8fPJQ0{y4aj_36^ZMQDQ)KD)teIOIv#n2a zU7UGAJgmKMYgF;t;_WFu(F)|LWsBz)1q@ZPPy|Bbux#yq3~ZO%?R0gDUW7{TLP=4j zAjGxHrvEIx8YDH&&n(#}6;uB0!?~4XZMk%AIFf=)+{R&m)R@jet215Tbl(^EAy5xJ z&*-eXRYF=_AoGW6ee2ky)~^(EXRPM6o4N7%md`+t3;%c=ZeZK`>8{AW2W|3*&7F5jncrLzFKTTH{x3CI)h0DEo8=}4?QXsGnZra z=w3x{7gqIE{YW%6tWWyHyh^q^L7=htU0EFOwy4C%_cN>& z&DmMmmDP=Q8!lZtw_0|6X(&I-dj3#&*2{4QZ#|++cPqGYy~iOWFm9`9Dfd{%%M-cG zwtm(oB*4jbs=|Tf;0@M?8h;w`$ZX`zwX)mD)=K$ICrsKR0s(^3i}yMQ==HF+`oY4R zhwcV9ZaUyLYHAlYhagW}Ur#zxpAD$>%>Z+~5L|0gH#g}Go%>d*Bhy*Tr$eF0Bf&E)koWG`)Azs|@VjIUG^1*s@1^@8(Rk zX5U$4Zr1tN$X%ya0JPa2CW}+}OPP;dfDDER?Xmq`a&xIYTm^t>E2R^~Qy*V^9wdg_B-e=pQGT|7Bi={RTh}3?G0hcstv%@ds ziZw~RmXB_#bT!97Zq>|WBZ-Ci<2Eag^RgS})2!@d4ts2W^u zmw7y1hUju;jhn>X>ATcdnER>7WwJ*$?0yT?JuJU6GJxVy&*U1jT#ub1M?iNr5X2|5_5?*Ky9;o3;?2UtS{Qa>yFOzCIVcY z);a##rf~z~JujuP#s>JERWK~|Rk6dMg1Wnk&+si&Ktpsy}h4YOK zU?c7x>Wv_&x!hqeO7{ z+tBktXd?nrYpCE+dQVpN>t#@12)mR*RuXW!RMs(yXzid45iI-B6cO!_c9e8clU%QJ%{*Hs#3r{d-Gjk|D z1E!EkdEU1_6&|XLH<@(4?IR{Dp9*bVGQ&&n4N+bTOzUe)C{Q}lG0JYZzmF!<7Re2P1aHb@a(&@*)iqD;s>Vv+Iw(gRjeN>MFo& zfcfrF%z8y9+;hqJW#sY^yo=r{8pC*xU0Kcv2p5(^*1=ca0CS_`A@w@-ACI%y5PfrtS}VxI*i0Mw<=dRGa=E~? zhn1;_G4ISRsQUS;Aymnr6On>xpFf#qv^o?X^MO7I(jBEdRW{4alR6ep+IEge??zke zSmWUEW)3A`Gu+csmh?)e2SAsv53Rjm`)fEsg4Yxhsx!uEooP)c&t`+q-5;*DTth{* zX2t6uo%MR*?QTD7&BY5VM)Z1Xm+-FRKUVw31J2siBTE4&+$%he*`-umLFRR1g9g#K zHksz4nqCud58rvy4dIAcvKrR*X@Fu-dR79Io3*S|>yAKeTU1Ui$0&_mdn3J+Z!X?T zb5W4BBKRrxC&cWW=kv+5h(+McBxvf|TBWnV8HEm~nS>4F1>C72Mi-#^A2mazZHZLW zQIaXm*G67aJzpzTwXPaXkJOqk>ew@Slzn+4?4Fc}>C~|6Cet*;%NTtzk>RYVgnU)_Q$8 z=WvdC-e7XPyxXH%e{yK7<3=}$1$EoTmabJ_-ib-;yJG;O#6I#OloP158#&ucr$-Tf zRiD&)=_8Tx$=!@O3_w=|Feg^dp%zY_xwjrdO@Fhmy}a|Zo8C6vz@2B9$7=md3!RCj zlB+fSuR%9}cLQ46>^wY%h1vX(Ds)f{8{m<#-jI=gh|j}ro|bA27!ACX zqw{HmuK<{|mTS8MD9n6~>{0i4^o)(n-RHS;j&7D<-Yj>_Xm>G+Q!yIPH;}*C3l@_# zzsA|JB;7#bDJC-C;PoQD^uFI(aR6Irp}KDw{w*t z5?ZKbj$;lzGN$Au$!pJF*4v7tbgb@%m!cXL%jw&<%^sp1Jw+-0I9#Ul^ZR3Crf&Wc zot*6%XxmpMrL>wTTw?-c@62B>11Jt{qT6&5Ab(+ zShTmibP6;kQb&DOxbQPDpA0X+ba!KZzs?FlR^C-ns0ylBrP{!r&ta22{X( zB@*)TnkQaB`qw5fH>L;(XrnxSLl*#Ib~3h7Em#VArvN)PF-S$CBJhX^(GzcvqF&WuPWJ(<;C6$r8_Vb6(LmY0BYz+A6?ntNi<=$(a&u{hc5 z@1gLapkD=;so2ghd&EnFf$=bNStTg|fo8ZZaQ7fI6RM1Gs(FmB|16HnIW`~9! z7+#1whwa{cHMfE|DxeWj=@P>Hv;_{Q!L3x*%FRnhY+0&}tu^suW?aiKduj~p8NKCx z0sOd5u;-EMqFYJ&b;6KEmq4`AMKnVfTR zIv04c*4^25H!jIWaoBqykyt>lr@Fip#SxJM@AhBaw?F>`O*rJ1cMM7yeAXW(m|bwo z#-Qn311Bh+?31;(hp%u!CLsP zwt_J}w@yD|HJ`$_^RM@2zZGQy_S$EeEygRH)m0}aG_U<`FdHpXp5nlJ*hoqThgVj^ zD%mrmLk#qaU>oaPrj

$;-rhpf3Rci|_Q|J? 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�OMZjmFeZ4Sgy(tsM}6!z^?7)o-UcWjVf73JME-WZiOo& zsQsQii8YjhJDYrYa(52Ur>x698^89O_)A4EXt26`1;>WnoOBuQYM-rt*-S7vQpELx0eZ(_U25K+ z^+k7bn>~RlxcZjQ+wYvb?mPHd5897eu~&Xh6-b^sPOX{D&TA+FVEgx}+Uus<<~F-e zaqJ{*?l8!7E!(ZZdC$V6uW~xZk(-jFTe|!pd6HtBZNz{Xk$qj;Dh}LYZ0A ztb^F#2+^(-x}Pj3+kqPcx`9#aSFf;@#+NZzXs-+ij%_oVoUFE9mTP^anya%U7 zI%;-v0w5X62<)^2ef%T-XfPjeGlf)5{_m`TgESW;Vy+=khDOM4gn zp>hghayB0~UQE2r_EgQ3&<`l42b=mr65-VivCUFMHxbyCWm z{rnbeP=h`s4~on|dJMbxuC4;)epmB*no(JYoG^dMm6^O=-9+AbU@SNM5{x1>sq1f2l07)okDjXZ*FYKK4K0@rlD zRf3@S^y0jrpK8CN%6G^DF0?8uzlHM)jIY=}FdiTOe0EZX^$@oo@o1K-&_Xa9$KVojVagtU$edQt@Uw5sZvjv>wmUiswuXLbOoD5BrJkB98-&VA31 z=i8>h-f%jns-;u->%v2d34i|t=$13WWxK-~vFLk}B5=p;M5{hSv2uSs0T@cQqTFri zyrDPLZcEjbklsZg5Iu0|e6bFTb-CB7EvL}|s#~UVT{|;rVg~+uv3j~tziw~!JN0TL zx*g9XdGJP*eOunVvuCGAm$rMcSAIV@r$i?n_sKmsmu=&Y9rS35XKnndWK5n(BZa|I z?WJ;X=n8l4be4Mgv*m87HZ@w(IgT8vnUxA7%bN2&J9I0qkzhINiquq$RIbG;| z9SQ8UuzYZ>TfX)vxjeKEeUKEO2>y(S@ZGo9te9-K3FXejwwDz= zvFG}LTYhaaF*#S@W)LzN^*Hv1dH3}UPn~d&9=N+q#kw`$fwu827SLm-sJew1+uznz z*4AhdVNu9#X!A3UG<@llIrwY~O+aTukaV_Z96~Ig8QOrZYrcWCTLVPmFB3kUUl-MX zdba*K+8DKi(&_ZLfIKt=t_Y7s(dJg{DYW!r4{7dw61&b)l zQOiPk2m&j#O;gZgH(fRO49}nSlD|m1#L1{;L+n1k(bW6bXZy{M@bI<SAl1}0dKzQJ{@*TlD8524n`Tms*MnddInaN9;cRvL=RH67pJ(XNUBf@Z^E#3d zKmVNH_l1#bgUD;!7p{H*eRBRb*HU z90K4seF)$$>6S=$GUq-v@&2B`{Fi5H__PhF*l=1(Idlnu=P<;POk77Hg5A%?O z?4NFA9|0`eroyZ!kcGffoT}$x@%>Vw;$eZ2r29?acs$MyarhF(x^DTpdFn@*X| z{qCRqXixv9ov#s8ifbk2kCr!xhmX+f zwRHXGyxji?I^h4xJ$n___y5Ct_PF|8q#Dtqc^Td1sm=cnkKsR7+5dcv8D!~Lh4<>( zIp?ak6~f6y4c@cp5RnQsyK%cp`;G`Lj#GhpQNLq8G#+!o`5#{1{&(xZUt3HFj@Ph> z66_7gQ@C}ctYUPw`2OTt(!JUJD_j1rKl1PQW2Km)`;!b(T4l-hKuoJmtqbnXe~2!> zc{p-c(z*QZnIcsNQRsHM)rO+Em_eIZT0CUmwdED3VgP4nXTE#*up=lXpAq4zBq`9m zV~l6(BZibCcRK;bdzk(0LtY`y(6im>eZ1`RMvq>Fgnc6C4q8{o(@D8km2{#t>ToM$ zX2yx&ZT7XArV{rjil0h=b-e1Zkd9R1U>*ghHaTnAYp;-nK!w|Dv30Vuh8!I-Y>ui> zMc;#wed(Se9`~&{Gu^BE{C4+;cb#qCC=)*@*NeCP#xs9aIrqukz(mCy^u2a>=IAkL z(I?tB(yF|~%P0Gm$1CX%^Bk>_lXPP#$>Ekwk38nOKD|2{)0Z4Pfz^13S7ik+t>Md0D2WA!7c5SN8I@ntTlcpp zA_@qiqF8{Sf`WC4B8Z|O79gPh|I^=O%{{a8KAGq2b*+6qCRfa3F&Lwd-dk&Tk0d&4 z|JZR$-CpK;up}MQasYjv+x+_9?lEH2$(PI-e3hdnO#lIOIt{i0kQ>Fq?y~R<~q!$#0f`n95yD$7@ zAx#Mv4Vg;#72UOKs=TD^$M~~gTiCfHrs#Zsw#z>@z3%>+jPk)J*IO8+1xpyruTLbI zNR>bq^Gh0?efMDDS(dDv6^~BKsreD5`=z*_)qUSN=l~C~&!jQxg`MJVh0$UG=8hQ~ z&0ctv#7J_me>TrKzOl0c7=64c-$ZliUf~)Jl*Hb!blAa}US(=NZ6^q3Y%idT+tNPb z5Hi*D7fdr##XEx=bGeMBUrDi7Oz#Btj5sG}>|`*;>BTt0dJlAzd_K?I``|GC$&li= zJ*-M6ePUl=>|af<=FEYNoX@udP=`z5aIOIe~NzmG6ciuS!he7?_ z_)H(E)7zW4VI%>%t#R;blsA1Sw?>wQhr4C5+uBCNFQbu^vAh#cmRO5z1ed;n$DbmF z=BatcM-OSTA~!yT&Z)bPt!{1}Yz_5wjqswQhXom;+)8x?Vu)5dG6(7SE4ESF5StJ+ zv)TjticdBtFN=B6a242AAf0E2ojL{cyF8?uc1ysglVs665!Kx<6Q{Ndwc*~Cm9coO z9FA>#76Q74GUzU>-GO{9j4P933nGkgg{#nA;(0o7?HBOt`^8qXlr%=4;yBXuKOP(% z@{(77yk|g4h$~~moS5#XWp`6;TJHVX$3HNteUspJOKaXS&1Q* zH&hI9FODDw;Me8knGQrYFF8;8W9-nu`&X={I?5F{#jfF`#=_y&4Q4!~^ech70Va)I zW-H2nsC4cmxa6N#96H@>AiCggK7x{n!&>xc**DFFHnzu;Rv#fw#hOHlep6u?Z8~0VytPlWJ^g;IN!fRhQ@0Xk{$(bmE}**q356~J+m$unWC^Z;FH(KGSM#WKF0j{5q^>2Z^aS2=Tq1<=D8_3 z-_pUdR9z&EHuD@E-TqF<4P_WLLiXU}LX~KuRK+13U0DD1G$69uP+?5pAP>oU&?hcB zgu3+y_6zGegYmn5>uyiIFR=aI71c?+VwCa>SkRsd$y7Fn%lCO67|3?)8E%d(S>vA z!i#4Xo!?*F?6jwDZuy?>zqVtiDmJlb0;yQP?ZBJv5#t-5vw6f@)PCq@*Bp$FG}OB+ z_m}MbGpKR2`r}_aW>e6>N#b!r*otpD&tI#?;jegtU{&9O47Ss)C zjNc3LU;y0FX2##rbzS$D5Of3&*!F=<$9B(qJpKHQ-RG~fR_n5IHwSBLv|uw^)gkpA z^~rSyFlnjn7w1Oz82;FXAc%SqHA?xT>?f_%M3{EvUnd}EOE{_6vVw~?KQVB{J5oZcB>3vxa9K}I>Q@Q~2fI&uS5f@mBZ9InxeBfD z_pcvi-}tyC)%;FW>4iL}X1Ecqi1BErx<5XlH#OPFgmiDPB$Fmj#0Irzulx;qrT1%AYfEeIY>Q^ z$Puq%KA8+{@KYC`onMHvO1o~~*c1s4^?mOf-}25`V99=mhxkU~cKq9>TKF``Np?Lh z2*0wFBvN0*+Wcy!ruDIM&1~we9Yo`*5XVIXN$1zX%xY|*i1i;?z>;2p66&IRIn__A z562Hz<>MuEH2;2KYtM7rxg-BBltvGuy)9d-@->MhJHO^li_cW}s11ZjGMsOPl6*+5 z-eGsAsF&YLp(kvU9xfb~s^m4a9fK*OLP&55 z#pd!|#xJ&{PW?VPSgFT@$L`Jc>&UZE{R?^k`Qa97>61cX!D0vR)8X zEv;zx%}>t}RkL7(iccEeto}}Yg6>&*)`t2Mf7$4hrhSMx>6p136ok*O|M#mjQmSa; z02ya1oOu!bC)Rm4uUllZXk6~?`FH&N%G2(minhOK@u&Ti+~j&Ch-KbdA*v1h?l_;M z13bv{C32EBe|o!1#fffkF&Rqd)dmSVkuf;i0oH5%STUya2bNxC*Fgbqbj{Ls29h7d z1mgB8B8KB83WArPt6Z-{zKIf-Yz9nVRU0eF0GXfOxlvDuo@(>r61tYS4$RW-m20?@yjegIaV8JI-gR@W%%)vBILInb4e~`|m^t$uPD@AaYBh!7 zT7yefO2>D4Xt+QwATHHHeZxEr`yL)vqjb4p1^jz5@ZRH@-jVaVnAXHyirU?_v+jn` zM~fPaQB%>h<7k^or?OAst?cLt5yOSg+W&_QzRC=IB>MoeYeW#K8c^luVG{iKBNtR< z+D=N$+MW@-Tw^b+(e$UO(jWEJ%`b1wQ+o?F;tvg+sp9yRpPmY$z8v%^%pbRw^mx1- z`7ztfbqi;mwXH+MwW({$YTt<3Z~Z2y+Y9CQa+)IZ5DflY#@%`l z|FH4=cP?EJZm%JuYW)_S!~Agl_pZSRt(!zm>#q0lw%IDus<3cgrR4eV?SFP$e_Dfm zU*9ip+b6s9h)C=x3;ows8tJDlNOpQG-g>XRoR?u{dVC>hV_*EL95ZR>o@vPx}k-P`5u4eP|8B|opc zq7`1csGq{8Z!;xj)Ygl4N{e0sK2j;=5 zl==hTNR)Wdnh;xT^Lc?l_x9-YAZImB}Iqi_2NF}mFyG(m&yX(U$Nln=Gd^w{71I=bN@DiNad*dU{FP-FHYY1KC^Ot*G??N!? zk1bZPI-?DsvPxZFY;0hKd~?j`9_8uu{Bn~MWJW?ONA(~czKQGkR&nTjQm6790-Uwe z?!#gIOTK6Nt57rqyH&X@qmFvP55!H5cZvkl>5MD?w5yD#)e<;wq;R1GLdD%cvPf^! z*dZgj+CP3)<;vH+V71)jc--6~CmlMKBbg` zF664wo0uR;eH4rJWorD!#=rMV6o^m8UjwhKUkN?v^cL4O1S##vN*@BPtVnp2grYH% zS0nG=EjWrg*w?`6O$ojFBI=b>L9;HZR(;vaMS0leIzqQw$U=|t$DZJTe^-|Ingxj$ z&2AU+06)uU71p64s`l3$vUBrCa%3zgov0hpW;0d%ddXqUg}Ea1+=le=0-ghDa^)cg z_tMNwv=&nN@v303e0z_`f-^HdV0Mc@KUH8_G?~A? zz!5#f!A>@Ns9G9zSho0c=L9a9zrL`CJFgP^r+hIg?r~ou-46g@%W`YGC~DfWTN>6@ zz)yzory)Kg1?CP#T<(6=$u*aj5VV&_N76g0LObms z+N5wBTvyX5KjEFyAJbUIx|b)|D!k3F9NJh|_s;6okipUV#>q1fWo^rh^~GigvHp>K zn9BDvI}$tBp=%#kPY~z!k8B^vqq#$Akd)&=eN+JTl~R2c?%`V`x#dLRYkte2zEbW^ zgYFen-;hvfn^K3U+46bLjQzrF{sk!Rd&zyaoOe2II%Kx_>{0 z8}xHi3U9z&zf@WTU1*#Lb9Y=x7c0NO=p#rtK(p1j?eln>g1!NrY2G)D8+}91D<3do zot^Q%4~C`h**gv9%R6;g05f|a@80;j0v?g~V1pN^*)e8oY^Z80_5!&#hK+@iW~D+x5}-IxC)H6stZfr=<%mgXaC{HcPv&__Zg#=zh$DA>T7?Ks3Y^ zt6gmE)IEW_F|%|)olIKHJ5R5<_)Qi75baO28-`DM_yKZrR6ctp)sa^nG7mD z?Ws$--1>DnUgb$5k(J|CaEr>-){7MK=dE(@wMwR-M&%X z|6C#ttsX?8_X~8U&vUAdq#xE=yM44+T7W5_AG{WGgc|nmpocpwRPrl87V6mCp9VGX z^9&xUkEv4d5O3YZSGPx0`Fn3T7oYp8 z*OsS-ezHfGj+%W#=-)YC$uk;LoKx@CFeigVqkocA3$j9Z~dVT-YuX}2_m&Kkf<=`8fr^< zb$?wg_y2IUgjW!Om=3Sk*G7));3ACxZ7imtG{Lm_j6Y>&FUwc692>f$b*(jX9_IgRoiT;y+*AFRO|v|8om;ycG*PL z)Z3XAe!l=3B@$zwjkatj-_}4s)c@#*{X>5!kl>*|w6-)N;aevi&VPCW{`q>iz;3}$ zU#BZwRcEwmh%6n-LS zIM?f_o$mtx6lb$F-p*6HUPgo*;PhJOBb$P()G11zAutm0Hiw9XFCu*{TD)%+{V_&NXbo)4w>gn;XpS%2zKX(_O-5|*83z^CA$F~Qx<79Pk zsC2w%zd!$V57=#-%^nDRS071u`|U$Rb~B8qQj7n~26aykHm(cgt@rLJcrrQ)tUn@P zww*EU?f0Z&)Ka~X&m=g62BffTDz)aQX>6no)0}njqmuh^ z#4c}#{Er38|I7rs6p<|x`PHsO0MET$pu^)UYE9+aeO2ngX!^HVYCqGo+poe@*510t=W2R7w+QS>%V1 z2YOZxR%Zlc->V?amxD2L__G6qBit(7beZ%$F~Q$Hz(wt+8Tc{{(AC|Vy6*Z6{i!yz zqH^bMzmIvZnU+1gj6M*C5?9gzc33ns1Fdk3g41pfnB-j>|E--h?BN-{o|iY3)@?BG z3yo8E_Zf=GVkq3(BYSEg0;w>Y><`oCuhXsdbDz9ZeSJ{P_#jcv8Pm*3OpqEK)weP7 zx0_}!?I=r27xKMXy{#;$awTGV*{QdTi<@)LN0|52BMR&wH-?CEe!6hxR7F{g|2hTD zWGnsMC;J{WI&Tyr0J(Gfv@vpgxXhAv#^_ZXL5NCu zZWOtdc)$v$^jU2xRW1eo+W%5d;Q92c^I{|pVRb7Cc`@#nmQ=A7KC}LwY%)6TH`H^v z>Jf7^kiV=3Lk-l@HvYbKf%SYKO;^<@d|5lz33A6AF8S9lF$Ef$p-n@3ib$?;90pvnD>9$obQ0Wd^A5 zkfWMAYfs{NI-OAaN0%QJ(rr~kv&yH~F0k=(H-n(gsIsG;*BM)d1dqq`cy8;MKv<3Q zvwdkbT7}n57~Z<8w3;3kzIVCWe#Dw56b6X^)->xzWX*17xhg)fTYs9j=cpMM4@kBT z+FF=y2r@gXw^TzD58oyMh@5zj=~02nrVa(TQFf(n7Os)Lch@rQF_MPP$(`CO-n%&G zbbi~nOL~5?@3s23Yr%{8UA~RlV_@sG_mV`dBy6w5~1O*3<*$O%H*UOziv#IHTbw%fSRwEfA#>iNp7cV=Gu z>2r11=w)CJ>V<(u&jD6 zVAspzJEXb`H)Ta+7B@s_H5%+-f;WoXlTrKnx2g|~l#G-gxi3}TVO@@-Gz}!d%~x@% zteHJEujCZPom|;#W?xj6#a=#h!ZvT^Wf;<8vRWyF_X(nsZJ*uDItAkNL!8^TN)%XMqoFUK3oE90BuRV(A8 z&Mvovh?wgT%Q5GuoqskirFRhVDTbRxgKX8m=056N@2}GB7g2nf&%=(Nxvy*Xd&-vi z5Fj*nAML_f3qDWpoPR+G^u6#*=nE0I!&EnIM#BU286~Ew+)|>O%TIJmVqR*LS)?wf znN7$0v*oNQ_ZU`C0jE#ewQW8NI z&@Ki?<#{@pjc;+RTpU9Q>RCugZNcfJyxB4+p>AAZX$g0ckTznq*GlkVM+cH;h%5DU zRbS=?QEJ@UIAc;BJ=g}qlXzm9?e_VWnFjm#LR`m-&-lD8C(Dc{Nob5TZ>&F=qK9LG z#x17}kSmjj%&AvS4Kt2h4!TYEOF{3Hr|M>;rjs+$zAiHT-S$bm1l;TGI$kj`+eHmu zVa1+z<42q|5_#F{r5ktppdGxir<|_& zTOH`kr%|?rx1!}+&CILR1hXqk4ac^vnd&vRh*3+SxccZ(1ygw*kv+{dypTzUV{1XF z@_K2ov{5*C9=lK zq&nem-I1Nx7rEAsKkL*lXl~p)zpG0zDvtC=d$P;;W@l|L)AYNeVude}dKe#YU=4t; zZuL3AlV||dtfY9b?{0=$XY1~!`{!ga?j*~pTnDIOr{_ad?UVP%%~LQaXH2sN+FUO1 zLTsRJvqNiJL5(xP)m%?_JN6*HL0*1nro2;2Yr`P_)p!@T+s`1`0SVqrf4T_I+DKHQ zdxazvDAy9exi9zLY~DUCm&dy!Hc{%qTOG61FOL_NEMS>%lfBOK4BHfKl62ZuEl!eq zsE?EckY=y`xfQgA{iS*c53Qq+WNfnQZ$j!|h41OAUY>#oVZX@Ndj>hBp9nyPfU+b) zDM^b6Vw0&0+mq&>y_DotRl1ieRK2@$5%EGR77UF{|yyHc$rio_+L& zv3qoxbr*Zt;jmMD6EH^$UQ9j^c$v?<375UT$K9=TYzg3@7OKaSuo`B(V`edB#Up7L z4XU&2o}Fd{5su|}YZwLfJ@7Ng=UwRWHKjmw9?rL=QWtK%bo4tbwESYOf6IxTu=GK8 zYjQm5s7Ns_KUo3IcY^#Bpd7P#u48Zwz6lsk5Qbl?@W=h;B$Oa#3>eJY&KsZFD_1UJ z5f8j<4$iX6w^e_h7`BMEza)g)GKbA#)6SEC9Y&0aRJl04o* z((%#M$!cquVU{oU^r=`>{)OJLiIt*{jD2o4UNVa4$9g9d$K_i%_4=v4rp~0Zoq?Uu ztc1OubluU(@-v=vi>KugKFm4Xb@@Ux{1kTgJP(INIdcPI*lLxkoLifz=)!Ve#5Jcc zLb#jbtNNh`44oYY%(NsfozNmcE1*+eath&xIwQ5p5Gn1DsZEJfeT%%phq*YT$v&ZEgJINi&<6Dp(qV}^E;d5v zE;zisjLm(vTTGM3MhjGsiFq}LfTvm$`$6ZMazBTR;%#E2cJd%@M6~wth&xP^m-(yO zX=-=zy?BhQbQ;}(fnj`ObcQBTBvpOY)prqfh2#vSxNy3d(_?yj;76|+BxYe82Mi$% z!Zuh)CLj-L7`I0}7m9J<_Z`UgY5H64Vdk=%tHpW1YB}yZ1hEyEDZrdMcthbI#aaHX zDg8w=*`6JHMrYs_MKAmBT)LT5gvz)-FOVhm5n-XiF&&s}`IG!21P+K@ptqKwS-T5_ zpeXDFtVH4+y$#B%Fn%oj%`J0z2MiEL>J97ifv4^3aBkYzHg5A`G|LR9ZM~jtmrDcr z1b#fH|MY3nD6JP)S`-csJ10fut*)&gh}VWRdvi|N3P^pDr{JPJ`O_P4FJFVH)-+aT zSf?TK^E@a4K6{2x4lSj<+Mn1Y)!fI^>V>o4rAe(ujTmK;LF_VKXWv4Vl5?BQn{hLK z`&%_m3ezM}E!J$bn*(~{*zt9e)wCVTj12j=sP zo`e{nj`6Is3sy-eeP-}| zcTt?_Os;cg*PF7BcsFi~rC&=SJ1I003RJGkh(nDUdBt=+Lb13&)S{21n1L} z+m*#n@}#V3`XMW2Shi(P*CSya*88mhNZPwvm~pDh+DT)p(`;M-PC--m^>l^0kzpt5 zfqC+%WDV3b`WI~WZf3A^wm)B_7GLnBzO`Fzg#_W zTUL7EK{HqBS^gX9$KV4nuW>3ijVPG*<&i}e>0|sV!!{3gIF@x9jR|qg`bMR@xkHE% zs1M^ziVM_#BiYIf0-bA$2)uNM$)Fk1w)OO4A@w3p3~WYO;f%tyNb{ zc`0QkE}wj=ZH}i`a;g#&ubD|D>-RQMaZi6V?)gS(hkl4ruvZZB4e0l2zq&c{%#F>d zpAC$54>xp~?)Fi7{oYp`nMe%GD*`3U;P6U9)>Vr1me>jwZjNYc*s-0wCohV8ngT`v z7k2wEze^JxbW2@n+LRw{m#oqe)WGF-+so4`KjnM~k;YbIt1Bf~1(nWLUt9O1bxn}- zXLmBaP1V<~2gZQ{IX7Or3_i}(91}&pCTtp5bRZe0okR7H7;m>TGFBd9oarpEK@*6qcsbS*-I%#iOY)ZMq{&76#4jp~Vd`7xo zSYr%+yLCJJ!=BlC+~=7+PNQn8Z%nfNIF&w()y88NJW|!2I@nW%K}QG+m9bjByN~_2 zCI{6;$(%ckQ_hjeHRTOjR3AJwM>fmuU%Us&qHpe`JEz0l9X7Wr;S%`<@Kc;?si@z- z@dF|Hg08ZJhfe;=wf^UlM>{-RfO{t zFx%3$+PZhDS!i4A^B&UWJDc570a;lpmzlP@Ec|z_w3G2pX}Db*8gY`}Vkxfq#yJWz z51dw#h<=Zz^Uf?S5uR{Q5+S337?M{iR~_NgjmNU?eA4uDofD$Z>c}n1ii_s&UVUh# z3ssc$q-s7qgQ*3ss=I$rEpK^k(h!I3_NsN_XgK zA$i3AQQ!U-WhR@L!krN07x4{W>kEBF3X8a=0FzdbRCd+TYYU-XxidR{dj zGj4J36`BnrKR)*=q1WO-fGu^WWi=2_w6*kV8m_>KLEUUG87FRfe<69foUEbQa461> zjqcdx*Xp)QyNVrep37c5C^BhM*$$5lBT6nZw+NX$c<3kIZv0xh(>bc&$$Ui%qw#&H zU6tYMi`lDf9DO z^bSS&j%^uQJ zEbNR8bXHh%cU**(_H=NcfKbP3pA@&|Fx}KxmC^F?0qle8{g%yVJ>88l!0~9ee|~Dw z3H09omuR$y&{BTWrx$fd#|X2>kP{%%8y?2HFXTbH3$LQhpNaUXf;?aSkGqQ2 z*-vJ+?a!5bsaTF-uR%K)bvXgryE>J^!Bs=Hkcq5Y3jll$f2liunbvNP)429B;2-}K z?7l=ke2)Ivp8bD$cKl!N<=;lc{}mHqU)TRxe!(uXGx1-_m1*-=7ozfCCbMw<;9H!T z`O&5Jvm)hx_H6to%?Zrur2CZL=;MB$rpLdfZorJWuEb0(RbwuG_I&gj|JIE_P?0FJ z--#LfV+0Z_elQjPgH-;%Wx)Q~Mfaa-i=nO^Pdi>-{^U*qXM5NAYjtDa0a5WUnF~>$ z%k1!ir%0P!*}@Rb^Z@JWd3uDrkm&y@p~&vy$Ld-*cAX^^PpE5FlHNJt z`!~l@D%-uRe>`0O|0~sI#o+(7RGU!_7`Or>9sI(`qxSh8i)cH~xo%E?X`Gw z0#r{U>-r?1Bb?8Jln|ajw_np&;vYXGp9^HAt4=o5Pxd|68 z?a761XrO4W!WEFCr+DMWuRXi?KqY{^^&!kLm9F;EUaCJU=T6q>3dt1odc$~h6AfSa zj)7nHsm19FY3pm+@^<>HgZhvplg?fJE&2T=MKq%M1Mr&UZ^dR&_%wDF2`T+Z&( zGPuQnp!Qey9>2KsSN3XnRrt=)U5y_1`&FW&@v1oP=?6{Ucv*DCEMQu@%k{ig)G<=E zZMv~9yV7ZQZBqfe{iQO)|jx-$g`raF0LGQ zzfhChOo0?8jK#BgjPVK(Y8<%0DJ?u7b2jt)7WtTMU-4{EzaR0ioqCS2M@HDsc9~@n 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 bXQ+Jl+78j{``{rdTA=7(lF8Pf{mcIc-3{z} literal 0 HcmV?d00001 diff --git a/experiment_example/reports/time_complexity_report.pdf b/experiment_example/reports/time_complexity_report.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9bc2099696e98e51fd2d619dc4c94983b871c482 GIT binary patch literal 116361 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 literal 0 HcmV?d00001 From 1dc142fef4c42e0f006756bd3725574c4ec1fea7 Mon Sep 17 00:00:00 2001 From: faux66 Date: Thu, 9 Oct 2025 22:42:16 +0300 Subject: [PATCH 13/17] fix: test --- tests/report/test_power_report_builder.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/report/test_power_report_builder.py b/tests/report/test_power_report_builder.py index 71138f6..340de77 100644 --- a/tests/report/test_power_report_builder.py +++ b/tests/report/test_power_report_builder.py @@ -55,14 +55,22 @@ def test_generate_table_data_has_correct_structure_and_values( table_data = builder._generate_table_data(mock_alternative, 0.05) assert len(table_data) == 2 + assert 10 in table_data + assert 20 in table_data + + row_size_10 = table_data[10] + + assert "KS" in row_size_10 + assert "AD" in row_size_10 - row_size_10 = table_data[0] - assert row_size_10["size"] == 10 assert row_size_10["KS"] == pytest.approx(2 / 3, 0.01) assert row_size_10["AD"] == pytest.approx(0.0, 0.01) - row_size_20 = table_data[1] - assert row_size_20["size"] == 20 + row_size_20 = table_data[20] + + assert "KS" in row_size_20 + assert "AD" in row_size_20 + assert row_size_20["KS"] == pytest.approx(2 / 3, 0.01) assert row_size_20["AD"] == pytest.approx(1 / 3, 0.01) From 597cd846f413e3e195f125ceadfb1cf5dd560c9e Mon Sep 17 00:00:00 2001 From: faux66 Date: Thu, 9 Oct 2025 23:12:54 +0300 Subject: [PATCH 14/17] fix: cli --- .../cli/commands/configure/alternatives/alternatives.py | 9 +++++---- pysatl_experiment/report/power/power.py | 3 +-- .../cli/commands/build_and_run/build_and_run.py | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pysatl_experiment/cli/commands/configure/alternatives/alternatives.py b/pysatl_experiment/cli/commands/configure/alternatives/alternatives.py index 1966319..ba9f876 100644 --- a/pysatl_experiment/cli/commands/configure/alternatives/alternatives.py +++ b/pysatl_experiment/cli/commands/configure/alternatives/alternatives.py @@ -39,7 +39,7 @@ def alternatives(ctx: Context, alt: tuple[str]) -> None: ) try: - validated_config = AlternativesConfig(experiment_type=experiment_type, alternatives=list(alt)) + validated_config = AlternativesConfig(experiment_type=experiment_type, alternatives=list(alt)) # type: ignore[arg-type] alternatives_data = validated_config.model_dump().get("alternatives", []) except ValidationError as e: @@ -49,9 +49,10 @@ def alternatives(ctx: Context, alt: tuple[str]) -> None: if error["loc"] and error["loc"][0] == "alternatives": if len(error["loc"]) > 1: index = error["loc"][1] - user_input = alt[index] - msg = f"For alternative #{index + 1} ('{user_input}'): {error['msg']}" - error_messages.append(msg) + if isinstance(index, int): + user_input = alt[index] + msg = f"For alternative #{index + 1} ('{user_input}'): {error['msg']}" + error_messages.append(msg) else: error_messages.append(f"- {error['msg']}") else: diff --git a/pysatl_experiment/report/power/power.py b/pysatl_experiment/report/power/power.py index 9f7a372..908e649 100644 --- a/pysatl_experiment/report/power/power.py +++ b/pysatl_experiment/report/power/power.py @@ -111,8 +111,7 @@ def _generate_table_data( for config in self.criteria_config: key = (alternative.generator_name, significance_level) results = self.power_result[config.criterion_code].get(key, {}).get(size, []) - power = np.mean(results) if results else 0.0 - + power = float(np.mean(results)) if results else 0.0 short_criterion_name = config.criterion_code.partition("_")[0] row_data[short_criterion_name] = round(power, 3) diff --git a/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run.py b/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run.py index 93a5db8..bcc46fb 100644 --- a/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run.py +++ b/pysatl_experiment/validation/cli/commands/build_and_run/build_and_run.py @@ -281,7 +281,7 @@ def _adapt_pydantic_to_dataclass(pydantic_config: PydanticBaseExperiment) -> Exp StepType: lambda x: StepType(x), } - legacy_config = from_dict( + legacy_config: ExperimentConfig = from_dict( data_class=legacy_dataclass_type, data=config_dict, config=Config(type_hooks=enum_mapping, cast=[Enum]), From 0dbd119fc0f0a1055f3d23df59678076228b3171 Mon Sep 17 00:00:00 2001 From: faux66 Date: Mon, 3 Nov 2025 18:57:42 +0300 Subject: [PATCH 15/17] fix: experiment configs --- experiment_example/Quick-Start_Template.md | 136 ++++++++++++++++++ .../configs/1_calculate_critical_values.json | 2 +- .../configs/2_evaluate_power.json | 2 +- .../configs/3_measure_time_complexity.json | 2 +- 4 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 experiment_example/Quick-Start_Template.md diff --git a/experiment_example/Quick-Start_Template.md b/experiment_example/Quick-Start_Template.md new file mode 100644 index 0000000..0e37a5b --- /dev/null +++ b/experiment_example/Quick-Start_Template.md @@ -0,0 +1,136 @@ +# Quick-Start Template: A 3-Step Experimental Workflow + +This directory provides a set of template configuration files for the `pysatl-experiment` framework. It is designed to serve as a starting point for conducting a robust, three-step comparison of statistical goodness-of-fit tests. + +The goal of this workflow is to help you make a data-driven decision about which statistical test is best suited for your specific hypothesis and potential alternatives. + +## The 3-Step Workflow + +This template follows a complete research cycle. Each step answers a different question, and they are designed to be run in sequence. + +--- + +### Step 1: Calibration +File: `1_calculate_critical_values.json` + +**The Question:** What are the correct decision thresholds for my chosen tests? + +**The Purpose:** Before you can use any statistical test, you must establish its baseline critical values. These values depend on your null hypothesis (the distribution you are testing for), the sample sizes, and the desired significance levels (alpha). This step calibrates your "measurement tools." + +**The Command:** +```bash +poetry run experiment build-and-run 1_calculate_critical_values +``` +--- +### Step 2: Evaluation +File: `2_evaluate_power.json` + +**The Question:** How effective are these tests at detecting the specific deviations I care about? + +**The Purpose:** This is the core scientific evaluation. You measure the **statistical power** of each test against one or more alternative hypotheses. A test with high power is very good at correctly rejecting the null hypothesis when it is indeed false. This step tells you which test is most effective for your specific problem. + +*This experiment requires the critical values generated in Step 1.* + +**The Command:** +```bash +poetry run experiment build-and-run 2_evaluate_power +``` + +--- + +### Step 3: Performance Analysis +File: `3_measure_time_complexity.json` + +**The Question:** What is the computational cost of using each test? + +**The Purpose:** This is the practical, engineering evaluation. If two tests show similar power, the faster one may be preferable, especially in data-intensive applications. This experiment measures the execution time of each test, helping you understand the trade-offs between effectiveness and performance. + +**The Command:** +```bash +poetry run experiment build-and-run 3_measure_time_complexity +``` + +--- + +## How to Adapt This Template for Your Own Research + +To use these files for your own experiment, copy this directory and modify the JSON configurations. The key is to ensure your parameters are consistent across the files. +#### 1. Define Your Null Hypothesis + +In all three files (`1_...`, `2_...`, `3_...`), change the `hypothesis` object to match the distribution you want to test for. + +**Example: Changing from `Normal` to `Weibull`** +```json + "hypothesis": "normal" +to + "hypothesis": "weibull" +``` + +#### 2. Choose the Criteria to Compare + +In all three files, update the `criteria` list to include the tests you want to evaluate. + +**Example: Comparing `Liliefos` and `Chi-Squared`** +```json + "criteria": [ + { + "criterion_code": "LILLIE", + "parameters": [] + }, + { + "criterion_code": "CHI2", + "parameters": [] + } + ], +``` +#### 3. Define the Alternative Hypothesis + +In `2_evaluate_power.json`, modify the `alternatives` array. This is the specific deviation you want your tests to be able to detect. + +**Example: Checking if tests for `Weibull` can detect an `Exponential` distribution** +```json +"alternatives": [ + { + "generator_name": "EXPONENTIALGENERATOR", + "parameters": [ + 0.5, + ] + } + ] +``` +#### 4. Adjust Experiment Parameters + +You can also change `sample_sizes`, `monte_carlo_count`, and `significance_levels` to fit the scope of your research. Just ensure the `sample_sizes` and `significance_levels` are consistent between the `critical_value` and `power` experiments. + +By following this structured, three-step approach, you can systematically evaluate and select the best statistical test for any given problem. + +--- + +## How to Run This Example Workflow + +The `pysatl-experiment` command-line tool is designed to look for experiment configurations in a dedicated `.experiment` directory at the root of the project. + +Therefore, to run these examples, you must first copy the JSON template files into that location. + +**1. Copy the configuration files:** + +Firstly you need create files +```bash +poerty run experiment create <1_calculate_critical_values> +``` + +**2. Run the experiments in sequence:** + +Once the files are in the `.experiment` directory, you can execute the workflow steps in order. Make sure you are in the project's root directory. +### First, run the calibration step +``` +poetry run experiment build-and-run 1_calculate_critical_values +``` +### Second, run the power evaluation +``` +poetry run experiment build-and-run 2_evaluate_power +``` +### Finally, run the performance analysis +``` +poetry run experiment build-and-run 3_measure_time_complexity +``` diff --git a/experiment_example/configs/1_calculate_critical_values.json b/experiment_example/configs/1_calculate_critical_values.json index 88c93f1..48053b4 100644 --- a/experiment_example/configs/1_calculate_critical_values.json +++ b/experiment_example/configs/1_calculate_critical_values.json @@ -31,6 +31,6 @@ 0.05, 0.1 ], - "storage_connection": "/home/moveton/projects/prog/pysatl-experiment/.storage/result.sqlite" + "storage_connection": "Here must be your path. Please, configure it in CLI" } } \ No newline at end of file diff --git a/experiment_example/configs/2_evaluate_power.json b/experiment_example/configs/2_evaluate_power.json index 56432f9..afa4218 100644 --- a/experiment_example/configs/2_evaluate_power.json +++ b/experiment_example/configs/2_evaluate_power.json @@ -40,6 +40,6 @@ 0.05, 0.1 ], - "storage_connection": "/home/moveton/projects/prog/pysatl-experiment/.storage/result.sqlite" + "storage_connection": "Here must be your path. Please, configure it in CLI" } } \ No newline at end of file diff --git a/experiment_example/configs/3_measure_time_complexity.json b/experiment_example/configs/3_measure_time_complexity.json index daee575..62c15be 100644 --- a/experiment_example/configs/3_measure_time_complexity.json +++ b/experiment_example/configs/3_measure_time_complexity.json @@ -31,6 +31,6 @@ 0.05, 0.1 ], - "storage_connection": "/home/moveton/projects/prog/pysatl-experiment/.storage/result.sqlite" + "storage_connection": "Here must be your path. Please, configure it in CLI" } } \ No newline at end of file From f30d26ab53fa31a717b4666b26fcbb82c991a0c6 Mon Sep 17 00:00:00 2001 From: faux66 Date: Mon, 3 Nov 2025 18:58:11 +0300 Subject: [PATCH 16/17] fix: rename file --- experiment_example/README.md | 136 ----------------------------------- 1 file changed, 136 deletions(-) delete mode 100644 experiment_example/README.md diff --git a/experiment_example/README.md b/experiment_example/README.md deleted file mode 100644 index 0e37a5b..0000000 --- a/experiment_example/README.md +++ /dev/null @@ -1,136 +0,0 @@ -# Quick-Start Template: A 3-Step Experimental Workflow - -This directory provides a set of template configuration files for the `pysatl-experiment` framework. It is designed to serve as a starting point for conducting a robust, three-step comparison of statistical goodness-of-fit tests. - -The goal of this workflow is to help you make a data-driven decision about which statistical test is best suited for your specific hypothesis and potential alternatives. - -## The 3-Step Workflow - -This template follows a complete research cycle. Each step answers a different question, and they are designed to be run in sequence. - ---- - -### Step 1: Calibration -File: `1_calculate_critical_values.json` - -**The Question:** What are the correct decision thresholds for my chosen tests? - -**The Purpose:** Before you can use any statistical test, you must establish its baseline critical values. These values depend on your null hypothesis (the distribution you are testing for), the sample sizes, and the desired significance levels (alpha). This step calibrates your "measurement tools." - -**The Command:** -```bash -poetry run experiment build-and-run 1_calculate_critical_values -``` ---- -### Step 2: Evaluation -File: `2_evaluate_power.json` - -**The Question:** How effective are these tests at detecting the specific deviations I care about? - -**The Purpose:** This is the core scientific evaluation. You measure the **statistical power** of each test against one or more alternative hypotheses. A test with high power is very good at correctly rejecting the null hypothesis when it is indeed false. This step tells you which test is most effective for your specific problem. - -*This experiment requires the critical values generated in Step 1.* - -**The Command:** -```bash -poetry run experiment build-and-run 2_evaluate_power -``` - ---- - -### Step 3: Performance Analysis -File: `3_measure_time_complexity.json` - -**The Question:** What is the computational cost of using each test? - -**The Purpose:** This is the practical, engineering evaluation. If two tests show similar power, the faster one may be preferable, especially in data-intensive applications. This experiment measures the execution time of each test, helping you understand the trade-offs between effectiveness and performance. - -**The Command:** -```bash -poetry run experiment build-and-run 3_measure_time_complexity -``` - ---- - -## How to Adapt This Template for Your Own Research - -To use these files for your own experiment, copy this directory and modify the JSON configurations. The key is to ensure your parameters are consistent across the files. -#### 1. Define Your Null Hypothesis - -In all three files (`1_...`, `2_...`, `3_...`), change the `hypothesis` object to match the distribution you want to test for. - -**Example: Changing from `Normal` to `Weibull`** -```json - "hypothesis": "normal" -to - "hypothesis": "weibull" -``` - -#### 2. Choose the Criteria to Compare - -In all three files, update the `criteria` list to include the tests you want to evaluate. - -**Example: Comparing `Liliefos` and `Chi-Squared`** -```json - "criteria": [ - { - "criterion_code": "LILLIE", - "parameters": [] - }, - { - "criterion_code": "CHI2", - "parameters": [] - } - ], -``` -#### 3. Define the Alternative Hypothesis - -In `2_evaluate_power.json`, modify the `alternatives` array. This is the specific deviation you want your tests to be able to detect. - -**Example: Checking if tests for `Weibull` can detect an `Exponential` distribution** -```json -"alternatives": [ - { - "generator_name": "EXPONENTIALGENERATOR", - "parameters": [ - 0.5, - ] - } - ] -``` -#### 4. Adjust Experiment Parameters - -You can also change `sample_sizes`, `monte_carlo_count`, and `significance_levels` to fit the scope of your research. Just ensure the `sample_sizes` and `significance_levels` are consistent between the `critical_value` and `power` experiments. - -By following this structured, three-step approach, you can systematically evaluate and select the best statistical test for any given problem. - ---- - -## How to Run This Example Workflow - -The `pysatl-experiment` command-line tool is designed to look for experiment configurations in a dedicated `.experiment` directory at the root of the project. - -Therefore, to run these examples, you must first copy the JSON template files into that location. - -**1. Copy the configuration files:** - -Firstly you need create files -```bash -poerty run experiment create <1_calculate_critical_values> -``` - -**2. Run the experiments in sequence:** - -Once the files are in the `.experiment` directory, you can execute the workflow steps in order. Make sure you are in the project's root directory. -### First, run the calibration step -``` -poetry run experiment build-and-run 1_calculate_critical_values -``` -### Second, run the power evaluation -``` -poetry run experiment build-and-run 2_evaluate_power -``` -### Finally, run the performance analysis -``` -poetry run experiment build-and-run 3_measure_time_complexity -``` From 2e95c113e839a049c838b03d0fd4ffca11c9a9ff Mon Sep 17 00:00:00 2001 From: faux66 Date: Sat, 8 Nov 2025 14:35:11 +0300 Subject: [PATCH 17/17] fix: delete duplicate file --- experiment_example/README.md | 136 ----------------------------------- 1 file changed, 136 deletions(-) delete mode 100644 experiment_example/README.md diff --git a/experiment_example/README.md b/experiment_example/README.md deleted file mode 100644 index 0e37a5b..0000000 --- a/experiment_example/README.md +++ /dev/null @@ -1,136 +0,0 @@ -# Quick-Start Template: A 3-Step Experimental Workflow - -This directory provides a set of template configuration files for the `pysatl-experiment` framework. It is designed to serve as a starting point for conducting a robust, three-step comparison of statistical goodness-of-fit tests. - -The goal of this workflow is to help you make a data-driven decision about which statistical test is best suited for your specific hypothesis and potential alternatives. - -## The 3-Step Workflow - -This template follows a complete research cycle. Each step answers a different question, and they are designed to be run in sequence. - ---- - -### Step 1: Calibration -File: `1_calculate_critical_values.json` - -**The Question:** What are the correct decision thresholds for my chosen tests? - -**The Purpose:** Before you can use any statistical test, you must establish its baseline critical values. These values depend on your null hypothesis (the distribution you are testing for), the sample sizes, and the desired significance levels (alpha). This step calibrates your "measurement tools." - -**The Command:** -```bash -poetry run experiment build-and-run 1_calculate_critical_values -``` ---- -### Step 2: Evaluation -File: `2_evaluate_power.json` - -**The Question:** How effective are these tests at detecting the specific deviations I care about? - -**The Purpose:** This is the core scientific evaluation. You measure the **statistical power** of each test against one or more alternative hypotheses. A test with high power is very good at correctly rejecting the null hypothesis when it is indeed false. This step tells you which test is most effective for your specific problem. - -*This experiment requires the critical values generated in Step 1.* - -**The Command:** -```bash -poetry run experiment build-and-run 2_evaluate_power -``` - ---- - -### Step 3: Performance Analysis -File: `3_measure_time_complexity.json` - -**The Question:** What is the computational cost of using each test? - -**The Purpose:** This is the practical, engineering evaluation. If two tests show similar power, the faster one may be preferable, especially in data-intensive applications. This experiment measures the execution time of each test, helping you understand the trade-offs between effectiveness and performance. - -**The Command:** -```bash -poetry run experiment build-and-run 3_measure_time_complexity -``` - ---- - -## How to Adapt This Template for Your Own Research - -To use these files for your own experiment, copy this directory and modify the JSON configurations. The key is to ensure your parameters are consistent across the files. -#### 1. Define Your Null Hypothesis - -In all three files (`1_...`, `2_...`, `3_...`), change the `hypothesis` object to match the distribution you want to test for. - -**Example: Changing from `Normal` to `Weibull`** -```json - "hypothesis": "normal" -to - "hypothesis": "weibull" -``` - -#### 2. Choose the Criteria to Compare - -In all three files, update the `criteria` list to include the tests you want to evaluate. - -**Example: Comparing `Liliefos` and `Chi-Squared`** -```json - "criteria": [ - { - "criterion_code": "LILLIE", - "parameters": [] - }, - { - "criterion_code": "CHI2", - "parameters": [] - } - ], -``` -#### 3. Define the Alternative Hypothesis - -In `2_evaluate_power.json`, modify the `alternatives` array. This is the specific deviation you want your tests to be able to detect. - -**Example: Checking if tests for `Weibull` can detect an `Exponential` distribution** -```json -"alternatives": [ - { - "generator_name": "EXPONENTIALGENERATOR", - "parameters": [ - 0.5, - ] - } - ] -``` -#### 4. Adjust Experiment Parameters - -You can also change `sample_sizes`, `monte_carlo_count`, and `significance_levels` to fit the scope of your research. Just ensure the `sample_sizes` and `significance_levels` are consistent between the `critical_value` and `power` experiments. - -By following this structured, three-step approach, you can systematically evaluate and select the best statistical test for any given problem. - ---- - -## How to Run This Example Workflow - -The `pysatl-experiment` command-line tool is designed to look for experiment configurations in a dedicated `.experiment` directory at the root of the project. - -Therefore, to run these examples, you must first copy the JSON template files into that location. - -**1. Copy the configuration files:** - -Firstly you need create files -```bash -poerty run experiment create <1_calculate_critical_values> -``` - -**2. Run the experiments in sequence:** - -Once the files are in the `.experiment` directory, you can execute the workflow steps in order. Make sure you are in the project's root directory. -### First, run the calibration step -``` -poetry run experiment build-and-run 1_calculate_critical_values -``` -### Second, run the power evaluation -``` -poetry run experiment build-and-run 2_evaluate_power -``` -### Finally, run the performance analysis -``` -poetry run experiment build-and-run 3_measure_time_complexity -```