Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

1
resposta
import numpy as np


# ---------------------------------------------------------
# 1) Definindo os estados e a matriz de transicao
# ---------------------------------------------------------
estados = ["Ensolarado", "Nublado", "Chuvoso"]

# Matriz de transicao P (linhas = estado atual, colunas = proximo estado)
#                 Ensolarado  Nublado  Chuvoso
# Ensolarado         0.70      0.20     0.10
# Nublado             0.30      0.40     0.30
# Chuvoso             0.20      0.30     0.50
matriz_transicao = np.array([
    [0.70, 0.20, 0.10],   # a partir de Ensolarado
    [0.30, 0.40, 0.30],   # a partir de Nublado
    [0.20, 0.30, 0.50],   # a partir de Chuvoso
])

assert np.allclose(matriz_transicao.sum(axis=1), 1.0), "As linhas da matriz devem somar 1!"


class CadeiaDeMarkovClima:
    """Modelo de previsao de clima usando Cadeia de Markov."""

    def __init__(self, estados, matriz_transicao):
        self.estados = estados
        self.matriz_transicao = matriz_transicao
        self.indice_estado = {nome: i for i, nome in enumerate(estados)}

    def prever_distribuicao(self, estado_inicial, n_dias):
        """
        Calcula a distribuicao de probabilidade sobre os estados
        apos 'n_dias', multiplicando o vetor de estado inicial
        pela matriz de transicao elevada a n_dias (P^n).
        """
        vetor_estado = np.zeros(len(self.estados))
        vetor_estado[self.indice_estado[estado_inicial]] = 1.0

        matriz_n_dias = np.linalg.matrix_power(self.matriz_transicao, n_dias)
        distribuicao_final = vetor_estado @ matriz_n_dias

        return dict(zip(self.estados, distribuicao_final))

    def simular_sequencia(self, estado_inicial, n_dias, semente=None):
        """
        Simula uma sequencia de estados climaticos dia a dia,
        sorteando o proximo estado com base nas probabilidades
        da linha correspondente da matriz de transicao.
        """
        rng = np.random.default_rng(semente)
        sequencia = [estado_inicial]
        estado_atual = estado_inicial

        for _ in range(n_dias):
            i = self.indice_estado[estado_atual]
            probabilidades = self.matriz_transicao[i]
            proximo_estado = rng.choice(self.estados, p=probabilidades)
            sequencia.append(proximo_estado)
            estado_atual = proximo_estado

        return sequencia

    def distribuicao_estacionaria(self):
        """
        Calcula a distribuicao estacionaria (de equilibrio) da cadeia,
        resolvendo pi * P = pi com soma(pi) = 1.
        """
        n = len(self.estados)
        A = np.vstack([self.matriz_transicao.T - np.eye(n), np.ones(n)])
        b = np.zeros(n + 1)
        b[-1] = 1.0
        pi, *_ = np.linalg.lstsq(A, b, rcond=None)
        return dict(zip(self.estados, pi))


# ---------------------------------------------------------
# 2) Testando o sistema
# ---------------------------------------------------------
if __name__ == "__main__":
    modelo = CadeiaDeMarkovClima(estados, matriz_transicao)

    print("=== Previsao: distribuicao apos 1 dia (hoje = Ensolarado) ===")
    print(modelo.prever_distribuicao("Ensolarado", 1))

    print("\n=== Previsao: distribuicao apos 3 dias (hoje = Ensolarado) ===")
    print(modelo.prever_distribuicao("Ensolarado", 3))

    print("\n=== Previsao: distribuicao apos 7 dias (hoje = Chuvoso) ===")
    print(modelo.prever_distribuicao("Chuvoso", 7))

    print("\n=== Simulacao de uma sequencia real de 10 dias (comecando Ensolarado) ===")
    print(modelo.simular_sequencia("Ensolarado", 10, semente=42))

    print("\n=== Distribuicao estacionaria (longo prazo) ===")
    print(modelo.distribuicao_estacionaria())

Saída real ao executar

=== Previsao: distribuicao de probabilidade apos 1 dia (hoje = Ensolarado) ===
  Ensolarado: 0.7000
  Nublado: 0.2000
  Chuvoso: 0.1000

=== Previsao: distribuicao de probabilidade apos 3 dias (hoje = Ensolarado) ===
  Ensolarado: 0.5100
  Nublado: 0.2680
  Chuvoso: 0.2220

=== Previsao: distribuicao de probabilidade apos 7 dias (hoje = Chuvoso) ===
  Ensolarado: 0.4535
  Nublado: 0.2834
  Chuvoso: 0.2631

=== Simulacao de uma sequencia real de 10 dias (comecando Ensolarado) ===
  Ensolarado -> Nublado -> Nublado -> Chuvoso -> Chuvoso -> Ensolarado -> Chuvoso -> Chuvoso -> Chuvoso -> Ensolarado -> Ensolarado

=== Distribuicao estacionaria (longo prazo) ===
  Ensolarado: 0.4565
  Nublado: 0.2826
  Chuvoso: 0.2609
1 resposta

Oi, Bruna. Tudo bem com você?

Sua implementação da cadeia de Markov para previsão do clima atende ao objetivo da atividade e demonstra uma boa aplicação dos conceitos apresentados. A definição dos estados, a construção da matriz de transição utilizando o numpy e a validação de que cada linha soma 1 mostram cuidado com a consistência do modelo. Também foi uma boa escolha incluir tanto a previsão da distribuição de probabilidades após um número de dias quanto uma simulação da sequência de estados, pois essas abordagens representam duas formas comuns de utilizar cadeias de Markov em problemas reais.

Como diferencial, você foi além do que a atividade solicitava ao implementar o cálculo da distribuição estacionária, permitindo analisar o comportamento da cadeia no longo prazo. Outro ponto positivo foi utilizar uma semente na geração de números aleatórios, tornando os testes reproduzíveis. Em um contexto semelhante, esse mesmo modelo poderia ser adaptado para prever o comportamento de clientes entre estados como "visitou", "adicionou ao carrinho" e "finalizou a compra", bastando alterar os estados e as probabilidades de transição.

Na sua visão, como a alteração dos valores da matriz de transição poderia influenciar a distribuição estacionária e as previsões obtidas após vários dias?

Parabéns pelo desenvolvimento da atividade e por compartilhar sua solução. Continue praticando e conte com o fórum sempre que precisar. Estamos à disposição para ajudar.

Alura Conte com o apoio da comunidade Alura na sua jornada. Abraços e bons estudos!