T operator()(RawArray<const T,2> x) const { // Temporary arrays and views GEODE_ASSERT(x.sizes()==vec(n+3,d)); // Collect quadrature points Array<T,2> tq(n,quads,uninit); Array<T,3> xq(n,quads,d,uninit); Array<T,3> vq(n,quads,d,uninit); for (int i=0;i<n;i++) { T_INFO(i) for (int q=0;q<quads;q++) { const T s = samples[q]; tq(i,q) = t1+dt*s; SPLINE_INFO(s) for (int a=0;a<d;a++) { X_INFO(i,a) xq(i,q,a) = a0*x0+a1*x1+a2*x2+a3*x3; vq(i,q,a) = b0*x0+b1*x1+b2*x2+b3*x3; } } } // Compute energy const auto Uq_ = U(tq.reshape_own(n*quads),NdArray<const T>(qshape,xq.flat),NdArray<const T>(qshape,vq.flat)); GEODE_ASSERT(Uq_.size()==n*quads); const auto Uq = Uq_.reshape(n,quads); // Accumulate T sum = 0; for (int i=0;i<n;i++) { const T dt = t[i+2]-t[i+1]; for (int q=0;q<quads;q++) sum += weights[q]*dt*Uq(i,q); } return sum; }
void hessian(RawArray<const T,2> x, RawArray<T,4> hess) const { // Temporary arrays and views GEODE_ASSERT(x.sizes()==vec(n+3,d) && hess.sizes()==vec(n+3,4,d,d)); const auto sx = smallx.flat.raw(), sv = smallv.flat.raw(); // Collect quadrature points const int e = 1+8*d+8*d*(d-1); Array<T,3> tq( n,quads,e,uninit); Array<T,4> xq(vec(n,quads,e,d),uninit); Array<T,4> vq(vec(n,quads,e,d),uninit); for (int i=0;i<n;i++) { T_INFO(i) for (int q=0;q<quads;q++) { const T s = samples[q], t = t1+dt*s; for (int j=0;j<e;j++) tq(i,q,j) = t; SPLINE_INFO(s) for (int a=0;a<d;a++) { X_INFO(i,a) const T x = a0*x0+a1*x1+a2*x2+a3*x3, v = b0*x0+b1*x1+b2*x2+b3*x3; for (int j=0;j<e;j++) { xq(i,q,j,a) = x; vq(i,q,j,a) = v; } int j = 1; for (int b=0;b<d;b++) { const T xb = sx[b], vb = sv[b]; xq(i,q,j++,a) -= xb; xq(i,q,j++,a) += xb; vq(i,q,j++,a) -= vb; vq(i,q,j++,a) += vb; xq(i,q,j ,a) -= xb; vq(i,q,j++,a) -= vb; xq(i,q,j ,a) -= xb; vq(i,q,j++,a) += vb; xq(i,q,j ,a) += xb; vq(i,q,j++,a) -= vb; xq(i,q,j ,a) += xb; vq(i,q,j++,a) += vb; for (int c=b+1;c<d;c++) { const T xc = sx[c], vc = sv[c]; xq(i,q,j++,a) -= xb+xc; xq(i,q,j++,a) -= xb-xc; xq(i,q,j++,a) += xb-xc; xq(i,q,j++,a) += xb+xc; vq(i,q,j++,a) -= vb+vc; vq(i,q,j++,a) -= vb-vc; vq(i,q,j++,a) += vb-vc; vq(i,q,j++,a) += vb+vc; vq(i,q,j++,a) -= sv[b]; xq(i,q,j ,a) -= sx[b]; vq(i,q,j++,a) += sv[b]; xq(i,q,j ,a) += sx[b]; vq(i,q,j++,a) -= sv[b]; xq(i,q,j ,a) += sx[b]; vq(i,q,j++,a) += sv[b]; } } } } } // Compute energies const auto Uq_ = U(tq.reshape_own(n*quads*d4),NdArray<const T>(q2shape,xq.flat),NdArray<const T>(q2shape,vq.flat)); GEODE_ASSERT(Uq_.size()==n*quads*d4); const auto Uq = Uq_.reshape(n,quads,d4); // Accumulate grad.fill(0); const auto inv_2s = GEODE_RAW_ALLOCA(d,Vector<T,2>); for (int a=0;a<d;a++) inv_2s[a] = vec(.5/sx[a],.5/sv[a]); for (int i=0;i<n;i++) { T_INFO(i) for (int q=0;q<quads;q++) { const T s = samples[q], w = dt*weights[q]; SPLINE_INFO(s) for (int b=0;b<d;b++) { const T wx = w*inv_2s[b].x*(Uq(i,q,4*b+1)-Uq(i,q,4*b )), wv = w*inv_2s[b].y*(Uq(i,q,4*b+3)-Uq(i,q,4*b+2)); grad(i ,b) += a0*wx+b0*wv; grad(i+1,b) += a1*wx+b1*wv; grad(i+2,b) += a2*wx+b2*wv; grad(i+3,b) += a3*wx+b3*wv; } } } }
void gradient(RawArray<const T,2> x, RawArray<T,2> grad) const { // Temporary arrays and views GEODE_ASSERT(x.sizes()==vec(n+3,d) && grad.sizes()==x.sizes()); const auto sx = smallx.flat.raw(), sv = smallv.flat.raw(); // Collect quadrature points const int e = 4*d; Array<T,3> tq( n,quads,e,uninit); Array<T,4> xq(vec(n,quads,e,d),uninit); Array<T,4> vq(vec(n,quads,e,d),uninit); for (int i=0;i<n;i++) { T_INFO(i) for (int q=0;q<quads;q++) { const T s = samples[q], t = t1+dt*s; for (int j=0;j<e;j++) tq(i,q,j) = t; SPLINE_INFO(s) for (int a=0;a<d;a++) { X_INFO(i,a) const T x = a0*x0+a1*x1+a2*x2+a3*x3, v = b0*x0+b1*x1+b2*x2+b3*x3; for (int j=0;j<e;j++) { xq(i,q,j,a) = x; vq(i,q,j,a) = v; } } for (int a=0;a<d;a++) { xq(i,q,4*a ,a) -= sx[a]; xq(i,q,4*a+1,a) += sx[a]; vq(i,q,4*a+2,a) -= sv[a]; vq(i,q,4*a+3,a) += sv[a]; } } } // Compute energies const auto Uq_ = U(tq.reshape_own(n*quads*e),NdArray<const T>(q2shape,xq.flat),NdArray<const T>(q2shape,vq.flat)); GEODE_ASSERT(Uq_.size()==n*quads*e); const auto Uq = Uq_.reshape(n,quads,e); // Accumulate grad.fill(0); const auto inv_2s = GEODE_RAW_ALLOCA(d,Vector<T,2>); for (int a=0;a<d;a++) inv_2s[a] = vec(.5/sx[a],.5/sv[a]); for (int i=0;i<n;i++) { T_INFO(i) for (int q=0;q<quads;q++) { const T s = samples[q], w = dt*weights[q]; SPLINE_INFO(s) for (int a=0;a<d;a++) { const T wx = w*inv_2s[a].x*(Uq(i,q,4*a+1)-Uq(i,q,4*a )), wv = w*inv_2s[a].y*(Uq(i,q,4*a+3)-Uq(i,q,4*a+2)); grad(i ,a) += a0*wx+b0*wv; grad(i+1,a) += a1*wx+b1*wv; grad(i+2,a) += a2*wx+b2*wv; grad(i+3,a) += a3*wx+b3*wv; } } } }
int main(int argc, char* argv[]) { Teuchos::RCP<Epetra_Comm> comm; #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); comm = Teuchos::rcp(new Epetra_MpiComm(MPI_COMM_WORLD)); #else comm = Teuchos::rcp(new Epetra_SerialComm()); #endif // This little trick lets us print to std::cout only if a (dummy) command-line argument is provided. int iprint = argc - 1; Teuchos::RCP<std::ostream> outStream; Teuchos::oblackholestream bhs; // outputs nothing if (iprint > 0 && comm->MyPID()==0) outStream = Teuchos::rcp(&std::cout, false); else outStream = Teuchos::rcp(&bhs, false); int errorFlag = 0; try { /**********************************************************************************************/ /************************* CONSTRUCT ROL ALGORITHM ********************************************/ /**********************************************************************************************/ // Get ROL parameterlist std::string filename = "input.xml"; Teuchos::RCP<Teuchos::ParameterList> parlist = Teuchos::rcp( new Teuchos::ParameterList() ); Teuchos::updateParametersFromXmlFile( filename, Teuchos::Ptr<Teuchos::ParameterList>(&*parlist) ); // Build ROL algorithm double gtol = parlist->get("Gradient Tolerance",1.e-6); double stol = parlist->get("Step Tolerance",1.e-12); int maxit = parlist->get("Maximum Number of Iterations",100); ROL::StatusTest<double> status(gtol,stol,maxit); //ROL::LineSearchStep<double> step(*parlist); Teuchos::RCP<ROL::Step<double> > step; Teuchos::RCP<ROL::DefaultAlgorithm<double> > algo; /**********************************************************************************************/ /************************* CONSTRUCT SOL COMPONENTS *******************************************/ /**********************************************************************************************/ // Build vectors unsigned dim = 4; Teuchos::RCP<std::vector<double> > x_rcp = Teuchos::rcp( new std::vector<double>(dim,0.0) ); ROL::StdVector<double> x(x_rcp); Teuchos::RCP<std::vector<double> > x0_rcp = Teuchos::rcp( new std::vector<double>(dim,0.0) ); ROL::StdVector<double> x0(x0_rcp); Teuchos::RCP<std::vector<double> > xr_rcp = Teuchos::rcp( new std::vector<double>(dim,0.0) ); ROL::StdVector<double> xr(xr_rcp); Teuchos::RCP<std::vector<double> > d_rcp = Teuchos::rcp( new std::vector<double>(dim,0.0) ); ROL::StdVector<double> d(d_rcp); for ( unsigned i = 0; i < dim; i++ ) { (*x0_rcp)[i] = 1.0/(double)dim; (*xr_rcp)[i] = random<double>(comm); (*d_rcp)[i] = random<double>(comm); } // Build samplers int nSamp = 1000; std::vector<std::vector<double> > bounds(dim); std::vector<double> tmp(2,0.0); double inc = 0.125; double val = -0.5; for (unsigned i = 0; i < dim; i++) { tmp[0] = val-inc; tmp[1] = val+inc; bounds[i] = tmp; inc *= 2.0; } Teuchos::RCP<ROL::BatchManager<double> > bman = Teuchos::rcp(new ROL::StdEpetraBatchManager<double>(comm)); Teuchos::RCP<ROL::SampleGenerator<double> > sampler = Teuchos::rcp(new ROL::MonteCarloGenerator<double>(nSamp,bounds,bman,false,false,100)); // Build risk-averse objective function bool storage = true; Teuchos::RCP<ROL::ParametrizedObjective<double> > pObj = Teuchos::rcp(new ParametrizedObjectiveEx1<double>(1.e1)); Teuchos::RCP<ROL::RiskMeasure<double> > rm; Teuchos::RCP<ROL::Objective<double> > obj; // Build bound constraints std::vector<double> l(dim,0.0); std::vector<double> u(dim,1.0); Teuchos::RCP<ROL::BoundConstraint<double> > con = Teuchos::rcp( new ROL::StdBoundConstraint<double>(l,u) ); // Test parametrized objective functions *outStream << "Check Derivatives of Parametrized Objective Function\n"; x.set(xr); pObj->setParameter(sampler->getMyPoint(0)); pObj->checkGradient(x,d,true,*outStream); pObj->checkHessVec(x,d,true,*outStream); /**********************************************************************************************/ /************************* RISK NEUTRAL *******************************************************/ /**********************************************************************************************/ *outStream << "\nRISK NEUTRAL\n"; rm = Teuchos::rcp( new ROL::RiskMeasure<double>() ); obj = Teuchos::rcp( new ROL::RiskAverseObjective<double>(pObj,rm,sampler,storage) ); // Test objective functions *outStream << "\nCheck Derivatives of Risk-Averse Objective Function\n"; x.set(xr); obj->checkGradient(x,d,true,*outStream); obj->checkHessVec(x,d,true,*outStream); // Run ROL algorithm step = Teuchos::rcp( new ROL::TrustRegionStep<double>(*parlist) ); algo = Teuchos::rcp( new ROL::DefaultAlgorithm<double>(*step,status,false) ); x.set(x0); clock_t start = clock(); algo->run(x,*obj,*con,true,*outStream); *outStream << "Optimization time: " << (double)(clock()-start)/(double)CLOCKS_PER_SEC << " seconds.\n"; // Print Solution *outStream << "x = ("; for ( unsigned i = 0; i < dim-1; i++ ) { *outStream << (*x_rcp)[i] << ", "; } *outStream << (*x_rcp)[dim-1] << ")\n"; /**********************************************************************************************/ /************************* RISK NEUTRAL *******************************************************/ /**********************************************************************************************/ *outStream << "\nRISK NEUTRAL\n"; obj = Teuchos::rcp( new ROL::RiskNeutralObjective<double>(pObj,sampler,storage) ); // Test objective functions *outStream << "\nCheck Derivatives of Risk-Averse Objective Function\n"; x.set(xr); obj->checkGradient(x,d,true,*outStream); obj->checkHessVec(x,d,true,*outStream); // Run ROL algorithm step = Teuchos::rcp( new ROL::TrustRegionStep<double>(*parlist) ); algo = Teuchos::rcp( new ROL::DefaultAlgorithm<double>(*step,status,false) ); x.set(x0); start = clock(); algo->run(x,*obj,*con,true,*outStream); *outStream << "Optimization time: " << (double)(clock()-start)/(double)CLOCKS_PER_SEC << " seconds.\n"; // Print Solution *outStream << "x = ("; for ( unsigned i = 0; i < dim-1; i++ ) { *outStream << (*x_rcp)[i] << ", "; } *outStream << (*x_rcp)[dim-1] << ")\n"; /**********************************************************************************************/ /************************* MEAN PLUS DEVIATION ************************************************/ /**********************************************************************************************/ *outStream << "\nMEAN PLUS DEVIATION\n"; // Absolute value approximation double gamma = 0.0; ROL::EAbsoluteValue eav = ROL::ABSOLUTEVALUE_C2; Teuchos::RCP<ROL::PositiveFunction<double> > pf = Teuchos::rcp( new ROL::AbsoluteValue<double>(gamma,eav) ); // Moment vector std::vector<double> order(2,0.0); order[0] = 2.0; order[1] = 4.0; // Moment coefficients std::vector<double> coeff(2,0.1); rm = Teuchos::rcp( new ROL::MeanDeviation<double>(order,coeff,pf) ); obj = Teuchos::rcp( new ROL::RiskAverseObjective<double>(pObj,rm,sampler,storage) ); // Test objective functions *outStream << "\nCheck Derivatives of Risk-Averse Objective Function\n"; x.set(xr); obj->checkGradient(x,d,true,*outStream); obj->checkHessVec(x,d,true,*outStream); // Run ROL algorithm step = Teuchos::rcp( new ROL::TrustRegionStep<double>(*parlist) ); algo = Teuchos::rcp( new ROL::DefaultAlgorithm<double>(*step,status,false) ); x.set(x0); start = clock(); algo->run(x,*obj,*con,true,*outStream); *outStream << "Optimization time: " << (double)(clock()-start)/(double)CLOCKS_PER_SEC << " seconds.\n"; // Print Solution *outStream << "x = ("; for ( unsigned i = 0; i < dim-1; i++ ) { *outStream << (*x_rcp)[i] << ", "; } *outStream << (*x_rcp)[dim-1] << ")\n"; /**********************************************************************************************/ /************************* MEAN PLUS VARIANCE *************************************************/ /**********************************************************************************************/ *outStream << "\nMEAN PLUS VARIANCE\n"; rm = Teuchos::rcp( new ROL::MeanVariance<double>(order,coeff,pf) ); obj = Teuchos::rcp( new ROL::RiskAverseObjective<double>(pObj,rm,sampler,storage) ); // Test objective functions *outStream << "\nCheck Derivatives of Risk-Averse Objective Function\n"; x.set(xr); obj->checkGradient(x,d,true,*outStream); obj->checkHessVec(x,d,true,*outStream); // Run ROL algorithm step = Teuchos::rcp( new ROL::TrustRegionStep<double>(*parlist) ); algo = Teuchos::rcp( new ROL::DefaultAlgorithm<double>(*step,status,false) ); x.set(x0); start = clock(); algo->run(x,*obj,*con,true,*outStream); *outStream << "Optimization time: " << (double)(clock()-start)/(double)CLOCKS_PER_SEC << " seconds.\n"; // Print Solution *outStream << "x = ("; for ( unsigned i = 0; i < dim-1; i++ ) { *outStream << (*x_rcp)[i] << ", "; } *outStream << (*x_rcp)[dim-1] << ")\n"; /**********************************************************************************************/ /************************* MEAN PLUS DEVIATION FROM TARGET ************************************/ /**********************************************************************************************/ *outStream << "\nMEAN PLUS DEVIATION FROM TARGET\n"; // Moment targets std::vector<double> target(2,-0.1); // Risk measure rm = Teuchos::rcp( new ROL::MeanDeviationFromTarget<double>(target,order,coeff,pf) ); // Risk averse objective obj = Teuchos::rcp( new ROL::RiskAverseObjective<double>(pObj,rm,sampler,storage) ); // Test objective functions *outStream << "\nCheck Derivatives of Risk-Averse Objective Function\n"; x.set(xr); obj->checkGradient(x,d,true,*outStream); obj->checkHessVec(x,d,true,*outStream); // Run ROL algorithm step = Teuchos::rcp( new ROL::TrustRegionStep<double>(*parlist) ); algo = Teuchos::rcp( new ROL::DefaultAlgorithm<double>(*step,status,false) ); x.set(x0); start = clock(); algo->run(x,*obj,*con,true,*outStream); *outStream << "Optimization time: " << (double)(clock()-start)/(double)CLOCKS_PER_SEC << " seconds.\n"; // Print Solution *outStream << "x = ("; for ( unsigned i = 0; i < dim-1; i++ ) { *outStream << (*x_rcp)[i] << ", "; } *outStream << (*x_rcp)[dim-1] << ")\n"; /**********************************************************************************************/ /************************* MEAN PLUS VARIANCE FROM TARGET *************************************/ /**********************************************************************************************/ *outStream << "\nMEAN PLUS VARIANCE FROM TARGET\n"; // Risk measure coeff[1] = 0.0; rm = Teuchos::rcp( new ROL::MeanVarianceFromTarget<double>(target,order,coeff,pf) ); coeff[1] = 0.1; // Risk averse objective obj = Teuchos::rcp( new ROL::RiskAverseObjective<double>(pObj,rm,sampler,storage) ); // Test objective functions *outStream << "\nCheck Derivatives of Risk-Averse Objective Function\n"; x.set(xr); obj->checkGradient(x,d,true,*outStream); obj->checkHessVec(x,d,true,*outStream); // Run ROL algorithm step = Teuchos::rcp( new ROL::TrustRegionStep<double>(*parlist) ); algo = Teuchos::rcp( new ROL::DefaultAlgorithm<double>(*step,status,false) ); x.set(x0); start = clock(); algo->run(x,*obj,*con,true,*outStream); *outStream << "Optimization time: " << (double)(clock()-start)/(double)CLOCKS_PER_SEC << " seconds.\n"; // Print Solution *outStream << "x = ("; for ( unsigned i = 0; i < dim-1; i++ ) { *outStream << (*x_rcp)[i] << ", "; } *outStream << (*x_rcp)[dim-1] << ")\n"; /**********************************************************************************************/ /************************* MEAN PLUS SEMIDEVIATION ********************************************/ /**********************************************************************************************/ *outStream << "\nMEAN PLUS SEMIDEVIATION\n"; // Plus function approximation gamma = 1.e2; std::vector<double> data2(2,0.0); data2[0] = 0.0; data2[1] = 1.0; Teuchos::RCP<ROL::Distribution<double> > dist2 = Teuchos::rcp(new ROL::Distribution<double>(ROL::DISTRIBUTION_PARABOLIC,data2)); Teuchos::RCP<ROL::PlusFunction<double> > plusf = Teuchos::rcp(new ROL::PlusFunction<double>(dist2,1.0/gamma)); pf = Teuchos::rcp(new ROL::PlusFunction<double>(dist2,1.0/gamma)); // Risk measure rm = Teuchos::rcp( new ROL::MeanDeviation<double>(order,coeff,pf) ); // Risk averse objective obj = Teuchos::rcp( new ROL::RiskAverseObjective<double>(pObj,rm,sampler,storage) ); // Test objective functions *outStream << "\nCheck Derivatives of Risk-Averse Objective Function\n"; x.set(xr); obj->checkGradient(x,d,true,*outStream); obj->checkHessVec(x,d,true,*outStream); // Run ROL algorithm step = Teuchos::rcp( new ROL::TrustRegionStep<double>(*parlist) ); algo = Teuchos::rcp( new ROL::DefaultAlgorithm<double>(*step,status,false) ); x.set(x0); start = clock(); algo->run(x,*obj,*con,true,*outStream); *outStream << "Optimization time: " << (double)(clock()-start)/(double)CLOCKS_PER_SEC << " seconds.\n"; // Print Solution *outStream << "x = ("; for ( unsigned i = 0; i < dim-1; i++ ) { *outStream << (*x_rcp)[i] << ", "; } *outStream << (*x_rcp)[dim-1] << ")\n"; /**********************************************************************************************/ /************************* MEAN PLUS SEMIVARIANCE *********************************************/ /**********************************************************************************************/ *outStream << "\nMEAN PLUS SEMIVARIANCE\n"; // Risk measure rm = Teuchos::rcp( new ROL::MeanVariance<double>(order,coeff,pf) ); // Risk averse objective obj = Teuchos::rcp( new ROL::RiskAverseObjective<double>(pObj,rm,sampler,storage) ); // Test objective functions *outStream << "\nCheck Derivatives of Risk-Averse Objective Function\n"; x.set(xr); obj->checkGradient(x,d,true,*outStream); obj->checkHessVec(x,d,true,*outStream); // Run ROL algorithm step = Teuchos::rcp( new ROL::TrustRegionStep<double>(*parlist) ); algo = Teuchos::rcp( new ROL::DefaultAlgorithm<double>(*step,status,false) ); x.set(x0); start = clock(); algo->run(x,*obj,*con,true,*outStream); *outStream << "Optimization time: " << (double)(clock()-start)/(double)CLOCKS_PER_SEC << " seconds.\n"; // Print Solution *outStream << "x = ("; for ( unsigned i = 0; i < dim-1; i++ ) { *outStream << (*x_rcp)[i] << ", "; } *outStream << (*x_rcp)[dim-1] << ")\n"; /**********************************************************************************************/ /************************* MEAN PLUS SEMIDEVIATION FROM TARGET ********************************/ /**********************************************************************************************/ *outStream << "\nMEAN PLUS SEMIDEVIATION FROM TARGET\n"; // Risk measure rm = Teuchos::rcp( new ROL::MeanDeviationFromTarget<double>(target,order,coeff,pf) ); // Risk averse objective obj = Teuchos::rcp( new ROL::RiskAverseObjective<double>(pObj,rm,sampler,storage) ); // Test objective functions *outStream << "\nCheck Derivatives of Risk-Averse Objective Function\n"; x.set(xr); obj->checkGradient(x,d,true,*outStream); obj->checkHessVec(x,d,true,*outStream); // Run ROL algorithm step = Teuchos::rcp( new ROL::TrustRegionStep<double>(*parlist) ); algo = Teuchos::rcp( new ROL::DefaultAlgorithm<double>(*step,status,false) ); x.set(x0); start = clock(); algo->run(x,*obj,*con,true,*outStream); *outStream << "Optimization time: " << (double)(clock()-start)/(double)CLOCKS_PER_SEC << " seconds.\n"; // Print Solution *outStream << "x = ("; for ( unsigned i = 0; i < dim-1; i++ ) { *outStream << (*x_rcp)[i] << ", "; } *outStream << (*x_rcp)[dim-1] << ")\n"; /**********************************************************************************************/ /************************* MEAN PLUS SEMIVARIANCE FROM TARGET *********************************/ /**********************************************************************************************/ *outStream << "\nMEAN PLUS SEMIVARIANCE FROM TARGET\n"; // Risk measure rm = Teuchos::rcp( new ROL::MeanVarianceFromTarget<double>(target,order,coeff,pf) ); // Risk averse objective obj = Teuchos::rcp( new ROL::RiskAverseObjective<double>(pObj,rm,sampler,storage) ); // Test objective functions *outStream << "\nCheck Derivatives of Risk-Averse Objective Function\n"; x.set(xr); obj->checkGradient(x,d,true,*outStream); obj->checkHessVec(x,d,true,*outStream); // Run ROL algorithm step = Teuchos::rcp( new ROL::TrustRegionStep<double>(*parlist) ); algo = Teuchos::rcp( new ROL::DefaultAlgorithm<double>(*step,status,false) ); x.set(x0); start = clock(); algo->run(x,*obj,*con,true,*outStream); *outStream << "Optimization time: " << (double)(clock()-start)/(double)CLOCKS_PER_SEC << " seconds.\n"; // Print Solution *outStream << "x = ("; for ( unsigned i = 0; i < dim-1; i++ ) { *outStream << (*x_rcp)[i] << ", "; } *outStream << (*x_rcp)[dim-1] << ")\n"; /**********************************************************************************************/ /************************* MEAN PLUS CVAR *****************************************************/ /**********************************************************************************************/ *outStream << "\nMEAN PLUS CONDITIONAL VALUE AT RISK\n"; double prob = 0.8; double c = 0.8; rm = Teuchos::rcp( new ROL::CVaR<double>(prob,c,plusf) ); obj = Teuchos::rcp( new ROL::RiskAverseObjective<double>(pObj,rm,sampler,storage) ); Teuchos::RCP<ROL::BoundConstraint<double> > CVaRcon = Teuchos::rcp( new ROL::CVaRBoundConstraint<double>(con) ); // Test objective functions double xv = 10.0*random<double>(comm)-5.0; double dv = 10.0*random<double>(comm)-5.0; Teuchos::RCP<ROL::Vector<double> > xp = Teuchos::rcp(&x,false); Teuchos::RCP<ROL::Vector<double> > dp = Teuchos::rcp(&d,false); ROL::CVaRVector<double> xc(xv,xp); ROL::CVaRVector<double> dc(dv,dp); *outStream << "\nCheck Derivatives of Risk-Averse Objective Function\n"; x.set(xr); obj->checkGradient(xc,dc,true,*outStream); obj->checkHessVec(xc,dc,true,*outStream); // Run ROL algorithm step = Teuchos::rcp( new ROL::TrustRegionStep<double>(*parlist) ); algo = Teuchos::rcp( new ROL::DefaultAlgorithm<double>(*step,status,false) ); x.set(x0); start = clock(); algo->run(xc,*obj,*CVaRcon,true,*outStream); *outStream << "Optimization time: " << (double)(clock()-start)/(double)CLOCKS_PER_SEC << " seconds.\n"; // Print Solution *outStream << "t = " << xc.getVaR() << "\n"; *outStream << "x = ("; for ( unsigned i = 0; i < dim-1; i++ ) { *outStream << (*x_rcp)[i] << ", "; } *outStream << (*x_rcp)[dim-1] << ")\n"; /**********************************************************************************************/ /************************* SMOOTHED CVAR QUADRANGLE *******************************************/ /**********************************************************************************************/ *outStream << "\nSMOOTHED CONDITIONAL VALUE AT RISK \n"; prob = 0.9; ROL::CVaRQuadrangle<double> scq(prob,1.0/gamma,plusf); //scq.checkRegret(); rm = Teuchos::rcp(&scq,false); obj = Teuchos::rcp( new ROL::RiskAverseObjective<double>(pObj,rm,sampler,storage) ); // Test objective functions xv = 10.0*random<double>(comm)-5.0; dv = 10.0*random<double>(comm)-5.0; xp = Teuchos::rcp(&x,false); dp = Teuchos::rcp(&d,false); ROL::CVaRVector<double> xq(xv,xp); ROL::CVaRVector<double> dq(dv,dp); *outStream << "\nCheck Derivatives of Risk-Averse Objective Function\n"; x.set(xr); obj->checkGradient(xq,dq,true,*outStream); obj->checkHessVec(xq,dq,true,*outStream); // Run ROL algorithm step = Teuchos::rcp( new ROL::TrustRegionStep<double>(*parlist) ); algo = Teuchos::rcp( new ROL::DefaultAlgorithm<double>(*step,status,false) ); x.set(x0); start = clock(); algo->run(xq,*obj,*CVaRcon,true,*outStream); *outStream << "Optimization time: " << (double)(clock()-start)/(double)CLOCKS_PER_SEC << " seconds.\n"; // Print Solution *outStream << "t = " << xq.getVaR() << "\n"; *outStream << "x = ("; for ( unsigned i = 0; i < dim-1; i++ ) { *outStream << (*x_rcp)[i] << ", "; } *outStream << (*x_rcp)[dim-1] << ")\n"; /**********************************************************************************************/ /************************* EXPONENTIAL UTILITY FUNCTION ***************************************/ /**********************************************************************************************/ *outStream << "\nEXPONENTIAL UTILITY FUNCTION\n"; rm = Teuchos::rcp( new ROL::ExpUtility<double> ); obj = Teuchos::rcp( new ROL::RiskAverseObjective<double>(pObj,rm,sampler,storage) ); // Test objective functions *outStream << "\nCheck Derivatives of Risk-Averse Objective Function\n"; x.set(x0); obj->checkGradient(x,d,true,*outStream); obj->checkHessVec(x,d,true,*outStream); // Run ROL algorithm step = Teuchos::rcp( new ROL::TrustRegionStep<double>(*parlist) ); algo = Teuchos::rcp( new ROL::DefaultAlgorithm<double>(*step,status,false) ); x.set(x0); start = clock(); algo->run(x,*obj,*con,true,*outStream); *outStream << "Optimization time: " << (double)(clock()-start)/(double)CLOCKS_PER_SEC << " seconds.\n"; // Print Solution *outStream << "x = ("; for ( unsigned i = 0; i < dim-1; i++ ) { *outStream << (*x_rcp)[i] << ", "; } *outStream << (*x_rcp)[dim-1] << ")\n"; } catch (std::logic_error err) { *outStream << err.what() << "\n"; errorFlag = -1000; }; // end try if (errorFlag != 0) std::cout << "End Result: TEST FAILED\n"; else std::cout << "End Result: TEST PASSED\n"; return 0; }
TYPED_TEST(QuantBlasTest, TestAxpbyComparativeFloatQuant) { typedef typename TypeParam::Dtype Dtype; // Expect at most 5% error float percentile_eps = 0.05; std::random_device rdev; std::mt19937 rngen(rdev()); // Need to test > 64 dimension std::uniform_int_distribution<int_tp> dimsRand(1, 256); std::uniform_int_distribution<int_tp> boolRand(0, 1); std::uniform_int_distribution<int_tp> factorRand(-25, 25); std::uniform_real_distribution<float> valRand(-2.0, 2.0); for (int_tp testIdx = 0; testIdx < 25; ++testIdx) { int_tp N = dimsRand(rngen); bool has_alpha = boolRand(rngen); bool has_beta = has_alpha ? boolRand(rngen) : true; bool alpha_with_quant = boolRand(rngen) && has_alpha; bool beta_with_quant = boolRand(rngen) && has_beta; float alpha_val; float beta_val; if (has_alpha) { alpha_val = alpha_with_quant ? valRand(rngen) : float(1.0); } else { alpha_val = 0.0; } if (has_beta) { beta_val = beta_with_quant ? valRand(rngen) : float(1.0); } else { beta_val = 0.0; } vector<int_tp> x_shape(1, 1); vector<int_tp> y_shape(1, 1); x_shape[0] = N; y_shape[0] = N; Blob<float> x(x_shape, Caffe::GetDefaultDevice()); Blob<float> y(y_shape, Caffe::GetDefaultDevice()); Blob<float> y_result(y_shape, Caffe::GetDefaultDevice()); Blob<Dtype> x_quant(x_shape, Caffe::GetDefaultDevice()); Blob<Dtype> y_quant(y_shape, Caffe::GetDefaultDevice()); Blob<float> y_unquant(y_shape, Caffe::GetDefaultDevice()); caffe_rng_gaussian(N, (float)0.0, (float)0.5, x.mutable_cpu_data()); caffe_rng_gaussian(N, (float)0.0, (float)0.5, y.mutable_cpu_data()); caffe_copy(N, y.cpu_data(), y_result.mutable_cpu_data()); QuantizerParameter qpm_x; QuantizerParameter qpm_y; QuantizerParameter qpm_alpha; QuantizerParameter qpm_beta; qpm_x.set_mode(CAFFE_QUANT_OBSERVE); qpm_y.set_mode(CAFFE_QUANT_OBSERVE); qpm_alpha.set_mode(CAFFE_QUANT_OBSERVE); qpm_beta.set_mode(CAFFE_QUANT_OBSERVE); Quantizer<float, Dtype> xq(qpm_x); Quantizer<float, Dtype> yq(qpm_y); Quantizer<float, Dtype> alphaq(qpm_alpha); Quantizer<float, Dtype> betaq(qpm_beta); // Normal GEMM caffe_axpby<float>(N, alpha_val, x.cpu_data(), beta_val, y_result.mutable_cpu_data()); // Observe all values that will be relevant for quantization xq.ObserveIn_cpu(N, x.cpu_data()); yq.ObserveIn_cpu(N, y.cpu_data()); yq.ObserveIn_cpu(N, y_result.cpu_data()); alphaq.ObserveIn_cpu(1, &alpha_val); betaq.ObserveIn_cpu(1, &beta_val); // Apply observed values to the quantizer xq.update(); yq.update(); alphaq.update(); betaq.update(); // Quantize A, B and C xq.Forward_cpu(N, x.cpu_data(), x_quant.mutable_cpu_data()); yq.Forward_cpu(N, y.cpu_data(), y_quant.mutable_cpu_data()); Dtype alpha_val_quant = has_alpha; Dtype beta_val_quant = has_beta; // Quantize alpha if (alpha_with_quant) { alphaq.Forward_cpu(1, &alpha_val, &alpha_val_quant); } // Quantize beta if (beta_with_quant) { betaq.Forward_cpu(1, &beta_val, &beta_val_quant); } if (Caffe::mode() == Caffe::Brew::CPU) { // TODO: Not implemented yet return; /*caffe_axpby<Dtype>(N, alpha_val_quant, x_quant.cpu_data(), beta_val_quant, y_quant.mutable_cpu_data(), alpha_with_quant ? &(alphaq.out_quantizer_values()) : nullptr, &(xq.out_quantizer_values()), beta_with_quant ? &(betaq.out_quantizer_values()) : nullptr, &(yq.out_quantizer_values()));*/ } else { Caffe::GetDefaultDevice()->template axpby<Dtype>(N, alpha_val_quant, x_quant.gpu_data(), beta_val_quant, y_quant.mutable_gpu_data(), alpha_with_quant ? &(alphaq.out_quantizer_values()) : nullptr, &(xq.out_quantizer_values()), beta_with_quant ? &(betaq.out_quantizer_values()) : nullptr, &(yq.out_quantizer_values())); } yq.Backward_cpu(N, y_quant.cpu_data(), y_unquant.mutable_cpu_data()); const QuantizerValues cqv = yq.in_quantizer_values(); float eps = std::max(std::abs(cqv.get_max<float>()), std::abs(cqv.get_min<float>())) * percentile_eps; for (int_tp i = 0; i < N; ++i) { EXPECT_NEAR(y_unquant.cpu_data()[i], y_result.cpu_data()[i], eps); // One error is enough to abort if (fabs(y_unquant.cpu_data()[i] - y_result.cpu_data()[i]) >= eps) { break; } } } }
TYPED_TEST(QuantBlasTest, TestGemvComparativeFloatQuant) { typedef typename TypeParam::Dtype Dtype; // Expect at most 5% error float percentile_eps = 0.05; std::random_device rdev; std::mt19937 rngen(rdev()); // Need to test > 64 dimension std::uniform_int_distribution<int_tp> dimsRand(1, 256); std::uniform_int_distribution<int_tp> boolRand(0, 1); std::uniform_int_distribution<int_tp> factorRand(-25, 25); std::uniform_real_distribution<float> valRand(-2.0, 2.0); for (int_tp testIdx = 0; testIdx < 25; ++testIdx) { int_tp M = dimsRand(rngen); int_tp N = dimsRand(rngen); CBLAS_TRANSPOSE trans_A = boolRand(rngen) ? CblasTrans : CblasNoTrans; bool has_alpha = boolRand(rngen); bool has_beta = has_alpha ? boolRand(rngen) : true; bool alpha_with_quant = boolRand(rngen) && has_alpha; bool beta_with_quant = boolRand(rngen) && has_beta; float alpha_val; float beta_val; if (has_alpha) { alpha_val = alpha_with_quant ? valRand(rngen) : float(1.0); } else { alpha_val = 0.0; } if (has_beta) { beta_val = beta_with_quant ? valRand(rngen) : float(1.0); } else { beta_val = 0.0; } vector<int_tp> A_shape(4, 1); vector<int_tp> x_shape(4, 1); vector<int_tp> y_shape(4, 1); A_shape[2] = M; A_shape[3] = N; x_shape[3] = trans_A == CblasTrans ? M : N; y_shape[3] = trans_A == CblasTrans ? N : M; Blob<float> A(A_shape, Caffe::GetDefaultDevice()); Blob<float> x(x_shape, Caffe::GetDefaultDevice()); Blob<float> y(y_shape, Caffe::GetDefaultDevice()); Blob<float> y_result(y_shape, Caffe::GetDefaultDevice()); Blob<Dtype> A_quant(A_shape, Caffe::GetDefaultDevice()); Blob<Dtype> x_quant(x_shape, Caffe::GetDefaultDevice()); Blob<Dtype> y_quant(y_shape, Caffe::GetDefaultDevice()); Blob<float> y_unquant(y_shape, Caffe::GetDefaultDevice()); caffe_rng_gaussian(M * N, (float)0.0, (float)0.5, A.mutable_cpu_data()); caffe_rng_gaussian(trans_A == CblasTrans ? M : N, (float)0.0, (float)0.5, x.mutable_cpu_data()); caffe_rng_gaussian(trans_A == CblasTrans ? N : M, (float)0.0, (float)0.5, y.mutable_cpu_data()); caffe_copy(trans_A == CblasTrans ? N : M, y.cpu_data(), y_result.mutable_cpu_data()); QuantizerParameter qpm_a; QuantizerParameter qpm_x; QuantizerParameter qpm_y; QuantizerParameter qpm_alpha; QuantizerParameter qpm_beta; qpm_a.set_mode(CAFFE_QUANT_OBSERVE); qpm_x.set_mode(CAFFE_QUANT_OBSERVE); qpm_y.set_mode(CAFFE_QUANT_OBSERVE); qpm_alpha.set_mode(CAFFE_QUANT_OBSERVE); qpm_beta.set_mode(CAFFE_QUANT_OBSERVE); Quantizer<float, Dtype> aq(qpm_a); Quantizer<float, Dtype> xq(qpm_x); Quantizer<float, Dtype> yq(qpm_y); Quantizer<float, Dtype> alphaq(qpm_alpha); Quantizer<float, Dtype> betaq(qpm_beta); // Normal GEMM caffe_gemv<float>( trans_A, M, N, alpha_val, A.cpu_data(), x.cpu_data(), beta_val, y_result.mutable_cpu_data()); // Observe all values that will be relevant for quantization aq.ObserveIn_cpu(M * N, A.cpu_data()); xq.ObserveIn_cpu(trans_A == CblasTrans ? M : N, x.cpu_data()); yq.ObserveIn_cpu(trans_A == CblasTrans ? N : M, y.cpu_data()); yq.ObserveIn_cpu(trans_A == CblasTrans ? N : M, y_result.cpu_data()); alphaq.ObserveIn_cpu(1, &alpha_val); betaq.ObserveIn_cpu(1, &beta_val); // Apply observed values to the quantizer aq.update(); xq.update(); yq.update(); alphaq.update(); betaq.update(); // Quantize A, B and C aq.Forward_cpu(M * N, A.cpu_data(), A_quant.mutable_cpu_data()); xq.Forward_cpu(trans_A == CblasTrans ? M : N, x.cpu_data(), x_quant.mutable_cpu_data()); yq.Forward_cpu(trans_A == CblasTrans ? N : M, y.cpu_data(), y_quant.mutable_cpu_data()); Dtype alpha_val_quant = has_alpha; Dtype beta_val_quant = has_beta; // Quantize alpha if (alpha_with_quant) { alphaq.Forward_cpu(1, &alpha_val, &alpha_val_quant); } // Quantize beta if (beta_with_quant) { betaq.Forward_cpu(1, &beta_val, &beta_val_quant); } if (Caffe::mode() == Caffe::Brew::CPU) { caffe_gemv<Dtype>(trans_A, M, N, alpha_val_quant, A_quant.cpu_data(), x_quant.cpu_data(), beta_val_quant, y_quant.mutable_cpu_data(), alpha_with_quant ? &(alphaq.out_quantizer_values()) : nullptr, &(aq.out_quantizer_values()), &(xq.out_quantizer_values()), beta_with_quant ? &(betaq.out_quantizer_values()) : nullptr, &(yq.out_quantizer_values())); } else { Caffe::GetDefaultDevice()->template gemv<Dtype>(trans_A, M, N, alpha_val_quant, A_quant.gpu_data(), x_quant.gpu_data(), beta_val_quant, y_quant.mutable_gpu_data(), alpha_with_quant ? &(alphaq.out_quantizer_values()) : nullptr, &(aq.out_quantizer_values()), &(xq.out_quantizer_values()), beta_with_quant ? &(betaq.out_quantizer_values()) : nullptr, &(yq.out_quantizer_values())); } yq.Backward_cpu(trans_A == CblasTrans ? N : M, y_quant.cpu_data(), y_unquant.mutable_cpu_data()); // print_matrix(A_quant.cpu_data(), M, K); // print_matrix(B_quant.cpu_data(), K, N); // print_matrix(C_quant.cpu_data(), M, N); // print_matrix(C_result.cpu_data(), M, N); // print_matrix(C_unquant.cpu_data(), M, N); const QuantizerValues cqv = yq.in_quantizer_values(); float eps = std::max(std::abs(cqv.get_max<float>()), std::abs(cqv.get_min<float>())) * percentile_eps; for (int_tp i = 0; i < (trans_A == CblasTrans ? N : M); ++i) { EXPECT_NEAR(y_unquant.cpu_data()[i], y_result.cpu_data()[i], eps); // One error is enough to abort if (fabs(y_unquant.cpu_data()[i] - y_result.cpu_data()[i]) >= eps) { break; } } } }