Vous êtes sur la page 1sur 40

Capítulo 8 - Funções recursivas

Neste capítulo aborda-se a problemática da definição recursiva de funções1. Começa-se pela definição de
sucessões por recursão, ou recorrência, mostra-se, em seguida, que o método de definição recursiva de
sucessões se pode generalizar a aplicações definidas sobre conjuntos livrementos gerados, e conclui-se,
mostrando que tal método pode ainda ser generalizado para definir recursivamente aplicações definidas sobre
quaisquer conjuntos nos quais esteja disponível uma relação bem fundada.
Aproveita-se ainda este capítulo para ilustrar como os resultados obtidos podem ser utilizados para
fundamentar a programação recursiva, praticada na disciplina (anterior) de "Paradigmas da Programação",
analisando alguns exemplos de programas recursivos desenvolvidos nessa disciplina.
Finalmente, como anexo a este capítulo, efectua-se uma comparação entre uma prova por indução e a
definição recursiva de uma função (no caso de um programa escrito na linguagem de programação
Mathematica).

Secção 1: Definição de sucessões por recursão (ou recorrência).

O método da definição de funções, por recursão, é muito importante e muito utilizado.


Informalmente, uma função diz-se definida recursivamente se a função se define à custa de si própria.
Naturalmente, isto, dito assim, diz pouco, e levanta dúvidas sobre se uma tal função está bem definida.
Neste capítulo procuraremos caracterizar melhor este conceito informal e veremos algumas condições que
garantem que tal (poderoso) mecanismo de definição de funções não é problemático.
Começaremos (nesta secção) por um caso bem conhecido dos alunos - a definição recursiva de
sucessões - e depois procuraremos generalizar os resultados estabelecidos.
Mais precisamente, nesta secção, iremos considerar a definição recursiva de sucessões de elementos de
um conjunto V, indexadas por |N0, i.e., usando a designação sintética, de sucessões0 de elementos de V
(entendidas como aplicações u: |N0V). Tal não é de modo algum indispensável para o que se segue
(podendo considerar-se antes2, alternativamente, p.ex. sucessões de elementos de V indexadas por |N1), mas
permite-nos mais facilmente fazer o paralelismo entre o método de definição de sucessões por recursão e o
método de prova por indução finita nos naturais, abordado na secção 1 do capítulo anterior.
É frequente definir sucessões por recursão, ou (também se diz) por recorrência, e os alunos já se
depararam com várias sucessões definidas por recorrência. Este método de definição de sucessões por

1 Não é essencial que os alunos, a que se dirige este texto, estudem as demonstrações dos resultados incluídos neste capítulo.

Aliás, mais do que conhecer até o próprio enunciado preciso de alguns dos resultados mais genéricos referidos neste capítulo, o

que é fundamental é que os alunos percebam a essência do método de definição por recursão de uma função, em cada um dos

casos aqui tratados, e que se apercebam da importância da existência destes resultados, que permitem fundamentar tal método.
2 Uma vez que o enunciado e demonstração dos (primeiros três) teoremas a seguir é trivialmente adaptável à consideração de

aplicações u definidas em |N1 (em vez de em |N0 ). Refira-se, aliás, que na última secção deste capítulo veremos como tais

teoremas podem ser também obtidos como casos particulares de um resultado mais geral.

277
recorrência tem muitas semelhanças com o método de prova por indução, apesar de serem coisas distintas3.
A definição, por recorrência, de uma sucessão u (de elementos de um conjunto V) consiste em duas coisas:
i) Dizer qual o valor (explícito) do primeiro termo da sucessão.
(Isto é, no caso que iremos considerar de uma sucessão0, u: |N0V, dizer a que é igual u(0).)
A chamada base da definição recursiva, ou condição inicial.
ii) Indicar como se calcula cada um dos outros termos à custa do termo anterior.
Isto é, para cada índice n distinto do inicial (i.e. para cada n1, no caso das sucessões0) indicar a regra
de cálculo que permite obter o valor de u(n) à custa do valor de u(n-1) (ou, de forma equivalente, indicar
para cada índice n, como obter o valor de u(n+1) à custa do valor de u(n)):.
O chamado passo da recursão, ou a equação de recorrência.
A este par de componentes da definição por recorrência - condição inicial e equação de recorrência - também
se chama uma relação de recorrência.
Vejamos um exemplo (relacionado com o problema das chamadas "torres de Hanoi", a abordar no
próximo capítulo):

Exemplo 1:
Uma sucessão0 de naturais u (isto é, a aplicação u: |N0|N0) pode ser definida pela seguinte relação de
recorrência (onde se usa a notação usualmente considerada para as famílias):
i) u0 = 0 (isto é, u(0) = 0)
ii) un+1 = 2 un +1 , para n0 (qualquer)


Nesta secção, já a seguir, iremos mostrar que a definição anterior não é problemática, no sentido de que
existe uma e uma só aplicação de |N0 em |N0 que satisfaz simultaneamente i) e ii).
Embora tal seja fundamental, na prática isso em geral não nos chega. Gostaríamos de ter uma definição
explícita de un (para qualquer n0), que nos dissesse directamente qual o valor de un (como função de n),
em vez de dispor apenas de uma definição recursiva, para evitar que para obter o valor de u500 tenhamos de
calcular sucessivamente u1, u2, u3, u4, u5, ...., u499. A importância prática da obtenção de "soluções
explícitas” para estas relações de recorrência justifica que se introduzam algumas técnicas para a resolução
de relações de recorrência, o que será deixado para o próximo capítulo.
Vejamos, então, que definições como a anterior, não são problemáticas.
Comecemos por abstrair o conceito de relação de recorrência ilustrado no exemplo 1.
Queremos definir uma sucessão0 u de elementos de um conjunto V (os elementos da sucessão0 u não
têm de ser obviamente naturais), que satisfaça as seguintes condições:
i) Condição inicial: tem-se u0 = a, com a um elemento de V
ii) para uma certa aplicação T:VV verifica-se a seguinte equação de recorrência:
un+1 = T(un), para qualquer natural n (ou, equivalentemente, un = T(un-1), para qualquer natural n>0)
A aplicação T traduz a regra de cálculo mencionada acima.

3 Um é um método de definição de funções e o outro um método de prova.

278
No caso do exemplo 1, V era |N0, a era 0 e T era a aplicação T: |N0|N0 dada por T = x.2x+1
A existência e unicidade de uma tal sucessão u é estabelecida no resultado a seguir.
Apesar do resultado a seguir estar de acordo com a nossa intuição, a sua demonstração (mais
precisamente, a demonstração da parte da existência) é um pouco mais complexa do que se poderia esperar
à primeira vista, e poderá ser omitida (nomeadamente numa primeira leitura).

Teorema 1:
Sejam V um conjunto e T uma aplicação de V em V (i.e. T: V  V). Então, para cada a  V, existe
uma, e uma só aplicação u: |N0  V que verifica as seguintes condições:
i) u(0) = a
ii) u(n+1) = T(u(n)), para qualquer natural n
(ou, equivalentemente, u(n) = T(u(n-1)), para qualquer n>0)
Demonstração (a demonstração da existência pode ser omitida, nomeadamente numa primeira leitura):
Comecemos pela unicidade, que se demonstra facilmente por indução.
Suponha-se que existem aplicações u1: |N0 V e u2: |N0V, cada uma delas verificando i) e ii), e
demonstremos, pel(a versão simples d)o princípio de indução finita que
n|N0 u1(n) = u2(n) (pelo que u1 = u2, c.q.d.)
Base:
Por i), u1(0) = a = u2(0)
Passo de indução:
Seja n0 qualquer, e suponha-se que se verifica u1(n) = u2(n) (HI).
Queremos demonstrar que então u1(n+1) = u2(n+1) (a tese da indução). Ora:
u1(n+1)
= por ii)
T(u1(n))
= por HI
T(u2(n))
= por ii)
u2(n+1) (c.q.d.)
Demonstremos agora a existência:
Comecemos por demonstrar, por indução (simples) "em k", que:
para cada k0 existe uma e uma só função u(k): [0,k]V (com [0,k] = {n|N0: 0nk})
que verifica i) e ii) no intervalo [0,k], isto é, que satisfaz:
k-i) u(k)(0) = a
k-ii) u(k)(n+1) = T(u(k)(n)), para qualquer natural n<k (condição relevante só se k>0)
Base:
para k=0, é imediato que existe uma e uma só função u(0): [0,0]V que verifica as condições
anteriores, que é dada por u(0)(0) = a
Passo de indução:

279
Seja k0 qualquer, e suponha-se que existe uma e uma só função u(k): [0,k]V que verifica as
condições k-i) e k-ii) (HI).
Queremos demonstrar que existe uma e uma só função u(k+1): [0,k+1]V que verifica as condições
(k+1)-i) u(k+1)(0) = a
(k+1)-ii) u(k+1)(n+1) = T(u(k+1)(n)), para qualquer natural n<k+1
Defina-se u(k+1): [0,k+1]V como se segue:
se 0nk, então u(k+1)(n) = u(k)(n)
u(k+1)(k+1) = T(u(k)(k))
É fácil verificar que u(k+1): [0,k+1]|N0 está bem definida e também (usando HI) que u(k+1) verifica
as condições (k+1)-i) e (k+1)-ii).
Resta-nos provar que é a única função nessas circunstâncias, o que se pode mostrar por um método
análogo ao usado em cima para demonstrar a unicidade de u.
Defina-se agora a aplicação u: |N0V (desejada) como se segue:
qualquer que seja o natural n, u(n) = u(n)(n)
É imediato que u está bem definida. Resta mostrar que u satisfaz i) e ii):
i) u(0) =u(0)(0) = a
ii) Seja n0 qualquer. Então:
u(n+1) = u(n+1)(n+1) = T(u(n)(n)) = T(u(n))


O resultado anterior pode ser generalizado em vários sentidos. Vejamos algumas das generalizações
possíveis.
Em primeiro lugar, não é obrigatório que a regra de cálculo de u(n+1) à custa de u(n) tenha de ser a
mesma para todo o natural n.
Por exemplo, podemos conceber casos em que a regra de cálculo é diferente para o caso em que n é par
e para o caso em que n é ímpar. Olhando para a demonstração anterior, pode constatar-se que ela pode ser
adaptada ao seguinte caso mais geral, em que
i) u(0) = a
ii) u(n+1) = Tn(u(n))
com, para cada natural n, Tn uma aplicação de V em V (i.e. Tn: V  V), que denota a regra a aplicar à
construção de u(n+1) à custa de u(n).
Por outro lado, em vez de considerarmos uma família (Tn)n|N0 de aplicações de V em V, podemos
considerar antes que temos uma aplicação4 T: |N0 x V  V, em que (quaisquer que sejam n|N0 e vV)

4 A ordem dos argumentos de T é irrelevante, mas temos de fixar alguma. Refira-se, ainda, que em vez de considerarmos em ii)

acima que "u(n+1) = Tn (u(n)) = T(n,u(n))", também poderíamos antes ter suposto que "u(n+1) = Fn + 1(u(n)) = F(n+1,u(n))", com

a "regra" F uma aplicação F: |N0 x V  V (ou F: |N1 x V  V). De facto, é imediato que uma “regra de cálculo” T que usa

(n,u(n)) pode ser transformada numa “regra de cálculo” F equivalente que usa (n+1,u(n)), e vice-versa (basta considerar que

F(m,v)=T(m-1,v), para m1 e vV, e, vice-versa, que T(n,v) = F(n+1,v), para n0 e vV). Considerações análogas podem ser

feitas a propósito de ii) do enunciado dos teoremas 2 e 3 a seguir.

280
T(n, v) = Tn(v)
(informalmente, passamos a ver o índice n como um argumento da função/regra T).
Somos assim conduzidos ao seguinte resultado (do qual o teorema 1 é um caso particular, em que
T(n,v) = T(k,v), para quaisquer n,k|N0 e vV):

Teorema 2 (Generalização do teorema 1):


Seja V um conjunto e seja T uma aplicação T: |N0 x V  V.
Então, para cada a  V, existe uma, e uma só aplicação u: |N0V que verifica as seguintes condições:
i) u(0) = a
ii) u(n+1) = T(n, u(n)), para qualquer natural n
(ou, equivalentemente, u(n) = T(n-1, u(n-1)), para qualquer n>0)


Por outro lado, no(s) teorema(s) anterior(es), apenas se considerou a definição, por recursão, de funções
de um argumento. Ora, é fácil verificar que o facto de a função u (em definição) ter mais do que um
argumento não afecta o exposto, desde que a recursão seja feita num só argumento (correspondente à
chamada variável da recursão), uma vez que, nessa situação, os outros argumentos funcionam apenas como
parâmetros.
De facto, suponha-se, por exemplo, que B e V são dois conjuntos quaisquer, e que se pretende definir
uma aplicação u: B x |N0  V, por recorrência no seu segundo argumento.
Seja bB qualquer. Pelo teorema anterior podemos definir, por recorrência, uma aplicação ub: |N0  V,
satisfazendo:
i) ub(0) = a, com aA
ii) ub(n+1) = T(n, ub(n)), para qualquer natural n
E a partir daí podemos definir u: Bx|N0  V, como se segue: u(b,n) = ub(n) (para quaisquer bB e n|N0).

Por outro lado, em i), o valor aA (não pode depender de outros valores ub(n), mas) não tem de ser o
mesmo para todos os b's. O que temos é de, para cada bB, definir explicitamente qual o valor que ub
toma em 0. Logo, a aplicação u:Bx|N0V, a definir por recorrência, deverá satisfazer (para qualquer bB):
i) u(b, 0) = g(b), para alguma aplicação g: B  V
ii) u(b,n+1) = T(n, u(b,n)), para qualquer natural n

Exemplo 2:
A soma de naturais pode definir-se por recorrência como se segue (recorde a observação 1-c) da secção 2 do
capítulo anterior):
Quaisquer que sejam os naturais m e n:
• m+0=m (isto é, +(m,0) = g(m), com g a função identidade)
• m + (n+1) = (m+n) + 1 (isto é, +(m,n+1) = T(n, +(m,n)), com T: |N0x|N0  |N0 dada por
T = x,y.(y+1), i.e., T(x,y) = y+1)


281
Analogamente, em ii), na definição de u(b,n+1) à custa de u(b,n), a regra a aplicar, tal como podia
depender de n, também pode depender de b.
Dito de outra forma, podemos dizer que temos uma aplicação5 T: Bx|N0xVV, e que u: Bx|N0V
tem de verificar as seguintes condições (para quaisquer bB e n|N0):
i) u(b, 0) = g(b), com g:BV
ii) u(b, n+1) = T(b, n, u(b,n))

Exemplo 3:
O produto de naturais pode definir-se por recorrência como se segue (recorde a observação 1-c) da secção 2
do capítulo anterior):
Quaisquer que sejam os naturais m e n:
• m*0=0 (isto é, *(m, 0) = g(m), com g a função constantemente igual a 0)
• m * (n+1) = (m*n) + m (isto é, *(m,n+1) = T(m, n, *(m,n)), com T: |N0x|N0x|N0  |N0
dada por T = x,y,z.(z+x), i.e., T(x,y,z) = z+x)


E, naturalmente, a situação não se altera se a aplicação u tiver mais argumentos.


Podemos, assim, enunciar o seguinte resultado mais geral (onde alguns, ou todos os conjuntos Bi
poderão, ou não, ser iguais a |N0, ou a V, e onde se supõe, para simplificar, que o argumento da recursão
de u é o último, embora tal não seja obviamente necessário):

Teorema 3 (Generalização do teorema 2):


Sejam
• k0,
• B1, ..., Bk e V conjuntos,
• aV se k=0 e g: B1x...xBk  V se k>0,
• e T: B1 x ... x Bk x |N0 x V  V (entendido como T: |N0 x V  V, se k = 0)
Então, existe uma, e uma só aplicação u: B1 x...x Bk x |N0  V que verifica as seguintes condições:
Quaisquer que sejam b1B1, ..., bkBk, n|N0,
i) u(b1, ..., bk, 0) = g(b1, ..., bk), se k>0, e u(b1, ..., bk, 0) = a, se k = 0
ii) u(b1, ..., bk, n+1) = T(b1, ..., bk, n, u(b1, ..., bk, n))


Observação (Teoria da computabilidade e as funções recursivas):


Em teoria da computabilidade procura-se caracterizar as funções que são computáveis, mostrando-se que são
computáveis, em particular, todas as funções naturais, de variáveis naturais, definidas recursivamente como
no teorema 3 anterior (com B1=...=Bk=V=|N0).

5 A ordem dos argumentos de T continua a ser irrelevante, mas temos de fixar alguma.

282
Permite-se ainda, na definição dessas funções, que as funções g e T possam ser funções parciais. Nesse
caso, a função u, que se obtém, também é uma função parcial, tendo-se que (quaisquer que sejam
b1,...,bk,n|N0):
• (b1, ..., bk, 0)  dom(u) sse (b1, ..., bk)  dom(g) (se k=0, então 0  dom(u))
• (b1, ..., bk, n+1)  dom(u)
sse
(b1, ..., bk, n)  dom(u) e (b1, ...,bk, n, u(b1,...,bk,n))  dom(T)
Refira-se também que se pode considerar formas mais gerais de definir funções naturais, de variáveis
naturais, por recursão, chamando-se então, por vezes, às funções que se podem obter do modo anterior de
funções recursivas primitivas. (A função de Ackermann, apresentada num exemplo à frente, neste capítulo,
é um exemplo de uma função que se pode definir recursivamente, mas que não é recursiva primitiva.)
Sobre o tópico da computabilidade, veja-se, por exemplo, o livro [10].


Secção 2: Definição por recursão sobre conjuntos livrementos gerados.

Podemos ainda generalizar a definição de funções, por recursão, noutros sentidos e, nomeadamente,
considerando que a recursão é efectuada noutros conjuntos, que não |N0 (ou |N1, para o qual se pode
obviamente transpor tudo o que se disse anteriormente, sem qualquer dificuldade). Sobre isso nos vamos
debruçar, nesta (e na próxima) secção. Para simplificar, vamos supor, nesta secção, que a função u, a
definir por recursão, tem um só argumento, mas o que se disse anteriormente sobre a extensão a funções de
vários argumentos permanece válido (assumindo, pelo menos para já, que a recursão é feita sempre num só
argumento).
Comecemos por observar, intuitivamente, porque é que uma definição recursiva de u: |N0V funciona
bem. Designe-se x+1 por s(x) (de sucessor de x).
Ora, como um natural n(>0) pode ser obtido, a partir do 0 aplicando essa operação s, um número finito
de vezes, de uma única forma, através da sequência de construção:
0, s(0), s(s(0), ...., s(...s( 0)...)
nvezes
a definição do valor de u(0) e do modo como se pode obter o valor de u(s(x)) a partir do valor de u(x) (para
qualquer natural x), permite-nos calcular o valor de u(n), de forma unívoca, num número finito (n) de
passos.
Ora, há outros conjuntos, de que falámos na última secção do capítulo anterior, que possuem uma
propriedade análoga: os conjuntos livremente gerados, a partir de S por um conjunto ops de operações.
Assim, também nesses conjuntos deverá ser possível definir funções por recursão. As diferenças em
relação ao teorema 1 da secção anterior são as seguintes:
i) temos de definir o valor de u em cada elemento do conjunto inicial:
pode considerar-se que existe uma aplicação g de S em V, e definir u(x) = g(x), para xS
(podendo dizer-se que a função u, em definição, estende essa função g ao conjunto X)

283
ii) A cada operação f em ops, associamos uma regra de cálculo, que designaremos a seguir de Tf, com a
mesma aridade que f, que é usada para calcular u(f(x1,...,xk)) a partir dos valores de u(x1), ..., u(xk).

Obtem-se, assim, o próximo resultado6:

Teorema 1 (Generalização do teorema 1 da secção 1):


Seja X o conjunto livremente gerado a partir de S (E) por um conjunto ops de operações em E.
Sejam V um conjunto e g uma aplicação7 g: S  V, e, para cada operação f em ops (suposta a seguir de
aridade k1), seja Tf uma aplicação de Vk em V (i.e. Tf: Vk  V).
Então, existe uma, e uma só aplicação u: X  V que verifica as seguintes condições:
i) para todo o8 xS: u(x) = g(x)
ii) para cada f em ops (designando por k a aridade de f, tem-se que), quaisquer que sejam x1,...,xkX,
u(f(x1,...,xk)) = Tf(u(x1), ..., u(xk))
Demonstração (a leitura desta demonstração pode ser omitida):
A ideia é definir u como a "união" de todas as funções que são suas aproximações, a seguir designadas de
aceitáveis9.
Diremos que uma função h: X 
/ V é aceitável, se h verifica as seguintes h-condições:
h-i) se xS e xdom(h), então h(x) = g(x)
h-ii) para cada f em ops (de aridade k), quaisquer que sejam x1,...,xkX:
se f(x1,...,xk)dom(h), então x1,...,xkdom(h) e h(f(x1,...,xk)) = Tf(h(x1), ..., h(xk))
Seja H o conjunto de todas as funções aceitáveis. Note-se que H, pois a função h0: X 
/ V, dada por
dom(h0)=S e h0(x) = g(x), para x em S, é aceitável (repare-se que, como X é livremente gerado, não
existirá f(x1,...,xk)dom(h0)=S).
Defina-se u: X 
/ V como se segue:
qualquer que seja xX
xdom(u) sse xdom(h) para alguma função aceitável h (i.e. dom(u) = U dom(h) )
h aceitável
e qualquer que seja xdom(u), se xdom(h), com h uma função aceitável, então u(x) = h(x)

Temos de verificar que:


a) u: X 
/ V está bem definida
(i.e. que, qualquer que seja xdom(u), existe um e um só vV tal que u(x) = v)

6 Na última secção do capítulo anterior supôs-se que E designava o nosso universo de trabalho e que, portanto, todos os

conjuntos estavam contidos em E. Aqui não se assume o mesmo, pelo que o conjunto V, no resultado a seguir, pode,

inclusivamente, não ter qualquer elemento em comum com o conjunto E.


7 O conjunto de partida de g não tem de ser necessariamente S (pode ser maior); g tem é de ser uma função que esteja definida

em S com valores em V.
8 É imediato que se S for um conjunto singular S={s},, então a condição a seguir é equivalente a dizer que u(s) = a, com aV (a

será o valor de g(s), na formulação indicada).


9 Usando a terminologia que é considerada por Franco de Oliveira, por exemplo no texto [40].

284
b) u é aceitável
(o que implicará que u verifica as condições i) e ii) do enunciado, se se mostrar que dom(u)=X)
c) dom(u) = X (tendo-se então que u: X  V, como se pretendia)
e que
d) u, assim definida, é a única aplicação de X em V que verifica as condições i) e ii) do enunciado.

Demonstração de a):
Seja
U = {xX: quaisquer que sejam h1 e h2 aceitáveis, se xdom(h1) e xdom(h2), então h1(x)=h2(x)}
Se provarmos que U é indutivo wrt(S;ops), então, pelo teorema 7.4.2, U = X (c.q.d.)
É fácil verificar que U é indutivo wrt(S;ops). Vejamos em pormenor:
• Seja xS e sejam h1 e h2 quaiquer funções aceitáveis tais que xdom(h1) e xdom(h2). Então:
h1(x) = g(x) = h2(x)
Logo, se xS então xU.
• Seja f em ops, qualquer (de aridade k), e x1,...,xkU quaisquer.
Queremos provar que f(x1,...,xk)U.
Sejam h1 e h2 quaiquer funções aceitáveis tais que f(x1,...,xk)dom(h1) e f(x1,...,xk)dom(h2).
Queremos provar que h1(f(x1,...,xk))=h2(f(x1,...,xk)). Ora:
Como h1 é aceitável:
f(x1,...,xk)dom(h1) implica que x1,...,xkdom(h1) e h1(f(x1,...,xk)) = Tf(h1(x1), ..., h1(xk)).
Analogamente:
x1,...,xkdom(h2) e h2(f(x1,...,xk)) = Tf(h2(x1), ..., h2(xk)).
Mas x1,...,xkU e x1,...,xkdom(h1) e x1,...,xkdom(h2) implica (pela definição de U) que:
h1(x1) = h2(x1), ..., h1(xk) = h2(xk)
Logo h1(f(x1,...,xk)) = Tf(h1(x1), ..., h1(xk)) = Tf(h2(x1), ..., h2(xk)) = h2(f(x1,...,xk)) (c.q.d.)

Demonstração de b):
Que se verifica u-i) ("se xS e xdom(u), então u(x) = g(x)") é imediato.
Que se verifica u-ii) é também fácil de verificar. Vejamos em pormenor:
Seja f em ops, qualquer (de aridade k), e x1,...,xkX quaisquer, tais que f(x1,...,xk)dom(u).
Queremos provar que x1,...,xkdom(u) e u(f(x1,...,xk)) = Tf,(u(x1), ..., u(xk))
Ora, se f(x1,...,xk)dom(u), então existe h aceitável tal que f(x1,...,xk)dom(h). E:
1)• x1,...,xkdom(h) (pois h é aceitável)
2)• x1,...,xkdom(u) (por 1) e definição de dom(u))
3)• h(f(x1,...,xk)) = Tf(h(x1), ..., h(xk)) (pois h é aceitável)
4)• u(f(x1,...,xk)) = h(f(x1,...,xk)) e u(x1) = h(x1), ..., u(x1) = h(xk) (por definição de u)
5)• u(f(x1,...,xk)) = Tf(u(x1), ..., u(xk)) (por 3) e 4))

Demonstração de c):
Se demonstrarmos que dom(u) é indutivo wrt(S;ops), então pelo teorema 7.4.2, dom(u) = X.
(Nota: é aqui que se usa o facto de X ser livremente gerado, e não simplesmente gerado.)

285
É imediato que S  dom(u), pois (como se viu em cima) h0 é aceitável e dom(h0)=S
Seja f em ops, qualquer (de aridade k), e x1,...,xkdom(u) quaisquer.
Queremos provar que f(x1,...,xk)dom(u).
1)• Seja 1ik. Como xi dom(u), existe hi aceitável tal que xi dom(hi).
2)• Defina-se h: X 
/ V como se segue:
dom(h) = U dom(hi)
1i k

e, qualquer que seja xdom(h), h(x) = hi(x), com 1ik, se xdom(hi)


Pelo que se provou na demonstração de a), é imediato que h está bem definida.
Que h é aceitável, pode verificar-se como se segue (de forma análoga à usada na dem. de b)):
h–i): se xS e xdom(h), então xS e existe 1ik tal que xdom(hi). E, como hi é aceitável,
hi(x) = g(x). Logo, por definição de h, tem-se h(x) = hi(x) = g(x) (c.q.d.)
h–ii) Seja f1 em ops, qualquer (de aridade j), e z1,...,zj X quaisquer, tais que f1(z1,...,zj )dom(h).
Queremos provar que z1,...,zj dom(h) e h(f1(z1,...,zj )) = Tf1(h(z1), ..., h(zj )).
Ora, se f1(z1,...,zj )dom(h), então 1ik e tal que f1(z1,...,zj )dom(hi). E tem-se
1)• z1,...,zj dom(hi) (pois hi é aceitável)
2)• z1,...,zj dom(h) (por 1) e definição de dom(h))
3)• hi(f1(z1,...,zj )) = Tf1(hi(z1), ..., hi(zj )) (pois hi é aceitável)
4)• h(f1(z1,...,zj )) = hi(f1(z1,...,zj )) e h(z1) = hi(z1), ..., h(zj ) = hi(zj ) (por definição de h)
5)• h(f1(z1,...,zj )) = Tf1(h(z1), ..., h(zj )) (por 3) e 4))
3)• Se f(x1,...,xk)dom(h), então (como já vimos que h é aceitável, por definição de u)
f(x1,...,xk)dom(u) (c.q.d.)
4)• Caso contrário (i.e. se f(x1,...,xk)dom(h)), "estende-se h" como a seguir:
Seja h: X 
/ V definida como se segue:
dom(h) = dom(h)  {f(x1,...,xk)}
Qualquer que seja xdom(h), h(x) = h(x)
h(f(x1,...,xk)) = Tf(h(x1), ..., h(xk)) (= Tf(h(x1), ..., h(xk)), pois x1,...,xkdom(h))
É fácil verificar que h está bem definida.
Mostremos que h é aceitável (o que implicará, então, que f(x1,...,xk)dom(u) (c.q.d.))
• Se xS e xdom(h), então (como X é livremente gerado) xf(x1,...,xk) e xdom(h).
Logo xdom(h) e, portanto: h(x) = h(x) = g(x) (pois h é aceitável)
• Seja f1 em ops qualquer e seja j a aridade de f1.
Sejam y1,...,yj X quaisquer tais que f1(y1,...,yj )dom(h).
Quer-se provar que então y1,...,yj dom(h) e h(f1(y1,...,yj )) = Tf1(h(y1), ..., h(yj )).
Se f1(y1,...,yj )dom(h), isso sai de h ser aceitável.
Caso contrário, f1(y1,...,yj )dom(h) e f1(y1,...,yj )dom(h). Logo f1(y1,...,yj ) = f(x1,...,xk)
Ora, como X é livremente gerado, tal implica que f1=f, j=k, y1=x1, ..., yj =xj .
Mas então y1,...,yj  dom(h) (pois (x1,...,xk)  dom(h)  dom(h)) e:
h(f(x1,...,xk))

286
= (por definição de h)
Tf(h(x1), ..., h(xk))
=
Tf1(h(y1), ..., h(yk)) (c.q.d.)

Demonstração de d):
Sejam u1 e u2 aplicações de X em V que verificam as condições i) e ii) do enunciado.
Queremos provar que u1=u2. Tal ficará provado, se demonstrarmos que o conjunto {xX: u1(x)=u2(x)}
é indutivo wrt(S;ops), o que se deixa como exercício.


Exemplo 1:
Seja E, por exemplo, o conjunto dos reais |R e seja X o conjunto gerado a partir de S={0} pelas operações
• f1: |R  |R, dada por f1(x) = x+1
• f2: |R  |R, dada por f2(x,y) = x*y
(Nota: como o produto de dois naturais ainda é um natural, é fácil verificar que X não é mais do que |N0).
Suponha-se, agora, que se pretende definir, por recursão, u: X|R (logo neste caso E=V=|R), satisfazendo:
i) u(0) = 0
ii-f1) u(f1(x)) = u(x)+2 , isto é, u(x+1) = u(x)+2
(na formulação do teorema 1: u(f1(x)) = Tf1(u(x)), com Tf1(y) = y+2)
ii-f2) u(f2(x,y)) = f2(u(x),u(y)) , isto é, u(x*y) = u(x)*u(x)
(na formulação do teorema 1: u(f2(x,y)) = Tf2(u(x),u(y)), com Tf2 = f2)
Ora, se existisse uma função u: X  |R satisfazendo i), ii-f1) e ii-f2), ter-se-ia, por exemplo:
u(1) = u(0+1) = u(f1(0)) = u(0)+2 = 0+2 = 2 e u(1) = u(1*1) = u(f2(1,1)) = u(1)*u(1) = 2*2 = 4
o que é impossível !
O problema não está no teorema 1, demonstrado, mas sim no facto de X não estar nas condições do
teorema. De facto, é fácil verificar que X não é livremente gerado a partir de S={0} pelas operações f1 e f2.


Exemplo 2:
No exemplo 5 da última secção do capítulo anterior considerámos, sobre o conjunto Arv das árvores
(guardando inteiros), as funções "na" (número de arestas) e "nn" (número de nós), satisfazendo:
nn-1) nn(<x>) = 1 (com x inteiro)
na-1) na(<x>) = 0 (com x inteiro)
nn-2) nn(<x,A1,...,Ak>) = 1+nn(A1) + ... + nn(Ak) (com k1, A1,...,Ak árvores e x inteiro)
na-2) na(<x,A1,...,Ak>) = k+nn(A1) + ... + nn(Ak) (idem)
O teorema 1 garante-nos que estas funções (na:Arv|N0 e nn:Arv|N0) estão bem definidas.
De facto, Arv é o conjunto livremente gerado a partir de
• S = {<x> : xZ} (o conjunto das árvores formadas por um só nó)
pelas operações
• fx: ( k1Ek)  E, com x inteiro, dadas por (para qualquer k1 e quaisquer e1,...,ekE)
fx(e1,...,ek) = <x,e1,...,ek>

287
ou, de outro modo equivalente (ver observação 2-c) da secção 4 do capítulo anterior), pelas operações
• f(k)x: Ek  E, com x inteiro e k1, dadas por (para quaisquer e1,...,ekE)
f(k)x(e1,...,ek) = <x,e1,...,ek>
e as condições acima para (por exemplo) "nn" podem ser reformuladas como se segue:
na-1) nn(<x>) = g(<x>) , com g:S|N0 a função constantemente igual a 0
na-2) para cada x inteiro e k1:
na(f(k)x(A1,...,Ak)) = Tk,x(na(A1),...,na(Ak)) (para quaisquer árvores A1,...,Ak),
com Tk,x:|N0k|N0 a regra, associada a f(k)x, dada por Tk,x(n1,...,nk) = k + n1, + .., + nk.


Exemplo 3:
No exemplo 4 (e 9) da secção 4 do capítulo anterior vimos que o conjunto das fórmulas de L¬, é o
conjunto livremente gerado a partir de S={pi ; i1} por f¬ e f.
Assim, a função (utilizada nesse exemplo 4) "npe" - número de parenteses esquerdos - pode ser definida,
para o conjunto das fórmulas, por recursão, como se segue:
i) npe(pi ) = 0
(isto é, na formulação do teorema 1, npe(pi )=g(pi ), com g:S|N0 a função constantemente igual a 0)
ii-¬) para qualquer fórmula :
npe((¬)) = npe() + 1
(i.e., na formulação do teorema 1, npe(f¬()) = T¬(npe()), com T¬:|N0|N0 dada por T¬(x) = x+1)
ii-) para quaisquer fórmulas 1 e 2:
npe((1  2)) = npe(2) + npe(1) + 1
(i.e., na formulação do teorema 1, npe(f(1, 2)) = T(npe(1), npe(2)), com T:|N02|N0 dada
por T(x,y) = x+y+1)


Na secção 1, enunciámos o teorema 2 como uma generalização do teorema 1. A demonstração do


teorema 1 anterior pode igualmente ser adaptada a uma generalização, análoga, desse teorema. O resultado
que se obtém encontra-se a seguir. Refira-se, a propósito, que os enunciados dos teoremas 1 e 2 desta
secção são "mais pesados" do que os enunciados dos correspondentes teoremas 1 e 2 da secção anterior, o
que advém de cobrirem um conjunto mais alargado de casos:

Teorema 2 (Generalização do teorema 1):


Seja X o conjunto livremente gerado a partir de S (E) por um conjunto ops de operações em E.
Sejam V um conjunto e g uma aplicação g: S  V, e, para cada operação f em ops (suposta a seguir de
aridade k1), seja Tf uma aplicação Tf: Xk x Vk  V.
Então, existe uma, e uma só aplicação u: X  V que verifica as seguintes condições:
i) para todo o xS: u(x) = g(x)
ii) para cada f em ops (de aridade k), quaisquer que sejam x1,...,xkX:
u(f(x1,...,xk)) = Tf(x1, ..., xk, u(x1), ..., u(xk))


288
Observação:
Pode verificar-se que a afirmação ii) do teorema anterior é equivalente à seguinte afirmação:
ii') Qualquer que seja o elemento y de X, não pertencente ao conjunto inicial S,
u(y) = Tf(x1, ..., xk, u(x1), ..., u(xk))
com f a única operação em ops e x1,...,xk os únicos elementos de X tais que y = f(x1,...,xk)
(unicidade que resulta de X ser livremente gerado).


Exemplo 4 (Programação recursiva sobre as listas da linguagem de programação Mathematica):


O resultado anterior dá suporte formal à seguinte afirmação (tantas vezes) feita na disciplina de
"Paradigmas da Programação":
Para definir, recursivamente, uma função u sobre qualquer lista w de números, pode (por exemplo):
• Definir qual o resultado na lista {} (i.e., definir u[w] para "w=={}")
• e, para "w!={}", assumir que conhece o resultado u[Drop[w,-1]] e a partir daí definir o resultado
de u[w]
Para o ver, basta ter em linha de conta que o conjunto das listas de números (do Mathematica), a seguir
designado de X, pode ser definido como o conjunto livremente gerado a partir de S = {List[]} pela
"operação Append", e atender a que, por outro lado, qualquer lista w{} pode ser (re-)construída, de uma
única forma, à custa de outra lista, recorrendo à "operação" Append, como
Append[Drop[w,-1],Last[w]]).
A título basicamente ilustrativo, precisemos o que se acabou de dizer (com todo o pormenor).
Em primeiro lugar, tal como definimos o conceito de operação, "Append" não é uma operação, mas
sim (recorde exemplo 6 da secção 4 do capítulo anterior) uma família de operações Appendx : E 
/ E (onde
E designa o conjunto das expressões bem formadas da linguagem Mathematica), com x um número (do
Mathematica), definidas como se segue:
• o domínio de Appendx é formado por todas as expressões da forma List[b1 ,...,bn ] , com b1 ,
...,bn n(0) números,
• e Appendx (List[b1 ,...,bn ]) (= Append[List[b1 ,...,bn ],x]) = List[b1 ,...,bn ,x].
Assim, e de uma forma mais precisa, podemos dizer que o conjunto X das listas de números (do
Mathematica) é o conjunto livremente gerado a partir de S = {List[]} pela família de operações Appendx
(com x um número).
Mas então, de acordo com o teorema 2 e a observação anterior (atender a que as operações Appendx são
operações unárias), existe uma única função u, do conjunto X das listas de números no conjunto resultado
V, em causa, que satisfaz:
i) para todo o w{List[]}: u[w] = g(w), com g: {List[]}  V
isto é, mais simplesmente, u[List[]] é igual a algum elemento de V
ii) qualquer que seja o elemento w de X, não pertencente ao conjunto inicial S (i.e. com wList[])
u[w] = Tf(v, u[v])

289
com f a única operação da forma Appendx e v a única lista tais que w = f(v) e Tf uma aplicação
Tf:XxVV.
Ora, para wList[], tem-se que w = f(v), com f da forma Appendx e v uma lista, sse x é Last[w]
e v é Drop[w,-1]. Logo, escrevendo10 T(x, v, u[v]) em vez de Tf(v, u[v]) com f= Appendx ,
podemos então dizer (usando a notação usual do Mathematica também para nos referirmos ao resultado das
funções e à lista vazia) que:
existe uma e uma só função u: X  V que satisfaz:
i) u[{}] é igual a algum elemento de V
ii) qualquer que seja a lista w diferente da lista vazia,
u[w] = T(Last[w], Drop[w,-1], u[Drop[w,-1]])
Mais ainda, como é claro da equação da recursão, no passo de recursão, para definirmos o resultado de
u[w] podemos referir-nos ao elemento Last[w], à lista Drop[w,-1] e ao valor u[Drop[w,-1]],
aplicando-lhes a regra T apropriada.
E era precisamente isto que fazíamos em "Paradigmas da Programação" quando definíamos
recursivamente uma função (de um argumento11) sobre listas.
Muitas vezes, alternativamente, definíamos u[w], para w{}, à custa de First[w] e Rest[w]: o
tratamento formal deste caso é perfeitamente análogo ao anterior.
Outra possibilidade, explorada mais raramente, consistia em definir u[w], para w{}, à custa do valor
de u noutras sublistas próprias de w. Os resultados da próxima secção darão suporte formal a esses casos.


Secção 3: Definição por recursão sobre conjuntos com uma relação bem fundada.

Os resultados enunciados suportam vários tipos de definição de funções por recursão. Existem, no
entanto, ainda casos de definição de funções por recursão, em que estamos interessados, que não são
cobertos por estes resultados.
A título ilustrativo, podemos mencionar a sucessão an , dada por
a0 = 7
a1 = 16
an = 5 an-1 - 6 an-2, para todo o n2
considerada no exemplo 5 da secção 1 do capítulo anterior.
Iremos, em seguida, mostrar como os resultados anteriores podem ser generalizados de modo a permitir
a definição de funções por recursão sobre quaisquer conjuntos nos quais está definida uma relação bem
fundada, o que permitirá cobrir casos como o anterior, e outros casos.

A ideia é simples:

10 Isto é, passando o índice x para argumento da função T, e vendo T como uma aplicação T: B x X x V  V (designando por

B o conjunto dos números do Mathematica).


11 Como já referimos, o facto da função u em definição ter mais argumentos não afecta a análise anterior (basta usar uma mera

extensão destes resultados, embora de enunciado "mais pesado"), desde que a recursão seja feita num só argumento.

290
Seja p uma relação bem fundada em X. Então, para definir uma aplicação u: X  V, basta:
i) definir qual o valor de u nos elementos minimais de X (em relação a p )
ii) dizer como se obtém o valor de u, num (qualquer) elemento não minimal y (de X), à custa dos valores
que u toma nos elementos x de X que são "menores" que y (i.e. que satisfazem x p y)
Mas, apesar da ideia anterior ser simples, a formalização de ii) tem de ser feita com cuidado.
A tentativa mais óbvia de formalização seria:
ii) definir u(y), para y não minimal, à custa de {u(x): x p y}
De acordo com esta ideia a função/regra de cálculo T a usar seria aplicada a um conjunto {u(x): x p y}
de valores em V. Mas neste conjunto não só eventuais repetições de elementos são "colapsadas" num só
elemento, como se perde a referência aos elementos x ( p y) dos quais os valores u(x) são provenientes. O
problema anterior é facilmente resolvido, se "a nossa regra de cálculo" T, que é usada para calcular u(y),
em vez de receber "como informação" (como argumento) o conjunto de valores {u(x): x p y}, passar a
receber como argumento o próprio conjunto12 {(x, u(x)): x p y}, definindo-se então:
ii) u(y) = T({(x, u(x)): x p y}), para y não minimal
Procuremos agora caracterizar mais formalmente qual o tipo de argumento da nossa regra de cálculo T.
Parece claro que T deve receber como argumento uma relação binária R entre X e V (uma vez que os
pares (x, u(x)) são formados por um elemento x de X e um elemento u(x) de V). Mas não será
eventualmente necessário que T esteja definido para todas as relações binárias entre X e V.
O que é o conjunto {(x, u(x)): x p y} (que é o argumento de T em ii) acima) ? Usando a terminologia
da secção 1 do capítulo 4 (e como já se referiu na última nota de rodapé), {(x, u(x)): x p y} não é mais do
que o gráfico da restrição de u ao conjunto {x: x p y}. Parece, assim, que basta exigir que T esteja definida
em todas as relações binárias entre X e V que possam ser o gráfico da eventual restrição de uma aplicação a
esse conjunto {x: x p y} (para y não minimal). Ou seja, T(R) deverá estar definido sempre que R for uma
relação binária funcional13 entre X e V cujo domínio seja da forma {x: x p y}, para y não minimal.

Resta-nos averiguar se será conveniente permitir que a função T, para o cálculo de u(y), possa receber
alguma outra "informação" (como argumento), para além do conjunto {(x, u(x)): x p y}. Um possível
critério será o de procurar definir T de um modo, suficientemente geral, que permita recuperar a recursão
sobre conjuntos livremente gerados a partir da recursão sobre conjuntos bem fundados.
De facto, nós sabemos (pelo teorema 4 da última secção do capítulo anterior) que nos conjuntos X,
livremente gerados a partir de um conjunto inicial S por um conjunto de operações ops, existe uma relação
bem fundada natural, sobre X, em que os elementos minimais são os elementos do conjunto inicial S e
em que (com f em ops) x p y=f(x1,...,xk) sse (x= x1 ou ... ou x= xk). Assim, em princípio, a definição
por recursão sobre um conjunto livremente gerado deverá poder ser vista como um caso particular da
recursão sobre um conjunto bem fundado, de acordo com essa relação p.

12 Isto é, usando a terminologia da secção 1 do capítulo 4, em vez de T receber como argumento o conjunto {u(x): x p y} =
u[{x: x p y}] (i.e. a imagem por u do conjunto {x: x p y}), T passa a receber como argumento o gráfico da restrição de u ao

(a esse) conjunto {x: x p y}.


13 Isto é (ver secção 1 do capítulo 4), uma relação R que satisfaz  
xX v1,v2 V (xRv1  xRv2  v1=v2).

291
Recordemos então o que se permitia (à "nossa regra de cálculo" no passo da recursão) no teorema 2 (da
secção) anterior, usando a sua reformulação referida na observação que se lhe seguia:
ii') O valor de y (pertencente a X e) não pertencente ao conjunto inicial S, é calculado como se segue
u(y) = Tf(x1, ..., xk, u(x1), ..., u(xk))
onde f é a única operação em ops e x1,...,xk os únicos elementos de X tais que y = f(x1,...,xk), e onde a
regra T pode depender da operação f em causa.
Assim, o cálculo de u(y) podia depender da "informação" descrita por x1, ..., xk, u(x1), ..., u(xk). Ora, o
conjunto {(x1, u(x1)), ..., (xk, u(xk))} = {(x, u(x)): x p y} capta (pelo menos no essencial14) tal
informação. Mas, em ii') permitia-se também que a regra a aplicar para o cálculo de u(y) pudesse depender
da operação f que era usada para gerar o y. Ora tal não se obtém a partir de {(x, u(x)): x p y}15. No
entanto, como num conjunto livremente gerado existe uma e uma só operação f que permite gerar um
elemento y, se permitirmos que a regra T, a aplicar, possa aceder também ao y, então a partir deste
podemos recuperar a informação da operação f que o gerou (bem como, também, a sequência x1, ..., xk dos
argumentos que permitem gerar y através dessa operação).
Deste modo, deverá permitir-se que u(y), para y não minimal, seja dado por
ii) u(y) = T(y,{(x, u(x)): x p y})
Estamos assim em condições de perceber o enunciado do próximo teorema16.

Notação:
No que se segue17, R FX,V designa o conjunto das relações binárias funcionais entre X e V, isto é, o
conjunto das relações binárias R entre X e V que satisfazem: xX v1,v2V (xRv1  xRv2  v1=v2).


Teorema 1 (Recursão sobre conjuntos onde está definida uma relação bem fundada):
Seja p uma relação bem fundada em X e seja V um conjunto.
Seja S o conjunto dos elementos minimais de X (em relação a p ) e g uma aplicação18 g: S  V.
Seja T: X x RFX,V  / V, tal que T(y,R) está definido sempre que y(X-S) e dom(R) = {x: x p y}
(isto é, T(y,R) está definido sempre que19 y é não minimal e o domínio de R é igual a {x: x p y}).

14 Perde-se a sequência dos argumentos, colapsando argumentos em diferentes posições, com o mesmo valor (notar que se

podia ter xi = xj, com ij). Mas, como veremos em seguida, temos formas de recuperar a sequência dos argumentos.
15 Pois se tivermos, em ops, duas funções f1 e f2, com a mesma aridade k, então elas geram a partir de um mesmo tuplo

(x1 ,...,xk ) dois elementos y1 e y2, distintos, mas {x: x p y1} = {x: x p y2}.
16 Que, à parte pequenas reformulações do enunciado, não é mais do que o teorema da recursão bem fundada que é

apresentado no livro [46] (ver aí "Theorem 10.19", na página 177).


17 No teorema a seguir podia-se considerar genericamente relações binárias entre X e V, mas não se ganha nada com isso,

bastando, para os fins em vista, considerar relações binárias funcionais.


18 O conjunto de partida de g não tem de ser necessariamente S (pode ser maior); g tem é de ser uma função que esteja definida

em S com valores em V. Por outro lado, como p é uma relação bem fundada em X (e como está implícito que X é não vazio),

tem-se que S é diferente do .


19 Podíamos mesmo dizer que T(y,R) está definido sse y(X-S) (i.e. y é não minimal) e o domínio de R é igual a {x: x p y}.

292
Então, existe uma e uma só aplicação u: X  V que verifica as seguintes condições:
i)20 para todo o xS: u(x) = g(x)
ii) qualquer que seja o elemento não minimal y (de X) 21, u(y) = T(y, {(x, u(x)): x p y})
Demonstração (análoga à demonstração do teorema 1 da secção anterior; a sua leitura pode ser omitida):
A ideia é definir u como a "união" de todas as funções que são suas aproximações, a seguir designadas de
aceitáveis.
Diremos que uma função h: X 
/ V é aceitável, se h verifica as seguintes h-condições:
h-i) se xS e xdom(h), então h(x) = g(x)
h-ii) qualquer que seja o elemento não minimal y, se y  dom(h), então
{x: x p y}  dom(h) e h(y) = T(y, {(x, h(x)): x p y})
Seja H o conjunto de todas as funções aceitáveis. Note-se que H, pois a função h0: X 
/ V, dada por
dom(h0)=S e h0(x) = g(x), para x em S, é aceitável (repare-se que não existe qualquer elemento não
minimal ydom(h0)).
Defina-se u: X 
/ V como se segue:
qualquer que seja xX
xdom(u) sse xdom(h) para alguma função aceitável h (i.e. dom(u) = U dom(h) )
h aceitável
e qualquer que seja xdom(u), se xdom(h), com h uma função aceitável, então u(x) = h(x)

Temos de verificar que:


a) u: X 
/ V está bem definida
(i.e. que, qualquer que seja xdom(u), existe um e um só vV tal que u(x) = v)
b) u é aceitável
(o que implicará que u verifica as condições i) e ii) do enunciado, se se mostrar que dom(u)=X)
c) dom(u) = X (tendo-se então que u: X  V, como se pretendia)
e que
d) u, assim definida, é a única aplicação de X em V que verifica as condições i) e ii) do enunciado.

Demonstração de a):
Seja
U = {xX: quaisquer que sejam h1 e h2 aceitáveis, se xdom(h1) e xdom(h2), então h1(x)=h2(x)}
Queremos provar que U = X.
Provemos tal resultado por indução bem fundada (como UX, o que temos de provar é que XU, isto
é que xXP(x), com P(x) = "xU"). Em pormenor:

20 O caso i) poderia ser incluído como um caso particular de ii), considerando g(y) = T(y,), para yS, e impondo que T(y,R)

estivesse definido também quando yS e dom(R) = {x: x p y} = .

No entanto, preferimos considerar i) à parte, para chamar a atenção que o valor de u nos elementos minimais tem de ser

definido de forma esplícita, independente do valor que u toma noutros elementos de X (apesar de, como veremos, em muitos

exemplos a definição explícita, "não recursiva", do valor de u não se restringir aos elementos minimais).
21 Isto é, u(y) = T(y,R) com dom(R) = {x: x p y} e em que um par (x,v)R se v é o valor que u atribui a x.

293
• Seja xS (i.e. x é minimal) e sejam h1 e h2 quaiquer funções aceitáveis tais que xdom(h1) e
xdom(h2). Então:
h1(x) = g(x) = h2(x)
• Seja y não minimal qualquer, e suponha-se que "qualquer que seja b p y, verifica-se P(b)" (HI).
Quer-se provar que se tem P(y) (i.e. yU).
Sejam h1 e h2 quaiquer funções aceitáveis tais que ydom(h1) e ydom(h2).
Queremos provar que h1(y)=h2(y). Ora:
Como h1 é aceitável:
ydom(h1) implica que {b: b p y}dom(h1) e h1(y)=T(y, {(b,h1(b)): b p y})
Analogamente:
ydom(h2) implica que {b: b p y}dom(h2) e h2(y)=T(y, {(b,h2(b)): b p y}).
Logo, por HI, h1(y) = T(y, {(b, h1(b)): b p y}) = T(y, {(b, h2(b)): b p y}) = h2(y) (c.q.d.)

Demonstração de b):
Que se verifica u-i) ("se xS e xdom(u), então u(x) = g(x)") é imediato.
Que se verifica u-ii) é também fácil de verificar. Vejamos em pormenor:
Seja y um qualquer elemento não minimal tal que ydom(u).
Queremos provar que {b: b p y}dom(u) e que u(y) = T(y, {(b, u(b)): b p y}).
Ora, se ydom(u), então existe h aceitável tal que ydom(h). E:
1)• {b: b p y}  dom(h) (pois h é aceitável)
2)• {b: b p y}  dom(u) (por 1) e definição de dom(u))
3)• h(y) = T(y, {(b, h(b)): b p y}) (pois h é aceitável)
4)• u(y) = h(y) e {(b, u(b)): b p y} = {(b, h(b)): b p y}
(por definição de u, pois h é aceitável e ydom(h) e {b: b p y}  dom(h))
5)• u(y) = T(y, {(b, u(b)): b p y}) (por 3) e 4))
Demonstração de c):
Como dom(u)  X, temos de provar que X  dom(u), isto é que xXP(x), com P(x) = "xdom(u)".
Vamos prová-lo por indução bem fundada.
Base:
Se xS, então xdom(h0) e h0 é aceitável. Logo xdom(u).
Passo de indução:
Seja y não minimal qualquer, e suponha-se que "qualquer que seja b p y, verifica-se P(b)" (HI).
Quer-se provar que se tem P(y) (i.e. ydom(u)).
1)• Seja b p y qualquer. Como, por HI, bdom(u), existe hb aceitável tal que bdom(hb).
2)• Defina-se h: X / V como se segue:
dom(h) = U dom(h b )
bpy
qualquer que seja xdom(h), h(x) = hb(x), com b p y, se xdom(hb)
Pelo que se provou na demonstração de a), é imediato que h está bem definida.
Que h é aceitável, pode verificar-se como se segue (de forma análoga à usada na dem. de b)):

294
h–i): se xS e xdom(h), então xS e existe b p y tal que xdom(hb). E, como hb é aceitável,
hb(x) = g(x). Logo, por definição de h, tem-se h(x) = hb(x) = g(x) (c.q.d.)
h–ii) Seja z um qualquer elemento não minimal tal que zdom(h).
Queremos provar que {d: d p z}dom(h) e que h(z) = T(z, {(d, h(d)): d p z}).
Ora, se zdom(h), então existe b p y tal que zdom(hb). E:
1)• {d: d p z}  dom(hb) (pois hb é aceitável)
2)• {d: d p z}  dom(h) (por 1) e definição de dom(h))
3)• hb(z) = T(z, {(d, hb(d)): d p z}) (pois hb é aceitável)
4)• h(z) = hb(z) e {(d, h(d)): d p z} = {(d, hb(d)): d p z}
(por definição de h, pois zdom(hb) e {d: d p z}  dom(hb))
5)• h(z) = T(z, {(d, h(d)): d p z}) (por 3) e 4))
3)• Se ydom(h), então (como já vimos que h é aceitável, por definição de u) ydom(u) (c.q.d.)
4)• Caso contrário (i.e. se ydom(h)), "estende-se h" como a seguir:
Seja h: X 
/ V definida como se segue:
dom(h) = dom(h)  {y}
Qualquer que seja xdom(h), h(x) = h(x)
h(y) = T(y, {(b, h(b)): bp y})
(= T(y, {(b, h(b)): b p y}), pois se b p y então bdom(h) e h(b) = h(b))
É fácil verificar que h está bem definida.
Mostremos que h é aceitável (o que implicará, então, que ydom(u) (c.q.d.))
• Se xS e xdom(h), então xy (pois y é um elemento não minimal) e xdom(h).
Logo xdom(h) e, portanto: h(x) = h(x) = g(x) (pois h é aceitável)
• Seja z um qualquer elemento não minimal e suponha-se que zdom(h).
Queremos provar que {b: b p z}dom(h) e que h(z) = T(z, {(b, h(b)): b p z}).
Se zdom(h), isso sai de h ser aceitável.
Caso contrário, zdom(h) e zdom(h). Logo z = y.
Mas então {b: b p z} = {b: b p y}  dom(h)  dom(h)). E:
h(z)
= (z = y)
h(y)
= (por definição de h)
T(y, {(b, h(b)): b p y}
= (z = y)
T(z, {(b, h(b)): b p z} (c.q.d.)

Demonstração de d):
Suponha-se que existiam u1: X  V e u2: X  V, satifazendo as condições i) e ii) do enunciado, e
provemos, pelo método da indução bem fundada, que:
yX P(y) , com P(y) a propriedade "u1(y) = u2(y)"

295
Base: Seja y minimal. Então:
u1(y)
= (por i))
g(y)
= (por i))
u2(y) (c.q.d.)
Passo de indução:
Seja y não minimal e suponha-se que "qualquer que seja b p y, verifica-se P(b)" (HI)
Quer-se provar que se verifica P(y). Ora:
u1(y)
= (por ii))
T(y, {(b, u1(b)): b p y})
= (por HI)
T(y, {(b, u2(b)): b p y})
= (por ii))
u2(y) (c.q.d.)


Observação 1:
Na generalidade dos casos a relação bem fundada p em consideração é tal que o conjunto {x: x p y} é
finito, para qualquer y. Veremos dois exemplos (os últimos) em que tal não se verifica, mas em que para o
cálculo de u(y), a regra T a utilizar só recorre a um número finito de pares (x1, u(x1)), ..., (xk, u(xk)), com
xi p y, para i=1,...,k (o que, atendendo a que a relação é bem fundada, acaba por garantir que o cálculo de
u(y), baseado nessas definições recursivas, é feito num número finito de passos).


Vejamos alguns casos particulares (de enunciado mais simples, e de interesse prático) que se podem
obter como corolário do teorema anterior, bem como alguns exemplos.

Corolário 1 (Compare-se com o teorema 1 da secção 1):


Sejam q um inteiro (qualquer), V um conjunto e F uma aplicação de V em V (i.e. F: V  V). Então, para
cada a  V, existe uma e uma só aplicação u: Zq  V que verifica as seguintes condições:
i) u(q) = a
ii) u(n) = F(u(n-1)), para qualquer n>q
(ou, de forma equivalente, u(n+1) = F(u(n)), para qualquer inteiro nq)

Demonstração:
Como vimos no exemplo 1 da secção 3 do capítulo anterior, a relação
x p y sse x = y-1 (quaisquer que sejam x e y pertencentes a Zq )
constitui uma relação bem fundada sobre Zq , em que o único elemento minimal é o q.

296
Pelo teorema 1 (desta secção), quaisquer que sejam
• a aplicação g: S  V
• e a função T: Zq x RelZq ,V 
/ V (onde, recorde-se, RelZq ,V designa o conjunto das relações binárias
funcionais entre Zq e V), que satisfaça
T(n,R) está definido sempre que n(Zq -S) (i.e. n>q) e o domínio de R é igual a {x: x p n}={n-1}
existe uma e uma só aplicação u: Zq  V que verifica:
i) qualquer que seja xS, u(x) = g(x), i.e. (pois S={q})
u(q) = g(q)
ii) para qualquer inteiro n(Zq -S), i.e. para qualquer inteiro n>q
u(n) = T(n, {(x, u(x)): x p n}) = T(n, {(n-1, u(n-1))}
Assim, o resultado desejado obtém-se se for possível definir g e T de modo a que:
a) g(q) = a
b) T(n, {(n-1, u(n-1))} = F(u(n-1)), para n>q
Ora, é imediato que a aplicação g: {q}  V, dada por g(q) = a, satisfaz a).
Por outro lado, garante-se b), definindo T(n, {(n-1,v)}) (para n>q e vV, quaisquer) como sendo o
mesmo valor que F atribui a v.
Finalmente, como só nos interessa o valor de T(n,R) para n>q e R da forma {n-1,v}, com vV,
podemos considerar que T só está mesmo definida nesses casos.
Assim, e em conclusão, T é a função T: Zq x RelZq ,V 
/ V dada por:
• T(n,R) está definido sse n(Zq -S) (i.e. n>q) e o domínio de R é igual a {x: x p n}={n-1}
• e, quaisquer que sejam n>q e vV, tem-se T(n,{(n-1,v)}) = F(v)


Corolário 2 (Compare-se com o teorema 2 da secção 1 22):


Sejam q um inteiro (qualquer), V um conjunto e F uma aplicação F: Zq x V  V. Então, para cada aV,
existe uma e uma só aplicação u: Zq  V que verifica as seguintes condições:
i) u(q) = a
ii) u(n) = F(n, u(n-1)), para qualquer n>q
(ou, de forma equivalente, u(n+1) = F(n+1, u(n)), para qualquer inteiro nq)
Demonstração (semelhante à anterior):
Considere-se a mesma relação bem fundada sobre Zq : x p y sse x = y-1
Para obter este resultado do teorema 1 tem de (ser possível definir g e T de modo a) ter-se:
i) g(q) = a (pois, pelo teorema 1, u(q) = g(q))
ii) e, para qualquer inteiro n>q:
T(n, {(n-1, u(n-1))} = F(n, u(n-1))
(pois, pelo teorema 1, u(n) = T(n, {(x, u(x)): x p n}) = T(n, {(n-1, u(n-1))})
Assim, o resultado sai do teorema 1, definindo:

22 Refira-se que em ii), abaixo, podia-se também considerar antes u(n+1) = F(n, u(n)), para qualquer inteiro nq.

297
• g é a aplicação g: S  V, dada por g(q) = a
• T é a função T: Zq x RelZq ,V 
/ V dada por:
T(n,R) está definido sse n(Zq -S) (i.e. n>q) e o domínio de R é igual a {x: x p n}={n-1}
e, quaisquer que sejam n>q e vV,
T(n,{(n-1,v)}) = F(n, v)


Exemplo 1:
Existe uma e uma só sucessão (un)n1 de naturais (ou seja, neste exemplo, u: |N1|N0) que satisfaz:
i) u1 = 2
ii) un = un-1 +2(n-1) , para n>1
Para o ver, basta considerar no resultado anterior: q = 1, a = 2 e F(n, k) = k+2(n-1), para quaisquer n|N1
e k|N0 (pois então un = u(n) = F(n, u(n-1)) = u(n-1) + 2(n-1) = un = un-1 +2(n-1), como se pretende).
Refira-se que no próximo capítulo obteremos uma definição explícita (como função de n) do termo
geral un desta sucessão.


Corolário 3 (Estende o corolário 1):


Sejam q um inteiro (qualquer), i um inteiro positivo, V um conjunto e F uma aplicação F: Vi  V.
Então, para cada tuplo (a0,...,ai-1) de i elementos de V, existe uma e uma só aplicação u: Zq  V que
verifica as seguintes condições:
i) u(q+j) = aj , para j = 0, ..., i-1
ii) u(n) = F(u(n-i), ..., u(n-1)), para qualquer inteiro nq+i
Demonstração:
A relação (quaisquer que sejam x e y pertencentes a Zq )
x p y sse y-i  x  y-1 (i.e. sse x=y-1  ...  x=y-i)
constitui uma relação bem fundada sobre Zq .
O único elemento minimal é o q.
Pelo teorema 1 existe uma e uma só aplicação u: Zq  V que satisfaz:
i) u(q) = g(q)
ii) e, para qualquer inteiro n>q, u(n) = T(n, {(x, u(x)): x p n})
(note-se que {x: x p n} = {x(Z): q  x  n-i  x  n-1})
Assim, para obter este resultado do teorema 1 tem de ter-se:
• g(q) = a0
• T(q+1, {(x, u(x)): x p q+1}) = T(q+1, {(q, u(q))}) = a1
• T(q+2, {(x, u(x)): x p q+2}) = T(q+2, {(q, u(q)), (q+1, u(q+1))}) = a2
• ...
• T(q+i-1, {(x, u(x)): x p q+i-1}) = T(q+i-1, {(q, u(q)), (q+1, u(q+1)), ..., (q+i-2, u(q+i-2))}) = ai-1
e, para nq+i:

298
• T(n, {(x, u(x)): x p n}) = T(n, {(n-i, u(n-i)), ..., (n-1, u(n-1))}) = F(u(n-i), ..., u(n-1))
Deste modo, o resultado sai do teorema 1 definindo:
• g: S  V, com g(q) = a0
• T: Zq x RelZq ,V 
/ V, tal que
T(n,R) está definido sse n(Zq -S) (i.e. n>q) e o domínio de R é igual a {x: x p n}
e, quaisquer que sejam y1,...,yi-1V,
T(q+1, {(q,y1)}) = a1
T(q+2, {(q, y1), (q+1, y2)}) = a2
...
T(q+i-1, {(q, y1), (q+1, y2), ..., (q+i-2, yi-1)}) = ai-1
e, quaisquer que sejam y1,...,yi V e nq+i,
T(n, {(n-i, yi ), ..., (n-1, y1)}) = F(yi , ..., y1)


Exemplo 2:
Existe uma e uma só sucessão (un)n0 de naturais (i.e. uma e uma só aplicação u: |N0|N0) que satisfaz:
u0 = 7
u1 = 16
un = 5 un-1 - 6 un-2, para todo o n2
Para o ver, basta considerar no resultado anterior: q = 0, i = 2, a0 = 7, a1 = 16 e F(x, y) = 5y - 6x (pois
então un = u(n) = F(u(n-2), u(n-1)) = 5 u(n-1) - 6 u(n-2) = 5 un-1 - 6 un-2, como se pretende).


Exemplo 3:
Existe uma e uma só sucessão (un)n0 de naturais (a chamada sucessão de Fibonacci) que satisfaz:
u0 = 0
u1 = 1
un = un-2 + un-1 para todo o n2
Para o ver, basta considerar no resultado anterior: q = 0, i = 2, a0 = 0, a1 = 1 e F(x, y) = x + y.
No próximo capítulo obteremos uma definição explícita (como função de n) do termo geral un da
sucessão de Fibonacci.


Corolário 4 (Estende o corolário 2):


Sejam q um inteiro (qualquer), i um inteiro positivo, V um conjunto e F uma aplicação F: Zq x Vi  V.
Então, para cada tuplo (a0,...,ai-1) de i elementos de V, existe uma e uma só aplicação u: Zq  V que
verifica as seguintes condições:
i) u(q+j) = aj , para j = 0, ..., i-1
ii) u(n) = F(n, u(n-i), ..., u(n-1)), para qualquer inteiro nq+i

299
Demonstração: Exercício.


Corolário 5 (Sequências/Listas):
Seja B um conjunto e X um conjunto de sequências de elementos de B (i.e. XB*) que é não vazio e
fechado para as subsequências, no sentido de que se yX e x é uma subsequência de y então xX (pelo que
a sequência vazia () pertence a X).
Seja V um conjunto e aV. Seja T: X x RFX,V 
/ V tal que T(y,R) está definido sempre que yX for uma
sequência não vazia e o domínio de R for igual ao conjunto {x: x é uma subsequência estrita de y}.
Então, existe uma e uma só aplicação u: X  V que verifica as seguintes condições:
i) u(()) = a
ii) u(y) = T(y, {(x, u(x)): x é uma subsequência estrita de y}), para y  ( )
Demonstração:
Sai imediatamente do teorema 1: basta considerar a seguinte relação bem fundada sobre X
x py sse x é uma subsequência estrita (ou própria) de y
cujo único elemento minimal é a sequência vazia, e considerar que a aplicação g: S  V (com S = {()}) é
dada por g(()) = a.


Como referimos, o facto de a função a definir por recursão ter mais do que um argumento não afecta os
resultados obtidos, desde que a recursão seja feita num só argumento. Ilustremos esta afirmação, a
propósito do corolário anterior:

Corolário 6 (Sequências/Listas; funções de dois argumentos com recursão num só):


Sejam C e B conjuntos, X um conjunto de sequências de elementos de B, que é não vazio e fechado para as
subsequências, V um conjunto e g: C  V. Seja F: C x X x RFX,V 
/ V, tal que F(c,y,R) está definido
sempre que cC, y for uma sequência não vazia e o domínio de R for igual a {x: x é uma subsequência
estrita de y}.
Então existe uma e uma só aplicação u: C x X  V que verifica as condições (para qualquer cC):
i) u(c, ()) = g(c)
ii) u(c, y) = F(c, y, {(x, u(c,x)): x é uma subsequência estrita de y}), para y  ( )
Demonstração:
Para cada cC, defina-se ac = g(c) e Tc : X x R FX,V 
/ V tal que Tc (y,R) está definida sse F(c,y,R) está
definida em cujo caso Tc (y,R) = F(c,y,R).
Então, pelo resultado anterior, para cada cC, existe uma e uma só aplicação uc : X  V que verifica as
seguintes condições:
c-i) uc (()) = ac = g(c)
c-ii) uc (y) = Tc (y, {(x, uc (x)): x é uma subsequência estrita de y}), para y  ( )
Seja u: C x X  V definida como se segue: u(c,y) = uc (y) (para quaisquer cC e yX).
É imediato que u está bem definida e que satisfaz i) e ii).

300
Igualmente se prova facilmente que u é a única aplicação nessas condições:
Caso existissem duas aplicações u1 e u2 nessas condições, se u1u2, existiriam cC e xX tais que
u1(c,x)u2(c,x).
Mas então, definindo u1c :XV e u2c :XV por u1c (y)=u1(c,y) e u2c (y)=u2(c,y) (para qualquer yX),
ter-se-ia u1c (x)u2c (x), o que entra em contradição com o resultado anterior (uma vez que quer u1 quer
u2 satisfazem c-i) e c-ii)).


Exemplo 4 (Pesquisa binária recursiva sobre as listas da linguagem de programação Mathematica):


Considere-se o seguinte programa (função) Mathematica que, recebendo um número c e uma lista de
números y, suposta ordenada (por forma não decrescente: i.e., informalmente, "por "), retorna True se c
ocorre na lista y, e False no caso contrário, recorrendo, para o efeito, a uma pesquisa binária recursiva:

u = Function[{c,y},
If[y=={}, False,
If[Length[y]==1,
If[y[[1]]==c, True, False],
If[c<=y[[Quotient[Length[y],2]]],
u[c,Take[y,Quotient[Length[y],2]]],
u[c,Drop[y,Quotient[Length[y],2]]]
] (* fim do último If *)

] (* fim do segundo If *)

] (* fim do primeiro If *)

] ;

Uma primeira questão que se pode colocar face a este programa é como se pode provar que "ele está
correcto" no sentido de que "retorna True se c ocorre em y, e False no caso contrário".

Sejam B o conjunto dos números da linguagem Mathematica e X o conjunto das sequências (listas no
Mathematica) de tais números que estão ordenadas (por forma não decrescente). Note-se que X é fechado
para subsequências, pois uma subsequência de uma sequência ordenada, também está ordenada.

Seja p a seguinte relação bem fundada em X:


x p y sse x é uma subsequência estrita de y (i.e. sse x é uma sublista estrita de y)

Notação:
No que se segue usaremos as funções predefinidas do Mathematica "Take", "Drop" e "Quotient", bem
como a usual notação Mathematica para nos referirmos ao resultado das funções Mathematica e ao
elemento que está numa certa posição de uma lista.
No entanto, para descrevermos uma lista por enumeração dos seus elementos, escreveremos
List[b1,...,bk] (recorrendo à notação funcional do Mathematica), em vez de (b1,...,bk), ou de {b1,...,bk}
(a notação Mathematica abreviada para a descrição de listas por enumeração), uma vez que à frente

301
precisaremos de falar em listas Mathematica, em pares ordenados e em conjuntos, e temos de poder
distinguir essas várias entidades, preferindo usar, como é prática neste texto, os parênteses para os pares
ordenados e as chavetas para os conjuntos.
Finalmente, embora nos programas Mathematica usemos == para a igualdade, no texto continuaremos
a usar =.

É imediato verificar que a função u definida satisfaz (para quaisquer c,bB e yX):
i) u[c,List[]] = False (i.e. usando a notação Mathematica abreviada: u[c,{}] = True)
ii) u[c,List[c]] = True (i.e. usando a notação Mathematica abreviada: u[c,{c}] = True)
u[c,List[b]] = False, para bc
iii) e, se k=#y>1 (i.e. se k=Length[y]>1), então
u[c,y] = u[c,Take[y,Quotient[k,2]]], se cy[[Quotient[k,2]]]
u[c,y] = u[c,Drop[y,Quotient[k,2]]], se c>y[[Quotient[k,2]]]
(onde Quotient[k,2] é igual a  k  )
 2

A demonstração de que a função u satisfaz a propriedade desejada (a seguir descrita informalmente):


quaisquer que sejam cB e yX, "u[c,y] = True sse c ocorre na sequência (lista) y"
é fácil de efectuar, recorrendo à indução bem fundada.

Mais precisamente, seja cB (qualquer) e provemos, por indução bem fundada, que:
yX P(y)
com P(y) a propriedade
"u[c,y] = True sse c ocorre na sequência y"

Base: Verifica-se P(y) para o único elemento não minimal de X, isto é, para y = List[].
Demonstração:
Imediato, pois u[c,List[]] = False e c não ocorre em List[]

Passo de indução:
Seja y não minimal qualquer, e suponha-se que
"qualquer que seja x p y, verifica-se P(x)" (HI)
Quer-se provar que se tem P(y).
Demonstração:
Se y é não minimal (i.e. y  List[]), há duas hipóteses:
• Hip 1: #y = 1
Neste caso, por ii) é imediato que se verifica P(y).

• Hip 2: #y > 1
Suponha-se que c  y[[Quotient[k,2]], com k=#y.
Então, como y está ordenado, tem-se que
(*) "c ocorre em y" sse "c ocorre em Take[y,Quotient[k,2]]".
E tem-se:

302
P(y)

u[c,y]=True sse c ocorre na sequência y
 (por (*))
u[c,y]=True sse c ocorre em Take[y,Quotient[k,2]]
 (por iii))
u[c,Take[y,Quotient[k,2]]]=True sse c ocorre em Take[y,Quotient[k,2]]

P(Take[y,Quotient[k,2]])

Mas, como Take[y,Quotient[k,2]] p y, por (HI), verifica-se


P(Take[y,Quotient[k,2]]).
Logo verifica-se P(y).

O caso em que c > y[[Quotient[k,2]] é análogo.

Na demonstração efectuada falámos várias vezes na função u.


É intuitivamente imediato que o programa atrás define uma função u. E, por essa razão, não se espera
que um "programador", ao escrever aquele programa, vá em seguida mostrar que ele define de facto uma
aplicação u: B x X  {True, False}. No entanto, um estudante de um curso universitário, seja ele de
Matemática ou de Informática, deve saber que tal pode ser fundamentado e saber (ou ter pelo menos uma
ideia de) como.
Vejamos então, a título basicamente ilustrativo, como podemos provar23 que se definiu de facto uma
aplicação u: B x X  {True, False}.

Mais precisamente, o que precisamos de mostrar é que as condições atrás referidas (para quaisquer
c,bB e yX):
i) u[c,List[]] = False
ii) u[c,List[c]] = True
u[c,List[b]] = False, para bc
iii) e, se k=#y>1 (i.e. se k=Length[y]>1), então
u[c,y] = u[c,Take[y,Quotient[k,2]]], se cy[[Quotient[k,2]]
u[c,y] = u[c,Drop[y,Quotient[k,2]]], se c>y[[Quotient[k,2]]
(que é imediato que o programa u satisfaz) definem, de facto, uma aplicação u: B x X  {True, False}

Para o efeito, podemos recorrer, por exemplo, ao corolário 6 anterior.


Ora, pelo corolário 6 (considerando no seu enunciado C=B), sendo V = {True,False}, g: B  V e
F: B x X x RFX,V 
/ V, tal que F(c,y,R) está definido sempre que cB, y é uma sequência não vazia e o
domínio de R é igual a {x: x é uma subsequência estrita de y}, existe uma e uma só aplicação u: BxXV
que verifica as condições (para qualquer cB):

23 Demonstração que não sendo difícil, é talvez um pouco mais trabalhosa que a demonstração por indução anterior.

303
a) u[c,List[]] = g(c)
b) u[c,y] = F(c, y, {(x, u[c,x]): x p y}) = F(c, y, {(x, u[c,x]): x é uma sublista estrita de y})
para y  List[]

Assim, se conseguirmos mostrar que existem g e F tais que a) e b) coincidem com i), ii) e iii),
teremos garantido o que pretendemos.

Definindo g: C  V, dada por g(c) = False (para qualquer cB), é imediato que a) coincide com i).

Para obter ii), a partir de b), tem de ter-se:


u[c,List[c]] = F(c, List[c], {(x, u[c,x]): x é uma sublista estrita de List[c]}) = True
u[c,List[b]] = F(c, List[b], {(x, u[c,x]): x é uma sublista estrita de List[b]}) = False,
para bc
Ora, se #y=1, então {(x, u[c,x]): x é uma sublista estrita de y} = {(List[], u[c,List[]])},
pelo que as condições anteriores podem ser reescritas como se segue:
F(c, List[c], {(List[], u[c,List[]])}) = True
F(c, List[b] , {(List[], u[c,List[]])}) = False, para bc
E, para obtermos as igualdades anteriores, podemos (basta) definir (para quaisquer números b e c , e
qualquer vV):
• F(c, List[c], {(List[],v)}) = True, e
• F(c, List[b], {(List[],v)}) = False, se cb

Resta-nos mostrar como definir F, de modo a que b) se reduza a iii) quando #y>1.
Para tal, terá de ter-se, para y(X) qualquer tal que k=#y>1 (usando y[[i]] para denotar o i-ésimo
elemento da lista/sequência y):
u[c,y] = F(c, y, {(x, u[c,x]): x p y})
= u[c,Take[y,Quotient[k,2]]], se cy[[Quotient[k,2]]
e = u[c,Drop[y,Quotient[k,2]]], se c>y[[Quotient[k,2]]

Ora, se y=List[b1 ,...,b k ], com k>1, então

Take[y,Quotient[k,2]]=List[b1 ,...,b Quotient[k,2]] e Take[y,Quotient[k,2]] py


Drop[y,Quotient[k,2]]=List[b<bQuotient[k,2]+1,...,b Q k] e Drop[y,Quotient[k,2]] py
pelo que as igualdades anteriores se obtêm definindo (com, para cada x, vx um qualquer elemento de V)
F(c, List[b1 ,...,bk ], R), com R = {(x, vx ) : x p List[b1 ,...,bk ]}
como sendo
• o elemento que está associado a List[b1 ,...,b Quotient[k,2]] em R,
isto é v List[b1,...,bQuotient[k,2]],
se c  bQuotient[k,2]
• e o elemento que está associado a List[b<bQuotient[k,2]+1,...,b Q k] em R,
isto é vList[bQuotient[k,2]+1,...,bk],
se c > bQuotient[k,2]

304
Finalmente, para os fins em vista, é imediato que só nos interessa o valor de F(c,y,R) para cB,
yList[] e dom(R)={x: x p y}. Logo, podemos considerar que o domínio de F é formado apenas por
tais ternos.


Dissemos atrás que podíamos definir por recursão uma função de vários argumentos, desde que a
recursão fosse feita só num dos argumentos. Para terminar, ilustremos como tal limitação pode ser
ultrapassada, pelo menos nalguns casos.
A ideia é que uma função u de n(2) argumentos, com valores nos conjuntos, respectivamente, X1, ...,
Xn, e resultado num conjunto V, pode ser vista (como sabemos) como uma aplicação u: X1x...xXn  V
(em que em vez de se escrever f((x1,...,xn)), se escreve f(x1,...,xn)). Assim, se definirmos uma relação bem
fundada p no próprio conjunto (produto cartesiano) X1x...xXn, podemos definir tal função u por recursão,
recursão que (apesar de conceptualmente ser feita no único argumento de u - um tuplo) na prática se traduz
numa recursão sobre os vários argumentos de u (componentes desse tuplo). Um exemplo ilustrará melhor
o que se pretende dizer.

Exemplo 5 (A função de Ackermann - "dupla recursão"):


A função dita de Ackermann é uma função de duas variáveis naturais e resultado natural, que se define
recursivamente como se segue:
a) u(0, y) = y+1, qualquer que seja o natural y
b) u(x, 0) = u(x-1, 1), qualquer que seja o natural x1
c) u(x, y) = u(x-1, u(x, y-1)), quaisquer que seja os naturais x1 e y1
Vejamos, a título complementar, como se pode utilizar o teorema 1, para mostrar que existe uma e uma
só aplicação uma aplicação u: |N0 x |N0  |N0 que satisfaz as condições a), b) e c), anteriores.

Recordemos o enunciado do teorema 1:


Seja p uma relação bem fundada num conjunto X e seja V um conjunto.
Seja S o conjunto dos elementos minimais de X e g uma aplicação g: S  V.
Seja T: X x RFX,V 
/ V, tal que T(b,R) está definido sempre que b(X-S) e dom(R) = {a: a p b}).
Então existe uma e uma só aplicação u: X  V que verifica as seguintes condições:
i) para todo o bS: u(b) = g(b)
ii) Qualquer que seja o elemento não minimal b (de X): u(b) = T(b, {(a, u(a)): a p b})

Seja X = |N0 x |N0 e V = |N0. Considere-se a a usual ordem lexicográfica em |N0x|N0:


(x1,y1) p (x2,y2) sse x1<x2 ou (x1=x2 e y1<y2)
Como se referiu na (única) observação incluída na secção 3 do capítulo 3, trata-se de uma relação bem
fundada.
- O único elemento minimal é o par (0,0) (i.e. S = {(0,0)})
- Se y>0, então {(n.m) (|N0x|N0): (n.m) p (0,y)} = {(0,0), (0,1), ..., (0,y-1)}.
- Se x>0, então {(n.m): (n.m) p (x,y)} é infinito, mesmo que y seja zero;
por exemplo {(n,m): (n,m)) p (1,0)} = {(0,0), (0,1), (0,2), (0,3), ...} = {(0,k): k|N0}.

305
(Outros exemplos: {(n.m): (n.m) p (1,1)} = {(0,k): k|N0}  {(1,0)}; etc.)

• Se definirmos g: S  V como se segue (g((0,0)) =) g(0,0) = 1, então i) reduz-se a:


i) u(0,0) = 1
que é uma das instâncias de a) acima, que podemos designar de a-1).

• Temos agora de definir24 T: X x R FX,V 


/ V de modo a que (descrevendo em ii) os elementos de X
como pares (n,m) de naturais e, como é usual, escrevendo u(n,m) em vez de u((n,m)))
ii) Qualquer que seja o elemento não minimal (x,y) (de |N0x|N0):
u(x,y) = T((x,y), {((n,m), u(n,m)): (n,m) p (x,y)})
traduza os restantes casos de a), bem como b) e c) acima.

• Vejamos como obter


a-2) u(0, y) = y+1, qualquer que seja o natural y>0
a partir de ii).

Considere-se um qualquer natural y>0.


Para se obter a-2), a partir de ii), terá de ter-se
T((0,y), {((n,m), u(n,m)): (n,m) p (0,y)}) = y+1
Tal será garantido, definindo, para qualquer natural y>0
T((0,y), R) = y+1, para qualquer25 R tal que dom(R) = {(n,m): (n,m) p (0,y)}
• Vejamos como obter
b) u(x,0) = u(x-1,1), qualquer que seja o natural x1
a partir de ii).

Considere-se um qualquer natural x1.


Para se obter b), a partir de ii), terá de ter-se
u(x,0) = T((x,0), {((n,m), u(n,m)): (n,m) p (x,0)}) = u(x-1,1)
Ora, como (x-1,1) p (x, 0), tem-se que u(x-1,1) é o elemento que está associado a (x-1,1) em
{((n,m), u(n,m)): (n,m) p (x,0)}
Assim, a igualdade acima será garantida, definindo, para qualquer natural x>0
T((x,0), R) como sendo o natural k tal que ((x-1,1), k)  R,
para qualquer26 R tal que dom(R) = {(n,m): (n,m) p (x,0)}

24 Recordar que, de acordo com o enunciado do teorema 1, T((x,y), R) pode só estar definido para

(x,y) diferente de (0,0) e R RFX,V tal que dom(R) = {(n,m): (n,m) p (x,y)}

mas tem de estar sempre definido para quaisquer (x,y) e R nessas condições.

Observe-se ainda que se R RFX,V é tal que dom(R) = {(n,m): (n,m) p (x,y)}, então os elementos de R serão da forma

((n,m), k), com (n,m) p (x,y) e k um natural.


25 Como se observou na nota de rodapé anterior, de acordo com o enunciado do teorema 1, T((0,y), R) tem de estar definido

para qualquer R RFX,V tal que dom(R) = {(n,m): (n,m) p (0,y)}.


26 Como (x-1,1) p (x,0), para tais relações existirá sempre um k tal que ((x-1,1), k)  R.

306
• Consideremos agora o caso mais difícil e vejamos como obter
u(x, y) = u(x-1, u(x, y-1)), quaisquer que seja os naturais x1 e y1
a partir de ii).

Considere-se naturais x1 e y1 quaisquer.


Para se obter c), a partir de ii), terá de ter-se
u(x, y) = T((x,y), {((n,m), u(n,m)): (n,m) p (x,y)}) = u(x-1, u(x, y-1))
Ora u(x-1, u(x, y-1)) é o natural que está associado a (x-1, u(x, y-1)) em
{((n,m), u(n,m)): (n,m) p (x,y)}
isto assumindo que (x-1, u(x, y-1)) p (x, y).
Mas, como se tem (x-1, k) p (x, y), para qualquer par da forma (x-1, k), com k natural, verifica-se
que (x-1, u(x, y-1)) p (x, y).
Por outro lado, u(x, y-1) é o natural que está associado a (x, y-1) em
{((n,m), u(n,m)): (n,m) p (x,y)}
isto assumindo que (x, y-1) p (x, y), o que se verifica.
Assim, garantiremos o que se pretende, definindo, para quaisquer naturais x1 e y1
T((x,y), R) como sendo o natural j tal que ((x-1, k), j)  R,
com k o natural tal que ((x, y-1), k)  R.

Finalmente, no que respeita ao domínio de T, pode considerar-se que T((x,y), R) só está definido nos
casos considerados, i.e. T((x,y), R) está definido sse (x,y)(0,0) e R é uma relação binária funcional entre
|N0 x |N0 e |N0 cujo domínio é dado por dom(R) = {(n,m): (n,m) p (x,y)}.


Vejamos mais alguns exemplos, de programação.

Exemplo 6 (De novo a programação recursiva sobre listas do Mathematica):


Na página 115 do livro [8] refere-se várias possibilidades de definir recursivamente uma função que junta
duas listas (faz o seu "Join"). Uma delas, que fugia um pouco ao padrão mais utilizado na disciplina de
"Paradigmas da Programação", é a seguinte:

junta = Function[{w,v},
If[v=={}, w,
junta[Append[w,First[v]],Rest[v]]
]
] ;

A razão porque se diz que esta definição fugia um pouco ao padrão mais utilizado na disciplina de
"Paradigmas da Programação" reside no facto de, embora a recursão estar aparentemente a ser feita no
segundo argumento (v) de "junta", quanto "junta" é invocada recursivamente (no passo da recursão), o
seu primeiro argumento não é o argumento inicial (w), mas sim Append[w,First[v]]. Assim, não é

307
exactamente verdade que a função "junta" acima esteja a ser definida por recursão apenas no seu segundo
argumento, e o corolário 6 atrás não poderá ser utilizado para mostrar que "junta" está bem definida.
Procuremos recorrer ao teorema 1 para mostrar que esta função está bem definida.

É imediato que, pela definição acima "junta" satisfaz:


a) junta[w,{}] = w, para qualquer lista w
b) junta[w,v] = junta[Append[w,First[v]],Rest[v]],
para qualquer lista w e qualquer lista v  {}

Seja L o conjunto das listas do Mathematica e considere-se que no enunciado do teorema 1, X=LxL e V=L.
Considere-se a seguinte relação p em X=LxL (com os w's e os v's a denotar sequências/listas e onde se
usa as mesmas convenções notacionais que no exemplo 4):

(w1 ,v 1 ) p (w2 ,v2 ) sse v2 List[] e v1 =Rest[v2 ]


É fácil verificar que se trata de uma relação bem fundada em X.
O conjunto S dos elementos minimais é formado por todos os pares de listas da forma (w, List[]) (com
wL).

Pelo teorema 1 (onde para a função Mathematica, junta, se usa as notações usadas nessa linguagem):
Sendo g: S  V e T: X x RFX,V 
/ V, tal que T((w,v),R) está definido sempre que (w,v)(X-S)
e dom(R) = {(s,z): (s,z) p (w,v)}), existe uma e uma só aplicação junta: X  V que verifica
as seguintes condições:
i) para todo o (w,List[])S: junta[w,List[]] = g(w,List[])
ii) Qualquer que seja o elemento não minimal (w,v) (de X = L x L):
junta[w,v] = T((w,v), {((s,z), junta[s,z]): (s,z) p (w,v)})

• Se definirmos g: S  V como se segue:


g(w, List[]) = w (para qualquer wL)
então i) reduz-se a:
i) junta[w,List[]] = w, para qualquer lista w
isto é, a) acima.

• Temos agora de definir T: X x RFX,V 


/ V, de modo a que
ii) Qualquer que seja a lista w e a lista vList[]:
junta[w,v] = T((w,v), {((s,z), junta[s,z]): (s,z) p (w,v)})
= T((w,v), {((s,Rest[v]), junta[s,Rest[v]]): s é uma lista})
traduza b) acima, i.e.
junta[w,v] = junta[Append[w,First[v]],Rest[v]],
para qualquer lista w e qualquer lista vList[]

Ou seja, temos de definir T de modo a que


T((w,v), {((s,Rest[v]), junta[s,Rest[v]]): s é uma lista})
seja igual a

308
junta[Append[w,First[v]],Rest[v]]

Ora, junta[Append[w,First[v]],Rest[v]] é o elemento que está associado a


(Append[w,First[v]],Rest[v]) em
{((s,Rest[v]), junta[s,Rest[v]]): s é uma lista}

Assim, devemos definir T((w,v), R) como sendo a lista x tal que


((Append[w,First[v]], Rest[v]), x)  R
para qualquer R tal que dom(R) = {(s,z): (s,z) p (w,v)} = {(s,Rest[v]): s é uma lista}.
• Finalmente, no que respeita ao domínio de T (analogamente ao que fizemos nos exemplos anteriores)
pode considerar-se que T((w,v), R) só está definido nos casos considerados27 (i.e. se vList[] e
dom(R) = {(s,z): (s,z) p (w,v)}).
Refira-se, por último, que não é essencial que a relação bem fundada p a considerar em X=LxL seja
p (w2 ,v2 ) sse v2 List[] e v1 =Rest[v2 ]
(w1 ,v 1 )
É fácil verificar que qualquer relação bem fundada p 1 em X, que tenha os mesmos elementos minimais e
estenda a relação p
(no sentido de que (w1 ,v 1 ) p (w2 ,v 2 ) implica (w1 ,v 1 ) p 1 (w2 ,v 2 ))
serve, pois pode sempre definir-se:
para w uma qualquer lista e v uma qualquer lista não vazia (i.e. para (w,v) não minimal) e qualquer R
(relação binária funcional entre X=LxL e V) tal que dom(R) = {(s,z): (s,z) p 1 (w,v)}:
T((w,v), R) como sendo a lista x tal que ((Append[w,First[v]], Rest[v]), x)  R
uma vez que se p 1 estende p , então (Append[w,First[v]], Rest[v]) p 1 (w,v).
Assim, por exemplo, podíamos antes ter considerado a seguinte relação bem fundada p 1 em X=LxL:
(w1 ,v 1 ) p 1 (w2 ,v2 ) sse v1 é uma parte final estrita de v2
ou a relação bem fundada p 1 em X=LxL dada por
(w1 ,v 1 ) p 1 (w2 ,v 2 ) sse v1 é uma subsequência estrita de v2
ou mesmo a relação bem fundada p 1 em X=LxL dada por
(w1 ,v 1 ) p 1 (w2 ,v 2 ) sse Length[v1 ] < Length[v2 ]

Naturalmente, o que se acabou de observar (sobre a possibilidade de existirem várias relações bem
fundadas que permitam suportar o esquema de recursão em causa) não é específico deste exemplo.


Exemplo 7 (Programação recursiva sobre listas do Mathematica - recursão sobre dois argumentos):
Nas páginas 115 e 116 do livro [8] indica-se o seguinte programa para testar se uma lista w é uma parte
inicial de outra lista v:

27 O que corresponde a considerar que o domínio de T é o menor possível (de acordo com o enunciado do teorema 1).

309
parteinicial = Function[{w,v},
If[w=={}, True,
If[v=={}, False,
IF[First[w]!=First[v], False,
parteinicial[Rest[w],Rest[v]]
]]]];

A função parteinicial está a ser caracterizada pela seguinte relação de recorrência28:


a) parteinicial[{},v] = True, para qualquer lista v
b) parteinicial[w,{}] = False, para qualquer lista w{}
c) e, para quaisquer listas w{} e v{},
parteinicial[w,v] = False, se First[w]!=First[v]
parteinicial[w,v] = parteinicial[Rest[w],Rest[v]], se First[w]==First[v]

Podemos recorrer outra vez ao teorema 1, para mostrar que existe uma e uma só função que satisfaz as
condições a), b) e c) anteriores. Para tal, basta considerar que no enunciado do teorema 1:
• L é o conjunto das listas do Mathematica, X = L x L e V = {True, False};
• p é a seguinte relação bem fundada29 em X=LxL:
(w1 ,v1 ) p (w2 ,v2 ) sse Length[w1 ]<Length[w2 ] ou Length[v1 ]<Length[v2 ]
em que o único elemento minimal é (List[],List[]) (i.e. na notação abreviada ({},{})) ;
• g:SV é dada por g(List[],List[]) = True ;
• e T: XxRFX,V 
/ V, com
T((w,v), R) definido sse (w,v)  (List[], List[]) e dom(R)={(s,z): (s,z) p (w,v)},
dada por:
- T((List[],v), R) = True
- T((w,List[]), R) = False (com wList[])
- e, se wList[] e vList[], então
T((w,v), R) = False, se First[w]First[v]
T((w,v), R) = ao x tal que ((Rest[w],Rest[v]), x)  R, se First[w]=First[v]
(note-se que (Rest[w],Rest[v]) p (w,v))
Que a função parteinicial dá o resultado pretendido pode mostrar-se, demonstrando por indução bem
fundada que:
(w,v)X P((w,v))
com P((w,v)) a propriedade "parteinicial[w,v] = True sse w é uma parte inicial de v"

28 Pelo tipo de teste de igualdade utilizado, podemos supor que se trata de listas de números (embora isto não seja uma questão

essencial para o que se pretende aqui ilustrar).


29 Podíamos também considerar antes a relação bem fundada: (w ,v ) p (w ,v ) sse "Length[w ]<Length[w ] e
1 1 2 2 1 2

Length[v1]<Length[v2]", ficando as definições e demonstrações a seguir (até) mais simples. Com tal relação bem

fundada, os elementos minimais passariam a ser todos os pares (w,v) em que w={} ou v={}.

310
Base: Verifica-se P((List[],List[]))
Demonstração:
Imediata, pois List[] é uma parte inicial de List[] e parteinicial[List[],v] = True,
para qualquer lista v (e, portanto, parteinicial[List[],List[]]=True).

Passo de indução:
Seja (w,v) não minimal qualquer, i.e. w List[] ou v List[], e suponha-se que
"qualquer que seja (s,z) p (w,v), verifica-se P((s,z))" (HI)
Quer-se provar que se tem P((w,v)).
Demonstração:
• Hip 1: w = List[].
Então w é uma parte inicial de qualquer lista e, por a), parteinicial[List[],v] = True
• Hip 2: wList[] e v=List[].
Então w não é uma parte inicial de v e, por b), parteinicial[w,List[]] = False
• Hip 3: wList[] e vList[].
Então:
w=List[w[[1]],...,w[[Length[w]]]]
é uma parte inicial de
v=List[v[[1]],...,v[[Length[v]]]]
sse
Length[w]  Length[v]
e, qualquer que seja i=1,...,Length[w], w[[i]]=v[[i]]
Logo:
- se First[w]First[v],
então w não é uma parte inicial de v e, por c), parteinicial[w,v] = False
- se First[w]=First[v],
então
w é uma parte inicial de v
sse (definição de parte inicial e First[w]=First[v])
Rest[w]={w[[2]],...,w[[Length[w]]]}
é uma parte inicial de
Rest[v]={v[[2]],...,v[[Length[v]]]}
sse (por HI, pois (Rest[w],Rest[v]) p (w,v))
parteinicial[Rest[w],Rest[v]] = True
sse (por c), parteinicial[w,v] = parteinicial[Rest[w],Rest[v]])
parteinicial[w,v] = True
(c.q.d)


311
Para concluir, e "falando" agora em termos informais, podemos dizer que uma relação bem fundada p,
num conjunto X, pode ser vista como traduzindo uma relação de complexidade entre os elementos de X, e
que a ideia por detrás da definição recursiva de uma função u é a de definir o valor de u num elemento à
custa do valor de u em elementos de menor complexidade, e assim sucessivamente (de modo recursivo) até
se chegar aos elementos de complexidade mínima.

Por outro lado, podemos dizer que a definição recursiva de uma aplicação u: X  V se traduz, de uma
forma simples, por um esquema do tipo:
0) se y é um elemento minimal, então o valor de u(y) é definido explicitamente, de uma forma que não
depende do valor de u noutros elementos de X (o valor de u(y) é dado por g(y), com g: S V e S o
conjunto dos elementos minimais, na formulação do teorema 1);
1) se y não é um elemento minimal, então são considerados k elementos de X, x1, ..., xk (todos eles p y),
e calcula-se o valor u(y) aplicando uma regra de cálculo (que designámos genericamente de T, ou F) a
u(x1). ..., u(xk), regra essa que poderá ainda utilizar os valores y, x1, ..., xk.

No entanto, como os exemplos mostraram, conforme o valor de y a regra de cálculo a utilizar poderá
variar (assim como os elementos x1, ..., xk a considerar para o cálculo de u(y)). Mais ainda, em muitos
casos o valor de u tem de ser definido explicitamente não só nos elementos minimais, mas também
noutros elementos de X.
Por outro lado, como também observámos nos últimos exemplos, o "argumento y" de u sobre o qual a
recursão é feita, muitas vezes não é um só argumento, mas o que podemos considerar "um tuplo de
argumentos", em cujo caso cada um dos elementos x1, ..., xk referidos acima também será um tuplo (com
o mesmo número de elementos que o tuplo y).
E, para além do argumento (ou tuplo de argumentos) sobre o qual é feita a recursão, a aplicação u
poderá ter outros argumentos, a seguir designados por c. (No que se segue cC poderá ser um só
elemento, ou um tuplo (c1,...,cr), em cujo caso C deverá ser visto como um produto cartesiano C 1x...xCr;
e comentários análogos podem ser feitos em relação a yX.)

Assim, em termos práticos (e de modo genérico), podemos dizer que a definição recursiva de uma
aplicação u: C x X  V se traduz tipicamente por um esquema, com uma sequência (finita) de (j+1, com
j>0) cláusulas do tipo:
0) se y é um elemento minimal, então o valor de u(c,y) é definido explicitamente, de uma forma que não
depende do valor de u noutros elementos de X (o valor de u(c,y) é dado por g(c,y));
1) caso contrário, se y satisfaz uma certa condição Q1(y) (ou, mais genericamente, se c e y satisfizerem
uma certa condição Q1(c,y)), então (em função de c e de y) selecciona-se k1 (0) elementos de X, x11,
..., x1k1 (todos eles p y), e calcula-se o valor u(c,y) aplicando uma regra T1 a u(c,x11), ..., u(c,x1k1),
regra que poderá ainda utilizar os valores c, y, x11, ..., x1k1 (se k1=0, então o cálculo do valor de u(c,y)
é definido de forma explícita, não dependendo do valor de u noutros elementos de X);
2) caso contrário, se y satisfaz uma certa condição Q2(y) (ou, mais genericamente, se c e y satisfizerem
uma certa condição Q2(c,y)), então (em função de c e de y) selecciona-se k2 (0) elementos de X, x21,
..., x2k2 (todos eles p y), e calcula-se o valor u(c,y) aplicando uma regra T2 a u(c,x21). ..., u(c,x2k2),

312
regra que poderá ainda utilizar os valores c, y, x21, ..., x2k2 (se k2=0, então o cálculo do valor de u(c,y)
é definido de forma explícita, não dependendo do valor de u noutros elementos de X);
....
j) caso contrário, (em função de c e de y) selecciona-se kj (1) elementos de X, xj1, ..., xjkj (todos
eles p y), e calcula-se o valor u(c,y) aplicando uma regra Tj a u(c,xj1). ..., u(c,xjkj), regra que poderá
ainda utilizar os valores c, y, xj1, ..., xjkj.

Como observação final recorde-se o esquema genérico seguido na disciplina de "Paradigmas da


Programação" (abreviadamente PP) para desenvolver programas recursivos, com a recursão feita sobre
listas, e justifiquemo-lo à custa do que estudámos nesta secção. Para simplificar, iremos considerar a
seguir apenas o caso em que a recursão é feita num só argumento (de tipo lista).

Observação 2 (Esquema seguido em PP para a elaboração de programas recursivos sobre listas)


Suponha-se que se pretende definir uma função
u = Function[{c,w}, ... ]
por recursão sobre o argumento w de tipo lista.
Para o fazer, dizia-se em "Paradigmas da Programação":
i)• Comece por definir qual o resultado para a lista vazia (i.e. o valor de u, para w={}, valor esse que
poderá eventualmente depender de c);
ii)• Em seguida, considere que w é uma (qualquer) lista não vazia, suponha que o valor de u está bem
definido para qualquer lista de comprimento menor que o de w, e:
a)• escolha uma dessas listas (de comprimento inferior a w), a seguir designada por v , e indique
como calcular o valor de u[c,w] à custa do valor de u[c,v]);
b)• no cálculo anterior poderá referir-se ainda aos argumentos c e w (para além de a u[c,v]);
c)• [que restrições deve a escolha de v satisfazer (para além de ter menor comprimento do que w) ? ]
a lista v deverá poder ser obtida a partir da lista w , isto é, mais precisamente, o termo da
linguagem Mathematica que denota a lista v deverá poder ser construído a partir de w (ou, mais
genericamente, a partir dos argumentos c e w);
d)• [que lista v escolher ? ]
satisfeitas as restrições anteriores, qualquer escolha serve para v; a melhor escolha é a que tornar
mais fácil a definição do valor de u[c,w] à custa do valor de u[c,v]; as escolhas mais
óbvias e simples (que poderão nem sempre funcionar) são v=Rest[w] ou v=Drop[w,-1].

Seja C o conjunto onde o argumento c assume valores, X o conjunto das listas do Mathematica e V um
conjunto onde o resultado de u assume valores.

O teorema 1 garante-nos que existe uma e uma só aplicação u: C x X  V que satisfaz i), ii-a), ii-b) e
ii-c) (nota: ii-d) traduz apenas considerações de carácter metodológico sobre a melhor escolha de v no passo
da recursão).

Para o ver, basta considerar que no enunciado do teorema 1 (adicionando-lhe o parâmetro c):

313
• p é a seguinte relação bem fundada em X:
v p w sse Length[v] < Length[w]
(em que o único elemento minimal é {}) ;

• g é a aplicação g: C x SV com g(c,{}) igual ao valor atribuído a u[c,{}] em i);


/ V, com T(c, w, R) definido sse w{} e dom(R) = {v: v p w}),
• e T é a função T: C x X x RFX,V 

dada por:
T(c,w,R) = F(c,w,x)
sendo x o valor tal que (v, x)  R, com v obtido a partir de c e w tal como em ii-c),
e onde F(c,w,u[v]) traduz a regra usada para calcular u[w] a partir de c, w e u[v], referida em ii-a)
e ii-b).

Que a função u definida satisfaz o que se pretendia com ela, deverá poder ser provado por indução
bem fundada, uma vez caracterizada formalmente a propriedade P desejada.


314
Anexo: Comparação entre uma prova por indução e a definição recursiva de uma função.

Compare-se a demonstração por indução finita de que


“se A é um conjunto finito, então #(A) = 2#A “ (teorema 3.1.3)
com a construção de uma função recursiva 30 para o
cálculo do conjunto das partes de um conjunto finito A
em que a função/programa em causa é escrita na linguagem de programação Mathematica, assumindo-se
que os conjuntos (finitos) são representados através de listas.

Demonstração por indução de que Cálculo recursivo das partes de um conjunto finito
n|No P(n), com P(n) a propriedade A (representado por uma lista)
n
A (se #(A) = n então #((A)) = 2 ) partes = Function[A, ??? ]

Base: Provar que se verifica P(0) Base: definir o resultado para a lista {}
Dem.: partes[{}] deve ser {{}}
Se #(A) = 0, então A =  e () = {} Isto é,
Logo: partes = Function[A,
0 #() If[A=={},
#(()) = #({}) = 1 = 2 =2 (*resultado*) {{}},
(c.q.d.) (*caso contrário*) ???
]];
Passo de indução: Seja k|N0 qualquer Passo de recursão: Seja A{} qualquer

Hipótese de indução (HI): Hipótese de recursão:


verifica-se P(k) Sabe-se calcular partes[B] para qualquer B  A

Tese: verifica-se P(k+1) Objectivo: definir partes[A]


Dem.:
Seja A qualquer com k+1 elementos.

Como #A = k+1  1, tem-se que A  . Considere-se um conjunto B com menos um elemento


Fixemos um elemento c  A e que A (e que se possa descrever facilmente a partir de
seja B o conjunto dos restantes elementos de A A). Seja por exemplo31 B = Rest[A]

Como #(B) = k, por HI, tem-se #((B))=2k Pela hipótese de recursão sabemos calcular
partes[B]
Temos agora de mostrar como é que a partir desse
conjunto se calcula o conjunto partes[A]

30 Sem nos preocuparmos em demonstrar (usando os resultados deste capítulo) que essa função está bem definida.

31 Pode considerar-se que a relação bem fundada que está por detrás desta recursão é a relação B pA sse “B é uma sublista

de A” , ou apenas que B pA sse B = Rest[A].

315
A chave da solução: os subconjuntos de A são A chave da solução: os subconjuntos de A são os
os subconjuntos de B, mais os conjuntos que se subconjuntos de B, mais os conjuntos que se obtêm
obtêm juntando a estes o c juntando a estes o First[A]
(atender a que A é igual a B mais First[A])

Assim: Solução:

#((A)) = 2 #((B)) = 2 *2k = 2k+1 Supondo que temos já definida uma função
acrescenta, que recebendo uma lista de listas w e
(c.q.d.)
um elemento c, acrescenta c a cada lista em w,

então partes[A] obtém-se


juntando (fazendo o Join d)a
"lista de conjuntos" dada por partes[B],
com a "lista de conjuntos" dada por
acrescenta[partes[B],First[A]]

Chega-se assim a:

partes = Function[A,
If[A=={}, {{}},
Join[partes[Rest[A]],
acrescenta[partes[Rest[A]],First[A]]]
]];

Conclusão:
As ideias essenciais (da prova por indução e da construção do programa recursivo) são as mesmas !
Pode considerar-se que a definição recursiva do cálculo das partes é mais difícil que a demonstração por
indução (notar que ainda se tem que definir a função acrescenta, o que se deixa como exercício).
O que será então que torna mais apelativo, pelo menos para os alunos de Informática, construir o
programa das partes, do que efectuar a prova por indução ?
Julgo que a resposta32 tem a ver com a possibilidade de experimentar e testar. Construído um
programa os alunos podem experimentá-lo logo (testá-lo) e ver que funciona !

32 Haverá quem diga que os alunos simplesmente não gostam de fazer demonstrações! Duvido que se possa fazer uma tal

afirmação genérica: os alunos têm é provavelmente pouca prática de demonstrar resultados, e enquanto não se aprende a fazer

demonstrações, fazendo-as, é natural que não se goste e não se sinta atraído por elas.

Poderá haver ainda quem diga que os alunos não vêem o interesse em estar a demonstrar um resultado que já se sabe (que já

foi provado) que é verdadeiro. Tal argumento só por si não colhe totalmente: muitos dos programas que os alunos constróem com

interesse, também já foram obtidos por outros. Mas, naturalmente, quando precisamos de provar que é verdadeiro um

determinado resultado que conjecturámos (e de que dependemos para conseguir realizar alguma tarefa que “temos entre

mãos”), então a sua demonstração (já) é (certamente) um desafio (tal como é um desafio para quem gosta de programar,

conseguir construir um programa considerado difícil) e não faltará motivação para a tentar realizar.

316

Vous aimerez peut-être aussi