[Python] RL problem - Car Rental Problem code check

Discussão em 'Python' iniciado por Stack, Junho 21, 2025.

  1. Stack

    Stack Membro Participativo

    I am trying to solve Jack's Car Rental problem in Barto and Sutton's Reinforcement Learning book: [​IMG]

    And after extensive debugging, my code is still incorrect. Great thanks to anyone who could spot some errors!

    Initialization


    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.colors import ListedColormap
    import math

    SIZE = 20
    states = np.zeros((SIZE+1,SIZE+1))
    policy = np.zeros((SIZE+1,SIZE+1))
    theta = 0.3
    gamma = 0.9

    Evaluation


    I tried to iterate through all (return, request) pairs, so that all the (s',r) pairs can be included.

    def gather_value(state, action):
    s1, s2 = state
    v_s = 0
    for req1 in range(s1+1):
    for req2 in range(s2+1):
    for ret1 in range(20-s1+1):
    for ret2 in range(20-s2+1):
    p = calculate_prob(req1, req2, ret1, ret2)

    reward, s1_prime, s2_prime = calculate_reward(req1, req2, s1, s2, ret1, ret2, action)

    if s1_prime > 20 or s2_prime > 20 or s1_prime < 0 or s2_prime < 0:
    continue

    v_s = v_s + p * (reward + gamma * states[int(s1_prime), int(s2_prime)])
    return v_s


    # The probability of the request and return values
    def calculate_prob(req1, req2, ret1, ret2):
    p1 = math.exp(-3) * 3**req1 / math.factorial(req1)
    p2 = math.exp(-4) * 4**req2 / math.factorial(req2)
    p3 = math.exp(-3) * 3**ret1 / math.factorial(ret1)
    p4 = math.exp(-2) * 2**ret2 / math.factorial(ret2)
    return p1 * p2 * p3 * p4

    def calculate_reward(req1, req2, s1, s2, ret1, ret2, action):
    avail1, avail2 = s1-action, s2+action
    avail1 = min(20, max(0, avail1))
    avail2 = min(20, max(0, avail2))
    rent1, rent2 = min(req1, avail1), min(req2, avail2)
    ret = -2 * abs(action)
    rental = (rent1 + rent2) * 10

    return ret + rental, min(20, s1-rent1+ret1), min(20, s2-rent2+ret2)


    Then,

    def policy_evaluation():
    break_loop = False
    while not break_loop:
    change = 0
    for i in range(SIZE+1):
    for j in range(SIZE+1):
    prev_state = states[i,j]
    states[i,j] = gather_value([i,j], policy[i,j])
    change = max(change, abs(prev_state - states[i,j]))
    if change < theta:
    break_loop = True

    Improvement


    def determine_action(state):
    max_value, max_action = -math.inf, 0
    for action in range(-5, 6):
    if not feasible(state, action):
    continue
    value = gather_value(state, action)
    # print("outside determine", value, max_value)
    if value > max_value:
    max_action = action
    max_value = value
    return max_action

    def feasible(state, action):
    s1, s2 = state
    a = abs(action)
    return (
    (action > 0 and s1 >= a and s2 + a <= 20) or
    (action <= 0 and s2 >= a and s1 + a <= 20)
    )


    Then,

    def policy_improvement():
    policy_stable = True
    for i in range(SIZE+1):
    for j in range(SIZE+1):
    old_action = policy[i,j]
    policy[i,j] = determine_action([i,j])
    if policy[i,j] != old_action:
    policy_stable = False

    if policy_stable:
    print("Iteration complete! ", states, policy)
    return True
    return False


    Then, there're a graphing and main() function:

    def show_graph(graph):
    # Create custom colormap matching the screenshot
    colors = [
    '#1a2c7b', '#2a4ca7', '#3a7bb7', '#5aa8c8', '#8ad2d1',
    '#c8e6be', '#f6f9c4', '#f9d77c', '#f9a76a', '#f86a5a', '#e93a4a'
    ]
    cmap = ListedColormap(colors)

    # Create plot
    plt.figure(figsize=(6, 6))
    plt.imshow(graph, cmap=cmap, vmin=-5, vmax=5, origin='lower', extent=[0, 20, 0, 20])
    plt.colorbar(ticks=range(-5, 6), label='Cars moved')
    plt.xlabel('Cars at location 2')
    plt.ylabel('Cars at location 1')
    plt.title('Optimal Policy')
    plt.show()


    and

    iter_count = 1
    while True:
    print("Start iteration: ", iter_count)
    policy_evaluation()
    if policy_improvement():
    break
    print("Finished iteration with policy: ", policy)
    show_graph(policy)
    iter_count += 1


    Sorry for the long post. I have been debugging this for nearly a day and thought about asking for help here. Any help is greatly appreciated!!

    The graph looks like this:

    [​IMG]

    but it is supposed to look like:

    [​IMG]

    I cannot find out where does the boundary problem occur, and how is the gradient in reverse of the expected graph.

    Continue reading...

Compartilhe esta Página