Commit db20756e by Tianqi Yang

feat(sim): simulate n times instead of n days

parent d39fb78b
180 0.01
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#include "markov_chain.h" #include "markov_chain.h"
using namespace std; using namespace std;
const int SIM_DAYS = 10000000; const int SIM_DAYS = 100000;
int main () int main ()
{ {
......
...@@ -15,7 +15,7 @@ using namespace std; ...@@ -15,7 +15,7 @@ using namespace std;
State::State () State::State ()
: coupon_count ( EXPIRE_DAYS ) : coupon_count ( EXPIRE_DAYS, 0 )
{ {
} }
...@@ -30,44 +30,51 @@ int & State::operator [] ( int i ) ...@@ -30,44 +30,51 @@ int & State::operator [] ( int i )
return coupon_count[i]; return coupon_count[i];
} }
pair<State, int> State::use_coupon ( int c ) const void State::pass_day ( int d )
{
for ( int i = d; i < EXPIRE_DAYS; ++i ) {
coupon_count[i - d] = coupon_count[i];
}
for ( int i = max ( EXPIRE_DAYS - d, 0 ); i < EXPIRE_DAYS; ++i ) {
coupon_count[i] = 0;
}
}
int State::use_coupon ( int c )
{ {
State result = *this;
int use_count = 0, current_use_count; int use_count = 0, current_use_count;
for ( int i = 0; i < EXPIRE_DAYS; ++i ) { for ( int i = 0; i < EXPIRE_DAYS; ++i ) {
current_use_count = min ( result[i], c / COUPON_COST ); current_use_count = min ( coupon_count[i], c / COUPON_COST );
c -= COUPON_COST * current_use_count; c -= COUPON_COST * current_use_count;
result[i] -= current_use_count; coupon_count[i] -= current_use_count;
use_count += current_use_count; use_count += current_use_count;
} }
return make_pair ( result, use_count ); return use_count;
} }
State State::pass_day ( int c ) const void State::add_coupon ( int c )
{ {
State result; coupon_count[EXPIRE_DAYS - 1] = c;
for ( int i = 1; i < EXPIRE_DAYS; ++i ) {
result[i - 1] = coupon_count[i];
}
result[EXPIRE_DAYS - 1] = c;
return result;
} }
double simulate_prob ( double lambda, double prob_day, int sim_days ) double simulate_prob ( double lambda, double prob_day, int sim_times )
{ {
mt19937 rand_gen ( static_cast < unsigned > ( chrono::system_clock::now ().time_since_epoch ().count () ) ); mt19937 rand_gen ( static_cast < unsigned > ( chrono::system_clock::now ().time_since_epoch ().count () ) );
poisson_distribution < int > poisson ( lambda ); poisson_distribution < int > poisson ( lambda );
uniform_real_distribution < double > uniform ( 0.0, 1.0 ); uniform_real_distribution < double > uniform ( 0.0, 1.0 );
State current_state; State current_state;
long long total_cost = 0, used_coupon = 0; long long total_cost = 0, used_coupon = 0;
for ( int day = 0; day < sim_days; ++day ) { for ( int go_time = 0; go_time < sim_times; ++go_time ) {
int current_cost = ( uniform ( rand_gen ) < prob_day ) ? poisson ( rand_gen ) : 0; int day = 1;
while ( uniform ( rand_gen ) >= prob_day ) ++day;
current_state.pass_day ( day );
int current_cost = poisson ( rand_gen );
total_cost += current_cost; total_cost += current_cost;
auto return_val = current_state.use_coupon ( current_cost ); int current_coupon = current_state.use_coupon ( current_cost );
used_coupon += return_val.second; used_coupon += current_coupon;
current_state = return_val.first.pass_day ( ( current_cost - return_val.second * COUPON_VALUE ) / COUPON_COST ); current_state.add_coupon ( ( current_cost - current_coupon * COUPON_VALUE ) / COUPON_COST );
} }
return ( static_cast < double > ( used_coupon * COUPON_VALUE ) / total_cost ); return ( static_cast < double > ( used_coupon * COUPON_VALUE ) / total_cost );
} }
...@@ -16,12 +16,14 @@ public: ...@@ -16,12 +16,14 @@ public:
int operator [] ( int i ) const; int operator [] ( int i ) const;
int & operator [] ( int i ); int & operator [] ( int i );
std::pair < State, int > use_coupon ( int c ) const; void pass_day ( int d );
State pass_day ( int c ) const; int use_coupon ( int c );
void add_coupon ( int c );
private: private:
std::vector < int > coupon_count; // i-th term indicates the number of coupons expired in the i-th day std::vector < int > coupon_count; // i-th term indicates the number of coupons expired in the i-th day
}; };
double simulate_prob ( double lambda, double prob_day, int sim_days ); double simulate_prob ( double lambda, double prob_day, int sim_times );
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment