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

Remove Metric <: SemiMetric <: PreMetric #228

Closed
wants to merge 8 commits into from
Closed
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
29 changes: 17 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,31 +141,36 @@ pairwise!(R, dist, X, dims=i)
Please pay attention to the difference, the functions for inplace computation are
`colwise!` and `pairwise!` (instead of `colwise` and `pairwise`).

## Distance type hierarchy
## Distance properties

The distances are organized into a type hierarchy.
Distances is an abstract class for function `d` that satisfies

At the top of this hierarchy is an abstract class **PreMetric**, which is defined to be a function `d` that satisfies

`MetricType` indicates the particular properties of the distance

`IsPreMetric` indicates that the distance is a premetric; i.e.,

d(x, x) == 0 for all x
d(x, y) >= 0 for all x, y

**SemiMetric** is a abstract type that refines **PreMetric**. Formally, a *semi-metric* is a *pre-metric* that is also symmetric, as
`IsSemiMetric` indicates that the distance is also symmetric; i.e.,

d(x, y) == d(y, x) for all x, y

**Metric** is a abstract type that further refines **SemiMetric**. Formally, a *metric* is a *semi-metric* that also satisfies triangle inequality, as
`IsMetric` indicates that the distance also satisfies the triangle inequality; i.e.,

d(x, z) <= d(x, y) + d(y, z) for all x, y, z

This type system has practical significance. For example, when computing pairwise distances
Note that we have `IsMetric <: IsSemiMetric <: IsPreMetric`.

These properties have practical significance. For example, when computing pairwise distances
between a set of vectors, you may only perform computation for half of the pairs, derive the
values immediately for the remaining half by leveraging the symmetry of *semi-metrics*. Note
that the types of `SemiMetric` and `Metric` do not completely follow the definition in
mathematics as they do not require the "distance" to be able to distinguish between points:
for these types `x != y` does not imply that `d(x, y) != 0` in general compared to the
mathematical definition of semi-metric and metric, as this property does not change
computations in practice.
values immediately for the remaining half by leveraging the symmetry of the distance.

Note that a subadditive distance is not necessarly a metric in the mathematical since
it is not required to be able to distinguish between points:
`x != y` does not imply that `d(x, y) != 0` in general compared to the
mathematical definition of metric.

Each distance corresponds to a distance type. The type name and the corresponding mathematical
definitions of the distances are listed in the following table.
Expand Down
17 changes: 12 additions & 5 deletions src/Distances.jl
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
module Distances

using LinearAlgebra
import LinearAlgebra: issymmetric
using Statistics
import StatsAPI: pairwise, pairwise!

export
# generic types/functions
PreMetric,
SemiMetric,
Metric,



export
Distance,
# traits
MetricType,
IsPreMetric,
IsSemiMetric,
IsMetric,
# generic functions
issymmetric,
issubadditive,
result_type,
colwise,
pairwise,
Expand Down
7 changes: 4 additions & 3 deletions src/bhattacharyya.jl
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
# be compared are probability distributions, frequencies or counts rather than
# vectors of samples. Pre-calc accordingly if you have samples.

struct BhattacharyyaDist <: SemiMetric end

struct HellingerDist <: Metric end
struct BhattacharyyaDist <: Distance end
MetricType(::Type{BhattacharyyaDist}) = IsSemiMetric

struct HellingerDist <: Distance end
MetricType(::Type{HellingerDist}) = IsMetric

# Bhattacharyya coefficient

Expand Down
2 changes: 1 addition & 1 deletion src/bregman.jl
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ of good automatic differentiation packages.

function evaluate(dist::Bregman, p::AbstractVector, q::AbstractVector)
"""
struct Bregman{T1 <: Function, T2 <: Function, T3 <: Function} <: PreMetric
struct Bregman{T1 <: Function, T2 <: Function, T3 <: Function} <: Distance
F::T1
∇::T2
inner::T3
Expand Down
Empty file modified src/common.jl
100644 → 100755
Empty file.
Loading