Pular para conteúdo

Lista 03 · Derivando dados medidos

Acompanha o capítulo 3. Aqui não há fórmula: só tabelas de medições — de uma indústria, de uma pista de aeroporto, de um foguete, de uma epidemia. O \(h\) é a distância entre as medições, e as bordas pedem cuidado.

Abrir no Colab

Baixar o caderno

Como esta lista funciona

Abra o caderno no Colab, escreva a sua solução no lugar do # TODO e rode a célula de teste logo abaixo. Ela mesma diz o que passou e o que falhou — você não precisa esperar correção de ninguém.

O código de cada exercício também está aqui embaixo, caso você prefira colar num editor local. Os testes comparam números com tolerância.

Exercícios marcados com ✏️ são à mão, no papel, com 4 casas decimais — como na parte em papel das avaliações.

Exercício 01

✏️ À mão — indústria química. Um reator é desligado e a temperatura do líquido é registrada a cada 5 minutos:

\(t\) (min) 0 5 10 15 20
\(T\) (°C) 95,0 82,4 71,6 62,3 54,3

a) Estime a taxa de resfriamento \(dT/dt\) em \(t = 0\), \(t = 10\) e \(t = 20\) min, usando em cada ponto a única fórmula possível (qual?).

b) Qual a unidade da resposta? O que o sinal significa?

c) A taxa fica maior ou menor com o tempo? Isso faz sentido físico?

Exercício 02

Escreva derivada_dados(t, y), que devolve um array com a derivada de \(y\) em cada ponto da tabela: progressiva no primeiro ponto, regressiva no último, central nos demais. O espaçamento de t pode ser irregular.

derivada_dados([0, 1, 3, 4], [0, 1, 9, 16])    # -> [1. 3. 5. 7.]
import numpy as np


def derivada_dados(t, y):
    """Derivada de y em relação a t, ponto a ponto (array)."""
    n = len(t)
    d = np.zeros(n)
    # TODO: d[0] progressiva; laço de 1 a n-2 com a central (divida por
    # t[i+1] - t[i-1], não por 2*h); d[n-1] regressiva
    return d


# --- testes (não altere) ---
import numpy as np


d = derivada_dados([0, 1, 3, 4], [0, 1, 9, 16])
assert len(d) == 4, "um valor por ponto da tabela"
assert abs(d[0] - 1) < 1e-9, "borda esquerda: progressiva"
assert abs(d[1] - 3) < 1e-9 and abs(d[2] - 5) < 1e-9, "meio: central com espaçamento irregular"
assert abs(d[3] - 7) < 1e-9, "borda direita: regressiva"
d = derivada_dados(np.array([0.0, 0.5, 1.0]), np.array([2.0, 3.0, 4.0]))
for i in range(3):
    assert abs(d[i] - 2) < 1e-9, "a derivada de uma reta é a inclinação em todo ponto"
print("Exercício 02: todos os testes passaram!")

Exercício 03

Aviação. Na decolagem, a posição de um avião na pista foi registrada a cada 2 segundos:

\(t\) (s) 0 2 4 6 8 10
\(x\) (m) 0 12 48 108 192 300

Escreva velocidade_final_kmh(t, x), que estima a velocidade no último instante da tabela, em km/h (multiplique m/s por 3,6).

Depois de passar nos testes: os dados seguem \(x = 3t^2\) exatamente. Qual a velocidade verdadeira em \(t = 10\) s? Por que a estimativa ficou abaixo?

def velocidade_final_kmh(t, x):
    """Velocidade no último ponto da tabela, em km/h."""
    # TODO: no último ponto só existe o vizinho da esquerda
    pass


# --- testes (não altere) ---
t = [0, 2, 4, 6, 8, 10]
x = [0, 12, 48, 108, 192, 300]
assert abs(velocidade_final_kmh(t, x) - 194.4) < 1e-6, "regressiva no último ponto, vezes 3,6"
assert abs(velocidade_final_kmh([0, 1, 2, 3], [0, 5, 10, 15]) - 18) < 1e-6, "5 m/s = 18 km/h"
print("Exercício 03: todos os testes passaram!")

Exercício 04

Aeroespacial. A telemetria de um foguete registrou a velocidade a cada 10 segundos, até o fim da queima do motor:

\(t\) (s) 0 10 20 30 40 50
\(v\) (m/s) 0 45 110 190 260 300

Escreva aceleracao_maxima(t, v), que devolve a maior aceleração (m/s²) da tabela. A função derivada_dados já está escrita: use-a e depois np.max.

Em que instante a aceleração foi máxima? Por que ela cai no fim da queima?

import numpy as np


def derivada_dados(t, y):
    """Derivada de uma tabela: progressiva no início, central no meio,
    regressiva no fim. JÁ ESCRITA."""
    n = len(t)
    d = np.zeros(n)
    d[0] = (y[1] - y[0]) / (t[1] - t[0])
    for i in range(1, n - 1):
        d[i] = (y[i + 1] - y[i - 1]) / (t[i + 1] - t[i - 1])
    d[n - 1] = (y[n - 1] - y[n - 2]) / (t[n - 1] - t[n - 2])
    return d


def aceleracao_maxima(t, v):
    """Maior aceleração (m/s²) da tabela de velocidades."""
    # TODO: a aceleração é a derivada da velocidade
    pass


# --- testes (não altere) ---
t = [0, 10, 20, 30, 40, 50]
v = [0, 45, 110, 190, 260, 300]
assert abs(aceleracao_maxima(t, v) - 7.5) < 1e-9, "a maior aceleração é em t = 30 s"
assert abs(aceleracao_maxima([0, 1, 2], [0, 9.8, 19.6]) - 9.8) < 1e-9, "queda livre"
print("Exercício 04: todos os testes passaram!")

Exercício 05

Saúde pública. O boletim de uma secretaria de saúde publica os casos acumulados de dengue, um número por dia. Escreva casos_novos(acumulados), que devolve uma lista com os casos novos de cada dia a partir do segundo: acumulado do dia menos acumulado do dia anterior.

casos_novos([10, 15, 25, 40, 50])    # -> [5, 10, 15, 10]

Que diferença finita é essa, e qual o \(h\)?

def casos_novos(acumulados):
    """Casos novos por dia, a partir do segundo dia."""
    novos = []
    # TODO: laço de 1 até o fim, append da diferença com o dia anterior
    return novos


# --- testes (não altere) ---
assert casos_novos([10, 15, 25, 40, 50]) == [5, 10, 15, 10]
assert casos_novos([0, 0, 3]) == [0, 3]
assert casos_novos([7, 7]) == [0], "nenhum caso novo"
print("Exercício 05: todos os testes passaram!")

Exercício 06

O pico da epidemia. Escreva dia_do_pico(acumulados), que devolve o número do dia com mais casos novos. O dia 0 é o primeiro da lista (ele não tem "casos novos"); os casos novos do dia \(i\) são acumulados[i] - acumulados[i - 1].

casos_novos já está escrita. Cuidado com o deslocamento de índice: a posição 0 da lista de casos novos é o dia 1.

dia_do_pico([10, 15, 25, 40, 50])    # -> 3   (15 casos novos no dia 3)
def casos_novos(acumulados):
    """Casos novos por dia, a partir do segundo dia. JÁ ESCRITA."""
    novos = []
    for i in range(1, len(acumulados)):
        novos.append(acumulados[i] - acumulados[i - 1])
    return novos


def dia_do_pico(acumulados):
    """Número do dia com mais casos novos."""
    # TODO: padrão extremo sobre casos_novos(acumulados); some 1 à posição
    pass


# --- testes (não altere) ---
assert dia_do_pico([10, 15, 25, 40, 50]) == 3
assert dia_do_pico([0, 100, 150, 160]) == 1, "o pico pode ser no primeiro dia"
assert dia_do_pico([5, 6, 8, 20]) == 3, "ou no último"
print("Exercício 06: todos os testes passaram!")

Exercício 07

Contra o ruído: vizinhos afastados. Escreva derivada_afastada(t, y, k), que devolve uma lista com a derivada central usando os vizinhos a distância k,

\[ \frac{y_{i+k} - y_{i-k}}{t_{i+k} - t_{i-k}}, \]

para cada \(i\) de k até len(t) - k - 1 (os pontos que têm os dois vizinhos).

t = [0, 1, 2, 3, 4, 5, 6]
y = [0, 1, 4, 9, 16, 25, 36]
derivada_afastada(t, y, 2)    # -> [4.0, 6.0, 8.0]

Depois de passar nos testes, aplique a função aos dados da estufa do capítulo 3 com \(k = 1, 6\) e \(24\). O que acontece com o pico da taxa?

def derivada_afastada(t, y, k):
    """Derivada central com vizinhos a distância k (lista)."""
    taxas = []
    # TODO: laço com i de k até len(t) - k - 1 (cuidado com o range)
    return taxas


# --- testes (não altere) ---
t = [0, 1, 2, 3, 4, 5, 6]
y = [0, 1, 4, 9, 16, 25, 36]
r = derivada_afastada(t, y, 2)
assert len(r) == 3, f"com k = 2 só os pontos 2, 3 e 4 têm os dois vizinhos (veio {len(r)})"
esperado = [4, 6, 8]
for i in range(3):
    assert abs(r[i] - esperado[i]) < 1e-9, f"posição {i}: veio {r[i]}, devia ser {esperado[i]}"
r = derivada_afastada(t, y, 1)
esperado = [2, 4, 6, 8, 10]
assert len(r) == 5, "k = 1 é a central comum: 5 pontos têm os dois vizinhos"
for i in range(5):
    assert abs(r[i] - esperado[i]) < 1e-9, "k = 1 é a central comum"
assert derivada_afastada(t, y, 3) == [6.0], "com k = 3 só sobra o ponto do meio"
print("Exercício 07: todos os testes passaram!")