[Optional] Custom policyΒΆ
It is possible to provide a custom policy in policy.h and policy.cpp. We will implement the decision rule as defined in Airplane MDP formulation.
First, we register the policy in mdp.cpp:
void MDP::RegisterPolicies(DynaPlex::Erasure::PolicyRegistry<MDP>& registry) const
{
registry.Register<RuleBasedPolicy>("rule_based",
"The heuristic rule");
}
Next, we implement policy.h, we implement the constructor and a function called GetAction(), which takes the state as input and outputs an action.
Furthermore, we define several variables that are parameters for tuning the policy.
namespace DynaPlex::Models {
namespace airplane /*must be consistent everywhere for complete mdp defininition and associated policies.*/
{
// Forward declaration
class MDP;
class RuleBasedPolicy
{
//this is the MDP defined inside the current namespace!
std::shared_ptr<const MDP> mdp;
const VarGroup varGroup;
double price_threshold_low;
double price_threshold_high;
int64_t seat_threshold_low;
int64_t seat_threshold_high;
int64_t remainingday_threshold;
public:
RuleBasedPolicy(std::shared_ptr<const MDP> mdp, const VarGroup& config);
int64_t GetAction(const MDP::State& state) const;
};
}
}
We can set the parameters in a seperate config file policy_config_0.json:
{
"id": "rule_based",
"price_threshold_low": 1000.0,
"price_threshold_high": 2000.0
}
Next, we implement the policy in policy.cpp:
...
//MDP and State refer to the specific ones defined in current namespace
RuleBasedPolicy::RuleBasedPolicy(std::shared_ptr<const MDP> mdp, const VarGroup& config)
:mdp{ mdp }
{
//provide default values and load parameters from json
config.GetOrDefault("price_threshold_low", price_threshold_low, 0.0);
config.GetOrDefault("price_threshold_high", price_threshold_high, 1.0);
//we can also set parameters directly in the constructor
seat_threshold_low = 1;
seat_threshold_high = 5;
remainingday_threshold = 9;
}
int64_t RuleBasedPolicy::GetAction(const MDP::State& state) const
{
if (state.RemainingSeats > seat_threshold_high)
{
return 1;//sell
}
if (state.PriceOfferedPerSeat > price_threshold_low)
{//only sell to type 1 and 2 customers
if (state.RemainingSeats <= seat_threshold_high && state.RemainingSeats >= seat_threshold_low)
{
if (state.RemainingDays <= remainingday_threshold)
{
return 1;//sell
}
}
}
if (state.PriceOfferedPerSeat > price_threshold_high)
{//only sell to type 1 customers
if (state.RemainingSeats <= seat_threshold_high && state.RemainingSeats >= seat_threshold_low)
{
if (state.RemainingDays > remainingday_threshold)
{
return 1;//sell
}
}
}
return 0;//no sales
}