Upgrade to Pro — share decks privately, control downloads, hide ads and more …

O Evolucionismo Resolvendo Problemas de Otimização

Filipe Saraiva
December 18, 2019

O Evolucionismo Resolvendo Problemas de Otimização

Como a teoria da evolução das espécies pode ser aplicada à resolução de problemas de otimização?

Apresentação realizada durante a XVI Semana Nacional de Ciência e Tecnologia - III Semana do Cérebro do Museu da UFPA.

Filipe Saraiva

December 18, 2019
Tweet

More Decks by Filipe Saraiva

Other Decks in Science

Transcript

  1. O Evolucionismo Resolvendo Problemas de
    Otimização
    III Semana do Cérebro
    Filipe Saraiva
    Filipe Saraiva | UFPA | 1 / 66

    View full-size slide

  2. Conteúdo
    WHOAMI
    Problemas de Otimização
    Problema do Caixeiro Viajante
    Problema da Mochila
    Evolucionismo
    Algoritmos Genéticos
    Etapas dos Algoritmos Genéticos
    Pseudocódigo
    Vídeo
    Conclusões
    Filipe Saraiva | UFPA | 2 / 66

    View full-size slide

  3. Conteúdo
    WHOAMI
    Problemas de Otimização
    Problema do Caixeiro Viajante
    Problema da Mochila
    Evolucionismo
    Algoritmos Genéticos
    Etapas dos Algoritmos Genéticos
    Pseudocódigo
    Vídeo
    Conclusões
    Filipe Saraiva | UFPA | 3 / 66

    View full-size slide

  4. WHOAMI
    Filipe Saraiva
    • Dr. & Me. Engenharia Elétrica (USP), Bel.
    Ciência da Computação (UFPI)
    • FACOMP & PPGCC - ICEN/UFPA
    • Membro do LAAI
    • Pesquisador de Inteligência Computacional
    Aplicada
    • Disciplinas de Fundamentos da Computação
    e Matemática Computacional
    • Desenvolvedor de Software Livre
    Filipe Saraiva | UFPA | 4 / 66

    View full-size slide

  5. Conteúdo
    WHOAMI
    Problemas de Otimização
    Problema do Caixeiro Viajante
    Problema da Mochila
    Evolucionismo
    Algoritmos Genéticos
    Etapas dos Algoritmos Genéticos
    Pseudocódigo
    Vídeo
    Conclusões
    Filipe Saraiva | UFPA | 5 / 66

    View full-size slide

  6. Problemas de Otimização
    Problemas de Otimização são problemas matemáticos onde há um
    conjunto de variáveis que devem ter seus valores ajustados de forma
    que, submetidas a um conjunto de restrições, consigam atingir o maior
    (ou o menor) valor possível de uma dada função.
    Filipe Saraiva | UFPA | 6 / 66

    View full-size slide

  7. Problema da Manufatura
    Uma manufatura produz mesas e bancos, sendo capaz de vender toda
    a sua produção no período. O único recurso restrito é a mão de obra,
    cuja produtividade, juntamente com os lucros, são:
    • Mesa: R$ 20 de lucro, necessita-se de 3 homens/hora na
    montagem e 4 homens/hora no acabamento;
    • Banco: R$ 24 de lucro, necessita-se de 6 homens/hora na
    montagem e 2 homens/hora no acabamento;
    No total, a manufatura dispõe de 60 homens/hora para trabalhar com
    montagem e 32 homens/hora para trabalhar com acabamento.
    Filipe Saraiva | UFPA | 7 / 66

    View full-size slide

  8. Problema da Manufatura
    Max Z = 20x1 + 24x2
    Suj. a:







    3x1 + 6x2 ≤ 60
    4x1 + 2x2 ≤ 32
    xi ≥ 0, ∀i = 1, 2
    Filipe Saraiva | UFPA | 8 / 66

    View full-size slide

  9. Problemas de Otimização
    Encontrar os valores das Variáveis de Decisão de forma que elas
    cumpram o Conjunto de Restrições e consigam otimizar a Função
    Objetivo ao melhor valor possível.
    Filipe Saraiva | UFPA | 9 / 66

    View full-size slide

  10. Exemplos
    Problemas de Otimização são encontrados nos mais diversos setores
    econômicos:
    • Construção;
    • Transportes;
    • Nutrição;
    • Logística;
    • Programação da produção;
    • ...
    Filipe Saraiva | UFPA | 10 / 66

    View full-size slide

  11. Otimização Combinatória
    Ao contrário de outros tipos de problemas de otimização, na
    otimização combinatória não há funções matemáticas relacionadas
    com os valores que as variáveis de decisão podem assumir.
    Na otimização linear o que temos é a combinação dos próprios
    elementos entre si.
    Filipe Saraiva | UFPA | 11 / 66

    View full-size slide

  12. Otimização Combinatória
    Otimização Linear: “quais quantidades de itens cabem na mochila de
    forma a maximizar seu valor?”
    vs
    Otimização Combinatória: “quais itens cabem na mochila de forma a
    maximizar seu valor?”
    Filipe Saraiva | UFPA | 12 / 66

    View full-size slide

  13. Conteúdo
    WHOAMI
    Problemas de Otimização
    Problema do Caixeiro Viajante
    Problema da Mochila
    Evolucionismo
    Algoritmos Genéticos
    Etapas dos Algoritmos Genéticos
    Pseudocódigo
    Vídeo
    Conclusões
    Filipe Saraiva | UFPA | 13 / 66

    View full-size slide

  14. Problema do Caixeiro Viajante
    Um dos Problemas de Otimização Combinatória mais conhecidos e
    desenvolvidos na literatura é o Problema do Caixeiro Viajante.
    Filipe Saraiva | UFPA | 14 / 66

    View full-size slide

  15. Problema do Caixeiro Viajante
    Enunciado
    A descrição do problema é a seguinte: “Dado um conjunto de cidades
    e um conjunto de estradas que ligam essas cidades, sair de alguma
    delas e visitar todas as demais, apenas uma vez, e voltar à cidade
    inicial, no menor caminho possível”.
    Filipe Saraiva | UFPA | 15 / 66

    View full-size slide

  16. Problema do Caixeiro Viajante
    Instância do Problema do Caixeiro Viajante
    Filipe Saraiva | UFPA | 16 / 66

    View full-size slide

  17. Problema do Caixeiro Viajante
    Matematicamente, é possível modelar as cidades e as estradas como
    um grafo, fazendo com que o problema passe a ser encontrar o ciclo
    hamiltoniano mínimo.
    Não há um algoritmo polinomial conhecido para resolver esse
    problema. Portanto, para obtermos a solução ótima, é necessário listar
    todas as soluções possíveis.
    O número de soluções possíveis é (n − 1)!/2, onde n é o número de
    cidades.
    Filipe Saraiva | UFPA | 17 / 66

    View full-size slide

  18. Problema do Caixeiro Viajante
    Se seu computador conseguir computar 1 milhão de ciclos
    hamiltonianos por segundo:
    Tamanho de n
    Função
    Custo 9 10 11 12 13 14 15 20
    (n − 1)!/2 Instantâneo 0,33s 4s 40s 9min 2h 1 dia 1mi anos
    Filipe Saraiva | UFPA | 18 / 66

    View full-size slide

  19. Problema do Caixeiro Viajante
    Aplicações
    Algumas aplicações possíveis do Problema do Caixeiro Viajante:
    • Problemas de logística;
    • Entrega de suprimentos;
    • Planejamento de rotas;
    • Planejamento e construção de estradas;
    • ...
    Filipe Saraiva | UFPA | 19 / 66

    View full-size slide

  20. Conteúdo
    WHOAMI
    Problemas de Otimização
    Problema do Caixeiro Viajante
    Problema da Mochila
    Evolucionismo
    Algoritmos Genéticos
    Etapas dos Algoritmos Genéticos
    Pseudocódigo
    Vídeo
    Conclusões
    Filipe Saraiva | UFPA | 20 / 66

    View full-size slide

  21. Problema da Mochila
    O Problema da Mochila é um problema de fácil compreensão e de
    ampla aplicação em problemas do mundo real.
    Filipe Saraiva | UFPA | 21 / 66

    View full-size slide

  22. Problema da Mochila
    Enunciado
    Dado um conjunto de itens com seus respectivos pesos e valores, e
    uma mochila com capacidade máxima, quais itens devem ser
    carregados na mochila de forma a termos o maior valor possível?
    Filipe Saraiva | UFPA | 22 / 66

    View full-size slide

  23. Problema da Mochila
    Instância do Problema da Mochila
    Filipe Saraiva | UFPA | 23 / 66

    View full-size slide

  24. Problema da Mochila
    O Problema da Mochila pode ser encontrado em diversos subtipos. O
    enunciado apresentado diz respeito ao Problema da Mochila 0-1
    onde os itens podem apenas estar ou não estar na solução.
    No Problema da Mochila Fracionada os itens podem ser alocados
    como frações de um todo, o que torna o problema linear. Em outros
    tipos, é possível ter mais de um item do mesmo tipo na mochila.
    Filipe Saraiva | UFPA | 24 / 66

    View full-size slide

  25. Problema da Mochila
    Para o Problema da Mochila, o número de combinações possíveis é
    dado pela seguinte função matemática:
    2n
    Filipe Saraiva | UFPA | 25 / 66

    View full-size slide

  26. Problema da Mochila
    Modelo Matemático
    Dado o conjunto de itens i e seus respectivos pesos ci e valores vi , e
    uma variável binária xi para representar se um dado item está (1) ou
    não (0) na mochila, e a capacidade máxima da mochila dada por p, a
    modelagem matemática do problema é dada por:
    Max Z = vi xi
    Suj. a: ci xi ≤ p
    Filipe Saraiva | UFPA | 26 / 66

    View full-size slide

  27. Problema da Mochila
    Aplicações
    Algumas aplicações possíveis do Problema da Mochila:
    • Investimento de capital;
    • Carregamento de veículos;
    • Orçamento;
    • Resolução de alguns algoritmos de criptografia;
    • ...
    Filipe Saraiva | UFPA | 27 / 66

    View full-size slide

  28. Prêmio do Millenium
    Clay Mathematical Institutte - Millenium Prize (U$ 1mi)
    Filipe Saraiva | UFPA | 28 / 66

    View full-size slide

  29. Conteúdo
    WHOAMI
    Problemas de Otimização
    Problema do Caixeiro Viajante
    Problema da Mochila
    Evolucionismo
    Algoritmos Genéticos
    Etapas dos Algoritmos Genéticos
    Pseudocódigo
    Vídeo
    Conclusões
    Filipe Saraiva | UFPA | 29 / 66

    View full-size slide

  30. Evolucionismo
    Filipe Saraiva | UFPA | 30 / 66

    View full-size slide

  31. Evolucionismo - Darwin
    Filipe Saraiva | UFPA | 31 / 66

    View full-size slide

  32. Evolucionismo - Mendel
    Filipe Saraiva | UFPA | 32 / 66

    View full-size slide

  33. Conteúdo
    WHOAMI
    Problemas de Otimização
    Problema do Caixeiro Viajante
    Problema da Mochila
    Evolucionismo
    Algoritmos Genéticos
    Etapas dos Algoritmos Genéticos
    Pseudocódigo
    Vídeo
    Conclusões
    Filipe Saraiva | UFPA | 33 / 66

    View full-size slide

  34. Algoritmos Genéticos
    Algoritmos Genéticos foi desenvolvido por Jonh Holland no início dos
    anos 70, como um método de resolução de problemas de otimização
    baseado na dinâmica evolutiva das espécies.
    Filipe Saraiva | UFPA | 34 / 66

    View full-size slide

  35. Algoritmos Genéticos
    Com inspiração no conhecimento sobre genética e evolução
    observados já naquela época (em especial, Darwin e Mendel), os GAs
    trabalham sobre um conjunto de soluções que terão partes
    combinadas ou modificadas, realizando a busca no espaço de
    soluções.
    Espera-se que essa busca conduza o GA a boas soluções a medida
    que as iterações vão acontecendo.
    Filipe Saraiva | UFPA | 35 / 66

    View full-size slide

  36. Algoritmos Genéticos
    Por ser baseado nos processos da evolução natural, o GA utiliza
    sobremaneira o linguajar da biologia evolutiva para nomear funções
    computacionais realizadas pelo método. A saber:
    • Indivíduo: uma solução (ou representação de uma solução) do
    problema trabalhado;
    • População: conjunto de indivíduos (soluções) do problema;
    • Geração: iteração de formação de novas populações do
    problema;
    Filipe Saraiva | UFPA | 36 / 66

    View full-size slide

  37. Algoritmos Genéticos
    Por ser baseado nos processos da evolução natural, o GA utiliza
    sobremaneira o linguajar da biologia evolutiva para nomear funções
    computacionais realizadas pelo método. A saber:
    • Seleção: processo onde 2 ou mais indivíduos são selecionados
    para gerar novos indivíduos combinados destes;
    • Cruzamento (Crossover): forma pela qual 2 ou mais indivíduos
    são combinados entre si, gerando novos indivíduos;
    • Mutação: alteração aleatória onde algum componente do
    indivíduo tem seu valor modificado.
    Filipe Saraiva | UFPA | 37 / 66

    View full-size slide

  38. Algoritmos Genéticos
    Podemos elencar as seguintes características para os GAs:
    • Algoritmo populacional;
    • Utiliza “operadores genéticos” (seleção, cruzamento e mutação)
    para realizar a busca;
    • A cada iteração (geração) uma nova população é formada da
    geração anterior.
    Filipe Saraiva | UFPA | 38 / 66

    View full-size slide

  39. Conteúdo
    WHOAMI
    Problemas de Otimização
    Problema do Caixeiro Viajante
    Problema da Mochila
    Evolucionismo
    Algoritmos Genéticos
    Etapas dos Algoritmos Genéticos
    Pseudocódigo
    Vídeo
    Conclusões
    Filipe Saraiva | UFPA | 39 / 66

    View full-size slide

  40. Etapas do Algoritmo Genético
    As principais etapas do GA são as seguintes:
    • Codificação dos indivíduos;
    • Geração da população inicial;
    • Seleção;
    • Cruzamento;
    • Mutação;
    • Geração da Nova População;
    • Critério de parada.
    Filipe Saraiva | UFPA | 40 / 66

    View full-size slide

  41. Codificação dos Indivíduos
    A maneira como um indivíduo é codificado no GA é de grande
    importância para o método pois a partir dele a busca é realizada e
    operadores de cruzamento ou mutação podem ser implementados de
    formas diferentes.
    Filipe Saraiva | UFPA | 41 / 66

    View full-size slide

  42. Codificação dos Indivíduos
    Por exemplo, para o Problema do Caixeiro Viajante poderíamos utilizar
    uma codificação inteira, onde cada valor representa o vértice do grafo
    que será visitado, na sequência.
    4 5 3 1 2
    No exemplo, os vértices visitados serão na ordem 4, 5, 3, 1 e 2.
    Filipe Saraiva | UFPA | 42 / 66

    View full-size slide

  43. Codificação dos Indivíduos
    Já para um problema binário, como o Problema da Mochila 0-1, uma
    codificação binária é suficiente para representar uma solução.
    0 1 0 0 1
    No exemplo, a solução contém apenas os itens 2 e 5 na mochila.
    Filipe Saraiva | UFPA | 43 / 66

    View full-size slide

  44. Geração da População Inicial
    O GA trabalha simultaneamente com um conjunto de soluções que
    chamamos população.
    No geral, no início do método essa população é gerada de forma
    aleatória. É possível também utilizar conhecimento da instância do
    problema ou heurísticas para gerar essa população.
    O tamanho da população é uma característica que o projetista do GA
    deve definir a priori. Se for muito grande, potencialmente haverá maior
    diversidade mas também haverá maior custo computacional. Uma
    população pequena terá menos diversidade, mas tornará o método
    mais rápido.
    Filipe Saraiva | UFPA | 44 / 66

    View full-size slide

  45. Seleção
    Cada indivíduo do GA tem um valor correspondente na função objetivo
    do método. Assim, é possível listá-los dos melhores para os piores em
    relação ao desempenho na função objetivo.
    O operador de seleção realiza a seleção de um ou mais indivíduos
    para terem seus genes misturados e assim criarem novos indivíduos.
    Filipe Saraiva | UFPA | 45 / 66

    View full-size slide

  46. Seleção
    Na seleção, indivíduos com melhor desempenho tem mais chances de
    serem selecionados. A ideia é que melhores indivíduos (“mais aptos”)
    tem mais chances de passarem seus genes para as próximas
    gerações.
    Há diversos operadores de seleção, dentre eles os mais conhecidos
    são a roleta e o torneio.
    Filipe Saraiva | UFPA | 46 / 66

    View full-size slide

  47. Seleção – Roleta
    Na roleta, indivíduos com melhor função objetivo tem
    proporcionalmente mais chances de serem selecionados. Nesse
    método, soma-se os valores das funções objetivo de toda a população
    e sorteia-se um número aleatório até esse valor somado. Cada
    indivíduo ocupa um espaço na roleta proporcional à sua função
    objetivo.
    O indivíduo que estiver ocupando a fatia do valor sorteado terá sido o
    selecionado nessa etapa.
    Filipe Saraiva | UFPA | 47 / 66

    View full-size slide

  48. Seleção – Torneio
    No método torneio, são realizadas 2 etapas de seleções. Na primeira,
    todos os indivíduos tem a mesma chance de serem selecionados,
    portanto seleciona-se um subconjunto do conjunto total de indivíduos.
    Em seguida, do subconjunto seleciona-se apenas os melhores, de
    forma gulosa.
    Filipe Saraiva | UFPA | 48 / 66

    View full-size slide

  49. Seleção
    O número de indivíduos que serão selecionados depende da maneira
    como os operadores genéticos são implementados. No geral, é
    comum que apenas 2 indivíduos sejam selecionados.
    Filipe Saraiva | UFPA | 49 / 66

    View full-size slide

  50. Cruzamento
    O operador de cruzamento combina partes dos genes dos indivíduos
    previamente selecionados para criar novos indivíduos para a geração
    seguinte.
    Há vários tipos de operadores de cruzamento, que dependem também
    da codificação utilizada. Veremos alguns utilizados na codificação
    binária.
    Filipe Saraiva | UFPA | 50 / 66

    View full-size slide

  51. Cruzamento
    Fazendo os indivíduos selecionados serem:
    P1: 0 1 0 0 1
    P2: 1 0 1 1 1
    Cruzamento de 1 ponto
    No cruzamento de 1 ponto temos um corte nos indivíduos
    selecionados gerando combinações entre os genes da esquerda do
    primeiro indivíduo com os da direita do segundo, e vice-versa. Para o
    exemplo:
    P1: 0 1 | 0 0 1 F1: 0 1 1 1 1
    P2: 1 0 | 1 1 1 F2: 1 0 0 0 1
    Filipe Saraiva | UFPA | 51 / 66

    View full-size slide

  52. Cruzamento
    Cruzamento de subcromossomo
    No cruzamento de subcromossomo tem-se dois cortes nos indivíduos
    e o subcromossomo (subconjunto de genes) entre esses dois cortes é
    trocado entre os dois indivíduos pais. Para o exemplo:
    P1: 0 | 1 0 0 | 1 F1: 0 0 1 1 1
    P2: 1 | 0 1 1 | 1 F2: 1 1 0 0 1
    Filipe Saraiva | UFPA | 52 / 66

    View full-size slide

  53. Cruzamento
    Cruzamento Máscara
    No cruzamento de máscara, cria-se aleatoriamente uma lista de 0 e 1
    do tamanho do indivíduo e gera-se novos indivíduos pegando o valor
    do gene do indivíduo 1 se o valor gerado na máscara foi 0, do indivíduo
    2 se o valor gerado foi 1, e o contrário para o segundo indivíduo. Para
    o exemplo:
    Máscara: 0 0 1 0 1
    P1: 0 1 0 0 1 F1: 0 1 1 0 1
    P2: 1 0 1 1 1 F2: 1 0 0 1 1
    Filipe Saraiva | UFPA | 53 / 66

    View full-size slide

  54. Mutação
    O operador de Mutação injeta diversidade na busca realizada pelo
    Algoritmo Genético. Utilizando uma porcentagem baixa, o operador
    altera os genes dos cromossomos para algum valor possível.
    No geral a mutação age sobre indivíduos gerados após o cruzamento.
    Utilizando uma taxa baixa (um valor comum é de 2% a 5%), o
    algoritmo percorre o cromossomo gene-a-gene e, caso um valor
    gerado aleatoriamente fique abaixo da taxa de mutação, o gene em
    análise é modificado.
    Filipe Saraiva | UFPA | 54 / 66

    View full-size slide

  55. Mutação
    Por exemplo, dado o cromossomo abaixo que foi sorteado para
    mutação, alteram-se os genes 1 e 3 para novos valores possíveis das
    variáveis de decisão.
    F1: 0 1 1 0 1
    F1: 1 0 0 1 1
    Filipe Saraiva | UFPA | 55 / 66

    View full-size slide

  56. Geração da Nova População
    Após a aplicação dos operadores genéticos, novos indivíduos vão
    sendo formados. Nessa etapa o GA deve formar uma nova população,
    o que marca a passagem de Geração no método.
    Em geral é gerado um número de indivíduos igual ao tamanho da
    população, que substitui a anterior e dá prosseguimento à execução do
    método.
    Filipe Saraiva | UFPA | 56 / 66

    View full-size slide

  57. Geração da Nova População
    É possível fazer algumas concessões na geração da nova população
    para direcionar a busca realizada pelo método.
    A mais comum é a chamada Elitismo, que é a presença automática
    do melhor indivíduo da geração anterior na geração posterior. Isso
    garante que a melhor solução encontrada sempre estará presente no
    GA.
    Filipe Saraiva | UFPA | 57 / 66

    View full-size slide

  58. Critério de Parada
    O critério de parada mais utilizado para o GA é quando o número de
    gerações atinge um valor máximo estabelecido.
    Outro critério de parada muito utilizado é quando o GA executa um
    certo número de gerações sem melhoria na melhor solução
    encontrada.
    Filipe Saraiva | UFPA | 58 / 66

    View full-size slide

  59. Conteúdo
    WHOAMI
    Problemas de Otimização
    Problema do Caixeiro Viajante
    Problema da Mochila
    Evolucionismo
    Algoritmos Genéticos
    Etapas dos Algoritmos Genéticos
    Pseudocódigo
    Vídeo
    Conclusões
    Filipe Saraiva | UFPA | 59 / 66

    View full-size slide

  60. Pseudocódigo
    Os principais parâmetros do Algoritmo Genético que precisam ser
    decididos durante o projeto do algoritmo são:
    • O tamanho da população;
    • O número de Gerações;
    • O operador de Seleção;
    • O valor da taxa de Cruzamento e qual será o Cruzamento;
    • O valor da taxa de Mutação e como será implementada;
    • Se o GA terá Elitismo ou não;
    • Critério de parada.
    A seguir temos o pseudocódigo para o Algoritmo Genético.
    Filipe Saraiva | UFPA | 60 / 66

    View full-size slide

  61. Pseudocódigo
    Gera População Inicial
    repita
    repita
    Executa Seleção
    Executa Cruzamento
    se Número aleatório for menor que Taxa de Mutação então
    Executa Mutação
    fim se
    até Gerar nova População
    Atualiza número de Gerações
    até Atingir critério de parada
    Filipe Saraiva | UFPA | 61 / 66

    View full-size slide

  62. Conteúdo
    WHOAMI
    Problemas de Otimização
    Problema do Caixeiro Viajante
    Problema da Mochila
    Evolucionismo
    Algoritmos Genéticos
    Etapas dos Algoritmos Genéticos
    Pseudocódigo
    Vídeo
    Conclusões
    Filipe Saraiva | UFPA | 62 / 66

    View full-size slide

  63. Vídeo
    https://www.youtube.com/watch?v=94p5NUogClM
    Filipe Saraiva | UFPA | 63 / 66

    View full-size slide

  64. Conteúdo
    WHOAMI
    Problemas de Otimização
    Problema do Caixeiro Viajante
    Problema da Mochila
    Evolucionismo
    Algoritmos Genéticos
    Etapas dos Algoritmos Genéticos
    Pseudocódigo
    Vídeo
    Conclusões
    Filipe Saraiva | UFPA | 64 / 66

    View full-size slide

  65. Conclusões
    • Há problemas de otimização muito complexos que não
    conseguimos resolver de maneira exata;
    • Para esses problemas, técnicas de inteligência computacional
    como os Algoritmos Genéticos são empregados para encontrar
    boas soluções, aceitáveis, ao problema;
    • Baseados na dinâmica evolutiva das espécies, os Algoritmos
    Genéticos são importantes ferramentas para problemas de
    otimização mas também para aprendizado.
    Filipe Saraiva | UFPA | 65 / 66

    View full-size slide

  66. O Evolucionismo Resolvendo Problemas de
    Otimização
    III Semana do Cérebro
    Filipe Saraiva
    Filipe Saraiva | UFPA | 66 / 66

    View full-size slide