123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- #ifndef __MONKEY_FIT__
- #define __MONKEY_FIT__
- #include <cmath>
- #include <iterator>
- #include <map>
- #include <deque>
- #include <algorithm>
- #include "base_data.h"
- struct monkey_fit
- {
- virtual ~monkey_fit(){}
- template<typename T> static double get_probab_max(T it,T ite,int sum,int N=3)
- {
- sum/=5;
- sum=std::max(3,sum);
- std::vector<std::tuple<T,T,float>> p;
- if(N==0)
- {
- auto it0=it;
- for(int i=0;it0!=ite;++it0,++i)
- {
- if(i%10==0) printf("\n");
- printf("%5d:%2d,",it0->first,it0->second);
- }
- printf("\n");
- }
- int s=0;
- for(auto i1=it;it!=ite;)
- {
- for(;s<sum && i1!=ite;++i1)
- s+=i1->second;
- if(s<sum) break;
- p.push_back(std::make_tuple(it,i1,1.*s/(std::prev(i1)->first-it->first+1)));
- s-=it->second; ++it;
- }
- if(p.empty())
- return 0;
- std::sort(p.begin(),p.end(),[](const std::tuple<T,T,int>&l,const std::tuple<T,T,int>&r){
- return 1.*std::get<2>(l) > 1.*std::get<2>(r);
- });
- int i=1;
- auto it1=std::get<0>(p[0]);
- auto it2=std::prev(std::get<1>(p[0]));
- for(;i<(int)p.size();++i)
- {
- if(std::get<2>(p[i])!=std::get<2>(p[i-1]))
- break;
- if(std::get<0>(p[i])->first < it1->first)
- it1=std::get<0>(p[i]);
- if(std::prev(std::get<1>(p[i]))->second > it2->second)
- it2=std::prev(std::get<1>(p[i]));
- }
- ++it2;
- double rc=0;
- int cc=0;
- int x=0;
- for(;it1!=it2;++it1)
- {
- rc+=it1->first*it1->second;
- cc+=it1->second;
- if(N==0)
- {
- if(x++%10==0) printf("\n");
- printf("%5d:%2d,",it1->first,it1->second);
- }
- }
- if(N==0)
- printf("\n");
- return rc/cc;
- }
- int round(double value)
- {
- return (value > 0.0)?floor(value + 0.5):ceil(value - 0.5);
- }
- virtual void reset(double monkey_speed = 0){}
- virtual void push(double time_second,double dist_meter) {}
- virtual double get_K() = 0;
- };
- struct monkey_fit_b :monkey_fit
- {
- static const int min_points = 60;
- static const int BN = 20;
- double k_init_;
- int count_;
- std::map<int,int> probab_b;
- monkey_fit_b()
- :k_init_(0)
- ,count_(0)
- {}
- monkey_fit_b(double s)
- :k_init_(s)
- ,count_(0)
- {}
- virtual void reset(double monkey_speed/*=0*/)
- {
- k_init_=monkey_speed;
- count_=0;
- probab_b.clear();
- }
- virtual void push(double time_second,double dist_meter)
- {
- double k=k_init_;
- ++count_;
- double b=(dist_meter-k*time_second)*BN;
- ++probab_b[round(b)];
- }
- double get_dist(double time_second)const
- {
- return k_init_*time_second + get_B();
- }
- double get_K()
- {
- return k_init_;
- }
- double get_B()const
- {
- if(count_<min_points)
- return 0;
- if(probab_b.size()<3)
- return 0;
- return 1.*get_probab_max(probab_b.begin(),probab_b.end(),count_)/BN;
- }
- };
- struct monkey_fit_k:monkey_fit
- {
- static const int min_points=60;
- static const int KN=50;
- int step_;
- uint32_t count_;
- std::map<int,int> probab_k;
- std::deque<point_2> m_points;
- monkey_fit_k()
- :step_(0)
- ,count_(0)
- {}
- virtual void reset(double speed /*=0*/)
- {
- probab_k.clear();
- m_points.clear();
- step_=0;
- count_ = 0;
- }
- virtual void push(double time_second,double dist_meter)
- {
- int cc=m_points.size();
- if(cc<60)
- {
- m_points.push_back(point_2(time_second,dist_meter));
- }
- else if(step_++>2)
- {
- m_points.push_back(point_2(time_second,dist_meter));
- step_=0;
- }
- if(cc<10)
- return;
- cc*=9./10;
- for(int i=0;i<3;i++)
- {
- int index=rand()%cc;
- double k=(dist_meter-m_points[index].y_)/(time_second-m_points[index].x_);
- if((1<k && k<3) || (-3<k && k<-1))
- {
- count_++;
- ++probab_k[round(k*KN)];
- }
- }
- }
- double get_K()
- {
- if(m_points.size()<min_points)
- return 0;
- return round(get_probab_max(probab_k.begin(),probab_k.end(),count_)/KN*10000)/10000.;
- }
- };
- #endif
|