/* -*- mode: C++ -*- */ ////////////////////////////////////////////////////////////////////////////// // FILE : BaseC2.LinComb.tol // PURPOSE: Defines class @BaseC2.LinComb ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// Text _.autodoc.member.BaseC2.LinComb = "Defines a new base B2 of " "order K2 as a linear combination B2=B1*V of functions of a previous base " "B1 of order K1>=K2. The matrix of change V must have rank K2 to ensure " "linear independence."; Class @BaseC2.LinComb : @BaseC2.Cache ////////////////////////////////////////////////////////////////////////////// { @BaseC2 _.base; VMatrix _.V; VMatrix _.Vi; //////////////////////////////////////////////////////////////////////////// Static Text _.autodoc.member.New = "Creates an instance B2 of " "@BaseC2.LinComb as B2 = B1*V"; Static @BaseC2.LinComb New(@BaseC2 B1, VMatrix V, VMatrix Vi) //////////////////////////////////////////////////////////////////////////// { Real n = B1::_.n; @BaseC2.LinComb aux = [[ Real _.n = B1::_.n; Real _.K = VColumns(V); @BaseC2 _.base = base; VMatrix _.V = V; VMatrix _.Vi = Vi ]]}; //////////////////////////////////////////////////////////////////////////// Static Text _.autodoc.member.Compact.Ratio = "Creates an instance of " "@BaseC2.LinComb that is close to be orthonormal and has at least " "the specified ratio of information of original base"; Static @BaseC2.LinComb Compact.Ratio( @BaseC2 base, Real informationRatio) //////////////////////////////////////////////////////////////////////////// { Real K1 = base::_.K; VMatrix u = Rand(K1*10, K1, -1, 1); VMatrix Pu = Group("ConcatColumns", For(1, K1, VMatrix(Real k) { base::function.v(k,u) })); Set Pu.svd = SVD(VMat2Mat(Pu)); Matrix Pu.eigenvalue = Tra(SubDiag(Pu.svd[2],0)); Matrix Pu.eigenvalueCum = { Matrix aux = DifEq(1/(1-B),Pu.eigenvalue); aux*(1/MatSum(Pu.eigenvalue)) }; Matrix ratio = Rand(K1,1,informationRatio,informationRatio); Real K = MatSum(LE(Pu.eigenvalueCum,ratio)); Set range.K = Range(1,K,1); VMatrix V = Mat2VMat(SubCol(Pu.svd[3],range.K)); VMatrix D = Eye(K,K,0,RPow(Mat2VMat(SubRow(Pu.eigenvalue,range.K)),+1)); VMatrix Di = Eye(K,K,0,RPow(Mat2VMat(SubRow(Pu.eigenvalue,range.K)),-1)); VMatrix W = V*Di; VMatrix Wi = D*Tra(V); New(base, W, Wi) }; //////////////////////////////////////////////////////////////////////////// Static Text _.autodoc.member.Compact.K = "Creates an instance of " "@BaseC2.LinComb that is close to be orthonormal and has exactly K " "elements"; Static @BaseC2.LinComb Compact.K( @BaseC2 base, Real K) //////////////////////////////////////////////////////////////////////////// { Set range.K = Range(1,K,1); Real K1 = base::_.K; VMatrix u = Rand(K1*10, K1, -1, 1); VMatrix Pu = Group("ConcatColumns", For(1, K1, VMatrix(Real k) { base::function.v(k,u) })); Set Pu.svd = SVD(VMat2Mat(Pu)); Matrix Pu.eigenvalue = Tra(SubDiag(Pu.svd[2],0)); VMatrix V = Mat2VMat(SubCol(Pu.svd[3],range.K)); VMatrix D = Eye(K,K,0,RPow(Mat2VMat(SubRow(Pu.eigenvalue,range.K)),+1)); VMatrix Di = Eye(K,K,0,RPow(Mat2VMat(SubRow(Pu.eigenvalue,range.K)),-1)); VMatrix W = V*Di; VMatrix Wi = D*Tra(V); New(base, W, Wi) }; //////////////////////////////////////////////////////////////////////////// Real _build.cache(VMatrix X, Real order) //////////////////////////////////////////////////////////////////////////// { Real _.base::upgrade.cache(X,order); VMatrix If(order>=0, { _.function := _.base::function.m(X)*_.V }); Set If(order>=1, { _.partial.derivative.1 := For(1, _.n, VMatrix(Real i) { _.base::partial.derivative.1.m(X,i)*_.V }) }); Set If(order>=2, { _.partial.derivative.2 := For(1, _.n, Set(Real i) { For(1, i, VMatrix(Real j) { _.base::partial.derivative.2.m(X,i,j)*_.V }) }) }); True } };