package com.github.liblevenshtein.transducer;
import java.io.Serializable;
/**
* The distance of each position in a state can be defined as follows:
*
* <p>
* <code>distance = w - i + e</code>
* </p>
*
* <p>
* For every accepting position, it must be the case that <code>w - i ≤ n - e</code>.
* It follows directly that the distance of every accepted position must be no
* more than {@code n}:
* </p>
*
* <p>
* <code>(w - i ≤ n - e) ⇔ (w - i + e ≤ n) ⇔ (distance ≤ n)</code>
* </p>
*
* <p>
* The Levenshtein distance between any two terms is defined as the minimum
* edit distance between the two terms. Therefore, iterate over each position
* in an accepting state, and take the minimum distance among all its accepting
* positions as the corresponding Levenshtein distance.
* </p>
*
* @author Dylon Edwards
* @since 2.1.0
*/
public abstract class DistanceFunction implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Returns the minimum distance between the spelling candidate and query term,
* implied by the positions within {@code state}.
* @param state Levenshtein state whose minimum, Levenshtein distance is to be
* determined.
* @param w Length of the query term.
* @return Minimum distance between the spelling candidate and query term,
* implied by the positions within {@code state}.
*/
public abstract int at(State state, int w);
/**
* Distance function for the standard, Levenshtein distance algorithm.
* @author Dylon Edwards
* @since 2.1.0
*/
public static class ForStandardPositions extends DistanceFunction {
private static final long serialVersionUID = 1L;
/**
* {@inheritDoc}
*/
@Override
public int at(final State state, final int queryLength) {
int minimumDistance = Integer.MAX_VALUE;
for (final Position position : state) {
final int i = position.termIndex();
final int e = position.numErrors();
final int distance = queryLength - i + e;
if (distance < minimumDistance) {
minimumDistance = distance;
}
}
return minimumDistance;
}
}
/**
* Distance function for the Levenshtein distance algorithms, extended with
* transposition (standard- and t-positions), and with merge and split
* (standard- and s-positions).
* @author Dylon Edwards
* @since 2.1.0
*/
public static class ForSpecialPositions extends DistanceFunction {
private static final long serialVersionUID = 1L;
/**
* {@inheritDoc}
*/
@Override
public int at(final State state, final int queryLength) {
int minimumDistance = Integer.MAX_VALUE;
for (final Position position : state) {
if (!position.isSpecial()) {
final int i = position.termIndex();
final int e = position.numErrors();
final int distance = queryLength - i + e;
if (distance < minimumDistance) {
minimumDistance = distance;
}
}
}
return minimumDistance;
}
}
}