• Nenhum resultado encontrado

Trabalho - 2, Sobre análise de algoritmos e técnicas de projeto de algoritmos, Disciplina: Análise de Algoritmos DT

N/A
N/A
Protected

Academic year: 2021

Share "Trabalho - 2, Sobre análise de algoritmos e técnicas de projeto de algoritmos, Disciplina: Análise de Algoritmos DT"

Copied!
12
0
0

Texto

(1)

Trabalho - 2 , Sobre análise de algoritmos e técnicas de projeto de

algoritmos, Disciplina: Análise de Algoritmos DT16002-00101.

Professor: Ramos, Gabriel de Oliveira gdoramos@unisinos.br

Aluno: Monteiro, Emiliano S. emilianomonteiro@edu.unisinos.br Aluno: Ormond, Eduardo.

eormond@gmail.br

30 de Março, 2020.

1

Disserte sobre análise de algoritmos.

Observação: Sua resposta deve englobar os seguintes temas: Tratabilidade, complexidade assin-totica, notação Big O, e classes de função. Para cada tema, explique o conceito, comente sobre sua importância, e apresente exemplos.

1.1 Tratabilidade.

A complexidade pode ser vista como parte do problema, pode ser vista como uma forma de mensurar o tamanho do trabalho para resolver o problema. Porém alguns problemas são dificeis ou "parecem"difíceis, parecendo intratáveis (são considerados NP-Completos (a partir da publicação de Cook, S. em "The Complexity of Theorem-proving procedures, 1971")). A tratabilidade dos problemas visa estudar as limitações dos problemas com relação à complexidade dos algoritmos se propõe a resolver.

Os limites de complexidade de um problema são superior e inferior; o limite superior refere-se ao melhor algoritmo que se conhece para resolver um problema, já o limite inferior é a melhor complexidade possível para o problema em questão. No caso de um limite inferior, ele é um resultado teórico que indica não ser possível desenvolver um algoritmo para o problema tratado até um determinado ponto (função). Pode haver diferença entre o limite superior e inferior. Quando a diferença deixa de existir a complexidade mínima do problema é conhecida, então a complexidade mínima é a menor que o algoritmo consegue obter para o problema em questão.

Os problemas são tratáveis se existe um algoritmo (polinomial) que o soluciona, já é considerado intratável se o limite superior é exponencial. Nos casos de problemas com limite superior exponencial e limite inferior polinomial temos problemas NP-completos, neste grupo a tratabilidade é um elemento não resolvido, pois não sabemos se temos ou não algoritmos polinomiais para aplicar. Ele será intratável se só a complexidade exponencial os resolvam.

Os tipos de problemas tratados aqui são dos seguintes tipos: a) de decisão, b) de localização e c) de otimização. No caso dos problemas de otimização são os casos de respostas sim/não (ex: o problema da cobertura da existência de vértices); quando são de localização exigem que se procure um elemento que satisfaça uma condição (ex: o problema da determinação da cobertura de vértices); e os problemas de otimização envolvem a qualidade ótima dos resultado (ex: cobertura mínima de vértices).

(2)

1.2 Complexidade assintótica

A complexidade assintótica está relacionada a quão rápido o algoritmo (crescimento da complexi-dade) é (quantas operações elementares são executadas) em relação ao conjunto de dados de entrada (entradas grandes); este é o comportamento mais desejado, pois conforme a quantidade de dados de entrada aumenta, o estudo da complexidade é mais importante menos nos casos de entradas pequenas. A análise assintótica se concentrar em verificar comportamentos para entradas grandes de dados.

Se dois algoritmos de classes de complexidade diferente, recebem entradas de um determinado comprimento, um deles será mais rápido independente da velocidade do computador no qual eles forem executados. A complexidade assintótica poderá ser computada pela quantidade de operações de modificação de dados ou comparações executados pelos algoritmos.

Uma cota assintótica superior é uma função que aumenta mais do que outra função, por exemplo: se tivermos uma linear e uma exponencial, a função exponencial cresce mais rápido que a função linear, então a função exponencial é assintótica superior em relação à função linear. Estas variações assintóticas podem ser definidas pela notações O, Ômega e Theta. Na notação O define-se uma cota assintótica superior, a notação ômega define uma cota assintótica inferior e a notação Theta define limites assintóticos exatos, ou seja, estes métodos assintóticos descrevem o comportamentos de limites das funções.

1.3 Notação Big O

A notação O é usada para os tipos de comportamentos dos algoritmos ao analisar o tempo de trabalho em função da entrada, estes tipos de comportamentos são as classes assintóticas. Estas classes não tratam da quantidade de operações, elas abordam o que é esperado nas variações das entradas. Estas classes são representadas pela notação O.

A notação O é usada nas classes assintóticas a seguir:

1. Constante O(1) 2. Logarítmica O(lg(n)) 3. Linear O(n)

4. Logaritmo linear O(n lg(n)) 5. Quadrática O(n2)

6. Cúbica: O(n3)

7. Exponencial: O(constanten)

Para determinação da classe assintótica de um determinado algoritmos usamos as seguintes regras e diretivas:

• Regra 1: constantes somadas ou multiplicadas na expressão matemática são consideradas; • Regra 2: "Se a expressão que determina o tempo de resposta incluir termos de classes diferentes,

vale a apenas o maior termo"[1].

(3)

• Diretiva A: Comandos de atribuição, I/O, chamada de módulos, testes condicionantes são O(1) • Diretiva B: Nos casos de blocos de comandos em laços de repetição ou decisão são usados 3

possibilidades de análise: pior caso, caso médio e melhor caso.

• Diretiva C: As operações internas em um bloco são contadas via somatório, blocos aninhados são contados como a somatória da somatória.

As regras e diretrizes ajudam a contar e escolher as classes assintóticas.

1.4 Classes de função

As classes de função são detalhadas a seguir [2]: 1. Constante O(1)

2. Logarítmica O(lg(n)) 3. Linear O(n)

4. Logaritmo linear O(n lg(n)) 5. Quadrática O(n2)

6.Cbica : O(n3)

7.Exponencial : O(constanten)

Nestas classe,s os algoritmos com entradas pequenas, tem tendências a serem mais rápidos, a entrada maior aumenta o tempo de execução.

Percebe-se que o comportamento polinomial é diferente do exponencial. Estes gráficos mostram que algoritmos polinomiais tem tempos de resolução computacional aceitável, já os polinomiais seu tempo computacional não é aceitável.

Note que outras considerações devem ser feitas além da análise assintótica, em algumas situações um algoritmo com um comportamento assintótico ruim pode ser preferível, por exemplo: a) existe com-plexidade na implementação b) algoritmos com entradas pequenas c) nas situações em que comparamos o pior caso x performance de execução.

A seguir as ordens de crescimento da complexidade e um breve representação gráfica: 1. Constante. −10 −5 0 5 10 4.5 5 5.5 6 x f (x ) 5

(4)

2. Logaritmica. 2 4 6 8 10 −2 −1 0 1 2 x f (x ) ln x 3. Linear. −10 −5 0 5 10 −10 −5 0 5 10 x f (x ) x 4. Logaritmo linear. 2 4 6 8 10 0 5 10 15 20 x f (x ) x * ln x

(5)

5. Quadrático. −10 −5 0 5 10 0 50 100 150 200 x f (x ) 2*x2 6. Cúbica. −10 −5 0 5 10 −1,000 −500 0 500 1,000 x f (x ) x5 7. Exponencial. −10 −5 0 5 10 0 2 4 6 8 ·106 x f (x ) 5x

(6)

2

Disserte sobre técnicas de projeto de algoritmos.

Observação: Sua resposta deve abordar as seguintes técnicas: Algoritmos gulosos, divisão e con-quista, e programação dinâmica. A resposta deve deixar clara a diferença entre estas técnicas, bem como as situações que cada uma delas é mais indicada em relação as demais. Além disso, para cada técnica, explique sua ideia geral, discuta sua importância para a computação, apresente suas carac-terísticas principais, e comente as formas de se analisar algoritmos utilizando esta tecnicas. Ao final, para cada técnica, cite exemplos de algoritmos que utilizam estas técnicas e que estejam alinhados com o tema da sua pesquisa.

2.1 Algoritmos gulosos.

Geralmente são aplicados a problemas de otimização, não garantem uma solução ótima. Tentam encontrar um ponto ótimo global após uma série de passos. Em cada etapa após selecionar um elemento, deve-se decidir se ele é viável para fazer parte da solução ou ser descartado. Durante estas decisões nenhum elemento deve ser analisado mais de uma vez.

Exemplo de algoritmo guloso[3]:

1 funcao metodoGuloso(d:D) -->r // funo metodo gulos 2 q ( sada r:R resposta tima para entrada d:D

3 sort auxiliar: E (elementos), P (partes da entrada), S(partes da sada); 4 var: p:P; // parte da entrada

5 s:S; // parte da sada

6 s:E; // parte da entrada

7 p <-- inicializaP(d); // inicializa parte da entrada a examinar 8 s <-- inicializaS(d); // inicializa resposta parcial

9 repetir

10 e <-- selecaoE(p,s); // seleciona o elemento 11 p <-- marcaP(e,p); // marca como selecionado 12 se e vivel e ento s <-- incluirS(e,s) 13 at -que p imprime s;

14 e <-- recupera(s); // recupera a sada da resposta pronta 15 retorna-saida(r);

16 fim-metodoGuloso;

São alguns exemplos de algoritmos gulosos: a) problema de seleção ativa, b) problema de sequen-ciamento de jobs, c) codificação huffman, d) em grafos: Árvore de abrangência mínima de Kruskal, Árvore de abrangência mínima de Prims, Árvore de abrangência mínima de Boruvka, Algoritmo de exclusão reversa para árvore de abrangência mínima, Algoritmo de caminho mais curto de Dijkastra, Custo mínimo para conectar todas os pontos, entre outros; e) inclusive para para o tratamento de pro-blemas NP-completos (1. Defina o problema da tampa, 2. Problema na embalagem do compartimento, 3. Colorir Gráfico, 4. Problema dos centros K, 5. Menor problema com as supercordas, 6. Problema do caixeiro viajante).

Exemplo de implementação em C sharp[4]:

1 using System;

2 using System.Text;

3 using System.Security.Cryptography;

4 // usa a nomenclatura de moedas americanas 5 public class classeTroco

6 {

(7)

8 qtdeRemanescente, int[] moedas) 9 { 10 if ((qtdeInicial % 0.25) < qtdeInicial) 11 { 12 moedas[3] = (int)(qtdeInicial / 0.25); 13 qtdeRemanescente = qtdeInicial % 0.25; 14 qtdeInicial = qtdeRemanescente; 15 } 16 if ((qtdeInicial % 0.1) < qtdeInicial) 17 { 18 moedas[2] = (int)(qtdeInicial / 0.1); 19 qtdeRemanescente = qtdeInicial % 0.1; 20 qtdeInicial = qtdeRemanescente; 21 } 22 if ((qtdeInicial % 0.05) < qtdeInicial) 23 { 24 moedas[1] = (int)(qtdeInicial / 0.05); 25 qtdeRemanescente = qtdeInicial % 0.05; 26 qtdeInicial = qtdeRemanescente; 27 } 28 if ((qtdeInicial % 0.01) < qtdeInicial) 29 { 30 moedas[0] = (int)(qtdeInicial / 0.01); 31 qtdeRemanescente = qtdeInicial % 0.01; 32 } 33 }

34 static void mostraTroco(int[] arr) 35 {

36 if (arr[3] > 0)

37 Console.WriteLine("Numero de quarters: " +

38 arr[3]);

39 if (arr[2] > 0)

40 Console.WriteLine("Numero de dimes: " + arr[2]); 41 if (arr[1] > 0)

42 Console.WriteLine("Numero de nickels: " + arr[1]); 43 if (arr[0] > 0)

44 Console.WriteLine("Numero de pennies: " + arr[0]); 45 }

46 static void Main() 47 {

48 Console.WriteLine("digite a quantidade de troco desejado:"); 49 double qtdeInicial = Convert.ToDouble(Console.ReadLine());

50 double paraTrocar = qtdeInicial;

51 double qtdeRemanescente = 0.0; 52 int[] moedas = new int[4];

53 fazTroco(qtdeInicial, qtdeRemanescente, moedas); 54 Console.WriteLine("Melhor forma: " +

55 paraTrocar + " centavos: ");

56 mostraTroco(moedas);

57 } 58 }

2.2 Algoritmos de divisão e conquista

Os problemas são resolvidos via decomposição e recombinação. As aplicabilidades na área da computação são: classificação por seleção, intercalação, multiplicação de matrizes, particionamento, seleção, etc. Uma vez que o problema foi quebrado em partes menores, estas partes devem ser

(8)

resolvi-das, as soluções obtidas são combinadas na solução do problema. É um processo recursivo.

Exemplo de algoritmo de divisão e conquista[3]:

1 funcao DivConquista(d:D)->R

2 // entrada-saida: q(a saida i resposta aceitavel para a entrada 3 var /*auxiliares*/ d1,...dm: D; /*pares*/

4 r1,...,rm:R; /*combinacoes*/

5 se simples(d) // verifica se a entrada e simples

6 entao retorne-saida(drt(d)) // se entrada simples entao sada direta 7 seno // a entrada nao e simples, vai para recursao

8 d1 <-- part1(d);...;dm <-- partm(d); // decomposiao

9 r1 <-- DivConquista(d1);...;rm<---DivConquista(d2); // atribuicao da decomposicao 10 retorne-saida(drt(d)) //fornece a saida combinada

11 fim-senao // fim da recursao 12 fim-se; // fim para a entrada simples 13 fim-DivConquista // fim da funcao

São exemplos de algoritmos de divisão e conquista: a) Pesquisa binária, b) Quicksort, c) Mesclar Classificação, d) Par de pontos mais próximo, e) Algoritmo de Strassen, f) Transformação rápida de Fourier de Cooley – Tukey (FFT) e, g) Algoritmo Karatsuba para multiplicação rápida.

As principais vantagens são a possibilidade de tratar problemas complexos, ao dividir problemas pode-se aplicar paralelismo distribuindo as tarefas de processamento em vários nós.

Exemplo de implementação de merge sort em C Sharp [5]:

1 int[] arr = new int[10] 2 { 3 1, 5, 4, 11, 20, 8, 2, 98, 90, 16 4 }; 5 6 MergeSort(arr, 0, arr.Length - 1); 7 Console.WriteLine("Sorted Values:"); 8 for (int i = 0; i < arr.Length; i++) 9 Console.WriteLine(arr[i]); 10

11 private void Merge(int[] input, int left, int middle, int right) 12 {

13 int[] leftArray = new int[middle - left + 1]; 14 int[] rightArray = new int[right - middle];

15

16 Array.Copy(input, left, leftArray, 0, middle - left + 1); 17 Array.Copy(input, middle + 1, rightArray, 0, right - middle); 18

19 int i = 0; 20 int j = 0;

21 for (int k = left; k < right + 1; k++) 22 { 23 if (i == leftArray.Length) 24 { 25 input[k] = rightArray[j]; 26 j++; 27 }

(9)

28 else if (j == rightArray.Length)

29 {

30 input[k] = leftArray[i];

31 i++;

32 }

33 else if (leftArray[i] <= rightArray[j])

34 { 35 input[k] = leftArray[i]; 36 i++; 37 } 38 else 39 { 40 input[k] = rightArray[j]; 41 j++; 42 } 43 } 44 } 45

46 private void MergeSort(int[] input, int left, int right) 47 {

48 if (left < right) 49 {

50 int middle = (left + right) / 2; 51

52 MergeSort(input, left, middle); 53 MergeSort(input, middle + 1, right); 54

55 Merge(input, left, middle, right);

56 } 57 }

2.3 Algoritmos de programação dinâmica

É iterativa/recursiva. É aplicada em problemas de otimização. Ela divide o problema em par-tes (mini problemas), soluciona os mini problemas, guarda os resultados de cada um, posteriormente combina estes mini resultados até resolver o problema maior original. O problema original é quebrado apenas um vez. Neste algoritmos todos os problemas menores devem ser testados para se descobrir qual é o melhor, pois só soluções boas são consideradas, as soluções não consideradas boas são descartadas, desta forma o algoritmo é considerado eficiente. Para cada sub problema já resolvido, seu resultado pode ser recuperado posteriormente se desejado.

Exemplo de programação dinâmica [3]:

1 funcao progdin(d:D) --. R // programacao dinamica

2 // entrada q (saida r:R resposta otima para entrada d:D) 3 // sort auxiliar parte p(de entrada) e s(saida)

4 var p:P; // partes de entradas 5 s:S; // partes de saidas

6 p <-- decompor(d); // decompor entradas

7 s <-- incluir_m(p); // inicializa com saida para partes mnimas 8 enquanto p falta s faa

9 (p) <-- (combinar) [p]; // combinar 10 (s) <-- (atualizar) [s]; // atualizar 11 fim-enquanto;

(10)

13 retorno-saida(r); // fornece a saida extraida 14 fim-progdin; // fim da funcao

Exemplos de uso: encontrar o caminho mais curto em um grafo direcionado, problemas de partici-onamento, vertex cover, roteamento em redes, problemas de estrutura ótima, problemas de estruturas sobrepostas, sequência de números fibonacci, números Bell (quantidades de vezes que é possível parti-cionar um conjunto), etc.

Algoritmos bem conhecidos que usam programação dinâmica: Bellman-Ford caminho mais curto, unix diff, tex.

Exemplo de implementação em C [6]: Para um conjunto (set) de números inteiros e o valor de uma soma (sum) destes números, determine se existe um subconjunto a partir do conjunto especificado cuja soma seja igual à soma especificada.

1 using System; 2 class exemplo {

3 static bool subConjunto(int[] set, int n, int sum)

4 {

5 bool[, ] subset = new bool[sum + 1, n + 1]; 6 for (int i = 0; i <= n; i++)

7 subset[0, i] = true;

8 for (int i = 1; i <= sum; i++)

9 subset[i, 0] = false;

10 for (int i = 1; i <= sum; i++) { 11 for (int j = 1; j <= n; j++) {

12 subset[i, j] = subset[i, j - 1];

13 if (i >= set[j - 1])

14 subset[i, j] = subset[i, j] || subset[i - set[j - 1], j - 1];

15 }

16 }

17 return subset[sum, n]; 18 }

19 public static void Main() 20 {

21 int[] set = { 3, 34, 4, 12, 5, 2 };

22 int sum = 9;

23 int n = set.Length;

24 if (subConjunto(set, n, sum) == true)

25 Console.WriteLine("encontrou um sub conjunto"); 26 else

27 Console.WriteLine("Nao encontrou um sub conjunto"); 28 }

(11)

3

Algoritmos alinhados com o tema de pesquisa

3.1 Eduardo Ormond:

O Interesse pelo tema 5G é devido a sua importância na atualidade e em como o celular vem mudando o cotidiano das pessoas através da internet. Partindo desse ponto, pode-se dizer que projeto consiste no entendimento dos conceitos relacionados ao 5G e a evolução bem como suas consequências no mundo atual. A expectativa é que o 5G possa, finalmente, concretizar conceitos como Internet das Coisas e Inteligência Artificial, promovendo uma verdadeira transformação na forma como as pessoas e organizações se relacionam na sociedade.

As contribuições esperadas a área de pesquisa em redes 5G:

• a) suporte ao desenvolvimento de novos algoritmos de escalonamento da camada de enlace, com base nas informações do sensoriamento colaborativo;

• b) suporte ao desenvolvimento de novas técnicas para caracterização do padrão ao de acesso ao canal a fim de permitir a utilização oportunística do canal sem causar prejuízos a transmissão primária;

• c) facilitar um ambiente para o desenvolvimento de algoritmos de detecção de espectro ideal em conjunto com estratégias de alocação ao de espectro e mecanismos de acesso ao espectro que atendam aos diferentes requisitos dos quatro cenários de aplicação das redes 5G.

3.2 Emiliano S. Monteiro:

Relação dos conteúdos alinhados com o tema de pesquisa tema "MODELO QUE COMBINA INTERNET DAS COISAS E BANCO DE DADOS DISTRIBUÍDO PARA MANTER E RASTREAR PRODUTOS CONTROLADOS E PERIGOSOS AO LONGO DA CADEIA DE DISTRIBUIÇÃO DO AGROTÓXICO", creio que poderão ser utilizados algoritmos nas seguintes situações:

a) na classificação e ordenamento de dados, pretende-se coletar dados sobre trânsito de produtos, registro e acompanhamento dos mesmos no órgãos de controle.

b) será necessário montar mais de uma blockchain para testar as alternativas viáveis ou construir uma do zero, de qualquer forma, poderão ser necessários algoritmos para avaliar a performance das operações realizadas na blockchain.

c) a movimentação de produtos poderá gerar caminhos pelo canal de distribuição de produtos controlados, portanto alguma forma de algoritmos envolvendo grafos e busca nos mesmo deverá ser necessária.

No momento, os ítens acima são uma previsão do que poderá ser utilizado a partir do próximo ano, de acordo com o cronograma do projeto de pesquisa, será nesse momento em que serão realizadas implementações e testes.

(12)

4

Referencias consultadas:

[1] FERTIG, Cristina. MEDINA, Marco. Algoritmos e programação - teoria e prática. 2a ed. São Paulo : Novatec Editora, 2006.

[2] DOMINGOS, Danilo de Oliveira. Estudando complexidade de algoritmos. Disponível em: http://dandomin.com.br/lib/Complexidadealgoritmos.pdf.Acessoem : 21maro2020.

[3] TOSCANI, Laira Vieira. VELOSO, Paulo A. S. Complexidade de algoritmos. Porto alegre: Instituto de informática da UFRGS. Série livros didáticos No13. Sagra Luzzatto. 2001.

[4] C# – Coin change problem : Greedy algorithm. csharp.com. 2017. Disponível em:

https://www.csharpstar.com/csharp-coin-change-problem-greedy-algorithm/. Acesso em: 21 março 2020.

[5] Merge Sort In C#. c-sharpcorner.com. 2020. Disponível em:

https://www.c-sharpcorner.com/blogs/a-simple-merge-sort-implementation-c-sharp. Acesso em: 22 março 2020.

[6] C# Program for Subset Sum Problem | DP-25. geeksforgeeks.org. 2020. Disponível em: https://www.geeksforgeeks.org/csharp-program-for-subset-sum-problem-dp-25/?ref=rp Acesso em: 20 março 2020.

Referências

Documentos relacionados

Figura A53 - Produção e consumo de resinas termoplásticas 2000 - 2009 Fonte: Perfil da Indústria de Transformação de Material Plástico - Edição de 2009.. A Figura A54 exibe

A participação foi observada durante todas as fases do roadmap (Alinhamento, Prova de Conceito, Piloto e Expansão), promovendo a utilização do sistema implementado e a

Ainda segundo Gil (2002), como a revisão bibliográfica esclarece os pressupostos teóricos que dão fundamentação à pesquisa e às contribuições oferecidas por

Local de realização da avaliação: Centro de Aperfeiçoamento dos Profissionais da Educação - EAPE , endereço : SGAS 907 - Brasília/DF. Estamos à disposição

Note on the occurrence of the crebeater seal, Lobodon carcinophagus (Hombron &amp; Jacquinot, 1842) (Mammalia: Pinnipedia), in Rio de Janeiro State, Brazil.. On May 12, 2003,

Desta maneira, observando a figura 2A e 2C para os genótipos 6 e 8, nota-se que os valores de captura da energia luminosa (TRo/RC) são maiores que o de absorção (ABS/RC) e

[r]

Os autores relatam a primeira ocorrência de Lymnaea columella (Say, 1817) no Estado de Goiás, ressaltando a importância da espécie como hospedeiro intermediário de vários parasitos