Martin Stone Davis wrote:

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

Reply via email to