Skip to content

Release v1.0.0 #1009

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

Merged
merged 7 commits into from
Mar 28, 2025
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
37 changes: 28 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

-

### Fixed

-

### Changed

-

### Removed

-

### Deprecated

-


## [1.0.0]

### Added

- Coreax is now considered stable. (https://github.com/gchq/coreax/pull/1009)
- Added Compress++ coreset reduction algorithm.
(https://github.com/gchq/coreax/issues/934)
- Added `reduce_iterative()` method to Kernel Herding. (https://github.com/gchq/coreax/pull/983)
- Added probabilistic iterative Kernel Herding benchmarking results. (https://github.com/gchq/coreax/pull/983)
- Analytic example with integration test for `GreedyKernelPoints` plus an analytic unit
test for the loss function. (https://github.com/gchq/coreax/pull/1004)

### Fixed

-

### Changed

- Changed the score function used by Stein Thinning in benchmarking.
Expand All @@ -35,10 +55,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- `Coming soon` sections from README and documentation, as covered by backlogs.
(https://github.com/gchq/coreax/pull/972)

### Deprecated

-
- **[BREAKING CHANGE]** Removed deprecated Coreset functionality - see v0.4.0's
deprecations for more detail. (https://github.com/gchq/coreax/pull/1009)


## [0.4.0]
Expand Down Expand Up @@ -405,7 +423,8 @@ from `coreax.inverses.RegularisedInverseApproximator`,
[//]: # (### Deprecated)
[//]: # (This is where existing but deprecated elements should be noted.)

[Unreleased]: https://github.com/gchq/coreax/compare/v0.4.0...HEAD
[Unreleased]: https://github.com/gchq/coreax/compare/v1.0.0...HEAD
[1.0.0]: https://github.com/gchq/coreax/compare/v0.4.0...v1.0.0
[0.4.0]: https://github.com/gchq/coreax/compare/v0.3.1...v0.4.0
[0.3.1]: https://github.com/gchq/coreax/compare/v0.3.0...v0.3.1
[0.3.0]: https://github.com/gchq/coreax/compare/v0.2.1...v0.3.0
Expand Down
22 changes: 7 additions & 15 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,9 @@ Refs: #123

### Breaking changes and deprecation

Since we are still pre-1.0, [SemVer] states that any release may contain breaking
changes. However, breaking changes should not be made without warning.

Any breaking changes must have a deprecation period of at least **one minor release,
or one month (whichever is longer),** before the breaking change is made. If the change
is one that may require significant changes to client code, such as removing a function
or class entirely, the deprecation period must instead be at least **two minor releases,
or two months (whichever is longer).**
Coreax is stable, so according to [SemVer], any breaking changes require incrementing
the major version number. Any change that would otherwise be breaking should instead be
made into a deprecation if possible.

Ensure that during the deprecation period, the old behaviour still works, but raises a
`DeprecationWarning` with an appropriate message (which should include which version
Expand All @@ -111,22 +106,19 @@ As an example, this is what the deprecation period for renaming `my_old_function
`my_new_function` would look like:

```python
# v0.1.0:
# v1.1.0:
def my_old_function(x: int) -> int:
return x + x + x + x

# v0.2.0:
# v1.2.0:
def my_new_function(x: int) -> int:
return x*4

@deprecated(
"Renamed to my_new_function."
+ " Deprecated since v0.2.0; will be removed in v0.3.0."
)
@deprecated("Renamed to my_new_function; will be removed in the next major version")
def my_old_function(x: int) -> int:
return my_new_function(x)

# v0.3.0:
# v2.0.0:
def my_new_function(x: int) -> int:
return x*4
```
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
[![linting: pylint](https://img.shields.io/badge/linting-pylint-yellowgreen)](https://github.com/pylint-dev/pylint)
[![Python version](https://img.shields.io/pypi/pyversions/coreax.svg)](https://pypi.org/project/coreax)
[![PyPI](https://img.shields.io/pypi/v/coreax)](https://pypi.org/project/coreax)
![Beta](https://img.shields.io/badge/pre--release-beta-red)

_© Crown Copyright GCHQ_

Expand Down
2 changes: 1 addition & 1 deletion coreax/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

"""

__version__ = "0.4.0"
__version__ = "1.0.0"

from coreax.approximation import (
ANNchorApproximateKernel,
Expand Down
134 changes: 15 additions & 119 deletions coreax/coreset.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

"""Module for defining coreset data structures."""

import warnings
from abc import abstractmethod
from typing import (
TYPE_CHECKING,
Expand All @@ -28,7 +27,7 @@
import equinox as eqx
import jax.numpy as jnp
from jaxtyping import Array, Shaped
from typing_extensions import Self, deprecated, override
from typing_extensions import Self, override

from coreax.data import Data, SupervisedData, as_data
from coreax.metrics import Metric
Expand Down Expand Up @@ -68,16 +67,6 @@ def points(self) -> _TPointsData_co:
def pre_coreset_data(self) -> _TOriginalData_co:
"""The original data that this coreset is based on."""

@property
@abstractmethod
@deprecated(
"Narrow to a subclass, then use `.indices` or `.points` instead. "
+ "Deprecated since v0.4.0. "
+ "Will be removed in v0.5.0."
)
def nodes(self) -> Data:
"""Deprecated alias for `indices` or `points`, depending on subclass."""

@abstractmethod
def solve_weights(self, solver: WeightsOptimiser[Data], **solver_kwargs) -> Self:
"""Return a copy of 'self' with weights solved by 'solver'."""
Expand All @@ -100,16 +89,6 @@ def __check_init__(self) -> None:
"by definition of a Coreset"
)

@property
@deprecated(
"Use `.points` instead. "
+ "Deprecated since v0.4.0. "
+ "Will be removed in v0.5.0."
)
def coreset(self) -> _TPointsData_co:
"""Deprecated alias for `.points`."""
return self.points


class PseudoCoreset(
AbstractCoreset[Data, _TOriginalData_co], Generic[_TOriginalData_co]
Expand All @@ -135,41 +114,15 @@ class PseudoCoreset(

def __init__(self, nodes: Data, pre_coreset_data: _TOriginalData_co) -> None:
"""Initialise self."""
if isinstance(nodes, Array):
warnings.warn(
"Passing Arrays into PseudoCoreset() is deprecated since v0.4.0. "
"Use PseudoCoreset.build() instead. "
"In v0.5.0, this will become a TypeError.",
DeprecationWarning,
stacklevel=2,
)
nodes = as_data(nodes) # pyright: ignore[reportAssignmentType]
if isinstance(pre_coreset_data, Array):
warnings.warn(
"Passing Arrays into PseudoCoreset() is deprecated since v0.4.0. "
"Use PseudoCoreset.build() instead. "
"In v0.5.0, this will become a TypeError.",
DeprecationWarning,
stacklevel=2,
)
# pylint: disable-next=line-too-long
pre_coreset_data = as_data(pre_coreset_data) # pyright: ignore[reportAssignmentType]
if isinstance(pre_coreset_data, tuple):
warnings.warn(
"Passing Arrays into PseudoCoreset() is deprecated since v0.4.0. "
"Use PseudoCoreset.build() instead. "
"In v0.5.0, this will become a TypeError.",
DeprecationWarning,
stacklevel=2,
)
# pylint: disable-next=line-too-long
pre_coreset_data = SupervisedData(*pre_coreset_data) # pyright: ignore[reportAssignmentType]

if not isinstance(nodes, Data):
raise TypeError("`nodes` must be of type `Data`")
raise TypeError(
"`nodes` must be of type `Data`. "
"To use an array, use PseudoCoreset.build() instead."
)
if not isinstance(pre_coreset_data, Data):
raise TypeError(
"`pre_coreset_data` must be of type `Data` or `SupervisedData`"
"`pre_coreset_data` must be of type `Data` or `SupervisedData`. "
"To use an array or tuple of arrays, use PseudoCoreset.build() instead."
)

self._nodes = nodes
Expand Down Expand Up @@ -238,40 +191,20 @@ def points(self) -> Data:
def pre_coreset_data(self):
return self._pre_coreset_data

@property
@override
@deprecated(
"Use `.points` instead. "
+ "Deprecated since v0.4.0. "
+ "Will be removed in v0.5.0."
)
def nodes(self) -> Data:
"""Deprecated alias for `points`."""
return self.points

@override
def solve_weights(self, solver: WeightsOptimiser[Data], **solver_kwargs) -> Self:
"""Return a copy of 'self' with weights solved by 'solver'."""
weights = solver.solve(self.pre_coreset_data, self.points, **solver_kwargs)
return eqx.tree_at(lambda x: x.points.weights, self, weights)


@deprecated(
"Use AbstractCoreset, PseudoCoreset, or Coresubset instead. "
+ "Deprecated since v0.4.0. "
+ "Will be removed in v0.5.0."
)
class Coreset(PseudoCoreset):
"""Deprecated - split into AbstractCoreset and PseudoCoreset."""


class Coresubset(
AbstractCoreset[_TOriginalData_co, _TOriginalData_co], Generic[_TOriginalData_co]
):
r"""
Data structure for representing a coresubset.

A coresubset is a :class:`Coreset`, with the additional condition that the coreset
A coresubset is a coreset, with the additional condition that the coreset
data points/nodes must be a subset of the original data points/nodes, such that

.. math::
Expand Down Expand Up @@ -302,42 +235,16 @@ class Coresubset(
# pylint: enable=invalid-name

def __init__(self, indices: Data, pre_coreset_data: _TOriginalData_co) -> None:
"""Handle type conversion of ``indices`` and ``pre_coreset_data``."""
if isinstance(indices, Array):
warnings.warn(
"Passing Arrays into Coresubset() is deprecated since v0.4.0. "
"Use Coresubset.build() instead. "
"In v0.5.0, this will become a TypeError.",
DeprecationWarning,
stacklevel=2,
)
indices = as_data(indices) # pyright: ignore[reportAssignmentType]
if isinstance(pre_coreset_data, Array):
warnings.warn(
"Passing Arrays into Coresubset() is deprecated since v0.4.0. "
"Use Coresubset.build() instead. "
"In v0.5.0, this will become a TypeError.",
DeprecationWarning,
stacklevel=2,
)
# pylint: disable-next=line-too-long
pre_coreset_data = as_data(pre_coreset_data) # pyright: ignore[reportAssignmentType]
if isinstance(pre_coreset_data, tuple):
warnings.warn(
"Passing Arrays into Coresubset() is deprecated since v0.4.0. "
"Use Coresubset.build() instead. "
"In v0.5.0, this will become a TypeError.",
DeprecationWarning,
stacklevel=2,
)
# pylint: disable-next=line-too-long
pre_coreset_data = SupervisedData(*pre_coreset_data) # pyright: ignore[reportAssignmentType]

"""Initialise self."""
if not isinstance(indices, Data):
raise TypeError("`indices` must be of type `Data`")
raise TypeError(
"`indices` must be of type `Data`. "
"To use an array, use PseudoCoreset.build() instead."
)
if not isinstance(pre_coreset_data, Data):
raise TypeError(
"`pre_coreset_data` must be of type `Data` or `SupervisedData`"
"`pre_coreset_data` must be of type `Data` or `SupervisedData`. "
"To use an array or tuple of arrays, use PseudoCoreset.build() instead."
)

self._indices = indices
Expand Down Expand Up @@ -416,17 +323,6 @@ def indices(self) -> Data:
"""The (possibly weighted) Coresubset indices."""
return self._indices

@property
@override
@deprecated(
"Use `.indices` instead. "
+ "Deprecated since v0.4.0. "
+ "Will be removed in v0.5.0."
)
def nodes(self) -> Data:
"""Deprecated alias for `indices`."""
return self.indices

@override
def solve_weights(self, solver: WeightsOptimiser[Data], **solver_kwargs) -> Self:
"""Return a copy of 'self' with weights solved by 'solver'."""
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ keywords = [
"coreset",
]
classifiers = [
"Development Status :: 4 - Beta",
"Development Status :: 5 - Production/Stable",
"Programming Language :: Python",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
Expand Down
Loading
Loading