#!/usr/bin/env python # coding: utf-8 # # Table of Contents #

Кратчайшее введение в Python для математики
Что это?
Всё взять и запустить!
Что-что, простите?
Картинка для привлечения внимания
Базовый Python
Арифметика
Структуры данных
Списки
Кортежи
Словари
Множества
Управляющие конструкции
Проверка условий
Циклы
Цикл for
Цикл while
Математические библиотеки
numpy
scipy
Линейная алгебра
Интегрирование и решение дифференциальных уравнений
sympy
matplotlib
Scatter plot
Полярные координаты
Векторные поля и ОДУ
Линии уровня (contour plot)
Виджеты
# # Кратчайшее введение в Python для математики # *Илья Щуров, НИУ ВШЭ.* # # Документ распространяется по лицензии [CC BY-SA 4.0 Unported](https://creativecommons.org/licenses/by-sa/4.0/deed.ru). Все фрагменты кода в этом блокноте переданы в [общественное достояние](https://creativecommons.org/publicdomain/zero/1.0/). Исходные коды доступны на [github](https://github.com/ischurov/odebook/mathandpython.ipynb). # ## Что это? # # Этот документ предназначен для тех, кто хочет быстро начать использовать Python при решении математических и околоматематических задач. В нём предполагается, что вы уже обладаете базовыми навыками программирования, но не знаете Python. Если таких навыков нет, вы, возможно, сможете использовать отдельные рецепты отсюда, но вряд ли получите ту свободу, которую даёт знание универсального языка программирования. # # Если вы никогда раньше не программировали — или наоборот, хотите освоить базовый Python более фундаментально, а уже потом переходить к его математическим приложениям — я рекомендую интерактивный курс [Pythontutor.ru](http://pythontutor.ru/) (там есть визуализатор пошагового выполнения кода и задачи с автоматической проверкой) или мой [курс по Python в ВШЭ](http://math-info.hse.ru/s15/m) (там есть видеолекции, ко всему прочему). # # По каждому разделу приводятся ссылки, с помощью которых вы можете подробнее узнать о данной теме. # ## Всё взять и запустить! # Самый простой способ запустить *Python*, ничего не устанавливая — использовать http://colab.research.google.com/ и запустить *New Notebook*. Откроется notebook, состоящий из ячеек. Если в ячейку ввести код и нажать *Shift + Enter*, он выполнится. Минусы: вы привязаны к интернету (код запускается на серверах Google), доступен только Python 3.6. # # Чуть сложнее: [скачать Anaconda](http://continuum.io/downloads), установить, найти в меню «Пуск» или его аналоге *Jupyter Notebook* или *IPython Notebook* и запустить. (Под Mac OS это Anaconda Launcher.) Откроется окно браузера, в нём надо выбрать *New → Python 3* или что-то похожее. # # ### Что-что, простите? # # Немного терминологии, чтобы не запутаться. # # - **Python** — это язык программирования. Мы будем использовать Python 3 (Python версии 2 больше не поддерживается). # - **Anaconda** — это дистрибутив, включающий в себя Python и всякие другие полезные для нас штуки, в том числе множество научных библиотек, которыми мы будем пользоваться. # - **Jupyter** — это среда, с помощью которой можно работать с Python в интерактивном режиме: ввели команду — получили результат. Когда-то давно она называлась **IPython Notebook**, но сейчас она умеет работать с другими языками и её переименовали в Jupyter. # - **Блокнотами (notebook)** называются документы, получающиеся при такой интерактивной работе. Они состоят из ячеек с кодом, результатами выполнения кода и дополнительными комментариями. Этот документ также является блокнотом. Блокноты имеют расширение ipynb. # ### Картинка для привлечения внимания # Подробнее о картинках [см. ниже](#matplotlib). # In[1]: import matplotlib.pyplot as plt get_ipython().run_line_magic('matplotlib', 'inline') get_ipython().run_line_magic('config', "InlineBackend.figure_format = 'svg'") import numpy as np r = np.linspace(0,200,100) ax = plt.subplot(111, projection='polar') ax.plot(r, r, color='b', linewidth=1.5); # ## Базовый Python # Этот раздел содержит шпаргалку по базовым возможностям Python. Вы можете его пропустить (сразу перейти к [разделу numpy](#numpy)) и обращаться к нему по мере необходимости, или кратко просмотреть, чтобы узнать, чем Python отличается от других языков. # ### Арифметика # In[2]: n = 10 # целое число (int) x = 0.12 # число с плавающей точкой (float) n * x # Результат выполнения последней команды будет выведем автоматически. # In[3]: type(n) # int — целое # In[4]: z = 1 + 2j # комплексное число, j — это мнимая единица z ** 2 # возведение в степень — две звёздочки, а не крышечка; крышечка это побитный XOR # In[5]: print(5 / 2) # деление в числах с плавающей точкой print(5 // 2) # целочисленное деление print(5 % 2) # взятие остатка # In[6]: from math import sqrt # импорт одной функции из модуля (библиотеки) sqrt(4) # In[7]: import math # другой способ импорта math.sin(math.pi) # In[8]: import math as m # то же, что и предыдущий, но короче m.sin(m.pi) # Подробнее: [конспект](http://nbviewer.ipython.org/github/ischurov/pythonhse/blob/master/Lecture%201.ipynb), [видео](http://www.youtube.com/watch?v=5Y5tKPKhurA). # ### Структуры данных # #### Списки # In[9]: my_list = [4, 10, 1, 3] # список (что-то вроде динамического массива) print(my_list[2]) # нумерация начинается с нуля # In[10]: my_list[3] = 99 my_list # In[11]: my_list.append(100) my_list # In[12]: my_list + [2, 3, 4] # конкатенация # In[13]: my_list # не изменился # In[14]: my_list.extend([2, 3, 4]) my_list # In[15]: my_list[2:5] # срез (slice); первый элемент включается, последний не включается # In[16]: min(my_list) # In[17]: max(my_list) # In[18]: sum(my_list) # In[19]: sorted(my_list) # In[20]: my_list # список не изменился # In[21]: my_list.sort() my_list # а теперь изменился # Подробнее: [конспект](http://nbviewer.ipython.org/github/ischurov/pythonhse/blob/master/Lecture%202.ipynb), [видео](https://www.youtube.com/watch?v=kBu3g-ITjY4). # #### Кортежи # Кортеж — это неизменяемый список. # In[22]: my_tuple = (12, 8, 3) my_tuple[1] # In[23]: my_tuple[1] = 10 # #### Словари # In[24]: my_dict = {'Alice': 5, 'Bob': 3, 'Claudia': 4} my_dict['Alice'] # In[25]: my_dict['Bob'] = 4 my_dict # Подробнее: [конспект](http://nbviewer.ipython.org/github/ischurov/pythonhse/blob/master/Lecture%205.ipynb), [видео](http://www.youtube.com/watch?v=z8bu_b5BboI). # #### Множества # In[26]: A = {9, 2, 5, 3, 10} B = {2, 10, 12, 15} 9 in A # In[27]: A | B # объединение # In[28]: A & B # пересечение # ### Управляющие конструкции # #### Проверка условий # In[29]: x = 10 if x > 8: print("x is rather big") else: print("x is very small") print("Could you increase it?") print("x =", x) # Блок, относящийся к управляющей конструкции, выделяется отступом. Закончился отступ — закончился и блок. Никаких фигурных скобок или конструкций `begin-end` в Python не предусмотрено. # In[30]: x = 15 if x > 10 and x % 2 == 0: print("x is big and even") else: print("either x is not so big or it is not even") # Подробнее: [конспект](http://nbviewer.jupyter.org/github/ischurov/pythonhse/blob/master/Lecture%203.ipynb#%D0%9F%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%BA%D0%B0-%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D0%B9). # ### Циклы # #### Цикл `for` # In[31]: my_list = [8, 9, 12] for x in my_list: print(x) print("Let's go to the next x") # In[32]: for x in range(5): print(x) # In[33]: list(range(2, 8)) # In[34]: # посчитаем факториал s = 1 n = 15 for x in range(1, n + 1): s = s * x print(s) # In[35]: # хотя конечно проще так: from math import factorial factorial(15) # In[36]: for i, x in enumerate(my_list): print("my_list[{0}] = {1}".format(i, x)) # In[37]: other_list = [10, 12, 13] # zip — застёжка-молния, состёгивает два или несколько списков for x, y in zip(my_list, other_list): print("x = {}, y = {}".format(x, y)) print("x + y =", x + y) # Подробнее: [конспект](http://nbviewer.jupyter.org/github/ischurov/pythonhse/blob/master/Lecture%202.ipynb#%D0%A6%D0%B8%D0%BA%D0%BB-for), [про enumerate](http://nbviewer.jupyter.org/github/ischurov/pythonhse/blob/master/Lecture%203.ipynb#%D0%9D%D1%83%D0%BC%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D1%8F-%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%D0%BE%D0%B2-%D1%81%D0%BF%D0%B8%D1%81%D0%BA%D0%B0), [про zip](http://nbviewer.jupyter.org/github/ischurov/pythonhse/blob/master/Lecture%205.ipynb#%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5-%D1%81%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D0%B5%D0%B9-%D0%B8-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F-zip%28%29). # #### Цикл `while` # In[38]: # найдем последнее число Фибоначчи, меньшее 1000 a = 1 b = 1 while b < 1000: c = a + b a = b b = c # можно было бы так: a, b = b, a + b print(a) # In[39]: # найдем предпоследнее число Фибоначчи, меньшее 1000 a = 1 b = 1 while True: # выполнять всегда c = a + b if c > 1000: break a = b b = c print(a) # Подробнее: [while](http://nbviewer.jupyter.org/github/ischurov/pythonhse/blob/master/Lecture%203.ipynb#%D0%A6%D0%B8%D0%BA%D0%BB-while). # ## Математические библиотеки # ### numpy # `numpy` — это библиотека для эффективной работы с массивами. Массивы `numpy` называются `numpy.array` или `numpy.ndarray` (это почти одно и то же) и похожи на списки, но работают быстрее. По своей концепции они похожи на MATLAB. # In[40]: import numpy as np x = np.array([4, 3, 10, 3]) # In[41]: x[2] # In[42]: y = np.array([10, 12, 3, 15]) x + y # поэлементное сложение # In[43]: x * y # и умножение тоже # In[44]: x.dot(y) # скалярное произведение # In[45]: x @ y # так тоже можно # In[46]: A = np.array([[1, 2], [3, 4]]) # матрица u = np.array([[1, 0]]) A @ u.T # умножение матрицы на вектор # In[47]: math.sin(x) # In[48]: np.sin(x) # поэлементное применение # In[49]: x # In[50]: x[x < 10] # выбрать все элементы x, меньшие 10 # `numpy` позволяет в большинстве случаев обходиться без циклов (которые в Python довольно медленные), заменяя их на поэлементные операции над списками. # Подробнее: [конспект](http://nbviewer.jupyter.org/github/ischurov/pythonhse/blob/master/Lecture%2011.ipynb), [видео](http://www.youtube.com/watch?v=A84rlgoVnMY). # ### scipy # Всякая разная математика. # #### Линейная алгебра # Решим систему уравнений # # \begin{equation} # \begin{pmatrix} # 3 & 4\\ # 4 & -3 # \end{pmatrix} # \begin{pmatrix} # x\\ # y # \end{pmatrix} # = # \begin{pmatrix} # 10\\ # 5 # \end{pmatrix} # \end{equation} # In[51]: from scipy.linalg import solve solve(np.array([[3, 4], [4, -3]]), np.array([10, 5]).T) # решить систему линейных уравнений # Подробнее: [документация](http://docs.scipy.org/doc/scipy/reference/linalg.html) (англ.) # #### Интегрирование и решение дифференциальных уравнений # Посчитаем $\int_0^1 x^2 \; dx$. # In[52]: from scipy.integrate import quad def f(x): # так мы определили функцию f(x)=x**2 return x**2 quad(f, 0, 1) # Решим дифференциальное уравнение $\dot x = x$. # In[53]: from scipy.integrate import odeint T = np.linspace(0, 1, 10) # равномерное разбиение отрезка [0, 1] с помощью 10 точек def f(x, t): return x odeint(f, 1, T) # Подробнее: [документация](http://docs.scipy.org/doc/scipy/reference/integrate.html) (англ.) # Решим систему # \begin{equation} # \dot x = y,\quad \dot y = - x # \end{equation} # In[54]: def f(X, t): # x = X[0], y = X[1] return [X[1], -X[0]] T = np.linspace(0, 2 * m.pi, 10) odeint(f, [1, 0], T) # ### sympy # Символьная математика. # In[55]: import sympy as sp from sympy import init_printing init_printing(use_latex = 'mathjax') # In[56]: x, y, z = sp.symbols('x y z') sp.expand((x + y)**10) # In[57]: sp.exp(-x**2 / 2).diff(x) # In[58]: sp.sin(x).series() # In[59]: sp.exp(x**2 + x**3).series() # In[60]: sp.integrate(sp.sin(x) ** 10) # In[61]: sp.exp(x**10).diff(x).subs({x:1}) # In[62]: print(sp.exp(x**10).diff(x).subs({x:1}).evalf(n=1000)) # In[63]: M = sp.Matrix([[x, 1], [1, x]]) M # In[64]: sp.Matrix([[x, 1], [1, x]]).eigenvects() # Подробнее: [документация](http://docs.sympy.org/latest/tutorial/index.html) (англ.) # ### matplotlib # Картинки. Основная библиотека — `matplotlib.pyplot` — очень похожа на MATLAB и работает в тесной связке с `numpy` и другими библиотеками. # In[65]: get_ipython().run_line_magic('matplotlib', 'inline') # иначе картинки не будут рисоваться get_ipython().run_line_magic('config', "InlineBackend.figure_format = 'svg'") # вывод в SVG для пущей красивости import matplotlib.pyplot as plt plt.plot([0, 1, 2, 3], [0, 1, 4, 9]) # In[66]: x = np.linspace(-4, 4) plt.plot(x, x**2) # In[67]: plt.plot(x, np.sin(x**2)) # In[68]: x = np.linspace(-4, 4, 1000) # возьмём точек побольше plt.plot(x, np.sin(x**2)) # In[69]: plt.plot(np.sin(x)) plt.plot(np.cos(x)) # In[70]: plt.plot(x, 1/x) # In[71]: plt.ylim(-4, 4) plt.plot(x, 1/x, label='$y = 1/x$') plt.plot(x, np.zeros_like(x)) plt.legend() # In[72]: plt.figure(figsize=(6, 6)) # квадратненько x = np.linspace(-1.5, 1.5, 100) y = x**2 plt.plot(x, y, label='$y = x^2$') plt.plot(y, x, label='$x = y^2$') plt.xlabel("$x$", fontsize=20) plt.ylabel("$y$", fontsize=20) plt.legend() # #### Scatter plot # In[73]: from scipy.stats import norm x = norm.rvs(size = 500) y = x + norm.rvs(size = 500) plt.scatter(x, y) # #### Полярные координаты # In[74]: r = np.linspace(0, 3.0, 10000) theta = 2 * np.pi * np.exp(r) ax = plt.subplot(111, projection='polar') ax.plot(theta, r, color='r', linewidth=1) # #### Векторные поля и ОДУ # Векторное поле дифференциального уравнения: # # $$\dot x=-0.1x+y,\quad \dot y = -x - 0.1y$$ # In[75]: plt.figure(figsize=(6,6)) plt.xlabel("$x$", fontsize=20) plt.ylabel("$y$", fontsize=20) x, y = np.mgrid[-3:3:0.5, -3:3:0.5] plt.quiver(x, y, -0.1 * x + y, -x - 0.1 * y) # Фазовый портрет того же уравнения. # In[85]: plt.figure(figsize=(6,6)) plt.xlabel("$x$", fontsize=20) plt.ylabel("$y$", fontsize=20) y, x = np.mgrid[-3:3:21j, -3:3:21j] # 21j здесь означает, что нужна 21 точка # Обратите внимание: y и x идут в обратном порядке! plt.streamplot(x, y, -0.1 * x + y, -x - 0.1 * y) # Несколько решений того же уравнения, найденные с помощью численного интегрирования вручную. # In[76]: def f(X, t): return np.array([[-0.1, 1], [-1, -0.1]] @ X) T = np.linspace(0, 10*m.pi, 1000) inits = [[1, 0], [0, 1], [1, 1]] plt.figure(figsize=(6,6)) plt.xlim(-1, 1) plt.ylim(-1, 1) plt.xlabel("$x$", fontsize=20) plt.ylabel("$y$", fontsize=20) for init in inits: traj = odeint(f, init, T) plt.plot(traj[:, 0], traj[:, 1]) # #### Линии уровня (contour plot) # Линии уровня функции $z=xy$. # In[77]: x, y = np.mgrid[-3:3:0.01, -3:3:0.01] z = x * y plt.contour(x, y, z, 20, cmap='gnuplot') # Касп (он же «ласточкин хвост») $x^2 - y^3 = 0$. # In[78]: import matplotlib matplotlib.rc('font', family='Arial') # иначе русские буквы не сработают x, y = np.mgrid[-1:1:0.001, 0:1:0.001] z = x**2 - y**3 plt.contour(x, y, z, levels=[0]) plt.title("Ласточкин хвост") # Подробнее: [pyplot tutorial](http://matplotlib.org/users/pyplot_tutorial.html) (англ.) # ### Виджеты # Виджеты позволяют добавить интерактивности: создают элементы управления (например, слайдеры), с помощью которых вы можете настраивать параметры вызываемых функций и сразу получать результат. Виджеты работают только если вы загрузили блокнот и свой IPython Notebook или в tmpnb. Если вы просто читаете эту страничку в Интернете, скорее всего, вы ничего интересного не увидите. # In[1]: import matplotlib.pyplot as plt import numpy as np # In[2]: get_ipython().run_line_magic('matplotlib', 'inline') # In[3]: from ipywidgets import interact, interactive, fixed, FloatSlider import ipywidgets as widgets # In[4]: @interact(a=FloatSlider(min=0, max=10, value=1, step=1e-3), b=FloatSlider(min=0, max=10, value=1, step=1e-3)) def plot_sin(a, b): x = np.linspace(-4,4,300) plt.ylim(-2,2) plt.plot(np.sin(a*x)*b) # Подробнее: [виджеты](http://nbviewer.jupyter.org/github/ipython/ipywidgets/blob/master/examples/Index.ipynb) (англ.)