Python для инженеров и исследователей

Содержание и дополнительные материалы

  1. Цель и задачи курса. Установка библиотек Python. Дистрибутив Anaconda
    • Свободные программы для Windows (Ф.Занько)
      Краткая история концепции свободного программного обеспечения, размышления о его роли и перспективах применения в образовании и науке, а также список лучших свободных программ для Windows, которые уже сегодня могут восполнить основные нужды среднего пользователя персонального компьютера. Этот материал обсуждался на Второй конференции "Свободное программное обеспечение в высшей школе" (Переславль-Залесский, 26-28 января 2007 г.), проведенной российской компанией "Альт Линукс".
  2. Python в роли калькулятора
    • Забавы с IDLE: день первый (Danny Yoo)
      Очень простое введение в программирование на Python. IDLE - это стандартная интегрированная среда разработки Python, полностью написанная на Python/Tk.
    • Как использовать IDLE (для версии 0.5) (Daryl Harms)
      Устаревшее описание возможностей среды IDLE. Тем не менее, оно до сих пор полезно для обучения. Части документа, не представляющие интереса для тех, кто пользуется современными версиями Python, зачеркнуты.
    • Документация IDLE
      Документация IDLE в версии Python 2.6.5. Фактически - это справочник команд.
    • Python в научной работе (Hinsen K.)
      Сильно устаревшее, но возможно еще представляющее интерес обзорное введение в Python/Tk для ученых. Изначально курс предназначался для специалистов из Института структурной биологии (Гренобль, Франция).
    • Программирование на Python (части 1-3) (Walters G.)
      Простое введение в основы языка Python: переменные, циклы, модули, функции и т.п. Любопытно, что эти уроки были опубликованы в свободном (!) электронном компьютерном журнале "Full CIrcle", издающемся энтузиастами дистрибутива Linux под названием Ubuntu.
  3. Библиотека научной графики Matplotlib

  4. Численное дифференцирование и интегрирование: библиотека NumPy/SciPy

  5. Введение в Python/Tk
    • Спасательный круг для изучающих Tkinter (Conway M.)
      Классическое введение в программирование графических интерфейсов с помощью Tkinter, включенное в официальную документацию Python. Помимо прочего содержит краткое введение в язык Tcl/Tk, на котором базируется модуль Tkinter, а также Карманный справочник опций и методов основных графических элементов управления.

    • Дзэн Питона в примерах (Blanks H.)
      Дзэн Питона - это хорошо известный набор афоризмов, иллюстрирующих философию и принципы хорошего стиля Python. Сопроводить их примерами кода - удачная идея, помогающая начинающим программистам понять практический смысл "правил дзэн".

  6. Tkinter - программирование графических интерфейсов
    • Краткий обзор Tkinter (Owen R.)
      Кроме очень краткого обзора Tkinter документ включает в себя редко встречающуюся в литературе, но важную для практики программирования информацию. Глубина изложения варьируется от самого простого уровня до изощренных приемов. Примеры программного кода из этого обзора в виде отдельных файлов: summary1.py, summary2.py и summary3.py.

    • Фольклор Tkinter (Owen R.)
      Документ содержит небольшую подборку редкой или неожиданной информации о Tkinter. Рассматриваются вопросы, связанные с использованием переменных Tk, автоматическим обновлением цвета и шрифтов в элементах управления, а также техника сокрытия элементов управления. Примеры программного кода из этого документа в виде отдельных файлов: folklore1.py и folklore2.py.

    • Lambda в Python (Driscoll M.)
      Лаконичное введение в одну из самых сложных для начинающих функций Python. Приводится пример использования lambda в обратных вызовах (callbacks) Tkinter.

    • Учебное пособие по Tkinter для новичков (Nardo M.)
      Как быстрее всего научиться программировать на Tkinter? Написать свой собственный текстовый редактор! Именно этому посвящено данное пособие. Правда, следует заметить, что метод объектно-ориентированного программирования, который широко используется в этом руководстве, создает некоторые дополнительные трудности для понимания кода.

  7. Дополнительные графические элементы управления, инструменты и рецепты
    • Эффективный оптимизированный графический элемент управления типа "дерево", написанный на Python и Tkinter (Charles E. "Gene" Cash)
      Удачная реализация популярного графического элемента управления, разработанного Microsoft. Обладает хорошей переносимостью (Windows, Linux, WinCE). Для работы элемента достаточно, чтобы в системе были установлены Python и Tkinter. В настоящее время входит в состав IDLE - интегрированной среды разработки для Python, созданной на базе Tkinter.

    • HTML Scraper - простой синтаксический анализатор html-файлов (Michael Foord)
      Scraper - это класс для синтаксического анализа html-файлов. Он включает в себя методы обработки "порций данных" с html-страницы, а также тегов. Эти методы могут быть перезаписаны вашими собственными методами обработки HTML в подклассах. Этот класс выполняет большую часть того, что делает HTMLParser.HTMLParser, за исключением зависания на плохом HTML. В нем используются регулярные выражения и часть логики из sgmllib.py (из стандартного дистрибутива Python). Наиболее полезен, когда нужно модифицировать часть страницы с гарантией того, что остальной код HTML не будет изменен анализатором.

    • Комментарии Python в стиле HTML: html2py.py, py2html.py и html2code.py (Занько Ф.)
      Три простых инструмента для работы с файлами, в которых код Python "встроен" в разметку HTML: 1) Процедура html2py() - это простой конвертер, способный преобразовывать html-страницы, содержащие код Python, в сценарии Python с расширением .py и запускать их на выполнение. Все, что не находится между тегами <CODE> и </CODE>, превращается в комментарии Python. А между этими тегами как раз и находятся "кусочки" кода Python. В целом они представляют собой законченную программу на Python, ее можно редактировать с использованием подсветки синтаксиса и сохранять в обычном редакторе, например в IDLE. 2) Возможно и обратное преобразование: другая процедура py2html() убирает все добавленные комментарии, восстанавливая оформление исходного html-файла. 3) Наконец, процедура html2code() выступает в роли фильтра, удаляющего все, что не находится между тегами <CODE> и </CODE>, и преобразующего html-страницы в "чистые" (без тегов HTML и объяснительного текста) сценарии Python. Для работы инструментов нужен модуль code_tag.py

0. Цель и задачи курса

Программирование - уникальный предмет, где обучающийся сталкивается с инженерным искусством как таковым. В так называемых "инженерных" дисциплинах обучение носит по большей части теоретический характер, расчеты просты и до проектирования конструкций, которые будут реально воплощены в "железе", дело никогда не доходит. Другое дело - программирование. В нем каждый имеет возможность проектировать, создавать и пользоваться в реальном виртуальном мире своего компьютера инженерными конструкциями собственного приготовления. Доступность, дешевизна, гибкость, практическая значимость программирования ставят эту дисциплину вне конкуренции как полигон для подготовки инженера или исследователя в любой области техники - ведь принципы инженерного искусства везде одни и те же. В этом смысле рядом с программированием можно поставить разве что электронные конструкторы типа Arduino. Но последние и сложнее, и специфичнее, и дороже.

Цель курса - в общедоступной форме изложить философию и принципы инженерного искусства на примере программирования. Курс базируется на свободном программном обеспечении и сам защищен свободной лицензией Creative Commons.

Практическая задача курса - быстро научить будущего или уже состоявшегося инженера или ученого использовать библиотеки Python в своей обычной работе: для построения графиков, проведения численных расчетов и т.п. Python - один из самых простых для освоения современных языков программирования, очевидный кандидат на замену Pascal в системе образования. Мой педагогический опыт показывает, что студенты вполне способны овладеть этим курсом, имея лишь опыт программирования на Паскале в школе.

Если говорить о методике обучения, то в заданиях курса практически не требуется писать код "с нуля", "с чистого листа". Вместо этого в качестве исходной точки любой задачи берется уже готовый код, который нужно переделать, дополнить или расширить. Такой подход гораздо эффективнее и ближе к реальной жизни.

По словам академика РАН, ректора Сколтеха Александра Кулешова, инженерия 70-х и нынешняя инженерия не имеют вообще ничего общего. Даже в самых высокотехнологичных компаниях мира – Airbus и Boeing, где очень сильные сотрудники, рядовой инженер тратит 60% времени на поиск аналога того решения, которое ему необходимо. То есть сидит в интернете и ищет там какую-то готовую модель, которую потом ему надо будет подправить. Настоящий курс ориентирует студентов именно на такой стиль работы.

Установка библиотек Python. Дистрибутив Anaconda

Сила Python - в его "внешних" библиотеках, неизмеримо расширяющих возможности языка. На сегодняшний день число только самых интересных, обязательных для изучения библиотек Python - явно больше 10. Все они требуют отдельной установки, зависят от тех или иных версий других библиотек и, бывает, конфликтуют друг с другом. Чтобы избавить пользователя от этих технических проблем, стали создавать дистрибутивы Python, включающие сам язык и его библиотеки. Они напоминают дистрибутивы Linux, если кто с ними сталкивался.

Для этого курса рекомендуется загрузить и установить дистрибутив Anaconda (300-500 Мбайт), созданный на базе версии Python 2.7 для 32-разрядной или 64-разрядной архитектуры. Установка происходит не так быстро, как хотелось бы.

Литература

  1. Свободные программы для Windows (Ф.Занько)
    Краткая история концепции свободного программного обеспечения, размышления о его роли и перспективах применения в образовании и науке, а также список лучших свободных программ для Windows, которые уже сегодня могут восполнить основные нужды среднего пользователя персонального компьютера. Этот материал обсуждался на Второй конференции "Свободное программное обеспечение в высшей школе" (Переславль-Залесский, 26-28 января 2007 г.), проведенной российской компанией "Альт Линукс".

1. Python в роли калькулятора

Самый простой способ начать работу с Python из дистрибутива Anaconda (на примере Windows 7) - нажать кнопку Пуск, в появившемся поле "Найти программы и файлы" ввести слово "idle" и нажать клавишу Enter (рис.1).

Рис.1. Запуск IDLE

Перед вами должно появиться окно IDLE (рис.2). Что такое IDLE? Это так называемая интегрированная среда разработки (Integrated Development Environment), разработанная создателями Python для облегчения программирования. IDLE полностью написана на языке Python, ее код можно посмотреть и при желании внести в него изменения.

Рис.2. Окно командной строки IDLE

Это одно из двух основных окон IDLE, с которыми вам предстоит работать. Его называют окном интерпретатора или окном командной строки. У интерпретатора есть замечательное свойство: как только будет введена команда, Python тут же исполнит ее и выведет на экран полученный результат. Фактически перед вами очень мощный и удобный калькулятор!

Попросим Python что-нибудь напечатать, например традиционную фразу: "hello world".

Рис.3. Первый диалог с интерпретатором Python: hello, world

Значки '>>>' играют роль приглашения: Python сигнализирует, что готов считывать новую команду. Также, обратите внимание, после ввода команды Python тут же выводит что получилось в результате ее выполнения.

Попробуем еще несколько команд. Посмотрите на рис.4:

Рис.4. Первый диалог с интерпретатором Python: простейшие вычисления

на нем показан результат запуска новых команд. Не слишком беспокойтесь о том, как правильно программировать: сейчас мы экспериментируем с Python, вводя в него команды. Если что-то не работает, исправляем ошибку и пробуем снова.

Хорошо, теперь зададимся вопросом: если закрыть Python и снова запустить его, как компьютер вспомнит, что мы напечатали? Никак. Нельзя напрямую сохранить содержимое окна интерпретатора, потому что в него входят и сами команды, и ответы системы, например значки '>>>' . Вместо этого мы создадим файл, в котором будут только команды, и сохраним его как документ с расширением *.py. Этот файл всегда можно открыть и запустить в Python, экономя время на повторном наборе всех его команд.

Попробуем. Начнем с чистого листа, открыв новое окно (рис.5).

Рис.5. Как открыть окно программ

Как видно, в новом окне ничего нет (рис.6) - оно целиком и полностью отдано под команды. Теперь Python не будет прерывать вашу работу с программой, вернее, пока вы не скажете ему это сделать. Чтобы не путать с окном интерпретатора, назовем его "окном программ".

Рис.6. Новое окно программ

Все, что мы хотели сделать,- это сохранить несколько строк, уже опробованных в окне интерпретатора. Реализуйте этот план, скопировав/вставив эти команды в окно программ (рис.7). Не забудьте при этом удалить приглашения ">>>", потому что они в программу не входят. Интерпретатор использует их, чтобы напомнить, что вы работаете в интерпретаторе. Но сейчас при редактировании отдельного файла эти артефакты интерпретатора совершенно ни к чему.

Рис.7. Окно IDLE с текстом программы

Запускаем файл на выполнение: находим в главном меню пункт Run, подпункт Run Module или просто нажимаем быструю клавишу F5 (рис.8).

Рис.8. IDLE предлагает сначала сохранить сделанную работу

Что-то пошло не так? Нет, просто нас застало врасплох правило IDLE сохранять любое окно с программой, прежде чем запустить ее. Это вопрос организации интерфейса пользователя. IDLE хочет убедиться, что вы не забыли сохранить свою работу, перед тем как начнете ее проверять в деле. Что ж, жмем OK и вводим имя нового файла. Еще раз F5 - и новая напасть: IDLE не нравятся русские буквы в тексте программы и вам предлагается явно задать кодировку (рис.9).

Рис.9. IDLE предлагает явно задать кодировку

Вопросы отображения символов, выходящих за пределы стандартного набора латинских символов ASCII, - это большая тема в Python. Сейчас нет смысла в нее влезать. Можно согласиться с предложением IDLE и позволить ей самой отредактировать ваш файл, согласившись добавить строку "# -*- coding: cp1251 -*-". Более универсальный вариант, которым я рекомендую пользоваться в будущем, - это выбор кодировки utf8 (юникод) вместо cp1251. Но пока сойдет и так: жмем Edit my file и снова F5.

Рис.10. Синтаксическая ошибка

А вот теперь дело серьезнее - синтаксическая ошибка! Python сигнализирует о нарушении грамматических правил языка (рис.10). Что там подсвечено красным? Ну, конечно, - пропущена закрывающая кавычка! Исправляем и еще раз F5.

Рис.11. Окно командной строки (интерпретатора) с результатами выполнения программы

Наконец-то! Появляется наш старый знакомый - окно интерпретатора с результатами выполнения программы (рис.11). Все в порядке.

В заключение убедимся, что созданный вами файл можно будет загрузить снова. Закрываем все окна IDLE и начинаем с чистого листа. Найдите команду Recent Files (последние файлы) в меню File: появится список, в котором на первом месте - ваша новая программа. Выберите ее, и она появится в окне программ.

Итак, вы овладели начальными навыками работы с Python. Теперь можно применить их в деле. Попытаемся использовать окно командной строки IDLE в роли калькулятора.

Начнем с простого:

Рис.12. Деление двух целых чисел

Что за дела, почему неправильный результат? Дело в том, что для Python число, записанное без десятичной точки, - это особый тип данных, так называемое целое число, которое не может иметь дробной части. Мы еще со школы привыкли не различать в записи целые и вещественные числа, но для компьютера это совершенно разные вещи. К этому нужно отнестись внимательно, чтобы избежать возникновения неожиданных ошибок при программировании вычислений.

Если тип чисел, над которыми производятся математические операции, не один и тот же, целое число будет автоматически преобразовано в вещественное. Для этого достаточно поставить у одного из чисел десятичную точку или экспоненту (рис.13).

Рис.13. Автоматическое преобразование типа числа

А какое максимальное целое число способен воспринять интерпретатор Python? Узнать это можно с помощью специальной функции maxint из библиотеки Python sys. Прежде чем вызывать функцию, ее нужно из библиотеки импортировать (рис.14). Библиотеку sys отдельно устанавливать не нужно - это фактически часть стандартного языка Python. Ее можно назвать "внутренней" библиотекой в отличие от других - "внешних" библиотек, которые, прежде чем использовать, приходится скачивать в Интернете и устанавливать, как обычную программу Windows. На следующих занятиях мы будем иметь дело с целым рядом таких библиотек, но работу по их установке, как правило, берет на себя дистрибутив Anaconda.

Рис.14. Максимальное целое число, поддерживаемое интерпретатором Python

В данном случае это число равно 231-1. На другом компьютере оно может быть другим. Заметьте, что две звездочки подряд (**) означают в Python возведение в степень.

А как быть, если нужно работать с числом, большим чем maxint? Попробуем получить число, состоящее из единицы и ста нулей, - знаменитый гугол. В честь этого числа названа компания Google. Введем в командную строку Python команду:
>>> 10**100 [Enter]

Рис.15. Гугол

Что ж, все работает, а справа от числа появилась заглавная L. Оказывается, когда заканчиваются целые числа, Python автоматически переходит на другой тип данных - так называемые длинные (long) целые. Символ L справа именно об этом и сигнализирует. Так что на наш век чисел хватит.

Два слова о стандартных математических функциях, таких как sqrt, log, log10, exp, sin, cos, tan, arcsin, arccos, arctan, sin, cosh, а также константах pi и e: они не относятся к базовой части языка, а сосредоточены в отдельном модуле math. Поэтому, прежде чем использовать, их нужно импортировать, как мы это уже делали с функцией maxint. Импортировать функции можно по отдельности:

Рис.16. Импортирование функций из модуля math по отдельности

или группами:

Рис.17. Импортирование функций из модуля math группами

или же возможно импортировать сразу все содержимое модуля:

from math import *

Также имеется возможность импортировать сам модуль:

import math

и использовать "расширенные" названия функций: math.sqrt, math.exp и т.д.

Задание

Решить один из приведенных ниже примеров тремя способами: сначала вручную (все вычисления столбиком должны быть записаны на листочке, арифметические ошибки допустимы, если они есть - перерешивать не нужно), затем с помощью стандартного калькулятора Windows или на телефоне, потом с помощью Python. Какой способ проще лично для Вас? Почему?

Вопросы

  1. Сталкивались ли вы с окном интерпретатора в Паскале?

  2. Попробуйте, работают ли клавиатурные комбинации для работы с буфером обмена (CTRL-C, CTRL-X, CTRL-V) в IDLE с включенной русской раскладкой.

Литература

  1. Забавы с IDLE: день первый (Danny Yoo)
    Очень простое введение в программирование на Python. IDLE - это стандартная интегрированная среда разработки Python, полностью написанная на Python/Tk.
  2. Как использовать IDLE (для версии 0.5) (Daryl Harms)
    Устаревшее описание возможностей среды IDLE. Тем не менее, оно до сих пор полезно для обучения. Части документа, не представляющие интереса для тех, кто пользуется современными версиями Python, зачеркнуты.
  3. Документация IDLE
    Документация IDLE в версии Python 2.6.5. Фактически - это справочник команд.
  4. Python в научной работе (Hinsen K.)
    Сильно устаревшее, но возможно еще представляющее интерес обзорное введение в Python/Tk для ученых. Изначально курс предназначался для специалистов из Института структурной биологии (Гренобль, Франция).
  5. Программирование на Python (части 1-3) (Walters G.)
    Простое введение в основы языка Python: переменные, циклы, модули, функции и т.п. Любопытно, что эти уроки были опубликованы в свободном (!) электронном компьютерном журнале "Full CIrcle", издающемся энтузиастами дистрибутива Linux под названием Ubuntu.

2. Библиотека научной графики Matplotlib

Сила Python - в его внешних библиотеках, невероятно расширяющих возможности языка. Один из самых интересных и полезных проектов такого рода - библиотека научной графики Matplotlib, разработанная американским нейробиологом Джоном Хантером (к сожалению, он умер в 2012 г. от рака). Графики, рисуемые Matplotlib,- очень хорошего, полиграфического качества, их вполне можно вставлять в научную статью или монографию.

Быстрее всего испытать в деле Matplotlib можно с помощью командной строки IDLE. Последовательно введем в нее три команды (рис.18), не забывая всякий раз нажимать [Enter] и дожидаться появления значков >>> . Первая команда импортирует часть библиотеки Matplotlib под названием pyplot и присваивает ей более короткое имя plt. Вторая команда формирует график, состоящий из точек со следующими координатами y: [1,3,2,5]. По умолчанию Matplotlib для координат x возьмет значения: [0,1,2,3]. Третья команда выводит полученный график на экран.

Рис.18. Применение Matplotlib в командной строке

Должно появиться новое окно с графиком (рис.19).

Рис.19. Простейший график Matplotlib, полученный из командной строки

Обратите внимание на кнопки, расположенные в верхней части окна: они бывают очень полезны. Разработчики Matplotlib визуально разделили их на три группы по функциональности.

Первая группа - - навигационные кнопки. Кнопки со стрелками аналогичны кнопкам "Вперед" и "Назад" интернет-браузеров. Кнопка с "домиком" возвращает графику первоначальный вид, отменяя все сделанные модификации.

Вторая группа - - кнопки, управляющие параметрами отображения графиков. Кнопка с "крестом" позволяет перемещать график внутри координатных осей без изменения масштаба. "Лупа" дает возможность разглядеть детали графиков.

В третью группу входит одна единственная кнопка - , с помощью которой можно сохранить получившийся график в виде графического файла с расширением *jpg, *.tif, *.png, *.pdf и т.д. Такой рисунок можно потом вставить в документ Word или разместить на html-странице в Интернете.

Поиграйте с этими кнопками.

Итак, команды Matplotlib, как и обычные команды Python, можно вводить прямо в командной строке интерпретатора и исполнять одну за другой, но в дальнейшем мы будем программировать графики в отдельных файлах - так удобнее и в конечном счете быстрее.

Цель работы

Конечная цель работы - построить график заданной функции, определив цвет графика, стиль линии и добавив легенду (пояснение) с формулой этой функции в нотации TeX. Для этого нужно изменить предлагаемый ниже пример-шаблон, предварительно скопировав его в буфер обмена и вставив в окно программ IDLE (т.е. его нужно запускать как отдельную программу из IDLE).

Не нужно стараться понять весь код примера. Достаточно, используя пример в качестве образца, понять, как его изменить, чтобы решить поставленную задачу.

Шаблон

Следующий пример строит график функции f(x)=sin(x)/x:

# -*- coding: UTF-8 -*-

# Импортируем стандартную, "внутреннюю" библиотеку math
import math

# Импортируем один из пакетов "внешней" библиотеки Matplotlib
import matplotlib.pyplot as plt

# Импортируем еще один пакет со вспомогательными функциями
from matplotlib import mlab

# Будем рисовать график этой функции
def func(x):
    """
    sinc(x)
    """
    if x==0:
        return 1.0
    return math.sin(x)/x

# Интервал изменения переменной по оси X
xmin=-20.0
xmax=20.0

# Шаг между точками
dx=0.01

# Создадим список координат по оси X на отрезке [xmin; xmax],
# включая концы
xlist=mlab.frange(xmin, xmax, dx)

# Вычислим значение функции в заданных точках
ylist=[func(x) for x in xlist]

# Рисуем график заданного цвета (color) и стиля (linestyle),
# с определенной формой маркера (marker), помечающего отдельную точку
plt.plot(xlist, ylist, color='b', linestyle='-', marker='', label="$\\frac{sin(x)}{x}$")

# Выводим легенду, описанную в предыдущей команде в значении параметра label
plt.legend(title=u"Функция")

# Покажем окно с нарисованным графиком
plt.show()

Рис.20. График функции sin(x)/x

Задание

Построить график одной из нижеперечисленных функций с заданными цветом, стилем линии и формой маркера; указать в легенде формулу функции в формате TeX; полученный график вставить в файл Word.
  1. y=math.log(x) - синий, сплошная линия, кружок

  2. y=math.sqrt(x) - черный, штриховая линия, треугольник вершиной вверх

  3. y=math.cosh(x) - гиперболический косинус - желтый, пунктирная линия, треугольник вершиной вниз

  4. y=math.sinh(x) - гиперболический синус - зеленый, штрихпунктирная линия, квадратик

  5. y=(4.*x**3-6.*x**2+1.)*math.sqrt(x+1)/(3.-x) - красный, пунктирная линия, шестиугольник

  6. y=2.*math.pow(x,1.5) - полукубическая парабола - пурпурный, сплошная линия, косой крест

  7. y=2.*x**3.+x*x-5*x+7. - кубическая парабола - голубой, сплошная линия, прямой крест

Справочный материал

Цвет

Самый простой способ задания цвета в Matplotlib - с помощью одиночного символа. Правда вариантов цветов в таком случае получается немного:

Тем не менее, на практике зачастую этого набора вполне хватает.

Другая возможность задания цвета в Matplotlib - с помощью строки, описывающей цвет полным английским словом. Таких именованных цветов намного больше, чем односимвольных. В документации есть хороший пример, генерирующий таблицу со всеми существующими именованными цветами. Она приведена ниже.

Стиль линии

Стиль линии также можно определять одиночным символом:

Символ
Линия
-
--
-.
:

Стиль маркера


Формулы в формате TeX

TeX (или LaTeX) - это система, позволяющая программировать верстку книг и научных статей, созданная Дональдом Кнутом, - одним из крупнейших в мире ученых в области информатики, написавшим культовую книгу "Искусство программирования". TeX появился в далеком 1978 г. (!) и до сих пор не потерял своих позиций в мире математиков и физиков. Свободные дистрибутивы этой издательской системы существуют и под Windows, и под Linux. Она не проста для усвоения, но позволяет создавать очень красивые (с точки зрения полиграфии) тексты. Matplotlib поддерживает систему обозначения математических формул, принятую в LaTeX. [Благодаря своему удобству эта система записи формул стала практически стандартом: она используется в Википедии, в редакторе формул LibreOffice и еще много где.] То есть дистрибутив LaTeX устанавливать не нужно, все заработает сразу.

Чтобы указать Matplotlib, что текстовая строка содержит формулу, достаточно эту формулу заключить в знаки $. Допустим, мы хотим, чтобы в легенде наш график обозначался формулой f(x)=sin(x)/x. Для этого достаточно параметру label функции plot, определяющей наш график, присвоить значение "$f(x)=\\frac{sin(x)}{x}$". Двойная обратная косая черта "\\" в TeX означает начало команды. Если нужно, чтобы в формуле появился кириллический символ, перед ней нужно поставить букву u, например так: u"$f(x)=\\frac{sin(x_{рю})}{x_{рю}}$".

Степени и индексы

Степени и индексы набираются с помощью знаков ^ и _ соответственно. Если показатель степени или индекс являются выражением, состоящим более чем из одного символа, то их надо заключать в фигурные скобки { и }. Например, следующие выражения преобразуются в формулы:

a^2+b^2=c^2         

a_2+b_2=c_2         

a^{b^{c}}             

Если у одной буквы есть как верхние, так и нижние индексы, то их можно указать в произвольном порядке:

a_{10}^{20}         

a^2_3                 

Если требуется, чтобы индексы располагались не один под другим, а на разных расстояниях от выражения, к которому они относятся, то нужно оформить часть индексов как индексы к "пустой" формуле (паре из открывающей и закрывающей фигурных скобок):

R_j{}^i{}_{kl}         

Дроби

Дроби, обозначаемые косой чертой, набираются непосредственно:

x+1/x    дает   

Дроби, в которых числитель расположен над знаменателем, набираются с помощью команды \\frac{числитель}{знаменатель}:

\\frac{(a+b)^2}{4}-\\frac{(a-b)^2}{4}=ab         

Скобки

Круглые и квадратные скобки набираются непосредственно. Для набора фигурных скобок используются команды \\{ и \\}. Например:

f\\{x,y\\}=(x^2+y^2)^2         

Другие типы скобок набираются с помощью команд \\lceil, \\rceil, \\lfloor, \\rfloor, \\langle, \\rangle. Например:

\\lceil X \\rceil, \\lfloor Y \\rfloor, \\langle Z \\rangle     

Для автоматического выбора размера скобок используются команды \\left и \\right, помещаемые перед открывающей и перед закрывающей скобками соответственно. Сравните:

(x+\\frac{1}{x})^2         

и

\\left( x + \\frac{1}{x} \\right)^2     

Корни

Корни набираются с помощью команды \\sqrt[n]{выражение}, обязательным аргументом которой является подкоренное выражение. Кроме обязательного аргумента можно указать необязательный аргумент, заключаемый в квадратные скобки, который является показателем корня.

\\sqrt{x+1}       

\\sqrt[3]{x+1}   

Интегралы и дифференциалы

В этом разделе собраны символы, наиболее часто используемые в дифференциальном и интегральном исчислении.

\\int           интеграл
\\iint          двойной интеграл
\\iiint         тройной интеграл
\\oint         круговой интеграл
\\partial     частная производная
\\infty        бесконечность
\\lim          предел
\\to           стрелка (в пределах)

Примеры использования:

\\int_{0}^{3}f(x)dx         

\\iint_{x^2+y^2=1}f(x,y)dxdy          (в Matplotlib отображается некорректно, как нижний индекс при знаке интеграла)

\\iiint_{x^2+y^2+z^2=1}f(x,y,z)dxdydz    (в Matplotlib отображается некорректно, как нижний индекс при знаке интеграла)

Неравенства

Строгие неравенства набираются непосредственно: a < b, a > b
Для нестрогих неравенств используются команды \\leq и \\geq:

,

Греческие буквы

Имя команды, задающей греческую букву совпадает с английским названием этой буквы. Исключение составляет буква "o" (омикрон), она совпадает с латинской буквой "o", поэтому специальной команды для нее не предусмотрено. Кроме того, некоторые греческие буквы имеют по два варианта написания, что также отражено в таблице. Только не забудьте вместо одиночной обратной косой черты ставить двойную!

Большинство прописных греческих букв совпадает по начертанию с латинскими буквами, поэтому специальных команд для них не предусмотрено - надо просто использовать соответствующую латинскую букву. Приведем перечень прописных греческих букв, не совпадающих с латинскими:

\\Gamma, \\Delta, \\Theta, \\Lambda, \\Xi, \\Pi, \\Sigma, \\Upsilon, \\Phi, \\Psi, \\Omega

Крышки, подчеркивания и т.д.

Команды для создания крышек, подчеркиваний и других подобных знаков имеют вид \\<имя>{выражение}, где <имя> - имя команды. Вот они:

\\hat{A} \\check{A} \\breve{A} \\acute{A} \\grave{A}
\\tilde{A} \\bar{A} \\vec{A} \\dot{A} \\ddot{A}


Можно использовать также следующие команды:

\\widetilde{ABC} \\widehat{ABC} \\overline{ABC}
\\overbrace{ABC} \\underbrace{ABC} \\underline{ABC}


Вопросы

  1. В чем разница между библиотеками math и Matplotlib с точки зрения программиста?

  2. Для чего в теле функции func(x) нашего примера стоит оператор условия? Что будет, если его убрать?

Литература

  1. Использование библиотеки Matplotlib (Ильин Е.)
    Серия шпаргалок, в каждой из которых находится короткий пример, акцентирующий внимание на какой-то одной возможности библиотеки.
  2. Matplotlib (pylab) простые вещи 2 (Колдунов Н.)
    Вольные переводы избранных отрывков документации к Matplotlib.
  3. Sandro Tosi. Matplotlib for Python Developers. Birmingham-Mumbai: PACKT Publishing, 2009.- 293 p.
    Книга идеально подходит для начинающих изучать Matplotlib: доступный английский язык, ясный код примеров на Python, много простых примеров и справочной информации.
  4. Alexandre Devert. matplotlib Plotting Cookbook. Birmingham-Mumbai: PACKT Publishing, 2014.- 205 p.
    Свыше 60 простых рецептов использования Matplotlib в практике ученого-исследователя (например, как визуализировать обтекание круглого цилиндра).
  5. Использование LaTeX для набора формул на форуме / Интернет-сайт "Физика в анимациях"

  6. Котельников И.А., Чеботаев П.З. LATEX по-русски. Новосибирск: Сибирский хронограф, 2004.- 496 с.
    Книга хорошо подходит для изучения LATEX, если вам понадобится или захочется с помощью этой системы подготовить для печати научную статью или книгу.

3. Численное дифференцирование и интегрирование: библиотека NumPy/SciPy

Дифференцирование и интегрирование - далеко не самые простые для понимания понятия высшей математики. Причем, эти операции вводятся на базе теории пределов с использованием бесконечно большой и бесконечно малой величин, что еще больше "добавляет туману". Для нас производные и интегралы неразрывно связаны с аналитическими формулами, но большую часть функций из реального мира не удается выразить с помощью формул. Студенты вузов сначала изучают дифференцирование и интегрирование аналитических функций, но это просто так сложилось исторически.

Гораздо более универсальными (и простыми для понимания) являются дискретные производные и интегралы. Рассмотрим элементарный пример. Возьмем некоторую функцию, пусть для простоты это будет квадратная парабола y=f(x)=x2, и разделим ее на малые одинаковые участки по оси x. Теперь заменим непрерывную линию y=f(x) значениями этой функции на границах между участками, то есть вместо линии будем работать с набором точек. Такую замену называют дискретизацией. Непрерывность функции - это на самом деле лишь математическая абстракция. В реальной жизни любой процесс - дискретный, если не сам по себе, то хотя бы с точки зрения измерительных приборов.

Итак, задаваемая формулой функция - это непрерывное множество точек, образующих сплошную линию, а дискретная функция - это последовательность участочков неопределенно-малой длины, задаваемых координатами - значениями функции - концов участочков. Не всякую функцию можно описать математической формулой, но любую функцию можно заменить ее дискретным аналогом.

Что находится между точками-узлами дискретной функции? Точно мы не знаем, информации об этом у нас нет. Можно строить разные предположения, основываясь на значениях дискретной функции в узлах, например можно соединить узловые точки прямой линией. Такие предположения называют интерполяцией.

Что же такое производная дискретной функции? Положим, что длина всех участков по оси x одинакова и равна единице (такую систему единиц измерения подобрать можно всегда). Тогда для первого участка от точки 0 до точки 1 производная будет равна y'=Δy/Δx=(y(1)-y(0))/1=(1-0)/1=1. Это значение производной относится ко всему участку между точками x=0 и x=1. Аналогично для второго участка от 1 до 2: y'=Δy/Δx=(y(2)-y(1))/1=(4-1)/1=3. И для третьего от 2 до 3: y'=Δy/Δx=(y(3)-y(2))/1=(9-4)/1=5. Если нарисовать график дискретной производной, он будет выглядеть примерно как на рис.21.

Рис.21. Дискретная производная

Теперь покажем, как связаны друг с другом дискретные функции и их непрерывные аналоги. Вместо постоянного значения производной на каждом отдельном участке поставим одну точку с тем же значением посередине соответствующего участка (рис.22). Наложим на рисунок графики непрерывной функции y=x2 и ее непрерывной производной y'=2x: они пройдут в точности через точки их дискретных аналогов.

Рис.22. Связь дискретной и аналитической производных

Итак, все довольно просто и ясно. Дискретная производная несет в себе по сути ту же информацию, что и сама дискретная функция. Зная значение функции в начальной точке и имея график дискретной производной, можно легко восстановить первоначальную функцию. Такая операция называется интегрированием.

Почему же этим довольно примитивным операциям уделяется столь много внимания, что им посвящены отдельные разделы высшей математики - дифференциальное и интегральное исчисления? Все дело в том, что законы природы нашего мира представляют собой математические соотношения, состоящие из производных и интегралов. Изменение одних величин (скажем, потенциальной энергии свободно падающего предмета над поверхностью земли), рассчитанных по определенным формулам (Ep=mgh), равно изменению других величин (допустим, кинетической энергии того же свободно падающего предмета), тоже рассчитанных по определенным формулам (Ek=mv2/2). Это закон сохранения энергии, который лежит в основании большинства дифференциальных уравнений физики. А производные как раз и суть изменения тех или иных параметров.

Цель работы

В этой работе вам нужно будет найти численную производную и численный интеграл от заданной функции. В принципе, обе эти операции нетрудно запрограммировать самому. Нахождение определенного интеграла по методу трапеций или по методу Симпсона - стандартная задачка по программированию. Написать процедуру для нахождения численной производной - еще проще. Тем не менее, для численного дифференцирования и интегрирования мы воспользуемся уже готовыми функциями из библиотеки NumPy/SciPy. Эта Python-библиотека поддерживает работу с многомерными массивами, в ней реализованы многие алгоритмы из линейной алгебры, преобразование Фурье, генератор случайных чисел и т.п. Наконец, она довольно быстрая - не уступает по скорости, скажем, аналогичным функциям коммерческого пакета MATLAB.

С педагогической точки зрения использование в учебном процессе уже готовых решений может показаться неправильным. Действительно, самостоятельное решение задач по программированию "с нуля" выглядит очень привлекательной идеей. Так были созданы Unix, Linux и многие другие великие программы. И все-таки, инженерная работа в современном мире подразумевае нечто другое: "большую часть своего времени специалист посвящает, условно говоря, рысканью по каталогу накопленных знаний. Даже в самых высокотехнологичных компаниях мира - Airbus и Boeing, где очень сильные сотрудники, рядовой инженер тратит 60% времени на поиск аналога того решения, которое ему необходимо. То есть сидит в интернете и ищет там какую-то готовую модель, которую потом ему надо будет подправить" [Юлаев А. "Мы снова оказались в 1929 году..." / znak.com.- 28 июня 2016 г.].

Еще одна пространная цитата:

"Нежелание выполнять ненужную работу считается великой добродетелью у программистов. Если бы китайский мудрец Лао-Цзы в наши дни все еще продолжал проповедовать учение Тао, то, возможно, его высказывание ошибочно переводили бы так: когда великий программист воздерживается от кодирования, то его сила чувствуется за тысячу миль. Действительно, современные переводчики предположили, что китайское понятие ву-вей, которое обычно передавалось словами "бездействие" или "воздержание от действия", вероятно, должно читаться как "наименьшее действие" или "наиболее эффективное действие", или как "действие в соответствии с естественным правом", что даже лучше описывает хорошую инженерную практику.

Следует помнить правило экономии. Повторные "поиски огня" и "изобретение колеса" для каждого нового проекта крайне расточительны. Время мышления дорого и весьма ценно по сравнению со всеми остальными производственными затратами при разработке программного обеспечения. Соответственно, его следует тратить на разрешение новых проблем, а не на переформулировку старых, для которых уже существуют известные решения. Такая позиция приносит наилучшую отдачу, как в понятиях интеллектуального капитала, так и в понятиях экономической эффективности инвестиций.

Изобретать заново колесо плохо не только потому, что при этом впустую тратится время, но и потому, что при этом часто создаются квадратные колеса. Существует почти непреодолимый сооблазн сэкономить на времени переизобретения, используя сырую и слабо продуманную версию, а это в долгосрочной перспективе часто оказывается ложной экономией (Генри Спенсер).

Наиболее эффективный способ избежать изобретения колеса заключается в заимствовании имеющейся конструкции и реализации, иными словами, в повторном использовании кода" [Реймонд Э.С. Искусство программирования для Unix.- М.: Издательский дом "Вильямс", 2005.- 544 с.].

Шаблоны

Вот как можно численно продифференцировать заданную функцию y=x2 и построить графики самой функции и ее производной, найденной численно и аналитически:

# -*- coding: UTF-8 -*-

# Импортируем стандартную, "внутреннюю" библиотеку math
import math

# Импортируем из SciPy функцию для численного определения
# производной derivative
from scipy.misc import derivative

# Импортируем один из пакетов Matplotlib
import pylab

# Импортируем пакет со вспомогательными функциями
from matplotlib import mlab


# Заданная функция (y=x*x)
def func(x):
    return x**2.

# Производная заданной функции, найденная аналитически, точно
def func_diff(x):
    return 2.*x

# Диапазон изменения переменной по оси X
xmin=-20.0
xmax=20.0

# Шаг между точками
dx=1.

# Создадим список координат по оси X на отрезке [-xmin; xmax],
# включая концы
xlist=mlab.frange(xmin, xmax, dx)

# Вычислим значения функции во всех заданных точках
ylist=[func(x) for x in xlist]

# Вычисляем производную численно во всех заданных точках
ylist2=[derivative(func, x, dx=1e-6) for x in xlist]

# Вычисляем точное значение производной во всех заданных точках
ylist3=[func_diff(x) for x in xlist]

# Рисуем график самой функции и ее производной, полученной численно
pylab.plot(xlist, ylist, 'b', label="y=$x^2$")
pylab.plot(xlist, ylist2, 'r.', label="""y'=$\\Delta y/\\Delta x$""")

# Рисуем график производной, найденной аналитически
pylab.plot(xlist, ylist3, 'r', label="""y'=2x""")

# Обозначаем координатные оси
pylab.xlabel('X',fontsize=16)
pylab.ylabel('Y',fontsize=16)

# Регулируем размер числовых отметок на координатных осях
pylab.xticks(fontsize=12)
pylab.yticks(fontsize=12)

# Рисуем координатную сетку
pylab.grid()

# Выводим легенду
pylab.legend(fontsize=12)

# Показываем окно с нарисованными графиками
pylab.show()

Рис.23. График функции y=x2 и ее производной, найденной численно и аналитически

Аналогичный пример численного интегрирования заданной функции и сравнение полученного результата с известным аналитическим решением:

# -*- coding: UTF-8 -*-

# Импортируем стандартную, "внутреннюю" библиотеку math
import math

# Импортируем из SciPy функцию для численного интегрирования
import scipy.integrate as integrate

# Импортируем один из пакетов Matplotlib
import pylab

# Импортируем пакет со вспомогательными функциями
from matplotlib import mlab


# Заданная функция (y=2x)
def func(x):
    return 2.*x

# Значение интеграла, найденного аналитически, точно
def func_integr(x):
    return x**2.

# Диапазон изменения переменной по оси X
xmin=-20.0
xmax=20.0

# Шаг между точками
dx=1.

# Создадим список координат по оси X на отрезке [-xmin; xmax],
# включая концы
xlist=mlab.frange(xmin, xmax, dx)

# Вычислим значения функции во всех заданных точках
ylist=[func(x) for x in xlist]

# Вычисляем интеграл от заданной функции численно во всех заданных точках
ylist2=[integrate.quad(func, 0.0, x)[0] for x in xlist]

# Вычисляем интеграл от заданной функции аналитически во всех заданных точках
ylist3=[func_integr(x) for x in xlist]

# Раскомментируйте следующую строку. Что выводится функцией integrate.quad
# в командную строку?
#print integrate.quad(func, 0.0, 3.)

# Рисуем график самой функции и интеграла от нее, полученного численно
pylab.plot(xlist, ylist, 'b', label="y'=2x")
pylab.plot(xlist, ylist2, 'r.', label="y=$\\int (2x)dx$")

# Рисуем график интеграла, найденного аналитически
pylab.plot(xlist, ylist3, 'r', label="y=$x^2$")

# Обозначаем координатные оси
pylab.xlabel('X',fontsize=16)
pylab.ylabel('Y',fontsize=16)

# Регулируем размер числовых отметок на координатных осях
pylab.xticks(fontsize=12)
pylab.yticks(fontsize=12)

# Рисуем координатную сетку
pylab.grid()

# Выводим легенду
pylab.legend(fontsize=12)

# Показываем окно с нарисованными графиками
pylab.show()

Рис.24. График функции y=2x и интеграла от нее, найденного численно и аналитически

Воспользовавшись "лупой" с панели инструментов окна Matplotlib, нетрудно убедиться, что определенные с помощью численных процедур значения производной и интеграла очень точно ложатся на графики, соответствующие аналитическим решениям.

Задание

Пользуясь шаблонами, построить графики численной производной и численного интеграла от заданной функции (свободный член во всех формулах опущен):


  1. Для этой и последующих функций шаг dx надо взять поменьше - скажем, 0.1 вместо 1. Иначе будет "потеряна" форма функции.
Ясно, что производная от правой части каждого уравнения равна подынтегральному выражению.

Сравнить полученные численные решения с точными. Указать в легенде свою исходную функцию и результат в формате TeX.

В заключение давайте немного "пошумим" - наложим на функцию func(x) случайный "белый" шум и снова ее численно продифференцируем и проинтегрируем. Для этого в начало каждого примера надо добавить строку:

import numpy as np

и модифицировать определение функции func(x):

return x**2.+0.0001*np.random.uniform(0.,1.)

Функция np.random.uniform(0.,1.) генерирует псевдослучайные числа в диапазоне от 0 до 1, а множитель 0.0001 определяет среднюю амплитуду случайных отклонений от идеального аналитического графика. Поэкспериментируйте с величиной этого множителя, увеличивая и уменьшая его порядок (0.001, 0.01, 0.1, 0.00001 и т.п.) и в случае дифференцирования, и в случае интегрирования. Обратите внимание, как будет меняться график численной производной и численного интеграла в зависимости от величины этого множителя.

Вопросы

  1. Почему при интегрировании в некоторых случаях численное и аналитическое решение могут быть смещены относительно друг друга по оси Y?

  2. Какая из операций - дифференцирование или интегрирование - более чувствительна к случайному шуму? Как вы думаете, почему?

Литература

  1. Массивы в scipy (numpy), шпаргалка (Колдунов Н.)
    Перевод шпаргалки по массивам в SciPy.
  2. Ivan Idris. NumPy Beginner's Guide. Birmingham-Mumbai: PACKT Publishing, 2013.- 287 p.
    Руководство по NumPy для начинающих.


Автор курса: Ф.С.Занько

Лицензия Creative Commons
Это произведение доступно по лицензии Creative Commons «Attribution-ShareAlike» («Атрибуция — На тех же условиях») 4.0 Всемирная.

О замеченных ошибках, неточностях, опечатках просьба сообщать по электронному адресу:
russianlutheran@gmail.com