domingo, 3 de janeiro de 2010

É o máximo!

Acontece com frequência termos que calcular o máximo (ou o mínimo) de uma função f. Isto é, queremos saber qual o valor de x para o qual f(x) assume o valor máximo (ou o mínimo).

O princípio de solução para esta questão não é difícil: calculamos o valor de da função em todos os pontos, identificamos o valor mais elevado (ou mais baixo, no caso do mínimo) e com isso sabemos o valor de x. Trata-se de uma actividade que aponta claramente para o uso de um ciclo for.

A questão mais delicada reside no facto de os cálculos serem feitos com o valor de f(x), mas o que pretendemos identificar é o argumento x. Por isso vamos precisar de manter memorizado o valor melhor para a função e o correspondente valor do argumento. Quanto ao mais podemos assumir que os valores do domínio podem estar ou não ordenados.

Vejamos a implementação e o teste para o caso da função seno.
01.from math import sin,radians
02. 
03.def arg_max(dom,func):
04.    """Calcula o máximo da função no domínio dado."""
05.    x_max = dom[0]
06.    f_max = func(x_max)
07.     
08.    for x in dom:
09.        x_val = func(x)
10.        if x_val > f_max:
11.            x_max,f_max = x,x_val
12.    return x_max
13. 
14. 
15.if __name__ == '__main__':
16.    valores = [radians(g) for g in range(0,360,45)]
17.    print arg_max(valores,sin)

Como se pode verificar usamos o facto de podermos passar como argumento uma função!

E se quisermos calcular o mínimo? Bem, o mínimo é o simétrico do máximo, certo? Então:
1.def arg_min(dom,func):
2.    """Calcula o mínimo da função."""
3.    return arg_max(dom, lambda x: -func(x))


Mas porque é que não podemos fazer simplesmente:
1.def arg_min(dom,func):
2.    """Calcula o mínimo da função."""
3.    return arg_max(dom, -func)

A resposta: assim não estaríamos a passar a referência para uma função mas a tentar fazer uma operação (unária neste caso) com um nome que não o permite. As funções lambda são também chamadas funções anónimas. Apenas existem durante o seu uso. Têm uma sintaxe simples:

lambda parâmetros : expressão

Os parâmetros podem existir ou não. Na expressão não podemos ter ciclos, nem return.Exemplos:
01.>>> func = lambda n : n + 3
02.>>> func(5)
03.8
04.>>> area_tri = lambda b,a: 0.5 * b * a
05.>>> area_tri(4,3)
06.6.0
07.>>> primo = lambda x: x[0]
08.>>> resto = lambda x: x[1:]
09.>>> lista = [1,2,3,4,5]
10.>>> primo(lista)
11.1
12.>>> resto(lista)
13.[2, 3, 4, 5]
14.>>> junta = lambda e,l: [e] + l
15.>>> junta(6,lista)
16.[6, 1, 2, 3, 4, 5]
17.>>> junta(primo(lista),resto(lista))
18.[1, 2, 3, 4, 5]
19.>>>

Sem comentários:

Enviar um comentário