/** \file logchisq.hpp \brief chi-square statistic \author Junhua Gu */ #ifndef LOG_CHI_SQ_HPP #define LOG_CHI_SQ_HPP #define OPT_HEADER #include #include #include #include #include using std::cerr;using std::endl; namespace opt_utilities { class negative_data_value :public opt_exception { public: negative_data_value() :opt_exception("log chisq statistics cannot be used when has negative data!") {} }; /** \brief chi-square statistic \tparam Ty the return type of model \tparam Tx the type of the self-var \tparam Tp the type of model parameter \tparam Ts the type of the statistic \tparam Tstr the type of the string used */ template class logchisq :public statistic { private: bool verb; int n; statistic* do_clone()const { // return const_cast*>(this); return new logchisq(*this); } const char* do_get_type_name()const { return "chi^2 statistic"; } public: void verbose(bool v) { verb=v; } public: logchisq() :verb(false) {} Ts do_eval(const Tp& p) { Ts result(0); for(int i=(this->get_data_set()).size()-1;i>=0;--i) { Ty y=std::log(this->get_data_set().get_data(i).get_y()); Ty ym=std::log(this->eval_model(this->get_data_set().get_data(i).get_x(),p)); Ty ye1=std::log(1+this->get_data_set().get_data(i).get_y_upper_err()/this->get_data_set().get_data(i).get_y()); Ty chi=(y-ym)/ye1; result+=chi*chi; } if(verb) { n++; if(n%10==0) { cerr< class logchisq,double,std::string> :public statistic ,double,std::string> { public: typedef double Ty; typedef double Tx; typedef std::vector Tp; typedef double Ts; typedef std::string Tstr; private: bool verb; int n; statistic* do_clone()const { // return const_cast*>(this); return new logchisq(*this); } const char* do_get_type_name()const { return "chi^2 statistics (specialized for double)"; } public: void verbose(bool v) { verb=v; } public: logchisq() :verb(false) {} Ty do_eval(const Tp& p) { Ty result(0); for(size_t i=0;i!=(this->get_data_set()).size();++i) { Ty y_model=this->eval_model(this->get_data_set().get_data(i).get_x(),p); Ty y_obs=this->get_data_set().get_data(i).get_y(); Ty y_err; if(y_model>y_obs) { y_err=std::abs(this->get_data_set().get_data(i).get_y_upper_err()); } else { y_err=-std::abs(this->get_data_set().get_data(i).get_y_lower_err()); } if(y_obs+y_err<0) { throw negative_data_value(); } Ty logy=std::log(y_obs); Ty logym=std::log(y_model); Ty logerr=std::log(y_obs+y_err)-log(y_obs); Ty chi=(logy-logym)/logerr; // Ty chi=(this->get_data_set().get_data(i).get_y()-this->eval_model(this->get_data_set().get_data(i).get_x(),p)); // cerr<eval_model(this->get_data_set()[i].x,p)<get_data_set()[i].y_upper_err<get_data_set()[i].x<<"\t"<get_data_set()[i].y<<"\t"<eval_model(this->get_data_set()[i].x,p)<