Let DDRA = the decaying decaying running average Let decayingDecayFactor=decayFactor * MIN(DRA,1-DRA) Then compute the new decaying decaying running average as: DDRA := DDRA*(1-decayingDecayFactor) + [1 or 0]*decayingDecayFactor
Attached is my attempt to implement this idea. I called it SelfAdjustingDecayingRunningAverage, but feel free to rename it if you like.
I will now see if we run into a similar problem using ResponseTimeEstimator for pDNF (epDNFGivenNotSearchFailed).
-Martin
package freenet.node.rt;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import freenet.Core;
import freenet.FieldSet;
import freenet.support.Logger;
/**
* Like DecayingRunningAverage, but adjusts the decayFactor downward the closer the
current value
* is to 0 or 1.
* Allows reports between 0 and 1, inclusive, but probably should only be used for
binary values.
*/
public class SelfAdjustingDecayingRunningAverage implements RunningAverage {
double currentVal;
final double decayFactor;
public SelfAdjustingDecayingRunningAverage(
double startVal,
double decayFactor) {
if (Double.isInfinite(startVal) || Double.isNaN(startVal))
throw new IllegalArgumentException(
"Infinite or NaN startVal: " + startVal);
if (startVal <= 0 || startVal >= 1)
throw new IllegalArgumentException(
"Not strictly between 0 and 1: " + startVal);
this.decayFactor = decayFactor;
this.currentVal = startVal;
}
public SelfAdjustingDecayingRunningAverage(
DataInputStream dis,
double decayFactor)
throws IOException {
this.decayFactor = decayFactor;
this.currentVal = dis.readDouble();
if (Double.isInfinite(currentVal)
|| Double.isNaN(currentVal)
|| currentVal <= 0
|| currentVal >= 1) {
throw new IOException(
"Invalid value serializing in: " + currentVal);
}
if (currentVal <= 0 || currentVal >= 1) {
Core.logger.log(
this,
"reset " + currentVal,
new Exception("debug"),
Logger.NORMAL);
currentVal = Core.hopTime(1);
}
}
public final double currentValue() {
return currentVal;
}
public synchronized final void report(double d) {
if (d < 0 || d > 1)
Core.logger.log(
this,
"Implausible report: " + d,
new Exception("debug"),
Logger.ERROR);
double adjustedDecayFactor =
decayFactor * Math.min(currentVal, 1 - currentVal);
currentVal =
currentVal * (1 - adjustedDecayFactor) + d *
adjustedDecayFactor;
// The current value must in the open interval (0,1). If it becomes 0
or 1, it will
// become irretrievably stuck.
// Bring value back into the open interval (0,1) if roundoff occurred.
if (currentVal==0) currentVal=Double.MIN_VALUE;
if (currentVal==1) currentVal=1-Double.MIN_VALUE;
}
public synchronized final void report(long d) {
report((double) d);
}
public static RunningAverageFactory factory() {
return new SelfAdjustingDecayingRunningAverageFactory();
}
static class SelfAdjustingDecayingRunningAverageFactory
implements RunningAverageFactory {
double defaultFactor = 0.2;
public RunningAverage create(double start) {
return new SelfAdjustingDecayingRunningAverage(start,
defaultFactor);
}
public RunningAverage create(DataInputStream dis) throws IOException {
return new SelfAdjustingDecayingRunningAverage(dis,
defaultFactor);
}
/* (non-Javadoc)
* @see freenet.node.rt.RunningAverageFactory#create(freenet.FieldSet)
*/
public RunningAverage create(FieldSet set)
throws EstimatorFormatException {
if (set == null)
throw new EstimatorFormatException("null set passed to
RunningAverage");
String impl = set.get("Implementation");
if (impl == null)
throw new EstimatorFormatException("no Implementation
in RunningAverage");
if (!impl.equals("SelfAdjustingDecayingRunningAverage"))
throw new EstimatorFormatException(
"unknown implementation " + impl);
String v = set.get("Version");
if (v == null || !v.equals("1"))
throw new EstimatorFormatException("Invalid version "
+ v);
String val = set.get("CurrentValue");
if (val == null)
throw new EstimatorFormatException("no CurrentValue");
double d;
try {
return new SelfAdjustingDecayingRunningAverage(
Double.parseDouble(val),
defaultFactor);
} catch (NumberFormatException x) {
throw new EstimatorFormatException(
"invalid CurrentValue " + val);
}
}
}
// Only write the value, not the decay factor
public int getDataLength() {
return 8;
}
public void writeTo(DataOutputStream out) throws IOException {
double cv;
synchronized (this) {
cv = currentVal;
}
out.writeDouble(cv);
}
/* (non-Javadoc)
* @see freenet.node.rt.RunningAverage#toFieldSet()
*/
public FieldSet toFieldSet() {
FieldSet fs = new FieldSet();
fs.put("Implementation", "SelfAdjustingDecayingRunningAverage");
fs.put("Version", "1");
fs.put("CurrentValue", Double.toString(currentVal));
return fs;
}
}
_______________________________________________ Devl mailing list [EMAIL PROTECTED] http://dodo.freenetproject.org/cgi-bin/mailman/listinfo/devl
