def kbb(T, k, Phi_mat, b, J): N = len(k) D = len(k[0]) I2 = [[[] for j in range(D)] for i in range(N)] I3 = np.zeros((N, D, len(b)), float) Beta = Phi_mat.dot(b) for i in range(N): for j in range(D): Beta_ij = Beta[(i * (J + 1)) : (i * (J + 1) + J + 1), j] # on calcule pour k_ij, la matrice des k(s,t) pour s,t dans la grille de [0,Ti] grid = T[i] * 1.0 * np.arange(J + 1) / J vecarg = cg.expandnp([grid, grid]) k_ij = np.apply_along_axis(k[i][j], 0, *(vecarg.T)).reshape(J + 1, J + 1) k_ij[0, :] = k_ij[0, :] * 0.5 k_ij[J, :] = k_ij[J, :] * 0.5 k_ij[:, 0] = k_ij[:, 0] * 0.5 k_ij[:, J] = k_ij[:, J] * 0.5 # On calcule alors l'intégrale Phi(s,Ti) k(s,t) Beta(t,Ti) sur [0,Ti]² I3[i, j, :] = ( Beta_ij.dot(k_ij).dot(Phi_mat[(i * (J + 1)) : (i * (J + 1) + J + 1), :]) * (T[i] ** 2) / (J ** 2) ) # Ainsi que l'intégrale k(s,t) Beta(s,Ti) Beta(t,Ti) sur [0,Ti]² # I2[i][j]= Beta_ij.dot(k_ij).dot(Beta_ij) * 1.*(T[i]**2)/(J**2) I2[i][j] = I3[i, j, :].dot(b) return (I2, I3)
def PhiK(L, T, k, Phi_mat, J): N = len(L) D = len(L[0]) Ints = [[[] for j in range(D)] for i in range(N)] for i in range(N): for j in range(D): Phi_mat_i = Phi_mat[(i * (J + 1)) : (i * (J + 1) + J + 1), :].T t = L[i][j] grid = T[i] * 1.0 * np.arange(J + 1) / J vecarg = cg.expandnp([t, grid]) K_ij = np.apply_along_axis(k[i][j], 0, *(vecarg.T)).reshape(J + 1, len(t)) K_ij[0, :] = K_ij[0, :] * 0.5 K_ij[J, :] = K_ij[J, :] * 0.5 Ints[i][j] = (T[i] / J) * Phi_mat_i.dot(K_ij) return Ints
def ISE(numbeta, Beta_fonc_est, b_learned, T, nb=40, plot_beta=False, resolution=100): ise = 0.0 Tmax = np.max(T) Tmin = np.min(T) Tgrid = np.linspace(Tmin, Tmax, nb, retstep=True) step = Tgrid[1] Tgrid = Tgrid[0] grille = np.vstack((Tgrid, np.arange(nb))) count = 0 for T_, i in grille.T: for t_ in np.arange(0.01, T_, step, float): count += 1 true_b = cg.beta_fonc(t_, T_, numbeta) est_b = Beta_fonc_est(*([t_, T_] + list(b_learned[:, 0]))) ise = ise + (true_b - est_b) ** 2 ise = ise / count print("ISE : " + str(ise)) if plot_beta: x = np.linspace(0.1, np.max(T), num=resolution) y = np.linspace(0.1, np.max(T), num=resolution) arr = [x, y] Grid = cg.expandnp(arr) x = Grid[:, 0] y = Grid[:, 1] arrV = np.zeros(resolution ** 2, float) n = 0 for i in range(resolution): for j in range(resolution): if j <= i: arrV[n] = Beta_fonc_est[0](x[n], y[n]) n += 1 Xfig = x.reshape((resolution, resolution)) Yfig = y.reshape((resolution, resolution)) Zfig = arrV.reshape((resolution, resolution)) fig = plt.figure().add_subplot(111) plt.imshow( Zfig, vmin=Zfig.min(), vmax=Zfig.max(), origin="lower", extent=[Yfig.min(), Yfig.max(), Xfig.min(), Xfig.max()], ) plt.colorbar() return ise
def construct_beta(Kbeta): # symbole associé au petit t (c'est à dire l'instant dans la période de suivi) t = sy.Symbol("t") # smbole associé au grand T (c'est à dire la durée de suivie) s = sy.Symbol("s") syPhi = sy.ones(Kbeta, 1) syb = sy.ones(1, Kbeta) b = [[] for k in range(Kbeta)] v = [np.arange(np.sqrt(Kbeta)), np.arange(np.sqrt(Kbeta))] expo = cg.expandnp(v) for x in range(len(expo[:, 0])): syPhi[x] = (t ** expo[x, 0]) * (s ** expo[x, 1]) syb[x] = sy.Symbol("b" + str(x)) b[x] = sy.Symbol("b" + str(x)) syBeta = syb * syPhi syBeta = syBeta[0, 0] arg = [t, s] + b Beta_fonc_est = sy.lambdify(tuple(arg), syBeta, "numpy") return Beta_fonc_est
def Comp_Psi(L, k_fonc, Theta, Gamma, i_subset=None): N = len(L) D = len(L[0]) Psi = [[[] for j in range(D)] for i in range(N)] Det = np.ones((N, D), float) if i_subset is None: veci = range(N) else: veci = i_subset for i in veci: for j in range(D): t_ij = L[i][j] m_ij = len(t_ij) vec = cg.expandnp([t_ij, t_ij]) args = list(vec.T) + list(Theta[i, j, :]) K = np.apply_along_axis(k_fonc, 0, *args).reshape((m_ij, m_ij)) Psi[i][j] = sc.linalg.inv(K + np.eye(m_ij) * Gamma[i, j] ** 2) Det[i, j] = sc.linalg.det(K + np.eye(m_ij) * Gamma[i, j] ** 2, check_finite=False) if Det[i, j] == 0.0: Det[i, j] = 0.01 return (Psi, Det)
def Pre_Comp_YX(L, T, Xdata, Y, Kbeta, J): t = sy.Symbol("t") s = sy.Symbol("s") # Récupération des variables et paramètres N = len(L) D = len(L[0]) # ----------------- Construction de la base fonctionnelle syPhi = sy.ones(Kbeta ** 2, 1) syb = sy.ones(1, Kbeta ** 2) v = [np.arange(Kbeta), np.arange(Kbeta)] expo = cg.expandnp(v) Phi_fonc = [[] for j in range(Kbeta ** 2)] for x in range(len(expo[:, 0])): syPhi[x] = (t ** expo[x, 0]) * (s ** expo[x, 1]) Phi_fonc[x] = sy.lambdify((t, s), syPhi[x], "numpy") syb[x] = sy.Symbol("b" + str(x)) syBeta = syb * syPhi Phi_mat = Comp_Phi(Phi_fonc, T, J) I_pen = J22_fast(syPhi, np.max(T), 50)[3] # ----------------- Construction des noyaux et leurs dérivées # Construction de la forme du noyau el1 = sy.Symbol("el1") per1 = sy.Symbol("per1") sig1 = sy.Symbol("sig1") args1 = [el1, per1, sig1] el2 = sy.Symbol("el2") sig2 = sy.Symbol("sig2") args2 = [el2, sig2] syk = cg.sy_Periodic((s, t), *args1) + cg.sy_RBF((s, t), *args2) args = [t, s] + args1 + args2 # Dérivation et construction des fonctions vectorielles associées k_fonc = sy.lambdify(tuple(args), syk, "numpy") n_par = len(args) - 2 k_der = [[] for i in range(n_par)] for i in range(n_par): func = syk.diff(args[i + 2]) k_der[i] = sy.lambdify(tuple(args), func, "numpy") return (Phi_mat, k_fonc, k_der, I_pen)
def Pre_Comp(L, T, Xdata, Y, Kbeta, J): t = sy.Symbol("t") s = sy.Symbol("s") # Récupération des variables et paramètres N = len(L) D = len(L[0]) # ----------------- INFERENCES DES PARAMS LONGITUDINAUX # print("[ ] Inférence des paramètres fonctionnels") model = pyGPs.GPR() kern1 = pyGPs.cov.RBF(log_ell=0.0, log_sigma=0.0) kern2 = pyGPs.cov.Periodic(log_ell=0.0, log_p=0.0, log_sigma=0.0) kern = pyGPs.cov.SumOfKernel(kern1, kern2) m = pyGPs.mean.Const() model.setPrior(mean=m, kernel=kern) model.setNoise(log_sigma=-2.30258) Theta = np.zeros((N, D, len(model.covfunc.hyp)), float) Gamma = np.zeros((N, D), float) moy_est = np.zeros((N, D), float) for i in range(N): for j in range(D): y = np.asarray(Xdata[i][j]) x = np.asarray(L[i][j]) try: model.optimize(x, y) moy_est[i, j] = model.meanfunc.hyp[0] Theta[i, j, :] = np.array(np.exp(model.covfunc.hyp)) Gamma[i, j] = np.exp(model.likfunc.hyp) except: # Problème d'inférence, paramètres défaut attribués moy_est[i, j] = np.mean(x) Theta[i, j, :] = np.array([0.05, np.std(x) ** 2, 0.05, 1.0, 0.0]) Gamma[i, j] = 1.0 pass # ----------------- RECUPERATION DES QUANTITES D'INTERET # print("[- ] Récupération des quantités d'intérêt") # Construction de la forme du noyau el1 = sy.Symbol("el1") sig1 = sy.Symbol("sig1") args1 = [el1, sig1] el2 = sy.Symbol("el2") per2 = sy.Symbol("per2") sig2 = sy.Symbol("sig2") args2 = [el2, per2, sig2] syk = cg.sy_RBF((s, t), *args1) + cg.sy_Periodic((s, t), *args2) args = [t, s] + args1 + args2 k_fonc = sy.lambdify(tuple(args), syk, "numpy") Psi = Comp_Psi(L, k_fonc, Theta, Gamma)[0] # ----------------- Construction de la base fonctionnelle # print("[-- ] Calcul des quantités d'intérêt") syPhi = sy.ones(Kbeta ** 2, 1) syb = sy.ones(1, Kbeta ** 2) v = [np.arange(Kbeta), np.arange(Kbeta)] expo = cg.expandnp(v) Phi_fonc = [[] for j in range(Kbeta ** 2)] for x in range(len(expo[:, 0])): syPhi[x] = (t ** expo[x, 0]) * (s ** expo[x, 1]) Phi_fonc[x] = sy.lambdify((t, s), syPhi[x], "numpy") syb[x] = sy.Symbol("b" + str(x)) syBeta = syb * syPhi I_pen = J22_fast(syPhi, np.max(T), 50)[3] # ----------------- Construction de l et V Un = np.ones(J + 1, float) Un[0] = 0.5 Un[J] = 0.5 Phi_mat = Comp_Phi(Phi_fonc, T, J) l = np.zeros((N, D * Kbeta ** 2), float) V = [[] for i in range(N)] vl = [[] for j in range(D)] for i in range(N): Phi_i = Phi_mat[(i * (J + 1)) : (i * (J + 1) + J + 1), :].T for j in range(D): Xij = Xdata[i][j] # Moyenne de F_ij estimée en amont Etaij = moy_est[i, j] t = L[i][j] grid = T[i] * 1.0 * np.arange(J + 1) / J vec = cg.expandnp([t, grid]) args = list(vec.T) + list(Theta[i, j, :]) K_ij = np.apply_along_axis(k_fonc, 0, *args).reshape(J + 1, len(t)) K_ij[0, :] = K_ij[0, :] * 0.5 K_ij[J, :] = K_ij[J, :] * 0.5 KPsi = K_ij.dot(Psi[i][j]) l[i, (j * Kbeta ** 2) : ((j + 1) * Kbeta ** 2)] = ( Phi_i.dot(KPsi.dot(Xij - Etaij) + Etaij * Un).reshape(-1) / J ) # on calcule pour k_ij, la matrice des k(s,t) pour s,t dans la grille de [0,Ti] vec = cg.expandnp([grid, grid]) args = list(vec.T) + list(Theta[i, j, :]) k_ij = np.apply_along_axis(k_fonc, 0, *args).reshape(J + 1, J + 1) k_ij[0, :] = k_ij[0, :] * 0.5 k_ij[J, :] = k_ij[J, :] * 0.5 k_ij[:, 0] = k_ij[:, 0] * 0.5 k_ij[:, J] = k_ij[:, J] * 0.5 Cov_FF = k_ij - KPsi.dot(K_ij.T) vl[j] = Phi_i.dot(Cov_FF).dot(Phi_i.T) / J ** 2 V[i] = sc.sparse.block_diag(tuple(vl)) # On ajoute une matrice diagonale pour rendre V[i] définie positive, mais on fait en sorte que ses valeurs propres soient petites par rapport à celles de V[i] pour ne pas trop affecter la vraisemblances sur l'espace autour de 0. # V[i]=V[i]+np.eye(D*Kbeta**2)*0.01*np.trace(V[i].toarray())/(D*Kbeta**2) return (l, V, I_pen)
def L_YX( P, Z, L, T, Xdata, Y, Phi_mat, k_fonc, k_der, Stochastic=False, Gradient=True, I_pen=None, Lambda=None, i_liste=None ): # Récupération des variables et paramètres N = len(L) D = len(L[0]) p = Z.shape[1] Kbeta = Phi_mat.shape[1] # Kbeta est ici la taille de la base complète J = int(-1 + Phi_mat.shape[0] / N) Alpha = P[0:p] b = P[p : (D * Kbeta + p)].reshape((Kbeta, D)) Sigma2 = 1.0 Eta = P[(D * Kbeta + p) : (N * D + D * Kbeta + p)].reshape((N, D)) # Sous forme d'array de taille (N,D) Gamma = P[(N * D + D * Kbeta + p) : (2 * N * D + D * Kbeta + p)].reshape( (N, D) ) # Sous forme d'array de taille (N,D) n_par = len(k_der) Theta = P[(2 * N * D + D * Kbeta + p) : ((2 + n_par) * N * D + D * Kbeta + p)].reshape( (N, D, n_par) ) # Sous forme d'array de taille (N,D,n_par) # --------------------------Options if Stochastic: # Si l'option stochastique est activée, on ne tient pas compte de la liste de i soumise I = np.random.randint(0, N) i_liste = [I] # Calcul des Psi, on ne calcule que ceux dont l'indice doit être évalué if i_liste is not None: (Psi, Det) = Comp_Psi(L, k_fonc, Theta, Gamma, i_subset=i_liste) seq_i = i_liste isit = np.array([(k in i_liste) for k in range(N)]) else: (Psi, Det) = Comp_Psi(L, k_fonc, Theta, Gamma) seq_i = range(N) isit = np.ones(N, float) # Vecteurs contenant respectivement les espérances de Yi | Xi notées Ei et leurs variances Vi (EY, VY) = (np.zeros(N, float), np.ones(N, float)) Beta = Phi_mat.dot(b) # Matrices contenant les Int_[0,Ti] E(F_ij(s)|X_ij)Beta_j(s,Ti) ds et les les Int_[0,Ti]² Cov(F_ij(s),F_ij(t)|X_ij) Beta_j(s,Ti)Beta_j(t,Ti) dsdt (EY_Int, VY_Int) = (np.zeros((N, D), float), np.ones((N, D), float)) # Matrice des dEi/dbj et dVi/dbj (dEdb, dVdb) = (np.zeros((N, D, Kbeta), float), np.zeros((N, D, Kbeta), float)) # Gradient (dEdEta, dLXdEta) = (np.zeros((N, D), float), np.zeros((N, D), float)) (dEdGamma, dVdGamma, dLXdGamma) = (np.zeros((N, D), float), np.zeros((N, D), float), np.zeros((N, D), float)) (dEdTheta, dVdTheta, dLXdTheta) = ( np.zeros((N, D, n_par), float), np.zeros((N, D, n_par), float), np.zeros((N, D, n_par), float), ) Dkij = np.zeros((n_par, J + 1, J + 1), float) XPsiX = np.zeros((N, D), float) # On prépare la matrice de rankisation Id = np.eye(Kbeta) add_diag = np.zeros(D, float) for j in range(D): add_diag[j] = b[:, j].dot(Id).dot(b[:, j]) # Calcul des quantités pour dL/dEtaij Grad = np.zeros(len(P), float) Un = np.ones(J + 1, float) Un[0] = 0.5 Un[J] = 0.5 for i in seq_i: grid = T[i] * 1.0 * np.arange(J + 1) / J vecarg = cg.expandnp([grid, grid]) Beta_i = Beta[(i * (J + 1)) : (i * (J + 1) + J + 1), :] Phi_mat_i = Phi_mat[(i * (J + 1)) : (i * (J + 1) + J + 1), :].T for j in range(D): Xij = Xdata[i][j] t_ij = L[i][j] m_ij = len(t_ij) # Moyenne de F_ij Etaij = Eta[i, j] # Evaluation du noyau k_ij sur la grille k_ij = np.apply_along_axis(k_fonc, 0, *(list(vecarg.T) + list(Theta[i, j, :]))).reshape((J + 1, J + 1)) k_ij[0, :] = k_ij[0, :] * 0.5 k_ij[J, :] = k_ij[J, :] * 0.5 k_ij[:, 0] = k_ij[:, 0] * 0.5 k_ij[:, J] = k_ij[:, J] * 0.5 vecarg2 = cg.expandnp([t_ij, grid]) K_ij = np.apply_along_axis(k_fonc, 0, *(list(vecarg2.T) + list(Theta[i, j, :]))).reshape(J + 1, m_ij) K_ij[0, :] = K_ij[0, :] * 0.5 K_ij[J, :] = K_ij[J, :] * 0.5 KPsi = K_ij.dot(Psi[i][j]) PsiX = Psi[i][j].dot(Xij - Etaij) # Calcul de la composante de Ei selon la jème VFT Phi_EspFij = Phi_mat_i.dot(Etaij * Un + KPsi.dot(Xij - Etaij)) / J EY_Int[i, j] = b[:, j].dot(Phi_EspFij) # Calcul de la composante de Vi selon la jème VFT V_i = Phi_mat_i.dot(k_ij - KPsi.dot(K_ij.T)).dot(Phi_mat_i.T) Phi_CovFij = V_i.dot(b[:, j]) / (J ** 2) # Ajout d'une matrice diagonale faible pour rankiser V^i_j extra_butter = add_diag[j] * 0.01 * np.trace(V_i) / Kbeta VY_Int[i, j] = b[:, j].dot(Phi_CovFij) # + extra_butter XPsiX[i, j] = (Xij - Etaij).dot(PsiX) if Gradient: # Calcul de l'intégrale de dEi/dbj dEdb[i, j, :] = Phi_EspFij # Calcul de l'intégrale de dEi/dbj dVdb[i, j, :] = 2 * Phi_CovFij # Evaluation de dérivées du noyau sur la grille vecarg3 = cg.expandnp([t_ij, t_ij]) DK_ij = np.zeros((n_par, J + 1, m_ij), float) DKt_ij = np.zeros((n_par, m_ij, m_ij), float) for npa in range(n_par): Dkij[npa, :, :] = np.apply_along_axis( k_der[npa], 0, *(list(vecarg.T) + list(Theta[i, j, :])) ).reshape((J + 1, J + 1)) DK_ij[npa, :, :] = np.apply_along_axis( k_der[npa], 0, *(list(vecarg2.T) + list(Theta[i, j, :])) ).reshape(J + 1, m_ij) DKt_ij[npa, :, :] = np.apply_along_axis( k_der[npa], 0, *(list(vecarg3.T) + list(Theta[i, j, :])) ).reshape(m_ij, m_ij) Dkij[:, 0, :] = Dkij[:, 0, :] * 0.5 Dkij[:, J, :] = Dkij[:, J, :] * 0.5 Dkij[:, :, 0] = Dkij[:, :, 0] * 0.5 Dkij[:, :, J] = Dkij[:, :, J] * 0.5 DK_ij[:, 0, :] = DK_ij[:, 0, :] * 0.5 DK_ij[:, J, :] = DK_ij[:, J, :] * 0.5 # Calcul des quantités pour dL/dThetaij BetaDK_ij = Beta_i[:, j].dot(DK_ij) BetaKPsiDKt_ij = Beta_i[:, j].dot(np.transpose(KPsi.dot(DKt_ij), (1, 0, 2))) dEdTheta[i, j, :] = (BetaDK_ij + BetaKPsiDKt_ij).dot(PsiX) / J dVdTheta[i, j, :] = (Beta_i[:, j].dot(Dkij) + (-2 * BetaDK_ij + BetaKPsiDKt_ij).dot(KPsi.T)).dot( Beta_i[:, j] ) / J ** 2 dLXdTheta[i, j, :] = -PsiX.T.dot(DKt_ij).dot(PsiX) + np.trace(DKt_ij.dot(Psi[i][j]), axis1=1, axis2=2) # Calcul des quantités pour dL/dGammaij dEdGamma[i, j] = Beta_i[:, j].dot(KPsi.dot(PsiX)) / J dVdGamma[i, j] = Beta_i[:, j].dot(k_ij - KPsi.dot(KPsi.T)).dot(Beta_i[:, j]) / J ** 2 dLXdGamma[i, j] = -(PsiX.T).dot(PsiX) + np.trace(Psi[i][j]) # Calcul des quantités pour dL/dEtaij dEdEta[i, j] = Beta_i[:, j].dot(Un + KPsi.dot(np.ones(m_ij))) / J dLXdEta[i, j] = -2 * PsiX.T.dot(np.ones(m_ij)) + 2 * np.ones(m_ij).dot(Psi[i][j]).dot(np.ones(m_ij)) # On calcule l'espérance de Y sachant X avec l'espérance de Y et le terme de conditionnement gaussien EY[i] = Z[i].dot(Alpha) + np.sum(EY_Int[i, :]) # On calcule la variance de Y sachant X avec le terme de variance issu des VFT X^i_j et de l'erreur résiduelle VY[i] = np.sum(VY_Int[i, :]) + Sigma2 # Calcul de la vraisemblance LYX = np.sum(isit * ((Y - EY) ** 2 / VY + np.log(VY))) + np.sum(XPsiX.reshape(-1)) + np.sum(np.log(Det.reshape(-1))) if Lambda is not None: (Pen, dPen) = Comp_Pen(I_pen, b.reshape(-1), D, Kbeta) LYX += Lambda * Pen if Gradient: # Calcul du Gradient a = isit * (-2 * (Y - EY) / VY) b = isit * ((np.ones(N, float) - (Y - EY) ** 2 / VY) / VY) # Par rapport à Alpha Grad[0:p] = np.ones(N, float).dot(a.repeat(p, axis=0).reshape((N, p)) * Z).reshape(-1) # Par rapport à b_j pour tout j de 1 à D dL_YlXdb = np.zeros((Kbeta, D)) A = a.repeat(Kbeta, axis=0).reshape((N, Kbeta)) B = b.repeat(Kbeta, axis=0).reshape((N, Kbeta)) for j in range(D): Grad[(p + j * Kbeta) : (p + (j + 1) * Kbeta)] = np.ones(N, float).dot(A * dEdb[:, j, :] + B * dVdb[:, j, :]) if Lambda is not None: Grad[p : (p + D * Kbeta)] += Lambda * dPen # Par rapport à Eta, Theta et Gamma # Eta A = (cg.expandnp([a, np.ones(D)]).T)[0].reshape(D, N).T B = (cg.expandnp([b, np.ones(D)]).T)[0].reshape(D, N).T Grad[(D * Kbeta + p) : (N * D + D * Kbeta + p)] = (A * dEdEta + dLXdEta).reshape(-1) # Gamma Grad[(D * Kbeta + p + N * D) : (D * Kbeta + p + 2 * N * D)] = (A * dEdGamma + B * dVdGamma + dLXdGamma).reshape( -1 ) # Theta A = np.transpose((cg.expandnp([a, np.ones(n_par * D)]).T)[0].reshape(n_par, D, N), (2, 1, 0)) B = np.transpose((cg.expandnp([b, np.ones(n_par * D)]).T)[0].reshape(n_par, D, N), (2, 1, 0)) Grad[(p + D * Kbeta + 2 * N * D) : ((2 + n_par) * N * D + D * Kbeta + p)] = ( A * dEdTheta + B * dVdTheta + dLXdTheta ).reshape(-1) # On renvoie le critère ainsi que le gradient if Stochastic: return (LYX, Grad, I) else: return (LYX, Grad, None) else: if Stochastic: return (LYX, None, I) else: return (LYX, None, None)
def J22_fast(syPhi, Tmax, J): # taille de la base fonctionnelle Kbeta = len(syPhi) # symbole associé au petit t (c'est à dire l'instant dans la période de suivi) t = sy.Symbol("t") # smbole associé au grand T (c'est à dire la durée de suivie) s = sy.Symbol("s") deb = time.clock() Phi = sy.ones(Kbeta, 1) for i in range(Kbeta): Phi[i] = syPhi[i] # dérivation de la base fonctionnelle (Phi_dsds, Phi_dsdt, Phi_dtdt) = (Phi.diff(s, s), Phi.diff(s, t), Phi.diff(t, t)) (Phi_mat_dsds, Phi_mat_dsdt, Phi_mat_dtdt) = ( np.zeros(((J + 1) ** 2, Kbeta), float), np.zeros(((J + 1) ** 2, Kbeta), float), np.zeros(((J + 1) ** 2, Kbeta), float), ) # Grille d'intégration carré (on retire le triangle supérieur plus loin) t_arg = sc.linspace(0, Tmax, J + 1) s_arg = t_arg args = cg.expandnp([t_arg, s_arg]).T for i in range(Kbeta): func = sy.lambdify((t, s), Phi_dsds[i], "numpy") Phi_mat_dsds[:, i] = np.apply_along_axis(func, 0, *args) func = sy.lambdify((t, s), Phi_dsdt[i], "numpy") Phi_mat_dsdt[:, i] = np.apply_along_axis(func, 0, *args) func = sy.lambdify((t, s), Phi_dtdt[i], "numpy") Phi_mat_dtdt[:, i] = np.apply_along_axis(func, 0, *args) (Is, Ic, It) = (np.zeros((Kbeta, Kbeta), float), np.zeros((Kbeta, Kbeta), float), np.zeros((Kbeta, Kbeta), float)) Un = np.ones(J + 1, float) # matrice triangulaire inférieure d'intégration a = cg.expandnp([np.arange(J + 1), np.arange(J + 1)]) triang = np.asarray(a[:, 0] <= a[:, 1], float).reshape((J + 1, J + 1)) # Calcul des intégrales for i in range(Kbeta): for j in range(Kbeta): if i <= j: Is[i, j] = ( Un.dot( Phi_mat_dsds[:, j].reshape((J + 1, J + 1)) * Phi_mat_dsds[:, i].reshape((J + 1, J + 1)) * triang ).dot(Un) * (Tmax ** 2) / (J * (J + 1)) ) Ic[i, j] = ( Un.dot( Phi_mat_dsdt[:, j].reshape((J + 1, J + 1)) * Phi_mat_dsdt[:, i].reshape((J + 1, J + 1)) * triang ).dot(Un) * (Tmax ** 2) / (J * (J + 1)) ) It[i, j] = ( Un.dot( Phi_mat_dtdt[:, j].reshape((J + 1, J + 1)) * Phi_mat_dtdt[:, i].reshape((J + 1, J + 1)) * triang ).dot(Un) * (Tmax ** 2) / (J * (J + 1)) ) else: (Is[i, j], Ic[i, j], It[i, j]) = (Is[j, i], Ic[j, i], It[j, i]) I_pen = Is + It + 2 * Ic I_pen = I_pen + np.eye(Kbeta) * 0.001 * np.trace(I_pen) / Kbeta return (Is, Ic, It, I_pen)