First time studying this topic?

Launch the interactive walkthrough to discover each component, including the 3D Q-Sphere Lab & Python in Colab.

Back to Reinforcement Learning
Topic 4.9

Q-Learning

Learn how agents discover optimal strategies through Q-learning, a fundamental reinforcement learning algorithm.

Learning Objectives

  • ✓Understand the Q-learning algorithm
  • ✓Learn how Q-values represent action quality
  • ✓Implement a simple Q-learning example in Python
  • ✓Visualize the learning process

📖Let's Begin with a Story

Imagine you're in a new city trying to find the best route from your hotel to a famous landmark. You don't have a map, but you can explore. On your first attempt, you take random turns, sometimes getting closer, sometimes farther away. When you finally reach your destination, you remember which turns led you forward and which led you astray. The next day, you try again. This time, you favor the turns that worked well yesterday, but you also try a few new paths — maybe there's an even better route. Over many days, you learn not just one route, but the value of taking each possible turn at each intersection. Eventually, you know exactly which turn to take at every point to reach your destination as quickly as possible. This is essentially how Q-learning works — an agent learns the value (quality) of each action in each situation through trial, error, and experience.

Why Should You Learn Q-Learning?

🎯 Practical & Engineering Stakes
1. Foundational algorithm: Q-learning is one of the most important and widely-used reinforcement learning algorithms. 2. No model required: Unlike some methods, Q-learning doesn't need to know how the environment works — it learns purely from experience. 3. Proven effectiveness: Q-learning has successfully solved games, robot control, resource management, and many real-world problems. 4. Gateway to deep RL: Understanding Q-learning is essential before learning Deep Q-Networks (DQN) and modern deep reinforcement learning. 5. Practical applications: Used in robotics, game AI, recommendation systems, traffic control, and resource optimization.

What Is It?

Simple Explanation

Q-learning is a method where an agent learns the "quality" (Q-value) of taking each possible action in each possible situation. It explores the environment, tries different actions, receives rewards, and gradually learns which actions lead to the best long-term outcomes. The "Q" stands for "quality" — how good is this action in this situation?

Technical Explanation

Q-learning is a model-free, off-policy reinforcement learning algorithm that learns the optimal action-value function Q*(s,a), which represents the expected cumulative reward of taking action a in state s and following the optimal policy thereafter. The algorithm updates Q-values iteratively using the Bellman equation, balancing exploration and exploitation to converge to the optimal policy.

📚 Key Terms

Q-Value

Simple: A number representing how good an action is in a particular situation
Technical: The expected cumulative future reward for taking a specific action in a specific state and following the optimal policy thereafter

Q-Table

Simple: A table storing Q-values for all state-action pairs
Technical: A lookup table with states as rows and actions as columns, where each cell contains the Q-value Q(s,a)

Learning Rate (α)

Simple: How quickly the agent updates its knowledge
Technical: A hyperparameter (0 < α ≤ 1) controlling the degree to which new information overrides old information in Q-value updates

Discount Factor (γ)

Simple: How much the agent values future rewards compared to immediate ones
Technical: A hyperparameter (0 ≤ γ ≤ 1) determining the present value of future rewards

📐 Mathematical Foundation

LaTeX KaTeX
Q(s,a)←Q(s,a)+α[r+γmax⁡a′Q(s′,a′)−Q(s,a)]Q(s,a) \leftarrow Q(s,a) + \alpha[r + \gamma \max_{a'} Q(s',a') - Q(s,a)]

What does it mean?

This is the Q-learning update rule. It adjusts the Q-value for taking action a in state s based on the reward received and the expected future rewards.

Understanding the Symbols

Symbol / TermMeaningBeginner Interpretation
Q(s,a)Q(s,a)Current Q-value for state s and action aHow good we currently think this action is in this situation
α(alpha)α (alpha)Learning rateHow much we update our belief (typically 0.1 to 0.5)
rrReward receivedImmediate feedback from taking the action
γ(gamma)γ (gamma)Discount factorHow much we care about future rewards (typically 0.9 to 0.99)
s′s'Next stateThe new situation after taking the action
maxQ(s′,a′)max Q(s',a')Maximum Q-value in next stateThe value of the best action we can take from the new situation

📊 Numerical Example

Suppose we are in state s=5, take action a='right', receive reward r=10, move to state s'=7, and our learning rate α=0.1 and discount factor γ=0.9. Current Q(5,right)=20, and the maximum Q-value in state 7 is 30.

Q(5,right) = 20 + 0.1[10 + 0.9×30 - 20] Q(5,right) = 20 + 0.1[10 + 27 - 20] Q(5,right) = 20 + 0.1[17] Q(5,right) = 20 + 1.7 Q(5,right) = 21.7

Result: The Q-value for taking action "right" in state 5 increases from 20 to 21.7, indicating we now believe this action is slightly better than we thought before.

⚙️ How Does It Work?

1

Initialize Q-Table

Create a table with all possible states and actions. Set all Q-values to zero (or small random values).

2

Observe Current State

The agent looks at its current situation in the environment.

3

Choose Action

Select an action using an exploration strategy (like epsilon-greedy): usually pick the best known action, but sometimes try random actions to explore.

4

Take Action and Observe

Execute the action, observe the reward received and the new state.

5

Update Q-Value

Use the Q-learning formula to update the Q-value based on the reward and expected future rewards.

6

Repeat

Continue this process for many episodes until Q-values converge to optimal values.

🌍 Where Is It Used?

Game Playing

Problem: Teaching a computer to play games optimally without programming specific strategies.

Solution: Q-learning discovers winning strategies by playing many games and learning which moves lead to victory.

Robot Navigation

Problem: A robot needs to learn to navigate through a space and reach goals while avoiding obstacles.

Solution: Q-learning allows the robot to learn optimal paths through trial and error, discovering efficient routes.

Resource Management

Problem: Optimizing when to charge batteries, allocate server resources, or schedule tasks efficiently.

Solution: Q-learning learns optimal timing and allocation strategies that maximize long-term efficiency.

🐍 Python Hands-On: Simple Q-Learning: Grid World Navigation

We'll implement Q-learning for a simple grid world where an agent learns to reach a goal.

Open Colab

1Install Required Packages

For Google Colab or Jupyter notebooks, run this shell command to install the required dependencies:

Terminal / Notebook Install Commandbash
!pip install numpy matplotlib
Packages:
numpymatplotlib

2Import Libraries

Import Statementspython
1import numpy as np
2import matplotlib.pyplot as plt

import numpy as np → NumPy provides numerical array operations for our Q-table and calculations.

import matplotlib.pyplot as plt → Matplotlib helps us visualize the learning progress and Q-values.

3Demonstration Code & Logic

Python Execution Codepython
1# ─── SECTION 1: ENVIRONMENT SETUP ───────────────────────────────────────
2# Define the environment
3GRID_SIZE = 5
4START_STATE = 0
5GOAL_STATE = 24
6
7# ─── SECTION 2: HYPERPARAMETERS ────────────────────────────────────────────
8# Q-learning parameters
9LEARNING_RATE = 0.1
10DISCOUNT_FACTOR = 0.9
11EPSILON = 0.1
12EPISODES = 500
13
14# ─── SECTION 3: Q-TABLE INITIALIZATION ─────────────────────────────────────
15# Initialize Q-table
16num_states = GRID_SIZE * GRID_SIZE
17num_actions = 4 # up, down, left, right
18Q = np.zeros((num_states, num_actions))
19
20# ─── SECTION 4: HELPER FUNCTIONS ───────────────────────────────────────────
21# Helper function: get next state
22def get_next_state(state, action):
23 row, col = state // GRID_SIZE, state % GRID_SIZE
24 if action == 0 and row > 0: row -= 1 # up
25 elif action == 1 and row < GRID_SIZE-1: row += 1 # down
26 elif action == 2 and col > 0: col -= 1 # left
27 elif action == 3 and col < GRID_SIZE-1: col += 1 # right
28 return row * GRID_SIZE + col
29
30# Helper function: get reward
31def get_reward(state):
32 if state == GOAL_STATE: return 100
33 else: return -1
34
35# ─── SECTION 5: TRAINING LOOP ──────────────────────────────────────────────
36# Training loop
37rewards_per_episode = []
38
39for episode in range(EPISODES):
40 state = START_STATE
41 total_reward = 0
42 steps = 0
43
44 while state != GOAL_STATE and steps < 100:
45 # Choose action (epsilon-greedy)
46 if np.random.random() < EPSILON:
47 action = np.random.randint(0, num_actions)
48 else:
49 action = np.argmax(Q[state])
50
51 # Take action
52 next_state = get_next_state(state, action)
53 reward = get_reward(next_state)
54
55 # Q-learning update
56 best_next_q = np.max(Q[next_state])
57 Q[state, action] = Q[state, action] + LEARNING_RATE * (reward + DISCOUNT_FACTOR * best_next_q - Q[state, action])
58
59 state = next_state
60 total_reward += reward
61 steps += 1
62
63 rewards_per_episode.append(total_reward)
64
65# ─── SECTION 6: VISUALIZATION ──────────────────────────────────────────────
66# Visualize learning progress
67plt.figure(figsize=(10, 5))
68plt.plot(rewards_per_episode)
69plt.xlabel('Episode')
70plt.ylabel('Total Reward')
71plt.title('Q-Learning Progress: Reward per Episode')
72plt.grid(True)
73plt.show()
74
75print(f"Training completed over {EPISODES} episodes")
76print(f"Final average reward (last 100 episodes): {np.mean(rewards_per_episode[-100:]):.2f}")
Step-by-Step Code Breakdown:

# ─── SECTION 1: ENVIRONMENT SETUP ───────────────────────────────────────

📌 Section 1 begins here. We first describe the world the agent lives in — a 5×5 grid with 25 cells. This is the "environment" in reinforcement learning.

# Define the environment

💬 Comment: This block sets up the rules of the grid world — its size, where the agent starts, and where the goal is.

GRID_SIZE = 5

📐 Sets the grid to 5 columns × 5 rows = 25 total cells. States are numbered 0 to 24 (top-left = 0, bottom-right = 24). UPPER_CASE naming signals this is a constant that should not change during the run.

START_STATE = 0

🚀 The agent always begins at state 0 (top-left corner, row=0, col=0). This is reset at the start of every episode so the agent re-learns from the same starting point each time.

GOAL_STATE = 24

🎯 The destination is state 24 (bottom-right corner, row=4, col=4). When the agent reaches this state, the episode ends with a large reward. The entire purpose of training is to learn the fastest path from state 0 → state 24.

# ─── SECTION 2: HYPERPARAMETERS ────────────────────────────────────────────

📌 Section 2: Hyperparameters are knobs you tune to control how the agent learns. These are NOT learned — you choose them before training.

# Q-learning parameters

💬 Comment: These four numbers control the speed, depth, curiosity, and duration of learning.

LEARNING_RATE = 0.1

📈 Alpha (α) = 0.1. This controls HOW FAST the agent updates its Q-values when it learns something new. Think of it as "how seriously do I take new information?" • α = 0.1 → 10% of new info replaces old belief each step (stable, gradual learning) • α = 1.0 → completely replaces old belief (too fast, unstable) • α = 0.0 → agent never learns at all ✅ 0.1 is a safe, standard choice for small environments.

DISCOUNT_FACTOR = 0.9

⏳ Gamma (γ) = 0.9. Controls HOW MUCH the agent values FUTURE rewards versus IMMEDIATE rewards. • γ = 0.9 → future reward is worth 90% of an equal immediate reward (forward-thinking agent) • γ = 0.0 → agent is completely greedy, only cares about the next immediate reward • γ = 1.0 → agent values all future rewards equally (can cause instability) ✅ 0.9 makes the agent plan ahead — essential for navigating a grid where the goal is many steps away.

EPSILON = 0.1

🎲 Epsilon (ε) = 0.1. Controls the EXPLORATION vs EXPLOITATION trade-off. • With 10% probability, the agent tries a RANDOM action (explore — discover new paths) • With 90% probability, the agent picks the BEST known action (exploit — use what it learned) ✅ This prevents the agent from getting stuck always doing the same thing. Without exploration, it might never find the optimal path.

EPISODES = 500

🔁 The agent will train for 500 complete episodes. One episode = one attempt to go from START → GOAL (or max 100 steps). More episodes = more practice = better Q-values. 500 is enough to converge on a good policy for this small 5×5 grid.

# ─── SECTION 3: Q-TABLE INITIALIZATION ─────────────────────────────────────

📌 Section 3: The Q-table is the agent's "brain" — a memory of how good each action is in each state.

# Initialize Q-table

💬 Comment: Before training, the agent knows nothing, so all Q-values start at zero.

num_states = GRID_SIZE * GRID_SIZE

🧮 Calculates total number of states: 5 × 5 = 25. Each cell in the grid is one state. This tells us how many rows the Q-table needs.

num_actions = 4 # up, down, left, right

🧭 The agent has 4 possible moves at every state: • Action 0 = UP (move to the row above) • Action 1 = DOWN (move to the row below) • Action 2 = LEFT (move to the column left) • Action 3 = RIGHT (move to the column right) The comment reminds us of this mapping. This tells us how many columns the Q-table needs.

Q = np.zeros((num_states, num_actions))

🗃️ Creates the Q-table: a 25×4 matrix (25 states × 4 actions), filled entirely with zeros. • Each row = one state (a grid cell) • Each column = one action (up/down/left/right) • Each cell Q[s, a] = estimated quality of taking action a in state s → At start, Q[0,0]=0, Q[0,1]=0, Q[0,2]=0, Q[0,3]=0 ... all zeros → After training, Q[0,3] might be large because "go right" from start is a good idea.

# ─── SECTION 4: HELPER FUNCTIONS ───────────────────────────────────────────

📌 Section 4: Two small utility functions that the training loop will call thousands of times.

# Helper function: get next state

💬 Comment: This function simulates the physics of the grid — what happens when the agent moves.

def get_next_state(state, action):

🔧 Defines a function that takes the current state (0–24) and chosen action (0–3), and returns the resulting next state. It handles wall collisions — if the agent tries to move off the grid, it stays in place.

row, col = state // GRID_SIZE, state % GRID_SIZE

🗺️ Converts the flat state number into 2D grid coordinates: • row = state // 5 (integer division: state 7 → row 1) • col = state % 5 (remainder: state 7 → col 2) Example: state 12 → row=2, col=2 (center of the grid) This lets us check if moving would go out of bounds.

if action == 0 and row > 0: row -= 1 # up

⬆️ Action 0 = UP. Subtracts 1 from the row (moves toward the top). The guard "row > 0" ensures the agent doesn't go above the top edge. If at row=0 and tries to go up → stays at row=0 (wall collision).

elif action == 1 and row < GRID_SIZE-1: row += 1 # down

⬇️ Action 1 = DOWN. Adds 1 to the row (moves toward the bottom). Guard "row < 4" prevents going below the last row. If at row=4 (bottom edge) and tries to go down → stays at row=4.

elif action == 2 and col > 0: col -= 1 # left

⬅️ Action 2 = LEFT. Subtracts 1 from the column (moves toward the left). Guard "col > 0" prevents going off the left edge. If at col=0 (left edge) and tries to go left → stays at col=0.

elif action == 3 and col < GRID_SIZE-1: col += 1 # right

➡️ Action 3 = RIGHT. Adds 1 to the column (moves toward the right). Guard "col < 4" prevents going off the right edge. If at col=4 (right edge) and tries to go right → stays at col=4.

return row * GRID_SIZE + col

🔄 Converts 2D coordinates back to a flat state number: next_state = row × 5 + col Example: row=2, col=3 → state = 2×5+3 = 13 This reverses the earlier decomposition and gives a single integer the Q-table can use as an index.

# Helper function: get reward

💬 Comment: Defines the reward signal — the feedback the agent receives after each action.

def get_reward(state):

🏆 Defines a reward function. Takes the state the agent just moved into and returns a number: • Positive number = good outcome • Negative number = bad/costly outcome This is how the environment "tells" the agent whether it did something worthwhile.

if state == GOAL_STATE: return 100

✅ If the agent reaches state 24 (the goal), it gets a reward of +100. This large positive signal teaches the agent that reaching the goal is highly desirable. The agent will update Q-values to make goal-reaching actions much more attractive.

else: return -1

⏱️ Every step that is NOT the goal gives a reward of -1. This "step penalty" encourages efficiency — the agent is penalized for wasting time. Without this, the agent might wander aimlessly and still get the +100 eventually. With -1 per step, the agent learns to reach the goal in as few moves as possible.

# ─── SECTION 5: TRAINING LOOP ──────────────────────────────────────────────

📌 Section 5: The core of Q-learning — repeatedly running episodes and updating the Q-table after every step.

# Training loop

💬 Comment: This is where the actual learning happens over 500 episodes.

rewards_per_episode = []

📊 Creates an empty Python list to record the total reward earned in each episode. After training, we'll plot this list to see how the agent improved over time. If rewards increase episode-by-episode, the agent is learning!

for episode in range(EPISODES):

🔁 Outer loop: repeats 500 times (episode = 0, 1, 2, ... 499). Each iteration is one complete training attempt — the agent starts fresh at state 0 and tries to reach state 24.

state = START_STATE

📍 Resets the agent's position to state 0 (top-left corner) at the start of every episode. This ensures each episode is a fresh attempt, just like a player starting a new game from the beginning.

total_reward = 0

💰 Initializes a running counter for the total reward accumulated during this episode. Starts at 0 and we add to it after each step. At the end of the episode, this tells us how well the agent performed.

steps = 0

👟 Counter for how many steps taken in this episode. Used to enforce the max-100-step limit. Prevents infinite loops in case the agent gets stuck in a cycle without reaching the goal.

while state != GOAL_STATE and steps < 100:

🔄 Inner loop: runs until EITHER the goal is reached (state == 24) OR 100 steps have been taken. This inner loop is one episode's decision-action-learn cycle. The 100-step cap prevents the agent from running forever early in training when it's mostly lost.

# Choose action (epsilon-greedy)

💬 Comment: The ε-greedy strategy decides whether to explore or exploit on each step.

if np.random.random() < EPSILON:

🎲 np.random.random() generates a float between 0.0 and 1.0 uniformly at random. If it falls below EPSILON (0.1), we explore. Since EPSILON=0.1, this happens ~10% of the time. The other 90% we exploit what we already know.

action = np.random.randint(0, num_actions)

🃏 EXPLORE: picks a random action integer from {0, 1, 2, 3} with equal probability. This is the exploration step — the agent tries something it might not normally choose, which might reveal a better path it didn't know about.

else:

🧠 EXPLOIT: we skip the random choice and use what the agent has learned.

action = np.argmax(Q[state])

🏹 Q[state] is a 1D array of 4 Q-values (one per action) for the current state. np.argmax() returns the index of the LARGEST value — the action the agent currently believes is best. Example: if Q[5] = [2.1, 4.7, 1.3, 3.9], then argmax = 1 (DOWN has the highest Q-value → take action DOWN).

# Take action

💬 Comment: Execute the chosen action and observe what happens in the environment.

next_state = get_next_state(state, action)

🌍 Calls our helper function to simulate the action: given the current state and chosen action, what cell does the agent land in? The result is the "next_state" — the agent's new position on the grid.

reward = get_reward(next_state)

🏅 Asks the environment: "What reward do I get for being in next_state?" Returns either +100 (goal reached!) or -1 (any other cell). This reward will be used to update the Q-value for the action just taken.

# Q-learning update

💬 Comment: This is the heart of the algorithm — updating the Q-table using the Bellman equation.

best_next_q = np.max(Q[next_state])

🔭 Looks ahead: "What is the BEST Q-value I could get from the next_state, regardless of which action I would take?" np.max(Q[next_state]) scans all 4 action Q-values in the next state and returns the maximum. This is the max Q(s',a') term from the Bellman equation.

Q[state, action] = Q[state, action] + LEARNING_RATE * (reward + DISCOUNT_FACTOR * best_next_q - Q[state, action])

⚡ THE BELLMAN UPDATE — the single most important line in Q-learning! Breaking it down step-by-step: ① reward + DISCOUNT_FACTOR * best_next_q → "What is this action actually worth?" = immediate reward + (0.9 × best future value) → This is called the TD Target (Temporal Difference Target) ② TD Target - Q[state, action] → "How surprised are we?" = difference between what we expected vs what actually happened → This is called the TD Error ③ LEARNING_RATE * TD_Error → "How much do we adjust?" = 0.1 × TD Error (small, gradual adjustment) ④ Q[state, action] = Q[state, action] + adjustment → Update the Q-value: nudge it toward reality If TD Error is positive → we underestimated, Q goes UP If TD Error is negative → we overestimated, Q goes DOWN If TD Error is zero → our estimate was perfect, Q stays SAME

state = next_state

📍 The agent "moves" — updates its current state to the new state. Now the agent is at the cell it just moved to. The next iteration of the while loop will start decision-making from this new position.

total_reward += reward

💰 Adds the step's reward to the episode's running total. After the episode ends, this sum tells us how well the agent did overall. Early episodes: very negative (many -1 steps, rarely reaches +100). Late episodes: near +100 - (few steps × 1) = efficient paths.

steps += 1

👟 Increments the step counter by 1 so the while-loop condition (steps < 100) can eventually stop an episode where the agent is wandering. Without this counter, a lost agent would loop forever.

rewards_per_episode.append(total_reward)

📈 At the END of each episode, save the total reward to the list. After 500 episodes, this list has 500 numbers. Plotting them reveals the learning curve: should trend upward from very negative (lost/wandering) to near positive (efficient goal-reaching).

# ─── SECTION 6: VISUALIZATION ──────────────────────────────────────────────

📌 Section 6: Plot the learning curve to visually confirm the agent improved over time.

# Visualize learning progress

💬 Comment: Create a graph showing how the agent's total reward per episode changed over training.

plt.figure(figsize=(10, 5))

🖼️ Creates a new matplotlib figure (plot canvas) with width=10 inches and height=5 inches. Always call this before plt.plot() to control the output size. A wider figure makes the learning curve easier to read.

plt.plot(rewards_per_episode)

📉📈 Plots the 500 episode rewards as a line graph: • X-axis = episode number (0 to 499) • Y-axis = total reward that episode • You should see the line start very low (negative, many wasted steps) and gradually climb higher (agent finds shorter paths and collects less penalties).

plt.xlabel('Episode')

🏷️ Labels the X-axis "Episode" so readers know each point on the x-axis represents one complete training attempt.

plt.ylabel('Total Reward')

🏷️ Labels the Y-axis "Total Reward" — the sum of all rewards in an episode. Negative values = agent was slow. Values close to +100 = agent found the goal quickly with few wasted steps.

plt.title('Q-Learning Progress: Reward per Episode')

📋 Adds a descriptive title to the chart. This makes the plot self-explanatory when shared or included in a report.

plt.grid(True)

📏 Adds a light grey grid to the plot background. Grids make it much easier to read values off the chart and spot trends, especially whether the curve is flat or rising.

plt.show()

👁️ Renders and displays the finished plot. In Google Colab, this appears inline below the cell. In a local script, it opens a pop-up window. Without plt.show(), nothing appears on screen.

print(f"Training completed over {EPISODES} episodes")

📢 Prints a confirmation message after all training is done. The f-string inserts the value of EPISODES (500) into the string automatically → "Training completed over 500 episodes".

print(f"Final average reward (last 100 episodes): {np.mean(rewards_per_episode[-100:]):.2f}")

📊 Evaluates and prints the agent's final performance: • rewards_per_episode[-100:] → slices the LAST 100 values from the list • np.mean(...) → computes the average of those 100 values • :.2f → formats the float to 2 decimal places Why the last 100 episodes? Because early training is chaotic — the agent is still learning. The last 100 episodes represent the agent after it has mostly converged to a good policy. A high average here confirms successful learning.

📋 Complete Script (All-in-One)

Click "Copy for Colab", open Google Colab, paste into a single cell, and run.

Google Colab Notebook Scriptpython
1# =========================================================
2# Simple Q-Learning: Grid World Navigation
3# Prepared for Google Colab (Run with Shift + Enter)
4# =========================================================
5
6# Step 1: Install required packages
7!pip install numpy matplotlib
8
9# Step 2: Import libraries
10import numpy as np
11import matplotlib.pyplot as plt
12
13# Step 3: Run Demonstration
14# ─── SECTION 1: ENVIRONMENT SETUP ───────────────────────────────────────
15# Define the environment
16GRID_SIZE = 5
17START_STATE = 0
18GOAL_STATE = 24
19
20# ─── SECTION 2: HYPERPARAMETERS ────────────────────────────────────────────
21# Q-learning parameters
22LEARNING_RATE = 0.1
23DISCOUNT_FACTOR = 0.9
24EPSILON = 0.1
25EPISODES = 500
26
27# ─── SECTION 3: Q-TABLE INITIALIZATION ─────────────────────────────────────
28# Initialize Q-table
29num_states = GRID_SIZE * GRID_SIZE
30num_actions = 4 # up, down, left, right
31Q = np.zeros((num_states, num_actions))
32
33# ─── SECTION 4: HELPER FUNCTIONS ───────────────────────────────────────────
34# Helper function: get next state
35def get_next_state(state, action):
36 row, col = state // GRID_SIZE, state % GRID_SIZE
37 if action == 0 and row > 0: row -= 1 # up
38 elif action == 1 and row < GRID_SIZE-1: row += 1 # down
39 elif action == 2 and col > 0: col -= 1 # left
40 elif action == 3 and col < GRID_SIZE-1: col += 1 # right
41 return row * GRID_SIZE + col
42
43# Helper function: get reward
44def get_reward(state):
45 if state == GOAL_STATE: return 100
46 else: return -1
47
48# ─── SECTION 5: TRAINING LOOP ──────────────────────────────────────────────
49# Training loop
50rewards_per_episode = []
51
52for episode in range(EPISODES):
53 state = START_STATE
54 total_reward = 0
55 steps = 0
56
57 while state != GOAL_STATE and steps < 100:
58 # Choose action (epsilon-greedy)
59 if np.random.random() < EPSILON:
60 action = np.random.randint(0, num_actions)
61 else:
62 action = np.argmax(Q[state])
63
64 # Take action
65 next_state = get_next_state(state, action)
66 reward = get_reward(next_state)
67
68 # Q-learning update
69 best_next_q = np.max(Q[next_state])
70 Q[state, action] = Q[state, action] + LEARNING_RATE * (reward + DISCOUNT_FACTOR * best_next_q - Q[state, action])
71
72 state = next_state
73 total_reward += reward
74 steps += 1
75
76 rewards_per_episode.append(total_reward)
77
78# ─── SECTION 6: VISUALIZATION ──────────────────────────────────────────────
79# Visualize learning progress
80plt.figure(figsize=(10, 5))
81plt.plot(rewards_per_episode)
82plt.xlabel('Episode')
83plt.ylabel('Total Reward')
84plt.title('Q-Learning Progress: Reward per Episode')
85plt.grid(True)
86plt.show()
87
88print(f"Training completed over {EPISODES} episodes")
89print(f"Final average reward (last 100 episodes): {np.mean(rewards_per_episode[-100:]):.2f}")
⚡ How to Run in Google Colab (3 Quick Steps)
  1. Click "Copy for Google Colab" above.
  2. Click Open New Google Colab Notebook (opens in a new tab).
  3. Click on the first empty code cell, press Ctrl + V (or Cmd + V) to paste, then press Shift + Enter to execute!

🔄 Algorithmic Execution Flow

1
Environment Setup

Define grid world parameters and initialize Q-table with zeros.

→
2
Episode Loop

Run 500 training episodes where the agent explores and learns.

→
3
Action Selection

Use epsilon-greedy strategy to balance exploration and exploitation.

→
4
Q-Value Update

Apply Q-learning formula to update knowledge based on experience.

→
5
Visualization

Plot learning progress showing improvement over episodes.

📥 Input / Initial State
A 5×5 grid environment with start state (0) and goal state (24).
📤 Expected Output
A trained Q-table and a plot showing learning progress over 500 episodes.
💡 What Does This Demonstration Show?

Initially, the agent explores randomly, receiving negative rewards. As training progresses, the Q-table improves, and the agent learns to reach the goal more efficiently. The upward trend in the reward plot shows successful learning — the agent discovers better strategies over time.

Course Learning Resource • Slide DeckLesson 612 Slides

Lesson 6: Reinforcement Learning Foundations

Q-learning, Bellman optimality equation, exploration-exploitation trade-offs, and deep Q-learning.

Author: Dr. Syed Muzamil Basha• FDP Approved Curriculum
Open in New Tab

📝 Learning Check

Test your understanding with these questions. Remember, this is for learning, not examination!

Question 1: What does the "Q" in Q-learning stand for?

Question 2: What is the purpose of the learning rate (α) in Q-learning?

Question 3: What does the discount factor (γ) control?

Question 4: In the Q-learning update formula, what does max Q(s',a') represent?

Question 5: Why is the epsilon-greedy strategy used in Q-learning?