Skip to content

Commit bd85a5a

Browse files
added new problem implement_the_sarsa_algorithm_on_policy
1 parent 847db56 commit bd85a5a

7 files changed

Lines changed: 128 additions & 0 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Implement the **SARSA** algorithm to estimate Q-values for a given set of deterministic transitions using greedy action selection.
2+
3+
- All Q-values are initialized to zero.
4+
- Each episode starts from a given initial state.
5+
- The episode ends when it reaches the $terminal$ state or when the number of steps exceeds $maxsteps$.
6+
- Changes made to Q-values are persistent across episodes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"input": "transitions = {\n ('A', 'left'): (5.0, 'B'),\n ('A', 'right'): (1.0, 'C'),\n ('B', 'left'): (2.0, 'A'),\n ('B', 'right'): (0.0, 'C'),\n ('C', 'down'): (1.0, 'terminal')\n}\n\ninitial_states = ['A', 'B']\nalpha = 0.1\ngamma = 0.9\nmax_steps = 10\n\nQ = sarsa_update(transitions, initial_states, alpha, gamma, max_steps)\n\nfor k in sorted(transitions):\n print(f\"Q{str(k):15} = {Q[k]:.4f}\")",
3+
"output": "Q('A', 'left') = 4.2181\nQ('A', 'right') = 0.0000\nQ('B', 'left') = 2.7901\nQ('B', 'right') = 0.0000",
4+
"reasoning": "The SARSA update rule is:\nQ(s,a) <- Q(s,a) + alpha * [reward + gamma * Q(s',a') - Q(s,a)]\n\nStarting from initial Q-values of 0, each episode updates Q-values based on the transitions.\n- Q('A', 'left') increases because it leads to B, and B can eventually return to A or C with additional rewards.\n- Q('A', 'right') and Q('B', 'right') remain 0.0 because the next state C leads directly to terminal with small reward.\n- Q('B', 'left') increases due to cyclic transitions giving non-zero rewards."
5+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
# Learn Section
3+
4+
# SARSA: On-Policy TD Control
5+
6+
**Goal**: Estimate the action-value function $Q^\pi \approx q^*$ using the SARSA algorithm (on-policy Temporal-Difference control).
7+
8+
## Parameters
9+
- Step size $\alpha \in (0, 1]$
10+
- Discount factor $\gamma \in [0, 1]$
11+
12+
## Initialization
13+
- Initialize $Q(s, a)$ arbitrarily for all $s \in \mathcal{S}^+$, $a \in \mathcal{A}(s)$
14+
- Set $Q(\text{terminal}, \cdot) = 0$
15+
16+
## Algorithm
17+
18+
**Loop for each episode:**
19+
1. Initialize state $S$
20+
2. Choose action $A$ from $S$ using a policy derived from $Q$ (e.g., greedy)
21+
22+
**Loop for each step of the episode:**
23+
1. Take action $A$, observe reward $R$ and next state $S'$
24+
2. Choose next action $A'$ from $S'$ using a policy derived from $Q$ (e.g., greedy)
25+
3. Update the action-value:
26+
$
27+
Q(S, A) \leftarrow Q(S, A) + \alpha \left[ R + \gamma Q(S', A') - Q(S, A) \right]
28+
$
29+
4. Set $S \leftarrow S'$, $A \leftarrow A'$
30+
5. Repeat until $S$ is terminal
31+
32+
This algorithm continuously improves the policy as it explores and learns from interaction, making it suitable for online reinforcement learning scenarios.
33+
34+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"id": "173",
3+
"title": "implement_the_SARSA_Algorithm_on_policy",
4+
"difficulty": "medium",
5+
"category": "Reinforcement Learning",
6+
"video": "",
7+
"likes": "0",
8+
"dislikes": "0",
9+
"contributor": [
10+
{
11+
"profile_link": "https://github.com/836hardik-agrawal",
12+
"name": "Hardik Agrawal"
13+
}
14+
]
15+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from collections import defaultdict
2+
def select_greedy_action(state,action_after_state,Q):
3+
actions = action_after_state.get(state,[])
4+
if not actions:
5+
return None
6+
else:
7+
max_q = max(Q[(state,a)] for a in actions)
8+
action_required = []
9+
for a in actions:
10+
if(Q[(state,a)] == max_q):
11+
action_required.append(a)
12+
final_action = min(action_required)
13+
return final_action
14+
def sarsa_update(transitions, initial_states, alpha, gamma, max_steps):
15+
Q = defaultdict(float)
16+
action_after_state = defaultdict(set)
17+
for (s,a) in transitions:
18+
action_after_state[s].add(a)
19+
20+
for state in initial_states:
21+
steps = 0
22+
s = state
23+
action = select_greedy_action(s,action_after_state,Q)
24+
while s!="terminal" and steps<max_steps:
25+
reward,next_state = transitions[(s,action)]
26+
steps+=1
27+
if next_state == "terminal":
28+
action_next = None
29+
next_q = 0
30+
else:
31+
action_next = select_greedy_action(next_state,action_after_state,Q)
32+
next_q = Q[next_state,action_next]
33+
34+
Q[(s,action)] += alpha*(reward+ gamma*next_q- Q[(s,action)])
35+
s = next_state
36+
action = action_next
37+
38+
return Q
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
def sarsa_update(transitions, initial_states, alpha, gamma, max_steps):
2+
"""
3+
Perform SARSA updates on the given environment transitions.
4+
5+
Args:
6+
transitions (dict): mapping (state, action) -> (reward, next_state)
7+
initial_states (list): list of starting states to simulate episodes from
8+
alpha (float): learning rate
9+
gamma (float): discount factor
10+
max_steps (int): maximum steps allowed per episode
11+
12+
Returns:
13+
dict: final Q-table as a dictionary {(state, action): value}
14+
"""
15+
# Your code here
16+
pass
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[
2+
{
3+
"test": "transitions = {\n ('A', 'go'): (1.0, 'B'),\n ('B', 'go'): (2.0, 'C'),\n ('C', 'go'): (3.0, 'terminal')\n}\ninitial_states = ['A']\nalpha = 0.5\ngamma = 0.9\nmax_steps = 5\nQ = sarsa_update(transitions, initial_states, alpha, gamma, max_steps)\nfor k in sorted(Q):\n print(f\"Q{str(k):15} = {Q[k]:.4f}\")",
4+
"expected_output": "Q('A', 'go') = 0.5000\nQ('B', 'go') = 1.0000\nQ('C', 'go') = 1.5000"
5+
},
6+
{
7+
"test": "transitions = {\n ('S1', 'left'): (2.0, 'S2'),\n ('S1', 'right'): (1.0, 'S3'),\n ('S2', 'left'): (0.5, 'terminal'),\n ('S3', 'right'): (0.5, 'terminal')\n}\ninitial_states = ['S1', 'S2', 'S3']\nalpha = 0.1\ngamma = 0.8\nmax_steps = 10\nQ = sarsa_update(transitions, initial_states, alpha, gamma, max_steps)\nfor k in sorted(Q):\n print(f\"Q{str(k):15} = {Q[k]:.4f}\")",
8+
"expected_output": "Q('S1', 'left') = 0.2000\nQ('S1', 'right') = 0.0000\nQ('S2', 'left') = 0.0950\nQ('S3', 'right') = 0.0500"
9+
},
10+
{
11+
"test": "transitions = {\n ('A', 'x'): (0.0, 'terminal'),\n ('A', 'y'): (5.0, 'B'),\n ('B', 'z'): (2.0, 'terminal')\n}\ninitial_states = ['A']\nalpha = 0.4\ngamma = 0.9\nmax_steps = 3\nQ = sarsa_update(transitions, initial_states, alpha, gamma, max_steps)\nfor k in sorted(Q):\n print(f\"Q{str(k):15} = {Q[k]:.4f}\")",
12+
"expected_output": "Q('A', 'x') = 0.0000\nQ('A', 'y') = 0.0000\nQ('B', 'z') = 0.0000"
13+
}
14+
]

0 commit comments

Comments
 (0)