Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix warnings + Add test workflow #97

Open
wants to merge 26 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f89ffe3
Fix typos
merajhashemi Aug 11, 2024
c380330
Remove tox
merajhashemi Aug 11, 2024
2531de4
Remove setup.cfg in tests
merajhashemi Aug 11, 2024
300518e
Update dependencies
merajhashemi Aug 11, 2024
ca5464b
Fix mypy config
merajhashemi Aug 11, 2024
9f895a1
Bump ruff version
merajhashemi Aug 11, 2024
b2a2f40
Simplify logic
merajhashemi Aug 11, 2024
a3892c2
Add `weights_only=True` when using `torch.load`
merajhashemi Aug 11, 2024
ba5e3a6
Sort `pyproject.toml`
merajhashemi Aug 11, 2024
decb34a
Add concurrency check to ci workflow
merajhashemi Aug 11, 2024
c12ef60
Fix typo
merajhashemi Aug 11, 2024
cbf9b07
Fix version tag glob in workflow
merajhashemi Aug 11, 2024
103da3a
Add workflow to test all supported python and PyTorch versions
merajhashemi Aug 11, 2024
b71ba96
Fix typo
merajhashemi Aug 11, 2024
26a6b31
Fix workflow combination
merajhashemi Aug 11, 2024
db6e262
Add cool badges To README
merajhashemi Aug 12, 2024
fc53fa1
Fix coverage badge color
merajhashemi Aug 12, 2024
54c3c3c
Refactor test helpers into separate testing package
merajhashemi Aug 13, 2024
2027c34
Remove tests and testing from coverage
merajhashemi Aug 13, 2024
0c0113c
Remove numpy from core dependencies
merajhashemi Aug 13, 2024
53850d7
Fix name
merajhashemi Aug 13, 2024
a09334c
Revert "Remove tests and testing from coverage"
merajhashemi Aug 13, 2024
de92a85
Improve README
merajhashemi Aug 13, 2024
2a24261
Add Simon to CITATION.cff
merajhashemi Aug 13, 2024
134ad62
Remove Makefile
merajhashemi Aug 19, 2024
f7769ff
Update discord invite link
merajhashemi Aug 19, 2024
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
15 changes: 14 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ on:
push:
branches: [ master ]

concurrency:
# github.workflow: name of the workflow
# github.event.pull_request.number || github.ref: pull request number or branch name if not a pull request
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}

# Cancel in-progress runs when a new workflow with the same group name is triggered
cancel-in-progress: true

jobs:
ci:
runs-on: ubuntu-latest
Expand All @@ -24,12 +32,13 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: "3.10"
cache: "pip"

- name: Pre-commit checks
uses: pre-commit/[email protected]

- name: Install package & dependencies
run: pip install --editable '.[dev, docs, tests, examples]'
run: pip install '.[tests]'

- name: Launch tests & generate coverage report
run: coverage run -m pytest tests
Expand All @@ -39,6 +48,10 @@ jobs:
uses: py-cov-action/python-coverage-comment-action@v3
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# If the coverage percentage is above or equal to this value, the badge will be green.
MINIMUM_GREEN: 90
# If the coverage percentage is below this value, the badge will be red.
MINIMUM_ORANGE: 80

- name: Store Pull Request comment to be posted
uses: actions/upload-artifact@v4
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/coverage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ jobs:
# artifact that contains the comment to be published
actions: read
steps:

- name: Post comment
uses: py-cov-action/python-coverage-comment-action@v3
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_PR_RUN_ID: ${{ github.event.workflow_run.id }}
# If the coverage percentage is above or equal to this value, the badge will be green.
MINIMUM_GREEN: 90
# If the coverage percentage is below this value, the badge will be red.
MINIMUM_ORANGE: 80
2 changes: 1 addition & 1 deletion .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
workflow_dispatch:
push:
tags:
- v.**
- 'v[0-9]+\.[0-9]+\.[0-9]+'

jobs:
publish:
Expand Down
48 changes: 48 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Run tests

on:
pull_request:
push:
branches: [ master ]

concurrency:
# github.workflow: name of the workflow
# github.event.pull_request.number || github.ref: pull request number or branch name if not a pull request
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}

# Cancel in-progress runs when a new workflow with the same group name is triggered
cancel-in-progress: true

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [ "3.9", "3.10", "3.11" ]
TORCH_VERSION: [ "1.13.1", "2.0.1", "2.1.2", "2.2.2", "2.3.1", "2.4.0" ]
include:
- python-version: "3.12"
TORCH_VERSION: "2.4.0"
exclude:
- python-version: "3.11"
TORCH_VERSION: "1.13.1"
steps:
- uses: actions/checkout@v4

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

- name: Install dependencies and PyTorch ${{ matrix.TORCH_VERSION }}
run: |
pip install --upgrade pip
pip install torch==${{ matrix.TORCH_VERSION }} '.[tests]'

- name: Launch tests
# Only run the unit tests, not the pipeline tests.
# Pipeline tests are too expensive to run for every python/PyTorch version.
# However, they are run as part the coverage job in the CI workflow
run: pytest --ignore=tests/pipeline tests
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ repos:
files: \.py$

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.5.6
rev: v0.5.7
hooks:
- id: ruff
types_or: [ python, pyi, jupyter ]
Expand Down
2 changes: 2 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ authors:
given-names: "Juan"
- family-names: "Hashemizadeh"
given-names: "Meraj"
- family-names: "Lacoste-Julien"
given-names: "Simon"
title: "Cooper: a toolkit for Lagrangian-based constrained optimization"
date-released: 2022-03-15
url: "https://github.com/cooper-org/cooper"
89 changes: 0 additions & 89 deletions Makefile

This file was deleted.

31 changes: 19 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
# Cooper

[![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/cooper-org/cooper/tree/master/LICENSE)
[![LICENSE](https://img.shields.io/pypi/l/cooper-optim)](https://github.com/cooper-org/cooper/tree/master/LICENSE)
[![Version](https://img.shields.io/pypi/v/cooper-optim?label=version)](https://pypi.python.org/pypi/cooper-optim)
[![Downloads](https://static.pepy.tech/badge/cooper-optim)](https://pypi.python.org/pypi/cooper-optim)
[![Python](https://img.shields.io/pypi/pyversions/cooper-optim)](https://pypi.python.org/pypi/cooper-optim)
[![DOCS](https://readthedocs.org/projects/cooper/badge/?version=latest)](https://cooper.readthedocs.io/en/latest/?version=latest)
[![Build and Test](https://github.com/cooper-org/cooper/actions/workflows/build.yml/badge.svg)](https://github.com/cooper-org/cooper/actions/workflows/build.yml)
[![Coverage](https://codecov.io/gh/cooper-org/cooper/graph/badge.svg?token=4U41P8JCE1)](https://codecov.io/gh/cooper-org/cooper)
[![HitCount](https://hits.dwyl.com/cooper-org/cooper.svg?style=flat-square)](https://cooper.readthedocs.io/en/latest/?version=latest)
[![Coverage badge](https://raw.githubusercontent.com/cooper-org/cooper/python-coverage-comment-action-data/badge.svg)](https://github.com/cooper-org/cooper/tree/python-coverage-comment-action-data)
[![Continuous Integration](https://github.com/cooper-org/cooper/actions/workflows/ci.yml/badge.svg)](https://github.com/cooper-org/cooper/actions/workflows/ci.yml)
[![Stars](https://img.shields.io/github/stars/cooper-org/cooper)](https://github.com/cooper-org/cooper)
[![HitCount](https://img.shields.io/endpoint?url=https://hits.dwyl.com/cooper-org/cooper.json&color=brightgreen)](https://cooper.readthedocs.io/en/latest/?version=latest)
[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/cooper-org/cooper/issues)
[![Discord](https://img.shields.io/badge/Discord-%235865F2.svg?logo=discord&logoColor=white)](https://discord.gg/Aq5PjH8m6E)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)

## About

Expand Down Expand Up @@ -103,20 +109,21 @@ for epoch_num in range(50):
### Basic Installation

```bash
pip install git+https://github.com/cooper-org/cooper.git
pip install cooper-optim
```

### Development Installation

First, clone the [repository](https://github.com/cooper-org/cooper), navigate
to the **Cooper** root directory and install the package in development mode by running:

| Setting | Command | Notes |
| ----------- | ---------------------------------------- | ----------------------------------------- |
| Development | `pip install --editable ".[dev, tests]"` | Editable mode. Matches test environment. |
| Docs | `pip install --editable ".[docs]"` | Used to re-generate the documentation. |
| Tutorials | `pip install --editable ".[examples]"` | Install dependencies for running examples |
| No Tests | `pip install --editable .` | Editable mode, without tests. |
| Setting | Command | Notes |
|-------------|-----------------------------------------|-------------------------------------------------|
| No Tests | `pip install --editable .` | Editable mode, without tests. |
| Development | `pip install --editable ".[test]"` | Editable mode. Matches test environment. |
| Development | `pip install --editable ".[dev]"` | Editable mode. Matches development environment. |
| Tutorials | `pip install --editable ".[notebooks]"` | Install dependencies for running notebooks. |
| Docs | `pip install --editable ".[docs]"` | Used to generate the documentation. |

## Package structure

Expand Down Expand Up @@ -172,7 +179,7 @@ the snippet below:

```bibtex
@misc{gallegoPosada2022cooper,
author={Gallego-Posada, Jose and Ramirez, Juan},
author={Gallego-Posada, Jose and Ramirez, Juan and Hashemizadeh, Meraj and Lacoste-Julien, Simon},
title={Cooper: a toolkit for Lagrangian-based constrained optimization},
howpublished={\url{https://github.com/cooper-org/cooper}},
year={2022}
Expand Down
16 changes: 4 additions & 12 deletions docs/source/additional_features.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ In this section we provide details on using "advanced features" such as
alternating updates, or the Augmented Lagrangian method, in conjunction with a
{py:class}`~cooper.optim.constrained_optimizers.ConstrainedOptimizer`.

______________________________________________________________________

(alternating-updates)=

## Alternating updates
Expand All @@ -25,21 +23,19 @@ variables. This two-stage process is handled by **Cooper** inside the

One can perform alternating updates in which the primal parameters are updated first. We
refer to this update strategy as `cooper.optim.AlternationType.PRIMAL_DUAL`.
.. math:

```
$$
x_{t+1} &= \texttt{primal_optimizers_update} \left( x_{t}, \nabla_{x} \mathcal{L}_{c_t}(x, \lambda_t)|_{x=x_t} \right)\\
\lambda_{t+1} &= \texttt{dual_optimizer_update} \left( \lambda_{t}, {\color{red} \mathbf{-}} \nabla_{\lambda} \mathcal{L}({\color{red} x_{t+1}}, \lambda)|_{\lambda=\lambda_t} \right)
```
$$

Alternative, `cooper.optim.AlternationType.DUAL_PRIMAL` carries out an update of the
dual parameters first.
.. math:

```
$$
\lambda_{t+1} &= \texttt{dual_optimizer_update} \left( \lambda_{t}, {\color{red} \mathbf{-}} \nabla_{\lambda} \mathcal{L}({\color{red} x_{t}}, \lambda)|_{\lambda=\lambda_t} \right) \\
x_{t+1} &= \texttt{primal_optimizers_update} \left( x_{t}, \nabla_{x} \mathcal{L}_{c_t}(x, \lambda_{t+1})|_{x=x_t} \right)
```
$$

:::{important}
Selecting `alternation_type=AlternationType.DualPrimal` does not double the number
Expand All @@ -57,8 +53,6 @@ allows for updating the Lagrange multiplier without having to re-evaluate
the loss function, but rather only the constraints.
:::

______________________________________________________________________

(augmented-lagrangian-const-opt)=

## Augmented Lagrangian method
Expand Down Expand Up @@ -172,8 +166,6 @@ for step_id in range(1000):
coop.dual_scheduler.step()
```

______________________________________________________________________

(multiple-primal-optimizers)=

# Multiple primal optimizers
Expand Down
3 changes: 1 addition & 2 deletions docs/source/constrained_optimizer.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,7 @@ will be equivalent to performing `optimizer.step()` on all of the
primal parameters.
:::

```{eval-rst}
.. include:: additional_features.rst
```{include} additional_features.md
```

```{eval-rst}
Expand Down
3 changes: 0 additions & 3 deletions docs/source/lagrangian_formulation.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ in Fig 1. of {cite:t}`cotter2019JMLR`.
```{eval-rst}
.. autoclass:: LagrangianFormulation
:members:

```

```{eval-rst}
Expand Down Expand Up @@ -144,8 +143,6 @@ in **Cooper** as a
```{eval-rst}
.. autoclass:: AugmentedLagrangianFormulation
:members:


```

```{eval-rst}
Expand Down
4 changes: 2 additions & 2 deletions docs/source/notebooks/plot_mnist_logistic_regression.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@
" start_epoch = 0\n",
" all_metrics = defaultdict(list)\n",
"else:\n",
" checkpoint = torch.load(checkpoint_path + \"/checkpoint.pth\")\n",
" checkpoint = torch.load(checkpoint_path + \"/checkpoint.pth\", weights_only=True)\n",
" batch_ix = checkpoint[\"batch_ix\"]\n",
" start_epoch = checkpoint[\"epoch\"] + 1\n",
" all_metrics = checkpoint[\"all_metrics\"]\n",
Expand Down Expand Up @@ -182,7 +182,7 @@
"del batch_ix, all_metrics, model, cmp, cooper_optimizer\n",
"\n",
"# Post-training analysis and plotting\n",
"all_metrics = torch.load(checkpoint_path + \"/checkpoint.pth\")[\"all_metrics\"]\n",
"all_metrics = torch.load(checkpoint_path + \"/checkpoint.pth\", weights_only=True)[\"all_metrics\"]\n",
"\n",
"fig, (ax0, ax1, ax2, ax3) = plt.subplots(nrows=1, ncols=4, sharex=True, figsize=(18, 4))\n",
"\n",
Expand Down
4 changes: 2 additions & 2 deletions docs/source/notebooks/plot_mnist_logistic_regression.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ if not os.path.isfile(checkpoint_path + "/checkpoint.pth"):
start_epoch = 0
all_metrics = defaultdict(list)
else:
checkpoint = torch.load(checkpoint_path + "/checkpoint.pth")
checkpoint = torch.load(checkpoint_path + "/checkpoint.pth", weights_only=True)
batch_ix = checkpoint["batch_ix"]
start_epoch = checkpoint["epoch"] + 1
all_metrics = checkpoint["all_metrics"]
Expand Down Expand Up @@ -167,7 +167,7 @@ for epoch_num in range(start_epoch, 7):
del batch_ix, all_metrics, model, cmp, cooper_optimizer

# Post-training analysis and plotting
all_metrics = torch.load(checkpoint_path + "/checkpoint.pth")["all_metrics"]
all_metrics = torch.load(checkpoint_path + "/checkpoint.pth", weights_only=True)["all_metrics"]

fig, (ax0, ax1, ax2, ax3) = plt.subplots(nrows=1, ncols=4, sharex=True, figsize=(18, 4))

Expand Down
Loading
Loading