Funções, Expressões e Excepções
Trajectórias Óptimas
DI/FCT/UNL
1º Semestre 2004/2005
1
Funções e Passagem de Parâmetros
• Em muitos casos, ao invocar-se uma função pretende-se
obter não apenas um mas vários resultados.
• Este requisito é tratado diferentemente em diferentes
linguagens de programação, dependendo em grande parte da
forma como são passados os parâmetros de uma função.
• Em OCTAVE, os parâmetros são passados exclusivamente
por valor (com uma excepção - nomes de funções).
• Isto quer dizer, que ao especificar-se uma variável no
parâmetro de uma função a invocar, o que se passa para a
função é o valor da variável.
• Durante a função, a variável não pode ser alterada no
programa que invoca a função!
2
Passagem de Parâmetros por Valor
• Exemplo: Consideremos a função
function y = f(x)
x = 2*x
y = x
endfunction;
• Se chamada com o valor x = 5, durante a computação da
função, esse valor é duplicado e retornado.
• Por exemplo, se invocarmos a função na sequência (pode ser
ao terminal)
..., x = 5; z = f(x); x, z, ...
os valores de x e y reportados no terminal são x = 5 e z = 10.
3
Passagem de Parâmetros por Valor
•
Exemplo: ..., x = 5; z = f(x); x, z, ...
function y = f(x)
x = 2*x;
y = x;
endfunction;
A computação da função f pode ser assim explicada:
1. Na instrução x=2*x o que é multiplicado por 2 é o valor
passado como parâmetro (i.e. 5) obtendo-se assim o valor 10.
2. Esse valor é atribuído a uma nova variável, também chamada
x, mas que é local à função, não sendo alterado o x do
programa principal.
3. Na instrução y=2*x, é a nova variável local que é
considerada, e portanto, y = 10, valor esse retornado.
4. No “programa principal” esse valor é atribuído à variável z.
4
Passagem de Parâmetros por Referência
• Outras linguagens (Pascal, C, C++, ...) permitem a passagem
de parâmetros por referência. Neste caso é passada a
referência à variável do programa principal, que pode assim
ser alterada pela função.
• Por exemplo se o parâmetro x fosse passado por referência
(indicado com uma notação fictícia)
..., x = 5; z = f(x); x, z, ...
function y = f(ref w)
w = 2*w;
y = w;
endfunction;
os valores de x e y reportados no terminal seriam x = 10 (a
variável w, no interior da função é a mesma variável que a
variável x, passada por referência!) e y = 10.
5
Funções com Múltiplos Resultados
• A passagem de parâmetros por referência permite que uma
função (ou procedimento) passe vários valores para o
programa que a invocou. Basta passar por referência as
variáveis onde esses valores devem ser “colocados”.
• O OCTAVE, não suporta passagem de parâmetros por
referência. A computação de vários resultados numa função é
conseguida pela computação de um vector de resultados.
• Por exemplo, se se pretender que a função f, com argumento
x, retorne dois valores, f1 e f2, especifica-se a função como
function [f1,f2] = f(x)
...
f1 = ...; f2 = ...;
...
endfunction;
6
Trajectórias Óptimas
• Exemplo: Trajectórias
• A anterior função alcance(v,alfa,ka) determinava o
alcance de um projéctil lançado com uma velocidade v e
ângulo alfa, num meio em que o coeficiente de atrito é ka.
• Com essa função pode-se determinar (através de um ciclo)
qual o maior alcance, mas não outras características da
trajectória em que possamos estar interessados (por exemplo,
altura atingida, tempo em que a atinge, tempo total da
trajectória ou uma combinação destas características).
• Essas características, especificamente a altura atingida e o
tempo total da trajectória podem ser retornados por uma
função, tiro(v,alfa,ka), especificada de uma forma
muito semelhante (a encarnado as diferenças).
7
Trajectórias Óptimas
function [xmax, ymax, tmax] = tiro(vi, alfa, ka)
dt = 0.01; g = 9.8;
t = 0;
ymax = 0;
x = 0; vx = vi*cos(alfa*pi/180) ;
y = 0; vy = vi*sin(alfa*pi/180);
ax = - ka * vx ; ay = -g - ka * vy;
while y >= 0
t = t + dt; x = x + vx * dt; y = y + vy * dt;
if y > ymax
ymax = y;
endif;
vx = vx + ax * dt;
vy = vy + ay * dt;
ax = - ka * vx;
ay = -g - ka * vy;
endwhile;
xmax = x; tmax = t;
endfunction;
8
Programas e Funções
• Podemos agora responder a um conjunto de perguntas,
assumindo-se uma dada velocidade inicial e coeficiente de
atrito, tais como:
– Qual a trajectória que atinge maior altura, com alcance
mínimo de x_min? Qual a altura e qual o ângulo de
disparo?
– Qual o alcance máximo atingido com uma trajectória que
não dura mais de um tempo limite, t_limite? Qual o seu
ângulo de disparo?
– Qual é a trajectória “máxima”, isto é cujo produto da
altura máxima pelo alcance e pelo tempo é máximo? Qual
o seu ângulo de disparo?
• Vejamos como responder à última destas questões.
9
Trajectórias Óptimas
function [xmax, ymax, tmax, amax] = tiro_maximo(vi, ka)
maximo = 0;
for alfa = 0:90
[x, y, t] = tiro(vi,alfa,ka);
v = x*y*t
if v > maximo
maximo = v;
xmax = x; ymax = y;
tmax = t; amax = alfa;
endif;
endfor;
endfunction;
10
Programas e Funções
• Em muitas situações não se pretende o melhor mas apenas
algo razoável. Consideremos por exemplo a questão:
– Será que existe uma trajectória (isto é, um lançamento feito a uma
velocidade vi e um ângulo alfa, num meio com coeficiente de atrito
ka) em que a altura seja maior que y1 e o alcance maior que x1?
• Esquemáticamente, devemos fazer uma pesquisa para todos
os valores de vi, alfa e ka (com uma determinada precisão), o
que se pode fazer encadeando 3 ciclos para (for).
• Assumamos que existem valores mínimos e máximos a
respeitar para vi, alfa e ka e que a precisão a utilizar é,
respectivamente, de 1ms-1, 1º e 0.1 s-1.
11
Trajectórias Óptimas
function [v,a,k]=
bom_tiro(xmin,ymin,vmin,vmax,amin,amax,kmin,kmax)
for vi = vmin:vmax
for alfa = amin:amax
for ka = kmin:0.1:kmax
[x, y, t] = tiro(vi,alfa,ka);
if x > xmin & y > ymin
v = vi; a = alfa; k = ka;
endif;
endfor;
endfor;
endfor;
endfunction;
12
Expressões Booleanas
• Este enunciado, embora correcto, é algo ineficiente, já que após a
descoberta de uma boa trajectória, todas as restantes trajectórias
são ainda calculadas!
• Esta ineficiência pode ser corrigida se se alterarem os ciclos
“para” por ciclos “enquanto”, mas impondo na condição de
entrada que não tenha sido ainda descoberta uma solução.
• Essa condição pode ser especificada através de uma expressão
booleana, resultante da conjunção de duas expressões booleanas
mais simples:
– A limitação normal do número de ciclos (p.ex. ka < kmax).
– Uma variável booleana, encontrada, que é falsa enquanto não
tiver sido encontrada uma solução
13
Expressões Booleanas
...
encontrada = 0
vi = vmin;
while vi <= vmax & !encontrada
alfa = amin;
while alfa <= amax & !encontrada
ka = kmin;
while ka <= kmax & !encontrada
[x, y, t] = tiro(vi,alfa,ka);
if x > xmin & y > ymin
v = vi; a = alfa; k = ka;
encontrada = 1
endif;
ka = ka + 0.1;
endwhile;
alfa = alfa + 1;
endwhile;
vi = vi + 1;
endwhile;
...
14
Expressões Booleanas
• Expressões booleanas podem ser construidas recursivamente a
partir de outras mais simples com os operadores booleanos de
– Conjunção, “e” ou “and”, expressa como & em OCTAVE
– Disjunção, “ou” ou “or”, expressa como | em OCTAVE
– Negação, “não” ou “not”, expressa como ! em OCTAVE
• As variáveis booleanas podem tomar os valores verdade ou falso.
Em OCTAVE, que só considera variáveis “numéricas”, 0
corresponde a falso e qualquer outro valor a verdade!
• De notar que uma variável booleana pode ser atribuído o valor
booleano de uma comparação numérica. Por exemplo:
encontrada = (x > xmin & y > ymax)
15
Excepções (em ciclos)
• Embora as expressões booleanas sejam muito convenientes e
permitam escrever programas muito compactos, neste caso a
passagem de ciclos “para” para ciclos “enquanto” torna os
programas menos “naturais”.
• Uma forma mais natural de expressar a intenção de descobrir a
solução é indicar que se pretende percorrer todo o intervalo de
possibilidades, excepto se se encontrar uma solução!
• A especificação de excepções é possível em muitas linguagens de
programação. No Octave utiliza-se a instrução “break”, para se
terminar excepcionalmente um ciclo.
16
Excepções (em ciclos)
• Por exemplo,
em vez da forma
pode utilizar-se a
forma mais simples
...
encontrada = 0; vi = vmin;
while vi <= vmax & !encontrada
...
if condição
encontrada = 1;
endif;
...
vi = vi + 1;
endwhile;
...
...
for vi = vmin:vmax
...
if condição
break;
endif;
...
endfor;
...
17
Excepções (em ciclos)
• Infelizmente, a explicitação de excepções não conduz sempre a
uma grande simplificação da especificação global do programa.
• No caso corrente, como existem três ciclos, ao sair do ciclo
interno (de ka) é necessário verificar se se deve igualmente sair do
ciclo intermédio (em alfa) e igualmente do ciclo externo (em vi).
• Em geral, é conveniente saber se o ciclo terminou de uma forma
“normal” ou “excepcional”, pelo que é conveniente continuar a
utilizar uma variável booleana para o efeito.
• Por exemplo, os três ciclos anteriores (em vi, alfa e ka) podem ser
especificados com excepções na forma
18
Excepções (em ciclos)
...
encontrada = 0
for vi = vmin: vmax
for alfa = amin:amax
for ka = kmin:kmax
[x, y, t] = tiro(vi,alfa,ka);
if x > xmin & y > ymi
v = vi; a = alfa; k = ka;
encontrada = 1; break;
endif;
endfor;
if encontrada
break
endif;
endfor;
if encontrada
break
endif;
endfor;
...
19
Excepções (em funções)
• Se, como é o caso corrente, existirem vários ciclos no interior de
uma função, e se se detectar no interior do ciclo mais interno que
o objectivo da função já foi atingido, existe um mecanismo de
excepção que permite terminar a função imediatamente.
• Assim, podem imediatamente terminar-se todos os ciclos, sem se
ter de verificar para cada um se o ciclo imediatamente interno
terminou com uma excepção ou não.
• No entanto, poderá ter interesse informar o programa (ou função)
que chama a função que pode terminar excepcionalmente, se a
sua terminação foi normal ou não, o que pode ser feito através de
uma variável adicional que é retornada no valor da função.
20
Trajectórias Óptimas
function [v,a,k,descoberta,x,y]=
bom_tiro(xmin,ymin,vmin,vmax,amin,amax,kmin,kmax)
descoberta = 0;
for vi = vmin:vmax
for alfa = amin:amax
for ka = kmin:0.1:kmax
[x, y, t] = tiro(vi,alfa,ka);
if x > xmin & y > ymin
v = vi; a = alfa; k = ka;
descoberta = 1; return;
endif;
endfor;
endfor;
endfor;
endfunction;
21
Um Pequeno Problema
• Em muitas situações, nomeadamente no corpo de ciclos, pretende-se trocar o valor de duas variáveis
AB
• Por hipótese, façamos A = 2 e B = 5.
• O problema é que ao fazer-se uma atribuição, por exemplo
AB
perde-se o valor inicial de A (fica A=B=5) e a atribuição B  A,
mantém a situação.
• A forma mais simples de resolver este problema é utilizar uma
variável secundária onde se guarda o valor inicial de A. As
instruções seguintes resolvem pois o problema:
CA % C=2
AB % A=5
BC % B=2
22
Download

Trajectórias Óptimas