diff --git a/.gitignore b/.gitignore index 1753c21..c6dc6af 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ __pycache__/ *.py[cod] *$py.class +htmls/*.ipynb + # C extensions *.so diff --git a/CHANGELOG.md b/CHANGELOG.md index 30352e0..9a26ab1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Released] +## [1.5.0] - 2025-11-21 + +### Added +- **Reproducibility support**: Added `seed` parameter to Bayesian statistical tests (`bayesian_sign_test`, `bayesian_signed_rank_test`) for deterministic results +- **Reproducibility support**: Added `seed` parameter to `HistoPlot` class for consistent jitter in histogram generation +- **Multi-platform CI**: Comprehensive GitHub Actions workflow testing on Windows, Linux (Ubuntu), and macOS +- **Smoke tests**: Added automated smoke tests for CLI and API functionality across all platforms +- **Environment files**: Added `requirements.txt`, `requirements-dev.txt`, and `environment.yml` for broader compatibility +- **Headless mode documentation**: Complete documentation and examples for running SAES without display (CI/CD, servers) +- **Headless mode examples**: Python and shell script examples for automated workflows (`examples/headless_mode_example.py`, `examples/headless_cli_example.sh`, `examples/headless_cli_example.bat`) +- **New test suite**: Added `test_bayesian_seed.py` specifically for verifying seed reproducibility +- **Documentation**: New reproducibility documentation page (`docs/usage/reproducibility.rst`) with best practices + +### Changed +- Updated `test_bayesian.py` to demonstrate both seed parameter usage and backward compatibility +- Enhanced README with sections on reproducibility and headless mode +- Improved documentation structure to include reproducibility guidance + +### Fixed +- Ensured all random operations can be made deterministic for reproducible research + ## [1.4.0] - 2025-11-15 ### Added diff --git a/README.md b/README.md index 0f04417..49cd6fa 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,51 @@ source venv/bin/activate # On Windows: venv\Scripts\activate pip install -e ".[dev]" ``` +### Using Environment Files + +For broader compatibility, environment files are provided: + +```sh +# Using pip with requirements.txt +pip install -r requirements.txt + +# Using conda with environment.yml +conda env create -f environment.yml +conda activate saes +``` + +## 🔄 Reproducibility + +SAES supports **deterministic seeds** for reproducible research: + +```python +from SAES.statistical_tests.bayesian import bayesian_sign_test +from SAES.plots.histoplot import HistoPlot + +# Bayesian tests with seed for reproducibility +result, _ = bayesian_sign_test(data, sample_size=5000, seed=42) + +# Histogram plots with consistent jitter +histoplot = HistoPlot(data, metrics, "Accuracy", seed=42) +``` + +See the [reproducibility documentation](https://jMetal.github.io/SAES/usage/reproducibility.html) for details. + +## 💻 Headless Mode + +SAES can run in headless mode (without display) for automated workflows, CI/CD pipelines, and server environments: + +```bash +# Set matplotlib backend +export MPLBACKEND=Agg + +# Run SAES commands +python -m SAES -ls -ds data.csv -ms metrics.csv -m HV -s friedman -op results.tex +python -m SAES -bp -ds data.csv -ms metrics.csv -m HV -i Problem1 -op boxplot.png +``` + +See `examples/headless_mode_example.py` for a complete Python example or `examples/headless_cli_example.sh` for CLI usage. + ## 🤝 Contributors - [![GitHub](https://img.shields.io/badge/GitHub-100000?style=flat&logo=github&logoColor=white)](https://github.com/rorro6787) **Emilio Rodrigo Carreira Villalta** diff --git a/SAES/statistical_tests/bayesian.py b/SAES/statistical_tests/bayesian.py index d13df96..0933b61 100644 --- a/SAES/statistical_tests/bayesian.py +++ b/SAES/statistical_tests/bayesian.py @@ -7,7 +7,8 @@ def bayesian_sign_test(data: pd.DataFrame, rope_limits=[-0.01, 0.01], prior_strength=0.5, prior_place="rope", - sample_size=5000) -> tuple: + sample_size=5000, + seed=None) -> tuple: """ Performs the Bayesian sign test to compare the performance of two algorithms across multiple instances. The Bayesian sign test is a non-parametric statistical test used to compare the performance of two algorithms on multiple instances. The null hypothesis is that the algorithms perform equivalently, which implies their average ranks are equal. @@ -40,6 +41,9 @@ def bayesian_sign_test(data: pd.DataFrame, sample_size (int): Total number of random_search samples generated. Default is 5000. + seed (int, optional): + Random seed for reproducibility. Default is None (non-deterministic). + Returns: tuple: A tuple containing the posterior probabilities and the samples drawn from the Dirichlet process. List of posterior probabilities: - Pr(algorith_1 < algorithm_2) @@ -62,6 +66,10 @@ def bayesian_sign_test(data: pd.DataFrame, else: raise ValueError("Initialization ERROR. Incorrect number of dimensions for axis 1") + # Set random seed for reproducibility + if seed is not None: + np.random.seed(seed) + # Compute the differences Z = sample1 - sample2 @@ -93,7 +101,8 @@ def bayesian_signed_rank_test(data, rope_limits=[-0.01, 0.01], prior_strength=1.0, prior_place="rope", - sample_size=1000) -> tuple: + sample_size=1000, + seed=None) -> tuple: """ Performs the Bayesian version of the signed rank test to compare the performance of two algorithms across multiple instances. The Bayesian sign test is a non-parametric statistical test used to compare the performance of two algorithms on multiple instances. The null hypothesis is that the algorithms perform equivalently, which implies their average ranks are equal. @@ -126,6 +135,9 @@ def bayesian_signed_rank_test(data, sample_size (int): Total number of random_search samples generated. Default is 5000. + seed (int, optional): + Random seed for reproducibility. Default is None (non-deterministic). + Returns: tuple: A tuple containing the posterior probabilities and the samples drawn from the Dirichlet process. List of posterior probabilities: - Pr(algorith_1 < algorithm_2) @@ -153,6 +165,10 @@ def weights(n, s): else: raise ValueError("Initialization ERROR. Incorrect number of dimensions for axis 1") + # Set random seed for reproducibility + if seed is not None: + np.random.seed(seed) + # Compute the differences Z = sample1 - sample2 Z0 = [-float("Inf"), 0.0, float("Inf")][["left", "rope", "right"].index(prior_place)] diff --git a/SOFTWARE_X_COMPLIANCE.md b/SOFTWARE_X_COMPLIANCE.md new file mode 100644 index 0000000..3871b19 --- /dev/null +++ b/SOFTWARE_X_COMPLIANCE.md @@ -0,0 +1,94 @@ +# Software X Compliance + +SAES meets all Software X publication requirements. + +## 1. Deterministic Seeds ✅ + +Bayesian tests support `seed` parameter for reproducibility: + +```python +from SAES.statistical_tests.bayesian import bayesian_sign_test +result, _ = bayesian_sign_test(data, sample_size=1000, seed=42) +``` + +## 2. Multi-Platform CI ✅ + +`.github/workflows/multi-platform-test.yml` tests on: +- Ubuntu, Windows, macOS +- Python 3.10, 3.11, 3.12 + +## 3. Smoke Tests ✅ + +Run comprehensive smoke tests (10 tests) - fully automated: + +```bash +chmod +x examples/smoke_test.sh +./examples/smoke_test.sh +``` + +The script automatically: +- Creates virtual environment if needed +- Installs dependencies +- Runs all tests in headless mode + +**Tests cover:** +- **LaTeX tables** (4): Mean/Median, Friedman, Wilcoxon pivot, Wilcoxon pairwise +- **Plots** (3): Boxplot single, Boxplot grid, Critical distance +- **Statistical APIs** (3): Bayesian tests with seeds, Plot classes + +## 4. Environment Files ✅ + +Multiple installation options: + +```bash +# Option 1: Requirements file +pip install -r requirements.txt + +# Option 2: Conda +conda env create -f environment.yml +conda activate saes + +# Option 3: Auto-install (smoke test does this) +./examples/smoke_test.sh +``` + +Files provided: +- `requirements.txt` - Core dependencies +- `requirements-dev.txt` - Development dependencies +- `environment.yml` - Conda environment + +## 5. Headless Mode ✅ + +For CI/CD and server environments: + +```bash +export MPLBACKEND=Agg +python -m SAES -ls -ds data.csv -ms metrics.csv -m HV -s friedman -op output.tex +``` + +The smoke test script runs in headless mode by default. + +## Quick Start + +```bash +# Clone and test +git clone https://github.com/jMetal/SAES.git +cd SAES +chmod +x examples/smoke_test.sh +./examples/smoke_test.sh +``` + +## Verification + +```bash +# Smoke tests (automated setup) +./examples/smoke_test.sh + +# Unit tests +python -m unittest discover tests +``` + +## Branch + +Feature branch: `feature/software-x-requirements` +Ready for merge (not merged yet, as requested) diff --git a/docs/usage/reproducibility.rst b/docs/usage/reproducibility.rst new file mode 100644 index 0000000..e14220f --- /dev/null +++ b/docs/usage/reproducibility.rst @@ -0,0 +1,138 @@ +Reproducibility and Seeds +========================= + +SAES supports deterministic behavior for reproducible research through random seed control. + +Why Reproducibility Matters +--------------------------- + +When analyzing stochastic algorithms, reproducibility is crucial for: + +- **Research validation**: Others can verify your results +- **Debugging**: Consistent results make it easier to identify issues +- **Comparisons**: Fair comparison requires consistent conditions +- **Publication**: Many journals and conferences require reproducible results + +Functions with Random Seeds +--------------------------- + +The following SAES functions support deterministic execution via the ``seed`` parameter: + +Bayesian Statistical Tests +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Both Bayesian tests support the ``seed`` parameter for reproducibility: + +.. code-block:: python + + from SAES.statistical_tests.bayesian import bayesian_sign_test, bayesian_signed_rank_test + import pandas as pd + + data = pd.DataFrame({ + 'Algorithm_A': [0.9, 0.85, 0.95, 0.9, 0.92], + 'Algorithm_B': [0.5, 0.6, 0.55, 0.58, 0.52] + }) + + # Deterministic results with seed + result1, _ = bayesian_sign_test(data, sample_size=5000, seed=42) + result2, _ = bayesian_sign_test(data, sample_size=5000, seed=42) + # result1 and result2 will be identical + + # Same for signed rank test + result3, _ = bayesian_signed_rank_test(data, sample_size=1000, seed=123) + +Histogram Plots +~~~~~~~~~~~~~~ + +The HistoPlot class supports seeding for consistent jitter when handling identical values: + +.. code-block:: python + + from SAES.plots.histoplot import HistoPlot + import pandas as pd + + data = pd.read_csv("results.csv") + metrics = pd.read_csv("metrics.csv") + + # Create histoplot with reproducible jitter + histoplot = HistoPlot(data, metrics, "Accuracy", seed=42) + histoplot.save_instance("Problem1", "output.png") + +Best Practices +------------- + +1. **Always use seeds for published research**: Set explicit seeds for all random operations +2. **Document your seeds**: Include seed values in your research papers and code +3. **Use different seeds for different experiments**: Avoid accidentally reusing the same random sequence +4. **Version control**: Include seed values in your version-controlled analysis scripts + +Example: Complete Reproducible Workflow +--------------------------------------- + +.. code-block:: python + + from SAES.statistical_tests.bayesian import bayesian_sign_test, bayesian_signed_rank_test + from SAES.plots.histoplot import HistoPlot + import pandas as pd + + # Load data + data = pd.read_csv("algorithm_results.csv") + metrics = pd.read_csv("metrics.csv") + + # Reproducible Bayesian analysis + SEED = 42 + algorithm_a = data[data['Algorithm'] == 'A']['MetricValue'] + algorithm_b = data[data['Algorithm'] == 'B']['MetricValue'] + + comparison_data = pd.DataFrame({ + 'Algorithm_A': algorithm_a.values, + 'Algorithm_B': algorithm_b.values + }) + + # Run Bayesian test with seed + result, samples = bayesian_sign_test( + comparison_data, + sample_size=5000, + seed=SEED + ) + + print(f"P(A < B): {result[0]:.4f}") + print(f"P(A ≈ B): {result[1]:.4f}") + print(f"P(A > B): {result[2]:.4f}") + + # Create reproducible visualization + histoplot = HistoPlot(data, metrics, "Accuracy", seed=SEED) + histoplot.save_all_instances("comparison.png") + +Headless Mode for Automated Workflows +------------------------------------- + +SAES can be run in headless mode (without display) for automated pipelines and CI/CD: + +.. code-block:: bash + + # Set matplotlib to use non-interactive backend + export MPLBACKEND=Agg + + # Run SAES commands + python -m SAES -ls -ds data.csv -ms metrics.csv -m HV -s friedman -op results.tex + python -m SAES -bp -ds data.csv -ms metrics.csv -m HV -i Problem1 -op boxplot.png + python -m SAES -cdp -ds data.csv -ms metrics.csv -m HV -op cdplot.png + +For Python scripts in headless environments: + +.. code-block:: python + + import matplotlib + matplotlib.use('Agg') # Must be called before importing pyplot + + from SAES.plots.boxplot import Boxplot + import pandas as pd + + # Your analysis code here + data = pd.read_csv("results.csv") + metrics = pd.read_csv("metrics.csv") + + boxplot = Boxplot(data, metrics, "Accuracy") + boxplot.save_instance("Problem1", "output.png") + diff --git a/docs/usage/usage.rst b/docs/usage/usage.rst index b3f5f40..eec7b98 100644 --- a/docs/usage/usage.rst +++ b/docs/usage/usage.rst @@ -14,3 +14,4 @@ This section provides a brief overview of the three different features that this html bayesian violin + reproducibility diff --git a/environment.yml b/environment.yml new file mode 100644 index 0000000..6e40a18 --- /dev/null +++ b/environment.yml @@ -0,0 +1,18 @@ +name: saes +channels: + - conda-forge + - defaults +dependencies: + - python>=3.10 + - pip + - pip: + - python-dotenv==1.0.1 + - numpy<2 + - matplotlib==3.9.2 + - Jinja2==3.1.6 + - scikit-posthocs==0.10.0 + - scipy>=1.7.0 + - pandas>=1.3.0 + - seaborn>=0.11.0 + - papermill==2.6.0 + diff --git a/examples/smoke_test.sh b/examples/smoke_test.sh new file mode 100755 index 0000000..457828c --- /dev/null +++ b/examples/smoke_test.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# SAES Comprehensive Smoke Tests +# Self-contained: Sets up environment and runs all tests + +set -e + +echo "=== SAES Smoke Tests ===" +echo "" + +# Setup virtual environment if needed +if [ ! -d ".venv" ]; then + echo "Creating virtual environment..." + python3 -m venv .venv + echo "✓ Virtual environment created" +fi + +# Activate virtual environment +echo "Activating virtual environment..." +source .venv/bin/activate + +# Install dependencies if needed +if ! python -c "import SAES" 2>/dev/null; then + echo "Installing SAES..." + pip install -q -e ".[test]" + echo "✓ SAES installed" +else + echo "✓ SAES already installed" +fi + +# Set headless mode +export MPLBACKEND=Agg +mkdir -p /tmp/saes_smoke_tests + +echo "" +echo "Running tests..." +echo "" + +DATA="tests/test_data/swarmIntelligence.csv" +METRICS="tests/test_data/multiobjectiveMetrics.csv" + +# LaTeX Tables (4 types) +echo "[1/10] LaTeX: Mean/Median table" +python -m SAES -ls -ds $DATA -ms $METRICS -m HV -s mean_median -op /tmp/saes_smoke_tests/mean_median.tex + +echo "[2/10] LaTeX: Friedman test table" +python -m SAES -ls -ds $DATA -ms $METRICS -m HV -s friedman -op /tmp/saes_smoke_tests/friedman.tex + +echo "[3/10] LaTeX: Wilcoxon pivot table" +python -m SAES -ls -ds $DATA -ms $METRICS -m HV -s wilcoxon_pivot -op /tmp/saes_smoke_tests/wilcoxon_pivot.tex + +echo "[4/10] LaTeX: Wilcoxon pairwise table" +python -m SAES -ls -ds $DATA -ms $METRICS -m HV -s wilcoxon -op /tmp/saes_smoke_tests/wilcoxon.tex + +# Plots (3 types) +echo "[5/10] Plot: Boxplot (single instance)" +python -m SAES -bp -ds $DATA -ms $METRICS -m HV -i DTLZ1 -op /tmp/saes_smoke_tests/boxplot.png + +echo "[6/10] Plot: Boxplot (all instances grid)" +python -m SAES -bp -ds $DATA -ms $METRICS -m HV -g -op /tmp/saes_smoke_tests/boxplot_grid.png + +echo "[7/10] Plot: Critical distance plot" +python -m SAES -cdp -ds $DATA -ms $METRICS -m HV -op /tmp/saes_smoke_tests/cdplot.png + +# Statistical Tests API (3 tests) +echo "[8/10] API: Bayesian sign test (with seed)" +python -c " +from SAES.statistical_tests.bayesian import bayesian_sign_test +import pandas as pd, numpy as np +data = pd.DataFrame({'A': [0.9,0.85,0.95,0.9,0.92], 'B': [0.5,0.6,0.55,0.58,0.52]}) +r1, _ = bayesian_sign_test(data, sample_size=1000, seed=42) +r2, _ = bayesian_sign_test(data, sample_size=1000, seed=42) +np.testing.assert_array_almost_equal(r1, r2, decimal=10) +" + +echo "[9/10] API: Bayesian signed rank test (with seed)" +python -c " +from SAES.statistical_tests.bayesian import bayesian_signed_rank_test +import pandas as pd, numpy as np +data = pd.DataFrame({'A': [0.9,0.85,0.95,0.9,0.92], 'B': [0.5,0.6,0.55,0.58,0.52]}) +r1, _ = bayesian_signed_rank_test(data, sample_size=500, seed=123) +r2, _ = bayesian_signed_rank_test(data, sample_size=500, seed=123) +np.testing.assert_array_almost_equal(r1, r2, decimal=10) +" + +echo "[10/10] API: Plot classes initialization" +python -c " +from SAES.plots.histoplot import HistoPlot +from SAES.plots.violin import Violin +from SAES.plots.boxplot import Boxplot +from SAES.plots.cdplot import CDplot +import pandas as pd +data = pd.read_csv('$DATA') +metrics = pd.read_csv('$METRICS') +histoplot = HistoPlot(data, metrics, 'HV') +violin = Violin(data, metrics, 'HV') +boxplot = Boxplot(data, metrics, 'HV') +cdplot = CDplot(data, metrics, 'HV') +" + +echo "" +echo "✓ All 10 smoke tests passed!" +echo " Tests cover: LaTeX tables (4), Plots (3), Statistical APIs (3)" +echo " Output directory: /tmp/saes_smoke_tests/" +ls -lh /tmp/saes_smoke_tests/ 2>/dev/null | tail -n +2 | wc -l | xargs echo " Files created:" diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..a89544e --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,25 @@ +# Development dependencies for SAES +# Install with: pip install -r requirements.txt -r requirements-dev.txt + +# Testing +coverage==7.6.8 +pytest>=7.0.0 +pytest-cov>=3.0.0 +Pillow>=9.0.0 + +# Code quality +black>=22.0.0 +flake8>=4.0.0 +mypy>=0.950 +isort>=5.10.0 +pre-commit>=3.0.0 + +# Documentation +sphinx==8.1.3 +sphinx_rtd_theme==3.0.2 + +# HTML generation +ipython<=8.30.0 +nbconvert==7.16.6 +ipykernel<=6.29.5 + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..6960468 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,14 @@ +# Core dependencies for SAES +# Generated from pyproject.toml for broader compatibility + +# Core runtime dependencies +python-dotenv==1.0.1 +numpy<2 +matplotlib==3.9.2 +Jinja2==3.1.6 +scikit-posthocs==0.10.0 +scipy>=1.7.0 +pandas>=1.3.0 +seaborn>=0.11.0 +papermill==2.6.0 + diff --git a/tests/htmls/bayesian.ipynb b/tests/htmls/bayesian.ipynb index 3bef08a..b0c77d6 100644 --- a/tests/htmls/bayesian.ipynb +++ b/tests/htmls/bayesian.ipynb @@ -3,7 +3,7 @@ { "cell_type": "code", "execution_count": null, - "id": "ebd39d2e", + "id": "db9d11d7", "metadata": { "papermill": { "duration": null, @@ -28,7 +28,7 @@ { "cell_type": "code", "execution_count": null, - "id": "a37ca2f0", + "id": "7d460180", "metadata": { "papermill": { "duration": null, @@ -47,7 +47,7 @@ { "cell_type": "code", "execution_count": null, - "id": "1ca39f1b", + "id": "d8e756db", "metadata": { "papermill": { "duration": null, @@ -72,7 +72,7 @@ { "cell_type": "code", "execution_count": null, - "id": "aac610b3", + "id": "4af90d53", "metadata": { "papermill": { "duration": null, @@ -93,7 +93,7 @@ { "cell_type": "code", "execution_count": null, - "id": "e578e373", + "id": "b441bd14", "metadata": { "papermill": { "duration": null, @@ -111,7 +111,7 @@ }, { "cell_type": "markdown", - "id": "46d636d1", + "id": "87095eb4", "metadata": { "papermill": { "duration": null, @@ -129,7 +129,7 @@ { "cell_type": "code", "execution_count": null, - "id": "803f7afc", + "id": "380a838a", "metadata": { "papermill": { "duration": null, @@ -147,7 +147,7 @@ }, { "cell_type": "markdown", - "id": "ba6bfa6e", + "id": "b9edb5cb", "metadata": { "papermill": { "duration": null, @@ -165,7 +165,7 @@ { "cell_type": "code", "execution_count": null, - "id": "0d7c5f7b", + "id": "4fb9404f", "metadata": { "papermill": { "duration": null, @@ -202,8 +202,8 @@ }, "papermill": { "default_parameters": {}, - "duration": 0.022066, - "end_time": "2025-11-08T18:27:09.819556", + "duration": 0.026258, + "end_time": "2025-11-21T17:51:43.171606", "environment_variables": {}, "exception": null, "input_path": "/Users/rorro6787/Desktop/SAES/SAES/html/notebooks/bayesian_posterior.ipynb", @@ -214,7 +214,7 @@ "metrics": "tests/test_data/multiobjectiveMetrics.csv", "pivot": "NSGAII" }, - "start_time": "2025-11-08T18:27:09.797490", + "start_time": "2025-11-21T17:51:43.145348", "version": "2.6.0" } }, diff --git a/tests/htmls/fronts2D.ipynb b/tests/htmls/fronts2D.ipynb index bf6137f..165250e 100644 --- a/tests/htmls/fronts2D.ipynb +++ b/tests/htmls/fronts2D.ipynb @@ -3,7 +3,7 @@ { "cell_type": "code", "execution_count": null, - "id": "957c9e95", + "id": "882c6358", "metadata": { "papermill": { "duration": null, @@ -29,7 +29,7 @@ { "cell_type": "code", "execution_count": null, - "id": "538b4d35", + "id": "d06ff02b", "metadata": { "papermill": { "duration": null, @@ -54,7 +54,7 @@ { "cell_type": "code", "execution_count": null, - "id": "37038ffa", + "id": "205bb992", "metadata": { "papermill": { "duration": null, @@ -79,7 +79,7 @@ { "cell_type": "code", "execution_count": null, - "id": "2b2f6f96", + "id": "54645c2a", "metadata": { "papermill": { "duration": null, @@ -102,7 +102,7 @@ { "cell_type": "code", "execution_count": null, - "id": "95be5f23", + "id": "ef54fb58", "metadata": { "papermill": { "duration": null, @@ -121,7 +121,7 @@ { "cell_type": "code", "execution_count": null, - "id": "91c32437", + "id": "351d0784", "metadata": { "papermill": { "duration": null, @@ -140,7 +140,7 @@ }, { "cell_type": "markdown", - "id": "fa35b774", + "id": "5102d6e0", "metadata": { "papermill": { "duration": null, @@ -158,7 +158,7 @@ { "cell_type": "code", "execution_count": null, - "id": "8257d3d6", + "id": "8d73552f", "metadata": { "papermill": { "duration": null, @@ -177,7 +177,7 @@ }, { "cell_type": "markdown", - "id": "0701d3b2", + "id": "e62fcbb7", "metadata": { "papermill": { "duration": null, @@ -195,7 +195,7 @@ { "cell_type": "code", "execution_count": null, - "id": "a89b6b54", + "id": "473e50e8", "metadata": { "papermill": { "duration": null, @@ -214,7 +214,7 @@ }, { "cell_type": "markdown", - "id": "619672a8", + "id": "4fd63d1c", "metadata": { "papermill": { "duration": null, @@ -232,7 +232,7 @@ { "cell_type": "code", "execution_count": null, - "id": "4e9aaa58", + "id": "93f3ff41", "metadata": { "papermill": { "duration": null, @@ -279,8 +279,8 @@ }, "papermill": { "default_parameters": {}, - "duration": 0.002144, - "end_time": "2025-11-08T18:27:09.869755", + "duration": 0.008946, + "end_time": "2025-11-21T17:51:43.301909", "environment_variables": {}, "exception": null, "input_path": "/Users/rorro6787/Desktop/SAES/SAES/html/notebooks/multiobjective_fronts2D.ipynb", @@ -292,7 +292,7 @@ "metrics": "tests/test_data/multiobjectiveMetrics.csv", "references": "tests/test_data/references" }, - "start_time": "2025-11-08T18:27:09.867611", + "start_time": "2025-11-21T17:51:43.292963", "version": "2.6.0" } }, diff --git a/tests/htmls/fronts3D.ipynb b/tests/htmls/fronts3D.ipynb index ede6a3a..3801e52 100644 --- a/tests/htmls/fronts3D.ipynb +++ b/tests/htmls/fronts3D.ipynb @@ -3,7 +3,7 @@ { "cell_type": "code", "execution_count": null, - "id": "ad13ebbd", + "id": "87525f32", "metadata": { "papermill": { "duration": null, @@ -29,7 +29,7 @@ { "cell_type": "code", "execution_count": null, - "id": "e2bba7a2", + "id": "2361787d", "metadata": { "papermill": { "duration": null, @@ -54,7 +54,7 @@ { "cell_type": "code", "execution_count": null, - "id": "e343abd8", + "id": "ec784710", "metadata": { "papermill": { "duration": null, @@ -79,7 +79,7 @@ { "cell_type": "code", "execution_count": null, - "id": "03238fbb", + "id": "cda5891b", "metadata": { "papermill": { "duration": null, @@ -102,7 +102,7 @@ { "cell_type": "code", "execution_count": null, - "id": "1079af49", + "id": "def236ec", "metadata": { "papermill": { "duration": null, @@ -121,7 +121,7 @@ { "cell_type": "code", "execution_count": null, - "id": "1fa1a174", + "id": "42eac1f9", "metadata": { "papermill": { "duration": null, @@ -140,7 +140,7 @@ }, { "cell_type": "markdown", - "id": "cb2a4c75", + "id": "a1e1fbdd", "metadata": { "papermill": { "duration": null, @@ -158,7 +158,7 @@ { "cell_type": "code", "execution_count": null, - "id": "90bef33f", + "id": "ba212c32", "metadata": { "papermill": { "duration": null, @@ -177,7 +177,7 @@ }, { "cell_type": "markdown", - "id": "5f7845c3", + "id": "68637e6b", "metadata": { "papermill": { "duration": null, @@ -195,7 +195,7 @@ { "cell_type": "code", "execution_count": null, - "id": "ab349d32", + "id": "d993e125", "metadata": { "papermill": { "duration": null, @@ -214,7 +214,7 @@ }, { "cell_type": "markdown", - "id": "46e4fd9b", + "id": "f6d44926", "metadata": { "papermill": { "duration": null, @@ -232,7 +232,7 @@ { "cell_type": "code", "execution_count": null, - "id": "48b4c8f0", + "id": "71546899", "metadata": { "papermill": { "duration": null, @@ -279,8 +279,8 @@ }, "papermill": { "default_parameters": {}, - "duration": 0.003249, - "end_time": "2025-11-08T18:27:09.892689", + "duration": 0.007209, + "end_time": "2025-11-21T17:51:43.391032", "environment_variables": {}, "exception": null, "input_path": "/Users/rorro6787/Desktop/SAES/SAES/html/notebooks/multiobjective_fronts3D.ipynb", @@ -292,7 +292,7 @@ "metrics": "tests/test_data/multiobjectiveMetrics.csv", "references": "tests/test_data/references" }, - "start_time": "2025-11-08T18:27:09.889440", + "start_time": "2025-11-21T17:51:43.383823", "version": "2.6.0" } }, diff --git a/tests/htmls/frontsND.ipynb b/tests/htmls/frontsND.ipynb index 52ae382..f94702e 100644 --- a/tests/htmls/frontsND.ipynb +++ b/tests/htmls/frontsND.ipynb @@ -3,7 +3,7 @@ { "cell_type": "code", "execution_count": null, - "id": "0713ffd5", + "id": "fa39921a", "metadata": { "papermill": { "duration": null, @@ -30,7 +30,7 @@ { "cell_type": "code", "execution_count": null, - "id": "183e2e9e", + "id": "4ff05456", "metadata": { "papermill": { "duration": null, @@ -55,7 +55,7 @@ { "cell_type": "code", "execution_count": null, - "id": "bd72ca07", + "id": "9dcc2e24", "metadata": { "papermill": { "duration": null, @@ -80,7 +80,7 @@ { "cell_type": "code", "execution_count": null, - "id": "2a0af258", + "id": "b14030b3", "metadata": { "papermill": { "duration": null, @@ -103,7 +103,7 @@ { "cell_type": "code", "execution_count": null, - "id": "641a16d0", + "id": "e44b31e8", "metadata": { "papermill": { "duration": null, @@ -122,7 +122,7 @@ { "cell_type": "code", "execution_count": null, - "id": "cd593de9", + "id": "95f5a802", "metadata": { "papermill": { "duration": null, @@ -141,7 +141,7 @@ }, { "cell_type": "markdown", - "id": "a54f8785", + "id": "356ad35e", "metadata": { "papermill": { "duration": null, @@ -159,7 +159,7 @@ { "cell_type": "code", "execution_count": null, - "id": "13d894f3", + "id": "4ece2b81", "metadata": { "papermill": { "duration": null, @@ -178,7 +178,7 @@ }, { "cell_type": "markdown", - "id": "36c49b5f", + "id": "d4ea0fd1", "metadata": { "papermill": { "duration": null, @@ -196,7 +196,7 @@ { "cell_type": "code", "execution_count": null, - "id": "cd3a8ba9", + "id": "67be1138", "metadata": { "papermill": { "duration": null, @@ -215,7 +215,7 @@ }, { "cell_type": "markdown", - "id": "3a2b31c0", + "id": "76944c52", "metadata": { "papermill": { "duration": null, @@ -233,7 +233,7 @@ { "cell_type": "code", "execution_count": null, - "id": "f690096f", + "id": "3ac1d600", "metadata": { "papermill": { "duration": null, @@ -280,8 +280,8 @@ }, "papermill": { "default_parameters": {}, - "duration": 0.002787, - "end_time": "2025-11-08T18:27:09.917859", + "duration": 0.007291, + "end_time": "2025-11-21T17:51:43.490304", "environment_variables": {}, "exception": null, "input_path": "/Users/rorro6787/Desktop/SAES/SAES/html/notebooks/multiobjective_frontsND.ipynb", @@ -294,7 +294,7 @@ "metrics": "tests/test_data/multiobjectiveMetrics.csv", "references": "tests/test_data/references" }, - "start_time": "2025-11-08T18:27:09.915072", + "start_time": "2025-11-21T17:51:43.483013", "version": "2.6.0" } }, diff --git a/tests/htmls/no_fronts.ipynb b/tests/htmls/no_fronts.ipynb index b0c462c..98bb6a9 100644 --- a/tests/htmls/no_fronts.ipynb +++ b/tests/htmls/no_fronts.ipynb @@ -3,7 +3,7 @@ { "cell_type": "code", "execution_count": null, - "id": "959e7cfa", + "id": "a0640d5d", "metadata": { "papermill": { "duration": null, @@ -27,7 +27,7 @@ { "cell_type": "code", "execution_count": null, - "id": "8fd51bdd", + "id": "8bdca087", "metadata": { "papermill": { "duration": null, @@ -52,7 +52,7 @@ { "cell_type": "code", "execution_count": null, - "id": "ff774d79", + "id": "1da4e750", "metadata": { "papermill": { "duration": null, @@ -77,7 +77,7 @@ { "cell_type": "code", "execution_count": null, - "id": "54237675", + "id": "0b0718f7", "metadata": { "papermill": { "duration": null, @@ -97,7 +97,7 @@ }, { "cell_type": "markdown", - "id": "ed79c690", + "id": "5cbb7959", "metadata": { "papermill": { "duration": null, @@ -115,7 +115,7 @@ { "cell_type": "code", "execution_count": null, - "id": "04c90694", + "id": "ccb03460", "metadata": { "papermill": { "duration": null, @@ -133,7 +133,7 @@ }, { "cell_type": "markdown", - "id": "59ff8f3f", + "id": "bd77d000", "metadata": { "papermill": { "duration": null, @@ -151,7 +151,7 @@ { "cell_type": "code", "execution_count": null, - "id": "75d4c58f", + "id": "5f8bceff", "metadata": { "papermill": { "duration": null, @@ -170,7 +170,7 @@ }, { "cell_type": "markdown", - "id": "1746b54e", + "id": "036518f9", "metadata": { "papermill": { "duration": null, @@ -188,7 +188,7 @@ { "cell_type": "code", "execution_count": null, - "id": "69af9c60", + "id": "607f3feb", "metadata": { "papermill": { "duration": null, @@ -207,7 +207,7 @@ }, { "cell_type": "markdown", - "id": "b1f0020e", + "id": "d3aae9a8", "metadata": { "papermill": { "duration": null, @@ -225,7 +225,7 @@ { "cell_type": "code", "execution_count": null, - "id": "b2807f83", + "id": "b85bc1d1", "metadata": { "papermill": { "duration": null, @@ -244,7 +244,7 @@ }, { "cell_type": "markdown", - "id": "b2abe8a4", + "id": "fbb9d0a1", "metadata": { "papermill": { "duration": null, @@ -262,7 +262,7 @@ { "cell_type": "code", "execution_count": null, - "id": "f3dff728", + "id": "44e0e451", "metadata": { "papermill": { "duration": null, @@ -281,7 +281,7 @@ }, { "cell_type": "markdown", - "id": "9cf9188e", + "id": "6f731dd1", "metadata": { "papermill": { "duration": null, @@ -299,7 +299,7 @@ { "cell_type": "code", "execution_count": null, - "id": "6a30b377", + "id": "5352be8d", "metadata": { "papermill": { "duration": null, @@ -318,7 +318,7 @@ }, { "cell_type": "markdown", - "id": "51cbee68", + "id": "c90a934f", "metadata": { "papermill": { "duration": null, @@ -336,7 +336,7 @@ { "cell_type": "code", "execution_count": null, - "id": "7dc700e3", + "id": "49515d18", "metadata": { "papermill": { "duration": null, @@ -355,7 +355,7 @@ }, { "cell_type": "markdown", - "id": "ca60e3e6", + "id": "d85819dc", "metadata": { "papermill": { "duration": null, @@ -373,7 +373,7 @@ { "cell_type": "code", "execution_count": null, - "id": "cf19114d", + "id": "7b90e8b1", "metadata": { "papermill": { "duration": null, @@ -411,8 +411,8 @@ }, "papermill": { "default_parameters": {}, - "duration": 0.001856, - "end_time": "2025-11-08T18:27:09.931057", + "duration": 0.005167, + "end_time": "2025-11-21T17:51:43.510423", "environment_variables": {}, "exception": null, "input_path": "/Users/rorro6787/Desktop/SAES/SAES/html/notebooks/multiobjective_optimization.ipynb", @@ -422,7 +422,7 @@ "metric": "HV", "metrics": "tests/test_data/multiobjectiveMetrics.csv" }, - "start_time": "2025-11-08T18:27:09.929201", + "start_time": "2025-11-21T17:51:43.505256", "version": "2.6.0" } },