// ch13_bootstrap_fit.cpp // Companion code for Chapter 13: Optimization and Data Fitting. // Standalone C++11; standard library only; console output without plotting. // Compile: c++ -std=c++11 -O2 -Wall -Wextra -pedantic ch13_bootstrap_fit.cpp -o ch13_bootstrap_fit // Edit the example settings in main(); routines above main() can be reused. // Fixed seeds reproduce runs with the same standard-library implementation. // Random distributions need not give identical sequences across compilers/languages. #include #include #include #include #include #include #include #include #include #include #include #include #include using Vec = std::vector; using Mat = std::vector; using Function = std::function; using ScalarFunction = std::function; const double pi = std::acos(-1.0); void require(bool condition, const std::string& message) { if (!condition) throw std::invalid_argument(message); } void finite_vector(const Vec& x) { require(!x.empty(), "A nonempty vector is required."); for (double v : x) require(std::isfinite(v), "Data must be finite."); } void check_bounds(const Vec& lo, const Vec& hi) { finite_vector(lo); finite_vector(hi); require(lo.size() == hi.size(), "Bounds must have matching dimensions."); for (std::size_t j=0; jlo[j] && std::isfinite(hi[j]-lo[j]), "Require finite upper > lower."); } double objective_value(double value) { require(std::isfinite(value), "Objective must return a finite real scalar."); return value; } double clip(double x, double lo, double hi) { return std::max(lo,std::min(hi,x)); } Vec linspace(double a, double b, int n) { require(n>=2, "Grid needs at least two points."); Vec x(n); for (int i=0; i uniform{0.0,1.0}; std::normal_distribution normal{0.0,1.0}; explicit Random(unsigned int seed) : engine(seed) {} double u() { return uniform(engine); } double z() { return normal(engine); } int index(int n) { return std::uniform_int_distribution(0,n-1)(engine); } }; struct Result { Vec point; double value=0.0; long long evaluations=0; int iterations=0; std::string status; }; void print_result(const Result& r) { std::cout << std::setprecision(12); for (std::size_t j=0; j0,"Degenerate data/resample: slope undefined; bootstrap aborted."); double slope=Sxy/Sxx; return {yb-slope*xb,slope}; } struct Bootstrap { Vec estimate,standard_errors,bias; Mat covariance,samples; }; // Independent pairs bootstrap. For fixed experimental x consider residual or // parametric resampling; dependent data need a scheme preserving that dependence. // Aborts explicitly on degenerate resamples rather than discarding them silently. Bootstrap bootstrap_line(const Vec& x, const Vec& y, int B, Random& rng) { finite_vector(x); finite_vector(y); require(x.size()==y.size() && x.size()>=3 && B>=2,"Invalid bootstrap data or resample count."); Bootstrap r; r.estimate=line_coefficients(x,y); r.samples.resize(B); Vec mean(2,0.0); for (int b=0;b(x.size())); xx[i]=x[j]; yy[i]=y[j]; } r.samples[b]=line_coefficients(xx,yy); for (int j=0;j<2;++j) mean[j]+=r.samples[b][j]/B; } r.covariance=Mat(2,Vec(2,0.0)); r.standard_errors=Vec(2); r.bias=Vec(2); for (const Vec& a:r.samples) for (int i=0;i<2;++i) for (int j=0;j<2;++j) r.covariance[i][j]+=(a[i]-mean[i])*(a[j]-mean[j])/(B-1); for (int j=0;j<2;++j) { r.standard_errors[j]=std::sqrt(r.covariance[j][j]); r.bias[j]=mean[j]-r.estimate[j]; } return r; } int main() { try { const unsigned int seed = 1; Random rng(seed); // Alternative: comment out the previous line and seed from system entropy. // Random rng(std::random_device{}()); Vec x=linspace(0,1,25),y(x.size()); for (std::size_t i=0;i