import numpy as np
import matplotlib.pyplot as plt
print("=" * 70)
print("PROGRAMAÇÃO DINÂMICA - ITERAÇÃO DE VALOR")
print("=" * 70)
# ============================================
# DEFINIÇÃO DO AMBIENTE
# ============================================
class AmbienteGrade:
"""Grade 4x4 com paredes e objetivo"""
def __init__(self):
# Mapa: 0=caminho, 1=parede, 2=objetivo
self.grid = np.array([
[0, 0, 0, 0],
[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 0, 2, 0]
])
self.n_estados = 16
self.n_acoes = 4 # 0=cima, 1=baixo, 2=esq, 3=dir
self.inicio = 0
self.objetivo = 14 # posição (3,2)
# Pré-computa transições
self.transicoes = {}
self.recompensas = {}
self._precomputar()
def _precomputar(self):
"""Calcula todas as transições e recompensas"""
for estado in range(self.n_estados):
linha = estado // 4
coluna = estado % 4
for acao in range(self.n_acoes):
# Calcula movimento
if acao == 0: # cima
nl = max(0, linha - 1)
nc = coluna
elif acao == 1: # baixo
nl = min(3, linha + 1)
nc = coluna
elif acao == 2: # esquerda
nl = linha
nc = max(0, coluna - 1)
else: # direita
nl = linha
nc = min(3, coluna + 1)
# Verifica parede
if self.grid[nl, nc] == 1:
prox_estado = estado
recompensa = -0.5
terminou = False
else:
prox_estado = nl * 4 + nc
if self.grid[nl, nc] == 2:
recompensa = 10.0
terminou = True
else:
recompensa = -0.1
terminou = False
self.transicoes[(estado, acao)] = prox_estado
self.recompensas[(estado, acao)] = recompensa
# ============================================
# ITERAÇÃO DE VALOR (PROGRAMAÇÃO DINÂMICA)
# ============================================
def iteracao_valor(ambiente, gamma=0.95, theta=1e-6, max_iter=1000):
"""Implementa iteração de valor para encontrar política ótima"""
V = np.zeros(ambiente.n_estados)
historico_valores = [] # para visualização
print(f"\n📊 Parâmetros:")
print(f" - γ (gamma) = {gamma}")
print(f" - θ (theta) = {theta}")
print(f" - Max iterações = {max_iter}")
for i in range(max_iter):
delta = 0
V_antigo = V.copy()
historico_valores.append(V.copy())
for s in range(ambiente.n_estados):
if s == ambiente.objetivo:
continue
# Calcula valor máximo sobre ações
valores_acoes = []
for a in range(ambiente.n_acoes):
s_prox = ambiente.transicoes[(s, a)]
r = ambiente.recompensas[(s, a)]
valor = r + gamma * V_antigo[s_prox]
valores_acoes.append(valor)
V[s] = max(valores_acoes)
delta = max(delta, abs(V[s] - V_antigo[s]))
if i % 50 == 0:
print(f" Iteração {i}: delta = {delta:.6f}")
if delta < theta:
print(f"\n✅ Convergiu após {i+1} iterações!")
break
# Extrai política ótima
politica = np.zeros(ambiente.n_estados, dtype=int)
for s in range(ambiente.n_estados):
if s == ambiente.objetivo:
politica[s] = -1
continue
valores_acoes = []
for a in range(ambiente.n_acoes):
s_prox = ambiente.transicoes[(s, a)]
r = ambiente.recompensas[(s, a)]
valores_acoes.append(r + gamma * V[s_prox])
politica[s] = np.argmax(valores_acoes)
return V, politica, historico_valores
# ============================================
# AVALIAÇÃO DA POLÍTICA
# ============================================
def avaliar_politica(ambiente, politica, gamma=0.95, max_passos=50):
"""Simula a política ótima para verificar seu desempenho"""
estado = ambiente.inicio
trajetoria = [estado]
recompensa_total = 0
passos = 0
while estado != ambiente.objetivo and passos < max_passos:
acao = politica[estado]
if acao == -1:
break
s_prox = ambiente.transicoes[(estado, acao)]
r = ambiente.recompensas[(estado, acao)]
trajetoria.append(s_prox)
recompensa_total += r
estado = s_prox
passos += 1
return trajetoria, recompensa_total, passos
# ============================================
# EXECUÇÃO PRINCIPAL
# ============================================
# Cria ambiente
ambiente = AmbienteGrade()
print("\n" + "=" * 70)
print("AMBIENTE: GRADE 4x4")
print("=" * 70)
print("\n🗺️ Mapa do ambiente:")
print(" Col0 Col1 Col2 Col3")
for i in range(4):
linha = f"Lin{i}: "
for j in range(4):
if ambiente.grid[i, j] == 1:
linha += " ██ "
elif ambiente.grid[i, j] == 2:
linha += " 🎯 "
else:
linha += " ·· "
print(linha)
print("\nLegenda: ·· = caminho | ██ = parede | 🎯 = objetivo (+10)")
print("Recompensas: -0.1 por passo | -0.5 por bater na parede")
# Executa iteração de valor
print("\n" + "=" * 70)
print("ITERAÇÃO DE VALOR (PROGRAMAÇÃO DINÂMICA)")
print("=" * 70)
V_otimo, politica_otima, historico = iteracao_valor(ambiente, gamma=0.95)
# Mostra função valor
print("\n" + "=" * 70)
print("FUNÇÃO VALOR ÓTIMA V*(s)")
print("=" * 70)
print("\n📈 Valores por estado:")
for i in range(4):
linha = ""
for j in range(4):
s = i * 4 + j
if ambiente.grid[i, j] == 1:
linha += " ██ "
elif s == ambiente.objetivo:
linha += " 🎯🎯 "
else:
linha += f" {V_otimo[s]:6.2f} "
print(linha)
# Mostra política ótima
print("\n" + "=" * 70)
print("POLÍTICA ÓTIMA π*(s)")
print("=" * 70)
setas = ['↑', '↓', '←', '→']
print("\n🎯 Melhor ação em cada estado:")
for i in range(4):
linha = ""
for j in range(4):
s = i * 4 + j
if ambiente.grid[i, j] == 1:
linha += " ██ "
elif s == ambiente.objetivo:
linha += " 🎯 "
else:
linha += f" {setas[politica_otima[s]]} "
print(linha)
# Simula uma trajetória
print("\n" + "=" * 70)
print("SIMULAÇÃO DA POLÍTICA ÓTIMA")
print("=" * 70)
trajetoria, recomp_total, passos = avaliar_politica(ambiente, politica_otima)
print(f"\n🚶 Trajetória do início ao objetivo:")
for i, s in enumerate(trajetoria):
linha = s // 4
col = s % 4
if s == ambiente.objetivo:
print(f" Passo {i}: → 🎯 OBJETIVO! (posição {linha},{col})")
else:
print(f" Passo {i}: posição ({linha},{col})")
print(f"\n💰 Recompensa total: {recomp_total:.2f}")
print(f"📏 Passos: {passos}")
# ============================================
# GRÁFICOS
# ============================================
print("\n" + "=" * 70)
print("GERANDO GRÁFICOS")
print("=" * 70)
plt.figure(figsize=(14, 5))
# Gráfico 1: Convergência da iteração de valor
plt.subplot(1, 2, 1)
# Calcula a mudança máxima por iteração
deltas = []
for i in range(1, len(historico)):
delta = np.max(np.abs(historico[i] - historico[i-1]))
deltas.append(delta)
plt.semilogy(deltas, 'b-', linewidth=2)
plt.xlabel('Iteração')
plt.ylabel('Mudança máxima (escala log)')
plt.title('Convergência da Iteração de Valor\n(quanto menor, mais próximo da solução)')
plt.grid(True, alpha=0.3)
plt.axhline(y=1e-6, color='r', linestyle='--', label='Critério θ = 1e-6')
plt.legend()
# Gráfico 2: Função Valor visual
plt.subplot(1, 2, 2)
V_mapa = V_otimo.reshape(4, 4)
mask = ambiente.grid == 1
V_mapa_masked = np.ma.masked_where(mask, V_mapa)
im = plt.imshow(V_mapa_masked, cmap='RdYlGn', interpolation='nearest', vmin=0, vmax=10)
plt.colorbar(im, label='Valor V*(s)')
for i in range(4):
for j in range(4):
s = i * 4 + j
if ambiente.grid[i, j] == 1:
plt.text(j, i, '██', ha='center', va='center', fontsize=16, color='gray')
elif s == ambiente.objetivo:
plt.text(j, i, '🎯', ha='center', va='center', fontsize=16)
else:
cor = 'white' if V_mapa[i, j] < 5 else 'black'
plt.text(j, i, f'{V_mapa[i, j]:.1f}', ha='center', va='center',
fontsize=10, color=cor, fontweight='bold')
plt.title('Função Valor Ótima V*(s)\n(verde = mais valioso)')
plt.xlabel('Coluna')
plt.ylabel('Linha')
plt.tight_layout()
plt.show()
# ============================================
# COMPARAÇÃO COM DIFERENTES GAMMAS
# ============================================
print("\n" + "=" * 70)
print("COMPARAÇÃO DE HIPERPARÂMETROS: DIFERENTES γ")
print("=" * 70)
gammas = [0.5, 0.9, 0.95, 0.99]
valores_iniciais = []
for gamma in gammas:
V, _, _ = iteracao_valor(ambiente, gamma=gamma, theta=1e-4, max_iter=200)
valores_iniciais.append(V[ambiente.inicio])
print(f"γ = {gamma}: V(início) = {V[ambiente.inicio]:.2f}")
print("\n📊 Interpretação:")
print(" - γ baixo (0.5): agente é 'míope' (valoriza recompensas imediatas)")
print(" - γ alto (0.99): agente planeja longo prazo (valoriza futuro)")
# ============================================
# EXPLICAÇÃO MATEMÁTICA
# ============================================
print("\n" + "=" * 70)
print("FUNDAMENTOS MATEMÁTICOS")
print("=" * 70)
print("""
✅ EQUAÇÕES FUNDAMENTAIS:
1. EQUAÇÃO DE BELLMAN PARA V*:
[latex] V^*(s) = \max_a \sum_{s',r} p(s',r|s,a) [r + \gamma V^*(s')] [/latex]
2. ITERAÇÃO DE VALOR (atualização):
[latex] V_{k+1}(s) = \max_a \sum_{s',r} p(s',r|s,a) [r + \gamma V_k(s')] [/latex]
3. POLÍTICA ÓTIMA EXTRAÍDA:
[latex] \pi^*(s) = \arg\max_a \sum_{s',r} p(s',r|s,a) [r + \gamma V^*(s')] [/latex]
✅ PROPRIEDADES DA PROGRAMAÇÃO DINÂMICA:
• Convergência garantida para V*
• Complexidade O(|S|² × |A|) por iteração
• Método de PLANEJAMENTO (modelo do ambiente é conhecido)
• Base teórica para algoritmos modernos
✅ HIPERPARÂMETROS CRÍTICOS:
• γ (gamma): Fator de desconto (0 a 1)
• θ (theta): Critério de convergência (ex: 1e-6)
• max_iter: Número máximo de iterações
""")
print("\n" + "=" * 70)
print("CONCLUSÃO")
print("=" * 70)
print("""
✅ A programação dinâmica resolve problemas baseados em valor de forma exata.
✅ Ela requer conhecimento completo do modelo do ambiente.
✅ Iteração de valor é simples e converge monotonicamente.
✅ A política ótima é extraída diretamente da função valor.
✅ Este método é a base teórica do aprendizado por reforço moderno.
""")
print("\n✅ PROGRAMA CONCLUÍDO COM SUCESSO!")