Commit d39fb78b by Tianqi Yang

feat(markov): add markov chain simulator

parents
main
Debug
.vs
*.vcxproj*
/**
* consts.cpp
* Define the constants
*/
#include "consts.h"
const int EXPIRE_DAYS = 30;
const int COUPON_COST = 100;
const int COUPON_VALUE = 50;
/**
* consts.h
* Define the constants
*/
#pragma once
extern const int EXPIRE_DAYS;
extern const int COUPON_COST;
extern const int COUPON_VALUE;
#include <bits/stdc++.h>
#include "markov_chain.h"
using namespace std;
const int SIM_DAYS = 10000000;
int main ()
{
int lambda;
double p;
cin >> lambda >> p;
for ( int i = 0; i < 10; ++i ) {
cout << setprecision ( 13 ) << ( 1 - simulate_prob ( lambda, p, SIM_DAYS ) ) << endl;
}
}
\ No newline at end of file
/**
* markov_chain.cpp
* Calculate the percentage of the off-sale
*/
#include "markov_chain.h"
#include "consts.h"
#include <algorithm>
#include <numeric>
#include <random>
#include <chrono>
using namespace std;
State::State ()
: coupon_count ( EXPIRE_DAYS )
{
}
int State::operator [] ( int i ) const
{
return coupon_count[i];
}
int & State::operator [] ( int i )
{
return coupon_count[i];
}
pair<State, int> State::use_coupon ( int c ) const
{
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 );
c -= COUPON_COST * current_use_count;
result[i] -= current_use_count;
use_count += current_use_count;
}
return make_pair ( result, use_count );
}
State State::pass_day ( int c ) const
{
State result;
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 )
{
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;
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 );
}
return ( static_cast < double > ( used_coupon * COUPON_VALUE ) / total_cost );
}
/**
* markov_chain.h
* Calculate the percentage of the off-sale
*/
#pragma once
#include <utility>
#include <vector>
class State
{
public:
State ();
int operator [] ( int i ) const;
int & operator [] ( int i );
std::pair < State, int > use_coupon ( int c ) const;
State pass_day ( int c ) const;
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 );
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