[
  {
    "path": "Code for grid world/README.md",
    "content": "# Code for the Grid-World Environment \n\n## Overview\n\nWe 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.\n\nPlease 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.\n\nI 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.\n\nYou are welcome to provide any feedback about the code such as bugs if detected.\n\n----\n\n## Python Version\n\n### Requirements\n\n- We support Python 3.7, 3.8, 3.9,  3.10 and 3.11. Make sure the following packages are installed: `numpy` and `matplotlib`.\n\n\n### How to Run the Default Example\n\nTo run the example, please follow the procedures :\n\n1. Change the directory to the file `examples/`\n\n```bash\ncd examples\n```\n\n2. Run the script:\n\n```bash\npython example_grid_world.py\n```\n\nYou will see an animation as shown below:\n\n- The blue star denotes the agent's current position within the grid world.\n- The arrows on each grid illustrate the policy for that state. \n- The green line traces the agent's historical trajectory. \n- Obstacles are marked with yellow grids. \n- The target state is indicated by a blue grid. \n- 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. \n- The horizontal number list above the grid world represents the horizontal coordinates (x-axis) of each grid.\n- The vertical number list on the left side represents their vertical coordinates (y-axis).\n\n![](python_version/plots/sample4.png)\n\n### Customize the Parameters of the Grid World Environment\n\nIf you would like to customize your own grid world environment, please open `examples/arguments.py` and then change the following arguments:\n\n\"**env-size**\", \"**start-state**\", \"**target-state**\", \"**forbidden-states**\", \"**reward-target**\", \"**reward-forbidden**\", \"**reward-step**\":\n\n- \"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).\n\n- \"start-state\" denotes where the agent starts.\n\n- \"target-state\" denotes the position of the target. \n\n- \"forbidden-states\" denotes the positions of obstacles. \n\n- \"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.  \n\nAn example is shown below:\n\nTo specify the target state, modify the default value in the following sentence:\n\n```python\nparser.add_argument(\"--target-state\", type=Union[list, tuple, np.ndarray], default=(4,4))\n```\n\nPlease 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.\n\n\n\nIf you want to save figures in each step, please modify the \"debug\" argument to  \"True\":\n\n```bash\nparser.add_argument(\"--debug\", type=bool, default=True)\n```\n\n\n\n### Create an Instance\n\nIf 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`:\n\n```python\nfrom src.grid_world import GridWorld\n\n \tenv = GridWorld()\n    state = env.reset()               \n    for t in range(20):\n        env.render()\n        action = np.random.choice(env.action_space)\n        next_state, reward, done, info = env.step(action)\n        print(f\"Step: {t}, Action: {action}, Next state: {next_state+(np.array([1,1]))}, Reward: {reward}, Done: {done}\")\n\n```\n\n![](python_version/plots/sample1.png)\n\n- 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:\n\n\n ```python\n     # Add policy\n     policy_matrix=np.random.rand(env.num_states,len(env.action_space))                                       \n     policy_matrix /= policy_matrix.sum(axis=1)[:, np.newaxis] \n ```\n\n- Moreover, to change the shape of the arrows, you can open `src/grid_world.py`:\n\n\n ```python\nself.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))   \n ```\n\n\n\n![](python_version/plots/sample2.png)\n\n-  To add state value to each grid:\n\n\n```python\nvalues = np.random.uniform(0,10,(env.num_states,))\nenv.add_state_values(values)\n```\n\n![](python_version/plots/sample3.png)\n\n- To render the environment:\n\n\n```python\nenv.render(animation_interval=3)    # the figure will stop for 3 seconds\n```\n\n------\n\n## MATLAB Version\n\n### Requirements\n\n- MATLAB >= R2020a, in order to implement the function *exportgraphics()*.\n\n### How to Run the Default Example\n\nPlease start the m-file `main.m`. \n\nFour figures will be generated: \n\nThe 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.\n\n<img src=\"matlab_version/policy_offline_Q_learning.jpg\" alt=\"policy_offline_Q_learning\" style=\"zoom:67%;\" />\n\nThe shape of the arrow can be customized in `figure_plot_1.m`\n\n```matlab\nfunction drawPolicyArrow(kk, ind, i_bias, j_bias, kk_new, ratio, greenColor, action)\n    % Obtain the action vector\n    action = action{kk};\n\n    % For the non-moving action, draw a circle\n    if action(1) == 0 && action(2) == 0  % Assuming the fifth action is to stay\n        plot(i_bias(ind), j_bias(ind), 'o', 'MarkerSize', 8, 'linewidth', 2, 'color', greenColor);\n        return;\n    else\n        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);\n        arrow.Parent = gca;\n    end\nend\n```\n\nThe 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. \n\n<img src=\"matlab_version/trajectory_Q_learning.jpg\" alt=\"trajectory_Q_learning\" style=\"zoom:67%;\" />\n\n<img src=\"matlab_version/trajectory_Bellman_Equation_dotted.jpg\" alt=\"trajectory_Bellman_Equation_dotted\" style=\"zoom:67%;\" />\n\nThe fourth figure is used to show the state value for each state. \n\n<img src=\"matlab_version/trajectory_Bellman_Equation.jpg\" alt=\"trajectory_Bellman_Equation\" style=\"zoom:67%;\" />\n\n### Code Description\n\n- The main reinforcement learning algorithm is shown below:\n\n\n```matlab\nfor step = 1:episode_length\n    action = stochastic_policy(state_history(step, :), action_space, policy, x_length, y_length);   \n    % Calculate the new state and reward\n    [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);\n    % Update state and reward history\n    state_history(step+1, :) = new_state;\n    reward_history(step) = reward;\nend\n```\n\n- The policy is shown as:\n\n\n```matlab\nfunction action = stochastic_policy(state, action_space, policy, x_length, y_length)\n    % Extract the action space and policy for a specific state\n    state_1d = x_length * (state(2)-1) + state(1); \n    actions = action_space{state_1d};\n    policy_i = policy(state_1d, :);\n\n    % Ensure the sum of policy probabilities is 1\n    assert(sum(policy_i) == 1, 'The sum of policy probabilities must be 1.');\n    \n    % Generate a random index based on policy probabilities\n    action_index = randsrc(1, 1, [1:length(actions); policy_i]);\n    \n    % Select an action\n    action = actions{action_index};\nend\n```\n\n- The state transition function is shown below:\n\n\n```matlab\nfunction [new_state, reward] = next_state_and_reward(state, action, x_length, y_length, target_state, obstacle_state, reward_forbidden, reward_target, reward_step)\n    new_x = state(1) + action(1);\n    new_y = state(2) + action(2);\n    new_state = [new_x, new_y];\n\n    % Check if the new state is out of bounds\n    if new_x < 1 || new_x > x_length || new_y < 1 || new_y > y_length\n        new_state = state;\n        reward = reward_forbidden;\n    elseif ismember(new_state, obstacle_state, 'rows')\n        % If the new state is an obstacle\n        reward = reward_forbidden;\n    elseif isequal(new_state, target_state)\n        % If the new state is the target state\n        reward = reward_target;\n    else\n         % If the new state is a normal cell\n        reward = reward_step;\n    end\nend\n```\n"
  },
  {
    "path": "Code for grid world/matlab_version/figure_plot.m",
    "content": "% by the Intelligent Unmanned Systems Laboratory, Westlake University, 2024\n\nfunction figure_plot(x_length, y_length, agent_state,final_state, obstacle_state, state_value, state_number, episode_length,state_update_2d,policy, action)\n    %% Inverse y coordinate\n \n    \n    xa_used = agent_state(:, 1) + 0.5;\n    ya_used = y_length+1-agent_state(:, 2) + 0.5;\n    \n    \n    state_space=x_length*y_length;\n    \n    \n    xf = final_state(:, 1);\n    yf = y_length+1-final_state(:, 2); \n    \n    \n    \n    xo = obstacle_state(:, 1);\n    yo = y_length+1-obstacle_state(:, 2);\n    \n    \n    \n    xs = state_update_2d(:, 1); \n    ys = state_update_2d(:, 2);\n    \n    state_update = (ys-1) * x_length + xs; \n                                                        \n    \n    \n    %%\n    \n    greenColor=[0.4660 0.6740 0.1880]*0.8;\n    \n    \n    \n    % Initialize the figure\n    figure();\n    \n    \n    % Add labels on the axes\n    addAxisLabels(x_length, y_length);\n    \n    % Draw the grid, state values, and policy arrows\n    r = drawGridStateValuesAndPolicy(x_length, y_length, state_number, state_value, policy, greenColor, action);\n    \n    % Color the obstacles and the final state\n    colorObstacles(xo, yo, r);\n    colorFinalState(xf, yf, r);\n    \n    % Draw the agent\n    agent = plot(xa_used, ya_used, '*', 'markersize', 15, 'linewidth', 2, 'color', 'b');  \n    hold on;\n    \n    axis equal\n    axis off\n    exportgraphics(gca,'policy_offline_Q_learning.pdf') \n    \n    \n    \n    % Initialize the figure\n    figure();\n    \n    % Add labels on the axes\n    addAxisLabels(x_length, y_length);\n    \n    % Draw the grid and add state values\n    r = drawGridAndStateValues(x_length, y_length, state_value);\n    \n    % Color the obstacles and the final state\n    colorObstacles(xo, yo, r);\n    colorFinalState(xf, yf, r);\n    \n    % Compute the de-normalized states\n    for i = 1:state_space\n        state_two_dimension_new(i, :) = de_normalized_state(state_number(i), x_length, y_length);\n    end\n    \n    \n    % Draw the agent\n    agent = plot(xa_used, ya_used, '*', 'markersize', 15, 'linewidth', 2, 'color', 'b');\n    hold on;\n    \n    \n    % Set axis properties and export the figure\n    axis equal;\n    axis off;\n    exportgraphics(gca, 'trajectory_Bellman_Equation.pdf');\n    \n    \n    \n    \n    \n    \n    % Initialize the figure\n    figure();\n    \n    % Add labels on the axes\n    addAxisLabels(x_length, y_length);\n    \n    % Draw the grid and add state values\n    r= drawGridAndStateValues(x_length, y_length, state_value);\n    \n    % Draw state transitions\n    for i=1:state_space\n        state_two_dimension_new(i,:)=de_normalized_state(state_number(i),x_length,y_length);\n    end\n    drawStateTransitions(state_space, state_update, state_two_dimension_new, episode_length);\n    \n    % Color the obstacles and the final state\n    \n    \n    colorObstacles(xo, yo, r);\n    colorFinalState(xf, yf, r);\n    \n    \n    % Draw the agent\n    agent = plot(xa_used, ya_used, '*', 'markersize', 15, 'linewidth', 2, 'color', 'b');\n    hold on;\n    \n    \n    % Set axis properties and export the figure\n    axis equal;\n    axis off;\n    exportgraphics(gca, 'trajectory_Q_learning.pdf');\n    \n    \n    \n    \n    % Initialize the figure\n    figure();\n    \n    % Add labels on the axes\n    addAxisLabels(x_length, y_length);\n    \n    % Draw the grid and add state values\n    r = drawGridAndStateValues(x_length, y_length, state_value);\n    \n    % Color the obstacles and the final state\n    colorObstacles(xo, yo, r);\n    colorFinalState(xf, yf, r);\n    \n    % Compute the de-normalized states\n    for i = 1:state_space\n        state_two_dimension_new(i, :) = de_normalized_state(state_number(i), x_length, y_length);\n    end\n    \n    % Draw transitions between states\n    for i = 1:episode_length - 1\n        line([state_two_dimension_new(state_update(i), 1) + 0.5, state_two_dimension_new(state_update(i + 1), 1) + 0.5], ...\n             [state_two_dimension_new(state_update(i), 2) + 0.5, state_two_dimension_new(state_update(i + 1), 2) + 0.5], ...\n             'Color', 'black', 'LineStyle', '--');\n        hold on;\n    end\n    \n    % Draw the agent\n    agent = plot(xa_used, ya_used, '*', 'markersize', 15, 'linewidth', 2, 'color', 'b');\n    hold on;\n    \n    \n    % Set axis properties and export the figure\n    axis equal;\n    axis off;\n    exportgraphics(gca, 'trajectory_Bellman_Equation.pdf');\n    \n    % Function definitions would be the same as provided previously\n\n\nend\n\n\n\nfunction o=de_normalized_state(each_state,x_length,y_length)\n\n         o=[mod(each_state-1,x_length),y_length-1-fix((each_state-1)/(x_length))]+[1,1];\nend\n\n\n\n\nfunction addAxisLabels(x_length, y_length)\n    for i = 1:x_length\n        text(i + 0.5, y_length + 1.1, num2str(i));\n    end\n    for j = y_length:-1:1\n        text(0.9, j + 0.5, num2str(y_length - j + 1));\n    end\nend\n\nfunction r= drawGridStateValuesAndPolicy(x_length, y_length, state_number, state_value, policy, greenColor, action)\n    ind = 0;\n    ratio = 0.5; % adjust the length of arrow\n    state_coordinate = zeros(x_length * y_length, 2); % Initialize state_coordinate\n    for j = y_length:-1:1       \n        for i = 1:x_length      \n            r(i, j) = rectangle('Position', [i j 1 1]);\n            ind = ind + 1;\n            state_coordinate(state_number(ind), :) = [i, j];\n            text(i + 0.4, j + 0.5, ['s', num2str(ind)]);\n            hold on;\n            \n            % Calculate bias\n            i_bias(ind) = state_coordinate(state_number(ind), 1) + 0.5;\n            j_bias(ind) = state_coordinate(state_number(ind), 2) + 0.5;\n            \n            % Draw policy arrows or state markers\n            for kk = 1:size(policy, 2)\n                if policy(state_number(ind), kk) ~= 0\n                    kk_new = policy(state_number(ind), kk) / 2 + 0.5;\n                    drawPolicyArrow(kk, ind, i_bias, j_bias, kk_new, ratio, greenColor, action);                \n                end\n            end\n        end\n    end\nend\n\n\nfunction drawPolicyArrow(kk, ind, i_bias, j_bias, kk_new, ratio, greenColor, action)\n    % Obtain the action vector\n    action = action{kk};\n\n    % For the non-moving action, draw a circle to represent the stay state\n    if action(1) == 0 && action(2) == 0  % Assuming the fifth action is to stay\n        plot(i_bias(ind), j_bias(ind), 'o', 'MarkerSize', 8, 'linewidth', 2, 'color', greenColor);\n        return;\n    else\n        % 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.\n        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);\n        arrow.Parent = gca;\n    end\nend\n\n\n% Function to draw the grid and add state values\nfunction r = drawGridAndStateValues(x_length, y_length, state_value)\n    ind = 0;\n    for j = y_length:-1:1       \n        for i = 1:x_length       \n            r(i, j) = rectangle('Position', [i j 1 1]);\n            ind = ind + 1;\n            text(i + 0.4, j + 0.5, num2str(round(state_value(ind), 2)));\n            hold on;           \n        end\n    end\nend\n\n% Function to color the obstacles\nfunction colorObstacles(xo, yo, r)\n    for i = 1:length(xo)\n        r(xo(i), yo(i)).FaceColor = [0.9290 0.6940 0.1250];\n    end\nend\n\n% Function to color the final state\nfunction colorFinalState(xf, yf, r)\n    r(xf, yf).FaceColor = [0.3010 0.7450 0.9330];\nend\n\n% Function to draw state transitions\nfunction drawStateTransitions(state_space, state_update, state_two_dimension_new, episode_length)\n    for i = 1:episode_length - 1\n        if state_two_dimension_new(state_update(i), 2) ~= state_two_dimension_new(state_update(i + 1), 2)       \n            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], ...\n                 [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], ...\n                 'Color', 'green');\n        elseif state_two_dimension_new(state_update(i), 1) ~= state_two_dimension_new(state_update(i + 1), 1)       \n            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], ...\n                 [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], ...\n                 'Color', 'green');\n        end\n        hold on;\n    end\nend\n\n\n"
  },
  {
    "path": "Code for grid world/matlab_version/main_example.m",
    "content": "% by the Intelligent Unmanned Systems Laboratory, Westlake University, 2024\n\nclear \nclose all\n\n% Initialize environment parameters\nagent_state = [1, 1];\nfinal_state = [3, 3];\nobstacle_state = [1, 3; 2, 1; 1, 2];\nx_length = 3;\ny_length = 4;\nstate_space = x_length * y_length; \nstate=1:state_space;\nstate_value=ones(state_space,1);\n\nreward_forbidden = -1;\nreward_target = 1;\nreward_step = 0;\n\n% Define actions: up, right, down, left, stay\nactions = {[0, -1], [1, 0], [0, 1], [-1, 0], [0, 0]};\n\n% Initialize a cell array to store the action space for each state\naction_space = cell(state_space, 1);\n\n% Populate the action space\nfor i = 1:state_space       \n    action_space{i} = actions;\nend\n\nnumber_of_action=5;\n\npolicy=zeros(state_space, number_of_action); % policy can be deterministic or stochastic, shown as follows:\n\n\n\n\n% stochastic policy \n\nfor i=1:state_space\n    policy(i,:)=.2;          \nend\n% policy(3,2)=0; policy(3,4)=.4;\n% policy(5,5)=0; policy(5,3)=.4;\npolicy(7,3)=1; policy(7,4)= 0; policy(7,2)= 0; policy(7,1)= 0; policy(7,5)= 0;\n% policy(6,2)=0; policy(6,3) = 1; policy(6,4) = 0; policy(6,5) = 0; policy (6,1) = 0;\n\n\n\n\n% Initialize the episode\nepisode_length = 1000;\n\nstate_history = zeros(episode_length, 2); \nreward_history = zeros(episode_length, 1);  \n\n% Set the initial state\nstate_history(1, :) = agent_state;\n\nfor step = 1:episode_length\n    action = stochastic_policy(state_history(step, :), action_space, policy, x_length, y_length);   \n    % Calculate the new state and reward\n    [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);\n    % Update state and reward history\n    state_history(step+1, :) = new_state;\n    reward_history(step) = reward;\nend\n\nfigure_plot(x_length, y_length, agent_state, final_state, obstacle_state, state_value, state, episode_length, state_history, policy, actions);\n\n%%   useful function \nfunction [new_state, reward] = next_state_and_reward(state, action, x_length, y_length, target_state, obstacle_state, reward_forbidden, reward_target, reward_step)\n    new_x = state(1) + action(1);\n    new_y = state(2) + action(2);\n    new_state = [new_x, new_y];\n\n    % Check if the new state is out of bounds\n    if new_x < 1 || new_x > x_length || new_y < 1 || new_y > y_length\n        new_state = state;\n        reward = reward_forbidden;\n    elseif ismember(new_state, obstacle_state, 'rows')\n        % If the new state is an obstacle\n        reward = reward_forbidden;\n    elseif isequal(new_state, target_state)\n        % If the new state is the target state\n        reward = reward_target;\n    else\n         % If the new state is a normal cell\n        reward = reward_step;\n    end\nend\n\nfunction action = stochastic_policy(state, action_space, policy, x_length, y_length)\n    % Extract the action space and policy for a specific state\n    state_1d = x_length * (state(2)-1) + state(1); \n    actions = action_space{state_1d};\n    policy_i = policy(state_1d, :);\n\n    % Ensure the sum of policy probabilities is 1\n    assert(sum(policy_i) == 1, 'The sum of policy probabilities must be 1.');\n    \n    % Generate a random index based on policy probabilities\n    action_index = randsrc(1, 1, [1:length(actions); policy_i]);\n    \n    % Select an action\n    action = actions{action_index};\nend\n"
  },
  {
    "path": "Code for grid world/python_version/examples/arguments.py",
    "content": "__credits__ = [\"Intelligent Unmanned Systems Laboratory at Westlake University.\"]\n'''\nSpecify parameters of the env\n'''\nfrom typing import Union\nimport numpy as np\nimport argparse\n\nparser = argparse.ArgumentParser(\"Grid World Environment\")\n\n## ==================== User settings ===================='''\n# specify the number of columns and rows of the grid world\nparser.add_argument(\"--env-size\", type=Union[list, tuple, np.ndarray], default=(5,5) )   \n\n# specify the start state\nparser.add_argument(\"--start-state\", type=Union[list, tuple, np.ndarray], default=(2,2))\n\n# specify the target state\nparser.add_argument(\"--target-state\", type=Union[list, tuple, np.ndarray], default=(4,4))\n\n# sepcify the forbidden states\nparser.add_argument(\"--forbidden-states\", type=list, default=[ (2, 1), (3, 3), (1, 3)] )\n\n# sepcify the reward when reaching target\nparser.add_argument(\"--reward-target\", type=float, default = 10)\n\n# sepcify the reward when entering into forbidden area\nparser.add_argument(\"--reward-forbidden\", type=float, default = -5)\n\n# sepcify the reward for each step\nparser.add_argument(\"--reward-step\", type=float, default = -1)\n## ==================== End of User settings ====================\n\n\n## ==================== Advanced Settings ====================\nparser.add_argument(\"--action-space\", type=list, default=[(0, 1), (1, 0), (0, -1), (-1, 0), (0, 0)] )  # down, right, up, left, stay           \nparser.add_argument(\"--debug\", type=bool, default=False)\nparser.add_argument(\"--animation-interval\", type=float, default = 0.2)\n## ==================== End of Advanced settings ====================\n\n\nargs = parser.parse_args()     \ndef validate_environment_parameters(env_size, start_state, target_state, forbidden_states):\n    if not (isinstance(env_size, tuple) or isinstance(env_size, list) or isinstance(env_size, np.ndarray)) and len(env_size) != 2:\n        raise ValueError(\"Invalid environment size. Expected a tuple (rows, cols) with positive dimensions.\")\n    \n    for i in range(2):\n        assert start_state[i] < env_size[i]\n        assert target_state[i] < env_size[i]\n        for j in range(len(forbidden_states)):\n            assert forbidden_states[j][i] < env_size[i]\ntry:\n    validate_environment_parameters(args.env_size, args.start_state, args.target_state, args.forbidden_states)\nexcept ValueError as e:\n    print(\"Error:\", e)"
  },
  {
    "path": "Code for grid world/python_version/examples/example_grid_world.py",
    "content": "\nimport sys\nsys.path.append(\"..\")\nfrom src.grid_world import GridWorld\nimport random\nimport numpy as np\n\n# Example usage:\nif __name__ == \"__main__\":             \n    env = GridWorld()\n    state = env.reset()               \n    for t in range(1000):\n        env.render()\n        action = random.choice(env.action_space)\n        next_state, reward, done, info = env.step(action)\n        print(f\"Step: {t}, Action: {action}, State: {next_state+(np.array([1,1]))}, Reward: {reward}, Done: {done}\")\n        # if done:\n        #     break\n    \n    # Add policy\n    policy_matrix=np.random.rand(env.num_states,len(env.action_space))                                            \n    policy_matrix /= policy_matrix.sum(axis=1)[:, np.newaxis]  # make the sum of elements in each row to be 1\n\n    env.add_policy(policy_matrix)\n\n    \n    # Add state values\n    values = np.random.uniform(0,10,(env.num_states,))\n    env.add_state_values(values)\n\n    # Render the environment\n    env.render(animation_interval=2)"
  },
  {
    "path": "Code for grid world/python_version/src/grid_world.py",
    "content": "__credits__ = [\"Intelligent Unmanned Systems Laboratory at Westlake University.\"]\n\nimport sys    \nsys.path.append(\"..\")         \nimport numpy as np\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches          \nfrom examples.arguments import args           \n\nclass GridWorld():\n\n    def __init__(self, env_size=args.env_size, \n                 start_state=args.start_state, \n                 target_state=args.target_state, \n                 forbidden_states=args.forbidden_states):\n\n        self.env_size = env_size\n        self.num_states = env_size[0] * env_size[1]\n        self.start_state = start_state\n        self.target_state = target_state\n        self.forbidden_states = forbidden_states\n\n        self.agent_state = start_state\n        self.action_space = args.action_space          \n        self.reward_target = args.reward_target\n        self.reward_forbidden = args.reward_forbidden\n        self.reward_step = args.reward_step\n\n        self.canvas = None\n        self.animation_interval = args.animation_interval\n\n\n        self.color_forbid = (0.9290,0.6940,0.125)\n        self.color_target = (0.3010,0.7450,0.9330)\n        self.color_policy = (0.4660,0.6740,0.1880)\n        self.color_trajectory = (0, 1, 0)\n        self.color_agent = (0,0,1)\n\n\n\n    def reset(self):\n        self.agent_state = self.start_state\n        self.traj = [self.agent_state] \n        return self.agent_state, {}\n\n\n    def step(self, action):\n        assert action in self.action_space, \"Invalid action\"\n\n        next_state, reward  = self._get_next_state_and_reward(self.agent_state, action)\n        done = self._is_done(next_state)\n\n        x_store = next_state[0] + 0.03 * np.random.randn()\n        y_store = next_state[1] + 0.03 * np.random.randn()\n        state_store = tuple(np.array((x_store,  y_store)) + 0.2 * np.array(action))\n        state_store_2 = (next_state[0], next_state[1])\n\n        self.agent_state = next_state\n\n        self.traj.append(state_store)   \n        self.traj.append(state_store_2)\n        return self.agent_state, reward, done, {}   \n    \n        \n    def _get_next_state_and_reward(self, state, action):\n        x, y = state\n        new_state = tuple(np.array(state) + np.array(action))\n        if y + 1 > self.env_size[1] - 1 and action == (0,1):    # down\n            y = self.env_size[1] - 1\n            reward = self.reward_forbidden  \n        elif x + 1 > self.env_size[0] - 1 and action == (1,0):  # right\n            x = self.env_size[0] - 1\n            reward = self.reward_forbidden  \n        elif y - 1 < 0 and action == (0,-1):   # up\n            y = 0\n            reward = self.reward_forbidden  \n        elif x - 1 < 0 and action == (-1, 0):  # left\n            x = 0\n            reward = self.reward_forbidden \n        elif new_state == self.target_state:  # stay\n            x, y = self.target_state\n            reward = self.reward_target\n        elif new_state in self.forbidden_states:  # stay\n            x, y = state\n            reward = self.reward_forbidden        \n        else:\n            x, y = new_state\n            reward = self.reward_step\n            \n        return (x, y), reward\n        \n\n    def _is_done(self, state):\n        return state == self.target_state\n    \n\n    def render(self, animation_interval=args.animation_interval):\n        if self.canvas is None:\n            plt.ion()                             \n            self.canvas, self.ax = plt.subplots()   \n            self.ax.set_xlim(-0.5, self.env_size[0] - 0.5)\n            self.ax.set_ylim(-0.5, self.env_size[1] - 0.5)\n            self.ax.xaxis.set_ticks(np.arange(-0.5, self.env_size[0], 1))     \n            self.ax.yaxis.set_ticks(np.arange(-0.5, self.env_size[1], 1))     \n            self.ax.grid(True, linestyle=\"-\", color=\"gray\", linewidth=\"1\", axis='both')          \n            self.ax.set_aspect('equal')\n            self.ax.invert_yaxis()                           \n            self.ax.xaxis.set_ticks_position('top')           \n            \n            idx_labels_x = [i for i in range(self.env_size[0])]\n            idx_labels_y = [i for i in range(self.env_size[1])]\n            for lb in idx_labels_x:\n                self.ax.text(lb, -0.75, str(lb+1), size=10, ha='center', va='center', color='black')           \n            for lb in idx_labels_y:\n                self.ax.text(-0.75, lb, str(lb+1), size=10, ha='center', va='center', color='black')\n            self.ax.tick_params(bottom=False, left=False, right=False, top=False, labelbottom=False, labelleft=False,labeltop=False)   \n\n            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)\n            self.ax.add_patch(self.target_rect)     \n\n            for forbidden_state in self.forbidden_states:\n                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)\n                self.ax.add_patch(rect)\n\n            self.agent_star, = self.ax.plot([], [], marker = '*', color=self.color_agent, markersize=20, linewidth=0.5) \n            self.traj_obj, = self.ax.plot([], [], color=self.color_trajectory, linewidth=0.5)\n\n        # self.agent_circle.center = (self.agent_state[0], self.agent_state[1])\n        self.agent_star.set_data([self.agent_state[0]],[self.agent_state[1]])       \n        traj_x, traj_y = zip(*self.traj)         \n        self.traj_obj.set_data(traj_x, traj_y)\n\n        plt.draw()\n        plt.pause(animation_interval)\n        if args.debug:\n            input('press Enter to continue...')     \n\n\n \n    def add_policy(self, policy_matrix):                  \n        for state, state_action_group in enumerate(policy_matrix):    \n            x = state % self.env_size[0]\n            y = state // self.env_size[0]\n            for i, action_probability in enumerate(state_action_group):\n                if action_probability !=0:\n                    dx, dy = self.action_space[i]\n                    if (dx, dy) != (0,0):\n                        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))\n                    else:\n                        self.ax.add_patch(patches.Circle((x, y), radius=0.07, facecolor=self.color_policy, edgecolor=self.color_policy, linewidth=1, fill=False))\n    \n    def add_state_values(self, values, precision=1):\n        '''\n            values: iterable\n        '''\n        values = np.round(values, precision)\n        for i, value in enumerate(values):\n            x = i % self.env_size[0]\n            y = i // self.env_size[0]\n            self.ax.text(x, y, str(value), ha='center', va='center', fontsize=10, color='black')"
  },
  {
    "path": "Lecture slides/Readme.md",
    "content": "My lecture slides are put into two folders.\n\n- The folder \"slidesForMyLectureVideos\" contains all **the slides that I used to record my lecture videos**.\n\n- The folder \"slidesContinuouslyUpdated\" contains **the slides that I updated continuously**.\n\nThe slides in the two folders are very similar, but there are some minor differences, such as typo correction and content adjustment.\n\n**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.**\n\n"
  },
  {
    "path": "Readme.md",
    "content": "# (Oct 2025) Latex source code of my slides\n\nIf 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.\n\nRegarding 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.\n\n***\n***\n\n# Why a new book on reinforcement learning?\n\nThis 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.\n\n- 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.\n\n- 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.\n\n- 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.\n\n- 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.\n\n- 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.\n\n[![Book cover](./Readme_Images/BookCoverSpringer.png)](https://link.springer.com/book/9789819739431)\n\n# Contents\n\nThe 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.\n\n![The map of this book](./Readme_Images/BookMap.png)\n\n\n# Readership\n\nThis book is designed for senior undergraduate students, graduate students, researchers, and practitioners interested in reinforcement learning.\n\nIt 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.\n\nThis 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.\n\n# About the author\nYou can find my info on my homepage https://www.shiyuzhao.net (GoogleSite) and my research group website https://shiyuzhao.westlake.edu.cn\n\nI 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. \n\nI sincerely hope this book can help readers smoothly enter the exciting field of reinforcement learning.\n\n# Citation\n\n```\n@book{zhao2025RLBook,\n  title={Mathematical Foundations of Reinforcement Learning},\n  author={S. Zhao},\n  year={2025},\n  publisher={Springer Press}\n}\n```\n# Lecture videos \n\nThe lecture videos have received **2,100,000+ views** over the Internet and received very good feedback!\nBy combining the book with my lecture videos, I believe you can study better. \n\n- **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).\n- **English lecture videos:** The English lecture videos have been uploaded to YouTube: [link here](https://youtube.com/playlist?list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&si=D1T4pcyHsMxj6CzB)\n\n[![](./Readme_Images/EnglishLectureVideo.png)](https://youtube.com/playlist?list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&si=B6mRR7vxBAjRAm_F)\n\n- [Overview of Reinforcement Learning in 30 Minutes](https://www.youtube.com/watch?v=ZHMWHr9811U&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=1)\n- [L1: Basic Concepts (P1-State, action, policy, ...)](https://www.youtube.com/watch?v=zJHtM5dN69g&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=2)\n- [L1: Basic Concepts (P2-Reward,return, Markov decision process)](https://www.youtube.com/watch?v=repVl3_GYCI&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=3)\n- [L2: Bellman Equation (P1-Motivating examples)](https://www.youtube.com/watch?v=XCzWrlgZCwc&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=4)\n- [L2: Bellman Equation (P2-State value)](https://www.youtube.com/watch?v=DSvi3xEN13I&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=5)\n- [L2: Bellman Equation (P3-Bellman equation-Derivation)](https://www.youtube.com/watch?v=eNtId8yPWkA&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=6)\n- [L2: Bellman Equation (P4-Matrix-vector form and solution)](https://www.youtube.com/watch?v=EtCfBG_eP2w&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=7)\n- [L2: Bellman Equation (P5-Action value)](https://www.youtube.com/watch?v=zJo2sLDzfcU&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=8)\n- [L3: Bellman Optimality Equation (P1-Motivating example)](https://www.youtube.com/watch?v=lXKY_Hyg4SQ&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=9)\n- [L3: Bellman Optimality Equation (P2-Optimal policy)](https://www.youtube.com/watch?v=BxyjdHhK8a8&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=10)\n- [L3: Bellman Optimality Equation (P3-More on BOE)](https://www.youtube.com/watch?v=FXftTCKotC8&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=11)\n- [L3: Bellman Optimality Equation (P4-Interesting properties)](https://www.youtube.com/watch?v=a--bck2ow9s&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=12)\n- [L4: Value Iteration and Policy Iteration (P1-Value iteration)](https://www.youtube.com/watch?v=wMAVmLDIvQU&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=13)\n- [L4: Value Iteration and Policy Iteration (P2-Policy iteration)](https://www.youtube.com/watch?v=Pka6Om0nYQ8&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=14)\n- [L4: Value Iteration and Policy Iteration (P3-Truncated policy iteration)](https://www.youtube.com/watch?v=tUjPFPD3Vc8&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=15)\n- [L5: Monte Carlo Learning (P1-Motivating examples)](https://www.youtube.com/watch?v=DO1yXinAV_Q&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=16)\n- [L5: Monte Carlo Learning (P2-MC Basic-introduction)](https://www.youtube.com/watch?v=6ShisunU0zs&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=17)\n- [L5: Monte Carlo Learning (P3-MC Basic-examples)](https://www.youtube.com/watch?v=axA0yns9FxU&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=18)\n- [L5: Monte Carlo Learning (P4-MC Exploring Starts)](https://www.youtube.com/watch?v=Qt8OMHPkLqg&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=19)\n- [L5: Monte Carlo Learning (P5-MC Epsilon-Greedy-introduction)](https://www.youtube.com/watch?v=dM3fYE630pY&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=20)\n- [L5: Monte Carlo Learning (P6-MC Epsilon-Greedy-examples)](https://www.youtube.com/watch?v=x6X_5ePT9gQ&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=21)\n- [L6: Stochastic Approximation and SGD (P1-Motivating example)](https://www.youtube.com/watch?v=1bMgejvWoAo&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=22)\n- [L6: Stochastic Approximation and SGD (P2-RM algorithm: introduction)](https://www.youtube.com/watch?v=1FTGcNUUnCE&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=23)\n- [L6: Stochastic Approximation and SGD (P3-RM algorithm: convergence)](https://www.youtube.com/watch?v=juNDoAFEre4&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=24)\n- [L6: Stochastic Approximation and SGD (P4-SGD algorithm: introduction)](https://www.youtube.com/watch?v=EZO7Iadp5m4&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=25)\n- [L6: Stochastic Approximation and SGD (P5-SGD algorithm: examples)](https://www.youtube.com/watch?v=BsxU_4qvvNA&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=26)\n- [L6: Stochastic Approximation and SGD (P6-SGD algorithm: properties)](https://www.youtube.com/watch?v=fWxX9YuEHjE&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=27)\n- [L6: Stochastic Approximation and SGD (P7-SGD algorithm: comparison)](https://www.youtube.com/watch?v=yNEV2cLKuzU&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=28)\n- [L7: Temporal-Difference Learning (P1-Motivating example)](https://www.youtube.com/watch?v=u1X-7XX3dtI&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=29)\n- [L7: Temporal-Difference Learning (P2-TD algorithm: introduction)](https://www.youtube.com/watch?v=XiCUsc7CCE0&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=30)\n- [L7: Temporal-Difference Learning (P3-TD algorithm: convergence)](https://www.youtube.com/watch?v=faWg8M91-Oo&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=31)\n- [L7: Temporal-Difference Learning (P4-Sarsa)](https://www.youtube.com/watch?v=jYwQufkBUPo&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=32)\n- [L7: Temporal-Difference Learning (P5-Expected Sarsa & n-step Sarsa)](https://www.youtube.com/watch?v=0kKzQbWZOlk&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=33)\n- [L7: Temporal-Difference Learning (P6-Q-learning: introduction)](https://www.youtube.com/watch?v=4BvYR2hm730&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=34)\n- [L7: Temporal-Difference Learning (P7-Q-learning: pseudo code)](https://www.youtube.com/watch?v=I0YhlOIFF4s&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=35)\n- [L7: Temporal-Difference Learning (P8-Unified viewpoint and summary)](https://www.youtube.com/watch?v=3t74lvk1GBM&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=36)\n- [L8: Value Function Approximation (P1-Motivating example–curve fitting)](https://www.youtube.com/watch?v=uJXcI8fcdWc&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=37)\n- [L8: Value Function Approximation (P2-Objective function)](https://www.youtube.com/watch?v=Z3HI1TfpJP0&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=38)\n- [L8: Value Function Approximation (P3-Optimization algorithm)](https://www.youtube.com/watch?v=piBDwrKt0uU&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=39)\n- [L8: Value Function Approximation (P4-illustrative examples and analysis)](https://www.youtube.com/watch?v=VFyBNEZxMMs&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=40)\n- [L8: Value Function Approximation (P5-Sarsa and Q-learning)](https://www.youtube.com/watch?v=C-HtY4-W_zw&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=41)\n- [L8: Value Function Approximation (P6-DQN–basic idea)](https://www.youtube.com/watch?v=lZCcbZbqVSQ&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=42)\n- [L8: Value Function Approximation (P7-DQN–experience replay)](https://www.youtube.com/watch?v=rynEdAdebi0&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=43)\n- [L8: Value Function Approximation (P8-DQN–implementation and example)](https://www.youtube.com/watch?v=vQHuCHjd6hA&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=44)\n- [L9: Policy Gradient Methods (P1-Basic idea)](https://www.youtube.com/watch?v=mtFHOj83QSo&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=45)\n- [L9: Policy Gradient Methods (P2-Metric 1–Average value)](https://www.youtube.com/watch?v=la8jQc3hX1M&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=46)\n- [L9: Policy Gradient Methods (P3-Metric 2–Average reward)](https://www.youtube.com/watch?v=8RZ_rQFe69E&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=47)\n- [L9: Policy Gradient Methods (P4-Gradients of the metrics)](https://www.youtube.com/watch?v=MvmtPXur3Ls&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=48)\n- [L9: Policy Gradient Methods (P5-Gradient-based algorithms & REINFORCE)](https://www.youtube.com/watch?v=1DQnnUC8ng8&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=49)\n- [L10: Actor-Critic Methods (P1-The simplest Actor-Critic)](https://www.youtube.com/watch?v=kjCZAT5Wh80&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=50)\n- [L10: Actor-Critic Methods (P2-Advantage Actor-Critic)](https://www.youtube.com/watch?v=vZVXJJcZNEM&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=51)\n- [L10: Actor-Critic Methods (P3-Importance sampling & off-policy Actor-Critic)](https://www.youtube.com/watch?v=TfO5mnsiGKc&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=52)\n- [L10: Actor-Critic Methods (P4-Deterministic Actor-Critic)](https://www.youtube.com/watch?v=dTjz1RNtic4&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=53)\n- [L10: Actor-Critic Methods (P5-Summary and goodbye!)](https://www.youtube.com/watch?v=npvnnKcXoBs&list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&index=54)\n\n**Some comments from YouTube and Amazon:**\n\n[![](./Readme_Images/review1.jpg)](https://youtube.com/playlist?list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&si=B6mRR7vxBAjRAm_F)\n[![](./Readme_Images/review2.jpg)](https://youtube.com/playlist?list=PLEhdbSEZZbDaFWPX4gehhwB9vJZJ1DNm8&si=B6mRR7vxBAjRAm_F)\n\n\n# Third-party code and materials\n\nMany 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. \n\n**Code**\n\n*Python:*\n- https://github.com/Ronchy2000/Multi-agent-RL/tree/master/RL_Learning-main (Oct 2025, by Rongqi Lu)\n\n- https://github.com/zhoubay/Code-for-Mathematical-Foundations-of-Reinforcement-Learning (Mar 2025, by Xibin ZHOU)\n\n- https://github.com/10-OASIS-01/minrl (Feb 2025)\n\n- https://github.com/SupermanCaozh/The_Coding_Foundation_in_Reinforcement_Learning  (by Zehong Cao, Aug 2024)\n\n- https://github.com/ziwenhahaha/Code-of-RL-Beginning by RLGamer (Mar 2024)\n  - Videos for code explanation: https://www.bilibili.com/video/BV1fW421w7NH\n\n- https://github.com/jwk1rose/RL_Learning by Wenkang Ji (Feb 2024)\n\n*Matlab:*\n-  https://github.com/EveryDayIsaSong/MATLAB-Code-for-Mathematical-Foundation-of-Reinforcement-Learning (by Yucheng Mao, Jan 2026)\n\n*R:*\n\n- https://github.com/NewbieToEverything/Code-Mathmatical-Foundation-of-Reinforcement-Learning\n\n*C++:*\n\n- https://github.com/purundong/test_rl\n\n\n**Study notes**\n\n*English:*\n\n- https://lyk-love.cn/tags/reinforcement-learning/ \nby a graduate student from UC Davis\n\n*Chinese:* \n\n- https://github.com/Peanut-Study/Reinforcement-Learning-Study-Note/tree/main (Jan 2026)\n  \n- https://zhuanlan.zhihu.com/p/692207843 \n\n- https://blog.csdn.net/qq_64671439/category_12540921.html\n\n- http://t.csdnimg.cn/EH4rj\n\n- https://blog.csdn.net/LvGreat/article/details/135454738\n\n- https://xinzhe.blog.csdn.net/article/details/129452000  \n\n- https://blog.csdn.net/v20000727/article/details/136870879?spm=1001.2014.3001.5502\n\n- https://blog.csdn.net/m0_64952374/category_12883361.html\n\nThere 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.\n\n**Bilibili videos made based on my course**\n\n- https://www.bilibili.com/video/BV1DMBYB6Edo （Jan 2026）\n\n- https://www.bilibili.com/video/BV1fW421w7NH\n\n- https://www.bilibili.com/video/BV1Ne411m7GX\n  \n- https://www.bilibili.com/video/BV1HX4y1H7uR\n  \n- https://www.bilibili.com/video/BV1TgzsYDEnP\n  \n- https://www.bilibili.com/video/BV1CQ4y1J7zu\n\n# Update history \n\n**(July 2025) Minor update: Typo corrections**\n\nIt 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.\n\nFinally, 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.\n\n**(Jun 2025) 10,000+ stars!**\n\n(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!\n\n**(Oct 2024) Book cover**\n\nThe 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.\n\n\n**(Sep 2024) Minor update before printing by Springer**\n\nI revised some very minor places that readers may hardly notice. It is supposed to be the final version before printing by Springer. \n\n**(Aug 2024) 3000 Stars and more code**\n\nThe book has received 3000+ stars, which is a great achievement to me. Thanks to everyone. Hope it really helped you.\n\nI 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:-)\n\n**(Jun 2024) Minor update before printing**\n\nThis 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.\n\n**(Apr 2024) Code for the Grid-World Environment**\n\nWe 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.\n\nPlease 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.\n\nI 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.\n\nYou are welcome to provide any feedback about the code such as bugs if detected.\n\n**(Mar 2024) 2K stars**\n\nThe book has received 2K stars. I also received many positive evaluations of the book from many readers. Very glad that it can be helpful. \n\n**(Mar 2024) Minor update**\n\nThe third version of the draft of the book is online now.\n\nCompared 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. \n\n**(Sep 2023) 1000+ stars**\n\nThe book received 1000+ stars! Thank everybody!\n\n**(Aug 2023) Major update - second version**\n\n*The second version of the draft of the book is online now!!*\n\nCompared 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. \n\nI 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.\n\n**(Nov 2022) Will be jointly published**\n\nThis book will be published *jointly by Springer Nature and Tsinghua University Press*. It will probably be printed in the second half of 2023.\n\nI 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!\n\n**(Oct 2022) Lecture notes and vidoes**\n\nThe *lecture slides* have been uploaded in the folder \"Lecture slides.\"\n\nThe *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\n\n**(Aug 2022) First draft**\n\nThe first draft of the book is online.\n"
  }
]