Curso: Ciência da Computação
Turma: 6ª Série
Teoria da Computação
Aula 6
Avisos
●
Hoje tem dúvidas sobre a segunda etapa da
ATPS.
●
Somente 28 alunos/alunas entregaram a ATPS
etapa 1. Ainda dá tempo.
●
Próxima aula será revisão para a prova.
●
Tem uma lista de exercícios para fazer para a
Programas
Um conjunto de operações e testes compostos de
acordo com uma estrutura de controle:
●
Monolíticos: desvios condicionais e incondicionais
●Iterativos: estruturas de iteração
Máquinas
●
Interpreta Programas
●
Possui uma interpretação para cada operação
Computação
●
Histórico do funcionamento da máquina para o
programa e um dado valor inicial.
Função Computada
●
Função parcial induzida a partir da máquina e
programa dados, a qual é definida sempre que,
para um dado valor de entrada, existe uma
Programas
Um conjunto estruturado de instruções que
capacitam uma máquina a aplicar
sucessivamente certas operações básicas e
testes sobre os dados iniciais fornecidos com o
objetivo de transformar esses dados numa forma
desejável.
●
Operações e Testes:
●
Operações: F, G, H...
●Testes: T1, T2, T3...
●Operação Vazia: √
Programa Monolítico
É estruturado com somente desvios condicionais e incondicionais. Não emprega mecanismos auxiliares como iteração, sub-divisão ou recursão, de modo que toda a lógica do programa está contida em um único bloco: um monólito.
Representados facilmente por um fluxograma.
Partida Parada Operação
Exemplo 1
Calcular a soma do números de 1 a 10 utilizando
somente elementos do fluxograma.
início
A = 0
A > 9
A = A + 1
Instruções Rotuladas
Além da forma de um fluxograma, o programa pode ser representado como uma sequência de instruções rotuladas.
Um rótulo ou etiqueta é uma cadeia finita de caracteres constituída de letras ou dígitos.
Uma Instrução rotulada assume as formas:
● Operação: Indica a operação a ser executada seguida de um
desvio incondicional para a instrução subsequente.
– r1: faça F vá_para r2 ou r1: faça √ vá para r2.
● Teste: Determina um desvio condicional, ou seja, que depende da
avaliação de um teste.
Exemplo de Programa Monolítico
1.faça F vá_para 2
2.se T1 então vá_para 1 senão vá_para 3
3.faça G vá_para 4
Definição de Rótulo, Instrução Rotulada
1. Um rótulo ou Etiqueta é uma cadeia de caracteres
finita (palavra) constituída de letras ou dígitos.
2. Uma instrução Rotulada i é uma cadeia de caracteres
finita (palavra) de uma das duas formas a seguir
(suponha que F e T são identificadores de operação e
teste, respectivamente e que r
1, r
2e r
3são rótulos):
2.1 Operação
r
1: faça F vá_para r
2ou r
1: faça √ vá_para r
22.2 Teste
Definição Formal de Programa Monolítico
Um Programa Monolítico é um par P(I, r)
● I: Conjunto Finito de Instruções Rotuladas
● r: Rótulo inicial que distingue a instrução inicial em I
Adicionalmente, relativamente ao conjunto I tem-se que:
● Não existem duas instruções diferentes com o mesmo rótulo. ● Um rótulo não associado a nenhuma instrução é um rótulo final.
A estrutura oferecida pelos programas monolíticos é típica das linguagens de máquinas e de programas montadores (assembly), entretanto isto se reflete de diversas maneiras em linguagens de alto nível.
Exemplos de Programas Monolíticos
1. P
1= (I
1,1) onde I
1é o conjunto constituído pelas
instruções rótuladas 1, 2, 3 e 4 do exemplo
anterior. Neste caso 5 é o rótulo final.
2. P
2= ({r
1: faça √ vá_para r
2}, r
1) onde r
2é um
rótulo final.
Programa Iterativo
● Substituem desvios incondicionais por estruturas cíclicas, permitindo
um melhor controle e manutenção de programas.
● A noção de programa iterativo deu origem às técnicas de
programação estruturada, inspirando toda uma geração de linguagens como Pascal.
● São baseados em três mecanismos de composição de instruções,
encontrados em diversas linguagens: Algol 68, Pascal, Ada, Fortran 90, etc
● Sequencial: composição de dois programas, resultando em um
terceiro, cujo efeito é a execução do primeiro e, após, a execução do segundo programa componente;
● Condicional: composição de dois programas, resultando em um
terceiro, cujo efeito é a execução de somente um dos dois programas componentes dependendo do resultado do teste;
Definição Formal de Programa Iterativo
Um Programa Iterativo P é indutivamente definido como
segue:
a) A operação √ constitui um programa iterativo;
b) Cada identificador de operação constitui um programa
iterativo;
c) Composição sequencial. Se V e W são programas
iterativos, então a composição sequencial denotada por V;W
resulta em um programa iterativo cujo efeito é a execução de
V e, após, a execução de W;
d) Composição condicional. Se V e W são programas
iterativos e se T é um identificador de teste, então a
Definição de Programa Iterativo
e) Composição enquanto. Se V é um programa iterativo e se
T é um identificador de teste, então a composição enquanto
denotada por enquanto T faça (V) resulta em um programa
iterativo que testa T e executa V, repetidamente, enquanto o
resultado do teste for o valor verdadeiro. Caso contrário, a
iteração termina.
f) Composição até. Se V é um programa iterativo e se T é um
identificador de teste, então a composição até denotada por
até T faça (V) resulta em um programa iterativo que testa T e
executa V, repetidamente, enquanto o resultado do teste for o
valor falso. Caso contrário, a iteração termina.
Programa Iterativo
Parênteses
podem ser empregados para mudar uma interpretação:
●
(enquanto T faça V); W
Exemplo de um Programa Iterativo
(se T1
então enquanto T2
faça (até T3 faça (V; W))
senão √)
Observações:
●
É trivial traduzir um programa iterativo para um
Como Podemos Representar um
Programa Iterativo Enquanto como um
Fluxograma?
Programa Recursivo
●
Nas linguagens de programação em geral o
conceito de programa recursivo aparece
associado ao de sub-rotinas recursivas.
●
Recursão é uma forma indutiva de definir
programas.
●
Sub-rotinas permitem a estruturação
hierárquica dos programas, possibilitando
níveis diferenciados de abstração.
Definição Expressão de Sub-Rotinas
Uma Expressão de Sub-Rotinas, ou simplesmente Expressão é indutivamente definida como se segue:
● A operação vazia, √, constitui uma expressão de sub-rotinas.
● Cada identificador de operação constitui uma expressão de
sub-rotinas.
● Composição sequencial: Se D
1 e D2 são expressões de sub-rotinas,
então a composição sequencial denotada por: D1 ; D2 resulta em uma expressão de sub-rotinas cujo efeito é a execução de D1 e, após a execução de D2;
● Composição condicional: Se D
1 e D2 são expressões de sub-rotinas e
T é um identificador de teste, então a composição condicional
Definição Formal de Programa Recursivo
Um Programa Recursivo P tem a seguinte forma:
●
P é E
0
, onde R
1def E
1, R
2def E
2, ..., R
ndef E
nOnde, para k є {1, 2, …,n}
●
E
0
: Expressão Inicial, que é uma expressão de
sub-rotinas.
●
E
k
: Expressão que define R
k, isto é, a expressão que
define a sub-rotina identificada por R
kAdicionalmente, para cada identificador de sub-rotina
referenciado em alguma expressão, existe uma
Raciocínio Recursivo
●
Lógica Recursiva.
●
Pilha de Dados e Operações.
Exemplo de Programa Recursivo:
●
P é R; S, onde:
R def F; (se T então R senão G; S)
S def (se T então √ senão F; R)
●
Exemplos Concretos:
Máquinas
●
As máquinas interpretam os programas suprindo todos os
recursos necessários para realizar a computação que eles
representam.
●
Cada identificador de operação ou teste interpretado pela
máquina deve ser associado a uma transformação na
estrutura da memória e a uma função verdade
respectivamente.
●
Nem todo identificador de operação ou teste é definido em
uma máquina.
●
Para cada identificador de operação ou teste definido em
uma máquina existe somente uma função associada.
Adicionalmente a máquina deve descrever o
Definição de Máquina
Uma máquina é uma héptupla: M = ( V, X, Y, π
X, πY, ΠF, ΠT ), onde: ● V – Conjunto de Valores de Memória
● X – Conjunto de Valores de Entrada ● Y – Conjunto de Valores de Saída ● π
X – Função de Entrada, tal que πX: X→V ● π
Y – Função de Saída, tal que πY: V → Y ● Π
F – Conjunto de Interpretações de Operações tal que, para cada
identificador de operação F interpretado por M, existe um única função
● π
F: V → V em ΠF ● Π
T – Conjunto de Interpretações de Testes tal que, para cada identificador
de teste T interpretado por M, existe uma única função:
● π
T: V → {verdadeiro, falso} em ΠT
Os conjuntos de interpretações podem ser vistos como conjuntos de funções, indexadas pelo subconjunto de identificadores de operações e testes para os
Exemplo: Máquina de Dois Registradores
Seja uma máquina com
dois registradores, a e b,
que assumem valores em
N, com duas operações e
um teste:
●
Subtrair 1 de a, se a > 0.
●Adicionar 1 em b.
●
Teste se a é zero.
Adicionalmente valores de
entrada são armazenados
em a (zerando b) e a saída
Implementação
dois_reg = ( N2, N, N, armazena_a, retorna_b,
{subtrai_a, adiciona_b}, {a_zero} ), onde:
● V = N2 = Conjunto de valores de memória. ● X = N = Conjunto de valores de entrada ● Y = N = Conjunto dos valores de saída
● armazena_a: N → N2, tal que, para todo n є N,
armazena_a(n) = (n, 0)
● retorna_b: N2 → N tal que, para todo n,m є N2,
retorna_b(n, m) = m
● subtrai_a: N2 → N2 tal que, para todo (n, m) є N2, ● subtrai_a(n, m) = (n-1, m), se n ≠ 0,
● subtrai_a(n, m) = (0, m), se n = 0.
● adiciona_b: N2 → N2 tal que, para todo (n, m) є N2,
Registradores
(O registrador de uma CPU (unidade central de processamento) são unidades de memória capazes de armazenar n bits. Os registradores estão no topo da hierarquia de memória, sendo assim, são o meio mais rápido e caro de se armazenar um dado. São utilizados na execução de programas de computadores, disponibilizando um local para armazenar dados. Na maioria dos computadores modernos, quando da execução das instruções de um programa, os dados são movidos da memória principal para os registradores. Então, as instruções que utilizam estes dados são executadas pelo processador e, finalmente, os dados são movidos de volta para a memória principal.)
Definição: Programa para uma Máquina
Diz-se que P é um programa para a máquina M se cada
operação e teste em P corresponder a uma interpretação em
M.
Formalmente:
Seja
M = ( V, X, Y, πX, πY, ΠF, ΠT ), uma máquina e P um programa onde
P
Fe P
Tsão conjuntos de operações e testes de P. P é um
programa para a máquina M se e somente se:
●
Para toda F em P
F
, existe uma única função
πF: V → V em ΠF.
●
Para todo T em P
T
, existe uma única função
πT: V → V em ΠT.
Exemplo: Programa para a Máquina de Dois
Registradores
Os programas iterativo itv_b ← a e recursivo rec_b ← a são programas para a máquina dois_reg e atribuem o valor armazenado em a ao
registrador b.
Programa Iterativo itv_b ← a
Até a_zero
faça (subtrai_a; adiciona_b)
Programa Recursivo rec_b ← a
Computações e Funções Computadas
Uma computação é, resumidamente, um histórico do funcionamento da máquina para o programa, considerando um valor inicial.
Uma computação de um programa monolítico em uma máquina é um histórico de instruções executadas e o correspondente valor de
memória. O histórico é representado como uma cadeia de pares onde:
● Cada par reflete um estado de máquina para o programa, ou seja, a
função a ser executada e o valor corrente de memória.
● A cadeia reflete uma sequência de estados possíveis a partir do
Definição: Computação de um Programa
Monolítico em uma Máquina
Seja M = ( V, X, Y, π
X, πY, ΠF, ΠT ), uma máquina e P = (I, r) um programa
monolítico para M, onde L é o seu correspondente conjunto de rótulos. Uma computação do programa monolítico P para a máquina M é uma cadeia (finita ou infinita) de pares de L x V (s0,v0)(s1,v1)(s2,v2)... onde so = r é o rótulo inicial do programa P e vo é o valor inicial de memória e, para cada par (sk,vk) da cadeia, onde K є (0,1,2,...), tem-se que (suponha que F é um identificador de operação, T é um identificador de teste e r', r'' são rótulos de L):
a) Operação:
a.1) Se sk é o rótulo de uma operação da forma: sk: faça F vá_para r’
então (sk+1, vk+1 ) = (r’, πF(vk)) é par subsequente de (sk, vk) na cadeia. a.2) Se sk é o rótulo de uma operação da forma sk: faça √ vá_para r’, então (s , v ) = (r’, v ) é par subsequente de (s , v ) na cadeia.
Definição: Computação de um Programa
Monolítico em uma Máquina
b) Teste:
● Se s
k é o rótulo de um teste da forma sk: Se T então vá_para r’ senão
vá_para r”, então (sk+1, vk+1 ) é par subsequente de (sk, vk) na cadeia , sendo que vk+1 = vk e:
i. sk+1 = r’ se πT(vk) = verdadeiro ii. sk+1 = r” se πT(vk) = falso
Uma computação é dita Finita ou Infinita, se a cadeia que a define é finita ou infinita, respectivamente.
Observações
●
A computação pode ser finita ou infinita,
conforme a cadeia for finita ou infinita.
●
Para um dado valor inicial de memória, a
correspondente cadeia de computação é única,
ou seja, a computação é determinística. Por
que?
●
Um teste e a operação vazia não alteram o
conteúdo de memória.
Exemplo: Computação Finita
Computação Finita de
Programa Monolítico na
Máquina de Dois
Registradores
1. Se a_zero então vá_para
9 senão vá_para 2.
2. faça subtrai_a vá_para 3.
3. faça adiciona_b vá_para 1.
(sk, vk) Ação
(1,(3,0)) Instrução inicial e valor de entrada armazenado. Em 1, como a<>0, desviou para 2.
Em 2, subtraiu 1 do registrador a e desviou para 3.
(2,(3,0)) (3,(2,0))
(1,(2,1)) Em 3, adicionou 1 ao valor de b e desviou para 1, Em 1, como a<>0, desviou para 2.
Em 2, subtraiu 1 do registrador a e desviou para 3.
(2,(2,1)) (3,(1,1))
(1,(1,2)) Em 3, adicionou 1 ao valor de b e desviou para 1, Em 1, como a<>0, desviou para 2.
Em 2, subtraiu 1 do registrador a e desviou para 3.
(2,(1,2)) (3,(0,2))
Exemplo: Computação Infinita
1. faça adiciona_b vá_para 1.
Porque é infinita?
Computação de um Programa Recursivo em
uma Máquina
A computação de um programa recursivo em uma
máquina é análoga a de um monolítico. O
histórico é representado na forma de uma cadeia
de pares onde:
●
Cada par reflete um estado da máquina para o
programa, ou seja, a expressão de sub-rotina a ser
executada e o valor corrente da memória;
●
A cadeia reflete uma sequência de estados
Definição: Computação de um Programa
Recursivo em uma Máquina
Seja M = ( V, X, Y, π
X, π
Y, Π
F, Π
T), uma máquina e P um programa
recursivo para M, tal que:
P é E
0onde R
1def E
1, R
2def E
2, ..., R
ndef E
m.
Uma computação do programa recursivo P na máquina M é uma
cadeia (finita ou infinita) de pares da forma:
(D
0, v
0)(D1, v1)(D2, v2)...
Definição: Computação de um Programa
Recursivo em uma Máquina
Para cada par (Dk, vk), supondo que F é um identificador de operação, T é um identificador de teste e C, C1 e C2 são expressões de sub-rotinas:
● Caso 1: D
k = √; C → (Dk+1, vk+1) = (C, vk) é par subsequente de (Dk, vk) na cadeia. ● Caso 2: D
k = F; C → (Dk+1, vk+1) = (C, πF(vk)) é par subsequente de (Dk, vk) na
cadeia. ● Caso 3: D
k = Ri; C → (Dk+1, vk+1) = (Ei;C, vk) é par subsequente de (Dk, vk) na cadeia. ● Caso 4: D
k = (C1; C2); C → (Dk+1, vk+1) = (C1;(C2;C), vk) é par subsequente de (Dk,
vk) na cadeia. ● Caso 5: D
k = Ek = (Se T então C1 senão C2); C → (Dk+1, vk+1) é par subsequente de
(Dk, vk) na cadeia, sendo que:
– Vk+1 = vk
Definição: Computação de um Programa
Recursivo em uma Máquina
Observações:
●
A computação pode ser finita ou infinita
conforme a cadeia for finita ou infinita.
●
A computação é determinística (por quê?)
●Teste ou referência a uma sub-rotina não
alteram o valor da memória.
●
Em uma computação finita, a expressão vazia
ocorre no último par da cadeia e não ocorre em
nenhum outro par.
Exemplo: Computação Finita de Programa
Recursivo
Considere o programa a seguir: duplica é R onde
R def (se zero então √ senão sub; R; ad; ad) Para a seguinte máquina:
um_reg = (N, N, N, idN, {ad, sub},{zero}) Onde:
– N corresponde, simultaneamente, aos conjuntos de valores de
memória, entrada e saída.
– IdN: é a função de entrada e de saída
– ad: N → N é interpretação tal que, para qualquer n є N,
ad(n)=n+1
– sub: N → N é interpretação tal que, para qualquer n є N:
● sub(n) = n-1, se n ≠ 0; sub(n) = 0, se n = 0.
Exemplo: Computação Finita de Programa
Recursivo
Para o valor inicial de memória 3, a correspondente computação finita deve ser representada como:
(R; √ ;3) Valor de entrada armazenado
((se zero então √ senão (sub; R; ad; ad)); √ , 3)
Caso 3
((sub;R;ad;ad); √ ,3) Como n ≠ 0, executa senão
(sub; (R;ad;ad); √ ,3) Caso 4, composição sequencial
((R;ad;ad); √ ,2) Subtraiu 1 da memória
(R; (ad;ad); √ ,2) Caso 4, composição sequencial
((se zero então √ senão (sub;R;ad;ad)); (ad;ad); √ , 2)
Caso 3
((sub;R;ad;ad);(ad;ad); √ , 2) Como n ≠ 0, executa senão
Exemplo: Computação Finita de Programa Recursivo
(R; (ad,ad) ; (ad;ad) ; √ ,1) Caso 4, composição sequencial ((se zero então √ senão (aub;R;ad;ad)); (ad;ad);
(ad;ad); √ ,1) Caso 3
((sub;R;ad;ad));(ad;ad);(ad;ad); √ ,1) Como n ≠ 0, executa senão (sub; (r;ad;ad);(ad;ad);(ad;ad); √ , 1) Caso 4, composição sequencial ((R;ad;ad);(ad;ad);(ad;ad); √ ,0) Subtraiu 1 da memória
(R; (ad;ad);(ad;ad);(ad;ad); √ ,0) Caso 4, composição sequencial ((se zero então √ senão (sub;R;ad;ad;));(ad;ad);
(ad;ad);(ad;ad); √ , 0) Caso 3
(√ ; (ad;ad);(ad;ad);(ad;ad); √ ;0) Como n=0, executa então ((ad;ad);(ad;ad);(ad;ad); √ ,0) Caso 1
(ad;(ad;(ad;ad);(ad;ad); √ ),0) Caso 4, composição sequencial ((ad;(ad;ad);(ad;ad); √ ),1) Adicionou 1 na memória
(ad;((ad;ad);(ad;ad); √ ,1) Caso 4, composição sequencial (((ad;ad);(ad;ad); √ ),2) Adicionou 1 na memória
(ad;(ad;(ad;ad); √ ),2) Caso 4, composição sequencial ((ad;(ad;ad); √ ). 3) Adicionou 1 na memória
(ad; ((ad;ad); √ ), 3) Caso 4, composição sequencial (((ad;ad); √ ), 4) Adicionou 1 na memória
Exemplo: Computação Finita de
Programa Recursivo
●
Note-se que o valor final da memória é o valor
inicial duplicado.
●
Observe-se que, usando a noção de recursão,
não foi necessário utilizar duas células de
memória, uma para controlar o ciclo e outra
para calcular o resultado.
●
De fato, a facilidade de recursão é usada para
determinar quantas vezes a operação ad
necessita ser executada.
Exercícios
1. Usando apenas os símbolos de fluxograma, representar um programa monolítico para calcular a soma dos 100 primeiros números ímpares.
2. Fazer o fluxograma do programa iterativo do exemplo dado em aula.
3. Desenhe um fluxograma que corresponde a cada um dos seguintes programas: 1. P2 = ({r1: faça √ vá_para r2}, r1);
2. Composição até (programa iterativo); 3. Programa sem instrução alguma; 4. Programa em loop.
4. Por que pode-se afirmar que a tradução de um programa iterativo para um monolítico é trivial?
5. Por que é possível afirmar que a computação de um programa monolítico em uma máquina, para um dado valor inicial de memória, é determinística?
6. Dê a definição forma da função computada (W,M) de um programa iterativo W em uma máquina M.
Exercícios
1. Traduza o fluxograma do programa monolítico abaixo em um programa recursivo. Início T1 F V T2 G Fim F V F
Exercícios
1. Traduza os fluxogramas dos programas monolíticos abaixo programas recursivos.