Programação Dinâmica

2,973 views
2,772 views

Published on

Programação Dinâmica

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
2,973
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
93
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Programação Dinâmica

  1. 1. 1 INTRODUÇÃO Programação dinâmica é um paradigma de programação aplicado sobretudo a problemas de otimização. Embora a técnica seja semelhante ao princípio de divisão e conquista, a solução do problema - denominada solução ótima - é encontrada a partir de uma série de escolhas que são feitas pelo algoritmo durante a execução do processo. Sabe-se, todavia, que o método de resolução de um problema estritamente grande pelo princípio de divisão e conquista consiste em dividir o problema em subproblemas, tornando o problema original cada vez menor. Por outro lado, a programação dinâmica simplifica o problema como um todo. Sedgewick (1990) e Cormen et al. (2002) ressaltam a importância de se distinguir o termo “programação" transportado pelo nome da técnica estudada. Os autores não definem a técnica como um processo de escrita de código, mas referem-se a ela como um processo de formulação de restrições por parte do problema que a utiliza. Ademais, Sedgewick (idem) destaca duas dificuldades que podem surgir com a utilização da técnica: • Nem sempre pode ser possível combinar as soluções de problemas menores para formar a solução de um maior; • O número de pequenos problemas a serem resolvidos pode ser inaceitavelmente grande; Nota-se, a partir dessas características que limitam a técnica, a ponte que a distancia da estratégia de divisão e conquista: esta, em sua última etapa, necessariamente combina as soluções encontradas nos subproblemas resolvidos para encontrar a solução do problema maior. Este trabalho pretende apresentar como o paradigma da programação dinâmica funciona. Para isto, alguns algoritmos já existentes que utilizam essa técnica serão mencionados, particularizando um deles para ser comentado a fim de que seja possível compreender e ilustrar mentalmente a importância do estudo desse estilo de programação.
  2. 2. 2 FUNDAMENTOS DE PROGRAMAÇÃO DINÂMICA Assim como outras áreas da ciência e da tecnologia, o estudo de algoritmos também possui seu dicionário de termos técnicos. A programação dinâmica, especialmente, utiliza esse dicionário e o complementa com seus próprios verbetes. Antes de apresentar e comentar alguns algoritmos que demonstram o funcionamento da programação dinâmica, este trabalho abordará neste capítulo a gama de termos que fundamenta a aplicação da técnica. 2.1 Solução ótima Um problema solucionável é aquele que possui solução. Ou seja, o problema é passível de ser resolvido e, mais, essa resolução é conhecida. Em geral, a solução de problemas computacionais não é única, mas é diversa e, muitas vezes, ilimitada. Os problemas da programação dinâmica são caracterizados por essa variedade de soluções existentes. Uma solução que existe e é ilimitada é chamada de solução ótima e existe apenas se as duas seguintes condições forem válidas: • Se a solução for possível: a solução considera ter todas as variáveis definidas para o problema; • Se a solução for ilimitada: ou seja, não tem tamanho, podendo crescer ou decrescer com o propósito de atender todas as restrições do problema. Em outras palavras, uma solução ótima é uma solução que otimiza a função-objetivo do problema (OLIVEIRA). Otimizar uma função é muito importante na utilização dessa estratégia. Como visto, uma das condições de existência de uma solução ótima é a sua não limitação em termos de crescimento. Computacionalmente falando, quanto maior for a entrada, maior será o custo do algoritmo. Portanto, uma solução ótima é aquela que resolve e otimiza o problema. 2.2 Elementos essenciais de algoritmos de programação dinâmica Cormen et al. (2002) separam em quatro etapas a construção de um algoritmo de programação dinâmica. São elas:
  3. 3. 1. Caracterizar a estrutura de uma solução ótima; 2. Definir recursivamente o valor de uma solução ótima; 3. Calcular o valor de uma solução ótima em um processo bottom-up; e 4. Construir uma solução ótima a partir das informações calculadas. Caracterizar a estrutura de uma solução ótima significa definir previamente que os subproblemas do problema mais geral também serão resolvidos. Todas as vezes que isso ocorrer, é dito que o problema apresenta uma subestrutura ótima. Cormen et al. (2002) apresentam um método padronizado para a descoberta dessa subestrutura. O capítulo 3 deste trabalho aplicará e comentará cada um dos tópicos citados pelo método, além de descrever com maior detalhamento as quatro etapas da construção de um algoritmo de programação dinâmica. Para que a programação dinâmica se torne aplicável a um problema, dois importantes elementos conceituais devem satisfazê-lo, a fim de que ele seja otimizado. Um deles é a existência de uma subestrutura ótima que resolva os problemas internos do problema mais geral; o outro, chamado de subproblema superposto, tem a função de diminuir o espaço utilizado pelo algoritmo. Quando um algoritmo se utiliza de subproblemas superpostos, é dito que o seu espaço para a resolução de subproblemas deve ser tão pequeno que "um algoritmo recursivo para o problema resolve os mesmos subproblemas repetidas vezes, em lugar de sempre gerar novos subproblemas" (Cormen et al., 2002, p. 276). Em outras palavras, o uso da técnica da recursão proverá a resolução dos subproblemas uma única vez, sem gerá-los repetidamente e combiná- los no final. Com este entendimento, a programação dinâmica é separada e estudada independentemente da técnica de divisão e conquista. 3 OTIMIZAÇÃO DE PROBLEMAS: O PROBLEMA DO PRODUTO DE CADEIAS DE MATRIZES 3.1 Enunciado Um problema clássico da programação dinâmica é a multiplicação de cadeias de matrizes. Dada uma cadeia de matrizes M1, M2, M3, ..., Mk, com k elementos e tamanhos m1xn1, m2xn2, m3xn3, ..., mkxnk, respectivamente, a multiplicação dessa cadeia, com matrizes que possuem propriedade associativa, será dada por M1 . M2 . M3 . .... Mk.
  4. 4. Matematicamente, o modo como uma matriz se associa a outra não influencia o resultado final da operação. Na computação, a associação de matrizes pode impactar o custo da solução desse problema. Embora, matematicamente, o modo de associação de uma matriz a outra não influencie o resultado final da operação, na computação, essa associação pode vir a impactar o custo da resolução desse problema. Exemplificando, realizar a multiplicação das duas últimas matrizes de uma cadeia em primeira instância poderá custar menos do que multiplicá-las ao final do processo. Na matemática, a existência de parênteses em dois elementos algébricos aplica a propriedade associativa, delimitando-os a serem resolvidos em primeira ordem. O do produto de cadeias de matrizes aplicado à programação dinâmica deve ser entendido como um problema que dificulta a multiplicação por conta da ordem disposta das matrizes. A solução geral do problema visa buscar a melhor ordem (ou seja, com menor custo computacional) para multiplicar as matrizes da sequência. 3.2 Resolução aplicada à programação dinâmica Como dito, o problema do produto de matrizes está na ordem em que serão efetuadas as operações. Este subcapítulo apresentará a resolução passo a passo do algoritmo conforme o método de construção de algoritmos de programação dinâmica mencionado em 2.2. A primeira etapa consiste em caracterizar a estrutura de uma solução ótima para o problema. Para que isso seja possível, uma subestrutura ótima deve ser encontrada antes a fim de minimizar o problema. Essa minimização deverá reduzir a resolução a ponto de torná-la tão pequena que se torne trivial. No caso da parentização de matrizes para um produto, a subestrutura ótima será a generalização de uma cadeia específica dentro da cadeia maior do problema. Para melhor ilustrar esse problema veja a Figura 1.
  5. 5. Figura 1 - Ilustração da subestrutura ótima do problema do produto da cadeia de matrizes Fonte: Autor Como foi possível perceber na primeira etapa, qualquer lugar do produto da cadeia é válido com um lugar de parentização, já que, examinando cada um dos lugares, tem-se uma opção ótima. A partir desta já definida, a segunda etapa surge para generalizar a escolha feita pelo algoritmo. Recursivamente, a solução é criada para medir o custo desta para as soluções dos subproblemas. Por definição, o problema será trivial se a linha for igual à coluna. Utilizando a primeira etapa, é possível supor que a escolha de um lugar Mk para a parentização, enquanto i = j, será igual ao menor custo possível para executar o produto. Como i = j, tem-se apenas uma matriz; ou seja, k = i x j, ou Mixj. Para Sedgewick (1990, p. 600), o algoritmo que calcula o custo pode ser definido conforme a Listagem 1.
  6. 6. Para i <- 1 a N passo 1 faça Para j <- i + 1 a N passo 1 faça custoi,j <- MaiorInteiro Fim-para Para i <- 1 a N passo 1 faça custoi,j <- 0 Fim-para Para j <- 1 a N passo 1 faça Para i <- 1 a N - j passo 1 faça Para k <- i + 1 a i + j passo 1 faça tempo <- custoi,k-1 + custok,i+j + ri * rk * ri+j+1 Se tempo < custoi,i+j então custoi,i+j <- tempo melhori,i+j <- k Fim-se Fim-para Fim-para Fim-para Fim-para Listagem 1 – Algoritmo de Sedgewick para o cálculo do custo de multiplicações Fonte: Autor “adaptado de” Sedgewick, 1990, p. 600
  7. 7. Para i <- 1 a N passo 1 faça Para j <- i + 1 a N passo 1 faça custoi,j <- MaiorInteiro Fim-para Para i <- 1 a N passo 1 faça custoi,j <- 0 Fim-para Para j <- 1 a N passo 1 faça Para i <- 1 a N - j passo 1 faça Para k <- i + 1 a i + j passo 1 faça tempo <- custoi,k-1 + custok,i+j + ri * rk * ri+j+1 Se tempo < custoi,i+j então custoi,i+j <- tempo melhori,i+j <- k Fim-se Fim-para Fim-para Fim-para Fim-para Listagem 1 – Algoritmo de Sedgewick para o cálculo do custo de multiplicações Fonte: Autor “adaptado de” Sedgewick, 1990, p. 600

×