Fernando Lobo. Algoritmos e Estrutura de Dados. Outra técnica de concepção de algoritmos, tal como Divisão e Conquista.
|
|
- Maria de Lourdes Azenha Filipe
- 6 Há anos
- Visualizações:
Transcrição
1 Programação Dinâmica Fernando Lobo Algoritmos e Estrutura de Dados 1 / 56 Programação Dinâmica Outra técnica de concepção de algoritmos, tal como Divisão e Conquista. O termo Programação Dinâmica é um bocado infeliz. Programação sugere programação de computadores. Dinâmica sugere valores que mudam ao longo do tempo. A técnica de Programação Dinâmica não tem que ver com uma coisa nem outra. 2 / 56
2 O que é então a Programação Dinâmica? É uma técnica de resolução de problemas. A ideia é resolver subproblemas pequenos e armazenar os resultados. Esses resultados são depois utilizados para resolver subproblemas maiores (e armazenando novamente os resultados). E assim sucessivamente até se resolver o problema completo. 3 / 56 Comparação com Divisão e Conquista Semelhanças Para resolver um problema combinamos as soluções de subproblemas. Diferenças Divisão e Conquista é eficiente quando os subproblemas são todos distintos. Se tivermos que resolver várias vezes o mesmo subproblema, a Divisão e Conquista torna-se ineficiente. Com Programação Dinâmica cada subproblema é resolvido apenas uma vez. 4 / 56
3 Exemplos de Programação Dinâmica A melhor maneira de aprender Programação Dinâmica é ver alguns exemplos. Exemplo simples: Calcular o n-ésimo número da sequência de Fibonacci. F n = 0, se n = 0 1, se n = 1 F n 1 + F n 2, se n > 1 5 / 56 Pseudocódigo Fib-Rec(n) if n == 0 return 0 if n == 1 return 1 return Fib-Rec(n 1) + Fib-Rec(n 2) Este algoritmo é muito mau. Porquê? 6 / 56
4 Vejamos o que acontece com n = 5 7 / 56 Fibonacci: Algoritmo de Divisão e Conquista Estamos a calcular a mesma coisa várias vezes! Pode-se provar que F n+1 /F n = F n > 1.6 n Qual a complexidade do algoritmo? Fn resulta da soma das folhas da árvores. Fn > 1.6 n = árvore tem pelo menos 1.6 n folhas. Logo, o algoritmo tem complexidade Ω(1.6 n ), o que é muito mau. Experimentem programá-lo e usar n = / 56
5 Fibonacci: Algoritmo de Divisão e Conquista No exemplo com n = 5, calculamos: F 4 1 vez F3 2 vezes F2 3 vezes F 1 5 vezes F0 3 vezes É trabalho desnecessário. Só deveríamos calcular cada F i uma e uma só vez. Podemos fazê-lo usando Programação Dinâmica. 9 / 56 Fibonacci: Algoritmo de Programação Dinâmica A ideia é resolver o problema de baixo para cima, começando pelos casos base e armazenando as soluções dos subproblemas. Fib-PD(n) F [0] = 0 F [1] = 1 for i = 2 to n F [i] = F [i 1] + F [i 2] return F [n] Complexidade temporal? Θ(n). Complexidade espacial? Θ(n). 10 / 56
6 Fibonacci: Algoritmo de Programação Dinâmica Para calcular F i basta ter armazenado as soluções dos dois subproblemas F i 1 e F i 2. Logo, podemos reduzir a complexidade espacial de Θ(n) para Θ(1). Fib-PD-v2(n) if n == 0 return 0 if n == 1 return 1 back2 = 0 back1 = 1 for i = 2 to n next = back1 + back2 back2 = back1 back1 = next return next 11 / 56 Outro exemplo: Coeficientes binomiais Ck n = ( ) n k = n! k!(n k)! ( n ) k é o número de combinações de n elementos k a k. Por palavras mais simples: número de maneiras distintas de escolher grupos de k elementos a partir de um conjunto de n elementos. Exemplo: Dado um conjunto de 10 alunos, quantos grupos distintos de 3 alunos se podem fazer? Resp: ( ) 10 3 = 10! 3!7! = 120 A aplicação directa da fórmula pode facilmente dar um overflow aritmético por causa dos factoriais, mesmo que o resultado final caiba perfeitamente num inteiro. 12 / 56
7 Coeficientes binomiais (cont.) Podemos definir ( n k) de modo recursivo. ( n ( k) = n 1 ) ( k 1 + n 1 ) k 1 a parcela: k-ésimo elemento pertence ao grupo é necessário escolher k 1 dos restantes n 1 elementos. 2 a parcela: k-ésimo elemento não pertence ao grupo é necessário escolher k dos restantes n 1 elementos. Casos base: k = 0, n = k ( n k) = 1 13 / 56 Algoritmo naive (de força bruta) Comb(n, k) if k == 0 or n == k return 1 else return Comb(n 1, k 1) + Comb(n 1, k) 14 / 56
8 Solução com Programação Dinâmica Comb-PD(n, k) for i = 0 to n for j = 0 to min(i, k) if j == 0 or j == i A[i, j] = 1 else A[i, j] = A[i 1, j 1] + A[i 1, j] return A[n, k] 15 / 56 Exemplo de execução: Comb-PD(5,3) i j / 56
9 Memoization É uma técnica semelhante à Programação Dinâmica. Mantém o algoritmo recursivo na forma top-down. A ideia é inicializar as soluções dos subproblemas com o valor Desconhecido. Depois, quando queremos resolver um subproblema, verificamos primeiro se já foi resolvido. Se sim, retornamos a solução previamente armazenada. Se não, resolvemos o subproblema e armazenamos a solução. Cada subproblema só é resolvido uma vez. 17 / 56 Versão memoized de Comb Comb-Memoized(n, k) for i = 0 to n for j = 0 to min(i, k) C[i, j] = unknown return M-Comb(n, k) M-Comb(i, j) if C[i, j] == unknown if j == 0 or j == i C[i, j] = 1 else C[i, j] = M-Comb(i 1, j 1) + M-Comb(i 1, j) return C[i, j] 18 / 56
10 Outro exemplo: cortar tubos (rod cutting) Problema: Dado um tubo de comprimento n e uma tabela com preços p i para pedaços de tubo de comprimento i (i = 1, 2,.. n), determinar o valor máximo de receita r n que se pode obter se podermos cortar o tubo em pedaços e vendê-los separadamente, assumindo que os cortes são gratuitos e os comprimentos dos pedaços de tubo são números inteiros. Exemplo: n = 4 length i price p i / 56 8 maneiras de cortar 20 / 56
11 Melhor solução: cortar em 2 pedaços de comprimento 2. Receita total é = 10. Para cada i = 1.. n 1, cortamos ou não cortamos = 2 n 1 maneiras de cortar o tubo. 21 / 56 Sub-estrutura óptima Vamos tentar definir a solução óptima em termos de soluções óptimas de subproblemas. Seja r i a receita máxima para um tubo de comprimento i. Então r n será o máximo de: p n r 1 + r n 1 r2 + r n 2... rn 1 + r 1 22 / 56
12 Uma decomposição mais simples Toda a solução óptima tem um pedaço mais à esq. (potencialmente de comprimento n no caso de não haver qualquer corte). A receita total vai ser o custo desse pedaço mais o custo da melhor receita que se consegue obter com cortes no pedaço de tubo que sobrar. r n é o máximo de: p 1 + r n 1 p 2 + r n 2... pn + r 0 23 / 56 Pseudocódigo Cut-Rod(p, n) if n == 0 return 0 q = for i = 1 to n q = max(q, p[i] + Cut-Rod(p, n i)) return q É muito ineficiente, tal como nos algoritmos de força-bruta para os números de Fibonacci e para as Combinações. 24 / 56
13 Árvore de chamadas recursivas de Cut-Rod com n = 4 Calcula o mesmo subproblema vezes sem fim. Complexidade: Θ(2 n ). 25 / 56 Abordagem com programação dinâmica Resolver cada subproblema apenas uma vez, e armazenar o resultado para uso futuro. Fazer uma abordagem bottom-up: resolver primeiro os subproblemas mais pequenos. Quando necessitamos de resolver um subproblema maior, usamos os resultados (já calculados) dos subproblemas mais pequenos. 26 / 56
14 Algoritmo de programação dinâmica Bottom-Up-Cut-Rod(p, n) Let r[0.. n] be a new array r[0] = 0 for j = 1 to n q = for i = 1 to j q = max(q, p[i] + r[j i]) r[j] = q return r[n] 27 / / 56
15 Complexidade temporal Dois ciclos encadeados que dependem linearmente de n, e tempo constante em cada iteração. Complexidade temporal é Θ(n 2 ). Passamos de tempo exponencial para tempo polinomial. 29 / 56 Reconstrução da solução O algoritmo retorna o valor da solução óptima, mas não a solução. Podemos obter a solução com a seguinte modificação: s[i] guarda o tamanho do pedaço de tubo mais à esquerda da solução óptima de um problema rod-cut de comprimento i. Extended-Bottom-Up-Cut-Rod(p, n) Let r[0.. n] and s[0.. n] be new arrays r[0] = s[0] = 0 for j = 1 to n q = for i = 1 to j if p[i] + r[j i] > q q = p[i] + r[j i] s[j] = i r[j] = q return r and s 30 / 56
16 Reconstrução da solução i r[i] s[i] Print-Cut-Rod-Solution(p, n) (r, s) = Extended-Bottom-Up-Cut-Rod(p, n) while n > 0 print s[n] n = n s[n] 31 / 56 Memoization Uma técnica semelhante à Programação Dinâmica. Mantém o algoritmo na forma recursiva (top-down). A ideia é usar uma flag para indicar se um subproblema já está resolvido. Depois, para resolver um subproblema temos de primeiro verificar se já foi resolvido. Se sim, basta retornar a solução previamente armazenada. Se não, resolvemos o subproblema e guardamos a solução para uso futuro. Cada subproblema só é resolvido uma vez. 32 / 56
17 Verão memoized de Cut-Rod Memoized-Cut-Rod(p, n) Let r[0.. n] be a new array for i = 0 to n r[i] = return Memoized-Cut-Rod-Aux(p, n, r) Memoized-Cut-Rod-Aux(p, n, r) if r[n] 0 return r[n] if n == 0 q = 0 else q = for i = 1 to n q = max(q, p[i] + Memoized-Cut-Rod-Aux(p, n i, r)) r[n] = q return q 33 / 56 Complexidade temporal Cada subproblema só é resolvido uma vez. Os subproblems têm tamanho 0, 1,..., n, e requerem um ciclo for sobre o seu tamanho Complexidade também é Θ(n 2 ). 34 / 56
18 Outro exemplo: Longest Common Subsequence (LCS) Dadas duas sequências, X = x 1 x 2... x m e Y = y 1 y 2... y n, encontrar uma subsequência comum a X e Y que seja o mais longa possível. Exemplo: X = n o c t u r n o Y = m o s q u i t e i r o LCS(X, Y ) = o t r o (também podia ser o u r o) 35 / 56 Algoritmo de força bruta Gerar todas as subsequências de X e verificar se também é subsequência de Y, e ir guardando a subsequência mais longa vista até ao momento. Complexidade? Θ(2 m ) para gerar todas as subsequências de X. Θ(n) para verificar se uma subsequência de X é subsequência de Y. Total: Θ(n 2 m ) É exponencial. Muito mau! 36 / 56
19 Será que podemos aplicar Programação Dinâmica? Se sim teremos de conseguir definir o problema recursivamente em termos de subproblemas. O n o de subproblemas tem de ser relativamente pequeno (polinomial em n e m) para que a Programação Dinâmica seja útil. Depois de definir o problema em termos de subproblemas, podemos resolver o problema de baixo para cima, começando pelos casos base e armazenando as soluções dos subproblemas. 37 / 56 Subestrutura óptima Vamos olhar para prefixos de X e Y. Seja X i o prefixo dos i primeiros elementos de X. Exemplo: X = n o c t u r n o X 4 = n o c t X0 = X3 = n o c X 8 = n o c t u r n o 38 / 56
20 Subestrutura óptima Seja X = x 1 x 2... x m e Y = y 1 y 2... y n. Seja Z = z 1 z 2... z k uma LCS entre X e Y. Três casos: 1 Se x m = y n, então z k = x m = y n e Z k 1 é uma LCS entre X m 1 e Y n 1. 2 Se x m y n e z k x m, então Z é uma LCS entre X m 1 e Y n. 3 Se x m y n e z k y n, então Z é uma LCS entre X m e Y n / 56 Demonstração do caso 1 Caso 1: Se x m = y n, então z k = x m = y n e Z k 1 é uma LCS entre X m 1 e Y n 1. Teremos de provar que z k = x m = y n. Suponhamos que tal não é verdade. Então a subsequência Z = z 1 z 2... z k x m é uma subsequência comum a X e Y e tem comprimento k + 1. Contradiz o facto de Z ser uma LCS entre X e Y. 40 / 56
21 Demonstração do caso 1 (cont.) Agora temos de provar que Z k 1 é uma LCS entre X m 1 e Y n 1. Suponhamos que existe uma subsequência W comum a X m 1 e Y n 1 que é mais longa que Z k 1. comprimento de W k. A subsequência W = W x m é comum a X e Y e tem comprimento k + 1. Contradiz o facto de Z ser uma LCS entre X e Y. 41 / 56 Demonstração dos casos 2 e 3 Caso 2: Se x m y n e z k x m, então Z é uma LCS entre X m 1 e Y n. Suponhamos que existe uma subsequência W comum a X m 1 e Y n com comprimento > k. Então W é uma subsequência comum entre X e Y. = Contradiz o facto de Z ser uma LCS entre X e Y. Caso 3: Se x m y n e z k y n, então Z é uma LCS entre X m e Y n 1. A demonstração do caso 3 é análoga à do caso / 56
22 Resumindo Podemos definir LCS(X m, Y n ) em termos de subproblemas., se m = 0 ou n = 0 LCS(X m, Y n ) = LCS(X m 1, Y n 1 ) x m, se x m = y n LCS(X m 1, Y n ) ou LCS(X m, Y n 1 ), se x m y n 43 / 56 Comprimento de LCS(X, Y ) Vamos tentar primeiro resolver um problema mais simples: Obter LCS(X, Y ) o comprimento de LCS(X, Y ) Seja c[i, j] = LCS(X i, Y j ) Queremos obter c[m, n] 44 / 56
23 Definição recursiva de c[i, j] c[i, j] = 0, se i = 0 ou j = 0 c[i 1, j 1] + 1, se i, j > 0 e x i = y j max(c[i 1, j], c[i, j 1]), se i, j > 0 e x i y j 45 / 56 Algortimo recursivo LCS-Length-Rec(X, Y, i, j) if i == 0 or j == 0 return 0 elseif X [i] == Y [j] return LCS-Length-Rec(X, Y, i 1, j 1) + 1 else a = LCS-Length-Rec(X, Y, i 1, j) b = LCS-Length-Rec(X, Y, i, j 1) return max(a, b) Chamada inicial: LCS-Length-Rec(X, Y, m, n) Tal como em Fib-Rec e Comb-Rec, a árvore dá origem a muitos subproblemas repetidos. O algoritmo é exponencial. Mas o número de subproblemas distintos = m n. 46 / 56
24 Podemos usar Programação Dinâmica LCS-Length-DP(X, Y ) m = X.length n = Y.length for i = 1 to m c[i, 0] = 0 for j = 0 to n c[0, j] = 0 for i = 1 to m for j = 1 to n if X [i] == Y [j] c[i, j] = c[i 1, j 1] + 1 elseif c[i 1, j] c[i, j 1] c[i, j] = c[i 1, j] else c[i, j] = c[i, j 1] return c[m, n] 47 / 56 Demo c[i, j] é preenchida linha a linha, da esquerda para a direita. 48 / 56
25 Como obter a LCS própriamente dita? O nosso algoritmo apenas obteve o comprimento da LCS. A ideia é alterar o código de LCS-Length-DP e, de cada vez que obtemos um c[i, j], registamos como é que ele foi obtido. Isso permite-nos reconstruir a solução. 49 / 56 Aqui vai o código alterado LCS-Length-DP-v2(X, Y ). for i = 1 to m for j = 1 to n if X [i] == Y [j] c[i, j] = c[i 1, j 1] + 1 b[i, j] = elseif c[i 1, j] c[i, j 1] c[i, j] = c[i 1, j] b[i, j] = else c[i, j] = c[i, j 1] b[i, j] = return c[m, n], b 50 / 56
26 Demo As setas, e são armazenadas em b[i, j]. b[i, j] indica o subproblema escolhido para obter c[i, j]. 51 / 56 Uma vez tendo a informação em b, podemos obter uma LCS entre X e Y. A chamada inicial é Print-LCS(b, X, m, n) Print-LCS(b, X, i, j) if i == 0 or j == 0 return // Não faz nada if b[i, j] == Print-LCS(b, X, i 1, j 1) print X [i] elseif b[i, j] == Print-LCS(b, X, i 1, j) else Print-LCS(b, X, i, j 1) 52 / 56
27 Complexidade A complexidade é Θ(m n) A Programação Dinâmica reduziu a complexidade de exponencial para polinomial. No livro têm mais exemplos de problemas resolvidos com Programação Dinâmica. 53 / 56 Versão memoized de LCS-Length LCS-Length-Memoized(X, Y ) m = X.length n = Y.length for i = 0 to m for j = 0 to n c[i, j] = unknown return M-LCS-Length(X, Y, m, n) 54 / 56
28 M-LCS-Length(X, Y, i, j) if c[i, j] == unknown if i == 0 or j == 0 c[i, j] = 0 elseif X [i] == Y [j] c[i, j] = M-LCS-Length(X, Y, i 1, j 1) + 1 else a = M-LCS-Length(X, Y, i 1, j) b = M-LCS-Length(X, Y, i, j 1) c[i, j] = max(a, b) return c[i, j] 55 / 56 Como aplicar a Programação Dinâmica? Para aplicarmos Programação Dinâmica ou Memoization para resolver um problema, temos de fazer 4 coisas: 1 Caracterizar a estrutura de uma solução óptima. 2 Definir o valor da solução óptima recursivamente em termos de subsoluções óptimas. 3 Calcular o valor de uma solução óptima de baixo para cima (no caso de P.D.) ou de cima para baixo (no caso de Memoization). 4 Obter a solução óptima através da informação calculada e armazenada no passo / 56
Comparação com Divisão e Conquista
Programação Dinâmica Programação Dinâmica Fernando Lobo Algoritmos e Estrutura de Dados II Outra técnica de concepção de algoritmos, tal como Divisão e Conquista ou Estratégias Greedy. O termo Programação
Leia maisO termo Programação Dinâmica é um bocado infeliz.
Programação Dinâmica Fernando Lobo Algoritmos e Estrutura de Dados II 1 / 18 Programação Dinâmica Outra técnica de concepção de algoritmos, tal como Divisão e Conquista ou Estratégias Greedy. O termo Programação
Leia maisSubsequência comum mais longa Em inglês, Longest Common Subsequence (LCS)
Programação Dinâmica Subsequência comum mais longa Em inglês, Longest Common Subsequence (LCS) Fernando Lobo Algoritmos e Estrutura de Dados II 1 / 23 Longest Common Subsequence (LCS) Dadas duas sequências,
Leia maisAnálise e Síntese de Algoritmos. Programação Dinâmica CLRS, Cap. 15
Análise e Síntese de Algoritmos Programação Dinâmica CLRS, Cap. 15 Contexto Revisões [CLRS, Cap. 1-10] Algoritmos em Grafos [CLRS, Cap. 22-26] Algoritmos elementares Árvores abrangentes Caminhos mais curtos
Leia maisPROGRAMAÇÃO DINÂMICA
PROGRAMAÇÃO DINÂMICA Programação dinâmica é tipicamente aplicada para problemas de otimização. O desenvolvimento de um algoritmo de programação dinâmica pode ser divido em 4 etapas. Caracterizar uma solução
Leia maisDesafios de Programação
Desafios de Programação 2018.1 Programação Dinâmica É um método de projeto de algoritmos que utiliza a memorização para melhorar a eficiência de um algoritmo. Método parecido com o de divisão e conquista
Leia maisProjeto e Análise de Algoritmos
Projeto e Análise de Algoritmos Aula 08 Maior Subsequência Comum (LCS) Edirlei Soares de Lima Problema Subsequência: sequência de caracteres não necessariamente contínuos, retirados
Leia maisComplexidade de Algoritmos. Edson Prestes
Edson Prestes Programação Dinâmica A programação dinâmica costuma ser aplicada a problemas de otimização resultando, em geral, em algoritmos mais eficientes que os mais diretos. Esse método é útil quando
Leia maisDivisão e Conquista. Fernando Lobo. Algoritmos e Estrutura de Dados II. É uma técnica para resolver problemas (veremos outras técnicas mais adiante).
Divisão e Conquista Fernando Lobo Algoritmos e Estrutura de Dados II 1 / 27 Divisão e Conquista É uma técnica para resolver problemas (veremos outras técnicas mais adiante). Consiste em 3 passos: Dividir
Leia maisCAL ( ) - MIEIC/FEUP Programação Dinâmica ( )
AL (-) - MIEI/FEUP Programação Dinâmica (--4) Técnicas de oncepção de Algoritmos (ª parte): programação dinâmica R. Rossetti, A.P. Rocha, A. Pereira, P.B. Silva, T. Fernandes AL, MIEI, FEUP Fevereiro de
Leia maisProjeto e Análise de Algoritmos Aula 4: Dividir para Conquistar ou Divisão e Conquista ( )
Projeto e Análise de Algoritmos Aula 4: Dividir para Conquistar ou Divisão e Conquista (2.1-2.2) DECOM/UFOP 2013/1 5º. Período Anderson Almeida Ferreira Adaptado do material desenvolvido por Andréa Iabrudi
Leia maisAnálise de Complexidade de Algoritmos
Análise de Complexidade de Algoritmos Algoritmos e Estruturas de Dados 2009/2010 Introdução Algoritmo: conjunto claramente especificado de instruções a seguir para resolver um problema Análise de algoritmos:
Leia maisAnálise de Problemas Recursivos. Algoritmos e Estruturas de Dados Flavio Figueiredo (
Análise de Problemas Recursivos Algoritmos e Estruturas de Dados 2 2017-1 Flavio Figueiredo (http://flaviovdf.github.io) 1 Lembrando de Recursividade Procedimento que chama a si mesmo Recursividade permite
Leia maisProgramação dinâmica. CLRS cap 15. = recursão com tabela = transformação inteligente de recursão em iteração
Programação dinâmica CLRS cap 15 = recursão com tabela = transformação inteligente de recursão em iteração Números de Fibonacci F 0 = 0 F 1 = 1 F n = F n 1 +F n 2 n 0 1 2 3 4 5 6 7 8 9 F n 0 1 1 2 3 5
Leia maisAULA 15. Algoritmos p.600/637
AULA 15 Algoritmos p.600/637 Programação dinâmica CLRS 15.1 15.3 = recursão com tabela = transformação inteligente de recursão em iteração Algoritmos p.601/637 Programação dinâmica "Dynamic programming
Leia maisProgramação dinâmica
Programação dinâmica CLRS 15.2 15.3 = recursão com tabela = transformação inteligente de recursão em iteração Algoritmos p. 1 Multiplicação iterada de matrizes Se A é p q e B é q r então AB é p r. (AB)[i,j]
Leia maisDivisão e Conquista: Par de Pontos mais Próximo
Divisão e Conquista: Par de Pontos mais Próximo Fernando Lobo Algoritmos e Estrutura de Dados II 1 / 18 Divisão e Conquista (cont.) Problema: Dado um conjunto de pontos no plano, obter o par de pontos
Leia maisAnálise e Complexidade de Algoritmos
Análise e Complexidade de Algoritmos Professor Ariel da Silva Dias Algoritmos Divisão e Conquista Construção incremental Resolver o problema para um sub-conjunto dos elementos de entrada; Então, adicionar
Leia maisAlgoritmos para Automação e Sistemas. Programação Dinâmica. Universidade Federal do Amazonas Departamento de Eletrônica e Computação
Algoritmos para Automação e Sistemas Programação Dinâmica Universidade Federal do Amazonas Departamento de Eletrônica e Computação Roteiro Programação Dinâmica Problemas de Otimização Linha de Montagem
Leia maisProjeto e Análise de Algoritmos Projeto de Algoritmos Programação Dinâmica. Prof. Humberto Brandão
Projeto e Análise de Algoritmos Projeto de Algoritmos Programação Dinâmica Prof. Humberto Brandão humberto@bcc.unifal-mg.edu.br Universidade Federal de Alfenas versão da aula: 0.3 Programação Dinâmica
Leia maisProgramação I Aula 16 Mais exemplos de recursão
Programação I Aula 16 Mais exemplos de recursão Pedro Vasconcelos DCC/FCUP 2018 Pedro Vasconcelos (DCC/FCUP) Programação I Aula 16 Mais exemplos de recursão 2018 1 / 27 Nesta aula 1 Desenhar árvores 2
Leia maisProgramação Dinâmica. Prof. Anderson Almeida Ferreira
Programação Dinâmica Prof. Anderson Almeida Ferreira Programação Dinâmica 1950, Bellman Evitar recálculos dos subproblemas em comum Menor para maior (bottom-up) Tabelas ou memorização É uma técnica de
Leia maisProblema de seleção de atividades. Aula 14. Exemplo. Algoritmos Gulosos. Algoritmos Gulosos. Intervalo: par ordenado de números
Problema de seleção de atividades Aula 14 Algoritmos Gulosos Prof. Marco Aurélio Stefanes marco em dct.ufms.br www.dct.ufms.br/ marco Intervalo: par ordenado de números [s[i],f[i]): início e fim do intervalo
Leia maisÉ interessante comparar algoritmos para valores grandes de n. Para valores pequenos de n, mesmo um algoritmo ineficiente não custa muito para ser
É interessante comparar algoritmos para valores grandes de n. Para valores pequenos de n, mesmo um algoritmo ineficiente não custa muito para ser executado 1 Fazendo estimativas e simplificações... O número
Leia maisDivisão e Conquista. Norton T. Roman. Apostila baseada nos trabalhos de Cid de Souza, Cândida da Silva e Delano M. Beder
Divisão e Conquista Norton T. Roman Apostila baseada nos trabalhos de Cid de Souza, Cândida da Silva e Delano M. Beder Divisão e Conquista Construção incremental Ex: Consiste em, inicialmente, resolver
Leia maisAula 06: Análise matemática de algoritmos recursivos
Aula 06: Análise matemática de algoritmos recursivos David Déharbe Programa de Pós-graduação em Sistemas e Computação Universidade Federal do Rio Grande do Norte Centro de Ciências Exatas e da Terra Departamento
Leia maisReferências e materiais complementares desse tópico
Notas de aula: Análise de Algoritmos Centro de Matemática, Computação e Cognição Universidade Federal do ABC Profa. Carla Negri Lintzmayer Programação Dinâmica (Última atualização: 6 de maio de 2019) Referências
Leia maisMedida do Tempo de Execução de um Programa. David Menotti Algoritmos e Estruturas de Dados II DInf UFPR
Medida do Tempo de Execução de um Programa David Menotti Algoritmos e Estruturas de Dados II DInf UFPR Classes de Comportamento Assintótico Se f é uma função de complexidade para um algoritmo F, então
Leia maisAnálise de complexidade
Introdução Algoritmo: sequência de instruções necessárias para a resolução de um problema bem formulado (passíveis de implementação em computador) Estratégia: especificar (definir propriedades) arquitectura
Leia maisAlgoritmos e Estruturas de Dados I Linguagem C
Algoritmos e Estruturas de Dados I (DCC/003) Algoritmos e Estruturas de Dados I Linguagem C Aula Tópico 11 Recursividade 1 Recursão Na linguagem C, uma função pode chamar outra função. A função main()
Leia maisTécnicas de Desenho de Algoritmos
Técnicas de Desenho de Algoritmos Mudança de ênfase: da implementação de algoritmos para o desenho de algoritmos A ver: 5 tipos de algoritmos abordagem ao problema exemplos complexidade em tempo e espaço
Leia maisEstruturas de Dados 2
Estruturas de Dados 2 Técnicas de Projeto de Algoritmos Dividir e Conquistar IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 1/83 Projeto de Algoritmos por Divisão
Leia maisDivisão e conquista. Eficiência de divisão e conquista
Divisão e conquista Divisão: resolver recursivamente problemas mais pequenos (até caso base) Conquista: solução do problema original é formada com as soluções dos subproblemas á divisão quando o algoritmo
Leia maisEstruturas de Dados, Análise de Algoritmos e Complexidade Estrutural. Carlos Alberto Alonso Sanches
CT-234 Estruturas de Dados, Análise de Algoritmos e Complexidade Estrutural Carlos Alberto Alonso Sanches CT-234 2) Algoritmos recursivos Indução matemática, recursão, recorrências Indução matemática Uma
Leia maisProgramação Dinâmica. Prof. Anderson Almeida Ferreira. Adaptado do material elaborado por Andrea Iabrudi Tavares
Programação Dinâmica Prof. Anderson Almeida Ferreira Adaptado do material elaborado por Andrea Iabrudi Tavares Programação Dinâmica 1950, Bellman Evitar recálculos dos subproblemas em comum Menor para
Leia maisAnálise e Complexidade de Algoritmos
Análise e Complexidade de Algoritmos Principais paradigmas do projeto de algoritmos - Recursividade - Tentativa e erro - Divisão e Conquista - Programação dinâmica - Algoritmos Gulosos e de Aproximação
Leia maisDivisão e conquista. Há divisão quando o algoritmo tem pelo menos 2 chamadas recursivas no corpo
Divisão e conquista Divisão: resolver recursivamente problemas mais pequenos (até caso base) Conquista: solução do problema original é formada com as soluções dos subproblemas á divisão quando o algoritmo
Leia maisn Programação Dinâmica n Exemplo: Sequência de Fibonnaci n Problemas de Otimização n Multiplicação de Matrizes n Principios de Programação Dinâmica
Proeto e Análise e Algoritmos Altigran Soares a Silva Universiae Feeral o Amazonas Departamento e Ciência a Computação Roteiro Exemplo: Sequência e Fibonnaci Problemas e Otimização Multiplicação e Matrizes
Leia maisAula 1. Teoria da Computação III
Aula 1 Teoria da Computação III Complexidade de Algoritmos Um problema pode ser resolvido através de diversos algoritmos; O fato de um algoritmo resolver um dado problema não significa que seja aceitável
Leia maisProjeto e Análise de Algoritmos
Projeto e Análise de Algoritmos Aula 05 Técnicas de Projeto de Algoritmos (Programação Dinâmica) Edirlei Soares de Lima Estratégias de Projeto de Algoritmos Força Bruta (Brute Force)
Leia maisSCC0601 Projeto de Algoritmos. Recursão
SCC0601 Projeto de Algoritmos Recursão Definição Uma função é dita recursiva quando é definida em seus próprios termos, direta ou indiretamente Dicionário Michaelis: ato ou efeito de recorrer Recorrer:
Leia maisALGORITMOS E ESTRUTURAS DE DADOS 2011/2012 ANÁLISE DE ALGORITMOS. Armanda Rodrigues 3 de Outubro 2011
ALGORITMOS E ESTRUTURAS DE DADOS 2011/2012 ANÁLISE DE ALGORITMOS Armanda Rodrigues 3 de Outubro 2011 2 Análise de Algoritmos Temos até agora analisado soluções de problemas de forma intuitiva A análise
Leia maisRecursividade. Objetivos do módulo. O que é recursividade
Recursividade Objetivos do módulo Discutir o conceito de recursividade Mostrar exemplos de situações onde recursividade é importante Discutir a diferença entre recursividade e iteração O que é recursividade
Leia maisComplexidade de Algoritmos
Complexidade de Algoritmos Prof. Diego Buchinger diego.buchinger@outlook.com diego.buchinger@udesc.br Prof. Cristiano Damiani Vasconcellos cristiano.vasconcellos@udesc.br Abordagens para Resolução de Problemas
Leia maisBusca Binária. Aula 05. Busca em um vetor ordenado. Análise do Busca Binária. Equações com Recorrência
Busca Binária Aula 05 Equações com Recorrência Prof. Marco Aurélio Stefanes marco em dct.ufms.br www.dct.ufms.br/ marco Idéia: Divisão e Conquista Busca_Binária(A[l...r],k) 1:if r < lthen 2: index = 1
Leia mais5. Análise de Complexidade de Algoritmos. João Pascoal Faria (versão original) Ana Paula Rocha (versão 2003/2004) Luís Paulo Reis (versão 2005/2006)
5. Análise de Complexidade de Algoritmos João Pascoal Faria (versão original) Ana Paula Rocha (versão 2003/2004) Luís Paulo Reis (versão 2005/2006) FEUP - MIEEC Prog 2-2006/2007 Introdução Algoritmo: conjunto
Leia maisConjuntos disjuntos. Objectivo resolver eficientemente o problema da equivalência estrutura de dados simples (vector) implementação rápida
Conjuntos disjuntos Objectivo resolver eficientemente o problema da equivalência estrutura de dados simples (vector) implementação rápida Desempenho análise complicada Uso problemas de grafos equivalência
Leia maisMC102 Aula 26. Instituto de Computação Unicamp. 17 de Novembro de 2016
MC102 Aula 26 Recursão Instituto de Computação Unicamp 17 de Novembro de 2016 Roteiro 1 Recursão Indução 2 Recursão 3 Fatorial 4 O que acontece na memória 5 Recursão Iteração 6 Soma em um Vetor 7 Números
Leia maisDivisão-e-Conquista ( ) CAL ( ) MIEIC/FEUP. ./rr (1) Técnicas de Concepção de Algoritmos
1 Técnicas de Concepção de Algoritmos (1ª parte): divisão e conquista R. Rossetti, A.P. Rocha, A. Pereira, P.B. Silva, T. Fernandes CAL, MIEIC, FEUP Fevereiro de 2011 2 Divisão e Conquista (divide and
Leia mais1 Congruências e aritmética modular
1 Congruências e aritmética modular Vamos considerar alguns exemplos de problemas sobre números inteiros como motivação para o que se segue. 1. O que podemos dizer sobre a imagem da função f : Z Z, f(x)
Leia maisProgramação Dinâmica. Prof. Marcio Delamaro ICMC/USP
Programação Dinâmica Prof. Marcio Delamaro ICMC/USP Características Resolve problemas combinando soluções para subproblemas Características Resolve problemas combinando soluções para subproblemas Opa!!!
Leia maisOrdenação: MergeSort. Prof. Túlio Toffolo BCC202 Aula 14 Algoritmos e Estruturas de Dados I
Ordenação: MergeSort Prof. Túlio Toffolo http://www.toffolo.com.br BCC202 Aula 14 Algoritmos e Estruturas de Dados I DIVISÃO E CONQUISTA Motivação É preciso revolver um problema com uma entrada grande
Leia maisCES-11. Noções de complexidade de algoritmos. Complexidade de algoritmos. Avaliação do tempo de execução. Razão de crescimento desse tempo.
CES-11 Noções de complexidade de algoritmos Complexidade de algoritmos Avaliação do tempo de execução Razão de crescimento desse tempo Notação O Exercícios COMPLEXIDADE DE ALGORITMOS Importância de análise
Leia maisAlgoritmos e Estruturas de Dados I 01/2013. Vetores e Recursividade. Pedro O.S. Vaz de Melo
Algoritmos e Estruturas de Dados I 01/2013 Vetores e Recursividade Pedro O.S. Vaz de Melo Problema 1 Implemente uma função que classifique os elementos de um vetor em ordem crescente usando o algoritmo
Leia maisElementos de Matemática Finita
Elementos de Matemática Finita Exercícios Resolvidos - Princípio de Indução; Algoritmo de Euclides 1. Seja ( n) k n! k!(n k)! o coeficiente binomial, para n k 0. Por convenção, assumimos que, para outros
Leia maisAlgoritmos e Estrutura de Dados. Algoritmos Prof. Tiago A. E. Ferreira
Algoritmos e Estrutura de Dados Aula 3 Conceitos Básicos de Algoritmos Prof. Tiago A. E. Ferreira Definição de Algoritmo Informalmente... Um Algoritmo é qualquer procedimento computacional bem definido
Leia maisAlgoritmo. Exemplo. Definição. Programação de Computadores Comparando Algoritmos. Alan de Freitas
Algoritmos Programação de Computadores Comparando Algoritmos Um algoritmo é um procedimento de passos para cálculos. Este procedimento é composto de instruções que definem uma função Até o momento, vimos
Leia maisComplexidade de Algoritmos
Complexidade de Algoritmos! Uma característica importante de qualquer algoritmo é seu tempo de execução! é possível determiná-lo através de métodos empíricos, considerando-se entradas diversas! é também
Leia maisIntrodução à Programação / Programação I
Introdução à Programação / Programação I Aula 18: Definições recursivas Rita P. Ribeiro 2017/2018 Departamento de Ciência de Computadores Nesta aula 1. Definições recursivas 2. Exemplos INTRODUÇÃO À PROGRAMAÇÃO
Leia maisTécnicas de análise de algoritmos
CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Técnicas de análise de algoritmos Algoritmos e Estruturas de Dados I Natália Batista https://sites.google.com/site/nataliacefetmg/ nataliabatista@decom.cefetmg.br
Leia maisDisciplina de Projetos e Análise de Algoritmos
Aula 6 - A Maior Subsequência Comum Possível (Programação Dinâmica Parte IV) Aplicações na Biologia Um problema bastante em voga na Biologia é a análise do DNA de dois ou mais organismos distintos. Um
Leia maisBCC202 - Estrutura de Dados I
BCC202 - Estrutura de Dados I Aula 13: Ordenação: MergeSort Reinaldo Fortes Universidade Federal de Ouro Preto, UFOP Departamento de Computação, DECOM Website: www.decom.ufop.br/reifortes Email: reifortes@iceb.ufop.br
Leia maisLista 1. 8 de abril de Algorithms: Capítulo 0, exercícios 1 e 2. Tardos: Todos exercícios do cap 2 do livro texto, exceto 7 e 8 letra b.
Lista 1 8 de abril de 2013 1 Exercícios Básicos 1.1 Na bibliografia Algorithms: Capítulo 0, exercícios 1 e 2. Tardos: Todos exercícios do cap 2 do livro texto, exceto 7 e 8 letra b. 1.2 Outros 1. Projete
Leia maisa) Defina uma função para obter o máximo entre dois números
IP, Resoluções comentadas, Semana 2 jrg, vs 002, Out-2012 a) Defina uma função para obter o máximo entre dois números A versão mais imediata talvez seja esta: public static int maior ( int a, int b ) {
Leia maisAula 03: Análise de algoritmos melhor caso, pior caso e caso médio
Aula 03: Análise de algoritmos melhor caso, pior caso e caso médio David Déharbe Programa de Pós-graduação em Sistemas e Computação Universidade Federal do Rio Grande do Norte Centro de Ciências Exatas
Leia maisCIC 111 Análise e Projeto de Algoritmos II
CIC 111 Análise e Projeto de Algoritmos II Prof. Roberto Affonso da Costa Junior Universidade Federal de Itajubá AULA 22 Combinatorics Binomial coefficients Catalan numbers Inclusion-exclusion Burnside
Leia maisPrincípio da Multiplicação Gerando todas as palavras de um alfabeto. > Princípios de Contagem e Enumeração Computacional 0/18
Conteúdo 1 Princípios de Contagem e Enumeração Computacional Princípio da Multiplicação Gerando todas as palavras de um alfabeto Permutações > Princípios de Contagem e Enumeração Computacional 0/18 Objetivos
Leia maisProcessamento da Informação
Processamento da Informação Fabrício Olivetti de França 02 de Fevereiro de 2019 Topics 1. Recursão 1 Recursão Indução Matemática Em bases matemáticas vocês aprenderam sobre indução matemática: Provamos
Leia maisCAL ( ) MIEIC/FEUP Estruturas de Dados ( )
Conjuntos Disjuntos R. Rossetti, A.P. Rocha, A. Pereira, P.B. Silva, T. Fernandes FEUP, MIEIC, CPAL, 2010/2011 1 Conjuntos Disjuntos Objectivo resolver eficientemente o problema da equivalência estrutura
Leia maisTécnicas de projeto de algoritmos: Indução
Técnicas de projeto de algoritmos: Indução ACH2002 - Introdução à Ciência da Computação II Delano M. Beder Escola de Artes, Ciências e Humanidades (EACH) Universidade de São Paulo dbeder@usp.br 08/2008
Leia maisEstruturas de Dados 2
Estruturas de Dados 2 Recorrências IF64C Estruturas de Dados 2 Engenharia da Computação Prof. João Alberto Fabro - Slide 1/31 Recorrências Análise da Eficiência de Algoritmos: Velocidade de Execução; Análise
Leia maisProgramação Dinâmica I SCC0210 Algoritmos Avançados (2/2011) Lucas Schmidt Cavalcante
Programação Dinâmica I SCC0210 Algoritmos Avançados (2/2011) Lucas Schmidt Cavalcante Introdução Soma máxima de uma subsequência contígua Problema do troco Quantidade de formas de dar troco Problema da
Leia maisMergesort. Aula 04. Algoritmo Mergesort. Divisão e Conquista. Divisão e Conquista- MergeSort
Mergesort Aula 0 Divisão e Conquista- MergeSort Prof. Marco Aurélio Stefanes marco em dct.ufms.br www.dct.ufms.br/ marco Mergesort é um algoritmo de ordenação recursivo Ele recursivamente ordena as duas
Leia maisMarcelo Keese Albertini Faculdade de Computação Universidade Federal de Uberlândia. 23 de Março de 2018
Relações de Recorrência Marcelo Keese Albertini Faculdade de Computação Universidade Federal de Uberlândia 23 de Março de 2018 Aula de hoje Nesta aula veremos Conceitos de Relações de Recorrência Resolução
Leia maisANÁLISE DE ALGORITMOS
ANÁLISE DE ALGORITMOS Paulo Feofiloff Instituto de Matemática e Estatística Universidade de São Paulo agosto 2009 Introdução P. Feofiloff (IME-USP) Análise de Algoritmos agosto 2009 2 / 102 Introdução
Leia maisProf. A. G. Silva. 25 de setembro de Prof. A. G. Silva INE5603 Introdução à POO 25 de setembro de / 35
INE5603 Introdução à POO Prof. A. G. Silva 25 de setembro de 2017 Prof. A. G. Silva INE5603 Introdução à POO 25 de setembro de 2017 1 / 35 Baseado em materiais da Recursividade Unisinos, Cesar Tacla (UTFPR),
Leia maisEndereçamento Aberto
Endereçamento Aberto ACH2002 - Introdução à Ciência da Computação II Delano M. Beder Escola de Artes, Ciências e Humanidades (EACH) Universidade de São Paulo dbeder@usp.br 11/2008 Material baseado em slides
Leia maisAULA 17. Algoritmos p.662/695
AULA 17 Algoritmos p.662/695 Mochila Dados dois vetores x[1.. n] e w[1.. n], denotamos por x w o produto escalar w[1]x[1] + w[2]x[2] + + w[n]x[n]. Suponha dado um número inteiro não-negativo W e vetores
Leia maisIntrodução Paradigmas
Introdução Paradigmas Recursividade Algoritmos tentativa e erro Divisão e conquista Programação dinâmica Algoritmos gulosos Algoritmos aproximados 1 Introdução O projeto de algoritmos requer abordagens
Leia maisAULA 24. Algoritmos p.856/905
AULA 24 Algoritmos p.856/905 Máximo divisor comum CLRS 31.1 e 31.2 Algoritmos p.857/905 Divisibilidade Suponha que a, b e d são números inteiros. Dizemos que d divide a se a = k d para algum número inteiro
Leia maisProgramação Estruturada
Programação Estruturada Recursão Professores Emílio Francesquini e Carla Negri Lintzmayer 2018.Q3 Centro de Matemática, Computação e Cognição Universidade Federal do ABC Recursão Recursão 1 Recursão 2
Leia mais1. O que podemos dizer sobre a imagem da função. f : Z Z, f(x) = x 2 + x + 1?
1 Congruências e aritmética modular Vamos considerar alguns exemplos de problemas sobre números inteiros como motivação para o que se segue. 1. O que podemos dizer sobre a imagem da função f : Z Z, f(x)
Leia maisIntrodução à Programação. João Manuel R. S. Tavares
Introdução à Programação João Manuel R. S. Tavares Sumário 1. Ciclo de desenvolvimento de um programa; 2. Descrição de algoritmos; 3. Desenvolvimento modular de programas; 4. Estruturas de controlo de
Leia maisAlgoritmos de Ordenação
Algoritmos de Ordenação Introdução à Ciência da Computação Prof. Edison Ishikawa Objetivo Apresentar diferentes algoritmos de ordenação de dados Mostrar como analisar os algoritmos em termos de tempo de
Leia maisPrincípio da boa ordenação. Aula 03. Princípio da boa ordenação. Princípio da boa ordenação. Indução Finita e Somatórios
Princípio da boa ordenação Aula 0 Indução Finita e Somatórios Prof. Marco Aurélio Stefanes marco em dct.ufms.br www.dct.ufms.br/ marco Aula 0 p. 1 Aula 0 p. Princípio da boa ordenação Princípio da boa
Leia maisANÁLISE DE COMPLEXIDADE DOS ALGORITMOS
1/18 ANÁLISE DE COMPLEXIDADE DOS ALGORITMOS Algoritmos 2/18 Algoritmos Algoritmo - sequência de instruções necessárias para a resolução de um problema bem formulado (passíveis de implementação em computador)
Leia maisModelagem com relações de recorrência. Exemplo: Determinada população dobra a cada ano; população inicial = 5 a n = população depois de n anos
Relações de recorrência 8. RELAÇÕES DE RECORRÊNCIA Introdução a relações de recorrência Modelagem com relações de recorrência Solução de relações de recorrência Exemplos e aplicações Relações de recorrência
Leia maisAED2 - Aula 11 Problema da separação e quicksort
AED2 - Aula 11 Problema da separação e quicksort Projeto de algoritmos por divisão e conquista Dividir: o problema é dividido em subproblemas menores do mesmo tipo. Conquistar: os subproblemas são resolvidos
Leia maisComparação entre duas metodologias de otimização para maximização do aproveitamento de área de chapas de vidro
Curso de Ciência da Computação Universidade Estadual de Mato Grosso do Sul Comparação entre duas metodologias de otimização para maximização do aproveitamento de área de chapas de vidro Davi Pereira Rocha
Leia mais7 Comandos e Estruturas de Controle
Lógica para a Programação - 1º semestre AULA 03 Prof. André Moraes 7 Comandos e Estruturas de Controle Na criação de algoritmos é comum utilizar conceitos de bloco lógico, entrada e saída de dados, constantes,
Leia mais> Princípios de Contagem e Enumeração Computacional 1/13
Princípios de Contagem e Enumeração Computacional > Princípios de Contagem e Enumeração Computacional 1/13 Objetivos Contar/listar o número de elementos de conjuntos finitos Aplicações > Princípios de
Leia maisAula prática 5. Funções Recursivas
Programação Funcional UFOP DECOM 2014.1 Aula prática 5 Funções Recursivas Resumo Definições recursivas são comuns na programação funcional. Nesta aula vamos aprender a definir funções recursivas. Sumário
Leia maisProgramação: Vetores
Programação de Computadores I Aula 09 Programação: Vetores José Romildo Malaquias Departamento de Computação Universidade Federal de Ouro Preto 2011-1 1/62 Motivação Problema Faça um programa que leia
Leia maisProgramação II RECURSÃO
Programação II RECURSÃO Bruno Feijó Dept. de Informática, PUC-Rio Motivação Escher: Metamorphosis (1937) - Drawing Hands (1948) Relativity (1953) http://www.worldofescher.com/gallery/ Alguém diz: Esta
Leia maisInterpolação polinomial: Diferenças divididas de Newton
Interpolação polinomial: Diferenças divididas de Newton Marina Andretta ICMC-USP 16 de maio de 2012 Baseado no livro Análise Numérica, de R. L. Burden e J. D. Faires. Marina Andretta (ICMC-USP) sme0500
Leia maisIntrodução à Programação
Introdução à Programação 1.Ano LCC-MIERSI DCC - FCUP Nelma Moreira Aula 12 Recursividade Recursão versus Iteração FACTORIAL outra vez! Muitas versões. n! = n (n - 1)... 1 int facti(int n){ int fac=n; while(--n>0){
Leia maisAnálise de Algoritmos
Análise de Algoritmos Parte destes slides são adaptações de slides do Prof. Paulo Feofiloff e do Prof. José Coelho de Pina. Algoritmos p. 1/36 Complexidade computacional Classifica os problemas em relação
Leia maisTabelas de Hash MBB. Novembro de Algoritmos e Complexidade LEI-LCC
Tabelas de Hash Algoritmos e Complexidade LEI-LCC 2010-2011 MBB Novembro de 2010 Tabelas e Acesso a Informação As estruturas de dados apresentadas anteriormente têm como objectivo o armazenamento de informação,
Leia maisTópicos Avançados em Algoritmos - exercícios de Prog. Din. com correcção parcial
Armando Matos, 2008/2009 Tópicos Avançados em Algoritmos - exercícios de Prog. Din. com correcção parcial 1. Optimizar o produto de matrizes Considere o problema da parentização óptima de uma multiplicação
Leia mais