/*
 *  $Id: AdaptMix.java,v 1.1 2008/07/11 04:50:51 nemo Exp $
 * 
 * Copyright (c) 2008, Nemo Semret.
 */
package edu.columbia.ee.e6773;

import java.util.Random;

/**
 * A mixed (i.e randomized) strategy, with adaptation.  Each day, cache in
 *  network k * with a probability p, where p is adjusted by "learning" the
 *  utility achieved by caching * and not-caching in that network in the past,
 *  as follows: 
 *  p = 0.5 + 0.5*(pro[k]-con[k])/(Math.abs(pro[k]) + Math.abs(con[k]))
 *  where pro[k] = sum of past utility when caching, con[k]
 *  = sum of utility when not caching.  
 *  This simple learning rule is such that if pro > 0 and con < 0, i.e. a clear
 *  win for caching ,the probability equals 1.  If both are postive or both are
 *  negative, then p will increase towards 1 if pro > con and 0 if pro < con.
*/
public class AdaptMix implements CDNAgent {
    double [] pro;
    double [] con;
    boolean [] a;
    double X;
    // N, m not used
    double N = 4;
    double m = 2;

    public AdaptMix() {
	Random rand = new Random(System.currentTimeMillis());
	pro = new double [K];
	con = new double [K];
	a = new boolean [K];
        for (int k = 0; k < K; k++) {
            pro[k] = rand.nextDouble();
	    con[k] = rand.nextDouble();
        }
    }
    
    public boolean[] startDay(long x) {
	Random rand = new Random(System.currentTimeMillis());
        X = x;
	double probab,r;
        for (int k = 0; k < K; k++) {
	    probab = 0.5 + 0.5*(pro[k]-con[k])/(Math.abs(pro[k]) + Math.abs(con[k]));
	    r= rand.nextDouble();
	    a[k] = (r < probab);
        }
        return a;
    }

    public void endDay(long[] b, long[]c) {
        double D = 10000;
        double U;
        for (int k = 0; k < K; k++) {
	    U = c[k]*V  - Pb*b[k]*X/1073741824.0;
	    if (c[k]>0) U -= (Pc*X/1073741824.0 + Sc);
	    if (D*(1.0-q)*X*8 < C[k]*1000000*60*60*24) { // k not congested
		U += (b[k]*V);
	    } 
            if (a[k]) pro[k] += U;
	    else con[k] += U;
        }
    }

    /**
     * Estimate (N, m) based on:
     * D*(1-q) = b[k]*N
     * D*q = c[k]*m
     */
    void estimateN (long[] b, long[]c) {
	double Nnew;
        for (int k = 0; k < K; k++) {
	    if (b[k]>0 && c[k]>0) {
		Nnew  = (c[k]*m*(1-q)/q)/b[k];
		m = 0.1*(b[k]*N*q/(1-q))/c[k] + m * .9;
		N = Nnew*0.1 + N * 0.9;
	    }
	}
    }
}
