package score;
import org.apache.commons.math.MathException;
import org.apache.commons.math.distribution.NormalDistributionImpl;
public class ScoringFunction {
FeatureVector muParameters;
double sigma;
double pEventuallyRead;
double w;
public ScoringFunction(FeatureVector muParameters, double sigma, double pEventuallyRead, double w) {
this.muParameters = muParameters;
this.sigma = sigma;
this.pEventuallyRead = pEventuallyRead;
this.w = w;
}
public double score(FeatureVector blockFeatures, double timeSinceLastInformativeEvent) {
double mu = blockFeatures.innerProduct(muParameters);
double wt = intervalWidth(mu);
double t = wt*(Math.floor(timeSinceLastInformativeEvent/wt) + 0.5);
return exactScore(mu, t);
}
public double nextScoreChange(FeatureVector blockFeatures, double timeSinceLastInformativeEvent) {
double mu = blockFeatures.innerProduct(muParameters);
double wt = intervalWidth(mu);
return wt*(Math.floor(timeSinceLastInformativeEvent/wt) + 1);
}
public double getSigma() {return sigma;}
private double exactScore(double mu, double timeSinceLastInformativeEvent) {
double pt_Q = lognormalPDF(timeSinceLastInformativeEvent, mu, sigma);
double F = lognormalCDF(timeSinceLastInformativeEvent, mu, sigma);
double pQ = pEventuallyRead;
return pt_Q*pQ/((1-pQ) + (1-F)*pQ);
}
private double mode(double mu) {return Math.exp(mu - sigma*sigma);}
private double intervalWidth(double mu) {return w*mode(mu);}
private double lognormalPDF(double x, double mu, double sigma) {
double sigma2 = sigma*sigma;
double y = Math.log(x) - mu;
return 1/(x*Math.sqrt(2*Math.PI*sigma2)) * Math.exp(-y*y/(2*sigma2));
}
private double lognormalCDF(double x, double mu, double sigma) {
NormalDistributionImpl z = new NormalDistributionImpl();
double ans;
try {
ans = z.cumulativeProbability((Math.log(x)-mu)/sigma);
} catch (MathException e) {
if (Math.log(x) < mu) ans = 0;
else ans = 1;
}
return ans;
}
}