Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 8 additions & 14 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,21 @@ jobs:
python-version: [ "3.11", "3.12", "3.13" ]

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install poetry
run: pipx install poetry
- name: Install Poetry
uses: snok/install-poetry@v1

- name: Install dependencies
run: poetry install --with dev

- name: Ruff
run: poetry run ruff check
- name: Run Pre-commit hooks
run: poetry run pre-commit run --all-files

- name: Install stubs
run: poetry run pip install types-PyYAML types-tqdm

- name: Mypy
run: poetry run mypy

- name: Pytest
run: poetry run python -m pytest tests
- name: Run tests
run: poetry run python -m pytest tests
33 changes: 33 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: check-merge-conflict
- id: check-ast

- repo: local
hooks:
- id: ruff-check
name: ruff check
entry: poetry run ruff check --fix --exit-non-zero-on-fix
language: system
types: [python]
files: ^(mpest/|experimental_env/|tests/).*

- id: ruff-format
name: ruff format
entry: poetry run ruff format
language: system
types: [python]
files: ^(mpest/|experimental_env/|tests/).*

- id: mypy
name: mypy check
entry: poetry run mypy
language: system
types: [python]
pass_filenames: false
33 changes: 25 additions & 8 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,27 @@ git checkout -b <type>/<what-this-branch-solves>



### 3. Make and Commit Changes
### 3. Set Up Your Development Environment

To start working on the code, you need to install the project dependencies and set up the pre-commit hooks. These hooks automatically check your code for quality and style before each commit.

1. **Install dependencies:**

Follow steps in [README.md](README.md)

2. **Install pre-commit hooks (Mandatory):**

```bash
pre-commit install
```

This command sets up the hooks in your local Git repository. **This is a required step for all contributors.**

Now your environment is ready. The hooks will run automatically every time you run `git commit`.



### 4. Make and Commit Changes

Work on the code in your new branch. When you're ready to save your changes, create a commit. We use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) to standardize commit messages.

Expand All @@ -48,7 +68,7 @@ Use the following types:
- `struct`: for changes related to the project structure (NOT CODE), for example, changing folder locations.
- `ci`: for various CI/CD tasks.
- `docs`: for changes in documentation.
- `chore`: for other changes that do not affect the code or tests (e.g., updating .gitignore, README.md).
- `chore`: for other changes that do not affect the code or tests (e.g., updating `.gitignore`, `README.md`).



Expand All @@ -64,7 +84,7 @@ Try to divide commits into atomic and independent parts. That is, do not add unr



### 4. Push Changes to Your Fork
### 5. Push Changes to Your Fork

After you have made one or more commits, push your branch to your remote fork on GitHub:

Expand All @@ -74,13 +94,13 @@ git push



### 5. Create a Pull Request (PR)
### 6. Create a Pull Request (PR)

Once your branch with the changes is in your fork, you can create a Pull Request to propose your changes to the main repository.

1. Go to your fork's page on GitHub (https://github.com/YOUR-USERNAME/pysatl-mpest).
2. You will see a notification prompting you to create a Pull Request for your recently pushed branch. Click the **"Compare & pull request"** button.
3. Ensure the base repository is PySATL/pysatl-mpest with the main branch, and the head repository is your fork and your working branch.
3. Ensure the base repository is `PySATL/pysatl-mpest` with the main branch, and the head repository is your fork and your working branch.
4. Give your Pull Request a meaningful title (following the [Conventional Commits](https://www.google.com/url?sa=E&q=https%3A%2F%2Fwww.conventionalcommits.org%2F) standard) and add a detailed description of the changes you've made.

#### Rules for Your PR to be Merged
Expand All @@ -98,6 +118,3 @@ For your Pull Request to be merged, it must meet the following requirements conf
Each pull request must be reviewed by one of the maintainers:

* Danil Totmyanin ([iraedeus](https://github.com/iraedeus))



12 changes: 6 additions & 6 deletions docs/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@

## 1.2. Цели документации

Документ предназначен для описания текущего состояния проекта `pysatl-mpest`.
Документ предназначен для описания текущего состояния проекта `pysatl-mpest`.

Целевой аудиторией являются разработчики, которые будут принимать участие в разработке/расширении библиотеки. По большей части данная документация предназначается для тех, кто будет разбираться со структурой проекта на *Летней школе*.

Expand Down Expand Up @@ -139,7 +139,7 @@ $$

#### Смеси распределений

Работа со смесями распределений идет через класс `MixtureDistribution`, который инициализируется с помощью списка объектов `Distribution`. Конкретные реализации распределений наследуются от `AModel`, после чего оборачиваются в класс `Distribution`.
Работа со смесями распределений идет через класс `MixtureDistribution`, который инициализируется с помощью списка объектов `Distribution`. Конкретные реализации распределений наследуются от `AModel`, после чего оборачиваются в класс `Distribution`.

Некоторые реализации EM используют оптимизацию, при которой параметры могут выйти из области определения. Таким образом необходимо нормализовать параметры для того, чтобы они были определены на всем $\mathbb{R}$. Методы объектов `AModel` использует внутренние (internal) параметры, тогда как `Distribution` использует внешние (external) параметры, которые являются общепринятыми.

Expand All @@ -160,7 +160,7 @@ $$
- `Python`: Как основной язык.
- `scipy`: На эту библиотеку делегировано сэмплирование, а так же написаны адаптеры к их оптимизаторам.
- `numpy`: Для векторизации.
- `matplotlib + seaborn`: Для визуализации данных (В основном используется в экспериментальном окружении).
- `matplotlib + seaborn`: Для визуализации данных (В основном используется в экспериментальном окружении).



Expand Down Expand Up @@ -238,7 +238,7 @@ $$
- `LikelihoodMStep` (для MLE-EM): пересчитывает параметры моделей, максимизируя взвешенную логарифмическую функцию правдоподобия. Может использовать `AOptimizer` или `AOptimizerJacobian` для численной оптимизации.
- `LMomentsMStep` (для ELM): пересчитывает параметры моделей на основе вычисленных L-моментов для каждого компонента смеси.



## 3.4. Вспомогательные

Expand Down Expand Up @@ -352,7 +352,7 @@ $$

3. **M-шаг:** вызывается `method.m_step.step(e_result)`:

Реализуется M-шаг алгоритма, возвращая результирующую смесь.
Реализуется M-шаг алгоритма, возвращая результирующую смесь.

4. **Обновление состояния смеси:**

Expand Down Expand Up @@ -434,7 +434,7 @@ sequenceDiagram

### Ядро (Mpest core)

1. Класс `Distribution` хоть и является оберткой для `AModel`, но не реализует всех его методов (например `lpdf`). Таким образом, для вызова нереализованных методов необходимо вызывать `model`, что плохо.
1. Класс `Distribution` хоть и является оберткой для `AModel`, но не реализует всех его методов (например `lpdf`). Таким образом, для вызова нереализованных методов необходимо вызывать `model`, что плохо.

2. Для некоторых алгоритмов (не для всех) необходимо преобразовывать параметры так, чтобы они были на всем $\mathbb{R}$. Из-за этого появляется разделение на внутренние (*internal_params*) и внешние (*external_params*) параметры. Сейчас в коде, преобразование во внутренние параметры происходит перед началом алгоритма (для всех алгосов, даже для тех, для которых это не является необходимым), а в конце происходит переход к внешним параметрам (общепринятым).

Expand Down
2 changes: 1 addition & 1 deletion docs/source/_static/EM algo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,3 @@ documentation for details.
:caption: API:

api/modules

2 changes: 1 addition & 1 deletion docs/source/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
:caption: Introduction:

.. include:: ../../README.md
:parser: myst_parser.sphinx_
:parser: myst_parser.sphinx_
3 changes: 1 addition & 2 deletions experimental_env/analysis/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
from itertools import permutations

import numpy as np
from scipy.integrate import quad

from mpest import MixtureDistribution
from mpest.utils import ANamed
from scipy.integrate import quad


class AMetric(ANamed, ABC):
Expand Down
6 changes: 3 additions & 3 deletions experimental_env/experiment/estimators.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
from concurrent.futures import as_completed
from concurrent.futures.process import ProcessPoolExecutor

from tqdm import tqdm

from experimental_env.utils import OrderedProblem, choose_best_mle
from mpest import Problem
from mpest.em import EM
from mpest.em.methods.l_moments_method import LMomentsMStep
from mpest.em.methods.likelihood_method import BayesEStep, LikelihoodMStep
from mpest.em.methods.method import Method
from mpest.optimizers import ALL_OPTIMIZERS
from mpest.utils import ANamed, Factory, ResultWithLog
from tqdm import tqdm

from experimental_env.utils import OrderedProblem, choose_best_mle

METHODS: dict = {
"Likelihood": [[Factory(BayesEStep), Factory(LikelihoodMStep, optimizer)] for optimizer in ALL_OPTIMIZERS],
Expand Down
4 changes: 2 additions & 2 deletions experimental_env/experiment/experiment_description.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
from collections.abc import Iterable, Iterator

import numpy as np

from experimental_env.preparation.dataset_description import DatasetDescrciption
from mpest import MixtureDistribution
from mpest.utils import ResultWithLog

from experimental_env.preparation.dataset_description import DatasetDescrciption


class StepDescription:
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
from pathlib import Path

import numpy as np
from mpest import Problem
from mpest.models import ALL_MODELS, AModel

from experimental_env.experiment.estimators import AEstimator
from experimental_env.experiment.experiment_description import ExperimentDescription
from experimental_env.experiment.experiment_saver import ExperimentSaver
from experimental_env.preparation.dataset_description import DatasetDescrciption
from mpest import Problem
from mpest.models import ALL_MODELS, AModel


class AExecutor(ABC):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"""A module that provides a class for generating initial mixtures with uniform distribution."""

from mpest import Problem

from experimental_env.experiment.experiment_executors.abstract_executor import AExecutor
from experimental_env.mixture_generators.random_mixture_generator import (
RandomMixtureGenerator,
)
from mpest import Problem


class RandomExperimentExecutor(AExecutor):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"""A module that provides a class for generating initial mixtures with standart parameters"""

from mpest import Problem

from experimental_env.experiment.experiment_executors.abstract_executor import AExecutor
from experimental_env.mixture_generators.standart_mixture_generator import (
StandartMixtureGenerator,
)
from mpest import Problem


class StandartExperimentExecutor(AExecutor):
Expand Down
6 changes: 3 additions & 3 deletions experimental_env/preparation/dataset_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
from pathlib import Path

import numpy as np
from mpest.core.distribution import Distribution
from mpest.core.mixture_distribution import MixtureDistribution
from mpest.models.abstract_model import AModel
from tqdm import tqdm

from experimental_env.mixture_generators.dataset_mixture_generator import (
DatasetMixtureGenerator,
)
from experimental_env.preparation.dataset_saver import DatasetDescrciption, DatasetSaver
from mpest.core.distribution import Distribution
from mpest.core.mixture_distribution import MixtureDistribution
from mpest.models.abstract_model import AModel


class RandomDatasetGenerator:
Expand Down
3 changes: 2 additions & 1 deletion experimental_env/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
import math
import re

from experimental_env.analysis.metrics import Parametric
from mpest import Distribution, MixtureDistribution, Problem
from mpest.models import ALL_MODELS
from mpest.utils import ResultWithLog

from experimental_env.analysis.metrics import Parametric


def create_mixture_by_key(config: dict, key: str) -> MixtureDistribution:
"""
Expand Down
2 changes: 1 addition & 1 deletion mpest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""

from mpest import em, models, optimizers, utils
from mpest.annotations import Params, Samples
from mpest.core.distribution import Distribution
from mpest.core.mixture_distribution import DistributionInMixture, MixtureDistribution
from mpest.core.problem import Problem, Result
from mpest.annotations import Params, Samples
6 changes: 3 additions & 3 deletions mpest/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
AModelDifferentiable,
AModelWithGenerator,
)
from mpest.models.beta import Beta
from mpest.models.cauchy import Cauchy
from mpest.models.exponential import ExponentialModel
from mpest.models.gaussian import GaussianModel
from mpest.models.pareto import Pareto
from mpest.models.uniform import Uniform
from mpest.models.weibull import WeibullModelExp
from mpest.models.cauchy import Cauchy
from mpest.models.pareto import Pareto
from mpest.models.beta import Beta

ALL_MODELS: dict[str, type[AModel]] = {
GaussianModel().name: GaussianModel,
Expand Down
7 changes: 6 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ sphinx = "^8.2.0"
hypothesis = "^6.131.7"
myst-parser = "^4.0.1"
furo = "^2024.8.6"
types-pyyaml = "^6.0.12.20250516"
types-tqdm = "^4.67.0.20250516"

[tool.poetry.group.experiments.dependencies]
tqdm = "^4.67.1"
Expand All @@ -42,7 +44,8 @@ ruamel-yaml = "^0.18.10"
[tool.ruff]
line-length = 120
output-format = "grouped"
exclude = ["*.ipynb", "__init__.py", "docs"]
src = ["mpest", "experimental_env", "tests"]
exclude = ["*.ipynb"]

[tool.ruff.format]
quote-style = "double"
Expand All @@ -53,6 +56,8 @@ docstring-code-format = true
select = ["A", "E", "F", "I", "PL", "RUF", "SIM", "UP", "W"]
ignore = ["PLR0913"]

[tool.ruff.lint.per-file-ignores]
"**/__init__.py" = ["F401"]

[tool.mypy]
files = ["mpest", "experimental_env"]
Expand Down
1 change: 0 additions & 1 deletion tests/core/test_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import pytest
from hypothesis import given
from hypothesis import strategies as st

from mpest.core.distribution import Distribution
from mpest.models import AModel, AModelWithGenerator

Expand Down
1 change: 0 additions & 1 deletion tests/core/test_mixture_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import pytest
from hypothesis import given
from hypothesis import strategies as st

from mpest import Distribution
from mpest.core.mixture_distribution import DistributionInMixture, MixtureDistribution
from mpest.models import AModel, AModelWithGenerator
Expand Down
Loading