0% acharam este documento útil (0 voto)
6 visualizações32 páginas

Fpc2024 Notes

Enviado por

kayky
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
6 visualizações32 páginas

Fpc2024 Notes

Enviado por

kayky
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 32

ICMC-USP

Notas de Aula
SME0332

Fundamentos de Programação de Computadores


com Aplicações em python para Física e Bioinformática

Roberto F. Ausas

December 3, 2024

Instituto de Ciências Matemáticas e de Computação


Universidade de São Paulo
Prefacio

Este documento está organizado por capítulos, cada um dos quais apresenta conceitos e ferramentas
essenciais para desenvolver programas de computador na linguagem python. Os problemas e exemplos
que serão desenvolvidos terão uma ênfase nas aplicações em física e bioinformática. Em cada capítulo serão
apresentados problemas e atividades que o aluno precisará desenvolver, com as quais, este será avaliado ao
longo do curso.

Que tópicos este curso apresenta

Ao longo do curso iremos estudar os seguintes temas listados na sequência:

Capítulo |01| Um primeiro contato à Programação em python;


Capítulo |02| Variaveis e Caminhadas Aleatórias, Cálculos Monte Carlo;
Capítulo |03| Processos Iterativos e Relaxações;
Capítulo |04| Outros tópicos de programação em python;

RFA
Contents

Prefacio ii

Contents iii

1 UM PRIMEIRO CONTATO À PROGRAMAÇÃO EM python 1


1.1 Preludio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Noções iniciais de python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2.1 Tipos de variáveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2.2 Estruturas condicionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2.3 Estruturas de repetição . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2.4 Funções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2.5 A biblioteca numpy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Lista 1: Rudimentos básicos de programação . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2 VARIAVEIS E CAMINHADAS ALEATÓRIAS, CÁLCULOS MONTE CARLO 10


2.1 Preludio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2 Cálculo de integrais por métodos Monte Carlo . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3 Caminhadas aleatórias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3 PROCESSOS ITERATIVOS E RELAXAÇÕES 15


3.1 Preludio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.2 Exemplos elementares de processos iterativos . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.3 Forma de equilibrio de uma corda elástica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

4 TÓPICOS VARIADOS DE PROGRAMAÇÃO EM python 21


4.1 Preludio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4.2 Processamento de imagens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4.3 Mais sobre gráficação e animação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.3.1 Plotagem de funções de 2 variáveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.3.2 Um sistema dinâmico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.3.3 Algoritmo de flooding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
4.4 Ordenamento e procura em arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
4.4.1 Ordenamento de arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

Alphabetical Index 29
UM PRIMEIRO CONTATO À
PROGRAMAÇÃO EM python 1
1.1 Preludio . . . . . . . . . . . 1
1.1 Preludio
1.2 Noções iniciais de python 2
1.3 Lista 1: Rudimentos bási-
A principal ideia por trás de aprender uma linguagem de programação
cos de programação . . . . 6
é a de automatizar certos cálculos que surgem em física ou engenharia,
que não poderiam ser resolvidos manualmente, sem o auxilio de um
computador.
Nas primeiras aulas precisamos introduzir alguns conceitos básicos de
programação (que se aplicam a qualquer linguagem) e posteriormente
precisamos introduzir a sintaxe específica da linguagem que vamos
utilizar ao longo do curso, que é a linguagem python.
De maneira muito geral, as linguagens de programação, podem ser
divididas em duas categorias:

I Linguagens compiladas: Dentre as primeiras temos linguagens


tais como C, C++ e Fortran. A escrita de código neste tipo de
linguagens de programação requer um domínio maior da sintaxe e
das funcionalidades da linguagen. Como contrapartida, este tipo de
linguagens produzem códigos que são muito rápidos pois tem sido
optimizadas ao longo dos anos, e por tanto são usadas amplamente
na Engenharia. De fato, a maioria dos códigos de cálculo usados
na indústria (Open Source ou comerciais) estão feitos com elas.
Ao compilar o código e gerar um arquivo binário optimizado, é
possivel tirar o maior proveito do poder de processamento de um
computador.

I Linguagens interpretadas: Por outra parte, as linguagens interpre-


tadas, como python e Matlab, são relativamente simples e intuitivas,
pela sua flexibilidade na sintaxe, tornando o processo de desen-
volvimento mais rápido e ágil. De maneira grosseira, o código vai
sendo executado a medida que se interpreta. Porém, se não são
tomados alguns recaudos no desenho do código, a performance
computacional delas pode estar bastante aquém do necessário para
resolver problemas de grande porte. Um exemplo prototípico disto,
é quando utilizamos uma estrutura de repetição (como um for) no
qual realizamos um grande número de operações em cada passo.
Ao longo de curso iremos chamando a atenção sobre isto, tentando
introduzir boas práticas de programação.

Como comparação, vejamos o exemplo de um código simples para criar


um array com números de ponto flutuante de dupla precisão, popular
ele com os números 0 , . . . , 𝑁 e imprimir o resultado na tela, usando
a linguagem compilada C (acima) e a linguagem interpretada python
(embaixo).
1 UM PRIMEIRO CONTATO À PROGRAMAÇÃO EM python 2

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i, N = 10;
double *array;
array=(double *) malloc(N*sizeof(double));
for(i=0; i < N; i++) {
array[i] = (double) i;
printf("%lf\n", array[i]);
}
free(array);
return 0;
}

import numpy as np
N = 10
array = np.arange(N)
print(array)

Olhando para o exemplo, já vemos que uma linguagem interpretada como


python se torna mais prática para um primeiro curso de programação,
pois o objetivo é desenvolver a capacidade de programar algoritmos para
resolver problemas práticos no computador, sem gastar muito tempo no
desenvolvimento de código.
Neste curso iremos adotar a linguagem python, a qual tem-se tornado
bastante popular nos últimos anos. Para facilitar a implementação dos pro-
gramas para resolver problemas de interesse, contaremos com algumas
bibliotecas específicas que facilitarão o trabalho:

I numpy: Para manipulação eficiente de matrizes e vetores, operações


de algebra linear computacional e vários métodos numéricos.

I scipy: Para métodos numéricos mais avançados ou específicos,


não cobertos pela anterior.

I matplotlib: Para plotagens e geração de gráficos em 2D e 3D.

1.2 Noções iniciais de python

Ao longo do curso iremos incorporando diversas ferramentas e funções


disponíveis em várias bibliotecas, mas antes vamos a introduzir alguns
conceitos essenciais de programação específicos de python. Se sugere
ir digitando em algum editor de código ou algum ambiente de progra-
mação.

1.2.1 Tipos de variáveis

Alguns dos tipos de variáveis mais usados são apresentados na sequên-


cia:
1 UM PRIMEIRO CONTATO À PROGRAMAÇÃO EM python 3

Números

São os objetos mais simples. Podem ser inteiros, de ponto flutuante,


complexos e booleanos, por exemplo:
1, -2, 3.1415, 6.02e23, 1 + 1j, True, False

Strings

São basicamente, listas de caracteres e se escrevem entre aspas simples


ou duplas:
"a", "USP", "21", "AbCdE", "---"

Listas

Servem para agrupar vários objetos.


mylist = [1, 3.14, "USP", True, -10000, 1+1j, myfunc]

A lista é indexada simplesmente pela posição do objeto, começando


desde 0, p.e.,
mylist[1] é 3.14
mylist[6] é myfunc

Diccionarios

É uma forma mais prática de definir listas com identificadores:


mydic = {"valor": 3.14, "minhauni": "USP", "lista": ["a", 2,
1+1j]}

Então,
mydic{"minhauni"} é "USP"
mydic{"lista"}[2] é 1 + 1j

1.2.2 Estruturas condicionais

Uma das estruturas de programação mais usadas é a estrutura condicional.


A sintaxe é simples:
if (Expressão lógica):

.
.
else:

.
.
ou em situações com mais de duas opções para decidir:
if (Expressão lógica 1):
1 UM PRIMEIRO CONTATO À PROGRAMAÇÃO EM python 4

.
.
elif (Expressão lógica 2):

.
.
else:

.
.
Notar os : no final das sentencias e a indentação dentro de cada bloco.

Advertência
A indentação é fundamental em python. Se esta não for respeitada o
interpretador não saberá quais instruções ficam dentro da estrutura e
por tanto o programa poderá ter comportamentos não esperados ou
em alguns casos parar a execução .

1.2.3 Estruturas de repetição

Existem duas estruturas de repetição que são muito usadas. A primeira


estrutura é o famoso for (o "para" em portugués):
for i in range(N):

.
.
A segunda estrutura de repetição que iremos usar as vezes é o while (o
"enquanto" em portugués):
while (Expressão lógica):

.
.
Com elas podemos fazer qualquer tipo de cálculo em que precisamos
iterar sobre os elementos de algum objeto ou repetir uma operação várias
vezes.
1 UM PRIMEIRO CONTATO À PROGRAMAÇÃO EM python 5

1.2.4 Funções

As declaração de funções é fundamental para poder organizar um código,


encapsulando uma serie de operações as quais pode ser necessário
realizar muitas vezes. A sintaxe para declarar uma função é:
def minhafunc(arg1, arg2, ...):

.
.
return var1, var2, ...

Novamente, notar os : no final da definição e a indentação dentro do


bloco da função.

1.2.5 A biblioteca numpy

Esta é uma das bibliotecas que mais serão usadas ao longo do curso.
Basicamente permite definir vetores, matrizes e tensores em geral, popu-
lados com números ou dados de um tipo homegêneo (i.e., todos números
inteiros, ou todos números de ponto flutuante, etc.). Esta biblioteca é
fundamental para poder realizar cálculos científicos com uma eficiencia
razoável, possivelmente similar à da uma linguagem compilada. Alguns
exemplos de uso na sequência:
import numpy as np

vec_ints = np.array([1,2,3,4], dtype=np.int32)


vec_doubles = np.array([1,2,3,4], dtype=np.float64)
x = np.linspace(start, end)
y = np.sin(x)
vetor_nulo = np.zeros(10, dtype=np.int32)
matriz_nula = np.zeros(shape=(5,3), dtype=np.float64)

A ideia era mostrar alguns exemplos simples para o aluno se familiarizar


um pouco com a sintaxe. Na sequência colocaremos os conceitos em
prática desenvolvindo códigos para resolver vários problemas.

Aviso importante

O material de estudo para desenvolver a primeira lista será a presente


apostila e os jupyter notebooks desenvolvidos pelo professor em
sala de aula, os quais foram disponibilizados no repositório da dis-
ciplina. Outras fontes de informação a ser consideradas são os sites
das bibliotecas que iremos utilizar, tais como https://numpy.org e
https://matplotlib.org/, assim como consultas dirigidas ao pro-
fessor em forma presencial ou por e-mail ([email protected]).
A lista na sequência deve estar pronta para o dia 24/09.
1 UM PRIMEIRO CONTATO À PROGRAMAÇÃO EM python 6

1.3 Lista 1: Rudimentos básicos de programação

A melhor forma para aprender a programar é resolver problemas concre-


tos. Na sequência temos a primeira lista de exercícios para desenvolver
códigos em python. Os exercícios poderão ser feitos em grupos de no
mínimo 2 e no máximo 2 integrantes, e a partir da data definida acima, o
professor chamará aleatóriamente aos grupos para explicar os exercícios.
Todos os membros do grupo deverão ser capaces de explicar qualquer
um dos exercícios.

Exercícios preliminares para praticar e não serão avaliados

1. Fazer um script que define um vetor randômico de dimensão


𝑁 e calcula a média dos valores das suas componentes, i.e.,

𝑁
1 X
𝑥¯ = 𝑥𝑖
𝑁 𝑖=1

Considerar 𝑁 = 10 , 100 , 1000 , 10000 , 100000 , 1000000.


2. Fazer um script que define uma matriz randômica de dimensão
𝑁 × 𝑁 e calcula a média dos valores dos seus elementos, i.e.,
𝑁 X 𝑁
1
𝐴¯ =
X
𝐴 𝑖𝑗
𝑁 × 𝑁 𝑖=1 𝑗=1

tomando 𝑁 = 10 , 100 , 500 , 1000.


3. Fazer um gráfico da função 𝑓 (𝑥) = 𝑥 𝑚 para diferentes valores
de 𝑚 considerando o intervalor 𝑥 ∈ [1 , 4]. Usar escala linear e
escala loglog.
4. Fazer uma função que calcula o produto escalar de dois vetores
randômicos a e b de ℝ3 , calcula a sua magnitude e determina o
ângulo 𝜃 que eles formam, usando a fórmula:

a · b = k a k k b k cos 𝜃

5. Considerar 10 dados que são jogados, podendo sair números


do 1 até o 6. A soma dos valores será
10
X
𝑆= 𝑑𝑖
𝑖=1

em que 𝑑 𝑖 é o que saiu em cada um dos dados. Jogar os 10


dados 100000 vezes e construir um histograma que mostre
o comportamento de 𝑆 . Um histograma seria um gráfico de
frequencia de um certo evento, ou seja, quantas vezes a soma
deu 10, quantas vezes a soma deu 11, quantas vezes a soma deu
12, ..., quantas vezes a soma deu 60. Para isto precissará usar a
função

counts, bins = np.histogram(s)


plt.stairs(counts, bins)

em que s será um vetor que guardou o resultados das 100000


realizações.
1 UM PRIMEIRO CONTATO À PROGRAMAÇÃO EM python 7

Exercícios que serão avaliados

1. Fazer uma função que:


I Pega dois vetores randômicos a e b de dimensão 𝑛 , e dois
escalares randômicos 𝛼 e 𝛽 e calcula um vetor c tal que

c = 𝛼a + 𝛽b

I Pega uma matriz randômica A de 𝑛 × 𝑛 e calcula a sua


𝑚 -essima potência

A𝑚 = A . . . A
| {z }
𝑚 vezes

(tomar valores de 𝑚 = 2 , 3 , 4).


Em todos os casos medir o tempo necessário para realizar
as operações para diferentes dimensões 𝑛 . Plotar o tempo de
cálculo como função da dimensão 𝑛 usando a escala linear
padrão e a escala loglog. No segundo ponto, colocar no mesmo
gráfico os resultados para os diferentes valores de 𝑚 . Tirar
conclusões.

Nota: Para que os resultados sejam interessantes, no primeiro


ponto, tomar valores de 𝑛 = 105 , 106 , . . . , 108 . Já, no segundo
ponto, tomar valores de 𝑛 = 500 , 1000 , 1500 , 2000.

2. Fazer uma função que recebe uma matriz randômica A de


dimensão 𝑚 × 𝑟 e outra matriz randômica B de dimensão 𝑟 × 𝑛 ,
verifica as suas dimensões e realiza a multiplicação delas no
sentido usual de algebra linear, para retornar uma matriz C de
dimensão 𝑚 × 𝑛 . A multiplicação deve ser feita usando todos os
for que sejam necessários. Considerando matrizes quadradas
(i.e., 𝑚 = 𝑟 = 𝑛 ), medir o tempo de cálculo como função da
dimensão e comparar com o tempo necessário fazendo A @ B.
Para que os resultados sejam interessantes tomar dimensões de
matriz 50 , 100 , 150 , 200 , 250, como anteriormente. Novamente,
plotar o tempo de cálculo como função da dimensão na escala
loglog.

3. Mapeo logístico: Considerar uma sequência de numéros gerada


da seguinte forma:

𝑥 𝑛 = 𝑎 𝑥 𝑛−1 (1 − 𝑥 𝑛−1 ), 𝑛 = 1, 2, . . . , 𝑁

Considerar 𝑁 = 5000, 𝑥 0 = 0.1 e diferentes valores de 𝑎 entre


0 e 4 (p.e., 𝑎 = 1 , 2 , 3.8 e 4). Calcular a média e a variança da
sequência:

𝑁 𝑁
1 X 1 X
𝑥¯ = 𝑥𝑖 , 𝜎 = (𝑥 𝑖 − 𝑥)
¯2
𝑁 𝑖=0 𝑁 − 1 𝑖=0

Programar-lo na mão e usando funções de numpy já prontas


Comparar os resultados.

4. No problema 3, plotar a sequéncia de valores obtida em cada


1 UM PRIMEIRO CONTATO À PROGRAMAÇÃO EM python 8

caso considerando os diferentes valores de 𝑎 pedidos. Fazer os


gráficos usando legendas, labels, e outros atributos que achar
interessante, para melhor ilustrar os resultados.

5. Continuando com a sequência do problema 3, fazer um código


que gera o diagrama de bifurcações, que é um gráfico que
mostra os valores que assume a sequência, como função dos
valores de 𝑎 . O resultado deveria ser algo do tipo mostrado
na figura ao lado, que no eixo horizontal tem os valores de
𝑎 usados para gerar a sequência e no eixo vertical todos os
possíveis valores que toma a sequência para o correspondente
valor de 𝑎 . Se sugere usar pontinhos bem pequenos para gerar
o gráfico. Explicar os resultados se auxiliando com os gráficos
do exercício anterior.

6. Algo de grafos: Considerar uma rede de distribuição com a


mostrada na figura ao lado. Esta pode ser um exemplo de uma
rede elétrica ou hidráulica e é basicamente o que se chama
um grafo). Notar que em geral ela estará caracterizada por um
certo número de nós (ou uniões), um certo nuúmero de arestas e
alguma informação sobre a conectividade entre pontos.
I Fazer uma estrutura de dados que sirva para descrever essa
rede. Idealmente, a estrutura deveria incluir algum tipo de
matriz ou array que indica como os nós e as arestas estão
relacionados. Adicionalmente, a estrutura deve conter um Figure 1.1: Diagrama de bifurcações.

array para descrever as coordenadas (𝑥, 𝑦) de cada nó.


Construir um exemplo inventando as coordenadas e plotar
a rede.
I Fazer uma função que deleta um nó e todas as arestas que
emanam dele.
I Fazer uma outra função em python que permita apagar
(ou deletar) uma aresta da rede. Notar que se a aresta possui
um nó que náo pertence a nenhuma outra aresta, esse nó
também precisa ser deletado.
I Finalmente, fazer uma função que insere uma nova aresta
na rede para conectar dois pontos já existentes.

7. O jogo da vida de Conway: O Jogo da vida é uma grade


ortogonal bidimensional de células quadradas, cada uma das Figure 1.2: Exemplo de uma rede.
quais está em um dos dois estados possíveis: viva ou morta.
Cada célula interage com seus oito vizinhos, que são as células
adjacentes horizontalmente, verticalmente ou diagonalmente.
A cada passo no tempo, ocorrem as seguintes transições:
I Qualquer célula viva com menos de dois vizinhos vivos
morre;
I Qualquer célula viva com dois ou três vizinhos vivos
continua viva para a próxima geração;
I Qualquer célula viva com mais de três vizinhos vivos
morre;
I Qualquer célula morta com exatamente três vizinhos vivos
torna-se uma célula viva.
A tarefa é fazer um programa de python que implementa o jogo
1 UM PRIMEIRO CONTATO À PROGRAMAÇÃO EM python 9

da vida:
I Uma grade com 100 × 100 células e condições iniciais
randômicas. que dependam de dois parâmetros 𝑝 0 e 𝑝 1
sendo as probabilidades de iniciar morta ou viva, respeti-
vamente. Testar diferentes valores;
I Uma grade menor e condições iniciais como as descritas no
https://en.wikipedia.org/wiki/Conway%27s_Game_of_
Life, de forma a reproduzir alguns padrões clássicos con-
hecidos como Still lifes, Oscillators e Spaceshifts.
O programa dever estar estruturado da seguinte forma:
# Grid size
N = 100

# Create an initial random grid


p0, p1 = 0.8, 0.2
grid = np.random.choice([0, 1], N*N, p=[p0, p1]).reshape(
N, N)

def update(frameNum, img, grid):


# Programar as regras de atualizacao
.
.
.
plt.title(f"Game of Life - Frame {frameNum}")
return img,

fig, ax = plt.subplots()
img = ax.imshow(grid, interpolation=’nearest’)
ani = animation.FuncAnimation(fig, update, fargs=(img,
grid,))
plt.show()
Explicar que o que cada parte do código faz.
VARIAVEIS E CAMINHADAS
ALEATÓRIAS, CÁLCULOS
MONTE CARLO 2
2.1 Preludio . . . . . . . . . . . . 10
2.1 Preludio
2.2 Cálculo de integrais por
métodos Monte Carlo . . . . 11
Neste capítulo iremos desenvolver alguns cálculos que envolvem variáveis
2.3 Caminhadas aleatórias . . . 13
aleatórias. Em alguns casos, a abordagem determinística não é a mais
apropriada, por diversos motivos: por exemplo, quando existe incerteza
em certas variáveis ou quando a complexidade do problema é tão
grande que não conseguimos barrer de maneira exaustiva todos os
possíveis valores e combinações que as variaveis envolvidas podem
assumir. Nesses casos, a abordagem estocástica torna-se mais conveniente.
Vamos apresentar alguns exemplos de cálculos estocásticos e desenvolver
códigos em python para realizá-los, incluindo, caminhadas aleatórias e
cálculo de integrais por métodos Monte Carlo.
Para começar, vamos considerar um exemplo que já foi introduzido:

Exemplo/Exercício 1

Considerar 𝑀 dados que são jogados, podendo sair números do 1 até


o 6. A soma dos valores será
𝑀
X
𝑆= 𝑑𝑖
𝑖=1

em que 𝑑 𝑖 é o número que saiu em cada um dos dados. Jogar os 𝑀 da-


dos 𝑁 vezes e construir um histograma que mostre o comportamento
de 𝑆 . Lembrando, um histograma é um gráfico de frequencia de um
certo evento, ou seja, quantas vezes a soma deu 𝑀 , quantas vezes a
soma deu 𝑀 + 1, quantas vezes a soma deu 𝑀 + 2, ..., quantas vezes
a soma deu 𝑁 × 𝑀 . Para fazer o histograma precissará usar a função

counts, bins = np.histogram(s)


plt.stairs(counts, bins)

em que s será um vetor que possui os resultados das 𝑁 realizações.


A primeira tarefa será desenvolver um código de python que grafica
os histrogramas que permitam visualizar como a variável aleatória 𝑆
está distribuida. Para isto:

I Generalizar o código desenvolvido no capítulo anterior para


que o cálculo esteja dentro de uma função, a qual deve receber
os valores de 𝑁 e 𝑀 ;
I Fazer um estudo barrendo diferentes valores de 𝑁 (p.e., 102 , 103 ,
104 , 105 , 106 , 107 ) e de 𝑀 (p.e., 2, 4, 8). Elaborar os histogramas
e pesquisar que opções existem para plotar os gráficos.

Este exercício será avaliado!


2 VARIAVEIS E CAMINHADAS ALEATÓRIAS, CÁLCULOS MONTE CARLO 11

2.2 Cálculo de integrais por métodos Monte


Carlo
Pergunta

Vamos supor que você precisa calcular o valor de 𝜋 usando o com-


putador. Como você faria sem usar nenhuma fórmula conhecida que
envolve series de potências ou coisas do tipo, apenas pode usar cálculo
de integrais, mas tem que fazer de conta que você não sabe como
calcular essas integrais na mão, apenas tem o computador. Pensar em
grupo por 15min e tentar elaborar uma estrategia.

Cálculo do número 𝜋

Vamos estimar el valor do número 𝜋 da seguinte forma: Se consideramos


a região quadrada [−1 , 1] × [−1 , 1] e um círculo inscrito, a razão das áreas
entre estes será
𝑅 = 𝜋/4
(ver figura).
Então, podemos propor um cálculo estocástico que consistirá em jogar
pontos dentro dessa região quadrada. Alguns desses pontos irão cair
dentro do circulo e outros fora. Como é de se esperar, a razão entre a
quantidade de pontos que cai dentro e a quantidade total de pontos
jogados, deveria tender justamente a razão entre as áreas de círculo e do
quadrado (𝜋/4).
Se denotarmos por 𝑁𝑐 e 𝑁 ao número de pontos dentro do círculo e ao
número total de pontos, respectivamente:

𝜋 #num. pontos no círculo 𝑁𝑐


Prob = = lim = lim
4 𝑁→∞ #num. total de pontos 𝑁→∞ 𝑁

Isto leva ao seguinte roteiro que precisamos executar:

1. Gerar (𝑥 𝑖 , 𝑦 𝑖 ), formado por dois números 𝑥 𝑖 e 𝑦 𝑖 entre −1 e 1,


independentes e com probabilidade uniforme.
2. Calcular 𝜃𝑖 , definida como igual a 1 se 𝑥 2𝑖 + 𝑦 𝑖2 < 1 e igual a 0 se
não. Seja Θ = {𝜃𝑖 } a sequência gerada.
3. Tirar a média
𝑁
1 X
𝜃ˆ = 𝜃𝑖
𝑁 𝑖=1

o qual se materializa no seguinte código de python:


# Computation of pi by a stochastic method

N = 10000 # Number of realizations


Nc = 0
for i in range(N):
x = -1.0 + 2.0*np.random.rand()
y = -1.0 + 2.0*np.random.rand()
if (x**2 + y**2 < 1.0):
Figure 2.1: Exemplo do cálculo MC.
Nc = Nc + 1
2 VARIAVEIS E CAMINHADAS ALEATÓRIAS, CÁLCULOS MONTE CARLO 12

Prob = Nc / N
print(’The estimate for pi is:’, 4*Prob)

Os resultados para diferente número de realizações se mostram na figura


ao lado e na tabela seguinte para 4 × 𝑝 (o que deveria tender a 𝜋)1 : 1: Um dos pontos a destacar é que esta-
mos usando uma distribuição uniforme
de probabilidades (np.random.rand())
# 𝑁 = 103 𝑁 = 104 𝑁 = 105 𝑁 = 106 𝑁 = 107 para gerar os pontos randômicos, i.e., a
1 3.0800 3.1492 3.1450 3.1418 3.1405 probabilidade é a mesma para qualquer
número em (0 , 1) e os pontos gerados
2 3.2320 3.1340 3.1396 3.1400 −− são "independentes" um dos outros. Isto
3 3.1240 3.1412 3.1469 3.1376 −− é um ingrediente essencial do método
4 3.0800 3.1660 3.1488 3.1406 −− MC.

Exercício 2 (será avaliado)


I Elaborar um código de cálculo que implementa o método Monte
Carlo para calcular o número 𝜋. Para isto, encapsular todos
os cálculos dentro de uma função que possa ser chamada
especificando o número de realizações;
I Elaborar uma tabela de resultados similar à mostrada acima;
I Para cada valor de 𝑁 , realizar uma média do resultado obtido
em cada execução do experimento;
I Plotar o erro em escala loglog do resultado (i.e., |𝜋 − 𝜋MC | )
como função de 𝑁 . Tirar alguma conclusão. O resultado que
irá obter será parecido com o mostrado na figura Figure 2.2.

Exercício 3 (será avaliado)


Figure 2.2: Comportamento do erro
Implementar o cálculo de número 𝜋 usando um método da soma como função de 𝑁 . A curva azul mostra
1
de Riemann (i.e., um método determinístico). Para isto considerar a a função 𝑁 − 2 que indica o compor-
tamento teórico esperado. Neste caso
soma de Riemann foram realizados 20 experimentos e em
𝑁
cada experimento foram jogados até 107
X
𝑆𝑅 = 𝑓 (𝑥 𝑖 ) Δ𝑥 pontos.
𝑖=1

em que 𝑓 (𝑥) = 1 − 𝑥 2 e Δ𝑥 = 1/𝑁 , sendo 𝑁 o número de subinter-
valos e 𝑥 𝑖 = 𝑖 Δ𝑥 . Claramente, lim𝑁→∞ 𝑆𝑅 = 𝜋4 .

I Considerar diferentes valores de 𝑁 e calcular o erro como


função de 𝑁 comparando com o valor de 𝜋 conhecido.
I Plotar e/ou fazer uma tabela para reportar os resultados.

Exercício 4 (será avaliado)

Considerar as funções 𝑓 (𝑥) = 1 + 1


2 sin3 (2 𝑥) e 𝑔(𝑥) = 3 + 1
2 cos5 (3 𝑥)
no intervalor [0 , 2𝜋].

I Plotar as funções.
I Usando uma tabela de integrais ou algum programa para
cálculo simbólico (p.e., Mathematica) calcular a área entre as
duas curvas.
I Calcular com um método Monte Carlo a área entre as duas
2 VARIAVEIS E CAMINHADAS ALEATÓRIAS, CÁLCULOS MONTE CARLO 13

curvas e comparar com o item anterior. O programa dever plotar


os pontos que caíram fora e dentro da região.

Exercício 5 (será avaliado)


Considerar as mesmas funções do exercício anterior mas agora con-
siderar que a esquerda e a direita a região está limitada por uma
parábola como mostrado na figura ao lado.
A parábola da esquerda passa pelos pontos [0 , 1], [−1 , 2.25], [0 , 3.5] e
a parábola de direita passa pelos pontos [2 𝜋, 1], [2 𝜋+1 , 2.25], [2 𝜋, 3.5].

I Plotar a região considerada graficando as funções correspon-


Figure 2.3: Região do exercício 5.
dentes.
I Calcular a área de região considerada usando o método Monte
Carlo e tabelar o resultado como função do número de pontos
sendo jogados. O programa dever plotar os pontos que caíram
fora e dentro da região.

Exercício 6 (será avaliado)


Calcular o número 𝜋 usando a técnica Monte Carlo mas agora trabal-
hando em três dimensões jogando pontos aleatórios dentro do cubo
[−1, 1] × [−1 , 1] × [−1 , 1] e considerando a esfera de raio 1 inscrita no
cubo:

I Modificar o código original para adaptar-lo ao novo cálculo.


I Fazer uma tabela para plotar os resultados como função do
número de pontos 𝑁 e avaliar o erro.
I Plotar os pontos num gráfico 3D tentando ajustar a transparência
dos pontos que ficam fora da esfera para poder enxergar os
pontos dentro da esfera.
I Tentar melhorar a eficiência do código vetorizando ele (pergun-
tar ao professor).

Estes e os proximos exercícios a serem disponibilizadas devem estar


prontos para a próxima avaliação, que será no dia 17/10.

2.3 Caminhadas aleatórias

Vamos supor uma grade quadrada em ℝ2 e uma partícula na posição


inicial R(0). Queremos estudar a evolução dessa partícula quando a
mesma realiza uma caminhada aleatória, i.e., se 𝑅(𝑡) representa a sua
posição no momento 𝑡 , então a sua posição no tempo 𝑡 + 1 será dada
por:
𝑡
X
R(𝑡 + 1) = R(𝑡) + 𝝃 𝑡 = R(0) + 𝝃𝑖
𝑖=1

em que o vetor 𝝃 𝑡 pode tomar um dos 4 valores na sequência:

(𝑎, 0), (0 , 𝑎), (−𝑎, 0), (0, −𝑎)


2 VARIAVEIS E CAMINHADAS ALEATÓRIAS, CÁLCULOS MONTE CARLO 14

cada um destes com uma probabilidade uniforme de 14 . No geral, a


trajetória desta partícula viajante (ou caminhante) terá a forma mostrada
na figura 2.4

Figure 2.4: Trajetória de uma partícula


em caminhada aleatória.

Exercício 7 (será avaliado)


Implementar um código que realiza caminhadas aleatórias em 2𝐷 .

I Plotar o resultado para várias realizações da caminhada e


considerando 𝑁 = 103 , 104 , 105 , 106 passos.
I Calcular o distância quadrática média percorrida, i.e.,

𝑑𝑚
2
(𝑡) = h(R(𝑡) − R(0)) · (R(𝑡) − R(0))i

como função de 𝑡 e fazendo um promédio sobre 𝑀 realizações,


tomando por exemplo 𝑀 = 1000 e 𝑀 = 10000 e 𝑁 = 104 passos.
I Estender o código para 3D.

Exercício 8 (opcional)

Estudo de agregados fractais:

I Considerar uma grade de 400 × 400 células de tamanho unitário.


I Colocar uma particula no centro da grade.
I Tomar 𝑛 particulas em posições aleatórias, que iniciem a uma
distância 𝐷 > 180 do centro da grade
I Executar as caminhadas aleatórias destas partículas. Figure 2.5: Agregado por difusão.
I Cada uma dessas caminhadas se dá por finalizada se a partícula
sai da grade ou se fica "grudada" a uma particula que já faz
parte do agregado, i.e., se ela chega numa posição que tem por
vizinho alguma partícula já grudada ao sistema.
I O resultado deveria se parecer com a Figure 2.5.
PROCESSOS ITERATIVOS E
RELAXAÇÕES 3
3.1 Preludio . . . . . . . . . . . . 15
3.1 Preludio
3.2 Exemplos elementares de
processos iterativos . . . . . 15
Neste capitulo o foco será dado a diversos processos iterativos que
3.3 Forma de equilibrio de uma
aparecem certos problemas da física. A ideia de um processo iterativo, é
corda elástica . . . . . . . . . 18
construir uma sequência de aproximações para um problema, i.e.,

{𝑎 0 , 𝑎1 , . . . , 𝑎 𝑘 , . . . }

em que 𝑎 0 é a condição inicial, a qual é dada ou conhecida. A quantidade


𝑎 pode representar alguma grandeza física, tal como a temperatura num
conjunto de pontos, a posição de uma partícula, a solução de um sistema
de equações, etc. Este tipo de cálculos são ideias para serem programados
no computador de maneira eficiente como veremos neste capítulo. Como
é de se esperar, as estruturas de repetição que temos aprendido são
essenciais para implementar estes cálculos no computador, i.e., of for e
o while.

3.2 Exemplos elementares de processos


iterativos
Exemplos:

(a) Sequência de Fibonacci: A famosa sequência de Fibonacci é


dada por:

𝑎0 = 0
𝑎1 = 1
𝑎𝑘 = 𝑎 𝑘−1 + 𝑎 𝑘−2 , 𝑘 = 2 , 3 , . . .

Neste caso particular, os dois primeiros elementos da sequência


são dados e o resto são calculados usando a fórmula anterior.
(b) Mapeo logístico: Este exemplo que já foi estudado no primeiro
capítulo é dado por:

𝑥 𝑛 = 𝑎 𝑥 𝑛−1 (1 − 𝑥 𝑛−1 ), 𝑛 = 1, 2, . . . , 𝑁

em que 𝑎 é um parâmetro dado e 𝑥 0 precisa ser escolhido.


(c) Iteração de ponto fixo: Dada uma função 𝜑(𝑥), a iteração de
ponto fixo é definida por

𝑥 𝑘+1 = 𝜑(𝑥 𝑘 )

com 𝑥 0 dado. Diz-se que 𝑥¯ é ponto fixo da função 𝜑 se 𝑥¯ = 𝜑( 𝑥)


¯
e a iteração de ponto fixo diz-se convergente se:

lim 𝑥 𝑘 = 𝑥¯
𝑘→∞
3 PROCESSOS ITERATIVOS E RELAXAÇÕES 16

(d) Iteração de Jacobi: Considerar o sistema de equações:

3𝑥 − 𝑦 = 2
−2 𝑥 + 4 𝑦 = 1

O processo iterativo de Jacobi, parte de uma condição inicial


[𝑥0 , 𝑦0 ] e a partir desta atualiza a cada iteração seguindo a regra:

1
𝑥 𝑘+1 = (2 + 𝑦 𝑘 )
3
1
𝑦 𝑘+1 = (1 + 2 𝑥 𝑘 )
4
Como pode-se ver, a ideia é que em cada equação se atualiza o
valor de uma das incógnitas com os valores das outras incógnitas
na iteração anterior. O processo iterativo deve ser executado
até que os valores de 𝑥 𝑘 e 𝑦 𝑘 estão suficientemente próximo
da solução do sistema, i.e., para 𝑘 suficientemente grande, se
denotarmos por ( 𝑥,
¯ 𝑦)
¯ a solução do sistema:

| 𝑥¯ − 𝑥 𝑘 | < 𝜀, | 𝑦¯ − 𝑦 𝑘 | < 𝜀

com 𝜀 pequeno. Em analise numérica pode-se demonstrar que


para certos tipos de sistemas, independentemente da condição
inicial 𝑥 0 , 𝑦0 , esse processo iterativo é convergente.
(e) Método de Newton: Dada uma função 𝑓 (𝑥) cujos zeros querem
ser achados, o processo iterativo:

𝑓 (𝑥 𝑘 )
𝑥 𝑘+1 = 𝑥 𝑘 −
𝑓 0(𝑥 𝑘 )

dependendo da função 𝑓 e do valor inicial 𝑥 0 , o processo


iterativo pode converger a um valor 𝑥¯ tal que 𝑓 ( 𝑥)¯ = 0 (i.e.,
uma raiz de 𝑓 ). O processo dever ser executado até que o valor
de 𝑥 𝑘 está suficientemente próximo da solução da equação.
Em analise numérica, pode-se demonstrar que dependendo da
função 𝑓 e do valor escolhido para 𝑥 0 , esse processo iterativo é
convergente.
(f) Método das potencias: Dada uma matriz 𝐴 ∈ ℝ 𝑛×𝑛 e um vetor
x0 ∈ ℝ 𝑛 de norma unitaria, no método das potencias calcula-se
um novo vetor x 𝑘+1 e um escalar 𝜆 𝑘+1 a partir do vetor anterior
seguindo a regra
y 𝑘+1 |
y 𝑘+1 = 𝐴 x 𝑘 , x 𝑘+1 = , 𝜆 𝑘+1 = x 𝑘+1 𝐴 x 𝑘+1
k y 𝑘+1 k

Notar que y 𝑘+1 = 𝐴 x 𝑘 = 𝐴2 x 𝑘−1 = · · · = 𝐴 𝑘+1 x0 . Dai o nome


do método. Dependendo da matriz 𝐴, o método converge ao
autovetor x̄ correspondente ao autovalor dominante 𝜆¯ da matriz
(i.e., o autovalor de maior módulo).

Aviso importante

Todos os exercícios deste capítulo serão avaliados nos dias 19/11 e


21/11.
3 PROCESSOS ITERATIVOS E RELAXAÇÕES 17

Exercícios
1. Implementar em python el ejemplo (a) da sequência de Fi-
bonacci. Programar-lo armazenando os resultados num vetor
e programar-lo usando o conceito de recorrẽncia, i.e., onde a
função chama-se a si mesmo tantas vezes quanto necessário
para calcular os elementos da sequência.
2. Fazer um programa de python que executa o processo de

iteração de ponto fixo do exemplo (c) para a função 𝜑(𝑥) = 1/ 𝑥
e graficar o processo iterativo como mostrado na figura ao lado.
Notar que a condição inicial escolhida no exemplo é 𝑥 0 = 0.75.

3. Programar o processo iterativo de Jacobi do exemplo (d) e


verificar quantas iterações são necessárias para atingir um erro
𝜀 = 10−2 , 10−3 , 10−4 , . . . , 10−8 . Graficar o número de iterações
como função do erro.
4. Programar o processo iterativo de Jacobi para o sistema de 3 × 3
da sequência:

 3 −1 −1  𝑥  1
−1 3 −1  𝑦  = 2
    
     Figure 3.1: Exemplo de iteração de ponto
−1 −1 3   𝑧  3 fixo.
    
5. Opcional Programar o método de Jacobi para um sistema geral
de equações em que a matriz 𝐴 ∈ ℝ 𝑛×𝑛 e o vetor de lado direito
b ∈ ℝ 𝑛 são dados, i.e.,

 𝑎11 𝑎12 ... 𝑎1𝑛   𝑏1 


 𝑎21 𝑎22 ... 𝑎2𝑛   𝑏2 
  

𝐴 =  . , 𝑏 =  . 
  

 .  .
   
𝑎𝑛1 𝑎𝑛2 ... 𝑎 𝑛𝑛  𝑏 𝑛 
  
Notar que neste sistema não conhecemos facilmente a solução,
justamente, a ideia do método proposto é achar ela, por tanto
não podemos avaliar a grandeza | 𝑥¯ 𝑖 − 𝑥 𝑘𝑖 | , onde o supraíndice
refere-se à 𝑖 -éssima incógnita e o subíndice à 𝑘 -éssima iteração.
Então, nesse caso como podemos saber em que momento parar
o processo iterativo? Pense alguma alternativa.
6. Implementar em python o processo iterativo de Newton do
exemplo (e), para encontrar as duas raizes no intervalo [0,2] da
função:
2
𝑓 (𝑥) = 𝑥 𝑒 −𝑥 − 0.1
Primeiro plotar a função no intervalo [-1,2]. Baseado no gráfico
da função escolher pontos iniciais 𝑥 0 que estejam próximos
das raizes procuradas. Escolher um erro 𝜀 pequeno e determi-
nar quantas iterações são necessárias para a convergência do
método.
7. Implementar o método das potencias do exemplo (f) na matriz

1 0 0
𝐴 = 0 2 0
 
0 0 3
 
3 PROCESSOS ITERATIVOS E RELAXAÇÕES 18

e na matriz
𝐴 = diag(𝑎 1 , 𝑎2 , . . . , 𝑎 𝑛 )
sendo 𝑎 𝑖 s números randômicos uniformemente distribuídos entre 0 e
1.

3.3 Forma de equilibrio de uma corda elástica

Vamos considerar uma corda em tensão como mostrado na figura.

I A tensão da corda será denotada por 𝜏 [N] e a mesma é conhecida;


I Para efeitos de modelagem, consideramos que a corda é discretizada
em 𝑁 segmentos de comprimento ℓ 0 , sendo o comprimento total
da corda denotado por 𝐿, então 𝐿 = 𝑁 ℓ 0 ;
I Os extremos da corda estão presos à parede, isto significa que o
ponto 𝑥 = 0 e 𝑥 = 𝐿 não podem se deslocar;
I O massa total da corda é dada por:
∫ 𝐿
𝑀= 𝜌(𝑥) 𝑑𝑥
0

em que a densidade 𝜌(𝑥) [kg/m] é uma função conhecida.


I Para efeitos de modelagem consideramos que a massa total da
corda 𝑀 é concentrada em 𝑛 = 𝑁 − 1 partículas de massa 𝑚 𝑖
equidistantes localizadas a distância ℓ 0 entre elas, sendo a massa
da 𝑖 -éssima partícula
ℓ0
∫ (𝑖+1) ℓ 0 + 2
𝑚𝑖 = 𝜌(𝑥) 𝑑𝑥, 𝑖 = 1, 2, . . . , 𝑛 − 1
ℓ0
(𝑖+1) ℓ 0 − 2

e
2 ℓ0 𝐿
∫ 3 ∫
𝑚0 = 𝜌(𝑥) 𝑑𝑥, 𝑚𝑛−1 = 𝜌(𝑥) 𝑑𝑥,
0 𝐿− 23 ℓ 0

I Em cada massa está aplicada a força para baixo devido a gravidade,


i.e.,
𝑝 𝑖 = −𝑚 𝑖 𝑔
I Em certas massas pode estar aplicada alguma força adicional 𝑓𝑖
I A corda encontra-se em equilíbrio estático devido ao balanço das
forças;
I Fazendo um balanço de forças na direção vertical, podemos escrever
que:
𝑦
F𝑖 = 0, 𝑖 = 0, . . . , 𝑛 − 1
em que
𝑦
F𝑖 = −𝑚 𝑖 𝑔 + 𝑓𝑖 + 𝐹𝑖𝜎
I Para calcular a força devido a tensão da corda usamos que:

𝐹𝑖𝜎 = −𝜏 (sin 𝜃𝐿𝑖 + sin 𝜃𝑅𝑖 )

sendo que para ângulos pequenos, podemos usar a seguinte aprox-


imação para 𝑖 = 1 , . . . , 𝑛 − 1
𝑦 𝑖 − 𝑦 𝑖−1 𝑦 𝑖 − 𝑦 𝑖+1
sin 𝜃𝐿𝑖 ≈ tan 𝜃𝐿𝑖 = , sin 𝜃𝑅𝑖 ≈ tan 𝜃𝑅𝑖 = ,
ℓ0 ℓ0
3 PROCESSOS ITERATIVOS E RELAXAÇÕES 19

Aqui já temos acertado os sinais de tudo para que resulte o sistema


da forma correta. Estas fórmulas servem para todas as massas se
definirmos
𝑦 −1 = 𝑦 𝑛 = 0
pois os extremos da cordas não podem se deslocar.
I Colocando tudo junto, para cada massa temos a equação de equi-
líbrio:
𝜏
−𝑚 𝑖 𝑔 + 𝑓𝑖 − (−𝑦 𝑖−1 + 2 𝑦 𝑖 − 𝑦 𝑖+1 ) = 0 (3.1)
ℓ0
Notar que no caso de densidade constante, podemos escrever para pontos
que não sejam o primeiro ou o último:
𝜏
−𝜌ℓ0 𝑔 + 𝑓𝑖 − (−𝑦 𝑖−1 + 2 𝑦 𝑖 − 𝑦 𝑖+1 ) = 0 (3.2)
ℓ0

Vale mencionar que uma forma mais correta de formular as equações


seria escrever o problema como uma EDO

𝑑2 𝑦
−𝜏 = −𝜌(𝑥)𝑔 + 𝑓 (𝑥)
𝑑𝑥 2
e aplicar um método de discretização tal como o método das difer-
enças finitas para aproximar a derivada segunda que aparece no lado
esquerdo.

Mini projeto

Considerar uma corda de comprimento 𝐿 = 1m, tensão 𝜎 = 2 N:

I Considerar a corda particionada em 𝑁 intervalos e duas funções


de densidade
(i) 𝜌(𝑥) = 1 kg/m
1 2
(ii) 𝜌(𝑥) = 12 (1 + 𝑒 −100 (𝑥− 2 ) ) kg/m
Fazer uma função de python para calcular a massa das 𝑁
particulas em ambos casos e para valores de 𝑁 = 10 , 20 , 40 , 80.

I Implementar um método iterativo pelo qual é encontrada a


posição de equilíbrio das massas usando iterações de Jacobi,
i.e., o posição da 𝑖 -éssima massa é achada a partir da posição
das massas vizinhas na iteração prévias.

I Implementar o método iterativo, conhecido como esquema de


Gauss-Seidel. Neste método, para achar a posição de equilíbrio
da 𝑖 -éssima massa, se formos avançando em orden progressiva,
i.e., 0 , 1 , 2 , . . . , emprega-se a posição da massa 𝑖 + 1 na iteração
prévia (pois ainda esta não tem sido calculada) e a a posição da
massa 𝑖 − 1 na iteração atual, pois ela sim já tem sido calculada.

Nos dois itens anteriores considerar 𝑁 = 10 , 20 , 40 , 80, 𝑔 =


9.8m/s2 e os dois casos de densidade dados anteriormente e
plotar a forma de equilíbrio da corda em cada caso.

I Para o caso com 𝜌 = 1 e 𝑁 = 80, aplicar uma força vertical


para baixo 𝑓39 na massa 𝑖 = 39 de valor variável e plotar o
3 PROCESSOS ITERATIVOS E RELAXAÇÕES 20

deslocamento sofrido pelo ponto como função de 𝑓39 .

I Repetir o anterior mas aplicando ao mesmo tempo uma força


para cima na massa 𝑖 = 17 e uma força para baixo na massa
𝑖 = 30. Plotar a forma de equilíbrio.
I (Exercício opcional) Agora considerar:
• A corda encontra-se imersa num fluido com densidade
𝜌 𝑓 = 1000kg/m3 (a.k.a. água)
• Vamos supor que o diámetro da corda é uma função de 𝑥
dada por:
1 2
𝜙(𝑥) = 2 (1 + 𝑒 −200 (𝑥− 2 ) )
• Considerar que a densidade volúmetrica 𝜌¯ do material da
corda é 900 kg/m3 .
• Considerar as 𝑓𝑖 s iguais a zero.
• Incluir a força de empuxo que o fluido faz sobre a corda,
calculando o volume da corda e distribuindo ele sobre as
partículas:
𝑓𝑖𝑏 = 𝜌 𝑓 𝑣 𝑖 𝑔
• Calcular a forma de equilibrio da corda e plotar.
TÓPICOS VARIADOS DE
PROGRAMAÇÃO EM python 4
4.1 Preludio . . . . . . . . . . . 21
4.1 Preludio
4.2 Processamento de ima-
gens . . . . . . . . . . . . . . 21
Neste capítulo iremos estudar algumas ferramentas adicionais para com-
4.3 Mais sobre gráficação e
pletar a formação nas técnicas de programação em python, incluindo, al-
animação . . . . . . . . . . . 23
gumas noções sobre processamento de imagens, algoritmos para procura
4.4 Ordenamento e procura
e ordenação de arrays e finalmente algumas funcionalidades interessantes
em arrays . . . . . . . . . . . 26
para gerar gráficos em 2D e 3D.

4.2 Processamento de imagens

Uma imagem não é outra coisa que uma lista de matrizes. Por exemplo
para uma imagem RGB teriamos uma lista de 3 matrizes. Considerar o
código

import matplotlib.image as mpimg


img = mpimg.imread(’stinkbug.png’)
plt.imshow(img)

Figure 4.1: Imagem em tons de cinza.

(o arquivo stinkbug.png está disponível no Tidia).


O objeto img é um array de 3 índices, como pode-se certificar vendo a
dimensão do mesmo:

> print(img.shape)
(375, 500, 3)

Cada matriz da lista representa um canal e os valores dentro da matriz a


intensidade de cada um dos 375 × 500 pixels da imagem. Se imprimirmos
o array veremos, neste caso particular, que todas as matrizes são muito
parecidas pois esta é uma imagem em tons de cinza.

array([[[0.40784314, 0.40784314, 0.40784314],


[0.40784314, 0.40784314, 0.40784314],
[0.40784314, 0.40784314, 0.40784314],
...,
[0.42745098, 0.42745098, 0.42745098],
[0.42745098, 0.42745098, 0.42745098],
[0.42745098, 0.42745098, 0.42745098]],

[[0.4117647 , 0.4117647 , 0.4117647 ],


[0.4117647 , 0.4117647 , 0.4117647 ],
[0.4117647 , 0.4117647 , 0.4117647 ],
...,
[0.42745098, 0.42745098, 0.42745098],
[0.42745098, 0.42745098, 0.42745098],
4 TÓPICOS VARIADOS DE PROGRAMAÇÃO EM python 22

[0.42745098, 0.42745098, 0.42745098]],

[[0.41960785, 0.41960785, 0.41960785],


[0.41568628, 0.41568628, 0.41568628],
[0.41568628, 0.41568628, 0.41568628],
...,
[0.43137255, 0.43137255, 0.43137255],
[0.43137255, 0.43137255, 0.43137255],
[0.43137255, 0.43137255, 0.43137255]],

Para manipular a imagem por simplicidade podemos pegar apenas um


canal dela, p.e.

A = img[:, :, 0]

e realizar operações sobre esta matriz. É isso que será desenvolvido


justamente nos seguintes exercícios.

Exercícios
1. Considerar a imagem do exemplo anterior. Visualizar a imagem
usando o comando plt.imshow. Visualizar a imagem original
img e visualizar o canal A considerando diferentes mapas de
cores:

plt.imshow(A)
plt.imshow(A, cmap="hot")
plt.imshow(A, cmap="’nipy_spectral’")

O resultado deveria ser algo assim:

2. Para a mesma imagem do exemplo, modificar a mesma para


que apareçam manchas circulares de cor branco e de cor preto
em posições aleatórias.
3. Programar uma função Suaviza para processar imagens. Para
isto será necessário carregar uma imagem
I Fazer uma função de suavizado em que a matriz resultante
B, em cada pixel (ou célula), tenha a média dos valores das
células correspondentes e das células adjacentes em hori-
zontal e em vertical da matriz de entrada A, i.e., pensando
a imagem como uma matriz

1
𝐵 𝑖𝑗 = (𝐴 𝑖,𝑗 + 𝐴 𝑖+1,𝑗 + 𝐴 𝑖−1,𝑗 + 𝐴 𝑖,𝑗+1 + 𝐴 𝑖,𝑗−1 )
5
Aplicar o algoritmo repetidas vezes e observar o resultado
Figure 4.2: Visualização esperada da im-
como função do número de vezes que ele é aplicado. agem.
I Fazer outra versão em que matriz resultante, em cada pixel,
tenha a média dos valores das células correspondentes,
das células adjacentes em horizontal, em vertical e em
diagonal.
4 TÓPICOS VARIADOS DE PROGRAMAÇÃO EM python 23

Tomar providências para o tratamento dos pixels que estão


na borda e aplicar as funções repetidas vezes em alguma
imagem que possua tons de cinza. Testar o algoritmo na
imagem do exemplo anterior ou em outra imagem que
achar.
4. Considerar a imagem de microscopio disponível no tidia no
arquivo concrete.jpg a qual corresponde a uma amostra de
concreto usado na construção civil.

I Para carregar a mesma pode considerar a parte inicial do


exercício anterior e ficar apenas com um canal. Estude a
matriz que resulta. Figure 4.3: Imagem de uma amostra de
concreto usada na construção civil.
I Recortar uma janela da imagem que esteja livre de ano-
tações. Considere diferentes tamanhos de janela.
I Apartir da imagem recortada no item anterior, elaborar
um algoritmo que processe a imagem para estimar a fração
de agregados, i.e., as partes em cinza mais escuro. Para isto,
precisará normalizar a imagem e determinar um limiar de
ton de cinza a partir do qual o pixel pode ser considerado
agregado. Para isto, considerar o código:

img = (recortada > limiar)*1.0

Analisar os resultados como função do valor tomado para


limiar.

4.3 Mais sobre gráficação e animação

4.3.1 Plotagem de funções de 2 variáveis

Para completar o nosso conhecimento de biblioteca matplotlib pre-


cisamos estudar algumas funções para realizar gráficos de funções.
Específicamente, queremos gráficar:

I Superfícies em 3D;
I Curvas de nível constante;
I Campos vetoriais;

No execício na sequência a ideia é pesquisar no site oficial do matplotlib


(https://matplotlib.org/) para conseguir reproduzir os gráficos mostra-
dos.

Exercícios
Considerar a função

𝑓 (𝑥, 𝑦) = cos(𝑥) cos(𝑦)

I Usando a função plt.plot_surface, plotar 𝑓 como superfície


em 3D, considerando diferentes pontos de vista;
I Usando a função plt.contourf, plotar gráficos com curvas de
nível da função usando diferentes escalas de cores;

Figure 4.4: Gráficos da função 𝑓 .


4 TÓPICOS VARIADOS DE PROGRAMAÇÃO EM python 24

I Usando
h a função plt.quiver, plotar o gradiente da função
i
𝜕𝑓 𝜕𝑓
|
∇𝑓 = ,
𝜕𝑥 𝜕𝑦
. Superpor o gráfico com as curvas de nível
constante e verificar visualmente que estas são ortogonais ao
gradiente.

Os gráficos tem que ser similares aos mostrados nas figuras.

4.3.2 Um sistema dinâmico

Considerar dois corpos de massas 𝑚1 e 𝑚2 , interagindo gravitacional-


mente de acordo com a fórmula:
𝛾𝑚1 𝑚2
F2→1 (r1 (𝑡), r2 (𝑡)) = − r12 = −F1→2 (r1 (𝑡), r2 (𝑡))
k r12 k 3

onde r12 = r2 − r1 , sendo r𝑖 a posição do 𝑖 -éssimo corpo. Sendo uma força


central, o movimento está restrito ao plano. Um esquema númerico para
calcular a evolução dos corpos, partindo da condição inicial dada

[r𝑖 (0), v𝑖 (0)] = r0𝑖 , v0𝑖


 

é dado no pseudo-codigo da sequência:

Método de avanço no tempo

Dada a condição inicial r0𝑖 , v0𝑖 e o passo de tempo Δ𝑡


 

Inicializar 𝑡 0 = 0, 𝑛 = 0
Enquanto 𝑡 𝑛 < 𝑇fin
F 𝑗→𝑖 (r1𝑛 ,r2𝑛 )
1. Calcular a aceleração: a𝑛𝑖 = 𝑚𝑖 , 𝑗 ≠ 𝑖, 𝑖 = 1 , 2
2. Atualizar a posição: r𝑛+
𝑖
1
= r𝑛𝑖 + v𝑛𝑖 Δ𝑡 + 21 a𝑛𝑖 Δ𝑡 2
F 𝑗→𝑖 (r1𝑛+1 ,r2𝑛+1 )
3. Atualizar a aceleração: a𝑛+
𝑖
1
= 𝑚𝑖 , 𝑗≠𝑖
4. Atualizar a velocidade: v𝑛+1
= v𝑛𝑖 + 1
a𝑛𝑖 + a𝑛+ 1

𝑖 2 𝑖
Δ𝑡
5. Guardar 𝑡 𝑛 , r𝑛𝑖 , v𝑛𝑖
 

6. Incrementar o tempo 𝑡 𝑛+1 = 𝑡 𝑛 + Δ𝑡


7. Incrementar 𝑛
Fim

Este esquema chama-se Método Verlet-Velocidade e é muito usado na


física computacional. No exercício a seguir o método é implementado
para estudar as trajetórias de dois corpos.

Exercícios
Na sequência considerar:
I 𝛾 = 1, Δ𝑡 = 0.01, 𝑚1 = 1, 𝑁steps = 2000
r01 , v01 = [[0 , 0], [0 , 0]],
 
I
r02 , v02 = [[1 , 0], [0 , 1]]
 
I
4 TÓPICOS VARIADOS DE PROGRAMAÇÃO EM python 25

1. Implementar o método Verlet-Velocidade numa função que


retorne as posições e velocidades dos corpos como função do
tempo.
2. Implementar uma função que salve o histórico completo num
arquivo de texto de tipo ascii. Para isto considerar as duas
variantes na sequência:
• Salvar posições e velocidades a medida que estão sendo
calculadas:
.
.
tn = 0
evolfile = open(’evol.txt’, ’w+’)
n = 0
while(tn < Tfin):
.
# Do your calculations
.
# Save the current time step
evolfile.write("%lf %lf %lf %lf %lf %lf ..."
%(tn, r1[0], r1[1], v1[0], v1[1], r2[0],
...))

tn = tn + 1
n = n + 1

evolfile.close()

• Ir guardando o histórico de posições e velocidades num


array e no final salvar ele num arquivo de uma vez:
.
.
tn = 0
n = 0
while(tn < Tfin):
.
# Do your calculations
.
# Store the current time step
solution[n, :] = tn, r1[0], r1[1], v1[0], v1[1],
r2[0] ...

tn = tn + 1
n = n + 1

# Save everything at once


np.savetxt(filename, solution)

3. Implementar uma função que carregue o arquivo ascii do ponto


anterior e plota as trajetórias dos corpos e a energia cinética
total do sistema como função do tempo, i.e.,

1 1
K(𝑡) = 𝑚1 k v1 k 2 + 𝑚2 k v2 k 2
2 2
Para isto, usar a função np.loadtxt de numpy, a qual recebe como
4 TÓPICOS VARIADOS DE PROGRAMAÇÃO EM python 26

argumento o nome do arquivo que quer ser carregado.

Para realizar as simulações considerar 𝑚2 = 0.001, 𝑚2 = 0.01, 𝑚2 =


0.1, 𝑚2 = 1, 𝑚2 = 2.

4. (Opcional) Realizar uma animação para ilustrar o movimento dos


corpos.

4.3.3 Algoritmo de flooding

A ideia é simular o processo de alagamento dentro de uma grade


quadrada com 𝑁 × 𝑁 células. No centro da grade temos uma fonte de
agua, a qual se espalha ao resto das células da grade. Dentro da grade
temos então as células em três possíveis estados:
I Célula não alagada, com valor: 0
I Célula alagada, com valor: 1
I Célula obstáculo, com valor: 2

As regras de atualização, de um passo para o seguinte, são simples:


"Se uma célula estiver alagada, então os seus vizinhos (acima, à dire-
ita, à esquerda e embaixo) ficam alagados, exceito se a célula for um
obstáculo"

Exercícios
Implementar um algoritmo de alagamento numa grade de 𝑁 × 𝑁
células e executa uma animação a medida que o algoritmo avança.
Para isto, considerar:

I Uma função init que inicializa a grade com um ponto central


que encontra-se no estado 1 e coloca diferentes configurações
de obtáculos que você achar interessante;
I Uma função update que, dada a grade no tempo atual, retorna
a nova grade que resulta de aplicar as regras ditas acima;
I Considerar diferentes valores de 𝑁 ;
I Usar a função FuncAnimation e experimentar com os valores
dos parâmetros frames e interval para ver o que acontece.

Figure 4.5: Resultado típico do algoritmo


4.4 Ordenamento e procura em arrays de flooding.

4.4.1 Ordenamento de arrays

Em computação é essencial contar com algoritmos de ordenamento


que sejam eficientes. Nesta seção iremos considerar três algoritmos que
servem para ordenar na ordem crescente os elementos de um vetor:
I Ordenamento de tipo bolha (Bubble sort)
I Ordenamento por seleção (Selection sort)
I Ordenamento rápido (Quick sort)

que estão dados na sequência:


4 TÓPICOS VARIADOS DE PROGRAMAÇÃO EM python 27

def bubble_sort(arr):
n = len(arr)
for i in range(n):
for j in range(0, n-i-1):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
return arr

def selection_sort(arr):
n = len(arr)
for i in range(n):
min_idx = i
for j in range(i+1, n):
if arr[j] < arr[min_idx]:
min_idx = j
arr[i], arr[min_idx] = arr[min_idx], arr[i]

return arr

def quick_sort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quick_sort(left) + middle + quick_sort(right)

Exercício
1. Explicar como que cada algoritmo funciona.
2. Criar um exemplo simples e mostrar o funcionamento passo a
passo de cada algoritmo.
3. Criar vetores de inteiros possuindo 𝑁 componentes e aplicar os
algoritmos. Para isto, considerar 𝑁 = 100 , 200 , 400 , 800 , 1600 e
medir o tempo consumido em cada caso. Plotar o tempo como
função de 𝑁 usando a escala loglog para todos os algoritmos.
Tirar conclusões.
Alphabetical Index

preface, ii

Você também pode gostar