强化学习+动态规划:杰克租车问题
问题描述
杰克管理一家有两个地点的租车公司。每一天,一些用户会到一个地点租车。如果杰克有可用的汽车,便会将其租出,并从全国总公司那里获得10美元的收益。如果他在那个地点没有汽车,便会失去这一次业务。租出去的汽车在还车的第二天变得可用。为了保证每辆车在需要的地方使用,杰克在夜间在两个地点之间移动车辆,移动每辆车的代价为2美元。该问题要求帮助杰克确定在不同情况下的移动车辆策略,使得杰克在该策略下的期望收益最大化。
引一波流
之前做这道题的时候发现网上的资料比较少。我自己就按照策略迭代和价值迭代写了一下,主要在知乎上面,可以点击以下链接访问
点我就可以啦
贴心地贴上代码:
from matplotlib import pyplot as plt
import numpy as np
from scipy.stats import poisson
import seaborn as sns
"""
Hyper parameters
<int> MAX_NUM: 每个停车场能停的最大数目(20)
<int> lam1_rent: 停车场1租车λ值(3)
<int> lam1_return: 停车场1还车λ值(3)
<int> lam2_rent: 停车场2租车λ值(4)
<int> lam2_return: 停车场2还车λ值(2)
<int> MAX_ACTION: 最大移动汽车数目(5)
<int> CAR_COST: 移动车辆的代价(2)
<int> CAR_EARNING: 租车的收入(10)
<float> DISCOUNT: 收益折扣(0.9)
<np.array> actions: 动作集合(-5,-4,…,4,5)
<int> POISSON_UPPER_BOUND: 限制泊松分布产生请求数目的上限
<dict> poisson_cache: 存储每个(n,λ)对应的泊松概率,key为n*(POISSON_UPPER_BOUND-1)+lam
"""
MAX_NUM = 20
lam1_rent = 3
lam1_return = 3
lam2_rent = 4
lam2_return = 2
MAX_ACTION = 5
DISCOUNT = 0.9
CAR_COST = 2
CAR_EARNING = 10
actions = np.arange(-MAX_ACTION, MAX_ACTION + 1)
POISSON_UPPER_BOUND = 11
poisson_cache = dict()
def poisson_prob(n, lam):
global poisson_cache
key = n * (POISSON_UPPER_BOUND - 1) + lam
if key not in poisson_cache:
poisson_cache[key] = poisson.pmf(n, lam)
return poisson_cache[key]
class dp:
def __init__(self):
self.v = np.ones((MAX_NUM + 1, MAX_NUM + 1), float)
self.actions = np.zeros((MAX_NUM + 1, MAX_NUM + 1), int)
self.gama = DISCOUNT
self.delta = 0
self.theta = 0.01
pass
def state_value(self, state, action, state_value, constant_returned_cars):
"""
:param state: 状态定义为每个地点的车辆数
:param action: 车辆的移动数量[-5,5],负:2->1,正:1->2
:param state_value: 状态价值矩阵
:param constant_returned_cars: 将换车的数目设定为泊松均值,替换为泊松概率分布
:return:
"""
# initial total return
returns = 0.0
# 移动车辆产生负收益
returns -= CAR_COST * abs(action)
# 移动后的车辆总数不能超过20
NUM_OF_CARS_1 = min(state[0] - action, MAX_NUM)
NUM_OF_CARS_2 = min(state[1] + action, MAX_NUM)
# 遍历两地全部的可能概率下(截断泊松概率)租车请求数目
for rent_1 in range(POISSON_UPPER_BOUND):
for rent_2 in range(POISSON_UPPER_BOUND):
# prob为两地租车请求的联合概率,概率为泊松分布
prob = poisson_prob(rent_1, lam1_rent) * poisson_prob(rent_2, lam2_rent)
# 两地原本汽车数量
num_of_cars_1 = NUM_OF_CARS_1
num_of_cars_2 = NUM_OF_CARS_2
# 有效租车数目必须小于等于该地原有的车辆数目
valid_rent_1 = min(num_of_cars_1, rent_1)
valid_rent_2 = min