Domanda

I'm trying to implement Bin Fu's approximate sum algorithm in a real language to have a better feel of how it works.

In a nutshell, this is an algorithm to compute $\hat{s}(x)$,an $(1+\epsilon)$ approximation on the value of $s(x)=\sum_{i=1}^n x_i$ (e.g. this means that $\hat{s}(x)$ satisfies: $\hat{s}(x)/(1+\epsilon)\leq s(x)\leq (1+\epsilon)\hat{s}(x)$[1]).

However, I must be doing something wrong because running my implementation doesn't give the right result, e.g. the $\hat{s}(x)$ I get out of it doesn't satisfy [1].

I suspect that in my implementation below, I'm existing too early, but I don't see what is causing this.

ApproxRegion<-function(x,b,delta,n){
    if(n<=1 || x[n]<b)          return(NULL)
    if(x[n-1]<b)                return(c(n,n))
    if(x[1]>=b)             return(c(1,n))
    m<-2
    while(n-m**2>0 && x[n-m**2+1]>=b)   m<-m**2
    r<-m
    while(m>=(1+delta)){
        m<-sqrt(m)  
        if(n-floor(m*r)>=0 && x[n-floor(m*r)+1]>=b) r=m*r   
    }
    return(c(n-floor(m*r)+1,n))
}       
ApproxSum<-function(x,n,epsilon){
    if(x[n]==0)         return(0)
    delta=3*epsilon/4
    rp<-n
    i<-0
    s<-0
    b<-x[n]/(1+delta)
    while(b>=delta*x[n]/(3*n)){
        R<-ApproxRegion(x,b,delta,rp)
        if(is.null(R))      break   
        rp<-R[1]-1;
        b<-x[rp]/(1+delta)
        si<-(R[2]-R[1]+1)*b
        s<-s+si
        i<-i+1
    }
    return(list(s=s,i=i))
}

However, when I run it

n<-100;
set.seed(123)
x<-sort(rexp(n));
eps<-1/10
y0<-ApproxSum(x=x,n=n,epsilon=eps);
y0$s*(1+eps)
sum(x)

I get that y0$s*(1+eps) is smaller than sum(x)

È stato utile?

Soluzione

Looks like you're loosing track of i vs i+1 in two places, the second while loop in ApproxRegion and the loop in ApproxSum. This looks like it works on your example:

ApproxRegion<-function(x,b,delta,n){
    if(n<=1 || x[n]<b)          return(NULL)
    if(x[n-1]<b)                return(c(n,n))
    if(x[1]>=b)             return(c(1,n))
    m<-2
    while(n-m**2>0 && x[n-m**2+1]>=b)   m<-m**2
    r<-m
    while(m>=(1+delta)){
        m<-sqrt(m)
        if(n-floor(m*r)>=0 && x[n-floor(m*r)+1]>=b) r=m*r
    }
    return(c(n-floor(r)+1,n))
}
ApproxSum<-function(x,n,epsilon){
    if(x[n]==0)         return(0)
    delta=3*epsilon/4
    rp<-n
    i<-0
    s<-0
    b<-x[n]/(1+delta)
    while(b>=delta*x[n]/(3*n)){
        R<-ApproxRegion(x,b,delta,rp)
        if(is.null(R))      break
        si<-(R[2]-R[1]+1)*b
        s<-s+si
        i<-i+1
        rp<-R[1]-1;
        b<-x[rp]/(1+delta)
    }
    return(list(s=s,i=i))
}

n<-100;
set.seed(123)
x<-sort(rexp(n));
eps<-0.001
y0<-ApproxSum(x=x,n=n,epsilon=eps);


> y0$s*(1+eps)
[1] 104.5955

> sum(x)
[1] 104.5719

> y0$s/(1+eps)
[1] 104.3866
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top