A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Metodologia de Dijkstra para desenvolvimento de ciclos

Apresentações semelhantes


Apresentação em tema: "Metodologia de Dijkstra para desenvolvimento de ciclos"— Transcrição da apresentação:

1 Metodologia de Dijkstra para desenvolvimento de ciclos
Aula 8 Metodologia de Dijkstra para desenvolvimento de ciclos

2 Introdução à Programação
Ciclos Parte importante da escrita de algoritmos Impossível demonstrar correcção com testes Condições invariantes importantes para demonstrar correcção Verdadeiras do início ao fim dos ciclos Fortes! Referem todas instâncias envolvidas Introdução à Programação 2003/2004

3 Introdução à Programação
potênciaDe() /** Devolve a potência n de x. @pre 0 ≤ n. @post potênciaDe = xn. */ double potênciaDe(double const x, int const n) { assert(0 <= n); int i = 0; double potência = 1.0; while(i != n) { potência *= x; ++i; } return potência; Inicialização Acção potência *= x; Passo ++i; Progresso Introdução à Programação 2003/2004

4 Diagrama de actividade
inic {PC: 0 ≤ n} int i = 0; double potência = 1.0; {0 ≤ n  i = 0  potência = 1} passo [i = n] {0 ≤ n  0 ≤ i < n  potência = xi} [i ≠ n] potência *= x; {0 ≤ n  i = n  potência = xn} acção ++i; {0 ≤ n  0 < i ≤ n  potência = xi} prog Introdução à Programação 2003/2004

5 Introdução à Programação
Condição invariante CI: 0 ≤ i ≤ n  potência = xi. Condição invariante explica funcionamento do ciclo Durante todo o ciclo potência contém xi, estando sempre i entre 0 e n Como i varia entre 0 e n, e termina com n, o objectivo é atingido Introdução à Programação 2003/2004

6 Metodologia de Dijkstra
Edsger Dijkstra Fundador da programação disciplinada Programação é uma ciência Metodologia Baseia-se na condição objectivo Programação é actividade orientada pelos objectivos Condição invariante retirada da condição objectivo Introdução à Programação 2003/2004

7 Soma dos primeiros n ímpares inteiros
int somaDosPrimeirosÍmpares(int const n) { int r = ?; ... return r; } Introdução à Programação 2003/2004

8 Introdução à Programação
Raiz inteira int raizInteiraDe(int const x) { int r = ?; ... return r; } Introdução à Programação 2003/2004

9 Especificar o problema
Escrever Pré-condição Condição objectivo

10 somaDosPrimeirosÍmpares()
/** Devolve a soma dos primeiros n naturais ímpares. @pre 0 ≤ n. @post somaDosPrimeirosÍmpares = (S j : 0 ≤ j < n : 2j + 1). */ int somaDosPrimeirosÍmpares(int const n) { assert(0 <= n); // 0 ≤ n. int r = ?; ... // CO: r = (S j : 0 ≤ j < n : 2j + 1). return r; } Introdução à Programação 2003/2004

11 Introdução à Programação
raizInteiraDe() /** Devolve a melhor aproximação por defeito de x1/2. @pre 0 ≤ x. @post 0 ≤ raizInteiraDe ≤ x1/2 < raizInteiraDe + 1. */ int raizInteiraDe(int const x) { assert(0 <= x); // 0 ≤ x. int r = ?; ... // CO: 0 ≤ r ≤ x1/2 < r + 1. assert(0 <= r and r * r <= x and x < (r + 1) * (r + 1)); return r; } Introdução à Programação 2003/2004

12 Será necessário um ciclo?
Verificar se ciclo é melhor abordagem Análise do problema Intuição! Experiência…

13 somaDosPrimeirosÍmpares()
/** Devolve a soma dos primeiros n naturais ímpares. @pre 0 ≤ n. @post somaDosPrimeirosÍmpares = (S j : 0 ≤ j < n : 2j + 1). */ int somaDosPrimeirosÍmpares(int const n) { assert(0 <= n); // 0 ≤ n. int r = ?; while(...) { ... } // CO: r = (S j : 0 ≤ j < n : 2j + 1). return r; Introdução à Programação 2003/2004

14 Introdução à Programação
raizInteiraDe() /** Devolve a melhor aproximação por defeito de x1/2. @pre 0 ≤ x. @post 0 ≤ raizInteiraDe ≤ x1/2 < raizInteiraDe + 1. */ int raizInteiraDe(int const x) { assert(0 <= x); // 0 ≤ x. int r = ?; while(...) { ... } // CO: 0 ≤ r ≤ x1/2 < r + 1. assert(0 <= r and r * r <= x and x < (r + 1) * (r + 1)); return r; Introdução à Programação 2003/2004

15 Obtenção da condição invariante
Programar é actividade orientada pelos objectivos Enfraquecer a CO para obter a CI

16 somaDosPrimeirosÍmpares()
Substituição de constante na CO por variável inic int i = ?; int r = ?; CO: r = (S j : 0 ≤ j < n : 2j + 1). r = (S j : 0 ≤ j < i : 2j + 1). CO’: r = (S j : 0 ≤ j < i : 2j + 1)  i = n. Não é equivalente a CO. Introdução à Programação 2003/2004

17 somaDosPrimeirosÍmpares()
/** Devolve a soma dos primeiros n naturais ímpares. @pre 0 ≤ n. @post somaDosPrimeirosÍmpares = (S j : 0 ≤ j < n : 2j + 1). */ int somaDosPrimeirosÍmpares(int const n) { assert(0 <= n); // 0 ≤ n. int i = ?; int r = ?; while(...) { ... } // CO’: r = (S j : 0 ≤ j < i : 2j + 1)  i = n. // que implica CO: r = (S j : 0 ≤ j < n : 2j + 1). return r; Introdução à Programação 2003/2004

18 somaDosPrimeirosÍmpares()
CO’: r = (S j : 0 ≤ j < i : 2j + 1)  i = n. Enfraquecendo as restrições relativas a i CI: r = (S j : 0 ≤ j < i : 2j + 1)  ? ≤ i ≤ ?. CI: r = (S j : 0 ≤ j < i : 2j + 1)  0 ≤ i ≤ n. Introdução à Programação 2003/2004

19 somaDosPrimeirosÍmpares()
/** Devolve a soma dos primeiros n naturais ímpares. @pre 0 ≤ n. @post somaDosPrimeirosÍmpares = (S j : 0 ≤ j < n : 2j + 1). */ int somaDosPrimeirosÍmpares(int const n) { assert(0 <= n); // 0 ≤ n. int i = ?; int r = ?; // CI: r = (S j : 0 ≤ j < i : 2j + 1)  0 ≤ i ≤ n. while(...) { ... } // CO’: r = (S j : 0 ≤ j < i : 2j + 1)  i = n. // que implica CO: r = (S j : 0 ≤ j < n : 2j + 1). return r; Introdução à Programação 2003/2004

20 Introdução à Programação
raizInteiraDe() A  B  C  D Factorização da condição objectivo Parte é negação da guarda Parte restante é condição invariante CO: A  B  C  D CI: A  C Sabendo que no final do ciclo se quer CI  ¬G  CO ¬G: B  D Logo, CI  ¬G = CO B A D A  C C Introdução à Programação 2003/2004

21 Introdução à Programação
raizInteiraDe() CO: 0 ≤ r ≤ x1/2 < r + 1, ou seja 0 ≤ r  r2 ≤ x  x < (r + 1)2 . Começando a procurar em 0 (zero) e terminando quando se sabe que o valor seguinte já não serve… CI: 0 ≤ r  r2 ≤ x. ¬G: x < (r + 1)2. Introdução à Programação 2003/2004

22 Introdução à Programação
raizInteiraDe() /** Devolve a melhor aproximação por defeito de x1/2. @pre 0 ≤ x. @post 0 ≤ raizInteiraDe ≤ x1/2 < raizInteiraDe + 1. */ int raizInteiraDe(int const x) { assert(0 <= x); // 0 ≤ x. int r = ?; // CI: 0 ≤ r  r2 ≤ x. while(...) { ... } // CO: 0 ≤ r ≤ x1/2 < r + 1. assert(0 <= r and r * r <= x and x < (r + 1) * (r + 1)); return r; Introdução à Programação 2003/2004

23 Determinação da guarda
Procurar guarda que leve ao resultado CI  ¬G  CO

24 somaDosPrimeirosÍmpares()
CI  ¬G: r = (S j : 0 ≤ j < i : 2j + 1)  0 ≤ i ≤ n  ¬G. CO’: r = (S j : 0 ≤ j < i : 2j + 1)  i = n. Qual a guarda mais simples que garante a verificação da CO? ¬G: i = n. ou seja, G: i ≠ n. CI  ¬G: r = (S j : 0 ≤ j < i : 2j + 1)  0 ≤ i ≤ n  i = n. CI  ¬G: r = (S j : 0 ≤ j < i : 2j + 1)  0 ≤ n  i = n. que implica CO. Introdução à Programação 2003/2004

25 somaDosPrimeirosÍmpares()
/** Devolve a soma dos primeiros n naturais ímpares. @pre 0 ≤ n. @post somaDosPrimeirosÍmpares = (S j : 0 ≤ j < n : 2j + 1). */ int somaDosPrimeirosÍmpares(int const n) { assert(0 <= n); // 0 ≤ n. int i = ?; int r = ?; // CI: r = (S j : 0 ≤ j < i : 2j + 1)  0 ≤ i ≤ n. while(i != n) { ... } // CO’: r = (S j : 0 ≤ j < i : 2j + 1)  i = n. // que implica CO: r = (S j : 0 ≤ j < n : 2j + 1). return r; Introdução à Programação 2003/2004

26 Introdução à Programação
raizInteiraDe() CO: 0 ≤ r  r2 ≤ x  x < (r + 1)2 . CI: 0 ≤ r  r2 ≤ x. Logo, sabendo que CI  ¬G = CO ¬G: x < (r + 1)2 ou seja, G: (r + 1)2 ≤ x. Introdução à Programação 2003/2004

27 Introdução à Programação
raizInteiraDe() /** Devolve a melhor aproximação por defeito de x1/2. @pre 0 ≤ x. @post 0 ≤ raizInteiraDe ≤ x1/2 < raizInteiraDe + 1. */ int raizInteiraDe(int const x) { assert(0 <= x); // 0 ≤ x. int r = ?; // CI: 0 ≤ r  r2 ≤ x. while((r + 1) * (r + 1) <= x) { ... } // CO: 0 ≤ r ≤ x1/2 < r + 1. assert(0 <= r and r * r <= x and x < (r + 1) * (r + 1)); return r; Introdução à Programação 2003/2004

28 Determinação da inicialização
Escolher inicialização tão simples quanto possível: Sabendo que PC é verdadeira Garantir verificação da CI

29 somaDosPrimeirosÍmpares()
/** Devolve a soma dos primeiros n naturais ímpares. @pre 0 ≤ n. @post somaDosPrimeirosÍmpares = (S j : 0 ≤ j < n : 2j + 1). */ int somaDosPrimeirosÍmpares(int const n) { assert(0 <= n); // 0 ≤ n. int i = ?; int r = ?; // CI: r = (S j : 0 ≤ j < i : 2j + 1)  0 ≤ i ≤ n. while(i != n) { ... } // CO’: r = (S j : 0 ≤ j < i : 2j + 1)  i = n. // que implica CO: r = (S j : 0 ≤ j < n : 2j + 1). return r; Introdução à Programação 2003/2004

30 somaDosPrimeirosÍmpares()
/** Devolve a soma dos primeiros n naturais ímpares. @pre 0 ≤ n. @post somaDosPrimeirosÍmpares = (S j : 0 ≤ j < n : 2j + 1). */ int somaDosPrimeirosÍmpares(int const n) { assert(0 <= n); // 0 ≤ n. int i = 0; int r = 0; // CI: r = (S j : 0 ≤ j < i : 2j + 1)  0 ≤ i ≤ n. while(i != n) { ... } // CO’: r = (S j : 0 ≤ j < i : 2j + 1)  i = n. // que implica CO: r = (S j : 0 ≤ j < n : 2j + 1). return r; Introdução à Programação 2003/2004

31 Introdução à Programação
raizInteiraDe() /** Devolve a melhor aproximação por defeito de x1/2. @pre 0 ≤ x. @post 0 ≤ raizInteiraDe ≤ x1/2 < raizInteiraDe + 1. */ int raizInteiraDe(int const x) { assert(0 <= x); // 0 ≤ x. int r = ?; // CI: 0 ≤ r  r2 ≤ x. while((r + 1)*(r + 1) <= x) { ... } // CO: 0 ≤ r ≤ x1/2 < r + 1. assert(0 <= r and r * r <= x and x < (r + 1) * (r + 1)); return r; Introdução à Programação 2003/2004

32 Introdução à Programação
raizInteiraDe() /** Devolve a melhor aproximação por defeito de x1/2. @pre 0 ≤ x. @post 0 ≤ raizInteiraDe ≤ x1/2 < raizInteiraDe + 1. */ int raizInteiraDe(int const x) { assert(0 <= x); // 0 ≤ x. int r = 0; // CI: 0 ≤ r  r2 ≤ x. while((r + 1)*(r + 1) <= x) { ... } // CO: 0 ≤ r ≤ x1/2 < r + 1. assert(0 <= r and r * r <= x and x < (r + 1) * (r + 1)); return r; Introdução à Programação 2003/2004

33 Escolha de um progresso
Um ciclo tem de terminar Num número finito de passos Rapidamente? Pode valer a pena investigar progressos complexos

34 somaDosPrimeirosÍmpares()
/** ... */ int somaDosPrimeirosÍmpares(int const n) { assert(0 <= n); // 0 ≤ n. int i = 0; int r = 0; // CI: r = (S j : 0 ≤ j < i : 2j + 1)  0 ≤ i ≤ n. while(i != n) { acção ++i; } // CO’: r = (S j : 0 ≤ j < i : 2j + 1)  i = n. // que implica CO: r = (S j : 0 ≤ j < n : 2j + 1). return r; Introdução à Programação 2003/2004

35 Introdução à Programação
raizInteiraDe() /** ... */ int raizInteiraDe(int const x) { assert(0 <= x); // 0 ≤ x. int r = 0; // CI: 0 ≤ r  r2 ≤ x. while((r + 1)*(r + 1) <= x) { acção ++r; } // CO: 0 ≤ r ≤ x1/2 < r + 1. assert(0 <= r and r * r <= x and x < (r + 1) * (r + 1)); return r; Introdução à Programação 2003/2004

36 Escolher acção tal que // CI e G. acção prog // CI.
Determinação da acção Escolher acção tal que // CI e G. acção prog // CI. Garante veracidade de CI apesar do progresso

37 somaDosPrimeirosÍmpares()
// CI: r = (S j : 0 ≤ j < i : 2j + 1)  0 ≤ i ≤ n. while(i != n) { // CI  G: r = (S j : 0 ≤ j < i : 2j + 1)  0 ≤ i ≤ n  i ≠ n. // CI  G: r = (S j : 0 ≤ j < i : 2j + 1)  0 ≤ i < n. acção // r = (S j : 0 ≤ j < i + 1 : 2j + 1)  0 ≤ i + 1 ≤ n. // r = (S j : 0 ≤ j < i + 1 : 2j + 1)  -1 ≤ i < n. ++i; } Falta um termo ao somatório. Introdução à Programação 2003/2004

38 somaDosPrimeirosÍmpares()
/** ... */ int somaDosPrimeirosÍmpares(int const n) { assert(0 <= n); // 0 ≤ n. int i = 0; int r = 0; // CI: r = (S j : 0 ≤ j < i : 2j + 1)  0 ≤ i ≤ n. while(i != n) { r += 2 * i + 1; ++i; } // CO’: r = (S j : 0 ≤ j < i : 2j + 1)  i = n. // que implica CO: r = (S j : 0 ≤ j < n : 2j + 1). return r; Introdução à Programação 2003/2004

39 Introdução à Programação
raizInteiraDe() // CI: 0 ≤ r  r2 ≤ x. while((r + 1)*(r + 1) <= x) { // CI  G: 0 ≤ r  r2 ≤ x  (r + 1) 2 ≤ x. // CI  G: 0 ≤ r  (r + 1) 2 ≤ x. acção // 0 ≤ r + 1  (r + 1) 2 ≤ x. // -1 ≤ r  (r + 1) 2 ≤ x. ++r; } Não é necessária acção! Introdução à Programação 2003/2004

40 Introdução à Programação
raizInteiraDe() /** ... */ int raizInteiraDe(int const x) { assert(0 <= x); // 0 ≤ x. int r = 0; // CI: 0 ≤ r  r2 ≤ x. while((r + 1)*(r + 1) <= x) ++r; // CO: 0 ≤ r ≤ x1/2 < r + 1. assert(0 <= r and r * r <= x and x < (r + 1) * (r + 1)); return r; } Introdução à Programação 2003/2004

41 E se alguma coisa falhar?
Voltar atrás acção ou inic demasiado complexas CI menos boa ...

42 Será que na soma dos ímpares o ciclo é necessário?
Inteiros na base 1 1: * 2: ** 3: *** 4: **** 5: ***** ... Impares 1: * 3: ** 5: *** 7: **** Soma dos primeiros 4 ímpares = * Introdução à Programação 2003/2004

43 Será que na soma dos ímpares o ciclo é necessário?
Inteiros na base 1 1: * 2: ** 3: *** 4: **** 5: ***** ... Impares 1: * 3: ** 5: *** 7: **** Soma dos primeiros 4 ímpares = ** Introdução à Programação 2003/2004

44 Será que na soma dos ímpares o ciclo é necessário?
Inteiros na base 1 1: * 2: ** 3: *** 4: **** 5: ***** ... Impares 1: * 3: ** 5: *** 7: **** Soma dos primeiros 4 ímpares = *** Introdução à Programação 2003/2004

45 Será que na soma dos ímpares o ciclo é necessário?
Inteiros na base 1 1: * 2: ** 3: *** 4: **** 5: ***** ... Impares 1: * 3: ** 5: *** 7: **** Soma dos primeiros 4 ímpares = **** Introdução à Programação 2003/2004

46 somaDosPrimeirosÍmpares()
/** Devolve a soma dos primeiros n naturais ímpares. @pre 0 ≤ n. @post somaDosPrimeirosÍmpares = (S j : 0 ≤ j < n : 2j + 1). */ int somaDosPrimeirosÍmpares(int const n) { assert(0 <= n); return n * n; } Introdução à Programação 2003/2004

47 Introdução à Programação
Aula 8: Sumário Importância da especificação do problema Noção de invariante de um ciclo Condição invariante, inicialização e guarda de um ciclo Metodologia de Dijkstra para desenvolvimento de ciclos: Obtenção da condição invariante Obtenção da guarda Inicialização Progresso Acção Importância da metodologia: Base formal para desenvolvimento Controlo dos erros Redução de surpresas Melhor raciocínio Maior eficiência Prática da construção de ciclos: usar ou não usar metodologia? Introdução à Programação 2003/2004


Carregar ppt "Metodologia de Dijkstra para desenvolvimento de ciclos"

Apresentações semelhantes


Anúncios Google