8 files
52.2 KB
15.2k tokens
10 symbols
1 requests
Download .txt
Repository: MathFoundationRL/Book-Mathematical-Foundation-of-Reinforcement-Learning
Branch: main
Commit: 25eb874a7680
Files: 8
Total size: 52.2 KB

Directory structure:
gitextract_pj0pi_9m/

├── Code for grid world/
│   ├── README.md
│   ├── matlab_version/
│   │   ├── figure_plot.m
│   │   └── main_example.m
│   └── python_version/
│       ├── examples/
│       │   ├── arguments.py
│       │   └── example_grid_world.py
│       └── src/
│           └── grid_world.py
├── Lecture slides/
│   └── Readme.md
└── Readme.md

================================================
FILE CONTENTS
================================================

================================================
FILE: Code for grid world/README.md
================================================
# Code for the Grid-World Environment 

## Overview

We added the code for the grid-world environment in my book. Interested readers can develop and test their own algorithms in this environment. Both Python and MATLAB versions are provided.

Please note that we do not provide the code of all the algorithms involved in the book. That is because they are the homework for the students in offline teaching: the students need to develop their own algorithms using the provided environment. Nevertheless, there are third-party implementations of some algorithms. Interested readers can check the links on the home page of the book.

I need to thank my PhD students, Yize Mi and Jianan Li, who are also the Teaching Assistants of my offline teaching. They contributed greatly to the code.

You are welcome to provide any feedback about the code such as bugs if detected.

----

## Python Version

### Requirements

- We support Python 3.7, 3.8, 3.9,  3.10 and 3.11. Make sure the following packages are installed: `numpy` and `matplotlib`.


### How to Run the Default Example

To run the example, please follow the procedures :

1. Change the directory to the file `examples/`

```bash
cd examples
```

2. Run the script:

```bash
python example_grid_world.py
```

You will see an animation as shown below:

- The blue star denotes the agent's current position within the grid world.
- The arrows on each grid illustrate the policy for that state. 
- The green line traces the agent's historical trajectory. 
- Obstacles are marked with yellow grids. 
- The target state is indicated by a blue grid. 
- The numerical values displayed on each grid represent the state values, which are initially generated as random numbers between 0 and 10. You may need to design your own algorithms to calculate these state values later on. 
- The horizontal number list above the grid world represents the horizontal coordinates (x-axis) of each grid.
- The vertical number list on the left side represents their vertical coordinates (y-axis).

![](python_version/plots/sample4.png)

### Customize the Parameters of the Grid World Environment

If you would like to customize your own grid world environment, please open `examples/arguments.py` and then change the following arguments:

"**env-size**", "**start-state**", "**target-state**", "**forbidden-states**", "**reward-target**", "**reward-forbidden**", "**reward-step**":

- "env-size" is represented as a tuple, where the first element represents the column index (horizontal coordinate), and the second element represents the row index (vertical coordinate).

- "start-state" denotes where the agent starts.

- "target-state" denotes the position of the target. 

- "forbidden-states" denotes the positions of obstacles. 

- "reward-target", "reward-forbidden" and "reward-step" represent the reward when reaching the target, the reward when entering a forbidden area, and the reward for each step, respectively.  

An example is shown below:

To specify the target state, modify the default value in the following sentence:

```python
parser.add_argument("--target-state", type=Union[list, tuple, np.ndarray], default=(4,4))
```

Please note that the coordinate system used for all states within the environment—such as the start state, target state, and forbidden states—adheres to the conventional Python setup. In this system, the point `(0, 0)` is commonly designated as the origin of coordinates.



If you want to save figures in each step, please modify the "debug" argument to  "True":

```bash
parser.add_argument("--debug", type=bool, default=True)
```



### Create an Instance

If you would like to use the grid world environment to test your own RL algorithms, it is necessary to create an instance. The procedure for creating an instance and interacting with it can be found in `examples/example_grid_world.py`:

```python
from src.grid_world import GridWorld

 	env = GridWorld()
    state = env.reset()               
    for t in range(20):
        env.render()
        action = np.random.choice(env.action_space)
        next_state, reward, done, info = env.step(action)
        print(f"Step: {t}, Action: {action}, Next state: {next_state+(np.array([1,1]))}, Reward: {reward}, Done: {done}")

```

![](python_version/plots/sample1.png)

- The policy is constructed as a matrix form shown below, which can be designed to be deterministic or stochastic. The example is a stochastic version:


 ```python
     # Add policy
     policy_matrix=np.random.rand(env.num_states,len(env.action_space))                                       
     policy_matrix /= policy_matrix.sum(axis=1)[:, np.newaxis] 
 ```

- Moreover, to change the shape of the arrows, you can open `src/grid_world.py`:


 ```python
self.ax.add_patch(patches.FancyArrow(x, y, dx=(0.1+action_probability/2)*dx, dy=(0.1+action_probability/2)*dy, color=self.color_policy, width=0.001, head_width=0.05))   
 ```



![](python_version/plots/sample2.png)

-  To add state value to each grid:


```python
values = np.random.uniform(0,10,(env.num_states,))
env.add_state_values(values)
```

![](python_version/plots/sample3.png)

- To render the environment:


```python
env.render(animation_interval=3)    # the figure will stop for 3 seconds
```

------

## MATLAB Version

### Requirements

- MATLAB >= R2020a, in order to implement the function *exportgraphics()*.

### How to Run the Default Example

Please start the m-file `main.m`. 

Four figures will be generated: 

The first figure is to show the policy: The length of an arrow is proportional to the probability of choosing this action, and the circle represents the agent would stay still. The meanings of other graphics and colors in this visualization are consistent with those used in Python.

<img src="matlab_version/policy_offline_Q_learning.jpg" alt="policy_offline_Q_learning" style="zoom:67%;" />

The shape of the arrow can be customized in `figure_plot_1.m`

```matlab
function drawPolicyArrow(kk, ind, i_bias, j_bias, kk_new, ratio, greenColor, action)
    % Obtain the action vector
    action = action{kk};

    % For the non-moving action, draw a circle
    if action(1) == 0 && action(2) == 0  % Assuming the fifth action is to stay
        plot(i_bias(ind), j_bias(ind), 'o', 'MarkerSize', 8, 'linewidth', 2, 'color', greenColor);
        return;
    else
        arrow = annotation('arrow', 'Position', [i_bias(ind), j_bias(ind), ratio * kk_new * action(1), - ratio * kk_new * action(2)], 'LineStyle', '-', 'Color', greenColor, 'LineWidth', 2);
        arrow.Parent = gca;
    end
end
```

The second and the third figures are used to draw the trajectory in two different manners: The former is for the trajectory generated by a stochastic policy. The latter is provided to show the deterministic trajectory. 

<img src="matlab_version/trajectory_Q_learning.jpg" alt="trajectory_Q_learning" style="zoom:67%;" />

<img src="matlab_version/trajectory_Bellman_Equation_dotted.jpg" alt="trajectory_Bellman_Equation_dotted" style="zoom:67%;" />

The fourth figure is used to show the state value for each state. 

<img src="matlab_version/trajectory_Bellman_Equation.jpg" alt="trajectory_Bellman_Equation" style="zoom:67%;" />

### Code Description

- The main reinforcement learning algorithm is shown below:


```matlab
for step = 1:episode_length
    action = stochastic_policy(state_history(step, :), action_space, policy, x_length, y_length);   
    % Calculate the new state and reward
    [new_state, reward] = next_state_and_reward(state_history(step, :), action, x_length, y_length, final_state, obstacle_state, reward_forbidden, reward_target, reward_step);
    % Update state and reward history
    state_history(step+1, :) = new_state;
    reward_history(step) = reward;
end
```

- The policy is shown as:


```matlab
function action = stochastic_policy(state, action_space, policy, x_length, y_length)
    % Extract the action space and policy for a specific state
    state_1d = x_length * (state(2)-1) + state(1); 
    actions = action_space{state_1d};
    policy_i = policy(state_1d, :);

    % Ensure the sum of policy probabilities is 1
    assert(sum(policy_i) == 1, 'The sum of policy probabilities must be 1.');
    
    % Generate a random index based on policy probabilities
    action_index = randsrc(1, 1, [1:length(actions); policy_i]);
    
    % Select an action
    action = actions{action_index};
end
```

- The state transition function is shown below:


```matlab
function [new_state, reward] = next_state_and_reward(state, action, x_length, y_length, target_state, obstacle_state, reward_forbidden, reward_target, reward_step)
    new_x = state(1) + action(1);
    new_y = state(2) + action(2);
    new_state = [new_x, new_y];

    % Check if the new state is out of bounds
    if new_x < 1 || new_x > x_length || new_y < 1 || new_y > y_length
        new_state = state;
        reward = reward_forbidden;
    elseif ismember(new_state, obstacle_state, 'rows')
        % If the new state is an obstacle
        reward = reward_forbidden;
    elseif isequal(new_state, target_state)
        % If the new state is the target state
        reward = reward_target;
    else
         % If the new state is a normal cell
        reward = reward_step;
    end
end
```


================================================
FILE: Code for grid world/matlab_version/figure_plot.m
================================================
% by the Intelligent Unmanned Systems Laboratory, Westlake University, 2024

function figure_plot(x_length, y_length, agent_state,final_state, obstacle_state, state_value, state_number, episode_length,state_update_2d,policy, action)
    %% Inverse y coordinate
 
    
    xa_used = agent_state(:, 1) + 0.5;
    ya_used = y_length+1-agent_state(:, 2) + 0.5;
    
    
    state_space=x_length*y_length;
    
    
    xf = final_state(:, 1);
    yf = y_length+1-final_state(:, 2); 
    
    
    
    xo = obstacle_state(:, 1);
    yo = y_length+1-obstacle_state(:, 2);
    
    
    
    xs = state_update_2d(:, 1); 
    ys = state_update_2d(:, 2);
    
    state_update = (ys-1) * x_length + xs; 
                                                        
    
    
    %%
    
    greenColor=[0.4660 0.6740 0.1880]*0.8;
    
    
    
    % Initialize the figure
    figure();
    
    
    % Add labels on the axes
    addAxisLabels(x_length, y_length);
    
    % Draw the grid, state values, and policy arrows
    r = drawGridStateValuesAndPolicy(x_length, y_length, state_number, state_value, policy, greenColor, action);
    
    % Color the obstacles and the final state
    colorObstacles(xo, yo, r);
    colorFinalState(xf, yf, r);
    
    % Draw the agent
    agent = plot(xa_used, ya_used, '*', 'markersize', 15, 'linewidth', 2, 'color', 'b');  
    hold on;
    
    axis equal
    axis off
    exportgraphics(gca,'policy_offline_Q_learning.pdf') 
    
    
    
    % Initialize the figure
    figure();
    
    % Add labels on the axes
    addAxisLabels(x_length, y_length);
    
    % Draw the grid and add state values
    r = drawGridAndStateValues(x_length, y_length, state_value);
    
    % Color the obstacles and the final state
    colorObstacles(xo, yo, r);
    colorFinalState(xf, yf, r);
    
    % Compute the de-normalized states
    for i = 1:state_space
        state_two_dimension_new(i, :) = de_normalized_state(state_number(i), x_length, y_length);
    end
    
    
    % Draw the agent
    agent = plot(xa_used, ya_used, '*', 'markersize', 15, 'linewidth', 2, 'color', 'b');
    hold on;
    
    
    % Set axis properties and export the figure
    axis equal;
    axis off;
    exportgraphics(gca, 'trajectory_Bellman_Equation.pdf');
    
    
    
    
    
    
    % Initialize the figure
    figure();
    
    % Add labels on the axes
    addAxisLabels(x_length, y_length);
    
    % Draw the grid and add state values
    r= drawGridAndStateValues(x_length, y_length, state_value);
    
    % Draw state transitions
    for i=1:state_space
        state_two_dimension_new(i,:)=de_normalized_state(state_number(i),x_length,y_length);
    end
    drawStateTransitions(state_space, state_update, state_two_dimension_new, episode_length);
    
    % Color the obstacles and the final state
    
    
    colorObstacles(xo, yo, r);
    colorFinalState(xf, yf, r);
    
    
    % Draw the agent
    agent = plot(xa_used, ya_used, '*', 'markersize', 15, 'linewidth', 2, 'color', 'b');
    hold on;
    
    
    % Set axis properties and export the figure
    axis equal;
    axis off;
    exportgraphics(gca, 'trajectory_Q_learning.pdf');
    
    
    
    
    % Initialize the figure
    figure();
    
    % Add labels on the axes
    addAxisLabels(x_length, y_length);
    
    % Draw the grid and add state values
    r = drawGridAndStateValues(x_length, y_length, state_value);
    
    % Color the obstacles and the final state
    colorObstacles(xo, yo, r);
    colorFinalState(xf, yf, r);
    
    % Compute the de-normalized states
    for i = 1:state_space
        state_two_dimension_new(i, :) = de_normalized_state(state_number(i), x_length, y_length);
    end
    
    % Draw transitions between states
    for i = 1:episode_length - 1
        line([state_two_dimension_new(state_update(i), 1) + 0.5, state_two_dimension_new(state_update(i + 1), 1) + 0.5], ...
             [state_two_dimension_new(state_update(i), 2) + 0.5, state_two_dimension_new(state_update(i + 1), 2) + 0.5], ...
             'Color', 'black', 'LineStyle', '--');
        hold on;
    end
    
    % Draw the agent
    agent = plot(xa_used, ya_used, '*', 'markersize', 15, 'linewidth', 2, 'color', 'b');
    hold on;
    
    
    % Set axis properties and export the figure
    axis equal;
    axis off;
    exportgraphics(gca, 'trajectory_Bellman_Equation.pdf');
    
    % Function definitions would be the same as provided previously


end



function o=de_normalized_state(each_state,x_length,y_length)

         o=[mod(each_state-1,x_length),y_length-1-fix((each_state-1)/(x_length))]+[1,1];
end




function addAxisLabels(x_length, y_length)
    for i = 1:x_length
        text(i + 0.5, y_length + 1.1, num2str(i));
    end
    for j = y_length:-1:1
        text(0.9, j + 0.5, num2str(y_length - j + 1));
    end
end

function r= drawGridStateValuesAndPolicy(x_length, y_length, state_number, state_value, policy, greenColor, action)
    ind = 0;
    ratio = 0.5; % adjust the length of arrow
    state_coordinate = zeros(x_length * y_length, 2); % Initialize state_coordinate
    for j = y_length:-1:1       
        for i = 1:x_length      
            r(i, j) = rectangle('Position', [i j 1 1]);
            ind = ind + 1;
            state_coordinate(state_number(ind), :) = [i, j];
            text(i + 0.4, j + 0.5, ['s', num2str(ind)]);
            hold on;
            
            % Calculate bias
            i_bias(ind) = state_coordinate(state_number(ind), 1) + 0.5;
            j_bias(ind) = state_coordinate(state_number(ind), 2) + 0.5;
            
            % Draw policy arrows or state markers
            for kk = 1:size(policy, 2)
                if policy(state_number(ind), kk) ~= 0
                    kk_new = policy(state_number(ind), kk) / 2 + 0.5;
                    drawPolicyArrow(kk, ind, i_bias, j_bias, kk_new, ratio, greenColor, action);                
                end
            end
        end
    end
end


function drawPolicyArrow(kk, ind, i_bias, j_bias, kk_new, ratio, greenColor, action)
    % Obtain the action vector
    action = action{kk};

    % For the non-moving action, draw a circle to represent the stay state
    if action(1) == 0 && action(2) == 0  % Assuming the fifth action is to stay
        plot(i_bias(ind), j_bias(ind), 'o', 'MarkerSize', 8, 'linewidth', 2, 'color', greenColor);
        return;
    else
        % Draw an arrow to represent the moving action; note that '-' used when drawing the y-axis arrow ensures consistency with the inverse y-coordinate handling.
        arrow = annotation('arrow', 'Position', [i_bias(ind), j_bias(ind), ratio * kk_new * action(1), - ratio * kk_new * action(2)], 'LineStyle', '-', 'Color', greenColor, 'LineWidth', 2);
        arrow.Parent = gca;
    end
end


% Function to draw the grid and add state values
function r = drawGridAndStateValues(x_length, y_length, state_value)
    ind = 0;
    for j = y_length:-1:1       
        for i = 1:x_length       
            r(i, j) = rectangle('Position', [i j 1 1]);
            ind = ind + 1;
            text(i + 0.4, j + 0.5, num2str(round(state_value(ind), 2)));
            hold on;           
        end
    end
end

% Function to color the obstacles
function colorObstacles(xo, yo, r)
    for i = 1:length(xo)
        r(xo(i), yo(i)).FaceColor = [0.9290 0.6940 0.1250];
    end
end

% Function to color the final state
function colorFinalState(xf, yf, r)
    r(xf, yf).FaceColor = [0.3010 0.7450 0.9330];
end

% Function to draw state transitions
function drawStateTransitions(state_space, state_update, state_two_dimension_new, episode_length)
    for i = 1:episode_length - 1
        if state_two_dimension_new(state_update(i), 2) ~= state_two_dimension_new(state_update(i + 1), 2)       
            line([state_two_dimension_new(state_update(i), 1) + 0.5, state_two_dimension_new(state_update(i), 1) + 0.5 + 0.03 * randn(1), state_two_dimension_new(state_update(i + 1), 1) + 0.5 + 0.03 * randn(1), state_two_dimension_new(state_update(i + 1), 1) + 0.5], ...
                 [state_two_dimension_new(state_update(i), 2) + 0.5, state_two_dimension_new(state_update(i), 2) + 0.25 + 0.03 * randn(1), state_two_dimension_new(state_update(i + 1), 2) + 0.75 + 0.03 * randn(1), state_two_dimension_new(state_update(i + 1), 2) + 0.5], ...
                 'Color', 'green');
        elseif state_two_dimension_new(state_update(i), 1) ~= state_two_dimension_new(state_update(i + 1), 1)       
            line([state_two_dimension_new(state_update(i), 1) + 0.5, state_two_dimension_new(state_update(i), 1) + 0.25 + 0.03 * randn(1), state_two_dimension_new(state_update(i + 1), 1) + 0.75 + 0.03 * randn(1), state_two_dimension_new(state_update(i + 1), 1) + 0.5], ...
                 [state_two_dimension_new(state_update(i), 2) + 0.5, state_two_dimension_new(state_update(i), 2) + 0.5 + 0.03 * randn(1), state_two_dimension_new(state_update(i + 1), 2) + 0.5 + 0.03 * randn(1), state_two_dimension_new(state_update(i + 1), 2) + 0.5], ...
                 'Color', 'green');
        end
        hold on;
    end
end




================================================
FILE: Code for grid world/matlab_version/main_example.m
================================================
% by the Intelligent Unmanned Systems Laboratory, Westlake University, 2024

clear 
close all

% Initialize environment parameters
agent_state = [1, 1];
final_state = [3, 3];
obstacle_state = [1, 3; 2, 1; 1, 2];
x_length = 3;
y_length = 4;
state_space = x_length * y_length; 
state=1:state_space;
state_value=ones(state_space,1);

reward_forbidden = -1;
reward_target = 1;
reward_step = 0;

% Define actions: up, right, down, left, stay
actions = {[0, -1], [1, 0], [0, 1], [-1, 0], [0, 0]};

% Initialize a cell array to store the action space for each state
action_space = cell(state_space, 1);

% Populate the action space
for i = 1:state_space       
    action_space{i} = actions;
end

number_of_action=5;

policy=zeros(state_space, number_of_action); % policy can be deterministic or stochastic, shown as follows:




% stochastic policy 

for i=1:state_space
    policy(i,:)=.2;          
end
% policy(3,2)=0; policy(3,4)=.4;
% policy(5,5)=0; policy(5,3)=.4;
policy(7,3)=1; policy(7,4)= 0; policy(7,2)= 0; policy(7,1)= 0; policy(7,5)= 0;
% policy(6,2)=0; policy(6,3) = 1; policy(6,4) = 0; policy(6,5) = 0; policy (6,1) = 0;




% Initialize the episode
episode_length = 1000;

state_history = zeros(episode_length, 2); 
reward_history = zeros(episode_length, 1);  

% Set the initial state
state_history(1, :) = agent_state;

for step = 1:episode_length
    action = stochastic_policy(state_history(step, :), action_space, policy, x_length, y_length);   
    % Calculate the new state and reward
    [new_state, reward] = next_state_and_reward(state_history(step, :), action, x_length, y_length, final_state, obstacle_state, reward_forbidden, reward_target, reward_step);
    % Update state and reward history
    state_history(step+1, :) = new_state;
    reward_history(step) = reward;
end

figure_plot(x_length, y_length, agent_state, final_state, obstacle_state, state_value, state, episode_length, state_history, policy, actions);

%%   useful function 
function [new_state, reward] = next_state_and_reward(state, action, x_length, y_length, target_state, obstacle_state, reward_forbidden, reward_target, reward_step)
    new_x = state(1) + action(1);
    new_y = state(2) + action(2);
    new_state = [new_x, new_y];

    % Check if the new state is out of bounds
    if new_x < 1 || new_x > x_length || new_y < 1 || new_y > y_length
        new_state = state;
        reward = reward_forbidden;
    elseif ismember(new_state, obstacle_state, 'rows')
        % If the new state is an obstacle
        reward = reward_forbidden;
    elseif isequal(new_state, target_state)
        % If the new state is the target state
        reward = reward_target;
    else
         % If the new state is a normal cell
        reward = reward_step;
    end
end

function action = stochastic_policy(state, action_space, policy, x_length, y_length)
    % Extract the action space and policy for a specific state
    state_1d = x_length * (state(2)-1) + state(1); 
    actions = action_space{state_1d};
    policy_i = policy(state_1d, :);

    % Ensure the sum of policy probabilities is 1
    assert(sum(policy_i) == 1, 'The sum of policy probabilities must be 1.');
    
    % Generate a random index based on policy probabilities
    action_index = randsrc(1, 1, [1:length(actions); policy_i]);
    
    % Select an action
    action = actions{action_index};
end


================================================
FILE: Code for grid world/python_version/examples/arguments.py
================================================
__credits__ = ["Intelligent Unmanned Systems Laboratory at Westlake University."]
'''
Specify parameters of the env
'''
from typing import Union
import numpy as np
import argparse

parser = argparse.ArgumentParser("Grid World Environment")

## ==================== User settings ===================='''
# specify the number of columns and rows of the grid world
parser.add_argument("--env-size", type=Union[list, tuple, np.ndarray], default=(5,5) )   

# specify the start state
parser.add_argument("--start-state", type=Union[list, tuple, np.ndarray], default=(2,2))

# specify the target state
parser.add_argument("--target-state", type=Union[list, tuple, np.ndarray], default=(4,4))

# sepcify the forbidden states
parser.add_argument("--forbidden-states", type=list, default=[ (2, 1), (3, 3), (1, 3)] )

# sepcify the reward when reaching target
parser.add_argument("--reward-target", type=float, default = 10)

# sepcify the reward when entering into forbidden area
parser.add_argument("--reward-forbidden", type=float, default = -5)

# sepcify the reward for each step
parser.add_argument("--reward-step", type=float, default = -1)
## ==================== End of User settings ====================


## ==================== Advanced Settings ====================
parser.add_argument("--action-space", type=list, default=[(0, 1), (1, 0), (0, -1), (-1, 0), (0, 0)] )  # down, right, up, left, stay           
parser.add_argument("--debug", type=bool, default=False)
parser.add_argument("--animation-interval", type=float, default = 0.2)
## ==================== End of Advanced settings ====================


args = parser.parse_args()     
def validate_environment_parameters(env_size, start_state, target_state, forbidden_states):
    if not (isinstance(env_size, tuple) or isinstance(env_size, list) or isinstance(env_size, np.ndarray)) and len(env_size) != 2:
        raise ValueError("Invalid environment size. Expected a tuple (rows, cols) with positive dimensions.")
    
    for i in range(2):
        assert start_state[i] < env_size[i]
        assert target_state[i] < env_size[i]
        for j in range(len(forbidden_states)):
            assert forbidden_states[j][i] < env_size[i]
try:
    validate_environment_parameters(args.env_size, args.start_state, args.target_state, args.forbidden_states)
except ValueError as e:
    print("Error:", e)

================================================
FILE: Code for grid world/python_version/examples/example_grid_world.py
================================================

import sys
sys.path.append("..")
from src.grid_world import GridWorld
import random
import numpy as np

# Example usage:
if __name__ == "__main__":             
    env = GridWorld()
    state = env.reset()               
    for t in range(1000):
        env.render()
        action = random.choice(env.action_space)
        next_state, reward, done, info = env.step(action)
        print(f"Step: {t}, Action: {action}, State: {next_state+(np.array([1,1]))}, Reward: {reward}, Done: {done}")
        # if done:
        #     break
    
    # Add policy
    policy_matrix=np.random.rand(env.num_states,len(env.action_space))                                            
    policy_matrix /= policy_matrix.sum(axis=1)[:, np.newaxis]  # make the sum of elements in each row to be 1

    env.add_policy(policy_matrix)

    
    # Add state values
    values = np.random.uniform(0,10,(env.num_states,))
    env.add_state_values(values)

    # Render the environment
    env.render(animation_interval=2)

================================================
FILE: Code for grid world/python_version/src/grid_world.py
================================================
__credits__ = ["Intelligent Unmanned Systems Laboratory at Westlake University."]

import sys    
sys.path.append("..")         
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches          
from examples.arguments import args           

class GridWorld():

    def __init__(self, env_size=args.env_size, 
                 start_state=args.start_state, 
                 target_state=args.target_state, 
                 forbidden_states=args.forbidden_states):

        self.env_size = env_size
        self.num_states = env_size[0] * env_size[1]
        self.start_state = start_state
        self.target_state = target_state
        self.forbidden_states = forbidden_states

        self.agent_state = start_state
        self.action_space = args.action_space          
        self.reward_target = args.reward_target
        self.reward_forbidden = args.reward_forbidden
        self.reward_step = args.reward_step

        self.canvas = None
        self.animation_interval = args.animation_interval


        self.color_forbid = (0.9290,0.6940,0.125)
        self.color_target = (0.3010,0.7450,0.9330)
        self.color_policy = (0.4660,0.6740,0.1880)
        self.color_trajectory = (0, 1, 0)
        self.color_agent = (0,0,1)



    def reset(self):
        self.agent_state = self.start_state
        self.traj = [self.agent_state] 
        return self.agent_state, {}


    def step(self, action):
        assert action in self.action_space, "Invalid action"

        next_state, reward  = self._get_next_state_and_reward(self.agent_state, action)
        done = self._is_done(next_state)

        x_store = next_state[0] + 0.03 * np.random.randn()
        y_store = next_state[1] + 0.03 * np.random.randn()
        state_store = tuple(np.array((x_store,  y_store)) + 0.2 * np.array(action))
        state_store_2 = (next_state[0], next_state[1])

        self.agent_state = next_state

        self.traj.append(state_store)   
        self.traj.append(state_store_2)
        return self.agent_state, reward, done, {}   
    
        
    def _get_next_state_and_reward(self, state, action):
        x, y = state
        new_state = tuple(np.array(state) + np.array(action))
        if y + 1 > self.env_size[1] - 1 and action == (0,1):    # down
            y = self.env_size[1] - 1
            reward = self.reward_forbidden  
        elif x + 1 > self.env_size[0] - 1 and action == (1,0):  # right
            x = self.env_size[0] - 1
            reward = self.reward_forbidden  
        elif y - 1 < 0 and action == (0,-1):   # up
            y = 0
            reward = self.reward_forbidden  
        elif x - 1 < 0 and action == (-1, 0):  # left
            x = 0
            reward = self.reward_forbidden 
        elif new_state == self.target_state:  # stay
            x, y = self.target_state
            reward = self.reward_target
        elif new_state in self.forbidden_states:  # stay
            x, y = state
            reward = self.reward_forbidden        
        else:
            x, y = new_state
            reward = self.reward_step
            
        return (x, y), reward
        

    def _is_done(self, state):
        return state == self.target_state
    

    def render(self, animation_interval=args.animation_interval):
        if self.canvas is None:
            plt.ion()                             
            self.canvas, self.ax = plt.subplots()   
            self.ax.set_xlim(-0.5, self.env_size[0] - 0.5)
            self.ax.set_ylim(-0.5, self.env_size[1] - 0.5)
            self.ax.xaxis.set_ticks(np.arange(-0.5, self.env_size[0], 1))     
            self.ax.yaxis.set_ticks(np.arange(-0.5, self.env_size[1], 1))     
            self.ax.grid(True, linestyle="-", color="gray", linewidth="1", axis='both')          
            self.ax.set_aspect('equal')
            self.ax.invert_yaxis()                           
            self.ax.xaxis.set_ticks_position('top')           
            
            idx_labels_x = [i for i in range(self.env_size[0])]
            idx_labels_y = [i for i in range(self.env_size[1])]
            for lb in idx_labels_x:
                self.ax.text(lb, -0.75, str(lb+1), size=10, ha='center', va='center', color='black')           
            for lb in idx_labels_y:
                self.ax.text(-0.75, lb, str(lb+1), size=10, ha='center', va='center', color='black')
            self.ax.tick_params(bottom=False, left=False, right=False, top=False, labelbottom=False, labelleft=False,labeltop=False)   

            self.target_rect = patches.Rectangle( (self.target_state[0]-0.5, self.target_state[1]-0.5), 1, 1, linewidth=1, edgecolor=self.color_target, facecolor=self.color_target)
            self.ax.add_patch(self.target_rect)     

            for forbidden_state in self.forbidden_states:
                rect = patches.Rectangle((forbidden_state[0]-0.5, forbidden_state[1]-0.5), 1, 1, linewidth=1, edgecolor=self.color_forbid, facecolor=self.color_forbid)
                self.ax.add_patch(rect)

            self.agent_star, = self.ax.plot([], [], marker = '*', color=self.color_agent, markersize=20, linewidth=0.5) 
            self.traj_obj, = self.ax.plot([], [], color=self.color_trajectory, linewidth=0.5)

        # self.agent_circle.center = (self.agent_state[0], self.agent_state[1])
        self.agent_star.set_data([self.agent_state[0]],[self.agent_state[1]])       
        traj_x, traj_y = zip(*self.traj)         
        self.traj_obj.set_data(traj_x, traj_y)

        plt.draw()
        plt.pause(animation_interval)
        if args.debug:
            input('press Enter to continue...')     


 
    def add_policy(self, policy_matrix):                  
        for state, state_action_group in enumerate(policy_matrix):    
            x = state % self.env_size[0]
            y = state // self.env_size[0]
            for i, action_probability in enumerate(state_action_group):
                if action_probability !=0:
                    dx, dy = self.action_space[i]
                    if (dx, dy) != (0,0):
                        self.ax.add_patch(patches.FancyArrow(x, y, dx=(0.1+action_probability/2)*dx, dy=(0.1+action_probability/2)*dy, color=self.color_policy, width=0.001, head_width=0.05))
                    else:
                        self.ax.add_patch(patches.Circle((x, y), radius=0.07, facecolor=self.color_policy, edgecolor=self.color_policy, linewidth=1, fill=False))
    
    def add_state_values(self, values, precision=1):
        '''
            values: iterable
        '''
        values = np.round(values, precision)
        for i, value in enumerate(values):
            x = i % self.env_size[0]
            y = i // self.env_size[0]
            self.ax.text(x, y, str(value), ha='center', va='center', fontsize=10, color='black')

================================================
FILE: Lecture slides/Readme.md
================================================
My lecture slides are put into two folders.

- The folder "slidesForMyLectureVideos" contains all **the slides that I used to record my lecture videos**.

- The folder "slidesContinuouslyUpdated" contains **the slides that I updated continuously**.

The slides in the two folders are very similar, but there are some minor differences, such as typo correction and content adjustment.

**If you are not studying my online lecture videos, I suggest you check the slides in the slidesContinuouslyUpdated folder since they have been improved continuously.**



================================================
FILE: Readme.md
================================================
# (Oct 2025) Latex source code of my slides

If you are a professor preparing a course and would like to use any content from my slides, feel free to reach out by email. I can share the source code with you. The slides were created using Latex/Beamer.

Regarding reader feedback and questions in the discussion section, please note that due to a high volume of commitments, there may be significant delays in my response. Your understanding would be greatly appreciated.

***
***

# Why a new book on reinforcement learning?

This book aims to provide a **mathematical but friendly** introduction to the fundamental concepts, basic problems, and classic algorithms in reinforcement learning. Some essential features of this book are highlighted as follows.

- The book introduces reinforcement learning from a mathematical point of view. Hopefully, readers will not only know the procedure of an algorithm but also understand why it was designed in the first place and why it works effectively.

- The depth of the mathematics is carefully controlled to an adequate level. The mathematics is also presented in a carefully designed manner to ensure that the book is friendly to read. Readers can selectively read the materials presented in gray boxes according to their interests.

- Many illustrative examples are given to help readers better understand the topics. All the examples in this book are based on a grid world task, which is easy to understand and helpful for illustrating concepts and algorithms.

- When introducing an algorithm, the book aims to separate its core idea from complications that may be distracting. In this way, readers can better grasp the core idea of an algorithm.

- The contents of the book are coherently organized. Each chapter is built based on the preceding chapter and lays a necessary foundation for the subsequent one.

[![Book cover](./Readme_Images/BookCoverSpringer.png)](https://link.springer.com/book/9789819739431)

# Contents

The topics addressed in the book are shown in the figure below. This book contains ten chapters, which can be classified into two parts: the first part is about basic tools, and the second part is about algorithms. The ten chapters are highly correlated. In general, it is necessary to study the earlier chapters first before the later ones.

![The map of this book](./Readme_Images/BookMap.png)


# Readership

This book is designed for senior undergraduate students, graduate students, researchers, and practitioners interested in reinforcement learning.

It does not require readers to have any background in reinforcement learning because it starts by introducing the most basic concepts. If the reader already has some background in reinforcement learning, I believe the book can help them understand some topics more deeply or provide different perspectives.

This book, however, requires the reader to have some knowledge of probability theory and linear algebra. Some basics of the required mathematics are also included in the appendix of this book.

# About the author
You can find my info on my homepage https://www.shiyuzhao.net (GoogleSite) and my research group website https://shiyuzhao.westlake.edu.cn

I have been teaching a graduate-level course on reinforcement learning since 2019. Along with teaching, I have been preparing this book as the lecture notes for my students. 

I sincerely hope this book can help readers smoothly enter the exciting field of reinforcement learning.

# Citation

```
@book{zhao2025RLBook,
  title={Mathematical Foundations of Reinforcement Learning},
  author={S. Zhao},
  year={2025},
  publisher={Springer Press}
}
```
# Lecture videos 

The lecture videos have received **2,100,000+ views** over the Internet and received very good feedback!
By combining the book with my lecture videos, I believe you can study better. 

- **Chinese lecture videos:** You can check the [Bilibili channel](https://space.bilibili.com/2044042934) or the [Youtube channel](https://www.youtube.com/channel/UCztGtS5YYiNv8x3pj9hLVgg/playlists).
- **English lecture videos:** The English lecture videos have been uploaded to YouTube: [link here](https://youtube.com/playlist?list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&si=D1T4pcyHsMxj6CzB)

[![](./Readme_Images/EnglishLectureVideo.png)](https://youtube.com/playlist?list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&si=B6mRR7vxBAjRAm_F)

- [Overview of Reinforcement Learning in 30 Minutes](https://www.youtube.com/watch?v=ZHMWHr9811U&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=1)
- [L1: Basic Concepts (P1-State, action, policy, ...)](https://www.youtube.com/watch?v=zJHtM5dN69g&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=2)
- [L1: Basic Concepts (P2-Reward,return, Markov decision process)](https://www.youtube.com/watch?v=repVl3_GYCI&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=3)
- [L2: Bellman Equation (P1-Motivating examples)](https://www.youtube.com/watch?v=XCzWrlgZCwc&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=4)
- [L2: Bellman Equation (P2-State value)](https://www.youtube.com/watch?v=DSvi3xEN13I&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=5)
- [L2: Bellman Equation (P3-Bellman equation-Derivation)](https://www.youtube.com/watch?v=eNtId8yPWkA&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=6)
- [L2: Bellman Equation (P4-Matrix-vector form and solution)](https://www.youtube.com/watch?v=EtCfBG_eP2w&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=7)
- [L2: Bellman Equation (P5-Action value)](https://www.youtube.com/watch?v=zJo2sLDzfcU&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=8)
- [L3: Bellman Optimality Equation (P1-Motivating example)](https://www.youtube.com/watch?v=lXKY_Hyg4SQ&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=9)
- [L3: Bellman Optimality Equation (P2-Optimal policy)](https://www.youtube.com/watch?v=BxyjdHhK8a8&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=10)
- [L3: Bellman Optimality Equation (P3-More on BOE)](https://www.youtube.com/watch?v=FXftTCKotC8&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=11)
- [L3: Bellman Optimality Equation (P4-Interesting properties)](https://www.youtube.com/watch?v=a--bck2ow9s&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=12)
- [L4: Value Iteration and Policy Iteration (P1-Value iteration)](https://www.youtube.com/watch?v=wMAVmLDIvQU&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=13)
- [L4: Value Iteration and Policy Iteration (P2-Policy iteration)](https://www.youtube.com/watch?v=Pka6Om0nYQ8&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=14)
- [L4: Value Iteration and Policy Iteration (P3-Truncated policy iteration)](https://www.youtube.com/watch?v=tUjPFPD3Vc8&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=15)
- [L5: Monte Carlo Learning (P1-Motivating examples)](https://www.youtube.com/watch?v=DO1yXinAV_Q&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=16)
- [L5: Monte Carlo Learning (P2-MC Basic-introduction)](https://www.youtube.com/watch?v=6ShisunU0zs&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=17)
- [L5: Monte Carlo Learning (P3-MC Basic-examples)](https://www.youtube.com/watch?v=axA0yns9FxU&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=18)
- [L5: Monte Carlo Learning (P4-MC Exploring Starts)](https://www.youtube.com/watch?v=Qt8OMHPkLqg&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=19)
- [L5: Monte Carlo Learning (P5-MC Epsilon-Greedy-introduction)](https://www.youtube.com/watch?v=dM3fYE630pY&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=20)
- [L5: Monte Carlo Learning (P6-MC Epsilon-Greedy-examples)](https://www.youtube.com/watch?v=x6X_5ePT9gQ&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=21)
- [L6: Stochastic Approximation and SGD (P1-Motivating example)](https://www.youtube.com/watch?v=1bMgejvWoAo&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=22)
- [L6: Stochastic Approximation and SGD (P2-RM algorithm: introduction)](https://www.youtube.com/watch?v=1FTGcNUUnCE&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=23)
- [L6: Stochastic Approximation and SGD (P3-RM algorithm: convergence)](https://www.youtube.com/watch?v=juNDoAFEre4&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=24)
- [L6: Stochastic Approximation and SGD (P4-SGD algorithm: introduction)](https://www.youtube.com/watch?v=EZO7Iadp5m4&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=25)
- [L6: Stochastic Approximation and SGD (P5-SGD algorithm: examples)](https://www.youtube.com/watch?v=BsxU_4qvvNA&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=26)
- [L6: Stochastic Approximation and SGD (P6-SGD algorithm: properties)](https://www.youtube.com/watch?v=fWxX9YuEHjE&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=27)
- [L6: Stochastic Approximation and SGD (P7-SGD algorithm: comparison)](https://www.youtube.com/watch?v=yNEV2cLKuzU&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=28)
- [L7: Temporal-Difference Learning (P1-Motivating example)](https://www.youtube.com/watch?v=u1X-7XX3dtI&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=29)
- [L7: Temporal-Difference Learning (P2-TD algorithm: introduction)](https://www.youtube.com/watch?v=XiCUsc7CCE0&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=30)
- [L7: Temporal-Difference Learning (P3-TD algorithm: convergence)](https://www.youtube.com/watch?v=faWg8M91-Oo&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=31)
- [L7: Temporal-Difference Learning (P4-Sarsa)](https://www.youtube.com/watch?v=jYwQufkBUPo&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=32)
- [L7: Temporal-Difference Learning (P5-Expected Sarsa & n-step Sarsa)](https://www.youtube.com/watch?v=0kKzQbWZOlk&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=33)
- [L7: Temporal-Difference Learning (P6-Q-learning: introduction)](https://www.youtube.com/watch?v=4BvYR2hm730&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=34)
- [L7: Temporal-Difference Learning (P7-Q-learning: pseudo code)](https://www.youtube.com/watch?v=I0YhlOIFF4s&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=35)
- [L7: Temporal-Difference Learning (P8-Unified viewpoint and summary)](https://www.youtube.com/watch?v=3t74lvk1GBM&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=36)
- [L8: Value Function Approximation (P1-Motivating example–curve fitting)](https://www.youtube.com/watch?v=uJXcI8fcdWc&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=37)
- [L8: Value Function Approximation (P2-Objective function)](https://www.youtube.com/watch?v=Z3HI1TfpJP0&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=38)
- [L8: Value Function Approximation (P3-Optimization algorithm)](https://www.youtube.com/watch?v=piBDwrKt0uU&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=39)
- [L8: Value Function Approximation (P4-illustrative examples and analysis)](https://www.youtube.com/watch?v=VFyBNEZxMMs&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=40)
- [L8: Value Function Approximation (P5-Sarsa and Q-learning)](https://www.youtube.com/watch?v=C-HtY4-W_zw&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=41)
- [L8: Value Function Approximation (P6-DQN–basic idea)](https://www.youtube.com/watch?v=lZCcbZbqVSQ&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=42)
- [L8: Value Function Approximation (P7-DQN–experience replay)](https://www.youtube.com/watch?v=rynEdAdebi0&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=43)
- [L8: Value Function Approximation (P8-DQN–implementation and example)](https://www.youtube.com/watch?v=vQHuCHjd6hA&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=44)
- [L9: Policy Gradient Methods (P1-Basic idea)](https://www.youtube.com/watch?v=mtFHOj83QSo&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=45)
- [L9: Policy Gradient Methods (P2-Metric 1–Average value)](https://www.youtube.com/watch?v=la8jQc3hX1M&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=46)
- [L9: Policy Gradient Methods (P3-Metric 2–Average reward)](https://www.youtube.com/watch?v=8RZ_rQFe69E&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=47)
- [L9: Policy Gradient Methods (P4-Gradients of the metrics)](https://www.youtube.com/watch?v=MvmtPXur3Ls&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=48)
- [L9: Policy Gradient Methods (P5-Gradient-based algorithms & REINFORCE)](https://www.youtube.com/watch?v=1DQnnUC8ng8&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=49)
- [L10: Actor-Critic Methods (P1-The simplest Actor-Critic)](https://www.youtube.com/watch?v=kjCZAT5Wh80&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=50)
- [L10: Actor-Critic Methods (P2-Advantage Actor-Critic)](https://www.youtube.com/watch?v=vZVXJJcZNEM&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=51)
- [L10: Actor-Critic Methods (P3-Importance sampling & off-policy Actor-Critic)](https://www.youtube.com/watch?v=TfO5mnsiGKc&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=52)
- [L10: Actor-Critic Methods (P4-Deterministic Actor-Critic)](https://www.youtube.com/watch?v=dTjz1RNtic4&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=53)
- [L10: Actor-Critic Methods (P5-Summary and goodbye!)](https://www.youtube.com/watch?v=npvnnKcXoBs&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=54)

**Some comments from YouTube and Amazon:**

[![](./Readme_Images/review1.jpg)](https://youtube.com/playlist?list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&si=B6mRR7vxBAjRAm_F)
[![](./Readme_Images/review2.jpg)](https://youtube.com/playlist?list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&si=B6mRR7vxBAjRAm_F)


# Third-party code and materials

Many enthusiastic readers sent me the source code or notes that they developed when they studied this book. If you create any materials based on course, you are welcome to write an email. I am happy to share the links here and hope they may be helpful to other readers. I must emphasize that I have not verified the code. If you have any questions, you can directly contact the developers. 

**Code**

*Python:*
- https://github.com/Ronchy2000/Multi-agent-RL/tree/master/RL_Learning-main (Oct 2025, by Rongqi Lu)

- https://github.com/zhoubay/Code-for-Mathematical-Foundations-of-Reinforcement-Learning (Mar 2025, by Xibin ZHOU)

- https://github.com/10-OASIS-01/minrl (Feb 2025)

- https://github.com/SupermanCaozh/The_Coding_Foundation_in_Reinforcement_Learning  (by Zehong Cao, Aug 2024)

- https://github.com/ziwenhahaha/Code-of-RL-Beginning by RLGamer (Mar 2024)
  - Videos for code explanation: https://www.bilibili.com/video/BV1fW421w7NH

- https://github.com/jwk1rose/RL_Learning by Wenkang Ji (Feb 2024)

*Matlab:*
-  https://github.com/EveryDayIsaSong/MATLAB-Code-for-Mathematical-Foundation-of-Reinforcement-Learning (by Yucheng Mao, Jan 2026)

*R:*

- https://github.com/NewbieToEverything/Code-Mathmatical-Foundation-of-Reinforcement-Learning

*C++:*

- https://github.com/purundong/test_rl


**Study notes**

*English:*

- https://lyk-love.cn/tags/reinforcement-learning/ 
by a graduate student from UC Davis

*Chinese:* 

- https://github.com/Peanut-Study/Reinforcement-Learning-Study-Note/tree/main (Jan 2026)
  
- https://zhuanlan.zhihu.com/p/692207843 

- https://blog.csdn.net/qq_64671439/category_12540921.html

- http://t.csdnimg.cn/EH4rj

- https://blog.csdn.net/LvGreat/article/details/135454738

- https://xinzhe.blog.csdn.net/article/details/129452000  

- https://blog.csdn.net/v20000727/article/details/136870879?spm=1001.2014.3001.5502

- https://blog.csdn.net/m0_64952374/category_12883361.html

There are also many others notes made by many other readers on the Internet. I am not able to put them all here. You are welcome to recommend to me if you find a good one.

**Bilibili videos made based on my course**

- https://www.bilibili.com/video/BV1DMBYB6Edo (Jan 2026)

- https://www.bilibili.com/video/BV1fW421w7NH

- https://www.bilibili.com/video/BV1Ne411m7GX
  
- https://www.bilibili.com/video/BV1HX4y1H7uR
  
- https://www.bilibili.com/video/BV1TgzsYDEnP
  
- https://www.bilibili.com/video/BV1CQ4y1J7zu

# Update history 

**(July 2025) Minor update: Typo corrections**

It has been nearly a year since the book's last update. During this period, keen-eyed readers have identified additional (about 10) typos and brought them to my attention. I really appreciate it. To prevent confusion for future readers, I have corrected these typos and updated the PDF files on GitHub. For the printed Springer edition, I prepared an errata list. Should you read a printed copy, you may consult this list as needed.

Finally, I wish to express heartfelt appreciation for our readers' invaluable contributions. Since its release, this book has received tremendous attention and feedback, enabling swift refinements. While I believe most typos have now been addressed, please don't hesitate to reach out if you spot anything that needs correction.

**(Jun 2025) 10,000+ stars!**

(Dec 2024) 4,000+ stars -> (Feb 2025) 5,000+ stars -> (Mar 2025) 7,000+ stars! -> (Apr 2025) 8,000+ stars! -> (May 2025) 9,000+ stars!

**(Oct 2024) Book cover**

The design of the book cover is finished. The book will be officially published by Springer early next year. It has been published by Tsinghua University Press.


**(Sep 2024) Minor update before printing by Springer**

I revised some very minor places that readers may hardly notice. It is supposed to be the final version before printing by Springer. 

**(Aug 2024) 3000 Stars and more code**

The book has received 3000+ stars, which is a great achievement to me. Thanks to everyone. Hope it really helped you.

I also received more code implementation from enthusiastic readers. For example, this [GitHub page](https://github.com/SupermanCaozh/The_Coding_Foundation_in_Reinforcement_Learning) provided Python implementation of almost all examples in my book. On the one hand, I am very glad to see that. On the other hand, I am a little worried that my students in my offline class may use the code to do their homework:-). Overall, I am happy because it indicates that the book and open course are really helpful to the readers; Otherwise, they would not bother to develop the code by themselves:-)

**(Jun 2024) Minor update before printing**

This is the fourth version of the book draft. It is supposed to be the final one before the book is officially published. Specifically, when proofreading the book manuscript, I detected some very minor issues. Together with some reported by enthusiastic readers, they have been revised in this version.

**(Apr 2024) Code for the Grid-World Environment**

We added the code for the grid-world environment in my book. Interested readers can develop and test their own algorithms in this environment. Both Python and MATLAB versions are provided.

Please note that we do not provide the code of all the algorithms involved in the book. That is because they are the homework for the students in offline teaching: the students need to develop their own algorithms using the provided environment. Nevertheless, there are third-party implementations of some algorithms. Interested readers can check the links on the home page of the book.

I need to thank my PhD students, Yize Mi and Jianan Li, who are also the Teaching Assistants of my offline teaching. They contributed greatly to the code.

You are welcome to provide any feedback about the code such as bugs if detected.

**(Mar 2024) 2K stars**

The book has received 2K stars. I also received many positive evaluations of the book from many readers. Very glad that it can be helpful. 

**(Mar 2024) Minor update**

The third version of the draft of the book is online now.

Compared to the second version, the third version is improved in the sense that some minor typos have been corrected. Here, I would like to thank the readers who sent me their feedback. 

**(Sep 2023) 1000+ stars**

The book received 1000+ stars! Thank everybody!

**(Aug 2023) Major update - second version**

*The second version of the draft of the book is online now!!*

Compared to the first version, which was online one year ago, the second version has been improved in various ways. For example, we replotted most of the figures, reorganized some contents to make them clearer, corrected some typos, and added Chapter 10, which was not included in the first version. 

I put the first draft of this book online in August 2022. Up to now, I have received valuable feedback from many readers worldwide. I want to express my gratitude to these readers.

**(Nov 2022) Will be jointly published**

This book will be published *jointly by Springer Nature and Tsinghua University Press*. It will probably be printed in the second half of 2023.

I have received some comments and suggestions about this book from some readers. Thanks a lot, and I appreciate it. I am still collecting feedback and will probably revise the draft in several months. Your feedback can make this book more helpful for other readers!

**(Oct 2022) Lecture notes and vidoes**

The *lecture slides* have been uploaded in the folder "Lecture slides."

The *lecture videos* (in Chinese) are online. Please check our Bilibili channel https://space.bilibili.com/2044042934 or the Youtube channel https://www.youtube.com/channel/UCztGtS5YYiNv8x3pj9hLVgg/playlists

**(Aug 2022) First draft**

The first draft of the book is online.
Download .txt
gitextract_pj0pi_9m/

├── Code for grid world/
│   ├── README.md
│   ├── matlab_version/
│   │   ├── figure_plot.m
│   │   └── main_example.m
│   └── python_version/
│       ├── examples/
│       │   ├── arguments.py
│       │   └── example_grid_world.py
│       └── src/
│           └── grid_world.py
├── Lecture slides/
│   └── Readme.md
└── Readme.md
Download .txt
SYMBOL INDEX (10 symbols across 2 files)

FILE: Code for grid world/python_version/examples/arguments.py
  function validate_environment_parameters (line 43) | def validate_environment_parameters(env_size, start_state, target_state,...

FILE: Code for grid world/python_version/src/grid_world.py
  class GridWorld (line 10) | class GridWorld():
    method __init__ (line 12) | def __init__(self, env_size=args.env_size,
    method reset (line 41) | def reset(self):
    method step (line 47) | def step(self, action):
    method _get_next_state_and_reward (line 65) | def _get_next_state_and_reward(self, state, action):
    method _is_done (line 93) | def _is_done(self, state):
    method render (line 97) | def render(self, animation_interval=args.animation_interval):
    method add_policy (line 140) | def add_policy(self, policy_matrix):
    method add_state_values (line 152) | def add_state_values(self, values, precision=1):
Condensed preview — 8 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (55K chars).
[
  {
    "path": "Code for grid world/README.md",
    "chars": 9287,
    "preview": "# Code for the Grid-World Environment \n\n## Overview\n\nWe added the code for the grid-world environment in my book. Intere"
  },
  {
    "path": "Code for grid world/matlab_version/figure_plot.m",
    "chars": 9110,
    "preview": "% by the Intelligent Unmanned Systems Laboratory, Westlake University, 2024\n\nfunction figure_plot(x_length, y_length, ag"
  },
  {
    "path": "Code for grid world/matlab_version/main_example.m",
    "chars": 3360,
    "preview": "% by the Intelligent Unmanned Systems Laboratory, Westlake University, 2024\n\nclear \nclose all\n\n% Initialize environment "
  },
  {
    "path": "Code for grid world/python_version/examples/arguments.py",
    "chars": 2360,
    "preview": "__credits__ = [\"Intelligent Unmanned Systems Laboratory at Westlake University.\"]\n'''\nSpecify parameters of the env\n'''\n"
  },
  {
    "path": "Code for grid world/python_version/examples/example_grid_world.py",
    "chars": 998,
    "preview": "\nimport sys\nsys.path.append(\"..\")\nfrom src.grid_world import GridWorld\nimport random\nimport numpy as np\n\n# Example usage"
  },
  {
    "path": "Code for grid world/python_version/src/grid_world.py",
    "chars": 6829,
    "preview": "__credits__ = [\"Intelligent Unmanned Systems Laboratory at Westlake University.\"]\n\nimport sys    \nsys.path.append(\"..\") "
  },
  {
    "path": "Lecture slides/Readme.md",
    "chars": 555,
    "preview": "My lecture slides are put into two folders.\n\n- The folder \"slidesForMyLectureVideos\" contains all **the slides that I us"
  },
  {
    "path": "Readme.md",
    "chars": 20917,
    "preview": "# (Oct 2025) Latex source code of my slides\n\nIf you are a professor preparing a course and would like to use any content"
  }
]

About this extraction

This page contains the full source code of the MathFoundationRL/Book-Mathematical-Foundation-of-Reinforcement-Learning GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 8 files (52.2 KB), approximately 15.2k tokens, and a symbol index with 10 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!