def MixedEstimator(abg_init, binnedTrain, dp_tol = 1e-2):
    phis = binnedTrain.bins.keys();
    theta = binnedTrain.theta

    dp = dp_tol*2.0;
    abg = abg_init
    
    while dp > dp_tol:
        Tf = binnedTrain.getTf()
   
        xmin = FPMultiPhiSolver.calculate_xmin(Tf, abg)
        dx = FPMultiPhiSolver.calculate_dx(abg, xmin)
        dt = FPMultiPhiSolver.calculate_dt(dx, abg, xmin, factor = 8.)

        S = FPMultiPhiSolver(theta, phis,
                             dx, dt, Tf, xmin)

        Fs = S.solve(abg, visualize=False)
        Ss = S.transformSurvivorData(binnedTrain)
        Ls = Fs[:,:,-1] - Ss
        Nus = S.solveAdjoint(abg, Ls)
    
        dGdp = S.estimateParameterGradient(abg, Fs, Nus)

        from numpy.linalg.linalg import norm
        
        dG_normalized = dGdp/ norm(dGdp) 
        
        dp = FortetLineEstimator(binnedTrain, abg, dG_normalized, dp_tol)
        
        abg = abg - dp*dG_normalized

        print 'dG = ', dG_normalized
        print 'dp = ', dp
        print 'abg = (%.3g, %.3g, %.3g)'%(abg[0],abg[1],abg[2])
        print '-'

    return abg
def AdjointEstimator():
    N_phi = 20;
    print 'N_phi = ', N_phi
    
    phis =  linspace(1/(2.*N_phi), 1. - 1/ (2.*N_phi), N_phi)
    
    file_name = 'sinusoidal_spike_train_N=1000_crit_1'
    print file_name
    
    binnedTrain = BinnedSpikeTrain.initFromFile(file_name, phis)
    
    phi_omit = None
    binnedTrain.pruneBins(phi_omit, N_thresh = 100, T_thresh = 10.0)
    print 'N_bins = ', len(binnedTrain.bins.keys())
    
    Tf = binnedTrain.getTf()
    print 'Tf = ', Tf
        
    phis = binnedTrain.bins.keys();
    theta = binnedTrain.theta
    
    
    ps = binnedTrain._Train._params
    abg_true = array((ps._alpha, ps._beta, ps._gamma))
    print 'abg_true = ', abg_true
    
    abg = abg_true
    xmin = FPMultiPhiSolver.calculate_xmin(Tf, abg)
    dx = FPMultiPhiSolver.calculate_dx(abg, xmin)
    dt = FPMultiPhiSolver.calculate_dt(dx, abg, xmin, factor = 8.)
    print 'xmin, dx, dt = ', xmin, dx, dt
    S = FPMultiPhiSolver(theta, phis,
                     dx, dt, Tf, xmin)

    abg_init = initialize5(binnedTrain)
    print 'abg_init = ', abg_init
        
#    start = time.clock()
#    abg_est = TNCEstimator(S, binnedTrain, abg_init)
#    print 'Est. time = ', time.clock() - start
#    print 'abg_est = ', abg_est
    
#    start = time.clock()
#    abg_est = NMEstimator(S, binnedTrain, abg_init)
#    print 'Est. time = ', time.clock() - start
#    print 'abg_est = ', abg_est
#
#    start = time.clock()
#    abg_est = COBYLAEstimator(S, binnedTrain, abg_init)
#    print 'Est. time = ', time.clock() - start
#    print 'abg_est = ', abg_est

#    start = time.clock()
#    abg_est = CGEstimator(S, binnedTrain, abg_init)
#    print 'Est. time = ', time.clock() - start
#    print 'abg_est = ', abg_est

    start = time.clock()
    abg_est = BFGSEstimator(S, binnedTrain, abg_init)
    print 'Est. time = ', time.clock() - start
    print 'abg_est = ', abg_est