// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.searchlib.ranking.features.fieldmatch;
/**
* The parameters to a string match metric calculator.
* Mutable until frozen.
*
* @author bratseth
*/
public final class FieldMatchMetricsParameters {
private boolean frozen=false;
private int proximityLimit=10;
private int maxAlternativeSegmentations = 10000;
private int maxOccurrences=100;
private float proximityCompletenessImportance =0.9f;
private float relatednessImportance =0.9f;
private float earlinessImportance =0.05f;
private float segmentProximityImportance =0.05f;
private float occurrenceImportance =0.05f;
private float fieldCompletenessImportance =0.05f;
private float[] proximityTable= new float[] { 0.01f, 0.02f, 0.03f, 0.04f, 0.06f, 0.08f, 0.12f, 0.17f, 0.24f, 0.33f, 1,
0.71f, 0.50f, 0.35f, 0.25f, 0.18f, 0.13f, 0.09f, 0.06f, 0.04f, 0.03f };
/* Calculation of the table above:
static {
System.out.println("Right order");
for (float i=0; i<=10; i++)
System.out.println(1/Math.pow(2,i/2));
System.out.println("Reverse order");
for (float i=0; i<=10; i++)
System.out.println(1/Math.pow(2,i/2)/3);
}
*/
private static FieldMatchMetricsParameters defaultParameters;
static {
defaultParameters=new FieldMatchMetricsParameters();
defaultParameters.freeze();
}
/** Returns the frozen default parameters */
public static FieldMatchMetricsParameters defaultParameters() {
return defaultParameters;
}
/** Creates an unfrozen marcg metrics object initialized to the default values */
public FieldMatchMetricsParameters() { }
/** Sets the maximum allowed gap within a segment. Default: 10 */
public void setProximityLimit(int proximityLimit) {
ensureNotFrozen();
this.proximityLimit=proximityLimit;
}
/** Returns the maximum allowed gap within a segment. Default: 10 */
public int getProximityLimit() { return proximityLimit; }
/**
* Sets the proximity table deciding the importance of separations of various distances,
* The table must have size proximityLimit*2+1, where the first half is for reverse direction
* distances. The table must only contain values between 0 and 1, where 1 is "perfect" and 0 is "worst".
*/
public void setProximityTable(float[] proximityTable) {
ensureNotFrozen();
this.proximityTable=proximityTable;
}
/**
* Returns the current proxmity table.
* The default table is calculated by
* 1/2^(n/2)
on the right order side, and
* 1/2^(n/2) /3
on the reverse order side
* where n is the distance between the tokens.
*/
public float[] getProximityTable() { return proximityTable; }
/** Returns the proximity table value at an index */
public float getProximity(int index) { return proximityTable[index]; }
/**
* Returns the maximal number of alternative segmentations allowed in addition to the first one found.
* Default is 10000. This will prefer to not consider iterations on segments that are far out in the field,
* and which starts late in the query.
*/
public int getMaxAlternativeSegmentations() { return maxAlternativeSegmentations; }
public void setMaxAlternativeSegmentations(int maxAlternativeSegmentations) {
ensureNotFrozen();
this.maxAlternativeSegmentations = maxAlternativeSegmentations;
}
/**
* Returns the number of occurrences the number of occurrences of each word is normalized against.
* This should be set as the number above which additional occurrences of the term has no real significance.
* The default is 100.
*/
public int getMaxOccurrences() { return maxOccurrences; }
public void setMaxOccurrences(int maxOccurrences) { this.maxOccurrences=maxOccurrences; }
/**
* Returns a number between 0 and 1 which determines the importancy of field completeness in relation to
* query completeness in the match
and completeness
metrics. Default is 0.05
*/
public float getFieldCompletenessImportance() { return fieldCompletenessImportance; }
public void setFieldCompletenessImportance(float fieldCompletenessImportance) {
ensureNotFrozen();
this.fieldCompletenessImportance = fieldCompletenessImportance;
}
/**
* Returns the importance of the match having high proximity and being complete, relative to segmentProximityImportance,
* occurrenceImportance and earlinessImportance in the match
metric. Default: 0.9
*/
public float getProximityCompletenessImportance() { return proximityCompletenessImportance; }
public void setProximityCompletenessImportance(float proximityCompletenessImportance) {
ensureNotFrozen();
this.proximityCompletenessImportance = proximityCompletenessImportance;
}
/**
* Returns the importance of the match occuring early in the query, relative to segmentProximityImportance,
* occurrenceImportance and proximityCompletenessImportance in the match
metric. Default: 0.05
*/
public float getEarlinessImportance() { return earlinessImportance; }
public void setEarlinessImportance(float earlinessImportance) {
ensureNotFrozen();
this.earlinessImportance = earlinessImportance;
}
/**
* Returns the importance of multiple segments being close to each other, relative to earlinessImportance,
* occurrenceImportance and proximityCompletenessImportance in the match
metric. Default: 0.05
*/
public float getSegmentProximityImportance() { return segmentProximityImportance; }
public void setSegmentProximityImportance(float segmentProximityImportance) {
ensureNotFrozen();
this.segmentProximityImportance = segmentProximityImportance;
}
/**
* Returns the importance of having many occurrences of the query terms, relative to earlinessImportance,
* segmentProximityImportance and proximityCompletenessImportance in the match
metric. Default: 0.05
*/
public float getOccurrenceImportance() { return occurrenceImportance; }
public void setOccurrenceImportance(float occurrenceImportance) {
ensureNotFrozen();
this.occurrenceImportance = occurrenceImportance;
}
/** Returns the normalized importance of relatedness used in the match
metric. Default: 0.9 */
public float getRelatednessImportance() { return relatednessImportance; }
public void setRelatednessImportance(float relatednessImportance) {
ensureNotFrozen();
this.relatednessImportance = relatednessImportance;
}
/** Throws IllegalStateException if this is frozen. Does nothing otherwise */
private void ensureNotFrozen() {
if (frozen)
throw new IllegalStateException(this + " is frozen");
}
/**
* Freezes this object. All changes after this point will cause an IllegalStateException.
* This must be frozen before being handed to a calculator.
*
* @throws IllegalStateException if this parameter object is inconsistent. In this case, this is not frozen.
*/
public void freeze() {
if (proximityTable.length!=proximityLimit*2+1)
throw new IllegalStateException("Proximity table length is " + proximityTable.length + ". Must be " +
(proximityLimit*2+1) +
" (proximityLimit*2+1), because the proximity limit is " + proximityLimit);
frozen=true;
}
}