def expectation_of_phi(v,DM,sigma): # STEP1: forward UTPS through dFdp V = zeros((Nv,max(DM,1))) V[Np,0] = 1. (y,W) = adolc.hos_forward(1,v,V,0) y = y.reshape((Nm,Np)) W = W.reshape((Nm,Np,shape(W)[1])) J = zeros((DM+1,1,Nm,Np)) # fill 0th degree of J J[0,0,:,:] = y # fill d'th degree of J for dm in range(1,DM+1): J[dm, 0,:,: ] = W[:,:,dm-1] # STEP2: reverse UTPM through PHI Jtc=Mtc(J[:,:,:,:]) cg.forward([Jtc]) retval = 0. for dm in range(DM+1): retval += unifom_distr_moment(dm,sigma) * Ff.x.TC[dm,0,0,0] return retval
def gradient_and_hessian_of_Phi(x): H = zeros((2,2)) # Hessian g = zeros(2) # gradient V = zeros((2,1)) F = zeros((2,2)) Fdot = zeros((2,2)) D = 1 keep = D+1 for n in range(2): # 1: hos_forward, propagate two directions V[n,0] = 1. (y,W) = adolc.hos_forward(1,x,V,keep) V[n,0] = 0. F[0,:] = y[:2] F[1,:] = y[2:] Fdot[0,:] = W[:2,0] Fdot[1,:] = W[2:,0] # 2: matrix forward cg.forward([Mtc(F,Fdot)]) # 3: matrix reverse Phibar = array([[1.]]) Phibardot = array([[0.]]) cg.reverse([Mtc(Phibar, Phibardot)]) # 4: hov_reverse U = zeros((1,4,2)) U[0,:,0] = cg.independentFunctionList[0].xbar.X.flatten() U[0,:,1] = cg.independentFunctionList[0].xbar.Xdot.flatten() res = adolc.hov_ti_reverse(1,U)[0].copy() g[:] = res[0,:,0] H[n,:] = res[0,:,1] return (g,H)
# 3: reverse evaluation of Phi cg.reverse([Mtc([[1.]], [[0.]])]) Jbar = FJ.xbar.X #print 'Jbar=',Jbar # 4: reverse evaluation of J x = v D = 1 keep = D + 1 V = zeros((Nv, D)) vbar = zeros(Nv) for np in range(Np): V[np, 0] = 1 u = (Jbar.T)[np, :].copy() adolc.hos_forward(1, x, V, keep) Z = adolc.hos_reverse(1, D, u) V[np, 0] = 0 print('Z=', Z) vbar += Z[2, 1] print(vbar) exit() #update v: x_k+1 = v_k - g v[2:] -= vbar[2:] print('number of iterations =', count) print('v_opt =', v) print('v0=', v0) # plot Phi # -------- def dFdp(p, q, ts, Sigma, etas):
def gradient_of_E_PHI(v,DM): """ computes the gradient of the expectation of PHI, i.e. grad( E[PHI] ), where E[PHI] is approximated by the method of moments up to moment degree DM. This gradient is then used in the steepest descent optimization below""" # multi indices for the full tensor of order DM-1 to compute d^(DM-1) PHI # the remaining order to compute d^DM PHI is achieved by a reverse sweep later Jq = generate_multi_indices(Nq,DM) NJq = shape(Jq)[0] # since Nq is usually much larger than Np # we want to be able to get one higher order derivative # w.r.t. q by reverse mode # that means we have to evaluate the mixed partial derivatives # d^2 F/dpdq in the forward mode # since UTPS cannot do those partial derivatives straightforward # we need to use interpolation J = zeros((DM+1,1,Nm,Np)) # Taylor series of degree DM has DM+1 taylor coefficients (i.e. count also the zero-derivative) qbar_rays = zeros((NJq,Nq,DM+1)) for nq in range(NJq): # 1: evaluation of J # here, we have to use nested interpolation # we need to compute # d^d F(x + s_1 z_1 + s_2 z_2) | # ---------------------------- | # d z_1 d^(d-1) z_2 |_z=0 # for s_1 = [1,0,0] resp. s_1 = [0,1,0] (one direction for each parameter p) # we use here formula (13) of the paper "Evaluating higher derivative tensors by forward propagation of univariate Taylor series" for np in range(Np): # each column of J for dm in range(DM+1): I = array([1,dm]) K = zeros((dm+1,2),dtype=int) K[:,0] = 1 K[:,1] = list(range(dm+1)) V = zeros((Nv,dm+1)) for k in K: s1 = zeros(Nv) s1[np] = k[0] s2 = zeros(Nv) s2[Np:] = k[1]*Jq[nq,:] V[:,0] = s1+s2 tmp = adolc.hos_forward(1,v,V,0)[1] J[dm,0,:,np] += (-1)**multi_index_abs( I - k) * multi_index_binomial(I,k) * tmp[:,dm] scale_factor = array([1./prod(list(range(1,d+1))) for d in range(DM+1)]) for dm in range(DM+1): J[dm,:,:,:] *= scale_factor[dm] # 2: forward evaluation of Phi Jtc=Mtc(J[:,:,:,:]) cg.forward([Jtc]) # 3: reverse evaluation of Phi Phibar = zeros((DM+1,1,1,1)) Phibar[0,0,0,0]=1. cg.reverse([Mtc(Phibar)]) Jbar = FJ.xbar.TC[:,0,:,:] #print Jbar #print shape(Jbar) ## 4: reverse evaluation of J vbar = zeros(Nv) dJ = zeros((Nq,DM+1)) # taylor coefficients for one direction in q for np in range(Np): # each column of J for dm in range(DM+1): I = array([1,dm]) K = zeros((dm+1,2),dtype=int) K[:,0] = 1 K[:,1] = list(range(dm+1)) V = zeros((Nv,dm+1)) for k in K: s1 = zeros(Nv) s1[np] = k[0] s2 = zeros(Nv) s2[Np:] = k[1]*Jq[nq,:] V[:,0] = s1+s2 keep = dm + 2 adolc.hos_forward(1,v,V,keep)[1] # U is a (Q,M,D) array # Jbar is a (D,M,Np) array U = zeros((1,Nm,keep)) for d in range(dm+1): U[0,:,d] = Jbar[d,:,np] #print 'U=',U Z = adolc.hov_ti_reverse(1,U)[0] #print 'Z=',Z #J[dm,0,:,np] += (-1)**multi_index_abs( I - k) * multi_index_binomial(I,k) * tmp[:,dm] #print shape(Z[0,:,:]) #exit() #print Z[0,:,dm+1] tmp = 1./prod(list(range(1,dm+2))) * (-1)**multi_index_abs( I - k) * multi_index_binomial(I,k) * Z[0,Np:,dm+1] dJ[:,dm] += tmp #vbar += tmp qbar_rays[nq,:,:] = dJ # use interpolation to build all PHI^(dm) 0<= dm <= DM derivative_tensor_list = [] for dm in range(DM+1): derivative_tensor = numpy.zeros([Nq for i in range(dm+1)]) I = generate_multi_indices(Nq,dm) d = sum(I[0,:]) NI = shape(I)[0] NJq = shape(Jq)[0] for ni in range(NI): for nj in range(NJq): derivative_tensor[tuple([0 for i in range(dm+1)])] += gamma(I[ni,:], Jq[nj,:]) * qbar_rays[nj,:,d] derivative_tensor_list.append(derivative_tensor) print(derivative_tensor_list) #print qbar_rays vbar[Np:] = derivative_tensor_list[0] #vbar[Np:] = dJ[:,0] return vbar
# 3: reverse evaluation of Phi cg.reverse([Mtc([[1.]],[[0.]])]) Jbar = FJ.xbar.X #print 'Jbar=',Jbar # 4: reverse evaluation of J x = v D = 1 keep = D+1 V = zeros((Nv,D)) vbar = zeros(Nv) for np in range(Np): V[np,0] = 1 u = (Jbar.T)[np,:].copy() adolc.hos_forward(1,x,V,keep) Z = adolc.hos_reverse(1,D,u) V[np,0] = 0 print 'Z=',Z vbar += Z[2,1] print vbar exit() #update v: x_k+1 = v_k - g v[2:] -= vbar[2:] print 'number of iterations =',count print 'v_opt =',v print 'v0=',v0 # plot Phi # -------- def dFdp(p,q,ts,Sigma, etas):
# time ALGOPY hos_forward x = UTP(numpy.random.rand(D, N)) start_time = time.time() for rep in range(reps): cg.pushforward([x]) end_time = time.time() time_hos_forward_algopy = end_time - start_time # time PYADOLC hos_forward x = numpy.random.rand(N) V = numpy.random.rand(N, D - 1) start_time = time.time() for rep in range(reps): adolc.hos_forward(1, x, V, keep=0) end_time = time.time() time_hos_forward_adolc = end_time - start_time # time PYADOLC.cgraph hos_forward x = numpy.random.rand(N) V = numpy.random.rand(N, 1, D - 1) for rep in range(reps): ap.forward([x], [V]) end_time = time.time() time_hos_forward_cgraph = end_time - start_time # time ALGOPY hov_forward x = UTPM(numpy.random.rand(D, P, N)) start_time = time.time() for rep in range(reps):
def gradient_of_E_PHI(v, DM): """ computes the gradient of the expectation of PHI, i.e. grad( E[PHI] ), where E[PHI] is approximated by the method of moments up to moment degree DM. This gradient is then used in the steepest descent optimization below""" # multi indices for the full tensor of order DM-1 to compute d^(DM-1) PHI # the remaining order to compute d^DM PHI is achieved by a reverse sweep later Jq = generate_multi_indices(Nq, DM) NJq = shape(Jq)[0] # since Nq is usually much larger than Np # we want to be able to get one higher order derivative # w.r.t. q by reverse mode # that means we have to evaluate the mixed partial derivatives # d^2 F/dpdq in the forward mode # since UTPS cannot do those partial derivatives straightforward # we need to use interpolation J = zeros( (DM + 1, 1, Nm, Np) ) # Taylor series of degree DM has DM+1 taylor coefficients (i.e. count also the zero-derivative) qbar_rays = zeros((NJq, Nq, DM + 1)) for nq in range(NJq): # 1: evaluation of J # here, we have to use nested interpolation # we need to compute # d^d F(x + s_1 z_1 + s_2 z_2) | # ---------------------------- | # d z_1 d^(d-1) z_2 |_z=0 # for s_1 = [1,0,0] resp. s_1 = [0,1,0] (one direction for each parameter p) # we use here formula (13) of the paper "Evaluating higher derivative tensors by forward propagation of univariate Taylor series" for np in range(Np): # each column of J for dm in range(DM + 1): I = array([1, dm]) K = zeros((dm + 1, 2), dtype=int) K[:, 0] = 1 K[:, 1] = list(range(dm + 1)) V = zeros((Nv, dm + 1)) for k in K: s1 = zeros(Nv) s1[np] = k[0] s2 = zeros(Nv) s2[Np:] = k[1] * Jq[nq, :] V[:, 0] = s1 + s2 tmp = adolc.hos_forward(1, v, V, 0)[1] J[dm, 0, :, np] += (-1)**multi_index_abs( I - k) * multi_index_binomial(I, k) * tmp[:, dm] scale_factor = array( [1. / prod(list(range(1, d + 1))) for d in range(DM + 1)]) for dm in range(DM + 1): J[dm, :, :, :] *= scale_factor[dm] # 2: forward evaluation of Phi Jtc = Mtc(J[:, :, :, :]) cg.forward([Jtc]) # 3: reverse evaluation of Phi Phibar = zeros((DM + 1, 1, 1, 1)) Phibar[0, 0, 0, 0] = 1. cg.reverse([Mtc(Phibar)]) Jbar = FJ.xbar.TC[:, 0, :, :] #print Jbar #print shape(Jbar) ## 4: reverse evaluation of J vbar = zeros(Nv) dJ = zeros( (Nq, DM + 1)) # taylor coefficients for one direction in q for np in range(Np): # each column of J for dm in range(DM + 1): I = array([1, dm]) K = zeros((dm + 1, 2), dtype=int) K[:, 0] = 1 K[:, 1] = list(range(dm + 1)) V = zeros((Nv, dm + 1)) for k in K: s1 = zeros(Nv) s1[np] = k[0] s2 = zeros(Nv) s2[Np:] = k[1] * Jq[nq, :] V[:, 0] = s1 + s2 keep = dm + 2 adolc.hos_forward(1, v, V, keep)[1] # U is a (Q,M,D) array # Jbar is a (D,M,Np) array U = zeros((1, Nm, keep)) for d in range(dm + 1): U[0, :, d] = Jbar[d, :, np] #print 'U=',U Z = adolc.hov_ti_reverse(1, U)[0] #print 'Z=',Z #J[dm,0,:,np] += (-1)**multi_index_abs( I - k) * multi_index_binomial(I,k) * tmp[:,dm] #print shape(Z[0,:,:]) #exit() #print Z[0,:,dm+1] tmp = 1. / prod(list(range(1, dm + 2))) * ( -1)**multi_index_abs(I - k) * multi_index_binomial( I, k) * Z[0, Np:, dm + 1] dJ[:, dm] += tmp #vbar += tmp qbar_rays[nq, :, :] = dJ # use interpolation to build all PHI^(dm) 0<= dm <= DM derivative_tensor_list = [] for dm in range(DM + 1): derivative_tensor = numpy.zeros([Nq for i in range(dm + 1)]) I = generate_multi_indices(Nq, dm) d = sum(I[0, :]) NI = shape(I)[0] NJq = shape(Jq)[0] for ni in range(NI): for nj in range(NJq): derivative_tensor[tuple([ 0 for i in range(dm + 1) ])] += gamma(I[ni, :], Jq[nj, :]) * qbar_rays[nj, :, d] derivative_tensor_list.append(derivative_tensor) print(derivative_tensor_list) #print qbar_rays vbar[Np:] = derivative_tensor_list[0] #vbar[Np:] = dJ[:,0] return vbar