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
4 changes: 2 additions & 2 deletions .github/workflows/python-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
python-version: ["3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v3
Expand All @@ -45,4 +45,4 @@ jobs:

- name: Test with pytest
run: |
coverage run -m pytest tests && coverage report -m --fail-under=75
coverage run -m pytest tests && coverage report -m --fail-under=50
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ build/
*.egg-info/

.coverage
.tox

# Documentation artifacts
_build/
Expand Down
2 changes: 1 addition & 1 deletion error_parity/_version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""File to keep the package version in one place."""
__version__ = "0.3.11"
__version__ = "0.3.12"
__version_info__ = tuple(__version__.split("."))
8 changes: 8 additions & 0 deletions error_parity/cvxpy_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,14 @@ def group_positive_prediction_rate(group_idx: int):

# Run solver
prob.solve(solver=cp.ECOS, abstol=SOLUTION_TOLERANCE, feastol=SOLUTION_TOLERANCE)

# NOTE: ECOS solver has been deprecated in favor of CLARABEL in cvxpy 1.3.2+
# https://www.cvxpy.org/updates/index.html?h=ecos#ecos-deprecation
# prob.solve(
# solver=cp.CLARABEL,
# tol_gap_abs=SOLUTION_TOLERANCE,
# tol_feas=SOLUTION_TOLERANCE,
# )
# NOTE: these tolerances are supposed to be smaller than the default np.isclose tolerances
# (useful when comparing if two points are the same, within the cvxpy accuracy tolerance)

Expand Down
152 changes: 152 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
[build-system]
requires = ["setuptools>=77.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "error-parity"
description = "Achieve error-rate parity between protected groups for any predictor"
license = "MIT"
license-files = ["LICENSE"]
authors = [
{ name = "AndreFCruz" },
]

# Keywords to be used by PyPI search
keywords = ["ml", "optimization", "fairness", "error-parity", "equal-odds"]

# PyPI classifiers, see https://pypi.org/classifiers/
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Science/Research",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]

requires-python = ">=3.9"

# These are defined below dynamically:
dynamic = [
"version",
"readme",
"dependencies",
"optional-dependencies",
]


[tool.setuptools.packages.find]
include = ["error_parity*"]
exclude = ["tests*"]

[tool.setuptools.dynamic]
version = { attr = "error_parity._version.__version__" }
readme = { file = "README.md", content-type = "text/markdown" }

# Main package dependencies
dependencies = {file = "requirements/main.txt"}

# Optional dependencies
[tool.setuptools.dynamic.optional-dependencies]
test = {file = "requirements/test.txt"}
dev = {file = "requirements/dev.txt"}
docs = {file = "requirements/docs.txt"}
all = {file = [
"requirements/dev.txt",
"requirements/test.txt",
"requirements/docs.txt",
]}

[project.urls]
homepage = "https://github.com/socialfoundations/error-parity"

# flake8
[tool.flake8]
max-complexity = 10
max-line-length = 120

per-file-ignores = """
# imported but unused
**/__init__.py: F401
"""

exclude = [
"docs/",
".tox/",
"build/",
"dist/",
]

[tool.pytest.ini_options]
minversion = "8.0"
testpaths = [
"tests",
]

# isort
[tool.isort]
profile = "hug"
force_single_line = false
src_paths = ["error_parity", "tests"]

# Coverage
[tool.coverage.run]
branch = true
source = ["error_parity"]
omit = ["error_parity/_version.py", "tests"]

[tool.coverage.report]
show_missing = true

# MyPy
[tool.mypy]
ignore_missing_imports = true
no_implicit_optional = false
strict_optional = false
exclude = [
"build",
"doc",
"tests",
"notebooks",
]
python_version = "3.11"

# Tox
[tool.tox]
legacy_tox_ini = """
[tox]
env_list =
py39
py310
py311
py312
lint
type

[testenv]
description = run unit tests
deps =
pytest>=8
coverage>=7
commands =
coverage erase
coverage run -m pytest {posargs:tests}
coverage report -m

[testenv:type]
description = run type checks
basepython = python3.11
deps =
mypy>=1.0
commands = mypy {posargs:error_parity}

[testenv:lint]
description = run linters
skip_install = true
deps =
flake8>=7.0
flake8-pyproject
commands = flake8 {posargs:error_parity tests}
"""
4 changes: 2 additions & 2 deletions requirements/main.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
pandas
numpy
numpy<2.0.0
scipy
tqdm
scikit-learn>=1.2
cvxpy>=1.3.2
cvxpy[ecos,clarabel]~=1.3.2
matplotlib
seaborn
4 changes: 2 additions & 2 deletions requirements/test.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pytest
coverage
pytest>=8.0
coverage>=7.0
folktables
tqdm
mypy
97 changes: 0 additions & 97 deletions setup.py

This file was deleted.

2 changes: 1 addition & 1 deletion tests/test_evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,5 @@ def test_equalized_odds_relaxation_costs(
higher_p_cost = results[higher_p_norm]

# Assert lower-p costs are higher (accuracy is lower)
assert lower_p_cost > higher_p_cost - SOLUTION_TOLERANCE, \
assert lower_p_cost > higher_p_cost - 2 * SOLUTION_TOLERANCE, \
f"l-{lower_p_norm} cost: {lower_p_cost} < l-{higher_p_norm} cost: {higher_p_cost}"
Loading