Commit db20756e by Tianqi Yang

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

parent d39fb78b
180 0.01
......@@ -2,7 +2,7 @@
#include "markov_chain.h"
using namespace std;
const int SIM_DAYS = 10000000;
const int SIM_DAYS = 100000;
int main ()
{
......
......@@ -15,7 +15,7 @@ using namespace std;
State::State ()
: coupon_count ( EXPIRE_DAYS )
: coupon_count ( EXPIRE_DAYS, 0 )
{
}
......@@ -30,44 +30,51 @@ int & State::operator [] ( int 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;
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;
result[i] -= current_use_count;
coupon_count[i] -= 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;
for ( int i = 1; i < EXPIRE_DAYS; ++i ) {
result[i - 1] = coupon_count[i];
}
result[EXPIRE_DAYS - 1] = c;
return result;
coupon_count[EXPIRE_DAYS - 1] = c;
}
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 () ) );
poisson_distribution < int > poisson ( lambda );
uniform_real_distribution < double > uniform ( 0.0, 1.0 );
State current_state;
long long total_cost = 0, used_coupon = 0;
for ( int day = 0; day < sim_days; ++day ) {
int current_cost = ( uniform ( rand_gen ) < prob_day ) ? poisson ( rand_gen ) : 0;
for ( int go_time = 0; go_time < sim_times; ++go_time ) {
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;
auto return_val = current_state.use_coupon ( current_cost );
used_coupon += return_val.second;
current_state = return_val.first.pass_day ( ( current_cost - return_val.second * COUPON_VALUE ) / COUPON_COST );
int current_coupon = current_state.use_coupon ( current_cost );
used_coupon += current_coupon;
current_state.add_coupon ( ( current_cost - current_coupon * COUPON_VALUE ) / COUPON_COST );
}
return ( static_cast < double > ( used_coupon * COUPON_VALUE ) / total_cost );
}
......@@ -16,12 +16,14 @@ public:
int operator [] ( int i ) const;
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:
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