{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Métodos numéricos usando Python (SciPy)\n", "======================================\n", "\n", "Visão geral\n", "--------\n", "\n", "O núcleo da linguagem Python (incluindo as bibliotecas padrão) fornece funcionalidades suficiente para realizar as tarefas de pesquisa computacional. No entanto, existem bibliotecas Python dedicadas (de terceiros) que oferecem funcionalidades estendidas:\n", "\n", "- ferramentas numéricas para tarefas freqüentes\n", "\n", "- que são convenientes\n", "\n", "- e mais eficientes em termos de tempo de processamento e requisitos de memória do que as funcionalidades do Python operando sozinhas.\n", "\n", "Nós enumeramos três desses módulos, em particular:\n", "\n", "- o módulo NumPy fornece um tipo de dado especializado para operar numericamente com vetores e matrizes (este é o tipo `array` fornecido pelo NumPy) além de ferramentas de álgebra linear.\n", "\n", "- o módulo Matplotlib (também conhecido como Pylab) fornece recursos de plotagem e visualização e \n", "\n", "- o módulo `SciPy` (*SCIentific PYthon*), que fornece uma infinidade de algoritmos numéricos (introduzido neste capítulo).\n", "\n", "Muitos dos algoritmos numéricos disponíveis através do SciPy e NumPy são fornecidos por bibliotecas compiladas estabelecidas que são muitas vezes escritas em Fortran ou C. Eles, por sua vez, serão executados muito mais rápido do que o código Python puro (interpretado). Como regra geral, esperamos que o código compilado seja duas ordens de magnitude mais rápido do que o código Python puro.\n", "\n", "Você pode usar a função de ajuda para cada método numérico para descobrir mais sobre a origem da implementação.\n", "\n", "SciPy\n", "-----\n", "\n", "O SciPy é construído com base no NumPy. Toda a funcionalidade do NumPy parece estar disponível também no SciPy. Por exemplo, em vez de:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import numpy\n", "x = numpy.arange(0, 10, 0.1)\n", "y = numpy.sin(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "podemos também usar:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import scipy as s\n", "x = s.arange(0, 10, 0.1)\n", "y = s.sin(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Primeiro, precisamos importar o SciPy" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import scipy as s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "O pacote SciPy fornece informações sobre sua própria estrutura quando usamos o comando de ajuda:\n", "\n", "```python\n", "help(scipy)\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A saída é muito longa. Então, estamos mostrando apenas parte dela aqui:\n", "\n", " stats --- Statistical Functions [*]\n", " sparse --- Sparse matrix [*]\n", " lib --- Python wrappers to external libraries [*]\n", " linalg --- Linear algebra routines [*]\n", " signal --- Signal Processing Tools [*]\n", " misc --- Various utilities that don't have another home.\n", " interpolate --- Interpolation Tools [*]\n", " optimize --- Optimization Tools [*]\n", " cluster --- Vector Quantization / Kmeans [*]\n", " fftpack --- Discrete Fourier Transform algorithms [*]\n", " io --- Data input and output [*]\n", " integrate --- Integration routines [*]\n", " lib.lapack --- Wrappers to LAPACK library [*]\n", " special --- Special Functions [*]\n", " lib.blas --- Wrappers to BLAS library [*]\n", " [*] - using a package requires explicit import (see pkgload)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Se estivermos procurando por um algoritmo para integrar uma função, podemos explorar o pacote `integrate`:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```python\n", "import scipy.integrate\n", "\n", "scipy.integrate?\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "produz:\n", "\n", "```text\n", "=============================================\n", "Integration and ODEs (:mod:`scipy.integrate`)\n", "=============================================\n", "\n", ".. currentmodule:: scipy.integrate\n", "\n", "Integrating functions, given function object\n", "============================================\n", "\n", ".. autosummary::\n", " :toctree: generated/\n", "\n", " quad -- General purpose integration\n", " dblquad -- General purpose double integration\n", " tplquad -- General purpose triple integration\n", " nquad -- General purpose n-dimensional integration\n", " fixed_quad -- Integrate func(x) using Gaussian quadrature of order n\n", " quadrature -- Integrate with given tolerance using Gaussian quadrature\n", " romberg -- Integrate func using Romberg integration\n", " quad_explain -- Print information for use of quad\n", " newton_cotes -- Weights and error coefficient for Newton-Cotes integration\n", " IntegrationWarning -- Warning on issues during integration\n", "\n", "Integrating functions, given fixed samples\n", "==========================================\n", "\n", ".. autosummary::\n", " :toctree: generated/\n", "\n", " trapz -- Use trapezoidal rule to compute integral.\n", " cumtrapz -- Use trapezoidal rule to cumulatively compute integral.\n", " simps -- Use Simpson's rule to compute integral from samples.\n", " romb -- Use Romberg Integration to compute integral from\n", " -- (2**k + 1) evenly-spaced samples.\n", "\n", ".. seealso::\n", "\n", " :mod:`scipy.special` for orthogonal polynomials (special) for Gaussian\n", " quadrature roots and weights for other weighting factors and regions.\n", "\n", "Integrators of ODE systems\n", "==========================\n", "\n", ".. autosummary::\n", " :toctree: generated/\n", "\n", " odeint -- General integration of ordinary differential equations.\n", " ode -- Integrate ODE using VODE and ZVODE routines.\n", " complex_ode -- Convert a complex-valued ODE to real-valued and integrate.\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As seções seguintes mostram exemplos que demonstram como empregar os algoritmos fornecidos pelo SciPy.\n", "\n", "Integração numérica\n", "---------------------\n", "\n", "O SciPy fornece uma série de rotinas de integração. Uma ferramenta com a finalidade de resolver integrais $I$ do tipo\n", "$$I = \\int_a^b f(x) \\, dx$$\n", "é fornecida pela função `quad()` do módulo `scipy.integrate`.\n", "\n", "Ela usa como argumento de entrada, a função a ser integrada $f(x)$ (\"integrando\") e os limites inferior $a$ e superior $b$. Ela retorna dois valores (em uma tupla): o primeiro é o resultado calculado e o segundo é uma estimativa do erro numérico desse resultado.\n", "\n", "Aqui está um exemplo que produz esta saída:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "O resultado numérico é 17.864264 (+-1.55113e-11)\n" ] } ], "source": [ "from math import cos, exp, pi\n", "from scipy.integrate import quad\n", "\n", "# função a ser integrada\n", "def f(x):\n", " return exp(cos(-2 * x * pi)) + 3.2\n", "\n", "# chamamos quad para integrar f de -2 a 2\n", "res, err = quad(f, -2, 2)\n", "\n", "print(\"O resultado numérico é {:f} (+-{:g})\".format(res, err))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note que `quad()` usa os parâmetros opcionais `epsabs` e `epsrel` para aumentar ou diminuir a precisão de sua computação. (Use `help(quad)` para saber mais.) Os valores padrão são `epsabs = 1.5e-8` e `epsrel = 1.5e-8`. Para o próximo exercício, os valores padrão são suficientes.\n", "\n", "### Exercício: integrar uma função\n", "\n", "1. Usando a função `quad` do SciPy, escreva um programa que resolva numericamente o seguinte: $I = \\int_0^1 \\cos(2\\pi x) \\, dx$.\n", "\n", "2. Encontre a integral analítica e compare-a com a solução numérica.\n", "\n", "3. Por que é importante ter uma estimativa da precisão (ou o erro) da integral numérica?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercício: plote antes de integrar\n", "\n", "É uma boa prática plotar a função integrando para verificar se ela é \"bem comportada\" antes de tentar integrá-la. Singularidades (ou seja, valores de $x$ para os quais $f(x)$ tende para menos ou mais infinito) ou outro comportamento irregular (como $f(x) = \\sin(\\frac{1}{x}$) perto de $x = 0$) são difíceis de manusear numericamente.\n", "\n", "1. Escreva uma função com o nome `plotquad` que leva os mesmos argumentos que o comando quad (i.e. $f$, $a$ e $b$) e que\n", "- (i) crie um gráfico do integrando $f(x)$ e\n", "- (ii) calcule a integral numérica usando a função `quad`. Os valores de retorno devem ser como aqueles para a função `quad`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Resolvendo equações diferenciais ordinárias (EDOs)\n", "---------------------------------------\n", "\n", "Para resolver uma EDO do tipo\n", "$$\\frac{dy}{dt}(t) = f(y,t)$$\n", "\n", "com uma dada condição inicial $y(t_0) = y_0$, podemos usar a função `odeint` do SciPy. Aqui está um programa de exemplo auto-explicativo (`useodeint.py`) para encontar\n", "\n", "$$y(t) \\quad \\mathrm{para} \\quad t \\in [0,2]$$\n", "dada a EDO :\n", "$$\\frac{dy}{dt}(t) = -2yt \\quad \\mathrm{com} \\quad y(0) = 1.$$" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n+/8uDQAI3oUggQAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "from scipy.integrate import odeint\n", "import numpy as N\n", "\n", "def f(y, t):\n", " \"\"\"este é o lado direito da EDO a ser integrada, i.e. dy/dt = f(y,t)\"\"\"\n", " return -2 * y * t\n", "\n", "y0 = 1 # valor inicial\n", "a = 0 # limites de integração para t\n", "b = 2\n", "\n", "t = N.arange(a, b, 0.01) # valores de t para\n", " # os quais queremos\n", " # a solução y(t)\n", "y = odeint(f, y0, t) # cálculo de y(t)\n", "\n", "import pylab # plotagem dos resultados\n", "pylab.plot(t, y)\n", "pylab.xlabel('t'); pylab.ylabel('y(t)')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "O comando `odeint` usa uma série de parâmetros opcionais para alterar a tolerância padrão de erro da integração (e para acionar a produção de saída de depuração). Use o comando de ajuda para explorá-los:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```python\n", "help(scipy.integrate.odeint)\n", "```\n", "\n", "irá mostrar:\n", "\n", "```\n", "Help on function odeint in module scipy.integrate.odepack:\n", "\n", "odeint(func, y0, t, args=(), Dfun=None, col_deriv=0, full_output=0, ml=None, mu=None, rtol=None, atol=None, tcrit=None, h0=0.0, hmax=0.0, hmin=0.0, ixpr=0, mxstep=0, mxhnil=0, mxordn=12, mxords=5, printmessg=0)\n", " Integrate a system of ordinary differential equations.\n", " \n", " Solve a system of ordinary differential equations using lsoda from the\n", " FORTRAN library odepack.\n", " \n", " Solves the initial value problem for stiff or non-stiff systems\n", " of first order ode-s::\n", " \n", " dy/dt = func(y, t0, ...)\n", " \n", " where y can be a vector.\n", " \n", " *Note*: The first two arguments of ``func(y, t0, ...)`` are in the\n", " opposite order of the arguments in the system definition function used\n", " by the `scipy.integrate.ode` class.\n", " \n", " Parameters\n", " ----------\n", " func : callable(y, t0, ...)\n", " Computes the derivative of y at t0.\n", " y0 : array\n", " Initial condition on y (can be a vector).\n", " t : array\n", " A sequence of time points for which to solve for y. The initial\n", " value point should be the first element of this sequence.\n", " args : tuple, optional\n", " Extra arguments to pass to function.\n", " Dfun : callable(y, t0, ...)\n", " Gradient (Jacobian) of `func`.\n", " col_deriv : bool, optional\n", " True if `Dfun` defines derivatives down columns (faster),\n", " otherwise `Dfun` should define derivatives across rows.\n", " full_output : bool, optional\n", " True if to return a dictionary of optional outputs as the second output\n", " printmessg : bool, optional\n", " Whether to print the convergence message\n", " \n", " Returns\n", " -------\n", " y : array, shape (len(t), len(y0))\n", " Array containing the value of y for each desired time in t,\n", " with the initial value `y0` in the first row.\n", " infodict : dict, only returned if full_output == True\n", " Dictionary containing additional output information\n", " \n", " ======= ============================================================\n", " key meaning\n", " ======= ============================================================\n", " 'hu' vector of step sizes successfully used for each time step.\n", " 'tcur' vector with the value of t reached for each time step.\n", " (will always be at least as large as the input times).\n", " 'tolsf' vector of tolerance scale factors, greater than 1.0,\n", " computed when a request for too much accuracy was detected.\n", " 'tsw' value of t at the time of the last method switch\n", " (given for each time step)\n", " 'nst' cumulative number of time steps\n", " 'nfe' cumulative number of function evaluations for each time step\n", " 'nje' cumulative number of jacobian evaluations for each time step\n", " 'nqu' a vector of method orders for each successful step.\n", " 'imxer' index of the component of largest magnitude in the\n", " weighted local error vector (e / ewt) on an error return, -1\n", " otherwise.\n", " 'lenrw' the length of the double work array required.\n", " 'leniw' the length of integer work array required.\n", " 'mused' a vector of method indicators for each successful time step:\n", " 1: adams (nonstiff), 2: bdf (stiff)\n", " ======= ============================================================\n", " \n", " Other Parameters\n", " ----------------\n", " ml, mu : int, optional\n", " If either of these are not None or non-negative, then the\n", " Jacobian is assumed to be banded. These give the number of\n", " lower and upper non-zero diagonals in this banded matrix.\n", " For the banded case, `Dfun` should return a matrix whose\n", " rows contain the non-zero bands (starting with the lowest diagonal).\n", " Thus, the return matrix `jac` from `Dfun` should have shape\n", " ``(ml + mu + 1, len(y0))`` when ``ml >=0`` or ``mu >=0``.\n", " The data in `jac` must be stored such that ``jac[i - j + mu, j]``\n", " holds the derivative of the `i`th equation with respect to the `j`th\n", " state variable. If `col_deriv` is True, the transpose of this\n", " `jac` must be returned.\n", " rtol, atol : float, optional\n", " The input parameters `rtol` and `atol` determine the error\n", " control performed by the solver. The solver will control the\n", " vector, e, of estimated local errors in y, according to an\n", " inequality of the form ``max-norm of (e / ewt) <= 1``,\n", " where ewt is a vector of positive error weights computed as\n", " ``ewt = rtol * abs(y) + atol``.\n", " rtol and atol can be either vectors the same length as y or scalars.\n", " Defaults to 1.49012e-8.\n", " tcrit : ndarray, optional\n", " Vector of critical points (e.g. singularities) where integration\n", " care should be taken.\n", " h0 : float, (0: solver-determined), optional\n", " The step size to be attempted on the first step.\n", " hmax : float, (0: solver-determined), optional\n", " The maximum absolute step size allowed.\n", " hmin : float, (0: solver-determined), optional\n", " The minimum absolute step size allowed.\n", " ixpr : bool, optional\n", " Whether to generate extra printing at method switches.\n", " mxstep : int, (0: solver-determined), optional\n", " Maximum number of (internally defined) steps allowed for each\n", " integration point in t.\n", " mxhnil : int, (0: solver-determined), optional\n", " Maximum number of messages printed.\n", " mxordn : int, (0: solver-determined), optional\n", " Maximum order to be allowed for the non-stiff (Adams) method.\n", " mxords : int, (0: solver-determined), optional\n", " Maximum order to be allowed for the stiff (BDF) method.\n", " \n", " See Also\n", " --------\n", " ode : a more object-oriented integrator based on VODE.\n", " quad : for finding the area under a curve.\n", " \n", " Examples\n", " --------\n", " The second order differential equation for the angle `theta` of a\n", " pendulum acted on by gravity with friction can be written::\n", " \n", " theta''(t) + b*theta'(t) + c*sin(theta(t)) = 0\n", " \n", " where `b` and `c` are positive constants, and a prime (') denotes a\n", " derivative. To solve this equation with `odeint`, we must first convert\n", " it to a system of first order equations. By defining the angular\n", " velocity ``omega(t) = theta'(t)``, we obtain the system::\n", " \n", " theta'(t) = omega(t)\n", " omega'(t) = -b*omega(t) - c*sin(theta(t))\n", " \n", " Let `y` be the vector [`theta`, `omega`]. We implement this system\n", " in python as:\n", " \n", " >>> def pend(y, t, b, c):\n", " ... theta, omega = y\n", " ... dydt = [omega, -b*omega - c*np.sin(theta)]\n", " ... return dydt\n", " ...\n", " \n", " We assume the constants are `b` = 0.25 and `c` = 5.0:\n", " \n", " >>> b = 0.25\n", " >>> c = 5.0\n", " \n", " For initial conditions, we assume the pendulum is nearly vertical\n", " with `theta(0)` = `pi` - 0.1, and it initially at rest, so\n", " `omega(0)` = 0. Then the vector of initial conditions is\n", " \n", " >>> y0 = [np.pi - 0.1, 0.0]\n", " \n", " We generate a solution 101 evenly spaced samples in the interval\n", " 0 <= `t` <= 10. So our array of times is:\n", " \n", " >>> t = np.linspace(0, 10, 101)\n", " \n", " Call `odeint` to generate the solution. To pass the parameters\n", " `b` and `c` to `pend`, we give them to `odeint` using the `args`\n", " argument.\n", " \n", " >>> from scipy.integrate import odeint\n", " >>> sol = odeint(pend, y0, t, args=(b, c))\n", " \n", " The solution is an array with shape (101, 2). The first column\n", " is `theta(t)`, and the second is `omega(t)`. The following code\n", " plots both components.\n", " \n", " >>> import matplotlib.pyplot as plt\n", " >>> plt.plot(t, sol[:, 0], 'b', label='theta(t)')\n", " >>> plt.plot(t, sol[:, 1], 'g', label='omega(t)')\n", " >>> plt.legend(loc='best')\n", " >>> plt.xlabel('t')\n", " >>> plt.grid()\n", " >>> plt.show()\n", "\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercício: usando `odeint`\n", "\n", "1. Abra um novo arquivo com o nome `testeEDOInt.py` em um editor de texto.\n", "\n", "2. Escreva um programa que calcule a solução $y(t)$ da EDO seguinte usando o algoritmo `odeint`:\n", "     $$\\frac{dy}{dt} = -\\exp(-t)(10 \\sin(10t) + \\cos (10t))$$\n", "      De $t = 0$ a $t = 10$. O valor inicial é $y(0) = 1$.\n", "\n", "3. Você deve exibir a solução graficamente nos pontos $t = 0$, $t = 0.01$, $t = 0.02$, ..., $t = 9.99$, $t = 10$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Localização de raízes\n", "------------\n", "\n", "Se você tentar encontrar um $x$ tal que\n", "$$f (x) = 0,$$\n", "então este é um problema chamado de *localização de raízes*. Observe que problemas como $g(x) = h(x)$ caem nesta categoria, pois você pode reescrevê-los como $f(x) = g(x) - h(x) = 0$.\n", "\n", "Várias ferramentas para localização de raízes estão disponíveis no módulo `optimize` do SciPy.\n", "\n", "### Localização de raiz pelo método de bisecção\n", "\n", "Primeiro, apresentamos o algoritmo `bisect`, que é (i) robusto e (ii) lento, mas conceitualmente muito simples.\n", "\n", "Suponhamos que precisemos calcular as raízes de $f(x) = x^3 - 2x^2$. Esta função tem uma raiz dupla em $x = 0$ (isto é trivial de ver) e outra raiz localizada entre $x = 1.5$ (pois $f(1.5) = - 1.125$) e $x = 3$ (pois $f(3) = 9$). É direto ver que esta outra raiz está localizada em $x = 2$. Aqui está um programa que determina esta raiz numericamente:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A raiz x é aproximadamente x= 2.00000023842,\n", "o erro é menor do que 1e-6.\n", "O erro exato é -2.38419e-07.\n" ] } ], "source": [ "from scipy.optimize import bisect\n", "\n", "def f(x):\n", " \"\"\"retorna f(x) = x^3 - 2x^2. Tem raízes em\n", " x = 0 (raiz dupla) e x = 2\"\"\"\n", " return x ** 3 - 2 * x ** 2\n", "\n", "# o programa principal começa aqui\n", "x = bisect(f, 1.5, 3, xtol=1e-6)\n", "\n", "print(\"A raiz x é aproximadamente x=%14.12g,\\n\"\n", " \"o erro é menor do que 1e-6.\" % (x))\n", "print(\"O erro exato é %g.\" % (2 - x))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "O método `bisect()` requer três argumentos obrigatórios: (i) a função $f(x)$, (ii) um limite inferior $a$ (para o qual escolhemos 1.5 no nosso exemplo) e (ii) um limite superior $b$ (para o qual escolhemos 3). O parâmetro opcional `xtol` determina o erro máximo do método.\n", "\n", "Um dos requisitos do método da bisecção é que o intervalo $[a,b]$ deve ser escolhido de tal forma que a função seja positiva em $a$ e negativa em $b$, ou que a função seja negativa em $a$ e positiva em $b$. Em outras palavras, $a$ e $b$ devem incluir uma raiz.\n", "\n", "### Exercício: localização de raízes usando o método `bisect`\n", "\n", "1. Escreva um programa com o nome `sqrt2.py` para determinar uma aproximação para $\\sqrt{2}$ encontrando uma raiz $x$ da função $f(x) = 2-x^2$ usando o algoritmo da bisecção. Escolha uma tolerância para a aproximação da raiz de $10^{-8}$.\n", "\n", "2. Documente a sua escolha do intervalo inicial $[a, b]$ para a busca da raiz: quais valores você escolheu para $a$ e $b$. Por quê?\n", "\n", "3. Estude os resultados:\n", "\n", "    - Que valor o algoritmo de bisecção retorna para a raiz $x$?\n", "\n", "    - Calcule o valor de $\\sqrt{2}$ usando `math.sqrt(2)` e compare-o com a aproximação da raiz. Quão grande é o erro absoluto de $x$? Como isso se compara com `xtol`?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Localização de raízes usando a função `fsolve`\n", "\n", "Um algoritmo (frequentemente) melhor (no sentido de \"mais eficiente\") do que o algoritmo da bisecção é implementado na função generalizada `fsolve()` para a localização de raízes de funções (multidimensionais). Este algoritmo precisa apenas de um ponto de partida próximo à provável localização da raiz (mas não possui convergência garantida).\n", "\n", "Aqui está um exemplo:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A raiz x é aproximadamente x= 2.000000000000006661\n", "O erro exato é -6.66134e-15.\n" ] } ], "source": [ "from scipy.optimize import fsolve\n", "\n", "def f(x):\n", " return x ** 3 - 2 * x ** 2\n", "\n", "x = fsolve(f, 3) # one root is at x=2.0\n", "\n", "print(\"A raiz x é aproximadamente x=%21.19g\" % x)\n", "print(\"O erro exato é %g.\" % (2 - x))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "O valor de retorno [6] de `fsolve` é uma matriz numpy de comprimento $n$ para um problema de localização de raízes com $n$ variáveis. No exemplo acima, temos $n = 1$.\n", "\n", "Interpolação\n", "-------------\n", "\n", "Dado um conjunto de $N$ pontos $(x_i, y_i)$ com $i = 1, 2, \\dots, N$, às vezes precisamos de uma função $\\hat{f}(x)$ que retorne $y_i = f(x_i)$ e que, além disso, forneça alguma interpolação dos dados $(x_i, y_i)$ para todo $x$.\n", "\n", "A função `y0 = scipy.interpolate.interp1d (x, y, kind = 'nearest')` realiza esta interpolação baseada em *splines* de ordem variável. Observe que a função `interp1d` retorna *uma função* `y0` que irá então interpolar os dados x-y para qualquer dado $x$ quando chamado como `y0(x)`.\n", "\n", "O código abaixo mostra isso, bem como os diferentes tipos de interpolação." ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import numpy as np\n", "import scipy.interpolate\n", "import pylab\n", "\n", "def cria_dados(n):\n", " \"\"\"Dado um inteiro n, retorne n pontos\n", " x e valores y como um numpy.array.\"\"\"\n", " xmax = 5.\n", " x = np.linspace(0, xmax, n)\n", " y = - x**2\n", " \n", " # faça os dados dos pontos x um tanto irregulares\n", " y += 1.5 * np.random.normal(size=len(x))\n", " return x, y\n", "\n", "# programa principal\n", "n = 10\n", "x, y = cria_dados(n)\n", "\n", "# usa uma malha mais fina e irregular para a plotagem\n", "xfine = np.linspace(0.1, 4.9, n * 100)\n", "\n", "# interpola com função constante por partes (p=0)\n", "y0 = scipy.interpolate.interp1d(x, y, kind='nearest')\n", "\n", "# interpola com função linear por partes (p=1)\n", "y1 = scipy.interpolate.interp1d(x, y, kind='linear')\n", "\n", "# interpola com função quadrática por partes (p=2)\n", "y2 = scipy.interpolate.interp1d(x, y, kind='quadratic')\n", "\n", "pylab.plot(x, y, 'o', label='dados')\n", "pylab.plot(xfine, y0(xfine), label='constante')\n", "pylab.plot(xfine, y1(xfine), label='linear')\n", "pylab.plot(xfine, y2(xfine), label='quadrática')\n", "pylab.legend()\n", "pylab.xlabel('x')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ajuste de curva\n", "-------------\n", "\n", "Já vimos que podemos ajustar funções polinomiais a um conjunto de dados usando a função `numpy.polyfit`. Aqui, apresentamos um algoritmo de ajuste de curva mais genérico.\n", "\n", "O SciPy fornece uma função um pouco genérica (baseada no algoritmo de Levenberg-Marquardt) através do `scipy.optimize.curve_fit` para ajustar uma determinada função (Python) a um conjunto de dados. O pressuposto é que temos um conjunto de dados com pontos $x_1, x_2, ... x_N$ e com valores de função correspondentes $y_i$ dependentes de $x_i$, tal que $y_i = f(x_i,\\textbf{p})$. Queremos determinar o vetor de parâmetros $\\textbf{p} = (p_1, p_2, \\dots, p_k)$ para que $r$, a soma dos resíduos, seja a menor possível:\n", "\n", "$$r = \\sum \\limits_{i = 1}^N \\left (y_i - f(x_i,\\textbf{p}) \\right)^2$$\n", "\n", "O ajuste da curva é de uso particular se os dados forem contaminados por ruídos: para um dado $x_i$ e $y_i = f(x_i, \\textbf{p})$, temos um termo de erro (desconhecido) $\\epsilon_i$ para que $y_i = f(x_i,\\textbf{p}) + \\epsilon_i$.\n", "\n", "Utilizamos o seguinte exemplo para esclarecer isso:\n", "$$f(x,\\textbf{p}) = a \\exp(-bx) + c, \\quad \\mathrm{i.e.} \\quad \\textbf{p} = (a, b, c)$$" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Os parâmetros ótimos são a=2.26288, b=1.50872, and c=0.605159\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXcAAAELCAYAAAAiIMZEAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xl8VNX9//HXJ8mEhDWyqQRZ3ADFQiIgiCBKFawWAdtq\nWxeqfrW1dlP5if2qtX7tV1qqba1W69ZNrfarmOJKVWxFVGSLAiIKFCUBCwQDCIFs5/fHncQQJplJ\ncmfuzOT9fDzmkVnOzHzmwnzm3HPP/RxzziEiIuklI+gARETEf0ruIiJpSMldRCQNKbmLiKQhJXcR\nkTSk5C4ikoaiJnczyzGzt83sHTNbbWY/jdCmg5k9YWbrzGyxmQ2IR7AiIhKbWHru+4HTnXPDgOHA\nZDMb3ajNZcCnzrmjgV8BP/c3TBERaYmoyd15PgvfDIUvjc98Ohf4U/j6k8BEMzPfohQRkRaJaczd\nzDLNrBjYCrzknFvcqEk+sAnAOVcN7AR6+BmoiIjELiuWRs65GmC4meUBT5vZUOfcqpa+mZldAVwB\n0KlTpxMHDx7c0pcQEWnXli1btt051ytau5iSex3nXLmZvQpMBhom91LgCKDEzLKAbkBZhOffD9wP\nMGLECLd06dKWvL2ISLtnZh/F0i6W2TK9wj12zCwXOAN4v1GzecAl4etfARY4VSQTEQlMLD33w4E/\nmVkm3o/B35xzz5rZrcBS59w84CHgL2a2DtgBXBC3iEVEJKqoyd059y5QEOH+mxtc3wd81d/QRESk\ntVo05i4iAlBVVUVJSQn79u0LOpS0lZOTQ9++fQmFQq16vpK7iLRYSUkJXbp0YcCAAeiUFv855ygr\nK6OkpISBAwe26jVUW0ZEWmzfvn306NFDiT1OzIwePXq0ac9IyV1EWkWJPb7aun1TL7lvXQMv/hiq\n9wcdiYhI0kq95F7+Mbx1D2xcGHQkIiJJK/WS+8DxEOoIa18IOhIRkaSVesk9lAtHne4ld50EKyJh\nt9xyC7/85S/j1j7VpFRyL1pRytjZC5i5sg/sKuXVf74cdEgiEoO67+7AWc8xdvYCilaUBh1S2kuZ\n5F60opQb5q6ktLyCBTUF1Dpj1auP6z+JSJJr+N11QGl5BTfMXenLd/dnP/sZxx57LKeccgpr166t\nv3/q1KmceOKJHH/88dx///1R2995550MHTqUoUOH8utf/xqAPXv2cPbZZzNs2DCGDh3KE088cdD7\nr1q1ipNPPrn+9vLly5k4cWKbP5cfUuYkpjnz11JRVQNAGd1Y7o5hAkv59vy1TC3IDzg6EWlKw+9u\nnYqqGua08bu7bNkyHn/8cYqLi6murqawsJATTzwRgIcffpju3btTUVHByJEjOe+889i4cWPE9suW\nLeMPf/gDixcvxjnHSSedxKmnnsqGDRvo06cPzz33HAA7d+48KIbjjjuODRs2UFNTQ2ZmJtdccw13\n3nlnqz+Tn1Km5765vOKA2y/XFHJCxkZqy0sCikhEYtH4uxvt/lgtXLiQadOm0bFjR7p27cqUKVPq\nH7vrrrsYNmwYo0ePZtOmTXz44YdNtn/99deZNm0anTp1onPnzkyfPp2FCxdywgkn8NJLL3H99dez\ncOFCunXrdlAMGRkZHH/88axevZqnnnqK/v37U1hYCMBNN93Ups/XVimT3Pvk5R5w+6Va7xd6eucW\nrxkiIgnU+Lsb7f62+uc//8nLL7/Mm2++yTvvvENBQUGrzvQ89thjWb58OSeccAI33ngjt956a8R2\no0ePZtGiRdxyyy387//+LwCffPIJVVVVbfocbZUyyX3mpEHkhjLrb693ffjIHcbF3VcHGJWIRNP4\nuwuQG8pk5qRBbXrd8ePHU1RUREVFBbt37+aZZ54BvOGTQw45hI4dO/L+++/z1ltvNdt+3LhxFBUV\nsXfvXvbs2cPTTz/NuHHj2Lx5Mx07duTCCy9k5syZLF++PGIco0eP5sYbb2TatGnk53vDTMXFxQwf\nPrxNn6+tUmbMvW5sbs78tWwur6BPXkeq8ifRf+NfYf9u6NAl4AhFJJKDv7u5zJw0qM3HygoLCzn/\n/PMZNmwYvXv3ZuTIkQBMnjyZ++67jyFDhjBo0CBGjx7dbPvCwkJmzJjBqFGjALj88sspKChg/vz5\nzJw5k4yMDEKhEPfee2/EOAYPHkyHDh24/vrr6+8rLi5m6tSpbfp8bWVBLZjkyzJ7G1+HP54NX/sz\nHHeuP4GJSFRr1qxhyJAhQYeRFK6++mpGjhzJJZdcUn/fZZddxgMPPEBGRtsGRyJtZzNb5pwbEe25\nKTMsE9ERoyEnT2erikjCrV+/nsGDB1NRUXFAYgd46KGH2pzY2yplhmUiysyCYyfBB/OhtgYyMqM/\nR0TEB0cddRTvv994Oenkkdo9d4BBZ0HFDtj0dtCRiIgkjdRP7kdNhIwQrH0+6EhERJJG6if3nK4w\ncJzG3UVEGkj95A4w6EtQ9iFs/zDoSEREkkJ6JPdjJ3t/I/TeVY1ORNqj9EjueUfAYScclNzjWY1O\nRCSZpUdyB29oZtNbsKes/q7mqtGJiKSzNEruZ4GrhQ9erL8rXtXoRESSXdok96JPerHZevPPub+v\nH1tPdDU6EUkODRfQiFV5eTm/+93vWvV+1157LcOGDeN73/seFRUVnHrqqdTU1ER9XmVlJePHj6e6\nurpV79uctEjuRStKueHpVRRVjeaUjJXsLf8PN8xdyWmDe8WlGp2IJLc33nijxc9pbXJfv349ixYt\n4p133uG3v/0tDz/8MNOnTyczM/oZ89nZ2UycODHiKk9tlRbJvW5s/ZmaMWRZLWdlLqGiqoZX39/G\n7dNPID8vFwPy83K5ffoJWrlJJE00tZxe586d2bhxI0OHDq2/75e//CW33HILEHkJvVmzZrF+/XqG\nDx/OzJkzAXjkkUcYNWoUw4cP58orrzyoN7527VomTJjARx99REFBAXv27OHRRx/l3HM/L2R42mmn\n8dJLLwFw44038r3vfe+gz/Doo4/6ul0g1WvLhNWNoa9x/VhX24cvZ7zJYzUT2VxewdSCfCVzkXh6\nYRZ8stLf1zzsBDhrdtRmkZbT69GjR9TnvfjiiwctoXfSSSexatUqiouLAa8i4xNPPMGiRYsIhUJc\nddVVPProo1x88cX1rzNo0CAuueQSBgwYwOWXX05lZSUbNmxgwIAB9W1++tOfcvPNN7N161ZWrFjB\nvHnzDohl6NChLFmyJJat0iJRe+5mdoSZvWpm75nZajP7QYQ2E8xsp5kVhy83+x5pMz4fQzeeqRnD\nSRlrOJQdGlsXSXORltOLRSxL6L3yyissW7aMkSNHMnz4cF555RU2bNhwULuVK1cybNgwALZv305e\nXt4Bj48fPx7nHHfeeSePP/54/XBN3TJ8mZmZZGdns3v37hZ99mhi6blXA9c655abWRdgmZm95Jx7\nr1G7hc65c3yNLkYzJw3ihrkrvaGZ2jH8yJ5iavbbDJk0K4hwRNqXGHrY8dBwOb2OHTsyYcKEA5bT\ny8rKora2tv52w8fqltB7/vnnufHGG5k4ceIBPXIA5xyXXHIJt99+e7NxrF69un74Jzc396Al/Vau\nXMmWLVvo0aMHXbp4iwo1XoZv//795OTktHALNC9qz905t8U5tzx8fTewBkiqcY6pBfn1Y+v/dn1Y\na0dyZY9iDceIpLGmltOrc+ihh7J161bKysrYv38/zz77bP1jkZbQ69KlywG954kTJ/Lkk0+ydetW\nAHbs2MFHH310wHvs3r2bUChEbq43SnDIIYdQU1NTn+C3bNnCN7/5Tf7+97/TuXNnXnzRm6rdcBm+\nsrIyevbsSSgU8nX7tGjM3cwGAAXA4ggPjzGzd4DNwHXOuYQubnrA2PrrH8LLP4FPN8IhAxIZhogk\nSFPL6QGYGaFQiJtvvplRo0aRn5/P4MGD6x9fuXLlQUvo9ejRg7FjxzJ06FDOOuss5syZw2233caZ\nZ55JbW0toVCIe+65h/79+9e/zqpVqw44aAtw5pln8vrrr3PyySczffp07rjjDoYMGcJNN93E9ddf\nz+TJkw9Yhu/VV1/l7LPP9n8DOediugCdgWXA9AiPdQU6h69/Cfiwide4AlgKLO3Xr5+Lmx0bnftJ\nV+deuyN+7yHSjr333ntBh9Ck7du3u7jmlyiWLVvmLrzwwmbbXHrppa6mpsY559y0adPc2rVrI7aL\ntJ2BpS6GnB3TVEgzCwFPAY865+ZG+IHY5Zz7LHz9eSBkZj0jtLvfOTfCOTeiV69eLf0dit0h/aHv\nKFh1UKgiksY2b97MmDFjuO666wKLobCwkNNOO63Zk5jqluGrrKxk6tSpHHvssb7HEXVYxswMeAhY\n45y7s4k2hwH/cc45MxuFN5ZfFqltwgw9D168HrathV46aUmkPejTpw8ffPBB0GFw6aWXxtQuOzv7\noAO5foml5z4WuAg4vcFUxy+Z2bfN7NvhNl8BVoXH3O8CLgjvPgTn+KmAwaqnAg1DRCQIUXvuzrnX\nAYvS5m7gbr+C8kWXw2DAKV5yn3ADWLMfQUQkraRF+YEmDT0PytbBJ+8GHYlI2gl65zzdtXX7pndy\nP+5cyMjS0IyIz3JycigrK1OCjxPnHGVlZW06sSktass0qWN3OOp0b9bMF3+qoRkRn/Tt25eSkhK2\nbdsWdChpKycnh759+7b6+emd3MEbmnn6SihZAkeMCjoakbQQCoUYOHBg0GFIM9J7WAa85fcyO8C7\nfws6EhGRhEn/5J7TFYacAyv/BlVaXk9E2of0T+4AhRfDvp2w5tnobUVE0kD7SO4DxkNef1jx56Aj\nERFJiPaR3DMyoOAi+PdrsOPgYvsiIummfSR3gOHfAMuAFY8EHYmISNy1n+TeLR+OPgOKH4Oa6qCj\n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\niKSh/w9oxQXGiZyWIQAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import numpy as np\n", "from scipy.optimize import curve_fit\n", "\n", "\n", "def f(x, a, b, c):\n", " \"\"\"Ajusta função y=f(x,p) com parâmetros p=(a,b,c). \"\"\"\n", " return a * np.exp(- b * x) + c\n", "\n", "# cria dados aleatórios\n", "x = np.linspace(0, 4, 50)\n", "y = f(x, a=2.5, b=1.3, c=0.5)\n", "\n", "# adiciona ruído\n", "yi = y + 0.2 * np.random.normal(size=len(x))\n", "\n", "# chama a função de ajuste\n", "popt, pcov = curve_fit(f, x, yi)\n", "a, b, c = popt\n", "print(\"Os parâmetros ótimos são a=%g, b=%g, and c=%g\" % (a, b, c))\n", "\n", "# plotagem\n", "import pylab\n", "yfitted = f(x, *popt) # equivalente a f(x, popt[0], popt[1], popt[2])\n", "pylab.plot(x, yi, 'o', label='dados $y_i$')\n", "pylab.plot(x, yfitted, '-', label='ajuste $f(x_i)$')\n", "pylab.xlabel('x')\n", "pylab.legend()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Observe que no código-fonte acima, definimos a função de ajuste $y = f(x)$ através do código Python. Podemos, portanto, ajustar funções (quase) arbitrárias usando o método `curve_fit`.\n", "\n", "A função `curve_fit` retorna uma tupla `popt, pcov`. A primeira entrada `popt` contém uma tupla dos parâmetros ótimos (no sentido de que estes minimizam o valor $r$). A segunda entrada contém a matriz de covariância para todos os parâmetros. As diagonais fornecem a variância dos parâmetro estimados.\n", "\n", "Para que o processo de ajuste de curva funcione, o algoritmo de Levenberg-Marquardt precisa iniciar o processo de ajuste com palpites iniciais para os parâmetros finais. Se estes não forem especificados (como no exemplo acima), o valor \"1.0\" é usado para o palpite inicial.\n", "\n", "Se o algoritmo falhar em obter uma função para os dados (mesmo que a função descreva os dados razoavelmente), precisamos dar ao algoritmo melhores estimativas para os parâmetros iniciais. Para o exemplo mostrado acima, podemos dar as estimativas para a função `curve_fit` mudando a linha\n", "\n", "```python\n", "Popt, pcov = curve_fit (f, x, yi)\n", "```\n", "para\n", "\n", "```python\n", "Popt, pcov = curve_fit (f, x, yi, p0 = (2,1,0.6))\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "se nossos palpites iniciais fossem $a = 2$, $b = 1$ e $c = 0.6$. Uma vez que tomamos o algoritmo \"aproximadamente na área correta\" no espaço de parâmetros, o ajuste geralmente funciona bem.\n", "\n", "Transformadas de Fourier\n", "------------------\n", "\n", "No exemplo seguinte, criamos um sinal como uma superposição de uma onda senoidal de 50 Hz e 70 Hz (com uma ligeira mudança de fase entre eles). Então, aplicamos a transformada de Fourier no sinal e plotamos o valor absoluto dos coeficientes (complexos) da transformada discreta de Fourier pela freqüência. Esperamos ver picos em 50Hz e 70Hz." ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\ndaYgAW+tfMkAAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import scipy\n", "import matplotlib.pyplot as plt\n", "pi = scipy.pi\n", "\n", "signal_length = 0.5 # [segundos]\n", "sample_rate=500 # taxa de amostragem [Hz]\n", "dt = 1./sample_rate # tempo entre as duas amostras[s]\n", "\n", "df = 1/signal_length # frequência entre pontos\n", " # no domínio da frequência [Hz] \n", "t=scipy.arange(0,signal_length,dt) # vetor tempo\n", "n_t=len(t) # comprimento do vetor de tempo\n", "\n", "# cria sinal\n", "y=scipy.sin(2*pi*50*t)+scipy.sin(2*pi*70*t+pi/4)\n", "\n", "# calcula a transformada de Fourier\n", "f=scipy.fft(y)\n", "\n", "# opera sobre as frequências significativas na transformada de Fourier\n", "freqs=df*scipy.arange(0,(n_t-1)/2.,dtype='d') # d = float com precisão dupla\n", "n_freq=len(freqs)\n", "\n", "# plota dados de entrada x tempo\n", "plt.subplot(2,1,1)\n", "plt.plot(t,y,label='dados de entrada')\n", "plt.xlabel('tempo [s]')\n", "plt.ylabel('sinal')\n", "\n", "# plota espectro de frequências\n", "plt.subplot(2,1,2)\n", "plt.plot(freqs,abs(f[0:n_freq]),\n", " label='abs(transformada Fourier)')\n", "plt.xlabel('frequência [Hz]')\n", "plt.ylabel('abs(DFT(sinal))')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "O gráfico inferior mostra a transformada discreta de Fourier (DFT) calculada a partir dos dados mostrados no gráfico superior." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Otimização\n", "------------\n", "\n", "Muitas vezes precisamos encontrar o máximo ou mínimo de uma função particular $f(x)$, onde $f$ é uma função escalar, mas $x$ poderia ser um vetor. As aplicações típicas são a minimização de algumas variáveis, tais como custo, risco e erro, ou a maximização de produtividade, eficiência e lucro. Rotinas de otimização normalmente fornecem um método para minimizar uma determinada função: se precisamos maximizar $f(x)$, criamos uma nova função $g(x)$ que inverte o sinal de $f$, ou seja, $g(x) = - f(x)$ e minimizamos $g(x)$.\n", "\n", "Abaixo, damos um exemplo mostrando (i) a definição da função de teste e (ii) a chamada da função `scipy.optimize.fmin`, que toma como argumento a função $f$ a ser minimizada e um valor inicial $x_0$ a partir do qual se inicia a busca pelo mínimo, e retorna o valor de $x$ para o qual $f(x)$ é (localmente) minimizado. Normalmente, a busca pelo mínimo é uma busca local, i.e, o algoritmo segue o gradiente local. Nós repetimos a busca pelo mínimo para dois valores ($x_0 = 1.0$ e $x_0 = 2.0$, respectivamente) para demonstrar que, dependendo do valor de partida, podemos encontrar diferentes mínimos para a função $f$.\n", "\n", "A maioria dos comandos (após as duas chamadas de `fmin`) no arquivo `fmin1.py` cria o gráfico da função, os pontos de partida para as buscas e o mínimo obtido:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Optimization terminated successfully.\n", " Current function value: -2.023866\n", " Iterations: 16\n", " Function evaluations: 32\n", "Busca iniciada em x=1., minimo é [ 0.23964844]\n", "Optimization terminated successfully.\n", " Current function value: -1.000529\n", " Iterations: 16\n", " Function evaluations: 32\n", "Busca iniciada em x=2., minimo é [ 3.13847656]\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\nzZqrawFOnDiRd999l7fffptVq1YB0LdvX7Zt2waATqfj5Zdf5sEHHzTCt6oZB7CWmUBX+//VHYBi\nGCoAmElZWRnDhg1Dq9U2uk9lZSVDhw6lurq6VXWUl5fTv39/evfuTc+ePfnLX/7S5GcOHTrE+PHj\nr/k5d+4cycnJ9OjRA4AOHToQEhLC448/zn/+8x+cnJwa/dwVOTk5BAfXrAru4OBwQ70vvvgiv//9\n7+teu7q6kpeXxz//+U8KCwvZuXNnq45BU6IDvcjKL6WwrOkgZm4pmRfxcnOiawfrT8qjWAarexDM\nVnzwwQdMnjy5wZPhFc7OzowcOZJVq1YxrRWP+ru4uLBp0yY8PDyoqqpi8ODB3HbbbQwYMKDRz8TE\nxLB27dobthcVFeHlVTNoWlJSQkZGBo6OjnXZjxr73BVBQUHk5OQQGxuLTqer2y6l5KmnnuK2226j\nT58+ddt9fHwoKiriqaeeavH3bonowJrvdORMIQMtPLXi7swC+oX5qJSgisGoO4BWWr58Ob169aJ3\n797cf//9ALz66qtER0cTHR3N66+/DtT0fY8bN47evXsTHR1d182xYsUK7rzzzrryRowYwYYNGwD4\n85//zB/+8AegpotkRSuTfQgh6k7QVVVVVFVVXTN//uTJk9x5553Ex8fTv39/jh071mhZERERZGdn\nU11dzaOPPsqLL75IbGwsSUlJzWrL5MmT+fLLL3nooYe44447SE5O5s033+S///0vGzdu5Isvvqjr\n9wc4ffo0ISZY4dJacgNcKKkg48JlNf9fMSirvgN4/tsjpJ4x7D/cqIC2/OWOnjfd58iRI7z44ots\n374dX19fCgoK2LNnD0uXLmXnzp1IKUlISGDYsGFkZGQQEBDAd999B0BhYSGVlZVkZGQQFhZ29bs8\n/zzPPfcc586dY9++fXX95NHR0ezevbvV30er1dK3b19OnDjB73//exISEoCagPDAAw+wZMkSunTp\nwrp161i8eDFLly5tsJz4+HjefvttHB0d+eCDmqTb8+fPb3Y72rRpc0PZiYmJADz66KPXbC8pKaFt\n27a4uLg0u/zWau/hQoCXq8UPBKdkXgTU/H/FsNQdQCts2rSJqVOn4utb02XQrl07tm3bxqRJk2jT\npg0eHh5MnjyZrVu3EhMTw4YNG3jyySfZunUrXl5eXLhwAW9v72vKHDp0KFJKXn31VVauXFnXNeTg\n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\nzsvNichObU0SAHZnFlCp1TGwi+r+UUzHtgPAokXg7n7tNnf3mu16EELc8Lq8vJyHH36YL774gkOH\nDjF37lzKy68mFWnTpo1edT777LOMGDGCw4cP8+23315TtmI8CZ3bsTf7IpXVOqPW80v6BRw1Qj0B\nrJiUbQeAadNgyRIIDa1JBh8aWvN62jS9is3OziY5ORmATz75hMGDB9edkH19fSkpKblprl9PT88G\nl1Xu0aMHmZmZpKenA/Dpp5/WvVdYWEhgYCBQkz5SMY2E8HaUV+k4dNq4TwUnp+cTF+KNu7OpVmhX\nFFsPAFBzss/MBJ2u5r96nvwBunfvzhtvvEFkZCQXL17koYcewtvbm7lz5xIdHc2tt95Kv379Gv38\nvffey8svv0xcXFzdyR5qljdesmQJ48aNo0+fPnTseHUp4AULFvD0008TFxd30+QwQ4YMYerUqfz0\n008EBQWxfv16vb+vPetXuyTDDiNOBy0sreLQ6UIGqumfiompy41WcHR05OOPP75h+4svvsiLL754\nw/brE0QMGjTommmg9a/ox44dS1pa2g1lJCYmcvz48WvqasjWrVubar7SAu09XIjo6MGukwX8foRx\n6kjOyEdK1ACwYnK2fwegKHrqH96OlMwCqrXGGQfYnn4BNycHYmvzESuKqagA0EJhYWEcPqzSGdiT\nhM7tuVypJTW3yOBlSynZlHaOxC7tcXZU/xwV01J/cYrShAG1M3O2/nrB4GUfzS0m52IZY6L8DF62\nojRFBQBFaULHtq70CvJiQ2rjSeJb68fUswgBIyNVAFBMTwUARWmGUZF+7D91iXPFhn3+4scjefQN\n8aGDp4tBy1WU5lABQFGaYXRtF82mo+cMVmbOxVJSc4sY01Nd/SvmYdMBIO6dOMTz4oafuHfijF73\nmjVrWLx48U33OXPmDFOmTDF43a+++ipRUVH06tWLkSNHkpWVZfA67E2PTp4EersZtBvoSlmjozoZ\nrExFaQmbDgCJQYk4O1y7sqKzgzMDgwYave4JEybw1FNP3XSfgICAmz4x3FpxcXGkpKRw8OBBpkyZ\nwoIFCwxeh70RQjA6yo9tJy5QWmmYNJE/Hsmjm58H4b76LROiKK1l0wHg2aHPohHXfkUH4cCzw55t\ndZlXloOeNWsW3bp1Y9q0aWzcuJFBgwYRERHBrl27gJqHux555BEAZs2axaOPPsrAgQPp3Llz3Uk/\nMzOT6Ojouv0nTpzI6NGjCQsL43//+x+vvvoqcXFxDBgwgIKCmidR9+/fz4ABA+jVqxeTJk3i4sUb\nlyoeMWIE7rVrIA0YMICcnJxWf1/lqtFRflRU6wwyG+ji5Up2ZRYwRl39K2Zk0wHA39Of2bGz6+4C\nnB2cmR07m04e+v2jO3HiBI8//jhpaWmkpaXxySefsG3bNl555RX+/ve/N/iZ3Nxctm3bxtq1axu9\nMzh8+DCrV69m9+7dLFy4EHd3d/bt20diYiLLly8HYMaMGbz00kscPHiQmJgYnn/++Zu29f333+e2\n227T6/sqNfqHt8PT1ZGNBugG2pR2Dq1Oqv5/xaxsOgDAtXcB+l79XxEeHk5MTAwajYaePXsycuRI\nhBDExMSQmZnZ4GcmTpyIRqMhKiqKvLyGTyAjRozA09OTDh064OXlxR133AFQV25hYSGXLl1i2LBh\nAMycOZMtW7Y02s6PP/6YlJQU5s+fr98XVgBwctAwontHNqWdQ1eb7Ke1fkw9S6e2rsQEehmodYrS\ncjYfAK7cBWiExiBX/wAuLlen7Gk0mrrXGo2m0YXa6n9GNnLyaE25jdm4cSOLFi1izZo115Sr6Gd0\nlB/5lytJv9T6ZSFKKqrZcvwCo6P8blhaXFFMyeYDANTcBQwOGWyQq39z8vLywsfHp27Bt48++qju\nbqC+ffv28bvf/Y41a9Zcs6Koor9h3Tvg5CDYe671eYK/3JNDWZWWyX0CDdgyRWk5u1gN1N/Tn59n\n/WzuZhjEsmXLePDBByktLaVz584sXbr0hn3mz59PSUkJU6dOBSAkJIQ1a9aYuqk2qa2rE4O7+pKc\neYHKal2L1+/R6STLkjPpHexNXIiPcRqpKM0kGuuOsATx8fEyJSXlmm1Hjx4lMjLSZG0oLi5WSdZr\nWdqxMPXfwhU/Hz/PzA928crU3kzpG9Sqz75+TywT42zjDiApKYnhw4ebuxkWwRKOhRBij5Qyvjn7\n2kUXkKIY0tAIXwI9BO9tzWh0PKcxH/5ykg6eLtwe42+k1ilK86kAoCgtJITg1jAn0s4W88uJ/GZ/\n7uSFy2w+dp7f9A9RSz8rFkH9FSpKKyQGOOLr4cK7WzOa/ZnlyZk4OQimJYQYr2GK0gIqAChKKzhp\nBDMSQ/n5+HmO5xU3uX9JRTWfp+QwLsafjm1dTdBCRWmaCgCK0krTB4Ti6qTh/a0nm9z3v5t+paSi\nmpkDw4zfMEVpJr0CgBDiZSFEmhDioBDiKyFEg0lNhRBjhRDHhBAnhBA3XyFNUaxEuzbO3NUniK/2\nnWZv9o1rMl3x45GzvPNzBvf1D1ZTPxWLou8dwAYgWkrZCzgOPH39DkIIB+AN4DYgCrhPCBGlZ73N\ntuLQCsJeD0PzvIaw18NYcWiFqapu1Ndff01qamrd6+eee46NGzfesF9SUhLjx49vdrn79+8nMTGR\nnj170qtXL1atWmWQ9iqN+9Oobvh7uzJ76W6Onb2xK+jkhcs8/tkBYgK9+MsdPc3QQkVpnF4Pgkkp\nf6z3cgfQ0OL2/YETUsoMACHESuBOILWBfQ1qxaEVzPt2HqVVpQBkFWYx79t5AEyLmWbs6htUXV3N\n119/zfjx44mKqomDL7zwgkHKdnd3Z/ny5URERHDmzBn69u3Lrbfeird3gzdmigF08HTh498mcNdb\n26FPHOSmX/N+OPB5py54pB7E1cnBPI1UlEYY8kngOUBDl5yBwKl6r3OAhMYKEULMA+YB+Pn5kZSU\ndM37Xl5eFBc3PegG8PSGp+tO/leUVpXy9IanmRA2oVllaLXaa+rLyspi8uTJxMbGcuDAASIjI3nn\nnXdwd3dn8eLFfP/995SXl5OQkMC///1vhBDcfvvtxMTEsGPHDsaPH88333xDUlISL7zwAh999BH/\n/Oc/GTt2LBMnTmTDhg089dRTuLu7M2DAAKqrqykuLiYlJYUnn3ySiooKXF1deeutt4iIiLimrf7+\nNXPLrzyw5evry8mTJ+natWuzvmtLj4W5lZeX3/D3YSolJSXX1P1oLw17A7oRfi4LZ+3VdZsqHByp\n7BXFiQO7OGGGdprC9cfCnlndsZBS3vQH2AgcbuDnznr7LAS+ovbJ4us+PwV4r97r+4H/NVWvlJK+\nffvK66Wmpt6wrTHir0LyV274EX8VzS6jqKjomtcnT56UgNy2bZuUUsrZs2fLl19+WUopZX5+ft1+\n06dPl2vWrJFSSjls2DD50EMP1b03c+ZM+fnnn9/wuqysTAYFBcnjx49LnU4np06dKseNGyellLKw\nsFBWVVVJKaXcsGGDnDx58k3bvXPnTtmjRw+p1Wqb/V2bcv2xMLeW/C0Y2ubNm2/YdnBXqixzdJYS\n6n6qXFylzM01fQNNqKFjYa8s4VgAKbIZ51cpZdNjAFLKUVLK6AZ+vgEQQswCxgPTaiu/3mkguN7r\noNptRhfi1fB868a2N1dwcDCDBg0CYPr06Wzbtg2AzZs3k5CQQExMDJs2beLIkSN1n7nnnnuaLDct\nLeeqfToAAAZ1SURBVI3w8HAiIiIQQjB9+vS69woLC5k6dSrR0dE89thj15R9vdzcXO6//36WLl2K\nRqMmeplKTL9InB+Yg3SuzULn7Izjb+dAJ5X0RbFM+s4CGgssACZIKUsb2W03ECGECBdCOAP3AiZZ\nmWzRyEW4O7lfs83dyZ1FIxfpVe71S/gKISgvL+fhhx/miy++4NChQ8ydO5fy8vK6fdq00S/t37PP\nPsuIESM4fPgw33777TVl11dUVMS4ceNYtGgRAwYM0KtOpeU0zz2HuBJ0HRzgWetegVaxbfpeHv4P\n8AQ2CCH2CyHeBhBCBAgh1gFIKauBR4D1wFHgMyll45evBjQtZhpL7lhCqFcoAkGoVyhL7lii9wBw\ndnY2ycnJAHzyyScMHjy47oTs6+tLSUnJTXP9enp6NtiX3qNHDzIzM0lPrxlI/PTTT+veKywsJDCw\nZvGwDz/8sMFyKysrmTRpEjNmzDBKsnmlGfz9YfZs0Ghq/quu/hULpu8soAZHF6WUZ4Db671eB6zT\np67WmhYzzeAzfrp3784bb7zBnDlziIqK4qGHHsLd3Z25c+cSHR1Np06d6NevX6Ofv/fee5k7dy7/\n+c9/rgkUrq6uLFmyhHHjxuHu7s6QIUPqAsWCBQuYOXMmL774IuPGjWuw3M8++4wtW7aQn59fFyQ+\n/PBDYmNjDffllaY9+ywcOaKu/hWLp5aDbsL1SyBnZmYyfvx4Dh8+bLI2WAq1HPRVlrDsr6VQx+Iq\nSzgWajloRVEUpUkqALRQWFiYXV79K4pie6wyAFhyt5ViGupvQFH0Z3UBwNXVlfz8fHUCsGNSSvLz\n83F1VcsqK4o+rC4pfFBQEDk5OZw/f94k9ZWXl6sTTS1LOhaurq4EBbUsH6+iKNeyugDg5OREeHi4\nyepLSkoiLi7OZPVZMnUsFMW2WF0XkKIoimIYKgAoiqLYKRUAFEVR7JRFPwkshDgPZJm5Gb7ABTO3\nwVKoY3GVOhZXqWNxlSUci1ApZYfm7GjRAcASCCFSmvtYta1Tx+IqdSyuUsfiKms7FqoLSFEUxU6p\nAKAoimKnVABo2hJzN8CCqGNxlToWV6ljcZVVHQs1BqAoimKn1B2AoiiKnVIBQFEUxU6pANACQojH\nhRBSCOFr7raYixDiZSFEmhDioBDiKyGEt7nbZEpCiLFCiGNCiBNCiKfM3R5zEUIECyE2CyFShRBH\nhBB/NHebzE0I4SCE2CeEWGvutjSXCgDNJIQIBsYA2eZui5ltAKKllL2A48DTZm6PyQghHIA3gNuA\nKOA+IUSUeVtlNtXA41LKKGAA8Hs7PhZX/BE4au5GtIQKAM33GrAAsOtRcynlj1LK6tqXOwB7WpO5\nP3BCSpkhpawEVgJ3mrlNZiGlzJVS7q39vZiaE1+geVtlPkKIIGAc8J6529ISKgA0gxDiTuC0lPKA\nudtiYeYA35u7ESYUCJyq9zoHOz7pXSGECAPigJ3mbYlZvU7NBaLO3A1pCavLB2AsQoiNQKcG3loI\nPENN949duNmxkFJ+U7vPQmq6AVaYsm2KZRFCeABfAn+SUhaZuz3mIIQYD5yTUu4RQgw3d3taQgWA\nWlLKUQ1tF0LEAOHAASEE1HR57BVC9JdSnjVhE02msWNxhRBiFjAeGCnt60GS00BwvddBtdvskhDC\niZqT/wop5Wpzt8eMBgEThBC3A65AWyHEx1LK6WZuV5PUg2AtJITIBOKllOZe8e//27tDnAaiKArD\n5ySElAAKhcRjMSBIikGwgiawggoESyDBoRC1GAQSR0iQGEwNO0BXkxByEe8tYGZI+kru/63giGbO\nvLnpu03YPpV0K+k4Ipazl3NF2F5TGXyfqDz43yVNIuKjabAGXN6G7iUtIuKydZ5VUU8AVxFx1jpL\nF8wA0NedpG1JL7bntmetAy1LHX5PJT2rDD0fMz78qyNJ55LG9Xcwr2/A+Ec4AQBAUpwAACApCgAA\nkqIAACApCgAAkqIAACApCgAAkqIAACApCgDoyPZB3YMwsr1Z78Hfb50LGIo/ggE92L5Wue9lQ9Jn\nRNw0jgQMRgEAPdheV7kD6EvSYUT8NI4EDMYnIKCfHUlbKvchjRpnAf6EEwDQg+0nlU1ge5J2I2La\nOBIwGPsAgI5sX0j6joiHuh/4zfY4Il5bZwOG4AQAAEkxAwCApCgAAEiKAgCApCgAAEiKAgCApCgA\nAEiKAgCApH4B27tfj/UFKw0AAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from scipy import arange, cos, exp\n", "from scipy.optimize import fmin\n", "import pylab\n", "\n", "def f(x):\n", " return cos(x) - 3 * exp( -(x - 0.2) ** 2)\n", "\n", "# encontra mínimos de f(x),\n", "# começa de 1.0 e 2.0 respectivamente\n", "minimum1 = fmin(f, 1.0)\n", "print(\"Busca iniciada em x=1., minimo é\", minimum1)\n", "minimum2 = fmin(f, 2.0)\n", "print(\"Busca iniciada em x=2., minimo é\", minimum2)\n", "\n", "# plota função\n", "x = arange(-10, 10, 0.1)\n", "y = f(x)\n", "pylab.plot(x, y, label='$\\cos(x)-3e^{-(x-0.2)^2}$')\n", "pylab.xlabel('x')\n", "pylab.grid()\n", "pylab.axis([-5, 5, -2.2, 0.5])\n", "\n", "# adiciona minimo1 para plot\n", "pylab.plot(minimum1, f(minimum1), 'vr',\n", " label='minimo 1')\n", "# adiciona ponto de partida 1 para plot\n", "pylab.plot(1.0, f(1.0), 'or', label='partida 1')\n", "\n", "# adiciona minimo2 para plot\n", "pylab.plot(minimum2,f(minimum2),'vg',\\\n", " label='minimo 2')\n", "\n", "# adiciona ponto de partida 2 para plot\n", "pylab.plot(2.0,f(2.0),'og',label='partida 2')\n", "\n", "pylab.legend(loc='lower left')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A chamada da função `fmin` produzirá algum diagnóstico de saída, como você pode ver acima.\n", "\n", "##### Valor de retorno de `fmin`\n", "\n", "Note que o valor de retorno da função `fmin` é um `array` do numpy que - para o exemplo acima - contém apenas um número já que temos um único parâmetro (aqui $x$) para variar. Em geral, `fmin` pode ser usada para encontrar o mínimo em um espaço de parâmetros de dimensão superior se houver vários parâmetros. Nesse caso, o `array` numpy conteria aqueles parâmetros que minimizam a função objetivo. A função objetivo $f(x)$ tem que retornar um escalar mesmo que haja mais parâmetros, ou seja, mesmo se $x$ for um vetor." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Outros métodos numéricos\n", "-----------------------\n", "\n", "SciPy e NumPy proporcionam o acesso a um grande número de outros algoritmos numéricos, incluindo interpolação, transformadas de Fourier, otimização, funções especiais (tais como funções de Bessel), processamento de sinais e filtros, geração de números aleatórios, e mais. Você pode começar a explorar as capacidades desses dois módulos usando a função `help` ou a documentação fornecida na web." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "scipy.io: entrada e saída no SciPy\n", "----------------------------\n", "\n", "O SciPy fornece rotinas para ler e escrever arquivos `.mat` do Matlab. Aqui está um exemplo de criação de um arquivo compatível com Matlab armazenando uma matriz (1x11), e posterior leitura desses dados em uma matriz numpy do Python usando a biblioteca de entrada e saída do SciPy:\n", "\n", "Primeiro criamos um arquivo `.mat` no Octave (Octave é, na maioria dos casos, compatível com Matlab):\n", "\n", "```octave\n", "octave: 1> a = -1: 0,5: 4\n", "a =\n", "Columns 1 through 6:\n", " -1,0000 -0,5000 0,0000 0,5000 1,0000 1,5000\n", "Columns 7 through 11:\n", " 2,0000 2,5000 3,0000 3,5000 4,0000\n", "octave: 2> save -6% octave_a.mat a % salva como versão 6\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Então, carregamos este *array* no Python:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from scipy.io import loadmat\n", "mat_contents = loadmat('static/data/octave_a.mat')" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'__globals__': [],\n", " '__header__': b'MATLAB 5.0 MAT-file, written by Octave 4.0.3, 2017-06-29 01:52:49 UTC',\n", " '__version__': '1.0',\n", " 'a': array([[-1. , -0.5, 0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. ]])}" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mat_contents" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[-1. , -0.5, 0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. ]])" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mat_contents['a']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A função `loadmat` retorna um dicionário: a chave (*key*) para cada item no dicionário é uma *string* cujo nome é o mesmo da matriz que foi salva no Matlab.\n", "\n", "Um arquivo Matlab pode conter vários *arrays*. Cada um deles é apresentado por um par chave-valor (*key:value*) no dicionário.\n", "\n", "Vamos salvar dois *arrays* a partir do Python para demonstrar isso:" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import scipy.io\n", "import numpy as np\n", "\n", "# cria dois arrays numpy\n", "a = np.linspace(0, 50, 11)\n", "b = np.ones((4, 4))\n", "\n", "# salva como arquivo mat\n", "# cria dicionario para savemat\n", "tmp_d = {'a': a,\n", " 'b': b}\n", "scipy.io.savemat('static/data/a_b.mat', tmp_d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This program creates the file `a_b.mat`, which we can subsequently read using Matlab or here Octave:\n", "\n", "Este programa cria o arquivo `a_b.mat`, que podemos subsequentemente ler usando o Matlab ou\n", "\n", " HAL47:code fangohr$ octave\n", " GNU Octave, version 3.2.4\n", " Copyright (C) 2009 John W. Eaton and others.\n", " \n", "\n", " octave:1> whos\n", " Variables in the current scope:\n", "\n", " Attr Name Size Bytes Class\n", " ==== ==== ==== ===== ===== \n", " ans 1x11 92 cell\n", "\n", " Total is 11 elements using 92 bytes\n", "\n", " octave:2> load data.mat\n", " octave:3> whos\n", " Variables in the current scope:\n", "\n", " Attr Name Size Bytes Class\n", " ==== ==== ==== ===== ===== \n", " a 11x1 88 double\n", " ans 1x11 92 cell\n", " b 4x4 128 double\n", "\n", " Total is 38 elements using 308 bytes\n", "\n", " octave:4> a\n", " a =\n", "\n", " 0\n", " 5\n", " 10\n", " 15\n", " 20\n", " 25\n", " 30\n", " 35\n", " 40\n", " 45\n", " 50\n", "\n", " octave:5> b\n", " b =\n", "\n", " 1 1 1 1\n", " 1 1 1 1\n", " 1 1 1 1\n", " 1 1 1 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note que há outras funções para leitura/escrita em formatos usados por IDL, Netcdf e outros na `scipy.io`.\n", "\n", "Para saber mais → veja [Tutorial Scipy](http://docs.scipy.org/doc/scipy/reference/tutorial/io.html)." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4" } }, "nbformat": 4, "nbformat_minor": 2 }