The Language of Technical Computing
- Release Notes
- PDF Documentation
Millions of engineers and scientists worldwide use MATLAB® to analyze and design the systems and products transforming our world. The
matrix-based MATLAB language is the world’s most natural way to express computational mathematics.
Built-in graphics make it easy to visualize and gain insights from data. The desktop
environment invites experimentation, exploration, and discovery. These MATLAB tools and capabilities are all rigorously tested and designed to work
together.
MATLAB helps you take your ideas beyond the desktop. You can run your analyses on
larger data sets, and scale up to clusters and clouds. MATLAB code can be integrated with other languages, enabling you to deploy algorithms
and applications within web, enterprise, and production systems.
Get Started
Learn the basics of MATLAB
Language Fundamentals
Syntax, array indexing and manipulation, data types, operators
Data Import and Analysis
Import and export data, including large files; preprocess data, visualize and
explore
Mathematics
Linear algebra, differentiation and integrals, Fourier transforms, and other
mathematics
Graphics
Two- and three-dimensional plots, images, animation
Programming
Scripts, functions, and classes
App Building
Create self-contained apps, embedded Live Editor tasks, and custom UI
components
Software Development Tools
Debugging and testing, organizing large projects, source control integration,
toolbox packaging
External Language Interfaces
External language and library interfaces, including Python, Java, C, C++, .NET,
and Web services
Environment and Settings
Preferences and settings, platform differences, adding hardware and optional
features
RADIOHATA.RU
RadioHata.RU
Портал радиолюбителя, начинающему радиолюбителю, Arduino, Raspberry Pi, книги по радиотехнике и электронике, простые схемы, схемы, радиотехнические журналы, видео, программы для радиолюбителя.
Download magazines: AudioXpress, Circuit Cellar, CQ Amateur Radio, Electronics For You, Elektronika dla Wszystkich, Elektorlabs, Elektor Magazine DVD, Elektronika Praktyczna, Elettronica In, ELV Journal, Funkamateur, Hi-Fi World, Klang+Ton, Nuts and Volts, Prakticka Elektronika A Radio, Practical Electronics, Practical Wireless, QST, Servo Magazine, Silicon Chip, Swiat Radio, The MagPi.
Скачать: Журнал Радио, Журнал Радиомир, Журнал Радиоаматор, Журнал Радиолоцман, Журнал Радиоконструктор, Журнал Радиосхема, Журнал Радиохобби, Журнал Ремонт и сервис, Журнал Компоненты и технологии, Журнал Электронная техника.
Скачать книги: Начинающему радиолюбителю, Телевидение и Радио, Источники питания, Для дома и быта, Прием-передача, Автолюбителю, Аудиотехника, Справочники, Учебники, Микроконтроллеры, Arduino, Raspberry Pi, Электроника, Электрика
Скачать: Программы для радиолюбителя, Видеокурсы.
Игорь Ануфриев Александр Смирнов Елена Смирнова (bhv fi fi MATLAB 7 __ • Работа с массивами, графика Игорь Ануфриев Александр Смирнов Елена Смирнова MATLAB 7 Санкт-Петербург «БХВ-Петербург» 2005 УДК ББК 681.3.06 32.973.26-018.2 А73 Ануфриев И. Е., Смирной А. Б., Смирнова Е. Н. А73 MATLAB 7. - СПб: БХВ-Петербург, 2005. - 1104 с.: ил. ISBN 5-94157-494-0 Книга посвящена применению пакета MATLAB и его расширений (Toolbox) для решения различных математических, экономических задач, задач математической физики, обработки данных и ряда других. По 1робно рассмотрена работа с массивами, описаны возможности высокоуровневой и ни жоуровнсвой графики. Значительный объем материала отведен вычислительным задачам: решению уравнений, систем линейных и нелинейных уравнений, интегрированию, аппроксимации функций, решению систем обыкновенных дифференциальных уравнений и уравнений в частных производных, задачам оптимизации и работе с разреженными матрицами. Изложены основы программирования на встроенном языке и принципы эффективного написания приложений в MATLAB, вопросы интеграции с MS Word и MS Excel. Описаны возможности расширений Toolbox. Приведено множество примеров и заданий для самостоятельной работы. Для удобства читателей тексты программ собраны на прилагаемом компакт-диске. Дгя научных работников, преп ’давателей, инженере я и стуоентов УДК 681.3.06 ББК 32.973.26-018.2 Группа подготовки издания: Главный редактор Зам главного редактора Зав. редакцией Редактор Компьютерная верстка Корректор Дизайн обложки Зав. производством Екатерина Кондукова Евгений Рыбаков Григорий Добин Алексей Семенов Натальи Смирновой Наталия Першакова Игоря Цырулышкова Николай Тверских Лицензия ИД Ns 02429 от 24.07.00. Подписано в печать 30.03.05. Формат 70x100'/,е. Печать офсетная. Усл. печ. л. 66 01. Тираж 5000 экз Заказ Ns 130 "БХВ Петербург". 194354, Санкт-Петербург, ул. Есенина, 5Б. Санитарно-эпидемиологическое заключение на продукцию Nt 77 99 G2 Э53.Д.005421.11.04 от 11.11 2004 г. выдано Федеральной службой по надзору в сфере защиты прав потребителей и благополучия человека Отпечатано с готовых диапозитивов в ОАО "Техническая книга" 190005, Санкт-Петербург. Измайловский пр., 29. ISBN 5-94157-494-0 О Ануфриев И Е., Смирнов А. Б , Смирнова Е. Н., 2005 © Оформление, илдлтельегао "БХВ-ПетербурГ', 2005 Оглавление Введение....................................................................1 Bl. О назначении и возможностях пакета MATLAB и его расширений _________ 1 В2. О содержании книги..................................................10 Часть 1. Основы работы в MATLAB............................................19 Глава 1. Простейшие вычисления.............................................21 Рабочая среда MATLAB ....................................................21 Арифметические вычисления................................................24 Простейшие вычисления..................................................24 Форматы вывода результата вычислений...................................25 Использование элементарных функций.....................................28 Встроенные элементарные функции........................................33 Тригонометрические, гиперболические и обратные к ним функции.........33 Экспоненциальная функция, логарифмы, степенные функции...............34 Функции для работы с комплексными числами............................34 Округление и остаток от деления......................................34 Использование переменных.................................................35 Сохранение и восстановление рабочей среды..............................38 Просмотр и удаление переменных, выбор имен переменных..................42 Эффективная работа из командной строки (Command History)...............................44 Задания для самостоятельной работы...................................... 48 Глав» 2. Работа с массивами................................................50 Ввод, сложение и вычитание векторов....................................51 Обращение к элементам вектора..........................................57 11рименение функций обработки данных к векторам .......................59 Поэлементные операции с векторами......................................62 Пес гроение таблицы значений функции...................................65 Построение графиков функции одной переменной...........................70 Умножение векторов.....................................................75 Скалярное произведение...............................................75 Векторное произведение...............................................76 Внешнее произведение.................................................77 Ввод матриц, простейшие операции.......................................78 Различные способы ввода.................................................................78 Обращение к элементам матриц.........................................79 Логическое индексирование............................................8J IV Оглавление Сложение, вычитание, умножение, транспонирование и возведение в степень.................................................... 84 Перемножение матрицы и вектора.................................86 Решение систем линейных уравнений................................86 Считывание и запись данных .. ................................ 87 Блочные матрицы..................................................89 Конструирование блочных матриц.................................89 Выделение блоков...............................................91 Удаление строк и столбцов......................................91 Заполнение матриц при помощи индексации..........................92 Создание матриц специального вида................................93 Визуализация матриц..............................................97 Поэлементные операции и встроенные функции..................... . 99 Поэлементные операции с матрицами..............................99 Вычисление математических функций от элементов матриц.........101 Применение функций обработки данных к матрицам..................102 Графики функций двух переменных.................................105 Задания для самостоятельной работы................................109 Задания на векторы..............................................109 Задания на матрицы..............................................109 Г лава 3. Высокоуровневая графика...................................112 Построение графиков из окна Workspace.............................112 Диаграммы и гистограммы...........................................116 Представление векторных данных..................................116 Диаграммы векторных данных....................................116 Гистограммы векторных данных..................................122 Представление матричных данных..................................126 Графики функций...................................................129 Графики функций одной переменной................................129 Графики в линейном масштабе...................................129 Графики в логарифмических масштабах...........................[32 Изменение свойств линий................................... 133 Оформление графиков...........................................135 I рафики параметрических и кусочно-заданных функций...........137 Графики функций двух переменных.................................140 Трехмерные i рафики функций...................................140 Контурные графики.............................................145 Оформление графика............................................148 Поворот графика, изменение точки обзора.......................153 Построение параметрически заданных поверхностей и линий.......156 Построение освещенной поверхности.............................159 Анимированные графики...........................................161 Работа с несколькими графиками....................................162 Вывод графиков в отдельные окна.................................163 Вывод нескольких графиков на одни оси...........................165 Несколько графиков в одном графическом окне.....................166 Визуализация векторных полей......................................169 Задания для самостоятельной работы................................174 Оглавление V Глава 4, Интерактивная среда для построения графиков................176 Графические объекты...............................................177 Редактор [рафиков.................................................178 Свойства осей, подписи, заголовок.................................183 Цветовое оформление, разметка и сетка ....................... 184 Подписи и заголовок...........................................186 Свойства линий и поверхностей.....................................187 Свойства линий................................................187 Свойства поверхностей ...................................... 19(1 Дополнительные элементы оформления.............................. 191 Обзор графиков и поверхностей................................... 196 Изменение масштаба, определение значений функции, поворот.......196 Камера для обзора графического объекта..........................197 Панель инструментов камеры......................................199 Сохранение, экспорт и печать....................................201 Задания для самостоятельной работы................................204 Глава 5. М-файлы....................................................205 Работа в редакторе М-файлов..................................... 205 Настройки редактора М-файлов................................. 209 Типы М-файлов.....................................................212 Файл-ирограммы..................................................212 У стачовка путей................................................215 Команды для установки путей...................................218 Файл -функции...................................................219 Фаил-функции с одним входным аргументом.......................220 Файл-функции с несколькими входными аргументами...............225 Файл-фупкции с несколькими выходными аргументами..............225 Разновидности функций.............................................227 Подфункции......................................................228 Вложенные функции...............................................232 Приватные функции...............................................234 Разбиение М-файла на ячейки..................................... 234 Диагностика М-файлов............................................ 237 Задания для самостоятельной работы................................239 Часть!!, вычисления и программирование..............................241 Глава 6. Методы вычислений в MATLAB.................................243 Исследование функций..............................................243 Встраиваемые и анонимные функции................................243 Решение уравнений...............................................246 Решение произвольных уравнений................................246 Вычисление всех корней полинома............................. 252 11ахиждение экстремумов функций.................................253 Минимизация функции одной переменной..........................253 Минимизация функции нескольких переменных.....................255 Управление ходом вычислений...................................258 VI Оглавление Болес подробно о jplot.................................. .. 262 Исследование функций, зависящих от параметров....................264 Интегрирование функций.............................................265 Вычисление определенных интегралов...............................265 Вычисление двойных инте1'ралов...................................268 Вычисление некоторых интегралов..................................269 Интегралы, зависящие от параметра..............................269 Интегралы с переменным верхним пределом........................271 Полиномы и интерполяция............................................271 Опспапии с полиномами............................................271 У множение, деление, сложение и вычитание......................271 Вычисление производных.........................................273 Интерполирование и сглаживание...................................274 Приближение по методу наименьших квадратов.....................274 Интерполяция сплайнами.........................................276 Интерполяция двумерных и многомерных данных....................278 Задачи линейной алгебры............................................281 Системы уравнений, определители, обращение матриц, ..............28 I Системы с плохо обусловленными матрицами.......................283 Переопределенные и недоопределенные системы....................285 Решение систем при помощи функции linsolve.....................287 Обращение матриц..................................... . . ... 290 Собственные числа и векторы матрицы, функции матриц.............. 290 Решение дифференциальных уравнений.................................293 Решение задачи Коши.............................................293 Решение уравнений Лотки—Вольтерры.............................298 Выбор солвера для решения задачи Коши..........................300 Управление процессом решения..................................301 Задание точности вычислений и шага интегрирования.............303 Управление выводом результатов................................307 Задание матрицы Якоби для повышения эффективности вычислений...312 Задачи с известными параметрами...............................314 Системы, не разрешенные относительно производной, дифференциально-алгебраические уравнения......................316 Решение дифференциальных уравнений с запаздывающим аргументом.... 323 Решение 1 раничных задач........................................330 Схема решения.................................................330 Простой пример граничной задачи...............................333 Возможности солвера bvp4c, управление вычислениями............335 Граничные задачи с неизвестными параметрами...................337 Решение задачи с особенностью на границе .....................342 Задания для самостоятельной работы 345 Глава 7. Управляющие конструкции языка программирования.............347 Операторы цикла................................... .... ....347 Цикл for........................................................347 Цикл while, суммирование рядов..................................357 Операторы ветвления...............................................361 Условный оператор if............................................361 Оглавление VII Проверка входных аргументов...................................................362 Организация ветвления.........................................................366 Оператор switch.................................................................371 Выход из фай 1-функпии, оператор ieiurn.........................................374 Прерывание и продолжение циклов...................................................375 Обработка исключительных ситуаций.................................................377 Логические выражения с массивами и числами........................................379 Операции отношения.............................................................„379 Логические операции с числами и массивами.......................................380 Приоритет логических и арифметических операций..................................383 Задания для самостоятельной работы................................................384 Глава 8- Обработка данных и приемы программирования в MATLAB........................386 Работа со строками................................................................386 Простейшие операции со строками.................................................386 Ввод и сцепление строк........................................................386 Сервисные функции для работы со строками......................................388 Массивы строк...................................................................390 Текстоные файлы ................................................................ 392 Открытие файла, считывание данных и закрытие файла..............................393 Запись в текстовый файл.........................................................396 Запись строк............................................................... 397 Форматный вывод.............................................................. 399 Простые структуры.................................................................403 Массивы структур и массивы ячеек..................................................408 Массивы структур................................................................408 Создание файл-функций для работы массивами структур.............................413 Запись данных массивов структур в текстовый файл................................414 Считывание информации из текстового файла.......................................416 Операции с массивами структур...................................................420 Массивы ячеек...................................................................421 Приложения с интерфейсом из командной строки......................................427 Простой пример, программа-калькулятор...........................................428 Формирование и исполнение команд, функция eval..................................432 Организация вывода текстовых результатов........................................437 Файл-функции с переменным числом аргументов.......................................437 Фснкции от функций................................................................446 Перманентные переменные.......................................................... 450 Рекурсивные функции............................,..................................455 Диалоговая отладка программ.......................................................467 Точки останова, пошаговое выполнение программы..................................467 Пример диалоговой отладки..........................................471 Задания для самостоятельной работы................................................477 Глава 9. Дескрипторная графике......................................................480 Основы дескрипторной графики......................................................480 Свойства графических объектов...................................................481 Функции set и get, текущие объекты...................... '....481 Свойства осей.................................................................482 Свойства линий и поверхностей.................................................486 VIII Оглавление Указатели на объекты............................................489 Изменение свойств линий и осей.................................489 Добавление линий графиков.................................... 492 Удаление и очистка объектов................................. ... 493 Влияние команд hold, cla, elf и reset на свойства окна и осей..494 Получение информации о свойствах графических объектов..........495 Использование указателей, примеры...............................497 Задание свойств в аргументах графических функций......... ..499 Размещение окон, осей и текста..................................500 Расположение графических окон и осей...........................500 Вывод текстовой информации......................................509 Графические объекты................................................522 Иерархия объектов................................................523 Объект Root......................................................524 Объект Figure (графическое окно).................................525 Базовые объекты (Core Objects)...................................527 Объекты Rectangle и Line, блок-схемы и диаграммы................527 Объект Patch, цветовое оформление объектов......................531 Освещение объектов, объект Light (источник света)...............541 Управление объектами, копирование, поиск, скрытые указатели......545 Объекты-группы hggroup и hgti anslbrm............................553 Рисованные объекты (Plot Objects)................................557 Часть III. Приложения с графическим интерфейсом......................561 Глава 10. Принципы создания приложений с GUI.........................563 Среда GUIDE......................................................564 Программирование событий.........................................568 Глава 11. Конструирование интерфейса.................................575 Управление свойствами объектов.....................................575 Работа над приложением.............................................577 Запуск приложения и его редактирование...........................577 Размеры об ьектов и их выравнивание..............................579 Всплывающие подсказки и пиктограммы..............................581 Программирование элемен гов интерфейса.............................582 Флаги, рамки.....................................................582 Переключатели....................................................586 Списки..........................................................593 Полосы скроллинга................................................598 Область ввода текста.............................................600 Свойства приложения................................................602 Изменение размеров приложения....................................602 Взаимодействие приложения со средой MATLAB.......................605 Способы программирования событий.................................606 11орядок обхода элементов управления клавишей <ТаЬ>..............607 Оглавление IX Глава 12. Диалоговые окна и меню приложения...............................609 Вилы диалоговых окон....................................................609 Окно подтверждения....................................................60Q Окна открытия и сохранения файла......................................611 Окно с сообщением об ошибке...........................................613 Меню графического окна..................................................614 Редактор меню.........................................................614 Программирование пунктов меню.........................................617 Оформление меню.......................................................618 Пункты меню с флагами состояния.....................................619 Разделительные линии................................................620 Упорядочение меню.....................................................621 Контекстное меню объектов...............................................622 Создание контекстного меню в рсдак горе...............................623 Связывание контекстного меню с объектом...............................624 Программирование контекстного меню....................................624 Глава 13. Программирование событий........................................627 События графических объектов............................................627 Приложение для получения ASCII-кода символа.............................628 Как вызываются подфункции обработки событий.............................630 Событие ButlonDownFcn.............................................................................................634 Событие ButlonDownFca осей............................................634 Событие ButtonDownFcn линии...........................................637 Создание приложений с GUI без среды GUIDE...............................638 Свойства объектов, полезные при программировании событий................641 Прерывание обработки событий..........................................641 Изменение формы курсора...............................................642 Часть IV. Использование Toolbox и решение прикладных задач................643 Глава 14. Решение за 1ач математической физики............................645 Простой пример..........................................................645 Постановка задачи................................................... 646 Среда pdelool, конструирование области................................646 Определение уравнения и граничных условий.............................649 Решение и визуализация результата.....................................652 Описание возможностей PDE Toolbox.......................................654 Эллиптическое уравнение...............................................655 Переменные коэффициенты и правая часть уравнения......................656 Параболическое и гиперболическое уравнения............................657 Пример нестационарной задачи..........................................658 Задача на собственные значения........................................661 Системы дифференциальных уравнений....................................661 Параметры триангуляции и управление процессом решения.................663 Конструирование геометрии области.......................................665 Геометрические примитивы..............................................665 Задание структуры области.............................................666 X Оглавление Композитные материалы...........................................668 Использование сетки.............................................669 Использование функций PDE Toolbox.................................670 Задание геометрии области.......................................670 Триангуляция....................................................678 Граничные условия и ко >ффициенты уравнения.................... 680 Солверы.........................................................682 Визуализация результата.........................................685 Решение модельной задачи........................................686 Функции PDE Toolbox.............................................688 Создание геометрических примитивов . . .......................689 Геомет рия области и триангуляция.............................689 Глава 15. Разреженные матрицы.......................................692 Работа с разреженными матрицами...................................692 Схема хранения..................................................692 Создаиие разреженных матриц................................ 694 Операции с разреженными матрицами...............................699 Задачи линейной ал1 ебры..........................................703 Факторизация матриц.............................................703 Профайлер.......................................................708 Решение систем уравнений и исследование спектра.................716 Глава 16. Оптимизация............................................. 718 Optimization Toolbox..............................................718 Линейное и нелинейное программирование..........................718 Линейное программирование.....................................718 Квадршичное программирование..................................721 Нелинейное программирование...................................724 11слинейныс задачи..............................................727 Задача о достижении границы...................................727 Минимизация функции с полубесконечными ограничениями..........728 Минимаксная задача............................................731 Решение нелинейных уравнений..................................733 Метод наименьших квадратов....................................735 Подбор параметров......................................... 736 Параметры оптимизации...........................................739 Примеры...........................................................741 Решение системы нелинейных уравнений............................742 Пример приложения с GUI.........................................746 Глава 17. Символьные вычисления.....................................751 Символьные переменные и функции...................................751 Определение переменных и функций и работа с ними................751 Матрицы и век горы..............................................754 Вычисления с символьными переменными............................756 Графическое представление функций...............................758 Упрощение, преобразование и вычисление выражений................760 Оглавление XI Решение задач........................................................ 763 Задачи линейной алгебры..............................................763 Суммирование и разложение в ряд................................... 767 Пределы, дифференцирование и интегрирование..........................769 Решение уравнений и систем......................................... 775 Решение дифференциальных уравнений и систем..........................778 Г лава 18. Работа со сплайнами в Spline Toolbox..........................784 Сплайны и формы их представления.......................................784 Кусочно-полиномиальная форма (ср-форма)..............................785 В-форма (разложение по базисным сплайнам)............................785 Интерполяционные сплайны...............................................786 Построение кубического сплайна.......................................786 Стандартные краевые условия........................................786 Операции над сплайнами.............................................788 Построение сплайна для вектор-фу акции.............................790 Произвольные краевые условия.......................................792 Использование сплайнов в В-форме.....................................795 Ci наживающие сплайны..................................................802 Интерактивное построение кривых........................................807 Приложение splinetool..................................................809 Сплайны для поверхностей...............................................814 Глава 19. Приближение данных и подбор параметров в Curve Fitting Toolbox.819 Приложение Curve Fitting Tool и его средства......................... 820 Создание множества данных для приближения..............................821 11редварительная обработка данных......................................824 Исключение данных из таблицы.........................................824 Начальная фильтрация табличной функции...............................826 Приближение табличных функций..........................................829 Создание приближений.................................................829 Контроль качества приближений........................................832 Типы аппроксимации для подбора параметров............................836 Определение собственной параметрической модели.......................840 Анализ построенных приближений........................................ 845 Глава 20. Решение экономических задач....................................848 Функции для работы с датами и временем.................................849 Представление времени и дат в MATLAB.................................849 Функции определения числа дней между датами..........................852 Расчеты денежных потоков...............................................856 Расчеты по обслуживанию кредитов...................................... 864 Расчеты по долговым ценным бумагам.....................................867 Дисконтные активы....................................................867 Купонные облигации... — . .......... . ................. 871 Портфельный анализ рисковых активов....................................881 Построение эффективной границы рисковых активов......................883 Оптимальный выбор портфеля...........................................887 Дополнительные ограничения при анализе портфелей.....................896 XII Оглавление Ч4С1 ь V. Дополнит ельные возможное ги MATLAB......................909 Глава 21. Связь MATLAB и MS Office.................................911 Публикация результатов работы...................................91 1 М-книТ и........................................................ 914 Настройка MATLAB и создание М-книги........................... 914 Группировка ячеек..............................................917 Управление М-книгой............................................920 Совместная работа в MATLAB и MS Excel............................921 Конфигурирование MS Excel......................................922 Обмен данными между MATLAB и MS Excel..........................923 Обращение к основным функциям MS Excel Link....................925 Функции MS Excel Link..........................................927 Глава 22. Модернизация приложений с GUI версии 5.3.................929 Пример приложения для MATLAB 5.3.................................929 Модернизация приложения..........................................931 Сохранение приложения в формате FIG............................932 Переход к форматам FIG и М.....................................934 Глава 23. Повышение производительности приложений MATLAB...........938 Ускорение работы М-файлов, экономия памяти.......................938 Поэлементные операции..........................................938 Экономия памяти................................................941 Выделение памяти под массивы...................................944 Связь MATLAB с другими языками программирования..................946 Конфигурирование MATLAB Compiler...............................947 Простой пример, сложение двух чисел........................... 948 Работа с комплексными переменными..............................952 Обмен массивами данных.........................................954 Ускорение работы при использовании циклов......................958 Приложения.........................................................961 Приложение 1. Основные команды и функции MATLAB и Toolbox..........963 Управление средой файлами и переменными.. ... 963 Получение справочной информации............................... 963 Управление средой MATLAB.......................................964 Управление переменными.........................................967 Манипулирование файлами и каталогами.......................... 969 Операторы и специальные символы..................................971 Логические операции и операторы................................972 Побитовые операции.............................................973 Логические функции...............................................978 Прл рам мирование................................................981 Конструкции языка..............................................981 Сервисные функции и переменные.................................982 Оглавление XIII Интерактивный ввод..............................................984 Объектно-ориентированное программирование и преобразование типов.986 Функции даты и времени..........................................986 Двоичные и текстовые файлы......................................987 Функции для работы с массивами ячеек............................995 Функции для работы со структурами...............................999 Звуковые и графические файлы . ................... ........ ..... 1003 Чтение, запись и преобразование звуковых данных................1003 Графические файлы ........................................... 1004 Операции со строками...................................... ..... 1007 Обработка строк................................................1007 Преобразования "строка-число"..................................1011 Преобразование системы счисления...............................1015 Работа с матрицами и массивами...................................1016 Создание матриц и массивов.....................................1016 Операции с массивами...........................................1018 Математические функции...........................................1019 Специальные функции............................................1019 Преобразование координат..................................... 1024 Решение различных математических задач...........................1025 Матричный анализ............................................. 1025 Решение спектральных задач.....................................1028 Решение линейных уравнений, разложение и обращение матриц......1029 Вычисление функций от матриц...................................1032 Поиск корней................................................. . 1033 Интерполяция и приближение данных..............................1035 Минимизация и оптимизация......................................1036 Дифференцирование и конечные разности..........................1037 Интегрирование.................................................1038 Решение дифференциальных уравнений и систем....................1039 Г рафика и визуализация данных............................... 1039 Интерактивная среда для построения и редактирования графиков...1039 Двумерные графики..............................................1040 Трехмерные и контурные графики.................................1046 Визуализация векторных полей...................................1061 Визуализация функции на непрямоугольной области.............. 1065 Оформление графиков............................................1068 Управление видом графика, камера...............................1072 Приложение 2. Описание компакт-диска...............................1081 Список ли Герату ры.............................................. 1082 Введение В1.0 назначении и возможностях пакета MATLAB и его расширений Название MATLAB является сокращением от Matrix Laboratory, и первоначально пакет MATLAB разрабатывался как средство доступа к библиотекам программ UNPACK и EISPACK, предназначенных для матричных вычислений. Пакет MATLAB создан компанией MathWorks около двадцати лет назад. Работа сотен ученых и программистов направлена на постоянное расширение его возможностей и совершенствование заложенных алгоритмов. В настоящее время MATLAB является мощным и универсальным средством решения задач, возникающих в различных областях человеческой деятельности. Спектр проблем, исследование которых может быть осуществлено при помощи MATLAB и его расширений (Toolbox), охватывает: матричный анализ, обработку сигналов и изображений, задачи математической физики, оптимизационные задачи, финансовые задачи, обработку и визуализацию данных, работу с картографическими изображениями, нейронные сети, нечеткую логику и многое другое. Около сорока специализированных Toolbox могут быть выборочно установлены вместе с MATLAB по желанию пользователя. В состав многих Toolbox входят приложения с графическим интерфейсом пользователя, которые обеспечивают быстрый и наглядный доступ к основным функциям. Пакет Simulink, поставляемый вместе с MATLAB, предназначен для интерактивного моделирования нелинейных динамических систем, состоящих из стандартных блоков. Обширная и удобная справочная система MATLAB способна удовлетворить потребности как начинающего, так и достаз очно опытного пользователя. Полная гипертекстовая информационная система (на английском языке) содержит описание встроенных функций и достаточно большое число примеров их использования. Ссылки позволяют переходить к разделам, имеющим отношение к изучаемому вопросу, что облегчает самостоятельный поиск интересующей информации. Доступ из командной строки к кратким сведениям о встроенных функциях обеспечивает возможность быстрого выбора нужного варианта обращения к функциям. Инженерам и научным работникам, проводящим самостоятельные исследования, оказываются полезными прилагаемые к пакету электронные книги в формате PDF. Данные книги не только дублируют справочную систему MATLAB и каждого Toolbox, но и содержат теоретические сведения и математическую ба- 2 Введение jy, необходимые для осознанного использования описываемых средств. Справочная система снабжена ссылками на книги и статьи, посвященные реализованным алгоритмам в MATLAB и Toolbox, что позволяет исследователю и разработчику собственных алгоритмов вникнуть в суть дела. MATLAB обладает хорошо развитыми возможностями визуализации двумерных и трехмерных данных. Высокоуровневые графические функции призваны сократить усилия пользователя до минимума, обеспечивая, тем не менее, получение качественных результатов. Интерактивная среда для построения графиков позволяет обойтись без графических функций для визуализации данных. Кроме toi о, она служит и для оформления результата желаемым образом: размещения поясняющих надписей, задания цвета и стиля линий и поверхностей, словом, для получения изображения, пригодного для включения в отчет или статью. Полный доступ к изменению свойств отображаемых графиков дают низкоуровневые функции, применение которых подразумевает понимание принципов компьютерной графики и владение приемами программирования. В MATLAB реализованы классические численные алгоритмы решения уравнений, задач линейной алгебры, нахождения значений определенных интегралов, аппроксимации, решения систем или отдельных дифференциальных уравнений. Для применения базовых вычислительных возможностей достаточно знания основных численных методов в рамках программы технических вузов. Решение специальных задач, разумеется, невозможно без соответствующей теоретической подготовки; впрочем, сведения, изложенные в справочной системе, оказываются неоценимым подспорьем для желающих самостоятельно разобраться в обширных возможностях пакета MATLAB. Простой встроенный язык программирования позволяет легко создавать собственные алгоритмы. Простота языка программирования компенсируется огромным множеством функций MATLAB и Toolbox. Данное сочетание позволяет достаточно быстро разрабатывать эффективные программы, направленные на решение практически важных задач. Визуальная среда GUIDE предназначена для написания приложений с графическим интерфейсом пользователя. Работа в среде GUIDE проста, но предполагает владение основами программирования и дескрипторной графики. Наличие определенного навыка работы в среде GLIDE предоставляет возможность создать визуальную среду для проведения собственных исследований, что значительно облегчает работу и существенно экономит врем? Зядыге 3 Объектно-ориентированный подход, заложенный в основ) MATLAB, обеспечивает современную эффективную технологию программирования. С учетом специфики решаемой задачи разработчик приложений MATLAB в дополнен не к существующим классам имеет возможность создавать собственные со своими методами. MATLAB прекрасно интегрируется со многими приложениями и средами программирования. Связь MATLAB и MS Word обеспечивает возможность написания в редакторе MS Word интерактивных документов, так называемых М-книг, основанных на специальном шаблоне. Пользователь, работающий с М-книгой, может запускать блоки команд MATLAB непосредственно из документа MS Word, причем результат выполнения команд отображается в М-книге. Данное средство прекрасно подходит для создания электронных отчетов и учебных пособий. Надстройка MS Excel Link, поставляемая вместе с МАТТ .АВ, существенно расширяет возможности MS Excel, обеспечивая доступ пользователя к функциям MATLAB и Toolbox. Подготовка данных осуществляется непосредственно в электронных таблицах, а обрашение к функциям производится либо из ячеек рабочего листа, либо в модуле, написанном на Visual Basic (VBA). MATLAB Builder for MS Excel позволяет реализовывать алгоритмы MATLAB в виде COM-объектов и использовать их в приложениях на VBA. Информация, хранящаяся в базах данных многих популярных форматов, может быть импортирована в MATLAB, нужным образом обработана и исследована при помощи функций MATLAB, а затем экспортирована в какую-либо другую базу данных. Для обмена данными используются команды языка запросов SQL. Поддерживается, в частности, связь с Microsoft Access, Microsoft SQL Server, Oracle. Имеется приложение с графическим интерфейсом, которое облегчает работу пользователей, не знакомых с языком запросов SQL. Символические вычисления в MATLAB основаны на библиотеке, являющейся ядром пакета Maple. Решение уравнений и систем, интегрирование и дифференцирование, вычисление пределов, разложение в ряд и суммирование рядов, поиск решения дифференциальных уравнений и систем, упрощение выражений — вот далеко не полный перечень возможностей MATLAB для проведения аналитических выкладок и расчетов. Поддерживаются вычисления с произвольной точностью. Пользователи, имеющие опыт работы в Maple, могут напрямую обращаться ко всем функциям данного пакета (кроме графических) и вызывать процедуры, написанные на встроенном языке Maple. 4 Введение Программный интерфейс приложения (API) реализует связь среды MATLAB с программами, написанными на С, Fortran или Java. Библиотека программного интерфейса позволяет вызывать имеющиеся модули на С, Fortran или Java из среды или программ MATLAB, обращаться к функциям MATLAB из программ на С или Fortran, осуществлять обмен данными между приложениями MATLAB и другими программами. Средства MATLAB Builder for СОМ предназначены для преобразования программ MATLAB в COM-объекты, доступные в других приложениях Для разработки интернет-приложений MATLAB создан MATLAB Web Server, причем процесс создания приложения достаточно прост— кроме умения программировать в MATLAB требуется только знание основ HTML. Подводя итог вышесказанному, можно сделать вывод, что начинающий пользователь MATLAB может в процессе работы совершенствовать свои знания как в области моделирования и численных методов, так и программирования, и визуализации данных. Огромным преимуществом MATLAB является открытость кода, что дает возможность опытным пользователям разбираться в запрограммированных алгоритмах и, при необходимости, изменять их. Впрочем, разнообразие набора функций MATLAB и Toolbox допускает решение большинства задач без каких-либо предварительных модификаций. Далее мы перечислим основные возможности Toolbox. Чтение этих сведений вы можете сопровождать запуском демонстрационных файлов MATLAB. Для этого следует запустить MATLAB и в меню Help выбрать пункт MATLAB Help Появляется окно интерактивной справочной системы, в левой части которого на вкладке Demos содержатся разделы MATLAB и Toolboxes. Щелчок мышью по названию раздела приводит к его раскрытию и отображению содержимого подразделов в праной части окна справочной системы (рис. В1). Посмотрите, например, обзор базовых графических возможностей пакета, который содержится в подразделах Graphics и 3-D Visualization. К примеру, в подразделе Graphics перейдите к пункту Functions of Complex V ariables и запустите соответствующую демонстрацию ппи помощи двойного щелчка мышью по названию пункта или щелчка мышью по ссылке Run this demo в верхнем правом углу окна справочной системы. В появившемся окне Functions of Ccmplex Variables нажимайте кнопку Next, при этом строятся графики функций комплексных переменных, а сами выражения для функций выводятся в заголовке графиков. Обратите внимание на текстовую область под графиком, в которой отображаются те команды, которые надо вызвать в MATLAB для получения подобных результатов. введение 5 Рнс. Bl. Окно справочной системы со ссылками на демонстрационные файлы Некоторые возможности MATLAB представлены видеодемонстрациями, например: использование интерактивной среды для построения графиков (пункт Interactive Plot Creation with the Plot Tools подраздела Graphics)- создание приложений с графическим интерфейсом (пункт Creating a GUI with GLIDE подраздела Creating Graphical User Interfaces). Если вы работали в прежних версиях MATLAB, то вам окажутся полезными видеообзоры новых возможное гей среды, редактора, графики и программирования, которые содержатся в подразделе New Features in Version 7. Двойной щелчок мышью по разделу Toolboxes приводит к раскрытию списка подразделов. Темы каждого подраздела охватывают многие практически важные задачи, которые могут быть решены при помощи данного Toolbox. Разумеется, возможности Toolbox не исчерпываются представленными в демонстрациях. Далее приведено краткое описание некоторых Toolbox. Примечание Для гою чтобы узнать, какие именно Toolbox входят в установку MATLAB на вашем компьютере, достаточно запустить MATLAB и в командной 6 Введен- строке (обозначенной символом ») набрать ver и нажать <Enter>. Выводятся названия всех доступных Toolbox с указанием их версий. Средства обработки сигналов собраны в нескольких Toolbox. Базовые инструменты для решения задач обработки сигналов находятся в Signal Processing Toolbox: П генерация, импорт и экспорт сигналов; □ разработка, анализ и применение цифровых фильтров с конечной и бесконечной импульсной характеристикой; □ конструирование аналоговых фильтров; □ преобразования, спектральный анализ и статистическая обработка сигналов, П моделирование параметрических временных рядов. В состав Signal Processing Toolbox входит несколько приложений с графическим интерфейсом, предназначенных для облегчения доступа к функциям Toolbox. Данные приложения позволяют импортировать1, визуализировать и исследовать сигналы, изучать спектр сигналов, интерактивно создавать фильтры с заданными характеристиками. Более широкие возможности для конструирования фильтров предоставляют Filter Design Toolbox и Filter Design HDL Coder. Разработка и анализ высокочастотных цепей могут быть осуществлены в RF Toolbox. Для построения моделей систем на основе экспериментально полученных данных служит System Identification Toolbox. При исследовании и обработке сигналов и изображений оказывается очень полезным вейвлетный анализ, который можно проделать средствами Wavelet Toolbox. Алгоритмы обработки изображений собраны в Image Processing Toolbox, функции которого позволяют осуществить: □ импорт и экспорт графической информации; □ геометрические операции, например такие, как изменение размеров и поворот; □ получение статистической информации об изображении; П анализ изображений, например, нахождение границ интенсивности; □ обработка изображений: изменение контрастности, применение фильтров; □ разработка линейных фильтров; □ дискретные преобразования, в частности, быстрое преобразование Фурье; □ операции над соседними элемен тами; В&едение 7 □ работа с картой цветов; □ различные методы представления цветов: □ преобразование типов изображений. В состав Image Processing Toolbox входит несколько демонстрационных приложений, охватывающих решение задач о нахождении границ изображений, фильтрации и разработки фильтров, сжатии изображения. Для работы с картографическими изображениями имеется отдельный Mapping Toolbox. Получение видеоинформации от внешних устройств может быть выполнено средствами Image Acquisition Toolbox. Среда MATLAB позволяет осуществить импортирование цифровых и аналоговых данных с использованием совместимого с PC оборудования, их обработку и экспортирование. Для обмена данными служат Data Acquisition Toolbox и Instrument Control Toolbox, функции которых поддерживают работу с оборудованием известных производителей. Для статистической обработки информации и анализа данных имеется несколько Toolbox Функции и приложения Statistics Toolbox покрывают широкий спектр статистических задач и реализуют основные методы их решения. Доступно более двадцати классических распределений, для них имеются функции распределения вероятности (и обратной к ней), плотности вероятности, вычисления моментов распределений и генерации выборки из распределения Основные классы статистических задач могут быть исследованы при помощи Statistics Toolbox, включая: П исследование линейных моделей; □ параметрическое оценивание; □ проверку гипотез; □ планирование эксперимента; □ задачи кластерного анализа и др. Statistics Toolbox содержит набор функций для построения статистических графиков и приложения с графическим интерфейсом пользователя, предназначенные для изучения распределений и аппроксимации данных с использованием регрессионной модели. Приближение данных различными способами реализовано в Curve Fitting Toolbox и Spline Toolbox, предоставляющих следующие возможности: □ предварительная обработка табличных данных до приближения; □ параметрическое и непараметрическое сглаживание; 8 Введение □ аппроксимация с использованием линейных и нелинейных моделей, причем имеется библиотека широко распространенных моделей и предусмотрена возможность создания собственных; □ устойчивые методы подбора параметров; □ вычисление различных критериев приближений; □ анализ данных: экстраполяция, интегрирование, дифференцирование; □ представление сплайнов в кусочно-полиномиальной форме и 5-форме, преобразование из одной формы в другую; □ интерполяция и сглаживание при помощи сплайнов; □ вычисление производных, интегралов и отображений от сплайнов; □ выбор оптимального расположения узлов сплайна; П тензорное произведение сплайнов для конструирования многомерных сплайн-функций; □ рациональные сплайны; □ применение сплайнов для решения нелинейных обыкновенных дифференциальных уравнений. Проблемы, возникающие в различных областях экономики и финансов, могут быть исследованы при помощи специализированных алгоритмов нескольких Toolbox: Financial, Financial Derivatives, GARCH, Financial Time Series, Datafeed и Fixed-Income. Перечислим основные задачи, решение которых может быть выполнено функциями и приложениями данных Toolbox: □ вычисление и анализ цены, доходности и чувствительности отдельных финансовых активов (основных и производных ценных бумаг) на срочном и спотовом рынках; □ проведение анализа для управления портфелями ценных бумаг; О подбор и оценивание стратегий хеджирования (страхования) операций на различных рынках; □ управление рисками, их выявление и оценивание; □ вычисление потоков платежей и их анализ, в том числе оценка инвестиционных проектов, анализ и прогнозирование экономических показателей; П проектирование составных финансовых инструментов, включая валютные операции; введение 9 □ моделирование и оценивание волатильности временных рядов методами математической статистики, проверка статистических гипотез, выявление корреляции обрабатываемых случайных процессов; П калькуляция цены, доходности и чувствительности активов с фиксированным доходом по методикам Ассоциации индустрии ценных бумаг США и Канады; Г) импортирование статистических данных с финансовых рынков и проведение на их основе технического анализа с привлечением большого количества индикаторов. Как мы уже упоминали, MATLAB поддерживает символьные вычисления. Symbolic Math Toolbox содержит функции, обеспечивающие доступ к вычислительному ядру Maple. Пользуясь ими, вы можете: производить интегрирование и суммирование, вычислять пределы и находить разложение функций в ряд, упрощать выражения, находить определители, решать задачи на собственные значения, применять различные преобразования, решать алгебраические и дифференциальные уравнения, проводить вычисления с любой точностью, словом, использовать все возможности символьной математики Maple. Интерфейс с Maple и входящими в его состав пакетами может быть налажен средствами Extended Symbolic Math Toolbox. Optimization Toolbox нацелен на решение основных линейных и нелинейных задач оптимизации, причем для задач с большим числом неизвестных предусмотрены весьма эффективные специальные методы. Класс задач, охватываемый данным Toolbox, включает: □ линейное и квадратичное программирование; □ минимизацию нелинейных функций при наличии нелинейных ограничений; П подбор параметров; □ минимаксные задачи и задачи о достижении цели Partial Diffeiential Equations Toolbox (PDE Toolbox) создан для решения задач математической физики, описываемых дифференциальными уравнениями и системами в частных производных, методом конечных элементов. Решение задач значительно упрощается благодаря приложению с графическим интерфейсом, которое позволяет пегко и наглядно осуществить все этапы решения задач методом конечных элементов — от задания области и граничных условий до визуализации результата. Приложение может быть легко настроено на определенный класс решаемых задач, например таких, как: □ теория упругости; □ элект ростатика и магнитостатика; 10 В ii >дение □ теплопроводность; □ теория диффузии. Нестационарные процессы отображаются при помощи анимированных графиков. В состав PDE Toolbox входят солверы для решения нелинейных задач и задач в адаптивном режиме. Возможности PDE Toolbox не ограничиваются вышеперечисленными типами задач, в частности, встроенные функции могут быть использованы для решения систем уравнений произвольной размерности. PDE Toolbox является хорошим компактным пакетом для обучения основам метода конечных элементов и введения в конечноэлементные пакеты. Однако серьезные инженерные практические задачи вряд ли могут быть решены в нем, поскольку он поддерживает только один тип конечных элементов— линейные треугольные. До 2003 г. в состав MATLAB входило приложение FEMLAB, которое затем стало отдельным программным продуктом, но FEMLAB может быть установлен и как приложение MATLAB. FEMLAB позволяет моделировать двумерные и трехмерные задачи, описываемые дифференциальными уравнениями в частных производных: перенос, течения, упругость и электромагнетизм. Следует подчеркнуть, что MATLAB и его расширения могут с успехом применяться для интерактивного моделирования и анализа нелинейных систем, исследования устойчивости, разработки цифровых и аналоговых систем связи, передачи и хранения информации. Многие практические задачи, возникающие в области нечеткой логики и нейронных сетей, могут быть решены с использованием соответствующих Toolbox. В 7-ую версию MATLAB включен Bioinformatics Toolbox, предназначенный для решения некоторых задач, лежащих на стыке биологии и информатики. В начале введения мы упомянули пакет Simulink, поставляемый вместе с MATLAB, который служит для исследования нелинейных динамических систем. Он хорошо интегрируется в среду MATLAB и расширяет ее возможности. Например, сочетание Simulink и Signal Processing Blockset позволяет в удобной среде разрабатывать алгоритмы обработки сигналов и генерировать код на С. Обзор возможностей, предоставляемый Simulink занимает много Mecia— мы отсылаем заинтересованных читателей к нескольким книгам [2, 5]. В2.0 содержании книги Разумеется, ограниченность объема книги не позволяет подробно описать все средства, которые MATLAB и Toolbox предоставляют в распоряжение исследователя и инженера. Введение 11 Первая часть книги посвящена основам работы в MATLAB. В главе I описаны рабочая среда и приемы эффективной работы из командной строки. Объяснено использование переменных и вычисление арифметических выражений, изменение формата вывода чисел и основные встроенные математические функции. Глава 2 книги подробно разъясняет принципы работы с матрицами и векторами, включая основы визуализации векторных и матричных данных. Особенности представления данных в виде массивов, в частности, матриц и векторов, дают пользователю более широкие возможности по сравнению с большинством языков программирования. Набор специальных функций и средств унифицирует работу с массивами данных, делая ее очень эффективной. Отсутствие навыков оперирования с массивами в MATLAB приводит к многочисленным затруднениям даже при решении самых простых задач. Глава 3 нацелена на обучение читателя свободному владению средствами высокоуровневой графики для построения диаграмм и гистограмм, линий, поверхностей и векторных полей. Пакет MATLAB обладает чрезвычайно мощными возможностями визуализации одномерных и многомерных данных различных типов, включая и построение графиков функций. Приведены команды, служащие для организации и оформления графических результатов с целью получения хорошо читаемых графиков. Интерактивная среда для построения графиков позволяет визуализировать данные, не прибегая к командам MATLAB. Кроме того, инструменты интерактивной среды могут быть использованы для редактирования существующих графиков, изменения свойств всех содержащихся на них объектов и манипулирования графиком, в частности, для осмотра поверхности со всех сторон. Эти вопросы, а также экспорт графических результатов и их печать описаны в главе 4. Работа из командной строки, разумеется, не очень удобна и подходит только для решения простых задач. Выход состоит в использовании М-файлов, т. е. программ и функций, содержащих нужную последовательность команд MATLAB. Написание основных типов М-файлов (файл-программ и файл-функций) во встроенном редакторе разобрано в главе 5. М-файлы сохраняются на диске и запускаются на выполнение так же, как и другие команды и функции MATLAB, что позволяет расширять набор стандартных средств MATLAB и создавать собственные пакеты программ для решения специальных задач. Более того, подавляющее большинство функций MATL ЛВ и Toolbox имеют открытый код, они запрограммированы в М-файлах, что дает опытному пользователю уникальную возможность разбираться в осо 12 Введение бен костях реализации алгоритмов и изменять их, приспосабливаясь к решению сложных специальных задач. Вторая часть книги посвящена более сложным вопросам — применению численных методов и программированию собственных, алгоритмов. Программирование в MATLAB не требует специальных знаний, достаточно понимать принципы алгоритмизации. Пользователи, имеющие опыт программирования на одном из алгоритмических языков, например. Basic, С или Pascal, легко освоят встроенный язык программирования, основанный на минимальном наборе конструкций. Решение классических задач численными методами при помощи функций MATLAB требует, в отличие от программирования, знаний, как минимум в объеме программы технических вузов. Поиск корней и минимизация функций, интегрирование и интерполирование, решение задач линейной алгебры, обыкновенных дифференциальных уравнений и систем разобраны в главе 6. Вычислительные алгоритмы MATLAB допускают их настройку на получение результата с определенной точностью и задание ряда опций для управления ходом вычислений. Данный круг вопросов также освещается в главе 6. Г'шва 7 содержит описание основных конструкций языка программирования MATLAB, включая операторы ветвления и циклов. Описаны логические операции и логическое индексирование в применении к массивам, которые зачастую позволяют сократить объем программы и повысить ее эффективность. Работа со строками, текстовыми файлами и специальными типами данных— массивами ячеек и структур — продемонстрирована в главе 8 на нескольких содержательных примерах. В этой же главе описан простейший способ организации взаимодействия программы MATLAB с пользователем на основе интерфейса из командной строки. Несколько разделов главы 8 информируют читателя о принципах написания файл-функций с переменным числом входных и выходных аргументов, поскольку подавляющее большинство функций MATLAB допускают именно такое универсальное обращение к ним. Уделено внимание созданию рекурсивных функций. Программирование сложных алюритмов нередко требует их отладки. Редактор MATLAB содержит набор средств для отладки программ, использование которых также пояснено в главе 8. Разработка в MATLAB программ, связанных с визуализацией данных, основана на управлении свойствами графических объектов прямо в ходе работы программы. Хорошо написанная программа не должна требовать от пользователя доработки графических результатов, к примеру, при помощи интерактивной среды для редактирования графиков. MATLAB является Введение 13 объектно-ориентирован ной системой, все его графические объекты выстроены в некоторую иерархию и имеют определенные свойства. Полный доступ к свойствам всех графических объектов эффективно реализуется средствами дескрипторной графики. Глава 9 раскрывает принципы управления свойствами графических объектов и содержит описание основных свойств. Простые примеры, приведенные в главе 9, демонстрируют основные возможности, имеющиеся в распоряжении разработчика графических программ в системе MATLAB. Третья часть книги предназначена для поэтапного обучения процессу создания приложений с графическим интерфейсом пользователя в среде GUIDE. Простота программирования и работы в среде GUIDE компенсируется потенциалом вычислительных и визуальных средств MATLAB и Toolbox. Разработка приложений с графическим интерфейсом пользователя в среде GLIDE занимает немного времени, но существенно облегчает и ускоряет проведение исследований. В главе 10 на примере простого приложения показан процесс размещения элементов интерфейса в окне приложения и программирование событий. Следует иметь в виду, что обработка событий элементов управления требует понимания основ дескрипторной графики, которые изложены в главе 9. Читая главу 11, вы продолжите работу над созданным приложением, пополняя его интерфейс флагами, переключателями, областями ввода и полосами скроллинга и программируя их с учетом обеспечения согласованной работы всех элементов управления. О том, как снабдить собственное приложение диалоговыми окнами, меню, в том числе контекстными, сообщается в 'лаве 12. Удобство работы с приложением во многом определяется хорошо продуманной структурой меню. Изменение структуры меню так же описано в этой главе. Глава 13, завершающая третью часть книги, содержит некоторые дополнительные сведения о программировании событий графических объектов, например, щелчка мышью или нажатия клавиши, и ряде свойств, связанных с этими событиями. Четверзая часть книги посвящена применению Toolbox для исследования некоторых специальных задач. Глава 14 раскрывает перед читателем возможности Toolbox Partial Differential Equations (PDE), позволяющего решать задачи математической физики, описываемые уравнениями в частных производных методом конечных элементов. Детально разобраны этапы решения задач в среде pdetool с графическим интерфейсом: описание геометрии области, задание уравнения и граничных условий, разбиение области 14 Введение сеткой, поиск приближенного решения и визуализация результата. Разобраны примеры стационарных и нестационарных задач. Следует иметь в виду, что с реда pdetool лишь облегчает доступ к большому набору функций PDE Toolbox. Непосредственное использование данных функций в собственных программах позволяет проводить более сложные исследования по сравнению с возможностями pdetool. В связи с этим в главе 14 приведено описание форматов представления данных, связанных с реализацией метода конечных элементов в PDE Toolbox, и разобраны примеры использования функций TooIdox. Решение многих современных сложных задач численными методами приводит к так называемым разреженным матрицам, т. е. матрицам, содержащим достаточно много нулевых элементов. Работа с разреженными матрицами в MATLAB с точки зрения пользователя происходит практически так же, как и с обычными. Разреженные матрицы принадлежат специальному классу, в котором обычные матричные операции переопределены в соответствии со спецификой разреженных матриц. Глава 15 поясняет схему хранения, создание и операции с разреженными матрицами. Профайлер MATLAB позволяет о гчезливо выявить преимущества учета структуры матрицы при решении задач линейной алгебры и матричного анализа, например таких, как факторизация матриц. Решение различных типов линейных и нелинейных оптимизационных задач на основе функций Optimization Toolbox разобрано в главе 16. Эффективное использование оптимизационных алгоритмов для решения сложных задач требует понимания методов и умения работать с разреженными матрицами. Приведен пример решения большой системы нелинейных уравнений. Отдельный раздел главы 16 посвящен написанию приложения с графическим интерфейсом пользователя для решения практически важной задачи о подборе параметров. Исследователи, чья работа сопряжена с проведением большого количества аналитических выкладок и программированием модулей для соответст вую-щих расчетов, несомненно, заинтересуются Symbolic Math Toolbox. Символьные вычисления основаны на мощном ядре Maple, при этом пользователь имеет доступ ко всем ресурсам MATLAB. Глава 17 этой книги нацелена на обучение пользователя работе с символьными выражениями, включая упрощение, преобразование и вычисление с произвольной точностью. Отдельные разделы данной главы описывают технику решения задач в аналитическом виде, включая матричный анализ, суммирование, разложение в рядьц нахождение пределов функций и интегрирование, поиск решения дифференциальнь х уравнений и систем. Введение 15 В главе 18 рассматривается приближение интерполяционными и сглаживающими сплайнами в Spline Toolbox. Сплайны могут быть сконструированы в де-форме и В-форме Описываются возможности задания различных граничных условий и их влияние на точность аппроксимации. Обсуждается ключевой момент в создании В-сплайнов— кратность узлов. Средства Toolbox позволяют приближать функции с различной степенью гладкости. Приводятся примеры пост роения кривых и поверхностей с помощью сплайнов. Возможности аппроксимации табличных функций, реализованные в Curve Fitting Toolbox, излагаются в главе 19. Описываются способы предварительной обработки данных, основанные на регрессионном анализе и других методах для начальной фильтрации данных. Разобраны создание собственных параметрических моделей и использование одной из стандартных на примере рациональной или частичной суммы ряда Фурье. Материал этой главы позволит читателю выполнить непараметрическое приближение либо сглаживающими сплайнами, либо интерполяционными методами. Поясняется, как провести анализ результатов, включающий экстраполяцию табличной функции, интегрирование и дифференцирование полеченного приближения. Глава 20 знакомит читателя с возможностями решения экономических задач в Financial Toolbox. Рассмотрены вопросы анализа потоков платежей в различных сферах бизнеса. Иллюстрируется применение функций 1 oolbox для расчетов, связанных с обращением купонных и бескупонных облигаций На примере модельных задач демонстрируются возможности по управлению портфелями рискованных ценных бумаг. Рассматриваются различные ьиды ограничений на состав портфеля и поясняются правила формирования и использования этих ограничений. Последняя, пятая, часть книги охватывает несколько вопросов, которые могут быть полезны читателям с различными уровнями подготовки. Глава 21 рассказывает об автоматической генерации отчетов и о работе с MATLAB в популярных форматах MS Word, MS Power Point, H FML и TeX. Интегрирование MATLAB c MS Word позволяет создавать в MS Word интерактивные документы (М-кннги) для представления постановки задачи, методов и результатов расчетов в наглядной форме с использованием всех возможностей мощного текстового редактора MS Word и среды MATLAB. Читатель М-книги может запускать блоки команд MATLAB и получать текстовый и графический результат прямо в M-книге. Раздел "Совместная работа в МА TLAB u MS Excel" главы 21 содержит информацию о конфшури-ровании MS Excel и организации совместной работы в MATLAB и MS Excel, Возможен не только обмен данными между средой MATLAB и таблицами MS Excel, но и вызов функций MATLAB, как из ячеек листа, так и из приложений на VBA. 16 Введение Пользователям, которые имеют приложения с графическим интерфейсом, созданные в MATLAB версии 5.3, несомненно, окажется полезной информация о модернизации приложений в формат, принятый в новых версиях. Глава 22 описывает процесс преобразования приложений из формата m/mat, поддерживаемого в MATLAB 5.3, в формат m/fig, который используется в версиях, начиная с шестой. Эффективное оперирование с данными большого объема в MATLAB подразумевает применение ряда приемов, которые описаны в главе 23. В ней обсуждаются: распределение памяти, преимущество встроенных поэлементных операций по сравнению с циклической организацией обработки данных и выбор данных подходящего типа. Работа пользователя MATLAB не ограничена только возможностями среды и модулей Toolbox. В пакет MATLAB входит библиотека функций MATLAB API, реализующих программный интерфейс приложений. Глава 23 содержит также основные сведения о MATLAB API и примеры интерфейса для внешних модулей, написанных на других языках программирования. В ряде случаев задействование внешних модулей повышает эффективность приложений MATLAB. Основные функции MATLAB и ряда Toolbox, сгруппированные по категориям. приведены в приложении 1. Краткое описание различных вариантов вызова функций снабжено ссылками на соответствующие разделы книги, в которых обсуждается использование данных функций. Для удобства работы с книгой все листинги приводимых программ занесены на прилагаемый компакт-диск, структура которого описана в приложении 2. Изложение материала в книге сопровождается примерами, а в конце некоторых 1лав приведены задания для самостоятельной работы. Данная книга ни в кой мере не претендует на полноту изложения. Достаточно сказать, что документация по MATLAB и Toolbox весьма объемна, в частности, описание PDE Toolbox содержит около трехсот страниц. Optimization Toolbox — около четырехсот, а описание Statistics Toolbox превосходит девятьсот страниц. Следует иметь в виду, что справочная система позволяет' не только научиться применять средства MATLAB для решения различных задач, но и разобраться в особенностях реализованных методов. Огромное количество сведений, содержащихся в документации и справочной системе, оказывается полезным для исследователей и инженеров, владеющих основами работы в MATLAB. Начинающий пользователь может просто запутаться в обилии информации. Поэтому часто мы приводим ссылки на разделы справочной системы для самостоятельного изучения материала. Предлагаемая вашему вниманию книга предназначена для тех читателей, которые хотят изучить принципы вычислений и программирования в Введение 17 MAI LAB и освоить работу в некоторых Toolbox. Углубление знаний в области решения специализированных задач позребует от читателя достаточно кропотливой самостоятельной работы. Список литературы, касающейся проз раммирования и решения задач в MATLAB, приведен в конце книги Пользователям предыдущей версии MATLAB будут интересны новшества, появившиеся в седьмой версии. Расширены возможности рабочей среды и ее компонент. Стало удобнее работать с несколькими файлами и графическими окнами — окна редактора М-файлов, графические окна и браузер переменных могут быть встроены в рабочую среду. Сохранив вид рабочей среды, вы легко восстановите его во время следующего сеанса работы. Появилась новая панель инструментов для размещения ярлыков, обеспечивающих быстрый доступ к собственным программам, приложениям и командам MATLAB. Редактор массивов и браузер переменных содержат средства для визуализации данных; кроме того, редактор массивов позволяет просматривать структуры, в том числе и вложенные. Графические средства претерпели некоторые изменения. Вместо редактора графиков появилась интерактивная среда для визуализации данных, не требующая обращения к графическим функциям. Данная среда содержит ряд компонентов, которые могут быть использованы для редактирования графиков. При оформлении графиков теперь допускается запись математических формул в формате LaTeX и добавление новых объектов: выносных подписей, геометрических фигур и разного рода стрелок. Эти поясняющие объекты могут быть привязаны к точке с заданными координатами и не менять своего положения, например, при выборе нового масштаба. Инструмент Data ( ursor графического окна предназначен для отображения координат точек графиков при помощи мыши и прикрепления к ним ярлыков со значениями координат. Построив и оформив графики, вы имеете возможность автоматически сгенерировать код, выполнение которого приведет к созданию графического окна с тем же содержимым. Данный код легко добавить в собственное приложение и модифицировать по мере надобности. Несколько изменилась структура графических объектов. Теперь в нее включены объекты-группы, облегчающие выполнение однотипных действий с набором объектов. В процессе программирования и отладки приложений оказывается полезным анализатор кода M-Lint, который подсказывает эффективные способы ускорения алгоритма и оптимизации работы с памятью. Отладчик М-файлов снабжен условной точкой останова. Предлагает ся новый способ организации работы в М-файле — блоки команд являются ячейками и могут быть выполнены в нужной последователь- 18 Введение ности. С этим новшеством связан удобный способ представления результатов работы в виде автоматически генерируемого отчета в одном из распространенных форматов MS Word, MS Power Point, HTML или LaTeX. Среда визуального программирования предлагает ряд новых объектов — панель для упрощения работы с переключателями и кнопки-переключатели. Ваше приложение с графическим интерфейсом теперь может использовать ActiveX -компоненты. Появились два новых типа функций — анонимные и вложенные. Они, в частности, могут быть использованы для решения математических задач, содержащих параметры. Соответствующие вычислительные функции MATLAB поддерживают и прежний способ обращения к ним, при котором параметры указываются в качестве дополнительных аргументов. Расширены и базовые вычислительные возможности — в состав MATLAB вошли солверы для решения обыкновенных дифференциальных уравнений и систем, не разрешенных относительно старшей производной. Изменения коснулись ряда Toolbox и компонент MATLAB; более того, появились несколько новых. Например, кроме упомянутых нами Bioinformatics Toolbox и Filter Design HDL Coder создан Genetic Algorithm and Direct Search Toolbox. Он содержит функции, расширяющие возможности Optimization Toolbox и вычислительных функций MATLAB для решения оптимизационных задач. Подробная информация о новшествах содержится на сайте производителя MATLAB — компании MaihWorks: http://www.mathworks.com. На этом сайте доступна документация в формате PDF, также вы можете найти руководства по использованию различных возможностей MATLAB, не включенные в справочную систему, и готовые решения. Из русскоязычных сетевых ресурсов мы рекомендуем сайт http://matlab.expunenta.ru, который содержит разделы, связанные с различными аспектами работы в MATLAB, Toolbox, Simulink и FemLab. Ведущие разделов не только размещают материалы, но и отвечают на вопросы пользователей. Мы с благодарностью примем ваши замечания и пожелания по поводу нашей книги и постараемся ответить на все ваши вопросы. Желаем вам успехов в изучении MATLAB. ЧАСТЬ I Основы РАБОТЫ В MATLAB 2 3«t ВО Глава 1 Простейшие вычисления Данная глава посвящена описанию рабочей среды MATLAB и вычислениям алгебраических выражений с использованием встроенных математических функций Команды, с которых мы начнем, не очень длинные, поэтому для простоты будем работать из командной строки MATLAB. Рабочая среда MATLAB При запуске MATLAB на экране открывается рабочая среда MATLAB, изображенная на рис. 1.1. Основными элементами рабочей среды являются: □ меню; □ панель инструментов с кнопками и раскрывающимся списком; □ окна с вкладками Workspace и Current Directory для просмотра переменных и установки текущего каталога; □ окно Command Window, служащее для ввода команд и вывода результата; □ окно Command History, предназначенное для просмотра и повторного выполнения ранее введенных команд (окно Command History может быть не пустым, если до этого пакет MATLAB использовался); □ строка состояния с кнопкой Start. При нажатии на кнопку Start открывается меню, приведенное на рис. 1.2. С его помощью обеспечивается доступ ко всем основным средствам MATLAB. 22 Часть I. Основы работы в MATlAB Рис. 1.1. Рабочая среда МATI.АВ Окно Command Window состоит из следующих элементов: □ заголовка с названием окна и двумя кнопками справа; □ рабочей области с командной строкой, в которой находится мигающий вертикальный курсор; □ полос скроллинга. Если рабочая среда MATLAB выглядит не так, как изображено на рис. 1.1, го следует в меню Desktop выбрать пункт Desktop layout, а затем в ниспадающем меню пункт Default (По умолчанию). Пункты меню Desktop позволяют добавлять одноименные окна в рабочую среду или убирать их. Открыт ые окна в меню отмечены флагом. В поле за! оловка каждого окна рядом с кнопкой закрытия находится кнопка Undock... для извлечения окна из рабочей среды MATLAB, если оно Глава 1 Простейшие вычисление 23 встроено, или кнопка Dock ... для встраивания отдельного окна в рабочую среду. В следующих главах описано использование указанного средства для различных окон. Все команды, описанные в этой главе, следует набирать в командной строке. Сам символ » приглашения командной строки, приведенный в примерах, набирать не нужно. Для просмотра рабочей области командного окна удобно использовать полосы скроллинга или клавиши <Home>, <End> для перемещения влево или вправо и <PageUp>, <PageDown> для перемещения вверх или вниз. Про использование клавиш <Т>, <Х>, <—», <<—> будет сказано дополнительно. Если вдруг после перемещения по рабочей области командного окна пропала командная строка с мигающим курсором, просто нажмите <Enter>. Важно запомнить, что набор любой команды или выражения должен заканчиваться нажатием на <Enter>, для того чтобы программа MATLAB выполнила эту команду или вычислила выражение. При запуске пакета в рабочей области окна Command Window появляются две ссылки MATLAB Help и Demos для вызова справочной системы или демонстрационных примеров. Об использовании среды Help см. далее в этой главе. MATLAB » /X Toolboxes h If SimuBnk > Blocksets » Shortcuts > Desktop Took > Qt Web ► Preferences... M Find Files .. Help -gf Demos 4k Start Рис. 1.2. Раскрывающееся меню по кнопке Start 24 Часть I. Основы работы в МА TlAB Арифметические вычисления Встроенные математические функции позволяют находить значения различных выражений. MATLAB предоставляет возможность управления форматом вывода результата. Команды для вычисления выражений имеют вид, свойственный всем языкам программирования высокого уровня. Простейшие вычисления Выберите вид рабочей среды "по умолчанию", как было описано выше, наберите в командной строке 1+2 и нажмите <Enter>. В результате в командном окне MATLAB отображается следующее; » 1 + 2 ans - 3 » I Что сделала программа MATLAB? Сначала она вычислила сумму 1 + 2, затем записала результат в специальную переменную ans и вывела ее значение, равное 3, в командное окно. Переменная ans автоматически создается, когда вычисляемое выражение не присваивается некоторой переменной. Информация о переменной ans сразу же появилась в окне Workspace (рис. L3). В первом столбце Name записано имя переменной. Следующий столбец Value показывает значение переменной, если это возможно. Содержимое столбца Size, по существу, демонстрирует основной принцип работы MATLAB. Программа MATLAB все данные представляет в виде массивов. Переменная ans является двумерным массивом размера один на один и занимает 8 байт памяти, о чем свидетельствует столбец Bytes. Наконец, в последнем столбце Class указан тип переменной — double array, т. е. массив, состоящий из чисел двойной точности. Любой столбец можно скрыть или отобразить, если на заголовке окна щелкнуть правой кнопкой и вызвать контекстное меню. По умолчанию все числа представляются о двойной точностью (double). В главе 2 говорится об использовании других типов чисел. В окне Command Window ниже ответа расположена командная строка с мигающим курсором, обозначающая, что среда MATLAB готова к дальней Гпава 1 Простейшие вычисления 25 шим вычислениям. Можно набирать в командной строке новые выражения и находить их значения. Рис. 1.3. Окно Workspace с информацией об использованных переменных среды Если требуется продолжить работу с предыдущим выражением, например, вычислить (1+2)/4.5, то проще всего воспользоваться уже имеющимся результатом, который хранится в переменной ans. Наберите в командной строке ar.s/4.5 (при вводе десятичных дробей используется точка) и нажмите <Erter>, получается: » ans/4.5 ans = 0.6667 » I Вид, в котором выводится результат вычислений, зависит от формата вывода, установленного в MATLAB. Рассмотрим подробнее этот вопрос. Форматы вывода результата вычислений Требуемый формат вывода результата определяется пользователем из меню рабочей среды МА ГЪАВ. Выберите в меню File пункт Preferences. На экране появится диалоговое окно Preferences, изображенное на рис. 1.4. Для установки формата вывода следует убедиться, что в списке левой панели выбран 26 Часть I Основы работы в MATLAB пункт Command Window (как показано на рис. 1.4). Задание формата производится из раскрывающегося списка Numeric format панели Text display. Рис. 1.4. Диалоговое окно Preferences MATLAB Разберем пока только наиболее часто используемые форматы. Выберите short в раскрывающемся списке Numeric format на панели Text display диалогового окна. Закройте диалоговое окно, нажав кнопку ОК Сейчас установлен короткий формат с плавающей точкой short для вывода результатов вычислений, при котором на экране отображаются только четыре цифры после десятичной точки. Наберите в командной строке 100/3 и нажмите <Enter>. Результат выводится в формате short: » ЮО/з ans = 33.3333 Гпава 1. Простейшие вычисления 27 Этот формат вывода сохранится для всех последующих вычислений, если только не будет установлен другой формат. Заметьте, что в МАП.АВ возможна ситуация, когда при отображении слишком большого или малого числа результат не укладывается в формат short. Вычислите 10 000/3, результат выводится в экспоненциальной форме: » 100000/3 ans = З.ЗЗЗЗе+004 То же самое произойдет и при нахождении 1/3000: » 1/3000 ans = З.ЗЗЗЗе-004 Однако первоначальная установка формата сохраняется и при дальнейших вычислениях — для небольших чисел вывод результата снова будет происходить в формате short. В предыдущем примере MATLAB вывела результат вычислений в экспоненциальной форме. Запись З.ЗЗЗЗе-004 обозначает 3.3333 НМ или 0.00033333. Аналогично можно набирать числа в выражениях. Например, проще набрать 10е9 или 1е10, чем 10 000 000 000, а результат будет тот же самый. Пробел между цифрами и символом е при вводе не допускается, т. к. это приведет к сообщению об ошибке: » 10 е9 ??? 10 е9 I Error: Missing MATLAB operator. Если требуется получить результат вычислений более точно, то следует выбрать на панели Text display в раскрывающемся списке Numeric Fermat значение long Результат будет отображаться в длинном формате с плавающей точкой long с четырнадцатью цифрами после десятичной точки. Форматы short е и 1 ong е предназначены для вывода результата в экспоненциальной форме с четырьмя и пятнадцатью цифрами после десятичной точки соотвег-ственно. Информацию о форматах можно получить, набрав в командной строке команду help с аргументом format: » help format В командном окне появляется описание каждого из форматов Задавать формат вывода можно непосредственно из командной строки при помощи команды format. Например, для установки длинного с плавающей 28 Часть I. Основы работы в MATLAB точкой формата вывода результатов вычислений следует ввести команду fc cmat long е в командной строке: » format long е » 1.25/3.11 ans - 4.019292604501608е-001 Обратите внимание, что команда help format выводит на экран название форматов прописными буквами. Однако команда, которую надо ввести, состоит из строчных букв. К этой особенности встроенной справки help надо привыкнуть. MATLAB различает прописные и сгрочные буквы. Попытка набора команды прописными буквами приведет к ошибке: » FOP'-IAT LONG Е ??? Undefined command/function 'FORMAT*. Для более удобного восприятия результата MATLAB выводит результат вычислении через строку после вычисляемого выражения. Однако иногда бывает удобно разместить больше строк на экране, для чего следует в диалоговом окне Preferences выбрать compact из раскрывающегося списка Numeric display. Добавление пустых строк обеспечивается выбором loose из раскрывающегося списка Numeric display. L Примечание j Все промежуточные вычисления MATLAB производит с двойной точностью, независимо от того, какой формат вывода установлен. Использование элементарных функций Предположим, что требуется вычислить значение следующего выражения: е'25(1п 11.3)03 Jsin 2.45 л + cos 3.78л tg33 Введите в командной строке это выражение в соответствии с правилами MATLAB и нажмите <Enter>. » емр(-2.5)*log(11.3)Л0.3 - 4>sqrt((sin(2.45*pi) + cos(3.78*pi))/tan(3.3)) Глава 1. Простейшие вычисления 29 Отвгт выводится в командное окно: ans = -3.2105 При вводе выражения использованы встроенные функции MATLAB для вычисления экспоненты, натурального логарифма, квадратного корня и тригонометрических функций. В следующем пункте приведены часто употребляемые встроенные математические функции. Аргументы функций заключаются в круглые скобки, имена функций набираются строчными буквами. Для ввода числа л достаточно набрать pi в командной строке. Арифметические операции в MATLAB выполняются- в обычном порядке, свойственном большинству языков программирования: П возведение в степень — Л; П умножение и деление — *, /; □ сложение и вычитание — +, -. Для изменения порядка выполнения арифметических операторов следует использовать круглые скобки. Если теперь требуется вычислить значение выражения, похожего на предыдущее, например -2 5 /. ,, ,.з f sin 2.45л + cos 3.78л )2 е (In 11.3) + --------------------- , I tg 3 3 ) то не обязательно снова набирать его в командной строке. Можно воспользоваться тем, что MATLAB запоминает все вводимые команды. Для повторного занесения их в командную строку служат клавиши <?>, <J->. Вычислите данное выражение, проделав следующие шаги 1. Нажмите клавишу <Т>, при этом в командной строке появится введенное ранее выражение. 2. Внесите в него необходимые изменения, заменив минус на плюс и квадратный корень на возведение в квадрат (для перемещения по строке с выражением служат клавиши <—», <<—>, <Home>, <End>). 3. Вычислите измененное выражение, нажав <Enter>. Получается » ехр(-2.5)*1од(11.3)Л0.3 + ((sin(2,45*pi) + cos(3.78*pi))/tan(3.3))"2 ans _ 121.2446 30 Часть I. Основы работы d МА TLAB Если необходимо получить более точный результат, то следует выполнить команду format long е, затем нажимать клавишу <Т> до тех пор, пока в командной строке не появится требуемое выражение и вычислить его. нажав <Enter>. » format long е » ехр(-2.5).3)Л0.3 - sqrt((sin(2,45*pi) + cos(3.78*pi))/tan(3.3)> ans = -3.210497097863031e+000 Вывести результат последнего найденного выражения в 3pvroM формате возможно без повторного вычисления. Следует изменить формат командой, а затем посмотреть значение переменной ans, набрав ее в командной строке и нажав <Enter>: » format short » ans ans = -3.2105 При вычислениях возможны некоторые исключительные ситуации, например, деление на ноль, которые в большинстве языков программирования приводят к ошибке. При делении положительного числа на ноль в MATLAB получается inf (бесконечность), а при делении отрицательного числа на ноль получается -inf (минус бесконечность) и выдается предупреждение: » 1/0 Warning: Divide by zero, ans = Inf При делении нуля на ноль получается NaN (не число) и также выдается предупреждение: >> 0/0 Warning: Divide by zero. ans = NaN При вычислении, например, V-l никакой ошибки или предупреждения не возникает. MATLAB автоматически переходит в область комплексных чисел: » sqrt(-l.O) ans = 0 + l.OOOOi Гпава I. Простейшие вычисления 31 При наборе комплексных чисел в командной строке MATLAB можно использовать либо i, либо j, а сами числа при умножении, делении и возведении в степень необходимо заключать в круглые скобки: » (2.1 + 3.2i)*2 + (4.2 + 1.71)Л2 ans = 18.9500 + 20.68001 Если не использовать скобки, то умножаться или возводиться в степень будет только мнимая часть и получится неверный результат: » 2.1 + 3.2i*2 + 4.2 + 1.71Л2 ans = 3.4100 4- 6.40001 Для вычисления комплексно-сопряженного числа применяется апостроф, который следует набирать сразу за числом, без пробела: » 2 - 31' ans = 2.0000 + 3.00001 Если необходимо найти комплексно-сопряженное выражение, то исходное выражение должно быть заключено в круглые скобки: » ((3.2 + 1.51)*2 + 4.2 + 7.9i)' ans = 10.6000 - 10.90001 MATLAB позволяет использовать комплексные числа в качестве аргументов встроенных элементарных функций: » sin(2 + 3i) ans = 9.1545 - 4.16891 Как узнать, какие встроенные элементарные функции можно использовать и как их вызывать? Наберите в командной строке команду help eifun, при этом в командное окно выводится список всех встроенных элементарных функций с их кратким описанием. Более подробные сведения можно получить из обширной интерактивной справочной системы, выбрав в меню Help рабочей среды пункт MATLAB Help. Открывается окно справочной системы. В левой части окна на вкладке Contents приведено ее оглавление. Для просмотра содержимого какого-либо раздела в правом окне следует выбрать его название в левом окне при помощи щелчка мыши Знак "+" слева от названия раздела служит для отображения его подразделов Найдите 32 Часть I. Основы работы в MATLAB раздел Functions — Categorical List (Функции по категориям), затем в подразделе Mathematics (Математика) — пункт Elementary Math Перед вами список всех элементарных математических функции, имеющихся в MATLAB (рис. 1.5). Щелчок по гиперссылке с названием функции позволяет получить полную информацию о ней. Для перехода вперед и назад по просмотренным страницам справочной системы используйте кнопки со стрелками. Help File Edit View Go Favorites Deskt.p Wu.dow Help n Help Navigator __ X 0 S M Corterts j index | Surch | Demos | ♦ 0 Release Noles -e Installation t-t 0 MATLAB ф-® Getting Started i±i -<j' Examples < IQ Desktop Tools and Developme +• llj Mathematics i Cl Programming i О Graphics “ t1 j 3-D Visualization 11J Creating Graphical User Interf. Functions - Categorical List t Desktop Tools and Developme i-r-Mathematics Arrays and Matrices Linear Algebra data Analysis and Fourier Polynomials Interpolation and Computal Coordinate System Convet Nonlinear Numerical Methc Specialized Math Sparse Matrices Math Constants !tJ Programming and Data Types rill- Elementary Math Functnns Categorical List (MATLAB Functions} Elementary Math • Trigonometric » Exponential » Complex • Bounding and Remainder Trigonometric acos acosd acosli acot acotd acoth a esc acscd acsch asec a seed asech asirt_ Inverse cosine Inverse cosine degrees Inverse hyperbolic cosine Inverse cotangent Inverse cotangent, degrees Inverse hyperbolic cotangent Inverse cosecant Inverse cosecant, degrees Inverse hyperbolic cosecant Inverse secant Inverse set ant. degrees Inverse hyperbolic secant Inyersesme__________________ Рис. 1.5. Окно интерактивной справочной системы Можно получить быстрый доступ к информации о функции, используя контекстное меню в окне Command Window. Для этого надо выделить имя Гпава 1. Простейшие вычисления 33 функции в ранее набранной команде и, щелкнув правой кнопкой мыши, выбрать в меню пункт Help on Selection. В следующем разделе приведены часто используемые функции. Встроенные элементарные функции Встроенные элементарные функции MA1LAB включают тригонометрические, гиперболические, экспоненциальные и логарифмические функции, а также функции для работы с комплексными числами и для округления различными способами. Тригоно метрические, гиперболические и обратные к ним функции Ниже перечислены встроенные в MATLAB тригонометрические функции и обратные к ним: □ sin, cos, tan, cot —синус, косинус, тангенс и котангенс; О sec, esc —секанс, косеканс (sec(x) = —у—-,csc(x) = —7—7); cos(x) sin(x) □ asin, acos, atan, eject —арксинус, арккосинус, арктангенс и арккотангенс; □ cis&c, acsc зркссканс, арккосеканс. Аргументы тригонометрических функций должны быть выражены в радианах. Обратные тригонометрические функции возвращают результат также в радианах. В MATLAB встроены следующие гиперболические функции и обратные к ним: □ sinh, cosh, tanh, coth — гиперболические синус, косинус, тангенс и котангенс; □ sech, csch — гиперболические секанс и косеканс; □ asinh, acosh, atanh, acoth— гиперболические арксинус, арккосинус, арктангенс и арккотангенс; □ asech, acsch — гиперболические арксеканс и арккосеканс. 34 Часть I. Основы работы в MATLAB Экспоненциальная функция, логарифмы, степенные функции Ниже перечислены названия этих функций в МА TLAB: □ ехр— экспоненциальная функция; □ log — натуральный логарифм; □ logic — десятичный логарифм; □ 1од2 — логарифм по основанию 2; П pow2 — возведение числа 2 в степень: □ sgrt — квадратный корень; □ nexrpow2 — степень, в которую надо возвести число 2, чтобы получить ближайшее число (большее или равное аргументу), например » next-pov;2 (1000) ans = 10 Функции для работы с комплексными числами К ним относятся следующие функции MATLAB: □ abs, angle— модуль г и фаза ф (в радианах от -Л до Л) комплексного числа a + i • b = г • (cosф + i • sin ф); □ complex — конструирует комплексное число по его действительной и мнимой части: >> complex(2.3, 5.8) ans = 2.3000 + 5.8000i □ ccnj —возвращает комплексно-сопряженное число; □ imag, real — мнимая и действительная часть комплексного числа. Округление и остаток от деления Ниже приведены примеры использования этих функций в MATLAB: □ fix — округление до ближайшею целого по направлению к нулю: » fix(l.B) » fix(-1.9) ans 1 ans -I Глава 1. Простейшие вычисления 35 □ floor, ceil -— округление до ближайшего целого по направлению к минус бесконечности или плюс бесконечности; » £1оог(3.2) » ceil(3.2) ans - ans = 3 4 □ round — округление до ближайшего целого: » round(4.1) » round(4.5) ans = ans - 4 5 □ mod— остаток от целочисленного деления (со знаком второго аргумента): » mod (5,2) » mod (5,-2) ans = ans = 1 -1 □ rem — остаток от целочисленного деления (со знаком первого аргумента): » mod(5,2) » mod(5,-2) ans = ans = 1 1 □ sign — знак числа. Примечание В MATLAB имеются встроенные специальные математические функции, такие как: функция Бесселя, полиномы Лежандра ит. д. Подробную информацию с примерами ем. в приложении I. Команда help specfun выдает список специальных функций с кратким описанием. Для более подробной информации требуется набрать в командной строке help и имя функции. В интерактивной справочной системе аналогичные сведения содержит пункт Specialized Math, который находится в подразделе Mathematics раздела Functions — Categorical List. Использование переменных Как и во всех языках программирования, в MATLAB предусмотрена возможность работы с переменными. Причем пользователь не должен заботиться о том, какие значения будет принимать переменная (комплексные, вещественные или только целые). Для того чтобы присвоить, например, пе 36 Часть I. Основы работы в MATLAB ременной z значение 1.45, достаточно написать в командной строке z=i.45, при этом MATLAB сразу же выведет значение z: » z = 1.45 Z = 1.4500 Здесь знак равенства используется в качестве оператора присваивания. Часто не очень удобно после каждого присваивания получать еще и результат Поэтому в MATLAB предусмотрена возможность завершать оператор присваивания точкой с запятой для подавления вывода результата в командное окно. Именем переменной может быть любая последовательность букв и цифр без пробела, начинающаяся с буквы. Строчные и прописные буквы различаются, например, Mz и mz являются двумя разными переменными. Количество воспринимаемых MATLAB символов в имени переменной составляет 63 (такие длинные имена редко бывают нужны). В качестве упражнения на использование переменных найдите значение следующего выражения: sin 1.3 л In3.4 sin 1.3л In 3.4 tg 2.75 th 2.75 tgT75 th 2.75 Наберите последовательность команд, приведенную ниже (обратите внимание на точку с запятой в первых двух операторах присваивания для подавления вывода промежуточных значений на экран) » х = sin(l.3*pi)Zlog(3.4); » у - sqrt(tan(2.75)Ztanh(2.75)); » z = (x + у) Z (x - у) г - 0.0243 - 0.99971 Последний оператор присваивания не завершается точкой с запятой для того, чтобы сразу получить значение исходного выражения. Обратите внимание на то, что все введенные переменные сразу появились в окне Workspace, как показано на рис. 1.6 (в дополнение к стандартной переменной ans, которая использовалась ранее). Конечно, можно было бы ввести всю формулу и получить тот же результат » (sin(1.3*pi)/1од(3.4) + sqrt(tan(2.75)Ztanh(2.75)))I(sin(1.3*pi)I... log(3.4) - sqrt(tan(2.75)/tanh(2.75))) Глава 1. Простейшие вычисления 37 ans = 0.0243 - 0.9997i Рис. 1.6. Рабочая среда MATLAB после вычисления переменных Но обратите внимание, насколько первая запись компактнее и яснее второй! Во втором варианте формула не помещалась в командном окне на одной строке, и пришлось записать ее в две строки, для чего в конце первой строки поставлены три точки. Примечание Для ввода длинных формул или команд в командную строку следует поставить три точки (подряд без пробелов), нажать клавишу <Enter> и продолжить набор формулы на следующей строке. Так можно разместить выражение на нескольких строках. MATLAB вычислит все выргжение или выполнит команду после нажатия на <Enter> в последней строке (в которой нет трех идущих подряд точек). MATLAB запоминает значения всех переменных, определенных во время сеацса работы. Если после ввода примера, приведенного выше, были проде 38 Часть I Основы работы в MATLAB лапы еще какие-либо вычисления, и возникла необходимость вывести значение х, то следует просто набрать х в командной строке и нажать <Enter>: х - -0.6611 Переменные, определенные выше можно использовать и в других формулах. Например, если теперь необходимо вычислить выражение г _______ у sin 1 .Зя /tg 2.75 2 In 3.4 th 2.75 то достаточно ввести следующую команду: » (х - у)''(3/2) ans = -0.8139 + 0.35471 Вызов функции в MATLAB обладает достаточной гибкостью. Например, вычислить е' 5 возможно, вызвав функцию ехр из командной строки: » ехр(3.5) ans = 33.1155 Другой способ состоите использовании оператора присваивания: » t = ехр(3.5) t = 33.1155 Предположим, что часть вычислений с переменными выполнена, а остальные придется доделать во время следующего сеанса работы с MATI АВ. В этом случае понадобится сохранить переменные, определенные в рабочей среде. Сохранение и восстановление рабочей среды Самый простой способ сохранить значения всех переменных— использовать в меню File пункт Save Workspace As. При этом появляется диалоговое окно Save to MAT-File, в котором следует указать каталог и имя файла. Предлагается сохранить файл в текущем каталоге (по умолчанию в подкаталоге work основного каталога MATLAB). Оставьте пока этот каталог. Гпава 1. Простейшие вычисления 39 В дальнейшем будет объяснено, как устанавливать пути к каталогам в MATLAB для поиска файлов. Удобно давать файлам имена, содержащие дату работы, например, work20-01-04. Выполните Save (Сохранять). МАП АВ сохранит результаты работы в файле work20-01-04.mat. Теперь можно закрыть MATLAB одним из следующих способов: □ выбрать в меню File пункт Exit MATLAB; □ нажать клавиши <Ctrl>+<Q>; □ набрать команду exit в командной строке и нажать <Enter>; □ нажать на кнопку закрытия окна MATLAB в правом верхнем углу его заголовка. Примечание Переменные в файлах с расширением mat хранятся в двоичном виде. Просмотр этих файлов в любом текстовом редакторе не даст никакой информации о переменных и их значениях. В следующем сеансе работы для восстановления значений переменных следует открыть файл work20-01-04.mat при помощи подпункта Open меню File. Теперь все переменные, определенные в прошлом сеансе, стали доступными. Их можно использовать во вновь вводимых командах. Сохранить и восстановить переменные среды можно также с помощью кнопок Load data file и Save на панели инструментов окна Workspace. Для скрытия или отображения панели инструментов окна надо вызвать контекстное меню, щелкнув правой кнопкой на заголовке. При восстановлении переменных после выбора файла для их загрузки возникает диалоговое окно, изображенное на рис. 1.7, позволяющее просмотреть значения переменных и отметить флагами те, которые следует загрузить. Можно сохранить значения одной или нескольких переменных. Для этого выберите переменную, щелкнув мышью по ее имени в окне Workspace. Для выбора нескольких переменных используйте стандартную комбинацию Windows — щелчок левой кнопкой мыши с удержанием клавиш <CtrI> или <Shift>. Затем на выделении сделайте правый щелчок мышью и выберите пункт Save As в контекстном меню. Открывается диалоговое окно Save to MAT-File, в котором следует выбрать имя файла. Обратите внимание, что созданный файл появился в окне Current Directory. Двойной щелчок мышью в этом окне по строке с именем файла приводит к восстановлению записанных в него переменных в рабочей среде. 40 Часть I. Основы работы < MATLAB Рис. 1.7. Диалоговое окно для восстановления переменных среды Workspace Сохранение всех переменных и восстановление рабочей среды можно выполнить и из командной строки. Для этого служат команды save и load. В конце сеанса работы с MATLAB необходимо выполнить команду » save work20-01-04 Расширение можно не указывать, MATLAB сохранит переменные рабочей среды в файле work20-01-04.mat. В начале следующего сеанса работы для считывания переменных следует ввести команду » load work20-01-04 Более подробные сведения о командах save и load можно получить, набрав в командной строке help save или help load. В интерактивной справочной системе вся информация об этих командах находится в пункте Opening, Loading, Saving Files подраздела File I/O раздела Functions — Categorical List. В MATLAB имеется возможность записывать исполняемые команды и результаты в текстовый файл (вести журнал работы), который потом можно легко прочитать или распечатать из текстового редактора. Для начала ведения журнала служит команда diary. В качестве аргумента команды diary Глава 1. Простейшие вычисления 41 следует задать имя файла, в котором будет храниться журнал работы. Набираемые далее команды и результаты их исполнения будут записываться в этот файл, например, последовательность команд » diary d20-01-04.txt » al - 3,- » а2 - 2.5; » аЗ - al + а2 >> аЗ = » 5.5000 » save work20-01-04 » quit производит следующие действия: 1. Открывает файл d20-01 -04.txt. 2. Производит вычисления. 3. С охраняет переменные в двоичном файле work20-0 l-04.mat. 4. Сохраняет на диске в подкаталоге work корневого каталога MATLAB журнал работы в файле d20-0l-04.txt и закрывает MATLAB. Посмотрите содержимое файла d20-01-04.txt в каком-нибудь текстовом редакторе, например, в стандартной программе Windows Блокнот (Notepad) В файле окажется следующий текст: al = 3; а2 = 2.5,- аЗ - al + а2 аЗ = 5.5000 save work20-01-04 quit Запустите снова MATLAB и восстановите значения введенных переменных, которые хранятся в файле work20-0l-04.mat, при помощи любого из описанных в начале этого раздела способов: команды load, или пункта Орел меню File рабочей среды, или окна Current Directory. Изучим возможность просмотра переменных, определенных в рабочей среде. 42 Часть I, Основы р-г< оты в MATLA8 Просмотр и удаление переменных, выбор имен переменных При работе с достаточно большим количеством переменных необходимо знать имена использованных переменных. Самый простой способ — воспользоваться окном Workspace, в котором находятся имена всех существующих в рабочей среде переменных. По умолчанию все переменные в списке расположены в алфавитном порядке. Щелчок мышью по заголовку столбца Name меняет порядок на обратный. Аналогично можно упорядочивать переменные по размеру занимаемой памяти и типу. Введите кроме вещественных переменных комплексную и проверьте результат упорядочивания по разным критериям. Двойной щелчок по строке с переменной в окне Workspace (или нажатие на кнопку Open панели инструментов окна Workspace) приводит к отображению ее содержимого в отдельном окне Array Editor, что, как следует из его названия (редактор массивов), будет особенно полезно при работе с массивами, которым посвящена гдтИва 2. В окне редактора массивов можно изменять значение элементов массива, добавить новые элементы или удалить существующие. Изменение формата вывода чисел осуществляется через меню Preferences в раскрывающемся списке Numeric format так, как было объяснено ранее. Подчеркнем еще раз, что все данные в MATLAB представляются в виде массивов, мы пока работаем с массивами из одной ячейки размера 1 на 1 (работа с массивами большей размерности подробно описана в главе 2). Вернемся в окно Workspace. Кроме сохранения и восстановления рабочей среды, окно Workspace позволяет удалять переменные. Для удаления необходимо выделить одну или несколько переменных при помощи мыши и клавиш <Ctrl> пли <Shift>. нажать кнопку Delete и подтвердить удаление в появляющемся диалоговом окне Confirm Delete. Аналогичные возможности предоставляют команды и функции MATLAB, предназначенные для оперирования с рабочей средой. Их описание содержится в разделе Functions — Categorical List (раздела Desktop Tools and Development, пункт Workspace, File, and Search Path) справочной системы Остановимся на некоторых из них. Для вывода в командное окно имен используемых переменных служит команда who >> who Your variables are: 31 a2 a3 Глава 1. Простейшие вычисления 43 Команда whos позволяет получить более подробную информацию о переменных в виде таблицы, аналогичной таблице окна Workspace: » whos Kame Size Bytes Class al lxl 8 double array a2 lxl 8 double array a3 lxl 8 double array Grand total is 3 elements using 24 bytes Кроме того, команда whos дает возможность узнать общий объем памяти, занимаемой всеми переменными рабочей среды. В нашем примере три переменные занимают 24 байта, о чем сказано в строке под таблицей. Для освобождения из памяти всех переменных используется команда clear. Если в аргументах указать список переменных (через пробел), то только они будут освобождены из памяти, например: » clear al аЗ » who Your variables are: a2 Очень полезной оказывается функция exist, которая сообщает, занято ли имя переменной в MATLAB. При вводе новой переменной следует не только убедиться в том, что это имя еще не занято под переменную пользователя, но и быть уверенным, что оно не используется в MATLAB (например, как встроенная функция или зарезервированное слово языка программирования). Вот простой пример. Запишем в переменную pi значение синуса от 3: » pi = sin(3) pi = 0.1411 Теперь посчитайте cos от л » z = cos(pi) z = 0.9901 Вычисления выполнены неверно, поскольку изменена системная константа pi. До тех пор пока значение pi не будет удалено из рабочей среды, воспользоваться константой л не удастся. Поэтому перед определением новой 44 Часть I. Основы работы в MATLAB переменной желательно вызвать функцию exist, указав имя переменной в апострофах во входном аргументе, например: » exist(‘d71) ans - О Если ответ— ноль, то имя этой переменной не конфликтует с зарезервированными словами MATLAB, и ей можно пользоваться. Сравните: exist ('max'), exist ('for'), existCpi1), exist ('fzero ‘- Значение, возвращаемое функцией exist, определяется тем, подо что занято запрашиваемое имя. В частности, если возвращается I, то такая переменная уже определена в рабочей среде. Смысл всех значений объяснен в справочной системе. Эффективная работа из командной строки (Command History) В рабочей среде MATLAB для вызова ранее введенных команд имеется дополнительное удобное средство — окно Command History с историей команд (см. рис. 1.1) История команд представляет собой запись команд всех проведенных сеансов работы с MATLAB, которые автоматически сохраняются в текстовом файле history.m. В начале протокола работы каждого сеанса отмечены время и дата его начала. Можно отключить запись вводимых команд в историю команд. Для настройки возможностей окна Command History выберите пункт Preferences в меню File рабочей среды. Открывается диалоговое окно Preferences. Выбор пункта Command History в левой половине окна приводит к отображению свойств окна истории команд (Command History Preferences) в правой половине окна Preferences Элементы управления расположены на двух панелях: Settings и Saving. В случае, если вы предполагаете использовать историю команд предыдущих сеансов работы, есть смысл обратить внимание на два значения перекэючателя. Одно из них: Save history file on quit, т. e. сохранение истории команд перед завершением сеанса работы с пакетом. Следует иметь в виду, что в случае аварий ного завершения работы история команд не запишется в файл history.m и, следовательно, введенные команды будут недоступны в следующем сеансе работы. Наиболее безопасный способ состоит в установке количества выполненных команд, после которого произойдет обновление файла history.m (Save after... commands). Например, значение 1 гарантирует, что ни одна ко Глава I. Простейшие вычисления 45 манда, кроме, быть может, последней не будет потеряна. Смысл остальных флаюв и переключателей ясен из их названия. При загрузке MATLAB окно Command History появляется на экране по умолчанию. Чтобы закрыть его, нужно в меню Desktop выбрать пункт Command History или нажать кнопку закрытия окна в самом окне Command History. Повторный выбор пункта Command History приводит к появлению одноименного окна в рабочей среде. История команд делает работу пользователя более эффективной, избавляя от необходимости вновь набирать введенные ранее команды. Если щелкнуть на какой-либо команде в окне левой кнопкой мыши, то данная команда становится текущей. Текущая команда в окне подсвечена синим. Для ее выполнения надо применить двойной щелчок мыши. Аналогичного результата можно добиться в окне Command History при помощи клавиш <Т>, <Х> и <Enter>. Лишнюю команду можно убрать из окна. Для этого ее надо сделать текущей и удалить при помощи клавиши <Delete>. Можно выделить несколько идущих подряд команд (рис. 1.8 — выделено пять команд) с использованием комбинации клавиш <Shift>+<T>, <Shift>+<J-> и выполнить их при помощи <Enter>, или удалить клавишей <Delete>. Command History ? X 100000/3 — 1/3000 FORMAT LONG E L -- exp (-2.5)*109(11.3)A0.3-sqrt((sin(2.45*pi)+C03(3.78*p e xp (- 2.5) * log (ГИЗ) “ I3 •78 * P Ч ) Г [format long e exp(-2.5)*log(11.3) format short Cut Ctrln-X 1) +C03 (3.78s Delete Selection Delete jel₽ctio' Clear Entire History teM-FL Create Shortcut Profile Соме Evaluate Selection —x = sin(1.3*pi)/log —у = sqrt(tan(2.75)/ —2 = (Х+У) / (X-y) Рис. 1.8. Окно Command History с группой выделенных команд и контекстным меню Выделение последовательно идущих команд можно производить левой кнопкой мыши с одновременным удерживанием клавиши <Shift>. Если команды не идут одна за другой, то для их выделения следует использовать 46 Часть I. Основы работы в MATLAB левую кнопку мыши с удерживанием клавиши <Ctrl>. Выделенную команду или команды можно перетащить (Drag and Drop) в окно Command Window, отредактировать (если требуется) и затем выполнить, нажав клавишу <Enter>. При щелчке правой кнопкой мыши по области окна Command History появляется всплывающее мгню. Пункт Cut служит для удаления выделенной команды или группы команд. Выбор пункта ( ору приводит к копированию выделенной команды или целой группы в буфер Windows. При помощи Evaluate Selection можно выполнить отмеченную группу команд. Для удаления текущей команды или группы команд предназначен пункт Delete Selection, для удаления всех команд до текущей — Delete to Selection, для удаления всех команд — Clear Entire History. Можно также скопировать или вырезать команды с помощью пунктов Сору и Cut меню Edit рабочей сре^ы. Скопированные команды можно поместить в командное окно, отредактировать их если требуется, а затем запустить, нажав клавишу <Enter>. Пункт Create M-File всплывающего меню позволяет создать файл-программу, содержащую выделенные команды (работе с файл-программами посвящена глава 5). Для запуска группы часто используемых команд удобно создать ярлык (shotcut), который будет размещен на отдельной панели рабочей среды. Щелчок мышью по ярлыку приводит к выполнению команд этой группы. Для создания ярлыка с использованием Command History следует выделить группу команд и выбрать в контекстном меню пункт Create Shortcut. Открывается окно редактора ярлыков, изображенное на рис. 1.9; его поле Callback содержит выделенные команды, которые можно отредактировать или добавить новые. Наберите в поле Label имя ярлыка, выберите в раскрывающемся списке Category значение Toolbar Shortcut и нажмите кнопку Save. Вы создали ярлык для выполнения связанных с ним команд, который автоматически разместился на панели ярлыков Shortcuts Toolbar. В дальнейшем ярлык и связанные с ним команды можно редактировать, если вызвать контекстное меню для ярлыка, которое показано на рис 1.10. С помощью этого же меню можно создать новый ярлык (New Shortcut) без использования окна истории команд. Ярлык можно разместить не только на панели ярлыков, выбрав другие значения поля Category (рис. 1.9) при его создании. Доступ ко всем ярлыкам осуществляется также через пункт Shortcuts всплывающет о меню, которое появляется при нажатии на кнопку Start (см. рис. 1.2) Если требующиеся команды не видны в окне Command History, то их можно попытаться найти, используя пункт Find в меню Edit. Откроется диалоговое окно Find (рис. 1.11). Глава 1. Простейшие вычислении 47 Рис. 1.9. Диалоговое окно Shortcut Editor Рис. 1.10. Размещение ярлыка в окне MATLAB и его кошекстное меню 48 Часть I. Основы работы в MATlAB Рис. 1.11. Диалоговое окно Find окна Command History. В поле Find what диалогового окна Find введите требуемую команду или ее часть, задайте направление поиска нажатием кнопок Previous (Предшествующая) или Next (Следующая) и условия поиска с помощью флагов: Match case (Поиск с учетом регистра). Whole word (Строгое совпадение). Wrap around (При достижении конца файла возобновить поиск с начала файла). Поиск осуществляется от текущей команды. Умение работать в командной строке MATLAB понадобится вам при чтении всей книги. Поэтому в следующих трех главах все примеры предполагают использование командного окна. В главе 5 объяснено создание собственных программ и функций, которые делают работу в MATLAB более эффективной. Однако практика показывает, что командная строка оказывается полезной даже достаточно опытным пользователям MATLAB, например, для быстрого получения справочной информации, независимой проверки и тестирования отдельных операторов программы. Кроме того, собственные программы и функции вызываются именно из командной строки. При возникновении затруднений обращайтесь снова к этой главе. Задания для самостоятельной работы Задайте переменные х и у и вычислит^ значения арифметических выражений. Выведите результат в различных форматах и сохраните полученные значения в файле. Гпава 1. Простейшие вычисления 49 Т = f • * 4 (siny + sin2y+ sm3y) + sin у + sin 2y sin 3y l + ev ' sin у + sin 2 у + sin 3y 1 + ед 3. f W= 1 + In у x+tgy J 4. R - sh Л - ch Г(х + In у)л/|х - In _y| ^|x~lnv| L 5. 5/cos2y + sin4y + Vev +e v (ex + e-x) (cos2y + sin4.v-2)“ 7. S arctg, x—sin у .r+ sin у л + siny x-siny । e( v-sin y)(x+sin у) 1 + arcsin (cos 2y) Г 2A + 3 л -1 Y 2х + 3“A‘ 1 + arcsin (cos 2y ) Глава 2 Работа с массивами Все данные МАП,АВ представляет в виде массивов. Очень важно правильно понять, как использовать массивы. Без этого невозможна эффективная работа в MATLAB, в частности; построение графиков, решение задач линейной алгебры, статистики, обработки данных и многих других. В этой главе подробно описаны вычисления с векторами и матрицами. Даже если вы знакомы с каким-либо языком программирования, все равно лучше прочесть эту главу, поскольку MATI.AB предоставляет пользователю обширные возможности для работы с массивами данных. Следующий раздел посвящен необходимым сведениям, касающимся массивов. Основные определения и соглашения Что такое массив, должно быть известно каждому, кто хоть немного занимался программированием. Массив— упорядоченная, пронумерованная совокупность однородных данных. У массива должно быть имя. Массивы различаются по числу размерностей или измерений: одномерные, двумерные, многомерные. Размером массива называют число элементов вдоль каждого из измерений. Доступ к элементам осуществляется при помощи индекса. В MATLAB нумерация элементов массивов начинается с единицы. Это значит, что индексы должны бычъ больше или равны единице. Важно понять, что вектор, вектор-строка, матрица или тензор явялются математическими объектами, а одномерные, двумерные или многомерные массивы — способы хранения этих объектов в компьютере. Всюду дальше в книге будут использоваться слова вектор и матрица, если больший интерес представляет сам объект, чем способ ею хранения. Вектор может быть записан в столбик (вектор-столбец) и в строку (век тор-строка). Вектор-столбцы и вектор-строки часто будут называться просто векторами, различие будет сделано в случаях, когда важен способ хранения вектора в MATLAB. Векторы и матрицы обозначаются курсивом, а соответствующие Гпава 2. Работа с массивами 51 им массивы прямым шрифтом "Courier", например: "вектор а содержится в массиве а", "запишите матрицу R в массив и". Вектор-столбцы и вектор-строки Ввод, сложение и вычитание векторов Работу с массивами начнем с простого примера— вычисления суммы векторов (1.3 А (7.1А (i= 5.4 Ь= 3.5 8.2 Для хранения векторов используйте массивы а и ь. Введите массив а в командной строке, используя квадратные скобки и разделяя элементы вектор-столбца точкой с запятой: » а = (1.3; 5.4; 6.9] а = 1.3000 5.4000 6.9000 В главе I было сказано, что точка с запятой в конце выражения используется для подавления вывода результата на экран. Оказывается, что этот символ предназначен и для разделения элементов век юр-столбцов. Так как введенное выражение не завершено точкой с запятой, то МА ГЬАВ автоматически вывела значение переменной а. Введите теперь второй вектор, подавив вывод на экран » Ь = [7.1; 3.5; 8.2J; Для нахождения суммы векторов используется знак +. Вычислите сумму, запишите результат в массив с и выведите его элементы в командное окно: » с _ а + b с - В.4000 8.9000 15.1000 3 Заг 130 52 Часть I. Основы работы & MATLAB Просмотрите появившуюся в окне Workspace информацию. Векторы a , b и с хранятся в двумерных массивах. В столбце Size указано 3x1, т. е. массивы имеют по три строки и одному столбцу, каждый из них занимает 24 байта памяти (столбец Bytesj. Аналогичные сведения можно получить при помощи встроенных функций ndinis И size: » па = ndins(a) па = 2 » sa = size(а) sa = 3 1 На первый взгляд может показаться, что ndims и size лишь дублируют информацию окна Workspace. Однако они позволяют не только вывести характеристики массивов в командное окно, но и записать их в переменные для дальнейшего использования, что существенно при создании собственных приложений в MATLAB. В главе J было замечено, что числа в MATLAB представляются в виде двумерного массива один на один. Теперь должно быть понятно, почему при сложении векторов используется тот же знак плюс, что и для сложения чисел. Естественно, для нахождения разности векторов следует применять знак минус, с умножением дело обстоит несколько сложнее. Если размеры векторов, к которым применяется сложение или вычитание, не совпадают, то выдается сообщение об ошибке. Особенность MATLAB представлять все данные в виде массивов является очень удобной. Пусть, например, требуется вычислить значение функции sin сразу для всех элементов вектора с (который хранится в массиве с) и записат ь результат в вектор d. Используйте следующий оператор присваивания >> d - sin(c) d = 0.В546 0.5010 0.5712 Гпава 2. Работа с массивами 53 Итак, встроенные в MATLAB элементарные функции приспосабливаются к виду аргументов; если аргумент является массивом, то результат функции будет массивом того же размера, но с элементами, равными значению функции от соответствующих элементов исходного массива. Убедитесь в этом еще на одном примере. Если необходимо найти квадратный корень из элементов вектора d со знаком минус, то достаточно записать: » sqrt(-d) ans - О + 0.9244i О + 0.7078i О + 0.75581 Оператор присваивания не использовался, поэтому MATLAB записала отвез в стандартную переменную ans. Ввод вектор-строки осуществляется в квадратных скобках, однако в отличие от вектор-столбца элементы следует разделять пробелами или запятыми. Операции сложения, вычитания и вычисление элементарных функций от вектор-строк производятся так же, как и с вектор-столбцами, в результате получается вектор-строка того же размера, что и исходные. » si = [349 2] S1 = 3 4 9 2 » s2 = [5 3 3 2] s2 = 5 3 3 2 » s3 = si + s2 s3 = 8 7 12 4 » s4 = log(s3) s4 = 2.0794 1.9459 2.4849 1.3863 Выясните, в каких массивах хранятся вектор-строки. Для этого можно использовать окно Workspace или функции ndims, size и команду иЬой: » whos Name Size Bytes Class 51 1x4 32 double array s2 1x4 32 double array s3 1x4 32 double array S4 1x4 32 double array 54 Часть I Основы работы в Л,'Д TLAB Итак, вектор-строки si, s2, s3 и s4 содержатся в двумерных массивах размерности один на четыре. Для определения длины вектор-столбцов или век-тор-строк служит встроенная функция length: » L = length(sl) L = 4 По умолчанию все числа (элементы массивов) хранятся с двойной точностью (double) и занимают 8 байтов. Большие массивы требуют для хранения значительных объемов памяти. Для уменьшения объема занимаемой массивами памяти можно применять другие способы хранения элементов массива: single для вещественных чисел, требующих для размещения 4 байта, и ints, intl6, int32 — для целых чисел, занимающих 1, 2 или 4 байта соответственно. Использование таких данных значительно экономит память и не влияет на функциональные возможности пакета MATLAB. Для изменения точности представления чисел предназначены одноименные с типом (Class) данных функций single, int8, intl6, int32: » q4 = single(s4); >> q3 = int32(s3) ; >> q2 = intl6(s2); » ql = int8(sl); Если теперь посмотреть распределение памяти под массивы, то легко заметить существенную разницу в отведенной для хранения памяти- » whos Name Size Bytes Class ql 1x4 4 int8 array q2 1x4 8 inti6 array q3 1x4 16 int32 array q4 1x4 16 single array sl 1x4 32 double array s2 1x4 32 double array s3 1x4 32 double array s4 1x4 32 double array Для массивов большой размерности экономия памяти может быть существенной. Выполнение арифметических операций с вещественными числами разного типа допустимо и дает результат с наименьшей точностью — single: » qs44 = q4 + s4 >> whos qs44 Гпава 2. Работа с массивами 55 Kame Size Bytes Class qs44 1x4 16 single array Попытка выполнить арифметические операции над целыми числами разных типов приводит к ошибке: » q31 — q3 + ql ??? Error using ==> plus Integers can only be combined with integers of the same class, or scalar doubles. Ьолее того, при преобразовании целого числа, когда для точного представления не хватает отводимой памяти, получается максимальное число для данного типа (т. е. неверный результат) без предупреждения об этом: » wl = 34567; » rl = int8(wl) Г1 = 127 » tl = int!6(wl) tl = 32767 Поэтому применение целых чисел, имеющих меньшую точность представления, ограничено. Вернемся к работе с векторами и матрицами, используя принятое по умолчанию представление чисел double. Из нескольких вектор-столбцов можно составить один, используя квадратные скобки и разделяя исходные вектор-столб цы точкой с запятой: » vl = [1; 2]; » v2 - [3; 4; 5]; » v = {vl; v2] v = 1 2 3 4 5 Для сцепления вектор-строк также применяются квадратные скобки, но сцепляемые вектор-строки отделяются пробелами или запятыми: » vl = [pi pi/2]; » v2 = [pi/3 pi/4 pi/5]; 56 Часть I, Основы работы в MATLAB » v = [vl v2] v = 3.1416 1.5706 1.0472 0.7854 0.6283 Запоминать правила сцепления вектор-строк и вектор-столбцов не требуется, достаточно посмотреть на вектор-строку v как на блочную строку. Элементы этой блочной строки, т. е. вектор-строки vl и v2, разделены пробелом в соответствии с правилом набора вектор-строк. Аналогичное рассуждение верно и для сцепления вектор-столбцов. Для просмотра и изменения значений элементов массивов удобно использовать редактор массивов (Array Editor). Дважды щелкните мышью по имени массива v в окне Workspace или нажмите кнопку Open Selection на панели инструментов окна Workspace при положении курсора на имени массива — откроется окно редактора массивов с содержимым вектор-строки v (рис. 2.1). И мя просматриваемого массива указано в строке заголовка окна. Рис. 2.1 Окно редакюра массивов Array Editor Двойной щелчок мышью по ячейке или нажатие клавиши <F2> (как и в таблицах MS Excel) позволяет редактировать содержимое соответствующего элемента массива. Убедитесь в этом, изменяя значения элементов и выводя массив в командное окно. При заполнении пустых клеток изменяются размеры массива так, что он остается прямоугольным наименьшей размерности и содержит все определенные элементы. При этом не определенные пользователем элементы приобретают нулевое значение. Для уменьшения размеров следует использовать элемент управления Delete (в контекстном Гпава 2. Работа с массивами 57 или оконном меню или на панели инструментов), а не Cut, который приводит лишь к обнулению элементов массива. Для работы с данными редактор массивов MATLAB предоставляет возможности, аналогичные MS Excel, Увеличьте длину вектор-строки v до 10, для чего выделите первые Пять ее элементов, скопируйте их при помощи всплывающего меню (или кнопки Сору панели инструментов, или одноименного пункта меню Edit), сделайте текущей шестую ячейку и используйте вставку (Paste) для дублирования первых пяти элементов вектор-строки. Проверьте при помощи командного окна изменился ли вектор v. Редактор массивов позволяет просматривать значения нескольких переменных. Двойной щелчок по строке с vl в окне Workspace приводит к появлению нового окна в редакторе массивов. Каждое из окон можно сделать активным при помощи соответствующей вкладки внизу окна редактора или выбрав его название в меню Window. Кнопки в правой части панели инструментов соответствуют различным способам расположения таблиц с содержимым массивов в окне редактора Array Editor. Также редакзор массивов оказывается очень полезным при отладке собственных программ (отладке программ посвящен разд. "Диалоговая отладка программ" главы 8). Обращение к элементам вектора Доступ к элементам вектора или вектор-строки осуществляется при помощи индекса, заключаемого в круглые скобки после имени массива, в котором хранится вектор. Если среди переменных рабочей среды есть массив v, определенный вектор-строкой » v = [1.3 3.6 7.4 8.2 0.9]; то для обращения, например, к четвертому элементу используется индексация: » И = v(4) И = 8.2000 Указание элемента массива в левой части оператора присваивания приводит к изменению в массиве » v(2) = 555 v - 1.3000 555.0000 7.4000 8.2000 0.9000 58 Часть I. Основы работы в MATLAB Из элементов массива можно формировать новые массивы, например: » u = [v(3); v(2); v(l)] u = 7.4000 555.0000 1,3000 Для помещения определенных элементов вектора в другой вектор в заданном порядке служит индексация при помощи вектора. Например, запись в вектор-строку w четвертого, второго и пятого элементов v производится следующим образом: » ind = [425]; » w = v(ind) w = В.2000 555.0000 0.9000 MATLAB предоставляет удобный способ обращения к блокам последовательно расположенных элементов вектора или вектор-строки. Для этого служит индексация при помощи знака двоеточия. Предположим, что в заданной вектор-строке w из семи элементов требуется заменить нулями элементы со второго по шестой. Индексация при помощи двоеточия позволяет просто и наглядно решить поставленную задачу: » w = [0.1 2.9 3.3 5.1 2.6 7.1 9.8]; » w(2:6} = 0; » w W = 0.1000 00 000 9.8000 Присваивание w(2:6) = о эквивалентно последовательности команд w(2) = 0; и(3) = 0; w(4) = 0; w(5) = 0; w(6) = 0. Индексация при помощи двоеточия оказывается удобной при выделении части из большого объема данных в новый массив: » w = [0.1 2.9 3.3 5.1 2.6 7.1 9.8]; » wl = w (3:5) wl — 3.3000 5.1000 2.6000 Составьте вектор-строку w2, содержащую элементы w кроме четвертого. Используйте двоеточие и сцепление строк: » w2 = [w(l:3] w[5:7)] Глава 2. Работа с массивами 59 ы2 = 0.1000 2.9000 3.3000 2.6000 7.1000 9.8000 Вместо w(5:7) можно написать и(5:end). Такая запись означает, что берутся элементы, начиная с пятого и заканчивая пос. 1едним. Вели же ввести просто w (end), то получим последний элемент массива: >> w(end) ans “ 9.8000 Еще один способ индексирования — логическое индексирование — описан в разд. '‘Логическое индексирование" данной главы. Элементы массива могут входить в выражения. Вычисление, например, среднего ieoметрического из элементов вектора и можно проделать следующим образом: » gm = (u(l) *u(2) *u(3)) Л (1/3) girt = 17.4779 Конечно, этот способ не очень удобен для длинных массивов. Для того чтобы найти среднее геометрическое, необходимо набрать в формуле все элементы массива. В MATLAB существует достаточно много специальных функций, облегчающих подобные вычисления. оименение функций обработки данных к векторам Перемножение элементов вектор-столбца или вектор-строки осуществляется при помощи функции prod: » z = [3,- 2; 1; 4; 6; 5] ; » р = prod(z) Р = 720 ' Зная об этой функции, несложно догадаться, как просто найти среднее геометрическое элементов вектора z: » gm = prod(z)^(l/length(z)) gm - 2.9938 60 Часть I. Основы работы в MATLAB Функция sum предназначена для суммирования элементов вектора Попробуйте самостоятельно вычислить среднее арифметическое элементов вектора z. Проверьте результат, вычислив среднее арифметическое, используя встроенную функцию mean. Вот что должно получиться: » sum(z)/length(z) ans = 3.5000 >> mean(z) ans = 3.5000 ‘ Для нахождения минимума и максимума из элементов вектора служат встроенные функции min и max: » М = max(z) м = б » m = min(z> m = 1 При обращении к функции min с двумя векторами в качестве входных аргументов получится вектор, каждый элемент которого есть минимум из двух элементов исходных векторов с одинаковыми номерами. » р = [3 12 8] ; » S = [4 10 7] ; » min(p, s) ans = 3 10 7 Часто необходимо знать не только значение минимального или максимального элемента в массиве, но и его индекс (порядковый номер). Вы уже видели, что интерфейс функций MATLAB достаточно универсален — большинство из них допускают обращение к ним с переменным числом входных и выходных аргументов. Вызовите функцию min с двумя выходными аргументами: » Im, k] - min(z) m — 1 к = 3 ( пава 2. Работа с массивами 61 В результате переменной m будет присвоено значение минимального элемента массива z, а номер минимально! о элемента занесен в переменную к. Как же узнать, как именно можно вызывать функцию. Для быстрого получения подсказки следует набрать в командной строке help и через пробел имя функции. MATLAB выведет в командное окно всевозможные способы обращения к функции с дополнительными пояснениями. Аналогичные сведения можно найти в интерактивной справочной системе, которой вы уже пользовались при чтении главы 1. Если известно имя функции, то проще всего воспользоваться индексным поиском (вкладка Index в левой части окна справочной системы MATLAB). В строке ввода Search index for: следует набрать имя функции, например, min, затем в левом окне выбрат ь раздел MATLAB и ознакомиться с содержимым правого окна. Информация обо всех функциях MATLAB для работы с векторными и матричными данными содержится в пункте Arrays and Matrices подраздела Mathematics раздела Functions — Categorical List (вкладка Contents). В число основных функций для работы с векторами входит функция упорядочения вектора по возрастанию его элементов sort. » г = [9.4 -2.3 -5.2 7.1 0.8 1.3]; » R = sort(г) R = -5.2000 -2.3000 0.8000 1.3000 7.2000 9.4000 Попробуйте упорядочить вектор по убыванию, используя эту же функцию sort. Правильный ответ: » R1 = -sort{-г) R1 = 9.4000 7.1000 1.3000 0.8000 -2.3000 -5.2000 Упорядочение элементов в порядке возрастания их модулей производится с привлечением вышеописанной функции abs: » R2 = sort(abs(г)) R2 - 0.8000 1.3000 2.3000 5.2000 7.1000 9.4000 Вызов sort с двумя выходными аргументами приводит к образованию массива индексов соответствия элементов упорядоченного и исходного массивов: » [rs, ind] = sort(г) rs = -5.2000 -2.3000 0.8000 1.3000 7.1000 9.4000 62 Часть I. Основы работы в MATLAB ind = 3 2 5 6 4 1 Равенство r(ind(k)) - rs(k) для к от 1 до length(r) связывает исходный массив г, упорядоченный rs и массив индексов ind. Если аргументом функций max и min является вектор, состоящий из комплексных чисел, то результатом является максимальный или минимальный по модулю элемент. Функция sort также упорядочивает комплексный вектор по модулю, а компоненты с равными модулями располагаются в порядке возрастания фаз. В число встроенных функций входят: дискретное преобразование Фурье — fft, свертка — conv, работа со звуком — sound и многие другие. Подробно о них написано в приложении 1. Самостоятельно о функциях обработки данных можно узнать, набрав в командной строке команду help data fun или обратившись к пункту Data Analysis and Fourier Transforms подраздела Mathematics раздела Functions — Categorical List интерактивной справочной системы MATLAB. В последующих разделал описано применение функций обработки данных к матричным данным. Примечание Дополнительные функции содержатся в специализированных Toolbox. Команда help stats выводит в командное окно список статистических функций, доступных в MATLAB, если установка MATLAB включает Statistics Toolbox. Более подробную информацию можно почерпнуть из раздела Statistics Toolbox интерактивной справочной системы. Поэлементные операции с векторами В предыдущих разделах вектор использовался в качестве аргумента математических функций, результатом которых являлся вектор с элементами, равными значениям функции от соответствующих элементов исходного вектора. Таким образом, происходило поэлементное вычисление вызываемой функции. В этом разделе подробно описаны возможности поэлементной работы с векторами, которые понадобятся в дальнейшем, в частности, для определения собственных функций и построения их графиков. Введите две вектор-строки: » vl = [2 -3 fl 1]; » v2 = |7 5 -6 9] ; Гпава 2, Работа с массивами 63 Операция . * (не вставляете пробел между точкой и звездочкой!) приводит к поэлементному умножению векторов одинаковой длины. В результате получается вектор с элементами, равными произведению соответствующих элементов исходных векторов: » u = vl.*v2 и “ 14 -15 -24 9 При помощи .Л осуществляется поэлементное возведение в степень: » р = vl.'"’2 р = 4 9 16 1 Показателем степени может быть вектор той же длины, что и возводимый в степень При этом каждый элемент первого вектора возводится в степень, равную соответствующему элементу второго вектора: » Р = vl.Av2 Р = 126.0000 -243.0000 0.0002 1.0000 Деление соответствующих элементов векторов одинаковой длины выполняется с использованием . / » d = vl. /v2 d = 0.2657 -0.6000 -0.6667 0.1111 Обратное поэлементное деление (деление элементов второго вектора на соответствующие элементы первого) осуществляется при помощи . » dinv = vl.v2 dinv = 3.5000 -1.6667 -1.5000 9.0000 Итак, точка в MATLAB используется не только для ввода десятичных дробей, но и для указания того, что деление или умножение массивов одинакового размера должно быть выполнено поэлементно. К поэлементным относятся и операции с вектором и числом. Сложение вектора и числа не приводит к сообщению об ошибке. MATI АВ прибавляет число к каждому элементу вектс ра. То же самое справедливо и для вычитания: » v = [4 6 8 10] ; » s = v + 1.2 64 Часть I. Основы работы в MATLAB s -5.2000 7.2000 9.2000 11.2000 » sl = 1.2 + v sl = 5.2000 7.2000 9.2000 11.2000 » г - 1.2 — v -2.8000 -4.8000 -6.8000 -8.8000 » rl = v — 1.2 rl = 2.8000 4.8000 6.8000 8.8000 Умножать вектор на число можно как справа, так и слева: » V = (4 6 8 10] ; » р = v*2 Р = 8 12 16 20 » pl = 2*V pl = 8 12 16 20 Делить при помощи знака / можно вектор на число: » р = v/2 Р = 2 3 4 5 Попытка деления числа на вектор-строку приводит к сообщению об ошибке-» р = 2/v ??? Error using ==> / Matrix dimensions must agree. При делении числа на вектор-столбец сообщение об ошибке не выдается. Это связано с тем, что в данном случае происходит решение системы линейных уравнений с прямоугольной матрицей, в которой число неизвестных превосходит число уравнений. Решение систем линейных уравнений разобрано в г wee 6. Если требуется разделить число на каждый элемент вектора и записать результат в новый вектор, то следует использовать операцию . /. Глава 2. Работа с массивами 65 » w = [4 2 6] ; » d - 12. /w d = 3 6 2 Все вышеописанные операции применимы как к вектор-строкам, так и к вектор-столбцам. Разберем, как правильно транспонировать и вычислять сопряженные векторы в MATLAB. Для вектор-столбца w, к примеру с тремя комплексными элементами (в частности и с вещественными), сопряженный к нему и* определяется как вектор-строка из его комплексно-сопряженных элементов, а транспонированный ит— просто как вектор-строка из его элементов, например: 3 + 2/ и* =[2-3/1 + 2/ 3 — 2/], лТ = [2 + 3/ 1-2/ 3 + 2/]. Аналоызчно определяется сопряжение и транспонирование для вектор-строки, приводящее к вектор-столбцу. Ясно, что для векторов, состоящих только из действительных чисел, операции сопряжения и транспонирования совпадают. Для нахождения сопряженного вектора в MATI АВ используется апостроф, а для транспонирования следует применять точку с апострофом: » и = [2 + 31; 1 - 2i; 3 + 2i]; » v = u v = 2.0000 - 3.0000i 1.0000 + 2.00001 3.0000 - 2.0000i » v = u.’ V = 2.0000 + 3.00001 1.0000 - 2.00001 3.0000 + 2.00001 Операции . ' и 1 над вещественными векторами приведут к одинаковым результатам. Поэлементные вычисления с массивами используются на протяжении всей книги. Построение таблицы значений функции Отображение функции в виде таблицы удобно, если имеется сравнительно небольшое количество значений функции. 66 Часть I. Основы работы в МА TLAB I Ijctl требуется вывести в командное окно таблицу значений функции в точках 0.2, 0.3, 0,5, 0.8, 1.3. 1.7, 2.5. Задача решается в два этапа. 1. Создайте вектор-строку х, содержащую координаты заданных точек. 2. Вычислите функцию у(л) от каждого элемента вектора х и запишите полученные значения в вектор-строку у. Важно только сделать это правильно! Необходимо пай ги значения функции для каждого из элементов вектор-строки х, поэтому операции в выражении для функции должны выполняться поэлементно, как было описано в предыдущих разделах. » х = [0.2 0.3 0.5 0.8 1.3 1.7 2.5] х = 0.2000 0.3000 0.5000 0.8000 1.3000 1.7000 2.5000 » у = sin(х).Л2./(1 + cos(x)} + ехр(-х).*1оа(х) У = -1.2978 -0.8473 -0.2980 0.2030 0.8040 1.2258 1.8764 Обратите внимание, что при попытке использования операций возведения в степень Л, деления / и умножения * (которые не относятся к поэлементным) выводится сообщение об ошибке уже при возведении sin(.v) в квадрат: » у = sin(x),'2/(l + cos(x)) + ехр(-х) *log(x) ??? Error using ==> Л Matrix must be square. Дело в том, что в MATLAB операции * и Л применяются для перемножения матриц соответствующих размеров и возведения квадратной матрицы в степень, о чем написано в разделах, посвященных работе с матрицами. Таблице можно придать более удобный для чтения вид, расположив значения функции непосредственно под значениями аргумента: » X X -0.2000 0.3000 0.5000 0.8000 1.3000 1.7000 2.5000 » у У = -1.2978 -0.8473 -0.298U 0.2030 0.8040 1.2258 1.8764 Часто требуется вывести значение функции в точках отрезка, отстоящих друг от друга на равное расстояние (шаг). Предположим, что необходимо вывести Глава 2. Работа с массивами 67 таблицу значений функции у(л)на отрезке [1, 2] с шагом 0.2. Можно, конечно, ввести вектор-строку значений аргумента х-[1,1.2,1.4,1.6,1.8, 2.0] из командной строки и вычислить все значения функции так, как описано выше. Однако если шаг будет не 0.2, а, например, 0.01, то предстоит большая работа по вводу вектора л. В MATLAB предусмотрено простое создание векторов, каждый элемент которых отличается от предшествующего на постоянную величину, т. е. шаг. Для ввода таких векторов служит двоеточие. Следующие два оператора приводят к одинаковым вектор-строкам: » х = [1, 1.2, 1.4, 1.6, 1.8, 2.0] х = 1.0000 1.2000 1.4000 1.6000 1.8000 2.0000 » х = 1:0.2:2 х = 1.0000 1.2000 1.4000 1.6000 1.8000 2.0000 Условно можно записать х = начальное значение : шаг : конечное значение Необязательно заботиться о том, чтобы сумма предпоследнего значения и шага равнялась бы конечному значению; например, при выполнении следующего оператора присваивания » х = 1:0.2:1.9 х = 1.0000 1.2000 1.4000 1.6000 1.8000 вектор-строка заполнится до элемента, не превосходящего определенное нами конечное значение. Шаг может быть и отрицательным: » х = 1.9:-0.2:1 х = 1.9000 1.7000 1.5000 1.3000 1.1000 В случае отрицательного шага начальное значение должно быть больше пли равно конечному для получения непустой вектор-строки. Попробуйте самостоятельно заполнить вектор-столбец элементами, начинающимися с нуля и заканчивающимися 0.5, с шагом 0.1. Для этого следует заполнить вектор-строку, а затем использовать операцию транспонирования: » х = (0:0.1:0.5) ' X = 0 68 Часть I, Основы работы в MATLAB 0.1000 0.2000 0,3000 0.4000 0.5000 Обратите внимание, что элементы вектора, заполняемого при помощи двоеточия, могут быть только вещественные, поэтому для транспонирования можно набрать знак апострофа вместо точки с апострофом. Круглые скобки использованы не случайно, без них операция транспонирования применилась бы только к числу 0.5, и в результате вектор х был бы строкой. Шаг, равный единице, допускается не указывать при автоматическом заполнении: » х = 1:5 X = 12 3 4 5 Выше мы рассмотрели индексацию при помощи двоеточия Очевидно, что при этом создается вектор индексов с постоянным шагом, который используется для выделения нужных элементов вектора. Выведите теперь таблицу значений функции y(x) = e-xsinl0x на отрезке [О. 1] с шагом 0.05, произведя следующие действия: 1. Сформируйте вектор-строку х при помощи двоеточия. 2 . Вычислите значения у(х) от элементов х (не забудьте использовать поэлементное умножение). 3. Запишите результат в вектор-строку у. 4. Выведите х и у. Результат, отображенный на экране, не очень напоминает таблицу: » х = 0:0.05:1; » у - ехр(-х).*sin(10*x); » х X = Columns 1 through 7 Гпава 2. Pabora с массивами 69 О 0.0500 0.1000 0.1500 0.2000 0.2500 0.3000 Columns 8 through 14 0.3500 0.4000 0.4500 0.5000 0.5500 0.6000 0.6500 Columns 15 through 21 0.7000 0.7500 0.8000 0.8500 0.9000 0.9500 1.0000 » У У = Columns 1 through 7 0 0.4560 0.7614 0.8586 0.7445 0.4661 0.1045 Columns 8 through 14 -0.2472 -0.5073 -0.6233 -0.5816 -0.4071 -0.1533 0.1123 Columns 15 through 21 0.3262 0.4431 0.4445 0.3413 0.1676 -0.0291 -0.2001 Вектор-строки x и у состоят из двадцати одного элемента, не помещаются на экране в одну строку и выводятся по частям. Так как к и у хранятся в двумерных массивах один на двадцать один, то выводятся по столбцам, каждый из которых состоит из одного элемента. Сначала выводятся столбцы с первого по седьмой (columns 1 through 7), затем — с восьмого по четырнадцатый (columns 8 through 14), и наконец — с пят надцатого по двадцать первый (Columns 15 through 21). Поимсчаиие Количество элементов, выводимых в одну строку, определяется текущими размерами окна и форматом вывода данных. Одним из способов получения таблицы является формирование матрицы из двух столбцов, первый из которых содержит значения абсцисс, а второй — ординат: » [х' у1] ans = 0 0 0.0500 0.4560 0.1000 0.7614 Далее в этой главе мы уделим достаточно внимания матрицам, а пока обратимся к простейшим способам графического представления функций, которое часто является более наглядным и удобным по сравнению с таблицей ее значений. 70 Часть I. Основы работы в MATLAB Построение графиков функции одной переменной MATLAB обладает хорошо развитыми графическими возможностями для визуализации данных. Графике в MATLAB посвящена глава 3. В настоящем разделе описано построение простейшего графика функции одной переменной на примере функции y(A-)-e-JcsinlOx, определенной на отрезке [о, 1]. Вывод отображения функции в виде графика состоит из следующих этапов: 1. Задание вектора значений аргумента х. 2. Вычисление вектора у значений функции у(л). 3. Вызов команды plot для построения графика. Команды для задания вектора х и вычисления функции лучше завершать точкой с запятой для подавления вывода в командное окно их значений (после команды plot точку с запятой ставить не нужно, т. к. она ничего не выводит в командное окно). Не забудьте использовать поэлементное умножение . * » х = 0:0.05:1; » у = ехр(-х).*sin(10*х); » plot(x, у) После выполнения команд на экране появляется окно Figure 1 с графиком функции, изображенное на рис. 2.2. Окно содержит меню, панель инструментов и область графика. В главе 3, посвященной графике в MATLAB, описаны команды, предназначенные для оформления графика. Сейчас нас будет интересовать сам принцип построения графиков и некоторые простейшие возможности визуализации функций. Для построения графика функции в рабочей среде MATLAB должны быть определены два вектора одинаковой размерности, например х и у. Вектор х содержит значения аргументов, а у — значения функции от этих аргументов. Команда plot соединяет точки с координатами (х(1), у <1)) прямыми линиями, автоматически масштабируя оси для оптимального расположения графика в окне. При построении графиков удобно расположить на экране командное окно MATLAB и окно с графиком так, чтобы они не перекрывались Например, используя кнопку Duck Figure (справа в строке меню окна), можно встроить графическое окно в рабочую среду лак, как показано на рис. 2.3. глава 2. Работа с массивами 71 Рис. 2.2. Простейший график функции Для получения отдельного графического окна следует нажать на кнопку Undock Figure Построенный график функции не должен иметь изломов, т. к. сама функция гладкая. Для точного построения графика вычислите функцию в большем числе точек на отрезке [0,1], т. е. задайте меньший шаг при вводе вектора к. Не забудьте, что можно занести в командную строку введенные ранее команды, затем отредактировать их и выполнить, нажав <Enter>. Следующие команды: » х = 0:0.01:1; » у = ехр(-х) .’,sin(10*x) ; » plotlx, у) 72 Часть I. Основы работы в MATLAB приводят к построению графика функции в виде плавной кривой, изображенной на рис. 2.4 (далее в книге почти всюду приводится только обласгь графика, без заголовка окна, меню и панели инструментов). Рис. 2.3. Расположение окна с графиком в окне MATLAB Примечание Построение графика можно осуществить с помощью инструментов окна Workspace Эта возможность рассматривается в следующей главе. Сравнение нескольких функций удобно производи гь, отобразив их графики на одних осях. Например, постройте на отрезке [-1, -О.з] графики функций /(x)<sin—т, у (х) = sin —у Гпава 2. Работа с массивами 73 при помощи последовательности команд, приведенной ниже: » X = —1:0.005:-0.3; » f = sin{x.z'-2) ; » g = б1п(1.2*х.л-2); » plotfx, f, x, g) Рис. 2.4. Гладкий график функции Получившиеся графики, приведенные на рис. 2.5, дают наглядное представление о поведении исследуемых функций. MATLAB выводит графики разным цветом. Монохромный принтер напечатает графики различными оттенками серого цвета, что не всегда удобно. Команда plot позволяет легко задать стиль и цвет линий, например, » plot(x, £, ’к-’, х, д, 'к:') осуществляет построение первого графика сплошной черной линией, а второго -— черной пунктирной (рис. 2.6). Аргументы 'к-' и 'к:' задают стиль и цвет первой и второй линий. Здесь к означает черный цвет, а дефис или двоеточие— сплошную или пунктирную линию. Визуализация данных и построение графиков подробно описаны в следующих главах. Окно с графиком можно закрыть, нажав на кнопку закрытия окна в его правом верхнем углу. 74 Часть I. Основы работы в МА TLAB Рис. 2.5. Два графика на одних осях Рис. 2.6. Изменение стиля н цвета линий графиков Построение графиков функций в MATLAB требует понимания работы с векторами — необходимо уметь вводить векторы, использовать двоеточие для автоматического заполнения с заданным шагом, применять поэлемент ные операции для вычисления функций от вектора значений аргумента. Все Гпава 2. Работа с массивами 75 эти вопросы были разобраны выше. Две следующие главы посвящены более детальному использованию графических средств пакета. Перейдем теперь к умножению векторов. Умножение векторов Вектор можно умножить на другой вектор скалярно (это произведение еще называют внугренним), векторно, или образовать так называемое внешнее произведение. Результатом скалярного произведения является число, векторного — вектор, а внешнего — матрица. Скалярное произведение Скалярное произведение векторов а и b длины N , состоящих из действительных чисел, определяется формулой N а-Ь=^акЬ» • *=1 Следовательно, для вычисления скалярного произведения необходимо просуммировать компоненты вектора, полученного в результате поэлементного умножения а на b, т. е. надо использовать функцию sum и поэлементное умножение. Найдите самостоятельно скалярное произведение векторов Ниже приведена требуемая последовательность команд: » а = [1.2; -3.2; 0.7]; » Ъ = [4.1; 6.5; -2.9]; » s - sum(a.*b) s = -17.9100 Скалярное произведение векторов можно также вычислить, применив функцию MAT] .АВ dot » s = dot <а,b}; Найдите длину (или, как еще говорят, модуль) вектора а |а| = у/а а . 76 Часть I. Основы работы в MATLAB Решение: » d - sqrt(dot(a, а)) d = 3.4886 Векторное произведение Векторное произведение a xb определено только для векторов из трехмерного пространства, т. е. состоящих из трех элементов. Результатом также является вектор из трехмерного пространства. Для вычисления векторного произведения в МА ['LAB служит функция cross: » а = [1.2; -3.2; 0.7]; » b = [4.1; 6.5; -2.9]; » с = cross(а, Ь) с = 4.7300 6.3500 20.9200 Для тренировки попробуйте вычислить axb+bxa . Если получился вектор, состоящий из нулей, то вы все проделали правильно, т. к. для любых векторов выполняется свойство axb = -bxa . Смешанное произведение векторов а, b, с определяется по формуле ubc -а-{Ьхс). Модуль смешанного произведения векторов равен объему параллелепипеда, построенного на этих векторах так, как показано на рис. 2.7. Рис. 2.7. Параллелепипед, образованный тремя векторами Гпава 2. Работа с массивами 77 Найдите объем параллелепипеда, если 3.5 0.5 -0.2 а = 0 ; Ь = 2.1 ; с= -1.9 0 0 2.8 Правильные действия таковы: » а = [3.5; 0; 0]; » Ь = [0.5; 2.1; 0] ; » с = [-0.2; -1.9; 2.8]; » V = abs(dot(a, cross(Ь, с))) V = 20.5800 Внешнее произведение Внешним произведением векторов о = = м называ" ется матрица C = (cjk) размера NxM , элементы которой вычисляются по формуле cjk =ajbk- Вектор-столбец а в MATLAB представляется в виде двумерного массива размера N на один. Вектор-столбец b при транспонировании переходит в зектор-строку размера один на М. Вектор-столбец и вектор-строка есть матрицы, у которых один из размеров равен единице. Фактически C = abT, где умножение происходит по правилу матричного произведения Для вычисления матричного произведения в MATLAB используется оператор "звездочка": » а = [1; 2; 3]; » Ь = 15; 6; 7] ; >> С - а*Ь' С = 5 6 7 10 12 14 15 18 21 MATLAB вывела в командное окно матрицу в привычном виде— по строкам. Используйте команду whos для просмотра переменных рабочей среды или окно Workspase. Числа, векторы и матрицы хранятся в двумерных мае- 78 Часть I. Основы работы в MATLAB сивах числа — в массивах, размерностью один на один, вектор-столбцы и вектор-строки содержатся в массивах, у которых одно из измерений равно единице, а для матриц выделяются двумерные массивы подходящих разме ров. Именно поэтому операции и встроенные функции в MATLAB приспосабливаются к виду аргументов, выдавая результат в соответствующем виде. Если вы внимательно изучили использование векторов, то читать следующие разделы о работе с матрицами не представит большого труда. Двумерные массивы, матрицы В этом разделе описан ввод матриц, математические операции с ними, поэлементные операции, вычисление функций от элементов матриц, чтение и запись с использованием текстового файла, простейшая визуализация матричных данных. Ввод матриц, простейшие операции Различные способы ввода Вводить небольшие по размеру матрицы удобно прямо из командной строки. Введите матрицу размерностью два на три <3 1 -1А А = I2 4 3 > Для хранения матрицы используйте двумерный массив с именем а. При вводе учтите, что матрицу А можно рассматривать как вектор-столбец из двух элементов, каждый из которых является вектор-строкой длиной три, следовательно, строки при наборе отделяются точкой с запятой: » А = [3 1 -1; 2 4 3] А = 3 1-1 2 4 3 Для изучения простейших операций над матрицами нам понадобится еще несколько матриц. Рассмотрим другие способы ввода. Введите квадратную матрицу размера три так, как описано ниже: '4 3 -Г В= 2 7 О Глав! 2. Работа с массивами 79 Начните набирать в командной строке » Б = [4 3-1 2 7 0 -5 1 2J Нажмите клавишу <Enter>. Обратите внимание, что MATLAB ничего не вычислила. Курсор мигает на следующей с гроке без символа ». Продолжи те ввод матрицы построчно, нажимая в конце каждой строки <Enter>. Последнюю строку завершите закрывающей квадратной скобкой, получается: в = 4 3-1 2 7 0 -5 12 Еще один способ ввода матриц состоит в том, что матрицу можно трактовать как вектор-строку, каждый элемент которой является вектор-столбцом. Например, матрицу два натри -1 Т 2 О 7 можно ввести при помощи команды: » С = [[3; 4] [-1; 2] [7; 0] ] С = 3-17 4 2 0 Посмотрите переменные рабочей среды в окне Workspace или наберите в командной строке whos. Итак, в рабочей среде содержится три матрицы, две прямоугольные и одна квадратная. Обращение к элементам матриц Доступ к элементам матриц осуществляется при помощи двух индексов — номеров строки и столбца, заключенных в кру! лые скобки, например » С(2, 3) ans = о 80 Часть I. Основы работы в MATLAB Элементы матриц могут входить в состав выражений: » С(1, 1) + С(2, 2) + С(2, 3) апз - 5 В качестве индексов могут выступать векторы, содержащие номера нужных строк и столбцов. Например, для выделения элементов первой и второй строк второго и третьего столбцов введенной выше матрицы В достаточно ввести команды: » i = [1 2]; » j = [2 3] ; » Bl = B{i, j) Bl = 3 -1 7 0 Расположение элементов матрицы в памяти компьютера определяет еще один способ обращения к ним. MATLAB хранит элементы матрицы в памяти по столбцам. Элементы матрицы Q размера m на п содержатся в памяти в последовательности: <711» 9X1’ 9ml- 912’ 922’ —’ 9л<2’ —’ 9|,г 92л —’ 9шл • Следовательно, для доступа к элементам матрицы можно использовать один индекс, задающий порядковый номер элемента матрицы в векторе. Например, элементы матрицы С, определенной в предыдущем разделе, записаны в таком порядке С(1, 1), С(2, 1), С(1, 2), С(2, 2), С(1, 3), С(2, 3) Поэтому обращение к элементам матрицы как к элементам вектора при помощи одного индекса (индексация при помощи порядкового номера) приводит к предсказуемому результату » С{5) ans — 7 но может послужить и источником ошибок в вычислениях, если один индекс случайно указан вместо двух— никакого предупреждения не выводится. Как правило, часто лучше использовать два индекса, за исключением некоторых специальных случаев, например, прохода элементов матрицы по столбцам. Еще одним способом обращения сразу ко всем элементам матрицы, удовлетворяющим некоторому условию, является логическое индексирование. Логи Гпава 2. Работа с массивами 81 ческое индексирование не является необходимым для выполнения обычных операций матричной алгебры, поэтому при первом чтении следующий раздел можно пропустить. Однако оно существенно расширяет возможности обработки векторных и матричных данных, позволяя наглядно и компактно записывать выражения с достаточно сложной логикой без программирования перебора данных. Логическое индексирование Логическое индексирование (logical subscripting) позволяет выбрать из массива элементы, удовлетворяющие определенным условиям, которые заданы логическим выраисением. Подробно логические выражения будут обсуждаться в г часе. 7, а здесь приведем простой пример. Пусть из введенной выше матрицы В требуется выбрать все отрицательные элементы и записать их в вектор f. Сначала выполним, казалось бы, недопустимое действие: запишем в переменную ind результат сравнения матрицы и числа ноль. » ind = В < О ind = 0 0 1 ООО 10 0 Образовался логический массив (logical array) ind того же размера, что и в (см. окно Workspace), состоящий из нулей и единиц, причем единицы соответствуют отрицательным элементам массива в. Указание логического массива ind в качестве единственного индекса исходного массива в позволяет решить поставленную задачу: » f = В(ind) f = -5 -1 Разумеется, можно было обойтись и без вспомогательного массива ind, написав сразу £ = в (в < 0). Если требуется присвоить новое значение элементам массива, удовлетворяющим определенному условию, то выражение в(в < 0) должно войти в левую часть оператора присваивания. Только что мы рассмотрели новый тип данных MATLAB — логические массивы. В нашем примере логический массив ±nd был автоматически создан при выполнении операции сравнения в > о. Было бы ошибкой считать, 82 Часть /. Основы работы в MATLAB что для выделения нужных элементов достаточно просто создать массив из нулей и единиц и указать его в качестве индекса массива. Введите, например, из командной строки массив indl с теми же элементами, что и ind: » indl = [0 0 1; 0 0 0; 1 00]; и попытайтесь использовать его для логического индексирования, получается ошибка: » В(indl) ??? Subscript indices must either be real positive integers or logicals. Выход состоит в преобразовании числового массива indl в логический массив ind2 при помощи функции logical, который затем применяется для индексирования: » ind2 = logical(indl); Убедитесь, что ind2 — логический массив, изучив информацию о нем в окне Workspace. Логическое индексирование векторов производится аналогично. Логическое индексирование позволяет получить значения нужных элементов матрицы или вектора или изменить их, но индексы элементов остаются неизвестными. Для поиска индексов элементов, удовлетворяющих определенному условию, служит функция find. Вот простой пример: требуется найти номера всех элементов вектора, равных максимальному значению. Вызов функции max с двумя выходными аргументами не решает эту задачу, поскольку находится только один элемент и его номер: » х = [12534515]; » [ш, к] - шах(х) m = 5 к = 3 Теперь мы знаем значение m максимального элемента, оно равно 5, и могли бы использовать логическое индексирование для записи всех максимальных значений в вектор. Двойной знак == обозначает логическое равенство: » хт - х(х == 5} хт = 5 5 5 i лана 2 Работа с массивами 83 но номера максимальных элементов все равно неизвестны. Вместо логического индексирования используем функцию find, указав во входном ее аргументе логическое выражение х == 5 » km = find(x == 5) km - 3 6 8 Функция find вернула номера элементов вектора, совпадающих с максимальным значением. Аналогичный поиск в матрице так же осуществляется при помощи find. П}сть, например, надо найти индексы всех неположительных элементов матрицы В, введенной выше. Вызовем find с двумя выходными аргументами — векторами, в которые требуется записать значения строчных и столбцевых индексов искомых элементов матрицы » [i> jl = find(В <= 0) i = 3 1 2 3 = 1 3 3 Действительно, все эти элементы b3i, bl3 и b23 меньше или равны нулю. В этом примере к функции find можно обратиться и с одним выходным аргументом: » k = find(B <= 0) к = 3 7 8 В этом случае вектор к содержит номера требуемых элементов матрицы с учетом описанной выше схемы хранения в памяти по столбцам. Обратимся теперь к основным операциям с матрицами в MATLAB. 4 За* ВО 84 Часть I. Основы работы в MATlAB Сложение, вычитание, умножение, транспонирование и возведение в степень При использовании матричных операций следует помнить, что для сложения или вычитания матрицы должны быть одного размера, а при перемножении число столбцов первой матрицы обязано равняться числу строк второй матрицы. Сложение и вычитание матриц, так же как чисел и векторов, осуществляется при помощи знаков плюс и минус. Найдите сумму и разность матриц С и А, определенных выше: » S = А + С S = 6 0 6 6 6 3 » R = С-А R = 0-2 8 2 -2 -3 Следите за совпадением размерности, иначе получите сообщение об ошибке: » S = А + В ??? Error using ==> + Matrix dimensions must agree. Для умножения матриц предназначена "звездочка": » р = с*в р = -25 9 11 20 26 -4 Умножение матрицы на число тоже осуществляется при помощи "звездочки", причем умножать на число можно как справа, так и слева: » р = А*3 р = 9 3-3 6 12 9 » Р = 3*А Р = 9 3-3 б 12 9 Транспонирование матрицы, так же как и вектора, производится при помощи .', а символ ' означает комплексное сопряжение. Для вещественных матриц эти операции приводят к одинаковым результатам: » В’ » в. ans ~ 4 2-5 ans = 4 2-5 Гпава 2. Работа с массивами 85 3 7 1 3 7 1 -102 I -102 Сопряжение и транспонирование матриц, содержащих комплексные числа, приведут к разным матрицам: » К = [1 - i, 2 + 3i; 3 - 5i, 1 - 9i] К = 1.0000 - l.OOOOi 2.0000 + 3.0000i 3.0000 - 5.0000i 1.0000 - 9.0000i » K' ans - 1.0000 + l.OOOOi 3.0000 + 5.0000i 2.0000 - 3.0000i 1.0000 + 9.0000i » K. ’ ans = 1.0000 - l.OOOOi 3.0000 - 5.00001 2.0000 + 3.00001 1.0000 - 9.0000i Вспомните, что при вводе вектор-строк их элементы можно разделять или пробелами, или запятыми. При вводе матрицы К применены запятые для более наглядного разделения комплексных чисел в строке. Возведение квадратной матрицы в целую степень производится с использованием оператора Л: » В2 = Вл2 В2 = 27 32 -6 22 55 -2 -28 -6 9 Проверьте полученный результат, умножив матрицу на саму себя. Убедитесь, что вы освоили простейшие операции с матрицами в MATLAB. Найдите значение следующего выражения (Л + С)В3(Д-С)Т. Учтите приоритет операций, сначала выполняется транспонирование, потом возведение в степень, затем умножение, а сложение и вычитание производятся в последнюю очередь. » (А + С)*ВЛ3*(А - с) ans = 1848 1914 10290 3612 86 Часть I. Основы работы в MATLAB Перемножение матрицы и вектора Поскольку вектор-столбец или вектор-строка в MATLAB являются матрицами, у которых один из размеров равен единице, то вес вышеописанные операции применимы и для умножения матрицы на вектор, или вектор-строки на матрицу. Например, вычисление выражения [1 3 -2] ' 2 О -4 8 9 1 > -8 3 4 можно осуществить следующим образом: » а = [13 -2] ; » В = [20 1; -4 8 -1; 0 9 2]; » с = [-8;3;4]; » а*В*с апз = 74 В математике не определена операция деления для матриц и векторов, однако в MATLAB символ используется для решения систем линейных уравнений. Решение систем линейных уравнений Решите небольшую систему, состоящую из трех уравнений с тремя неизвестными: 1.2х| + 0.3х2 — 0.2х3 = 1.3; 0.5.Х] + 2.1х2 + 1.3х3 = 3.9; -0.9х, +0.7х2 +5.6х3 =5.4. Введите матрицу системы в массив а, для вектора правой части используйте массив о. Решите систему при помощи символа » х = АЬ х = 1.0000 1.0000 1.0000 Проверьте, правильный ли получился ответ, умножив а на х. Глава 2 Работа с массивами 87 j Примечание л Алгоритм решения систем линейных уравнений при помощи оператора определяется структурой матрицы коэффициентов системы. В частности, MATLAB исследует, является ли матрица треугольной, или может быть приведена перестановками строк и столбцов к треугольному виду, симметричная матрица или нет, квадратная или прямоугольная (MALLAB умеет решать системы с прямоугольными матрицами — переопределенные . или недоопределенные). По (тому решать системы при помощи разумно, когда выбор алгоритма решения поручается MATLAB. Если же имеется информация о свойствах матрицы системы, то следует использовать специальные методы (подробнее о решении систем линейных уравнений сказано в главе 6). Решение систем небольшой размерности можно выполнить, введя матрицу системы и вектор правой части непосредственно из командной строки. Однако часто требуется найти решение системы, состоящей из большого числа линейных уравнений. Для ввода данных можно воспользоваться редактором массивов, который предоставляет удобный способ ввода и дае~ возможность легко проверить введенные данные на наличие ошибок. Вот один из возможных способов. Создайте в рабочей среде два пустых массива размера ноль на ноль при помощи квадратных скобок: » а - [ ]; » Ь = [ ]; Откройте в редакторе массив а и определите нужный размер в строках ввода Size:. Затем введите элементы матрицы в ячейки таблицы. Обратите внимание, что при нажатии <Enter> происходит переход к ячейке, расположенной под текущей. Это хорошо, если матрица вводится по столбцам. Если предпочтительнее заносить значения элементов по строкам, то следует выбрать пункт Preferences... в меню File редактора массивов и в появившемся окне Array Editor Preferences задать желаемое направление перехода в раскрывающемся списке Direction. Флаг Move selection after Enter должен быть включен. Аналогичным способом вводится вектор правой части системы. Матрица и вектор правой части системы могут .хранит вся в файлах. В следующем разделе на примере решения системы показано, как считать данные из текстового файла, получить результат и записать его в файл. Считывание и запись данных Перед нами стоит задача — решить систему линейных уравнений, матрица и вектор правой части которой хранятся в текстовых файлах matr.txt, 88 Часть I. Основы работы в MATLAP rside.txt, и записать результат в файл sol.txt. Матрица записана в файле построчно, элементы в строке отделены пробелом, вектор правой части записан в столбик, как показано на рис. 2,8. файл matr txt файл r'ide txt 345 0.11 - -0 25 7.25 1.08 5 97 - 0.09 0.91 • -041 1.06 5.84 4 23 Рис. 2.8. Файлы с матрицей и вектором правой части системы Подготовьте файлы с данными, например, в стандартной программе Windows Блокнот (Notepad). Скопируйте файлы matr.txt, rside.txt в подкаталог work основного каталога MATLAB. Для считывания из файла используйте команду load, для записи — save. Применив load и save для сохранения и считывания переменных рабочей среды описано в главе 1, однако при работе с файлами данных используется функциональный способ вызова этих команд с выходными аргументами: » А = load('matr.txt1); » b = load('rside.txt'); » x = Ab; » save 1 sol.txt' x -ascii Параметр -ascii означает запись в текстовом формате. После выполнения данных команд в каталоге work создастся файл sol.txt, в котором в столбик будет записано решение системы. Посмотреть содержимое файла можно, используя любой текстовый редактор. Для записи результата в файл с двойной точностью следует использовать команду save 'sol.txt' х -ascii -double. На рис. 2.9 приведено содержимое файла sol.txt в случае использования команды save с параметром -doable и без него. 3 5756116е+000 35756115823410211е+000 -1.4288319е+000 -1.4288318561740618е+000 2 8680803е+000 2.8680803204263223е+ 000 save 'sol.txt* х ‘-ascii save 'sol.txt' х -ascii -double Рис. 2.9. Содержимое файла sol.txt Глава 2. Работа с массивами 89 Аналогично можно записать матрицу в текстовый файл. Запись, например, матрицы Д, хранящейся в массиве а, в файл matrA.txt осуществляется командой save 'matrA.txt' A -ascii. Запись в файл и считывание из файла осуществляются по строкам. Блочные матрицы Очень часто в приложениях возникают так называемые блочные матрицы, т. е. матрицы, составленные из непересекающихся подматриц (блоков). Соответствующие размеры блоков должны совпадать. Конструирование блочных матриц Введите матрицы и создайте из них блочную матрицу учитывая, что матрица К состоит из двух строк, в первой строке матрицы А и В а во второй — С и D: » К = [А В; С D] к = -14 2 0 -14 0 5 3-389 -3 3 1 10 Блочная матрица получена. Можно было поступить и по-другому, а именно, считать, что матрица К состоит из двух столбцов, в первом — матрицы А и С , а во втором — В и D. Как бы тогда следовало записать команду для создания блочной матрицы? Проверьте себя » К = [ [А; С] [В; D] ] 90 Часть I. Основы работы в MATLAB Вот еще один пример для проверки знаний о работе с массивами в МА Г1 АВ. Требуется составить блочную матрицу м = 'S | a bTiJ L 1 где 5 = (2 О' 3 ; « = Г4А Решение этой задачи следующее: » S = [2 0; О 3] ; » а = [ 4; 5 ] ; » b = (-9 9]; » М = [S а; Ь 2.5] М = 2.0000 0 4.0000 0 3.0000 5.0000 -9.0000 9.0000 2.5000 Последний оператор можно заменить на эквивалентный м = [ [s,- b] [а,-2.5] ]. MATLAB позволяет конструировать блочно-диагональные матрицы с помощью функции blkdiag. Рассмотрим пример: » R = и 2; 3 4]; » Q = [567; 8 9 10; 11 12 13]; » Т = [-3 5; 6 7] ; Z = blkdiag(R, Q, Т) Z = 1 2 0 0 0 0 0 3 4 0 0 0 0 0 0 0 5 6 7 0 0 О 0 8 9 10 0 0 0 0 11 12 13 0 0 00000-35 0 0 0 0 0 6 7 Блоки, используемые функцией blkdiag, не обязательно должны быть квадратными и одного размера. Глава 2. Работа с массивами 91 Обратной задачей к конструированию блочных матриц является выделение блоков. 4 10 12 0 11 10 Выделение блоков Выделение блоков матриц осуществляется индексацией при помощи двоеточия, которая уже использовалась в предыдущих разделах для выделения блоков из векторов. Введите матрицу fl 2 0 2' 5 5 ’ I9 2 3 5, загем выделите очерченный блок, задав номера строк и столбцов при помощи двоеточия: » Р1 = ₽(2:3,2:3) Р1 = 10 12 И 10 Для выделения из матрицы столбца или строки (т. е. массива, у которого один из размеров равен единице) следует в качестве одного из индексов использовать номер столбца или строки матрицы, а другой индекс заменить на двоеточие без указания пределов. Например, запишите вторую строку Р в вектор р » Р = Р(2, :) Р = 4 10 12 5 При выделении блока до конца матрицы можно не указывать ее размеры, а использовать end: » р = Р(2, 2:end) Р - 10 12 5 Удаление строк и столбцов Как уже было сказано, в MATLAB парные квадратные скобки [ ] обозначают пустой массив, который, в частности, позволяет удалять сгроки и 92 Часть I. Основы работы в MA1LAR столбцы матрицы. Для удаления строки следует присвоить ей пустой массив Удалите, например, первую строку квадратной матрицы: » М = [2 0 3 114 6 1 3]; » М(1, :) = [ ]; » М м = 114 6 13 Обратите внимание на соответствующее изменение размеров массива, которое можно посмотреть в окне Workspace или проверить при помощи size. Аналогичным образом удаляются и столбцы. Для удаления нескольких идущих подряд столбцов (или игрок) им нужно присвоить пустой массив. Удалите второй и третий столбец в м » М<:, 2:3) = [ 1 М = 1 6 Индексация существенно экономит время при вводе матриц, имеющих определенную структуру. Заполнение матриц при помощи индексации Выше было описано несколько способов ввода матриц в MATLAB, в том числе считывание из файла и использование редактора массивов. Однако если матрица обладает простой структурой, то бывает проще сгенерировать ее, чем вводить. Рассмотрим пример такой матрицы: т = 4 11 1 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 Генерация матрицы Т осуществляется в три этапа: 1. Создание массива т размера пять на пять, состоящего из нулей. 2. Заполнение первой строки единицами. I лава 2 Работа с массивами 93 3. Заполнение части последней строки минус единицами до последнею элемента. Соответствующие команды MATLAB приведены ниже (они записаны в три колонки с целью экономии места, но набирать их надо последовательно). Команды не завершаются точкой с запятой для вывода пр^межу точных результатов в командное окно с целью слежения за процессом формирования матрицы » А(1: : 5, 1:5) = 0 » А(1, :) = 1 » A(end, , 3:end) = -1 А = А = А = 0 0 0 0 0 1 1 1 1 1 1 111 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 - -1 -1 Создание некоторых специальных матриц в MATLAB осуществ. >яется при помощи встроенных функций. Создание матриц специального вида Заполнение прямоугольной матрицы нулями производится встроенной функцией zeros, аргументами которой являются число строк и столбцов матрицы. » А = zeros(3, б) А = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Один аргумент функции zeros приводит к образованию квадратной матрицы заданного размера: » А = zeros(3) А = 0 0 0 0 0 0 0 0 0 Единичная матрица инициализируется при помощи функции eye: » I = еуе(4) 94 Часть I. Основы работы в MATLAB I = 10 0 0 0 10 0 0 0 10 0 0 0 1 Функция eye с двумя аргументами создает прямоугольную матрицу, у которой на главной диагонали стоят единицы, а остальные элементы равны нулю: » I = eye(4, 8) I = 10000000 01000000 00100000 00010000 Матрица, состоящая из единиц, образуется в результате вызова функции ones: » Е = ones(3, 8) Е = 11111111 11111111 11111111 Использование одного аргумента в ones приводит к созданию квадратной матрицы, состоящей из единиц. MATLAB предоставляет возможность заполнения матриц случайными элементами. Результатом функции rand является матрица чисел, распределенных случайным образом между нулем и единицей, а функции randn — матрица чисел, распределенных по нормальному закону: » R = rand(3, 5) R -0.9501 0.4860 0.4565 0.4447 0.9218 0.2311 0.8913 0.0185 0.6154 0.7382 0.6068 0.7621 0.8214 0.7919 0.1763 » RN = randn(3, 5) RN = 0.1139 -0.0956 -1.3362 -0.6918 -1.5937 1.0668 -0.8323 0.7143 0.8580 -1.4410 0.0593 0.2944 1.6236 1.2540 0.5711 Гпава 2 Рабо га с массивами 95 Обращение к функциям rand и randn с одним входным аргументом приводит к формированию квадратных матриц. Вопрос об автоматическом заполнении вектор-столбцов или вектор-строк не должен поставить нас в тупик, поскольку мы знаем, что вектор-ci олбец или вектор-строка в MATLAB являются матрицей, у которой один из размеров равен единице. Заполните вектор-строку шестью случайными числами. Проверьте себя, выполнив следующий пример: » г = rand(l, б) 0.7468 0.4451 0.9318 0.4660 0.4186 0.8462 Часто возникает необходимость создания диагональных матриц, т. е. матриц, у которых все внедиагональные элементы равны нулю. Функция diag формирует диагональную матрицу из вектор-столбца или вектор-строки, располагая их элементы по диагонали матрицы: » d = [1; 2; 3; 4] ; » D = diag(d) D = 10 0 0 0 2 0 0 0 0 3 0 0 0 0 4 Для заполнения не главной, а побочной диагонали предусмотрена возможность вызова функции diag с двумя аргументами. В этом случае второй аргумент означает, насколько побочная диагональ отстоит от главной, а его знак указывает на направление, плюс— вверх, минус— вниз от главной диагонали: » d = [1; 2]; » D = diag(d, 2) D - 0 0 10 0 0 0 2 0 0 0 0 0 0 0 0 » D = diagtd, -2) D - 0 0 0 0 0 0 0 0 96 Часть I. Основы работы в MATLAB 10 0 0 0 2 0 0 Функция diag служит и для выделения диагонали матрицы в вектор, например » А = [10 1 2; 1 20 3; 2 3 30] А = 10 1 2 1 20 3 2 3 30 » d = diag(A) d = 10 20 30 Все функции MATLAB для создания матриц специального вида описаны в справочной системе, см. пункт Arrays and Matrices подраздела Mathematics раздела Functions — Categorical List. Проделайте следующее упражнение для того, чтобы убедится, что вы освоили автоматическое заполнение матриц, работу с блочными матрицами и запись данных в файл. Заполните и запишите в файлы матрицы: Г! 0 0 0 0 2 2 2 2 2 ' 0 1 0 0 0 2 2 2 2 2 <2 1 0 0 0 0 О' 0 0 1 0 0 2 2 2 2 2 1 2 1 0 0 0 0 0 0 0 1 0 2 2 2 2 2 0 1 2 1 0 0 0 0 0 0 0 1 2 2 2 2 2 м = 3 3 3 3 3 -4 0 0 0 0 ; G = 0 0 1 2 1 0 0 0 0 о 1 2 1 0 3 3 3 3 3 0 —4 0 0 0 0 0 0 0 1 2 i 3 3 3 3 3 0 0 -4 0 0 0 0 0 0 0 i 2 3 3 3 3 3 0 0 0 -4 0 с 7 7 3 3 3 3 0 0 0 0 -4 Матрицу М можно представить в виде блочной матрицы из четырех квадратных блоков размера пять, диагональные блоки формируются при помощи eye, а внедиагональные—с использованием ones: » М - [еуе(5) 2*ones(5); 3*ones(5) - 4*еуе(5)],- » save 'И.txt' М -ascii I лава 2. Работа с массивами 97 Квадратная матрица г* размера семь является трехдиагональной. Заполняя эту матрицу, можно использовать то обстоятельство, что G является суммой диагональной матрицы и двух матриц с шестью ненулевыми элементами над и под главной диагональю. » G = 2*еуе{7) + diag(ones(l, 6), 1) + diag(ones(l, 6), -1) » save 'G.txt' G -ascii Посмотрите содержание полученных файлов (они должны находиться в подкаталоге work основного каталога MATLAB). Матрицы больших размеров удобно представлять в наглядном виде. В программе MATLAB это можно проделать при помощи визуализации матриц. В следующем разделе разобраны простейшие способы визуализации матричных данных. Визуализация матриц Матрицы с достаточно большим количеством нулей называются разреженными. Ч^сто необходимо знать, где расположены ненулевые элементы, т. е. получить так называемый шаблон матрицы. Для этого в MATLAB служит функция spy. Посмотрим шаб юн матрицы G, определенной в предыдущем разделе » G = 2*еуе{7) + diag(ones(l, 6), 1) + diag(ones(l, 6), -1) После выполнения команды spy на экране появляется графическое окно Figure 1. На рис. 2.10 изображена часть окна без заголовка, меню и панели инструментов. На вертикальной и горизонтальной осях отложены номера строк и столбцов. Ненулевые элементы обозначены маркерами, внизу графического окна указано число ненулевых элементов (nz = 19). Наглядную информацию о соотношении величин элементов матрицы дает функция imagesc, которая интерпретирует матрицу как прямоугольное изображение. Каждый элемент матрицы представляется в виде квадратика, цвет которого соответствует величине элемента. Для того чтобы узнагь со-ответивие цвета и величины элемента, следует использовать команду colorbar, выводящую рядом с изображением матрицы шкалу цвета. Наконец, для печати на монохромном принтере удобно получить изображение в оттенках серою цвета, используя команду colormap (gray). Мы будем работать с матрицей М, определенной в предыдущем разделе. 9в Часть I. Основы работы в МА ПАВ О 1 2 3 4 5 6 7 8 О 1 2345Б78 nz= 19 Рис. 2.10. Шаблон разреженной матрицы Рис. 2.11. Ин герпретання матрицы как изображения Гпава 2 Работа с массивами 99 Набирайте команды, указанные ниже, и следите за состоянием графического окна: » imagesc(M) » colorbar » colormap(gray) В результате получается наглядное представление матрицы, приведенное на рис. 2.11. Подробно про использование графики в MATLAB написано в следующих главах, однако уже сейчас вы можете визуализировать матрицы, с которыми мы будем работать при изучении поэлементных матричных операций. Поэлементные операции и встроенные функции Поскольку векторы и матрицы хранятся в двумерных массивах, то применение математических функций к матрицам и поэлементные операции производятся так же, как для векторов. Работа со встроенными функциями (такими как min, max, sum и т. д.) имеет свои особенности в применении к матрицам. Поэлементные операции с матрицами Введит е две матрицы <2 5 -1Л Л—1 2 8 А Д = ; В = ^3 4 9 J ^7-3-5, Умножение каждого элемента одной матрицы на соответствующий элемент другой производится при помощи оператора . * » С = А.*В С = -2 10 -8 21 -12 -45 Для деления элементов первой матрицы на соответствующие элементы второй используется ./, а для деления элементов второй матрицы на соответствующие элементы первой служит . » R1 = А./В R1 = -2.0000 2.5000 -0.1250 100 Часть I. Основы работы в МА TLAB 0.4286 -1.3333 -1.8000 » R2 = АЛЕ R2 = -0.5000 0.4000 -8.0000 2.3333 -0.7500 -0.5556 Поэлементное возведение в степень осуществляется при помощи . ~ » Р “ А. Л2 Р - 4 25 1 9 16 81 Показатель степени может быть матрицей того же размера, что и матрица, возводимая в степень. При этом элементы первой матрицы возводятся в степени, равные элементам второй матрицы: » рв = А.ЛВ рв = 1.0е+003 * 0.0005 0.0250 0.0010 2.1870 0.0000 0.0000 Обратите внимание на форму вывода результата. Во-первых, выделен общий множитель 1. Ое+003 для всех элементов результирующей матрицы, т. е. ответ выглядит так: , (0.0005 0.0250 0.0010 А ( 0.5 25 П РВ = 103- = ^2.1870 0.0000 0.0000J ^2187 0 0^ Во-взорых. при возведении 4-3 и 9-5 получились нули, т. е. произошла потеря точности из-за того, что использовался формат short. Дело в том, что 4~3 =0.0156, 9~5 =0.000016935, а эти числа малы по сравнению с остальными. и допустимого числа знаков формата short не хватает для их отображения на экране. Если мы хотим получить более точный результат поэлементного возведения в степень, то мы должны задать формат long, и затем вывести РВ снова: » format. long » РВ РВ = 1.0е+003 Глава 2. Работа с массивами 101 0.00050000000000 0.02500000000000 0.00100000000000 2.18700000000000 0.00001562500000 0.00000001693509 Заметьте, что повторного вычисления элементов матрицы РВ не потребовалось. Вне зависимости от установленного формата вывода все вычисления производятся с двойной точностью (в предположении, что данные типа single не участвуют в операциях). Перейдем теперь к вычислению математических функций от элементов матриц. Вычисление математических функций от элементов матриц Очень важно сразу понять, что в книгах по теории матриц формула cos А, где А — квадратная матрица, означает вычисление косинуса от матргцы, которое осуществляется при помощи разложения в ряд. В MATLAB имеется возможность вычисления функций от матриц (вычисление функций от матриц описано в разд. "Собственные числа и векторы, матрицы, функции матриц " главы 6). Запись с = cos (А) в МАТ1 АВ приводит к вычислению косинусов от элементов массива а и записи их в массив с того же размера, что и А. Нахождение, например, косинусов от элементов матрицы гл/2 -л/2 А= Л -Л 0 2л 0 2л л/3, производится при помощи следующих команд » А = [pi/2 -pi/2 0; pi -pi 2*pi; 0 2*pi pi/3]; » C = cos(A) C = 0.0000 0.0000 1.0000 -1.0000 -1.0000 1.0000 1.0000 1.0000 0.5000 Аналогично вычисляются и другие математические функции. Использование функций обработки данных для матриц (нахождение максимума, минимума, суммы и др.) несколько отличается от их применения при работе с векторами. 102 Часть I. Основы работы в MATLAB Применение функций обработки данных к матрицам Функция sum вычисляет сумму элементов вектора. С другой стороны, векторы в MATLAB, так же как и матрицы, хранятся в двумерных массивах. Возникает вопрос: что же будет, если в качестве аргумента suit, использовать не вектор, а матрицу. Оказывается, MATLAB вычислит вектор-строку, длина которой равна числу столбцов матрицы, а каждый элемент является суммой соответствующего столбца матрицы, например: » М = [1 -2 -4 3-6 4 2 -2 0] ; » s = sum(M) s = 6 -10 0 Функция sum по умолчанию вычисляет сумму по столбцам, изменяя первый индекс массива при фиксированном втором. Для того чтобы производить суммирование по строкам, необходимо вызвать sum с двумя аргументами, указав место индекса, по которому следует суммировать » s2 = sum(M, 2) s2 = -5 1 0 Заметьте, что sum(M) и sum(M, 1) приводят к одинаковым результатам. Итак, функция sum суммирует или по строкам, или по столбцам, выдавая результат в виде вектора или вектор-строки. Аналогично работает и функция prod: » р = prod(M) >> р2 = prod(M, 2) р = р2 = 6 -24 0 8 -72 0 Функция sort упорядочивает элементы каждого из столбцов матрицы в порядке возрастания. Вызов sort со вторым аргументом, равным двум, приводит к упорядочению элементов строк: » МС = sort(M) мс - » MR = sort(M, 2) MR = 1 -6 -4 -4 -2 1 Гпава 2 Работа с массивами 103 2-20 -634 3-24 -202 Так же как и для векторов, функция sort позволяет получить матрицу индексов соответствия элементов исходной и упорядоченной матриц. Для этого необходимо вызвать sort с двумя выходными аргументами: » [МС, Ind] = sort(M) мс = 1 -6 -4 2-2 0 3-2 4 Ind = 12 1 3 13 2 3 2 Ма грицы м, мс и Ind связаны между собой так: мс (i, j) = м (ind(i, j), j), где i и j изменяются от одного до трех. Функции 1пйх и min вычисляют вектор-строку, содержащую максимальные или минимальные элементы в соответствующих столбцах матрицы: » тпх = max(M) » mn = min(M) mx = mn = 3-24 1-6-4 Для того чтобы узнать не только значения максимальных или минимальных элементов, но и их номера в столбцах, следует вызвать max или пип так. » [mx, k] - max(M) » [mn, n] = min(M) тх = тп = 3-24 1-6-4 к = п = 2 12 12 1 Обратите внимание, что во втором столбце матрицы м два равных максимальных элемента — первый и третий. Всегда возвращается номер первого максимального элемента (второй элемент в вектор-строке равен единице). Точно гак же работает и min в случае двух равных минимальных элементов в столбце матрицы. Ovhkuhh max и min позволяют выделить максимальные или минимальные элементы из двух матриц одинаковых размеров и записать результат в новую ма трицу того же размера, что и исходные: » р = [4 з -1 2 0 7],- 104 Часть!. Основы работы в MATLAB » Q = [10 0 11 -5 3 22] >> R = max(P, Q) R = 10 3 11 2 3 22 Одним из аргументов может быть число. В результирующую матрицу записывается максимум из этого числа и соответствующего элемента исходной магрицы: » S = шах(Р, 1) S = 4 3 1 2 17 Если оба аргумента функций min 11 ли max являются числами, то возвращает* ся минимальное или максимальное из этих чисел. Для нахождения максимума или минимума не по столбцам матрицы, а по строкам, предусмотрена следующая форма вызова со вторым аргументом — пустым массивом: » шх = max(S, [ ], 2) mx = 4 7 Для того чтобы дополнительно получить номера максимальных элементов в строках, используем вызов шах с двумя выходными аргументами: » [mx, j ] = max (S, [ ], 2) mx = 4 7 3 = 1 3 Рассмотрим функцию rot90, поворачивающую массив на 90 градусов против часовой стрелки. Примените эту функцию к упоминавшемуся массиву р: » ql = rot90(p) ql = -1 7 Гпава 2. Работа с массивами 105 3 о 4 2 Примените функцию повторно, теперь уже к массиву qi. » q2 = rot90(ql) q2 = 7 0 2 -13 4 Функция fiipir обеспечивает зеркальное отражение от условной вертикали, прохолящей через середину массива: » fiipir(q2) ans = 2 0 7 4 3-1 Обратите внимание на го, что вектор-столбец не изменяется под воздействием функции fiipir: » q3 = [1,- 2; 3; 4; 5] ; » fiipir(q3) ans = 1 2 3 4 5 Более подробно про обработку матричных данных можно узнать из приложения или вывести список всех встроенных функций обработки данных командой help datafun, а затем посмотреть информацию о нужной функции, например, help max, или обратиться к интерактивной справочной системе. В заключение этой главы описан принцип использования матричных данных при построении графиков функций двух переменных в MATLAB. Графики функций £.вух переменных Построение графика функции двух переменных в MATLAB на прямоугольной области определения переменных включает два предварительных этап: i: 1. Разбиение области определения прямоугольной сеткой. 106 Часть I. Основы работы в МА <7 АБ 2. Вычисление значений функции в точках пересечения линий сетки и запись их в матрицу. Построим график функции z(x,y) = x2 + у2 на области определения в виде квадрата xg[O, 1], уе[О, 1], Необходимо разбить квадрат равномерной сеткой (например, с тагом 0.2) так, как показано на рис. 2.12, и вычислить значения функций в узлах, обозначенных точками. Рис. 2.12. Прямоугольная область построения графика Удобно использовать два двумерных массива х и Y размерностью шесть на шесть для хранения информации о координатах узлов. Массив х состоит из одинаковых строк, в которых записаны координаты л1, х2, ..., хб, a y содержит одинаковые столбцы с yl, у2, ..., уб. Значения функции в узлах сетки запишем в матрицу z такой же размерности (6x6), причем для вычисления магриды z используем выражение для функции, но с поэлементными матричными операциями. Тогда, например, z(3,4) как раз будет равно зна Глава 2. Работа с массивами 107 чению функции z(x,y) в точке (лЗ, у4). Для генерации массивов сетки х и y по координатам узлов в MATLAB предусмотрена функция meshgrid, для построения графика в виде каркасной поверхности — функция mesh. Следующие операторы приводят к появлению на экране окна с графиком функции, изображенным на рис. 2.13 (точка с запятой в конце операторов не ставится для того, чтобы проконтролировать генерацию массивов): » [X, Y] = meshgrid(0:0.2:1, 0:0.2:1) X = О 0.2000 0.4000 0.6000 0.8000 1.0000 0 0.2000 0.4000 О.бСОО 0.8000 1.0000 О 0.2000 0.4000 0.6000 0.8000 1.0000 О 0.2000 0.4000 0.6000 0.8000 1.0000 0 0.2000 0.4000 0.6000 0.8000 1.0000 0 0.2000 0.4000 0.6000 0.8000 1.0000 Y = 0 0 0 0 0 0 0.2000 0.2000 0.2000 0.2000 0.2000 0.2000 0.4000 0.4000 0.4000 0.4000 0.4000 0.4000 0.6000 0.6000 0.6000 0.6000 0.6000 0.6000 0.8000 0.8000 0.8000 0.8000 0.8000 0.8000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 » Z = Х.Л2 + У.Л2 Z = 0 0.0400 0.1600 0.3600 0.6400 1.0000 0.0400 0.0800 0.2000 0.4000 0.6800 1.0400 0.1600 0.2000 0.3200 0.5200 0.8000 1.1600 0.3600 0.4000 0.5200 0.7200 1.0000 1.3600 0.6400 0.6800 0.8000 1.0000 1.2800 1.6400 1.0000 1.0400 1.1600 1.3600 1.6400 2.0000 » meshtx, Y, Z) График функции, изображенный на рис. 2.13, получился достаточно грубым из-за редкой сегки, покрывающей область изменения аргументов. Для более точного построения следует выбрать меньший шаг сетки: » [X, Y] = meshgrid(0:0.05:l, 0:0.05:1); » Z = Х.Л2 + ¥.Л2; » mesh(X, Y, Z) Соответствующий график приведен на рис. 2.14. 108 Часть I. Основы работы в MAI LAB Рис. 2.13. График функции z(x, у) Рис. 2.14. График функции х(л, у) на более мелкой сетке Следующая глава посвящена подробному описанию графических возможностей, предоставляемых MATLAB для визуализации данных. Гпава 2 Работа с массивами 109 Задания для самостоятельной работы Успешная работа в MATLAB и большинстве Toolbox невозможна без понимания принципов обращения с массивами данных. Самостоятельное решение приведенных ниже заданий поможет вам убедиться, что вы освоили операции с векторами и матрицами, и эти вопросы не будут вызывать затруднений при чтении следующих разделов. При необходимости обращайтесь к материалу этой главы и справочной системе. Задания на векторы В следующих заданиях необходимо придумать универсальный способ решения, пригодный для произвольных векторов, и протестировать его на различных показательных примерах. 1. Переставить элементы вектора в обратном порядке, используя индексацию подходящим вектором, и записать результат в новый вектор. 2. Выделить в новый вектор элементы лектора с четными номерами. 3. Найти сумму только положительных элементов вектора. 4. Заменить элементы вектора, отличающиеся от среднего геометрического его элементов более чем на 10%, на среднее геометрическое. 5. Заменить все минимальные элементы вектора максимальным значением его элементов. 6. Найти число положительных и отрицательных элементов вектора. Задания на матрицы 1. Задана квадратная матрица —1.2 4.6 -0.3л А = 2.8 9.9 -0.7 0.9 -2.5 7.1 Элементы матрицы А обозначим aik . Требуется узнать и записать размер матрицы в переменную п (конечно, он равен 3, но лучше использо 110 Часть ' Основы работы в MATLAB вать функцию для автоматического определения размера) и вычислить приведенные ниже величины (нормы матрицы): р = max £ |«1Jt I, q = max £|«/A|, s = £ |«й|. |</<НА=1 1<*<н,=1 ,д.=1 2. При помощи встроенных функций для заполнения стандартных матриц, индексации двоеточием и, возможно, поворота, транспонирования или вычеркивания получите следующие матрицы: 1 0 0 0 0 U1 1 0 0 0 0 0 -1' -1 3 1 0 0 0 0 0 1 0 0 0 -1 0 0 -1 4 1 0 0 0 0 0 1 0 -1 0 0 0 0 -1 5 1 0 0 9 0 0 0 5 0 0 0 0 0 0 -I 6 1 0 0 0 -1 0 1 0 0 0 0 0 0 -1 7 0 0 -1 0 0 0 1 0 _5 0 0 0 0 -1 8_ -1 0 0 0 0 0 1 ’1 0 0 0 0 0 0 0 0 0 О' '1 0 0 0 1 0 0 0 0 0 О' 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 1 о 0 0 0 0 0 1 0 0 0 1 3. Сконструируйте блочные матрицы (используя ф}нкции для заполнения стандартных матриц) и определите заданные величины, применяя функции обработки данных и поэлементные операции. 1 0 0 4 0 0 0 1 0 0 4 0 0 0 10 0 4 2 2 2 3 3 3 2 2 2 3 3 3 2 2 2 3 3 3 глава 2. Работа с массивами 111 ‘ 1 1 -3 -3 -3 -3 1 1 -3 -3 -3 -3 -3 -3 2 0 0 0 5 -3 3 0 2 0 0 ; * = <+1 /=1 -3 -3 0 0 2 0 -3 -3 0 0 0 2 Переставьте столбцы матрицы в порядке возрастания суммы элемен- тов столбца. • Найдите сумму всех положительных элементов матрицы. • Считайте матрицу из файла matr.txt, замените в ней все элементы, большие среднего арифметического ее элементов, на среднее арифметическое и запишите ее в файл newmatr.txt. • Определите макси малоный столбцовый и строчный индексы отрицательных элементов матрицы. Глава 3 Высокоуровневая графика В данной главе списаны основные возможности высокоуровневой (high-level) графики MATLAB для отображения функций двух и трех переменных, визуализации векторных и матричных данных и векторных полей. Высокоуровневая графика позволяет пользователю получать результаты в графическом виде, прикладывая минимум усилий с использованием функций из командной строки. Работу, связанную с масштабированием осей и подбором цветов, MATLAB берет на себя. Удобным средством интерактивного создания графиков и редактирования свойств изображаемых объектов является редактор графических объектов (далее будем называть его редактором графиков), которому посвящена следующая глава. Его изучение разумно рассмотреть после ознакомления с основными функциями, поскольку он является графическим интерфейсом для вызова этих функций. Кроме того, окна Workspace также предоставляют возможность визуализации данных, что бывает особенно удобно на начальной стадии создания рисунков. С этой возможности мы и начнем обсуждение средств MATLAB для высокоуровневой графики. Для чтения этой главы необходимо уметь работать с массивами — векторами и матрицами, понимать выполнение поэлементных операций с массивами, Все эти необходимые сведения были изложены в главе 2. Построение графиков из окна Workspace Создание различных типов графиков, о которых пойдет речь далее, можно осуществить с помощью средств графического интерфейса окна Workspace В предыдущей главе мы разобрали применение функции plot для построе Глава 3. Высокоуровневая i рафика 113 ния графика функции у(х) = е AsinlOx на отрезке [0,1]. Для получения графика необходимо создать массивы исходных данных » х = 0:0.01:1; » у = ехр{-х).*sin(10*x); Вместо вызова plot обратимся теперь к окну Workspace. В нем появились два массива х и у. Для построения графика функции у(х) следует выделить эти массивы щелчком мыши по имени массива с удержанием <Ctrl>, и выбрать тип графика plot(x,y) либо из контекстного меню, открываемого щелчком правой кнопкой мыши (рис. 3.1), либо из раскрывающегося списка типов графиков на панели инструментов окна Workspace (рис. 3.2). Рис. 3.1. Контекстное меню для выбора типг графика Примечание Если панеть инструментов окна Workspace отсутствует, го ее можно отобразить при помощи контекстного меню окна. Для этого следует щелк- 114 Часть I. Основы работы в MATLA4 нуть правой кнопкой мыши по заголовку окна Workspace и в появившемся меню выбрать пункт Workspace 1 oulbar Рис. 3.2. Раскрывающийся список для выбора типа графика Выбор plot(x,y) в контекстном меню или раскрывающемся списке приводит к автоматическому вызову plot, который отображается в командном окне plot(x, у, DisplayName1, ’у vs х' ,'XDataSource', 'х', 1 YDataSource ’, ’ у') и появлению графика функции. Мы пока не будем обсуждать смысл входных аргументов функции plot, поскольку в данном примере она автоматически вызывается с использованием средств низкоуровневой графики, которые достаточно подробно описаны в главе О Следует отметить, что для графического отображения пары векторов х и у допустимо несколько способов, им соответствуют остальные пункты меню или элементы списка. Например, выбор plot (у, х) приводит к построению обратной зависимости *(у). Гпава 3. Высокоуровневая графика 115 Список типов графиков содержит пункт More Plots (Другие графики), выбор которого приводит к открытию дополнительного окна для выбора типа графика (рис. 3.3). Рис. 3.3. Дополнительное окно для выбора типа графика Дополнительное окно разделено на три колонки. В первой (Categories) пользователь выбирает категорию, к которой относится график, во второй (Plot Types) отмечает конкретный тип графика, а в третьей (Description) содержится описание для отмеченного типа графика. Кнопки в данном окне позволяют либо построить 1 рафик в том же окне (Plot), либо в новом (Plot New Figure), либо закрыть окно без построения (Close). 5 Tsr 130 116 Часть I. Основы работы в MATLAB При использовании средств окна Workspace для визуализации данных необходимо следить за тем, чтобы выбранные данные соответствовали друэ другу. В предыдущем примере таким условием являлось совпадение длин векторов х и у. Попытка использовать векторы разной длины приведет к сообщению об ошибке! Перед тем как перейти к описанию функций высокоуровневой графики, приведем еще один пример графического представления только одного вектора. Изучите пункты всплывающего меню для вектора у. Оказывается, можно построить "график вектора", т. е. зависимость элементов вектора от их номера (пункт plot(y)). Векторные данные могут быть представлены диаграммами различных типов (пункты bar(y), pie(y)). Знакомство с функциями высокоуровневой графики MATLAB мы начнем с диаграмм и гистограмм. Диаграммы и гистограммы Наглядным способом представления векторных и матричных данных являются диаграммы и гистограммы. Значение элемента вектора пропорционально высоте столбика диаграммы (в случае столбчатой диаграммы) или площади сектора диаграммы (для круговой диаграммы). Гистограммы используются для получения информации о распределении данных по заданным интервалам. Представление векторных данных Диаграммы векторных данных Отображение вектора в виде столбчатой диаграммы осуществляется функцией bar. Запишите, например, вектор-строку л-= [1.2 1.7 2.2 2.4 2.5 1.3 1.1 0.5 0.4 0.1] в переменную Jata и представьте ее столбчатой диаграммой, вызвав функцию bar с аргументом х: » data = [1.2 1.7 2.2 2.4 2.5 1.3 1.1 0.5 0.4 0.1]; » bar(data) На экране появится графическое окно, изображенное на рис. 3.4, содержащее столбчатую диаграмму вектор-строки (далее в книге на рисунках приводится только область построения графика, а заголовок окна, меню и па Гпава 3 Высокоуровневая графика 117 нель инструментов опускаются, за исключением следующей главы, где рассматривается редактор графиков). По горизонтальной оси откладывается номер элемента вектора, а по вертикальной— его значение. Аргументом функции bar может быть как вектор-строка, так и вектор-столбец. Разметку горизонтальной оси можно задать вектором с возрастающими значениями. В этом случае первый аргумент bar является вектором с координатами точек разметки, а второй — вектором значений, которые требуется отобразить на диаграмме. Удобно использовать этот способ построения диаграммы для отображения значений элементов векторов в зависимости не от их номера, а, например, от времени, если в вектор записаны результаты измерений в некоторые моменты времени. Важно, чтобы длины этих векторов совпадали, иначе будет выдано сообщение об ошибке. » time = 10.0 0.1 0.2 0.4 0.5 0.8 1.1 1.3]; » data = [2.85 2.93 2.99 3.26 3.01 2.25 2.09 1.79]; » bar(time, data) Результат приведен на рис. 3.5. Пропущенные столбики соответствуют тем моментам времени, в которые измерения не производились. Выбор ширины столбцов осуществляется заданием третьего дополнительного аргумента. По умолчанию ширина равна 0.8. Диаграмма без промежутков между столбиками получается, если установить ширину равной единице. Выбор значений, больших единицы, приводит к перекрывающимся 118 Часть I. Основы работы в MATLAB столбикам. В качестве примера отобразите функцию x(/) = sinf -е( на отрезке [-1.1] в виде столбчатой диаграммы без промежутков, выполнив следующую последовательность операций: » t = -1:0.1:1; » х = sin (t) . *ехр (t) ; » bar(t, x, 1.0) Рис. 3.5. Результаты измерений Результат (диаграмма без промежутков между столбиками) показан на рис. 3.6. Примечание Функция barb строит горизонтальную столбчатую диаграмму, т. е. повернутую на 90 градусов. Для построения объемных диаграмм применяется функция ЬагЗ. Использование barb и ЬагЗ аналогично bar. Если требуется оценить вклад каждого из элементов вектора в общую сумму его элементов, то удобно построить круговую диаграмму при помощи функции pie,например: » data = [19.5 13.4 42.6 7.9]; >> pie(data) Гпава 3. Высокоуровневая графика 119 Рис. 3.6. Отображение функции в виде диаграммы В результате получается диаграмма, изображенная на рис. 3.7, в которой площади секторов отвечают процентному вкладу каждого из элементов вектора в общую сумму, т. е. MATLAB нормирует значения, вычисляя data/sum(data). Рис. 3.7. Круговая диаграмма 120 Часть I. Основы работы в MATLAP Текстовые пояснения к секторам диаграммы более информативны, чем только значений долей в процентах. Разместить пояснения можно двумя способами. Один из них — воспользоваться редактором графиков (редактированию графиков посвящена глава 4). Если же в результате работы приложения должна появиться готовая диаграмма с подписями данных, то придется применить специальные команды низкоуровневой графики (автоматическое размещение подписей к данным с использованием команд низкоуровневой графики объяснено в главе 9). Если сумма элементов вектора (аргумента pie) больше или равна единице, то MA TLAB производит нормировку и строит круг, состоящий из секторов. Если сумма меньше единицы, то нормировка не производится и получается круг с пропущенным сектором, закон как на рис. 3.8. Рис. 3.8. Круговая диаграмма с выброшенным сектором Часто необходимо отодвинуть от круга диаграммы сектор, соответствующий некоторому элементу. Это можно проделать, задав вторым аргументом функции pie вектор, состоящий из единиц и нулей, причем единица стоит в позиции, соответствующей номеру отделяемой части. Диаграмма с отделенным сектором (рис. 3.9), отвечающим значению 13.4, выводится в результате выполнения команд >> data = [19.5 13.4 42.6 7.9]; » parts = [0 1 О О] ; » pie(data, parts) Гпава 3. Высокоуровневая графика 121 Можно отделить несколько секторов, расположив единицы во вспомогательном векторе на подходящих позициях. Важно только, чтобы размеры векторов были одинаковы. Рис. 3,9. Круговая диаграмма с отделенным сектором В качестве упражнения напишите команды построения диаграммы с отделенным сектором, соответствующим максимальному значению среди элементов вектора, автоматически создав вспомогательный вектор. Используйте функции zeros для создания нулевого вектора той же длины, что х, и max. с двумя выходными аргументами для поиска номера максимального элемента в векторе х. Ниже приведена требуемая последовательность команд: » parts = zeros{size(data)); » [mx, ind] - max(lata); » parts(ind) = 1; » pie(data, parts) Визуализация векторных данных может быть осуществлена при помощи pie3 и ЬагЗ, которые строят трехмерные круговые и столбчатые диаграммы, например, команды » data = [24.1 10.2 17.4 11.9]; » parts = [1 0 0 0]; » pie3(data, parts) 122 Часть I. Основы работы в MATLAB приводят к появлению трехмерной круговой диаграммы с отделенным сектором, изображенной на рис. 3.10. Рис. 3.10. Трехмерная круговая диаграмма Гистограммы векторных данных Обработка данных включает вопрос о том, сколько данных попало в тот или иной интервал. Для получения наглядного представления о распределении данных служит функция hist. Например, команды » data = randn(100000, 1); » hist(data) заполняют вектор data числами, распределенными по нормальному закону, разбивают интервал, которому они принадлежат, на десять равных частей (по умолчанию) и строят гистограмму попадания чисел в каждый из интервалов, Получающаяся гистограмма приведена на рис. 3.11. Примечание Обратите внимание на масштаб вертикальной оси. Число Ю4 в левом верхнем углу значит, что значения по вертикальной оси умножаются на 10 000, т. е. по вертикальной оси отложены числа 5000, 10 000, 15 000 и т. д. Для увеличения числа интервалов следует в качестве второго аргумента указать число интервалов, например, hist (data, 50). Вместо автоматического разбиения на равные интервалы можно использовать собственное, Глава 3. Высокоуровневая графика 123 задав вторим аргументом вектор, содержащий центры интервалов. Команды » data = [0.9 1.0 1.1 1.2 1.4 2.4 3.0 3.3]; >> centers = [1.1 2.3 3.2]; » hist(data, centers) Рис. 3.11. Гистограмма распределения чисел по десяти интервалам Рис. 3.12. Гистограмма распределения по интерва там, задаваемым центрами 124 Часть I. Основы работы в MATLAB приводят к построению диаграммы, изображенной на рис. 3.9, где звездочки на горизонтальной оси отмечают центры интервалов. Часто необходимо задать не центры, а границы интервалов. Для построения таких гистограмм следует использовать функцию histc в сочетании с вышеописанной bar. Функция histc возвращает вектор, содержащий число величин, попавших в заданные вторым аргументом полуоткрытые интервалы с включенным левым концом. При помощи функции bar с дополнительным аргументом 'histc' полученный вектор представляется в виде гистотрам мы » data = [0.9 1.0 1.1 1.2 1.4 2.4 3.0 3.3]; » intervals = [1.1 2.0 3.2]; » count = histc(data, intervals) count = 3 2 0 » bar(intervals, count) В результате выполнения вышеописанных команд появляется гистограмма, приведенная на рис. 3.13. Рис. 3.13. Гистограмма распределения по интервалам, задаваемым границами Функцию his1 можно вызывать с одним или двумя выходными аргументами для получения массивов с информацией о распределении данных, при этом гистограмма не строится. В случае одного аргумента в него записыва Глава 3 Высокоуровневая графика 125 ется вектор, содержащий распределение данных по интервалам. С ледующий пример демонстрирует создание вектора count из пяти элементов, каждая компонента которого является числом элементов из data, попавших в один из пяти интервалов » data = randn(10000, 1); » count = hist(data, 5) count = 98 1915 5398 2434 155 Использование hist с двумя аргументами приводит к получению дополнительного вектора с информацией о расположении интервалов » [count, intervals] = hist(data, 5) count = 98 1915 5398 2434 155 intervals = -3.0520 -1.5614 -0.0707 1.4199 2.9106 Функция rose предназначена для построения угловых гистограмм (в полярных координатах). Аргументом функции rose является вектор значений в радианах. Угловые гистограммы дают наглядное представление о данных, связанных с измерениями направлений. Пусть, например, в течение суток каждый час измерялось направление ветра в градусах. Результат измерений содержится в файле winddir.dat. Для выяснения преобладающего направления используйте круговую гистограмму, считав значения из файла в вектор data и преобразовав их в значения в радианах. Файл winddir.dat сохраните в подкат алоге work основного каталога MATLAB » data = load('winddir.dat'); » datarad = data * pi/180; » rose(datarad} Получающаяся круговая гистограмма изображена на рис. 3.14. Из нее следует, что преобладающее направление примерно равно 100° Функция rose, так же как и hist, допускает получение информации о распределении по интервалам и о границах интервалов при вызове ее с выходными аргументами. Гистограмма в этом случае не отображается. Если производятся измерения группы величин, то результат представляет собой матрицу. Для отображения матричных данных используются те же функции, что и для векторных данных. Особенности работы с матричными данными изложены в следующем разделе. 126 Часть Основы работы в MATLAB Рис. 3.14. Круговая гистограмма распределения направлений ветра Представление матричных данных Предположим, что в матрице data, состоящей из четырех строк и трех столбцов, содержатся результаты измерений трех величин за четыре момента времени. Для построения столбчатой диаграммы данных примените функцию bar, задав в качестве аргумента массив data: » DATA = [1.2 1.4 1.1 3.7 3.5 3.1 2.0 2.8 2.2 4.2 4.7 4.1]; » bar (DATA) В результате появляется диаграмма сгруппированных данных, изображенная на рис. 3.15. На диаграмме расположены четыре группы данных, каждая из которых состоит из трех столбиков, соответствующих измеряемым величинам. Использование аргументов функции bar для визуализации матричных данных не отличается от случая векторных данных, разобранного в предыдущем разделе. Например, ширина интервалов между столбцами внутри группы задается при помощи числового параметра. Диаграмма с перекрывающимися столбцами внутри группы, приведенная на рис. 3.16, получена при ПОМОЩИ bar (DATA, 1.7). Глава 3. Высокоуровневая графика 127 Рис. 3.15. Диаграмма сгруппированных данных Рис. 3.16. Диаграмма сгруппированных данных с перекрывающимися столбцами Вклад каждой из величин в общую сумму внутри группы хорошо виден на диаграмме с накоплением, в которой каждая группа отображается в виде столбика, состоящего из частей. Число частей равно числу измеряемых величин, а их высота соответствует вкладу каждой величины в сумму внутри группы. На рис. 3.17 показана диаграмма с накоплением, построенная при помощи функции bar с дополнительным аргументом: bar (data, ' stack'). 128 Часть I. Основы работы в MATLAB Рис. 3.17. Диаграмма с накоплением Использование функции barh в случае матриц осуществляется так же, как и bar. Наглядная трехмерная столбцевая диаграмма, представляющая матричные данные. получается, если применить функцию ЬагЗ. Рис. 3.18. Дна! рамма с областями Проследить за изменением величин и одновременно узнать вклад значений в общую сумму позвотяет функция area, выводящая диаграмму с области- Глава 3. Высокоуровневая i оафика 1?9 ми. Запишите в матрицу gain поквартальную прибыль от продаж трех видов продукции и проследите за изменением прибыли при помощи диаграммы с областями (рис. 3.18). » GAIN = [12.0 23.0 48.0 10.6 31.5 49.0 8.0 25.0 78.0 9.6 29.0 61.5]; » area(GAIN) Дополнительные возможности для визуализации разреженных матриц и представлении матриц в виде изображений предоставляют функции spy и xmagesc (применение spy И imagesc описано в главе 2). Перейдем теперь к построению графиков функций одной и двух переменных. Г рафики функций MATLAB предоставляет обширные возможности для визуализации функций одной и двух переменных. Использование функций для построения графиков с минимальным набором задаваемых параметров (остальные MATLAB выбирает автоматически) приводит к получению качественных графиков. В этом разделе разобрано управление основными свойствами линий па графиках, которое осуществляется при помощи дополнительных параметров графических функций. Г рафики функций одной переменной MATLAB позволяет строить графики функций в линейном, логарифмическом и полулогарифмическом масштабах. Причем в одном окне можно построить графики нескольких функций, даже определенных на разных отрезках. Графики в линейном масштабе Построение графиков функций одной переменной в линейном масштабе осуществляется при помощи функции plot. В зависимости от входных аргументов функция plot позволяет строить один или несколько графиков, изменять цвет и стиль линий и добавлять маркеры на каждый график. В главе 2 приведен пример вывода простейшего графика функции одной пере 130 Часть I. Основы работы в MATLAB менной и объяснено, почему при вычислении вектора значений функции необходимо применять поэлементные операции » х = 0:0.05:1; » у = ехр(-х).*sin(10*x); » plotfx, у) Обратите внимание, что фактически мы строим график табличной функций, т. е. зависимость одного вектора от другого. Неудачный выбор шага по оси абсцисс может исказить реальную картину поведения функции. МА П АЬ предоставляет другую возможность (fpiot) для визуализации аналитически заданных функций с адаптивным подбором шага, учитывающим особенности поведения исследуемой функции (использование fpiot объяснено в главе 5). Итак, всюду в этой главе мы будем иметь дело с таблично заданными функциями одной и двух переменных. При создании таблицы значений следует уделять повышенное внимание выбору шага вычисления В этом убеждает простой пример. Требуется построить график функции /(.r) = e-T(sinx-l-0.1sin(1007Lr)) на отрезке [0,1]. Выберите сначала шаг 0.01 по оси х, а затем 1/99 (не забудьте пересчитать вектор со значениями функции). Первый график для шага 0.01 просто неверный (почему9). Сравнение нескольких функций легко производить, построив графики на одних координатных осях. Постройте графики функций /(л) = е-0’,А5т2л и g(x) = e-t)'2' sin2 л на отрезке [-2п, 2я]. Сгенерируйте вектор-строку значений аргумента х и вектор-строки f и д, содержащие значения функций. Команда plot с двумя парами аргументов приводит к графику, изображенному на рис. 3.19. » х = -2*pi:0.01:2*pi; » f = ехр(-0.1*х),*sin(x).л2; » g = ехр(-0.2*х),*sin(x).~2; » plot(x, f, х, g) Функции необязательно должны быть определены на одном и гом же отрезке. В этом случае при построении графиков MATLAB выбирает максимальный отрезок, содержащий остальные. Важно только в каждой паре векторов абсцисс и ординат указать соответствующие друг другу векторы, например: » xl = -pi:0.01:2*pi; >> f = exp(-0.l*xl).*sin(xl).Л2; » х2 = -2*pi:0.01:pi; » g = ехр(-0.2*х2).*sin(x2).л2; » plot(xl, f, x2 ,g) Гпава 3. Высокоуровневая графика 131 Рис. 3.14. Графики двух функций Аналогичным образом при помощи задания в plot через запятую пар аргументов: вектор абсцисс, вектор ординат, осуществляется построение графиков произвольного числа функций. к Примечание Использование plot с одним аргументом— вектором приводит к построению "графика вектора", т. е. зависимости значений элементов вектора от их номеров. Аргументом plot может быть и матрица, в этом случае на одни координатные оси выводятся графики столбцов. Иногда требуется сравнить поведение двух функций, значения которых сильно отличаются друг от друга. График функции с небольшими значениями практически сливается с осью абсцисс, и установить его вид не удается. В этой ситуации помогает функция piotyy, которая выводит графики в окно с двумя вертикальными осями, имеющими подходящий масштаб. Сравните, например, две функции /(л) = л-3 и F(a) = 1000-(x + 0.5) 4 » х = 0.5:0.01:3; » f = х.ж-3; » F = 1000*(х+0.5),~-4; » plctyytx, f ,х, F) 132 Часть I. Основы работы в MATlAB Результат приведен на рис. 3.20. При выполнении этого примера обратите внимание, что цвет графика совпадает с цветом соответствующей ему оси ординат. Рис. 3.20. Сравнение функций при помощи plot у у Функция plot использует линейный масштаб по обеим координатным осям. Однако MATLAB предоставляет пользователю возможность строить графики функций одной переменной в логарифмическом или полулогарифмическом масштабе. Г рафики в логарифмических масштабах Для построения графиков в логарифмическом и полулогарифмическом масштабах служат функции: □ loglog (логарифмический масштаб по обеим осям); □ semilogx (логарифмический масштаб только по оси абсцисс); □ semi logy (логарифмический масштаб только по оси ординат). Аргументы loglog, semilogx и semilogy задаются в виде пары векторов значений абсцисс и ординат так же, как для ф} нкции plot, описанной в предыдущем разделе. Гпава 3. Высокоуровневая графика 133 Постройте, например, графики функций /(х) = 1п0.5х и g (л) = sin In хна отрезке [0.1,5) в логарифмическом масштабе по оси х; » х = 0.1:0.01:10; » f = log(0.5*x); » g = sin(log(x)); » semilogxfx, f, x ,g) Получающиеся графики изображены на рис. 3.21. Рис. 3.21. Графики в полулогарифмической шкале Функции loglog и semiiogy вызываются аналогичным образом. Изменение свойств линий Построенные графики функций должны быть максимально удобными для восприятия. Часто требуется нанести маркеры, изменить цвет линий, а при подготовке к монохромной печати— задать тип линии (сплошная, пунктирная, штрих-пунктирная и т. д.). MATLAB предоставляет возможность управлять ВИДОМ ГрафИКОВ, ПОСТрОеНЛЫХ При ПОМОЩИ plot, loglog, semilogx и semiiogy, для чего служит дополнительный аргумент, помещаемый за каждой парой векторов. Этот аргумент заключается в апострофы и состоит из трех символов, которые определяют: цвет, тип маркера и тип линии. Используются одна, две или три позиции, в зависимости от требуемых 134 Часть I. Осногы рабэ!ы в MATLAB изменений. В табл. 3.1 приведены возможные значения данного аргумента с указанием результата Таблица, 3,1, Свойства линии Цвет Тип маркера Тип линии У m с г 9 b W к желтый розовый голубой красный зеленый синий белый черный О X S d V р h точка кружок крестик знак "плюс" звездочка квадрат ромб треугольник вершиной вниз треугольник вершиной вверх треугольник вершиной влево треугольник вершиной вправо пятиконечная звезда шестиконечная звезда — сплошная пунктирная штрих-пунктирная штриховая Например, для построения первого графика (рис. 3.19) красными точечными маркерами без линии, а второго пунктирной черной линией следует использовать команду plot (х, f, 'г.', х, g, ’ k:'). Результат приведен на рис. 3.22. Обратите внимание, что абсциссы маркеров совпадают со значениями аргумента, содержащимися в х. Это не всегда хорошо, ведь для получения гладкой кривой требуется вычислить вектор значений функции в достаточно большом числе точек, что приводит к слишком частому расположению маркеров или даже их перекрытию. Простой прием позволяет по Глава 3. Высокоуровневая графика 135 местить маркеры в заранее выбранные позиции. Строится два графика функции, один — сплошной линией, а второй — только маркерами для небольшого набора значений аргумента: » к = -1:0.01:1; » у = з!п(2*р1*х.Л2); » хт = -1:0.2:1; » ym = sin(2*pi*xm.A2); » plot(x, у, 'k', xm, ут, 'ко') Рис. 3.22. Изменение параметров линий Оформление графиков Удобство использования графиков во многом зависит от дополнительных элементов оформления: координатной сетки, подписей к осям, заголовка и легенды. Такие возможности реализуются либо с помощью дополнительных параметров, задающих свойства объектов, либо с помощью вспомогательных команд и функций. Перечислим основные из них. Сетка наносится командой grid ОП, функции xlabel, ylabel служат для размещения подписей к осям, a title— для заголовка. При необходимости сопроводить трафик легендой следует использовать функцию legend. Все перечисленные команды применимы к графикам как в линейном, так и в логарифмическом и полулогарифмическом масштабах. Следующие команды выводят графики из 136 Часть I. Основы работы в MATLAB менения суточной температуры, изображенные на рис. 3.23. которые снабжены всей необходимой информацией. » time = [0 4 7 9 10 11 12 13 13.5 14 14.5 15 16 17 18 20 22]; » tempi = [14 15 14 16 18 17 20 22 24 28 25 20 16 13 13 14 13]; » Cemp2 = [12 13 13 14 16 18 20 20 23 25 25 20 16 12 12 11 10]; » plot(time, tempi, 'го-', time, temp2, 'go-') » grid on » title('Суточные температуры') » xlabel('Время (час.)*) » уlabe.( "Температура (С)') » legend)'10 мая', 'll мая1) Рис. 3.23. График изменения суточной температуры Примечание J Символы кириллицы могут неправильно отображаться в нелокализован-ной версии MATLAB. Один из способов решения проблемы заключается в изменении текстового файла matlabrc.m, находящегося в подка галоге tool-ЬохУоса) основного каталога MATLAB. Используя любой текстовый редактор, добавьте в конец файла строку: set(0,'Defau]tAxesFontNanie','nMB_ шрифта. с_русскими_символами') (см. также примечание в разд. "Сервисные функции дняработы со строками" главы 8). Гпава 3. Высокоуровневая графика 137 При размещении легенды следует учесть, что порядок н количество аргументов команды legend должны соответствовать линиям на графике. Последним дополнительным аргументом legend может быть положение легенды в графическом окне: П -1 — вне графика в правом верхнем углу графического окна; □ О — выбирается лучшее положение в пределах графика так, чтобы как можно меньше перекрывать сами графики; □ 1 — в верхнем правом углу графика (это положение используется по умолчанию); □ 2 — в верхнем левом углу графика; П 3 — в нижнем левом углу графика; □ 4 — в нижнем правом углу графика. Такой способ задания места легенды был принят в прежних версиях MATLAB и поддерживается в версии 7. Кроме того, появилась другая возможность для указания положения легенды за счет привлечения ее свойства Location. Восемнадцать допустимых его значений приведены в справочной системе. Для того чтобы посмотреть их, достаточно набрать в командной строке help legend или обратиться к аналогичной информации в интерактивной справочной системе, воспользовавшись индексным поиском по слову legend. Например, для вывода легенды справа от осей следует выбрать значение 'EastOutside'. >> legend!'10 мая', 'll мая', 'Location', 'EastOutside') В заголовке графика, легенде и подписях осей допускается добавление формул и изменение стилей шрифта при помощи формата ТеХ, подробно об этом написано далее. Г рафики параметрических и кусочно-заданных функций Для построения функций, заданных параметрически, следует сперва сгенерировать вектор значений аргумента. Затем необходимо вычислить значения функций и записать их в векторы, которые и надо использовать в качестве аргументов plot. График функции ^(/) = O.5 sinr, y(z) = 0.7-cosz для zg[0, 2л] (эллипс), приведенный на рис. 3.24, получается при помощи следующих команд: » t - 0:0.01:2*pi; » х = 0.5*sin(t); 138 Часть I. Основы работы в MATLAB » у = 0.7*cos(t); » ylctfx, у) Рис. 3.24. График параметрически заданной функции Для того чтобы проверить свои знания о работе с массивами, постройте график кусочно-заданной функции (кусочно-функциональной зависимости): л-sinx, -2л<х<-л; У(х) = -п<х< л; Л-Sin3 X, л<х<2л. Сначала необходимо вычислить каждую из трех ветвей, т. е. фактически получить три пары массивов xl и yi, х2 и у2, хЗ и уЗ, затем объединить значения абсцисс в вектор х, а значения ординат в у и вывести график функции, задаваемой парой массивов х и у: » xl = -2*pi:pi/30:-pi; » yl = pi*sin(xl); » х2 = -pi: pi/30:pi; » у2 = pi-abs(x2); » хЗ = pi: pi/30:2*pi; » уЗ = pi*sin(xl).л3; » x = [xl x2 хЗ); Глава 3. Высокоуровневая графика 139 » У = [у1 у2 уЗ]; >> plot(x, у) При таком подходе получается график, изображенный на рис. 3.25. Рис. 3.25. График функции, заданной кусочным образом Рис. 3.26. График функции, заданной кусочным образом (разные цвета и маркеры ветвей) 140 Часть I. Основы работы в MATlAB Можно поступить и по-другому — построить графики трех ветвей, как три различные функции, каждую своим цветом и маркером: » plot(xl, yl, ’г+', х2, у2, *кх', хЗ, уЗ, 'bs') В этом случае график имеет более наглядный вид. т. к. каждая ветвь функции отображается своим цветом (рис. 3.26). Г рафики функций двух переменных MATLAB предоставляет различные способы визуализации функций двух переменных — построение грехмерных графиков и линий уровня, параметрически заданных линий и поверхностей. Трехчерные графики функций В главе 2 был разобран простой пример построения трехмерного графика при помощи функции mesh. Напомним, что для отображения функции двух переменных следует: 1. Сгенерировать матрицы с координатами узлов сетки на прямоугольной области определения функции. 2. Вычислить функцию в узлах сетки и записать полученные значения в матрицу. 3. Использовать одну из графических функций MATLAB, например, mesh. 4. Нанести на график дополнительную информацию, в частности, соответствие цветов значениям функции. Сетка генерируется функцией meshgrid, вызываемой с двумя входными и двумя выходными аргументами. Входными аргументами являются векторы, элементы которых соответствуют сетке на прямоугольной области построения функции. Если область построения функции — квадрат и шаг сетки по обоим направлениям одинаков, то допустимо указать один аргумент, например: [х, y] = meshgrid(-1:0.05:1). Выходными аргументами являются матрицы с абсциссами и ординатами узлов сезки. Как было объяснено в главе 2, их структура влечет необходимость использования поэлементных операций при вычислении матрицы со значениями функции в узлах сетки. Изучим основные возможности, предоставляемые MATLAB для визуализации функций двух переменных, на примере построения графика г(л, у) = 4 sin 2лл cos 1.5 лу (1 - х2 I у (1 - у) Г: лва 3. Высокоуровневая графика 141 на прямоугольной области определения ле[~1, 1], ys[0, 1]. Подготовьте матрицы с координатами узлов сетки и значениями функции: » [X, Y] = meshgrid(-1:0.05:1, 0:0.05:1); » Z = 4*sin(2*pi*X),*cos(1.5*pi*Y).*(1 - X.A2).*Y.*(1 - Y) ; Для построения каркасной поверхности, изображенной на рис. 3.27, используется функция mesh, вызываемая с тремя аргументами » mesh(X, Y, Z) Рис. 3.27. Каркасная поверхность (mesh) Интерфейс функции mesh и аналогичных ей графических функций, которые описаны ниже, достаточно гибок. Кроме приведенного способа обращения к mesh с тремя входными аргументами (матрицами), допускается также ряд других. В частности, если указан только один входной аргумент— матрица, то на осях абсцисс и ординат откладываются значения, соответственно, столбцевых и строчных индексов ее элементов. Вместо номеров строк и столбцов можно указать векторы, состоящие из требуемых чисел. Эти векторы задаются в первых двух входных аргументах, а матрица — в третьем. Цве г чиний поверхности соответствует значениям функции. По умолчанию рисуется только видимая часть поверхности. При помощи команды hidden off можно сделать каркасную поверхность "прозрачной", добавив 142 Часть /. Основы работы в MATLAB скрытую от взора часть (рис. 3.28), Команда hidden on убирает невидимую часть поверхности, возвращая графику прежний вид. Рис. 3.28. Прозрачная каркасная поверхность (mesh, hidden off) Функция surf строит каркасную поверхность графика функции и заливает каждую клетку поверхности определенным цветом, зависящим от значения функции в точках, соответствующих углам клетки. Команда » surf(X, Y, Z) приводит к графику, изображенному на рис. 3.29. В пределах каждой клетки цвет постоянный. Команда shading flat позволяет убрать каркасные линии. Для получения поверхности, плавно залитой цветом, зависящим от значений функции (рис. 3.30), предназначена команда shading interp. При помощи shading faceted можно вернуться к виду поверхности, приведенной на рис. 3.29. Трехмерные графики, изображенные на рис. 3.27—3.30, удобны для получения представления о форме поверхности, однако по ним трудно судить о значениях функции. В MATLAB определена команда colo-bar. которая выводит рядом с графиком цветовую шкалу, устанавливающую соответствие между цветом и значением функции Постройте при помощи surf график поверхности и дополните его информацией о цвете. » surr(X, Y, Z) » colorbar Гпава 3. Высокоуровневая графика 143 Рис. 3.29. Каркасная поверхность, залитая цветом (surf) Рис. 3.30. Поверхность, залитая цветом (surf, shading interp) Рисунок 3.31 иллюстрирует получающийся результат. Окно вывода графика несколько уменьшается из-за того, что рядом размещается цветовая шкала. Команду colorbar можно применять в сочетании со всеми функциями, строящими т рехмерные объекты. Однако, пользуясь графиком, изображенным на рис. 3.31, трудно сделать вывод о значении функции в той или иной точке плоскости xv. Более информативным является график, содержащий линии уровня функции, т. е. 144 Часть I. Основы работы в MATL АВ линии постоянства значений функции, на плоскости ху (рис. 3.32). Для получения такого графика следует использовать meshc или surfc вместо mesh или surf соответственно; » surfc(X, Y, Z) » colorbar Рис. 3.31. Соответствие цвета и значений функции (colorbar) Рис. 3.32. График поверхности с линиями уровня на плоскости ху (surfc) Глава 3. Высокоуровневая графика 145 MATL AB позволяет построить поверхность, состоящую из линий уровня, при помощи функции contours. Эту функцию можно использовать так же, как и описанные выше mesh, surf, meshc и surfc с тремя аргументами. При этом число линий уровня выбирается автоматически. Имеется возможность задать четвертым аргументом в contour3 либо число линий уровня, либо вектор, элементы которого равны значениям функции, отображаемым в виде линий уровня. Задание вектора удобно, когда требуется исследовать поведение функции в некоторой области ее значений (срез функции) Постройте, например, поверхность, состоящую из линий уровня, соответствующих значениям функции от 0 до 0.5 с шагом 0.01: » levels = 0:0.01:0.5; » contour3(X, Y, Z, levels) » colorbar Результат приведен на рис. 3.33. Рис. 3.33. График среза функции, состоящий из линий уровня (contours) Часто более содержательную информацию о числовых значениях дают плоские контурные графики с линиями уровня исследуемой функции. Контурные графики MA1LAB предоставляет возможность получать различные типы контурных графиков при помощи функций contour и contourf. Разберем их возможно- 146 Часть!. Основы работы в МА TLAB сти на примере функции из предыдущего раздела. Использование contour с тремя аргументами » contour(X, Y, Z) приводит к графику, изображенному на рис. 3.34, на котором показаны линии уровня на плоскости ху. Рис. 3.34. Линии уровня функции (contour) Такой график является малоинформативным, он не позволяет узнать значения функции на каждой из линий уровня. Использование команды colorbar также не позволит точно определить значения функции. Каждую линию уровня можно снабдить ярлыком с соответствующим значением исследуемой функции при помощи определенной в MATLAB функции clabel. Функция clabel вызывается с двумя аргументами: матрицей, содержащей информацию о линиях уровня и указателем на график, на котором следует нанести разметку. Нам пока ничего не говорят эти слова. Про указатели будет сказано в главах, посвященных созданию собственных приложений, а про структуру матрицы с информацией о линиях уровня можно узнать при помощи help. Оказывается, пользователю не нужно самому создавать аргументы clabel. Функция contour, вызванная с двумя выходными параметрами, не только строит линии уровня, но и находит требуемые для clabel параметры. Используйте contour с выходными аргументами (в матрице CMatr содержится информация о линиях уровня, а в векторе h — указатели). За Глава 5 Рысор^уровневая графика 147 вершите вызов contour точкой с запятой для подавления вывода на экран значений выходных параметров и нанесите на график сетку: » [CMatr, h] = contoui(X, Y, Z); >> clabel(CMatr, h) >> grid on Полученный график приведен на рис. 3.35. Рис. 3.35. Маркированные линии уровня (contour, clabel) Дополнительным аргументом функции contour (так же, как и contour3, описанной выше) может быть или число линий уровня, или вектор, содержащий значения функции, для которых требуется построить линии уровня. Наглядную информацию об изменении функции дает заливка прямоугольной области определения цветом, зависящим от значения функции в точках плоскости. Для построения таких графиков предназначена функция contourf, использование которой не отличается от применения contour. В следующем примере выводится график, изображенный на рис. 3.36, который состоит из двадцати линий уровня, а промежутки между ними заполнены цветами, соответствующими значениям исследуемой функции: » contourfix, Y, Z, 20) » colorbar 6 Зак во 148 Часть I. Основы работы в MATLAB Рис. 3.36. Заливка цветом промежутков Между ЛИНИЯМИ УРОВНЯ (contour.f) Оформление графика Простым, но эффективным способом изменения цветового оформления графика является установка цветовой палитры при помощи функции colormap. Следующий пример демонстрирует, как подготовить график функции для печати на монохромном принтере, используя палитру gray. Результат приведен на рис. 3.37. » surfc(X, Y, Z) >> colorbar » colormap(gray) » title('График функции z(x, у)') » xlabel('x') » ylabel('у') » zlaoel('z') Обратите внимание, что команда colormap (gray) изменяет палитру графического окна, т. е. следующие графики будут выводиться в этом окне также в серых тонах. Для восстановления первоначального значения палитры следует применить команду colormap('default'). Цветовые палитры, доступные в MATLAB, приведены в табл. 3.2. Гпава 3. Высокоуровневая графика 149 Рис. 3.37. Г рафик с нанесенными обозначениями (палитра gray) Таблица 3.2. Палитры цвета Палитра Изменение цвета autumn Плавное изменение: красный-оранжевый-желтый bone Похожа на палитру gray, но с легким оттенком синего цвета colorcube Каждый цвет изменяется от темного к яркому cool Оттенки голубого и пурпурного цветов copper Оттенки медного цвета flag Циклическое изменение: красный-белый-синий-черный gray Оттенки серого hot Плавное изменение: черный-красный-оранжевый-желтый-белый hsv Плавное изменение (как цвета радуги) jet Плавное изменение: синий-голубой-зеленый-желтый-красиый pink Похожа на палитру gray, но с легким оттенком коричневого цвета prism Циклическое изменение: красный-оранжевый-желтый-зеленый-синий-фиолетовый spring Оттенки пурпурного и желтого summer Оттенки зеленого и жал того 150 Часть I. Основы работы в MATLAB Таблица 3.2 (окончание) Палитра Изменение цве.а vga Палитра Windows из шестнадцати цветов white Один белый цвет winter Оттенки синего и зеленого Поэкспериментируйте самостоятельно, задавая различные палитры цвета и способы построения функций. Добавление заголовка графика и подписей к осям осуществляется теми же командами title, xlabel, ylabel, что применялись при визуализации функций одной переменной. Несложно догадаться, что для вертикальной оси предназначена команда zlabel. Часто требуется добавить формулу в заголовок или рядом с вертикальной осью. Использование в аргументах команд некоторых математических обозначений в формате ТеХ позволяет добавлять формулы на график. В заголовок графика, изображенного на рис. 3.37, поместите формулу отображаемой ф) нкции z = 4 - sin 2ти- • cos 1.5лу • (1 - х2 j у • (1 - у). Используйте команду (три точки служат для размещения команды в двух строках; если она целиком помещается в командной строке, то ее можно набирать без переноса) >> title(’4 sin(2pi{itx)) cos(1.5pi{ity)) (1 - {ity}"{2})... {ity) (1 -{ity})’) которая приводит к появлению требуемого заголовка. Если вам знаком ТеХ, то вопросов возникнуть не должно. Если же вы не работаете в ТеХ, то просто используйте правила набора формул и изменения свойств шрифтов, приведенные в табл. 3.3. Таблица 3.3. Правила набора формул и изменения свойств шрифтов Что гребуется Команда ТеХ Результат Выделение курсивом одного символа или текста [itx) X 1.2(itP) 1.2Р {МгГиперболический} синус Гиперболический синус Глава 3. Вь.сокоуровневач графика 151 Таблица 3.3 (окончание) Что требуется Команда ТеХ Результат Выделение жирным шрифтом одного символа или текста Шаблон матрицы (bfM) Шаблон матрицы M {bfA4X) фильтра АЧХ фильтра Набор символа или текста жирным курсивом Векторы {bfitx} и {bfity} Векторы х и у {bfiСОптимальная} кривая Оптимальная кривая Изменение шрифта и его размера ffontname{arial)fonts ize{14}Z-функция) Z-функция Степень, верхний индекс хл{2) х2 )itx)A)2.5) л2-5 (ite)л{it-x) е х Нижний индекс f_)5) <5 f_{itxx) Примечание Прямой шрифт текста в ТеХ устанавливается командой пп. Для получения обычного прямого шрифта можно не указывать никаких команд. Возможно использование {реческих букв и специальных символов, например title ('Зависимость при a=pi') приводит к заголовку: "Зависимость при а = л". В табл. 3.4 и 3.5 приведены команды ТеХ для вставки некоторых прописных и строчных греческих букв и специальных символов. Таблица 3.4. Греческие буквы Команда Символ Команда Символ Команда Символ alpha а lambda X chi Z beta Р mu В psi V gamma У nu V omega CD 152 Часть I. Основы работы в MATLAB Таблица 3.4 (окончание) Команда Символ Команда Символ Команда Символ delta 5 xi Gamma Г epsilon E rho P Delta Д eta n sigma о Theta 0 theta 0 tau T Lambda Л kappa к phi <p Phi Ф Таблица 3.5. Специальные символы Команда Символ Команда Символ lfcq < J eftrightarrow <-> geq > leftarrow <— pm ± rightarrow propto оо downarrow г partial э uparrow т Текст в формате ТеХ можно использовать в качестве аргумента функций title, xlabel, ylabel при построении двумерных графиков и в тех же командах вмест е с zlabel для трехмерных графиков. В качестве упражнения создайте график, изображенный на рис. 3.38. Ниже приведена последовательность команд, обеспечивающих требуемый результат. » [X. Y] = meshgrid(O:0.05:1, -2:0.05:0); » Z = -ехр(-У.'’2) . *cos (3*pi*X) . *Х. * (1 - X).*Y; » surfc(X, Y, Z) » colormap(gray) » cclorbar » title('График (itz) = — {ite}*{-{ity}Л{2}} cos(3 pi {itx})... {Xitx} (1 - {itx)> {ity}') » xlabel ( 1 x1 ) » ylabel('у1) » zlabel(' z' ) Гпава 3. Высокоуровневая графика 153 Рис. 3.38. Задание для самостоятельной работы По умолчанию в MATLAB поддерживается основной формат ТеХ, однако имеется возможность перейти к расширенному формату LaTeX для набора более сложных формул. Мы вернемся к этому вопросу в главе 9, поскольку он связан с обращением к свойствам текстовых объектов, каковыми являются заголовок и подписи к осям (см. разд. "Текстовые объекты" главы 9). Поворот графика, изменение точки обзора Примеры, приведенные в предыдущих разделах, свидетельствуют о том, что при построении трехмерных поверхностей оси координат располагаются всегда одинаковым образом. Часть поверхности остается при этом скрытой. Для получения полной информации о поверхности ее желательно "осмотреть" со всех сторон. Положение наблюдателя за системой координат, изображенной на рис. 3.36, характеризуется двумя углами: азимутом (Az) и углом возвышения (Е1). Азимут отсчитывается от оси, противоположной у, а угол возвышения от плоскости ху. На рис. З.ЗУ положительные направления отсчета обозначены стрелками. Изменение положения наблюдателя относительно графика в MATLAB осуществляет функция view. Аргументами view являются азимут и угол воз 154 Часть I. Основы работы в МА FLAB вышения, отсчитываемые в градусах. По умолчанию Л? = -37 5°, Ei =30°. Для того чтобы узнать текущее положение наблюдателя, следует вызвать view с двумя выходными аргументами: » [Az, El] = vj ew Az = -37.5000 El = 30 Рис. 3.39. Положение наблюдателя Положение наблюдателя задается входными аргументами view. Посмотрите, например, на поверхность, изображенную на рис. 3.38, возвышаясь над биссектрисой первого квадранта плоскости ху под углом 45°, для того чтобы увидеть скрытую часть поверхности. Используйте команду view (135,45}, при этом получается график, приведенный на рис. 3.40. Разверните график поверхности так, как показано на рис. 3.41, чтобы посмотреть на него вдоль оси у со стороны плоскости гг . Несложно догадаться, что необходимо использовать viewto, 0). Потренируйтесь самостоятельно, наблюдая за графиком поверхности из различных точек. Глава 3 Высокоуровневая графика 155 Рис. 3.40. График с точки зрения наблюдателя с Az = 135°, Е1 = 45- Рис. 3.41. Наблюдатель смотрит на i рафик вдоль оси у со стороны плоскости xz 156 Часть I, Основы работы в MATLAB Построение параметрически заданных поверхностей и линий MATLAB позволяет строить трехмерные линии, определенные формулами: л = л(г), y = y(t),z = z(t), fc], н поверхности, задаваемые зависимостями л = х(н, v), y = y(u,v), z = z(m, v), ие[а,b], ve[c, Jj. Функция plot3 визуализирует параметрически заданные линии, используя в качестве аргументов векторы, содержащие значения функций х(г). у(г) и z(z), вычисленные для значений параметра t. Сначала следует сформировать вектор t, что проще всего сделать, используя заполнение с постоянным шагом при помощи двоеточия, а затем вычислить и записать в векторы соответствующие значения функции. Получите, например график линии л=е 5o'/5osin/, у = е 50l/50cosr, z = f, re [0,100]. Используйте для этого следующие команды: » t = 0:0.1:100; » х = exp(at>s(t - 50)/50).*sin(t); » у = exp(abs(t - 50)/50).*cos(t); » z = t; » plot3(x, y, z) » grid on В результате выводится т рафик, изображенный на рис. 3.42. Также имеется возможность изменять тип и цвет линии, добавлять маркеры (см разд. "Изменение свойсп ie линий " данной главы). Например, plot3 (х, у, ' г:') рисует красную пунктирную линию. Параметрически заданную поверхность можно построить при помощи любой из функций, предназначенных для отображения трехмерных графиков. Важно только правильно подготовить аргументы. Дело в том, что функции 11 У («'') могут быть многозначны, что надо учесть при создании матриц с информацией о расположении узлов сетки на области построения и матрицы, содержащей значения функции z(w.i) в этих точках. Поставим задачу отобразить поверхность (конус), определенную зависимостями г(«,г) = 0.3 и-cost. у(и.г) = 0.3-и-sinv , z(u-.v) = 0.6-h , и.з’Е [-2л, 2л]. Гпава 3. Высокоуровневая графика 157 Рис. 3.42. Параметрически заданная линия (plots) Сгенерируйте при помощи двоеточия вектор-столбец и вектор-строку, содержащие значения параметров на заданном интервале (важно, что и — вектор-столбец, a v — вектор-строка!): » и = (-2*pi:0.l*pi:2*pi)'; » v = [-2*pi:0.1*pi:2*pi]; Далее сформируйте матрицы х, Y, содержащие значения функций y(w,v) в точках, соответствующих значениям параметров при помощи внешнего произведения векторов (звездочка без точки): » X = 0.3*u*cos(v); » Y = 0.3*u*sin(v); Матрица z должна быть того же размера, что х и Y и, кроме того, она должна содержать значения, соответствующие значениям параметров. Если бы в функцию z(«,v) входило произведение и и v, то матрицу z можно было заполнить аналогично х и у при помощи внешнего произведения. С другой стороны, функцию z(w,v)можно представить в виде ?(«,v) = 0.6-«-g(v), где g(v) = l. Поэтому для вычисления z снова примените внешнее произведение на вектор-строку той же размерности, что v, состоящую из единиц; » Z = 0. 6*u‘ones(size(v)); 158 Часть I. Основы работы в MATLAB Все требуемые матрицы созданы. Используйте теперь любую из описанных выше функций для построения трехмерных графиков. Например, последо-ват ельность команд » surf(X, Y, Z) » colorbar >> xlabel(’itx = 0.3 » ylabel- 0.3 » zlabel('itz = 0.6 itu cos itv') itu sin itv') itu ') приводит к графику, изображенному на рис. 3.43. Рис. 3.43. График параметрически заданной поверхности Псстрочте самостоятельно прозрачную каркасную поверхность эллипсоида. заданного соотношениями л(и,|) = cosn-cosv, = 0.7cosh-sinv, z(M,v) = 0.8-sinH, «,ve[—2 л, 2л]. Требуемый результат позволяет получить следующая последовательность команд: » u = (-pi:0.1*pi:pi)'; » v = -pi:0.l*pi:pi; » X = cos(u)*cos(v); » Y = 0.9*cos(u)*sin(v); » Z = 0.8*sin(u)’tones(size(v)) ; » mesh(X, Y, Z) » hidden off Глава 3. Высокоуровневая графика 759 Все способы построения трехмерных графиков, описанные выше, изменяют цвет поверхности в зависимости от значений функции, что приводит к поверхности, выглядящей не совсем естественно. В то же время MATLAB позволяет получить очень наглядное изображение поверхности в трехмерном пространстве, освещенной с одной или нескольких сторон. Построение освещенной поверхности Предположим, что поверхность графика функции сделана из материала с определенными свойствами отражения и поглощения света, и, кроме того, можно управлять расположением источника света. Эти две возможности вместе с поворотом графика позволяют получить естественно выглядящую поверхность, повернутую и освешенную под нужным углом. Для построения освещенной поверхности применяется функция surf 1. Постройте освещенную поверхность, задаваемую на прямоугольной области ле[-1, 1], уе [О, 1] формулой z (х, у ) = 4 • sin 2лх • cos 1.5яу • - х2 ) • у • (1 — у ). При использовании surfi удобно задавать цветовые палитры: copper, bone, gray, pink, в которых интенсивность цвета изменяется линейно. Для получения плавно изменяющихся оттенков следует использовать shading interp. Команды, приведенные ниже, приводят к получению требуемой освещенной поверхности, изображенной на рис. 3.44. » [X, Y] = meshgri<3(-l:0.05:1, 0:0.05:1); » Z = 4*sin(2*pi*X).*cos(1.5*pi*Y).*(1 - Х.Л2).*У.*(1 - Y) ; » surfi(X, Y, Z) » colormap('copper1) » shading interp » xlabel('x') » ylabel('у') » zlabel(1 z’) По умолчанию источник света имеет азимут, больший на 45°, чем наблюдатель, и тот же угол возвышения. Дополнительным четвертым аргументом surfi может быть вектор-строка из двух элементов — азимута и угла возвышения источника света. Измените, например, азимут источника на -90° по отношению к наблюдателю, а угол возвышения установите в ноль. 160 Часть I. Основы работы в MATLAB Это можно проделать при помощи команд » [Ав, El] = view; » surflfx, Y, Z, [Az-90, 0]) » shading interp В результате получается освещенная поверхность, изображенная на рис. 3.45. Рис. 3.44. Освещенная поверхность Рис. 3.45. Изменение положения источника света Гпава 3, Высокоуровневая графика 161 Анимированные графики При изучении движения точки на плоскости или в трехмерном пространстве полезно не только построить траекторию точки, но и следить за движением точки по траектории. MATLAB предоставляет возможность получить анимированный график, на котором кружок, обозначающий то1,ку, перемещается на плоскости или в пространстве, оставляя за собой след в виде линии — траектории движения. График похож на летящую комету с хвостом. Для построения анимированных графиков применяются функции comet и сотегз. Постройте, например, траекторию движения точки в течение 10 секунд, координаты которой изменяются по закону , , sin t , ч cos/ х(/) =--- v(/) =-----. v’ / + 1 v 7 / + 1 Действуйте точно так же, как при построении графика параметрически заданной функции, но для визуализации результата используйте commit: » t = [0:0.001:10]; » х = sin(t)./(t+1); » у = cos(t)./(t+1); » comet(x, y) При выполнении последней команды следите за тем, чтобы окно с графиком было поверх остальных окон. Окончательный вид траектории движения приведен на рис. 3.46. Рис. 3.46. Окончательный вид траектории движения (commet) 162 Часть I. Основы работы в MATLAB Скоростью движения кружка можно управлять, задавая различные шаги при автоматическом заполнении вектора, соответствующего времени. Использование comet с одним аргументом (вектором) приводит к построению динамически рисующегося графика значений элементов номера в зависимости от их номеров. Функцию comet можно вызвать и с третьим дополнительным числовым параметром, который задает длину хвоста кометы. По умолчанию он равен 0.1. Обратите внимание, что при изменении размеров графического окна или при его минимизации и посзсдующем восстановлении траектория движения пропадает. Это связано со способом, который применяет MATLAB для построения графика. Получите самостоятельно траекторию движения фиксированной точки на окружности, катящейся по прямой (циклоиду). Циклоида описывается параметрическими зависимостями л-(г) = Т — sin/, y(/) = l-cosr. Для построения траектории точки, перемещающейся в пространстве, используется функция comet3. Пусть координаты точки в течение 100 секунд изменялись по следующему закону .г = e-l,-50l/51) sin 1, у = e-lz-5f)l/50 cost, z — t. Отобразите траекторию движения точки, применяя приведенные ниже команды: » t = 0:0.1:100; » х = exp(abs{t - 50)/50).*sin(t); » у = exp(abs(t - 50)/50).*cos(t); » z = t; » comet3{x, y, z) Функцию comet3 можно вызывать с четвертым числовым аргументом, который так же, как и в случае comer задает длину хвоста кометы. Работа с несколькими графиками Во всех примерах, приведенных в предыдущих разделах, графики выводились в специальное графическое окно с заголовком Figure 1. При следующем построении графика предыдущий пропадал, а новый выводился в то же самое окно. MATLAB предоставляет следующие возможности работы с несколькими I рафиками: □ вывод каждого графика в свое окно; □ вывод нескольких графиков в одно окно (на одни координатные оси); Гпава 3. Высокоуровневая графика 163 □ отображение в пределах одного окна нескольких графиков, каждого на своих осях. Вывод графиков в отдельные окна Команда figure, определенная в MATLAB, служит для создания пустого графического окна и отображения его на экране. Окно становится текущим, т. е. все последующие графические функции будут осуществлять построение графиков в этом окне. Для получения нового графического окна следует снова использовать figure. Например, последовательность команд » [X, Y] = meshgridl-1:0.05:1, 0:0.05:1); » Z = 4*sin(2*pi‘X).*cos(1.5*pi*Y).*(1 - X.~2).*Y.*(1 - Y); » figure » mesh(X, Y, Z) » figure » surfi(X, Y, Z) приводит к появлению на экране двух графических окон: Figure 1, содержащего каркасную поверхность, и Figure 2 с освещенной поверхностью. Окно Figure 2 является текущим, т. к. было создано последним. Команды, набираемые далее, например » colormap('copper1) » shading interp приведут к изменениям именно в этом окне. Для того чтобы сделать графическое окно Figure 1 текущим, следует щелкнуть на нем мышкой, вернуться в рабочую среду MATLAB и продолжать ввод команд. Команды повлекут изменения в окне Figure 1. Для очистки всего текущего окна используется команда elf (сокращение от clear figure), а для того, чтобы убрать только график, но оставить оси, заголовок и названия осей, следует применить cla (сокращение от clear axes). Вышеописанным способом можно получить сколько угодно графических окон и вывести в них графики различных функций или визуализировать декторные и матричные данные. Однако для изменения того или иного графика придется искать его окно на экране и делать его текущим при помощи щелчка мыши. Есть более универсальный и удобный способ работы с несколькими окнами. При создании каждого нового графического окна при помощи figure следует вызвать ее с выходным аргументом. Этот аргумент называется в MATLAB указателем на графическое окно. Значением выходного аргумента является число, совпадающее с номером графическою окна. 164 Часть I. Основы работы в MATLAB Для того чтобы сделать графическое окно текущим, следует вызвать figure, указав в качестве входного аргумента указатель на требуемое графическое окно. Разберите использование указателей на следующем примере. Требуется создать два графических окна, построить в них графики функций f = sinx и g = In х, а затем оформить их — дать за] оловки и нанести сетку на втор« !Й график (рис. 3.47). Последовательность команд, приведенная ниже, позволяет получить желаемый результат. » sinGr = figure; » InGr = figure; » x = [0.1:0.05:10]; » f = sin(x); » g = log(x); » figure(sinGr) » plot(x, f) » figure(InGr) » plot(x, g) » figure(sinGr) » ticle('itf = sinXitx') » figure(InGr) » title)'itg = lnitx') » grid on Рис. 3.47. Вывод графиков в разные окна Гпава 3. Высокоуровневая графика 165 Для того чтобы очистить графическое окно с указателем inGr, следует использовать olf(InGr). Удаление графика из первого окна, на которое указывает sinGr, Производится при ПОМОЩИ cla (sinGr). Bb i од нескольких графиков на одни оси Возможность отображения нескольких графиков функций одной переменной На ОДНИХ ОСЯХ ИСПОЛЬЗОВаЛаСЬ при изучении plot, plotyy, semiiogx, semilogy, loglog. Перечисленные команды позволяют выводить графики нескольких функций, задавая соответствующие векторные аргументы парами, например, plot (х, f, х, g). Однако при построении трехмерных графиков или различных типов графиков объединять их на одних осях не было возможности. Для объединения графиков предназначена команда hold on, которую нужно задать перед построением следующего графика. В следу кэшем примере выводится пересечение плоскости и конуса, заданного параметрически. Результат приведен на рис. 3.48. » u = (-2*pi:0.1*pi:2*pi)'; » v = -2*pi:0.l*pi:2*pi; » X = 0.3*u*cos(v); » Y = 0.3*u*sin(v); » Z = 0.6*u*ones(size(v)); » surf(X, Y, Z) » [X, Y] = meshgr‘d(-2:0.1:2); » Z = 0.5*X + 0.4*Y; » hold on » mesh{x, Y, Z) » hidden off Команда hidden off применена для того, чтобы показать часть конуса, находящуюся под плоскостью. Обратите внимание, что hold on распространяется на все последующие выводы графиков. Для размещения графиков на новых осях следует выполнить команду hold off Команда hold on может применяться и для расположения нескольких графиков функций одной переменной, например, » plot(x, f, х, g) эквивалентно последовательности » plot(x, f) » hold on » plot(x, g) 166 Часть I. Основы работы в МА TLAB Рис. 3.48. Пересечение плоскости и конуса Несколько графиков в одном графическом окне MATLAB позволяет разместить в графическом окне несколько осей и вывести на них различные графики. Самый простой способ заключается в разбиении окна на определенное число частей по вертикали и горизонтали с использованием функции subplot, которая располагает оси в виде матрицы и используется с тремя параметрами: subplot (i, j, n). Здесь i и j — число подграфиков по вертикали и горизонтали, ап— номер подграфика, который надо сделать текущим. Номер отсчитывается от левого верхнего угла построчно. Последовательность вызовов » subplot(3, 2, 1) » subplot(3, 2, 2) » subplot (3, 2, 6) приводит к размещению шести осей координат в графическом окне (рис 3.49). Текущими являются последние созданные оси, т. е. все графические функции будут осуществлять вывод на правые нижние оси. Для вывода графиков на другие осн их надо сделать текущими. Это достигается либо щелчком мыши по ним, либо повторным вызовом функции subplot. Например, команда subplot (3, 2, 4} предполагает наличие шести подграфиков и делает четвертый текущим, что схематично изображено на рис. 3.49. Глава 3. Высокоуровневая графика 167 Рис. 3.49. Схема расположения подграфиков после выполнения команды subplot (3, 2, 4) После выполнения subplot (3, 2, 4) все графические функции будут осуществлять вывод именно в этот подграфик. В качестве завершающего упражнения постройте графики функции z (х, у) = 4 • sin 2лх cos 1.5ity • (1 - х2 ) • у • (1 - у) на прямоугольной области определения хе [-1, 1], [О, 1] всеми извест- ными способами, размещая их на отдельных подграфиках. Названия команд, применяемых для построения графиков, включите в заголовки подграфиков. » [X, Y] = m°shgiid(“l:0.05:1, 0:0.05:1); » Z = 4*sin(2‘pi*X).*cos(1.5*pi*Y).*(1 - Х.Л2).*Y.*(1 - Y); » subplot(3, 2, 1) » mesh(X, Y, Z) » title{'mesh') » subplot(3, 2, 2) 168 Часть I. Основы работы в MATLAB » surf(X, Y, Z) » title('surf‘) » subplot(3, 2, 3) » meshcfX, Y, Z) » title('meshc‘) » subplot(3, 2, 4) » surfcfX, Y, Z) » title(’surfc’) » subplot(3, 2, 5) » contour3(X, Y, Z) » title('contour31) » subplot(3, 2, 6) » surfi(X, Y, Z) » shadi ng interp » title('surfi’) » colormap(gray) Рис. 3.50. Использование подграфиков (subplot) Гпава 3. Высокоуровневая графика 169 В результате получается графическое окно, изображенное на рис. 3.50, которое содержит шесть подграфиков, наглядно демонстрирующих способы построения трехмерных графиков в MATLAB. Обратите внимание, что последняя команда colormap (gray) изменяет палитру всего графического окна, а не подграфиков по отдельности. Визуализация векторных полей Функции compass, feather и quiver графически представляют совокупность двумерных векторов. В качестве примера построим зависимость вектора скорости u = (ux, Uy'j тела, брошенного под углом к горизонту, от времени: «х=»хО’ "v=MyO-—'• т здесь , nv0 — проекции вектора начальной скорости; т — масса; g — ускорение свободного падения; / — время. Векторы скорости должны исходить из точек, принадлежащих траектории движения зела. Если его начальное положение совпадает с началом координат, то траектория движения описывается законом: д 2 x = uxOt, у = . 2т Выберем параметры задачи так, чтобы при иа0 = 0.5, иу0=0.8 продолжительность полета составила две секунды до падения тела на поверхность, и проследим за изменением его скорости через каждые 0.2 секунды » t = О:0.2:2; Запишите координаты тела в эти моменты времени в массивы х и у, а проекции скоростей на оси в их и иу: » х = 0.5*t; » у = 0.8*t.*(l - 0.5*t); » их(1:length(х)) = 0.5; » иу = 0.8*(1 - t>; Для визуализации поля скоростей вызовите функцию quiver, указав в качестве первой пары входных аргументов массивы х и у с координатами начальных точек векторов, в качестве второй — векторы их и иу со значения 170 Часть I. Основы работы в МАТ1 АВ ми проекций векторов скоростей и масштабирующий множитель 0.5 последним пятым аргументом: » quiver(х, у, их, иу, 0.5) Получается наглядная картина движения тела, изображенная на рис. 3.51. В нашем примере функция quiver изображает векторное поле, заданное на кривой линии. Рис. 3.51. Зависимость скорости тела от времени (функция quiver) Обратите внимание, что векторы масштабируются, их длины на графике не совпадают с реальными значениями Во-первых, автоматического масштабирования можно избежать, указав в качестве пятого аргумента ноль » quiver(х, у, их, иу, 0) Во-вторых, можно оставить автоматическое масштабирование, но указать коэффициент увеличения (или уменьшения) длины векторов после него. Сравните: » quiver(х, у, их, иу, 1.5) >> quiver(х, у, их, иу, 0.3) Функция qurver допускает замену стрелок, которыми рисуются векторы по умолчанию, на начинающиеся с маркера отрезки. Тип линии, цвет и маркер Глава 3. Высокоуровневая графика 171 указываются вместо масштабирующего множителя или после него (т. е. пятым или шестым входным аргументом). » quiver(х, у, их, иу, 'or—') » quiver(х, у, их, иу, 2.1, '*к:’) Подумайте, как отобразить не только векторы скорости, но и траекторию движения в виде плавной кривой. Очевидно, что нужно заново вычислить координаты тела с достаточно малым шагом по времени и использовать команду hold on для наложения линии движения тела па построенный график поля скоростей. Функции corpass и feather реализуют другие способы графического отображения векторных полей Они отличаются от quiver тем, что не требуют задания начальных точек векторов. Функция compass представляет все векторы исходящими из начала координат, a feather — исходящими из равноотстоящих точек на одной прямой. Эти функции удобны, если надо отследить изменение скорости безотносительно к траектории. Вызовите compass и feather, указав в качестве входных аргументов массивы со значениями проекций вектора скорости: » compass(их, иу) » feather(их, иу) Результаты представлены, соответственно, на рис. 3.52 и 3.53. Рис. 3.52. Зависимость скорости тела от времени (функция compass) 172 Чисть I Основы работы в МАТ!.АВ Функции compass и feather могут иметь единственный входной аргумент — комплексный вектор, что эквивалентно вызову от двух векторов, первый из которых — вектор вещественных частей, а второй — мнимых. Управление свойствами линий, используемых вместо стрелок, производится так же, как и в quiver. Рис. 3.53. Зависимость скорости тела от времени (функция feather) Полная информация о функциях quiver, compass и feather содержится в интерактивной справочной системе MATLAB и приложении 1. Отметим, что функция quiver может быть использована для визуализации двумерных векторных полей, например, градиента функции (см. пример в справочной системе). Для представления трехмерных векторных полей, заданных на поверхности, служит quiver3. Один из возможных примеров— векторы нормали к поверхности — приведен в справочной системе. Для нахождения нормалей в этом примере привлечена функция surfnorm. Она вычисляет компоненты векторов нормали в точках поверхности, которые соответствуют точкам сетки на плоскости (л, у), генерируемым функцией meshgrid. Изучите Г лава 3. Выс жоуровневая графика 173 пример и самостоятельно постройте внешние нормали к шару радиуса I (рис. 3.54). Проверьте себя: >> u = (-pi:pi/15:pi) » V = -pi:pi/15:pi; » X = sin (u) *cos (v) ; » Y = sin(u)*sin(v); » Z = cos(u)‘ones(size(v)); » surf(X, Y, Z) » [U, V, W] = surfnorm(X, Y, Z); » held on » Quiver3(x, Y, Z, U, V,W, 4, 'k'>; Рис. 3.54. Внешние нормали к шару (функция quiver3) Для изображения трехмерных векторных полей, таких как распределение скоростей в движущейся жидкости или газе, MATLAB предоставляет функцию coneplot. Краткое описание функции дано в приложении 1. 174 Часть I. Основы работы в MATLAB Задания для самостоятельной работы 1. Построй ге графики функций одной переменной на отрезке [0.01, 2п]. , sinx , ч _х fx) =——, Sx)=e соях. Выведите графики различными способами: • в отдельные графические окна; • в одно окно на одни оси; • в одно окно на отдельные оси. Дайте заголовки, разместите подписи к осям, легенду, используйте различные цвета, стили линий и типы маркеров, нанесите сетку. Нарисуйте часть графика для отрицательных значений функции синим цветом, а для положительных — красным. Примите во внимание, что на самом деле отображается зависимость одного вектора от другого. Следовательно, можно применить функцию find для поиска индексов гре-буемых элементов вектора со значениями функции и индексацию вектором для выделения нужных компонент. 2. Визуализируйте функцию двух переменных на прямоугольной области определения 2(x,y) = ^sinx2 + cosj'2^ , хе [-1,1], уЕ [-1, 1]. Выведите графики различными способами: • каркасной поверхностью; • за читой цветом каркасной поверхностью; • промаркированными линиями уровня (самостоятельно выбрать зпа чения функции, отображаемые линиями уровня); • освещенной поверхностью. Расположите графики в отдельных графических окнах и в одном окне с соответствующим числом осей. Представьте вид каркасной или освещенной поверхности с нескольких точек обзора. Отметьте на трехмерном графике точки экстремумов. Используйте то, что значения функции в узлах сечки хранятся в матрице. Определите Гпава 3, Высокоуровневая грзсрика 175 максимальное значение функции при помощи шах. Функция find позволит узнать столбцевые и строчные индексы этих тпементов матрицы. Завершающий этап состоит в вызове plot3 для расположения маркеров в точках трехмерного пространства на графике. 3. Постройте векторное поле градиента функции. Визуализируйте трехмерное векторное поле на поверхности (возьмите разные поверхности): • поверхность является гиперболоидом; • поверхность является параболоидом; • поверхность задана параметрически: x(w, v)=cosh-cosv, у(и, v) = sinw-sinv, z(«, v) = h-v, и, ve[O,3J. Постройте векз орные поля: • поле направлений отраженного света, падающего параллельным пучком на поверхность; • поле направлений преломленного света, падающего параллельным пучком на поверхность; • поле направлений отраженного света, направленного из точечного источника. Рассмотрите изменение полей направлений в зависимости от взаимного расположения поверхности и источника. При пост роении поля направлений подберите масштабный множитель и количество точек приложения векторов на поверхности для получения наилучшего представления о характере поля. Поле нормалей к поверхности, необходимое для определения направления лучей отраженного или преломленного вектора, вычислите с помощью функции surfnorm. Глава 4 Интерактивная среда для построения графиков MATLAB предоставляет удобное интерактивное средство для построения графиков и корректировки их вида, нанесения дополнительной информации. подготовки их к печати, сохранения и экспорта в различные графические форматы — набор инструментов высокоуровневой графики (Plot Tools), который далее будем называть редактором графиков. Использование редактора оправданно, когда требуется подготовить небольшое число графиков для печати или для вставки в какой-либо документ. Редактор графиков позволяет выполнять простейшие операции: задавать тип и цвет линии или свойства поверхности непосредственно при построении графика, размещать заголовок и легенду, подписывать оси. Начинающим пользователям этого вполне достаточно. Однако при написании собственных приложений в MATLAB с графическим выводом результатов часто возникает необходимость получить уже готовый график без дальнейшего редактирования. Возможна и более сложная ситуация, при которой отдельные элементы графиков должны изменяться прямо в ходе работы приложения, например, цвет или толщина уже существующей линии. В случае, когда приложение использует несколько графических окон со своими осями, необходимо выводить результаты на нужные оси в определенном графическом окне. Для решения этих задач не обойтись без средств дескрипторной графики (Handle Graphics), которой посвящена глава d Работая в редакторе графиков, вы познакомитесь со структурой графических объектов MATLAB и многообразием их свойств, что впоследствии облегчит понимание дескрипторной графики. Глава 4. Интерактивная среда для построения графиков 177 Г рафические объекты MATLAB является объектно-ориентированной системой, причем все графические объекты расположены в определенной иерархической последовательности. Для освоения средств, описываемых в настоящей тлаве. достаточно использовать упрощенное представление о графических объектах. Основным объектом является графическое окно (figure), в каждом окне могут быть расположены одна или несколько систем координат, определяемых своими осями (axes). На каждой системе осей размещаются другие графические объекты, например линии (line) или поверхности (surface). Кроме того, в области графического окна можно разместить различные поясняющие объекты: стрелки (arrow, doublearrow), стрелки с текстовой надписью (text-arrow), надписи (textbox), геометрические фигуры (ellipse, rectangle). Поясняющие объекты принадлежат специальному слою примечаний (annotationlayer) графического окна. Рис. 4.1. Структура объектов MATLAB (упрощенный вариант) Важно понимать, что при вызове функций высокоуровневой графики, например, plot (не важно из командной строки или средствами графического интерфейса), сначала создается графическое окно и принадлежащие ему оси, на которые выводятся линии графика. Другими словами, команда 178 Часть I. Основы работы в МА fLAB plot создает все необходимые в иерархии графические объекты, а не "просто строит график". В случае других графических функций (например, surf, mesh или contour и др.) ситуация аналогична, только мы уже имеем дело не с линиями, а с поверхностями. Редактор графиков позволяет легко изменить свойства каждого из вышеперечисленных объектов. Редактор графиков Для начала работы с редактором графиков (далее в этой главе просто редактор) следует подготовить данные для визуализации. Проиллюстрируем работу на следующем примере: на одной паре осей построим графики функций sinx и cosx на отрезке [0.5], а на другом— поверхность функции е~х ~у • (х -1)2 sin 2nv для х, уе[—1,1]. Ниже приведена последовательность команд для подготовки данных: » х = 0:0.1:5; » f = sin(pi*x); » д - cos(pi*x); » [X, Y] = meshgrid(-1:0.05:1); » Z = ехр(-Х.Л2 - ¥.Л2).*(Х - 1).л2.*sin(2*pi*Y); Для вызова редактора графиков воспользуйтесь командой >> plottools Появляется среда редактора графиков, изображенная на рис. 4.2 Редактор графиков содержит графическое окно Figure 1 с меню и панелью инструментов и три вспомогазельных окна: Figure Palette (Шаблоны графики), Plot Browser (Браузер объектов) и Property Editor - Figure (Редактор свойств графических объектов). Обратите внимание, что на панели инструментов графического окна выбран инструмент Edit Plot предназначенный для перехода в режим редактирования. Наличие вспомогательных окон определяется состоянием флагов в одноименных пунктах меню View графического окна. Кроме того, для одновременного отображения или скрытия всех вспомогательных окон служат две последние кнопки на панели инструментов графического окна: Hide Plot Tools (Закрыть окна) и Show Plot Tools (Показать окна), причем всегда доступна только одна из них. Глава 4. Интерактивная среда для построения графиков 179 Рис. 4.2. Среда редактора графиков Примечание Для перехода в среду редактора графиков мы вызвали команду plottools. Если в MATLAB не открыто ни одного графического окна, то в результате выполнения этой команды создается графическое окно со всеми вспомогательными элементами среды редактора графиков. Если же одно или несколько окон открыто, то режим редактирования включается для текущего графического окна. Быстрый переход в среду редактора графиков осуществляется нажатием кнопки Show Plot Tools на панели инструментов графического окна. Окно шаблонов графики (Figure Palette) используется для размещения осей в пределах графического окна, задания данных для визуализации и размещения пояснений. Соответствующие части окна имеют подзаголовки: New Subplots, Variables, Annotations. Любая часть может быть свернута или открыта с помощью щелчка мышью на заголовке. Для создания осей следует щелкнуть мышью по типу системы осей (2D Axes или 3D Axes) в разделе New Subplots либо использовать кнопку "добавить 7 Зм. 130 180 Часть I. Основы работы в MATLAB области" <Е ►]) для указания количества подобластей длл построения графиков и способа их расположения в графическом окне. Ь нашем примере требуются две системы координат: двумерные оси для графиков тригонометрических функций и трехмерные — для поверхности. Последовательные щелчки мышью по 2D Axes и 3D Axes приводят к размещению нужных нам осей, причем при создании новых осей уже имеющиеся автоматически изменяют свои размеры так, чтобы избежать перекрытия. Сейчас оси находятся друг под другом. Для горизонтального расположения осей следовало бы вместо щелчка по 3D Axes использовать кнопку "добавить области" и. применяя протаскивание мышью, указать желаемый способ добавления осей. В режиме редактирования размеры и расположение осей изменяются при помощи мыши. Выделенные щелчком мыши оси заключаются в рамку с квадратными маркерами, при наведении курсора мыши на них он меняет форму на двустороннюю стрелку. Изменение размеров производится перемещением мыши с удержанием левой кнопки, причем маркеры в вершинах рамки служат для пропорционального изменения размеров, а маркеры в серединах сторон — для независимого изменения ширины и высоты. Для перемещения выделенных осей в пределах окна следует подвести курсор мыши к одной из координатных осей (курсор должен состоять из четырех стрелок) и применить перетаскивание мышью. Заметьте, что при создании осей в окне браузера объектов (Plot Browser) появляется информация о созданных графических объектах. В окне редактора свойств (Property Editor) отображаются доступные для редактирования свойства текущего объекта. Далее мы обсудим изменение свойств графических объектов. Раздел Variables содержит переменные рабочей среды, в том числе и созданные только что массивы х, f, g, х, y, z. Приступим к их визуализации. Постройте сначала зависимость f от х на двумерных осях. Для этого сделайте осп текущими, выделите массивы f и х в разделе Variables (при помощи мыши с удержанием <Ctrl>) и выберите plot(x,f) в контекстном меню. На осях появился график синуса. Теперь требуется добавить график косинуса, которому соответствуют массивы g и х. Однако повтор описанных выше действий для пары g и х приведет к исчезновению графика синуса. Поэтому следует воспользоваться кнопкой Add Data в окне браузера объектов, либо одноименным пунктом контекстного меню осей. В обоих случаях появляется диалоговое окно Add Data to Axes, в раскрывающихся списках которого X Data Source и Y Data Source необходимо выбрать подходящие массивы рабочей среды, т. е. х и g соответственно. Раскрывающийся список Plot Туре позволяет задать тип графика — в нашем случае следует оставить предлагаемый по умолчанию. После нажатия на ОК график косинуса добавился на оси. Гпава 4, Интерактивная среда для построения графиков 181 t Примечание j При создании одного графика можно предварительно не создавать систему осей. Например, при перетаскивании массива данных из области Variables в графическое окно редактора автоматически будет создан объект системы осей нужной размерности и изображен график. Аргументом функции будут индекс (индексы) элемента массива. Перейдем теперь к построению графика поверхности, определяемой массивами х, Y и z. Сделайте текущими трехмерные оси и нанесите на них график поверхности одним из двух разобранных выше способов— при помощи раздела Variables либо кнопки Add Data. Заметьте, что в браузере объектов отображаются построенные линии (потомки двумерных осей) и поверхность (потомок трехмерных осей). Слева от названия каждого объекта находится флаг, сброс которого позволяет сделать объект невидимым. Например, если требуется получить поверхность, изображенную не на осях, а в самом окне, то следует сделать соответствующие оси невидимыми. Аналогичным образом скрываются линии и поверхности. При этом они существуют как графические объекты, и установка флага приводит к их отображению. Для добавления объекта в группу выделенных объектов можно пользоваться как графическим окном (щелчок мышью с удержанием <Shift>), так и браузером (щелчок мышью с удержанием <Ctrl>). Разумеется, невидимые объекты можно выделить только в браузере. Для удаления выделенного объекта или группы служит клавиша <Delete>, либо пункт Delete контекстного меню. Кроме того, для удаления всех потомков осей проще всего очистить оси, выбрав в их контекстном меню пункт Clear Axes. Потренируйтесь выделять объекты, делать их невидимыми и удалять, но затем приведите графическое окно в исходное состояние, изображенное на рис. 4.3, и сделайте его текущим объектом, щелкнув мышью по свободному месту окна. Сейчас редактор свойств отображает его настройки. Строка ввода Figure Name предназначена для определения заголовка графического окна. Например, введите текст "Редактор графиков". Сброс флага Show Figure Number обеспечивает удаление из заголовка слова Figure и номера окна. Выпадающий список Colormap служит для задания палитры графического окна, которая определяет способ закраски трехмерных поверхностей. Цвет фона графического окна изменяется при помощи кнопки Figure Color Мы перечистили наиболее часто используемые настройки графического окна. Для доступа ко всем его свойствам придется прибегнуть к инспектору свойств, окно которого Property Inspector открывается при нажатии на кнопку Inspector в окне редактора свойств. 182 Часть I Основы работы в МА~П.АВ Обзору свойств графических объектов посвящена глава 9. Рис. 4.3. Окно редактора графиков с графическими объектами Окно редактора свойств всегда содержит средства для редактирования только часто изменяемых характеристик текущего графического объекта, а кнопка Inspector позволяет открыть окно инспектора свойств с полным перечнем свойств объекта. Часть элементов окна редактора свойств доступна из контекстного меню при щелчке правой кнопкой мыши на текущем объекте. Редактор свойств отображает настройки текущего объекта — графического окна, осей, линий и поверхностей. Следовательно, перед редактированием любого объекта необходимо сделать его текущим. Мы уже обсудили основные свойства графического окна и обратимся теперь к свойствам его потомков. В заключение этого раздела заметим, что дтя изменения свойств графических объектов существует несколько спосо- Гпава 4 Ин.ерактивная среда для построения графиков 183 Бов. Один из них — использование редактора свойств, другой — контекстного меню объекта. Скажем, для задания цвета фона графического окна достаточно выбрать пункт Color его контекстного меню Кроме того, ряд опций доступен из меню графического окна, например, меню Edit позволяет определить палитру (пункт Colormap), или удалить всех его потомков (пункт Clear Figure). Как правило, мы будем указывать одно из возможных решений, оставляя читателю возможность найти остальные и остановить свой выбор на том, которое кажется наиболее удобным. Свойства осей, подписи, заголовок Как мы уже замечали, для перехода к свойствам объекта необходимо сделать его текущим. Сделайте, например, текущими двумерные оси (см. рис. 4.3), щелкнув мышью по свободному месту в пределах осей или выбрав их в списке браузера объектов. При использовании боаузера объектов легко выбрать нужные оси, т. к. они содержат две линии, указанные в списке браузера. Выбранные оси выделяются рамкой с квадратными маркерами в графическом окне. Она не только свидетельствует о том, что оси стали текущим объектом, но и позволяет изменять их размеры, как было объяснено в предыдущем разделе. Рис. 4.4. Диалоговое окно Property Editor для форматирования осей После выбора осей диалоговое окно редактора свойств соответствует свойствам осей, что отражено в его заголовке— Propertj Editor - Axes (рис. 4.4). Заметьте, что ряд свойств задается независимо для каждой из осей при помощи соответствующей вкладки X Axis, Y Axis или Z Axis. 184 Часть I. Основы работы в MATLAB Элементы управления окна редактора свойств обеспечивают доступ к наиболее часто используемым свойствам осей, которые мы сейчас опишем. Для обращения, ко всем свойствам осей придется воспользоваться инспектором свойств, окно козооого появляется при нажатии на кнопку Inspector. Далее мы приведем несколько примеров, когда обращение к инспектору свойств оказывается необходимым. Цветовое оформление, разметка и сетка Для задания цвета фона и цвета линий осей следует воспользоваться соответствующими кнопками окна редактора свойств в группе Colors (см. рис. 4 4). Но при таком способе цвета всех линий осей совпадают Для независимого выбора цвета каждой линии следует обратиться к инспектору свойств, который появляется при нажатии на кнопку Inspector. В левой части появившегося окна Property Inspector найдите свойства XColor, YColor и ZColor. которые отвечают за цвет каждой из осей, и выберите желаемый цвет, нажав на кнопку справа от названия свойства. Обсудим допустимые настройки разметки осей, их масштаба и сетки. Масштаб каждой из осей (линейный или логарифмический) устанавливается независимо для каждой оси на соотве гс гвующей ей вкладке в раскрывающихся списках X Scale, Y Scale или Z Scale. На этих же вкладках задаются пределы каждой из осей в полях ввода X Limits, Y Limits и Z Limits. Для каждой из осей возможно либо обычное направление (флаг Reverse сброшен), либо обратное (флаг Reverse установлен). Для размещения координатной сетки, очевидно, служат флаги X, Y и Z группы Grid. Обратите внимание, что координаты линий сетки совпадают с координатами разметки, которая выбирается автоматически. Разберем этот вопрос более подробно. Имеется возможность задавать координаты разметки и подписи к ним для каждой оси. Для этого следует нажать кнопку Ticks и в появившемся диалоговом окне Edit Axis Ticks перейти к вкладке, соответствующей нужной оси. Размещенные на вкладке элементы управления позволяют задать равномерный шаг разметки (переключатель Step by и соответствующая строка ввода) или определить произвольные координаты. Для задания произвольных координат разметки следует установить флаг Manual в группе X Tick Location и добавить или удалить их в столбце Locations при помощи кнопок Insert или Delete. При этом существуют два способа подписей к разметке. Они либо являются значениями координат (при установленном переключателе Auto 1 руппы X Tick Labehk либо вводятся в столбце Labels (при вводе автоматически устанавливается переключатель Manual). Глава 4. Интерактивная среда для построения графиков 185 При маркировке осей не допускается использование формата ТеХ. Кроме основной разметки, можно отобразить также более мелкую, установив флаг Show minor ticks. Соответственно, кроме редкой сетки, отвечающей основной разметке, может быть построена мелкая сетка. Здесь не обойтись без инспектора свойств, в котором следует установить свойствам XMinor-Grid, YMinorGrid или ZMinorGrid значение on при помощи кнопки справа от названия свойства. Потренируйтесь применять описанные выше средства редактора на примере двумерных осей рис. 4.3. Приведите их к виду, представленному на рис. 4.5. Рис. 4.5. Масштабирование, пределы и разметка осей Для установки требуемых свойств осей необходимо произвести следующие действия. I. Сделайте доступными поля Limits оси х, отключив флаг Auto, введите правый предел 4 для оси абсцисс и нажмите <Enter> для того, чтобы изменения вступили в силу. Аналогичным образом задайте пределы -1.2, 1.2 по оси у. 2. Добавьте сетку, включив флаги Grid для осей х и у. 3. Откройте диалоговое окно Edit Axis Ticks, нажав кнопку Ticks. Установите переключатель Step by и внесите значение шага 1 в расположенную рядом с ним строку ввода. Используйте кнопку Apply, а не ОК, поскольку в окне Edit Axis Ticks еще надо будет сделать ряд настроек. 4. Задайте теперь подписи к разметке по оси х. Для этого установите переключатель Manual в группе X Ticks Labels и введите в каждой ячейке столбца Labels обозначения разметки х - 0 , х = 1, х = 2, х = 3, Y ('о). 186 Часть /. Основы работы в MATLAB 5. Разметьте ось у в соответствии с рис. 4.5, перейдя к вкладке Y Axis в окне Edit Axis Ticks. Вкладка Font окна редактора свойств позволяет выбрать шрифт осей в раскрывающемся списке Font Name, изменить его размер при помощи списка Size и стиль. Левый список в группе Style предназначен для задания толщины шрифта, а правый — наклона. Цвет текста совпадает с цветом соответствующей координатной оси. Подписи и заголовок Заголовок графика набирается в области ввода Title окна редактора свойств, а подписи к координатным осям задаются в строках ввода Label на вкладках со свойствами каждой из осей. После ввода подписи к координатной оси достаточно нажать <Enter> для ее появления в графическом окне. Заголовок же может состоять из нескольких строк, разделяемых <Enter>, поэтому для его отображения следует щелкнуть мышью по осям. После ввода заголовка в окне браузера надпись Axes (no title) изменится на текст заголовка, что облегчает выбор нужных осей для редактирования. Подписи к текущим осям и заголовок можно ввести при помощи меню Insert графического окна (пункты X Label, Y Label, Z Label, Title). Выбор соответствующего пункта меню приводит к появлению области ввода для заголовка или подписи к координатной оси прямо в графическом окне. Набор текста следует завершить щелчком мыши вне области ввода. Заюловок может содержать формулы, задаваемые в форматах ТеХ и LaTeX. Дайте такой заголовок верхнему графику графического окна, как показано на рис. 4.6. Для получения требуемого заголовка следует набрать в области ввода Title строку в формате ТеХ: График функций sin pi{itx} и cos piirtx} и щелкнуть мышью по осям. Появился заголовок — принадлежащий осям текстовый объект. Правила записи математических формул в формате ТеХ, используемые в МАЗ LAB приведены в главе 3. Подпишите координатные оси, например так, как на рис. 4.6. Обсудим теперь основные возможности по редактированию заголовка и подписей к осям. Двойной щелчок мышью по этим объектам позволяет изменять текст прямо в графическом окне без обращения к редактору свойств. Для перехода в редакторе свойств к основным свойствам текстовых объектов подписей и заголовка следует сделать их текущими при помощи щелчка мыши. В левой части содержатся раскрывающиеся списки для задания ха- Гпава 4 Интеракшвнач среда для построения графиков 187 рсктержтик текстового поля: стиля линии рамки вокруг текс га (Line Style), толщины линии (I ine Width), цвета фона (Background) и рамки (Edge Color) Рис. 4.6. График с заголовком и подписями осей Остальные элементы управления позволяют изменять свойства шрифта. Список Interpreter служит для указания уровня поддержки стандарта ТеХ (об этом шла речь в предыдущей главе). Переключатель Alignment указывает способ выравнивания текста в поле. Под именем Font объединены кнопка задания цвета символов и четыре раскрывающихся списка для указания, имени шрифта, его размера, толщины и стиля. Большинство перечисленных установок можно сделать и из всплывающего меню текстового объекта. Дополнительные возможности форматирования текста становятся доступными в окне инспектора свойств. Например, угол поворота текста в градусах указывается при помощи его свойства Rotation. Свойства линий и поверхностей Редактор свойств позволяет легко установить стиль, цвет и толщину линий и маркеров по своему усмотрению, изменять свойства образующих поверхности элементов, а также выбирать различные способы визуализации одномерных и двумерных массивов. Свойства линий Перейдите к свойствам какой-нибудь из линий верхнего графика, приведенного на рис. 4.6, сделав ее текущим объектом шелчком мыши. Окно редактора свойств приобретет вид, изображенный на рис. 4.7. 188 Часть I Основы работы в MATLAB рис. 4.7. Диалоговое окно Property Editor для изменения свойств линий В левой части окна редактора свойств расположены- □ одно поле ввода Display Name, предназначенное для изменения имени линии, которое отображается в легенде при ее добавлении; □ три однотипных раскрывающихся списка (X Data Source, Y Data Source, Z Data Source), позволяющие выбрать массивы данных из рабочей среды для построения графика. Опция auto для независимой переменой означает, что в качестве аргумента используется индекс массива. После выбора данных следует нажать кнопку Refresh Data для того, чтобы обновление вступило в силу. □ Инструменты правой части окна редактора связаны со способом визуализации данных и видом графика. □ Раскрывающийся список Plot Туре служит для переопределения типа графика. Например, для одномерного массива можно изменить обычный график (Line) на столбцевую диаграмму (Ваг). □ Три раскрывающихся списка в поле Line определяют вид линии (сплошная, штриховая, пунктирная, штрихпунктирная), ее толщину в пунктах (1пт = 1/72 дюйма) и цвет. □ Четыре раскрывающихся списка в поле Marker используются для задания типа маркера, его размера в пунктах, цвета границ и внутренности (только для полых маркеров). При помощи этих элементов управления легко изменить вид линии графика по своему усмотрению. Пункты No line (none) и No marker (none) раскрывающихся списков для выбора стиля линии и маркеров означают их отсутствие на графике. Ряд настроек может быть также сделан из контекстного меню линии. Глава 4 Интерактивная среда для построения графиков 189 Измените свойства линий и маркеров графиков, изображенных на рис. 4.6, гак, чтобы получившиеся графики имели вид, приведенный на рис. 4.8. Рис. 4.8. Изменение стиля линий и маркеров Вам предстоит выполнить следующие действия. 1. Сделайте текущим график косинуса, щелкнув по линии графика левой кнопкой мыши для доступа к ее свойствам в редакторе. 2. В раскрывающемся списке поля Line для типа линии установите значение no line. 3. В раскрывающемся списке поля Marker выберите тип маркера в форме пятиконечной звезды и задайте в соседних списках красный цвет для границы и синий для внутренности маркера. 4. Задайте размер маркера 5 пт (в списке такого значения нет, поэтому введите его с клавиатуры). 5. Сделайте текущим график синуса. 6. Изменит е цвет линии на синий. 7. Установите тип маркера в форме кружка, размер 4 пт, задайте желтый цвет для внутренности маркера и синий для контура. Перейдем теперь к изучению свойств поверхности. Поскольку сетка поверхности состоит из линий, то при чтении следующего раздела вы встретитесь с аналогичной настройкой вида этих линий. 190 Часть I. Основы работы в MATLAB Свойства поверхностей В графическом окне, приведенном на рис. 4.3, сделайте поверхность текущей и обратитесь к окну редактора свойств. Ребра сетки поверхностей имеют те же свойства, что и линии двумерных графиков, рассмотренные в предыдущем разделе. Инструменты для настройки их вида содержатся в разделах Edges и Markers. Они предназначены для одновременного изменения или удаления линий, параллельных как оси абсцисс, так и ординат. Если же требуется оставить линии только одного из направлений, то понадобится инспектор свойств. В нем следует найти свойство MeshStyle и установить его значение в row для отображения линий сетки, параллельных оси х, или column — для оси у. Цвет заливки ячеек поверхности задается в поле Faces. Раскрывающийся диалог позволяет отказаться от закраски граней (опция No Face Color), либо выбрать: □ один из цветов, общий для всех ячеек; □ свой цвет каждой ячейки в зависимости от значения функции, или от освещения поверхности, если для ее построения была выбрана функция surfl (опция Faceted); □ плавное изменение цвета (опция Blended). Результат выбора последних двух опции зависит также и от цветовой палитры графического окна. Возможно и явное указание цвета при помощи матрицы в раскрывающемся списке С Data Source, но этот способ мы рассмотрим при детальном изучении свойств графических объектов (см. главу 9 "Дескрипторная графика"). Рис. 4.9. Диалоговое окно Property Editor для изменения свойств поверхностей Глава 4. Интерактивная среда для построения графиков 191 С существующей поверхностью могут быть связаны любые подходящие но размерам массивы рабочей среды, которые указываются в списках X Data Source. Y Data Source и Z Data Source. После их выбора требуется нажать кнопку Refresh Data для обновления графика. В качестве упражнения измените приведенную на рис. 4.3 поверхность в соответствии с рис. 4.10. Рис. 4.10. Изменение свойств поверхности Для получения требуемого результата следует выполнить такие действия. 1. Определите тип маркера треугольник (Д). 2. Установите размер маркера, равный 6 в списке, задающем его размер. 3. Задайте зеленый цвет заливки маркера. 4. Задайте розовый цвет контура маркера. 5 Отмените изображение ребер поверхности (значение no line для типа линии в разделе Edges). 6. Выберите серый цвет в списке Faces. Дополнительные элементы оформления Размещение дополнительной информации на графике осущестзляется при помощи стрелок, линий, надписей, легенды и шкалы палитры (colorbar), которая устанавливает соответствие между цветом участков поверхности и значением функции. Выбор нужного объекта производится в меню Insert графического окна из раздела Annotation окна шаблонов графики (Figure Palette) или при помощи соответствующих инструментов панелей графических окон Figure Toolbar и Plot Edit Toolbar, которые добавляются или уби 192 Часть I. Основы работы в MATLAB раются в меню View. Фактически любой дополнительный элемент может быть размещен одним из указанных способов, поэтому в дальнейшем будем пояснять использование одного из инструментов для отдельных объектов. Для того чтобы добавить стрелку (линию), следует в меню Insert выбрать пункт Arrow (Line) и нарисовать ее мышью при нажатой левой кнопке. Находясь в режиме редактирования, можно перемещать в пределах графического окна все объекты, включая стрелки и линии, и изменять их размеры (используя маркеры выделения границ) при помощи движения мыши, удерживая нажатой левую кнопку. В режиме редактирования выделенный графический объект удаляется из контекстного меню выбором пункта Cut, или нажатием на клавишу <DeIete>. В любое место в пределах графического окна можно поместить надпись, для чего следует, например, в разделе Annotation окна шаблонов графики (Figure Palette) выбрать элемент Text Box и щелкнуть левой кнопкой мыши в рабочем поле графического окна. Появится поле для ввода текста. При наборе текста допустимо использование форматов ТеХ и LaTeX. причем текст может размещаться в несколько строк. Выход из режима набора текста осуществляется щелчком мыши вне текстовой области. Двойной щелчок левой кнопкой мыши по текстовому объекту позволяет редактировать его содержимое. При необходимости нанести на рисунок текстовый комментарий со стрелкой. лучше использовать элемент Text Arrow, объединяющий стрелку и поясняющий текст. Добавьте стрелки и подписи на график так, как показано на рис. 4.11. Рис. 4.11. Добавление стрелок и надписей 193 Глава 4. Интерактивная среда для лее- роения гра риков При обозначении дочек минимума и максимума в приведенном варианте можно использовать либо два объекта (Text Arrow и Arrow), либо три объекта (Text и два элемента Arrow). Выделение линии, стрелки или текстового объекта приводит к автоматическому отобоажению их свойств в диалоговом окне Property Editor. Например, для объекта Text Arrow окно редактора свойств содержит две вкладки (рис. 4.12). Одна из них, Text, относится к тексту, ее состав рассмотрен выше в разд. "Поописи и заголовок" этой главы. Вторая. Arrow, содержит поля для определения свойств линии и указателя (наконечника) стрелки: список Head Style определяет форму указателя, а два других — Head Width и Head Length — линейные размеры (ширину и длину). Рнс. 4.12. Диалоговое окно Property Editor для объекта Text Arrow Если оси содержат графики нескольких функций одной переменной, то их полезно сопроводить легендой, содержащей образцы линий и подписи к ним. В качестве подписи выбирается значение одного из свойств линии — ее имени, которое задается в поле Display Name редактора свойств. Дайте имена sin и cos линиям наших графиков синуса и косинуса (см. рис. 4.3) и добавьте легенду, например, из контекстного меню осей, выбрав в нем пункт Show Legend, или при помощи меню Insert графического окна или панели инструментов. Теперь график приобретает вид, изображенный на рис. 4.13. Когда текущим объектом является легенда, окно редактора свойств позволяет изменить ее свойства (рис. 4.14). Элемент Location служит для выбора места легенды в пределах осей или вне их. Установка переключателя best приводит к выбору наилучшего положения легенды с наименьшим перекрытием других элементов. Впрочем, легенда может быть перемещена в любое место графического окна при помощи мыши. Раскрывающийся список Orientation предназначен для определения способа отображения элементов 194 Часть I. Основы работы в MATLAB легенды: в строку (опция Horizontal), или в столбец (опция Vertical). Инструменты поля Color позволяют назначить цвета рамки и фона, a Font — характеристики шрифта легенды. Рис. 4.13. Добавление легенды Рис. 4.14. Диалоговое окно Property Editor для объекта Legend Трехмерные графики, построенные при помощи функций mesh и surf, полезно снабдить шкалой палитры, т. е. информацией о соответствии цвета поверхности значению функции. Наиболее просто ее отобразить при помощи кнопки Insert Colorbar панели инструментов Figure Toolbar графического окна, или пункта Colorbar меню insert. В любом случае это приводит к размещению вертикальной шкалы с цветовой гаммой справа от выделенной пары осей с графиком поверхности (эквивалент команды coiorbar). В окне редактора свойс тв доступен элемент управления Location, такой же, как и для легенды, который позволяет выбрать положение и ориентацию шкалы. Гпава 4. Интерактивная среда для построения графиков 195 Контекстное меню легенды дает ряд дополнительных возможностей по сравнению с редактором свойств. Пункт Standart Colormaps позволяет быстро изменить палитру графического окна на одну из предопределенных. Эти палитры легко могут быть изменены по своему желанию одним из двух способов. Во-первых, выбор пункта Interactive Colormap Shift приводит к изменению вида курсора мыши, движение которого вдоль шкалы модифицирует набор цветов или оттенков для закраски поверхности. Во-вторых, для более тонкого редактирования палитры имеется специальный редактор Colormap editor (рис. 4.15), который запускается выбором пункта Launch Colormap Editor контекстного меню. Рис. 4.15. Редактор палитры Работа в редакторе палитры достаточно проста. Указатели, расположенные под шкалой, служат для задания цвета текущего участка, который выбирается двойным щелчком мыши по указателю. Для добавления указателя следует щелкнуть под нужным участком шкалы, а для удаления — выделить его и выбрать в меню Edit пункт Delete. Выбор одной из стандартных пали гр 196 Часть I. Основы работы в MATLAB производится в меню Took, например, white (только белый цвет) хорошо подходи г для создания собственной палитры. Для поверхностей можно дополнительно задавать источники освещения, используя пункт Light меню Insert графического окна. В редакторе свойств этого объекта указываются: цвет источника освещения Color, способ освещения — Style и три координаты точки расположения источника свеса в системе осей —- Position. Способ освещения Infinite означает, что пучок света состоит из параллельных лучей (в этом случае координаты источника игнорируются), a Local — лучи радиально исходят из точечного источника света, находящегося в заданной позиции. Обзор графиков и поверхностей Инструменты графического окна позволяют увеличивать и уменьшать графики линий и поверхностей, перемещаться по ним, интерактивно получать значение функции в выбранной точке графика, осматривать поверхности с различных сторон. Изменение масштаба, определение значений функции, поворот На панели Figure Toolbar расположены три инструмента, позволяющие более детально изучить график. Это инструменты уменьшения (Zoom out) или увеличения масштаба (Zoom in) и перемещения по графику (Pan). Например, если вы выбрали режим увеличения масштаба Zoom in, то в области графика курсор мыши приобретает форму, изображенную на пиктограмме соответствующего инструмента. Вы можете либо протаскиванием мыши при нажатой левой кнопке определить область для просмотра, либо щелкнуть в ту точку графика, которая после изменения масштаба должна быть в центре. Контекстное меню, вызываемое правой кнопкой, позволяет установить параметры масштабирования (Zoom Options), вернуться к первоначальному масштабу (Reset to Original View) или к предыдущему (Zoom Out). Если установлен режим перемещения по графику, то при нажатой левой кнопке мыши вы можете передвигать график без изменения масштаба. Дополнительные элементы (стрелки, надписи, легенда и т п ) не перемещаются вместе с графиком, поскольку они не "привязаны" к осям. Однако средствами редактора можно зафиксировать координаты некоторой точки объекта в системе координат осей графика. Предположим, что график снабжен стрелкой (объект arrow), которая при изменении масштаба или пе Гпава 4 Интерактивная среда для построении графиков 197 ремещении графика должна вести себя гак же, как и сам график. Для этого следует выбрать в меню Tools пункт Pin to Axes (при этом курсор мыши изменит форму — указателем является тонкий конец) и щелкнуть левой кнопкой мыши по той точке стрелки, которую следует привязать к осям. Если таких точек две, то снова выберите пункт Pin to Axes и отметьте вторую точку. Следите, чтобы при этом выбранный объект остался текущим, ибо его смена будет означать, что привязка объекта не выполнена. Проверьте, что стрелка теперь перемещается, увеличивается и уменьшается вместе с графиком. Для привязки всей стрелки, как и других поясняющих объектов, служит пункт Pin to Axes контекстного меню объекта. MATLAB предоставляет удобное средство для интерактивного определения координат точек на графиках линий и поверхностей и для размещения соответствующих ярлыков со значениями независимых переменных и функции. Выберите инструмент Data Cursor и щелкните левой кнопкой мыши по точке на графике— появляется ярлык с координатами точки. Перемещение мыши с удержанием левой кнопки вдоль графика приводит к перемещению ярлыка и обновлению информации в нем. Контекстное меню ярлыка позволяет управлять процессом отображения, например, можно добавить еще одно окно, выбрав пункт Create New Datatip (тогда предыдущее остается связанным с последней точкой), или удалить все образованные окна — Delete AllDatatips. Еще один инструмент Rotate 3D панели Figure Toolbar трафического окна служит для поворота поверхности движением мыши при нажатой левой кнопке. Во время вращения в левом нижнем углу графического окна отображаются текущие значения азимута (Az) и угла склонения (£/), смысл которых мы обсуждали при использовании функции view для задания точки обзора (см. разд. "Поворот графика, изменение точки обзора" главы 3). MATLAB предоставляет более развитое средство для просмотра трехмерных объектов — камеру, возможностям которой посвящены следующие два раздела. Камера для обзора графического объекта Существует более развитое средство управления видом графика по сравнению с заданием точки обзора. Когда мы смотрим на трехмерный объект, изображенный на экране компьютера, мы на самом деле видим его проекцию на экран, осуществляемую при помощи некоторой камеры (Camera в 198 Часть I. Основы работы в MATLAB MA1LAB). Рисунок 4.16 поясняет взаимное расположение камеры и трафи-ческого объекта. Рис. 4.16. Взаимное расположение камеры и графического объекта Работа с камерой определяется следующими параметрами. П Режим отображения удаленного объекта. В пакете предусматривается использование двух режимов: • orthographic, размеры элементов объекта зависят только от расстояния от объекта до камеры, причем не происходит искажения (параллельные прямые остаются параллельными), т. е. оси координат остаются ортогональными; • perspective, изображение элементов объекта зависит как от расстояния от объекта до камеры, так ног размера самого элемента, удаленные части мельче близлежащих (параллельные прямые могут изображаться непараллельными), т. е. оси координат в перспективе. Гпава 4. Интерактивная среда для построения графиков 199 Г) Угол обзора (View angle) в градусах, больший нуля и меньший либо равный 180, Изменение угла обзора влияет на размер графического объекта на экране, а перспектива осей не претерпевает изменений, □ Положение камеры относительно объекта (Position). Положение камеры в системе координат осей задается вектором с координатами [х, у, z]. Приближение камеры к объекту при фиксированном значении угла обзора View angk позволяет увеличить масштаб просмотра, отдаление камеры приводит к уменьшению масштаба. □ Положение графического объекта (Target). Точка с координатами [х, у, z], на которую направлена камера. Вместе с Positon это свойство определяет ось камеры, приведенную на рис. 4.16. □ Поворот камеры вокруг оси просмотра (Пр vector), задается координатами [х, у, z] вектора камеры (рис. 4.16) Панель инструментов камеры Быстрый доступ к свойствам камеры производится из панели инструментов Camera Toolbar, которая появляется при установке флага Camera Toolbar в меню View графического окна. Панель Camera Toolbar состоит из нескольких групп. Группа инструментов, изображенная на рис. 4.17, предназначена для управления движением камеры и расположением источника света. Рис. 4.17. Инструменты управления движением камеры и расположением источника света В эту группу входят следующие инструменты: □ Orbit Camera— вращение камеры вокруг основной оси (про выбор основной оси см. ниже); □ Orbit Scene Light — управление положением источника света, который добавляется и убирается при помощи инструмента Toggle Scene Light, расположенного на панели Camera Toolbar; □ Pan/Tilt Camera — перемещение графического объекта (основная ось направлена вверх); 200 Часть I. Основы работы в МА И АВ □ Move Camera Horizontally/Vertically—движение камеры по горизонтали или вертикали; □ Move Camera Forwartl/Back — приближение камеры к графическому объекту движением мыши вправо или вверх, о удаление — влево или вниз; □ Zoom Camera— увеличение угла обзора движением мыши вправо или вверх, уменьшение — налево или вниз; □ Roll Camera— поворот камеры вокруг своей оси вращением мыши по (или против) часовой стрелке в пределах графического окна. При первом применении инструмента появляется окно с предупреждением о том, что следует установить автоматический подбор размеров осей. Это окно появляется только один раз в течение всего сеанса работы MATLAB, причем при использовании инструментов управления камерой требуемые установки производятся автоматически. Чтобы избежать появления в дальнейшем данно! о окна следует установить в нем флаг Do not show this dialog again. Пиктограмма кнопки позволяет легко выбрать тип движения камеры или источника света, и затем, перемещением указателя мыши в пределах графического окна при нажатой левой кнопке мыши, осуществить желаемое действие. Часть инструментов управления движением камеры: Orbit Camera, Pan/Tilt Camera требуют задания основной оси (principal axis), по отношению к которой происходит движение камеры. Основная ось направлена вверх на экране. При использовании этих инструментов становится доступной группа инструментов панели Camera Toolbar, приведенная на рис. 4.18, причем по умолчанию основной является ось z. Возможно задание осей х, у пли z в качестве основных, или установка свободного движения безотносительно какой-либо оси. I i Рис. 4.18. Инструменты выбора основной оси При помощи остальных инструментов, расположенных на панели Camera Toolbar и представленных на рис. 4.19, можно □ добавить или удалить один ис точник света (Toggle Scene Light); □ установить ортогональную проекцию осей на экран (Orthographic Projection); Глава 4. Интерактивная среда для построения графиков 201 □ отобразить оси в перспективе ("Perspective Projection); □ вернуть графику первоначальный вид (Reset Camera and Scene Light); □ остановить движение графика (StoD Camera/Light Mot'ont, что может быть полезно, если вы задали слишком много перемещений движением мыши и MATLAB долго обрабатывает изменение графического окна. ? 0 0 & © Рис. 4.19. Дополнительные инструменты работы с камерой Сохранение, экспорт и печать Для сохранения графического окна используются пункты Save или Save as меню File графически! о окна. MATLAB сохраняет графическое окно в файле с расширением fig. Открыть графическое окно в текущем и следующих сеансах работы с MATI АВ можно при помощи пункта Open меню File любого графического окна или рабочей среды MATLAB (при открытии из рабочей среды требуется выбрать fig в фильтре расширений диалогового окна Open). Экспорт графики из MATLAB производится в различные графические форматы, в частности: EPS. Al, BMP, GIF, TIFF, JPEG и др. При экспорте в графический файл записывается только область графического окна без меню и панели инструментов. Для экспортирования предназначен пункт Save as меню File при выборе типа файла, отличного от fig. Криме сохранения содержимого графического окна как файла с расширением fig или графического файла, имеется и альтернативная возможность — автоматическое создание соответствующего кода на языке программирования MATLAB, выполнение которого приведет к появлению графика. Для получения такого кода в меню File графического окна следует выбрать пункт Generate M-File, после чего начнется генерация кода. Текст кода откроется в редакторе М-файлов, и его можно сохранить и запустить на выполнение Мы уделим достаточно внимания программированию в MATLAB, в частности, следующие две главы посвящены конструкциям встроенного 202 Часть /. Основы работы в MAIi АВ языка программирования и написанию собственных программ. Поэтому мы отложим обсуждение возможности генерации М-файла до следующей главы. Еще один пример создания М-файла приведен в в разд. "Объекты Rectangle и Line, блок-схемы и диаграммы" главы 9. MATLAB предоставляет возможность управлять видом графика при печати Выбор пункта Page Setup меню File приводит к появлению на экране окна многостраничного диалога Page Setup, изображенного на рис. 4.20. Рис. 4.20. Диалоговое окно Page Setup Задание размеров графика и его положения на странице осуществляется при помощи элементов управления, расположенных на вкладке Size and Position, причем эта вкладка содержит образец страницы. По умолчанию установлен переключатель Use screen size, centered on page, что соответствует печати графика того же размера, что и на экране, в центре листа. Для расположения графика на листе по своему усмотрению установите переключатель Use manual size and position, при этом становятся доступными элементы управле гпава 4. Интерактивная сред i для, юс кроения графиков 203 ния. расположенные на панели Manual size and position. В нолях Тар. Left, Width и Height определяются координаты верхнего левого угла, ширина и высота графика. Единицы измерения выбираются в поле Units, причем Normalized соответствует заданию относительных величин (высота и ширина листа считаются равными единице). Для непропорционального растяжения I рафика на всю область листа следует нажать кнопку Fill Page Максимально возможное растяжение с сохранением пропорций происходит при нажатии кнопки Fix aspect ratio. Кнопка Center служит для помещения графика в цечтое листа. При помощи мыши можно изменять размеры и расположение графика в поле с образцом страницы. Вкладка Paper предназначена для установки размеров и ориентации листа бумаги, причем в образце листа, размещенном на этой вкладке, так же возможно изменение размеров и положения графика при помощи мыши. Задание черно-белой печати или цветной печати производится из вкладки Lines and Text. Если вы печатаете на черно-белом принтере и хотите получить оттенки серого для цветных элементов (линий и текста), то следует установить переключатель Color. Для печати текста и линий черным цветом выберете Black and White. При изменении размеров графика в диалоговом окне Page Setup MATLAB автоматически подбирает пределы осей и разметку для обеспечения хорошего вида графика. Автоматическому подбору соответствует переключатель Recompute limits and ticks, содержащийся на вкладке Axes and Figure. Если вы хотите напечатать график в том виде, в котором он изображен на экране, то установите переключатель Keep screen limits and ticks. Как правило, нет смысла печатать серый фон графического окна, что и делается по умолчанию (установлен переключатель Force white background) Если же требуется напечатать график на фоне графического окна, то следует установить переключатель в положение Keep screen background color. Диалоговое окно для установки параметров принтера доступно из пункта Print Setup меню File графического окна, а диалоговое окно печати — из пункта Print. После установки параметров страницы перед печатью полезно воспользоваться предварительным просмотром при помощи пункта Print Preview меню File графического окна. Более полную информацию можно получить, обратившись к разделам справочной системы из меню Help графического окна 204 Часть I Основы работы в МА TLAB Задания для самостоятельной работы Постройте поверхности из задания к главе 3. Используя средства редактора свойств Property Editor, оформите их графическое представление: П задайте характ еристики осей; □ подберите цветовую палитру для лучшего отражения свойств поверхности; □ поварьируйте свойства граней и маркеров точек сетки; □ воспользуйтесь камерой для всестороннего осмотра и изучения поверхности. Глава 5 М-файлы В предыдущих главах мы рассмотрели достаточно простые примеры, для выполнения которых требуется набрать несколько команд в командной строке. Для более сложных задач число команд возрастает, и работа в командной строке становится непродуктивной. Использование истории команд, сохранение переменных рабочей среды или ведение дневника при помощи diary незначительно повышают производительность работы. Эффективное решение состоит в оформлении собственных алгоритмов в виде программ (М-файлов), которые можно запустить из рабочей среды или из редактора. Встроенный в MATLAB редактор М-файлов позволяет не только набирать текст программы и запускать ее целиком или частями, но и отлаживать алгоритм. Подробная классификация М-файлов приведена ниже. Отладка программ описана в главе 8. Работа в редакторе М-файлов Раскройте меню File рабочей среды MATLAB и в пункте New выберите подпункт M-file или нажмите кнопку New M-file на панели инструментов рабочей среды. Новый файл открывается в окне редактора М-файлов, которое приведено на рис. 5.1. Вид строки меню и панели инструментов зависит от ширины окна. Если оно достаточно узкое, то часть инструментов перемещается в раскрывающийся список. Наберите в редакторе команды для построения двух графиков на разных осях в одном графическом окне. Не обязательно набирать много команд — наша цель сейчас состоит в том, чтобы научиться выполнять команды из 206 Часть I. Основы раооты в MATLAB редактора М-файлов. Ограничьтесь командами, приведенными в листинге 5.1. Рис. 5.1. Окно редактора М-файлов MATL AB ............. ... -....................... Листинг 5.1. Команды для построения графиков X = 0:0.1:7,• f = ехр(-х); subplot(1, 2, 1) plotfx, f) g = sin(x); subplot(1, 2, 2) plot(x, g) Сохраните теперь файл с именем mydemo.m в подкаталоге work основного каталога MATLAB, выбрав в меню File редактора пункт Save as. Для запуска на выполнение всех команд, содержащихся в файле, следует выбрать пункт Run в меню Debug, или просто нажать <F5>. На экране появится графическое окно Figure 1, содержащее графики функций. Результат эквивалентен последовательному выполнению команд листинга 5.1 в командном окне. Однако если вы решили построить график косинуса вместо синуса, то достаточно просто изменить оператор присваивания д = sin(x) в М-файле на д = cos (х) и запустить из редактора все команды. Аналогичные действия из командной строки потребовали бы больше времени. Глава 5. М-файлы 207 Если вы создали новый файл в редакторе и набрали в нем команды, то необязательно сначала сохранять его из меню File, а только потом выполнять. Можно сразу раскрыть меню Debug Пункт Run в этом случае заменяется на Save and Run, он позволяет запустить программу, предварительно сохранив ее. Очень удобной возможностью редактора М-файлов является выполнение части команд. Закройте графическое окно Figure 1. Выделите при помощи мыши, удерживая левую кнопку, первые четыре команды листинга 5.1. Затем откройте контекстное меню правой кнопкой мыши и выберете пункт Evaluate Selection. То же самое можете сделать, используя клавиатуру: клавишами со стрелками при нажатой <Shift> выделите первые четыре команды листинга 5.1 и выполните их из пункта Evaluate Selection меню Text или нажмите клаьишу <F9>. Обратите внимание, что в графическое окно вывелся только один график, соответствующий выполненным командам. Выполните оставшиеся три команды листинга 5.1 и проследите за состоянием графического окна. Потренируйтесь самостоятельно, наберите какие-либо примеры из предыдущих глав в редакторе М-файлов и запустите их. Другая возможность для выполнения фрагмента М-файла рассматривается далее в разд. "Разбиение М-файла на ячейки" этой главы. Если в М-файле при наборе сделана ошибка, то она выявляется в процессе исполнения. MATLAB выполняет команды до неправильно введенной, после чего в командное окно выводится сообщение об ошибке. Создайте в редакторе новый файл mydemo2.m, например, при помощи кнопки New М-Ше панели инструментов редактора, со следующими командами: у = [12 3] z = у*у х = у Очевидно, что во второй строке допущена ошибка. Попытка выполнения такого файла приведет к выводу в командное окно следующего сообщения с гиперссылкой на место ошибки. ??? Error using --> mtimes Inner matrix dimensions must agree. Error in ==> mydemo2 at 2 z = y*y Щелчок мыши по гиперссылке с именем М-файла делает окно редактора активным и помещает курсор в строку с ошибкой. 208 Чпсть I. Основы работы в МАТсЛЬ Выполняемые команды осуществляют вывод результата в командное окно. Например, в предыдущем примере вывелось значение у. Для подавления вывода следует завершать команды точкой с запятой. Отдельные блоки М-файла (особенно большого размера) целесообразно снабжать комментариями, которые пропускаются при выполнении, но удобны при работе с М-файлом. Комментарии в MATLAB начинаются со знака процента и автоматически выделяются зеленым цветом (по умолчанию), например: ^построение графика sin(x) в отдельном окне Для исключения части исполняемого кода без его удаления или если количество строк комментариев достаточно велико, можно использовать блок комментариев, начинающийся со строки из двух символов %{ (знака процента и открывающейся фигурной скобки) и заканчивающийся строкой из двух символов %} (закрывающейся фигурной скобки и знака процента). Открытие существующего М-файла производится при помощи пункта Open... меню File рабочей среды либо редактора М-файлов. Открыть файл в редакторе можно и командой edit из командной строки, указав в качестве аргумента имя файла, например: » edit mydemo Команда edit без аргумента приводит к открытию редактора и созданию нового файла без имени (Untitled). Если вы ввели команду с именем несуществующего файла mydemo4: » edit tnydemo4 то MATLAB воспримет это как желание создать новый М-файл с указанным именем. На экран будет выведено диалоговое окно с запросом: "File mydemo4.m does not exist. Do you want to create it?" (Файл не существует, хотите ли вы создать такой файл?). При выборе Yes файл будет создан и откроется в редакторе М-файлов. Примечание В этом же окне имеется флаг Do not show this prompt again, установка которого отключит появление запроса на создание нового файла. В этом случае указание имени несу шествующего файла в качестве параметра команды edit сразу приведет к его созданию. Вы можете восстановить появление этого запроса, обратившись к настройкам редактора. Для этого Гпава 5. М-файлы 209 выберите в меню File рабочей среды или редактора М-файлов пункт Preferences. Появляемся одноименное окно, в левом поле которого следует перейти к пункту Fditor/Debugger и установить флаг Show dialog prompt when editing files that do not exist в правом поле. В редакторе М-файлов может быть одновременно открыто несколько файлов. МА 11 АВ позволяет менять способ отображения файлов в редакторе. По умолчанию окно Editor редактора только одно, и при открытии каждого нового файла оно снабжается закладкой внизу рабочей области с именем файла для быстрого перехода к окну с требуемым файлом или для его закрытия кнопкой на закладке. Последние пять кнопок на панели инструментов (см. рис. 5.1) дают возможность выбрать способ расположения окон с файлами в рабочей области редактора. Например, ее можно разделить по горизонтали или по вертикали для отображения двух файлов. Используя технику dock/undock, можно открыть каждый файл в своем окне редактора или, наоборот, встроить его в другое окно редактора. Для выполнения указанных операций в правой части строки меню присутствуют соответствующие инструменты Dock и Unduck. Если окно редактора единственное, то использование Dock приводит к встраиванию окна редактора М-файлов в окно рабочей среды MATLAB, при этом кнопка Undock дополнительно появляется в заголовке окна редактора для получения обратного эффекта. Настройки редактора М-файлов Для изменения настроек редактора М-файлов следует выбрать в меню File редактора или рабочей среды пункт Preferences. Появляется одноименное диалоговое окно для настройки ряда компонент рабочей среды MATLAB. В левой части окна отображены названия компонент, часть которых представлена раскрывающимся списком (слева находится знак +), позволяющим перейти к требуемой труппе свойств. При изменении опций той или иной компоненты следует выбрать ее в списке и перейти к элементам управления в правой части окна Preferences. Среди компонент есть и редактор М-файлов — раскрывающийся список Editor/Debugger. Рассмотрим далее наиболее важные настройки редактора. При выборе заголовка раскрывающегося списка Editor/Debueeer в правой части окна отображаются общие настройки, связанные с редактированием файлов в MATLAB Панель Editur позволяет использовать вместо стандартного редактора MATLAB любой другой текстовый редактор, скажем, Notepad (Блокнот). Причем создание нового М-файла будет осуществляться по-прежнему в редакторе М-файлов, а открытие файлов — в выбранном 210 Часть I, Основы работы в MATLAB редакторе. К общим настройкам относится также длина списка последних открытых файлов (Number of entries), который располагаегся в меню File редактора или рабочей среды. При запуске MATLAB возможно автоматическое открытие тех файлов, с которыми велась работа во время предыдущей сессии, если при завершении работы редактор нс был отдельно закрыт. Для этого следует установить флаг On restart reopen files from previous MAT! AB session. Сделайте активным пункт Display в левой части окна. В правой части окна появятся средства для изменения режимов. Например, в разделе General Display Options расположены два ф. iara Флаг Show Khe numbers установлен и указывает на то, что в рабочей области выделена колонка для нумерации строк текста в файле, а флаг Enable data tips in edit mode сброшен. Его установка позволяет вывести значение переменной рабочей среды на всплывающую подсказку при наведении на переменную курсора мыши в редакторе. Разумеется, соответствующие переменные должны существовать в рабочей среде, поэтому их просмотр имеет смысл после выполнения М-файла. Воспользуйтесь этой возможностью для получения значений переменных созданного вами файла mydemo.m. При записи выражений, содержащих много скобок, очень полезным оказывается автоматический контроль за их парностью, который настраивается в пункте Keyboard&Indenting. Контроль может производиться в процессе набора, для чы о следует установить флаг Match parentheses while typing. В раскрывающемся списке Show match with вы можете выбрать, как при наборе выражения редактор будет показывать парную скобку: Underline — подчеркиванием, Highlight — выделением фона символа или Balance — выделением фона двух парных скобок. Редактор распознает незакрытые скобки и информирует вас одним из способов, представленных в раскрывающемся списке Show mismatch with Веер— звуковым сигналом. Strikethrough— перечеркнутым символом или None — никак. Возможен также быстрый поиск парной скобки в уже набранном выражении при наведении на нее курсора или оповещенье об отсутствии таковой. Для настройки этой опции установите флаг Match parentheses on arrow key or mouse movement и обратитесь к раскрывающимся спискам, расположенным под ним. Еще одна удобная возможность — режим автосохранения файлов, параметры которого можно изменить в пункте Autosave. Для включения автосохранения следует установить флаг Autosave on. После этого появляется доступ ко всем элементам управления, в частности, можно выбрать интервал времени, через который будет происходить сохранение файла. По умолчанию файл сохраняется с тем же именем и расширением asv, которое можно изме Гпава 5. М-файлы 211 нить и на любое другое, установив переключатель Replace extansiun with, и задав новое расширение в строке ввода справа от переключателя. 1ш не рекомендуем использовать для этих целей расширение т, поскольку при каждом автоматическом сохранении файла будет выводиться диалоговое окно с предупреждением об изменении файла вне редактора. По умолчанию копии автоматически сохраняемого файла размещаются в том же каталоге, что и оригинал, но можно выбрать и отдельный каталог, установив переключатель Single directory и воспользовавшись кнопкой справа от него. Настройка выделения цветом различных фрагментов текста (ключевых слов, текстовых строк, комментариев, ошибок и т. п.) производится в пункте Color, а выбор шрифта и его характеристик— в пункте Font (Custom). Для изменения шрифта следует в списке Desktop tools выбрать Editor и при установленном переключателе Custom на панели Font to Use выбрать тип шрифта, его размер и стиль. Мы обсудили только общие настройки редактора, остальные мы будем упоминать по мере надобности. Например, при наборе программ возможен автоматический отступ, что особенно удобно при использовании вложенных циклон или условных операторов. О наиболее важных опциях, связанных с автоотступом, сказано в главе 7, которая посвящена конструкциям языка программирования МА PLAB. Приведенные в книге примеры лучше всего набирать и сохранять в М-файлах. снабжая их необходимыми комментариями. Применение численных методов и программирование в MATLAB, описанное в следующей части книги, как правило, требуют создания М-файлов. Можно использовать редактор М-файлов и без запуска МАП АВ. Для этого дважды щелкните по значку с М-файлом в окне с содержимым папки, в которой он хранится. Файл откроется в редакторе М-фаилов. Однако при этом редактор является самостоятельным приложением. Файл можно только редактировать, но не выполнять. Разумеется, расширение m в Windows должно быть ассоциировано с приложением meditor.exe (редактором М-файлов), что выбирается либо при установке MATLAB, либо в свойствах папки в Windows. Итак, у нас есть более удобное средство выполнения команд, чем командная строка. Разберем теперь, какие типы М-файлов существуют в MATLAB. 8 Зак. 130 Часть I. Основы работа в MATLAB 212 Типы М-файлоз М-файлы в MATLAB бывают двух типов: файл-программы (Script M-Files), содержащие последовательность команд, и файл-функции (Function M-Files), в которых описываются функции, определяемые пользователем. Файл-программы Файл-программы представляют собой простейший тип М-файлов. Они не имеют входных и выходных аргументов и оперируют переменными, существующими в рабочей среде, или могут создавать новые переменные. Файл-программу mydemo вы написали при прочтении предыдущего раздела. Все переменные, объявленные в файл-программе. становятся доступными в рабочей среде после ее выполнения. Запустите файл-программу mydemo, приведенную в листинге 5.1. Перейдите в окно Workspace (рис. 5.2) и убедитесь, что все введенные в М-файле переменные появились в рабочей среде. Рис. 5.2. Диалоговое окно Workspace после выполнения файл-программы mydemo Все созданные при исполнении М-файла переменные остаются в рабочей среде после ею завершения, и их можно использовать в других файл-программах и в командах, выполняемых из командной строки. Гпава 5. М-файлы 213 Запуск файл-программы осуществляется двумя способами. 1. Из редактора М-файлов так, как описано выше. 2. Из командной строки пли другой файл-программы, при этом в качестве команды используется имя М-файла (без расширения). Применение второго способа намного удобнее, особенно если созданная файл-программа будет неоднократно использоваться впоследствии. Фактически созданный М-файл становится командой, которую понимает MATLAB. Закройте все графические окна и наберите в командной строке mydemo, появляется графическое окно, соответствующее командам файл-программы mydemo.т. После ввода команды mydemo MATLAB производит следующие действия. 1. Проверяет, является ли введенная команда именем какой-либо из переменных, определенных в рабочей среде. Если введена переменная, то выводится ее значение. 2. Если введена не переменная, то MATLAB ищет введенную команду среди встроенных функции. Если команда оказывается встроенной функцией, то происходит ее выполнение. 3. Если введена не переменная и не встроенная функция, то MATLAB начинает поиск М-файла с названием команды и расширением гл. Поиск начинается с текущего каталога (Current Directory); если М-файл в нем не найден, то MATLAB просмазривает каталоги, установленные в пути поиска (Path) (установка путей поиска и текущего каталога описана в следующем разделе). Найденный М-файл выполняется в MATLAB. Если ни одно из вышеперечисленных действий не привело к успеху, то в командное окно выводится сообщение, например, если сделать ошибку: » mydem ??? Undefined function or variable 'mydem'. Последовательность поиска MATLAB говорит о том, что очень важно правильно задавать имя собственной файл-программы при сохранении ее в М-файле. Во-первых, ее имя не должно совпадать с именем существующих функций в MATLAB. Узнать, занято имя или нет можно при помощи функции exist, которую вы уже использовали при работе с переменными few разд "Просмотр и уоаление переменных, выбор имен переменных" главы 1). Во-вторых, имя файла не должно начинаться с цифры, знаков "+" или словом с тех символов, которые могул быть интерпретированы MATLAB 214 Часть I. Основы работы в MATLAB как ошибка при вводе выражения. Например, если вы назовете М-файл с файл-программой 5prog.m, то при ее запуске из меню редактора или по <F5> получите сообщение ??? 5ргод I Error: Missing MATLAB operator. Это не удивительно, т. к. MATLAB ждет от вас 5 + prog (или 5,prog) для вычисления арифметического выражения с переменной prog (или добавления 5 в качестве первого элемента к вектор-строке prog). Следовательно, правильным было бы имя prog5.m (или хотя бы p5rog.m), но только начинающееся с буквы. Обратите внимание, что если вы запускаете на выполнение выделенные команды (могут быть выделены все команды) М-файла с неверным именем при помощи <F9>, то ошибки не будет. Фактически происходит последовательное выполнение команд, не отличающееся от их вызова из командной строки, а не работа файл-программы. Очень распространена еще одна ошибка при задании имени файл-программы, которая на первый взгляд имеет необъяснимые последствия: программа запускается только один раз. Повторный запуск не приводит к выполнению программы. Разберем эту ситуацию на примере файл-программы из листинга 5.1, которую вы сохранили в файле mydemo.m. Переименуйте файл в х.га, затем удалите все переменные рабочей среды из окна браузера переменных Workspace или из командной строки » clear all Выполните файл-программу, например, из редактора, нажав <F5>. Появляется графическое окно с двумя графиками и ничего не предвещает подвоха. Закройте теперь графическое окно и запустите программу снова. Графическое окно больше не создаст ся, зато в командное окно вывелись значения массива х в соответствии с первым пунктом приведенного выше алгоритма поиска MATLAB. Эти обстоятельства следует учитывать при выборе имени файл-программы. Не менее важный вопрос связан с третьим пунктом алгоритма поиска MATLAB— текущим каталогом и путями поиска. Как правило, собственные М-файлы хранятся в каталогах пользовате ля. Для того чтобы система MATLAB могла найти их, следует установить пути, указывающие расположение М-файлов. Глава Ь. М-файлы 215 Установка путей Установка текущего каталога и путей поиска производится при помощи интерфейса рабочей среды MATLAB либо с использованием команд. Содержимое текущего каталога отображается в окне С urrent Directory с одноименной вкладкой (рис. 5.3) Наличие этого окна в рабочей среде зависит от того, установлен пи флаг слева от названия пункта Current Directory меню View рабочей среды. Если флага нет, то следует выбрать указанный пункт меню. Рис. 5.3. Диалоговое окно Current Directory в режиме отображения файлов Текущий каталог устанавливается выбором из раскрывающегося списка Current Directory на панели инструментов рабочей среды MATLAB. Если в списке нет нужного каталога, то его можно добавить в диалоговом окне Browse for Folder, которое появляется после нажатия на кнопку, расположенную справа от списка. Текущий каталог можно задать или создать при помощи инструментов окна Current Directory. Инструмент Show Visual Directory позволяет сделать содержимое окна более информативным (рис. 5.4) Навигация по дереву каталогов осуществляется в области Subfolders, где перечислены имена вложенных папок с указанием в скобках числа файлов ч них и ссылка на папку верхнего уровня <UP>. Ниже расположены флаги для получения сведений о файлах текущего каталога и кнопка Refresh для обновления содержимого окна в случае установки или сброса какого-либо флага. Перед списком файлов расположены две ссылки для создания нового файла (New file) или генерации файла contents.m с информацией о содержимом каталога (run contentsrpt). Эго средство удобно, если в текущем катало 216 Часть I. Основы работы в MATLAB ге много файлов, и вы хотите иметь список файлов с примечанием об их назначении. После создания файла contents.in, состоящего из строк комментариев с именами файлов, появляется еще одна ссылка edit Contents.m. Дополнительно в последнем столбце таблицы с файлами выводится первая встречающаяся строчка комментария в М-файле или информация No help при отсутствии таковой. Рис. 5.4. Диалоговое окно Current Directory в режиме навигации Примечание Комментарий в таблице окна Current Directory будет корректно воспроизводится в окне, если он нс содержит символов национальною алфавита. В противном случае только в файле contents.m будет верно отражен текст комментария (см примечание в рам). "Оформление .графиков" главы 3 по использованию символов кириллицы). Определение путей поиска файлов производится в диалоговом окне Set Path навигатора путей, доступ к которому осуществляется из пункта Set Path меню File рабочей среды. Окно Set Path изображено на рис. 5.5. Гпава 5. М-файлы 217 Рис. 5.5.Диалоговое окно Set Path Для добавления каталога нажмите кнопку Add Folder и в появившемся диалоговом окне Browse for Folder выберите требуемый каталог. Добавление каталога со всеми его подкаталогами осуществляется при нажатии на кнопку Add with Subfolders. Путь к добавленному каталогу появляется в списке М 4TLAB Search Path. Порядок поиска соответствует расположению путей в нем — первым просматривается каталог, путь к которому размещен вверху списка. Порядок поиска можно изменить, или вообще удалить путь к какому-либо каталогу. Для этого 1ребуемын каталог выделяется в списке и его положение определяется при помощи следующих кнопок: □ Move to 1 op — поместить вверх списка; □ Move Up — переместить вверх на одну позицию; □ Move Down — переместить вниз на одну позицию; □ Move to Bottom — поместить вниз списка; □ Remove — удали гь из списка. 218 Часть I. Основы работы в MATLAB Внесенные изменения действуют только до конца текущего сеанса MATLAB. Если желательно сохранить установки путей и для следующих сеансов, то после внесения изменений следует сохранить информацию о путях поиска, нажав кнопку Save. При помощи кнопки Default можно восстановить стандартные установки, а кнопка Revert предназначена для возврата к предыдущим сохраненным установкам. Примечание Рекомендуется хранить собственные М-файлы вне подкаталога too'box основного каталога MATLAB по двум причинам. Во-первых, при переустановке MATLAB файлы, которые содержатся в подкаталогах основного каталога MATLAB, могут быть уничтожены. Во-вторых, при запуске MATLAB все файлы подкаталога toolbox размещаются в иамятм компьютера некоторым оптимальным образом так, чтобы увеличить производительность работы. Если вы записали М-файл в этот каталог, то воспользоваться им можно будет только после перезапуска MATLAB. Команды для установки путей Действия по установке путей дублируются командами. Текущий каталог устанавливается командой cd, например: » cd C:usersigor Ряд команд MATLAB допускает их вызов в функциональной форме. Например, эквивалентное обращение к cd с входным аргументом — строкой следующее: cd(’С:usersigor'). Функциональная форма является более универсальной, поскольку позволяет задавать в качестве входных аргументов не только строки, но и строковые переменные, содержащие имя каталога. Это оказывается полезным при написании собственных приложений. Работа со строковыми переменными описана в главе 8. Функция cd, вызванная без аргумента, возвращает путь к текущему каталогу. Для добавления каталогов в пути поиска служит команда addpath, которая по умолчанию помещает каталог в начало списка поиска, например: » addpath C:elena Это можно проверить при помощи path, которая возвращает список каталогов „входящих в пути поиска. Заметьте, что вызов path как команды приводит к отображению списка путей поиска в командном окне, а обращение в функциональной форме с выходным аргументом р = path позволяет занести пути поиска в строковую переменную (в нашем случае р). Глава S М-файлы 219 Для добавления каталога в конец списка следует использовать параметр -end >> addpath C:alex -end Так же, как и cd, команда addpath может быть вызвана в функциональной форме: addpath (C:elena). При добавлении сразу нескольких каталогов их имена указываются во входных аргументах addpath через запятую. Аналогичные возможности предоставляет path: path(path, 'c:usersigor'), которая помещает каталог в конец списка, a path(’c:usersigor1, path) — в начало. Для уда пения определенного каталога из списка путей поиска предназначена функция rmpath. Например, rmpath(’с: usersigor*) удаляет путь к каталогу c:usersigor из списка путей. Функция rmpath может быть вызвана и в командной форме: rmpath (' с: usersigor') . ^Преду прежде н и el Не удаляйте без необходимости пути к каталогам, особенно к тем, в назначении которых вы не уверены. Удаление может привести к тому, что часть функций, определенных в MATLAB, станет недоступной. Мы привели в этом разделе только наиболее используемые функции (команды) MATLAB для манипулирования каталогами. Полная информация содержится в справочной системе в разделах: MATI. 4В Functions: Functions - Categorical List; Desktop Tools and Development; Workspace, Search Path, and File; Search Path или bile Operations. Файл-функции Рассмотренные выше файл-программы являются последовательностью команд MATLAB, они не имеют входных и выходных аргументов. Для решения вычислительных задач и написания собственных приложений в MATLAB часто требуется программировать файл-функции, которые производят необходимые действия с входными аргументами и возвращают результат в выходных аргументах. Число входных и выходных аргументов зависит от решаемой задачи — может быть только один входной и один выходной аргумент, несколько и тех и других, или только входные аргументы. Возможна ситуация, когда входные и выходные аргументы отсутствуют. В этом разделе разобрано несколько простых примеров, позволяющих понять работу с файл-функ щ 1я м и. Более сложные примеры файл-функций приведены в главе 8. 220 Часть I. Основы работы в MATLAB Файл-функции, так же как и файл-программы, создаются в редакторе М-файлов. Файл-функции с одним входным аргументом Предположим, что в вычислениях часто необходимо пспользова)ь значение функции е Имеет смысл один раз написать файл-функцию, а потом вызывав ее всюду, где необходимо вычисление этой функции для заданного аргумента. Откройте в редакторе М-файлов новый файл и наберите текст лист ши а 5.2. Листинг 5.2. Файл-функиия г одним входным и одним выходным аргументом function f = myfun(x) f = exp(-x)*sqrt((хл2 + l)/(x'4 + 0.1)); Слово function в первой строке определяет, что данный файл содержит файл-функцию. Первая строка является л/еоля.кои функции, в коюроп размещаю гея имя функции и списки входных и выходных аргументов Входные аргументы записываются в круглых скоб» ах после имени функции В нашем примере есть только один входной аргумент - х. Выходной аргумент t указывается слева от знака равенства в заголовке фунт пни. При выборе имени файл-функции следует позабонп ь< я об ощугсгвии конф шктов с занятыми именами в MATLAB. Аналогичный вопрос мы обсуждали выше: как сохранить файл-программу в файле с уникальным именем. Тот же самый подход, основанный на обращении к функции e-tst-. вы можете применить для задания имени файл-функции. После заголовка размещается тело фаил-фу нкцип один или несколько операторов (их может быть достаточно много), которые реализуют алгоритм получения значения выходных переменных из входных. В нашем примере алгоритм простои — по заданному х вычисляется арифметическое выражение и результат записывается в f Теперь сохраните файл в рабочем каталоге, обратите внимание, что выбор пунктов Save или Save as... меню File приводит к появлению диалоговою окна сохранения файла, в ноле File name которого уже содержится название myfun. Сохраните файл-функцию в файле с предложенным именем. Теперь Глава 5. М-файлы 221 созданную функцию можно использовать так же, как и встроенные sin, cos и другие, например, из командной строки: » у _ myfun(1.3) У = 0.2600 При создании файл-функции myfun мы подавили вывод значения f в командное окно, завершив оператор присваивания точкой с запятой. Если этого не сделать, то оно выведется при обращении у = myfun(1.3). Как правило, лучше избегать вывода в командное окно результатов промежуточных вычислений внутри файл-функции. Имя файл-функции не обязательно должно совпадать с именем файла, однако обращение к ней происходит по имени файла. Например, если в файле f22.m содержится функция с заголовком g = init(z), зо ее следует вызывать так: » f = f22(-0.9) а вовсе не » f = init(-0.9) Вызов собственных функций может осуществляться из файл-программы и из другой файл-функции. Предупреждены ejj Каталог, в котором содержатся файл-функции, должен быть текущим, или путь к нему должен быть добавлен в пути поиска, иначе MATLAB просто не найдет функцию или вызовет вместо нее другую с тем же именем (если она находится в каталогах, доступных для поиска). Файл-функция, приведенная в листинге 5.2, имеет один существенный недостаток. Попытка вычисления значений функции от массива приводит к ошибке, а не к массиву значений так, как это происходит при использовании встроенных функций. » х = [1.3 7.2],- » у - nryfui. (х) ??? Error using ==> mpower Matrix must be sguare. Error in --> myfun at 2 f - exp(-x) *sqrt ( (хЛ2 + l)/(x'4 + 0.1)); 222 Часть I, Основы работы в MATLAB Если вы изучили работу с массивами, то устранение этою недостатка не вызовет затруднений. Необходимо просто при вычислении значения функции применить поэлементные операции (см. ризд. "Поэлементные операции с векторами» главы 2). Измените тело функции, как указано в листинге 5.3. Не забудьте сохранить изменения в файле myfun.m! Примечание "j Внесение изменений в текст файл-функции без сохранения файла — часто распространенная ошибка начинающих пользователей. Если файл не сохранен, то, как не сложно убедиться, будет вычисляться старая функция. О том, что файл изменен и не сохранен, свидетельствует звездочка в заголовке окна редактора рядом с именем редактируемого файла. Листинг 5.3- Файл-функция, работающая с массивом значений • . • .. .» . а. .а , .а, .ааа.ааааа -<Ьав,ааБ,« function f = myfun(х) f = exp(-x).‘sqrt((x.л2 + 1)./(х.л4 + 1)); Теперь аргументом функции myfun может быть как число, так и вектор или матрица значений, например- » х = [1.3 7.2]; » у = myfun(х) У = 0.2600 0.0001 Переменная у, в которую записывается результат вызова функции myfun, автоматически становится вектором нужного размера. Постройте график функции myfun на отрезке [0,4] при помощи файл-программы или из командной строки: » х = 0:0.5 :4 ; » у - myfun(х); » plot(x, у) Решение вычислительных задач средствами MATLAB потребует от вас умения программировать файл-функции, соответствующие поставленной задаче (например, правая часть системы дифференциальных уравнений или подынтегральная функция). Гпава 5. М-файлы 223 Решению вычислительных задач посвящена глава 6. Мы рассмоз рим сейчас только один простой пример того, как использование файл-функций упрощает визуализацию математических функций. Только что вы посгроили график при помощи plot. Заметьте, что для вычисления вектора у не обязательно было вызывать myfun — можно сразу записать выражение для него и потом указать пару х и у в plot. Имеющаяся в нашем распоряжении файл-функция myfun позволяет обратиться к специальной функции fplot, которой зребуется указать имя нашей файл-функции (в апострофах) или указатель на нее (с оператором @ перед именем функции) и границы огрезка для построения графика (в векторе из двух элементов) » fpiot('myfun', [0 4]) или » fpiot (Gnyfun, [0 4]) Постройте графики plot и fpiot на одних осях (используйте hold on) так, как показано на рис. 5.6. График, построенный fpiot, более точно отражает поведение функции, т. к. алгоритм fpiot автоматически подбирает шаг аргумента, уменьшая его на участках быстрого изменения исследуемой функции. Рис. 5.6. Сравнение plot и fpiot 224 Часть I. Основы работы в MATLAB Как было отмечено в главе 3, существенную роль играет выбор mai а, причем неудачный выбор шага может привести к неверному результату. Вернитесь к примеру из главы 3, в котором при помощи plot требовалось построить график функции /(с)-е ' (sin.v + 0.1sin(lUU7Lv)) на отрезке |0,1] и предлагалось выбрать шаг 0.01 Запрограммируйте соответствующую файл-функцию myfuni (листинг 5.4) и сохраните ее в файле myfun I .m. ..... --------------------------------------------------------...................................*.........' ...............................-1 Гистинг 5.4. Файл-фун| а . для ьычисления исследуемой функции КЯКм1........................................................ ............................................................................................................................ i function z = myfuni(t) z = exp(-t),*(sin(t) + 0,l*sin(100*pi*t)); Примечание В этом примере мы намеренно использовали z и t. Имена аргументов фаил-функции могут быть любые, они никак не связаны с теми переменными, от которых будет вызываться ф^йл-функцня или в которые будет записываться результат. Например, при вызове а = myfuni(Ь) входной аргумент t станет равным Ь, затем вычислится z, и переменная а примет се значение. Рис, 5.7. Выбор niai а функцией t plor Гпава 5. М-файлы 225 Для построения графика осталось вызвать fpiot. В ея можете узнать о выборе значений аргумента функцией fpiot, указав третьим ее входным аргументом свойства линии и маркера так же, как и в plot. Возьмите точку в качесг ве маркера и сплошную линию » fpiot(@myfuni, [0 1], Получается график, приведенный на рис. 5.7. Абсциссы маркеров соответствуют адаптивно подобранным значениям независимой переменной, в которых fpiot вычислила исследуемую функцию для корректной визуализации. Функция fpiot позволяет задавать ряд параметров, управляющих выбором значений абсцисс (см. разд. "Более подробно о fpiot"главы 6). Файг.-функции с несколькими входными аргументами Написание файл-функций с несколькими входными аргументами практически не отличается от случая одного аргумента. Все входные аргументы размещаются в списке через запятую. Например, листинг 5.5 содержит файл-функцию, вычисляющую длину радиус-вектора точки трехмерного про-Г~2 2 2 странства у]х + у + z . ................ » АО -о • ' - • «"иишдеи>">— Пистинг 5.5. Файл-функция с тремя входными аргументами function г = radius3(х, у. z) г = sqrt(x.-2 + у. Л2 + г.Л2); Для вычисления длины радиус-вектора теперь можно использовать функцию radius3, например: » R = radius3(l, 1, 1) R = 1.732 Кроме функций с несколькими аргументами, MATLAB позволяет создавать функции, возвращающие несколько значений, т. е. имеющих несколько выходных аргументов. Файл-функции с несколькими выходными аргументами Файл-функции с несколькими выходными аргументами удобны при вычислении функций, возвращающих несколько значений (в математике они называются вектор-функцпи). Выходные аргументы добавляются через запя 226 Часть I. Основы работы в МА TLAB тую в список выходных аргументов, а сам список заключается в квадратные скобки. Листинг 5.6 содержит пример такой файл-функции hms для перевода времени, заданного в секундах, в часы, минуты и секунды. : Листинг 5.6. Функция перевода секунд ь часы, минуты и секунды function [hour, minute, second] = hms(sec) hour = floor(sec/3600); minute = flcor((sec - hour*3600)/60); second = sec - hour*3600 - minute*60; При вызове файл-функций с несколькими выходными аргументами результат следует записывать в вектор соответствующей длины: » [Н, М, S] = hms (10000) Н = 2 м = 46 S = 40 Если список выходных аргументов пуст, т. е. заголовок выглядит так: function myfun (а, Ь) ИЛИ function [ 1 = myfun(а, Ь), ТО файл-функция не будет возвращать никаких значений. Такие функции тоже иногда оказываются полезными. Предусмотрена возможность создавать файл-функции, которые сами приспосабливаются к числу входных и выходных аргументов. Большинство функций MATLAB работают именно таким образом. Подробнее о создании файл-ф) нкций и файл-программ написано в части II, посвященной программированию собственных приложений. Функции МАТ1 АВ обладают еще одним полезным качеством — возможностью получения информации о них при помощи команды help, например, help fpiot. Собственные файл-функции гак же можно наделить этим свойством, используя строки комментариев Все строки комментариев после заголовка и до тела функции или пустой строки выводятся в командное окно командой help. Изучите содержимое файла fpiot.m с файл-функцией fpiot, который расположен в подкаталоге toolboxmatlabspecgraph основного каталога MATLAB. Разместите в файл-функции hms комментарии о ее назначении (листинг 5.7) и проверьте: help hms. глава 5. М-файлы 227 ч-,л | . - Листинг 5.7. Помещение комментариев в файл-функцию .... ................................. function [hour, minute, second] - bins (sec) %hms - перевод секунд в часы, минуты и секунда % Функция hms предназначена для перевода секунд % в часы минуты и секунда. % [hour, minute, second] = hms (sec) % sec ~ число секунд % hour - число полн! к часов minute - число полных минут % second - остаток секунд hour = floor(sec/3600); minute = floor((sec - hour*3600)/60); second = sec - hour*3600 - minute*60; Мы намеренно записали в первой строке комментариев краткую информацию о файл-функции. Первая строка комментариев после заголовка функции называется Hl-line и используется при поиске командой lookfor. Эта команда ищет указанное слово в строках Hl-line всех файл-функций в каталогах, указанных в путях поиска, в том числе и в текущем каталоге. Проверьте: lookfor hms. Нашлась как ваша функция, так и ряд встроенных функций для преобразования формата времени. Все встроенные функции MATLAB оформлены именно в таком стиле, поэтому при создании набора функций, предназначенных для широкого круга пользователей, есть смысл придерживаться данных соглашений. Примечание g Блок комментариев нельзя использовать для получения подсказки г.о команде help. Разновидности функций Оформление алгоритма в одной файл-функции не всегда удобно. Некоторые стандартные часто повторяющиеся действия следует оформить в виде отдельных функций, связанных с основным алюритмом. MATLAB предоставляет различные способы организации связей между функциями — приватные функции, подфункции, вложенные функции. 228 Часть I. Основы работы в MATLAB Подфункции Использование подфункций и вложенных функций основано на выделении часта алгоритма в самостоятельную функцию, текст которой содержится в том же файле, что и основная функция. Рассмотрим модельный пример. Предположим, что в файл-функции simple, хранящейся в файле simple.m, часто приходится вычислять некоторое выражение. Конечно, можно простым копированием строк добавить соответствующие операторы (листинг 5.8). Листинг 5.8. Файл-функция simple в файле simple.m .... ............................................................................. _ ......... .... ют. ......... «.•«1.1... 1.1 function simple; X = 1.1; У = 2.1; fl = хл3 - 2*ул3 + 3*(хА2 + ул2) - х*у + 9 х = 3.1; у = 4-2; f2 = хл3 - 2*ул3 + 3*(хл2 + ул2) - х*у + 9 х = -2.8; У = 0.7; £3 = хл3 - 2*ул3 + 3*(хл2 + у~2) - х*у + 9 Проще и нагляднее определить вычисляемое выражение в подфункции £ с двумя входными и одним выходным аргументом и разместить ее в том же М-файле simple.m. Листинг 5.9. Файл-функция simple с подфункцией f в файле simple.m . I 1НЮТ.МММ................. I» ....... ................ , ....... .....а...•-..... Д..........-.1 function simple; % Основная функция fl = f(l.l, 2.1) f2 = f(3.1, 4.2) f3 = f(-2.8, 0.7) function z = f(x, y) % Подфункция z = x~3 - 2*yA3 + 3*(хл2 + ул2) - x*y + 9; Первая функция simple является основной функцией в simple.m, именно ее операторы выполняются, если пользователь вызывает simple, например, из Гпава 5. М-файлы 229 командной строки. Каждое обращение к Подфункции f в основной функции приводит к переходу к размещенным в подфункции операторам и последующему возврату в основную функцию. Файл-функция может содержать одну или несколько подфункций со своими входными и выходными караморами, но основная функция может быть только одна Заголовок новой подфункции одновременно является признаком конца предыдущей. Основная функция обменивается информацией с подфункциями только при помощи входных и выходных параметров. Переменные, определенные в подфункциях и в основной функции, являются вокальными. они доступны в пределах своей функции. Листинг5.10 содержит пример файл-функции с подфункцией, приводящий к ошибке! : Листинг 5.10. Недопустимое использование локальных параметров function simplel; ALP = 5.3; BET = 9.1; fl = f(l.l, 2.1) function z = ffx, y) z = хл3 - 2*ул3 + 3*(хл2 + ул2) - х*у + 9 + ALP*BET; Попытка выполни гь функцию simple! приведет к выводу сообщений о том, что переменная ALP (она первой встретилась при интерпретации оператора) не определена: » simplel ??? Undefined function or variable 'ALP'. Error in ==> simplel > f at 6 z = хл3 - г’у-'З + 3*(хл2 + ул2) - х*у + 9 i ALP*BET; Error in --> simplel at 4 fl = f(l.l, 2.1) Один из возможных верпам сов использования переменных, которые являются общими для всех функции М-файла, состоит в объявлении данных переменных в начале основной функции и подфункции как глобальных, при помошп global со списком имен переменных, разделяемых пробелом (листинг 5.11). Листийг 5.11. Объявление глобальных переменных ......................................... function simple2; global ALP BET ALP = 5.3; 230 Часть I. Основы работы в MATLAB ВЕТ = 9.1; fl = f(l.l, 2.1) function z - f(x, y) global ALP BET z = хл3 - 2*ул3 + 3*(хл2 + yA2) - х*у + 9 + ALP*BET; Следует иметь в виду, что лучшим способом обмена переменными между основной функцией и подфункциями является передача их в параметрах подфункции. Значение глобальных переменных может быть случайно изменено в рабочей среде или при вызове другой файл-программы или файл-функции, которая обращается к одноименным глобальным переменным. Отметим особенности работы с подфункциями, которые часто приводят к ошибкам. Источником ошибок часто является неверное указание подфункции в качестве входного аргумента таких функций MATLAB, как fpiot, fzero, fminsearch, quad и других, вызываемых внутри основной функции. Обязательно использование ссылки на подфункцию, а не ее имени, иначе MATLAB игнорирует подфункцию и начинает искать файл-функцию в текущем каталоге и в путях поиска. Листинг 5.12 содержит простой пример основной функции mainfun с подфункцией subfun, демонстрирующий недопустимость задания имени подфункции в первом входном аргументе fpiot. Листинг 5.12. Правильный и неправильный вызов fpiot в основной функции function mainfun % основная функция figure & создание графического окна subplot(2, 1, 1) % создание верхней пары осей fpiot(@subfun, [1 5]) % правильный вызов fpiot с указате; ем на подфункции subplot(2, 1, 2) % создание нижней пары осей fpiot(1 subfun', [1 5]) % неправильный вызов fpiot с именем подфункции function у = subfun(х) % подфункция у = sin(pi*x); В результате вызова » mainfun создается графическое окно с двумя парами осей, причем только верхний график, полученный при вызове fpiot с указателем на подфункцию, являет- Гпава 5. М-файлы 231 ся верным. Если в текущей папке и путях поиска нет файл-функции subfun, то нижний график содержит прямую линию. Так всегда работает fpiot, когда MATLAB не может найти М-файл с файл-функцией для построения графика. Заметьте, что при наличии в текущей лапке файл-функции suhfun в М-файле fpiot будет пытаться построить ее график. Подфункция доступна только внутри основной функции. Если вы решите вызвать подфункцию f не из файл-функции simple (см. листинг 5.11), а из другой файл-функции, файл-программы или просто из командной строки, то получите сообщение об ошибке: » f(1, 1) ??? Undefined command/function 'f'. Разумеется, если в текущем каталоге (или путях поиска MATLAB) находится файл-функция f, хранящаяся в файле f.m, или в рабочей среде объявлена переменная f, то ошибки может и не быть, или она будет другого характера. Если доступны различные одноименные функции (приватные, подфункции, встроенные, пользовательские из текущего каталога, функции из Toolbox), то приоритет связывания имени и объекта следующий. 1. Ищется имя в текущей рабочей среде: могут быть определены либо переменная с таким именем, либо вложенная функция (см. далее в этой главе), либо анонимная функция или inline-функция, которые рассматриваются в следующей главе. 2. Ищется подфункция в текущем М-файле. 3. Ищется приватная функция (см. следующий раздел). 4. Ищется встроенная функция (built-in function). 5. Далее производится поиск требуемой файл-функции в текущем каталоге и путях поиска MATLAB. Таким образом, пользовательские функции имеют приоритет за исключением случая файл-функции из текущего каталога по отношению к встроенной. Как узнать, является ли функция MATLAB встроенной или нет? Для этой цели служит специальная функция exist, о которой шла речь в главе 1. Возвращаемые значения в случае, если аргумент функция, таковы: 1 — имя занято под переменную рабочей среды, 2 — функция расположена в путях поиска файлов, 5 — встроенная функция (built-in function). Приватные функции и подфункции не идентифицируются. Сравните, например max и bar: » exist max ans = 5 232 Часть I. Основы работы в МАТ/АВ » exist bar ans - 2 Итак, функция шах является встроенной, a bar — нет. Поэтому, если в текущем каталоге есть две функции nicix и bcii?, которые вызываются из команд-ной строки или некоторой функции, то обращение будет происходить к встроенной функции max и пользовательской bar. Вложенные функции Другой разновидностью функций, доступных в одном М-файле, являются вложенные функции. Если подфункция является внешней по отношению к основной функции, то вложенная функция является внутренней. В силу этого обстоятельства переменные из рабочей среды основной функции доступны и во вложенной функции. Простейшая структура функции main, содержащей вложенную fnested, представлена в листинге 5 13. Листинг 5.13. Простейшая вложенная функция function main; ALP = 5.3; BET = 9.1; fl = fnested(1.1, 2.1) function z = fnested(x, y) z = хл3 - 2*ул3 + 3*(хл2 + ул2) - х*у + 9 + ALP*BET; end end Сравните эту функцию с функцией simplel из листинга 5.10, где функция f реализовалась как подфункция, и переменные alp и бет были неизвестны внутри подфункции. Теперь переменные alp и бет доступны в теле функции. При написании вложенных функции следует использовать оператор end для закрытия тела функции. Поэтому вложенная функция может размещаться в любом месте тела функции, ее содержащей. Основная функция также завершается оператором end. В одном М-файле допускается использование подфункций и вложенных функций одновременно, но тогда последним оператором подфункции должен быть end. Глава 5. М-файлы 233 Уровень вложенности функций не ограничен. По лому при многоуровневом вложении возникает вопрос, какие вызовы допустимы, а какие нет. Функция может обратиться к своей вложенной функции, но нс может использовать вложенную функцию нижнего уровня, Вложенная функция может обратиться к функции тою же уровня. Функция нижнего уровня может вызвать функцию верхнего уровня, в которую она вложена, и все функции, доступные из нее. На практике такой сложной структуры вложенности функций, как правило, не требуется. Другая проблема многоуровневого вложения— это доступность переменных в среде вложенных и внешних функций. Переменные, определенные во внешней функции, доступны и во вложенной, и наоборот. Исключение составляет случай коллизии переменных для функций одного уровня В этом случае во вложенных функциях это разные локальные переменные с одним именем. Естественно, что во внешней ф нкции доступ к двум переменным с одним именем невозможен, поэтому ни одна из них недоступна. Вложенные функции могут быть доступны не только в М-файле. если использовать указатель на вложенную функцию. В листинге 5.14 приведен пример такого использования вложенной функции для создания двух однотипных функций с разными параметрами. Листинг 5.14. Указатель на вложенную функцию function pointer - f rxed parinla. b, c) % а, о, с - параметры процесса. % Создание указателя на вложенную фунщию pointer = Эргосезз; function у = process (t) у = a’sin(b.*t + с}; end end Запишите функцию fixed_parm в текущий каталог и выполните команды: » f = fixed-jearm (1.5, 2, О) ; > > g = fixed carmtl, 10, 25}; » fpiot(f. [-2, 2]) > > hold on; > > fpiot(g, [-2, 2]) 234 Часть I. Основы работы в MATLAB В результате будут построены графики двух разных функций. Таким образом, созданы две функции f и д, зависящие от одной переменной, для koto-dux значения параметров зафиксированы на момент обращения к функции fixed_parm. Приватные функции Простейший прием сделать некоторые функции видимыми или нет, состоит в размещении М-файлов в рабочих каталогах. Определенная структура каталога с пользовательскими файл-функция ми позволяет задать некоторые вспомогательные функции, которые используются только файл-функциями, содержащимися в М-файлах данного каталога, а для файл-функций из других каталогов являются недоступными. Для этого следует создать подкаталог с именем private и разместить в нем вспомогательные файл-функции. Рисунок 5.8 поясняет доступ к приватным функциям. *НД Vrorkl private- I— funl.m '— fun2.m calc.m myplot m fiinl.m fun2.m test.m—' main.rn-’ Файл-функции test и main не имеют доступа к приватным функциям, размещенным в подкаталоге private другого каталога. Рис. 5.8. Схема доступа к приватным функциям Разбиение М-файла на ячейки Вернемся теперь к файл-программам и обсудим удобное средство выполнения отдельных их частей. Один из способов — выделение фрагмента кода и Гпава 5 М-файлы 235 его выполнение при помощи <F9> — был рассмотрен выше. Кроме этого, редакт ор М-файлов позволяет разбить всю программу на ячейки и выполнять их независимо. Текст разбивается на ячейки при помощи строк комментариев, начинающихся с двух идущих подряд знаков процента (% %). Для использования средств редактора при работе с ячейками кода следует установить режим Cell Mode, выбрав в меню Cell пункт Enable Cell Mode. При этом становятся доступными другие пункты этого меню, а выбранный изменится на Disable Cell Mode для отмены режима. Кроме того, появляется панель инструментов для работы с ячейками. Для оформления файла можно использовать следующие пункты меню Cell: □ Insert Cell Divider — вставка разделителя ячеек из двух символов процента (%%). Если курсор находится не в первой позиции строки, то разделитель вставляется за текущей строкой, иначе перед ней; □ Insert Cell Divider around Selection— вставка разделителей ячеек (% %) до и после выделенного фрагмента (строки предварительно должны быть выделены); □ Insert Text Markup— раскрывающийся пункт меню для вставки строк образцов комментариев в место, где расположен курсор. Способ исполнения ячеек файла также определяется в меню Cell: □ Evaluate Current Cell — выполняются строки текущей ячейки, и она остается тек> щей; □ Evaluate Current Cell and Advance — выполняются строки текущей ячейки, и текущей становится следующая ячейка; □ Evaluate Entire File — выполняется весь файл. При выполнении файла зребуется, чтобы переменные, используемые в командах и функциях, присутствовали в среде Workspace. Поэтому не рекомендуется исполнять ячейки файл-функций, т. к. имена аргументов при обращении к функции и имена параметров в тексте функции, как правило, не совпадают. Предупреждение Выполнение ячеек М-файла в режиме Cell Mode происходит без предварительного сохранения его на диске, в отличие от запуска всего файла при помощь <F5>. Поэтому, если вы отлаживаете шаил, не забудьте его сохранить, иначе внесенные изменения могут быть потеряны. 236 Часть I. Основы работы в MATLAB Перемещение по ячейкам вверх и вниз осуществляется выбором в меню Cell пунктов Previous Cell и Next Cell соответственно. Цвет фона ячейки определяется в настройках редактора в диалоговом окне Preferences. В нем следует выбрать пункт Display, установить флаг Show cell highlighting и выбрать цвет в раскрывающемся списке справа of флага Для освоения простейших принципов работы с М-файлами. разбитыми на ячейки, создайте новый файл и скопируйtc туда 1екс1 из файла mydemo.m (см. листнн! 5.1). Переместите курсор в конец строки piot(x,f) и в меню Cell выберите пункт Insert Cell Divider. После л ой строки вставшей строка из двух знаков процента %*, летящая файл на две ячейки Выполните весь файл, используя пункт Evaluate Entire File или соответствующую кнопку на панели инструментов. Измените функцию ехр(-х) на 1од{1 + х) и выполните содержащийся в первой ячейке код. выбрав пункт Evaluate Current Cell Вид первого графика изменится. Аналогичным образом можно вывести график другой функции на трутне оси. выполнив вторую ячейку. Не закрывайте графическое окно, потому что мы сейчас рассмотрим еще один М-файл. разбитый на ячейки.— автоматически созданную файл-функцию, которая соответствует нашему графическому окну. Перейдите в графическое окно и сгенерируйте код для его построения, выбрав в меню File пункт Generate M-File В редакторе М-файлов создается новое окно с текстом файл-функции createfigure, приведенным в листинге 5.15. Листинг 5.15- Автоматически созданная функция для графического окна function oreatefiguretxl, yl, у2) 4CREATE71GURE(X1, Yl, Y2) % Xl: vector of x data % Yl: vector of у data % Y2: vector of у datj % Auto-generated by MATLAh on 24-Jul-2004 08:16:35 % % Create f igure frgurel = figure('PaperPosition', [0.6345 6.345 20.3 15.23], ‘Papersize‘, [20.98 29.681) ,- %'t <reate axes axesl = axes(1 Outerposition', [0 0 0.4823 1], 'Parent1,figurel); hold(axesl, 'all1); Г лава 5. М файлы 23/ %% Create plot plotl - plot(xl, yl, 'Parent', axesl) %% Create axes axes2 = axes(1 Outerposition', [0.4823 0 0.5177 1], 'Parent', figurel); hold(axes2, 1 all'); %% Create plot plot2 = plot(xl, y2, 'Parent’, axes2); MATLAB сощает файл-функцию с выделением ячеек для каждого шага построения: создания графического окна, осей и графиков, вы можете изменить и дополнить текст этой файл-функции по своему усмотрению. Файл-функция зависит от трех аргументов xl, yl и у2, являющихся формальными параметрами, которые не определены в рабочей среде Workspace. Можно, например, удалить заголовок, превратив файл-функцию в файл-программу, и заменить формальные переменные xl, yl и у2 на переменные рабочей среды х, f и g соотвегственно. Последовательное выполнение ячеек полученной файл-программы продемонстрирует все шаги для создания графического окна с графиками нужной функции. В качестве упражнения добавьте в нужные ячейки команды для вывода заголовков к графикам. Разбиение файл-программы на ячейки и их выполнение дает возможность контроля за ходом работы программы. Для файл-функций применение этой технологии сопряжено с определенными трудностями, поскольку ее переменные являются локальными. Это обстоятельство подчеркнуто в справочной системе MATLAB. Редактор М-файлов включает в себя более мощный инструмент-— отладчик, описанию и демонстрации возможностей которого мы уделим далее внимание при программировании приложений (средства диалоговой отладки рассматриваются в г wee 8). Обратимся теперь к еще одной привлекательной возможности MATLAB, которая помогает эффективно реализовывать собственные алгоритмы — к средству M-Lint для диагностики М-файлов. Диагностика М-файлов В состав среды MATLAB включено средство M-Lint для проверки качества и корректности написанного кода. Для этого после сохранения М-файла следует в меню редактора Tools выбрать пункт Check ( ode with M-Lint (если 238 Часть I. Основы работы в MATLAB файл не был сохранен, то этот пункт меню называется Save and Check Code with М-Lint). Воспользуйтесь этим средством для проверки файл-функции из листинга 5.9. После выполнения проверки появится окно М-Lint Code Check Report с отчетом, представленное на рис. 5.9. Рис. 5.9. Окно М-Lint: Code Check Report с диагностическими сообщениями В каждом предупреждении указаны номер строки и выявленный недочет. Номер строки является гиперссылкой, щелчок мыши по которой приводит к переходу к соответствующей строке в редакторе М-файлов. В нашем примере выявлены три типа недостатков. Во-первых, выведено сообщение о том, что в первой строке не требуется символ точки с запятой. Во-вторых, переменные fl, f2, f3 нигде не используются (строки 3,4 и 5). В-третьих, пользователю рекомендуется < тавить точку с запятой для подавления вывода результатов выполнения на экран (строки 3,4 и 5). В нашем случае имеет смысл учесть информацию об использовании точек с запятой. Остальная диагностика не важна, т. к. пример с файл-функцией simple иллюстрировал другие возможности пакета MATLAB. Гпава 5. М-файлы 239 Задания для самостоятельной работы I. Напишите и выполните файл-программу построения графиков следующих функций с заголовком, подписями к осям, сеткой. Используйте разные типы линий и маркеров. Для вычисления значений функций создайте файл-функцию. Для fpiot и plot используйте две подобласти на одном рисунке: • w(x) = sin(ln(x + l))+cos(ln(x + l)), . /(*) =-----Ц-. [-0.9, 0.9]; xG [0, 2л]; . g(x) = xxX, хе [0.5, 1.5]; 2 й(х) = ЬГП 6л Х-— х2 3 * хе [0,1]. 2. Напишите и выполните файл-программу для построения поверхностей. Для вычисления значений функций создайте файл-функцию: • z(x, j) = e3isin0-5 * * *’9' +e^,nO'57W, x,je[-l,l]; • w(x, y) = sin(e2*-e 2>J+cos(e2>l -e 2x), x, ye [0,1]. 3. Напишите файл-функцию для решения следующих задач: • по заданному вектору определить номер его элемента с наибольшим отклонением от среднего арифметического всех элементов вектора; • вычислить сумму всех элементов вектора с нечетными индексами; • найти максимальное значение среди диагональных элементов заданной магрицы; • переставить первый столбец квадратной матрицы с ее диагона пью; • просуммировать все внедиагональные элементы заданной матрицы; 240 Часть I. Основы работы в MATLAB • заменить максимальный элемент вектора средним значением всех его элементов; заменить элемент матрицы с индексами 1.1 произведением всех элементов матрицы; • построить многоугольник (замкнутый) с координатами вершин (х,-. у;), заданными векторами v и j * • отобразить элементы заданного вектора синими маркерами, а максимальный элемент— красным и вернуть значение и номер максимального элемента. ЧАСТЬ II Вычисления И ПРОГРАММИРОВАНИЕ Глава 6 Методы вычислений в MATLAB MATLAB обладает большим набором специальных функций, реализующих различные численные методы. Нахождение корней уравнений и систем, приближение табличных функций, интегрирование, решение задач линейной алг ебры, оптимизация, решение систем обыкновенных дифференциальных уравнений, работа с разреженными матрицами — воз далеко не полный перечень возможное гей. предоставляемых MATLAB. В этой главе разобрано решение типовых задач на применение вычислительных методов. Теоретические проблемы численного анализа рассматриваемых задач выходят за рамки настоящей книги. Исследование функций Решение уравнений, нахождение максимума или минимума функции одной или нескольких переменных осуществляются вызовом специальных функций MATLAB. Число аргументов этих функций может быть различным, в зависимости от требуемого вида результата. Для работы с ними, как правило, необходимо запрограммировать исследуемую функцию, например, в виде файл-функции. При этом можно обращаться к файл-функции либо по имени файла, либо по ссылке на нее (см. разд. "Файл-функции"главы 5). Если исследуемая функция задается достаточно простой и короткой формулой, то не обязательно составлять файл-функцию. Вместо этого удобно ввести встраиваемую функцию (inline-функцию), воспользовавшись функцией inline, или определить анонимную функцию. Встраиваемые и анонимные функции Вс граиваемая функция определяется при помощи функции ini ine, обращение к которой выглядит следующим образом: И.ля_функции = iniine('формула', список_аргументов) 9 ЗахВО 244 Часть II. Вычисления и программирование Список аргументов не обязателен, а 'формула' является текстовой строкой и задает выражение для вычисления значения функции. Следующий пример демонстрирует создание в рабочей среде встраиваемой функции fun; » fun = inline('sin(х) - х.Л2.*cos(x)*) fun - Inline function: fun(x) = sin(x) - x.A2.*cos(x) Inlme-фунция fun может быть использована как любая другая функция MATLAB, например: » у = fun(0.5) У = 0.2600 Если функция зависит от нескольких переменных, то все они являются аргументами введенной inline-функции и располагаются в алфавитном порядке: >> funl = inline(’sin(а‘х) - х. Л2.*cos(b*x) ' ) funl = Inline function: funl(a,b,x) = sin(a*x) - x.Л2.*cos(b*x) Для изменения порядка аргументов их следует перечислить через запятые в списке после выражения, определяющего вид функции: » fun2 = inline(’sin(а‘х) - х.Л2.*cos(b*x)1, 'х', ’а’, 1Ъ’) f un2 = Inline function: fun2(x, a, b) = sin(a*x) - x.Л2.*cos(b*x) Если в списке случайно пропущен хотя бы один из аргументов, то inline-функцией воспользоваться не удастся: » fun3 = inline('sin(а*х) - х. Л2.*cos(b*x) 1, 'х', ’b’) fun3 = Inline function: fun3(x,b) - sin(a*x) - x.Л2.*cos(b*x) Даже при наличии переменной а в рабочей среде вызов функции fun3 при ведет к сообщению о том, что аргумент а не задан: >> а = 1 ; » fun3(5,0) Глава 6. Методы вычислений в MATLAB 245 ??? Error using ==> inlineeval Error in inline expression ==> sin(a*x) - x.л2.*ros(b*x) ??? Error using ==> eval Undefined function or variable 1 a’, Error in ==> inline.subsref at 25 INLINE_OUT_ = inlineeval(INLINE_INPUTS_, INIINE_OBJ_.inputExpr, INLINE_OBJ_.expr); Этот пример демонстрирует, что при вычислении значения встраиваемой функции переменные рабочей среды недоступны. Все аргументы функции inline должны быть символьными строками, заключенными в апострофы, или строковыми переменными. В противном случае получается недопустимая конструкция. Работа со строковыми переменными описана далее в книге, а при чтении этой главы достаточно придерживаться простого правила — ставить апострофы в аргументах функции inline. Аль гернативный способ задания исследуемой функции состоит в объявлении анонимной функции с помощью оператора указателя (@): Имя_функции = @(список_аргументов) формула В отличие от inline-функции,, и аргументы, и формула записываются в обычном виде, а не как текстовые строки в апострофах. Кроме того, анонимной функции доступны переменные рабочей среды, которые входят в формулу. Одпако они являются константами, в качестве которых берутся значения этих переменных в момент создания анонимной функции, и последующее изменение их значений не будет учитываться при вычислении функции: » а= 1; » gun3 = @(х, Ь) (sin(a*x) - х.Л2.*cos(b*x)) дипЗ = @(х, b) sin(a*x) - х.Л2.*cos(Ь*х) » дипЗ(5, 0) ans - -25.9589 » а = 1000; » дипЗ(5, 0) ans = -25.9589 По способу использования анонимная функция напоминает inline-функнию, но отличается тем, что создается указатель на функцию, который связан с 246 Часть II. Вычисления и программирование исполняемым кодом. Это хорошо видно либо в окне Workspace, либо при выводе информации о функциях с помощью whos: > whos gun3 Name Size Bytes Class gunJ lxl 16 function_handle array Grand total is 1 element using 16 bytes » whos fun3 Name Size Bytes Class fun3 lxl 908 inline object Grand total is 79 elements using 908 bytes Информация о выделенной под функции памяти показывает, что для анонимной функции исполняемый код и указатель на нее отделены, а для iriine-функции это единый объект. Вышеописанные способы задания исследуемых математических функций (по имени М-файла, по ссылке, анонимная функция или inline-функция) допустимы во всех вычислительных алгоритмах MATLAB, о которых пойдет речь в следующих разделах. Мы будем использовать все эти возможности и ряд других. Подчеркнем, что для достаточно простых исследуемых функций удобнее всего определить соответствующую inline или анонимную функцию. В то же время, если функция задана громоздким выражением, лучше всего написать соответствующий М-файл. А в случае, когда функция вычисляется по сложному алгоритму, это оказывается просто необходимым. Решение уравнений Для нахождения корней произвольных уравнений служит функция f zero, а для определения всех корней полиномов применяется roots. Решение произвольных уравнений Функция fzero позволяет приближенно вычислить корень уравнения на некотором интервале или ближайший к заданному начальному приближению. В простейшем варианте fzero вызывается с двумя входными и одним выходным аргументом х = fzero ('func_name1, х0), где func_name — ИМЯ файл-функции, вычисляющей левую часть уравнения, хо — начальное приближение к корню, х — найденное приближенное значение корня. Решите, например, на отрезке [-5, 5] уравнение: sinx-x2 cosx = 0. (6-1) Главг:Ь Мет эры вычислений в MATLAB 247 Перед нахождением корней полезно построить график функции, входящей в левую часть уравнения. Для получения графика можно прибегнуть к plot, но все равно понадобится запрограммировать функцию, поэтому имеет смысл воспользоваться fpiot, которая к тому же позволяет получить более точный график по сравнению с plot (написанию собственных файл-функции посвящен разд. "Файч-функции" глав,,! 5). В листинге 6.1 приведен текст требуемой файл-функции. function у = myf(х) у = sin(x} - х.Л2.*cos(х); Теперь постройте график функции myf, используя fpiot, и нанесите сетку. » fpiot(‘myf’, [-5 5]) » grid on Из графика функции, изображенного на рис. 6.1 (пояснения на графике нанесены средствами MATLAB), видно, что на этом отрезке имеются чегыре корня. Один корень равен нулю, в чем несложно убедиться, подставив х = О в уравнение (6.1). Рис. 6.1. График левой части уравнения (6.1) 248 Часть II. Вычисления и программирование Уточните значение корня, расположенного вблизи х = —5, при помощи fzero: » xl - fzero('myf‘, -5) Zero found in the interval: [-4.7172, -5.2]. xl - -4.7566 Итак, приближенное значение корня равно -4.7566. При указании начального приближения к корню алгоритм fzero автоматически отделяет корень, т. е. вблизи заданного начального приближения находится отрезок, содержащий корень. В этом случае fzero может использовать больший интервал определения функции, чем исходный отрезок [-5, 5]. Проверьте ответ, вычислив значение функции myf в точке xl » inyf(xl) ans = 2.6645е-015 Конечно, то. что значение функции близко к нулю, вообще говоря, не означает достаточную точность найденного корня. Гарантированная точность приближенного значения определяется расстоянием до его истинного значения или (что фактически то же самое) количеством верных значащих цифр. Заданию точности вычислений посвящен разд. "Управление ходом вычислении" данной главы. Для того чтобы увидеть больше значащих цифр корня xl, следует установить формат long и вывести xl еще раз (точность проводимых пакетом MATLAB расчетов не зависит от формата вывода результата!). » format long » xl Xl = -4.75655940570290 Возникает вопрос, сколько в ответе точных значащих цифр, т. е. с какой точностью найдено решение. На компьютере вычисления производятся с числами, имеющими 52 двоичных разряда в мантиссе (без учета порядка числа). Это соответствует относительной погрешности представления чисел, которую возвращает функция ерз, вызываемая без входных аргументов: » eps ans = 2.220446049250313е-016 Глава 6. Методы вымолены- в MATLAB 249 Алгоритм функции fzero по умолчанию находит корень уравнения с точностью ерз, т. е. + 2 в шестнадцатом знаке после десятичной точки — практически с максимально возможной точностью. Чтобы убедиться в этом, измените формат представления данных на long е и bl (ведете xl: » format long е » xl Xl - -4.75б559405702904е+000 Число значащих цифр увеличилось на одну (по сравнению с форматом long). Это самое точное представление числа в десятичной форме для пакета MATLAB- Измените последнюю цифру 4 на 5 и вычислите значение myf в точке xl: » xl = -4.756559405702905е+000; » myf(xl) ans = -1.765254609153999e-014 Поскольку исследуемая функция сменила знак, то между этими значениями лежит искомый корень уравнения. Следовательно, ошибка в найденном корне в последней значащей цифре. Численное решение любой задачи требует дополнительных расчетов, подтверждающих (как правило, только косвенно) правильность полученных результатов. Для задачи нахождения корня уравнения вы только что проделали такой численный эксперимент. Проверьте работу fzero, вычислив корень myf, расположенный вблизи нуля, там, где точное значение корня равно нулю. » х4 = fzero('myf’> -0.1) Zero found in the interval: [0.028, -0.19051]. x4 - -1.242386505963434e-022 Функция fzero действительно гарантирует, что точность решения не меньше eps. Найдите самостоятельно корни х2 и хЗ, расположенные около точек -2 и -5. 250 Часть II. Вычисления и программирование Вместо начального приближения вторым параметром fzero можно задагь интервал, на котором следует найти корень: » х2 = fzero!'myf', [-3 -1]) Zero found in the interval: [-Л -1]. x2 - -1.85392745969615 На границах указываемого интервала функция должна принимать значения разных знаков, иначе выведется сообщение об ошибке! В качестве исследуемой функции может выступать и встроенная математическая функция,например » fzero('sin', [2 4]) Zero found in the interval: [2, 4]. ans = 3.14159265358979 Допустимы другие способы вызова fzero, о которых шла речь ранее в этой главе. Во-первых, функцию с исследуемой математической функцией можно задать при помощи указателя на нее: »х2 = fzero (vtaiyf, [-3 -1]); х2 = -1.8539 Во-вторых, воспользовавшись функцией inline: » fun = inline!'sin(х) - x."2.*cos(x)') fun = Inline function: fun(x) = sin(x) - х.Л2.*соз(х) » xl = fzero(fun, -5) xl = -4.7566 » fun(xl) ans = 2.6645e-015 В-третьих, создав анонимную функцию: >> fun = @(х) sin(x) - x.*2.*cos(x) fun - @(x) sin(x) - х.л2.*соб(х) » xl = fzero(fun, -5) Г лава 6. Методы вычислений в MATLAB 251 xl = -4.7566 Обращение к fzero с двумя выходными аргументами позволяет не только приближенно найти корень, но и получить значение функции в найденной точке. » [х2, f] = fzero(@myf, -2) х2 = -1.8539 f = -2.2204е-016 Важной особенностью fzero является то, что она вычисляет только те корни, в которых функция меняет знак, а не касается оси абсцисс. Найти корень уравнения х2 =0 при помощи fzero не удается: » fun=inline{'х."2') ; » х - fzero(fun, -0.1) Exiting fzero: aborting search for an interval containing a sign change because NaN or Inf function value encountered during search (Function value at 1.372960e+154 is Inf) Check function or try again with a different starting value. x4 = NaN В данном примере fzero пыталась найти промежуток, на границах которого значения функции myf имеют различные знаки, что гарантировало бы существование корня на этом промежутке. Такой промежуток, естественно, определить не удалось, и fzero вывела сообщение об ошибке в командное окно. Программирование собственных приложений с использованием вычислительных функций требует получения сведений о завершении вычислительного процесса для перехода к соответствующему блоку алгоритма. Обращение к fzero стремя выходными аргументами » [xl, fl, flag] = fzerolfun, 0.1); позволяв! выбрать дальнейшие действия в зависимости от содержимого переменной flag. Положительное значение flag свидетельствует об успешном завершении вычислительного процесса. Отрицательное значение говорит о том, что либо не удалось отделить интервал со сменой знака функции на границах, либо в процессе вычислений получилось комплексное значение, бесконечность, или выполнена операция с неопределенным результатом, например, деление нуля на ноль. 252 Часть II. Вычисления и программирование Функция fzero, так же как и большинство вычислительных функций MATLAB, допускает управление многими параметрами заложенных в ней алгоритмов. Кроме того, для контроля выполнения алгоритма и изменения его параметров следует получить информацию о ходе вычислений. Управление алгоритмом и контроль за ним требуют специальных способов вызова функций MATLAB (см. разд. "Управление ходом вычислений"данной главы и приложение I). В ычисление всех корней полинома Полином в MATLAB задается вектором его коэффициентов, например, для определения полинома р = х7 +3.2Л5-5.2л4 + 0.5х2 + х-3 следует использовать команду » р = [1 О 3.2 -5.2 О 0.5 1 -3]; Число элементов вектора, т. е. число коэффициентов полинома, всегда на единицу больше его степени, нулевые коэффициент должны содержаться в векторе. Функция polyval предназначена для вычисления значения полинома от некоторого аргумента: » polyval(р, 1) ans = -2.5008 Аргумент может быть матрицей или вектором, в этом случае производится поэлементное вычисление значений полинома и результат представляет матрицу или вектор того же размера, что и аргумент. Нахождение всех корней полиномов осуществляется при помощи функции roots, в качестве аргумента которой указывается вектор с коэффициентами полинома. Функция roots возвращает вектор корней полинома, в том числе и комплексных: » г = roots(р) -0.5668 + 2.06981 -0.5668 - 2.06981 1.2149 0.5898 + 0.64351 0.5898 - 0.64351 -0.6305 + 0.55341 -0.6305 - 0.55341 Гпава 6. Методы вычислений в MATLAB 253 Известно, что число всех корней полинома совпадает с его степенью. Убедитесь в правильности работы roots, вычислив значение полинома от вектора его корней: » polyval(p,r} ans “ 1.0е-012 * -0.1008 + 0.08991 -0.1008 - 0.0899i -0.0666 0.0027 - 0.0018i 0.0027 + 0.0018i 0.0102 - 0.0053i 0.0102 + 0.0053i В верхней строке результата содержится общий множитель 1.0е-012, на который следует умножить каждую компоненту получившегося вектора. Нахождение экстремумов функций Вычислительные функции МАП,АВ позволяют найти точки минимума функции одной или нескольких переменных. Результатом является локальный минимум, т. е. точка, в окрестности которой значения исследуемой функции превышают ее значение в точке локального минимума. Для определения точек локального максимума нет специальной функции, поскольку достаточно искать минимум функции с обратным знаком. Минимизация функции одной переменной Поиск локального минимума функции одной переменной на некотооом отрезке осуществляется при помощи fminbnd, использование которой схоже с fzero. Найдите локальные минимумы функции 2 е +sin37tx (6.2) на отрезке [-1.5,1.5]. Требуется предварительно создать соответствующую файл-функцию, назвав ее, к примеру ftest, или ввести inline или анонимную функцию (написанию собственных файл-функций посвящен разд. "Файл-функции" главы 5). 11еред нахождением локальных минимумов постройте график исследуемой функции командой fpiot. Из графика, приведенного на рис. 6.2, Видно, что 2Ь4 Часть II Вычисления и программирование исследуема? функция имеет четыре локальных минимума. Ri 1числите значение х, при котором достигается второй локальный минимум, задав первым аргументом fminbnd имя файл-функции или указатель на нее, а вторым и третьим -— границы отрезка, на котором ищется локальный минимум (установка точности и дополнительных параметров минимизации описана в разо. "Управление ходом вычислений" данной главы): » х2 = fminbnd(@ftest, -0.5, 0) х2 = -0.1629 Для лучшего понимания работы fminbnd задайте интервал поиска, содержащий все точки локальных минимумов. » хх = fminbnd('ftest1, -1.5, 1.5) хх = 0.4861 Для одновременного вычисления значения функции в точке минимума следует вызвать fminbnd с двумя аргументами: » [х2, f] = fminbnd(@ftest, -0.5, 0) x2 = -0.1629 Глава 6. Методы вычислений в MATLAB 255 f = 0.0275 Так же, как и fzero, функция fmintnd может быть вызвана с тремя выходными аргументами: » [х2, f, flag] = fminDnd(@ftest, -0.5, 0); Аргумент flag может принимать три значения: положительное — при нахождении локального минимума, нулевое — при достижении максимального количества вызовов исследуемой функции и отрицательное — в случае расходимости вычислительного процесса Найдите самостоятельно остальные локальные минимумы и максимумы функции (6.2). Рекурсивный алгоритм для поиска всех локальных минимумов на отрезке приведен в главе 8. Искать минимум функции можно также с применением fminsearch, рассматриваемой далее, которая предназначена для минимизации функции одной и нескольких переменных. Минимизация функции нескольких переменных Минимизация функции нескольких переменных является 6oj.ee сложной задачей по сравнению с минимизацией функции одной переменной, однако комбинированный адаптивный алгоритм функции fminsearch позволяет во многих случаях успешно решить эту задачу. Функция fminsearch требует указания начального приближения для искомой точки минимума, которое в случае функции одной переменной должно быть числом, а для функции нескольких переменных — вектором. Задайте начальное приближение равное -0.5 в примере предыдущего раздела и найдите точку локальною минимума: » х2 — fminsearch(@ftest, -0.5) х2 = -0.1629 Выбирая последовательно подходящие начальные приближения, найдите все точки минимумов и максимумов функции. Рассмотрим теперь минимизацию функций нескольких переменных на примере функции двух переменных /(х, y) = sinnx-sinTiy. (6.3) 256 Часть II. Вычисления и программирование Сначала получше представление о поведении функции, построив ее линии уровня при помощи следующих команд (отображение линий уровня функции двух переменных описано в разд. "Контурные графики" главы 3): » [X, Y] = meshgridtO:0.01:2); » Z = sin(pi*X).*sin(pi*Y); » [CMatr, h] = contour(X, У, Z,[-0.96, -0.9, -0.8, -0.5, -0.1, 0.1, ..., 0.5, 0.8, 0.9, 0.961); » clabel(CMatr,h) » colormap(gray) На получившемся графике, приведенном на рис. 6.3, видно расположение локальных минимумов и максимумов. Рис. 6.3. Расположение локальных максимумов и минимумов функции (6.3) Перед применением fminsearch необходимо создать файл-функцию, вычисляющую значения искомой функции, причем аргументом файл-функции должен быть вектор, первый элемент которого соответствует переменной эс, а второй — у. Текст требуемой файл-функции ftestz приведен в листинге 6.2. Гпава 6. Методы вычислений в MATLAB 257 ............ • лмцм .».. Листинг 6.2. Файл-функция ftest2 ........ ........ ..л .........•. 1^5... function f = ftest2(v) X = v(l) У = V(2) ; f = sin(pi*x) . *sin(pi*y),- Теперь для нахождения локального минимума вызовите fminsearch с двумя входными аргументами — именем файл-функции и начальным приближением и выходным аргументом— вектором с координатами искомой точки минимума: » М = fminsearch('ftest2', [1.4, 0.6]) И = 1.5000 0.5000 Решение найдено с точностью 104, как по значениям х и у, так и по значению функции. Для получения не только вектора с координатами точки минимума, но и значения функции следует вызвать fminsearch с двумя выходными аргументами: >> [М, f] = fminsearch(@ftest2, [1.4, 0.6]) И = 1.5000 0.5000 f = -1.0000 Обращение к fminsearch с третьим дополнительным выходным аргументом flag » [И, f, flag] = fminsearch(@ftest2, [1.4, 0.6]); позволяет записать в него информацию о причине останова вычислительного алгоритма. Смысл его значений тот же, что и для функции fminbnd, рассмотренной в предыдущем разделе. Исследуемая функция может зависеть от произвольного числа переменных н. В этом случае входной аргумент argvect соответствующей файл-функции и начальное приближение должны быть векторами длины п. В нашей задаче не обязательно было программировать файл-функцию в М-файле. Поскольку входным аргументом анонимной функции может быть вектор, то следующие команды приведут к поиску минимума: » fun = @(v)sin(pi*v(l)).*sin(pi*v(2)); » [М, f] = fminsearch(fun, [1.4, 0.6]) 258 Часть II. Вычисления и программирование и = 1.5000 0.5000 f = -1.0000 Optimization Toolbox, которому посвящена главе 16, содержит дополнительные средства минимизации функций. Например, fminunc можно использовать для поиска минимума функции нескольких переменных. Управление ходом вычислений Функции fzero, fminbnd и fminsearch допускают определение дополнительных параметров для управления вычислительным процессом и контроля за ним. Параметры задаются в управляющей структуре, которую мы будем называть options, как в справочной системе MATLAB, хотя имя может быть произвольным. Перед вызовом вычислительных функций следует предварительно сформировать переменную options в соответствии с характером требуемого контроля, воспользовавшись функцией optimset. Переменная options на самом деле является структурой. Это новый тип данных— до сих пор вы имели дело только с числовыми массивами. При чтении разделов этой главы умение работать со структурами не требуется, можно просто следовать приведенным правилам заполнения, просмотра и использования управляющей структуры options (работа со структурами данных описана в главе 8). Приступим к формированию структуры options на примере минимизации функции одной переменной (6.2) при помощи fminbnd. Получим сначала информацию о работе алгоритма минимизации на его последнем шаге. Для этого вызовем функцию optxmset с одним выходным аргументом options и двумя входными 'Display' и 'final', а затем укажем options в дополнительном четвертом входном аргументе fminknd. Всюду дальше мы будем использовать термины свойство, вид контроля, опция или параметр (в данном случае Display) и значение свойства или параметра (в данном случае 'final'). Установите формат вывода long, поскольку нам понадобятся все значащие цифры для анализа результата. » format long » options = optimset('Display', 'final'),- » x2 ~ fminbnd(@ftest, -0.5, 0, options) Optimization terminated successfully: Гпава 6. Мето^.ч вычислений в MATLAB 259 the current х satisfies the termination criteria using OPTIONS.TolX of 1.000000e-004 x2 = -0.1629 Кроме координаты точки локального минимума выводится информация об успешном завершении вычислительного процесса и точности, с которой (по умолчанию) найдено решение. Для изменения точности следует заново сформировать структуру options, указав еще одну пару входных аргументов. В следующем примере мы задаем не только опцию Display, но и точность IO 9 по аргументу при помощи параметраToix. » options = optimset('Display', 'final', 'TolX', 1.0e-09); » x2 = fminbnd.@ftest, -0.5, 0, options) Optimization terminated successfully: the current x satisfies the termination criteria using OPTIONS.TolX of 1.000000e-009 x2 = -0.16269942641268 Сравните полученный результат co значением, вычисленным fminbnd с используемой по умолчанию точностью 104. Различие получено в шестом знаке после десятичной точки, следовательно, при первом вычислении точность была 10 5, а не 10 4 как выведено в сообщении. Информация, возвращаемая функцией fminbnd, содержит гарантированную точность, в то время как реальная точность может быть больше. Аналогичным образом точность задается при нахождении корней и минимизации функции нескольких переменных. В общем случае входные аргументы optimset задаются попарно options = optimset(...,'вид_контроля', значение,...) В двух предыдущих примерах Display и Toix — виды контроля, a ’final’ и 1.0е-09, соответственно— их значения. Возможные сочетания параметрон вид_контроля и значение приведены в табл. 6.1. Таблица 6.1. Параметры optimset Вид контроля Значение Результат Примечание Display off' Информация о вычислительном процессе не выводится ' iter’ Выводится информация о каждом шаге вычислительного процесса 260 Часть II. Вычисления и программирование Таблица 6.1 (окончание I Вид контроля Значение Результат Примечание Display 'final' Выводится информация только о завершении вычислительного процесса 'notify' Выводится предупреждение, если процесс не сходится (используется по умолчанию) MaxFunEvals Целое число Максимальное количество вызовов исследуемой функции Только для fminbnd fminsearch Maxiter Целое число Максимальное количество итераций вычислительного процесса Только для fminbnd fminsearch To1Fun Положительное вещественное число Точность по функции для останова вычислений Только для fminbnd fminsearch TolX Положительное вещественное число Точность по аргументу функции для останова вычислений Oi раничиьать количество вызовов функций и число итераций имеет смысл, если есть опасение, что получить решение не удастся из-за расхождения вычислительного процесса. В некоторых случаях приходится уменьшать точность. например, если вычисление исследуемой функции занимает много времени, а требуется получить только несколько первых значащих цифр ответа. Пользователям, имеющим представление о численных методах, полезны сведения о ходе вычислений, выводимые на экран при значении параметра Display, равном ‘iter’. Последовательность команд » options = optimset(‘Display', 'iter', 'TolX', 1.0e-09); » x2 = fminbnd(@ftest, -0.5, 0, options) приводит к появлению в командном окне кроме результата еще и таблицы, каждая строка которой соответствует одной итерации и содержит информацию о том, какой раз вызывалась исследуемая функция, текущее приближение и значение функции от него и метод, применяемый на данной итерации. Func- count -0.309017 f (х) 0.873024 Procedure initial 1 Гпава 6. Методы вычислений в MATLAB 261 2 -0.190983 0.063294 golden 3 -0.118034 0.117247 golden 9 -0.162Р99 0.0275217 parabolic 10 -0.162В99 0.0275217 parabolic Функция optimset служит также для модификации существующей структуры. Например, если сначала была задана только точность по аргументу » options = optimset('TolX1, 1.0е-09); а в дальнейшем потребовалось дополнительно указать точность по функции и получить информацию о каждом шаге вычис. 1ительного процесса, то достаточно обратиться к функции optimset следующим образом: » options = optimset(options, 'TolFun', 1.0e-07, 'Display', 'iter'); Примите во внимание, что можно создать несколько структур с различными именами, к примеру: options! и options2, для различных вариантов управления вычислительным алгоритмом. Для просмотра всех текущих опций можно вывести структуру options в командное окно или о гкрыть ее в редакторе массивов двойным щелчком по строке с options в окне браузера переменных рабочей среды. Получение значения отдельного параметра производится при помощи функции optimget, входными аргументами которой являются имя структуры и название требуемого параметра: » err = optimget(options, 'TolX') err = 1.0000e-009 Если данному параметру не было присвоено значение при генерации структуры, то возвращается пустой массив. Вызов функции optimset без входных аргументов » optimset приводит к отображению в командном окне названия всего множества параметров вместе с их допустимыми значениями. В фигурных скобках указаны значения, используемые в вычислительном алгоритме по умолчанию. В разделе справочной системы MATLAB Mathematics: Function Functions: Minimizing Functions and rinding Zeros размещена подробная информация о минимизации функций и решении уравнений и, кроме тою, приведены ссылки на литературу с описанием вычислительных методов, реали юван-ных в MATLAB. Некоторые дополнительные возможности функций fpiot, fzero, fminbnd и fminsearch обсуждаются в следующем разделе. В заключение этого раздела отметим, что большинство вычислительных функций, в 262 Часть II. Вычисления и программирование том чиспе fzero, fminbnd и fminsearch, написаны на языке программирования MATLAB Они имеют открытый код и расположены в подкаталоге toolboxmatlabfunfun основного каталога MATL АВ. Более подробно о fpiot Мы уже отмечали, что fpiot учитывает поведение функции за счет адаптивного выбора шага, что приводит к графикам, достаточно точно отображающим поведение исследуемой функции. Уделим теперь более пристальное внимание тем способам вызова fpiot, которые позволяют настраивать адаптивный выбор шага, получать вместо графика таблицу значений функции и работать с математическими функциями, зависящими от одного или нескольких параметров. До сих пор при использовании fpiot мы задавали во входных аргументах имя файл-функции (указатель на нее, inline или анонимную функцию), пределы независимой переменной и свойства линии. Самый общий способ вызова fpiot таков: [X, Y] = fpiot(@pfun, limits, tol, n, LineSpec, Pl, P2,...) След) ет учесть, что при указании необязательных выходных аргументов в х заносятся значения независимой переменной, by — соответствующие значения функции, а сам график не выводится. Таким образом, fpiot позволяет получить таблицу значений функции, для визуализации которой достаточно выполнить plot(X,Y). Длина списка входных аргументов должна быть больше или равна двум, т. е. функция, вычисляющая значения математической функций, и вектор с пределами для построения графика задаются всегда. Отметим, что вектор limits может содержать как два элемента — пределы по оси абсцисс, так и четыре— пределы по оси абсцисс и ординат, например, fpiot (@sin, ;-2’pi 2*pi -0.5 0.5]). Алгоритм fpiot адаптивно подбирает шаг, измельчая его вблизи участков быстрого роста или убывания функции гак, чтобы обеспечить относительную точность 2»10-3. При необходимости, точность можно задать в третьем входном аргументе tol (она должна быть меньше единицы). Сравните графики функции sin(l/x) на отрезке 10.01 1], построенные с точностью 2«10-3 по умолчанию и с точностью 10 4. » fun = inline('sin(lZx)1) » subplot(2, 1, 1) » fpiot(fun, [0.01 11) » subplot(2, 1, 2) » fplottfun, [0.01 1], 1.0e-4) Гпава 6. Метода вычислений в MATLAB 263 Другой способ управления алгоритмом fpiot состоит в задании минимального числа разбиений исходного отрезка n (1 по умолчанию), причем п должно быть больше либо равно единице. Пятый параметр LineSpec предназначен для определения типа линии, цвета и маркера. Поскольку точность toi может быть только меньше единицы, минимальное число разбиений л больше единицы, a LineSpec не является числом, то функция fpiot допускает один из следующих вызовов с тремя входными аргументами » fplottOpfun, limits, tol) » fpiot(@pfun, limits, n) » fpiot(@pfun, limits, LineSpec) и сама выбирает нужную последовательность действий. Разберем теперь назначение входных аргументов, которые указываются, начиная с шестой позиции списка после LineSpec. Исследуемая математическая функция может зависеть от нескольких параметров, например: у(х) = е₽,Л ~p2sinx. Требуется построить графики функций для следующих пар значений: д =0.1, р2 = 2; р(=0.2, р2=2.5; р]=0.3, р2 =3.7. Разумеется, можно написать три функции для вычисления у(х), или каждый раз вносить изменения в одну и ту же функцию. Гораздо эффективнее запрограммировать функцию с тремя входными аргументами, первый из которых — независимая переменная, а остальные — параметры функции (листинг 6.3). function f = pfun(x, pl, p2) f = exp(p]*x) - p2*sin(x); Теперь при вызове fpiot следует указать текущие значения параметров в списке входных аргументов, начиная с шестой позиции. Для этого необходимо задать пять предыдущих аргументов, причем в качестве tol, п или LineSpec можно взять пустой массив — будут использоваться установленные по умолчанию значения. Удовлетворимся стандартной точностью и минимальным числом разбиений, определим только тип линии для каждой пары параметров: » fplot(@pfun, [-3 3], [ ], [ ], 0.1, 2); » hold on » fpiot(Spfun, [-3 3], [ ],[ ], ', 0.2, 2.5); » fplot(@pfun, [-33], [),[], 0.3 ,3.7); 264 Часть II. Вычисления и программирование Возможность работы с функциями, зависящими от параметров, реализована не только в fpiot. Все обсуждаемые в этой главе вычислительные задачи допускают наличие параметров. В следующем разделе мы продемонстрируем минимизацию и нахождение корней таких функций. Исследование функций, зависящих от параметров Функции fzero, fminbnd и fminsearch поддерживают работу с математическими функциями, зависящими от параметров. Заметим, что версия MATLAB 7.0 унаследовала от предыдущей тот же подход, что остался в fpiot, хотя его описание исключено из справочной системы. Значения параметров последовательно задаются в списке входных аргументов после управляющей структуры options. Заполнение самой структуры не обязательно, если при решении уравнения или минимизации функции достаточно определенных по умолчанию значений ’Display’, 'MaxFunEvals', ’Maxlter’, 'ToiFun1, ‘TolX’. Как и в случае с fpiot допускается указание пустого массива вместо неинтересующей нас управляющей стр)ктуры, например » [xl, fl] = fzero(@pfun, 0, [ ], 0.1, 2) xl = 0.5570 fl = 0 Аналогичным образом решается задача о поиске локального минимума функции, зависящей от параметров. В версии 7.0 рекомендуется применять подходы, основанные на использовании анонимных или вложенных функций. В первом случае достаточно задать значения параметров в переменных рабочей среды и обратиться к функции, определив в качестве аргумента анонимную функцию: >> pl = 0.1; » р2 = 2; >> [xl, fl] = fzero(@(x) exp(pl*x) - p2*sin(x), 0) xl = 0.5570 fl = 0 i лае а и Методы вычислений в МА П AF> 265 Поскольку при создании анонимной функции переменные среды фиксируются, то нег смысла определять отдельно анонимную функцию и передавать ее имя в качестве аргумента, ибо для новых параметров все команды надо повторить. В листинге 6.4 приведен пример использования вложенных функций для решения той же задачи. .......—.............................................................. Листинг 6.4. Использование функции, зависящей от параметра, в качестве аргумента fzero function [х, у] = frootfpl, р2, хО) [х, у] = fzero(@pfun, хО); function f = pfun(x) f = exp{pl*x) - p2*sin(x); end end Терерь вместо вызова функции fzero следует обращаться к собственной функции froot: >> [х, у] = froot(0.1, 2,0) х = 0.5570 У = о При необходимости можно добавить управляющую структуру options в список входных аргументов для передачи ее fzero. Пользователь пакета может выбрать наиболее приемлемый для него вариант. Интегрирование функций Этот раздел посвищен приближенному вычислению определенных интегралов и двойных определенных интегралов с заданной точностью. Пользователь имеет возможность выбирать наиболее подходящий метод численного интегрирования в зависимости от свойств подынтаральной функции. Вычисление определенных интегралов Начнем с примера нахождения значения определенного интеграла 1 j е-л sin х dx. 266 Часть II. Вычисления и программирование Первым шагом является создание функции, вычисляющей подынтегральное выражение, ее текст приведен в листинге 6.5. function f = fint(x) f = exp(-x).*sin(x); Теперь для вычисления интеграла вызовите quad, задав первым аргументом ссылку на функцию fint, а вторым и третьим — нижний и верхний пределы интегрирования. В качестве выходного аргумента можно указать имя переменной, в которую следует записать найденное значение: » f srmat long » I = quad(@fint, -1, 1) I = -0.66349146785310 Примечание Подынтегральная функция может быть задана именем, либо определена как inline-функция или анонимная так же, как и в случае fzero, fminsearch,fminbnd. k По умолчанию функция quad вычисляет приближенное значение интеграла с точностью И)6. Для изменения точности вычислений следует задать дополнительный четвертый аргумент: » I = quad<@fint, -1, 1, 1.0е-07) I = -0.66349366574399 Реализованный в quad рекурсивный алгоритм основан на квадратурной формуле Симпсона с автоматическим подбором шага интегрирования для достижения требуемой относительной погрешности. Сравнивая полученные результаты, можно сделать вывод, что относительная погрешностью-6 не дает ожидаемого количества верных знаков после десятичной точки. Проблема заключается в способе оценки погрешности вычислений в применяемом алгоритме, но этот вопрос из области вычислительной математики выходит за рамки излагаемого материала. При использовании средств пакета необходимо просто учитывать его особенности Если пользователь знаком с теоретическими аспектами применяемого метода, то ему окажется полезной трассировка вычислений, которая выводится в командное окно при ненулевом значении пятого входного аргумента quad. Информация о ходе вычислений представлена в виде таблицы. В каждой ее строке приведены значе- Глава 6. Me год/1 вычислений в MATLAB 267 ния количества вычислений подынтегральной функции, начальная точка текущего промежутка интегрирования, его длина и значение интеграла: » I = quad(@fint, -1, 1, 1. .0е-07, 3) 9 -1.0000000000 5.43160000е-001 -0.7696256630 11 -1.0000000000 2.71580000е-001 -0.4927577867 13 -1.0000000000 1.35790000е-001 -0.2772168074 15 -0.8642100000 1,35790000е-001 -0.2155409801 37 0.4568400000 5.43160000е-001 0.1696814429 39 0.4568400000 2.71580000е-001 0.0830983395 41 0.7284200000 2.71580000е-001 0.0865830829 Проанализируйте количество точных знаков в зависимости от задаваемой точности вычислений в quadi для примера, разобранного выше. Функции quad и quadl могут выводить следующие диагностические сообщения: □ ’Minimum step size reached' — шаг интегрирования достиг минимального значения, но требуемая точность не получена. Возможно, функция имеет неинтегрируемую особенность, □ 'Maximum function count exceeded* — достигнут предел максимального количества вычислений значений подынтегральной функции (более 10 000). Возможно, функция ведет себя как функция с неинтегрируемой особенностью; □ 'Infinite or Not-a-Number function value encountered'—Произошло переполнение при вычислении интегранда во внутренней точке интервала интегрирования. Например, при интегрировании функции у = х“°'9, имеющей интегрируемую особенность, по отрезку [0,1] » fun = inline('х.Л-0.91); » I = quad(fun, 0, 1, 1е-7) Wajning: Minxmum step size reached; singularity possible. > In quad at 88 I = 9.8955 в командное окно выводится сообщение о достижении минимально возможного шага интегрирования, причем делается вывод о возможной осо- 268 Часть II. Вычисления и программирование беннисти подынте! ральной функции. Диагностическое сообщение сопровождается номером строки файл-функции quad, выполнение которой привело к предупреждению. Очевидно, что полученный ответ 9.8955 не соответств) ет заданной точности — обращение к quadi также не улучшит ситуацию. Причина заключается в методах, реализованных в MATLAB для вычисления определенных интегралов. Численное интегрирование функций с особенностями может быть основано на квадратурных формулах, узлы которых не являются границами инт ервала, или на квадратурных формулах с весовой функцией для выделения особенности. Такой алгоритм вы сможете запрограммировать самостоятельно после чтения главы 7, посвященной конструкциям языка программирования MATLAB. В главе 8 рассмотрено написание собственных файл-функций для вычисления определенных интегралов на основе других квадратурных формул. После вывода предупреждения о том, что функция может иметь особенность, вычисления продолжаются. Попробуйте вычислить интеграл от функции у = 1/х по отрезку [0,1], на котором она имеет неинтегрируемую особенность. Примечание При интегрировании негладких функций (типа |х|, или имеющих интегрируемый разрыв) интервал интегрирования следует разбивать на части так, чтобы на подынтервалах функция была гладкой. Вычисление интегралов от быстроменяющихся функций так же возможно при разбиении исходного промежутка на участки монотонности подынтегральной функции. Вычисление двойных интегралов В MATLAB определена функция dblquad для приближенного вычисления двойных интегралов. Как и в случае вычисления определенных интегралов, следует написать файл-функцию для вычисления подынтегрального выражения. Найдите значение интеграла 1 л । j (er sin v + е 1 cos v 0-л dxdy . Функция fintz должна содержать два входных аргумента х и у, ее текст приведен в листинге 6 6 Глава 6. Методы вычислений в MATLAB ?6& function f — f int2(x, y) f = exp(x).‘sin(у) .л2 + exp(-x).*cos(у) .л2; Вмести файл-функции можно использовать анонимные или inline-функции. Функция dblquad имеет пять входных аргументов, при ее вызове необходимо учесть, что первыми задаются пределы внутреннего интеграла по х, а вторыми — внешнего по у: » dblquad(@fint2, -pi, pi, 0, 1) ans = 23.0977 Дополнительным шестым параметром можно задать точность вычисления интеграла. Поскольку в dblquad реализованы двумерные квадратурные формулы, основанные на одномерных, то при вычислении двойного интеграла dblquad использует quad. Если седьмым аргументом указать 'quadi', то будет применяться соответствующий алгоритм » format long » dblquad(6fint2, -pi, pi, 0, 1, 1.0e-012, 'quadi') ans = 23.09747871451549 В случае гладких подынтегральных функций задание 'quadi' позволяет сократить время счета. Вычисление некоторых интегралов В данном разделе разобрано несколько примеров: интегрирование функции, зависящей от параметров, и вычисление интеграла с переменным верхним пределом. Интегралы, зависящие от параметра Функции quad и quadi позволяют находить значения интегралов, зависящих от параметров. Приемы передачи параметров те же. что и для функции fzero. Опишем ту возможность, которая осталась недокументированной в последней версии пакета. Аргументами функции, вычисляющей подыдте- 270 Часть II. Вычисления и программирование тральное выражение, должна быть не только переменная интегрирования, но и все параметры. Значения параметров указываются через запятую, начиная с шестого аргумента quad или quadi. Вычислите интеграл J | р}х2 + р2 sin x)<Zx -i при значениях параметров р} = 22.5, р2 - -5.9 по квадратурным формулам Ньютона—Котеса с автоматическим выбором шага. Текст функции fparam, зависящей от трех аргументов, которая вычисляет значение подынтегральной функции, приведен в листинге 6.7. function z = fparam(x, Pari, Par2) z = Раг1.*х.Л2 + Par2.*sin(x); Найдите значение .if теграла при помощи quad, использование quadi производится аналогично. » q = quad(@fparam, -1, 1, 1.0е-05, 1, 22.5, -5.9) Ч = 15.00000005742834 Пятый параметр, равный единице, поставлен для вывода в командное окно таблицы с информацией о ходе рекурсивного алгоритма интегрирования. Если нужно получить только значение интеграла, то пязый параметр должен быть нулем. Заметьте, что если пропустить этот параметр, то появится сообщение об ошибке, т. к. функция fparam предполагает наличие трех входных аргументов. Итак, при вычислении интеграла, зависящего от параметров, их следует указывать, начиная с шестого аргумента quad или quadi. Также для вычисления интеграла, зависящего от параметров, может быть использована анонимная функция: » Pari = 22.5; » Раг2 - -5.9; » q - quad{@(x) Раг1.*х.л2 + Par2.*sin(x), -1, 1, 1.0е-05) q = 15 В качестве упражнения примените вложенную функцию для решения этой задачи. Глава 6. Методы вычислений в MATLAB 271 Интегралы с переменным верхним пределом Интеграл с переменным верхним пределом представляет собой некоторую функцию, например у F(у) = JеА (sin х—cosx)dx, о Для вычисления такого интеграла придется написать две функции: fint — для подынтегральной функции, и Fy — которая находит значения интеграла для каждого значения у. Тексты требуемых функций приведены в листинге 6.8, причем Fy является основной функцией, a fint — подфункцией. ‘•>.1... ...-... ........................................................ .......-Ы. ....... .. Листинг 6.8. Файл-функция, вычисляющая значение интеграла ......................... ................................................................... function f = Fy(y) f = quadl(@fint, 0, у, 1.0e-09); function f = fint(x) f = exp(x).*(sin(x) - cos(x)); Теперь можно вычислить интеграл при любом значении верхнего предела, задав его в качестве аргумента Fy. I [остроение графика зависимости интеграла от верхнего предела осуществляется при помощи fpiot » fpiot(@Fy, [0, pi]) Полиномы и интерполяция Текущий раздел посвящен операциям с полиномами и решению задачи интерполяции при построении полинома, наилучшим образом приближающего двух- и трехмерные табличные данные. Операции с полиномами Умножение, деление, сложение и вычитание Напомним, что полиномы в MATLAB представляются в виде вектора коэффициентов (задание полинома, нахождение всех его корней и вычисление значений описано в разд. "Вычисление всех корней полинома" данной главы). 272 Часть II. Вычисления и программирование Умножение двух полиномов осуществляется при помощи conv. Например, для вычисления произведения я(л) полиномов р(х) = х5+х3 +1 и д(х) = л2 + 2 с + 3 следует создать два вектора их коэффициентов и использовать их в качестве аргументов conv: »р = [10100 1]; » q = [123]; » S = COnv(p, q) s “ 12423123 В результате получается полином седьмой степени, соответствующий вектору s s(x) = jc7 + 2л6 +4х5 +2л-4 + Зл3 + л2 + 2х+3 . Функция deconv осуществляет деление полиномов с остатком. Она вызывается с двумя выходными аргументами — частным и остатком от деления: » [d, г] = deconv(p, q) d = 1-222 0 0 0 0-10-5 Размер вектора, содержащего коэффициенты остатка, равен максимальному из размеров векторов, соответствующих делимому полиному и его делителю. Для сложения и вычитания полиномов в MATLAB нет специальной функции. В то же время использование знака "+" для нахождения суммы полиномов разной степени приведет к ошибке, т. к. нельзя складывать векторы разных размеров. Если вы изучили работу с массивами и создание файл-функций, то написание собственной функции для нахождения суммы полиномов не представляет большого труда. Алгоритм сложения полиномов, которым соответствуют векторы р и q, достаточно прост, требуется: 1. Выбрать максимальный размер из двух векторов. 2. Соответствующим образом преобразовать каждый из двух векторов к максимальному размеру. 3. Сложить новые векторы. В листинге 6.9 приведен текст файл-функции polysum, находящей значение суммы полиномов. Гпава 6. Методы вычислений в MATLAB 273 Листинг 5.9. ®аил-функцир polysum, вычисляющая сумму полиномов • .. .-•. . • - • . .... . . V, . **, . ........;. RMMMMII*л.-.Д ..ИиИИВЖЬг^гЛж^ЯИКЯИИИПхз function s = polysumlp, q) % гычисление суммы полиномов, заданных векторами коэффициентов % нахождение наибольшей из длин входных векторов maxlen = max(length(р), length(q)); % создание вспомогательных векторов pl и ql длины maxlen, % имеющих нулевые элементы pl = zeros(1, maxlen); ql = zeros(1, maxlen); % преобразование исходных векторов к векторам одинакового % размера maxlen pl (maxlen - length(р) + 1:maxlen) = р,-ql(maxlen - length(q) + l:maxlen) = q; ? вычисление коэффициентов полинома, являющегося суммой исходных % полиномов s = pl + ql; Теперь для нахождения суммы и разности полиномов следует использовагь polysum. » s = polysum(р, q) s = 10 112 4 » d = polysum(p, -q) d = 1 0 1 -1 -2 -2 Вычисление производных Функция piolyder предназначена для вычисления производной не только от полинома, но и от произведения и частного двух полиномов. Вызов polyder с одним аргументом — вектором, соответствующим полиному, приводит к вычислению вектора коэффициентов производной полинома: » р = [10 10 0 1]; » pl = polyder(р) pl = 5 0 3 о о 274 Часть Ч. Вычисления и программирование Для вычисления производной от произведения полиномов следует использовать polyder с двумя входными аргументами: » р = [1 0 1 О О 1J ; » q = [12 3] ; » pql = polyder(р, q) pql = 7 12 20 8 9 2 2 Если необходимо найти производную отношения двух полиномов в виде дроби, числитель и знаменатель которой гак же являются полиномами, то следует вызвать polyder с двумя выходными аргументами: » [n, d] = polyder(р, q) n = 3 8 16 4 9 -2 -2 d = 1 4 10 12 9 Первый аргумент п результата содержит коэффициенты числителя, а второй d — знаменателя получающегося отношения полиномов. Интерполирование и сглаживание Табличные данные очень часто удобно интерпретировать как некоторую функцию, в частности, полиномиальную или сплайн — гладкую функцию, которая на отрезках области определения равна полиномам определенной степени. Будем различать два критерия приближения табличных функций: интерполирование, при котором аппроксимирующая функция совпадает с табличной в узлах, и сглаживание, основанное на минимизации некоторого критерия, например, суммы квадратов отклонений в узлах. Итак, возникает задача о построении полиномиальной или кусочно-полиномиальной функции для приближения некоторых дискретных данных. Набор вычислительных функций MATLAB содержит функции для решения таких задач, как в случае одномерных, так и многомерных данных. Одним из простейших способов приближения табличных функций, предлагаемым MATLAB, является полиномиальное сглаживание методом наименьших квадратов. Приближение по методу наименьших квадрате Пусть исследуемая функция дана в виде табл. 6.2. Построение полинома фиксированной степени для приближения табличной функции одной переменной производится при помощи polyfit. Первые два ее входные аргу Глава 6. Методы вычислений в MATLAB 275 мента являются векторами со значениями абсцисс и ординат табличной функции, а третий — требуемой степенью полинома. Таблица 6.2. Функция заданная таблицей xi 0.1 0.2 0.4 0.5 0.6 0.8 1.2 У. -3.5 -4.8 -2.1 0.2 0.9 2.3 3.7 Приблизьте ее полиномами четвертой, пятой и шестой степени и выведите I рафик, отражающий характер приближений. Для решения этой задачи создайте файл-программу LSinterp, текст которой приведен в лист инге 6.10. ri IMJ.K и I- ... । . .. - иллишиаял u I > и >««•« । п-• •• • <>•«।• . Листинг 6.10. Приближение полиномами методом наименьших квадратов % заполнение массивов для табличной функции х = [6.1 0.2 0.4 0.5 0.6 0.8 1.2]; у = [-3.5 -4.8 -2.1 0.2 0.9 2.3 3.7]; % вывод графика табличной функции маркерами plot(x, у, ’ко’) % вычисление коэффициентов полиномов разных степеней, % приближающих табличную функцию по методу наименьших % квадратов р4 = polyfit(х, у, 4); I нахождение коэффициентов полинома 4-ой степени р5 = polyfit(х, у, 5); % нахождение коэффициентов полинома 5-ой степени рб = polyfit(х, у, 6); % нахождение коэффициентов полинома 6-ой степени ' построение гр афиков полиномов t = 0.1:0.01:1.2; ₽4 = polyval(p4, t); Р5 = polyval(p5, t); Рб = polyval(p6, t); hold on plot(t, P4, ’k-', t, P5, 'k:', t, P6, 'k-.'l legend(’табличные данные', 'n = 4', 'n = 5’, 'n = 6',0) title('Приближение табличной функции полиномами степени п') В резуль гате выполнения файл-функции LSinterp получается график, изображенный на рис. 6.4. Приближение методом наименьших квадратов дает хороший результат не всегда, более того, при увеличении степени возможно Ю Зи. 130 £76 Часть II. Вычисл -ния и программирование ухудшение приближения, как происходит, например, при п = 6. В нашем случае полином шестой степени является интерполяционным полиномом, значения которого совпадают со значениями табличной функции. Чем не менее такое приближение используется, например, для построения полиномиальной регрессии при моделировании данных. Обычно, при интерполировании таблично заданной функции применяются сплайны для получения плавного перехода от одно! о значения к другому. Приближение табличных функций по методу наименьших квадратов является простейшей задачей подбора параметров. Более детально этот класс задач разобран в главе 19, посвященной описанию Curve Fitting Toolbox. Интерполяция сплайнами Самым простым способом интерполяции является аппроксимация данных сплайном нулевого порядка (на каждом участке степень полинома равна нулю), при которой значение в каждой промежуточной точке принимается равным ближайшему значению, заданному в таблице. В результате данные Глава 6. Методы вычислений в MATLAB 277 приближаются ступенчатой функцией, а само приближение называется интерполяцией по соседним точкам. Линейная интерполяиия основана на соединении соседних точек отрезками прямых — табличные данные приближаются ломаной линией (сплайн первого порядка дефекта единица). Для получения более гладкой функции следует применять интерполяцию кубическими сплайнами. Все эти способы реализованы в функции interpl, для использования которой следует задать координаты абсцисс промежуточных точек, в которых вычисляются значения интерполянта, и способ интерполирования: □ ' nearest ’ — приближение по соседним элементам; □ 'linear' — линейная интерполяция (применяется по умолчанию, если способ ин терполирования не задан); □ 'spline' —интерполяция кубическими сплайнами; □ pchip ’ — интерполяция кубическими эрмитовыми сплайнами. При использовании pchip вторая производная сплайна может быть разрывна (в этом случае говорят, что сплайн имеет дефект два) в отличие от spline. Однако кубический эрмитовый сплайн сохраняет участки монотонности исходных данных. Выходным аргументом interpl является вектор значений интерполянта в промежуточных точках. Текст файл-программы interpidem для сравнения различных способов интерполирования приведен в листинге 6.11. % заполнение массивов для табличной функции х = [0.1 0.2 0.4 0.5 0.6 0.8 1.2]; у = [-3.5 -4.8 -2.1 0.2 0.9 2.3 3.7]; % вывод графика табличной функции маркерами plot(к, у, 'ко') % задание пр< межут >чных точек для интерполирования xi = [х(1):0.01:x(length(x))]; % вычисление ступенчатой функции в промежуточных точках ynear = interpl(х, у, xi, 'nearest'); % вычисление кусочно-линейной функции в промежуточных точках yllne = interpl(х, у, xi, 'linear'); % можно не указывать 'linear' % вь’чи 'пение кубического сплайна в промежуточных точках yspline = interpl(х, у, xi, 'spline'); hold on 278 Часть II. Вычисления и программирование % построение графиков интерполянтов plotfxi, ynear, ‘k', xi, yline, 'к:', xi, yspline, 'к-.') title(’Различные способы интерполяции функций') xlabeK1itx’) ylabel(1ity‘) legend I'табличная функция', 'по соседним элементам (nearest)’, ... 'линейная (linear)', 'кубические сплайны (spline)',4) Выполнение interpidem приводит к появлению графика, изображенного на рис. 6.5, который наглядно демонстрирует способы интерполяции. Добавьте самостоятельно график кубического эрмитова сплайна, указав 'pchip' в качестве четвертого аргумента функции interpl. MATLAB позволяет интерполировать не только одномерные, но также двумерные и многомерные данные. Интерполяция двумерных и многомерных данных Интерполяция двумерных данных связана с построением функции двух переменных. приближающей заданные в точках (х,-, у, ) значения z,-- Для ин- Гпзеа 6. Мет эр*! вычислений в MATLAB 279 терполированмя двумерных данных следует задать промежуточные узлы командой meshgrid и воспользоваться tnterp2, которая реализует один из способов интерполирования, в зависимости от значения последнего аргумента: □ 'nearest' — интерполяция по соседним элементам; □ 'bilinear' или 'linear1 — билинейная интерполяция (применяется по умолчанию, если способ интерполирования не задан); □ 'bicubic' или 'cubic'—интерполяция бикубическими сплайнами; □ ' spline'— интерполяция кубическими сплайнами. Для ускорения вычислений в случае равноотстоящих точек с монотонно изменяющимися координатами, соответствующих табличным данным, используются, соответственно, аргументы '*nearest'. '*linear', ’*cubic' ИЛИ '*spline'. Сравнение первых трех вышеперечисленных способов интерполяции может быть осуществлено при помощи файл-программы interp2dem, текст которой приведен в листинге 6.12. Для избежания утомительного ввода таблицы двумерных данных они генерируются при помощи некоторой функции двух переменных. Листинг 6.12. Файл-программа interp2dem -in.».»!.. II........ Al,................ ............ ...Г!, и ,. .л % генерирование значений табличной функции [X, Y] = moshgrid(0:0.2:1); Z = sin(3*pi*X),*sin(3*pi*Y).*ехр(-Х.л2 - У.л2); % визуализация табличной функции subplot (2, 2, 1) surf(X, Y, Z) t i tle('табличная функция') % создание сетки для промежуточных значений [Xi, Yi] = meshgrid(0:0.02:1)i % интерполяция no соседним значениям ZiNear = interp2(X, Y, Z, Xi, Yi, 'nearest'),- % билинейная интерполяция (можно не указывать 'bilinear') ZiBiLin = interp2 (X, Y, Z, Xi, Yi, 'bilinear'),- % бикубическая интерполяция ZiBiCub = in*-erp2(X, Y, Z, Xi, Yi, 'bicubic'); 280 Часть II. Вычисления и программирование % вывод результатов subplot(2, 2, 2) surf(Xi, Yi, ZiNear) title(’по соседним значениям (near)') subplot(2, 2, 3) surf(Xi, Yi, ZiBiLin) title('билинейная (bilinear)') subplot(2, 2, 4) surf(Xi, Yi, ZiBiCub) title('бикубическая (bicubic)') На рис. 6.6 приведены графики, полученные при помощи interp2dem. Графики отражают поведение интерполирующих функций, полученных различными способами. Рис. 6.6. Различные способы приближения двумерных данных (interpz) Для аппроксимации трехмерных данных служит функция interp3, для многомерных— interpn. Создание многомерных сеток осуществляется функцией ndgrid. Многомерное приближение производится аналогично двумерному, подробнее о нем можно узнать из справочной системы по MATLAB, набрав в разделе Index имя функции interpn. Глава 6. Методы t» счислений в МА П АВ 281 В этом разделе разобраны самые простые способы приближения табличных функций сплайнами различных порядков. Применению сплайнов посвящен Spline Toolbox (см. главу 18). Задачи линейной алгебры Поскольку название MATLAB является сокращением от Matrix Laboratory (матричная лаборатория), то естественно предположить, что возможности MATLAB для задач линейной алгебры достаточно широки. Действительно, специальные функции MATLAB позволяют вычислять нормы матриц и векторов, обращать матрицы, решать системы линейных уравнений, в том числе переопределенные и недоопределенные (с прямоугольными матрицами), находить собственные числа и векторы, факторизовать матрицы, вычислять функции матриц. В приложениях очень часто встречаются разреженные матрицы (содержащие большое число нулевых элементов). Для эффективного решения задач с разреженными матрицами существуют специальные алгоритмы, многие из которых реализованы в MATLAB. Для того чтобы осознанно использовать богатые возможности, предоставляемые MATLAB для решения задач линейной алгебры с разреженными матрицами. необходимо, как минимум, обладать знаниями в объеме программы технического вуза (разреженным матрицам посвящена глава 17). Данный раздел описывает простейшие возможности, которые предоставляет MATLAB для решения систем линейных уравнений, вычисления определи гелей, нахождения собственных чисел и векторов. Системы уравнений, определители, обращение матриц Знак обратной косой черты предназначен для решения систем линейных алгебраических уравнений, слева от него записывается матрица системы, а справа— вектор правой части. Причем, как матрица, так и вектор правой части могут быть комплексными. MATLAB сама подбирает наиботее эф-фек гивный метод и решает систему. Решение системы уравнений рассмотрено в качестве примера в разд. "Решение систем линейных уравнений " главы 2. Использование знака является самым простым способом решения, однако даже при таком простом подходе возможны существенные затруднения В справочной системе приведен алгоритм решения систем линейных урав 282 Часть I1 Вычисления и программирование нений, который учитывает вид матрицы системы уравнений. Кратко этот алгоритм описывается следующим образом. 1. Если матрица квадратная и ленточная с ограниченной шириной ленгы, то применяется специальный алгоритм решения для ленточных матриц. 2. Если матрица треугольная, то используется метод подстановки. 3. Если матрица перестановками строк и столбцов свидится к треугольной, то применяется модификация метода подстановки. 4. Если матрица симметричная (эрмитова в комплексном числовом пространстве) с положительными элементами на диагонали, то вызывается функция chol, которая пытается выполнить разложение Холецкого. При этом в процессе разложения выясняется положительная определенность матрицы. В случае положительно определенной матрицы находится множитель разложения Холецкого, с которым решаются две системы методом подстановки для получения решения исходной системы уравнений. Если матрица системы разрежена, то перед разложением Холецкого производится симметричная перестановка строк и столбцов по алгоритму минимальной степени с целью уменьшения заполнения множителей Холецкого. Для выполнения этой операции вызывается функция symmmd. 5. Если матрица хессенбергова, но не разреженная, то применяется метод сведения к системе с треугольной матрицей. 6. Если матрица квадратная и не удовлетворяет условиям пп. 1—5, то используется метод Гаусса в форме LU-факторизации. Для разреженных матриц предварительно переставляются строки и столбцы с целью уменьшения заполнения матричных множителей LU-разложения. 7. Если матрица прямоугольная, то происходит обращение к функции qr для QR-факторизации матрицы, которая позволяет найти наилучшее решение системы в смысле наименьших квадратов. Алгоритм qr учитывает, разреженная матрица, или нет. Функции МА I LAB, используемые в вышеописанном алгоритме, основаны на процедурах популярных библиотек LAPACK и UMFPACK для решения задач линейной алгебры. Соответствующая информация содержится в справочной системе MATI АВ. Для ее получения достаточно обратиться к разделу MATLAB: Functions — Categorical List: Mathematics: Linear Algebra и перейти в нем по гиперссылке and /. При этом открывается страница справочной системы, пункт Algorithm которой посвящен обсуждаемому здесь алгоритму. В нем упомянуты те функции библиотеки LAPACK. к которым обращается MATLAB при решении систем линейных уравнений. В ряде случаев, например, для разреженных магриц, MATLAB вызывает про !лава 6. Методы вычислений в MATLAB 283 цедуры библиотеки UMFPACK. Внизу страницы расположены две гиперссылки для доступа к документации этих библиотек в Интернете. В главе 15 рассматриваются особенности решения систем с разреженными матрицами. Системы с плохо обусловленными матрицами Рассмотрим простой пример; требуется найти решение следующей системы: 2Х| + Зх2 + Зх3 = 8; 4х( + 2х2 + Зх3 =7; 6х| +5.г2 + 6х3 =7. Введите матрицу и вектор из командной строки и примените обратную косую черту: » А = [2 3 3 4 2 3 6 5 6]; » b = [8; 7; 7] ; » х = АЬ В командное окно выводится предупреждение о том, что матрица вырождена или плохо обусловлена, и затем полученное решение х: Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND - 1.306145e-017. x = 1.0e+016 * 0.9007 1.8014 -2.4019 Полученное решение неверно, в чем несложно убедиться проверкой, умножив А на х. Дело в том, что л является вырожденной, ее определитель равен нулю. Для вычисления определителя предназначена встроенная функция det: » det(А) ans = о 284 Часть II. Вычисления и программирование Однако "очень маленькое" значение определителя еще не означает, что при решении системы возникнут трудности. Например, система 1.0-1(Г4%+2.01(Г41 =1; 2.0 КГ41 X]+3.0-КГ40 =2 решается точно, никаких сообщений не выводится, хотя определитель матрицы системы равен 2.96-10-80 (убедитесь в этом, решив систему и вычислив определит ель!). Возможность решения системы линейных алгебраических уравнений с приемлемой точностью определяется числом обусловленности матрицы, характеризующим чувствительность решения к ошибкам вычисления и точности представления данных в компьютере. Если оно велико, то ответ может получиться не очень точным или даже неверным. Перед решением системы имеет смысл вычислить число обусловленности матрицы системы при помощи функции cond, задав аргументом матрицу. Например, для первой системы функция cond выдает следующий результат: » cond(А) ans = 2.7526е+016 Число обусловленности матрицы второй системы равно 3.0808 и система решается правильно. На самом деле число обусловленности матрицы первой системы равно бесконечности. MATLAB использует численные методы для нахождения числа обусловленности, которые в применении к плохо обусловленным матрицам могут давать неверный результат. Но все равно, большое значение числа обусловленности сигнализирует о том, что найденное решение системы может быть неправильным. Знак обратной косой черты может быть применен для одновременного решения нескольких систем с одной и той же матрицей и разными правыми частями. Для этого из вектор-столбцов правых частей следует сформировать матрицу и поместить ее после знака обратной косой черты. Результатом является матрица, каждый столбец которой ес^ь решение соответствующей системы линейных уравнений. В отличие от последовательного решения систем, такой подход существенно экономит время, поскольку разложение матрицы выполняется только один раз. Гпава 6. Методы вычислений в MATLAB 285 Переопределенные и недоопределенные системы MATLAB позволяет решать системы с прямоугольными матрицами, так называемые переопределенные системы, в которых уравнений больше неизвестных, и недоопределенные системы с числом уравнений, меньшим числа неизвестных. Переопределенные системы встречаются в задачах подбора нескольких параметров с целью удовлетворения соотношениям, число которых больше, чем число параметров. Рассмотрим задачу о подборе параметров а и b некоторого физического закона у = a-e~‘ + b-t по результатам измерения величины у в моменты времени, приведенные в табл. 6.3. Таблица 6.3. Результаты измерений физической величины 0 0.1 0.2 0.3 0.4 0.5 У. 4.25 3.95 3.64 3.41 3.21 3.04 Для нахождения параметров потребуем соответствия измерений физическому закону, т. е. выполнение шести равенств вида: у,- = а - е-,< + b • . Эти равенства являются ни чем иным, как переопределенной системой из шести линейных алгебраических уравнений с двумя неизвестными а и b, матрица А и вектор правой части Y системы имеют вид А = 1 1 сь о го 1 ... 1 1 «£* bZ О* IU* 1 1 , Y = У|' У2 Уб Для нахождения неизвестных следует решить эту систему в MATLAB при помощи знака обратной косой черты. Напишите самостоятельно файл-функцию без параметров, решающую данную систему и строящую маркерами график исходных данных и линией график физического закона с полу 286 Часть II. Вычисления и программирование пившимися параметрами. Физический закон лучше оформить в виде функции от грех аргументов — переменной t и параметров а, Ь. Текст файл-функции fit с вложенной функцией law содержится в листинге 6.13. function [a, b]=fit function у = law(t, a, b) у = a.*exp(-t) + b.*t; end % задание таблицы с экспериментальными данными t = [0; 0.1; 0.2; 0.3; 0.4; 0.5]; у= [4.25; 3.95; 3.64; 3.41; 3.21; 3.04]; % создание матрицы системы линейных уравнений А = [exp(-t) t] ; % решение системы и получение искомых коэффициентов физического закона х = Ау; а = х(1) ; Ъ = х(2) ; % построение графика экспериментальных данных plot(t, у, 's') hold cm % построение графика физического закона fplot(@law, [0 0.5], [ ], [ ], а, Ь) end Файл-функция fit строит изображенные на рис. 6.7 графики данных и физического закона при найденных значениях параметров, которые она возвращает в выходных аргументах » [a, fa] = fit » а - 4.247В b = 0.9070 Внесите самостоятельно в файл-функцию fit некоторые изменения. Пусть табличные данные считываются из текстового файла функцией load, а на график наносится вся необходимая информация. Глава 6. Методы вычислений в МА И АВ 287 Рис. 6.7. Подбор параметров физического закона Перейдем теперь к недоопределенным системам, число неизвестных в которых больше числа уравнений. В самом простом случае недоопределенная система состоит из одного уравнения с двумя неизвестными, которое имеет бесконечно много решений. При нахождении решения недоопределенной системы MATLAB ищет базисное решение, содержащее как можно больше нулей. Базисное решение тоже может быть не единственным. Решите в качестве упражнения систему Х| + 2x2 + = 2; Зх| +4х2 +5т3 =2 и произведите проверку, умножив матрицу системы на найденное решение. Для решения нескольких переопределенных или недоопределенных систем с одной и той же матрицей применим тот же самый подход, что и при решении систем с квадратной матрицей, описанный в конце предыдущего раздела. Решение систем при помощи функции linsolve При использовании знака обратной косой черты для решения системы линейных уравнений выбор метода решения остается за MATLAB. Более широкие возможности предоставляет функция linsolve, которая, так же как и знак обратной косой черты, позволяет решать систему или несколько систем с одной и той же необязательно квадратной матрицей АХ = В, и при этом допускает выбор метода ее решения в соответствии со свойствами 288 Часть II. Вычисления и программирование матрицы, указанными пользователем. В простейшем случае обращение к функции linsolve имеет вид: X = linsolve(А, В) При этом для решения системы в случае квадратной матрицы А применяется LU-разложение с выбором ведущего элемента, а для прямоугольной — QR-разложение. Рассмотрим, как повлиять на выбор более эффективного метода решения, учитывая свойства матрицы. Для этого следует сформировать управляющую структуру, содержащую поля со значениями true или false в зависимости от свойств матрицы, и указать ее в качестве третье!о входного аргумента функции linsolve. Будем, как и ранее, использовать для управляющей структуры имя options, хотя оно может быть произвольным, более того, если решается много систем с разными свойствами, целесообразно создать несколько управляющих структур, используя нужную в конкретном случае. Поле transa определяет, как задана матрица системы: значение true означает, что солверу передается транспонированная матрица системы. Например, если введена матрица А и надо решать систему АТХ = В, то следует обратиться к солверу следующим образом: » options.TRANSA = true; » у = linsolve(А, В, options) Параметры, определяющие свойства матрицы системы, сведены в табл. 6.4. Таё.шца 6.4. Фчагн, определяющие свойства матрицы системы Флаг Свойство матрицы LT Нижняя треугольная UT Верхняя треугольная UHESS Верхняя почти треугольная (хессенбергова) SYM Симметричная POSDEF Положительно определенная RECT Прямоугольная В табл. 6.5 представлены возможные комбинации значений флагов в управляющей структуре Некоторые комбинации очевидны, например, хессенбер-гова матрица не может быть треугольной, а некоторые, которые могли бы совмещаться, не допустимы. Например, треугольная матрица может быть Гпава 6. Методы вычислений в MATLAB 289 положительно определенной, но при выборе способа решения определяющим фактором является ее профиль. Таблица 6.5. Возможные комбинации флагоь LT C’T UHESS SYM POSDEF RFCT true false false false false true/false false true false false false true/false false false true false false false false false true true true true false false false false false true/false ^Предупрежде н и ej Функция linsolve не проверяет правильность свойств матрицы, которые указаны в управляющем параметре, и не выводит никаких предупреждений. Поэтому результат может быть неверный. Если матрица системы плохо обусловлена или ее ранг меньше размерности, то выводится предупреждение. Например, решение системы с линейно зависимыми строками дает результат: > А = [2 3 3 -2 -3 -3]; » Ь = [В; 7] ; >> X = linsolve(А, Ь) Warning: Rank deficient, rank - 1, tol = 2.8262e-015. X = 0 0.1667 0 Сообщение можно подавить, если задать второй выходной аргумент, в который записывается ранг матрицы (в случае прямоугольной матрицы) или величина, обратная к числу обусловленности (в случае квадратной матрицы). » [X, г] = linsolve(А, Ь) х - о 290 Часть II. Вычисления и прогр.мирование 0.1667 0 г = 1 Если предупреждения подавляются, го следует использовать значение выходного аргумента для оценки правильности получаемого решения. Обращение матриц Обратной к квадратной невырожденной матрице А называется такая матрица А-1, которая при умножении на А справа и слева дает в результате единичную матрицу. Встроенная функция inv обращает матрицу, ее входным аргументом является исходная матрица, а выходным — обратная. Введите квадратную матрицу размера три самостоятельно, убедитесь в ее невырожденности при помощи det и найдите обратную, а затем проверьте результат умножением справа и слева полученной матрицы на исходную. В принципе, решение систем линейных уравнений с квадратной матрицей может осуществляться умножением обратной матрицы на вектор правой части системы Однако такой способ требует существенно больше времени и памяти, к тому же он может дать большую погрешность решения. Поэтому для решения систем следует применять знак обратной косой черты или функцию linsolve. Функция pinv позволяет найти псевдоодратную матрицу к исходной прямоугольной. » А = II 2; 34; 5 6]; » Р = pinv (А) ; » Р*А ans = 1.0000 0.0000 -0.0000 1.0000 Собственные числа и векторы матрицы, функции матриц Собственные числа и собственные векторы и, О квадратной матрицы А удовлетворяют равенствам A — А.,!/,. Функция eig, вызванная с входным аргументом матрицей, находит все собственные числа матрицы и запи-сываег их в выходной аргумент — вектор: » А = [2 3; 3 5) ; » lam = eig (А) Гпава 6 Методы рьр делений в MATLAB 291 lam = 0.1459 6.8541 Для одновременного вычисления всех собственных векторов и чисел следует вызвать eig с двумя выходными аргументами. » [U, Lam] = eig{A); Первый выходной аргумент и представляет собой матрицу, столбцы которой являются собственными векторами. Для доступа, например, к первому собственному вектору следует использовать индексацию при помощи двоеточия » ul = и (:, 1) ; Вторым выходным аргументом Lam возвращается диагональная матрица, содержащая собственные числа исходной матрицы. » Lam Lam = 0.1459 0 о 6.8541 Проверьте, правильно ли найдены, например, второе собственное число и соответствующий ему собственный вектор. Воспользуйтесь определением: » A*U{:, 2) - Lam(2, 2)*U(:, 2) ans = 1.0е-015 * 0.4441 -0.8882 Возведение квадратной матрицы в любую целую степень осуществляется при помощи знака Л, например: » В = А"2 В = 13 21 21 34 При возведении матрицы в целую положительную степень происходит матричное умножение матрицы на саму себя столько раз, каков показатель степени, в отличие от поэлементного умножения при помощи операции Для отрицательных степеней вычисляется степень обратной матрицы. Возможно использование дробных степеней. Если требуется извлечь корень из квадратной матрицы, то лучше применить функцию sqrtm. Матричные экспонента И ЛОГарифм ВЫЧИСЛЯЮТСЯ При ПОМОЩИ фуНКЦИЙ ехргп и logm. 2Q2 Часть II. Вычисления и программирование Пользователь может найти значение любой функции от матрицы. Для этого следует создать собственную файл-функцию, анонимную функцию или ir.line-функцию. а затем использовать специальную функцию funm, задав первым аргументом матрицу, а вторым имя файл-функции в апострофах или указатель на функцию. Вычислите, например e^-sirM. Текст соответствующей файл-функции matrf приведен в листинге 6.14. При создании файл-функции обязательно использование поэлементных операций! . ........ .... ............................................ ... ................... Листинг 6.14. Файл-фу нкция matrf для вычисления функции матрицы function В = matrf(А) В = ехр(А). *sin(A); Теперь при помощи funm найдите значение заданной функции от матрицы в: » В = furm(A, ©matrf) В = 141.6829 228.9756 228.9756 370.6585 Для контроля точности вычислений функции от матрицы лучше использовать вызов funm с двумя выходными аргументами. Во второй аргумент помещается информация о точности вычислений. Встроенные математические функции MATLAB (sin, cos и другие) можно вычислять от матриц аналогичным образом, например » В = funm(A, 'sin') Предпочтительнее производить вычисления функций от матриц с использованием специальных матричных функций expm, logm, sqrtm, т. е., например, ехрт .А) вместо funm(A, 'exp') и т. д. В этих матричных функциях реализованы специальные алгоритмы, работающие точнее и надежнее, чем общий алгоритм funm. Функции матриц имеют широкую область применения, в частности, решение системы линейных дифференциальных уравнений с начальным условием ,/у — = АХ. X(Q) = X0 может быть найдено по формуле Х(1) - Х{) е‘ *. Решению дифференциальных уравнений и систем посвящен следующий раздел. Гпааа 6 Мъчолы ^^ычйслений в MATLAB 293 Решение дифференциальных уравнений Данный раздел посвящен описанию возможностей, предоставляемых МА I LAB, для численного решения задач Коши и краевых задач для обыкновенных дифференциальных уравнений произвольного порядка и систем, включая краевые задачи с неизвестными параметрами и вырождающимися коэффициентами. Рассматривается также решение дифференциальных уравнений с запаздывающим аргументом. Для решения этих задач предназначены специальные функции MATI АВ. в вычислительной математике их называют солверы. MATLAB имеет достаточно большой набор сотверов, основанных на различных численных методах. Решение задачи Коши Для решения задачи Коши в MATLAB существует семь сольеров: ode45, ode23, odell3, odel5s, ode23s, ode23t И ode23tb. Методика ИХ использования одинакова, включая способы задания входных и выходных аргументов. В достаточно общем случае вызов солвера для решения задачи Коши производится следующим образом (здесь под solver понимается один из перечисленных выше солверов): [Т, Y] = solver(odefun,interval,YO,options) где odefun — функция для вычисления вектор-функции правой части системы уравнений, interval — массив из двух чисел, задающий промежуток для решения уравнения, yo— заданный вектор начальных значений искомой вектор-функции, options — структура для управления параметрами и ходом вычислительного процесса. Солвер возвращает массив т с координатами узлов сетки, в которых найдено решение, и матрицу решений Y, каждый столбец которой является значением компоненты вектор-функции решения в узлах сетки. Далее мы обсудим применение солверов и управление процессом решения на ряде показательных примеров из перечисленных выше классов задач. Задача Коши для дифференциального уравнения состоит в нахождении функции, удовлетворяющей дифференциальному уравнению произвольного порядка (л) tit ' (п~ и начальным условиям при t =/0 V ('о ) = «о ’ /Оо ) = “i»• • •» ('о) = «п-1 • 294 Часть II. Вычисления и программирование Схема решения таких задач в MATLAB состоит из следующих этапов. 1. Приведение дифференциального уравнения к системе дифференциальных уравнений первого порядка (если изначально задана система, то в этом нет необходимости). 2. Написание специальной функции для системы уравнений. 3. Вызов подходящего солвера. 4. Визуализация результата. Разберем решение дифференциальных уравнений на примере задачи о колебаниях материальной точки под воздействием внешней силы в среде, оказывающей сопротивление колебаниям. Перемещение точки в среде описывается уравнением второго порядка у" + 2у + 1 Оу = sin /. Предположим, что координата точки в начальный момент времени равнялась единице, а скорость — нулю. Тогда соответствующие начальные условия имеют вид у(0) = 1, у'(0) = 0. Пример носит демонстрационный характер, поэтому размерности физических величин указываться не будут. Теперь исходную задачу надо привести к системе дифференциальных уравнений. Для этого вводят столько вспомо-га тельных функций, каков порядок уравнения. В данном случае необходимы две вспомогательные функции У] и у2, определяемые формулами Т1=У. У2 = У- Несложно догадаться, что система дифференциальных уравнений с начальными условиями, требуемая для дальнейшей работы, такова У1 =У2> р|(0) у2 =-2у3-10у1+sin/; Второй этап состоит в написании функции для системы дифференциальных уравнений. Функция должна иметь два входных аргумента: переменную /, по которой производится дифференцирование, и вектор, размер которого равен числу неизвестных функций системы. Число и порядок аргументов фиксированы, даже если t явно не входит в систему. Выходным аргументом функции является вектор правой части системы. Текст функции oscii для разбираемого примера приведен в листинге 6.15. (6.4) Глава 6. Методы вычислений в MATLAB 295 Решите задачу, используя, например, солвер odeli3. Входными аргументами солверов в самом простом случае являются: указатель на функцию (или ее имя в апострофах), вектор с начальным и конечным значением времени наблюдения за процессом и вектор начальных условий. Выходных аргументов два: вектор, содержащий значения времени, и матрица значений искомых функций в соответствующие моменты времени. Значения функций расположены по столбцам матрицы, в первом столбце— значения первой функции, во втором— второй ит. д. В силу проделанных замен = j, Уг~У'’ столбец матрицы содержит как раз значения неизвестной функции у((), входящей в исходное дифференциальное уравнение, а второй столбец — значения ее производной. Как правило, размеры матрицы и вектора достаточно велики, поэтому лучше сразу отобразить результат на графике. Применение солвера для нахождения решения при t < 15 и визуализация результата продемонстрированы на примере файл-функции solvdem, приведенной в листинге 6.15, где функция oscil реализована как подфункция. Листинг 6.15- Файл-функция эсЗлЩалдля решения дифференциального уравнения (6.4) • ...а - I I . а I ’,«пга . . .-4»»- function solvdem % формирование вектора начальных условий УО = [1; 0J; % вызов солвера от функции oscil, начального и конечного % момента времени и вектора начальных условий [Т, У] = odell3(@oscil, (0 15], Y0); % вывод графика решения исходного дифференциального уравнения % (маркеры - точки, линия - сплошная) plot(T, У(:, 1), 'г.-') % вывод графика производной от решения исходного % дифференциального уравнения (маркеры - точки, линия - пунктир) hold on plot(T, Y(:, 2), 'k.:’) % вывод пояснений на график title(’Решение (ity) primeprime+2{ity} prime+10{ity) =sin(itt)') xlabel(‘itt') ylabel{'{ity}, {ityl prime ') legend(1 координата', 'скорость', 4) grid on hold off 296 Часть II. Вы fncni нир и программирование % подфункция вычисления правых частей уравнений function F = oscil(t, у) F = ly(2); -2*у(2) - 10*у(1) + sin(t)]; В результате выполнения файл-функции solvdem на экран выводятся графики, изображенные на рис. 6.8, которые отражают поведение координаты точки и ее скорости в зависимости от времени. Из графика видно, что приближенное решение и его производная удовлетворяют начальным условиям, колебание происходит в установившемся режиме, начиная с / = 5. Солверы moi ут найти приближенное решение для заданных значений независимой переменной. Для этого следует в качестве второго входного аргумента указать вектор с этими значениями, упорядоченными по возрастанию или убыванию. Рис. 6.8. Решение дифференциального уравнения (6.4) Заметим, что интерфейс солверов допускает обращение к ним с одним выходным аргументом: » sol - odel!3(@oscil, [0 15], YO) ; Глава 6. Методы вычислений в MATLAB 297 Такой вызов солвера приводит к образованию структуры sol с информацией о полученном приближенном решении. Поле х структуры sol содержит вектор-строку значений независимой переменной, а поле у— матрицу из соответствующих значений компонент решения, записанных в строки (работа со структурами данных подробно описана в главе 8). Проще говоря, sol.x эквивалентно Т’, a sol.у— Y' для рассмотренного выше обращения к солверу с двумя выходными аргументами т и Y в файл-функции soivdem, текст которой приведен в листинге 6.15 (напомним, что апостроф означает гранспонирование). Если бы в soivdem солвер был вызван с единственным выходным аргументом, то для построения графиков компонент приближенного решения следовало бы использовать команды (проверьте!). plot(sol.x, sol.yd, 'г.-') plotfsol.x, sol.y(2, :), 'k.:') Мы привели альтернативный вариант интерфейса солверов с одним выходным аргументом, поскольку он позволяет ответить на вопрос: как получить значение решения в любой точке отрезка. Действительно, солверы вычисляют приближенное решение задачи Коши в конечном числе точек на заданном отрезке, причем координаты точек выбираются солвером или задаются пользователем. Для определения значений компонент решения в промежуточных точках придется прибегнуть к интерполяции. Эффективную интерполяцию осуществляет функция deval, использование которой требует структуры sol с информацией о решении. Самый простой способ вызова функции deval >> sxint = deval(sol, xint) предполагает указание вектора xint с координатами точек, в которых следует вычислить решение. Найденные значения компонент построчно записываются в выходном аргументе, т. е. в sxint (:, i) хранятся значения всех компонент искомой вектор-функции в точке с координатой xint(i). Например, для вычисления компонент решения на отрезке [0, 5] в равноотстоящих точках с шагом 0.02 и построения графиков достаточно выполнить команды: » xint = 0:0.02:5; » sxint - deval(sol, xint); » plotfxint, sxintd, :), xint, sxint(2, :)) Интерполяция возможна только для некоторых компонент решения, в этом случае необходимо указать их номера в векторе idx и включить его в список входных аргументов » sxint = deval(sol, xint, idx) 298 Часть II. Вычисления и программирование В нашем примере решение задачи Коши для системы дифференциальных уравнений, соответствующей исходной задаче для дифференциального уравнения второго порядка, было получено при помощи солвера odeii3, который основан на методе Адамса—Бэшфорта—Милтона. Кроме солвера odell3, MATLAB имеет еше ряд солверов для задачи Коши: ode45, ode23, odeibs, ode2 3s, ode23t, ode23tb, интерфейс которых не отличается от odel13. J Примечание J Вызов солвера с одним и двумя выходными аргументами приводит к одинаковому выбору узлов на заданном отрезке. Единственный солвер ode45 добавляет промежуточные точки и сам осуществляет интерпо тацию в случае обращения к нему с двумя выходными аргументами. При выборе солвера для решения задачи необходимо учитывать свойства системы дифференциальных уравнений, иначе можно получить неточный результат или затратить слишком много времени на решение. В следующем разделе на примере системы уравнений Лотки—Зольтерры демонстрируется важность соответствия солвера решаемой задаче. Решение уравнений Лотки—Вольтерры В качестве объекта исследования возьмем модель Лотки—Вольтерры борьбы за существование. Обозначим: yj (г) — число жертв, у2 (г) — число хищников. Число хищников и жертв в течение времени I изменяется по закону У=Р-У~Р-УУ2^ (,~ , (0.3) у2=-/?-у2+г-у|у2, где Р— увеличение числа жертв в отсутствие хищников, R— уменьшение числа хищников в отсутствие жертв. Вероятность поедания хищником жертвы пропорциональна их числу >j У2, ПРИ этом слагаемое ~Р'УУ2 соответствует вымиранию жертв, а г-у|У2 — появлению хищников. Возьмите для примера Р = 0.8, R — , р = г = 0.001, считайте, что в начальный момент времени было 1000 жертв и 1100 хищников. При помощи солвера odeli3 решите эту систему дифференциальных уравнений для t <100, а затем используйте ode23s (задание ею аргументов производится аналогично odeil3). Выведите полученные при помощи odeli3 и ode23s решения на разные графики, и сравните их. Листинг 6.16 содержит текст необходимых функций. Глава t; Методы вычислений в MATLAB 299 Как известно, точным решением задачи Лотки—Вольтерры на плоскости У[Уг является замкнутая кривая. Графики приближенных решений, приведенные на рис. 6.9, сильно отличаются друг от друга, хотя вычисления по умолчанию в ode!13 и ode23s происходят с одинаковой точностью. Приближенное решение, полученное солвером ode23s, намного точнее, чем в случае odeil3. Дело в том, что уравнения Лотки—Вольтерры являются примером так называемых жестких систем, для решения которых в пакете MATLAB имеются специальные солверы. Один из них — ode23s. В справочной системе MATLAB приведен другой пример жесткой задачи — уравнение Ван-дер-Поля с большим значением параметра, для исследования которой следует применять специальный солвер odeiSs (см. разд. Mathematics: Examples: Differential Equations - Initial Value Problems, подразделы The van der Pol Equation, p = 1000 (Stiff) и Stiff Problem (van der Pol Equation) справочной системы MATLAB). Рис. 6.9, Сравнение солверов ode!13 и ode23s Итак, при решении в MATLAB дифференциальных уравнений и систем с начальными условиями следует правильно выбирать солвер в зависимости от свойств задачи. В следующем разделе кратко обсуждаются области применения солверов MATLAB. 300 Часть II. Вычисления л программирование *а,............................................................................. ... Листинг 6.16. Фай -функция для сравнения ode45 и ode23s L................................ ......А............................................................ function comparesolveis % формирование вектора начальньк условий Y0 = (1000; 1100]; % вызов солвера odel!3 [Т, Y] = odell3(@LotVol, [0 100]. Y0); % вывод графика решения исходного дифференциального уравнения % в виде параметрической кривой subplot(1, 2, 1) plot(Y(:, 1), Y(:, 2)) % вывод пояснений на график title('Решение уравнений Лотки—Вольтерры (odell3)') хlabel('жертвы') ylabel('хищники'I %вызов солвера ode23s [Т, Y] = ode23s(SLotVol, [0 100], Y0); % выв^д графика решения исходного дифференциального уравнения % в виде параметрической кривой subplot(1, 2, 2) plot(Y{:, 1), Y(:, 2)) % вывод пояснений на график title('Решение уравнений Лотки-Вольтерры (ode23s)') xlabe_('жертвы') ylabel('хищники 1) % подфункция вычисления правых частей уравнений function F = LotVoKt, у) F = [О.е*у(1> - 0.001*у(1)*у(2); -1.0*у(2) + 0.001*у(1)*у(2)]; Выбор солвера для решения задачи Коши В данном разделе описана стратегия применения солверов MATLAB для решения обыкновенных дифференциальных уравнений или систем с начальными условиями Читатели, имеющие представление о численных методах решения дифференциальных уравнений могут воспользоваться описанием алгоритмов солверов, которые приведены в справочной системе MATLAB Глава ^.Методы вычислений в MATLAB 301 Очень часто солвер ode45 дает вполне хорошие результаты, им стоит воспользоваться в первую очередь. Он основан на формулах Рунге—Кутты четвертого и пятого порядка точности. Солвер ode23 также основан на формулах Рунге—Кутты, но уже более низкого порядка точности. Имеет смысл применять ode23 в задачах, содержащих небольшую жесткость, когда требуется получить решение с невысокой степенью точности. Если же требуется получить решение нежесткой задачи с высокой точностью, то наилучший результат даст odel!3, основанный на методе переменного порядка Адамса—Бэшфорта—Милтона. Солвер odeil3 оказывается особенно эффективным для нежестких систем дифференциальных уравнений, правые части которых вычисляются по сложным формулам. Все солверы пытаются найти решение с относительной точностью ПН и абсолютной— ПН. Хорошим тестом качества приближенного решения является увеличение точности вычислений (задание точности вычислений и ряда других параметров описано в следующем разделе). Если все попытки применения ode45, ode23s, ode!13 не приводят к успеху, то возможно, что решаемая система является жесткой. Для решения жестких систем подходит солвер odeiSs, основанный на многошаговом методе Гира, который допускает изменение порядка. Если требуется решить жесткую задачу с невысокой точностью, то хороший результат может дать солвер ode23s, реализующий одношаговый метод Розенброка второго порядка. Простейшее использование вышеперечисленных солверов производится так же, как и odell3 (см. разд. "Схема решения задач с начальными условиями” данной главы). При решении практических задач важно контролировать вычисления. Все солверы допускают задание ряда параметров, позволяющих повысить эффективность вычислений в зависимости от решаемой задачи. В частности, при решении жестких задач задание якобиана системы позволяет увеличить быстродействие вычислений. Одной из важнейших характеристик приближенного решения является его точность. Управление процессом решения Эффективное решение дифференциальных уравнений невозможно без понимания основных вопросов связанных с численными методами. Солверы MATLAB не являются "черными ящиками". Пользователю необходимо выбрать подходящий солвер, в зависимости от свойств решаемой задачи, и произвести необходимые установки, обеспечивающие получение приближенного решения с требуемыми свойствами, например, с заданной точностью. Солверы допускают указание параметров для контроля и управления вычислительным процессом. Способ задания параметров солверов ode45, 302 Часть II. Вычисления и программирование ode23, odell3, odel5s, ode23s, ode23t И ode23tb аналогичен тому, который вы применяли при нахождении корней функции или локальных минимумов. Значения параметров записываются в управляющую структуру, которая создается функцией odeset. В общем случае обращение к odeset имеет вид: options = odeset(..., 'видконтроля', значение, ...) Параметры солверов, сгруппированные в категории по своему назначению, приведены в табл. 6.6. Следует иметь в виду, что неоправданное изменение многих параме гров может повлечь уменьшение эффективности солвера или получение неверных результатов. Таблица 6.6. Параметры odeset Г рупии Имя параметра (вид контроля) Контроль точности вычислений RelTol, AbsTol, Normcontrol Шаг интегрирования Initialstep, MaxStep Выходные данные OutputFcn, OutputSel, Refine, Stats Якобиан Jacobian, JPattem, Vectorized Матрица масс и матрица системы ОДУ Mass, MStateDependence, MvPattern, MassSingular, Initialslope События Events Только для odel5s MaxOrder, BDF Структура с опциями солверов модифицируется так же, как и в случае с optimset при решении уравнений и минимизации функций: options = odeset(options, ви д_контроля, значение,...) Вызов odeset без входных аргументов позволяет посмотреть в командном окне имена всех свойств и их возможные значения, причем в фигурных скобках указаны значения, используемые солверами по умолчанию. Функция odeget предназначена для извлечения значения свойства из структуры значение = odeget(options, вид_контроля) При генерации структуры функцией odeset значение могло быть не определено, в этом случае возвращается пустой массив. Предназначение всех параметров солверов раскрыто в интеракзивной справочной системе. Для получения этой информации обратитесь к описанию Гпава 6. Методы вычислений в MATLAB 303 функции odeset (воспользовавшись, например, индексным поиском на вкладке Index) и к разд. Mathematics: Difkrential Equations: Initial Value Problems for ODEs and DAEs: Changing ODE Integration Properties. Ряд опций солверов, к изменению которых приходится прибегать наиболее часто, мы рассмотрим в следующих нескольких разделах. Задание точности вычислений и шага интегрирования Точность вычислений оказывает существенное влияние на качество приближенного решения. Управляющие параметры солверов и их значения для данного вида контроля перечислены в табл. 6.7. Допускается два способа контроля точности в зависимости от значения параметра Normcontrol: 1. По локальной погрешности et z-ой (yf) компоненты вектора решений, если параметр Normcontrol имеет значение 'off (по умолчанию). 2. По евклидовой норме погрешности, для Normcontrol, установленного в ’on*. В первом случае точность считается достигнутой при выполнении условий |е,- (tk )j < maxfRelToi-ly,- (tk )|, AbsTol(i)} для всех компонент вектора решений на каждом шаге по времени tk . Во втором случае принимается во внимание суммарная характеристика для всех компонент решения — евклидова норма вектора || || (вычисляемая встроенной функцией norm)— и точность считается достигнутой, если на каждом шаге по времени tk выполняется неравенство ||е|| <max{RelTol||y||, AbsTol}. В случае покомпонентной оценки параметр AbsTol (абсолютная точность) может быть числом, если требуется задать фиксированную абсолютную точность для всех компонент решения. Для контроля абсолютной точности каждой компоненты следует указать вектор значений. Можно считать, что относительная точность ReiTol определяет число верных значащих цифр во всех компонентах решения. Однако если среди компонент решения есть близкие к нулю, то для более точного их вычисления следует уменьшать соответствующий элемент вектора значений AbsTol. Шаг интегрирования солвера определяется двумя свойствами: □ Maxstep — задает максимальный шаг (по умолчанию десятая часть промежутка интетрирования); □ initialstep — задает начальный шаг, и если он не определен, то выбирается солвером с учетом начальных значений для вектора решений. При нулевых значениях шаг может оказаться слишком большим. 304 Часть II Вычисления и программирование Таблица 6,7, Параметры контроля точности вычислений Вид контроля Значение Примечание WormControl 'off' (по умолчанию) Контроль точности по максимальной локальной погрешности ’ on’ Контроль точности по второй норме вектора локальной погрешности RelToi число (10~J по умолчанию) Относительная точность вычислений AbsTol число или векз op (10 6 по умолчанию) Точность для контроля компонент вектора решения Убедиться в том, что заданных по умолчанию значений, в частности, относительной погрешности I03, не всегда достаточно для получения хорошего приближения, можно на следующем простом примере. Решите систему дифференциальных уравнений У=У* У2=-1/12 на отрезке [я, 100] при начальных условиях j1(zz) =Inez, _у2(а) = 1/о, взяв а = 0.001. Легко проверить, что точным решением этой системы является y^lnz, J'2 = 1Л- Напишите самостоятельно файл-функцию для решения данной системы со-лвером ode45, содержащую подфункцию rsbad для вычисления правой части системы. Расположите на одном графике точное и приближенное решение. Результат, приведенный на рис. 6.10, является довольно неожиданным для погрешности 10~3 (используемой по умолчанию). Применение других солверов и задание более мелкого максимального или начального шагов не улучшает ситуацию. Выход состоит в уменьшении относительной погрешности вычислений при помощи формирования options с использованием odeset и включении options дополнительным четвертым аргументом в солвер. Д чя задания относительной погрешности служит параметр RelToi. например options = odeset('RelToi', 1.0е-04) Гпава 6. Методы вычислении в MATLAB 305 Рис. 6.10. Сравнение приближенного решения с точным (погрешность по умолчанию) Дополните созданную файл-функцию вызовами ode45, предваряя каждое обращение к солверу установкой точности. Не забывайте включать options в список аргументов солвера! Рис. 6.11. Сравнение приближенного решения с точным при различных погрешностях 306 Часть II Вычисления и программирование При возникновении затруднений обратитесь к листингу 6.17. Выведите 1 рафики приб лиженных решений для погрешностей 103, 104, 10 6 так, как показано на рис. 6.11 Только точность 10-6 обеспечивает получение приближенного решения, график которого почти совпадает с графиком точного решения. function difficultproblem а = 0.001; Y0 - [log(а); 1/а]; % задание начальных условий % BstsoB солвера ode45 для решения с различней точностью % и вывод графиков приближенных решений % относительная точность 0.001 options = odeset{'RelTol', 1.0е-3); [T, Y] = ode45(Srsbad, [a 100], Y0, options); plot(T, Y(:,l), 'k:’) % относительная точность 0.0001 options = odeset(’RelTol', 1.Ле-4); [T, Y] = ode45(Srsbad, [a 100], YO, options); hold on plot(T, Y(:, 1), 'k—') % относительная точность 0.000001 options = odeset(1RelTol•, 1.0e-6); [T, Y] = ode45(Brsbad, [a 100], Y0, options); plot(T, Y(;, 1), 1k-') % вывод графика точного решения t = [а:4:100] ; у = log(t); plottt, у, ‘ко’) % нанесение информации на график xlabel('itt') ylabel('ity1) title('Сравнение приближений при различных погрешностях') Глава 6 Методы вычислений в MATLAB 307 legend>'10л{-3}', ,10'‘{-4}', '10л{-6}', 'точное решение', 4) grid on hold off % подфункция вычисления правых частей уравнений function F = rsbad{t, у) F = (у(2); -1.0/tA2J; Управление выводом результатов Примеры предыдущих разделов предполагали вызов солверов с двумя выходными аргументами— массивами или одним— структурой. В них возвращался вектор значений независимой переменной и матрица со значениями компонент решения в соответствующих точках. Полученные массивы мы использовали для визуализации и анализа результата. Вернитесь к уравнению (6.4), для решения которого была создана файл-функция, приведенная в листинге 6.15, уберите выходные аргументы у солвера и вывод решения функцией plot. Вызов солвера без выходных аргументов приводит к появлению графического окна, изображенного на рис. 6.12, в котором отображается процесс численного интегрирования дифференциального уравнения и выводятся все компоненты вектора решения. Рис. 6,12. Графическое отображение процесса численно! о интегрирования 1‘ Заг ВО 308 Часть II. Вычисления и программирование Возможности вывода результата, предоставляемые солверами MATLAB, не исчерпываются только таким способом визуализации решения. Пользователь может выбрать альтернативное графическое представление результата, более того, допускается контролировать процесс численного интегрирования и отображать его на графике по своему усмотрению. Для этою следует воспользоваться одним из видов контроля управляющей структуры — OutputFcn. Его значение должно быть указателем на функцию (или ее именем), производящую требуемые операции. Имеется несколько стандартных функций. □ odeplot — построение графиков компонент решения; □ odephas2 — построение графиков компонент решения в фазовых координатах для двумерного процесса; □ odephas3 — построение графиков компонент решения в фазовых координатах для трехмерного процесса; □ odeprint — печать решения. Заметьте, что вызов солвера без выходных аргументов приводит к появлению гех же графиков, что и применение odeplot, поскольку вид контроля OutputFcn принимает значение eodepiot: » options = odeset('OutputFcn', Sodeplot) » [T,Y] = ode45(@oscil, [0 15], YO, options); Представление решения на фазовой плоскости такое, как на рис. 6.13, производи гея при помощи odephas2: » options = odeset('OutputFcn', @odephas2) » [T,Y] = ode45(@oscil, [0 15], YO, options); Пользователь может создавать свои файл-функции для визуализации решения или обработки результатов каждого шага численною мигрирования. Рассмотрим один простой пример. Требуется производить численное инти рпрование дифференциального уравнения у+ v = e' (sinx + 2cosy) (6.6) при начальных условиях у(0) = 0, F(z, Кдо тех пор, пока модуль значения функции у(а) не превзойдет 100 Приведите уравнение к системе обыкновенных дифференциальных уравнений и запрограммируйте ее правую часть в файл-функции syst (листинг 6.18). > i/ава 6. Методы вычислений в MATLAB 309 Рис. 6.13. Визуализация решения дифференциального уравнения (6.4) на фазовой плоскости (odephas2) Листинг 6.18. Правая часть системы дифференциальных уравнений (6.6) function F = syst(t, у) F = [у(2); exp(t).*(sin(t) +2*cos(t)) — y(l>); При вызове солвера, к примеру, odeii3, требуется указать отрезок интегрирования, но его правая граница заранее неизвестна — мы не знаем априори, в какой момент времени модуль значения функции станет больше 100 Например, для отрезка [0, 10] получаются существенно большие значения: » [T,Y] = odell3(@syst, [0, 10], [0 1]) » plot(T, Y(:, 1)) Выход состоит в написании файл-функции для обработки значения, вычисленного на текущем шаге интегрирования. Солвер будет вызывать эту фу нкцию после каждого шага и осуществлять дальнейшие действия в зависимости от возвращаемого ей значения. Назовем эту функцию solproc. Ее заголовок должен иметь вид: function status = solproc(t, у, flag) 310 Часть II. Вычисления и программирование Входной аргумент flag является строковой переменной и может принимать одно из трех значений, которое в свою очередь определяет содержимое t и у: □ 'init' — при первом вызове функции solproc солвером до начала процесса интегрирования. При этом t является вектором из двух элементов— границ отрезка интегрирования по времени, а у — вектором начальных значений; □ (пустая строка)— после каждого шага интегрирования. Во входных аргументах t и у находятся текущие значения аргумента и приближенного решения. Аргумент t может содержать несколько текущих значений, при этом в i-ом столбце массива у записаны значения компонент решения для t (1); □ 'done' — после завершения численного решения системы дифференциальных уравнений. В качестве с и у передаются пустые массивы. В случае, когда flag является пустой строкой, длина входного аргумента t определяется значением свойства Refine. По умолчанию оно равно 1 и все солверы (кроме ode45) на каждом шаге будут вызывать функцию solproc только от одного значения независимой переменной. Соответственно, у будет вектором со значениями компонент решения, чем мы и будем пользоваться в нашем примере для солвера odell3. Управляющий параметр Refine предназначен для увеличения числа точек, в которых вычисляется решение на каждом шаге интегрирования. Если Refine установлен в 1 (по умолчанию), то приближенное решение находится только для конца отрезка, по которому производится интегрирование на текущем шаге. При увеличении Refine вводятся промежуточные точки на отрезке интегрирования, которые разбивают его на столько интервалов, сколько указано в Refine. Решение в этих точках вычисляется при помощи специальных продолжений, экономящих время счета. Солвер ode45, в отличие от остальных, всегда по умолчанию использует 4 интервала. В результате работы функции solproc формируется выходной аргумент status, который может быть 1 либо 0. Если солвер обнаруживает, что функция solproc вернула 1, то процесс интегрирования прекращается, а если 0 — то продолжается. Итак, нам требуется запрограммировать функцию, реализующую простой алгоритм: если flag-— пустая строка и модуль значения у(1) превосходит 100, то вернуть 1. иначе вернуть 0. Текст требуемой файл-функции приведен в листинге 6.19. Глава 6. Методы вычислений в MATLAB 311 function status = solproc(t, у, flag) % функция определяет, превысил ли модуль первой компоненты % решения число 100 после каждого шага интегрирования % если да — status = 1, если нет — status = О status = (length(flag) == 0)&&(abs(у(1)) > 100) В теле функции для определения значения выходного аргумента мы записали логическое выражение с оператором && (логическое "и"), который при невыполнении первого условия второе уже не проверяет. Действительно, второе условие имеет смысл проверять только в том случае, когда солвер на текущем шаге интегрирования вызвал нашу функцию с flag, равным пустой строке. При последнем вызове solproc солвером во входном аргументе у передается пустой массив, и обращение к его первому элементу привело бы к ошибке (запись логических выражений в MATLAB подробно рассмотрена в главе 7). При формировании структуры options задайте указатель на функцию solproc в качестве значения OutputFcn, вызовите солвер odell3 и постройте Iрафик первой компоненты решения. » options = odeset('OutputFcn', ©solproc) » [T, Y] = odell3(@syst, [0, 10], [0 1], options) » plot(T, Y(:,l)) Получившийся график, приведенный на рис. 6.14, свидетельствует о своевременном останове вычислительного процесса. Мы привели, пожалуй, самый простой пример использования информации, получаемой в процессе численного интегрирования. Функция обработки решения solproc могла бы содержать и более сложный алгоритм, записанный на языке программирования MATLAB, который реализует собственный способ визуализации решения и ряда его характеристик. После освоения конструкций языка программирования и дескрипторной графики вам будут понятны тексты файл-функций odeplot, odephas2, odephas3, расположенных в подкаталоге toolboxmatlabfunfun основного каталога MATLAB. Изучение алгоритмов этих файл-функций позволит получить представление о том, как организовать обработку выходных данных солверов (программированию и дескрипторной графике посвящены главы 7—9). При помощи параметра Outputsei вы можете определять номера компонент решения, которые будут передаваться в файл-функцию обработки. Для этого необходимо указать вектор номеров требуемых компонент или один но 312 Часть II. Вычисления и программирование мер, как это сделано в следующем примере для графического отображения процесса нахождения только первой компоненты решения. » options = cdeset('OutputFcn', Sodeplot, 'OutputSel', 1) » [T, Y] = ode!13(@syst, [0, 10], [0 1], options) Рис. 6.14. Решение дифференциального уравнения (6 6) с крн герием останова солвера по значению функции При контроле за наступлением некоторых событий в процессе численного интегрирования часто важно достаточно точно знать время наступления события Для этого следует запрограммировать файл-функцию специального вида, задать указатель на нее в качестве значения параметра Events и вызвать солвер с пятью выходными аргументами или структурой. Задание матрицы Якоби для повышения эффективности вычислений После завершения счета солвер может вывести в командное окно суммарную информацию о вычислительной работе, включающую количество вычислений правой части матрицы Якоби, успешных и неуспешных шагов солвера и другие сведения. Для этого следует установить свойство 'stats' в on' Подробное описание всех свойств управляющей структуры и примеры содержатся в справочной системе MATLAB в разд. Mathematics: Differential Equations: Initial Value Problems for ODEs and DAEs: Changing ODE Integration Properties Гпава 6 Методы вычислений в МА TLAB 313 При решении жестких систем дифференциальных уравнений солверы odeiSs, ode23s, ode23t и cde23tb аппроксимируют матрицу Якоби правой части системы методом конечных разностей. Эффективность вычислений может быть повышена путем задания матрицы Якоби в явном виде. Для этого следует написать файл-функцию, которая возвращает матрицу Якоби для текущих значений независимой переменной и компонент решения. Заголовок функции должен иметь вид function J = jmatrft, у) Для того чтобы солвер мог воспользоваться явными формулами, необходимо присвоить свойству Jacobian управляющей структуры указатель на функцию jmatr. Если матрица Якоби постоянна, то не требуется программировать файл-функцию — достаточно указать ее в качестве значения свойства Jacobian. Для рассмотренной выше системы уравнений Лотки—Вольтерры (6.5), при Р = 0.8, R = 1, р = г = 0.001, функция, вычисляющая матрицу Якоби, приведена в листинге 6.20. -----............................................................. ; Листинг 6.20. Программирование матрицы Якоби function J = JLotVol(t, у) J = [0.8 - 0.001*у(2) - 0.001*у(1) 0.001*у(2) -1 + 0.001*у(1)]; Внесите JLotVol в качестве подфункции в файл-функцию comparesolvers (листинг 6.16) и перед вызовом солвера ode23s в основной функции сформируйте управляющую структуру options и укажите ее в качестве входного аргумента ode23s. Соответствующие команды приведены в листинге 6.21. •..."ЦТ •• .....................................л, w .......Ч;..........................%......г*....... ; Листинг 6.21. Указание матрицы Якоби солверу —«а.-- • w. । <«, - ..... . ... ..к. „••••. ., ........... лп..... ................ options = odeset(’Jacobian1, @JLotVol); [Т, У] = ode23s(©Lotvol, [0 100], Y0, options); Теперь при обращении к файл-функции comparesolvers солвер ode23s будет использовать явные формулы для элементов матрицы Якоби. Системы дифференциальных уравнений большой размерности могут иметь матрицу Якоби с небольшим числом ненулевых элементов, т. е. разреженную. В этом случае имеет смысл подсказать солверу, где расположены ее ненулевые элементы, подлежащие аппроксимации в процессе численного интегрирования. Для этих целей служит свойство jpattern, значением ко 314 Часть II. Вычисления и программирование торого должна быть разреженная матрица с элементами 0 и 1, определяемая шаблоном матрицы Якоби (разреженным матрицам посвящена глава 15). Задачи с известными параметрами Солверы MATLAB допускают решение систем обыкновенных дифференциальных уравнений, правая часть которых зависит от некоторых параметров pi, р2, ... с известными значениями. В предыдущих версиях MATLAB передача параметров была организована посоедством интерфейса солверов. Эта возможность сохранилась и в версии 7, однако ее описание исключено из справочной системы, поскольку реализованы другие методы передачи параметров, основанные на использовании вложенных или анонимных функций. Способ обращения к солверам, унаследованный из предыдущих версий, состоит в указании значений параметров в списке входных аргументов, начиная с пятой позиции после управляющей структуры options » [T,Y] = ode45(@syst, [tO, tl] , YO, options, pl, p2, ...) ИЛИ >> sol = ode45(@syst, [tO, tl], YO, options, pl, p2, ...) Вызов других солверов для задачи Коши производится аналогично; кроме того, вместо структуры options допускается задание пустого массива для нахождения приближенного решения с точностью и другими опциями, установленными по умолчанию. Такой подход накладывает определенные требования на интерфейс функции, вычисляющей правую часть системы дифференциальных уравнений — ее заголовок должен иметь вид: function F = syst(t, у, pl, р2,...) Если в процессе решения используются явные формулы для вычисления матрицы Якоби, то параметры включаются в список входных аргументов соответствующей функции function F = jac(t, у, pl, р2,...) Приведенная выше система дифференциальных уравнений Лотки— Вольтерры зависит от четырех параметров: Л р, R и г, и при многократном ее решении для различных значений параметров целесообразно написать соответствующую файл-функцию, вместо того, чтобы каждый раз изменять значения этих параметров. Текст такой файл-функции приведен в листинге 6.22. Глава 3. Методы вычислений в MATLAB 315 ..... .............................«••«•"g-. --------------------- ---------------------- Листинг 6.22. Передача параметров Чеоез входные аргументы солвера . . ...... v , . ........ ............... ................w# - . . - . • • •..... ....... ...........«к............. function LVpar(Р, p, R, r) YO = 11000; 1100]; % задание начальных условий % формирование управляющей структуры с матрицей Якоби options = odeset('Jacobian', OJLotVolPar); % вызов солвера и передача значений параметров [Т, Y] = ode23s(BLotVolPar, [0 100], Y0, options, P, p, R, r) ; % построение графика решения figure plot(Y(:, 1], Y(:, 2)) % подфункция для вычисления правой части системы, зависящей от параметров function F = LotVolPar(t, у, Р, р, R, г) F = [Р*у(1] - р*у(1)*у(2) -R*y(2) + r*y(1)*у(2)]; % подфункция для вычисления матрицы Якоби, зависящей от параметров function J = JLotVolPar(t, у, Р, р, R, г) J = [Р - Р*У(2) - р*у(1) r*y(2) - R + г*у(1)]; Теперь обращение к файл-функции LVpar позволяет решить задачу Лотки— Вольтерры для различного набора значений параметров, например » LVpar(0.75, 0.002, 0.95, 0.001) ИЛИ » LVpar(0.8, 0.001, 0.9, 0.003) Альтернативный способ решения задач с известными параметрами состоит в использовании анонимных или вложенных функций. Мы обсуждали этот подход при поиске корней и локальных минимумов функций, поэтому приведем здесь только текст соответствующей файл-функции с двумя вложенными функциями без дополнительных комментариев (листинг 6.23), Обращение К LVparl ПРОИЗВОДИТСЯ Так Же, как И К LVpar. .......................................................... ..-..........................................., Листинг6.23. Передача параметров через входные аргументы солвера function LVparl(Р, р, R, г) % вложенная функция для вычисления правой части системы, % зависящей от параметров function F = LotVotPar<t, у) 316 Часть II. Вычисления и программирование F = ;р-у(1) - р*у(1)*у(2) -R*y(2) + г*у(1)*у(2)]; end % вложенная функция для вычисления матрицы Якоби, зависящей от параметров function J = JLotVolPar{t, у) j = (р - р*у(2) - р*у(1) r*y(2) - R + г*у(1)]; end; YO = [1000; 1100]; % задание начальных условий % формирование управляющей структуры с матрицей Якоби options = odeset(1Jacobian', SJLotVolPar); % вызов солвера [Т, Y] = ode23s(@LotVolPar, [0 100], Y0, options); % построение графика решения figure plot(Y(:, 1), Y(:, 2)) end Системы, не разрешенные относительно производной, дифференциально-алгебраические уравнения До сих пор мы рассматривали задачу Коши для систем дифференциальных уравнений, разрешенных относительно производных У' = /(КУ). MATLAB позволяет решать системы дифференциальных уравнений, заданных в неявной форме F(f, у, У') = 0. Важным частным случаем таких систем являются системы с матрицей масс M(l, Y)Y'=F(t,Y), причем М (t, У) может быть как невырожденной, так и вырожденной. Для решения систем вида F(t, У, У') = 0 служит солвер odei5i, а системы с матрицей масс могут быть решены любым из солверов. Заметим, что область применения солвера ode23s ограничена только постоянными матри Глава Г Методы вычислений в MATLAB 317 цами, а в случае вырожденной матрицы необходимо прибегать к солверам odelbs и ode23t. Вырожденная матрица масс соответствует системе дифференциальноалгебраических уравнений, которая наряду с дифференциальными у'- f(t, у, и) содержит алгебраические связи g(z, у, w) = 0. Здесь f и g — заданные вектор-функции, а у и и — искомые вектор-функции. Такая система может быть решена в МАП АВ при условии, что ее индекс равен единице, т. е. матрица невырождена. При решении дифференциаль- но-алгебраических уравнений применяется их сведение к системе М Y' ~ F(t,Y) с вырожденной матрицей масс где I — единичная матрица, размер которой совпадает с длиной вектора неизвестных у, а остальные блоки нулевые и V = Если дифференциальные уравнения в системе дифференциально-ал1 ебраи-ческих уравнений не разрешены относительно производной, то для решения такой системы следует применять солвер odel5i. Рассмотрим сначала решение систем с вырожденной матрицей масс на часто приводимом примере, опубликованном Робертсоном, для иллюстрации решения жестких уравнений — нелинейную задачу химической кинетики. Одно из дифференциальных уравнений системы (Уз(г) = 3-107у2(г)2) заменено уравнением баланса. у{ (0 = "Wl (') + 1о4№ (')тз 0)1 720) = ОО4Л(/)-1О4у,(/)у/3(/)-3-1О7у2(/)2; /е [0,100], ^1(0) = !, у2(0) = 0, j3(0) = 0. (6.7) Примечание _ С некоторыми отличиями эта же задача приведена в демонстрационном пцимере из пакета MATLAB (функция ihbidae). 318 Часть II. Вычисления и программирование В нашем случае матрица масс постоянна и имеет вид: fl О 0^ М = 0 О 1 о 0 °, Для иллюстрации применения солвера odelSs при решении задач указанного класса написана файл-функция (листинг 6.24) без аргументов, с использованием вложенной функции для вычисления вектора F(t. У). График каждой функции выводится на свои оси, при этом автоматически масштабируется ось ординат для компоненты у2. ё Листинг 6.24. Решение системы дифференциальных уравнений Ё с матрицей масс function example_dae % Вложенная функция вычисления вектора f(x, у) function resid = rob(t, у) resid = zeros(3, 1); resid (1) = -0.04*y{l) + le4*y(2) *y(3) ,- resid (2) = +0.04«y(l) - le4*y(2)*y(3) - Зе7*у(2)л2; resid (3) = y(l) + y(2) + y(3) - 1; end % начальные условия. y0 = [1; 0; 0] ; % матрица масс m = diag([1, 1, 0]); % интервал интегрирования. xtime = [0 100]; % задание управляющей структуры (точность) options = odeset(‘RelToi', It 4, 'mass', m); % вызов солвера [t,yj = odelSs(@rob, xtime, yO, options); % вывод графиков решений subplot(3, 1, 1); plor(t, y(:, 1)); grid on legend ('y_{l)1 ) ; subplot(3, 1, 2); plot(t, y(:, 2)); Глава 6. Методы вычислений в МАУ ,АВ 319 grid on legend ('у_{2}*); subplot (3, 1, 3); plot(t, у(:, 3)1; grid on legend ('y_{3}‘, 4); end После выполнения файл-функции из листинга 6.24 получаются результаты, представленные на рис 6.15. Рис. 6.15. Решение задачи химической кинетики (6.7) Подробные сведения о настройках солверов для решения задач с матрицей масс приведены в справочной системе MATLAB. Управляющая структура позволяет задать кроме матрицы масс еще ряд опций, в частности: степень зависимости матрицы масс от неизвестных, расположение ее ненулевых элементов для задач большой размерности и информацию о вырожденности матрицы. В разд. Mathematics: Differential Equations: Initial Value Problem^ for 320 Часть II Вычисления и программирование ODEs and DAEs: Examples: Applying the ODE Initial Value Problem Solvers приведен пример уравнения в частных производных, которое методом прямых приводится к системе обыкновенных дифференциальных уравнений с матрицей масс. Обратимся теперь к решению задачи Коши для дифференциальных уравнений вида F(t, Y, У')“0, не разрешенных относительно старшей производной, при помощи солвера odeisi. Обращение к нему несколько отличается от случая рассмотренных выше солверов, поскольку во входных его аргументах должно быть задано значение YpO производной решения в начальный момент времени Y'ifo)-. [Т, Y] - odel5i(odefun, interval, YO, YpO, options) Смысл остальных его аргументов тот же самый: odefun — функция для вычисления вектор-функции F ; interval — отрезок, по которому производится интегрирование, или упорядоченный вектор значений независимой переменной, для которых следует найти решение; Y0— вектор начальных значений У’(/{)); options— управляющая структура. Моменты времени и найденное решение в них записываются в вектор-столбец т и матрицу Y. Возможен вывод результата и в структуру с полями х и у, которая в дальнейшем используется для вычисления решения в произвольной точке из отрезка интегрирования (см. разд. "Решение задачи Коши"этой главы). Возникает вопрос, откуда взять начальное значение для производной, которое не может быть произвольным, поскольку в начальный момент времени /(1 требуется выполнение условия совместности F(/o, У(/о), E'(t0)) = 0. Для приближенного удовлетворения этому условию служит функция decic. В достаточно общем случае обращение к ней выглядит следующим образом [YO.YpO] = decic (<->d<=fun, t0, YOInit, YOFlag, YpOInit, YpOFlag) н подразумевает, что заданы начальные приближения к к(г0) и У'(г0) соответственно в векторах YOInit и YpOInit. Каждому из них сопутствует свои флаг — векторы YOFlag и YpOFlag той же длины, они указывают компоненты векторов YOInit и YpOInit, которые могут изменяться при удовлетворении условия согласования. Для запрета изменения некоторой компоненты решения или производной следует установить элемент вектора флага с номером компоненты в 1, а для разрешения в 0. Действительно, не всегда допустимо произвольное изменение начальных значений. В задаче Коши вектор У(/о) задан и требуется найти подходящее К’(г0). Для ’того следует задать флаг YOInit, целиком состоящий из единиц. Если никакие компоненты векторов YOInit или YpOInit не фиксируются, то соответствующий флаг можно не задавать. Возвращаемые значения yo и Ypo приближенно удовлетворяют условиям совместности и могут служить входными аргументами солвера odelbi. Гпава 6, Методы вычислений в MATlAB 321 Примечание По умолчанию условия совместности удовлетворяются с относительной точностью IO 3. Для изменения точности следует обратиться к функции decic с седьмым входным аргументом — управляющей структурой options, предварительно сформировав ее при помощи odeset (поле RelTol отвечает за относительную погрешность). Для контроля выполнения условий совместности полезно вызвать функцию decic с третьим входным аргументом, в который заносится невязка, т. е, значение f(r0, У(г0), У'(/о)) для приближенно найденных К(г0), ^Оо)- Продемонстрируем использование солвера odeisi на примере уравнения Клеро: у = у г + h(y). Известно, чго у = Ct+h(C) есть общее решение этого уравнения, с ним мы и будем сравнивать получаемое приближенное решение. Рассмотрим задачу Коши для уравнения Клеро при h(s)=es: y = yt+ey у(0) = е, ге[0, 5] э с точным решением у = х + е. Поскольку это дифференциальное уравнение первого порядка, то неизвестной является всего одна функция, и при обращении к decic в качестве флагов используются числа YOFlag = 1 и YpOFlag = с (листинг 6.25). После выполнения функции decic полученные начальные значения для функции и ее производной выводятся в командное окно. Обратите внимание, что начальное значение функции не изменилось из-за того, что соответствующий флаг равен единице, а начальное значение производной найдено достаточно хорошо (точное значение равно единице) так, что невязка при удовлетворении условиям совместности имеет порядок 10~9. Вычисленные величины yd и УрО мы передаем в качестве входных аргументов солвера odeisi и сравниваем приближенное решение с точным (рис. 6.16). ^у.... W. ........................................-..о Листинг 6.25. Использование солвера od< >15х для решения уравнения Клеро Л I K»Vvi« Al - . ЧЧ • I Л I. - I. . • I • I < • И ...•• • I . - . I ••.... . . . . .... . fll .1 1 • > I < . .. III •«Vaal I *4 function klero tO = 0; % начальная точка отрезка интегрирования [0, 5] YOInit = exp(l); % заданное начальное условие YOFlag = 1; % начальное значение искомой функции не должно измениться % при удовлетворении условиям совместности 322 Часть II. Вычисления и программирование YpOTnit =0; % приближение для начального значения производной YpOFlag = 0; % начальное значение производной искомой функции может % измениться при удовлетворении условиям совместности format j ong е % Поиск начального значения производной, удовлетворяющего % условиям совместности [YO, YpO] - decic(@klerofun, tO, YOInit, YOFlag, YpOInit, YpOFlag) % Решение уравнения Клеро на отрезке [0, 5] [Т, Y] = odel5i(@klerofun, [tO 5], YO, YpO); % Построение графика приближенного решения p!ot(T, Y, ’o'); hold on % Построение графика точного решения exsol = inline ('х + exp(D'); fplotfexsol, [tO 5]) legend(1приближенное решение',’точное решение') function F = klerofun(t, Y, Yp) F = Y - Yp*t - exp(Yp); Рис. 6.16. Решение уравнения Клеро Глава 6. Методы вычислений в MATLAB 323 В случае системы дифференциальных уравнений схема решения принципиально не отличается от разобранного примера, только YO, YpO, YOInit, YpOInit, YOFlag и YpOFlag должны быть векторами, как и выходной аргумент функции для вычисления F(t, К, К'). Дополнительные возможности солвера odel5i, в том числе решение систем с заданными параметрами, и опции управляющей структуры описаны в справочной системе MATLAB (см. разд. MATLAB: Mathematics: Differential Equations: Initial Value Problems for ODEs and DAEs: Solver for Fully Implicit ODEs и следующий за ним, а так же станицы, посвященные функциям odeisi и decic). Предупреждение J При формировании структуры options некоторые параметры используются не так, как для остальных солверов. Например, по другому передается матрица Якоби с постоянными коэффициентами, а именно в массиве ячеек, содержащем две матрицы dF/dy и dF/dy. Работа с массивами ячеек описана в < wee 8. Мы рассмотрели решение задачи Коши для дифференпиалиных уравнений и систем, включая дифференциально-алгебраические уравнения и общий случай уравнений, не разрешенных относительно старшей производной. Обратимся теперь к другому типу дифференциальных уравнений — диф ференци-альным уравнениям с запаздывающим аргументом. Решение дифференциальных уравнений с запаздывающим аргументом В пакет МATI АВ входит солвер dde23 для решения задач, описываемых системами дифференциальных уравнений вида: = ...,y(t~Tk)), /е[а.А], (6.8) где y(t) — искомая вектор-функция; f — известная вектор-функция правой части системы; tj, т2,..., — моменты запаздывания (положительные числа). Для решения системы уравнений (6.8) требуется знать поведение решения для t <a , т. е. вектор-функцию предыстории S(/). Схема решения дифференциальных уравнений с запаздывающим аргументом в MATLAB состоит из следующих этапов. 1. Написание функции для вычисления правой части системы уравзений, входными аргументами которой являются не только t и у, но и значения компонент решения в моменты времени т,, т2 ,..., . 324 Часть II. Вычисления и программирование 2. Написание функции для предыстории с единственным входным аргументом t (если вектор-функция предыстории является постоянной, то эта функция не является обязательной). . 3. Вызов солвера dde23 с указанием исходных данных: функции правой части системы, моментов запаздывания Т], т2,..., функции предыстории (или постоянного вектора) и границ отрезка [«, fe]. 4. Визуализация результата, который солвер dde23 возращает в структуре. Разберем решение дифференциальных уравнений на следующем модельном примере: требуется найти решение системы на отрезке [0, 4] с предыстрои-ей £(/): Л =^(№Ю + .Vi (/-1-5)+ У2(/-2)); z inw ч S(/) = . (6.9) У2 = ~(у> (') + >) (г-2) + .у3(/-0.5)); lcos™ J Начнем с программирования функции ddefun. Ее входными аргументами должны являться: время t, вектор у компонент решения и матрица Z, столбцы которой содержат значения компонент решения в моменты запаздываний. В нашем случае т( =0.5, т2=1.5, т3=2 и матрица Z имеет следующий вид: Z=fy,(/-T|) -Vi(/-T2) лО-'Сз)' Уг0-т2) В функции ddefun мы ввели вспомогательные переменные для вектор-функции у(л), вычисленной в моменты запаздываний (листинг 6.26). ....................................-........................... Листинг 6.26. Файл-функция adetun для правой части системы уравнений (6.9) function F - ddefunft, у, Z) % Вычисление привой части системы запаздывающих дифференц. уравнений % t - время % у - вектор со значениями компонент у(1), у(2), ..., у(к) % Z - матрица со значениями компонент в момент запаздываний: % Z (:, j ) = у (t - tau(j)), j = 1, 2, ... k Гпава f голы вычислений в MATLAB 325 Yl = Zf:,l); % вектор значений компонент для t = tau(l) Y2 = Z(:,2) ; % вектор значений компонент ДЛЯ t = tau(2) Y3 = Z(:,3); % вектор значений компонент для t = tau(3) F = [pi/3*(y(2) + ¥2(1) + Y3(2)) -pi/3*(y(l) +¥3(1} +¥1(2})J; Перейдем теперь к написанию функции ddehistory с предысторией решения. В нашем случае она простая, ее текст приведен в листинге 6.27. ......................„............................................. Листинг 6.27 Файл-функция ddehx tory предыстории решения ................................................................................ . . ...... Eunction S = ddehistory(t) % вычисление вектора комп энент предыстории решения S = [sin(pi*t) cos(pi*t)]; Осталось вызвать солвер dde23, графически отобразить решение и проанализировать его. В отличие от солверов для решения систем обыкновенных дифференциальных уравнений, солвер dde23 возвращает решение только в одном виде — всгруктуре: » sol = dde23(Sddefun, [0.5 1.5 2], @ddehistory, [0 4]); Содержимое структуры sol следующее: □ sol.x— вектор-строка со значениями независимой переменной t, для которых найдено приближенное решение; □ sol.у— массив со значениями у(/), каждая строка которого содержит соответствующую компоненту решения; □ sol. ур — массив со значениями у'(/), каждая строка которого содержит первую производную от соответствующей компоненты решения. При анализе решения примите во внимание, что точным решением модельной задачи являются функции .V|(/) = sin7ix и у2 (i) = cosгос. Постройте графики каждой компоненты точного и приближенного решения на своей паре осей в одном графическом окне и сравните их. Имеет смысп написать файл-функцию, включив в нее и вызов солвера, и все вспомогательные функции (листинг 6.28). Листинг 6.28. Файл-функция ddetest ........................ 1 г...... ..............Л......-........................................................................ .лЛгЖ.'.......Я........... function ddetest % вызов солвера dde23 326 Часть II. Вычисления и программирование sol = dde23 (@ddefun, [0.5 1.5 2],@ddehistory, [0 4]); figure subplot(2, 1, 1) % график приближенного значения первой компоненты plot(sol.х, sol.y(l, :>, 'о') % задание первой компоненты точного решения yl = inline(1 sin(pi*t)'}; hold on % построение графика первой компоненты точного значения fpiot(yl, [0,4], ’г') title('Первая компонента решения') legend('приближенное значение','точное значение’) subplot(2, 1, 2) % график приближенного значения второй комп эненты plot(sol.х, sol.yd, :), ' + ') % задание первой компоненты точного решения у2 = inline('cos(pi*t)'); hold on s построение графика второй компоненты точного значения rplot(y2, [0, 4], 'г') title('Вторая компонента решения') legend(1 приближенное значение', 'точное значение') % function S = ddehistory(t) % вычисление вектора компонент предыстроии решения S = [sin(pi*t) cos(pi*t)]; % function F = ddefunft, y, Z) % Гычисление правой части системы запаздывающих дифференц. уравнений % t - время % у - вектор со значениями компонент у(1), у(2),... , у(к) % Z - матрица со значениями компонент в момент ян па здывя ний; % Z(:, j) = y(t - tau(j)), j = 1, 2, ..., k Yl = Z(:, 1); % вектор значений компонент для t = tau(1) Y2 = Z(:, 2); % вектор значений компонент для t = tau(2) Y3 = Z(:, 3); % вектор значений компонент для t = tau(3) F = [pi/3*(y(2) + Y2(l) + Y3(2)) -pi/3*(y(l) + Y3(l) + Yl(2))]; Гпава 6. Методы вычпса в MATLAB 327 После вызова ddetest получаются 1 рафики, приведенные на рис. 6.17. Они свидетельствуют о правильно найденном решении. Первая компонента решения Вторая компонента решения + приближенное значение ------точное значение Рис. 6.17. Решение дифференциального уравнения (6.9) с запаздывающим аргументом Для ньписления значений приближенного решения в произвольных точках отрезка следует применить функцию deval так же, как и в случае рассмотренной выше задачи Коши. Обсудим теперь задание параметров вычислительного процесса. Управляющая структура формируется функцией ddeset, использование которой аналогично odeset при решении задачи Коши для систем обыкновенных дифференциальных уравнений. Солвер dde23 позволяет задавать относительную и абсолютную точность (по умолчанию Ю3 и 10 6 соответственно), способ контроля точности —- по норме или покомпонентно, начальный и максимальный шаг, например: » options = ddeset(1RelTol', le-5, 'AbsTol', le-8) » sol = dde23(Gddefun, [0.5 1.5 2],©ddehistory, [0 4], options) 328 Часть II. Вычисления и программирование Отслеживание событий и обработка получаемых в процессе решения значений, в том числе и визуализация приближенного решения, требуют привлечения свойств Events, OutputFcn и OutpucSel. Для вывода суммарной информации о вычислительном процессе следует воспользоваться свойством Stats. При решении дифференциальных уравнений с запаздывающим аргументом существенным обстоятельством является потеря непрерывности производных решения низких порядков. Обычно разрывы возникают уже в начальной точке отрезка и повторяются затем через моменты времени, совпадающие с запаздываниями, но для производных более высоких порядков. Поэтому набор свойств солвера ode23 пополнен опцией Jumps, значением которой должен быть вектор с координатами разрывов как предыстории, так и коэффициентов дифференциальных уравнений. Начальным значением искомой вектор-функции у(«) по умолчанию является S(o). Вообще говоря, начальное значение может быть отличным от5(я), в этом случае поле initialY управляющей структуры должно содержать заданный вектор у (а). Примеры решения дифференциальных уравнений с запаздывающим аргументом и их обсуждение приведены в справочной системе MATLAB в пунктах разд. Mathematics: Differential Equations: Initial Value Problems for DDEs. В завершение этого раздела обратимся к несколько измененной модели Лотки—Вольтерры. в которой увеличение количества хищников происходит по истечении времени т после встречи хищника и жертвы (решение уравнений Лотки—Вольтерры описано выше в этой главе). Этот процесс описывается системой дифференциальных уравнений с запаздывающим аргументом У1 = У'2 (О + f' У| (' - т)у2 0 “ 4 Возьмите т — 0.1, а значения коэффициентов те же, что и для рассмотренных выше уравнений Лотки—Вольтерры (6.5): Р = 0.8, R = 1, р = г = 0.001. Будем считать предысторию постоянной— ЮОи жертв и 1100 хищников. Запрограммируйте функции- LotVolDel—для вычисления правой части системы и LotVolHis — для предыстории решения, причем предусмотрите возможность указания значений параметров при вызове солвера после входного аргумента options. Решите систему дифференциальных уравнений с запаздыванием на временном отрезке [0. 50] и сравните полученный ре- Глава б. Методы вычислений в MATLAB 329 зультаз с решением аналогичной системы без запаздывания. При решении систем установите одинаковую относительную точность, к примеру 10 5. Тексты функций приведены в листинге 6.20, а получающийся после выполнения файл-функции 1 рафик — на рис. 6.18. При вызове dde23 постоянную предысторию можно было бы задать вектором вместо указателя на функцию LotVolHis. Мы использовали функцию для того, чтобы подчеркнуть необходимость дополнительных входных аргументов в случае, когда правая часть системы дифференциальных уравнений зависит о г параметров. Разумеется, этот же пример можно выполнить и с помощью вложенных или анонимных функций. i Листинг 6.29. Файл-функция для сравнения двух моделей function LotVol2(Р, р, R, г) % решение системы дифференциальных уравнений с запаздыванием options = ddeset('RelTol', 1.0е-05); % установка относительной точности % вызов солвера с указанием коэффициентов системы sol = dde23(@LotVolDel, 0.1, @LotVolHis, [0 50], options, P, p, R, r); plot(sol.у(1, sol.у(2, :), ':') % вывод графика приближенного решения % решение системы дифференциальных уравнений без запаздывания options = odeset('RelTol', 1.0е-05) % установка относительной точности % вызов солвера с указанием коэффициентов системы [Т, Y] = ode23s(@LotVolPar, [0 50], [1000 1100], options, Р, р, R, г); hold on plot(Y(:, 1),Y(:, 2)) % вывод графика приближенного решения % вывод пояснений на график title('Модели системы "хищчик-жортва"') xlabel('жертвы') у label(1 хищники') legend(’c запаздыванием', 'без запаздывания’) % подфункция LotVolDel для вычисления правой части системы (6.10) function F = LotVolDel(t, у, Z, Р, р, R, г) F = [Р”у(1) - р*у(1)*у(2); -R*y(2) + r*Z(1)*Z(2)] ; % подфункция LotVolHis для вычисления предыстории решения function Н = LotVolHis(t, Р, р, R, г) Н = [1000; 1100]; 330 Часть II. Вычисления и программирование Рис. 6.18. Решение уравнения Лотки Вольтерры (6.10) с запаздывающим аргументом Решение граничных задач В данном разделе на простых примерах иллюстрируются возможности решения граничных задач для обыкновенных дифференциальных уравнений и систем дифференциальных уравнений первого порядка в MATLAB при помощи солвера t>vp4c. Описаны возможности солвера для решения задач с особенностями и нахождения неизвестных параметров дифференциальных уравнений. Схема решения Рассмо грим решение граничных задач на примере обыкновенного дифференциального уравнения второго порядка. Требуется найти функцию у(х), удовлетворяющую на отрезке [a, Z>] дифференциальному уравнению / = /(*> у, у) и граничным условиям (X-y(a)-t ₽ У(я) = A, y-y(bj + &-y'(b^-B. Гпава 6 Mt тоды вычислений в MATLAB 331 Здесь а, ₽, у, 5, А, В — заданные числа. Решение этой задачи состоит из следующих этапов. 1. Преобразование дифференциального уравнения второго порядка к системе двух уравнений первого порядка. 2. Написание функции для вычисления правой части системы. 3. Написание функции, определяющей граничные условия. 4. Формирование начального приближения при помощи специальной ФУНКЦИИ bvpinit. 5. Вызов солвера bvp4c для решения граничной задачи. 6. Визуализация результата. Первые два этапа выполняются практически так же, как и при решении задачи Коши (см. разд. "Решение задачи Коши" данной главы). Введение вспомогательных функций у] (х) и у2 (х) приводит к системе уравнений первого порядка относительно них: Ji -У2> ,У2=/(Х’У1’У2)- Функция правой части системы зависит от х и вектора у, состоящего из двух компонент, у (1) соответствует уь а у(2) — у2, и программируется так же, как при решении задачи Коши. При постановке граничных условий для вспомогательных функций требуется преобразовать их так, чтобы в правых частях стояли нули: а-у](а) + Р-у2(а)-Л=О, y-y1(h) + 5-y2(h)-B = O. Функция, описывающая граничные условия, зависит от двух аргументов — вектороь уа и yb и имеет следующую структуру (листинг 6.30). function g = bound(ya, yb) g = [alpha*ya(l) + beta*ya(2) - A; gaitina*yb(1) + delta*yb(2)]; Вмес го alpha, beta, gamma, delta, А и в следует подыавить заданные числа. Солвер bvp4c основан на методе конечных разностей, т. е. получающееся решение есть векторы значений неизвестных функций в точках отрезка (в 332 Часть II. Вычисления и программирование узлах сетки). Выбор начальной сетки и приближения может оказать в зияние на решение, выдаваемое солвером t>vp4c. Для задания начальной сетки и приближения предназначена функция bvpinit, обращение к которой в самом простом случае выгля шт следующим образом; initsol = bvpinit(начальная сетка, начальное приближение к решению) Начальная сетка определяется вектором координат узлов, упорядоченных по возрастанию и принадлежащих отрезку [</- Z>]. Если имеется априорная информация о решении, то разумно среди точек начальной сетки указать те. в которых решение сильно изменяется. Формирование равномерной сетки целесообразно производить функцией linspace: X = linspace(а, b, п) возвращающей вектор х из п равноотстоящих узлов между а и ь, включая границы. Заданная сетка модифицируется солвером в процессе решения для обеспечения требуемой точности. Постоянное начальное приближение задается вектором из двух элементов для функций у^х), Jh(x). Начальное приближение может зависеть от х, в этом случае требуется запрограммировать функцию, которая по заданному v возвращает вектор из двух компо-ненз’ со значениями Vj(x), у2(х), и поместить указатель на нее во втором входном аргументе bvpinit. В результате работы bvpinit генерируется структура initsol с информацией о начальном приближении. После определения начального приближения вызывается солвер bvp4c, входными аргументами которого являются указатели на функции правой части системы и граничных условий, начальное приближение и, при необходимости, управляющая структура с параметрами вычислительного процесса. Управляющая структура формируется при помощи функции bvpset. Солвер bv₽4c возвращает единственный выходной аргумент— структуру с информацией о расчетной сетке, значения искомой функции и ее производной. Солвер bvp4c так же, как и солвер dde23 для дифференциальных уравнений с запаздыванием, позволяет получить результат только в виде структуры, в отличие от солверов для задачи Коши (работа со структурами подробно описана в главе &). Для вычисления значений приближенного решения в произвольных точках отрезка следует применить функцию devai так же, как и в случае рассмотренной выше задачи Коши. В следующих разделах процесс решения граничных задач разобран на простом модельном примере, кроме того, приведены возможности солвера bvp4c для исследования более широких классов граничных задач. Гпава 6. Mtscati вычислений в МА TlAB 333 Простой пример граничной задачи Требуется решить граничную задачу для обыкновенного дифференциального уравнения второго порядка y"--sinx, у(0) = 0, у'(117г/2)+у(11л/2) = -1. При помощи солвера bvp4c и сравнить полученное решение с точным у = sin х. Система дифференциальных уравнений первого порядка, соответствующая исходному уравнению, и граничные условия для нее находятся просто: ITi-Ti- у.(0) = 0, у2(11л/2)+у|(1171/2) + 1 = 0. (6.11) [_y2-~s|nx; Написать функцию rside для системы уравнений также не представляет большого труда, ее текст приведен в листинге 6.31. Как было указано в предыдущем разделе, функция для граничных условий имеет два входных аргумента. Каждый аргумент является вектором значений неизвестных функций у, и у2 в начальной и конечной точке промежутка. Поэтому функция граничных условий должна быть такой, как bound в листинге 6.31. Решение граничной задачи оформите в виде файл-функции, в которой необходимо’ 1. При помощи bvpinit задать начальную сетку на отрезке [О,11л/2], например, из 10 узлов, и постоянное начальное приближение: yj(x) = l, у2(х) = 0. 2. Вызвать солвер bvp4c и получить приближенное решение. 3. Отобразить 1рафически приближенное решение, извлекая нужные компоненты из структуры, возвращаемой солвером. 4. Добавить график точного решения y = sin(x) на отрезке [0, 11л/2]. Текст файл-функции содержится в листинге 6.31. ° • ' ................................... ; листинг 6.31. Файл-функция для решения граничной задачи (6.11) function boundproblem % формирование начальной сетки и постоянного приближения yl = 1, у2 = О nieshin.lt - linspace(O, ll*pi/2, 20); yinit = [10] 334 Часть II. Вычисления и программирование initsol = bvpinit(meshinit, yinit); % вызов солвера sol = bvp4c(@rside, @bound, initsol); % использсвание полей x и у структуры sol для построения решения т в sol.х содержатся координаты сетки % в sol.у матрица sol.yll, :) соответствует значениям функции yl в sol.xi:} % sol.у(2, :) соответствует значениям функции у2 в sol.xf:) plot(sol.x, sol.yd, "k.') % вывод графика точного решения для сравнения hold on fpiot(@sin, [0 ll*pi/2]) title("Решение граничной задачи солвером bvp4c") legend('приближенное решение', "точное решение") % функция rside для правых частей системы уравнений (6.11) function f = rside(х, у) f = [у (2) ; -sin(x) ] % функция bound граничных условий function f = bound(ya, yb) f = [ya(l); yb(2) + yb(l) + 1] Рис. 6.19. Сравнение приближенного и tomhoi о решений I раничной задачи (6.11) Гпава 6, Методы вычислений в MATLAB 335 Получающиеся графики приближенного и точного решений исходной задачи приведены на рис. 6.19, они свидетельствуют о том, что для прос гых задач солвер bvp4c дает хорошие результаты. По умолчанию решение найдено с относительной точностью 10 3 и абсолютной Ю”6 по невязке. Задание точности вычислений, ряда других опций солвера bvp4c и решение более сложных задач обсуждается в следующих разделах. Возможности солвера bvp4c, управление -вычислениями Солвер bvp4c позволяет решать граничные задачи для систем обыкновенных дифференциальных уравнений произвольного порядка п У-fix, у), хе[а,г>], g(y(a), y(b)) = 0. Здесь у — неизвестная вектор-функция; g — вектор-функция граничных условий. Правило программирования функции для вычисления правой части системы и вектор-функции граничных условий остается тем же, что и в случае системы второго порядка, рассмотренной в предыдущем разделе. Точность решения контролируется при помощи двух опций управляющей структуры RelTol — для относительной точности и AbsTol — для абсолютной. Сама управляющая структура генерируется функцией bvpset Options = bvpset( RelTol', 1.0e-05, 'AbsTol',1.Oe-07) и задает ся в качестве четвертого входного аргумента солвера bvp4c. Абсолютная точность участвует в оценке каждой компоненты вектор-функции невязки т(х) = у’(х)_/(х,у(Л)), где у(х)— приближенное решение, и может быть числом, либо вектором из п элементов. Параметр RelTol используется для оценки интегральной нормы ]| || компонент невязки ?• на каждом из участков расчетной сетки. Вычисления останавливаютс я при выполнении условия: Ik- / max{|^| , AbsTol (i) / RelTol} || < RelTol. Возможна ситуация, когда решение граничной задачи найдено, но по каким-то причинам требуется вычислить его с большей точностью. В этом случае в качестве начального приближения для солвера bvp4c допускается указание полученной структуры с приближенным решением. Например, в примере предыдущего раздела было получено решение с установленной по умолчанию точностью: sol = bvr>4c(@rside, ©bound, initsol); 336 Часть II. Вычисления и программирование Для нахождения решения, скажем, с относительной точностью 10~7 достаточно сформировать управляющую структуру options = bvpset('RelToi', le-7); и обратиться к солверу sol = bv₽4c(@rside, @bound, sol, options); Солвер может прервать вычисления, не достигнув заданной точности, поскольку по умолчанию число узлов расчетной сетки не должно превышать целой части от 1000/п. При появлении такого сообщения следует увеличить максимально допустимое число узлов, установив подходящее значение для параметра Nmax управляющей структуры. В алгоритме солвера bvp4c частные производные функций g и f аппроксимируются конечными разностями. Использование аналитических выражений для них может повысить эффективность вычислений. В случае системы линейных уравнений матрица Якоби правой части системы постоянна и содержащий ее массив задается в качестве значения свойства FJacobian. Для нелинейных систем потребуется запрограммировать функцию, так же, как и в случае решения задачи Коши (решение задачи Коши для систем обыкновенных дифференциальных уравнений описано выше в згяой глдее). Функция, вычисляющая производные вектор-функции g(ya, уь) граничных условий dg/da , dg/dyb , должна иметь заголовок function [dgdya, dgdyb] = boundjac(ya, yb) и по заданным y(«) и y(b) возвращать векторы dg/dyh. Солвер bvp4c будет вызывать boundjас для нахождения частных производных, если свойству BCJacobian управляющей структуры установить значение @bcundjac. Ускорение работы солвера возможно за счет специального способа программирования функции для правой части системы. В примере предыдущего раздела (листинг 6.31) функция rside по заданной паре значений л и у() вычисляла ./ ( *, у(х)). Альтернативный вариант интерфейса предполагает возможность вычисления матрицы F~ f(X, у(Х)) для заданного вектора значений независимой X переменной и матрицы у(X). Модифицированная функция приведена в листинге 6.32. 1 Листинг 6.32. Векторизованная файл-функция для правой части системы (6.11) function F = rsidevect. (X, Y) % Вычисление правой части системы дифференциала ных уравнений Гпава L Методы вычислений в MATLAB 337 % для вектора значений X. Возвращается матрица F, каждый столбец % которой F(:, j) есть f(x(j), y(x(j))). L = length(X); % определение количества значений независимого аргумента F = zeros(2, L); % создание нулевой матрицы F подходящего размера % вычисление компонент векгор-4-УНКЦИИ правой части для всех значений % независимой переменной F(l, :)= Y(2, :); % вычисление первой компоненты F(2, :) = -sin(X); % вычисление второй компоненты Для переключения солвера bvp4c на использование векторизованной функции служит свойство vectorized управляющей структуры, которое по умолчанию равно 'off. В листинге 6.31 следует заменить подфункцию rside на rsidevect и изменить обращение к солверу: options = bvpset('Vectorized', 'on'); sol = tvp4c(Srsidevect, ©bound, initsol, options); Суммарная информация о вычислениях— количество узлов расчетной сетки, максимум невязки и число обращений к функциям правой части системы и граничных условий — выводится в командное окно, если значением свойства stats является 'оп'. Класс задач, решаемых солвером bvp4c, включает в себя граничные задачи для систем обыкновенных дифференциальных уравнений с неизвестными параметрами и систем с вырождающимися коэффициентами. В следующих двух разделах демонстрируется решение этих задач на простых примерах. Граничные задачи с неизвестными параметрами Солвер bvp4c так же, как и солверы для задачи Коши и уравнений с запаздыванием, позволяет решать граничные задачи для систем обыкновенных дифференциальных уравнений с параметрами. Однако в случае граничных задач параметры могут быть как известные, так и подлежащие определению в процессе вычислений. Рассмотрим общую постановку граничной задачи с подлежащими определению параметрами. Требуется найти вектор-функцию у(л) и вектор параметров р, удовлетворяющие на отрезке La, />] системе дифференциальных уравнений у — f(x,y, р) и граничным условиям: g(y(a), т(^)’ р) = 0- Решение таких задач предполагает указание начального приближения как для искомой вектор-функции, так и для всех параметров. Для этого следует инициализировать структуру с начальным приближением, задав три входных аргумента: meshinit — массив узлов начальной сетки, yinit — начальное приближение для искомой вектор- 338 Часть //. Вычисления и прогр 1ммир.свач..е функции (постоянный вектор или указатель на функцию) и parinit — вектор стартовых значений параметров. solinit - bvpinit(meshinit, yinit, parinit) Функция bvpinit создает структуру solinit, поле pdramsters которой CO-держит начальные приближения для неизвестных параметров. При программировании функции для вычисления правой части системы и граничных условий следует предусмотреть возможность передачи значений параметров в третьем входном аргументе— векторе. Заголовки функций должны иметь вид: function f = rsidepar(x, у, par) И function f = boundpar(ya, yb, par) В случае успешного завершения вычислений солвер bvp4c возвращает структуру SO) » sol = bvp4c(@rsidepar, Sboundpar, solinit) Узлы сетки записаны в sol.x, приближение к вектор-функции в sol.у, а найденное значение параметров в sol.parameters. Разберем поиск неизвестных параметров граничных задач на модельном примере с одним параметром. Требуется найти функцию и(х) и число X, удовлетворяющие на отрезке [0, л] дифференциальному уравнению н' + 2Хи' + 2Х2н = 0 и граничным условиям и(0) = 0, л(л) = О. Такого класса задачи часто возникают при определении собственных чисел и собственных функций дифференциальных операторов. Приведенная выше задача, очевидно, имеет тривиальное решение н(х)~0, не представляющее практического интереса. Как правило, имеется целый спектр параметров, при которых существует ненулевое решение и(х), определенное с точностью до мультипликативной константы. Наша задача не полностью определена, поскольку если ы(х) — решение, то с-н(х) также является решением для любой константы с. Следовательно, необходимо подчинить искомую вектор-функцию некоторому нормировочному условию, например: и'(0) = 1. Введем обозначения у5(х) = и(х), у2(х) = и'(х) и перейдем от дифференциального уравнения второго порядка к системе обыкновенных дифференциальных уравнений первого порядка с соответствующими граничными условиями Jl(0) = 0, Л(л) = 0, №(0)-1 = 0. (6.12) Глава 6. Методы вычислений в MATLAB 339 Примечание В такой постановке эту задачу можно трактовать, как задачу Коши с дополнительным условием на другом конце для определения параметра При этом нельзя гарантировать существование решения. Создадим теперь функции rsidepar для вычисления правой части системы и boundpar для граничных условий в соответствии с приведенным выше правилом (листинг 6.32). Важно, что хотя граничные условия не зависят от параметра, все равно третий аргумент par должен формально присутствовать в списке входных аргументов функции boundpar. Осталось запрограммировать функцию для определения начального приближения, которое существенным образом влияет на результат вычислений для задач с неизвестными параметрами. В нашем примере хорошим начальным приближением может оказаться yt(x) = sinx (и, соответственно y2(x) = cosx), поскольку оно точно удовлетворяет всем трем граничным условиям. Текст функции yinit приведен в листинге 6.33. Теперь сгенерируйте структуру solinit с информацией о начальном приближении, выбрав сетку с 10 равноотстоящими узлами на промежутке [0, п] и взяв Х = 0.8 в качестве стартового значения параметра. Вызовите солвер bvp^c. отобразите графически первую компоненту вектор-функции решения (т. е. искомую функцию м(х)) и найдите параметр Л. Текст файл-функции boundparproblem, осуществляющей перечисленные действия, приведен в листинге 6.33. В качестве выходного аргумента она возвращает значение искомого параметра. : листинг 6.33. Файл-функция для решения граничной задачи i с пграметро-л (612) * . «•••• *»*» . ,»». ..... , .... ... .. . .*. .. >.... • • .. .S- . • -•>- • •* function par = boundparproblem Meshinit = linspacefO, pi, 10); % генерация начальной сетки Pinit = 0.8; % стартовое принижение для параметра £ генерация структуры с информацией о начальном приближении solinit = bvpinit(meshinit, @yinit, pinit); % вызов солвера sol = bvp4c(Srsidepar, @boundpar, solinit); % занесение в par найденного значения параметра par - sol.parameters 1 З.и во 340 Часть II Вычисления и программирование % построение графика первой компоненты найденной вектор-функции plot (sol .х, sol.yd,:), 'о') % % функция правой части системы дифференциальных уравнений (6.12) function f = rsidepar(x, у, par) f = ly(2); -2*par*y(2) - 2*рагЛ2*у(1)]; end % функция граничных условий function f = boundpar(ya, yb, par) f = [ya(D; yb(l); ya(2) - 1]; end % функция начального приближения function f = yinit(x); f = [sin(x); cos(x)]; end end В результате работы файл-функции получается А. = 0.99999361754175 (т. е. А = 1 с достаточной степенью точности) и функция н(х), представленная на рис. 6.20. Рис. 6.20. Решение граничной задачи с параметром (6.12) Гпава 6. Методы вычислений в МATI.АВ 341 В нашей модельной задаче известно точное решение. Значениями X. могут быть целые числа, а соответствующими функциями и(х) являются Добавьте график функции н(х) = е vsinx, отвечающей Л-1, к графику приближенного решения и убедитесь, что оно вычислено верно. Найдите еще несколько значений Л и соответствующих функций п(х), задавая в качестве стартового приближения к параметру числа, близкие к целым: 2.3. 3.2, 4.2, 5.1. Солвер возвращает хорошие приближения к точным (целым) значениям искомых параметров. Заметьте, что с увеличением значения параметра возрастает число смен знака соответствующей ему функции и (х) на отрезке [0, л]. Обсудим теперь влияние начального приближения к вектор-функции. Например, исходный выбор yj(x) = sinx, y2(x) = c°sx не позволяет определить значение параметра даже для хорошего начального приближения 6.001 к точному значению 6 параметра Л. Следовательно, необходимо каким-то образом выбрать другое начальное приближение к вектор-функции. Конечно, точное решение свидетельствует о том, что хорошим начальным приближением может служить (х) = sin 6х, _y2(x) = 6cos6x. Но если бы точное решение было неизвестно, то можно было бы воспользоваться нашим наблюдением об увеличении количества участков смены знака решения и(х) при возрастании Л. Модифицируйте функцию yinit и найдите решение для стартового значения 6.2 параметра Л. Как было отмечено в начале этого раздела, в общем случае граничная задача может содержать как неизвестные, так и известные параметры. Наличие неизвестных параметров приводит к более сложной задаче с вычислительной точки зрения, в то время как присутствие известных параметров требует только использования расширенного интерфейса солвера bvp4c и функций, к которым он обращается. В общем случае с неизвестными и известными параметрами заголовки функций граничных условий и правой части системы дифференциальных уравнений должны иметь вид: function Е = rsidepartx, у, par, pl, р2,—) res = boundpar(ya, yL, par, pl, p2,...) end 342 Часть II. Вычисления и программировг чие где par — вектор неизвестных параметров, а аргументы pl, р2,... являются заданными параметрами. Если неизвестных параметров нет, то заголовки функций граничных условий и правой части системы дифференциальных уравнений упрощаются: function f = rsxdcpar(х, у, pl, р2,...) res = boundpar(ya, yb, pl, p2,...) end При вызове солвера значения известных параметров pl, р2, ... следует указать в списке входных аргументов, начиная с пятой позиции после управляющей структуры. » sol - bvp4c(odefun, befun, solinit, options, pl, p2...) Разумеется, в случае отсутствия подлежащих вычислению параметров не требуется подбирать приближение для них при инициализации структуры с начальным приближением функцией bvpinit. Эффективность вычислений может быть повышена за счет задействования аналитических выражений элементов матрицы Якоби правой части системы дифференциальных уравнений и частных производных вектор-функции граничных условий. Для получения информации об интерфейсе соответствующих функций обратитесь к описанию функции bvpset, воспользовавшись, например, индексным поиском в справочной системе MATLAB. В следующем разделе приведен еще один класс задач — граничные задачи с вырождающимися коэффициентами — решение которых может быть получено при помощи солвера bvp4c. Решение задачи с особенностью на границе Солвер bvp4c позволяет решать граничные задачи для дифференциальных уравнений с вырождающимися коэффициентами при условии, что они эквивалентны системе дифференциальных уравнений первого порядка у =—5у + /(х,у), xg[O, й|, Ь>0 с граничными условиями g(y(O), j'(fe)) = O. При этом матрица 5 должна быть постоянной и удовлетворять необходимому условию существования непрерывного решения: 5_у(0) = 0. Возможна и более общая постановка граничной задачи, включающая неизвестные параметры, которые могут входить как в вектор-функцию f, так и в вектор-функцию граничных условий g. Гпава 6. Методы вычислений в MATLAB 343 Последовательность действий при исследовании вырождающихся задач в целом схожа с решением рассмотренных выше классов граничных задач. Отличие состоит в том, что функция правой части системы должна вычислять только f(x, у), а матрица S передается солверу в качесзве значения свойства Singula г Те rm управляющей структуры. Разберем решение вырождающихся граничных задач на модельном примере. Требуется найти решение уравнения на отрезке [0,2], удовлетворяющее граничным условиям: н'(0) = 0, w(2) = -7. Легко убедиться, что точным решением является функция 1-х3. Преобразуйте исходную задачу к граничной задаче для системы уравнений первого порядка, введя новые функции у, (л) = и (х), у ] (л ) = 0: к](2)+7 = 0; , 2 / , , ' (6.13) У2 = -У1 -2Т1 + 2(1 -х ); |у2(0) = 0. Запись системы уравнений в векторном виде позволяет получить матрицу 5 и вектор-функцию f (х, у): , 1 , . Го оА . . (у2 У У =—Sy + f(x,v), S = , f(x,y)= / , j j j, о 2 -2yj+2(i-x3) ’ 4 7 k v 'j Полученная задача входит в класс вырождающихся граничных задач, которые могут быть решены при помощи солвера bvp4c. Действительно, матрица 5 обеспечивает выполнение условия 5 у (0) = 0, т. к. у2 (0) = 0. Запрограммируйте функцию rsbside для вычисления /(х, у) и функцию sbouna граничных условий. Определите подходящее начальное приближение, например, постоянное у0 = [-7, 0], для которого 5у0 - 0. Задайте исходную сетку на отрезке [0, 2] из пяти равноотстоящих узлов и решите задачу с относительной точностью 10-6. Сравните графически полученное решение с точным, так как это сделано на рис. 6.21. В случае возникновения затруднений воспользуйтесь листингом 6.34. 3J4 Часть II Вычисления и программирование Рис. 6.21. Сравнение приближенного решения вырождающейся граничной задачи с точным . Листинг 6.34. Файл-функиия для решения вырождающейся граничной I задачи (6.13)............................... ’....I_____ Ъ function SingularProblem S = [00; 02]; % Задание матрицы S у0 = [-7 0]; % Определение начального приближения meshinit = linspace(0, 2, 5); % Задание начальной сетки % Формирование структуры с начальным приближением solinit = bvpinit(meshinit, у0); % Формирование управляющей структуры options = bvpset(1SingularTerm', S, 'RelTol*, le-6) % Вызов солвера sol - bvp4c(©rsbside, ©abound, solinit, options) % Построение графика nej вой компоненты решения plot(sol.x, Sol.y(l,:), 'or'); % Добавление графика точного решения и легендь. fun = inline!'1 - х.л3'); hold on fpiot(fun, [02]) Гпава 6 Методы вычислении в MATLAB 345 legend(’приближенное решение', 'точное решение') % % функция для вычисления f(х, у) function f = rsbside(x, у) f = [у (2) -2*у{1) + 2*(1 - х.Л3}]; % % функция граничных условий function g = sbound(ya, yb) g = [ya(2} yb(l) + 7]; Задания для самостоятельной работы l. Вычислите интеграл от функции cos(x->/2)e2sinjc-l по промежутку между ее двумя соседними корнями, принадлежащими отрезку [0,4]. 2. Вычислите интеграл от функции sinx —х2 cosx = 0 по промежутку между ее локальным максимумом и локальным минимумом, абсциссы которых принадлежат отрезку [-5, 0]. 3. Найдите корень уравнения f (г) = 0.1, если /(z) = jxtg2xdx. о 4. Решите систему дифференциальных уравнений для хе [0,5]: У2 (*) = ~у2 (х - о.5)+(х -1); S!(x) = sinx + 0.1; S2 (х) = х-2 J46 Часть II. Вычисления и программирование и для полученного решения вычислите: • интеграл по всему промежутку от (х, • корни уравнения у, (х) = -1. 5. Реши ге дифференциальное уравнение для хе [0, 7]: 6. у* + 3у-O.ly2 = 2sinx, у(0) = 0.02, ух(0) = 1 и для полученного решения найдите все локальные максимумы и минимумы у(х). Глава 7 Управляющие конструкции языка программирования Файл-функции и файл-программы, которые вы создавали при чтении двух предыдущих глав, являются самыми простыми примерами программ. Все команды MATLAB., содержащиеся в них, выполняются последовательно. Для решения многих более серьезных задач требуются программы, в которых действия повторяются циклически, а в зависимости от некоторых условий выполняются различные части программы. В данной главе описаны управляющие конструкции языка программирования MATLAB, которые могут быть использованы при написании как файл-программ, так и файл-функций. Операторы цикла Схожие и повторяющиеся действия выполняются при помощи операторов цикла for и while. Цикл for предназначен для выполнения заданного числа повторяющихся действий, a while— для действий, число которых заранее не известно, но известно речевые продолжения цикла. Цикл for Использование for осуществляется следующим образом: for count = start:step:final команды MATLAB end Здесь count — переменная цикла, start— ее начальное значение, final — конечное значение, a step — шаг, на который увеличивается count при каж 348 Часть II. Вычисления it программирование дом следующем заходе в цикл. Цикл заканчивается, как только значение count становится больше final. Переменная цикла может принимать не только целые, но и вещественные значения любого знака. Разберем применение цикла for на некоторых характерных примерах. Пусть требуется вывести графики семейства кривых для хЕ [0. 2л], которое задано функцией у(х, a) = e~axsinx, зависящей от параметра а, для значений параметра а от -0.1 до 0.1 с шагом 0.02. Можно, конечно, последовательно вычислять ^(х, а) и строить ее графики для различных значений а от -0.1 до 0.1, но гораздо удобнее использовать цикл for. В редакторе М-файлов наберите текст файл-программы, приведенный в листинге 7.1, сохраните его в файле FORdeml.m и запустите файл-программу на выполнение (или из редактора М-файлов, или из командной строки, набрав в ней FCRdemi и нажав <Enter>) (работа в редакторе М-файлов и запуск файл-лрограмм описаны в главе 5). figure % создание графического окна х = 0:pi/30:2*pi; % вычисление вектора значений аргумента % перебор значений параметра в цикле for а = -0.1:0.02:0.1 % вычисление вектора значений функции для текущего значения параметра у = ехр(-а*х}.*sin(x); % добавление графика функции hold on plotfx, у) end Редактор М-файлов автоматически предлагает расположить опепаторы внутри цикла с otctj пом от левого края. Используйте эту возможность для структурирования текста программы. Редактор автоматически устанавливает отступы подходящей длины, если выбран переключатель Smart indent на вкладке Language для компоненты Editor/Debugger в диалоговом окне Preferences В результате выполнения FORdemi появится графическое окно, изображенное па рис. 7.1, которое содержит требуемое семейство кривых. Гпава 7. Управляющие конструкции языка программирования 349 Рис. 7.1. Семейство кривых Напишите файл-программу для вычисления суммы 10 1 $=£-. Алгоритм вычисления суммы использует накопление результата, т. е. сначала сумма равна нулю, затем в переменную к заносится единица, вычисляется 1/А! (т. е. 1/1!), добавляется к S и результат снова заносится в S'. Далее к увеличивается на единицу, и процесс продолжается, пока последним слагаемым не станет 1/10!. Файл-программа FORdem2, приведенная в листинге 7.2, вычисляет искомую сумму. Если шаг цикла равен 1, то его можно не указывать. % ФАЙЛ-ПРОГРАММА ДЛЯ ВЫЧИСЛЕНИЯ СУММЫ % 1/11 + 1/2! + ... + 1/10! % обнуление S для накопления -уммы S = о,- 350 Часть II. Вычисления и программирование % накопление суммы в цикле с шагом 1 for к = 1:10 Б = S + 1/factorial(к); end % вывод результата в командное окно S Наберите файл-программу в редакторе М-файлов, сохраните в текущем каталоге в файле FORdem2.m и выполните се Результат отображается в командном окне. т. к. в последней строке файл-программы содержится s без точки с запятой для отображения значения переменной s в командное окно s = 1.7183 Обратите внимание, что остальные строки файл-программы, которые могли бы повлечь вывод промежуточных значений, завершаются точкой с запятой для подавления вывода в командное окно. Первые две строки с комментариями не случайно отделены пустой строкой от остального текста программы. Именно они выводятся на экран, ко1да пользователь при помощи команды help из командной строки получает информацию о назначении файл-программы FORdem2 » help F0Rdem2 ФАЙЛ-ПРОГРАММА ДЛЯ ВЫЧИСЛЕНИЯ СУММЫ 1/1! + 1/2! + ... + 1/10! При написании файл-программ и файл-функций не пренебрегайте комментариями, особенно если вы планируете продолжить работу с ними! Важно понять, что все переменные, использующиеся в файл-npoi рамме, становятся доступными в рабочей среде (см. окно Workspace). Они являются так называемыми глобальными переменными. Например, для получения значения к после выполнения FORdem2 следует просто набрать к в командной строке и нажать <Enter>. Результат очевиден, т. к. последний раз цикл for выполнялся как раз для к, равного десяти. С другой стороны, в файл-программе могут использоваться все переменные, введенные в рабочей среде, т. е. переменные всех файл-программ и рабочей среды являются общими. Это может послужить источником ошибок, поскольку файл-программа изменяет содержимое одноименных переменных рабочей среды, которые могли быть инициализированы из командной строки или в другой файл-программе. Гпава 7. Управляющие конструкции языка программирования 351 Поставим задачу вычислить сумму, похожую на предыдущую, но зависящую еще от переменной х: ю s^: Для вычисления данной суммы в файл-прогргмме F0Rdem2, приведенной в листинге 7.2, требуется изменить строку внутри цикла for на S = S + х. "к/factorial (к) Перед запуском программы следует определить переменную х в командной строке. Вычисление, например, 5(1.5), производится из командной строки при помощи следующих команд: » х = 1.5; » F0Rdem2 S = 3.4S17 В качестве х может быть вектор или матрица, поскольку в файл-программе F0Rdem2 при накоплении суммы использованы поэлементные операции. Перед запуском F0Rdem2 нужно обязательно присвоить переменной х некоторое значение, а для вычисления суммы, например из пятнадцати слагаемых, придется внести изменения в текст файл-программы. Гораздо лучше написать универсальную файл-функцию, у которой в качестве входных аргументов будут значение х и верхний предел суммы, а выходным — значение суммы 5(х). Использование конструкций языка программирования, в частности, циклов, в файл-функцкях производится так же, как и в файл-программах. Создавая файл-функцию, внесите некоторое усовершенствование в алгоритм. При вычислении к-го слагаемого ак -хк/ку. требуется возвести л в степень к и вычислить факториал к . Для небольшого числа слагаемых эти действия выполняются практически мгновенно, но при увеличении числа слатаемых и большом наборе значений х время счета может оказаться весьма большим. В нашем примере несложно заметить связь между двумя соседними слагаемыми. Предположим, что уже вычислено а5 =лс5/3!, тогда очевидно, что а6 =а4 ‘х/(>, а для произвольного к справедливо рекуррентное соотношение: ак = а*ч х/к , связывающее текущее и предыдущее слагаемые, в котором формально а0 = 1. Достаточно часто такой подход позволяет эффективно вычислять суммы, возникающие в практических 352 IL Вычислений и программирование задачах. Коэффициент, на который следует умножать предыдущее слагаемое, равен отношению ak/ak_x. Файл-функция sumN, вычисляющая 5(х), приведена в листинге 7.3. ... ’ •------ --- ‘ ............. Листинг 7.3. Файл-функция sumN для вычисления суммы function s ~ sumN(x, N) % ТйЙЛ—ФУНКЦИЯ ДЛЯ ВЫЧИСЛЕНИЯ СУММЫ % х/1! + хл2/2! + ... + хлИ/Ы! % использование: S - sum(x, N) ? обнуление S для накопления суммы s = 0; .начальное значение, соответствующее m = 0 u = 1 ; % накопление суммы в цикле for тп = 1:Н u = u.*x/m; s = s + и; end О назначении и способе вызова файл-функции sumN пользователь может узнать, набрав в командной строке help sumN. В командное окно выведутся первые три строки с комментариями, отделенные от текста файл-функции пустой строкой. Ясно, что для х = 1.5 и N = 10 функция sumN даст тот же результат, ЧТО И FORdera2 : » S - sumN(1.5, 10) s = 3.4817 Обратите внимание, что внутренние или локальные переменные m и и (райл-функции sumN не являются глобальными. Попытка просмотра значения переменной m или и из командной строки после выполнения файл-функции sumN приводит к сообщению о том, что функция, или переменная, не определена (разумеется, если она не была инициализирована до вызова sumN). Если в рабочей среде имеется глобальная переменная с тем же именем га, определенная из командной строки или в файл-программе, то она никак не связана с локальной переменной m в файл-функции. Как правило, лучше Глава 7. Управляющие конструкции языка программирования 353 оформлять собственные алгоритмы в виде файл-функций для того, чтобы переменные, используемые в алгоритме, не портили значения одноименных глобальных переменных рабочей среды. Впрочем при необходимости файл-функция можег использовать глобальные переменные (см. разд. "Подфункции" главы 5). Циклы for могут быть вложены друг в друга, при этом переменные вложенных циклов должны быть разными. Вложенные циклы удобны для заполнения матриц. Например, в разд. MATLAB: Programming: Basic Program Components: Program Control Statements: Loop Control — for, while, continue, break справочной системы MATLAB содержится пример заполнения матрицы Гильберта при помощи вложенных циклов. Элементы матрицы Гильберта порядка л определяются формулами a, j = l/(i + j -1), для i,j = 1,2, ..., п . Скопируйте пример в новый М-файл при помощи буфера обмена Windows, сохраните с именем HILdem.m и продолжите работу с ним, как с файл-программой. Примечание Не пренебрегайте возможностью запускать примеры, приведенные в справочной системе MATLAB, и изменять их по своему усмотрению, добиваясь желаемого результата. Перед вычислением элементов матрицы целесообразно инициализировать ее при помощи функции zeros, которая создает массив, заполненный нулями. Иначе в цикле размеры массива будут динамически увеличиваться, что потребует дополнительного времени. Для вывода матрицы на экран достаточно добавить в конце файл-программы имя массива, содержащего матрицу. Следует снабдить части файл-программы комментариями. После небольших изменений в скопированном примере файл-программа HILdem выглядит так. как показано в листинге 7.4. v ...... .. .. ............ : Листинг 7.4. Файл-программа HILdem для нахождения матрицы Гильберта ...-.....................-...................-..-...-...-.................; % Задание размера ма1: рицы п = 4; % Инициализация матригщ и заполнение ее нулями а - zeros(n); % Вычисление матрицы Гильберта порядка п for i - l:n 354 Часть II. Вычисления и программирование for j = l:n a(i, j) = 1/(i + j - 1) ; end end % Вывод матрицы Гильберта на эмран а Запуск HlLdem приводит к выводу в командное окно матрицы Гильберта четвертого порядка и появлению в рабочей среде новой глобальной переменной — массива а размера четыре на четыре, содержащего элементы матрицы Гильберта. «I Примечание _ Инициализация любых используемых переменных считается хорошим стилем написания программ, она необходима во многих языках программирования. В MATLAB инициализация не обязательна, формально команду а = zeros (п) можно было пропустить, поскольку MATLAB автоматически увеличивает размеры массива по мере присвоения значений его элементам и выхода за верхнюю границу быть не может. Эта особенность может послужить источником ошибок. Пренебрежение инициализацией таит в себе еще одну опасность. Пусть в рабочей среде уже есть массив а размера 10 на 10, а в файл-программе HlLdem инициализация отсутствует. Тогда после выполнения HlLdem массив не изменит размеры, а элементы, строчные и столбцевые индексы которых превосходят четыре, остану гея без изменений. Поставим теперь задачу — исследовать границы спектра матрицы Гильберта для различных порядков матрицы (от первого до некоторого n-го) и отобразить результат в виде графиков значений максимального и минимального собственных чисел в зависимости от размера матрицы. Для решения этой задачи требуется N раз выполнить операторы файл-программы HlLdem, приведенной в листинге 7.4, изменяя п от единицы до N. После вычисления матрицы Гильберта порядка п необходимо: 1. Найти ее спектр при помощи встроенной функции eig. 2. Определить границы спектра, т. е. максимальный и минимальный элемент вектора — аргумента eig. 3. Запомнить границы в элементах с индексом п некоторых вспомогательных векторов. В конце следует визуализировать результат (операциям с матрицами, в частности, нахождению спектра, посвящен разд. "Заоачи пинейноу алгебры" главы б). Гпава 7. Управляющие конструкции языка программирования 355 Напишите файл-функцию Hiispect, которая выводит на разные оси графического окна зависимости максимального и минимального собственных чисел матрицы Гильберта от порядка матрицы (для минимального собс. венного числа используйте логарифмическую шкалу по оси ординал). Входным аргументом файл-функции Hiispect должен быть максимальный порядок исследуемых матриц, выходные аргументы в данном случае не нужны. При возникновении затруднений воспользуйтесь листингом 7.5. Исследуйте границы спектра матрицы Гильберта до двенадцатого порядка. Графическое окно, появляющееся в результате вызова » Hiispect(12) должно выглядеть так, как показано на рис. 7.2. Примечание При решении практических задач, требующих много вычислений, становится актуальной проблема временных затрат компьютера. Оказывается, что заполнение матриц лучше осуществлять при помощи индексации или встроенных функций MATLAB, если структура матрицы позволяет это. Например, для получения матрицы Гильберта предназначена функция hilb. Увеличению производительности программ пользователя посвящена глава 23. 356 Часть II. Вычисления и программирование i Листинг 7.5. Файл-функция Hiispect для исследования спектра !“тР"Чь,г“"ь6ерта.................... function HilSpect(N) % Исследование границ спектра матрицы Гильберта % использование: HilSpect(N), N — максимальный порядок % инициализация массивов для границ спектра Lmax = zeros(1, N) ; Lmin = zeros(1, N); % вычисления для матриц от первого порядка до N-ro for n = 1:N % заполнение матрицы Гильберта, вместо вложенных циклов % можно использовать встроенную функцию А = hilb(n); А = zeros(п); for k = 1:п for j = l:n А(к, j) = 1/(к + j - 1); enJ end % вычисление спектра и его границ Lambda = eig(A); Lmax(n) = max(Lambda); Lmin(n) = niin( Lambda) ; end S вы=од зависимостей границ спектра от порядка матрицы figure; subplot(2, 1, 1) plot(Lmax, 'ко-') title('Максимальное собственное число матрицы Гильберта') xlabel('itN') grid on subplot(2, 1, 2) semi logy (Lmin, 'k*-') title('Минимальное собственное число матрицы Гильберта’) xlabel('itN'I grid on глава 7 Управляющие конструкции языка npoi раммирования 357 В алгоритм заполнения последовательности матриц можно внести усовершенствование, поскольку при увеличении п на единицу новая матрица образуется из старой добавлением строки и столбца. Воспользуйтесь симметричностью матрицы Гилберта и тем, что MATLAB динамически увеличивает размеры массива по мере необходимости. При возникновении затруднений обратитесь к листингу 7.6, в котором приведен подходящий блок операторов. ........................................ Листинг 7.6. Вычисления матриц ГилЬберта добавлением строки и стол она ............•* ....................... .............. А = 1; for п = 2 :N for k = l:n - 1 A(n, k) = 1/ (n + k - 1) ; A(k, n} = A(n, k); end A(n, n) = l/(2*n - 1) ; end В заключение этого раздела отметим еще одну особенность цикла for, которая наряду с возможностью задания вещественного счетчика цикла с постоянным шагом делает цикл for достаточно универсальным. В качестве значений переменной цикла допускается использование массива значений-for count = А команды MATLAB end Если а— вектор-строка, то count последовательно принимает значение ее элементов при каждом заходе в цикл. В случае двумерного массива а на i -ом шаге цикла count содержит столбец а( :, i). Разумеется, если А является вектор-столбцом, то цикл выполнится всего один раз со значением count, равным а. Цикл for оказывается полезным при выполнении определенного конечного числа действий. Существуют алгоритмы с заранее неизвестным количеством повторений, реализовать которые позволяет более гибкий цикл while. Цикл while, суммирование рядов Цикл while служит для организации повторений однотипных действий в случае, когда число повторений заранее неизвестно и определяется выполнением некоторого условия. Рассмотрим пример на вычисление суммы, по 358 Часть If Чычисленич и программирование хожий на пример из предыдущего раздела. Требуется найти сумму ряда для заданного х (разложение в ряд sin х): S^-^: Конечно, до бесконечности суммировать не удастся, но можно накапливать сумму с заданной точностью. Известно, что для знакопеременного ряда теоретически достаточно удерживать слагаемые, превышающие по модулю заданную точность, например, I010. Однако суммирование таких рядов с ограниченной точностью вычислений может привести к потере значащих цифр и, в конечном итоге, к неверному результату. Значение к, обеспечивающее малость текущего слагаемого, заранее неизвестно, поэтому циклом for воспользоваться не удастся. Выход состоит в применении цикла while, который работает, пока выполняется условие цикла: while условие повторения цикла команды MATLAB end В данном примере условием повторения цикла являемся то, что модуль текущего слагаемого x2k+i/(2k + 1)! больше К)-10. Для записи условия в форме, понятной MATLAB, следует использовать знак ">" (больше). Текст файл-функции mysin, вычисляющей сумму ряда на основе рекуррентного соотношения х2 °* 2Л(2Л + 1)°*-1’ приведен в листинге 7.7. Конечно, в общем случае малость слагаемого— понятие относительное, слагаемое может быть, скажем, порядка 1О10, но и сама сумма того же порядка. В этом случае условие окончания суммирования должно быть другим, а именно малость модуля отношения текущего слагаемого к уже накопленной части суммы. Пока не будем обращать на это внимания — нашей задачей является изучение работы с циклами. Листинг 7.7. Файл-функция пувт, вычисляющая синус разложением в ряд function s = mysin (х) % Вычисление синуаа разложением в ряд % Использование: у = mysin(x), -pi < х < pi [лава 7. Управляющие конструкции языка программирования 359 8 вычисление первого слагаемого суммы для к = О к = 0; и - к; s = и; % вычисление вспомогательной перем-'нной х2 = х*х; while abs ( u ) > 1. Ое-Ю k = k + 1,- u = -u* x2/(2*k)/(2*k + 1); s = s + u; end Обратите внимание, что у цикла while, в отличие от for, нет переменной цикла, поэтому пришлось до начала цикла к присвоить единицу, а внутри цикла увеличивать к на единицу. Сравните теперь результат, построив графики функций mysin и sin на отрезке [-я, л] на одних осях, например, при помощи fpiot (команды можно задать из командной строки): » fplot(@mysin, [-pi, pi]) » hold on » fplot(@sin, [-pi, pi], 'k.') Рис. 7.3. Сравнение mysin и sin 360 Часть II. Вычисления и программирование Получающиеся графики изображены на рис. 7.3, они свидетельствуют о правильной работе файл-функции mysin. Условие цикла while может содержать логическое выражение, составленное из операций отношения и логических операций или операторов. Для задания условия повторения цикла допустимы операции отношения, приведенные в табл. 7 1. Таблица 7.1. Операции отношения Обозначение Операция отношения == Равенство < Меньше <= Меньше или равно >= Больше или равно -= Не равно Задание более сложных условий производится с применением логических операторов или операций. Например, условие —1<х<2 состоит в одновременном выполнении неравенства х>-1 и х<2 и записывается при помощи логического оператора and ancl(x >= -1, х < 2) или эквивалентным образом с применением логической операции "и" — s (х >= -1) & (х < 2) Основные логические операции и операторы и примеры их записи приведены в табл. 7.2 (логические выражения подробно описаны в разд. "Логические операции с числами и массивами " этой главы). Таблица 7.2. Логические выражения Тип выражения Выражение Логический оператор Логическая операция Логическое "и" л <3 и Л=4 and (х < 3, к==4) (х<3) & (к = 4) Логическое "млн" л = I или 2 or (х == 1, х — 2) (х == 1) | (х == 2) Отрицание "не" а ^1.9 not (а == 1.9) -(а == 1.9) Гпава f Управляющие конструкции я зыка программирования 361 Примечание * Операторы not, and и or являются функциями, возвращающими значения "истина" (логическая единица) или "ложь" (логический ноль). Такие же значения принимает любое логическое выражение. При вычислении суммы бесконечного ряда имеет смысл ограничить число слагаемых. Если ряд расходится из-за того, что его члены не стремятся к нулю, то условие на малость текущего слагаемого может никогда не выполниться и программа зациклится. Выполните суммирование, ограничив число слагаемых. Добавьте в условие цикла while файл-функции mysin (см. листинг 7.6) ограничение на количество слагаемых: (abs(u) > 1.0е-10 ) & ( к <= 100000) или в эквивалентной форме: and(absfu) > 1.0е-10, к <= 100000) Для задания порядка выполнения логических операций следует использовать круглые скобки (подробнее про логические операторы и логические операции и про возможность применения их к массивам написано в разд. "Логические выражения с массивами и числами” данной главы). При программировании алгоритмов кроме организации повторяющихся действий в виде циклов часто требуется выполнить тот или иной блок команд в зависимости от некоторых условий, т. е. использовать ветвление алгоритма. Операторы ветвления Условный оператор if и оператор переключения switch позволяют создать гибкий разветвляющийся алгоритм, в котором при выполнении определенных условий выполняется соответствующий блок операторов или команд MATLAB. Практически во всех языках программирования имеются аналогичные операторы. Условный оператор if Оператор if может применяться в простом виде, для выполнения блока команд при удовлетворении некоторого условия, или в конструкции if-eiseif-eise для написания разветвляющихся алгоритмов. 362 Часть II. Вычисления и программирование Проверка входных аргументе» Начнем с простейшего примера — создайте файл-функцию для вычисления 77ч, Она работает для любых значений л, причем для -1<х<1 результат является комплексным числом. Предположим, что вычисления происходят в области действительных чисел и требуется вывести сообщение о том, что результат является комплексным числом. Перед вычислением функции следует произвести проверку значения аргумента х и вывести в командное окно предупреждение, если модуль х меньше единицы. Здесь уже не обойтись без условного оператора if, применение которого в самом простом случае выглядит так: if условие команда MATLAB end Если условие верно, то выполняются команды MATLAB, размещенные между if и end, а если условие неверно, то происходит переход к командам, расположенным после end. Условие является логическим выражением и записывается по правилам, описанным в предыдущем разделе. Файл-функция, проверяющая значение аргумента, приведена в листинге 7.8. В нем мы использовали функцию warning, которая служит для вывода предупреждения в командное окно. "...---------.........-............... .,,. Листинг 7.8. Файл-функция Rfun, проверяющая значение аргумента function f - Rfun(x); % вычисляет едгс{хл2 - 1) % выводит предупреждение, если результат комплексный % использование у = Rfun(x} % проверка аргумента if abs(x) < 1 warning('результат комплексный') end % вычисление функции f — sqrt(x',2 - 1); [ лава 7. Управляющие конструкции языка программирования 363 Теперь вызов в Eun от аргумента, меньшего единицы по модулю, приведет к выводу в командное окно предупреждения: » у = Rfun(0.2) результат комплексный О + 0.979795897113271 Файл-функция Rfun только предупреждает о том, что ее значение комплексное, все вычисления с ней продолжаются. Если же комплексный результат означает ошибку вычислений, то следует прекратить выполнение функции, испо льзуя error вместо warning. Примечание В отличие от warning, выполнение error приводит к останову программы. Напишите файл-фучкцию root2, которая по коэффициентам квадратного уравнения находит только вещественные его корни, а для комплексных выдает ошибку. Текст файл-функции root2 приведен в листинге 7.9. function [xl, х2] = root2(а, b, с) % возвращает вещественные корни квадратного % уравнения ахл2 + Ьх + с = О % если корни комплексные, то выдается сообщение об ошибке % использование [xl, х2] = root2(а, Ь, с) D = Ьл2 - 4*а*с; % вычисление дискриминанта % проверка на наличие вещественных корней if D < 0 error(1комплексные корни') end % вычисление корней xl = (-Ь + sqrt(D) ) /2; х2 = (-to — sqrt(D))/2; 364 Часть II. Вычисления и программирование При решении квадратного уравнения, корни которого комплексны, root2 остановит вычисления и выведет соответствующее предупреждение в командное окно: » [xl, х2] = root2(l, 0, 1) ??? Error using ==> root-2 комплексные корни При составлении файл-функций следует предусмотреть еще один вид контроля — проверку количества входных и выходных параметров. Если пользователь вызовет функцию root2 с двумя входными параметрами, то получит сообщение об ошибке при выполнении того оператора файл-функции, который содержит неопределенный параметр. В случае вызова функции root? с одним выходным аргументом или без аргументов будет вычислен только первый корень квадратного уравнения, что также введет пользователя в заблуждение. Лучше заранее предупредить пользователя о характере ошибки и прекратить работу файл-функции. Кроме того, следует учесть, что файл-функция root2 не может принимать массивы в качестве входных аргументов. Если даже использовать поэлементные операции при вычислениях, то дискриминант уравнения D будет массивом, а что такое D > 0 для массива, будет рассмотрено далее (логические выражения подробно описаны в разд. "Логические выражения с массивами и числами " данной главы). Дополните функцию root2 вышеописанными видами контроля, предотвращающими неправильное ее использование. Встроенные функции nargin и nargout возвращают. соответственно, число входных и выходных аргументов. с которыми была вызвана файл-функция. Для проверки, являются ли входные аргументы числами или массивами, следует сначала найти размеры соответствующих переменных при помощи size, а затем проверить их на равенство единице. Вывод текста в командное окно в коде выполнения файл-программы или файл-функции осуществляется оператором disp, сам текст указывается в апострофах: disp('текст'). Листинг 7.10 содержит правильно запрограммированную файл-функцию, при использовании которой не должно возникнуть сложностей. Листинг 7.10. Файл-функция root2, предотвращающая неправильное ее использование г ............. tunction [xl, х2] - root2(а, Ь, с} % возвращает вещественные корни квадратного % уравнения ах"2 + Ъх + с = 0 % использование [xl, х2] = root2Ь, с) Глава 7. Управляющие конструкции языка программирования 365 % проверка числа входных аргументов if (neirqrn < 3) error{'залайте три коэффициента квадратного уравнения') end % проверка, являющая ли входные аргументы числами [Na, Ma] = size(а); [Mb, Mb] = size(b); [Nc, Me] = size(c); % если хотя бы один из размеров входных аргументов не равен единице, % то выводится сообщение об ошибке и файл-функция прекращает работу if (Na ~= 1) | (Ma ~= 1) | (Nb ~= 1) | (Mb ~= 1) | (Nc ~= 1) | (Мс -= 1) error('входные аргументы должны быть числами’) end D = ЬА2 - 4*а*с; % вычисление дискриминанта % проверка на наличие комплексных корней, если корни комплексные, % то выводится сообщение об ошибке и файл-функция прекращает работу if D < О error(’комплексные корни’) end % вычисление корней xl = (-b + sqrt(D))/2; х2 = {-b — sqrt(D))/2; % если root2 вызвана с одним выходным аргументом, % то выводится предупреждение if nargout ~= 2 warning(•это только один корень 1) <11зр('для получения двух корней используйте') disp('[xl, х2] = гоос2(а, Ь, с)') end Только что вы создали фай а-функцию в том же стиле, в котором написаны многие стандартные функции MATLAB. Функция hadamard, использующаяся для получения матрицы Адамара, является файл-функцией, содержащейся в файле hadamard.m подкаталога toolboxmatlabelmat основного каталога МАП АВ. При наличии определенного опыта программирования и желания писать собственные вычислительные программы большую пользу может принести самостоятельное изучение алгоритмов файл-функций, рас 366 Часть II Вычисления и программирование положенных в подкаталогах toolbox. Большинство из них имеют открытый код, что позволяет понять принципы эффективного программирования в MATLAB Другие функции являются встроенными. Соответствующие М-файлы содержат только комментарии, в которых указана информация об использовании функции. Например, функции cos соответствует М-файл cos.m подкаталога toolboxesmatlabelfun основного каталога МА ГЬАВ. Файл cos.m не содержит операторов, последняя строка комментариев %Buiid-in function указывает на то, что cos является встроенной функцией. Организация ветвления В общем виде оператор ветвления представляет конструкцию if-elseif-else, работу которой поясняет пример файл-функции ifdem, приведенной в листинге 7.11. function ifdem(а) % пример использования структуры if-elseif-else if (а == 0) displ'a равно нулю') elseif а == 1 displ'a равно единице’) elseif а == 2 displ'a равно двум’) elseif а >= 3 disp('а больше или равно трем') else disp('a меньше трех, но не ноль, не единица и не двойка.’) end В зависимости от выполнения того или иного условия работает соответствующая ветвь программы, если все условия неверны, то выполняются команды, размещенные после else. Вызовы функции ifdem с различными аргументами позволяют убедиться в вышесказанном: » ifdem(l) а равно единице » ifdem(1.2) а меньше трех, но не ноль, не единица и не двойка » ifdem(2) Гпава 7. Управляющие конструкции языка программирования 367 а равно двум » ifdem(3) а больше или равно трем » ifdem(-l) а меньше трех, но не ноль, не единица и не двойка Ветвей может быть сколько угодно (добавьте несколько eiseif с похожими условиями в ifdem) или только две, например; if (а == 0) disp('а равно нулю’) else disp(’а не равно нулю1) end В случае двух ветвей используется завершающее else, a eiseif пропускается. Оператор if должен заканчиваться end. Файл-функция ifdem наглядно демонстрирует работу оператора if, но на практике оказывается бесполезной. Действительно полезный пример — вычисление кусочно-заданной Функции sinx-1, х<-я; у(х) = - х/n, -тг<х<тг; —COST, Х>71, которое реализуется файл-функцией pwfun. Ее текст приведен в листинге 7.12. Обратите внимание на следующие моменты. I. Число ветвей if-eiseif-eise равно трем. 2. Во второй ветви достаточно только проверить, что х<п, условие х>-п уже выполнено (иначе бы отработала первая ветвь в if-elseif-eise и оператор if закончил работу). 3. В последней ветви нет смысла проверят ь :тикакие условия, она работает, если все предыдущие условия неверны, что как раз соответствует х> -тс. Листинг 7.12, Файн-функцит pwfun Function у = pwfun (х) % вычисляет кусочно-линейную функцию % sin(x) - 1, если х < -р: % у(х)= x/pi, если -pi <= х % -cos(х), если х >= pi sin(x) - 1, x/pi, -cos(x), если x < -pi если -pi <= x < pi если x >— pi 368 Часть II. Вычислении и программирование % использование у = pwfun(х), х — число; if х < -pi у = sin(x) -1; elseif х < pi % проверка x >= -pi не нужна! у = x/pi; else % здесь x >= pi у - -cos(x); end Для пос гроения графика кусочно-заданной функции pwfun следует воспользоваться командой » fpiot(Gpwfun, [-3*pi, 3*pi]), которая приводит К графику, изображенному на рис. 7.4. Рис. 7.4. График кусочно-заданной функции Мы не случайно выбрали fpiot для построений графика кусочно-заданной функции. Функцией plot воспользоваться не удастся, т. к. требуется предварительно вычислить вектор значений функции от вектора аргументов, а pwfun не умеег работать с входным аргументом-вектором. Убедиться в этом можно, построив график pwfun командами: » х - -3*pi:pi/100:3*pi; » у = pwfun(х); » plotfx, у) Гпава 7. Управляющие конструкции языка программирования 369 Никакой ошибки при выполнении файл-функции не возникает, однако график строится неправильно. Дело в том. что вектор х входит в условия оператора if. Операции отношения (<, <=, >, >=, ~=) могут специальным образом применят ься и к векторам, о чем подробно написано ниже, а при обычном применении в данном примере не дают ожидаемого результата. Выход состоит в программировании следующего алгоритма вычисления кусочнозаданной функции, для реализации которого достаточно понимания вышеописанного материала. 1. Проверка числа входных аргументов, если число входных аргументов не равно единице, то завершение работы файл-функции с сообщением об ошибке (выход по ошибке). 2. Проверка, является ли входной аргумент вектором или числом, один из размеров входного аргумента должен быть равен единице. Если это условие не выполняется, то выход по ошибке. 3. Нахождение длины входного аргумента. 4. Создание вектора выходного аргумента того же размера, что и входной аргумент, и заполнение его нулями. 5. Перебор всех элементов входного вектора с использованием цикла for, вычисление от них значений кусочно-заданной функции и запись в соответствующие элементы выходного вектора. Попытайтесь составить файл-функцию самостоятельно. В случае возникновения затруднений руководствуйтесь листингом 7.13. - ..................................................................... 1истинг 7.13. Файл-функция pwfun (входной аргумент — число или лектор) function у = pwfunl(x) % вычисляет кусочно-линейную функцию % sin(х) - 1, если х < -pi % у(х)= x/pi, если -pi <= х < pi % -cos(х), если х >= pi % использование у — Ewfun(x), х — число или вектор; % проверяем количество входных аргументов, если аргумент не один, % то выхс дим из файл-функции по ошибке if nargin ~= 1 error('должен быть один входной аргумент') end % проверяем, является ли входной аргумент вектором или числом [Nx, Мх] = size(x); 370 Часть II. Вычисления и программирование % если оба размера входного аргумента не равны единице, % то выходим по ошибке if (Их — 1) & (Мх 1) error('аргументом функции может быть вектор или число') end Lx = length(х); % находим длину вектора % инициализируем выходной аргумент — вектор у % у должен быть того же размера, что х у = zeros(size(х)); % перебираем все элементы вектора х в цикле for i = l:Lx % вычисляем функцию в зависимости от значения x(i) if x(i) < -pi y(i) = sin(x(i)) - 1; eiseif x(i) < pi % проверка x > -pi не нужна! y(i) = x(i)/pi; else % здесь x > pi y(i) - -cos(x(i)); end end Входными аргументами файл-функции pwfuni могут быть как число, так и вектор, причем если входной аргумент является вектор-строкой (вектор-столбцом), то результат тоже вектор-строка (вектор-столбец). В качестве завершающего упражнения попытайтесь улучшить pwfuni так, чтобы ее входным аргументом могла быть и матрица. Учтите, что вектор в MATLAB, так же как и матрица, является двумерным массивом, у которого один из размеров равен единице. Очевидно, что для перебора элементов входного аргумента придется использовать вложенные циклы for. При появлении вопросов посмотрите листинг 7.14. •» .... • .««lar'О *' ’' • '“Vм..................- - - д -дд “ - а» 5f у V * Ж**.*1_г .. Листинг 7.14. Файл-функция pwfun2 (входной аргумент — двумерный массив) function у = pwfun2(х) % вычисляет кусочно-линейную функцию % sin(x) - 1, если х < -pi % у(х)= x/pi, если -pi <= х < pi % -cos(x), если х >= pi % использование у = pwfun(х), х — число, вектор или матрица; Гпава 7. Управляющие конструкции языка программирования 371 % проверяем количество входных аргументов, если аргумент не один, % то выходим из файл-функции по ошибке if nargin ~= 1 error(’должен быть один входной аргумент') end % нахождение размеров входного аргумента [Nx, Их] = size(x); % инициализируем выходной аргумент % двумерный массив у того же размера, что х у = zeros(size(х)); % перебираем все элементы массива х в двойном цикле for i = 1:Nx for j = l:Mx % вычисляем функцию в зависимости от значения x(i,j) if x(i, j) < -pi y(i, j) = sin(x(i,j)) - 1; elseif x(i, j) < pi % проверка x > -pi не нужна! y{i, j) = x(i, j)/pi; else % здесь x > pi y(i< j) = -cos(x(i, j)); end end end В фаил-функции pwfun2 можно было бы обойтись одним циклом, если учесть схему расположения двумерных массивов в памяти п применить индексацию порядковым номером (см. главу 2). В этом случае переменная i единственного цикла должна меняться от 1 до Nx*Mx, а вместо х (i, j) и y(i, j) следует указать х (i) и у (i). Оператор switch Предположим, что при работе с функцией двух аргументов -|t-y| - 2 е 1 S1D ЛХ- COS7LV 13 Зак ВО 372 Часть II. Вычисления и программирование приходится визуализировать ее четырьмя различными способами каркасной поверхностью, сплошной поверхностью, выводить линии уровня пли строить освещенную поверхность. Удобно создать файл-функцию, один из входных аргументов которой vis будет определять способ визуализации. Если vis равен единице, то строится каркасная поверхность, для vis. равного двум — сплошная и т. д. Можно, конечно, использовать оператор if в полном виде if-eiseif-eise, который в зависимости от значения vis выполняет нужную ветвь программы, выводящую соответствующий график. Однако оператор переключения switch позволяет написать более наглядную программу. I [рименение switch поясняет следующий фрагмент: switch а case -1 disp('а = -1') case О disp('а = О') case 1 disp('а = 1') case {2, 3, 4} disp{1 а равно 2 или 3 или 4 ') otherwise disp('а не равно -1, 0, 1, 2, Зи4') end Каждая ветвь определяется оператором case, переход в нее выполняется тогда, когда переменная оператора switch (в данном примере a) принимает значение, указанное после case, или одно из значений списка case. После выполнения какой-либо из ветвей происходит выход из switch, при этом значения, заданные в других ветвях case, уже не проверяются. Если подходящих значений для а не нашлось, то выполняется ветвь оператора переключения, соответствующая otherwise. Оператор switch как нельзя лучше подходит для решения поставленной задачи о выводе различных графиков исследуемой функции. Попытайтесь написать файл-функцию самостоятельно. Входными аргументами являются границы построения исследуемой функции по каждой из переменных: xmin, xmax, ymin, ушах и способ построения графика, определяемый vis. Все пять входных аргументов должны быть числами, причем xmin меньше хтах и ymin меньше ушах— не забудьте сделать соответствующую проверку! Выходные аргументы в данном случае не требуются. Текст файл-функции mypiot3D для решения поставленной задачи приведен в листинге 7.15. Гпава 7. Управляющие конструкции языка программирования 373 ..................................... 7.....7..... ... • Листинг 7.15. Файл-функция myplot3L i ............................(К...................л..................... function myplot3D(xmin, xmax, ymin, ушах, vis) % строит график поверхности функции % -|х*у| 2 % е * sin(pi*x) * cos(pi*x ) % на области xmin <— х <= xmax ymin <= у <= ушах % использование: myplot3D(xmin, xmax, ymin, ушах, vis) % vis = 1 — каркасная поверхность % vis - 2 — залитая поверхность % vis = 3 — линии уровня j vis = 4 — освещенная поверхность % проверяем числа входных аргументов, % если число входных аргументов не равно пяти, то выходим по ошибке if nargin ~= 5 error('Задайте xmin, xmax, ymin, ymax, vis') end % проверяем число выходных аргументов, если файл-функция вызвана % с выходными аргументами, то выходим по ошибке if nargout > О error('Функция myplot3D не имеет выходных аргументов') end % находим максимальный из размеров входных аргументов М = max{[size(xmin) size(xmax) size(ymin) size(ymax) size(vis)]); % если хотя бы один из размеров входных аргументов не равен единице, % то выходим по ошибке if И ~= 1 error('входные аргументы должны быть числами’) end % проверяем границы построени t, если нижняя граница больше или равна % верхней, то выходим по ошибке if {xmin >= xmax) | (ymin >= ymax) error(•нижняя граница должна быть меньше ве рхней *) end % вычисление шагов по х и у для построения графика поверхности dx - (xmax - xmin) /40; 374 Часть II. Вычисления и программирование dy = (ушах - ymin) /40; % генерация сетки [X, Y] = meshgrid(xmin:dx:xmax, yminidy :ymax); % вычисление функции Z = exp(-abs (X. *Y) . *sin(pi*X) . 'cos (pi*X./'2) ) ; % определение способа построения в зависимости от vis switch vis case 1 % каркасная поверхность figure mesh{X, Y, Z) case 2 % залитая поверхность figure surf(X, Y, Z) case 3 % линии уровня функции figure contour(X, Y, Z) case 4 i освещенная поверхность figure surfi(X, Y, Z) colormap(copper) shading interp otherwise % непредусмотренная ситуация disp(’vis может быть 1, 2, 3 или 4’) end Оператор switch удобно применять тогда, когда есть соответствие между дискретными значениями некоторой переменной и последующими действиями. Для определения ветви программы в зависимости от выполнения более сложных условий, например а > о, приходится использовать оператор i с. Выход из файл-функции, оператор return Файл-функция всегда прекращает свою работу после выполнения последнего оператора. Если алгоритм файл-функции предполагает ветвление, то это часто приводит к необходимости завершить функцию в каждой ветви. Применение условного оператора приводит к достаточно сложной структуре if-elseif-else, которая может быть упрощена за счет задействования оператора return. ] 1ри достижении этого оператора выполнение файл-функции Гпава 7. Управляющие конструкции языка программирования 375 прекращается и происходит возврат в точку вызова— командное окно, другую файл-функцию или файл-программу. В качестве примера мы рассмотрим вычисление кусочно-заданной функции, которое было организовано с использованием конструкции if-eiseif-eise в файл-функции pwfun (см. листинг 7.12). Оператор return позволяет запрограммировать файл-функцию без ветвления так, как показано в листинге 7.16. Листинг 7.16. Файл-функция pwfun3 с досрочным завершением работы по return ......... .... ... • .... I. I. . . ! . * • ••••• ..... - J L , L ... ... ..a... -.. .... ............... . . . function у = pwfun3(x) % вычисляет кусочно-линейную функцию % sin(x) - 1, если х < -pi % У'.х) = x/pi. если -pi <= х < pi % -cos(x), если x >= pi % использование у = pwfun3(х), х - число; if х < -pi у = sin(x) - 1; return end % здесь x >= -pi if x < pi у = x/pi; return end % здесь x >= pi у = -cos(x) f Прерывание и продолжение циклов Циклическое выполнение блока операторов в ряде случаев может потребовать либо прерывания цикла, т. е. досрочного выхода из него, либо перехода к следующему шагу цикла без выполнения части оставшихся операторов. При организации циклических вычислений операторами while или for следует позаботиться о том, чтобы внутри цикла не возникало ошибок или нежелательных действий. Например, пусть дан вектор х, состоящий из целых чисел, и требуется сформировать новый вектор у по правилу 376 Часть II. Вычисления и программирование y(i) = x(i}/x(i + 1). Очевидно, что задача может быть решена при помощи цикла for. Но если один из элементов исходного вектора равен нулю, то при делении получится inf и последующие вычисления могут оказаться бесполезны. Предотвратить подобную ситуацию можно досрочным выходом из цикла, если текущее значение x{i) равно нулю. Следующий фрагмент программы демонстрирует использование оператора break для прерывания цикла (листинг 7.17), у = zeros(length(х) - 1) for i = 1: length(х) - 1 if x(i) == 0 break end yti) = x(i + 1)/x(i); end При выполнении условия x(i) == о оператор break заканчивает цикл и происходит выполнение операторов, которые расположены в строках, следующих за end. Оператор break можно использовать и с циклом while. В случае вложенных циклов break осуществляет выход из внутреннего цикла. Примечание J Грамотным условием проверки вещественного числа на ноль является условие малости его абсолютной величины, поскольку "величина" машинного нуля (т. е. интервал вещественных чисел эквивалентных машинному нулю) существенно больше минимального расстояния между компьютерными числами. Функция realmin дает минимальное вещественное положительное число, которое представляется в компьютере с предусмотренным количеством значащих цифр. Все числа, меньшие по абсолютной величине /того значения, представляются машинным нулем. Функция realmax возвращает максимальное по модулю вещественное число, превышение которого приводит к значению Inf. Внутри цикла может возникнуть ситуация, при которой выполнение оставшейся части операторов не требуется, а сразу следует перейти к новому шагу цикла. В этом случае оказывается удобным оператор continue, который хоть и не является незаменимым, но позволяет обойтись без разветвленной структуры if-elseif-else, что делает текст программы более понятным. Гпава 7. Управляющие конструкции языка программирования 377 Обработка исключительных ситуаций Хорошо написанная программа предотвращает ошибочные действия, которые приводят к досрочному ее завершению. К немедленному прерыванию работы файл-функции приводит, например, неверный ее вызов пользователем. В приведенных выше примерах (см листинги 7.10, 7.13—7.15) мы контролировали возможные ошибки в интерфейсе и прекращали работу файл-функции, выводя информацию о допустимом ее использовании. Следующий источник ошибок— сам алгоритм. Часть некорректных математических операций в MATLAB, в отличие от многих языков программирования, не приводит к останову выполнения программы. При делении на ноль получается бесконечность (ini), деление нуля па ноль приводит к NaN, сумма бесконечности и числа имеет результатом бесконечность. Однако попытка считывания информации из несуществующего файла при помощи load, обращение к несуществующей переменной или функции, несовпадение размеров массивов в операторе присваивания обязательно прервут работу программы. Предположим, что в процессе выполнения программы следует считать в переменную данные из файла, преобразовать их и отобразить в виде круговой диаграммы, а затем продолжить некоторые вычисления, которые не связаны со считанными данными. Последовательность операторов, соответствующая требуемым действиям, приведена в листинге 7.18. А - load('my.dat‘; pie (А) X = [12-1 -2]; X = Х.Л2 Если MATLAB обнаруживает файл my.dal в путях поиска и считывает данные из него, то фрагмент программы из листинга 7.18 работает успешно (схема поиска файлов, которую применяет MATLAB, описана в разд. "Установка путей"главы 5‘ работа с текстовыми файлами подробнее разбирается в главе 8). Однако если файл найти не удалось, или при чтении из него возникли ошибки, то MATLAB выведет сообщение в командное окно и закончит выполнение программы. Выходом из подобных ситуаций является конструкция try. .. catch, позволяющая обойти исключительные ситуации, которые 378 Часть II. Вычисления и программирование приводят к ошибке, и предпринять некоторые действия в случае их возникновения. Схема использования try.. .catch выглядит следующим образом try % операторы, выполнение которых % может привести к ошибке catch % операторы, которые следует выполнить % при возникновении ошибки в блоке % меящ* try и catch end Фрагмент программы, приведенный в листинге 7.18, лучше оформить с использованием try... catch так, как это сделано в листинге 7.19. Листинг 7. I. Обработка ошибки при чтении данных из файла .......-...♦•*** -* А - -А • -..- • •• . * вЬ >«•*«»•* .» . ........... ................: try А = load(’my.dat1); pie [А) catch disp(‘ не могу найти файл my.dat ') end X = [1; 2; -1; -2] ; X = Х.А2 Теперь при отсутствии нужного файла my.dat программа выдаст сообщение об этом и продолжит работу: » не могу найти файл my.dat X = 14 14 В качестве аргумента функции disp разумно использовать функцию lasterr, возвращающую системное сообщение об ошибке. Замените в листинге?.^ Строку disp(’не могу найти файл my.dat’) на СГрОКу disp(lasterr) и выполните файл-программу — в командное окно выводится диагностическое сообщение о возникшей ошибке: Error using ==> load Unable to read file my.dat: file does not exist. Гпава 7. Управляющие конструкции языка программирования 379 Логические выражения с массивами и числами MATL-ХВ является средой, ориентированной на вычисления с матричными данными. В предыдущих разделах использовались логические выражения вида а > о, (а == 1) & (Ь > 2), где а,ь— числа. Поскольку MATLAB представляет числа массивами размера один на один, то ес тественно ожидать, что и массивы могут входить в логические выражения. Универсальным средством обработки матричных данных служат логические операции. Они позволяют просто и наглядно записывать алгоритмы, реализация которых в других языках достаточно громоздка. В данном разделе описано расширение логических операций и операций отношения на случай массивов. Разумеется, все, что касается логических операций и операций отношения для массивов, справедливо и для чисел. Объяснено применение логического индексирования при работе с массивами, которое существенно облегчает обработку данных. Операции отношения Результатом операций отношения, как любого логического выражения, может быть или "истина", или "ложь". При х равном двум, условие х >= 2 оказывается истинным. "Истине" в MATL АВ соответствует логическая единица, "ложь" обозначается логическим нулем. Арифметические переменные могут использоваться в одном выражении с логическими, в отличие от многих языков программирования. Например, выражение а + (Ь > с) не является ошибочным, в чем легко убедиться при помощи команд: » а = 1; » Ь = 5; »с = 3; » а = а + (Ь > с> а = 2 Условие ь > с выполняется, т. е. является "истиной". Результат операции отношения "больше" равен единице, которая прибавляезся к а. Использование операции "меньше" привело бы к логическому нулю, сложение которого с переменной а не изменило бы ее значения. Результат выполнения логического выражения может быть присвоен переменной: » f _ а Ь f = 1 380 Часть II. Вычисления и прогр шмирование Посмотрите тип t в окне Workspace браузера рабочей среды — переменная fявляется логической, точнее логическим массивом размера 1 на 1. Операции отношения применимы к массивам одинакового размера. Происходит пиэчеменптое сравнение и результатом является логический массив того же размера, что и исходные, состоящий из нулей и единиц. Единицы соответствуют тем элементам, для которых условие выполняется, а ноль означает невыполнение условия, например: » А = [1 2 3 4; 5 6 7 8; 9 10 11 12]; » В = [3 2 3 3; 562 2; 4 10 11 11]; » С = А == В С = 0 110 110 0 0 110 » D = А > В D = 0 0 0 1 0 0 11 10 0 1 При сравнении двумерных массивов больших размеров удобно использовать команду spy для визуализации результата, которая приводит к появлению графического окна с шаблоном матрицы. Элементы результирующей магрицы отображаются точками, что наглядно показывает, для каких элементов выполняется проверяемое условие (построение шаблона матрицы командой spy описано в разд. "Визуа чизация матриц" главы 2). Логические операции с числами и массивами Конструирование условий операторов if и while осуществляется с помощью логических операторов and, or и not или в эквивалентном виде с использованием логических операций &, | и ~. Вычисление логических выражений, содержащих and (i), or (|) и not (~), с массивами приводит к поэлементному их выполнению над элементами массивов, результатом является массив того же размера, что и исходные, причем: □ and (s) дает единицу, если оба соответствующих элемента массивов не равны нулю, если хотя бы один из них ноль, то результатом будет также ноль; Г) or (1) дает единицу, если хотя бы один элемент не равен нулю; Гпава 7. Управляющие конструкции языка программирования 381 □ not (~) применяется к одному массиву, если элемент массива не ноль, то соответствующий элемент результирующего массива равен нулю, если элемент исходного массива ноль, то — единице. Примечание Операндами логических выражений могут быть как логические массивы, так и числовые. Одним из операндов логических выражений может быть число или логический ноль или единица. В этом случае происходит поэлементное выполнение логической операции для каждого элемента массива и числа. Выполнение операторов and и or над массивами различных размеров недопустимо. Следующие примеры демонстрируют использование логических операций: » А = [13; -1 0]; » В = [0 4; 8 8] ; » С = А&В С = О 1 1 о » D = А|в D = 1 1 1 1 » Е = -А Е = 0 О 0 1 Кроме операторов and и or в MATL AB определена функция хог, выполняющая операцию "исключающее или". Функция хог имеет два входных аргумента — массивы одинакового размера. Если один из элементов входного массива не равен нулю, а второй равен, то хог записывает единицу на соответ ствующег место выходного массива. Во всех остальных случаях (ноль и ноль, не ноль и не ноль) хог записывает ноль. Аргументами хог могут быть массив и число и, конечно, два чиста. Логические операции s и | учитывают оба операнда для вычисления результата. В то же время значение логического выражения в ряде случаев определяется значением только первого операнда. Если первый операнд логического "или" является "истиной", то результат всегда будет "истина". Если первый операнд логическою "и" — "ложь", то результат— "ложь". Операции и 1 I отличаются от & и I тем, что в перечисленных двух ситуациях 382 Часть II. Вычисления и программирование они не проверяют значение второго операнда (операция &б была использована нами в главе 6 при управлении процессом решения дифференциального уравнения для простой реализации алгоритма файл-функции solproc (см. листинг 6.19)). Проверка на наличие нулевых элементов в векторе осуществляется функцией all. которая возвращает единицу, если среди элементов вектора нет нулей, н ноль в противном случае: » v = [12 0] » q = al 1 (v) q = о Аргументом функции all может быть и матрица В этом случае all проверяет каждый столбец матрицы на наличие нулей и записывает результат в вектор, каждый элемент которого соответствует столбцу исходной матрицы: » М = [93 -1; 02 2]; » р = all(М) Р = 0 1 1 Исследование па наличие ненулевых элементов производится функцией any, которая возвращает единицу, если во входном векторе есть хотя бы один ненулевой элемент. Функция any, так же как и all, работает с матрицами по столбцам. Некоторые индексные логические матрицы вычисляются по исходной матрице при помощи специальных функций MATLAB, перечисленных ниже. Каждая функция для входной матрицы находит индексную логическую матрицу из нулей и единиц, соответствующую проверяемому условию. П isfinite — единицы соответствуют числам, нули — inf, NaN. □ isinf — единицы соответствуют +inf, -inf, нули —- числам. П j snan — единицы соответствуют NaN, нули — числам. □ isprime — единицы соответствуют простым числам, нули — остальным. О isreal— единицы соответствуют вещественным числам, нули-— комплексным. При обработке матричных данных так же оказывается полезной достаточно универсальная функция find и логическое индексирование (применение find и лотческого индексирования рассмотрено в разд. "Логическое индексирование" главы 2). Гпава 7. Управляющие конструкции языка программирования 383 В приведенных выше примерах программ условия операторов if-eiself-eise и while содержали логические выражения со скалярными значениями — либо "истина", либо "ложь". Однако в эти конструкции языка программирования MATLAB могут входить выражения с массивами, причем как с числовыми, так и логическими. Формальное правило таково: условие считается выполненным, если результатом выражения является массив, состоящий только из логических единиц или ненулевых элементов. Пустой массив и "ложь" эквивалентны. Приоритет логических и арифметических операций Поскольку логические и арифметические операции могут входить в одно выражение, то возникает вопрос о том, в какой последовательности они выполняются. Например, в выражении а + в.Л2 > с сначала выполняется поэлементное возведение в степень, затем сложение и, наконец, сравнение значения суммы а + в. Л2 и с. Приоритет операций отражен в следующем списке (в порядке выполнения). 1. Логические операторы: and, or, not, хог (поскольку они являются функциями). 2. Отрицание 3. Транспонирование, возведение в степень (в том числе поэлементное), знак плюс или минус перед числом. 4. Умножение и деление (в том числе поэлементное). 5. Сложение и вычитание. 6. Операции отношения: >, >=, <, <=, ==. 7. Логическое "и" s. 8. Логическое "или" |. 9. Логическое "и" &ь. 10. Логическое "или" i |. Сначала выполняются операции над аргументами функций and, or, not и хог, например, два выражения: and(A,B)+c и А&в+с не эквивалентны’ В более ранних версиях МАИ АВ операции & и | имели одинаковый при-опитет, что следует учитывать при переносе приложений, разработанных в старых версиях MATLAB, в новую версию пакета. 384 Часть II. Вычисления и программирование Для изменения порядка операций следует применять круглые скобки. Они также полезны для придания достаточно длинному выражению легкочитаемого вида. Задания для самостоятельной работы Напишите файл-функцию для решения поставленной задачи. Там, где это возможно, предложите два решения: с использованием конструкций языка программирования и без них, применяя функцию find и др. I. Вычислить произведение элементов вектора, не превосходящих среднее арифметическое значение его элементов. 2. Подсчитать число нулей и единиц в заданной матрице. 3. Определить количество положительных элементов вектора, расположенных между его максимальным и минимальным элементами. 4. Просуммировать отрицательные элементы матрицы, лежащие ниже главной диагонали. 5. Заменить положительные элементы вектора суммой всех его отрицательных элементов. 6. Заполнить квадратную матрицу Л , каждый элемент которой определяется следующим образом: /-у, i>j', i + j, i=J’, i2+J2> i<J- 7. Вычислить сумму: 8. Для матрицы Л =(«,;) размера л на т найти значение выражения: I j jb? Z Унуавляк шиJ „оч :тоугчии я; ыьа программирования 38b 9. По заданному х найти максимальное значение и, для которого следующая сумма не превосходит 100: s(x) = X 1=1 10. Вычислить сумму: с заданной точностью е. Суммировать следует, пока модуль отношения текущего слагаемого к уже накопленной части суммы превосходите. Сравнить результат с точным значением, построив графики ev и s(.) для хе [0,5]. И. Заданы окружности, координаты их центров содержатся в массивах х и у, а радиусы в массиве г. Известны координаты некоторой точки. Требуется вывести график, на котором маркером отмечено положение точки, синим цветом изображены те окружности, внутри которых лежит точка, а остальные окружности нарисованы красным цветом. Глава 8 Обработка данных и приемы программирования в MATLAB Простейшие способы организации последовательности выполнения команд и операторов MATLAB изложены в главе 7. Данная глава посвящена описанию возможностей MATLAB, предназначенных для программирования более сложных алгоритмов. Разобрано использование массивов-структур и массивов-ячеек для хранения и обработки данных, операции со строками, работа с текстовыми файлами, с оздание файл-функций с переменным числом входных и выходных аргументов, рекурсивных файл-функций, поиск ошибок средствами встроенного отладчика и некоторые дру! не вопросы, тесно связанные с эффективным программированием собственных алгоритмов. Работа со строками Операции со строками являются важным элементом программирования в MATLAB. Вы уже использовали строки при чтении предыдущих глав. Например, входной аргумент 'го-' функции plot или входной аргумент TolX' функции optimset являются примерами строк. Наряду с обычными действиями, допустимыми со строками в большинстве языков программирования высокого уровня, MATLAB предоставляет программисту возможность сформировать команду MATLAB в виде строковой переменной, а затем выполнить ее. Простейшие операции со строками Ввод и сцепление строк Строки в MATLAB хранятся в массиве символов. Присвойте строковой переменной str значение 'Hello, world!* (набирать следует в апострофах). Глава 8. Обработка данных и приемы программирования в MATLAB 387 Не завершайте оператор присваивания точкой с запятой для того, чтобы сразу увидеть значение str. При наборе строки обратите внимание, что не завершенная апострофом строка отображается синим цветом. » str = 'Hello, World!' str - Hello, World! Посмотрите информацию о переменной str в окне Workspace (или в командном окне при помощи whos) Name Size Bytes Class str 1x13 26 char array Переменная str является одномерным массивом символов (char array) из тринадцати элементов, занимающим в памяти 26 байт, каждый символ кодируется двумя байтами. Поскольку строки хранятся в одномерных массивах. то к ним применимы некоторые операции с вектор-строками, в частности, сцепление (работа с векторами описана в разд. "Вектор-столбцы. и вектор-строки" главы 2). Индексация позволяет получить доступ к символам строковой переменной, причем возможно как задание числового индекса, так и выделение в отдельную строку нескольких идущих подряд символов при помощи двоеточия. В качестве упражнения переставьте слова в переменной str, т. е, получите строку 'World, Hello!'. Рели вы изучили работу с массивами, то решение не представит большого труда. » strnew = [str(8:12) str(6:7) str(l:5) str(13)] strrew — World, Hello! Составление одной строки из нескольких может быть произведено и при помощи функции strcat, аргументами которой являются строки, подлежащие сцеплению. Обратите внимание, что функция street игнорирует пробелы в конце строк и результат получается не такой, как при использовании векторного сцепления в предыдущем примере: » strl - str(8:12); » str2 = str(6:7); » Str3 = str(1:5); » str4 = str(13); » newstr = strcat(strl, str2, str3, str4) newstr = World, Hello! 388 Часть II. Вычисления и программирование Сервисные функции для работ ы со строками МА FLAB имеет ряд сервисных функций для облегчения работы со строками Поиск подстроки в строке осуществляет findstr, которая возвращает массив с начальными позициями вхождений. » str = 'MATLAB хранит строки в виде вектор-строк’; » substr = ' строк ' ; » pos = findstr(str, substr) pos = 15 36 Функция findstr полагает, что подстрока с образцом для поиска содержится во входном аргументе меньшего размера, а строка, в которой производится поиск,— в аргументе большего размера, поэтому необязательно заботиться о порядке входных аргументов. Примечание Символы кирилицы могут некорректно отображаться в некоторых приложениях Windows, в частности, в нелокализованной версии MATLAB. Разрешение проблемы состоит в следовании рекомендациям, которые дают эффект для других программ, например, Adobe Photoshop. Данные советы связанные с изменением кодовой страницы, легко найти в соответствующих пособиях или в Интернете при помощи любого поискового сервера, набрав в строке запроса, например, "русские символы photoshop". См. также замечание в разд. "Оформление графиков" главы 3. Сравнение двух строк выполняется функцией strcmp, которая возвращает логическую единицу для равных строк и ноль в противном случае: » strl = 'abcl23def098gh'; » str2 = 1abcl23def098gh'; » rez = strcmp(strl, str2) rez - 1 Функция st rm mp позволяет установить совпадение первых нескольких символов в двух строках, опа используется так же, как strcmp, только в качестве третьего параметра следует указать число сравниваемых символов от начала строк: >> strl - Hello, World!'; » str2 = Hello, Igor!',- » rez = strncmp(strl, str2, 5) rez = 1 Гпава 8. Обработке данных и приемы программирования в MATLAB 389 Функция strrep заменяет все встречающиеся подстроки на другие, первый ее входной аргумент является строкой, в которой следует произвести изменения, второй — подстрокой, подлежащей замене, а третий — подстрокой с образцом замены. Замените, например, "6,5" на "7.0" в предложении "МА П АВ 6.5 является последней версией пакета". Используйте strrep так, как указано ниже: » str = 'MATLAB 6.5 является последней версией пакета’; >> newstr = strrep(str, '6.5', '7.0') newstг = MATLAB 7.0 является последней версией пакета Преобразование всех прописных букв в строчные производит функция upper. Функция lower осуществляет обратное преобразование. Строка, требующая преобразования, задается входным аргументом данни1Х функций. Функция is char проверяет, является ли входной аргумент строкой или нет, возвращая логическую единицу или ноль соответственно. Другие функции описаны в следующих разделах, посвященных созданию простых программ с интерфейсом пользователя из командной строки рабочей среды MATLAB (полный список сервисных функций обработки строк приведен в приложении /). Перечисленные выше функции значительно облегчают труд программиста, избавляя его от необходимости самостоятельного программирования алгоритмов поиска и замены. Заметьте, что изложенных в предыдущей главе сведений вполне достаточно для написания собственных файл-функции, выполняющих аналогичные действия. Действительно, поскольку строки хранятся в одномерном массиве символов, то перебором всех элементов строки в цикле можно осуществить поиск и замену одних подстрок на другие. В качестве упражнения напишите файл-функцию strnumpos, которая находит позиции всех цифр, входящих в строку, и возвращает результат в виде вектора. Примените цикл for для перебора всех символов строки и if для проверки на цифру. Воспользуйтесь листингом 8.1 в случае возникновения затруднений. Листинг 8.1. Файл-функции strnumpos для поиска цифр в строке _____..... ........ ... .. ....— --— .—.... ... — .. . ...Жй function pos = strnumpos(str) % функция strnumpos возвращает позиции цифр в строке % использование: pos = strnumpos(str) % strnumpos(str) % проверка входных и выходных аргументов % допускается не более одного выхе дного аргумента if nargout > 1 390 Часть II Вычисления и программирование error('функция имеет не более одного выходного аргумента') end % должен быть один входной аргумент if nargin ~= 1 error('должен быть один входной аргумент‘) end S входной аргумент должен быть строкой if ~ ischar (str) error('входной аргумент должен быть строкой') end % вычисляем длину строки slen = length(str); % Обнуляем счетчик числа цифр в строке digits = 0; % создаем пустой массив для хранения позиций цифр в строке pos = [ ]; % перебираем в цикле все символы строки for k = 1:slen % проверяем, 1 является ли текущий символ str (к) цифрой if (str(к) == О') 1 (str(к) == '1') I (str(k) == '2') |.. (str(к) == 3') I (str(к) == '4') I (str(к) == '5') |.. (str(к) == 6'} 1 (str(k) == '7') | (str (к) == '8') |.. (str (к) = 9') % текущий символ str(к) — цифра, поэтому % увеличиваем счетчик числа цифр на единицу digits - digits + 1; % добавляем позицию цифры в массив pos, увеличивая его длину pos(digits) = k; end end Далее в этой главе в разд. "Диалоговая отладка программ" функция strnump-js реализована в более компактной форме. Массивы строк Удобной возможностью организации строковых переменных являются массивы строк, которые формируются так же, как обычные вектор-столбцы, но Гпава 8. Обработка данных и приемы программирования в MATt АВ 391 в качестве их элементов выступают строки одинаковой длины Создайте, например, массив names ИЗ строк 'Иван1, ’Олег’, 'Петр': » names = I'Изан'; 'Олег'; 'Петр'] names = Иван Олег Петр Доступ к строкам в массиве осуществляется при помощи индексации: » names(1, :) ans = Иван Использование строк разной длины недопустимо: » surnames = ['Иванов1; 'Васильев1; 'Петров'] ??? Error using ==> vertcat All rows in the bracketed expression must have the same number of columns. Очевидно, что names является двумерным массивом (матрицей), состоящим из симзолов, поэтому возникает ограничение на одинаковую длину строк. Короткие строки следует дополнить пробелами до максимальной из длин строк, входящих в массив. Функция char позволяет просто решить эту задачу: » surnames = char(’Иванов', 'Васильев', 'Петров') surnames = Иванов Васильев Петров К первой и последней строке добавились справа два пробела, и длина всех строк стала одинаковой. Для удаления лишних пробелов при доступе к строкам массива предназначена функция deblank: » surnl = deblank(surnames 11, :)) surnl = Иванов Аргументами char могут быть и массивы строк, что позволяет помещать строки в начало или конец существующих массивов строк, например: » surnames = char(suznames, 'Сидоров') sumanur = Иванов 392 Часть II. Вычисления и программирование Васильев Петров Сидоров Поиск в массиве строк производится функцией strmatch, входными аргументами которой являются образец подстроки для поиска и массив строк, а выходным — номера строк массива: » mas = char('Март', 'Апрель*, 'Май'); » ind - strmatch('Ma', mas) ind = 1 3 Задание дополни тельного третьего аргумента ' exact’ означает поиск подстроки целиком, вхождение в различные контексты не учитывается. Наличие большого числа строк приводит к необходимости хранения их в текстовых файлах. Подготовка и корректировка текстового файла могут быть осуществлены средствами любого текстового редактора, в том числе редактора М-файлов MATLAB. Текстовые файлы Обработка информации в файле включает в себя: чтение данных, их изменение или использование и, наконец, сохранение полученных результатов. Программирование обработки информации состоит из следующих этапов: открытие файла, считывание данных, запись информации, закрытие файла. Файлы можно использовать либо только для чтения (входные файлы с исходными данными) или только для записи (выходные файлы с результатами обработки), либо для изменения (входной и выходной файл одновременно). Следующие разделы посвящены описанию команд MATLAB, реализующих вышеперечисленные действия, и демонстрации их использования на некоторых простых примерах. Примечание Средства работы с файлами в MATLAB имеют много общего со средствами среды программирования языка С. Существенным отличием является ввод данных из файла, ориентированный на работу с массивами. Гпава 8. Обработка данных и приемы программирования в MATLAB 598 Открытие файла, считывание данных и закрытие файла Команда fopen предназначена для открытия cj шествующего или создания нового файла. Имя файла указывается в апострофах первым входным аргументом. Второй аргумент задает способ доступа к файлу, он может принимать следующие значения: П ' rt' — открываемый текстовый файл предназначен только для чтения; □ ’ rt+ ’ — открываемый текстовый файл предназначен для чтения и записи; □ 'wt'— создаваемый пустой текстовый файл предназначен только для записи; □ ’wt+’ — создаваемый пустой текстовый файл предназначен для записи и чтения; □ ’at’ — открываемый текстовый файл предназначен только для добавления данных в конец файла (если файла не существует, то он создается); □ ’at+' — открываемый текстовый файл предназначен для добавления данных в конец файла и чтения данных (если файл не существует, то он создается). Символ t указывает на то, что файл текстовый. Вышеперечисленные способы доступа возможны и для двоичных файлов. Например: 'и+' означает создание пустого двоичного файла для чтения и записи. Выходным аргументом fopen является идентификатор (ссылочный или логический номер), присвоенный файлу. Если файл открыть не удалось, то идентификатор становится равным минус единице. Ошибки часто возникают из-за того, что MATLAB не может найти требуемый для чтения файл. Всегда лучше указывать полное имя файла, при задании только имени и расширения МА ГЬАВ производит поиск в текущем каталоге и путях поиска. Например, если в вашем текущем каталоге нет файла beep.гл, то fopen(’beep.m’, ’rt ’) найдет его в подкаталоге toolboxmatlabgenerat основного каталога MATLAB. Функция fopen может быть вызвана и со вторым дополнительным выходным аргументом— строковой переменной с сообщением о резуль гате открытия. Считывание строк из открытого текстового файла производится командой fgeti, входным аргументом которой является идентификатор файла, присвоенный ему при открытии, а выходным — строковая переменная. Каждое обращение к fgeti позволяет последовательно считывать строки по одной от начала до конца файла. Контроль за достижением конца файла осущест 394 Часть II Вычисления и программирование вляется функцией feof с входным аргументом — идентификатором файла, feof возвращает логическую единицу, если в файле нет больше строк, и логический ноль в противном случае. По окончании работы необходимо закрыть файл командой fciose, указав в качестве входного аргумента идентификатор файла. Файл-функция myview (листинг 8.2) демонстрирует открытие текстового файла, занесение содержимого в массив строк и вывод их на экран. Вызов файл-функции с входным аргументом — именем любого существующего файла, заключенным в апострофы, приводит к отображению содержимого файла в командном окне. Если М-файл с файл-функцией myview хранится в текущем каталоге МА 11 АВ, то myview (• myview.m1) выводит листинг самой файл-функции (текст, набранный кириллицей, может выводиться некорректно). Листинг * .2. Файл-функция myview для просмотра содержим го файла ......... ....................................... • ••t. . ft function myview(filename); % функция выводит содержимое текстового файла на экран % использование myview('имя файла') % проверка аргументов if nargout — О error('функция не имеет вь_« дных аргументов'); end if nargin -= I error('функция вызывается с одним входным аргументом'); end if -ischar(filename) error(1 входной аргумент функции должен Сыть строкой1); end % Открытие текстового файлы для считывания (аргумент 'rt'), % имя файла хранится в filename, % идеи гификатор файла записывается в F, % строка с информацией о возможных ошибках - в mes [F, mes] = fopen(filename, 'rt'); % Если файл успешно открылся, то идентификатор не равен минус единице if F ~= -1 MAS = ''; % сначала массив состоит только из пустой строки 6 Последовательное считывание из файла строки до тех пор, i пока не достигнут конец файла Гпава 8. Обработка данных и приемы программирования в МА TLAB 395 while feef(F) — О % считывание строки line = fgetl(F); % добавление считанной строки в массив строк MAS = char(MAS, line); end % закрытие файла fclose (F) ; J вывод массива строк в командное окно disp(MAS) else % В эту ветвь программа заходит, если при открытии файла % возникли ошибки; происходит ;«фо{мирование об ошибке % и вывод в командное окне сообщения, выданного fopan disp (' (ЗИИБКА при открытии файла') disp(mes) end В качестве упражнения напишите файл-функцию, которая ищет заданную проку в текстовом файле и возвращает вектор с номерами строк файла, содержащих ее. Файл-функция должна иметь два входных аргумента— имя файла и искомую строку и один выходной— массив с номерами строк. Используйте функцию findstr, описанную выше, для поиска подстроки в строке. Попытайтесь обойтись без считывания содержимого текстового файла в массив строк для экономии памяти (текстовый файл может быть достаточно большим). Основной блок алгоритма приведен в листинге 8.3, дополните его проверкой входных и выходных аргументов. function rows = mysearch(filename, substring) % файл-функция mysearch ищет подстроку в текстовом файле % и возвращает номера строк, содержащих данную подстроку % Использование rows - mysearch(filename, substring) % Здесь добавьте проверку параметров % Открытие файла [F, mes] = fopen(filename, 'rt+'); 396 Часть II. Вычисления и программирование % Проверка, успешно ли открыт файл if F ~= -1 count - 0; % обнуление счетчика строк find =0; % обнуление счетчика строк, содержащих подстроку rows = [ ]; % создание пустого массива для хранения номеров строк % Последовательная обработка строк while feof(F) == 0 line = fgeti(F) % считывание текущей строки count = count +1; % увеличение счетчика строк % Сравнение длин строки файла и подстроки, % поиск имеет смысл в строках, которые длиннее подстроки if length(line) >= length(substring) % определение позиций вхождения подстроки pos = findstr(substring, line); % проверка, что массив вхождений pos не пуст if length(pos) > 0 find = find + 1; % увеличение счетчика найденных строк % Занесение номера найденной строки в выходной массив rows(find) = count; end end end fclose(F); % закрытие файла else % обработка ошибки при открытии файла disp('ОШИБКА при открытии файла'); disp(mes) end Запись в текстовый файл Символы текстового файла образуют строки со словами, предложениями или числами. Запись текстовых строк достаточно проста, а вот для занесения в текстовый файл чисел приходится прибегать к специальным форматам. Вывод информации в текстовый файл производится при помощи функции fprinti. В следующих двух разделах демонстрируется использование Fprintf на примере создания файла, содержащего таблицу значений функции с заголовком и шапкой. Глава 8. Обработка данных и приемы программирования в MATLAB 397 Запись строк Добавление строки в текстовый файл осуществляется при помощи fprnntf, вызванной с двумя входными аргументами— идентификатором файла и строкой с текстом, например, команд;! fprintf(F, 'Строка добавлена командой fprintf. ') записывает соответствующую строку в файл с идентификатором F, присвоенным ему при открытии. Последующая команда fprintf выводит заданную строку сразу за предыдущей, а не на новой строке: fprintf(F, 1 Еще строка.’) Для вывода текст а с новой строки следует добавить символ перевода строки п в начало новой строки после апострофа: fprintf (F, 1пЭтот текст с новой строки.') В результате выполнения трех вышеперечисленных команд содержимое текстового файла станет следующим: Строка добавлена командой fprintf. Еще строка. Этот текст с новой строки. Символ перевода строки п можно разместить в конце строки, после которой текст должен начинаться с новой строки, например, последовательность команд fprintf(F, 'Строка добавлена командой fprintf. ') fprintf(F, ’Еще строка.п') fprintf(F, 'Этот текст с новой строки.') приводит к аналогичному результату. Конечно, вторым аргументом fprintf может быть не только строка, заключенная в апострофы, но и строковая переменная: str = 'Этот текст добавляется в файл.' fprintf(F, str) Подумайте, как в данном случае указать команде fprintf, что следующий вывод должен осуществляться с новой строки. Очевидно, чзо решение вопроса заключается в сцеплении строк либо при помощи квадратных скобок, либо с использованием strcat: str = 'Этот текст запишется в файл, а следующий — с новой строки'; fprintf (F, [str ' n'J); или fprintf (F, s.trcat(str, 1n‘)); Создайте файл-программу, текст которой приведен в листинге 8.4, выполните ее и посмотрите содержимое файла example.txt, например, при помощи редактора М-файлов, установив в раскрывающемся списке Files of 398 Часть II. Вычисления и программирование type диалогового окна Open фильтр All Files (*.*) для отображения списка всех файлов. 1Ц W‘ 'vH'Sff *У**ЧЧ И»7 ;«.-у •у’1%7 VX-JV - Листин) „] 4. Файл-программа, демонстрирующая вывод строк в текстовый файл [F, mes] = f open {'exar^j е. txt ’, 'w'); fprintf(F, 'Эта отрока добавлена командой fprintf); fprintf (F, ’Еще строкап') fprintf(F, 1 Новая строка') fciose(F); Идентификатор файла может быть опущен, в этом случае производится вывод в командное окно. Начните работу над программой, выводящей таблицу значений функции sin. Напишите файл-функцию sintable, записывающую в файл название и шапку таблицы, приведенные ниже. ЗАГЛИЦА ЗНАЧЕНИЙ ФУНКЦИИ sin(x) I х I у= sin(x)| Поставленная задача решается при помощи четырех вызовов fprintf (листинг 8.5). ...JV...........-....... ’2*.. . . .... ...J..... ............... Листинг 8.5 Фаип-функция li.itab: е для записи названия и шапки таблицы в файл function sintable!filename) % файл-функция для вывода таблицы sin (х) в файл % Использование sintable(filename) % Добавьте проверку входных и выходных параметров % Открытие нового файла для записи [F, тлев] = f open (filename, 'w'); % Печать в файл заголовка таблицы fprintf(F, 'ТАБЛИЦА ЗНАЧЕНИЙ ФУНКЦИИ sin(x)Xn'); 'лааа 8. Обрабс тка данных и приемы программирования в MATLA3 399 % Печать в файл шапки таблицы fprintf(F, '--------------------п'); fprintf(F, х | у= sin(x)|n'); fprintf (F, 1-------------------n*) ; % Закр! [тие файла fclose(F) ; Итак, вывод текста в файл не представляет большого труда. Занесение чисел или значений переменных требует привлечения форматного вывода. Основные сведения, касающиеся форматного вывода, изложены в следующем разделе. Форматный вывод Задание формата вывода значений переменных в командное окно описано в глаае I. Например, форматы short, long, short е, long е задаются командой format или из меню рабочей среды. Функция fprintf допускает гораздо более гибкое управление видом записи чисел в файл. Схема использования fprintf при работе с числовыми переменными такова: fprintf(идентификатор, 'список форматов', список переменных) Здесь первый аргумент, как и в случае вывода строк, является идентификатором файла, второй — строка с кодами форматов, которые определяют вид записи значений переменных из списка, заданного третьим аргументом. В списке может быть одна или несколько переменных, в том числе и массивов Разберем применение форматного вывода на простом примере. Требуется записать значения переменных х = -pi/4 и у = sin(x) в файл в формате с плавающей точкой, оставляя четыре цифры после десятичной точки для х и восемь цифр— для у. Создайте файл-программу, приведенную в листинге 8.6, и выполните ее. [F, mes] = fopen('twonum.txt', 'w'); x = -pi/4; у = sin(x); fprintf(F, '%7.4f%11.8f’, x, y); fclose(F); rayview(' twonum. txt') ; Обратите внимание на второй аргумент команды fprintf. Код %7.4f задает формат вывода переменной х, которая расположена на первом месте в спи 400 Часть II. Вычисления и программирование ске вывода. Знак процента указывает на начало формата, цифра 7 обознача^ ет, что всего под значение переменной х отводится семь позиций (включая десятичную точку и место под знак, которое резервируется и для положительных чисел), цифра 4 после разделителя-точки обеспечивает точность отображения результата— четыре цифры после десятичной точки. Спецификатор f указывает на то, что следует вывести число в формате с плавающей точкой. Аналогичным образом работает формат %n.8f для вывода у. Примечание При использовании форматного вывода следует учесть, что если количество элементов в списке вывода больше числа кодов формата, то форматные коды применяются повторно, начиная с первого. После выполнения файл-программы из листинга 8.6 содержимое файла twonum.txt составляют два числа — значения переменных х и у с требуемым числом цифр, выводимых на экран ранее написанной функцией myview: -0.7854-0.70710678 Соответствие форматов и получаемого результата приведено на схеме, изображенной на рис. 8.1, каждая позиция подчеркнута. Рис. 8.1. Схема соответствия форматов вывода и результата Значения х и у вывелись одно за другим без разделителя, что затрудняет чтение результата. Можно было бы указать в списке форматов больше позиций под вывод второю числа, например, %7.4f%is.8f'. Поскольку у меньше единицы и выравнивание числа в выделенном для него поле по умолчанию производится по правому краю, то числа в данном случае будут разделены пробелами. Но если в листинге 8.6 заменить у = sin(x) на Глава 8. Обработка данных и приемы программирования в MATLAB 401 у = ioooooo*sin (х), то числа снова не будут разделены. Кроме того, пятнадцати позиций не хватило под вывод у с восьмью знаками после дес>тучной точки, и MATLAB автоматически увеличил поле вывода. Поэтому при задании форматов следует предусмотреть некоторые разделители между числами. Форматы данных можно разделять любым текстом, включая пробелы, который запишется в текстовый файл между соответствующими значениями. Внесите изменения в команду fprintf файл-программы, приведенной в листинге 8.6. Дополните запись в файл некоторыми пояснениями, так как приведено ниже fprintf{F, 'х = %7.4f у = %11.8f', х, у); и выполните файл-программу. Содержимое файла twonum.txt выглядит теперь следующим образом: х = -0.7854 у = -0.70710678 Помещение символа п в спискок форматов приводит к последующему выводу данных с новой строки. Кроме f, допустимы и другие спецификаторы форматов, в частности, спецификатор е означает вывод в экспоненциальной форме (полный список спецификаторов приведен в приложении /). После знакг! процента может размещаться флаг, позволяющий задать некоторые дополнительные параметры отображения чисел. Флаг может принимать следующие значения: □ знак плюс, для отображения знака положительных чисел; □ знак минус, означающий выравнивание числа по левому краю в отведенном для него поле (по умолчанию число выравнивается по правому краю); П цифра ноль, предназначенная для заполнения оставшихся позиций слева от числа нулями. Команды, приведенные ниже, демонстрируют использование флага: а = 0.56; Ъ = 1.1; с = 1.22 fprintf{F, 'а = %+7.3f b = %-ll.lf с = %07.2fn', а, Ь, с}; Дополните ими файл-программу, приведенную в листинге 8.6, и посмотрите результат: а = +0.560 b = 1.1 с = 0001.22 Полезной особенностью fprintf является то, что список ввода может быть матрицей. Матрица выводится по столбцом — с последовательным применением форматов из списка. 402 Часть II. Вычисления и программирование Команды [F, mes] = fopen(‘randmatr.txt', ‘w*); R = rand(3) disp{R) fprintf(F, ’I %7.4f | %7.4f | %7.4f (Xn1, R'); f close (F) ; выводят квадратную матрицу r размера три на три из случайных чисел в командное окно и файл, столбцы в файле разделены вертикальными линиями. Обратите внимание, что аргументом команды fprintf является транспонированная матрица R', т. к. fprintf работает с матрицей по столбцам. Матрица, отображенная в командном окне, совпадает с матрицей, записанной в файл randmatr.txt. Информации о форматах, приведенной выше, вполне достаточно для завершения работы над файл-функцией sintable, предназначенной для вывода таблицы значения функции sin в файл. В случае возникновения затруднений обратитесь к листингу 8.7, в котором приведена часть файл-функции, отвечающая за вывод таблицы (разумеется, данный блок должен предшествовать закрытию файла функцией fciose). Операторы, осуществляющие запись в файл названия и шапки таблицы, приведены в листинге 8.5. % Создание вектора значений аргумента х = 0:pi/2:2*pi; % Конструирование матрицы, пе] вая строка которой содержит % значение аргумента, а вторая — значения функции sin М = [х; sin(x) ]; % форматный вывод элементов матрицы fprintf(F, 1|%7.3f|%10.4f|n', M); Вставьте вышеприведенный блок операторов в вашу файл-функцию sin table и вызови! е ее, указав в качестве входного аргумента строку с именем файла table.dat. В результате создается файл table.dat, содержимое которого приведено ниже: ТАБЛИЦА ЗНАЧЕНИЙ ФУНКЦИИ sin(x) | у= sin(x)| | 0.0001 0.00001 Гпава 8. Обработка данных и приемы программирования в MATLAB 403 I 1.571( 1.00001 I 3.1421 0.00001 I 4.7121 -1.00001 6.2831 -0.00001 Простые структуры Структура представляет собой элемент данных, содержащий разнотипные поля, например, числа, массивы и строки. Вам уже приходилось иметь дело со структурами при чтении главы 6, в которой была описана генерация структуры options специальными функциями optimset и odeset с целью управления процессом вычислений. Решение уравнений при помощи fzero потребовало задания значений полей Tolx, ToiFun, Display, причем сами значения были как числами, гак и строками. Научимся теперь создавать собственные структуры и оперировать данными, хранящимися в их полях. Создание простой структуры осуществляется командой struct, имеющей формат: имя_структуры = struct(имя_поля1,значение!,имя_поля2,значение2,...) где именами полей являются строки или строковые переменные, а значениями — данные любых типов, включая числовые массивы, строки, массивы строк и структуры. Следующая команда создает структуру transaction, содержащую параметры сделки по ценным бумагам (можно набирать в одну строку без символа переноса строки ..., используемого в MATLAB): » transaction = struct('time', [10,20,46], ’stock', 'RESR', 'volume',... 10000, 'price', 0.23, 'currency', 'USD', 'bid', 0.21, 'ask', 0.27) Результат сразу же вывелся в командное окно в форме таблицы, каждая строка которой содержит название поля и его значение: transaction = time: [10 20 46] stock: 'EESR' volume: 10000 price: 0.2300 currency: 'USD1 bid: 0.2100 ask: 0.2700 Поля стуктуры transaction имеют следующий смысл: time— время совершения сделки, stock — код ценной бумаги, volume — объем сделки, price — цена исполнения сделки, currency — код валюты расчетов по сделке, bid — цена спроса на момент совершения сделки, ask — цена предложения на мо- 14 Зак. ВО 404 Часть II. Вычисления и программирование мент совершения сделки. В рассматриваемой структуре значениями полей являются числа, строки и массив чисел. Значения полей можно посмотреть и в окне Workspace. До главы 20, где будут детально рассмотрены способы представления даты и времени и функции для работы с ними, мы будем записывать эти данные в собственном формате. В данном случае время задается массивом из трех чисел: часы (от 0 до 24), минуты и секунды (от 0 до 60). Обращение к значению поля обеспечивается идентификатором, состоящим из имени структуры и имени поля, разделенных точкой. Такое составное имя всегда интерпретируется как обращение к полю структуры. Сумма сделки в рублях может быть вычислена с использованием содержимого полей структуры и курса ЦБ РФ на дату совершения сделки exchange: >> exchange = 28.5214,- >> format bank >> settlement = exchange * transaction.price * transaction.volume settlement = 65599.22 Изменение формата вывода результата желательно для получения ответа в фирме, удобной при проведении финансовых вычислений. Полями структуры могут быть другие структуры. В структуре transaction имеются три однотипых поля — это цена исполнения, цена предложения и цена спроса. Все они связаны с валютой. Изменим структуру transaction, выделив эти поля в одну новую структуру strike: » transaction = struct('time', [10,20,46],'stock', 'EESR‘, 'volume', ... 10000, 'strike', struct('currency', 'USD', 'price',0.23, 'bid', 0.21, ... 'ask', 0.27)) transaction - time: [10 20 46] stock: 'EESR' volume: 10000 strike: [1x1 struct] Для доступа к полю второй структуры следует использовать составное имя включающее имя основной структуры, имя вложенной структуры и имя поля, разделенные точкой. Цена сделки теперь вычисляется по формуле: » settlement = exchange*transaction.strike.price*transaction.volume Глава 8. Обработка данных и приемы программирования в MATLAB 405 Выражения для задания вложенной структуры можно (и нужно для упрощения) разбить на части, результат получится тот же самый >> А = struct!'currency', 'USD', 'price', 0.23, 'bid', 0.21, ... 'ask1, 0.27}; >> transaction = struct('time', [10, 20, 46], 'stock', 'EESR',... 'volume', 10000, 'strike', A) transaction = time: [10 20 46] stock: 'EESR' volume: 1Э000 strike: [lxl struct] Обратите внимание, что при выводе структуры transaction в командное окно поля вложенной структуры strike не отображаются. Для того чтобы посмотреть значения полей вложенной структуры, следует обратиться именно к ней: » transact!on.strike ans = currency: 'USD' price: 0.2300 bid: 0.2100 ask: 0.2700 Существующая структура может быть изменена, если добавить или удалить поле. Добавление поля происходит при присвоении некоторого значения ранее не существовавшему полю. Примечание Присвоение полю значения позволяет создавать структуры. Например, если в рабочей среде нет переменной S, или она есть, но не является структурой, то оператор присваивания S.h = 17 приводит к созданию структуры S с полем h, в котором записано число 17. Добавим поле exchange в структуру а. >> A.exchange - 26.5214 А = currency: 'USD' price: 0.23 bid: 0.21 ask: 0.27 exchange: 26.5214 406 Часть II. Вычисления и программирование При этом не происходит автоматического изменения структуры transact] on: >> transaction.strike.exchange ??? Reference to non-existent field 'exchange'. Для внесения изменений в структуру transaction следует изменить поле strike: » transaction.strike = А; » transaction.strike.exchange ans = 28.5214 Удаление поля осуществляется с помощью функции rmtield. Удалите, к примеру, поле time » transaction = rmfield(transaction, 'time ') Если в качестве выходного аргумента rmfield указать другое имя, то старая структура останется без изменений, а новая будет соответствовать старой с удаленным полем. При обращении к полю структуры его имя можно задавать текстовой строкой в круглых скобках после точки: » transaction.('volume') ans - 10000 Это дает возможность использовать строковую переменную для идентификации поля: >> field ='volume'; >> transaction.(field) ans = 10000 Возникает вопрос, как по имени структуры узнать названия ее полей и сохранить их в строковых переменных. Для этой цели служит встроенная функция fieldnames: » names - fieldnames(transaction) names = 'stock’ 'volume' 'strike' Посмотрите в окне Workspace браузера переменных рабочей среды инфор-мацню о переменной names* Она представляет собой не массив строк, а от Глава 8. Обработка данных и приемы программирования в MATLAB 407 носится к типу cell array (массив ячеек). Работу с таким типом данных мы рассмотрим далее в этой главе. Заметим сейчас, что для выделения содержимого ячейки из массива следует указать ее номер в фигурных скобках после имени массива ячеек. Например, обращение » f2 = names{2} 12 - voJ ume приводит к записи содержимого второго элемента массива ячеек names в строковую переменную 12, которую можно теперь использовать для доступа К нужному ПОЛЮ структуры transaction » v = transaction.(12) v = 10000 Просмотр и редактирование содержимою полей структуры transaction удобно производить в редакторе массивов (Array Editor), который открывается двойным щелчком кнопкой мыши по имени структуры в окне Workspace. При чтении главы 2 вы уже прибегали к редактору массивов для доступа к элементам числовых массивов. Рассмотрим теперь некоторые ею возможности для работы со структурами. Рис. 8.2. Просмотр вложенной структуры с помощью Array Editor 408 Часть II. Вычисления и программирование Редактор массивов позволяет обратиться к значениям полей структуры, в том числе и к полю со вложенной структурой strike, при помощи двойною щелчка мыши по названию поля в столбике Field. Содержимое поля открывается в новом окне редактора массивов, причем окно снабжено вкладкой с именем поля (рис. 8.2). Итак, двойной щелчок мышью приводит к отображению содержимого поля. Обычный щелчок по имени поля в столбике Field делает это поле текущим, а повторный щелчок позволяет изменить название поля. Ввод нового имени поля завершается нажатием <Enter> или щелчком мыши по другому полю. Кнопка Up на панели инструментов редактора массивов служит для перехода вверх по урввням вложенности, т. е. при активном окне с содержимым некоторого поля структуры transaction, например, поля strike, нажатие на Up приведет к отображению структуры transaction. Массивы структур и массивы ячеек Обычные массивы удобны при работе с однородными данными — числами или строками. Информация может быть представлена в виде таблицы с полями, содержащими однотипные элементы, в этом случае наилучшим выбором является массив структур. Эффективное оперирование группой данных различных типов позволяет осуществить массивы ячеек, работу с которыми мы рассмотрим чуть позже. Массивы структур Проиллюстрируем использование массивов структур на простом примере. Предположим, что успеваемость группы студентов по шести предметам представлена в табл.8.1. Таблица 8.1. Успеваемость студентов группы 201 № Фамилия Имя Год рождения Оценки по предметам I II III IV V VI 1 Алексеев Иван 1980 5 4 4 5 5 4 2 Васильев С ергей 1981 3 4 4 3 5 4 3 Кашин Павел 1979 4 3 4 4 5 4 4 С срова Наталья 1981 4 3 3 5 4 5 5 Терехова Ольга 1980 5 5 5 5 4 5 Гпава 8 Обработка данных и приемы программирования в MATLAB 409 Для хранения информации естественно задействовать массив структур, каждый элемент которого является структурой с одинаковым набором полей, содержащих соответствующее значение. Информация о каждом студенте заключена в структуре со следующими полями: □ фамилия (Family), содержит строку с фамилией; □ имя (мате), содержит строку с именем; О ГОД рождения (Year), Содержит ЧИСЛО', □ оценки (Marks), содержит массив из шести элементов с оценками. Схема, демонстрирующая организацию данных табл. 8.1 в виде массива структур, приведена на рис. 8.3. Family Алексеев Name Иван Year 1980 Marks 544 55 4 Family Ьасильев Name Сергей Year 1981 Marks 34 43 54 Family Терехова Name Ольга Year 1980 Marks 555545 Рис. 8.3. Организация таблицы в виде массива структур При работе с массивами структур необходимо придерживаться двух правил. 1. Доступ к структурам, входящим в массив, осуществляется при помощи индексации. 2 Поле отделяется от имени элемента массива структур при помощи точки. Поскольку каждый элемент массива структур является структурой, то допускаются два способа создания и заполнения массива структур — операторами присваивания для всех полей каждой структуры массива или функцией struct, позволяющей занести значения сразу во все поля структуры. Операторы присваивания, последовательно заполняющие массив структур данными из табл. 8.1, приведены в листинге 8.8. Альтернативный вариант занесения информации в поля структур массива состоит в последовательном 410 Часть II Вычисления и программирование применении функции struct для заполнения каждой структуры, входящей в массив, например, для первой структуры: GR201(l) = struct)’Family1, 'Алексеев*, 'Name', 'Иван', ... ’Year', 1980, ‘Marks', [544554]); .....................”* ......XT”?*........... ’ ....... Листинг 8.8. Заполнение масс* ва структур при помощи операторов прис гивания ................................... .......... z.-............................ .л.:..____.... . ........ > Заполнение первой структуры массива GR201(1).Family = ’Алексеев'; GR201(1).Name = 'Иван'; GR201(1).Year = 1980; GR201(1).Marks = [544554]; % Заполнение второй структуры массива GR201(2).Family = 'Васильев'; GR201 (2) .Name = 'Сергей'; GR201(2).Year = 1981; GR201(2).Marks =[344354]; % Заполнение третьей структуры массива GR201(3).Family = 'Кашин'; GR201{3).Name = 'Павел’; GR201(3).Year = 1979; GR201(3).Marks =[434454]; % Заполнение четвертой структуры массива GR201(4).Family = 'Серова'; GR201(4}.Name = ’Наталья'; GR201(4).Year = 1981; GR201(4).Marks =[433545]; ' Заполнение пятой структуры массива GR2C1(5).Family = 'Терехова'; GR2 01(5).Name = ’Ольга'; GR201(5).Year = 1980; GR201(5).Marks =[555545]; Заполните массив структур GR201, создав ф1айл-программу GR201F111 в соответствии с листингом 8.8. Посмотрите значение переменной GR201 из командной строки: » GR201 GR201 = Гпава 8. Обработка данных и приемы программирования в MATLAB 411 1x5 struct array with fields: Family Name Year Marks В отличие от переменных, содержащих числа, массивы, строки или простые структуры, задание имени массива структур не приводит к отображению в командном окне значений полей. Выводится только информация о размере структуры и названиях полей. Просмотр содержимого полей какой-либо структуры массива требует задания ее индекса: » GR201(3) ans = Family: 1 Кашин1 Nar..e: ’ Павел' Year: 1979 Marks: [434454] f’Hg, гЖАИИР** -1л, 'ЕЖ -1Q2SJ Fte Edit View Graphics Peuug Desktop Window Help n Filo Edit View GreoSot t sbug Desktop Window Hdp J tffl l|c Fairily Name Year Mart* ДЙ Airay Editor - GR2D1 BHD He Edit View Debus Desktop Window Help » F X Ifl 1 <St Efe Si I FS?! * j ТЙ 1 Stockists». -1 ' ЕЗ CO В 61 [ЁГ Value 'Алексеев Иван' 19И_ [5 4 4 5 S 41 Fl' Famiv I- a Year H rks Value Ьосильев' Сергей' 1981 [34 43 5 41 : 3 4 5 I 1 ii| <1x1 stm. <1x1 stm. , <1x1 siru . <1x1 slm <1x1 stm.. Рис. 8.4. Просмотр элементов массива структур с помощью Array Editor 412 Часть II. Вычисления и программирование Для контроля и изменения значений полей массива структур удобно пользоваться редактором массивов. Двойной щелчок мышью по одной из клетрк таблицы со структурой приводит к появлению ее содержимого в окне, снабженном вкладкой с именем массива и номером структуры. Если требуется одновременно просмотреть несколько структур массива (рис. 8.4), удобно вывести их в разные окна редактора при помощи кнопки L ndock в строке меню. Указание поля структуры позволяет получить доступ к его значению: » GR201(2,.Year ans = 1981 Функция length, примененная к массиву структур GR201, возвращает его длину, т. е. количество входящих в него структур: » length(GR201) ans = 5 Дополните файл-программу, приведенную в листинге 8.8, операторами, выводящими значения полей структур. Используйте цикл for для перебора всех элементов массива GR201 (листинг 8.9). ....•tv -... • * ’ "С...;.............•'”'"•""J'r* Листинг 8.9. Вывод значений полей структуры в командное окно Len = length(GR201); for k = 1:Len disp (GR201 (k)) end Массивы структур могут быть двумерными, тогда обращение к какой-либо структуре осущесз вляется при помощи двух индексов, а для выяснения размеров массива следует обратиться к функции size. Проход по всем элементам двумерною массива структур можно организовать при помощи двух вложенных циклов for. Примечание Двумерные массивы структур хранятся в памяти по столбцам, как и двумерные числовые массивы, поэтому допустимо обращение к их элементам с одним индексом. Гпава 8. Обработка данных и приемы программирования в MATLAB 413 Создание файл-функций для работы массивами структур Обработка данных, содержащихся в массивах структур, требует написания собственных файл-функции. Массив структур передается в качестве аргумента файл-функции, доступ к содержимому полей осуществляется при помощи имен полей структуры так, как описано выше. Операции, применяемые к значениям полей, должны соответствовать содержащимся в них данным. Создайте файл-функцию groupprogr, отображающую среднюю успеваемость группы студентов по каждому курсу (см. табл. 8.1). Результат представьте в виде столбцевой диаграммы, число столбцов которой равно числу курсов. Алгоритм решения достаточно прост. Следует определить число студентов, используя функцию length для нахождения размера массива структуры, и количество курсов, т. е. длину вектора, хранящегося в поле Marks какой-либо структуры. Далее перебором по всем курсам и студентам при помощи двух вложенных циклов for найдите среднее арифметическое из оценок студентов за каждый курс. Запишите результат в вектор-строку и получите столбцевую диаграмму, используя функцию bar. Текст файл-функции groupprogr приведен в листинге 8.10. Листинг 8/п Файл-функ ия groupprogr для определения успеваемости ^группы ....................... - ......Г. ........ . ....._______.w,. . .. . .. . function meanmarks = groupprog(GROUP); % функция вычисляет средний балл студентов по каждому гредмету % и выводит результат в виде столбцевой диаграммы. % Возвращает массив, каждый элемент которого равен % среднему баллу по предмету с соответствующим номером % использование meanmark = groupprog(GROUP) % GROUP — массив структур с полями % Family (строка), Name (строка), Year (число), % Marks (вектор-строка с отметками) % нахождение числа студентов в группе N = length(GROUP); % Определение количества курсов по информации для % первого студента Courses = length(GROUP(1).Marks); % Инициализация массива meanmarks и запс. шение его нулями meanmarks = zeros(1, Courses); 414 Часть II. Вычисления и программирование % Перебор курсов и вычйвление средней успеваемости for course = 1:Courses % Суммирование баллов, получ, иных каждым из студ< :нтов по % курсу с номером course for student = 1:N meanmarks(course) = meanmarks(course) GROUP(student).Marks(course); end % Нахождение среднего арифметического meanmarks(course) = meanmarks(course) / N; end % Построение столбцевой диаграммы bar(meanmarks); Проверьте работу файл-функции groupprog на примере структуры GR2C1. Запись данных массивов структур в текстовый файл Работа с большими объемами данных, содержащихся в массивах структур, значительно облегчается при использовании текстовых файлов для хранения и считывания информации. Запись информации из массива структур в текстовый файл требует применения форматного вывода функцией fprintf (описание форматного вывода приведено в разд. "Форматный вывод" данной главы). Список вывода fprintf состоит из полей, значения которых необходимо записать в текстовый файл, а форматы соответствуют типам данных, хранящимся в полях. Напишите файл-функцию writegroup, которая реализует построчный вывод значений всех полей структур массива с информацией об успеваемости группы студентов. Имя текстового файла и массив структур являются входными аргумензами writegroup. Содержимое файла должно иметь организацию, схожую с табл. 8.1, например такую, как приведена в листинге 8.11. Установите фиксированное число отводимых позиций под вывод строк и чисел и выравнивание в области вывода по левому краю при помощи флага. Для вывода значения поля структуры, содержащего строку, примените спецификатор формата s. Например, формат *%-10з’ означает выравнивание строки по левому краю в поле вывода из 10 позиций. Гпава 8. Обработка данных и приемы программирования в MATLAB 415 Фамилия Имя Год Оценки Алексеев Иван 1980 5 4 4 5 5 4 Васильев Сергей. 1981 3 4 4 3 5 4 Кашин Павел 1979 4 3 4 4 5 4 Серова Наталья 1981 4 3 3 5 4 5 Терехова Ольга 1980 5 5 5 5 4 5 Воспользуйтесь листингом 8.12 в случае возникновения затруднений. «... •миишж • • • „|»ЧМ»ЧЬ. >••*>•>•»»». . - . .aiauiaau,utuu .... .. Листинг 8.12. Факir -функция wrV-agroup для записи информации о группе : в файл function writegroup(filename, GROUP) % Файл-фучк^ч для записи таблицы с успеваемостью группы % студентов в текстовый файл. % Использование writegroup(filename, GROUP) % fiJ ename ~ имя файла % group — массив структур с полями % Family (строка), Name (строка), Year (число), % Marks (вектор-строка с шестью отметками) % Нахождение числа студентов в группе W = length(GROUP); % Открытие файла с именем filename для записи F = fopen(filename, 'w'); % Запись шапки таблицы с выравниванием по левому краю каждой строки fprintf(F, ’%-14s %-10s %-4s %-6sn',... 1 Фамилия', 1Имя', ’Год’ , 'Оценки'); % Запись в файл содержимого полей каждой структуры в строку for s = 1:N fprintf(F, '%-14s %-10s $4.Of... %2.0f %2.0f %2.0f %2.0f %2.0f %2.0fn',... GROUP(s).Family, GROUP(s).Name, GROUP(s).Year, GROUP(s).Marks); end % Закрытие файла fciose(F); 416 Часть И. Вычисления и программирование Конечно, эффективная работа с данными невозможна без умения считывать их из файла. Следующий раздел посвящен получению информации из текстового файла, имеющего определенный формат Считывание информации из текстового файла Функция fscanf позволяет последовательно считывать данные из текстового файла, разделенные одним или несколькими пробелами, и записывать их в переменные подходящих типов. Условно можно считать, что fscanf осуществляет обратное действие по отношению к fprintf, а именно, считывание в заданном формате. Содержимое текстового файла составляют такие элементы, как текст и числа. Текст всегда считываегся в строковые переменные, а числа можно занести как в строковые, так и числовые переменные. Вызов функции fscanf производится с тремя входными аргументами — идентификатором файла, строкой с форматом, числом считываемых в данном формате объектов и одним выходным аргументом, в который записывается результат. а = fscanf(идентификатор, ’список_фирматов’, число считываемых элементов) Для считывания строки предусмотрен спецификатор формата s, для целых чисел— d, а для вещественных— д. Необходимо следить за соответствием формата и данных, хранящихся в файле. Работу с функцией fscanf проще всего понять на нескольких простых примерах. Пусть, например, в файле student! .txt. состоящем из одной ст роки, содержится информация о студенте: Александров 1990 учащийся 201 4.5 Файл-программа, приведенная в листинге 8.13, записывает фамилию Александров в строковую переменную Family, целое число (год) 1990 — в переменную Year, звание учащийся— в строковую переменную status, целое число (номер группы) 201— в Group, вещественное число (средний балл) 4.5 — в меапмагк. Считывание сопровождается выводом в командное окно для контроля. ..........:....'Г*................. —...’ Листинг 8.13. Поэлементное считывание _____ ____ . j • ... - . : ______ nsn I ипл I Oiuunnw ........ .................-«.ж F = fopen('studentl.txt', 'r'); Family - fscanf(F, ' %s’, 1) Year = fscanf(F, '%d', 1) Status - fscanf(F, '%s', 1) Group = fscanf(F, '%s’( 1) McanMark = fscanftF, '%g', 1) fclose(F); Глава 8. Обработка данных и приемы программирования в MATLAB 417 Разобранный выше пример демонстрирует самый простой вариант использования fscanf— поэлементное считывание, при котором каждый вызов fscanf заносит в переменную соответствующее значение. Замените команды с fscanf (листинг 8.13) на одну str = fscanf(F, ’%s', 5) и посмотрите содержимое str. В данном случае вся информация интерпретируется как текстовая и заносится в одну строковую переменную: str = Александров!990учащийся2014.5 Допустимо не указывать число считываемых объектов и вызывать функцию fscanf только с двумя входными аргументами. Если при этом используется формат %s, то все содержимое считается в строковую переменную так же, как показано выше. Числовые форматы %d и %д позволяют записать содержимое файла, состоящего из чисел, в вектор. Считывание чисел продолжается до тех пор, пока не будет достигнут конец файла или не встретится текст. Пусть, например, в файле res.dat хранится следующая информация (необязательно в одну строку): 1.2274 1.4998 -2.0337 {результаты измерений) Функция fscanf (листинг 8.14) заносит числовые значения в вектор vect, состоящий из трех элементов, и отображает его содержимое в командном окне. Для последующего считывания строки перед закрытием файла следовало бы применить fscanf с форматом %s. Листинг 8.14, Считывание чисел в вектор ................... ....... Мий!............................ F = fopen{1 res.dat’, 'г'); vect = fscanf(F, ’ %g') f close (F) ; Если числовая информация, представленная в файле, обладает матричной структурой, то задание вектора, содержащего размеры матрицы, в качестве третьего аргумента fscanf позволяет записать информацию в матрицу. Создайте файл с матрицей размера три на четыре, приведенный в листинге 8.15. ........................................................ ................... .......,.................................................................................. ..... Листинг 8.15. Содержимое текстового файла для ввода матрицы - . ... . . .. ........5.»......». ........................................................Г... л.......... .. . . . .......................- ....... 1.4 5.2 0.4 -1.1 -2.1 3.6 7.1 0.8 2.0 2.9 8.3 -0.1 418 Часть II. Вычисления и программирование Используйте команду м = fscanf(f, '%g*, [3 4]) для заполнения матрицы данными из файла и выведите ее содержимое в командное окно. Матрица считалась из файла в заданном виде. Расположение матрицы в виде таблицы в файле необязательно, ее элементы могут быть записаны в строку, столбец или произвольным образом. Способ формирования матрицы задается вектором, указанным в списке входных параметров fscanf, а сами элементы считываются последовательно и помещаются в нужные позиции. Для того чтобы убедиться в этом, считайте из файла (листинг 8,15) матрицу командами И = fscanf(F, К = fscanf(F, Р = fscanf(F, R = fscanf(F, ’%g', [43]) '%g', [6 2]) %g', [12 1]) ' %g', [2 6]) и посмотрите результат, отобразив содержимое матриц в командном окне. Важно только, чтобы в файле имелось достаточно элементов для формирования матрицы. Информация, хранящаяся в файле, может представлять собой таблицу определенной структуры, например, такой, как в листинге 8.11. Все столбцы имеют одинаковое назначение и содержат элементы одного типа. Использование массивов структур значительно облегчает работу с подобными файлами. Напишите самостоятельно файл-функцию readgroup для считывания данных в массив структур с полями Family, Kame (строковые переменные), Year (числовая переменная), Marks (вектор-строка из целых чисел) Имя текстового файла задается во входном аргументе readgroup, а выходным аргументом является массив структур (доступ к полям структур массива описан в ргид. "Массивы структур"данной главы). Реализуйте следующий алгоритм в файл-функции. 1. Первая строка является шапкой таблицы, ее не следует заносить в структуру. Используйте функцию fgetl для считывания первой строки. 2. Примените поэлементное считывание в подходящих форматах для заполнения структур массива информацией, содержащейся в каждой строке файда, начиная со второй. 3. Используйте счет чик для обращения к структ)рам массива, который увеличивается на единицу перед работой с новой структурой. 4. Считывание производите в цикле while, пока не будег достигнут конец файла. 5. При считывании оценок в вектор-строку задайте требуемый размер (один на шесть) в третьем аргументе fscanf. функция readgroup для считывания информации из файла Гпава 8. Обработка данных и приемы программирования в MATLAB 419 Листинг 8.16 содержит возможный вариант файл-функции readgroup. : Листинг 8.16. Ф II п ; в массив структур function GROUP = readgrouptfilename) % Файл-функция для считывания таблицы с успеваемостью группы % студентов из текстового файла в массив структур. % Использование writegrouptfilename, GROUP) % filename — имя файла % group — массив структур с полями % Family (строк i), Name (строка), Year (число), % Marks (вектор-строка с шестью отметками) % Открытие текстового файла с именем filename для записи F = fopen(filename, 'rt’); % Считывание первой строки с шапкой таблицы if feof(F) == О line = fgetl(F); end % Обнуление счетчика числа студентов count = 0; % Создание пустого массива структур GROUP = [ ]; 1 Последовательное считывание строк (начиная со второй) % и распределение информации, содержащейся в ней, % по полям структур массива GROUP. Каждая строка файла ? содержит информацию об одном студенте while fenf fF) == 0 count = count + 1; % увеличение счетчика студентов % Считывание строки с фамилией GROUP (count).Family = fscanf(F, '%s', 1); % Считывание строки с именем GROUP(count).Name = fscanf(F, '%s', 1); % Считывание года рождения GROUP(count).Year = fscanf(F, '%d', 1); 420 Часть II Вычисления и программирование % Считьиэание массива с оценками в вектор-столбец GROUP(count).Marks = fscanf(F, '%d', [1, 6]); end % Закрытие файла fciose(F); Операции с массивами структур Каждый элемент массива структур является простой структурой, и к нему применимы операции и функции для простой структуры, описанные выше. Однако все структуры массива должны иметь одинаковые имена полей, поэтому изменение поля (но не его значения) в одной структуре неизбежно влечет аналогичные изменения во всех структурах массива. Добавление нового поля во все структуры массива осуществляется при помощи оператора присваивания, в левой части которого задается название нового поля, а в правой части — его значение для данной структуры массива. Дополните первую структуру массива GR201 (листинг 8.8) полем квоок, содержащим номер зачетной книжки студента: CR291(1).NBook = 127001; Проверьте, что поле NBook добавилось во все структуры массива. Наберите GR201 в командной строке и нажмите <Enter> для получения информации о массиве структур. Значение 127001 занесено в поле NBook только первой структуры, поле NBook остальных структур пока содержат пустые массивы, например: » GR201(2).NBook ans = [ 1 Заполнение поля NBook остальных структур производится аналогичными операторами присваивания. Для удаления поля простой структуры мы использовали функцию rmfield. В случае массива структур она удаляет выбранное поле во всех структурах массива. Первым ее входным аргументом является имя массива, а вторым — строка или строковая переменная с названием поля. Преобразованная структура возвращается в выходном аргументе rmfield. Удалите, например, поле Year из структур массива GR201 (см. листинг 8.8) и запишите результат в массив д201: g201 = rmfield(GR2C1, ’Year') Вторым аргументом функции rmfield может быть массив строк, содержащий названия удаляемых полей. Гпава 8. Обработка данных и приемы программирования в MATLAB 421 Формирование массива строк описано в разд. "Массивы строк" данной главы. Удобную возможность для получения названия всех полей сгруктуры предоставляет функция fieldnames, входным аргументом которой является массив структур, а выходным — массив ячеек, содержащий строки с названиями полей. Определение названий полей массива структур, запись их в строковые переменные и дальнейшее использование ничем не отличаются от случая простой структуры. » GRFields = fieldnames(GR201) GRFields = 'Family’ 'Name' 'Year' 'Marks' 'Nbook' » f4 = GRFields{4) f4 = Marks » M5 = GR201(5).{£4) M5 = 5 5 5 5 4 5 Полученные строковые переменные или строки с названием имени поля используются в качестве входных аргументов функций getfield и setfield, которые, соответственно, предназначены для получения и установки значения поля структуры. Примеры вызова getfield и setfield приведены ниже. » Namel = getfield(GR201(1), 'Name'); » GR201(2) = setfield(GR201(2), 'Name', 'Алексей'); При написании собственных файл-функций для работы со структурами используйте isstruct для проверки, является ли переменная структурой или нет. Входным аргументом isstruct задается переменная, подлежащая проверке, а результатом является либо "истина” (логическая единица), либо "ложь" (логический ноль). Перед обращением к полю полезно убедиться в том, что оно определено в структуре при помощи функции isf ieid. Первый входной аргумент isfield является именем структуры, а второй — строковой переменной с названием поля. Функция isfield возвращает так же логический ноль или единицу. Массивы ячеек Кроме числовых массивов, массивов строк и структур в MATLAB определен еще один тип переменных — массив ячеек, который хорошо приспособ 422 Часть II. Вычисления и программировав ие лен для хранения разнородных данных. В данном разделе приведены основные сведения, касающиеся массивов ячеек, которые понадобятся, в частности, при создании функций с переменным числом аргументов. Массив ячеек состоит из ячеек или контейнеров, каждый из которых может содержать данные различных типов. Организация данных массива ячеек более удобна по сравнению с массивом структур в том случае, когда не представляется возможным выделить однотипные поля, или когда требуется упростить доступ к отдельным типам данных. В качестве примера рассмол -рим обработку информации о результатах экспериментов, представленных в виде прямоугольных матриц размера два на три. Каждый эксперимент производил студент, его фамилия, имя и номер группы хранятся в структуре. Эксперименты происходили при заданных преподавателем значениях параметров (рис. 8.5). Обратите внимание, что содержимое контейнеров действительно разнородно, даже структуры имеют отличающиеся поля, а в ячейку (4,3) занесена запись о невыполнении эксперимента. Заполнение массива ячеек осуществляется поэлементно, причем для доступа к отдельным контейнерам применяется индексация, индексы заключаются в фигурные скобки. Способ присваивания значений определяется типом данных, например, при внесении структуры следует отделить поле от ячейки при помощи точки. Листинг 8.17 содержит файл-программу, заносящую информацию (см. рис. 8.5) в контейнеры массива ячеек exper. ячейка 1,1] ячейка 1,2| ячейка 1,3] доц. Петров доц. Гришин асс-Зинин ячейка 2,1] ячейка 2,2] ячейка 2,2] 2.2 0.3 1.7 вариант N2 2.0 0.2 1.4 ячейка 3, ] ячейка 3,2| ячейка 3,3 Family Иванов Name Алексей Group 201 Family Сергеев Name Антон Group 202 Family Пашин Name Антон Info Вечерн. ф.-т ячейка 4,1] ячейка 4,2] ячейка 4,2] -1.33 0.35 1.74 0.99 0.98 0.78 -1.43 0.24 1.88 0.90 0.91 0.59 рез. не получен Рис. 8.5. Содержимое ячеек Глава 8. Обработка данных и приемы программирования в MATLAB 423 Если имя создаваемого массива ячеек занято в рабочей среде под обычный массив, то перед поэлементным заполнением массива ячеек следует удалить его из рабочей среды командой clear или из окна Workspace браузера переменных, иначе MATLAB выдаст сообщение об ошибке. ------------.............................. : Листинг 8.17. Заполнение массива ячеек . ГЛЖЯ.ЙЙЬЯ............. .......... % ЗАПОЛНЕНИЕ ПЕРВОГО СТОЛБЦА МАССИВА EXPER % Занесение строки с информацией о преподавателе в ячейку (1, 1) EXPER{1, 1} = ’доц. Петров Е.А.’; % Занесение вектора параметров в ячейку (2, 1) EXPER{2, 1} = [2.2 0.3 1.7]; % Занесение структуры с информацией о студенте в ячейку (3, 1) EXPER{3, 1].Family = ‘Иванов’; EXPER(3, l}.Name = ‘Алексей’; EXPER(3, 1].Group = 201; % Занесение результатов эксперимента в ячейку (4, 1) EXPER(4,1) = [-1.33 0.35 1.74; 0.99 0.98 0.78]; S ЗАПОЛНЕНИЕ ВТОРОГО СТОЛБЦА МАССИВА EXPER % Занесение строки с информацией о преподавателе в ячейку (1, 2) EXPERfl, 2} = ’доц. Гришин С.Е.’; % Занесение вектора параметров в ячейку (2, 2) EXPER{2, 2} = ’Вариант N2’; % Занесение структуры с информацией о студенте в ячейку (3, 2) EXPER(3, 2}.Family - ‘Сергеев’; EXPER{3, 2).Name = ‘Антон’; EXPER[3, 2].Group = 202; % Занесение результатов эксперимента в ячейку (4, 2) EXPER{4, 2} = [-1.43 0.24 1.88; 0.90 0.91 0.59]; % ЗАПОЛНЕНИЕ ТРЕТЬЕГО СТОЛБЦА МАССИВА EXPER % Занесение строки с информацией о преподавателе в ячейку (1, 3) EXPER[1, 3} = ‘асе. Зинин К.О.'; % Занесение вектора параметров в ячейку (2, 3) EXPER{2, 3] = [2.3 0.3 1.5]; 424 Часть II, Вычисления и программирование % Занесение структуры с информацией о студенте в ячейку (3, 3) EXPER{3, 3).Family - 'Пашин1; EXPER{3, 3}.Name - 'Антон1; EXPER(3, 3).Info = 'Вечерн. ф~т'; % Занесение результатов эксперимента в ячейку (4, 3) EXPER{4, 3} = ’рез. не получен’; В результате выполнения команд, приведенных в листинге 817, в рабочей среде создается массив ячеек exper. Просмотр содержимого массива exper из командной строки приводит к отображению информации в сжатом виде: » EXPER EXPER = 'доц. Петров Е.А.' 'дйц. Гришин С.Е.' 'асе. Зинин К.О.’ [1x3 double] 'Вариант N2' [1x3 double] [lxl struct] [lxl struct] [lxl struct] [2x3 double] [2x3 double] [1x20 char ] Функция celldisp с входным аргументом — именем массива ячеек выводит значения всех контейнеров в командное окно. Более наглядным способом представления больших массивов ячеек является отображение схемы массива в графическом окне при помощи cellplot, обращение к которой » cellplot(EXPER) приводит к появлению графического окна, изображенного на рис. 8.6. Массивы чисел или текстовые строки обозначаются макетами таблиц с соответствующим числом строк и столбцов, а записи — квадратами. Для наглядности на рис 8.6 текстовая строка "Вариант N2" вынесена над обозначением массива, ее содержащего. В дру! их ячейках текстовые строки не выводятся, поскольку они содержат много символов. Способ заполнения массива ячеек, описанный выше, является одним из двух возможных в MATL АВ. Второй способ состоит в том, что обращение к ячейке происходит при помощи обычной индексации в круглых скобках, а в правой части оператора присваивания помещается ячейка, содержимое которой заключается в фигурные скобки. Например, заполнение ячейки (1,1) массива exper (листинг 8.17) может выглядеть следующим образом: EXPERU, 1) = {’доц. Петров Е.А.’] Функция size находит размер массива ячеек: » size(EXPER) ans = 4 3 Глава 8, Обработка данных и приемы программирования в MATLAB 425 Рис. 8.6 Схема массива ячеек (celldisp) Массив ячеек может представая гь собой не только матрицу с контейнерами, но и вектор. Для досту па к содержимому контейнеров в этом случае применяется один индекс в фигурных скобках. Функция length возвращает число ячеек. Доступ к содержимому контейнеров массива ячеек осуществляется при помощи индексов. Обратите внимание, что при обращении к элементам массива ячеек индексы могут заключаться как в круглые, так и фигурные скобки » S = EXPER{3, 2} S = Family: 'Сергеев' Name: 'Антон 1 Group: 202 426 Часть II Вычисления и программирование » С = EXPER(3, 2) С - [1x1 struct] В чем же разница? Изучите тип переменных s и с, например, в окне Workspace браузера рабочей среды. Переменная s является структурой (массивом структур размера 1 на 1), а с— ячейкой (массивом ячеек размера 1 на 1). Поэтому для обращения к содержимому элемента массива ячеек следует использовать фигурные скобки, если с ним требуется выполнить дальнейшие операции, определяемые типом содержимого ячейки. Если же необходимо выделить именно ячейку, то следует указать индексы в круглых скобках. » S.Name ans = Антон Выбирайте нужные скобки, иначе получите сообщение об ошибке » С.Name ??? Attempt to reference field of non-structure array ’C’. Напишите файл-функцию students, возвращающую массив строк с именами студентов, участвовавших в выполнении эксперимента. Входным аргументом файл-функции students (листинг 8.18) должен быть массив ячеек, имеющий такую же схему расположения данных, как и exper, только число столбцов может быть произвольным. Структуры с информацией о студентах размещаются в третьей строке массива ячеек. Число столбцов массива структур опредепите при помощи size. Используйте цикл for для перебора контейнеров со структурами. Строки с фамилиями студентов добавляйте в массив строк при помощи char. Листинг 8.18. Файл-функция students, выделяющая фамилии студентов из массива ячеек function strmas = students(CELLMAS) % файл-функция формирует массив строк с фамилиями % студентов, участвующих в эксперименте. % Использование strmas = students(CELLMAS) % Определен™ размеров массива ячеек SizeMas - size(CELLMAS); % Нахождение числа студентов (информация о деятельности % каждого сдудента хранится в столбце) NStudents = SizeMas(2); Гпава 8. Обработка данных и приемы программирования в MATLAB 427 if NStudents >= 1 % Если число студентов больше или равно е, (инице, то % считываем из поля Family третьей ячейки первого столбца % фамилия студента и заносим в массив строк strmas strmas - CELLMAS{3, 1} .Family; eno % Продолжаем считывание по всем оставшимся столбцам, % начиная со второго for k = 2:NStudents % Считываем фамилию из поля Family третьей ячейки k-го столбца fam = CELLMAS{3, к} .Family; % Добавляем фамилию в массив строк strmas = char(strmas, fam); end Результатом работы файл-функции students является массив строк с фамилиями студентов, участвовавших в проведении эксперимента: » st = students(EXPER) st = Иванов Сергеев Гашин Дополните файл-программу students, приведенную в листинге8.18, проверкой, является ли входной аргумент массивом ячеек. Примените функцию isceii, которая возвращает "истину" (логическую единицу), если ее входной аргумент — массив ячеек, и "ложь" (логический ноль) в противном случае. Имеет смысл также проверять, содержит ли текущая ячейка структуру или нет. Для этого следует воспользоваться функцией isstruct. Кроме того, перед обращением к полю структуры полезно убедиться в его наличии, для чего служит функция isfield. Приложения с интерфейсом из командной строки Хорошо написанная программа позволяет пользователю не только производить вычисления, но и управлять процессом в ходе работы программы. Одним из способов взаимодействия пользователя с приложением является организация интерфейса при помощи командной строки. Перед выполнени 428 Часть II. Вычисления и программирование ем некоторых действий программа приостанавливает работу и выдает запрос в командное окно. Ответ пользователя определяет дальнейший ход выполнения программы. Данный раздел посвящен написанию приложений с таким достаточно примитивным интерфейсом, позволяющим пользователю управлять работой программы. Простой пример, программа-калькулятор Хорошим демонстрационным примером приложения с интерфейсом из командной строки является программа-калькулятор, вычисляющая результат арифметических операций. Пользователь вводит число, затем выбирает арифметическое действие, вводит второе число и получает результат. Для написания такой программы требуется умение организовать вывод текста на экран и получать ответ от пользователя. Как мы уже упоминали, вывод текста в командное окно осуществляется функцией disp. Применение disp обеспечивает только одностороннюю связь программы с пользователем. Для интерактивного взаимодействия следует привлечь еще функцию input. Выходной аргумент input является значением, введенным пользователем с клавиатуры в командную строку в ответ на запрос. Запросом является строка, указанная в качестве входного аргумента, например: n = input('Введите значение п = При выполнении данной команды в командное окно выводится сообщение "Введите значение п = " и выполнение программы приостанавливается до тех пор, пока пользователь не введет число с клавиатуры и не нажмет <Enter>. После выполнения input переменной п присвоится введенное значение. Ошибочный ввод не числа, а, например, символа приведет к сообщению об ошибке и повторному появлению запроса на ввод. Функция input допускает ввод строк в строковую переменную, указанную в качестве выходного аргумента, причем вторым дополнительным входным аргументом следует указать 's’, например: паше = input('Введите имя *, 's' ); На запрос input следует ввести строку, не заключая ее в апострофы, строка записывается в переменную паше. Напишите файл-функцию, реализующую следующий алгоритм. 1. Считывание первого числа в числовую переменную (подмените input). 2. Получение знака арифметической операции (+, -, * или /) и занесение его в строковую переменную (примените input со вторым аргументом ’s’). 3. Считывание второго числа в числовую переменную. Глава 8. Обработка данных и приемы программирования в МА П. АВ 429 4. Выполнение арифметического действия в зависимости от введенного знака операции (используйте оператор переключения switch). 5, Вывод результата в командное окно. Программу оформите в виде файл-функции без входных и выходных аргументов. Текст требуемой файл-функции приведен в листинге 8.19. Г.... " W.W « ^Листинг 8.19 Файл-функция calc function calc % Калькулятор с интерфейсом командной строки % Считывание в числовую переменную числа, введенного пользователем а = input(’Введите первое число 1); % Считывание в строковую переменную операции, введенной пользователем oper = input('Введите арифметическую операцию (+, -, *, /) ’, 's'); % Считывание в числовую переменную числа, введенного пользователем b = input('Введите второе число '); % Вычисление результата арифметической операции switch oper case 1+‘ а + Ь case '-’ а - Ь case 1 *' а * b case '/’ а / Ь otherwise error(1 неизвестная арифметическая операция') end Работа с файл-функцией calc не требует никаких дополнительных пояснений для пользователя, ему достаточно следовать инструкциям, выводимым в командное окно, и результат будет получен. Файл-функция calc достаточно хорошо защищена от неправильного использования. Команда input без дополнительного аргумента • s1 проверяет, что введено число, и повторяет запрос в случае неправильного ввода. Ошибка при выборе арифметической операции обрабатывается ветвью otherwise оператора switch, которая выводит сообщение о неправильно введенной операции. Результат 430 Часть II. Вычисления и программирование пользователь получает в стандартной переменной ans. Диалог файл-функции calc приведен ниже: » calc Введите первое число 1.2 Введите арифметическую операцию (+, *, /) + Введите второе число 3.1 ans - 4.3000 Попробуйте изменить файл-функцию calc так, чтобы ответ имел более наглядный вид Например, если производится сложение 1.2 и 3.1, то в командное окно выводится 1.2 + 3.1 = 4.3. Задача состоит в формировании строки с результатом (из введенных чисел, знака арифметической операции, знака "=", ответа) и выводе ее в командное окно. Обратите внимание, что строка результата формируется как из строк, например,'+’ и так и из чисел 1.2, 3.1,4.3, которые хранятся в переменных. Очевидно, что для получения требуемой строки следует применить сцепление. Перед сцеплением необходимо преобразовать значение переменной в строку при помощи функции num2str, входной аргумент которой является числом или переменной с числовым значением, а выходной — строковой переменной, соответствующей данному числовому значению. Примечание Часто кроме конвертирования числа в строку требуется обратное преобразование строки в число, которое осуществляется функцией str2num. Во входном аргументе задается строка из символов, например: '123.77', или '1.98е-03',ав выходном аргументе возвращается соответствующее число. Входным аргументом может быть и массив строк, который преобразуется в числовой массив. Если преобразование невозможно, например, а = str2num (112А99'), то результатом работы будет пустой массив (подробно о функциях преобразования сказано в приложении 1). Вышеописанная модификация вида результата требует некоторых изменений в тексте файл-функции calc, приведенном в листинге 8.19. Операторы, реализующие ввод пользователя, остаются без изменений. Попытайтесь самостоятельно модернизировать файл-функцию calc, в случае возникновения вопросов обратитесь к листингу 8.20, в котором приведены операторы, обрабатывающие ввод пользователя и выдающие результат. Диалог файл-функцни calc теперь выглядит следующим образом: » calcl_ 4 Введите первое число 1.2 Введите арифметическую операцию (+, , /) + Глава 8. Обработка данных и приемы программирования в MATLAB 431 Введите второе число 3.1 1.2 + 3.1 = 4.3 Листинг 8.20. Улучшение вида результата работы файл-функции calc function calcl % Калькулятор с интерфейсом командной строки % Считывание в числовую переменную числа, введенного пользователем а = input(’Введите первое число '); % Считывание в строковую переменную операции, введенной пользователем oper = input('Введите арифметическую операцию (+, -, *, /) *, 's'); % Считывание в числовую переменную числа, введенного пользователем b = input(1Введите второе число '); % Вычисление результата арифметической операции switch oper case ’+1 res = a + b; case '-' res = a — b; case '*' res = a * b; case 1/' res = a / b; otherwise error(’неизвестная арифметическая операция') end % Преобразование чисел в строки stra = num2str{a); strb = num2str(b); strres = num2strI res); % Сцепление строк str = strcat(stra, oper, strb, steres); % Вывод строки с результатом в командное окно disp(str) Вышеописанные примеры содержат оператор переключения switch, который производит вычисления в зависимости от знака арифметической one- 432 Часть II. Вычисления и программирование рации, выбранного пользователем. Заметьте, что пользователь вводит числа и арифметическую операцию, которые входят в арифметическое выражение, понятное MATLAB. Рациональнее создать с грику с арифметическим выражением, выполнить ее, как команду MATLAB и вывести результат, тем самым избежав перебора. Такой подход позволяет дополнительно использовать возведение в степень, ввод числа и и придает программе более наглядный вид. Действительно незаменимой и очень полезной функцией является eval, которая служит для выполнения команды MATLAB, записанной в строке или строковой переменной. Формирование строки с командой и ее выполнение функцией eval описаны в следующем разделе. Формирование и исполнение команд, функция eval Встроенная функция eval позволяет выполнить строку, которая содержит команду MATJ АВ. Строка с командой является входным аргументом eval, например: » str = ’1 + 2' ; » eval(str) ans = 3 Перед выполнением команду можно сформировать из нескольких с грок: » strl = 'у = sin('; » str2 = '3/2*pi‘; » str3 = ')'; » str = strcatfstrl, str2, str3); » eval(str) У = -1 Используйте функцию eval в файл-программе caici, приведенной в листинге 8.20, для формирования и вычисления результата арифметического выражения без перебора арифметических операций, которое было реализовано оператором switch. Файл-<Ьункция са1с2, приведенная в листинге 8.21, решает поставленную задачу. function calc2 % Калькулятор с интерфейсом командной строки Гпава 8. Обработка данных и приемы программирования в MATLAB 433 % Считывание в строковую переменную операции, введенной пользователем а = input('Введите первое число ‘; % Считывание в строковую переменную операции, введенной пользователем oper = input('Введите арифметическую операцию ( + , *, / ,Л) 's'); % Считывание в строковую переменную операции, введенной пользователем Ь = input('Введите второе число '); % Преобразование чисел в строки stra = num2str(a); strb = num2str(b); I Формирование строки с арифметическим выражением (строка завершается % точкой с запятой для подавления вывода промежуточных результатов % в командное окне str = strcat(’res = stra, oper, strb, 1;1); ‘ Вычисление арифметического выражения, % его результат хранится в переменной res eval(str); % Формирование строки с результатом в виде '1.2 + 3.1 = 4.3' strres = num2str(res); % Сцепление строк str = strcat(stra, oper, strb, ' = ', strres); % Вывод строки с результатом в командное окно disp(str) Интерфейс пользователя, предоставляемый файл-функцией са1с2, точно такой же, как в calcl, текст которой приведен в листинге 8.20. Формирование и выполнение команд MATLAB при помощи eval позволило сделать алгоритм калькулятора более компактным и универсальным. В качестве завершающего упражнения на использование строк и функции eval напишите программу для построения графиков функции одной переменной с интерфейсом пользователя из командной строки. Работа с программой должна выглядеть следующим образом. 1. Запрос функции, график которой требуется построить. Пользователь задает формулу функции без учета поэлементных операций, т. е. например, exp(х)*sin(х),а не exp(х).*sin(х). 2. Запрос границ отрезка. Пользователь вводит левую и правую границы. 3. Запрос цвета, стиля линий и маркеров. Пользователь выбирает номер цвета, стиля и маркера из предлагаемых списков (ограничьте выбор несколькими возможностями для уменьшения объема программы). 434 Часть II. Вычисления и программирование 4. Вывод графика функции в графическое окно. 5. Запрос на продолжение работы с программой. Пользователь вводит 'у' или 'п'. Запрограммируйте алгоритм в файл-функции без входных и выходных аргументов. Оформите весь диалог внутри цикла while, который работает, пока некоторая строковая переменная flag равна 'у'. До цикла присвойте flag значение 'у'. В конце цикла получите ответ от пользователя о продолжении работы при помощи input и занесите ответ в переменную flag. Запишите функцию, введенную пользователем, в строковую переменную, а пределы построения графика— в числовые переменные. Замену обычных операций на поэлементные выполните при помощи strrep. Вывод списка возможных цветов, типов линий и маркеров осуществите функцией disp. Используйте операторы переключения switch для формирования строки с командой plot в зависимости от номера цвета и стиля линии, и типа маркера, выбранных пользователем из списка. Возможный вариант текста файл-функции для визуализации функций с интерфейсом командной строки приведен в листинге 8.22. Заметьте, что при некорректном вводе формулы для отображаемой функции программа myplot прекратит работу. Предположим, что пользователь ввел 1п(х) вместо встроенной 1од(х). Ошибка возникнет при выполнении строки с командой eval при вычислении вектора у значений функции. Улучшите самостоятельно файл-функцию myplot, заключив блоки с возможными источниками ошибок в конструкцию try.. .catch, которая предназначена для обработки исключительных ситуаций. :...... ‘ .....................................................• - -.£ Ё Листинг 8.22. Пример файл-Аучкции myplot с интерфейсом командной строки ’ function myplot( ) % Построение графское функций, % диалог с пользователем из командной строки disp(’ПРОГРАММА ДЛЯ ПОСТРОЕНИЯ ГРАФИКОВ’) disp(’ФУНКЦИЙ ОДНОЙ ПЕРЕМЕННОЙ’) flag = ' у' while flag = ’у’ % Запрос функции strfun = input('Введите функцию, налуимер, ехр(х)*sin(х) ', ’s'); % Запрос левой границь отрезка left = input. (‘Введите левую границу отрезка, например, -1.2 '); % Запрос правой границы отрезка right = input(’Введите правую границу отрезка, например, 1.3 '); .'лава 8. Обработка данных и приемы программирования в MATLAB 435 % Запрос типа линии disp (' Выберите тип линии:') disp(’ сплошная 1') disp(’ пунктирная 2') disp(’ штриховая 3’) linetype = input('Введите 1, 2, или 3 '); % Запрос цвета линии disp(1 Выберите цвет линии:') disp(1 красная 1') disp('синяя 2') di sp('черная 3•) linecolor = input('Введите 1, 2, или 3 '); % Запрос маркери disp ('Выберите тип марю ;ра: ') disp('без маркера 0') disp('звездочка 1') disp('кружок 2’) marker = input(1 Введите 0, 1, или 2 '); % Обработка ввода пользователя, формирование строки % с командой plot и ее выполнение. % Замена арифметических операций на поэлементные str fun = strrep(strfun, strfun = strrep(strfun, '/', './'); strfun = strrep(strfun, 1Л .Л1); % Генерация вектора значений аргумента х = left : (right - left)/30 : right; % Генерирование строки для вычисления вектора значений функции % строка заканчивается точкой с запятой для подавления вывода % промежутсчных результатов на экран strhelp = strcat(’у =’, strfun, % Вычисление вектора значений функции eval(strhelp); % значения функции теперь хранятся в векторе у % Формирование строки с командой plot sLrplct = 'plot(x, у,'; ' Добавление информации о типе линии switch l_netype case 1 strplot = strcat(strplot, 15 3м. 130 436 Часть II. Вычисления и программирование case 2 strplot = strcat(strplot, *'':’); case 3 strplot = strcat(strplot, '''—'); otherwise error(’неизвестный тип линии') end % Добавление информации о цвете линии switch linecolor case 1 strplot - strcat(strplot, 'r'); case 2 strplot = strcat(strplot, *b‘); case 3 strplot = strcat(strplot, 'k'); otherwise error('неизвестный цвет линии') end % Добавление информации о маркере switch marker case О strplot = stj cat(strplot, ''''); case 1 strplot = strcat(strplot, case 2 strplot = strcat(strplot, 'o'''); otherwise error('неизвестный тип маркера’) end % Завершение генерации строки с командой plot strplot - strcat(strplot, ')'); % Выполнение команды plot eval(strplot) % Запрос на продолжение работы flag = input(1 Продолжить работу? (у — да, п — нет)’, 's'); end Гпава 8. Обработка данных и приемы программирования в MATLAB 437 Обработку ввода пользова геля можно производить в бесконечном цикле, задав в качестве условия цикла while единицу, а выход из цикла производить оператором break. Организация вывода текстовых результатов Вывод результатов в удобно читаемой форме — одно из необходимых условий хорошо написанной программы. Для отображения в командном окне результатов работы файл-программы или файл-функции мы применяли функцию disp совместно с преобразованием чисел в строки или допускали вывод значения выражения в командное окно, не завершая оператор присваивания точкой с запятой. Этих приемов зачастую оказывается недостаточно для написания программы, которая общается с пользователем через командное окно. Один из способов организации вывода текстовых данных в командное окно состоит в специальном вызове функции fprintf (которую вы использовали для записи текстовых файлов). Если в качестве идентификатора файла указать единицу или вообще пропустить его, то вывод происходит не в файл, а в командное окно. Создайте, например, файл-программу с текстом листинга 8.7, только исключите идентификатор файла F из списка входных аргументов функции fprintf. Запустите ее и убедитесь, что выводимая в командное окно информация соответствует той, которая ранее записывалась в текстовый файл. Возможности отображения массивов данных в MATLAB не ограничиваются их выводом в текстовый файл или командное окно. Функция openvar позволяет открыть окно редактора массивов Array Editior с содержимым числового массива, массива строк, структур или ячеек, определенного в рабочей среде. Строка или строковая переменная с именем массива указываются во входном аргументе openvar. Например, если в рабочей среде есть массив mas, то следует написать openvar ( 'mas' ). Примите во внимание, что openvar работает только с переменными рабочей среды. Переменные, созданные внутри файл-функции, являются локальными и не видны в рабочей среде, поэтому эта возможность доступна только в файл-программах (классификация переменных описана в разд. ''Подфункции" и "Вложенные ф) акции" главы 5). Файл-функции с переменным числом аргументов Большинство стандартных функций MATLAB допускают обращение к ним с различным числом входных и выходных аргументов, например, функция 438 Часть II. Вычисления и программирование для нахождения минимума fminbnd, которую можно вызвать с одним или более выходными аргументами и с тремя или более входными. При этом алгоритм fminbnd адаптируется к выбору пользователя и осуществляв! требуемую последовательность действий. Обратитесь к встроенной справке по fminbnd при помощи help с именем функции для того, чтобы узнать о всевозможных вариантах вызова. В данном разделе описано создание собственных файл-функций, способных работать с переменным числом аргументов. Вам понадобится использовать массивы ячеек, основные сведения о которых вы получили при чтении этой главы (см. разд. "Массивы ячеек" данной главы). Разберем сначала принцип организации файл-функции с переменным числом входных аргументов на следующем примере. На плоскости задано произвольное количество кругов (координатами центров и радиусами (xl, yl, Ri), (х2, у2, R1) и т. д.) и точка с координатами (рх, ру). Требуется определить, лежит ли точка внутри какого-либо круга или нет (рис. 8.7). Рис. 8.7. Расположение кругов и точки Напишем файл-функцию point, входными аргументами которой будут координаты точки и нескольких вектор-строк из трех элементов, задающих положение кругов, а выходным — число, единица или ноль в зависимости от попадания точки в один из кругов. Для случая, изображенного на рис. 8.7, вызов функции point будет выглядеть следующим образом: f - point(px, ру, [xl yl Rl], [x2 y2 R2], [хЗ y3 R3] , [х4 у4 R4]) Первые три входных аргумента являются обязательными, но число векто-ров-стрик соответствует числу кругов и может быть различным. MATLAB предла! ает простой способ решения проблемы. Все входные аргументы упаковываются в специальный массив (вектор) ячеек varargin, каждый аргумент занимает ровно одну ячейку так, как показано на рис. 8.8. I лава 8. Обработка данных и приемы программирования в MATLAB 439 ячейка1J ячейка 2J ячейка 3J ячейка 4j ячейка 5j ячейка 6 J рх РУ [xl yl Rl] [x2 y2 R2] [хЗ уЗ R3] [х4 у4 R4] Рис. 8.8. Хранение аргументов в varargin Массив varargin является единственным входным аргументом файл-функции, ее заголовок выглядит так: Eunction where = point(varargin) Доступ к входным аргументам, т. е. ячейкам, производится при помоши заключения индекса в фигурные скобки и последующим обращении с содер жимым в зависимости от типа хранимых данных. Например, varargind) содержит абсциссу точки, varargin(2} — ординату, varargin{5) (3) — радиус третьего круга и т. д. Напишите файл-функцию point, придерживаясь следующего алгоритма. I. Нахождение длины массива varargin при помощи length. 2. Проверка длины varargin, если она меньше трех, то задано недостаточно аргументов — выход по ошибке (используйте error). 3. Извлечение из varargin координат точки в переменные. 4. Извлечение из varargin координат центров кругов и радиусов в три век-гора подходящей длины (примените цикл for). 5. Перебор всех кругов, вычисление расстояния от центра круга до точки и сравнение его с радиусом. Если найден хотя бы один круг, в который попала заданная точка, то выходному аргументу следует присвоить значение, равное единице, и прекратить перебор выходом из цикла командой break. Листинг 8.23 содержит текст требуемой файл-функции, снабженный необходимыми комментариями. :.........................................—***«* .-..........." ......... I Листинг 8.23. Файл-функция point с переменным числом входных аргументов Z.-t >>'»> лЪ ..«<•" ... *.... j* .'...i. Д. . । •«•••• . • .....л.п.. ....... м. function where = point(varargin) % файл-функция определяет попадание точки с заданными % координатами (рх, ру) в круги с центрами % в (xl, yl), (х2, у2) и т. д. и радиусами Rl, R2 и т. д. % Возвращает % 1 в случае попадания 440 Часть II. Вычисления и программирование Ч 0 в случае непопадания % Использование whdre = point(рх, ру, [xl, yl, R1] , [х2, у2, R2], . ..) % Проверка числа входных аргументов (числа ячеек varargin) if length(varargin) < 3 error(’Недостаточно входных аргументов') end ? Бтщсление координат точки из первых двух ячеек Xpoint = varargin{l); Ypoint = varargin{2); % Нахоадение числа заданных кругов % (число ячеек varargin без перв| к двух) Ncircle = length(varargin) — 2; % Извлечение координат центров и радиусов кругов for i = 1:Ncircle Xcircle(i) = varargin{i + 2}(1); Ycircle(i) = varargin{i + 2}(2); Rcircle(i) = varargin{i + 2) (3); end % Полагаем where =0, т. e. пока нет ни одного нужнего круга where = 0; % Перебор кругов в цикле for i = 1:Ncircle % Вычисление расстояния от точки до центра текущего круга dist = sqrt((Xpoint - Xcircle(i))л2 + (Ypoint - Ycircle(i))л2); % Сравнение расстояния с радиусом круга if dist <= Rcircle(i) where =1; % Требуемый круг найден break % Дальше проверять нет смысла end end Дополните файл-функцию point исследованием правильности задания входных аргументов. Следует убедиться, что первые две ячейки массива varargin содержат вещественные числа, а остальные — векторы длиной, равной трем, также состоящие из вещественных чисел (листинг 8.24). Используйте функции isnumeric (проверяет, является ли ее входной аргумент числовым массивом) и isreal (проверяет, является ли ее входной аргумент вещественным массивом или массивом строк). Гпава 8. Обработка данных и приемы программирования в MATLAB 441 Листинг 8.24. Проверка входных аргументов файл-функции point •« • .. . . ... . . .. . . *«гт .«Г,»**..... it ~isnumeric(varargin{l}) | -isreal(varargin(l)) |... max(size(varargin{1}) ~= 1) error(1 Аргумент N1 должен быть вещественным числом') end if ~isnumeric(varargin{2}) | -isrea^(varargin{2}) |... max(size(varargin{2}) ~= 1) error(’Аргумент N2 должен быть вещественным числом') end for i = 3:length(varargin) if ~isnumeric(varargin{i)) | -isreal(varargin{i)) |... min(size(varargin{i})) -= 1 | length(varargin{i)) ~=3 |... varargin{i)(3) < 0 strl = 'Аргумент N’; str2 = nun2str(i); str3 = ' долж. быть вещ. вектором дайной 3 с третьим эл-том >= О’; strerror = strcat(strl, str2, str3); error(s trerror) end end Операторы, приведенные в листинге 8.24, следует поместить после проверки длины массива ячеек varargin. Теперь файл-функция point защищена от неправильного использования, например: » point (1, 1, [0, 3, -1]) ??? Error using ==> point Аргумент N3 долж. быть вещ. вектором дайной 3 с третьим эл-том >= О Усовершенствуйте файл-функцию point, добавив операторы, выводящие в графическое окно заданную точку и круги для получения наглядного результата. Очевидно, что требуется применить команды plot для построения параметрически заданных функций (окружностей) и заданной точки (визуализация параметрически заданных функций одной переменной описана в разд. "Графики параметрических и кусочно-заданных функций" главы 3). Блок операторов, осуществляющих отображение данных в графическое окно, приведен в листинге 8.25. Данный блок следует разместить после извлечения параметров из массива ячеек varargin. 442 Часть II Вычисления и программирование % Отображение ланных в графическое окно figure; % Создание окна % Построение окружностей t = 0:pi/20:2*pi; % задание вектора параметра for i = l:Ncircle % Вычисление векторов, соответствующих параметрически I заданным функциям, которые определяют окружности х = Rcircle(i)*cos(t) + Xcircle(i); у = Rcircle(i)*sin(t) + Ycircle(i); plot tx, y) % построение окружности hold on end % Вывод точки красным маркером plottXpoint, Ypoint, 'or') hold off axis square % сохранение одинакового масштаба осей Работа файл-функции point сопровождается теперь появлением графического окна с расположением кругов и точки, например, вызов f = point(l, 1, [0 3 3], [2 -1 3.3], [-1 -2 2 ]); приводит к появлению графика, изображенного на рис. 8.9. Рис. 8.9. Графическое окно с расположением кругов и ючки Гпава 8, Обработка данных и приемы программирования в MATLAB 443 Список входных параметров в заголовке файл-функции может содержать комбинацию обязательных и произвольных аргументов. Например, заголовок файл-функции point может иметь такой вид: function where = point (рх, ру, varargin) В данном случае в массив ячеек упаковываются векторы из трех элементов с координатами центров и радиусами кругов, начиная с первой ячейки массива, а параметры рх и ру передают координаты заданной точки. Массив varargin всегда указывав гея последним! Обратимся теперь к написанию файл-функций с переменным числом выходных аргументов. Продолжите работу с файл-программой point. Задача теперь состоит в том, чтобы point допускала следующие варианты обращения к ней. 1. f = point(px, ру, [xl yl Ri], [x2 y2 R2], ...). В f записывается ноль или единица, в зависимости от принадлежности точки какому-либо кругу. 2. [f, кс] = point(px, ру, [xi yi Ri], [х2 у2 R2],...). В f записывается ноль или единица, а в Nc — число кругов, которым принадлежит точка. 3. [f, Nc, Num] = point(px, py, [xl yl RI], [x2 y2 R2 ],...). В f записывается ноль или единица, в Nc — число кругов, которым принадлежит точка, в массив Num— номера этих кругов в списке входных аргументов. Произвольное число выходных аргументов возвращается файл-функцией в специальном массиве ячеек varargout, для чего следует предусмотреть операторы, записывающие выходные аргументы в сс ответствующие ячейки данного массива. Заголовок файл-функции с переменным числом входных и выходных аргументов в М-файле выглядит следующим образом: function varargout = myfun(varargin) Аргументы, указание которых обязательно, могут быть помещены в списки входных и выходных аргументов до varargin и varargout соответственно. Например, первый выходной аргумент функции point, принимающий значение ноль или единица в зависимости от попадания точки в круги, указывается всегда, поэтому имеет смысл выделить его в списке выходных аргументов. Ниже приведен заголовок файл-функции point, которая допускает три варианта вызова, перечисленные выше. function [where, varargout] = point(varargin) Внесите необходимые дополнения в текст файл-функции point (см. листинги 8.23—8.25). 1. Измените заголовок, предусмотрев один фиксированный выходной аргумент where и произвольное число дополнительных аргументов при помощи varargout. 444 Часть II. Вычисления и программирование 2. Перебирайте все круги в цикле for, запоминая число кругов и их номера, содержащих заданную точку (оператор break уже не нужен). 3. Запишите результаты в соответствующие ячейки массива в зависимости от числа выходных аргументов, с которыми была вызвана файл-функция (используйте nargout для определения их числа и оператор switch для заполнения требуемых ячеек). Обратитесь к листингу 8.26 в случае возникновения вопросов. Листинг не содержит проверки числа и типа входных параметров и операторов вывода исходных данных л графическое окно. Данные блоки остаются без изменений (см. листинги 8.24 и 8.25). .......................................-..v. . .*..... ...—51^......... Листинг 8.26. Файл-функция points с переменным числом входных ; аргументов ;.........~ ....................... .........i'............................. ...... ................ function [where, varargout] = point(varargin) s файл-функция определяет попадание точки с заданными % координатами (рх, ру) в круги с центрами % в (xl, yl), (х2, у2) и т. д. и радиусами Rl, R2 и т. д. % Использование % where = point(рх, ру, [xl, yl, R1], [х2, у2, R2],...) % where равно 1, если точка попала в какой-либо круг, 0—в противном случае % [where, NC] = point(рх, ру, [xl, yl, Rl], [x2, y2, R2],...) % NC равно числу кругов, содержащих точку % [where, NC, Nums] = point(рх, py, [xl, yl, Rl], [x2, y2, RB],...) % В вектор Nums записываются номера кругов, содержащих точку % Выделение координат точки из первых двух ячеек Xpoint = varargin]1); Ypoint = varargin{2); % Нахождение числа заданных кругов % (число ячеек varargin без первых двух) Ncircle = length(varargin) — 2; % Извлечение координат центров и радиусов кругов for i = 1:Ncircle Xcircla(i) = varargin{i + 2}(1); Ycircle(i) = vararginfi + 2}(2); Rcircle(i) - varargin{i + 21(3); end Глава б Обработка данных и приемы программирования в МА ГГАВ 445 % Сначала where = 0, т. е. пока нет ни одного нужного круга where = 0; % Сначала число кругов, содержащих точку, равно нулю NC = 0; % Перебор кругов в цикле ter i - l:Ncircle % Вычисление расстояния от точки до центра текущего круга dist = sqrt((Xpcint - Xcircle(i))Л2 + (Ypoint - Ycircle(i))Л2); % Сравнение расстояния с радиусом круга if dist <= Rcircle(i) where =1; % Требуемый круг найден % Увеличение числа найденных кругов на единицу NC = NC + 1; % Сохранение номера круга в массиве Nums Nums(NC) - i; end end % Запись полученных результатов в выходной массив ячеек в зависимости % от числа выходных аргументов, с которыми была вызвана point switch rargout case(2) % Было указано два выходных аргумента, следовательно, надо записать % только число кругов в первую ячейку varargout varargout[l} = NC; case' 3) % Было указано три выходных аргумента, следовательно, надо записать % число кругов и массив с их номерами в первые две ячейки varargout varargout{l} = NC; varargout(2} = Num?; end Итак, написание файл-функции с переменным числом входных и выходных аргументов не представляет большого труда, но требует понимания работы с массивами ячеек. В качестве упражнения измените фййл-функцию point так, чтобы она содержала два обязательных входных аргумента — координаты точки. Заголовок point должен выглядеть следующим образом: function [where, varargout] = point(рх, py, varargin) 446 Ч 1сть II Вычисление и ipoi раммирование Следующий раздел посвящен программированию файл-функций, входными аргументами которых, наряду с обычными переменными, являются другие файл-функции. Функции от функций Предположим, что для исследования функций требуется запрограммировать собственный алгоритм, который должен оперировать с достаточно большим набором функций. Алгоритм естественно оформить в виде файл-ф1 нкции, но тогда при работе с новой функцией придется внести изменения в М-файл. MATLAB предоставляет возможность написания файл-функций, входными аргументами которых являются другие файл-функции (функции fminsearch, fzero, quad, описанные в главе 6, подразумевают именно такой способ вызова). Имя файл-функции передается в строковой переменой, а ее вычисление производится при помощи команды feval. Например, синус можно вычислить обычным способом, вызвав sin(x), или используя feval с входными аргументами — названием 'sin' и артументом х: » х = pi/2; » feval('sin', х) ans = 1 Первый входной аргумент feval может быть и указателем на inline-функцию или анонимной функцией, результат будет аналогичный: » feval (@sin, х) ans = 1 В общем случае все входные аргументы исследуемой функции задаются в списке аргументов feval через запятую после имени функции, например, следующие три вызова некоторой функции myfun эквивалентны [a, b] = myfun (х, у, z) [a, b] = feval(’myfun', х, у, г) (a, b] = feval(@myfun, х, у, z) Применение feval разберем на следующем простом примере. Пусть алю-ршм исследования функций является обычным методом половинного деления для нахождения корня уравнения /(х) = 0. В качестве f(x) может выступать как математическая функция, определенная в MATL AB, так и заданная пользователем в М-файле. Считается, что задан отрезок, на кото Гпава 8. Обработка данных и приемы программирования в MATLAB 447 ром ищется корень, и точность вычислений. Алгоритм метода половинного деления очень простой. 1. Проверить, что на границах отрезка /(л) принимает значения разных знаков. 2. Если длина отрезка меньше заданной точности, взять в качестве приближенного значения корня любую из ei о границ. 3. Найти среднюю точку отрезка и вычислить в ней значение функции. Если в центре отрезка функция равна нулю, то корень найден и вычисления останавливаются. 4. В качестве нового отрезка выбрать ту половину, на 1раницах которой знаки /(л) различны, и продолжить вычисления с п. 2. Напишите файл-функцию half, реализующую метод половинного деления (листинг 8.27). Обращение к half должно выглядеть следующим образом: » г = half(’myf’, а, Ь, е) или » г = half(@myf, а, Ь, е) Здесь myf — имя исследуемой функции; а и ь — границы первоначального отрезка; е — точность вычислений. Листинг 8-27. Файл-функция hal f для решения уравнений ме >д.~- юловинного деления ‘„MSr........................................ ................ function root = half(fname, left, right, epsilon) % файл- функция находит корень уравнения f (х) =0 % методом половинного деления % Использование % root = halftfname, left, right, epsilon) % fi.atne - имя файл-функции, вычисляющей f (x) % left, right — левая и правая границы отрезка % epsilon — точность вычислений % Проверка значений функции на границах отрезка if feval(fname, left)*feval(fname, right) > 0 error(’ Одинаковые знаки функции на граница < отрезка') end % Деление отрезка пополам while (right — left) > epsilon 448 Часть]!. Вычисления и программирование center = (right + left)/2,- % вычисление середины % Проверка на равенстве f (х) нулю в center if feval(fname, center) == 0 break % найден точный корень, дальше делить нет смысла end % Выбор нужной половины отрезка, на границах которой % f(х) принимает значения разных знаков if feval(fname, left)*feval(fname, center) < 0 right - center; else left = center; end end % Приближенное значение корня равно координате любой границы % последнего полученного отрезка root = right; Теперь в качестве исследуемой функции может выступать как встроенная математическая функция MATLAB, так и функция с одним входным аргументом, описанная пользователем в М-файле, например: » г = half('sin', 3, 3.5, 1.0е-4) 3.1416 ИЛИ » г = half(@sin, 3, 3.5, 1.0е-4) г - 3.1416 Путь к М-файлу, в котором описана исследуемая функция, должен быть установлен в MATLAB при помощи навигатора путей или соответствующей команды (задание рутеи поиска описано в разд. " Установка путей" главы 5) Улучшите интерфейс файл-функции half (см. листинг 8.27) так, чтобы точность вычислений была необязательным параметром. Если точность не задана, то по умолчанию она полагается 10 3. Предусмотрите обращение к half с одним или двумя выходными параметрами. Во второй дополнительный параметр записывается значение функции в найденном приближенном значении корня. Очевидно, что задача сводится к написанию файл-функции с переменным числом аргументов (см. разд. "Файл-функции с переменным числом аргументов” данной главы). Глава 8. Обработка данных и приемы программирования в MATLAB 449 Листинг 8.28 содержит текст требуемой файл-функции. Обратите внимание, что в списках входных и выходных переменных присутствуют как обязательные параметры, так и дополнительные, передающиеся при помощи varargin И varargout. ; Листинг 8 28. Файл-функция half с переменным числом аргументов i ; .....................................£М>........................1......Л? function [root, varargout] = half(fname, left, right, varargin) % файл-функция находит корень уравнения f(х) = О 1 методом половинного деления % Использование % root - half(fname, left, right, epsilon) % fname — имя файл-функции, вычисляющей f(x) % left, right — левая и правая границы отрезка, на % котором находится корень % epsilon — точность вычислений, если не задана, то % по умолчанию 1.0е-03 % [root. Fun] = half(fname, left, right, epsilon) % Fun = f(root) % Если число входных аргументов равно четырем, то последний % аргумент содержит точность вычислений, а если трем, то точность % устанавливается по умолчанию 1.0е-03 switch nargin case(4) epsilon = varargin{!}; case(3) epsilon = 1.0e-03; otherwise error(1 Может быть три или четыре входных аргумента') end % Проверка значений функции на границах отрезка if feval(fname, left)*feval(fname, right) > 0 error('Одинаковые знаки функции на границах отрезка1 Г end % Деление отрезка пополам while (right — left) > epsilon center = (right + left)/2; % вычисление середины отрезка % проверка на равенство f(х) нулю в середине отрезка 450 Часть II. Вычисления и программирование if feval(fname, center) 0 break % найден точный корень, дальше делить нет смысла end % Выбор нужной половины отрезка, на границах которой % f (х) принимает значения разных знаков if feval(fname, left)*feval(fname, center) < 0 right = center; else left = center; end end % Приближенное значение корня равно координате любой границы % последнего полученного отрезка root = right; if nargout == 2 varargout{1} = feval(fname, root); end Теперь файл-функция half стала более универсальной, например, возможно такое обращение к ней: » [г, f] = half(6sin, 3, 3.5) г = 3.1416 f = 2.1639е-005 При передаче функции в качестве аргумента кроме ее имени или указателя можно использовать также имя inline-функции пли анонимную функцию (см разд. "Встраиваемые и анонимные функции"главы 6). Перманентные переменные Кроме глобальных и локальных переменных имеется еще один тип переменных — перманентные (persistent). Так же как и локальные, они доступны только в пределах своей функции, но в отличие от них сохраняются в памяти после выхода из функции, и их значения можно использовать при Гпава 8. Обработка данных и приемы программирования в MATLAB 451 следующем ее вызове. При первом вызове функции все перманентные переменные являются пустыми массивами. Перманентные переменные— это фактически локальные статические переменные. Однако мы будем придерживаться терминологии пакета MATLAB. Перманентные переменные оказываются полезными при программировании рекурсивных функций, т. е. функций, повторно обращающихся к себе (в разе. "Рекурсивные функции"этой главы приведены примеры таких функций) Поясним использование перманентных переменных на примере вычисления определенного интеграла по квадратурным формулам. В случае подынтегральных функций с интегрируемой особенностью на границе промежутка стандартные функции quad и quadi приводят к появлению предупреждения о достижении минимально возможного шага дробления исходного промежутка и нахождении интеграла с невысокий точностью (см. разд. "Вычисление определенных интегралов"главы 6). Сейчас мы приступим к написанию собственной файл-функции для вычисления определенных интегралов при помощи чебышевской квадратурной формулы: Л — г- 11 j/(x)dr =------X/ <• " *=i с и узлами tk, которые принадлежат базовому промежутку [-1,1] и не содержат точек 1 и -I. Например, для и = 5 значения узлов квадратурной формулы следующие: для н = 4: 12 12 12 12 /l~ 3 Зх/5’,2~ 3 + Зл/5’/з- + 3 Зл/Г /4~ + 3 + Зх/5' ^Алгоритм вычисления интеграла предполагает использование обобщенной квадратурной формулы, т. е. деление исходного интервала на заданное количество равных частей и вычисление интеграла на каждом из подынтервалов по квадратурной формуле. Изучая программирование рекурсивных функций при чтении следующего раздела этой главы, вы сможете улучшить этот алгоритм за счет адаптивного выбора шага дробления и получить функцию, пригодную для практических расчетов. 452 Часть II. Вычисления и программирование Реализуйте алгоритм вычисления определенного интеграла по обобщенным квадратурным формулам с пятью узлами в файп-функции chn5 с подфункцией ch5. Основная функция chr.5 должна иметь четыре входных аргумента. I. Имя, или указатель на файл-функцию с подынтегральной функцией. 2. Левая граница отрезка интегрирования. 3. Правая граница отрезка ин гегрнрования. 4. Число дроблений исходного отрезка. Результат вычислений возвращается в выходном аргументе файл-функции chn5 Подфункция ch5 служит для нахождения приближенного значения интеграла по произвольному отрезку [с, d] по квадратурной формуле чебышевского типа с пятью узлами и будет вызываться в основной функции для каждого из подынтервалов. Список входных аргументов ch5 должен содержать: 1. Имя, или указатель на файл-функцию с подынтегральной функцией. 2. Левую границу отрезка интегрирования. 3. Правую границу отрезка интегрирования. В подфункции ch5 следует вычислить значения узлов для базового промежутка [-1, 1], записать их в вектор длины 5, найти значение интеграла по квадратурной формуле и вернуть его в выходном аргументе. Очевидно, что массив со значениями узлов достаточно заполнить только один раз при первом обращении к ch5. Следовательно, хорошим выбором является объявление этого массива как перманентной переменной. Не забудьте сделать проверку содержимого перманентной переменной на пустой массив, который означает, что она еще не была инициализирована. Для проверки воспользуйтесь функцией isempty, которая возвращает логическую единицу, если ее входной аргумент оказался пустым массивом, и ноль, если массив непустой. В листинге 8.29 представлена возможная реализация основной функции с т.п 5 и подфункции ch5. В теле подфункции ch5 определен перманентный массив узлов х5 для базового промежутка. Он заполняется только один раз при первом обращении к подфункции. Листинг 8.29 Вычисление интегоала по чебышевской квадратурной формуле function int_val = chn5(f, а, Ь, п) % Вычисление определенного интеграла % по чебышевским квадратурным формулам % Использование int_val = chn5(f, а, Ь, п) Гпава 8. Обработка данных и приемы программирования в МА TLAB 453 f - подынтегральная функция имя файл-функции, указатель или inline-функция а, b - нижний и верхний пределы интегрирования % п - число дроблений отрезка интегрирования J = 0; % начальное значение суммы h ={b - а)/п; % шаг дробления отрезка [а, Ь] % накопление суммы интегралов по каждому подынтервалу for i = 1:n b = а + h; % вычисление интеграла по подынтервалу % по чебышевской квадратурной формуле J = J + ch5 (f, а, b) ; а = Ь; end; int_val = J; function chval = ch5(f, c, d) % объявление перманентного массива для хранения % значений узлов квадратурной формулы persistent х5 % проверка, был ли массив инициализирован i f isempty(х5) % вычисление значений узлов квадратурной формулы dl = (5 - sqrt(11))/3; d2 = (5 + sqrt(11))/3; x5(4) = sqrt(dl)/2; x5(5) - sqrt(d2)/2; x5(l) = -x5(5); x5(2) = -x5(4); x5(3) = 0; end; % вычисление интеграла по (c, d) хс = с + (d - с)*0.5*(1 + х5); fc - teval(f, хс); chval = (d - c)/5*sum(fc); 454 Часть II Вычисления и программирование Для проверки вычислите интеграл по промежутку [0,1] от функции y = x-tJ‘9, увеличивая количество дроблений исходного промежутка от 10 с возрастанием на порядок до 10 000, Формирование вектора таких значений, равноотстоящих в логарифмической шкале, удобно производить при помощи специальной функции logspace, например, z = logspace (2, 6, 5) генерирует вектор из пяти чисел 102, 103, .... Ю6. В листинге 8.30 приведена файл-программа Chn5_test для тестирования функции chn5. ...-............................................ .. . . . .... ..................-..-....... Листинг 8.30. Файл .программа Chn5_test для тестирования функции chn5 • । • 4 • . • . г. 2.. ....... • I • • . . . • И* . * Ы % Определение inline-функции func=inline('х.Л-0.9'); % вывод шапки таблицы disp([' Интеграл ' Число дроблений ’ ]); % увеличение числа дроблений на порядок в цикле % и вывод таблицы значений for n = logspace(l, 4, 4) int_ch5 = chn5(func, 0, 1, n); dl = num2str(int_ch5); d2 = num2str(n); disp([blanks(3), dl, blar.ks(14), d2]); end; Выполнение файл-программы дает следующий результат: » Chn5_test Интеграл Число дроблений 4.6002 10 5.7743 100 6.6434 1000 7.3338 10000 Пока файл-функция chn5, основанная на обобщенных квадратурных формулах, работает намного хуже, чем quadi. Даже при дроблении интервала на 10 000 частей не удалось получить хорошую точность из-за особенности на левой границе отрезка (a = 0). Вычислите интеграл от функции у = У0,5. Результат получается лучше, но тоже не очень точный. Извесз но, что в случае интегрируемой особенности для достижения приемлемой точности необходимо выбирать переменный шаг дробления исходного промежутка. Вы Гпава 8. Обработка данных и приемы программирования в MATLAB 455 сможете усовершенствовать файл-функцию chn5, добавив адаптивный выбор шага, при чтении следующего разд. "Рекурсивные функции" этой главы. Рекурсивные функции Содержание этого раздела не претендует на описание технологии проектирования рекурсивных алгоритмов. Мы ограничимся только иллюстративными примерами с пояснениями их реализации в MATLAB. Поддержка выполнения рекурсивных алгоритмов состоит в том, что при рекурсивном вызове функции все ее переменные сохраняются в памяти, а при возврате в точку вызова они восстанавливаются. Использование перманентных переменных может быть полезно для организации дополнительной передачи данных при вызове функции, т. к. они не восстанавливаются после завершения текущего вызова, а имеют те значения, которые были перед выходом из тела функции. Далее эти приемы иллюстрируются на нескольких примерах. В качестве первого примера рекурсивной функции рассмотрим адаптивное изменение шага дробления отрезка при интегрировании по обобщенным квадратурным формулам. Итак, вернемся к проблеме интегрирования функций с интегрируемой особенностью на границе промежутка. Для решения поставленной задачи вы начали работу над файл-функцией chn5 при чтении разд. "Перманентные переменные" этой главы (см. листинг 8.29). Файл-функция chn5 делит отрезок интегрирования на заданное число подынтервалов равной дзины и вычисляет интеграл по каждому из подынтервалов по квадратурной формуле чебышевского типа с пятью узлами. Известно, что для эффективного численного интегрирования функции с особенностью желательно сгущать точки дробления в области, прилегающей к особой точке, добиваясь примерно одинаковой погрешности интегрирования Е на каждом из подынтервалов. Возникает вопрос: как оценить погрешность величины интеграла, полученною при помощи квадратурной формулы, если точного значения интеграла мы не знаем. Для оценки точности на подынтервале интегрирования можно воспользоваться приемом, основанным на идее Рунге,— вычислить два приближенных значения интеграла по квадратурным формулам с различным числом узлов и сравнить их (значения узлов квадратурной формулы приведены в разд. "Перманентные переменные" этой главы). Алгоритм численного интегрирования состоит из следующих шагов. 1. Начальное разбиение отрезка — единственный подынтервал совпадает с отрезком. 2. Для каждого подынтервала находится два приближения J4 и J5 по квадратурным формулам чебышевского типа с четырьмя и пятью узлами 456 Часть II Вычисления и программирование 3. Если |J4 - J51 <Е, то точность на подынтервале считается достигнутой, если это неравенство не выполняется, то он делится пополам и для каждого из образовавшихся подынтервалов повторяются действия пп. 2 и 3 Таким образом, вычисления происходят в адаптивном режиме. Подынтервалы автоматически делятся на два типа: часть из них остается неизменными (на которых достигнута заданная точность) и интегрирование по ним не производится, а остальные подвергаются дроблению для уменьшения погрешности. Оставим в стороне вопрос о выборе параметра Е (приведенной точности), ибо он выходит за рамки излагаемого материала. Отметим только, что Е не определяет число верных знаков результата, а служит для равномерного распределения погрешности по подынтервалам. Привлечение рекурсивного вызова позволяет написать простую файл-функцию, поскольку число подынтервалов и их длины заранее неизвестны и изменяются в процессе вычислений, а для всех появляющихся подынтервалов требуется выполнить одинаковые действия. Имеет смысл предусмотреть ограничение на .минимальную длину подынтервалов, иначе уровень вложенности рекурсивных вызовов может быть слишком большим, что повле-чет увеличение времени счета. Примечание J MATLAB имеет ограничение по количеству вложенных вызовов функции — 500, что можно узнать при помощи команды get(0, 'Recursi onLimit'). Изменение этого параметра, например на 700 производится при помощи set(0, 1 RecursionLimit *, 700). Следует иметь в виду, что увеличение допустимого числа рекурсивных вызовов может привести к нехватке памяти и зависанию пакета. Реализуйте адаптивный алгоритм интегрирования в файл-функции chet45 с одним выходным аргументом — приближенным значением интеграла и пятью входными: 1. Подынтегральная функция, которая задается ссылкой на соответствующую файл-функцию, или ее именем, или inline-функцией, или анонимной функцией. 2. Нижний предел интегрирования а. 3. Верхний предел интегрирования Ь. 4. Параметр е для контроля точности на подынтервалах интегрирования. 5. Параметр ет для ограничения на минимальную длину подынтервалов. Используйте подфункцию ch5 для вычисления интеграла по подынтервалам при помощи квадратурной формулы с пятью узлами (см. листинг 8.29) и Гпава 8. Обработка данных и приемы программирования в MATLAB 457 подфункцию ch4 для случая четырех узлов, которая программируется аналогичным образом. В случае возникновения затруднений воспользуйтесь лист ингом 8.31, содержащим текст основной функции и двух подфункций. Г” • --- *' ’ ; - — - * • .................... 5 Листинг 8.31. Рекурсивная функция для вычисления опоедел в «н го [интеграла function J = cheb45(fun, а, b, е, ет) % Вычисление определенного интеграла % Использование J = cheb45(fun, a, b, е, ет) % fun - имя файл-функции, указатель или inline-функция % а - нижний предел интегрирования % Ь - верхний предел интегрирования % е - параметр для контроля за равномерным распределением погрешности % ет - минимальная длина подан гер' «лов % J - значение интеграла % вычисление интеграла по пятиузловой квадратурной формуле J5 = ch5(fun, а, Ь); % проверка на достижение минимальной длины подынтервала if abs(b - а) > em % вычисление интеграла по четырехузловой квадратурной формуле J4 = ch4(fun, а, Ь) ; 8 оценка погрешности на текущем подынтервале if abs(J4 - J5) <= e % погрешность меньше или равна допустимой J = J5; else % погрешность больше допустимой % находим половину длины подынтервала h = (b - а) /2; " вычисляем интеграл по левой половине подынтервала Л. = cheb45(fun, а, а + h, е, ет); % вычисляем интеграл по правой половине подынтервала JR = cheb45(fun, а + h, b, е, ет) ; % вычисляем интеграл по исходному подынтервалу J = JL + JR; end end 458 Часть II. Вычисления и программирование function I = ch5(fun, с, d) % Вычисление интеграла по пятиузловым формулам persistent х5 if isempty(x5) dl = (5 - sqrt(11})/3; d2 = (5 + sqrt(11})/3 ; x5(4) - sqrt(dl)/2; x5(5) - sqrt(d2)/2; x5(l) = -x5(5); x5(2) = -x5(4); x5<3) = 0; end; h = (d - с) /2; хс = с + h*(1 + х5); fc = feval(fun, xc) ; I = sum(fc)*(d - c)/5; function I = ch4(fun, c, d) % Вычисление интеграла по четырехузловым формулам persistent х4 if isempty(x4) dl = (1 - 2/sqrt(5)}/3 ; d2 = (1 + 2/sqrt(5))/3; x4 (3) = sqrt(d2); x4(4) = sqrt(dl); x4(l) = -x4(4); x4 (2) = -x4(3); end; h = (d - c)/2; хс = c + h*(1 + x4) ; fc = feval(fun, xc); I = sum(fc)*(d - c)/4; Проверьте работу файл-функции cheb45, вычисляя интеграл Jx09^ о Глава 8. Обработки данных и приемы программирования в MATLAB 459 для различных значений параметра Е = 10’, 10 2,10~9. Для тестирования удобно создать файл-программу, в которой значение е изменяется в цикле, а результаты сводятся в таблицу. Возможный вариант файл-программы Ch_test45 приведен в листинге 8.32. 5 «у.-- ..............................-т'ЦД ..: Пистинг 32. Файл-программа Ch_test45 для тестирования функции с1м.Ь45 « ........... ........................................... : % определение inline-iyHKijmi f = inline('х.Л-0.9'); % вывод шапки таблицы disp([' е ', 1 Значение интеграла ’]); % изменение точности в цикле for е = legspace(-1, -9, 9) % вычисление интеграла, минимальная длина подынтервалов - ноль J = cheb45(f, О, 1, е, 0); % вывод строки таблицы fpzintf(%9.Ое %15.10fn’, е, J) end Наша файл-функция досгазочно успешно работает в случае подынтегральных функции с интегрируемой особенностью. » Ch test45 е Значение интеграла 1е-001 4.9244236668 1е-002 9.4845672033 1е-003 9.9475656427 1е-004 9.9945745917 1е-005 9.9993836026 1е-006 9.9999301713 1е-007 9.9999914100 le-ooe 9.9999989635 1е-009 9.9999998738 Сравнение с файл-функцией chn5 (листинг 8.29), допускающей подынтервалы только равной длины, свидетельствует об эффективности адаптивного рекурсивного алгоритма. При интегрировании функции с более сильной особенностью, например, л-0'95, потребуется увеличение максимально допустимого числа вложенных вызовов. 460 Часть II. Вычисления и программирсеанис Примечание /Т Конечно, результат для тестовых примеров будет еще более убедительным, если применить специальные квадратурные формулы с весами, учитывающими характер интегрируемой особенности. Но построение обобщенных формул такого класса в общем случае пе представляется возможным. Поэтому для постоянного применения они неудобны и здесь не рассматриваются. При использовании рекурсии часто необходимо получить информацию о числе рекурсивных вызовов и значениях данных на каждом уровне рекурсии. В нашем примере это может быть номер вызова функции и границы текущего подынтервала интегрирования. Одна из возможных модификаций файл-функции cheb45 приведена в листинге 8.33, который следует дополнить подфункциями сЬ4 и ch5. Новая файл-функция cheb45c не только вычисляет интеграл, но и выводит промежуточные сведения об адаптивном подборе шага интегрирования. Переменное число входных и выходных параметров позволяет осуществить сбор статистики после первого рекурсивного обращения к файл-функции. . ........................................................................................... Листинге 33. Функция cheb4Jc с выводом информации о рекурсивных вызовах iviTntTH-i.i .THVCVWST. . . - ,л ......... »»».>*............ ............ *>>> .«*... . function [J, varargout] = dheb45c(fun, a, b, e, em, varargj.nl if isentpty(varargin) % первый вызов файл-функции % в счетчик числа вызовов заносится 1 count = 1; vararoout(11 = count; % вывод шапки таблицы disp(['номер вызова', ' левая граница', ' правая граница']) else % рекурсивный вызов % увеличение счетчика числа вызовов на 1 varargout)1) = varargin)1} + 1; count = varargout{1}; end % яывод строки таблицы о номере рекурсивного вызова % и границах подынтервала fprintf)'%Td %18.4е %14.4en', count, а, Ь) J5 = ch5(fun, а, Ь) ; if abs(b - а) > em Гпава 8. Обработка д 1нных и приемы программирования в MATLAB 461 J4 = ch4(fun, a, b),- if abs(J4 - J5) <= e J = J5; else h = (b - a)/2; [JL, count] = cheb45c(fun, a, a + h, e, em, count); [JR, count] = cheb45c(fun, a + h, b, e, em, count); J = JL + JR; end end % возвращение в выходном аргументе текущего номера вызова функции varargout(1} = count; Проверьте работу файл-функции cheb45c: » J = cheb45c(f, 0, 1, 1е-5, 0) Примечание Если оценка количества вызовов рекурсивной функции не требуется по существу алгоритма, а нужна только на этапе отладки программы, то удобнее пользоваться глобальными переменными, т. к. после завершения отладки глобальные счетчики вызовов могут быть удалены или закомментированы. Алгоритмы стандартных функций MATLAB quad, quadi являются рекурсивными с адаптивным выбором шага интегрирования. Вы можете самостоятельно изучить их, поскольку соответствующие файл-функции имеют открытый код. Они находятся в подкаталоге toolboxmatlabfunfurA основного каталога MATLAB. Большинство вычислительных алгоритмов можно реализовать, не используя механизм рекурсии, однако встречаются задачи рекурсивные по своей природе. Рассмотрим задачу о выводе содержимого полей структуры в командное окно, поля которой могут быть также структурами, причем уровень вложенности структур произвольный. Создайте структуру transaction, подобную рассмотренной в разд. "Простые структуры"этой главы » А = struct('currency', 'USD', 'price', 0.23, 'bid', 0.21, ... ask', 0.27); >> transaction - struct('time', [10,20,46], 'stock', 'EESR', ... 'volume', ... 10000, ’strike', A, 'exchange', 28.5214 ); 462 Часть II Вычисления и nporpat. <мирование При просмотре содержимого структуры transaction в командном окне имена полей вложенной структуры а и их значения не отображаются. Запрограммируйте рекурсивную функцию structfield, выводящую значения всех полей структуры, включая поля вложенных структур. В начале алгоритма задайте перманентную переменную, которая имеет смысл счетчика вложенности. Далее запишите в массив ячеек имена всех полей структуры, воспользовавшись функцией fieldnames. Организуйте цикл по всем полям структуры. В цикле проверяйте содержимое текущего поля при помощи функции isstruct, которая возвращает логическую единицу, если переданный ей параметр является структурой, или логический ноль в противном случае. Если значение текущего поля — структура, то вывод названия ее полей и их содержимого осуществляется рекурсивным вызовом функции. В остальных случаях требуется просто вывести название поля и его значение. Для более наглядного отображения вложенных структур в командном окне предусмотрите отступ от левого края, пропорциональный уровню структуры, т. е. значению счетчика вложенности. Листинг 8.34 содержит один из вариантов рекурсивной файл-функции structfield. *— ....... ...''' •“SfiJjjT'T.............—— • —....— ........................... Листинг ’.34. P ’курсивная файл-функция для просмотра вложенных стрктур .'.1 function structfield(somestruct); % Файл функция для вывода содержимого вложенных структур % вводим перманентную переменную - счетчик вложенности persistent level if isempty(level) « первый вызов функции, инициализация счетчика вложенности level = 0; end % запись имен полей в массив ячеек fnames = fieldnames(somestruct); % определение количества полей L = length(fnames); i проход по всем полям структуры в цикле for k = 1:L % получение имо:и текущего поля field = fnames(к); % создаем строку из пробелов для отступа от левого края str = blanks(10*level); Глава 8. Обработка данных и приемы программирования в MATLAB 463 % проверка, является ли текущее поле i труктурои if isstiuct(somestruct. (field)) % текущее поле - структура % увеличиваем счетчик вложенности level = level + 1; % выводим имя поля, являющегося структурой disp([str, 'значения полей вложенной структуры ', field]) % реурсивный вызов функции structfieldtsomestruct.(field)); % уменьшаем счетчик вложенности level = level - 1; else % текущее поле не является структурой % выводим имя поля и его значен!е disp([str 'значение поля ', field]) disp(somestruct.(field)) end end Проверьте работу файл-функции structfieid на примере структуры transaction: » structfield(transaction) значение поля time 10 20 46 значение ноля stock EESR значение поля volume 10000 значения полей вложенной структуры strike значение поля currency USD значение поля price 0.2300 значение поля bid 0.2100 значение поля ask 0.2700 464 Часть II. Вычисления и программирование значение поля exchange 28.5214 Дополните самостоятельно функцию structfieid контролем вводимого параметра, который должен быть структурой. Примечание В функции structfieid счетчик уровня вложенности level не является обязательным. Он служит только для вычисления длины отступа от левого края при выводе вложенных структур. В заключение рассмотрим пример организации алгоритма при помощи рекурсивного вызова подфункции, что оказывается удобным при накоплении данных в ходе рекурсии. Задача состоит в поиске всех локальных минимумов функции f (х) внутри заданного отрезка [л, б]. Для ее решения подходит следующая последовательность действий. I. Выбираем середину отрезка в качестве начального приближения к точке минимума и вычисляем абсциссу z локального минимума f(x} на [л, £>], используя стандартную функцию fminsearch. 2. Если z лежит внутри промежутка, то в качестве нового отрезка [л, Z>] последовательно выбираем [л, г] и [z, b] и выполняем для них п. 1. Поиск для текущего отрезка завершается, если z = л, либо z = b. Этот алгоритм применим для многих функций, имеющих конечное число локальных минимумов. Перед обсуждением программирования алгоритма разберем подробнее п. 2, в котором проверяется условие нахождения точки внутри промежутка. Пусть функция fminsearch вычислила абсциссу локального минимума z, удовлетворяющую неравенству a<z<b . В соответствии с алгоритмом, поиск локальных минимумов осуществляегся теперь на отрезках [л, г] и [z, £>]. Пусть в качестве нового отрезка [л, берется отрезок [л, z] - Если внутри [л, £>] нет локального минимума, то fminsearch вернет значение z, близкое к Ь, поскольку локальный минимум находится приближенно Выполнение неравенства a < z < b повлечет ошибочное предположение о наличии локального минимума и ненужное разбиение отрезка [л, Ь] на две части. Для предотвращения такой ситуации необходимо учесть погрешность, с которой fminsearch вычисляет локальный минимум, и вместо уело- Гпава 8. Обработка данных и приемы программирования в MATLAB 465 вия a <z<i> проверять a + E<z<b-z, где величина Е превосходит погрешность счета локального минимума. Перейдем теперь к описанию возможной реализации алгоритма в файл-фу акции с основной функцией al lmin и рекурсивной подфункцией loc_min. Заголовок основной функции function [xmin, ymin] = allmin(fun, a, b) предполагает ее вызов от указателя на файл-функцию, вычисляющую /(л), и границ исходного отрезка а и b. Вместо указателя может быть имя файл-функции или inline-функция. Основная файл-функция должна вернуть пару векторов со значениями абсцисс и ординат точек локальных минимумов. Интерфейс подфункции удобно организовать следующим образом. function xmin = loc_min(fun, a, b, е, new_set) где в качестве а и ь выступают границы текущего промежутка, на котором следует найти локальный минимум; е — величина Е в условии принадлежности локального минимума отрезку: new set — флаг инициализации накапливаемых переменных. При первом вызове функции флаг new set следует задать отличным от 0, например, 1. При повторных вызовах функции его значение должно быть равно 0. В обсуждаемом примере иллюстрируется еще одно применение перманентных переменных, о котором шла речь ранее— передача данных при повторных вызовах функции. Выходной аргумент xmin — массив с вычисленными абсциссами локальных минимумов. Мы намеренно вынесли рекурсивную часть алгоритма в подфункцию, поскольку список ее входных аргументов содержит параметры е и new set, которые не входят в исходные данные задачи, задаваемые пользователем. Один из возможных вариантов основной функции с подфункцией приведен в листинге 8.35. Искомые точки упорядочиваются по возрастанию абсцисс и отмечаются маркерами на графике исследуемой функции Г ....... у,...................................... ..........V? ; Листинг 8 35. Функция поиска г.экальных минимумов функции на промежутке function [xmin, ymin] = allmin(fun, a, b) % Поиск локальных минимумов fun внутри заданного интервала (а, Ь) % Использование [xmin, ymin] = allminifun, a, b) % задание погрешности для проверки условия попадания точки внутрь (а, Ъ) е “ 1е-4*(Ь - а); % вызов рекурсивной подфункции xmin = loo min(fun, a, b, e, 1); 466 Часть II. Вычисления и программирование % сортировка точек минимума в порядке возрастания Kinin = sort (xmin) ; % вычисление значений функции в точках локального минимума ymin = fevalffun, xmin); % вывод графика функции с отмеченными точками локального минимума figure fpiot(fun,[а Ь]) hold on ploclxmin, ymin, 'ro') function xmin = loc_min(fun, a , b, e, new_set) % Рекурсивная подфункция для поиска всех локальных минимумов % Начальная инициализация для накапливаемых результатов persistent n pnt if new .set ~= 0 pnt = [ J ; n = 0; end; % задание начального приближения с = 0.5*(а + Ь); % поиск локального минимума на [а, Ь] z = fminseareh(fun, с); if andtz >a+e, z<b-e) % найден новый локальный минимум увеличиваем счетчик % и добавляем локальный минимум в массив n - n + 1; pnt(n) = z; % поиск локальных минимумов на подынтервалах loc_min(fun, a, z, е, 0) ; loc_min(fun, z, Ь, е, 0); end % возвращаем массив найденных точек xmin = pnt; Проверьте работу файл-функции, вычислив локальные минимумы функции / (л) - sin (х) + sin (Юл) на отрезке [-2, 2]. » f = inline(’sin(х) + sin(10*x)') >> [xmin, ymin] = allmin(f, -2 ,2) Гпава 8. Обработка данных и приемы программирования в MATLAB 467 xmin - -0.1669 -1.4153 -0.7924 1.0950 0.4623 1.7295 ymin _ -1.1613 -1.9878 -1.7096 -0.1100 -0.5500 -0.0124 Фу нкцию loc min можно выделить в отдельный файл и использовать самостоятельно. В этом случае флаг new set (если его значение ноль) позволяет к найденным ранее точкам добавить локальные минимумы той же функции из других промежутков Выбор средней точки отрезка в качестве начального приближения в fminsearch не всегда приводит к нахождению локального минимума внутри отрезка. Можно усовершенствовать алгоритм, выбирая различные начальные приближения, например, равноотстоящие с некоторым шагом точки. Диалоговая отладка программ Среда программирования в MATLAB имеет стандартные средства диалоговой отладки программ (файл-программ и файл-функций). Эти средства встроены в редактор М-файлов. Течки останова, пошаговое выполнение программы При отладке программы используется понятие точки останова (Breakpoint). Точка останова это строка исходного текста программы, при достижении которой выполнение программы приостанавливается, и у вас появляется возможность обратиться к тексту программы в редакторе М-файлов для просмотра текущих значений переменных, изменения точек останова или прекращения процесса отладки в случае локализации ошибки. Точки останова можно установить в любом М-файле, открытом в редакторе. Точки останова бывают безусловные, условные и временные. Безусловная точка останова связывается с исполняемой строкой программы. Исполняемые строки программы (в отличие от комментариев) отмечены в редакторе знаком расположенным слева от строки. Щелчок мыши по нему приводит к появлению безусловной точки останова в данной строке, при этом знак заменяется на красный кружок. Для удаления безусловной точки останова применяется щелчок мышью по кружку. Аналогичного результата для текущей строки программы можно добиться выбором пункта Set/Clear 16 Зак. во 468 Часть II. Вычисления и прог,- ^ммирование Breakpoint в меню Debug редактора М-файлов, или нажатием <F12>, или кнопкой Set/CJcar Breakpoint на панели инструментов. Примечание Если в редакторе М-файлов отсутствует панель инструментов, то следует выбрать в меню Desktop пункт Editor Toolbar. Вместо красного кружка может появится серый, свидетельствующий о том, что в программе есть синтаксическая ошибка или в текст программы были внесены изменения и файл не сохранен. В первом случае выводится диалоговое окно MATLAB Editor с предупреждением о том, какого характера и в какой строке М-файла ошибка. Во втором случае достаточно сохранить файл. Если каталог с М-файлом не является текущим или путь к нему не указан в путях поиска MATLAB то появляется диалоговое окно MATLAB Editor, переключатели которого позволяют сделать каталог текущим или добавить путь к нему в пути поиска. При достижении безусловной точки останова выполнение программы всегда приостанавливается. Это в ряде случаев может оказаться неудобным, например, если при отладке цикла for требуется приостановить выполнение программы, только если счетчик цикла принимает значение 100. Гораздо лучше использовать условную точку останова, которая сработает только при выполнении некоторого условия. Для размещения условной точки останова в некоторой строке с исполняемыми операторами следует установить в нее курсор и в меню Debug выбрать пункт Set/Modify Conditional Breakpoints. В появившемся диалоговом окне (рис. 8.10) надо записать логическое выражение, которое будет проверяться до исполнения этой строки и, если оно удовлетворяется, произойдет временное прекращение (приостанов) исполнения кода. Условная точка останова, связанная со строкой текста программы, отмечается желтым кружком на месте знака слева от текста. Можно сделать эту точку останова неактивной, не удаляя ее (она будет игнорироваться), с целью последующей ее активизации. Переключение из активного состояния в неактивное производится выбором в меню Debug пункта Enable/Disable Breakpoint. При деактивации точки останова кружок перечеркивается. Такой же эффект получается и для безусловных точек останова. Деактивировать условную точку останова можно щелчком левой кнопки мыши по желтому кружку. Учтите, что при щелчке мыши по неактивной точке останова она удаляется, а не активируется. Аналогичные возможности предоставляет контекстное меню, появляющееся при щелчке левой кнопкой мыши в поле редактора с номерами строк файла. В частности, легко превратить безусловную точку останова в условную при помощи пункта меню Set/Modify Condition. Глава 8. O6f аротка данных и приемы программирования в MATLAB 469 Рис. 8.10. Диалоговое окно для задания условия останова При достижении условной или безусловной точки останова вы имеете возможность продолжить отладку одним из способов, которые выбираются в меню Debug, или при помощи соответствующих кнопок на панели инструментов. □ Step (или <F10>) — пошаговое выполнение одной строки программы и остановка на следующей. Точка останова возникает в следующей строке и уничтожается автоматически после дальнейшего выполнения программы. □ Step In (или <F11>)— пошаговое выполнение, включая операторы вызываемых файл-программ и файл-функиий. □ Step Out (или <Shift>+<Fl 1 >)— выполнение функции до конца и возврат в вызываемый М-файл (при условии, что при выполнении не встретится безусловная или условная точка останова). □ Run (Continue) (или <F5>)— начало (продолжение) выполнения М-файла до следующей безусловной или условной точки останова, □ Go Until Cursor— продолжение исполнения до строки М-файла, в которой находится курсор. □ Exit Debug Mode — прекращение процесса отладки. При этом на строку, в которой выполнение программы временно приостановилось, указывает зеленая стрелка. Для отмены сразу всех условных и безусловных точек останова служит пункт Clear Breakpoints in All Files меню Debug либо одноименная кнопка на панели инструментов редактора М-файлов. Отметим еще один вид условных точек останова, которые не связаны ни со строкой М-срайла, ни с каким-либо М-файлом, а определяются рядом исключительных ситуаций. Пусть, например, в процессе вычислений выводится предупреждение, скажем, о делении на ноль, и мы хотим выяснить, в ка 470 Часть II. Вычисления и программирование ком М-файле и по какой причине это происходит, и посмотреть значения соответствующих переменных. Самый удобный способ— автоматически открыть файл в редакторе и поместить временную точку останова в "подозрительную" строку, выполнение которой повлекло данное предупреждение. Для этого, во-первых, убедитесь, что в меню редактора Debug рядом с названием пункта Open m-files when Debugging установлен флаг (если его нет, то просто выберите этот пункт). Во-вторых, в том же меню перейдите к пункту Stop if Errors/Warnings. Появляется многостраничное диалоговое окно Stop if Errors/Warnings for All Files, изображенное на рис. 8.11. Каждая его вкладка позволяет задать действия MATLAB при возникновении одной из исключительных ситуаций: □ Errors — возникает событие, приводящее при обычной работе программы к сообщению об ошибке (например, обращение к неопределенной переменной или функции, или выход за границы массива) Ошибки, возникающие внутри блока обработки исключительных ситуаций try.. .catch, игнорируются; □ Try/Catch Errors— возникает любая ошибочная ситуация знутри блока try...catch; □ Warnings— программа выполнила действия, сопровождающиеся выводом предупреждения (например, решение системы с плохо обусловленной матрицей); □ Nan or Inf — управление приостановкой исполнения, если при вычислении арифметических выражений получается NaN или inf (например, при делении на ноль). Рис. 8.11. Диалоговое окно для остановок при исключительных ситуациях Глава 8. Обработка данных и приемы программирования в MATLAB 471 На каждой вкладке находится несколько переключателей. Выбор первого отменяет появление условной точки останова. Второй переключатель как раз и предназначен для автоматического приостановления работы М-файла и открытия ею в редакторе (при условии, что в меню Debug рядом с названием пункта Open m-files when Debugging должен быть флаг). Итак, в зависимости от желаемого вида контроля следует установить второй переключатель на одной или нескольких вкладках и нажать кнопку ОК. Более того, окно редактора можно закрыть, поскольку при возникновении исключительной ситуации оно откроется и укажет вам на оператор М-файла, послуживший источником ошибки или предупреждения. ц Примечание Третий переключатель на всех вкладках кроме Nan or Inf служит для отслеживания ошибок или сообщений только с определенными идентификаторами. Подробнее об этом написано в справке по окну Stou if Errors/ Warnings for Ml Files, которая выводится при нажатии на кнопку Help. Заметим, что выбор в меню Debug пункта Clear Breakpoints in All Files или нажатие на одноименную кнопку панели инструментов редактора приводит к отмене описанного выше режима. Поимер диалоговой отладки Разберем процесс отладки на конкретном примере. При чтении разд. "Сервисные функции для работы со строками" этой главы вы создали функцию strnumpos (см. листинг 8.1), предназначенную для нахождения позиций всех цифр, входящих в строку. Результатом выполнения функции является вектор с номерами позиций цифр. Попытаемся теперь упростить ее так, как это сделано в листинге 8.36. Вместо перебора всех цифр мы использовали функцию isnumeric для проверки, является ли текущая позиция цифрой, или нет. Новая функция названа strnumposi, из нее исключена проверка входных и выходных аргументов и оставлен только алгоритм поиска для упрощения визуального контроля при отладке. Листинг 8.36. Функция strnumposi для диалоговой отладки function pos = strnumposl(str) slen = length(str); digits = 0; pcs = [ ]; for k = l:slen if isnumeiic(str(k)) 472 Часть II. Вычисления и программирование digits = digits + 1; pos(digits) = к; end end Создайте файл-программу check (листинг 8.37), в которой вызывается функция strnumposl, и запустите ее. Листинг В.37. Файл-лр грамма check для отладки функции sti numposl -............... ............ ....... ............. -... .. . ....... ...............1 line = 'B 2003 году Санкт-ПетерОургу - 300 лет' position = strnumposl(line) При исполнении М-файла получается заведомо неправильный результат — пустой массив: » check line = В 2003 году Санкт-Петербургу - 300 лет position = [ ] Приступая к отлалке, целесообразно вначале очистить окно Command Window (командой cic) и Workspace, т. е. удалить все переменные рабочей среды (командой clear all или средствами самого браузера переменных.) Оставьте видимыми необходимые окна так, чтобы ими было удобно пользоваться. Откройте файлы check и strnumposl в редакторе М-файлов, сделав текущей файл-программу check. Наиболее удобно встроить окно редактора М-файлов в рабочую среду и расположить его поверх окна Command History, как показано на рис. 8.12. Для этого надо воспользоваться кнопкой Dock Editor на панели инструментов редактора М-файлов и затем перетащить его за заголовок при нажатой левой кнопке мыши на окно Command History. Меню окна редактора М-файлов объединится с меню рабочей среды. Можно избрать и другой подход для компоновки окон — извлечь из среды MATLAB браузер переменных и командное окно и разместить необходимые окна, включая редактор М-файлов, на экране без перекрытия так, чтобы ими было удобно пользоваться. Для отделения окон от рабочей среды служит кнопка UnDock... на заголовке окна или одноименный пункт меню Desktop. Однако в этом случае при открытии других окон, на Гпава 8. Обработка данных и приемы программирования в MATLAB 473 пример, окна редактора массивов или окна редактора графиков придется располагать все окна заново. Рис. 8.12. Размещение окон при отладке на экране 1 Перейдите в окно редактора М-файлов и установите безусловную точку останова на первой команде файл-программы check. Для этого щелкните мышкой по знаку справа от номера строки или поместите курсор в первую строку и нажмите <F12>. Знак минус изменился на красный кружок. Использование функциональных клавиш сущее гвенно повыыаег эффективность работы, поэтому далее мы будем упоминать нужную клавишу (или комбинацию), а в скобках приводить название соответствующею пункта меню Debug или кнопки на панели инструментов редактора М-файлов. Нажмите <F5> (Run) для выполнения программы. Происходит переход в режим отладки и выполнение программы до первой точки останова, т. е. до первой строки. На первый взгляд отладчик ничего не сделал, но это не так — в первой строке появилась временная точка останова, о чем свидетельствует знак стрелки, указывающей на первую команду. Этот знак дает 474 Часто Н Вычисления и программирования возможность определить место в программе, где выполнение операторов приостановлено. Точно так же происходит и при достижении условной точки останова. Кроме того, изменилось приглашение командной строки в окне Command W indow, свидетельствующее о проведении диалоговой отладки. Далее будем выполнять программу в пошаговом режиме. Нажатие на <F10> (Step) приводит к выполнению первой команды в файл-программе check. Обратите внимание, что в окне браузера переменных рабочей среды Workspace появилась переменная line, доступная для присмотра. В окне Command Window отобразился результат выполненной команды. В конце первой строки файл-программы check мы намеренно не поставили точку с запятой (листинг 8.37) для вывода полученного результата в командное окно. Временная точка останова переместилась во вторую строку файл-программы, слева от нее расположена стрелка. Поскольку наша цель — нахождение ошибки в файл-функции strnumposl, то теперь следует пошагово выполнять ее операторы. Нажатие <F11> (Step In) влечет автоматическое открытие файла strnumposI.m с нашей файл-функцией в окне редактора и помещение временной точки останова в строке с первым оператором файл-функции. Примечание < Разница между <FI0> (Step) и <F11> (Step In) проявляется только в тех строках программы, которые содержат вызов файл-функций или файл-программ. Если в процессе отладки требуется зайти в файл-функцию или файл-программу и пошагово выполнять ее операторы, то следует выбрать <F11> (Step In). С другой стороны, если в строке программы происходит обращение к стандартной файл-функции, например, fzero, и ее отладка не входит в ваши планы, то лучше выполнить строку за один шаг при помощи <FJO> (Step). Всегда можно отказаться от пошагового выполнения файл-функции, выполнить ее оставшиеся строки и вернуться к оператору, следующему за ее вызовом. Для этого необходимо воспользоваться комбинацией клавиш <Shift>+<F11> (Step Out). Выполните пошагово часть операторов файл-функции strnumposl до условного оператора if, нажимая <FI0>. Обратите внимание, что все локальные переменные файл-функции и входной аргумент str отображаются в окне браузера Workspace. В раскрывающемся списке Stack на панели инструментов редактора М-файлов или окна Workspace установлено имя файл-функции. Этот список содержит сейчас всего три строки: strnumposl, cheek и Base и позволяет в любой момент отладки отобразить в окне браузера соответственно: локальные переменные файл-функции strnumposl и ее аргументы (входные и выходные), если они уже созданы; переменные файл-программы check или переменные рабочей среды. Напомним, что перемен Гпава 8. Обработка данных и приемы программирования в MATLAB 475 ные фанл-нрограмм и рабочий среды являются общими, поэтому выбор check приводит к тому же резулы ату, что и Base Примечание В случае рекурсивной файл-функции каждое обращение к ней фиксируется в списке Stack, что дает возможность отслеживать значения переменных для вызовов различной вложенности. За изменением значений переменных в процессе отладки удобно следить в окне редактора массивов Array Editor. Откройте окно Array Editor со значением к при помощи двойного щелчка мыши по имени переменной к в окне браузера (или из всплывающего меню, или с помощью кнопки Open на панели инструментов окна Workspace). Аналогичным образом отобразите содержимое переменной str в окне редактора массивов так, как показано на рис. 8.13. Рис. 8.13. Контроль значении переменных в процессе отладки 476 Часть II Вычисления и программирование Пошагово выполняя файл-функцию strnumposl, убедитесь в том, что для значений 1 и 2 счетчика цикла к условие оператора if не выполняется, т. е. не происходит перехода к операторам, расположенным внутри тела if. Так и должно быть, поскольку первый и второй символы строки str не являются цифрами. Когда значение к достигает 3, должно получиться верное условие в операторе if. т. к. третий символ в строке являете я цифрой. Однако перехода к блоку внутри тела оператора if не происходит. Ошибка локализована и процесс отладки можно пока прервать, выбрав в меню Debug пункт Exit Debug Mode или нажав одноименную кнопку на панели инструментов редактора М-файлов. Итак, необходимо выяснить, что же на самом деле проверяет оператор if. Внесите небольшие изменения в файл-функцию strnumposl. Перед условным оператором присвойте вспомогательной переменной tempi значение str (k), a temp2 — результат, возвращаемый isnumeric (tempi). Нс забудьте сохранить файл strnumposl.т. Теперь мы изберем более быстрый путь отладки программы, установив только одну условную точку останова в строке файл-функции с оператором if при достижении счетчиком значения 3. Для этого установите курсор в строку с оператором if, выберите в меню Debug пункт Set/Modify Conditional Breakpoints. В появившемся окне введите: к==з. В файл-программе check точка останова уже не понадобится и ее можно удалить. Начните отладку снова, запустив файл-программу check при помощи <F5> (Run). Теперь приостанов произойдет только в функции strnumposl при значении счетчика цикла к, равном 3. Проанализируй ге значения переменных tempi и temp2, открыв их для просмотра в Array Editor. Значение tempi показывает, что третий символ строки str на самом деле воспринимается не как число (double), а как символ (char), вернее массив символов размера 1 на 1. Поэтому функция isnumeric возвращает логический ноль, что подтверждается значением переменной temp2. Допущена ошибка в используемом типе данных. Прервите отладку и подумайте, как проверить, является ли символ цифрой или нет. Преобразование строки в число функцией str2num, о котором было сказано в этой главе, позволяет корректно произвести нужную проверку. При преобразовании текущего символа строки str возможны всего два варианта: число, если текущий символ — цифра, и пустой массив во всех остальных случаях Следовательно, достаточно проверить равенство нулю длины возвращаемого str2num массива (листинг 8.38). ................................................................... ................................... Листинг 8.38. Новая функция strnumpoi 1 для диалоговой отладки function pos = strnumposl(str) slen = length (str) digits = 0; pos = [ ]; Гпава 8. Обработка данных и приемы программирования в MATLAB 477 for к = l:slen а = str2num(str(к)); if length(а)О digits = digits + 1; pos (digits) = к; end end Повторите отладочные действия и убедитесь, что происходит правильное заполнение элементов выходного массива. Внесите окончательные изменения в файл-функцию strnumposl, а именно верните комментарии и проверку входных аргументов так, как было сделано в функции strnumpos (см. листинг 8.1). Примечание 2, Проверка условия соответствия символа цифре использует особенности пакета MATLAB. Однако в таком случае алгоритм становится непереносимым в другие срезы. Поэтому условие проверки лучше записать в форме, приемлемой для любой среды программирования. Например, str(k) >= 'О’ ь str(k) =< *9'. В этом разделе мы на простом примере привели основные приемы отладки программ средствами MATLAB. При самостоятельной работе над заданиями следующего раздела воспользуйтесь отладчиком MATLAB для пошагового выполнения алгоритма. Задания для самостоятельной работы 1. Напишите файл-функцию для решения поставленной задачи. • Подсчитайте число вхождений подстроки в строку. • Найдите количество пробелов в строке. • Определите количество цифр в строке. • Удалите идущие подряд одинаковые символы в строке. • Замените идущие подряд одинаковые символы в строке на один. • Строка является предложением, в котором слова разделены пробелами. Переставьте первое и последнее слово. 478 Часть II. Вычисления и программирование • Образуйте строку, состоящую из первых букв строк, входящих в массив строк. • Выведите номера одинаковых строк в массиве строк. • Определите количество символов в каждой строке массива строк без учета пробелов. • Но заданному массиву строк образуйте новый, исключив повторяющиеся строки. • Замените в строке цифры числительными (вместо 1,2,... — один, два,...). • Задана строка, содержащая текст и числа. Выделите числа в числовой массив. 2. Напишите файл-функцию для считывания данных из файла в структуру или массив структур с подходящими полями. Алексеев Сергей 1980 544535 Иванов Константин 1981 343435 Петров Олег 1980 555445 21 марта 2002 0.56 0.58 0.49 0.44 23 марта 2002 0.36 0.32 0.28 0.25 25 марта 2002 1.62 1.68 1.71 1.91 195251 СПб Политехническая 29 195256 СПб Науки 49 195256 СПб Науки 24 Результаты наблюдений Time=0.0 0.1 0.2 0.3 0.4 0.5 0.6 Mass= 2.1 2.3 2.3 1 9 1.8 2.4 2.9 0.8 0.7 0.5 1.1 3.2 0.3 0.4 Алексеев Иван 121-22-04 Сидоров Николай 101-21-99 Тимофеев Сepi ей 570-00-03 (номера телефонов должны быть записаны в поля структур как целые числа). Глава 8. Обработка данных и приемы программирования в MATLAB 479 3. Считайте матрицы и векторы из файла в подходящие по размеру массивы. Обратите внимание, что в файлах содержится рядом две или три матрицы или вектора, их следует занести в разные массивы. 0.1 0.2 0.3 9.91 1.9 0.4 0.1 8.01 4.7 5.1 3.9 7.16 12 3 4 5 6 7 8 12 3 4 6 7 8 9 0.5 0.6 0.7 0.8 99 80 33 21 15 90 0.1 0.2 0.3 0.4 100 200 300 4. Проведи ге диалоговую отладку файл-функции allmin с рекурсивной подфункцией из листинга 8.37, если условие попадания точки минимума в интервал сформулировать без использования погрешности е. Для исключения "зацикливания" алгоритма введите условие, ограничивающее количество найденных точек числом 100. 5. Напишите файл-функцию для поиска всех корней функции /(х) на заданном отрезке с использованием стандартной функции fzero. Глава 9 Дескрипторная графика Визуализация результатов связана с управлением видом получающихся графиков. Хорошо написанное приложение само формирует окончательный вид графических результатов и не требует от пользователя внесения каких-либо изменений, например, в редакторе графиков, который описан в главе -f Более того, в процессе работы приложения может возникнуть необходимость изменить, например, толщину линии, вывести текст в мафическое окно или удалить поверхность. В этом случае редактор графиков оказывается бесполезным. MATLAB предоставляет в распоряжение программиста так называемую дескрипторную или управляемую графику (Handle Graphics), основанную на низкоуровневых графических функциях. Дескрипторная графика, в отличие от высокоуровневой графики, которой посвящена глава 3, позволяет получить доступ к свойствам всех графических объектов и изменять их по своему усмотрению. Средства управления графическими объектами, описанные в данной главе, потребуются при разработке приложений MATLAB с графическим интерфейсом. Созданию приложений с графическим интерфейсом посвящены главы 10—13. Основы дескрипторной графики Поскольку MATLAB является объектно-ориентированной системой, то все элементы (графическое окно, оси, линии, поверхности, текстовые области пт. д.) являются объектами. Объекты расположены в определенной иерархической структуре, которую мы подробно обсудим ниже Проще говоря, графическому окну может принадлежать одна или несколько пар осей со своими объектами: линиями, поверхностями или текстом. То есть линия, поверхность или текст не могут просто быть выведены в графическое ок Гпава 9. Дескрипторная графика 481 но — в нем обязательно должны находиться оси, которым принадлежат эти объекты. Каждый объект имеет обширный набор свойств, изменение значений которых позволяет добиться требуемого вида объекта. В главе 4 рассмотрен процесс задания свойств объектов в редакторе графиков, который состоит из двух этапов. 1. Выбор нужного объекта из списка в окне Plot Browser или указание его щелчком мыши (при этом объект становится текущим). 2. Установка нужных свойств при помощи элементов управления окна редактора графиков, соответствующего текущему объекту. При написании собственных приложений, осуществляющих отображение результатов в графическом виде, необходимо знать доступные свойства каждого объек га и уметь изменять их значения в программе. В этом разделе на ряде примеров мы рассмотрим принципы управления основными свойствами графических объектов, а детальное описание их иерархической структуры, свойств и точная терминология приведены в разд. "Графические объекты " этой главы. Св ойства графических объектов Функции set и get позволяют получить и установить свойства любого из объектов в определенные значения. Применение данных функций состоит, по существу, из тех же этапов, что и задание значений в редакторе графиков. а именно — выбор объекта и установка значения свойсз ва. Функции set и get, текущие объекты Постройте график синуса на отрезке [0,10], используя plot. Команды, которые понадобятся при чтении данного раздела, достаточно короткие, поэтому можно задавать их из командной строки, писать файл-программу или файл-функцию в М-файле нет смысла. Итак, операторы » х=0:0.1:10; » y=sin(x); » plot(х, у) приводят к появлению графика функции. В данном случае в результате работы plot создались три графических объекта: графическое окно Figure 1, оси и линия графика синуса. Манипулирование свойствами обьектов в 482 Часть II. Вычисления и программирование МА ГЬАВ производится функциями get и set. Функция get предназначена для получения значений свойств, a set для установки новых значений. При этом функциям get и set следует указать, с каким из существующих объектов ведется работа. Имеется три стандартных функции, возвращаемые значения которых могут быть использованы в качестве входного аргумента get и set: □ gcf — текущее графическое окно; □ дса — текущие оси; □ дсо — текущий графический объект. Обратите внимание, что использование дсх, дса, дсо открывает доступ к свойствам текущего окна, осей или объекта. В данном случае есть только одно графическое окно, оно и является текущим. Единственные оси в графическом окне также являются текущими. Про использование дсо для определения текущего объекта сказано ниже. Свойства осей Выведите в командное окно свойства осей, содержащих график функции, который был построен в предыдущем разделе, для чего выполните команду. » get(дса) В командном окне отображается таблица свойств и их значений. Свойств достаточно много, среди них есть очевидные, а назначение некоторых на первый взгляд кажется непонятным. Свойства осей условно можно разделить на две группы — общие свойства и свойства каждой из осей х, у или г. Название свойств второй группы начинается с соответствующей буквы х, у или z. Таблицы 9.1 и 9.2 содержат основные свойства, которые часто применяю гея при создании приложений. Функция get допускает обращение к ней с двумя вхотны ми аргументами, вторым аргументом является название свойства, значение которого требуется получить, например, команда » fn = get(gca,'FontName1) записывает название шрифта, используемого в текущих осях, в строковую переменную fn и выводит ее значение на экран: fn = Helvetica Глава 9. Дескрипторная графика 483 Таблица 9.1. Свойства, отвечающие за общий виО осей Название свойства Описание Значения Box Заключение осей в прямоугольную рамку •on' (по умолчанию) или 'off Color Цвет фона осей Вектор из трех элементов, задающий цвет в формате RGB, например [III], или один из определенных цветив: г, g и т. д. (см. приложение 1). По умолчанию цвет белый FcntAngle Наклон шрифта разметки осей ' normal ’ (по умолчанию) или 'italic' FontName Название шрифта Строка с названием шрифта, например ' Courier' Fontsize Размер шрифта (по умолчанию в пунктах, 1 пункт = 1/72 дюйма) Целое число (по умолчанию 12) Fontweight Толщина шрифта ’normal' (по умолчанию), 'bold', 'light',или ’demi' GridLineStyle Стиль линий сетки ' — *, (по умолчанию) ' -. ' или ’ попе' LineWidth Толшина линий осей Значение в пунктах(по умолчанию 0.5) Visible Отображение осей ' on' (по умолчанию оси видны), 'off DataAspec tRat io Масштаб осей Вектор из трех элементов, задающий относительный масштаб по каждой из осей PlotBoxAspectRatiо Размеры осей Вектор из трех элементов, задающий относительные размеры каждой из осей 484 Часть II. Вычисления и программирование Таблица 9.2. Свойства каждой из осей (на примере оси X) Название свойства Описание Значения XColor Цвет оси Вектор из трех элементов, задающий цвет в формате RGB, например [111], или один из определенных цветов: ' г ', 'д' И Т. Д. (см. приложение 1) XDir Направление оси 'normal' или 'reverse1 (обратное) XGrid Сетка, перпендикулярная оси 'on' или 'off' XAxisLocation Расположение оси (для оси z отсутствует) 'top' или ’bottom' ('right' или 'left' для оси у) XLim Пределы изменения переменной Вектор из двух компонент, равных пределам изменения переменной, например [-1.5 2.3] XScale Масштаб оси 'linear' или 'log' XTick Координаты разметки оси Вектор с координатами разметки, например [013 5] XTickLabel Разметка оси Вектор ячеек с названиями разметки (число ячеек равно длине вектора с координатами разметки), например {'zero';1 one';1 three'; 'five'} Команда set позволяет установить каждому свойству осей любое из допустимых значений. Первым аргументом задается дса, а вторым и третьим — пара: 'свойство', значение. Приведите оси с графиком синуса (ем. предыдущий раздел) к виду, указанному на рис. 9.1. Гпава 9- Дескрипторная графика ч85 Рис. 9.1. Изменение свойств осей Для этого расположите командное окно MATLAB и графическое окно на экране так, чтобы они не перекрывали друг друга, и при выполнении приведенных ниже команд следите за состоянием осей. Следующие команды задают толщину линий осей, координаты и обозначения разметки, наносят линии сетки и устанавливают цвет фона осей, совпадающий с цветом графического окна: » set(gca, 'Linewidth', 2) » set(gca, 'YTick',[-1 0 1]) » set(дса, 'YTickLalel1,{'у=-1'; 'y=0',- 'y=l'}) » set(gca, 'XGrid', ’ on') » set(gca, 'GridLines', » set(gca, 'Color', [0.8 0.8 0.8]) Часть названий свойств заканчивается словом Mode, например, YTickMode. Такие свойства могут иметь только два значения — 'auto' (устанавливаемое по умолчанию) или 'manual’, причем 'auto' соответствует автоматическому подбору значения соответствующего свойства, в данном случае YTick. Задание вектора в YTick приводит к смене значения YTickMode с 'auto' на 'manual'. Всегда можно отменить проделанные изменения свойства YTick, установив YTickMode в 'auto'. Вышесказанное справедливо для всех свойств, имеющих сопутствующее свойство, которое заканчивается на Mode. 486 Часть II. Вычисления u программирование Итак, команда set позволяет получить доступ к свойствам из собственной файл-программы или файл-функции и изменить вид графика по своему усмотрению. Названия свойств и их возможные значения не отличаются от приведенных в инспекторе свойств, который вы использовали при чтении главы 4 (см. разд. "Цветовое оформление, разметка и сетка"). Среди названий свойств осей, полученных при помощи get(gca), есть Title, Xlabei, Ylabel, Zlabel. Обратите внимание, что их значения не являются текстовыми строками. Они содержат указатели на соответствующие текстовые объекты, об использовании указателей и текстовых объектах подробно написано ниже (см. разд. "Указатели на объекты" и "Текстовые объекты" данной главы). Свойства осей XLim, YLim, ZLim, DataAspectRatio, PlotBoxAspectRacio, отвечающие за пределы, масштаб и относительные размеры осей, взаимосвязаны. Например, относительные размеры осей зависят от пределов и масштаба, более того, при заданных DataAspectRatio, XLim, YLim и, возможно, ZLim значение свойства PlotBoxAspectRatio игнорируется. Таблица связей между ЭТИМИ свойствами И сопутствующими К НИМ XLimMode, YLimMode, ZLimMode, DataAspectRatioMode П PlotBoxAspectRatioMode Приведена в справочной системе MATLAB (см. информацию о свойстве DataAspectRatio осей, например в разд. MATLAB: Functions - Alphabetical List (гиперссылка Axes Piopertiesl). В этом разделе мы рассмотрели только наиболее часто используемые свойства осей, заметим, что всего их более 100. Ряд свойств отвечают за расположение осей в пределах графического окна. Этот вопрос мы обсудим ниже (см. разд "Управление положением осей " данной главы). Графические объекты MATLAB обладают достаточно большим набором свойств, описание которых слишком объемно. Цель этой главы — дать представление об организации графических объектов, их типах и основных приемах работы с ними. Поэтому мы иногда будем только упоминать о тех или иных свойствах, одновременно давая ссылки на соответствующие разделы интерактивной справочной системы. Одним из основных разделов является MATLAB: Graphics: Handle Graphics Objects. Кроме того, быстрый доступ к назначению всех свойств графических объектов производится из браузера свойсгв, размещенного в разд. MATLAB: Handle Graphics Property Browser Использование браузера свойств графических объектов описано в разд. "Полу чение информации о свойствах графических объектов" этой главы. Се ойства линий и поверхностей Стандартная функция дса, задаваемая в качестве аргумента set и get, позволяет получить доступ к свойствам текущих осей. Однако для обращения Глава 9. Дескрипторная графика 487 к текущей линии графика или поверхности в MATLAB нет специальной встроенной функции. Сделайте линию текущим, объектом при помощи щелчка мыши по ней в графическом окне, затем выведите таблицу свойств и их значений в командное окно, используя дсо: » get(дсо) Многие из этих свойств вы изменяли в редакторе при прочтении главы 4. Таблица 9.3 содержит наиболее часто употребляемые свойства линии. Таблица 9.3. Свойства линий Название свойства Описание Значении Color Цвет Вектор из трех элементов, задающий цвет в формате RGB, например [ill], или один из определенных цветов: • г', 'д’ и т. д. (см. приложение I) LineStyle Стиль линии графика ' - * (по умолчанию), ' —', ' :', ' -. ' или ’ попе ’ LineWidth Толщина линии в пунктах (1 пункт = = 1/72 дюйма) Положительное число Marker Тип маркера Одно из стандарта ix обозначений, например 'o','s' (см. табл. 3.1) MarkerEdgeColor Цвет границы маркера Такие же, как у Color MarkerFaceColor Цвет маркера Такие же, как у Color Markersize Размер маркера в пунктах Положительное число Приведите график синуса (см. рис. 9.1) к виду, изображенному на рис. 9.2, используя функции set и дсо. Очевидно, что требуется выполнить следующие команды: » sst(дсо, » set(дсо, » settjeo, » set(дсо, » set{дсо. 'Color', 'k') ’Linewidth1, 2) 1Marker', ’o') 'MarkerFaceColor1, 'w') ’Markersize1, 8) 488 Часть II. Вычисления и программирование Рис. 9.2. Изменение свойств линии Свойства поверхностей изменяются аналогичным образом. Создайте график поверхности какой-либо функции двух переменных, сделайте поверхность текущей при помощи щелчка мыши и выведите таблицу со свойствами и их значениями в командное окно. Изучите самостоятельно возможные свойства (обратитесь к разд. "Свойства линии и поверхностей" главы 4 и разд. MATLAB: Handle Graphics Property Browser справочной системы MATLAB). Ги Примечание Функции высокоуровневой графики для построения поверхностей (mesh, surf, surfi и др.) основаны на низкоуровневой функции surface, которая позволяет создать поверхность с любыми заданными свойствами. Функция дсо указывает на текущий объект, выбранный пользователем щелчком мыши. Данным объектом может быть не только линия или поверхность, но и оси, и графическое окно. Убедитесь в этом, щепкая по объектам И ВЫВОДЯ ИХ СВОЙСТВа При ПОМОЩИ get И дсо. Программирование собственных алгоритмов, связанных с визуализацией данных, как правило, предполагает наличие нескольких графиков, т. е. имеется ряд объектов (графические окна, оси, линии, поверхности и т. д.), свойства которых необходимо изменять в ходе выполнения программы. Объект может быть текущим в данный момент, если он только что был создан или пользователь выбрал его щелчком мыши. Однако часто в ходе выполнения Гпава 9. Дескрипторн w графика 489 программы необходимо установить некоторые свойства объекта не являющимся текущими. Эта задача летки решается при помощи указателей. Указатели на объекты Создание любого графического объекта в MATLAB сопровождается появлением числового указателя на него, таким образом, каждый объект уникальным образом идентифицируется в среде MATLAB. Функции gcf, gca и дсо как раз возвращают указатели на текущее окно, оси и любой текущий объект соответственно. Целесообразнее всего при создании графических объектов записывать их указатели в переменные, которые будут использоваться впоследствии для обращения к нужным объектам. Вызов функций figure, axes, plot, mesh, surfl и т. д. с выходным аргументом приводит к присвоению ему указателя на соответствующее графическое окно, оси, линию графика или поверхность. Причем, если plot осуществляет построение нескольких линий (задано несколько пар векторов значений аргумента и функции), то выходной аргумент является вектором указателей на линии графика. Первый его элемент есть указатель на линию, отвечающую первой паре входных аргументов, второй элемент — указатель на вторую линию и т. д. Изменение свойств линий и осей Оформите последовательность команд для построения графиков двух функций, приведенную в листинге 9.1, в виде файл-программы в М-файле. Названия переменных, содержащих указатели, начинается с символа h. - *............«... . •* ...... ... ... •. - Листинг 9.1. Сохранение указателей на графические объекты ... . ................................................................................:.Л.л’... ..........Гл................ j Формирование векторов со значениями аргумента и функций t = 0:0.1:7; х = sin(t); у = cos(t); % Создание графического окна и запись указателя на него в hFig hFig = figure; М Создание осей в текущем графическом окне и запись указателя на них в hAx %} hAx - axes; 490 Часть //. Вычисления и программирование £{ Построение линий графиков на текущих осях и запись указателей на линии в вектор hLines hLines(1) содержит указатель на первую линию (sin(t)) hLines(2) содержит указатель на вторую линию (cos(t)) %} hLines = plot(t,x, t,y); Операторы приводят к появлению графического окна с графиками двух функции — синуса и косинуса, изображенного на рис. 9.3. На первый взгляд, з о г же результат получается и при использовании plot (t, х, t, у) без предварительного создания окна, осей и получения указателей. Рис. 9.3. Исходный вид графиков Предположим, однако, что после команд, содержащихся в листинге9.1, в программе расположен блок операторов, которые производят вывод некоторых графиков на новые оси других графических окон. Может возникнуть необходимость вернуться к графическому окну с графиками синуса и косинуса и внести некоторые изменения в вид графиков, например, нанести сетку вдоль оси у, изменить стиль линий, т. е. установить новые свойства осей и линий. Указатели, записанные в переменные hAx и hLines. позволяют легко добиться желаемого результата, приведенного на рис. 9.4. Гпава 9. Дескрипторная графика 491 Рис. 9.4. Измененные графики (set и указатели на объекты) Для этого следует использовать функцию set с указателем на объект и парой 'Свойство', значение (ЛИСТИНГ 9.2). .....д..,..™............................. . Листинг 9,2. Изменение свойств линии и осей при помощи указателей •<••*, ..... » . , -Л*»»»» .Я»»»» .... •*»• •**-•* .««*«< J. .. «* % Установка свойства XGrid осей с указателем ЬАх в 'on' set(hAx, 'XGrid', 'on') % Задание цвета первой линии (графика синуса) с указателем hLines(1) set(hLines(1), 'Color ’, ' k') % Задание толщины первой линии (графика синуса) с указателем hLines(1) set (liLines (1) , ' Linewidth', 3) % Задание цвета второй линии (графика косинуса) с указателем hLines(2) set(hLines(2), ’Color', 'k') ?. Задание типа маркера второй линии (графика косинуса) % с указателем hLines(2) set (liLines (2), 'Marker', 'o’) % Задание цвета маркеров второй линии (графика косинуса) % с указателем hLines(2) set(hLines(2), 1MarkerFaceColor', 'w') % Задание цвета границ маркеров второй линии (графика косинуса) % с указателем hLines(2) set (hLines (2), 'MariterEdgeColor', *k‘) 492 Часть II. Вычисления и программирование Первым входным аргументом функции set может быть вектор указателей на некоторые объекты, в этом случае изменяются свойства всех шданных объектов. Примененный подход позволяет получить в дальнейшем свойства любого из созданных графических объектов и делать нужный объект текущим для дополнительных изменений, например, добавления графиков на оси. В любой момент можно вернуться к значениям свойств объекта, установленным по умолчанию. Для этого служит функция reset, в качестве входного аргумента которой задается указатель на объект. Добавление линий графиков Команда plot осуществляет вывод графика на текущие оси поэтому для добавления линий следует сначала сделать требуемые оси текущими, задав входным аргументом функции axes указатель на них, выполнить hold on, а затем использовать plot, желательно с выходным аргументом, для сохранения указателя на новую линию и установить ее свойства при помощи set. Добавьте, например, на оси окна, приведенного на рис. 9.4, график iog(l + t), изобразив его черной пунктирной линией толщиной в три пункта так, как показано на рис. 9.5. Рис. 9.5. Добавление линии i рафика на заданные оси Очевидно, что файл-программу, осуществляющую построение графиков синуса и косинуса и изменение их свойств (листинги 9.1 и 9.2), следует дополнить последовательностью команд, указанной в листинге 9.3. Гпава 9. Дескрипторная графика 493 % Заполнение вектора значений функции z = log (t + 1) ; % Установка текущих осей (с графиками синуса и косинуса) axes jhAx); % Команда hold on нужна для того, чтобы plot добавила линию графика, % а не вывела график в отдельном графическом окне hold on % Добавление линии графика log(t + 1) и сохранение указателя % на нее в переменной hLog hLog = plot(t, z}; % Установка цвета линии графика log(t + 1) set(hLog, 'Color', 'k'); % Установка стиля линии графика log(t + 1) set(hLog, ’Linestyle', ' — ’); % Установка толщины линии графика log(t + 1) set(hLog, 'Linewidth', 3); Заметьте, что можно было не создавать отдельную переменную для хранения указателя на новую линию, а дополнить вектор указателей hLines при помощи оператора hLines (3) = plot (t, z). Хранение указателей на однотипные объекты в массивах оказывается удобным при одновременном изменении их свойств. При таком подходе команда set(hLines, 'Color', 'г') изменяет цвет всех трех линий. Еще один пример работы с массивом указателей приведен ниже. Удаление и очистка объектов Идентификация объекта указателем позволяет не только устанавливать его свойства, но и удалять его командой delete, входным аргументом которой является соответствующий указатель. Например, команда delete(hLines(1)) убирает линию графика синуса с осей графического окна, изображенного на рис. 9.5. Следует иметь в виду, что удаление осей повлечет исчезновение всех графических объектов (линий и поверхностей), принадлежащих данным осям. Аналогично, удаление графического окна приводит к тому, что пропадают все объекты, размещенные в нем. Альтернативным способом удаления линий и поверхностей является очистка осей. Сначала надо еде- 494 Часть II. Вычисления и программирование лать оси текущими, а затем использовать команду очистки текущих осей cla, например, следующие операторы очищают оси с указателем hAK: axes(hAx) cla Очистка текущего графического окна производится командой cif. Влияние команд hold, cla, elf и reset на свойства окна и осей Остановимся более подробно на влиянии команды hold на свойства осей и графического окна. Графическое окно и оси имеют свойство NextPlot, определяющее способ вывода графических объектов при помощи высокоуровневых функций (plot, surf и т. д.), которое может принимать одно из следующих значений: 'add', 'replace' ИЛИ ' replacechildren'. В зависимости от значения свойства NextPlot текущего графического окна при новом графическом выводе возможна одна из трех ситуаций: □ 'add' (по умолчанию)— для вывода используется текущее графическое окно; □ 'replace' — удаляются все объекты, принадлежащие графическому окну. а все его свойства (кроме Position, которое отвечает за положение окна на экране монитора) принимают значения, установленные по умолчанию; □ 'replacechildren' — удаляются все объекты, принадлежащие графическому окну, но его свойства не изменяются. Перед выводом графических объектов высокоуровневые функции проверяют значение свойства NextPlot текущих осей, которое определяет способ вывода: □ 'add' — графический объект добавляется на оси; □ 'replace' (по умолчанию)— перед размещением нового объекта удаляются все старые, принадлежащие осям, а свойства осей (кроме Position, которое отвечает за положение осей в пределах графического окна) принимают значения, установленные по умолчанию; □ ’replacechildren’ — то же, что и replace, но без изменения свойств осей. Очистка осей командой cla приводит к установке значения 'replacechildren' свойству NextPlot осей, а последовательное выполнение cla и reset — значения 'replace'. То же самое верно и для elf в применении к графическому окну. Команда hold on устанавливает значение Глава 9. Дескрипторная графика 495 свойств NextPlot текущего графического окна и осей в 'add', a hold off изменяет только значение NextPlot текущих осей на replace'. Получение информации о свойствах графических объектов Подробное описание всех свойств графических объектов приведено в нескольких разделах справочной системы MATLAB. Во-первых, структура графических объектов и приемы работы с ними разобраны в разд. MATLAB: Grannies: Handle Graphics Objects. Во-вторых, список функций дескрипторной графики с гиперрсылками на соответствующие страницы приведен в разд. MATLAB: Functions — Categorical List: Graphics: Handle Graphics. Кроме того, возможен быстрый доступ к информации о свойствах графических объектов из браузера свойств, размещенного в разд. MATLAB: Handle Graphics Property Browser. Обсудим, как пользоваться этим разделом. При выборе разд. MATLAB: Handle Graphics Property Browser в правом окне справочной системы MATLAB появляются вкладки с названиями объектов, которые являются гиперссылками. Вкладки Figure и Axes не требуют пояснений — они служат .для доступа к свойствам графического окна и осей. Щелчок мышью по этим гиперссылкам приводит к появлению списка всех свойств объекта и их назначения в нижней части окна, причем она разделяется на два столбика. В левом столбике с полосой скроллинга находятся гиперссылки с названиями свойств объекта, при переходе по гиперссылке в правом столбике отображается описание выбрандого свойства и его возможные значения. Установленные по умолчанию значения заключены в фигурные скобки. Кроме того, вверху окна показывается место выбранного объекта в иерархии графических объектов MAI LAB. Вкладка UI Objects предназначена для элементов графического интерфейса пользователя, которому посвящены следующие несколько глав. Выбор вкладки Core Objects приводит к появлению части иерархической структуры объектов, в которую включены базовые объекты: линия (Line), текстовый объект (Text), полигональный (Patch) и т. д. (работа с базовыми объектами рассмотрена в разд. ''Графические объекты", а с текстовым объектом -— в разд. "Текстовые объекты" данной главы). Большинство высокоуровневых графических функций создают рисованные объекты (Plot Objects), используя базовые объекты Щелчок мышью по одноименной вкладке в окне браузера свойств позволяет отобразить названия рисованных объектов (гиперссылки) и их место в иерархии. Заметьте, что нарисованная функцией plot линия в действительности является объектом Lineseries с более широким набором свойств, чем у базового объекта Line. 496 Часть II, Вычисления и программирование Аналогично, функции loglog, semilogx, semilogy и plot 3 так же приводят к созданию объекта Lineseries, Функции для построения столбчатых диаграмм bar и barh рисуют объект Barseries, а функция area — объект Areaseries. Контурные графики, полученные при помощи contour, это объекты Contourgroup. Результатом работы функций mesh, meshc, surf и surfc является объект Surfaceplot. Таблица соответствий высокоуровневых графических функций и создаваемых ими объектов приведена в разделе справочной системы MATLAB: Graphics: Handle Graphics Objects: Plot Objects. Для того чтобы выяснить, какой именно объект создает высокоуровневая графическая функция, достаточно перейти к ее описанию в справочной системе, например, в разд. MATLAB: Functions — Categorical List: Graphics Яци в разд. MATLAB: Functions — Alphabetical List. Итак, если требуется получить свойства объектов, порожденных большинством высокоуровневых графических функций, то следует обратиться к содержимому вкладки Plot Objects. Графические объекты MATLAB могут быть сгруппированы для выполнения однотипных операций или доступа к ним как к одному объекту. Вкладка Group Objects предназначена для просмотра свойств двух возможных типов сгруппированных объектов: hggroup и hgtransform (работа со сгруппированными объектами описана в разе). "Объекты-группы hggroup и hgtransform" датой главы).. Последняя вкладка Annotation Objects служит для просмотра свойств поясняющих объектов: стрелок, линий, надписей и т. п., которые вы создавали при помощи интерактивной среды для построения графиков при чтении главы 4 (создание поясняющих объектов объяснено в разд. "Размещение текста, линий и стрелок в графическом окне"данной главы). Еще одну возможность для получения информации о свойствах и их допустимых значениях предоставляют функции get и set. Функция get, как было описано выше, позволяет вывести установленные значения всех свойств или только одного свойства. Список всех возможных значений конкретного свойства может быть получен при помощи set, первый аргумент которой является указателем на графический объект, а второй — названием нужного свойства данного объекта. Например, все обозначения для маркеров, определенные в MATLAB, выводятся в командное окно следующим образом (hL — указатель на некоторую линию): » set(hL, 'Marker’} [ + ] о | * | . | x | square | diamond | v | Л | > | < | pentagram | hexagram | {none} ] Гпава 9. Дескрипторная графика 497 Использование указателей, примеры Наличие большого числа графических объектов требует умения оперировать их свойствами. Эффективной оказывается запись указателей на однотипные объекты в числовой массив. Газберем обработку графических объектов на примере файл-функции с интерфейсом из командной строки, предназначенной для исследования различных математических функций. Пользователь задает в командной строке формулы для вычисления функций одной переменной х (в соответствии с правилами MATLAB), а программа выводит графики функций в графическое окно, автоматически выделяя маркерами i рафик последней построенной функции, а жирной линией — график функции, имеющей максимальное значение среди всех введенных функций. По завершении работы (пользователь ввел end на запрос программы) графическое окно закрывается. Предусмотрите также возможность очистки осей, которая происходит, если пользователь вводит new. Оформите программу в виде файл-функции с входными аргументами — границами области определения функций. Вначале постройте графическое окно и оси в нем, сохраните указатели на данные объекты. Запрос на ввод ор1анизуйте в цикле while при помощи команды input. Обработку ввода пользователя произведите с использованием switch. Запоминайте номер функции с максимальным значением и само значение в некоторых переменных. Максимальное значение проще всего найти, применяя max к вектору значений функции. Указатели на линии графиков записывайте в массив Листинг 9.4 содержит текст файл-функции maxfun, в которой реализован вышеописанный алгоритм. Листинг 9.4. Файл-функция maxfvn, использующая указатели на объекты .............................................................. ................................ ........................ ............................... .... function maxfun(а, Ь) % Файл функция для исследования функций на отрезке [а, Ь] % Использование: maxfur,(a, b) % Создание графического окна (оно становится т >кущчм’ hF = figure; % Создание осей в текущем графическом окне hAx - axes; % Установка NextPlot для добавления графиков на оси set(hAx, 'NextPlot', 'add') % Радание вектора значений аргумента х = а:(Ь - а)/30:Ь; str ; % инициализация строки запроса ввода пользователя 498 Часть II. Вычисления и программирование funcount = О; % инициализация счетчика риеденн-^х функций hFuns = []; % инициализация массива указателей на линии графиков % Обработка ввода пользователя в бесконечном цикле while 1 str=input('Введите функцию, или new, или end: ','s'); switch str case 'new' % Пользователь задал очистку осей axes(hAx); % оси с указателем hAx стали текущими cla % очистка текущих осей case 'end' % Пользователь завершает работу с программой break % выход из цикла otherwise % Пользователь ввел новую функцию % Формирование команды для вычисления массива значений eval(strcat('у =',str,';')); funcount = funcount + 1; % увеличение счетчика функций % Оси hAx должны быть текущими для вывода графика axes(hAx) % Построение графика функции, введенной пользователем, % и добавление указателя на него в массив указателей hFuns(funcount) = plot(x, у); % Установка требуемых свойств линии графика новой функции set(hFuns(funcount),'Marker', 'o', 'MarkerEdgeColor*, 'k1, ... 'MarkerFaceColor’, 'w', ’Color', 'k') if funcount == 1 % пользователь ввел одну функцию "laxval = max(у); % находим ее максимальное значение Nmaxval = 1; % цока первая функция имеет максимальное значение % Рисуем ее график жирной линией set(hFuns(funcount), 'Linewidth', 3) else % пользователь ввел две или более функций % Удаление маркеров с графика предыдущей функции set(hFuns(funcount - 1), 'Marker', 'none') M = max(y); % находим максимальное значение новой функции if М > maxval % Новая функция принимает самое большое значение среди % всех функций, введенных пользователем, поэтому % ее график должен рисоваться жирной линией Глава 9. Дескрипторная графика 499 set (hFaiiS {funcount), 'LineWidth', 3) % Линия графика функции, которая ранее имела максимальное % значение, теперь не должна быть жирной set(hFuns(Nmaxval), 'LineWidth', 1} % Запоминаем новое максимальное значение и номер функции maxval = М; Nmaxval = funcount; else % значения новой функции не превосходят значений предмиутих set(hFuns(funcount), 'LineWidth', 1) end end end end % Выход из цикла while производится, когда пользователь ввел end delete(hF) % удаление графического окна с экрана Сделайте работу файл-функции naxfun более надежной, применив конструкцию try...catch для обработки исключительной ситуации, которая может возникнуть при неверном вводе формулы для исследуемой функции. Задание свойств в аргументах графических функций Применение указателей на графические объекты полезно при изменении свойств объекта в ходе работы программы. Создание объекта с определенными свойствами может быть осуществлено и при помощи высокоуровневых функций. В качестве дополнительных входных аргументов задаются пары 'свойство', значение. Например, последовательность команд листинга 9.5 приводит к графику, изображенному на рис. 9.4, который ранее мы получали установкой свойств линий и осей функцией set с указателями на данные графические объекты (см. листинги 9.1 и 9.2). ’•“**'*******’**“ ..'уауудму,— Листинг 9.5. Задание свойств в аргументах графических функций * а. - < . . . .... .. .....а..-..- а. •. . ..... . > V. *»*»**. **^»^*.***.»^.^., .... ..... . t = 0:0.1:7; х = sin(t); у = cos(t); figure axes('XGrid', ' on1, 'NextPlot', 'add') 17 3sk 130 500 Часть II. Вычисления и программирование plotit, х, 'Color', 'к', 'LineWidth', 3) p^ot(t, у, 'Color', 'к','Marker', 'o', 'MarkerFaceColor', 'w', . . . 'MarkerFaceColor', 'w', 'MarkerEdgeColor', 'k'); Обратите внимание, что в случае указания нескольких пар векторов со значениями аргумента и функции происходит одновременное изменение свойств всех линий, например- » plotft, х, t, у, 'Color', 'г', 'Linewidth', 3, 'Marker', ’o') Если дальнейшее изменение свойств объектов не предполагается, то можно обойтись без выходных аргументов, в которые заносятся указатели на создаваемые объекты. Разумеется, если сохранить указатели, то их можно задействовать впоследствии для изменения свойств этих объектов. Аначогич-ным образом задаются свойства графического окна (в списке входных аргументов функции figure), осей (в списке входных аргументов функции axes) и поверхностей (в списке входных аргументов surf, mesh и других функций) Следующий раздел посвящен созданию графических окон и осей с заданными размерами и положением на экране, а также выводу на них текстовой информации. Размещение окон, осей и текста Вывод результатов работы требует предварительного создания графических окон и осей с заданными размерами и положением. Кроме того, хорошо написанное приложение не должно быть привязано к какому-либо разрешению, установленному на мониторе. Следующие разделы посвящены описанию тех свойств графических окон и осей, которые оказываются полезными при организации вывода графиков и текста в различные окна и оси. Расположение графических окон и осей Рассмотрим свойства графического окна, определяющие его вид, положение и размеры на экране мони гора, а также свойства осей, которые позволяют не только расположить оси в любом месте графического окна, но и сделать согласованными изменения размеров осей и графического окна. Управление положением графических окон Свойство Position графического окна отвечает за положение окна на экране и его размер. Значением Position является вектор из четырех элементов, имеющий следующий формат: [left bottom width height). Гпава 9. Дескрипторная графика 501 где left задает расстояние от левого края монитора до левого края области окна без учета толщины рамки, bottom означает расстояние от нижнего края монитора до нижнего края области окна, также без учета толщины рамки, a width и height определяют, соответственно, и'ирину и высоту области окна. Рис. 9.6. Положение графического окна на экране На рис. 9.6 приведена схема расположения графического окна на экране монитора, рабочая область окна изображена белым цветом. Графическое окно белого цвета позволяет убедиться в том, что рамки действительно присутствуют. Толщина левой и нижней рамок составляет четыре пиксела. Представление графических результатов в собственных программах часто не требует отображения в графическом окне его меню. У становка свойства MenuBar в 'попе' приводит к скрытию меню и, следовательно, увеличению области окна. Создайте графическое окно без меню командой » hF - figure('Color', 'w', 'MenuBar', 'none') и получите его размеры, указав входными аргументами get указатель на текущее ОКНО И Position: » pl = get(hF, 'Position') pl = 232 258 560 420 Единицами измерения по умолчанию являются пикселы Про установку других единиц написано ниже. Максимизируйте теперь графическое окно при помощи кнопки, расположенной в верхнем правом углу окна (рамки окна при этом не отображаются на экране) и выведите значение свойства Position еще раз (числа в данном примере получены на мониторе с разре bO2 Часть II. Вычисления и программирование шением 1024x768, если ваш монитор настроен на другой режим, то результаты могут отличаться): » р2 = get(hF,'Position') р2 = 1 1 1024 749 Итак, сейчас ширина рабочей области совпадает с шириной экрана, а 768 -- 749= 19 пикселов отводится под заголовок графического окна Figurel помещенный вверху окна. Несложные подсчеты позволяют найти требуемые ширину и высоту графических окон, располагающихся на экране заданным образом. Однако для того чтобы обеспечить правильную работу программы вне зависимости от установленного разрешения монитора, следует предварительно получить его. Разрешение монитора хранится в виде вектора из четырех элементов в свойстве screensize объекта с указателем, равным нулю (объекта Root) (положение объекта Root в иерархии объектов MATLAB и его свойства приведены в разд. "Объект Root" этой главы). » s = get(0, 'ScreenSize') s - 1 1 1024 768 Единицы измерения размера экрана зависят от значения свойства Units объекта Root, по умолчанию установлены пикселы. Очевидно, что графическое окно без меню и рамки, занимающее ьесь экран, появляется в результате выполнения команд, приведенных в листинге 9.6. •V.«...."“Л. ... .. .... . ... .. ..... Листинг 9.6. Расположение графического окна на есь экран % Нахождение размеров экрана SCRsize = get(0, 'ScreenSize') 5 Область окна начинается от левого и нижнего края экрана, % рамка не нужна left = SCRsize(1); bottom = SCRsize(2); % Ширина области окна равна ширине экрана width = SCRsize(3); % Высота окна вычисляется с учетом ширины заголовка окна height = SCRsize(4) - 19; % Создание окна без меню, рабочая область и заголовок растянуты % на весь экран, границы не отображаются hF = figure('Position',[left bottom width height],'MenuBar','none') Глава 9 Дескрипторная графика 503 Создайте и расположите на экране два графических окна без строки меню, делящих экран на равные части по вертикали. Оформите результат в виде файл-функции, возвращающей вектор указателей на графические окна. При вычислении размеров и положения окон учтите ширину рамки и заголовка окна. = ........................................................................ Листинг 9.7 о.зйг -функция fxg2 для создания двух графических окон ................... ... ........ ..а», а. ... ..... .... К. .... ............ function hFigs = fig2 % Создание двух графических окон равной высоты, делящих экран % на две части по вертикали. Возвращает вектор указателей на окна % Использование hFigs = fig2 % Нахождение размеров экрана SCPsize = get(0, 'Screensize'); % Выделение ширины и высоты экрана SCRwidth = SCRsize(3); SCRheight = SCRsize(4); % Ширина, высота и отступ слева одинаков для обоих окон width = SCRwidth -5-3; height = (SCRheight - 19 - 5 - 3 - 19 - 5 - 3)/2; left = 5; % Отступ снизу для нижнего графического окна равен 5 пикселям bottom2 =5; % Вычисление отступа снизу для верхнего окна с учетом толщины % рамок и заголовка нижнего окна и толщины верхней рамки нижнего % окна bottoml = 5 + height +19+5+3; % Создание окон без меню, рамки отображаются hFigs(1) - figure('Position', [left bottoml width height],... 'MenuBar’, ’none', 'Color', ' w'); hFigs(2) = figure('Position', [left bottoms width height],... 'MenuBar', 'none', 'Color', 'w’>; Аналогичным образом размещается на экране любое число графических окон с заданными размерами и положением. Следующим этапом является создание подходящих осей в пределах графических окон. 504 Часть II. Вычисления и программирование Управление положением осей Оси графиков являются объектами, принадлежащими графическим окнам, причем каждое графическое окно может содержать несколько осей. Функция subplot предлагает самый простой способ расположения осей — в виде матрицы (применение subplot описано в разд. "Несколько графиков в одном графическом окне" главы 3). Еолее универсальным подходом является создание осей при помощи функции axes с указанием их размеров и положения. Создайте новое графическое окно без меню и оси. заключенные в рамку, сохраните указатели на данные обьекты и получите значение свойства Position осей: » hF = figure('MenuBar' ; 'none', 'Color', V); » hAx = axes(’Box', 'on’); » a = get (hAx, 'Position') a = 0.1300 0.1100 0.7750 0.8x50 Итак, положение рамки осей задается вектором из четырех элементов (left bottom width height] где left равно расстоянию от левой границы рабочей области графического окна до рамки, bottom— от нижней границы рабочей области графического окна до рамки, a width и height, соответственно, определяют ширину и высоту рамки осей (рис. 9.7 и 9.8 для случая двумерных и трехмерных осей). По умолчанию используются нормализованные единицы для измерения расстояний, т. е. ширина и высота рабочей! области графического окна принимаются равными единице, а начало координат помещается в левый нижний угол области окна. Единицы измерения устанавливаются свойством units осей Нормализованные единицы 'normalized' наиболее удобны при управлении расположением осей Если при помощи свойств DataAspectRatioMode ИЛИ PlotBoxAspectkatioMode задана пропорция между длинами осей (т. е. размеры осей не являются независимыми), то оси будут занимать максимально возможную площадь прямоугольной области ширины width и высоты height. При использовании свойства Position не всегда удается расположить оси так, чтобы хватило места для координат разметки, заголовка и подписей к осям. Более гибкое управление положением осей позволяют осуществить три свойства: ActivePositionPr<iperty, Outerposition И Tightlnset. Значением свойства Outerposition, так же как и Position, явчяется вектор из четырех элементов. В данном случае он задает левый нижний угол, ширину и высоту воображаемого прямоугольника, который заключает в себя оси и поля вокруг них с заголовком и подписями к осям. Расположение осей Гпава 9. Дескрипторная графика 505 при помощи Outerposition гарантирует, что эти элементы всевда будут видны. Рис. 9.7. Расположение двумерных осей в графическом окне Рис. °.8. Расположение трехмерных осей в графическом окне Свойство Tightlnset служит для точного определения размеров полей вокруг рамки, которые нужны для координат разметки осей, заголовка и подписей к осям. Это свойство доступно только для чтения, его значением является вектор из четырех элементов: [left bottom right top], где left — ширина добавленного поля слева от рамки осей, a bottom, right и top — снизу, справа и сверху соответственно. Значения свойств outerposition и Tightlnset, так же как и Position, измеряются в единицах, указанных в Units. 506 Часть II Вычисления и программирование В качестве примера создайте оси » hA=axes('Position', [0.2 0.2 0.6 0.6]} и выведите значение свойства Tightlnset » t=get(hA,'Tightlnset') t = 0.0393 0.0405 0.0089 0.0190 Затем добавьте подпись к оси ординат и снова обратитесь к Tightlnset » ylabel('ось у') » t=get(hA,'Tightlnset'} t = 0.0857 0.0405 0.0089 0.0190 Для подписи по оси v дополнительно понадобилось поле шириной 0.0857 --0.0393 = 0.0464 в нормализованных единицах измерения. Напишите файл-функцию ахезЗ, которая создает три пары осей на заданном графическом окне так, как изображено на рис. 9.9, и возвращает указатели на созданные оси. Входным аргументом ахезЗ должен быть указатель на графическое окно. Рис. 9.9. Пример расположения осей Глава 9. Дескрипторная графика 507 Текст файл-функции axes3 приведен в листинге 9.8. 7” . .................... .......... ............ 1м с г ИНГ 9.3. Ф йп-функция хезЗ t.................. :....................... function hAx = ахезЗ(hF) % Создание осей в графическом окне с указателем hF. % Возвращает вектор указателей на оси. % Использование hAx = ахезЗ(hF) figure(hF) % Окно с указателем hF становится текущим % Создание осей в текущем окне hAx(l) = axes(’OuterPosition’, [0 0.5 0.5 0.5], 'Box', ’on’); hAx(2) = axes('OuterPosition', Д0.5 0.5 0.5 0.5], 'Box', 'on'); hAx(3) = axes('OuterPosition', [0 0 0.5 0.5], 'Box', 'on'); Файл-функции axes3 и fig2 (см. листинг 9.7) позволяют лепсо получить два графических окна, разделяющих экран монитора по вертикали на равные части, каждое из окон содержит по три оси: » hFigs = fig2; » hAxTop = ахезЗ(hFigs(1)); » hAxBot = ахезЗ (hFigs (2) ); При изменении размеров графического окна размеры осей также изменяются. При этом MATLAB пересчитывает их, ориентируясь на свойство Position либо Outerposition. Выбор определяется значением свойства ActivePositionProperty: 'position' либо 'outerposition'(ПО умолчанию) соответственно. Рели ActivePositionProperty установлено в 'outerposition', то заголовок, подписи к осям и разметка не выйдут за пределы графического окна при уменьшении его размеров. Однако если вы создали оси и задали их свойству Position некоторое значение, TO ActivePositionProperty автоматически приобретет значение 'position'. Пример работы с графикой. Исследование функций Используйте файл-функцию axes3 (см. листинг 9.8) при решении следующей задачи. Требуется написать программу для исследования поведения функций вблизи корня и локального минимума. Программа должна выводить в одном графическом окне три iрафика— график функции на заданном интервале и графики этой функции вблизи локального минимума и корня. Прщрамму оформите в виде файл-функции zeroandmin. Имя исследуемой функции (или указатель на нее, или inline-функция) и границы интервала 508 Часть II. Вычисления и программирование задаются во входных аргументах zeroandmin. Построение графиков функций осуществите при помощи fpiot, которая сама подбирает вектор значений аргумента, учитывающий особенности поведения функции (применение fpiot и функций MATL.AB, предназначенных для нахождения локальных минимумов и нулей, описано в разд. "Файл-функции с одним входным аргументом" главы 5 и "Исследование функций" г швы б). Листинг 9.9. Файл-функция z^rcanomin, предназначенная для исследования функций function zei oandfnin (fun, a, b) % Исследование поведения функций вблизи корня и % локального минимума на отрезке [а, Ь] % Использование zeroandmin(fun, а, Ь) % Формирование параметров функций fzero и fminbnd % Подавление вывода в командное окно информации о ходе вычислений options = optimset('Display', 'off'); % Поиск нуля функции на [а, Ь] zero = fzero(fun, (а b], options); 4 Поиск локального минимума функции на [а, Ь] xmin = fminbnd(fun, a, b, options); % Создание графического окна hF = figure('MenuBar', 'none', 'Color', 'w'); % Использование axes3 для построения трех осей hAx = axes!(hF); % Задание delta для вывода графиков вблизи корня и % локального минимума delta = (b - а)/30; axes(hAx(1)) % оси с указателем ЬАх(1) стали текущими % Вывод графика функции вблизи ее минимума на верхние левые оси fpiot(fun, [xmin - delta xmin + delta]) axes'hAx(2)) % оси с указателем hAx(2) стали текущими % Вывод графика функции вблизи ее нуля на верхние правые оси fplctffun, [zero - delta zero + delta]) axes(hAx(3)) % оси с указателем hAx(3) стали текущими % Вывод графика функции на [а, Ь] на нижние оси fpiot(fun, [а b]) Гпава 9. Дескрипторная графика 509 Теперь исследовать поведение функции вблизи корня и локального минимума и одновременно вывести график всей функции не представляет большою труда, например,вызов » zeroandmin{@sin, -pi, pi) приводит к появлению графического окна, изображенного на рис. 9.10, с графиком синуса на отрезке [-л. л] и i рафиками, которые построены в окрестностях точек, интересующих пользователя. Рис. 9.10. Исследование функции sin(.r) при помощи zeroandmin Вывод текстовой информации Результаты, представленные в графической форме, следует снабдить соответствующими пояснениями, которые облегчают чтение графиков. Добавление заголовков на текущие оси осуществляется командой title так, как описано в разд "Оформление графиков" главы 3. Разберем более общий подход, позволяющий изменять заголовки в ходе выполнения программы и размещать текст и формулы в произвольном месте графического окна. 510 Часть II Вычисления и программирование Текстовые объекты Мы уже упоминали, что функции высокоуровневой графики title, xlabel, уlabel и ziabei служат не только для добавления заголовка и подписей к осям, ио и возвращают указатели на соответствующие текстовые объекты. Следовательно, можно управлять свойствами полученного объекта для достижения желаемого результата. Команда hTxt = title('График функции sin({itx))') не только добавляет заголовок над областью текущего . рафика, но и позволяет впоследствии изменять его при помощи ус гановки свойств текстового объекта с указателем hTxt. Например, в любом месте программы можно изменить цвет заголовка, использовав set: set(hTxt, 'Color', 'г') Текстовый объект может быть заключен в прямоугольную рамку, причем цвета рамки и фона выбираются независимо. Поля между текстом и рамкой также не являются фиксированными. Свойства текстовых объектов, отвечающие за характеристики шрифта, цветовое оформление и поля вокруг текста и их возможные значения, приведены в табл. 9.4. Таблица 9.4. Общие сидйажа шрифта Название свойства Описание Значения String Текст Строка в апострофах или строковая переменная или массив ячеек, состоящий из строк, для получения многострочного текста. Может содержать текст в формате ТеХ и LaTeX FontAngle Наклон шрифта ' normal' — прямой (по умолчанию), 'italic' —курсив Fonr.Name Название шрифта Строка с названием шрифта, установленного на компьютере, например, 'Courier' Fontsize Размер шрифта Целое число FontWeight Толщина шрифта 'normal' (по умолчанию). 'bold', 'light' ИЛИ 'demi' Гпава 9. Дескрипторная графика 511 Таблица 9.4 (окончание) Название свонст ва Описание Значения Interpreter Использование формата 1 eX для отображения греческих букв и символов ' tex’ — использовать формат ТеХ (по умолчанию). ’ latex' — использовать формат LaTeX, 'none' —не использовать Color Цвет шрифта Вектор из трех элементов, задающий цвет в формате RGB, например [111] или один из определенных цветов: 'г', 'д' и т. д. (см. приложение 1) Backgroundcolor Цвет фона Вектор из трех элементов, задающий цвет в формате В GB, например [111] или один из определенных цветов: 'г', 'д' и т. д. (см. приложение 1) Linestyle Стиль линий прямоугольной рамки (по умолчанию), ' — '-.' или ' попе' LineWidth Толщина линий прямоугольной рамки в пунктах (1 пункт = = 1/72 дюйма) Положительное число EdgeColor Цвет рамки Вектор из трех элементов, задающий цвет в формате RGB, например [l 11] или один из определенных цветов: ' г', 'д' и т. д. (см. приложение I) Margin Ширина полей в пунктах(1 пункт= - 1/72 дюйма) Положительное число Команда title использует функцию text, которая создает текстовый объект, принадлежащий текущим осям. Создание и размещение текстовых объектов на текущих осях может быть выполнено при помощи функции text. Входными аргументами text в простейшем случае являются координат, определяющие положение текста и строка, а в качестве необязательного вы 512 Часть II. Вычисл! >ния и программирование ходного аргумента задается указатель на созданный текстовый объект, например hTxt = text(x, у, 'точка с координатами (х, у)') Более общее обращение к text позволяет управлять свойствами текстового объекта: hTxt = text('Свойство', значение, 'Свойство', значение,...) MATLAB предоставляет обширные возможности для управления положением текстовых объектов в пределах осей (табл. 9.5). Следует иметь в виду, что координаты текстового объекта могут быть выражены в различных единицах измерения в зависимости от требуемого результата. Координаты отсчитываются от левого нижнего угла осей и могут быть абсолютные inches, centimeters, points, pixels или нормализованные normalized (ширина и высота области осей принимаются равными единице, а начало координат помещается в левый нижний угол области окна). Кроме того, удобно использовать координатную систему осей для вывода текста в нужную позицию — свойство Units текстового объекта должно иметь значение data (именно оно стоит по умолчанию). Данный способ является наиболее подходящим, если требуется вывести текст рядом с определенной точкой графика. Примечание Текстовый объект принадлежит осям согласно иерархии графических объектов, однако он не обязательно находится внутри осей. Выведите, например, значение свойства Position для заголовка или подписей к осям и сравните координаты текстового объекта с пределами осей. Команды, приведенные в листинге 9.10, строят график ф} нкции и размещают пояснения в заданной точке с координатами (Xtext, Ytext). ' , л. • «. jq * .. • • . । . i, । । . i . . • UM-* . .... • л .ll'juumji • » Листинг 9.10 Вывод текстового объекта точку с заданными координатами ..................... ..... ............................................................—$.....'ki.’f.S % Создание графического окна и осей hF = figure('MenuBar', 'none', ’Color', 'w'); hAx = axes; % Генерация векторов значений аргумента и функции х - -2:0.01:3; у = ехр(-х.л2); plot(х,у) % Задание координат положения текстового объекта Xtext = 1.17; Глава 9. Дескрипторная гоасЬика 513 Ytext = exp(-Xtext.л2); % Создание и отображение текстового объекта hTxt = text (Xtext, Ytext, 'Mefr.arrow Функция (ityf = (ite}A{-x^2J’); Результат выполнения файл-программы, приведенной в листинге 9.10, изображен на рис. 9.11. Рис. 9.11. Помещение текста в заданную позицию Итак, положение текстового объекта задается координатами в любой из вышеперечисленных систем единиц. Свойства HorizontaiAl igrunent и VerticalAlignment предназначены для указания способа выравнивания области текстового объекта относительно заданного положения. 4.Hiddle-and..............bottomind Рис, 9,12. Выравнивание области текстового объекта 514 Ча'.гь II Вычислрнир и пре раммирование Некоторые примеры выравнивания приведены на рис. 9.12. Полную информацию о значениях данных свойств можно получить при помощи справочной системы MATLAB. Таблица 9.5. С войства, отвечанлцие м расположение текста Название свойства Описание Значения HorizontalAlignment Выравнивание по горизонтали относительно положения, заданного Position ' left ’ (по умолчанию), 'center', 'right' Position Положение текста в пределах осей Вектор из двух или трех элементов, определяющий расположение текстового объекта, единицы измерения задаются свойством units Rotation Угол поворота текста Значение в градусах Units Единицы измерения 'inches', 'centimeters1, 'points', 'pixels', 'normalized', 'data' (no умолчанию) VerticalAlignment Выравнивание по вертикали относительно положения, заданного Position 'top', 'cap', 'middle'(no умолчанию), ' baseline', 'bottom' Visible Отображение текстового объекта 'on' (поумолчанию), 'off Усовершенствуйте файл-функцию zeroandmin (см. листинг 9.9) так, чтобы в окне с графиком функции указывалось положение корня и локального максимума, а верхние графики в увеличенном масштабе снабдите соответствующими заголовками. Очевидно, что для задания положения текстовых объектов требуется знать не только абсциссу точки минимума, но и ординату. Используйте обращение к функции fminbnd, позволяющее одновременно получить требуемое значение функции в точке локального минимума. Листинг 9.11. Изменение файл-функции zeroandmin % Поиск локального минимума функции на [а, Ь] t лава 9. Дескрипторная графика 515 % Получение значения функции и аргумента локального минимума [xmin, frtkin] = fminbnd(fun, a, b, options); % Заголовки и пояснения axes[hAx(1)) % левые верхние оси текущие title('Лок. минимум') % добавление заголовка axes(hAx(2)) % правые верхние оси текущие title(’Ноль функции') % добавление заголовка axes(hAx(3)) % нижние оси текущие % Создание текстового объекта, расположенного в нуле функции hTxtZer = text('String', 'leftarrow ноль', 'Position' , [zero 0]); % Создание текстового объекта, расположенного в лок. минимуме функции hTxtMin = text('String', 'leftarrow лок.мин.’,... 'Position' , [xmin fmin], 'Rotation', 90); Графики, которые теперь выводит файл-функция zeroandmin, более наглядны (рис. 9.13). Рис. 9.13. Результат работы усовершенствованной zeroandmin В графическом окне, приведенном на рис. 9.13, имеется свободное место внизу справа, которое можно использовать для вывода численных результа 516 Часть II. Вычисления и программирование тов. Согласно иерархии объектов, текст может принадлежать только осям, поэтому возникает вопрос, как поместить текст в произвольное место графического окна. Линии, стрелки и текстовые пояснения При чтении главы 3 вы освоили специальные инструменты Plotting Tools интерактивной среды для рисования стрелок, линий и добавления текстовой информации в графическое окно. Данные элементы размещаются на специальных невидимых осях — слое пояснений (Annotation layer), совпадающих по размерам с графическим окном. Рассмотрим теперь, как добиться аналогичного результата в файл-программе или файл-функции Все поясняющие объекты (Annotation objects) создаются при помощи одной функции annotation. Первым ее входным аргументом является строка с названием объекта: 'line' — линия (Annotation Line), 'arrow' — стрелка (Arrow), ' doublearrow • — двунаправленная стрелка (Doublearrow). 'textarrow1 —стрелка с текстовой надписью (Textarrow), 'textbox' —текстовая надпись (TextBox), 'ellipse' — эллипс (Ellipse) или 'rectangle' — прямоугольник (Rectangle). В скобках приведены названия этих объектов в справочной системе. Остальные входные аргументы определяются типом выбранного объекта. Причем для одномерных обьектов, т. е. линий и разного рода стрелок, указываются два вектора х и у с координатами начальной х(1), у(1> и конечной х(2), у(2) точек. Двумерные объекты (текстовая надпись, эллипс или прямоугольник) требуют задания вектора из четырех элементов в качестве второго входного аргумента функции annotation: координат левого нижнего угла, ширины и высоты объекта. В случае эллипса определяется прямоугольная рамка, в которую он вписан. Примите во внимание, что значения координат должны быть в нормализованных единицах графического окна, т. е. ширина и высота окна равны единице, а начало координат находится в левом нижнем углу окна (см. разд. "Управление положением осей"данной главы). Выходным аргументом функции annotation является указатель на созданный объект, который необходим для изменения значений его свойств при помощи set. Рассмотрим свойства поясняющих объектов на примере стрелки с текстовой надписью (объекта Texlarrow), указывающей на начало координат графического окна. Сначала создадим графическое окно и сам объект, сохранив указатель на него в переменной ьта » figure » hTA = annotation('textarrow', [0.5 0], [0.5 0]); Так же как и в случае текстовых объектов, свойство sting позволяет определить надпись к стрелке. Глава 9. Дескрипторная графика 517 Значением свойства sting может быть строка или массив ячеек строк для многострочного текста: » txt{l} = 'Начало координат’; » txt{2} = 'графического окна' » set (МА, 'String', txt) Форма острия стрелки выбирается с привлечением свойства Headstyle, которое может принимать различные значения. По умолчанию свойство Headstyle установлено в значение *vback2'. Для получения, например, обычного треугольною закрашенного острия следует выбрать значение 'plain': » set (МА, ' HeadStyle', ' plain') Сокращения для всех типов стрелок приведены в справочной системе — обратитесь к соответствующей таблице при помощи браузера свойств графических объектов. Ширина и длина острия стрелки определяются значениями свойств Headwidth и HeadLength соответственно. Толщина линии зависит от значения свойства Linewidth. Значения этих свойств задаются в пунктах (1 пункт = 1/72 дюйма). Разберем более подробно цветовое оформление объекта Textarrow, поскольку оно несколько отличается по сравнению с другими поясняющими объектами. Для выбора одинакового цвета стрелки и текста достаточно одного свойства color: >> set (МА, 'Color', 'm') В данный момент прямоугольная рамка, заключающая в себя текст, не видна, поскольку СВОЙСТВО TextEdgeColor по умолчанию установлено в 'попе'. Цвет рамки устанавливается независимо: » set (МА, 'TextEdgeColor', 'b') Аналогичным образом можно выбрать и цвет шрифта: » set (МА, 'TextColor', 'g') Однако последующее изменение значения свойства color приведет к одновременному изменению значений СВОЙСТВ Textcolor и TextEdgeColor (если только оно не 'попе'). Поэтому при выборе цветов для элементов объекта Textarrow сначала устанавливается свойство color, а затем выбирается цвет текста и рамки. Отметим еще ряд свойств, полезных при создании объекта Textarrow: TextBaokgroundcoior— цвет заливки внутренности прямоугольной рамки, TextLineWidth— толщина ЛИНИЙ рамки в пунктах. TextRotation— VIол поворота в градусах, TextMargin— поля вокруг текста в пикселах. Смысл 518 Ч, ють II. Вычисления и про, раммированиь СВОЙСТВ FontName, Fontsize, FontWeight, HorizontalAlignment, verticalAlignment тот же самый, что и у текстовых объектов (см. paid. "Текстовые объекты"данной главы). Положение объекта Textarrow может быть изменено установкой свойств х и Y. Их значениями являются векторы с координатами начальной и конечной точки. Мы достаточно подробно рассмотрели свойства объекта Textarrow, поскольку он состоит из стрелки и текстовой надписи. Среди его свойств много общих с остальными поясняющими объектами. Теперь при помощи браузера свойств графических объектов легко самостоятельно научиться управлять видом других объектов слоя Annotation layer. Функция annotation, так же как и многие функции высокоуровневой графики, позволяет указывать значения свойств поясняющих объектов при их создании (см. разд. "Задание свойств в аргументах графических функций" ванной главы). Например, следующее обращение к annotation приводит к созданию прямоугольника шириной 0.5 и высотой 0.6, левая нижняя точка которого имеет координаты (0.3, 0.2) (в нормализованных единицах графического окна). Получающийся прямоугольник с красными границами заливается зеленым цветом. » hR = annotation('rectangle', [0.3 0.2 0.5 0.6], 'EdgeColor', 'г'. 1FaceColor’, 'g') Свойства поясняющего объекта, созданного функцией annotation, могут быть изменены из контекстного меню, которое активизируется щелчком левой кнопки мыши по объекту. В качестве упражнения завершите работу над файл-функцией zeroandmin, снабдив ее операторами, которые выводят в правый нижний угол графического окна значения переменных fmin, xmin и zero в три строки (листинги 9.9 и 9.11). Воспользуйтесь поясняющим объектом Textbox. Требуемый блок приведен в листинге 9.12. Ли тинг 9. 2. Вьп од текста е гр< ^ическое окно % Формирование массива ячеек строк strmas{l} = ['Rnin = nnmzstr(fmin)]; strmas{2) = ['Xmin = num2str(xmin)]; s*-rmas{3J = [’Xzero = *, num2str(zero)]; Гпава 9. Дескрипторная графика 519 % Создание объекта Textbox без рамки в правом нижнем угяу окна hTB=annotation(1 textbox',[0.6, 0.1, 0.4, 0.3], 'LineStyle', ‘none’); % Вывод текстовой информации set(НТВ, ’String', strmas) % Установка свойств шрифта setttiTB, 'Fontsize', 12, 'Fontweight', 'bold') Окончательный вариант файл-функции zeroandmin позволяет получить не только графическую информацию-о поведении функции вблизи интересующих точек, но и соответствующие числовые значения (рис. 9.14). Рис, 9.14. Вывод текста в графическое окно Для вывода текста в любое место графического окна можно использовать также следующий прием. Добавляются невидимые оси, равные по размеру графическому окну, со свойством visible, установленным в 'off. Данные оси существуют как объект, но не отображаются в графическом окне. При помощи функции text создается текстовый объект, принадлежащий невидимым осям. Он воспринимается как текст, размещенный в графическом окне. Многострочный текст формируется в массиве ячеек, каждая ячейка кот орого содержит строку, и указывается в качестве значения свойства string текстового объекта (листинг 9.13). 520 Часть II. Вычисления и программирование Листинг 9.13. Вывод текста в графическое окно ,—.................................».........л................................... % Создание вспомогательных невидимых осей, равных по размерам % графическому окну hHelpAx = axes; set(hHelpAx, ‘Position’, [0011], 'Visible', 'off') % Вывод текста во вспомогательные < ,си hlnfo = text(0.6, 0.3, strmas); t Установка свойств шрифта setfhlnfo, 'Fontsize', 12, 'Fontweight*, 'Boid') При наличии некоторого опыта работы в LaTeX вы можете выводить достаточно сложные формулы в графическое окно. Один пример разобран в следующем разделе. Вывод математических формул в формате LaTeX Интерпретаторы ТеХ и LaTeX, входящие в состав MATLAB, позволяют использовать эти стандарт ы для получения хорошо выглядящих математических формул. При чтении главы J, посвященной высокоуровневой графике, вы уже набирали формулы в формате ТеХ, прибегая только к самым простым его командам для изменения шрифта или записи индексов (см. табл. 3.3—3.5). Текст с командами ТеХ записывается в строку, или строковую переменную и указывается во входном аргументе высокоуровневых функций title, xlabel и др., или в качестве значения свойства string текстового, или поясняющих объектов TextBox и TextArrow. При этом происходит автоматическая интерпретация команд ТеХ, поскольку свойство interpreter данных объектов по умолчанию имеет значение ’ tex'. Стандарт LaTeX пред оставляет более широкие возможности для набора формул. Мы не будем описывать здесь основные возможности LaTeX. а продемонстрируем па примере получение графического окна с формулами, например, изображенного на рис. 9.15. Последовательность операторов, приводящая к размещению формул в графическом окне, приведена в листинге 9.14. Отличия по сравнению с ТеХ состоят в том, что мы заключаем каждую формулу в два знака доллара, устанавливаем свойство interpreter в значение 'latex' и используем определенные в LaTeX команды. Поскольку строки с формулами достаточно длинные, то для наглядности мы ввели переменные, содержащие части строки, которые сцепили затем при задании значения свойству string. Гпава 9. Дескрипторная графика 521 Кроме того, мы выводим текстовые объекты на невидимые оси, как предлагалось делать в конце предыдущего раздела. Рис. 9.15. Вывод формул в графическое окно ?'- ..................................... I..... Листинг 9.14- Вывод формул в формате LaTeX % Создание графического окна белого цвета без меню figure('Color', 'w', 'MenuBar', 'none') % Создание невидимых осей, совпадающих по размеру с графическим окном axes('Visible', ’off', 'Position', [0011]) % Создание первого текстового объекта и указание его координат hForml = text ('Position', [0.2 0.7]),- % Ввод первой формулы в формате LaTeX в две строковые переменные sl - ' $$intlimits_{-l}''leta(xi)dxiapprox' sll = 'sumlimits_{k = 1}лп a_keta(xi_k),; % Включение интерпретатора LaTeX, задание значения свойству String % и размера шрифта для первого текстового объекта set(hForml, 'Interpreter', 'latex', 'String', [sl sll], 'FontSize', 18) % Создание второго текстового объекта и указание его координат hForm2 = text('Position', [0.2 0.4]); 522 Часть II. Вычисления и программирование: % Ввод второй формулы в формате LaTeX в три строковые переменные s2 = '$$a_k = frac{2}{(l-xi_k'2)left[' s21 = ’displaystylefrac{d P_n}{dxi}' b22 - '(xi_k)right]Л2},quad n = 1,2,ldots$$'; % Включение интерпретатора LaTeX, задание значения свойству String " и размера шрифта для второго текстового объекта set(hForm2, 'Interpreter’, 'latex*, 'String', [s2 s21 s22], 'Fontsize’, 18) В качестве упражнения добейтесь аналогичного результата с использованием поясняющего объекта Textbox. Г рафические объекты При чтении предыдущих разделов этой главы вы познакомились с принципами работы с графическими объектами на примере окон, осей, линий, поверхностей, текстовых и поясняющих объектов. Кроме того, нам понадобился сам корьевой объект Root для получения информации о текущем разрешении монитора. Многообразие графических объектов MATLAB не исчерпывается перечисленными типами объектов и включает в себя ряд других. Среди всех графических объектов выделяются базовые (Core): осн (Axes), рисунки (Image), источники света (Light), линии (Line), поверхности (Surface), полигональные объекты (Patch) и прямоугольники (Rectangle). Базовые объекты являются основой для создания более сложных композитных объектов (Composite objects). Практически все графические объекты, с которыми вы работали при чтении предыдущих разделов,— композитные. Многие высокоуровневые графические функции группируют базовые объекты для получения требуемого результата в виде рисованных объектов (Plot objects). Этот вопрос мы уже затрагивали при обсуждении работы с браузером графических объектов (см. разд. "Получение информации о свойствах графических объектов" данной главы). Рассмотренные в предыдущем разделе поясняющие объекты (Annotation objects) так же являются композитными Свойства рисованных и поясняющих объектов позволяют изменять вид составляющих их базовых объектов. Например, двунаправленная стрелка Doublearrow, созданная функцией annotation hA = annotation('doublearrow', [0 1],[0 1]) в действительности образована пятью базовыми объектами — тремя линиями (Line) и двумя полигональными объектами (Patch). Свойства HeadlStyle, HeadlLength, HeadlWidt h, Head2Style, Head2Length И HeadZWidth Гпава 9. Дескрипторная графика 523 объекта Doublearrow служат для изменения вида и размеров каждого острия стрелки, т. е. базового полигональною объекта (Patch). Свойства Linestyle н Linewidth объекта Doublearrow предназначены для управления типом и толщиной одного из базовых объектов I ine, образующих стрелку. Остальные два базовых объекта Line являются невидимыми-— они расположены в начальной и конечной точках стрелки. Другой пример— отображение линий уровня функции двух переменных при помощи contour — приведен в справочной системе. Соответствующий рисованный объект Contourseries состоит из полигональных объектов (см раздел справочной системы MATLAB:Graphics: Handle Graphics Objects: Plot Objects) Объекты могут быть сгруппированы при помощи специальных функций. Такие объекты-группы (Group objects) позволяют обращаться к ним как к одному объекту, что в ряде случаев оказывается очень удобным (см. разд. "Объекты-группы hggroup u hgtransform"этой главы). Как правило, всюду дальше мы будем .зазывать базовые и различные композитные объекты просто объектами, если это не приведет к неоднозначности. Сейчас мы более подробно обсудим иерархию и свойства объектов MATLAB за исключением элементов управления (кнопок, переключателей и т. п.), которые используются при написании приложений с графическим интерфейсом. Написанию приложений с графическим интерфейсом посвящены главы 10—13. Иерархия объектов Достаточно полная структура объектов, за исключением элементов управления приложением с графическим интерфейсом, приведена на рис. 9.16. Для освоения материала необходимы два понятия из области объектно-ориентированного программирования — предок и потомок. Объект самого верхнего уровня Root не имеет предков, а его потомками являются графические окна — объекты Figure. Свойства Root позволяют произвести нскоз о-рые глобальные установки MATLAB. Объект Figure представляет собой отдельное графическое окно. У Root может быть много потомков Figure, т. е. в MATLAB может быть открыто одновременно произвольное число графических окон. Оси являются потомком графического окна и предком для базовых, рисованных и группированных объектов. Невидимые оси слоя примечаний так же есть потомок графического окна и предок для поясняющих объектов. Свойства Parent и children каждого объекта содержат указатели на его предков и потомков соответственно. Поскольку у объекта Root нет предка, то значением Parent является пустой массив, а у объектов самого низкого уровня отсутствуют потомки, следовательно, значением их 624 Часть II. Вычисления и программирование свойства children так же является пустой массив. При наличии у объекта нескольких потомков свойство children содержит вектор указателей на них. Указатели на объекты могут быть скрытыми, подробнее об этом сказано ниже (см. разд. "Управление объектами, копирование, поиск, скрытые указатели " данной главы/, Рнс. 9.16. Иерархия графических объектов MATL AB Объект Root Корневой объект Root автоматически создается при запуске MATLAB, указатель на Root всегда равен нулю. Он предназначен для установки общих свойств, характеризующих работу пакета. Например, задание формата вывода результатов вычислений в командное окно может быть осуществлено не только при помощи команды format с соответствующим аргументом, но и установкой свойству Format объекта Root значений: 'short'shortE' (по умолчанию), 'long', 'longE' и др., а свойству Formatspacing значения 'compact' для вывода результатов на каждой строке вместо ’ loose', принятого по умолчанию. Свойства screenDepth и Screensize позволяют получить информацию о цветовой палитре монитора (разрядности цвета) и размере экрана в единицах, определяемых значением свойства Units, которое по умолчанию равно 'pixels Размер экрана содержится в векторе из четырех элементов с коор Гпава 9, Дескрипторная графика 525 динатами левого нижнего угла монитора, его шириной и высотой. Поскольку по умолчанию единицами измерения являются пикселы, то screensize возвращает текущее разрешение монитора. Мы использовали это свойство объекта Root при размещении двух графических окон, делящих экран монитора на равные части (см. листинг 9.6). Отметим, что свойство screensize доступно только для чтения, т. е. вы не можете изменять разрешение монитора из собственных приложений. При чтении разд. "Рекурсивные функции" главы 8 вы выполняли команду get (0, 'RecursionLxmit ’) для получения максимально возможной глубины рекурсивных вызовов (500 по умолчанию) и set(О, 'RecursionLimit', 700) для ее увеличения, т. е, прибегали к свойству RecursionLiinit объекта Root Указатель на текущее графическое окно является значением свойства jurrentFigure. Вектор указателей на все имеющиеся графические окна содержится в свойстве Children объекта Root. Упорядочение данного вектора позволяет расположить графические окна на экране в нужной последовательности. Объект Figure (графическое окно) Потомками Root являются графические окна— объекты Figure, которые создаются функцией figure или автоматически при использовании высокоуровневых графических функций plot, surf и т. д. Свойства создаваемого объекта Figure определяются при его создании аргументами figure, например, figure ('Color’, 'w'). Если аргументы не заданы, то создается графическое окно со свойствами, установленными по умолчанию. Доступ к установленным по умолчанию свойствам объектов Figure производится только с уровня предка Figure, т. е. объекта Root. Используется следу ющий формат названия свойства: Ое1аи1ГНазваниеОиъектаНазваниеСвойства названиеОбъекта в данном случае графического окна есть Figure, а назва-ниесвойства — некоторое свойство объекта Figure. Например, значение [0.8 0.8 0.8] свойства DefauiFigurecoior (в формате RGB) свидетельствует о том. что по умолчанию графическое окно имеет серый цвет: » get(0, 'DefaultFigureColor') ans = 0.8000 0.8000 0.8000 Изменение цвета производится функцией set: » set(0,'DefaultFigureColor1, 'w'} 526 Часть II. Вычисления и программирование Проверьте, что теперь создаваемые графические окна по умолчанию будут белого цвета » figure Однако свойства, указанные во входных аргументах функции figure, имеют больший приоритет по сравнению с определенными по умолчанию: » figure('Color', 'k') Аналогичном образом можно установить собственные значения свойств всех графических объектов (кроме Plot Objects), которые будут использоваться по умолчанию при их создании. Определение свойств, например, объекта Line может быть произведено как с уровня корневого объекта, так и с уровня текущего графического окна или осей. Предпочтение отдается установкам, сделанным на самом низком уровне в иерархии графических объектов. Определению свойств графических объектов, применяющихся по умолчанию, посвящен раздел справочной системы MATLAB: Graphics: Handle Graphics Objects: Setting Default Property Values. Приведем некоторые свойства графических окон, которые оказываются полезными при организации вывода графических результатов (свойства Position, Color, MenuBar рассмотрены в разд. "Управление положением графических окон" этой главы). При создании окна его заголовок состоит из слова Figure и порядкового номера. Привлечение свойств NumberTitle и Name позволяет создать графическое окно с желаемым заголовком: » hF = figure('MenuBar', 'none', 'IjumDerTitle1, 'off',... 'Name', 'Результаты работы*); Графические окна допускают изменение размеров при помощи мыши. Это не всегда удобно, поскольку иногда окно должно быть фиксированного размера. За возможность изменения размера окна отвечает свойство Resize, которое по умолчанию имеет значение *оп'. Для запрета Hci изменение размера следует установить его в * off'. В иерархии объектов потомками графических окон являются оси и слой пояснений (невидимые оси). Свойствам осей, а также поясняющих объектов было уделено достаточно внимания в этой главе. Также мы привели основные свойства рисованных объектов — линий и поверхностей, которые создаются высокоуровневыми функциями типа line, surf, mesh и др., и свойства базового объекта Text. Перейдем теперь к более детальному описанию Гпава 9. Дескрипторная графика 527 свойств потомков осей и приемам работы с ними, демонстрируя их на простых примерах. Базовые объекты (Core Objects) Рассмотрим работу с базовыми объектами на примере линий, прямоугольников, полигональных объектов и источников света. Текстовые объекты мы уже использовали, например, для размещения комментариев на осях графика функции (см. разд. "Текстовые объекты" данной главы). Объекты Rectangle и Line, блок-схемы и диаграммы Хотя название базового объекта Rectangle переводится как прямоугольник, он допускает скругленные углы и его форма может изменяться вплоть до эллипса или окружности. Для его создания служит одноименная функция rectangle. В самом общем случае она вызывается и входными и выходными аргументами: hR = rectangle!..., 'название свойства', значение,...) возвращая указатель на созданный графический объект — прямоугольник Размеры и положение прямоугольника задаются вектором из четырех элементов [х, у, w, h] в качестве значения свойства Position, где х и у—координаты левого нижнего угла, a w и h — ширина и высота прямоугольника в системе координат осей. Свойство Curvature отвечает за скругление углов, его значением должен быть вектор длины два [cw ch], в котором cw — скругляемая часть от ширины, a ch— от высоты прямоугольника. Компоненты cw и ch могут изменяться от 0 до 1, причем 0 означает отсутствие скругления. Например, последовательность команд » hF = figure; » hA = axes ('EataAspectRatio', [1 1 1], 'XLim', [0 1], ’YLim', [0 1]),- » hR = rectangle(’Position', [0.25 0.25 0.5 0.5], 'Curvature', [1 1]); создает квадратное графическое окно, на котором расположена пара осей с фиксированными пределами по г и у, содержащих окружность. Мы использовали равный масштаб по каждой из осей для графического вывода без искажения размеров Задание пределов осей позволило избежать автоматического их изменения, поскольку свойства осей XLimMode и YT,imMode по умолчанию имеют значение 'auto'. Объект Rectangle имеет еще ряд свойств, назначение которых очевидно: Edgecolor, FaceColor— цвет границы и внутренности прямоугольника, Linewidth и Linestyle —толщина и стиль линии границы. 528 Часть II Нычигп^нмд и программирование При помощи объекта Rectangle легко конструировать диаграммы и блок-схемы, элементы которых соединяются линиями— объектами Line. Линия может быть ломаной, для ее создания применяется функция line, одно из возможных обращений к ней выглядит следующим образом: hL = line(x, у, 'название свойства', значение,...) Векторы х и у содержат коорцинаты точек плоскости, через которые следует провести линию, а свойства объекта Line в целом имеют тот же смысл, что и для объекта Lineseries (см. разд. "Свойства тний и поверхностей"этой главы). Различие между объектами Line и Lineseries мы обсудим ниже. В выходном аргументе hL возвращается указатель на объект Line. Для получения линии в трехмерном пространстве вместо пары векторов следует указать три вектора х, у и z с координатами вершин ломаной. Массивы х, у и z могут быть и двумерными, в этом случае каждому столбцу отвечает своя линия, а указатели на все линии записываются в вектор hL. Альтернативный способ вызова функции line предполагает указание массивов с координатами вершин в качестве Значений СВОЙСТВ XData, YData И ZData. Рис. 9.17. Схема, построенная при помощи базовых объектов Rectangle, Line и Text Глава 9. Дескрипторная графика 523 Разберем теперь рисование простых схем и диаграмм при помощи объектов Rectangle, Line и Text на примере схемы, приведенной на рис. 9.17. Разумеется, рисование таких схем может быть выполнено в интерактивной среде для построения графиков, которой вы пользовались при изучении главы 3. Мы сейчас обсуждаем случай, когда блок-схема является результатом работы собственного приложения. При создании нашей схемы использован тот же самый грием, что и для вывода текста в произвольное место зрафическо-го окна— невидимые оси, совпадающие по размеру с графическим окном (см. разд. "Размещение текста, тиши и строчок в графическом окне" этой главы). Перед размещением объектов на схеме требуется определить их координаты и размеры в системе координат осей, для чего можно сначала нарисовать схему на бумаге в клеточку. Гораздо эффективнее задействовать сетку осей на этапе конструирования схемы. Причем удобно сначала расположить оси так, чтобы были видны координаты разметки. Когда схема будет готова, останется выключить сетку, увеличить размеры осей и сделать их невидимыми. Для получения схемы начните работу над файл-программой mychart, воспользовавшись листингом 9.15, а для контроля перед размещением каждого нового объекта выполняйте уже набранный блок команд. Несмотря на то, что на оси все время выводятся новые графические объекты, команда hold on или установка свойства NextPlot в значение 'add' не требуются. Низкоуровневые графические функции, в том числе rectangle и line, в отличие от высокоуровневых, всегда добавляют объект на оси. ............... -f. .................................. ..............4>, мр,... >......... Листинг 9.15. Начало файл-пр. граммы mychart ; ............ .. — .......................................................................................................................... .. . .. % Создание графического окна hF = figure('Position', [200 200 500 500], 'MenuBar', 'none',... 'NumberTitle', 'off', 'Name', 'Структура объектов MATLAB', 'Color', 'w'); % Создание вспомогательных осей с сеткой hA = axes ('XLim', [0 100], 'YLim', [0 100], 'DataAspectRatio', [1 1 1], - 'XTrck', 0:5:100, 'YTick', 0:5:100, 'XGrid', 'on', 'YGrid', 'on'); % Создание круга с надписью Root hRl = rectangle)'Position', [45 80 10 10], 'Curvature', [1 1], 'LineWidth', 2); hTl - text(50, 85, 'Root', ’HorizontalAlignment', 'center', ’Fontweight', 'bold') % Создание левого прямоугольника с надписью Figure hR2 = rectangle ('Position', [10 65 20 10], 'LineWidth', 2),- hT2 = text(20, 70, 'Figure', 'HorizontalAlignment', 'center', ... 530 Часть II Вычисления и программирование ' FontWerght', 'bold') Создание централ! кого прямоугольника с надписью Figure hR3 = rectanglet'Position', [40 65 20 10], 'Linewidth', 2); ПТЗ = text(50, 70, 'Figure', 'HorizontalAligrunenf, 'center', ... 'FontWe ight’, 'bold') % Создание правого прямоугольника с надписью Figure hR3 = rectangle('Position', [40 65 20 10], 'Linewidth', 2); hT3 = text(50, 70, 'Figure', 'HorizontalAlignment', 'center', ,,, 'Fontweight', 'bold') % Создание линии, соединяющей круг и левый прнмоугольник hLl = line([20 50], [75 80], 'LineWidth', 2, 'Color', 'k') I la данном этапе схема должна выглядеть так, как показано на рис. 9.18. Структура объектов MatLab Рис. 9.18. Использование сетки осей для размещения элементов схемы Гпава 9. Дескрипторная графика 531 Разместите остальные элементы самостоятельно, а затем измените вызов функции axes в начале файл-программы mychart на следующий: hA - axes('Position', [0011], 'XLim', [0 100], 'YLim', [0 100], ... 'DataAspectRatio', [1 1 1], 'Visible', 'off'); Результат должен соответствовать рис. 9.17. Большие возможности для рисования блок-схем дает слой пояснений и принадлежащие ему объекты: стрелки, текстовые надписи, прямоугольники и эллипсы (см. разд. "Размещение текста, линий и стрелок в графическом окне" этой главы). Как вы уже знаете, слой пояснений это невидимые оси. На этапе проектирования удобно сделать их видимыми, снабдить сеткой и расположить в графическом окне так, чтобы видеть координаты разметки. Единственная сложность — получение указателя на невидимые оси, который является скрытым (доступ к скрытым указателям обсуждается в разд. "Управление объектами, копирование, поиск, скрытые указате ли " данной главы). Отметим еще один способ быстрого написания кода для рисования блок-схем. Интерактивная среда для построения графиков позволяет вручную располагать поясняющие объекты и генерировать файл-функцию, запуск которой приводит к воспроизведению нарисованной схемы в графическом окне. Блоки операторов этой файл-функции можно копировать в собственную программу для вывода нужных элементов блок-схем. Объект Patch, цветовое оформление объектов Объект Patch (полигональный объект) представляет собой один или несколько многоугольников на плоскости, или фигуру с одной или несколькими гранями в трехмерном пространстве. Свойства объекта Patch допускают гибкое управление его цветом — от постоянного до изменяющегося по заданному закону. Универсальность полигональных объектов позволяет моделировать сложные двумерные и трехмерные физические объекты. Для создания объекта Patch служит встроенная функция patch, обращение к которой в самом простом случае имеет вид: hr = patch(х, у, С) где векторы х и у содержат координаты вершин многоугольника, ас — способ указания цвета: одно из стандартных сокращений: 'г', 'д' и т. д., или вектор из трех чисел для указания цвета в формате RGB. Совпадение координат первой и последней вершин не требуется, поскольку функция patch автоматически соединяет их отрезком, образуя замкнутый многоугольник. Необязательный выходной аргумент содержит указатель на объект Patch. 18 Зак. 130 532 Часть II. Вычисления и программирование В качестве примера напишем приложение, которое позволяет рисовать мно-юугольные объекты при помощи мыши. В окне приложения пользователь расставляет вершины многоугольника щелчком по левой кнопке мыши и для создания многоугольника нажимает одну из клавиш для задания его цвета (<г>. <g>, <b>, <с>. <m>, <у>, <k>, <w>), клавиша <х> служит для выхода из режима рисования. Пам понадобится функция ginput. Она предназначена для получения координат точки осей, в которой был произведен щелчок мышью. Во входном аргументе ginput указывается число выбираемых точек п. а возвращает она массивы х и у с координатами точек, и массив flag Toil же длины с информацией о действиях пользователя. [х, у, flag] = ginput(п) Если при выборе точки была нажата левая кнопка мыши, то соответствующий элемент массива flag равен 1. средняя— 2 и правая— 3. В случае нажатия клавиши ячейка массива flag содержит ASCII код символа. Если пользователь нажал <Entcr>, то функция ginput досрочно прекращает ра-6oiy. ц Примечание Для получения ASCII кода используется функция double, например, double]'х'), а для преобразования ASCII кода в символ— функция char, например, char 1100). Итак, требуется в цикле считывать координаты выбираемой точки и распознаешь нажатую клавишу или кнопку мыши. Возможный вариант файл-программы mypatch приведен в листинге 9.16. Образ иге внимание, что оси являются невидимыми и их размеры совпадают с размерами графического окна. Сбор информации и обработка действий пользователя производятся в бесконечном цикле while, для выхода из которого служит оператор break. Для натлядности на месте выбранных точек появляются маркеры, а после создания многоугольника они удаляются. Рисование маркера организовано при помощи вырождающейся в точку линии— объекта Line, положение которого задается парой чисел. Функция patch, так же как и line, не проверяет значение свойства NextPlot осей, а прост добавляет новый объект на оси. Поэтому для размещения нескольких объектов Ракh команда hold on или установка свойства NextPlot в значение 'add' не требуются. ; Листинг 9.16. Файл-программа mypatch для рисования мн >гоугольника i Создание графического окна finure('Position',[200 200 400 400], 'MenuBar', 'none', 'Color', 'w1, ... 'Nftais', 'inypatch', 'NumberTitle1, 'off') Гпава 9. Дескрипторная графика 533 % Создание невидимых осей axes ('Position', [0 0 1 1], 'Visible', 'off', 'XLim', [0 1], 'YLim', [О ID % Создание пустых массивов для накопления % координат вершин многоугольников X = [ ]; Y = [ ]; % Создание пустого массива для накопления указателей на маркеры вершин hM = [ ] % Сбор информации в бесконечном цикле while 1 % Считывание координат точки и выбора пользователя [х, у, flag] = ginput(l) if flag == double]'x') % Была нажата клавиша x, выход из цикла break end if flag = 1 % Был щелчок левой кнопкой мыши % Добавление координат точки в вектор-столбцы X = [X; х]; Y = [Y; у]; % Помещение в эту точку маркера и сохранение указателя на него h = line(x, у, 'Marker', 'Color', *k'); hM = [hM h] ; else % Была нажата клавиша или кнопка мыши, отличная от левой с = char(flag); if (с = 'r')I(с = 'д')|(с == 'Ь')I(с = 'с')|(с == 'm'J| (с == 'у')|(с == 'к')|(с == 'w') j Создание многоугольника выбранного цвета patch (X, Y, с) о Удаление маркеров delete(hM) % Подготовка массивов к созданию нового многоугольника hM = [ ]; X = [ ]; Y = [ ]; else % Была нажата клавиша, Д”я которой нет соответствия цвету disp(’Неверный цвет') end end end 534 Часть II. Вщисления и программирование Файл-программа mypatch позволяет рисовать произвольные объекты, например, объект, представленный на рис. 9.19. На основе листинга 9.16 легко создать файл-функцию, возвращающую указатели на все созданные полигональные объекты для дальнейшего изменения их свойств Пирамида, изображенная на рис. 9.19, в действительности состоит из трех плоских объектов Patch, каждый из которых является треугольником. Как было отмечено в начале этого раздела, несколько многоугольников могут образовывать один объект Patch. Для получения такого объекта следует указать двумерные массивы в качестве первых двух входных аргументов функции patch, причем каждый столбец массива х должен содержать абсциссы вершин соответствующего многоугольника, а у— их ординаты. Например, команда >> ЬР = patch(rand(4, 3),rand(4, 3), 'г') приводит к появлению полигонального объекта Patch, являющеюся объединением трех красных четырехугольников со случайным образом выбранными координатами вершин. I лава 9. Дескрипторная графика 53S Примечание j Если многоугольники объекта Patch имеют разное число вершин, то неиспользуемым элементам массивов координат присваивается значение NaN (не число). В приведенных примерах полигональные объекты были фиксированного цвета. Возможности заливки цветом достаточно обширны — в частности, допускается указание цвета каждой вершины с плавным его изменением внутри многоугольных областей, составляющих объект Patch. Цвет вершины задается в формате RGB или индексируется, т. е. задается числом, которое соответствует цвету палитры графического окна. Рассмотрим, как обеспечить градиентную заливку трапеции, изображенной на рис. 9.20. Создайте графическое окно с цветовой палитрой gray (оттенки серого цвета) » figure » colormap(gray) Рис. 9.20. Объект Patch с плавным изменением цвета от вершины к вершине Затем задайте векторы с координатами и индексированным цветом каждой вершины для палитры gray, учитывая, что максимальное значение будет соответствовать белому цвету, а минимальное — черному: [0; 1; 2; 3]; 536 Часть II, Вычисления и программирование » у = 10; 2; 2; 0]; » С = И,- 1; 0; 0]; Для получения требуемого результата осталось вызвать функцию patch: » patch(X, у, С; Задание цвета вершин в формате RGB требует создания массива с с подходящим числом измерении. Если объект Patch состоит из одного многоугольника. причем х и у являются векторами, как в только что рассмотренном примере, то массив с трехмерный размера 4 на I на 3, причем каждое его сечение длины 3 содержит три числа: доли красного, зеленого и синего цветов. Например, иьи'ледоватсльность команд: » f igur » Cd, 1, 1:3) = [100]; » С(2, 1, 1:3) = L0 1 01; » С |3, 1, 1:3) = [001]; » С!4, 1, 1:3) = [000); » patch(х, у, С) создаст трапецию с красной, зеленой, синей и черном вершиной и плавно изменяющимся цветом внутри области. В обшем случае, если х и у— матрицы размера m на п, то трехмерный массив с должен иметь размеры m на п на 3. В справочной системе MA TLAB приведено общее правило формирования многомерного массива с при указании индексированного цвета вершин и цвета в формате RGB для двумер ных и трехмерных полигональных объектов (см. описание функции Patch, например, в разд. MATLAB: Functions — Alphabetical List). Обратимся теперь к созданию трехмерного объекта Patch, для построения которою следует обратиться к функции patch с четырьмя входными аргументами: hP = patch(х, у, z. С) где х, у и z — матрицы с координатами вершин каждого многоугольника, образующего грань, а " постоянный цвет или массив подходящей размерности В разделе справочной системы MATI АВ: 3-D Visualization: Creating 3-D Models with Patches: Vlulti-baceted Patches рассмотрен пример построения куба и указано содержимое массивов. До сих пор мы использовали высокоуровневый способ вызова функции patch и не задействовали свойства обьекта. Геометрия полигональною объекта описывается свойствами, приведенными в табл. 9.6. Гпава 9. Дескрипгорнак гр крика 537 Таблица 9.6. Саоштва объекта Patch, отвечающие га его геометрию Названа* свойства Описание Значения XData,YData, ZData Координаты вершин многоугольников, образующих грани Двумерные массивы (или векторы для плоского объекта, состоящего из одного многоугольника) Faces Массив связей между вершинами Двумерный массив, каждая строка которого содержит номера вершин для соответствующей грани Vertices Координаты вершин многоугольников,образующих грани Двумерный массив Назначение свойств XData, YData, ZData очевидно — их значениями являются те же самые массивы, которые указываются при высокоуровневом вызове функции patch. Следующие два обращения к patch приводят к появлению одинаковых по форме двумерных полигональных объектов: patch (х, у, о и patch ('XData1, х, 'YData', у). Отличие состоит в том, что в первом случае задан цвет, а при низкоуровневом использовании patch цвет выбирается по умолчанию (черный), поскольку не были установлены свойства, определяющие цвет поли! опального объекта. Эти свойства описаны ниже., мы отметим сейчас только одно: Facecolor— цвет граней. Его значением, например, может быть один из стандартных цветов 'г', 'д', 'Ь', 'w'. Таким образом, patchfx, у, 'w') и patch('Xdata', х, 'YData', у, 'FaceColor', ’w') эквивалентны. Обсудим назначение еще двух свойств Faces и Vertices, которые позволяют задать полигональный объект альтернативным образом. Объект Patch является набором многоугольников со своими вершинами, однако его можно интерпретировать как набор вершин и связей между ними, образующих грани полигонального объекта. Например, для пирамиды, изображенной на рис. 9.21, первая грань является многоугольником с вершинами 1, 2, 3 и 4, вторая — 1, 4 и 5 и т. д. Такой способ описания полигонального объекта более эффективен, чем хранение координат вершин каждой грани, поскольку часто требует меньше памяти. Массив с координатами вершин задается в качестве значения свойства Vertices, причем его л-ая строка содержит координаты вершины с номером л. Свойство Faces служит для определения номеров вершин граней. Его значением является массив с номерами вершин, в котором А-ая строка отвечает А-ой грани, причем число столбцов массива равно максимальному числу вершин среди всех граней. Поскольку разные грани могут иметь неоди 538 Часть II, Вычисления и программирование наковое число вершин (в нашем примере 3 и 4), то будут использоваться не все элементы в строках этого массива — ненужным элементам присваивается NaN. Рис. 9.21. Нумерация граней и вершин пирамиды Итак, для построения пирамиды необходимо сформировать два массива и указать их в качестве значений свойств Faces и vertices. Функция patch не изменяет размерность объекта на графике, двумерном по умолчанию, поэтому воспользуйтесь свойством осей Cameraposition для выбора точки обзора. Следующие команды создают графическое окно, оси и требуемый полигональный объект с гранями белого цвета. » hF = figure; » hA = axes('CameraPosition', [10 12 8]) ; » V = [-1 0 0 0 10 10 0 0-10 0 0 2]; » F = [12 3 4 541 NaN 215 NaN 325 NaN 435 NaN]; » hP = patchi'Vertices', V, 'Faces', F, 'FaceColor', 'w') [ лава 9 p -крипторная графика 539 Варьируя точку обзора, убедитесь, что полученный объект действительно трехмерный. Примените функцию set для изменения цвета граней, например, на красный. Объект Patch имеет набор свойств для цветового оформления, управления освещенностью и прозрачностью. Обсудим более подробно заливку цветом элементов объекта Patch. Существует два способа закраски полигонального объекта: задание цвета граней или вершин. Мы использовали самый про-сгой вариант первого способа при создании призмы — свойство FaceCoicr, т. е. цвет граней, принимало значение 'w1 и все грани были белые. Для получения разноцветных граней следует установить свойство Facecolor в значение 'flat' и определить цвет каждой грани в зависимости от способа описания полигонального объекта. Если объект Patch создан при помощи массивов с координатами вершин многоугольников (свойств XData, YData, ZData), то следует привлечь свойство CData. Его значением должен быть массив с информацией о цвете вершин или граней, в индексированном виде или в формате RGB. Это тот же самый массив с, который мы указывали во входных аргументах patch при высокоуровневом вызове: patch(х, у, с) ИЛИ patch(х, у, г, С). Заливка цветом полигонального объекта, который сконструирован на основе связей между вершинами (свойств Vertices и Faces), потребует задействования свойства FaceVertexCData. Его значением может быть скаляр, вектор или матрица Скаляр служит для задания индексированного цвета, одинакового для всех граней. Вектор-строка длины 3 воспринимается как цвет всех граней в формате RGB. Вектор-столбец, длина которого равна числу граней, определяет индексированный цвет каждой грани. Матрица с числом строк, равным числу граней, и тремя столбцами позволяет задать цвет в формате RGB для каждой грани, например: » FC = [О О О 0 10 0 0 1 10 0 110] » hP = patch]’Vertices’, V, 'Faces', F, 'FaceCclor', 'flat', ... 'FaceVertexCData', FC) Указание цвета вершин предоставляет более широкие возможности по оформлению полигонального объекта по сравнению с фиксированным цветом каждой грани. Как и в случае постоянного цвета внутри грани, способ конструирования объекта Patch определяет выбор между свойствами CData и FaceVertexCData. Только теперь длина соответствующих векторов или число строк в матрице должны равняться числу вершин. Для плавного из- 540 Часть II. Вычисления и программирование менсния нвета от вершины к вершине следует установить свойство FaceCalorВ значение 'interp', В случае, когда задан цвет вершин н свойство Facecolor принимает значение 'flat', цвет внутри грани постоянный и определяется цветом первой вершины многоугольника, образующего грань. Примеры закраски куба приведены в справочной системе MATLAB в разд. MATLAB: 3-D Visualization: Creating 3-D Models with Patches: Multi-Faceted Patches. Передние грани полигонального объекта скрывают от взора те. которые расположены за ними Грани допускают произвольную степень прозрачности, которая устанавливается при помощи свойства FaceAipha. Его значением является неотрицательное число, например: >> set(hP, 'FaceAipha', 0.5) причем 0 соответствует полностью прозрачным граням, а 1 —непрозрачным. Каждая грань может иметь свой коэффициент прозрачности, который определяется в век 1 ор-столбце с числом элементов, равным числу граней. Этот вектор берется в качестве значения свойства FaceVertexAlphaData, а FaceAipha устанавливается в 'flat'. Более гибкое управление прозрачностью требует определения коэффициентов для каждой вершины в векторе и задания свойству FaceAipha значения 'interp'. В этом случае прозрачность в пределах грани плавно изменяется от вершины к вершине. Если FaceAipha установлено в 'tiat', то прозрачность всей грани определяется коэффициентом для первой ее вершины. Перейдем теперь к свойствам ребер полигонального объекта. Свойства линий ребер LineStyle, LineWidth, Marker, MarkerSize комментировать не требуется, они используются так же, как и в случае линии— объекта Line. Отметим только, что маркеры размещаются в вершинах многоугольников. Цвет ребер зависит от значения свойства EdgeCclor и может быть одним из сокращений для цвета, либо цветом в формате RGB. Кроме того, значение flat’ приводит к совпадению цветов ребра и вершины, из которой оно исходит, a 'interp' —к плавному изменению цвета между его вершинами. Ребра не прорисовываются, если EdgeCclcr установлено в 'попе'. Степень прозрачности ребер зависит от значения свойства EdgeAlpha. Если его значение— число от 0 до 1, то все ребра имеют одинаковую прозрачность. Определение прозрачности каждого из ребер потребует привлечения свойства FaceVertexAlphaData и установки значения EdgeAlpha В 'flat' ИЛИ 'interp'. В качестве упражнения измените прозрачность граней и ребер призмы, увеличивающуюся от основания. Глава 9. Дескрипторная графика 541 Одна из возможных. последова1ельностей команд приведена ниже: » Т = Ц; 1; 1; 1; 0] » set(hP, 'FaceVertexAlphaLita', Т, 'FaceAlpha1, 'interp') >> setthP, 'LineWidth', 3, 'EdgeColor', 'c', 'EdgeAlpha', 'interp’) Смысл коэффициентов прозрачности ребер или вершин определяется значением свойства AjphahataMapping, которое по умолчанию равно 'scaled', т. е. коэффициенты прозрачности масштабируются. Если в нашем примере положить т = [3,- 3; 3; 3; 0J. то ничего не изменится Прозрачность определяется также свойством графического окна Alphamap и осей ALim. которые в наших примерах принимаются установленными по умолчанию. Примеры, посвященные изменению цвета ребер и маркеров, приведены в подразделах разд. MATLAB: 3-D Visualization: Creating 3-D Models with Patches: Patch Edge Coloring справочной системы MATLAB. Поверхность, т. e. объект Surface, так же как и полигональный объект, допускает различную степень прозрачности, изменение стиля сетки поверхности и цвета ячеек. При этом название соответствующих свойств поверхности го же самое, что и в случае обьекта Patch: FaceAlpha, FaceColor. Linestyle и т. д. Исключение составляет свойство FaceVertexAlphaData для поверхности вместо него используется AlphaData. В следующем разделе мы рассмотрим освещение трехмерных объектов на примере поверхности, поскольку полигональные объекты освещаются аналот нчиым образом. Объекты Surface и Patch схожи друг с другом — полигональный объект является более общим случаем поверхности, которая определена на сетке с прямоугольными ячейками. Ьолее того, поверхность может быть преобразована в полигональный объект при помощи специальной функции surf2patch. Освещение объектов, объект Light (источник света) Освещение поверх Iостей и полигональных объектов позво 1яет получить естественный вид моделируемых трехмерных объектов. При чтении главы 3 вы использовали функцию высокоуровневой графики surfl для получения освещенной поверхности, а при работе в редакторе свойств добавляли источники света с заданными характеристиками. В этом разделе мы обсудим возможности низкоуровневой графики для освещения трехмерных объектов. Источник света создается при помощи функции tight, которая возвращает указатель на объекз- Light. Источники свез а бывают двух типов: с парал- 542 4 ten I! Вычисления и программирование дельными лучами и лучами, направленными радиально, что определяется его свойством style. Его значение 'infinite' (по умолчанию) соответствует бесконечно удаленному источнику с параллельными лучами, а local' — источнику, испускающему лучи света во все стороны. Положение источника в системе координат осей задается его свойством Position, которое по умолчанию принимает значение [1 0 1], причем для бесконечно удаленного источника его значение говорит лишь о направлении освещения. Третьей характеристикой объекта Light является его цвет (белый по умолчанию), для выбора которого служит свойство Color. Рассмотрим освещение трехмерных объектов на примере параметрически заданного конуса x(u, у) = 0.3 и-cosv, у(н, v)=0.3-и-sin v, z(«,v) = 0.6h, и, ve [-л, л]. Построение поверхностей второго порядка, заданных параметрически, в том числе и конуса, описано в разд. "Построение параметрически заданных поверхностей и линий"главы 3. Создайте подходящие массивы х, Y и z, графическое окно и оси: » u = (-pi:0.05*pi:pi)'; » v = -pi:0.05*pi:pi; » X = 0.3*u*cos(v); » Y - 0.3*u*sin(v); » Z = 0.6*u*ones(size(v)); » hF = figure; » hA = axes; Для получения поверхности примените низкоуровневую функцию surface, воспользовавшись свойствами XData, YData, ZData, FaceColor И Linestyle объекта Surface: » hS = surface('XData', X, 'YData', Y, 'ZData', Z, 'FaceColor', 'g', ... 'LineStyle', 'none') Функция surface в отличие от высокоуровневых surf, mesh и др. не устанавливает трехмерный вид осей, поэтому следует позаботиться о выборе точки обзора: » set(hA, 'Cameraposition', [-15 -25 20]) Создайте теперь источник белого света с параллельными лучами, направление которых определяется вектором [0 -1 0]: » hLt=light(1 Position',(0 -1 0J) Конус освещается светом, исходящим от бесконечно удаленного источника. Остановимся на некоторых особенностях полученного изображения, кото Гпава 9. Дескрипторная графика 543 рые связаны со способом освещения трехмерных объектов. Изменение точки обзора позволяет убедиться в отсутствии неосвещенных участков. Например, посмотрите на скрытую от света часть конуса » set(hA, 'CameraPosition', [0 1 0]) Цвет ее темнее освещенной части, но не черный, который должен соответствовать неосвещенной поверхности. Дело в том, что при создании объекта Light на оси автоматически добавляется рассеянный свет белого цвета и свойство осей AmbientLightColor принимает значение 'w'. Задайте черный цвет, т. е. отсутствие равномерного освещения » setfhA, 'AmbientLightColor', 'k') Теперь неосвещенная источником света часть конуса стала черного цвета. Вернитесь к первоначальной точке обзора поверхности и включите равномерное освещение » setfhA, 'CameraPosition', [-15 -25 20]) » setfhA, 'AmbientLightColor', 'w') Заметно, что освещенная поверхность не является гладкой — оттенок зеленого цвета в пределах каждой ее ячейки не изменяется. Плавность освещения определяется свойством FaceLighting, которое по умолчанию равно 'flat' и задает постоянный цвет. Для линейной интерполяции оттенка цвета внутри ячейки следует использовать значение 'goraud': » set(hS, 'FaceLighting', 'gouraud') Значениями свойства FaceLighting могут также быть 'phong' (более сложный алгоритм подбора оттенков, часто приводящий к лучшему результату) и 'попе' (ячейки поверхности не реагируют на освещение). Стиль подсветки линий сетки поверхности выбирается аналогичным образом с использованием свойства EageLighting: » setfhS, 'LineStyle', '-') » set(hS, 'EdgeColor', 'g') » set(hS, 'EdgeLighting1, 'phong') Видимая часть внутренности конуса освещена не только равномерным светом, но и параллельными лучами источника, хотя она и является скрытой от лучей света частью поверхности. Таков стандарзный способ освещения трехмерного объекта — если нормаль к поверхности направлена от камеры, то освещается внутренняя ее часть. Нормаль к конической поверхности действительно направлена наружу, в чем несложно убедиться, построив векторы нормали к поверхности (см. разд. "Визуализация векторных полей" главы 3). Ответственным за освещение внутренности трехмерных объектов является свойство BackFaceLighting. По умолчанию оно принимает значение 544 Часть II. Вычисления и программирование ' reverselit', но если изменить его на 'unlit', то лучи света источника перестают падать на внутреннюю поверхность конуса. » set(hS, 'BackFaceLighting', 'unlit') При выборе 'reverselit' возможно некорректное отображение границ освещенной замкнутой поверхности, поскольку может оказаться, что нормаль в некоторой точке направлена от камеры, хотя сама точка видна. В этом случае прибегают к значению 'lit' (см. пример для сферы в разделе справочной системы MATLAB: 3-D Visualization: Lighting as a Visualization Tool: Back Face Lighting}. Мы рассмотрели свойства трехмерных объектов и осей, отвечающих за способы освещения. Обратимся теперь к отражению света от поверхности. Можно считать, что поверхность изготовлена из некоторого материала с заданными характеристиками отражения света. Самый простой способ состоит в выборе одного из стандартных мазериалов при помощи команды высокоуровневой графики material. Изменяйте материал и наблюдайте за видом освещенной поверхности. » material metal » material shiny » material dull » material default Проделайте аналогичные эксперименты для точечного источника света, установив свойство style объекта Light в ' local » setfhLt, 'Style', 'local') Отражение материалом света, исходящего из источника, определяется четырьмя свойствами трехмерного объекта: □ specularstrength — доля отраженного света. Значение— число от 0 до 1, по умолчанию 0.9; □ Diffusestrength— интенсивность рассеивания света по поверхности Значение — число от 0 до 1, по умолчанию 0,6; □ specularSxponent — резкость отраженного света, т. е. величина светового пятна на поверхности. Значение — число, большее 1, по умолчанию 10: □ SpecularColorReflectance— цвет отраженного света, который может изменяться от комбинации цвет ов объекта и источника до цвета падающего света. Значение — число от 0 до I, по умолчанию 1 (цвет света источника). Трехмерный объект отражает также равномерный свет, за цвет которого, как было упомянуто выше, отвечает свойство AmbientLightCo? or осей. Доля отраженного рассеянного света зависит от материала и задается при помо Гпава 9. Дескрипторная графика 545 щи свойства Ambientstrength объекта. Его значением может быть число от О до 1, по умолчанию 0.3. Изменяя значения перечисленных свойсть. наблюдайте за видом конической поверхности. Примеры освещенной поверхности для различных значений этих свойств приведены в справочной системе в подразделах разд. MATLAB: 3-D Visualization: Lighting as a Visualization Tool: Reflectance Characteristics of Graphics Objects. Освещение полигональных объектив, рассмотренных в предыдущем разделе, производится аналогичным образом. Управление объектами, копирование, поиск, скрытые указатели Объектно-ориентированная графика MATLAB предоставляет возможность копирования объектов в соответствии с их иерархией. Например, оси графического окна могут стать потомком только графического окна, того же самого или другого. При этом скопированные оси имеют тех же самых потомков, что и исходные, разумеется, с новыми указателями. Линии, поверхности и другие объекты самого низкого уровня могут быть скопированы только на оси. Другими словами, объект не может быть скопирован сам по себе— для него обязательно должен существовать предок. Копирование объектов производится при помощи функции copyobj, обращение к которой имеет вид hi = copyobj (h, р), где h— указатель на копируемый объект, р— на предок для нового объекта, а ы — на новый объект. Функция copyobj копирует объекты вместе со всеми их потомками. Кроме копирования, существует еще ряд возможностей для управления графическими объектами. Для смены предка объекта служит его свойство Parent. Создайте, например, графическое окно с указателем hF, на котором находятся оси с диаграммой и новое окно с указателем hFl » hF = figure; » hA = axes; » hb = bar([l 2 3 1J) ,- » hFl = figure; Оси имеют единственного потомка — объект Barseries, представляющий столбцевую диаграмму одномерных данных. Для перемещения осей вместе с их потомком в окно с указателем hFl следует установить значение свойства Parent осей В hFl: » set{hA, ‘Parent’, hFl) 546 Часть II. Вычисления и программирование Согласно иерархии графических объектов, значением свойства Parent осей может быть только указатель на графическое окно, а для линий, поверхностей и других объектов самого низкого уровня — указатель на оси. Объект Root является предком всех графических окон, а следовательно значение их свойст ва Parent всегда равно нулю. Ряд сервисных функций позволяет осуществить поиск всех потомков объекта (функция allchild), поиск всех потомков с определенными свойствами (функция findali), поиск объектов с определенными свойствами (функция findobj), удаление (функция delete) и ряд других. Применение функции delete для удаления объектов описано в разд. "Удаление и очистка объектов" данной главы. Список всех функций для управления графическими объектами приведен в разделе справочной системы MATLAB: Functions — Categorical List: Graphics: Handle Graphics. Использование специальных функций для управления графическими объектами делает работу с ними более продуктивной. В качестве примера рассмотрим графическое окно, содержимое которого приведено на рис. 9.22. Разумеется, можно создать две пары осей, нанести на каждую из них полигональные объекты и объекты Rectangle и установить свойство Facecolor каждого объекта в нужное значение. Рис. 9.22. Графическое окно, получаемое прч помощи управления Графическими объектами Гпава 9. Дескрипторная графика 547 Поступим по-другому: 1. Нарисуем левые оси и объекты на них. 2. Скопируем оси в то же самое графическое окно, удалим их потомков и поместим новые оси в левую часть окна. 3. На новые оси скопируем объекты Patch и Rectangle и приведем их к требуемому виду. Более простой способ без удаления потомков осей, основанный на поиске объектов нужного типа, рассмотрен ниже. Файл-лрО1рамма ехс1ат2, приведенная в листинге 9.17, выполняет перечисленные действия. % создание графического окна и левой пары осей hF = figure!'MenuBar', 'none'); ИА = axes!'OuterPosition', [0 0 0.5 1], 'XLim',[-1.3 1.3], ... 'YLirn', [-1.5 3.5], 'DataAspectRatio', [1 1 1]) % создание треугольного объекта Patch и круглого объекта Rectangle hP = patch(’XData', [-1 0 1], 'YData', [3 0 3], 'FaceColor', 'w', 'LineWidth', 4) hR = rectangle!'Position', [-0.5 -1.2 11], ... 'Curvature', [1 1], 'LineWidth', 4, 'FaceColor', 'k') % копирование осей hA в графическое окно hF hAl = copyobj(hA, hF) % поиск всех потомков новых осей hAl и их удаление h = get(hAl, 'Children') delete(h) % размещение новых осей hrtl в левой части графического окна set(hAl, 'OuterPosition', [0.5 0 0.5 1]) % копи; свание объектов Patch и Rectangle на новые оси hAl hPl = copyobj(hP, hAl) hRl = copyobj(hR, hAl) ? изменение цвета заливки объектов Patch и Rectangle set(hRl, 'FaceColor', 'w') setthPl, 'FaceColor', 'k') 548 Часть II. Вычисления и программирование Остановимся более подробно на поиске потомков графических объектов. В файл-программе exclaml мы обратились к свойству children для получения указателей на потомков осей — объектов Patch и Rectangle На самом деле потомков больше, но они имеют скрытые указатели, доступ к которым при помощи свойства children закрыт. Убедиться в этом позволяет функция allchild, которая возвращает вектор из указателей на потомков графического объекта. Создайте, например, пустые оси, выведите значение их свойства children и сравните с тем, что возвращает allchild: » hA = axes; » hCl = get(hA, ’Children1) hCl = Empty matrix: 0 - by - 1 » hC = allchild(hA) hC = 104.0005 103.0005 102.0005 101.0011 Итак, даже при отсутствии графических объектов (линий, поверхностей и т. д.), оси всегда имеют потомков. Более того, они не являются невидимыми, о чем говорит значение свойства visible, например, первого потомка: » get(hC(l), 'Visible') ans = on Мы знаем, что согласно иерархии графических объектов осям могут принадлежать потомки различных типов. Тип любого графического объекта записан в его свойстве Туре, которое может принимать одно из следующих значений, 'root', 'figure', 'axes', 'image', 'light', 'line', 'patch', 'rectangle', 'surface', 'text', 'hggroup', 'hgtransform' И 'uicontrol', определяющих тип объекта. Объекты последнего из перечисленных типов являются элементами приложений с графическим интерфейсом, которым посвящены следующие несколько глав. Работу со сгруппированными объектами, тип которых 'hggroup' ИЛИ 'hgtransform', МЫ рассмотрим чуть позже в этой главе. Отметим только сейчас, что большинство рисованных объектов, создаваемых функциями высокоуровневой графики, имеют тип hggroup' (например, Contourgroup или Barseries). Выясним тип потомков осей со скрытыми указателями, вызвав функцию get от вектора указателей на них: » get(hC, 'Туре') ans = ' text' Гпава 9. Дескрипторная графика 549 'text’ 'text' 'text' Содержимое возвращаемого массива ячеек свидетельствует о том, что все четыре потомка осей есть текстовые объекты. Они не видны, потому что значениями их свойств string являются пустые строки (проверьте). Эти текстовые объекты служат для размещения заголовка и подписей к осям, причем указатели на них являются значениями свойств осей Title, XLabel, YLabel И ZLabel, например, команды » set(hC(l),'String', 'заголовок') И » hT = get(hA, 'Title'); » set(hT, 'String', 'заголовок') приводят к одинаковому результату — появлению заголовка осей. Для скрытия указателя на объект достаточно установить его свойство Handlevisibility в значение 'off, как это и делается для четырех текстовых объектов (потомков осей) при создании осей: » get(hC, ’Handlevisibility') ans — 'off 'off 'off' 'off Но все скрытые указатели можно одновременно сделать доступными с уровня корневого объекта, для чего следует его свойство ShowHiddenHandles установить в значение 'on': » set(0, 'ShowHiddenHandles', 'on') Проверьте, что теперь видны указатели на текстовые объекты — потомки осей: » hCl = get(hA, 'Children') hCl = 155.0057 154.0057 153.0057 152.0057 550 Часть It Вычисления и программирование Значения их свойства 'Handlevisibility' не изменились, поэтому возврат к прежней глобальной установке: » set(0, 'ShcwHxIdynHandles', 'off') снова приведет к скрытию указателей на них. Объекты со скрытыми указателями применяются для того, чтобы предотвратить их случайное изменение операторами, набираемыми в командной строке или выполняемыми в другом приложении MATI AR. В качестве примера создайте графическое окно со скрытым указателем, установив его свойство Handlevisibility в значение 'off >> hF = figure('Handlevisibility', 'off') hF = 1 При дальнейшем графическом выводе команды MATLAB не обнаружат этого графического окна и создадут новое окно с парой осей или задействуют графическое окно, указатель на которое не является скрытым (если свойство ShowHiddenHandles корневого объекта установлено в 'off'): » fpiot(Gain, [0 3*pi]) Заметим, что графический объект со скрытым указателем, равным 1, существует и команды close (1) или delete (1) приведут к закрытию окна. Более того, возможна модификация свойств окна функцией set, например, » set(l, 'Color', 'w') Для предотвращения случайного изменения свойств 1рафических окон со скрытыми указателями имеет смысл использовать вещественные значения указателей вместо целых, присваиваемых по умолчанию. Для этого следует установить свойство integerHandie в значение ' off'. Обсудим теперь влияние скрытых указателей на результаты поиска объектов при помощи других функций: findall и findobj. Функция findall служит для получения указателей на потомков заданного объекта, расположенных ниже по иерархии, причем возможен поиск потомков с определенными свойствами. Например, после выполнения файл-программы exclamZ создается графическое окно с указателем hF, для поиска всех его потомков достаточно обратиться к findall следующим образом: » hC = findall(hF) В командное окно выводится вектор, включающий указатели на графическое окно и все его потомки— оси и принадлежащие им объекты, в том числе и объекты со скрытыми указателями. Функция findall позволяет найти объекты с заданными значениями их свойств, для этого следует указать пары 'свойство', значение через запятую в списке входных аргументов. Следующие команды выделяют полигональный объект черного цвета Глава 9. Дескрипторная графика 551 среди всех потомков графического окна, созданного программой exclamZ (см. листинг 9.17), и изменяют его цвет на серый: >> hC - Eindall(hF, 'Type', 'patch', 'FaceColor', ’k") » setlhC, 'FaceColor', [0.8 0.8 0.8]) Функция findobj производит схожие c findaii действия, но игнорирует объекты со скрытыми указателями. Кроме того, findobj допускает еще ряд способов вызова. В качестве первого входного аргумента может быть задан вектор указателей, тогда поиск объектов с нужными свойствами будет производиться для всех перечисленных объектов и их потомков. Если список входных аргументов findobj содержит только пары 'свойство', значение, то просматриваются все существующие графические объекты. Вызов findobj без входных аргументов позволяет получить указатели на все графические объекты. Функция findobj позволяет добавлять логические операторы в поиск по значениям и свойствам объектов, делая его более гибким, а также ограничиться поиском до определенного уровня иерархии (см. информацию о findobj в справочной системе MATLAB, например в разд. MATLAB: Functions — Categorical List: Graphics: Handle Graphics). В файл-программе exclamZ, приведенной в листинге 9.17, можно было не удалять потомки вторых осей, а найти указатели на них при помощи findobj и затем установить требуемые значения свойств. Этот подход реализован в файл-программе exclamZf (листинг 9.18). Листинг9.18. Файл-программа exclamZf, демонстрирующая копирование ....................... Si:;...... % создание графического окна и левой пары осей hF = figure; hA = axest'CucerPosition', [0 0 0.5 1], 'XLim', [-1.3 1.3], ... 'YLim', [-1.5 3.5], 'DataAspectRatio', [1 1 1]) % создание треугольного объекта Patch и круглого объекта Rectangle hP = patch ('XData', [-1 0 1], 'YData', [3 0 3], 'FaceColor', 'w1, 'LineWidth', 4) hR = rectangle('Position', [-0.5 -1.2 1 1], 'Curvature', [11], ... 'LineWidth', 4, 'FaceColor', 'k') % копирование осей hA в графическое окно hF hAl = copyobj (hA, hF) % размещение новых осей hAl в левой части графического окна set(hAl, 'OuterPosition', [0.5 0 0.5 1]) % поиск потомков (объектов Patch и Rectangle) новых осей hRl = findobj(hAl, 'Type', 'rectangle'); hPl = findobj(hAl, 'Type', 'patch'); 552 Часть II Вычисления и программирование % задание цвета объектов Patch и Rectangle set{hRl, 'FaceColor', 'w') set(hPl, 1FaceColor', ' k') Функции поиска объектов позволяют расширить возможности многих высокоуровневых графических функций. Например, обращение к файл-функции pie3tr из листинга 9.19 приводит к появлению круговой трехмерной диаграммы с прозрачными отделенными друг от друга секторами. При создании этой файл-функции был использован вектор указателей на графические объекты (Surface и Patch), которые создает стандартная функция pie3 при конструировании трехмерной диаграммы. . Листинг 9.‘19. Файл-функция pie3tr для вывода диаграммы с прозрачными : секторами .......... , ...... । , > ... • I г Г. । . . .. . ........ I ...... 1.1 . ..•• . .... .......... >• .... • .. ........ а. ....а.......... function h = pie3tr(X) % Файл-функция для вывода прозрачной диаграммы с отделенными секторами % построение круговой трехмернай диаграммы с отделенными секторами h = pie3(X, ones(size(X))) % задание текуцему графическому окну белого цвета set(gcf, 'Color', 'w') % поиск полигональных объектов среди элементов диаграммы % и изменение их свойств hP = findobj(h, 'Type', 'patch') set(hP, ’FaceAipha', 0.1, 'Linestyle', 'none') % поиск поверхностей среди элементов диаграммы % и изменение их свойств hS = findobj(h, 'Type', 'surface') set(hS, 'FaceAipha', 0.4, 'LineStyle', 'none') Справочная система MATLAB содержит ряд примеров, в которых применяются функции высокоуровневой графики, а дополнительные элементы оформления наносятся при помощи низкоуровневой графики. Например, возможно изменить значения в процентах у секторов круговой диаграммы на текстовые надписи, управлять видом контурных графиков (см. в справочной системе MATLAB разд. Graphics: Creating Specialized Plots). Функция pie3 возвращает вектор указателей на базовые графические объекты Surface, Patch и Text. В приведенном выше примере мы воспользовались первыми двумя из них для придания круговой диаграмме желаемого Глава 9. Дескрипторная графика 553 вида. Результатом работы большинства высокоуровневых графических функций является сгруппированный объект hggroup, который позволяет обращаться с ним, как с единым объектом. В начале этого раздела приведен пример о переносе столбцевой диаграммы с одних осей на другие. Проверьте, что созданный функцией bar объект Barseries имеет тип hggroup. В предыдущих версиях MATLAB выходным аргументом всех высокоуровневых графических функций были указатели на объекты, названные базовыми в версии 7. Для совместимости эта возможное!ь предоставлена и в версии 7. Достаточно указать 'v6' в качестве первого входного аргумента графической функции. Сравните, например, типы графических объектов, указатели на которые возвращаются при следующих двух обращениях к bar: h = bar([l 2 3] ) И hp = bar('v6‘, [1 2 3]). Рассмотрим теперь более подробно работу со сгруппированными объектами. Объекты-группы hggroup и hgtransform Согласно иерархии, группы являются потомками осей и предками для всех объектов, которые могут быть потомками осей, т. е. базовых, рисованных и поясняющих объектив. Следовательно, группы могут быть потомками некоторой группы. Различается два типа групп: hggroup и hgtransform. Создание объекта hggroup позволяет обращаться с формирующими его объектами как с единым целым. Например, всю группу объектов можно сделать видимой или невидимой с привлечением ее свойства visible. Группа может быть текущим объектом, если был сделан щелчок мышью по какому-нибудь из ее элементов. Кроме того, вся группа может быть выделена щелчком мыши только по одному из ее объектов. Для раелизации двух последних возможностей следует установить свойство HitTest в значение 'off' для каждого объекта, входящего в группу hggroup. Группа hgtransform позволяет не только делать объекты видимыми или невидимыми, но и поворачивать, перемещать и масштабировать все сгруппированные объекты одновременно. Для создания групп служат одноименные функции hggroup и hgtransform, которые имеют одинаковый интерфейс. Рассмотрим работу с группами на примере группы hgtransform, включающей в себя поверхность и полию-нальный объект. При помощи следующих команд создайте графическое окно, оси с заданной точкой обзора, плоскую поверхность и стоящую на ней пирамиду: » hF = figure; » hA - axes(‘Cameraposition1, [10 12 5]); 554 Часть II, Вычисления и программирование » [X,Y] = mesi.gr.id(-2:0.5:2) ; » Z = zeros<size(X)).‘zeros(size(Y)); » hS = surface('XData', X, 'YData1, Y, 'ZData', Z, 'FaceColor', 'y', ... 'EdgeCoJcr', 'r', 'FaceAlpha', 0.8, 'EdgeAipha', 0.8); » V = [-1 0 0 0 10 10 0 0-10 0 0 1]; » F = [1 2 3 4 5 4 1 NaN 215 NaN 325 NaN 435 NaN]; » hP = patch('Vertices', V, 'Faces', F, 'FaceColor', 'g', ... 'EdgeColor', 'r1, 'FaceAlpha', 0.8, 'EdgeAlpha', 0.8); Объедините теперь поверхность и пирамиду в группу. Для этого следует создать группу при помощи функции hgtransform. Входными аргументами группы могут быть пары ’свойство', значение, а выходным является указатель на созданный объект— группу. Нам требуется создать группу, являющуюся потомком осей, следовательно ее свойство Parent надо установить в значение ьа (указателя на оси): » hGT = hgtransform('Parent*, hA); Потомками группы должны стать поверхность и призма, поэтому укажите в качестве значений их свойства Parent указатель на группу: » set(hS, 'Parent', hGT) » set(hP, 'Parent', hGT) Перед преобразованиями группы скопируем ее и зададим ббльшую прозрачность входящим в нее объектам, т. е. ее потомкам: » hGTO = -opyobj(hGT, hA); » hCO = get(hGTO, 'Children') » set(hCO, 'FaceAlpha', 0.1, 'EdgeAlpha', 0.1) Все преобразования мы будем осуществлять над группой с указателем hGT, а скопированная группа послужит для наглядного представления о преобразованиях. Обсудим теперь поворот вокруг осей, перемещение и масштабирование группы. Каждое из этих преобразований задается матрицей размера 4 на 4. Глава 9 Дескри"~орная графика Ь55 Например, для поворота вокруг оси х следует сформировать матрицу '1 0 0 0" Я = 0 cose* -sinOA 0 л 0 sin6x cos6x 0 0 0 0 1 7 где значение 6Л (в радианах) определяет величину поворота. Положительное значение 0А приводит к повороту против часовой стрелки, если смотреть по направлению к началу координат, а отрицательное, соответственно, к повороту по часовой стрелке. Матрицы поворота вокруг остальных двух осей имеют похожий вид. 11еремещение и масштабирование так же задаются матрицами размера 4 на 4. Мы не приводим их по двум причинам. Во-первых, их структура указана в справочной системе (см. разд. MATLAB: Graphics: Handle Graphics Objects: Group Objects: Transforming Objects). Во-вторых, существует специальная функция makehgtform для формирования этих матриц. Первым ее входным аргументом указывается желаемый тип преобразования, а вторым — его числовые характеристики. Для формирования матрицы поворота Rx вокруг оси х следует указать 'xrotate' и угол поворота: Rx = makehgtform)'xrotate', teta) Для получения матриц поворота вокруг осей у и z вместо 'xrotate' используются, соответственно, 'yrotate' И 'zrotate'. Перемещение может быть определено вектором из трех элементов [tx ty tz] для каждой из осей. Матрица перемещения т генерируется при следующем обращении к функции makehgtform: Т - makehgtform)’translate', [tx ty tz]) Задание коэффициентов масштабирования вдоль каждой из осей в векторе [sx, sy, sz] И ВЫЗОВ М = makehgtform)'scale', [sx, sy, sz]) приводит к получению матрицы масштабирования м. При равномерном изменении размеров коэффициенты равны. В этом случае вместо вектора достаточно указать скалярное значение: М = makehgtform)'scale', s) Для применения вышеописанных преобразований следует привлечь свойство Matrix группы hgtransform Его значением может быть одна из матриц поворота, перемещения или масштабирования, или их произведение для 556 Часть It. Вычисления it программирование ряда последовательных преобразований. Продемонстрируем сказанное на примерах. Сместим группу вверх по оси с на две единицы, для чего сформируем подходящую матрицу: » Tz = makehgtformf'translate', [0 0 2]) и осуществим преобразование >> setfhGT, 'Matrix', Tz) Как и следовало ожидать, плоскость и пирамида сместились вверх на заданное расстояние. Однако последующее смещение вдоль оси у не сохранит предыдущего преобразования. » Ту = makehgtform('translate', [0 1 0] ) ; » setfhGT, 'Matrix', Ту) Одновременное применение двух пли более преобразований выполняется при помощи произведения соогвез сгвующих матриц: » Т = Ty*Tz » set(hGT, ’Matrix', Т) Например, для поворота на 90° вниз вокруг линии х = -2 следует сначала произвести смещение на две единицы в положительном направлении оси х, затем осуществить поворот вокруг оси g и произвести обратное смещение. » Txl = makehgtformf'translate', [2 0 0]) » Ry = makehgtformf'yrotate', pi/2) » Tx2 = makehgtformf'translate’, [-2 0 0]) » T - Tx2*Ry*Txl » setfhGT, 'Matrix', T) Обратите внимание, что при преобразовании важен порядок множителей матрицы т— они учитываются справа налево. Изменение этого порядка приведет к другим преобразованиям, например » Т2 - Txl*Ry*Tx2 » setfhGT, 'Matrix1, Т) или » ТЗ = Txl*Tx2*Ry » setfhGT, ‘Matrix’, ТЗ) Для возвращения группы в исходное состояние используется единичная матрица размера 4 на 4: » Т = eye(4) » setfhGT, 'Matrix', Т) Глава 9. Дескрипторная графика 557 В справочной системе MATLAB включен пример преобразований для группы hgtransform с достаточно сложной и разветвленной структурой, в котором мы рекомендуем разобраться самостоятельно (см. разд. MATLAB: Graphics: Handle Graphics Objects: Group Objects: Example — Transfoi tiling a Hierarchy of Object»). В следующем разделе мы рассмотрим работу с рисованными объектами, большинство из которых являются сгруппированными объектами hggroup. Рисованные объекты (Plot Objects) Высокоуровневые графические функции создают рисованные объекты, ряд свойств которых позволяет получить простой доступ к составляющим их базовым объектам. Часть свойств рисованных объектов расширяет их возможности по сравнению с соответствующими базовыми объектами. Приведем простой пример. При чтении разд. "Свойства линий и поверхностей" этой главы вы познакомились с основными свойствами объекта Lineseries, получаемого при помощи функции plot. С другой стороны, базовый объект Line обладает теми же самыми свойствами: толщина и цвет линии, тип, размер и цвет маркеров, XData, YData и ZData (для задания координат точек вершин ломаной) и т. д. Сравнение наборов свойств объектов Lircseries и Line позволяет выявить свойства, специфичные для рисованного объекта Lineseries. Способы получения информации о свойствах графических объектов и их назначении описаны в разд. "Полу некие информации о свойствах графических объектов " ванной главы. Рисованная линия допускает связывание с ней строки, которая будет выводиться в области легенды рядом с образцом линии. Для этого следует обратиться к свойству DispiayName объекта Lineseries, например: » X = 0:0.1:10; » £ = sin(х); » д = cos(х); » hF = figure » h? = axes » hL = plot(x, f, x, g) » set(hL(l), 'DisplayName', 'sin {itx}') » set(hL(2), ‘DisplayName’, 'cos {itx}') Заданные строки появятся при отображении легенды на осях » hLG = legend[hA, 'snow'} 5Ь8 Часть II. Вычисления и юа гнив Примечание j Функция legend возвращает указатель на легенду — пару осей с потомками: линиями и текстовыми объектами. В этом несложно убедиться, посмотрев тип объекта с указателем hLG и тип его потомков. В любой момент с линией может быть связана другая строка: » set(hL(2), 'Display-Name’, 'график косинуса') Теперь для обновления легенды достаточно обратиться к функции legend следующим образом: » legend(hLG) Кроме текстовой информации для легенды, с объектом Lineseries можно связать имена переменных, подлежащих графическому отображению. Имена переменных указываются в качестве значения свойств XDataSource. YDataSource и ZDataSource. При изменении значений этих переменны, и вызове функции refreshdata произойдет обновление графика. Если функция refreshdata вызвана без входных аргументов, то изменения коснутся только предков текущего графического окна. Обращение к refreshdata с одним входным аргументом— указателем на графическое окно или сам рисованный объект — позволяет более точно идентифицировать обновляемые объект ы: » time = 0:0.05:8; » fun = sin(time). Л2; » hF = figure; » hA = axes; » hL = plot(time,fun); » set(hL, 'XDataSource', 'time', 'YDataSource', 'fun'); » fun = sin (time) .''З; » refreshdata(hL) Соответствующие переменные (в нашем примере time и fun) должны существовать в рабочей среде, иначе выводится предупреждение и график не модифицируется. При вызове refreshdata из файл-функцг.и возможно использование и локальных переменных, дтя чего следует указать 'caller’ в качестве второго входного аргумента refreshdata. Все рисованные объекты: Areaseries, Barseries. Contourgroup и т. д. — обладают перечисленными выше свойствами, только у плоских объектов отсутствует свойство ZDataSource, а у объекта Surfaceplot — DisplayName. Большая часть рисованных объектов является сгруппированными объектами hggroup. Исключение составляют только Lineseries и Surfaceplot Например, контурный график функции двух переменных — объект Contourgroup — состоит из базовых объектов Patch и Text. Линии уровня отображаются п* помощи полигональных объектов, а текстовые служат для подписи зщ .-ний функции на линиях уровня. Гпава 9. Дескрипторная графика В юве 3 мы обсудили применение высокоуровневых функций contoui подобных ей для построения различных типов контурных графиков. Ост новимся теперь на ряде свойств объекта Contourgroup, полезных nj оформлении контурных графиков. Напомним, что для отображения графика функции двух переменных требу ется еоздат значения сетку в прямоугольной области на плоскости ху, вычислит! и в узлах сетки и вызвать contour, например: Ld(-l:0.2:l, -2:0.2:0); X + Y); Z) О * ч contour — указатель he на сгруппированный с из двух строк с информацией о линиях точно проста— каждой линии уровня столбцов. Первый столбец каждой "Ч данной линии уровня и число вер-'xihx столбцах записаны абсцесса и •чением свойства contou: * °С.< ' % + к л функции в ее узла; J нием свойств уЛ *ат< 560 Часть II. Вычисления и программирование ва установлены в 'auto', что приводит к автоматической генерации значений функции, отображаемых линиями уровня. Значение 'manual' выключает автоматическую генерацию — при изменении значения ZData контурный график перестраивается с прежним шагом (Levelstep), или списком значений (LevelList) исследуемой функции. Свойства LevelstepMode и LeveiListMode меняют значение 'auto' на 'manual' при установке свойствам LevelStep И LevelList НОВЫХ значений. Ряд свойств объекта Contourgroup отвечает за вывод значений функции на линиях уровня. Для отображения значений следует установить cboiictbc ShowText в значение 'on', а для скрытия — в 'off. По умолчанию маркиру ются все линии уровня, однако можно ограничить выбор несколькими лт ниями при помощи свойств TextList или Textstep. Как и в случае LevelLi; и Levelstep, задается либо вектор из соответствующих значений функци либо постоянный шаг. Свойства TextListMode и TextstepMode нринимаг одно из двух значений: 'auto' (по умолчанию) или 'manual'. Значение 'aut приводят к автоматической разметке всех линий уровня в соотвстс^ , ЗНаче^1ями LevelList И Levelstep, a 'manual' отключает ав^о разм/кУ- Изменение значений Textstep и TextList привол^р0'^4 Панствующих свойств TextstepMode И TextLlstMod^ ьрр шрифта и цветовое оформление ярл* „т обращения к потомкам рисованшгУ <ь цует вь)брать текстовые объе>~ cP*' vv » >емые гвойства. Для ,<Г 4' Ч-^' ья фу/щия f ipd' л® «s" >>’УХ Ух, X6 ЧАСТЬ III Приложения с ГРАФИЧЕСКИМ ИНТЕРФЕЙСОМ Глава 10 Принципы создания приложений с GUI Приложения MATLAB с графическим интерфейсом являются графическими окнами, содержащими элементы управления (кнопки, списки, переключатели, флаги, полосы скроллинга, области ввода, меню), а также оси и текстовые области для вывода результатов работы. Создание приложений включает следующие основные этапы — расположение нужных элементов интерфейса в пределах графического окна и программирование событий, которые возникают при обращении пользователя к данным объектам, например, при нажатии кнопки. Процесс работы над приложением допускает постепенное добавление элементов в графическое окно, запуск, тестирование приложения и возврат в режим редактирования. Конечным результатом является программа с графическим интерфейсом пользователя (GUI), содержащаяся в одном или нескольких файлах, запуск которой производится указанием ее имени в командной строке или в другом приложении МАТ1,АВ. Отметим, что в пакет MATLAB входит Runtime Server, предназначенный для создания приложений, запуск которых не требует установки MATLAB. Элементы управления являются графическими объектами— потомками I рафического окна в иерархии объектов. Они могут быть созданы при помощи специальных функций низкоуровневой графики. Однако гораздо эффективнее воспользоваться визуальной средой GUIDE, которая позволяет создать заготовку окна приложения, разместить на ней элементы управления, запрограммировать события и их взаимосвязь. 19 Зак. 130 564 Часть III, Приложения с графическим интерфейсом Среда GUIDE Перейдите в визуальную среду GUIDE, выполнив команду guide в командной строке. Появляется окно GUIDE Quick Start, изображенное на рис. 10.1, которое помогает настроить визуальную среду на создание приложения нужного типа или открыть существующее для продолжения работы. Рис. 10.1. Окно быстрого старта для среды GUIDE. Шаблон для нового приложения выбирается в списке GUIDE, templates на вкладке Create New GUI. Возможен один из следующих вариантов: □ Blank GUI (Default) — пустое окно приложения без элементов управления осей и меню; □ GUI with Uicontrols — окно приложения со строками ввода, переключателями и кнопками; □ GUI with Axes and Menu — окно приложения, содержащее оси, раскрывающийся список, кнопки и меню; □ Modal Question Dialog — модальное диалоговое окно с кнопками Yes и No. Установка флага Save on startup as позволяет задать имя файла, в котором будет содержаться окно приложения. Глава 10. Принципы создания приложений с GUI 565 Мы начнем с пустого окна приложения и будем сами размещать необходимые элементы управления. Имя файла приложения не обязательно выбирать заранее, его всегда можно сохранить из среды GUIDE. Итак, выберите опцию Blank GUI и нажмите кнопку ОК Появляется редактор среды GUIDE, заголовок которого untitled fig означает, что в нем открыт новый файл, увеличьте немного размеры окна так, как изображено на рис. 10.2. Панель инс1 рументов для управления приложением Панель инструментов для Размещения элементов интерфейса Заготовка окна приложения Рис. 10.2. Редактор среды GUIDE Редактор среды GUIDE содержит: П строку меню; □ панель инс грументов управления приложением; П заготовку окна приложения с нанесенной сеткой; □ панель инструментов для добавления элементов интерфейса на окно приложения. Редактор позволяет разместить различные элементы интерфейса (рис. 10.3). Для этого требуется нажать соответствующую кнопку на панели инструментов и поместить выбранный объект щелчком мыши на заготовку окна приложения. Другой способ состоит в задании прямоугольной области объекта перемещением мыши по области заготовки окна с удержанием левой кнопки. Размер и положение добавленных объектов изменяются при помощи мыши. Перед изменением размера следует выбрать режим выделения объектов и сделать объект текущим, щелкнув по нему кнопкой мыши. Названия элементов управления появляются на всплывающих подсказках при наведении курсора мыши на кнопки панели инструментов. Впрочем, можно снабдить кнопки соотвеиггвующими надписями, для чего следует в 666 Часть III. Приложения с графическим интерфейсом меню File среды GUIDE выбрать пункт Preferences и в появившемся одноименном диалоговом окне установить флаг Show names in component palette. Выбор режима выделения объектов в окне приложения Кнопка Переключатель Область ввода . текста Раскрывающийся список Кнопка-переключатель Обычная панель -— ---- Полоса скроллинг! ---- Флаг Текстовая область Список Оси Панель для группы переключателей или кнопок-ь ереключа гелей ActiveX-компоненты Рис. 10.3 Панель инструментов для добавления элементов интерфейса Потренируйтесь располагать элементы интерфейса и изменять их размеры, например, получите окно приложения, которое похоже на окно, изображенное на рис. 10.4. Приложение в данный момент находится в режиме редактирования. Любой объект можно удалить с окна, выделив его и нажав <Delete>. Запуск приложения производится гри помощи кнопки Run (рис. 10.5). При нажатии на нее появляется диалоговое окно GUIDE, которое сообщает о том, что запуск приложения приведет к его сохранению. Установка флага Do not show this dialog again позволяет избежать появления этого сообщения в дальнейшем. На жмите Yes, появляется диалоговое окно сохранения файла. Сохраните приложение в файле myguiO (расширение fig предлагается автоматически). Примечание Для автоматического сохранения приложения перед запуском можно сбросить флаг Show save confirmation on activate в диалоговом окне Preferences с настройками среды GUIDE. Состояние этого флага и флага Do not show this dialog again согласованы, если вы установили флаг Do not show this dialog again, то флаг Show save confirmation on activate при этом сбрасывается. И, наоборот, для появления диалогового окна GUIDE с запросом на сохранение приложения перед запуском следует установить флаг Show save confirmation on activate в окне Preferences. Гпава 10. Принципы создании приложений с GUI 567 Обычная панель Флаги Панель для группы переключателей a*es! Panel .Г” Check Вм Переключатели 1 Г Owe* Ви Оси I____b_ SaacTe ' U«« I Область - ввода * текста axes? Текстовая “ Список § г- HI.______________________, Push ЕМоп | Push Baton | Push Button | Toggle Button Toggle Baton | £ Раскрывающийся список Кнопки Кнопки-переключатели Полосы скроллинга Рис. 10.4. Пример окна приложения с элементами управления Tab Order Editor (редактор порядка Align Objects обхода элементов (выравнивание управления объектов) к .авишей <ТаЬ>) Property Inspector (инспектор свойств) Run (запуск приложения) Г RadaButkM Menu Editor M-file Editor Object Browser (редакторменю) (редактор М-файлов) (браузер объектов) । Рис. 10.5. Панель инструментов управления приложением Приложение запускается в отдельном окне с заголовком myguiO. Пользователь может нажимать на кнопки, устанавливать флаги, переключатели, обращаться к спискам, разумеется, при этом ничего полезного не происходит. Недостаточно разместить элементы интерфейса в окне приложения, следует 568 Часть III. Приложения с графическим интерфейсом позаботиться о том, чтобы каждый элемент выполнял нужные функции при обращении К нему пользователя. Например, при нажатии на кнопку производятся вычисления и строятся графики полученных результатов, переключатели позволяют установить цвет линий, полоса скроллинга изменяет толщину линии, в области ввода пользователь указывает некоторые параметры, управляющие ходом вычислений. Обратите внимание, что перед запуском приложения в редакторе М-файлов открылся файл myguiO.m, содержащий файл-функцию и ряд подфункций. При чтении следующих разделов вы будете использовать автоматически созданный М-файл для программирования событий элементов интерфейса. Программирование интерфейса, изображенного на рис. 10.4, является слишком сложным для начинающего программиста. Закройте окно приложения, редактор М-файлов и редактор приложений. Следующий раздел посвящен изучению основ программирования элементов управления на простом примере. Программирование интерфейса более подробно описано в следующей главе. Программирование событий Цель данного раздела состоит в объяснении принципа программирования событий в среде GUIDE. Приложение в MATLAB хранится (по умолчанию) в двух файлах с расширением fig и т, первый из них содержит информацию о размещенных в окне приложения объектах, а второй является М-файлом с основной функцией и подфункциями. Добавление элемента интерфейса из редактора приложения приводит к автоматическому созданию соответствующей подфункции. Данную подфункцию следует наполнить содержимым — операторами, которые выполняют обработку события, возникающею при обращении пользователя к элементу интерфейса (программирование подфункций описано в разд. "Подфункции" главы 5). Начните с создания простого приложения, окно которого содержит оси и две кнопки, предназначенные для построения графика и очистки осей. Перейдите в среду GUIDF командой guide с пустым окном приложения так, как было описано в предыдущем разделе. Выберите в меню Tools редактора приложений пункт GUI Options..., появляется диалоговое окно GUI Options. Данное окно позволяет устанавливать некоторые общие свойства создаваемого приложения. Убедитесь, что в раскрывающемся списке Command-line accessibility текущей строкой является Callback (GUI becomes Current Figure within Callbacks), включен переключатель Generate FIG-file and M-file и установлены все флаги, входящие в группу с ним. В следующей главе мы обсудим смысл всех опций. Сейчас отмстим, что выбранные нами значения приводят к автоматической генерации заготовок для подфункций обра Глава 10.1 Принципы создания приложений с GUI 569 ботки событий и позволяют использовать окно приложения для графического вывода. Расположите на форме оси и кнопку так, как показано на рис. 10.6. На кнопке автоматически размещается надпись Push Button, а на осях— axesl. Следующий этап очень важный. Кнопка и оси являются элемен сами интерфейса, им следует дать имена, которые уникальным образом идеятифици-ровали бы их среди всех объектов окна приложения (мы добавим их позже) и свидетельствовали об их назначении. Рис. 10.6. Расположение кнопки и осей в окне приложения Щелчком мыши выделите кнопку Push Button и вызовите инспектор свойств Property Inspector при помощи панели инструментов управления приложением (рис. 10.5). Появляется окно инспектора свойств, приведенное на рис. 10.7, в котором содержится таблица названий свойств кнопки и их значений. Напомним, что элементы управления являются объектами U1 Objects, котопые принадлежат графическому окну согласно иерархии графических объектов MATLAB. Если вы внимательно изучили материал главы 9, посвященной дескрипторной графике, то смысл некоторых свойств для вас очевиден (например, Background color или Fontsize). Важнейшим свойством в данный момент является Тад, которое содержит тэг или имя объекта. При добавлении элементов управления им автоматически при- 570 Часть III. Приложения с графическим интерфейсом сванваются имена, причем по умолчанию они состоят их типа объекта и номера (в нашем случае pushbutton]). Дадим кнопке информативное имя. которые говорит как о типе элемента, так и о его назначении. Эта кнопка будет служить для построения графика, что следует отразить в ее имени. Рис. 10.7. Редактор свойств Property Inspector Гпава 10. Принципы создания приложений с GUI 571 Установите свойство Тад в значение btnPiot, для чего щелкните мышью по строке справа от названия свойства, наберите требуемое значение и нажмите <Enter>. Мы выбрали аббревиатуру btnPiot исходя из сокращения btn для button (кнопка) и Plot (график). В дальнейшем будет говориться, что некоторому объекту или элементу управления следует дать имя, или установить его тег в некоторое значение. Аналогичным образом установите тег осей в значение axMain. Следует различать имя объекта и надпись на нем. Сейчас кнопка с именем btnPiot содержит текст Push Button. Измените его, установив в инспекторе свойств Property Inspector свойство string в значение Построить. Теперь надпись на кнопке соответствует ее назначению. При создании приложений с графическим интерфейсом вам прилезся часто прибегать к инспектору свойств Property Inspector для установки свойств объектов в подходящие значения. Не обязательно каждый раз делать объект текущим, а затем открывать окно инспектора свойств Property Inspector при помощи соответствующей кнопки на панели инсгрументов среды GUIDE. Во-первых, если окно Propel ty Inspector открыто, то щелчок мышью по объекту приводит к отображению его свойств в этим окне. Во-вторых, щелчок правой кнопкой мыши на любом объекте вызывает появление контекстного меню, содержащего пункт Property Inspector. Пожалуй, самое быстрое обращение к Property Inspector осуществляется двойным щелчком мыши по объекту. Все эти способы пригодны и для изменения свойств окна ирмложения. Сохраните приложение, для чего выберите в меню File среды GUIDE пункт Save as, создайте папку MyFirstGui (например, в текущем каталоге) и дайте имя mygui.fig окну приложения. Обратите внимание, что открылся редактор М-файлов, содержащий сопутствующий файл mygui.m. Данный файл сформировался автоматически, его структура схематично представлена в листинге 10.1. .........'•.г;:............................................................................................................................... Листинг 10.1 Структура М-файла ппнложечия с графическим интерфейсом .„'...ГЛ..,............... ........................... . .................................;.......................................... function varargout = mygui(varargin) % --- Executes on button press in btnPiot. function btnPlot_Callback(hObject, eventdata, handles) % hObject handle to btnPiot (see GCBO) % eventdata reserved ~ to be defined in a future version of MATLAB % handles structure with handles and user data (see GUlDATA) 572 Часть III. Приложения с графическим интерфейсом Основная функция mygui предназначена для инициализации приложения, поэтому редактировать ее не следует. Сейчас нас будет интересовать подфункция btnPiot Caiiback. Приложение mygui содержит одну кнопку Построить с именем btnPiot. Когда пользователь нажимает на нее в работающем приложении, то генерируется событие Callback данного элемента управления. При этом вызывается подфункция btnPiot ca] iback. Заметьте, что имя подфункции образовано именем (тегом) кнопки и названием события. Данная подфункция не содержит операторов, и при нажатии на кнопку ничего не происходит. Завершающий этап состоит в задании действий, которые выполняются при нажатии пользователем на кнопку Построить. Запрограммируйте подфункцию btnPiot Caiiback обработки события Callback кнопки Построить с именем btnPiot в соответствии с листингом 10.2 (автоматически созданные комментарии убирать не обязательно). В дальнейшем мы будем говорить, что требуется запрограммировать событие Callback некоторого объекта без указания имени подфункции и подробного описания самого объекта. г............................................................... : i Листинг 10.2, Обработка события Callback кнопки с именем btnPiot function btnPlot_Callback(hObject, eventdata, handles) x = -2:0.2:2; у = exp(-x.*2); pxot(x, у) Перейдем теперь к запуску приложения mygui. Нажмите кнопку Run на панели инструментов среды GUIDE. Поскольку приложение сохранено в отдельном каталоге MyFirstGui, то появляющееся диалоговое окно предлагает сделать этот каталог текущим. Убедитесь, что выбран переключатель Change MATLAB current directory, и нажмите ОК. Теперь каталог MyFirstGui стал текущим, и при последующих запусках приложения это окно выводиться не будет, при условии, если вы не измените текущий каталог из рабочей среды. Перед запуском может появиться еще одно диалоговое окно, в котором следует подтвердить сохранение файлов с расширениями fig и гл, содержащих приложение (автоматическое сохранение приложения и соответствующая опция среды GUIDE описаны в конце предыдущего раздела этой главы). После выполнения описанных действий на экране отображается окно приложения mygui. Нажатие на кнопку Построить приводит к отображению графика функции на осях. Следующим нашим шагом будет добавление кнопки, предназначенной для очистки осей. Глава 10. Принципы создания приложений с GUI 573 Завершите приложение при помощи кнопки закрытия окна в призом верхнем углу и продолжите работу над mygui в среде GIUDE. Добавьте кнопку так, как показано на рис. 10.8, задайте в редакторе свойств имя btnciear и надпись Очистить. Осталось запрограммировать событие Callback этой кнопки. Для быстрого перехода к соответствующей подфункции btnciear caiiback воспользуйтесь всплывающим меню, для чего щелкните правой кнопкой мыши по кнопке Очистить и выберите в пункте View Callbacks подпункт Callback. Становится активным окно редактора М-файлов, причем заголовок нужной подфункции выделен. Разместите единственный оператор очистки осей cla в подфункции (листинг 10.3). Рис. 10.8. Окно приложения с двумя кнопками »•'.......«*«.......*................. ............................• Листинг 10.3. Об аботта события кнопки с именем btnciear .. . .<. .. . — ..... .л. .*...—. ». .. function btndear_Callback(hObject, evenLdata, handles) cla 574 Часть III. Приложения с графическим интерфейсом Запустите приложение и убедитесь, что названия кнопок соответствуют выполняемым действиям, В этой главе мы рассмотрели основные действия при написании приложений с графическим интерфейсом в среде GUIDE: размещение элементов управления в окне приложения, задание их свойств, программирование событий и запуск приложения. В следующей главе мы обсудим некоторые приемы, применяемые для того, чтобы сделать интер |)ейс приложения интуитивно понятным. Продолжая работу над приложением mygui, вы научитесь использовать другие элементы управления, программировать события и осуществлять их взаимосвязанное поведение. Глава 11 Конструирование интерфейса Данная глава посвящена продолжению работы над приложением с графическим интерфейсом mygui, которая была начата в предыдущей главе. Описан процесс создания приложения, предназначенного для визуализации функций и интерактивного управления видом получающихся графиков. Объяснено, как размещать различные элементы интерфейса в окне приложения и программировать их события в М-файле, связанном с приложением. Управление свойствами объектов Разработка приложения связана с изменением свойств объектов, которые они получают по умолчанию при размещении их на заготовке окна. Элементы управления являются графическими объектами Uicontrol и полная информация о назначении их свойств доступна в браузере свойств графических объектов справочной системы MATLAB (использование браузера свойств графических объектов обсуждается в разд. "Получение информации о свойствах графических объектов" главы 9), Некоторые из свойств, например, размер кнопки, надпись ча ней и свойства шрифта, устанавливаются при создании объекта в режиме редактирования и изменять их, как правило, не требуется. Ряд свойств объектов необходимо устанавливать программно прямо в ходе работы приложения для обеспечения согласованного поведения элементов управления. Приступим к усовершенсгвованию приложения mygui . Пусть мы желаем, чтобы при запуске доступной являлась только кнопка Построить, а при нажатии на Построить выводился график и она становилась недоступной, зато появлялась бы возможность нажать кнопку Очистить для удаления графика, и начать все сначала. Итак, всегда доступна только одна из кнопок в зависимости от состояния осей. 576 Часть III. Приложения с графическим интерфейсом Решение поставленной задачи требует привлечения свойства объекта Enable, которое отвечает за возможность доступа к нему пользователем, значение 'on' разрешает доступ, a 'off', соответственно, запрещает. Поскольку элементы интерфейса являются графическими объектами, то для изменения их свойств следует прибегнуть к функции set (применение функции set описано в главе 9). В данном случае изменяется значение только одного свойства, поэтому функция set должна быть вызвана с тремя входными аргументами — указателем на объект, строкой с названием свойства и его значением. Заметьте, чго свойства одного объекта должны изменяться в подфункции обработки события Callback другого объекта. Следовательно, надо иметь возможность доступа к указателю на любой существующий объект. Требуемые указатели содержат входные аргументы hobject и handles подфункций, которые обрабатывают события элементов управления. В hobject хранится указатель на тот объект, событие которого обрабатывается в данный момент, a handles является структурой с указателями на все объекты. Имена полей структуры совпадают со значениями свойств Тад существующих элементов интерфейса. Например, handles.btnPiot является указателем на кнопку Построить с именем btnPiot. Доступ к кнопке Очистить должен быть запрещен в начале работы приложения, пока пользователь не нажмет Построить. Установите в инспекторе свойств для кнопки Очистить Enable в off, используйте кнопку со стрелкой в строке со значением свойства. Остальные изменения значения Enable кнопок должны происходить в ходе работы приложения. Для разрешения и запрещения доступа к кнопкам нужно внести дополнения в обработку их событий Callback. В подфункцию обработки события Callback КНОПКИ Построить добавьте: □ установку свойства Enable кнопки Очистить в 'on' (после вывода графика следует разрешить доступ к ней); □ установку свойства Enable кнопки Построить в ' off (после вывода графика она должна стать недоступной). Аналогичные изменения произведите в обработке события Callback кнопки Очистить, а именно: □ установку свойства Enable кнопки Построить в 'on' (после очистки осей досз уп к ней должен быть разрешен); □ установку свойства Enable кнопки Очистить в 'off' (после очистки осей следует запретить доступ к кнопке). Подфункции btnPiot Caiiback и btnClear_callback должны быть запрограммированы так, как показано в лист инге 11.1. Гпава 11. Конструирование интерфейса 577 .—..............------------- ••••..............................,.ч.. Листинг 111. обработка событии Callback КНОПОК btnPiot И btnClear ........ .. .... ............ ».........-L. . . function bl nPlot_Ca]Ibaek(hObject, eventdata, handles) X = -2:0.2:2; y - exp (-x. "2) ; plot(x, y) % Кнопка Построить должна стать недоступной после вывода графика set(hObject, 'Enable', ’off') % Кнопка Очистить должна стать доступной set(handles.btnClear, 'Enable', 'on') function btnClear_Callback(hObject, eventdata, handles) cla % очистка осей % Кнопка Очистить должна стать недоступной после очистки осей set(hObject, 'Enable', 'off') % <нопка Построить должна стать доступной set < handles.btnPiot, ’Enable', 'on') Сохраните изменения в редакторе М-файлов. Запустите приложение mygui и убедитесь, что всегда доступной является только одна из кнопок Пострвоть или Очистить, что является хорошей подсказкой для пользователя о возможных действиях. Закройте окно приложения и редактор приложений. Следующий раздел посвящен запуску приложения из командной строки и переходу в режим редактирования. Работа над приложением Запуск приложения и его редактирование Запуск приложения осуществляется не только из редактора приложений. Возникает вопрос, как работать с уже созданным приложением с графическим интерфейсом и, возможно, вносить в него требуемые изменения. Для запуска приложения достаточно в качестве команды задать ею имя в командной строке » mygui Появляется окно приложения, обращение к элементам интерфейса окна приводит к соответствующим действиям. 578 1 !аг:>ь III Приложения г графичегкии интерфейсом Примечание Каталог с приложением должен содержаться в путях поиска MATLAB или являться текущим. Установка путей поиска описана в главе 5. Очень часто сразу не удается написать законченное приложение, и необходимое усовершенствование проявляется только в ходе работы с приложением. В любой момент можно продолжить редактирование двумя способами: 1. Выполнить guide в командной строке, что приводит к отображению диалогового окна быстрого старта GUIDE Quick Start, в котором следует перейти к вкладке Open Existing GUI и воспользоваться списком Recently opened files или кнопкой Browse для поиска нужного файла с расширением fig. 2. Указать имя приложения через пробел после команды guide, например, guide mygui, при этом появляется среда GUIDE, в которой открыто mygui. В этом случае каталог с приложением должен быть текущим. Рис. 11.1. Окно приложения с заголовком Глава 11. Конструирование интерфейса 579 Перейдате в режим редактирования приложения mygui любым из перечисленных способов и продолжите работу над ним. Измените название окна приложения на "Визуализация функций" так, чтобы работающее приложение mygui имело вид, изображенный на рис. 11.1. Заголовок окна задается свойством Name графического окна. Установите в инспекторе свойств Property Inspector свойс гво Name окна приложения в Визуализация функций. Запустите mygui и убедитесь, что приложение имеет нужный заголовок. Желательно располагать элементы интерфейса в порядке, обеспечивающем удобную работу пользователя с приложением. Приложение хорошо вьпля-дит, если однотипные элементы, например, кнопки, флаги нт.д., определенным обоазом выровнены в окне приложения. Среда GUIDE предоставляет разработчику приложений несколько способов выравнивания добавляемых объектов — сетку, линейку и специальные инструменты. Размеры объектов и их выравнивание Редактор приложений содержит заготовку окна приложения, размер которого изменяется при помощи мыши, удерживая нажатой левую кнопку на квадратике, расположенный в правом нижнем его углу. Для задания точных размеров и положения окна запущенного приложения выберите в инспекторе свойств Property Inspector подходящие единицы измерения (пикселы, сантиметры и т. д.), обратившись к свойству Unit, и установите свойство Position в нужное значение (см. разд. "Управление положением графических окон"главы 9). На окно нанесена сетка с достаточно крупным шагом (по умолчанию). Аккуратное расположение большого числа элементов управления требует точного задания их положения Поскольку элементы управления Uicontrol являются графическими объектами (потомками графических окон), то естественно ожидать, что среди их свойств есть предназначенные для задания их размеров и положения в графическом окне. Эти свойства называются Position и unit, причем значением position должен быть вектор из четырех чисел (расстояние от левого и нижнего края окна, ширина и высота) в единицах измерения, установленных в unit. Элементы управления и оси могут быть сгруппированы и размещены на некоторой панели — графическом объекте Uipanel. В этом случае они являются потомками объекта Uipanel и их положение задается относительно этой панели. Сама панель есть потомок графического окна, поэтому значение свойства Position объекта Uipanel определяет ее положение в пределах окна. Предком для элементов управления может быть еще одна панель Uibuttongroup, которая предназначена для обеспечения согласованного поведения группы переключателей или кнопок-переключателей —- когда может быть включен только один элемент управления из всей группы Для до 580 Часть III. Приложения с графическим интерфейсом бавления панелей Uipanel и Uibuttongroup в окно приложения служат, соответственно, кнопки Panel и Button Group редактора среды GUIDE. Мы используем эти панели для размещения переключателей и флагов в окне нашего приложения mygui. Значения свойств Position и Units могут быть установлены в инспекторе свойств Property Inspector при размещении элементов управления и панелей в окне приложения или в подфункциях обработки событий, если работающее приложение должно изменить вид окна. Для аккуратного расположения элементов управления и панелей на этапе проектирования интерфейса можно избрать и более простой способ, чем установка свойству Position подходящего значения. Он состоит в использовании вспомогательных средств среды GUIDE: сетки, линеек и инструментов выравнивания. Для отображения линеек и доступа к свойствам сетки следует в меню Tools выбрать пункт Grid and Rules. Появляется диалоговое окно Grid and Rulers, изображенное на рис. 11.2. Рис. 11.2. Диалоговое окно Grid and Rulers Установка флага Show rules снабдит окно визуальной среды GUIDE горизонтальной и вертикальной линейками. Линейки позволяют размещать элементы интерфейса в позиции с любыми координатами в пикселах, отсчитываемыми от левого нижнего угла заготовки окна приложения. Следует выделить объект (например, кнопку) щелчком мыши и двигать его в окне следя за указателями его положения на линейке. Однако если установлен флаг Snap to grid, то непрерывного движения объекта не происходит — одна или две его границы стремятся совпасть с линиями сетки. Такое поведение перемещаемых объектов называется привязкой к сетке. В сочетании с достаточно мелким шагом сетки, который устанавливается в списке Grid Size (in Pixels), привязка позволит вам быстро оформлять приложение. Плавно из Глава 11 Менструирование интерфейса 581 менять положение выделенного объекта можно при помощи к лавиш со с грелками. Одновременное удержание <Ctrl> приводит к перемещению с учетом привязки к сетке. Перед размещением элементов управления полезно разметить окно приложения горизонтальными и вертикальными линиями выравнивания. Для этого следует навести курсор мыши на соответствующую линейку (курсор меняет фирму на двустороннюю стрелку) и, удерживая левую кнопку мыши, вытащить синюю линию на заготовку для окна приложения. Линии выравнивания отображаются, если установлен флаг Show giudts в диалог овом окне Grid and Rules. Передвижение объектов к линии выравнивания вызывает автоматическое расположение их границ на данной линии. Сами линии выравнивания можно убирать с окна приложения, перетаскивая их мышью обратно на линейку. Привязка объектов к линиям выравнивания действует и при сброшенном флаге Snap to grid. Выравнивание группы объектов производится с привлечением специальных средств, доступных в диалоговом окне Align Objects, для появления которого следует выбрать в меню Tools пункт Align Objects. Пиктограммы инструментов этого окна информативны и не требуют комментариев. Отметим только, что перед применением какого-либо из них следует выделить выравниваемые объекты щелчком мыши с одновременным удержанием <Ctrl>. Отредактируйте вид приложения mygui, используя вышеописанные возможности. Всплывающие подсказки и пиктограммы Всплывающие подсказки, которые появляются при наведении курсора мыши на элементы управления, существенно облегчают работу с приложением. Для снабжения элементов управления всплывающими подсказками следует установить их свойству Tooltipstring требуемое значение. Используйте инспектор свойств Property Inspector для добавления всплывающих подсказок к кнопкам Построить и Очистить, например, "Построение графика функции" и "Удаление графика функции" соответственно (кавычки набирать не следует). На кнопках и кнопках-переключателях могут быть размещены пиктограммы, поясняющие их назначение. Предположим, что цветная пиктограмма хранится в файле pict.bmp с глубиной цвета 24 bit. Сна"ала необходимо 582 Часть III. Приложения с графическим интерфейсом считать рисунок при помощи функции unread в некоторый массив рабочей среды, к примеру р: » Р = imreadl'pict20.bmp', 'bmp'); Затем в инспекторе свойств Property Inspector следует обратиться к свойству CData кнопки или кнопки-переключателя и установить его в значение р. Для этого можно либо набрать имя массива в строке ввода справа от названия свойства и нажать <Enter>, либо воспользоваться кнопкой, размещенной рядом с названием свойства для открытия диалогового окна CData, в котором имя массива вводится в строке Enter Expression. При этом в инспекторе свойств Property Inspector вместо имени массива отобразится информация о его размерах (трехмерный массив) и типе данных (unit8). Пиктограммы отображается на кнопках после запуска приложения. Следующие разделы посвящены размещению и программированию основных элементов интерфейса. Программирование элементов интерфейса Флаги, рамки Флаги позволяют произвести одну или несколько установок, определяющих ход работы приложения. Продолжите работу над mygui, предоставьте пользователю возможность наносить линии сетки на график. Окно приложения должно содержать два флага с названиями сетка по х и сетка по у. Если пользователь нажимает кнопку Построить, то не только строится график функции, но и на оси наносится сетка по выбранным координатам. Нажатие на Очистить должно приводить к исчезновению графика функции и скрытию сетки. Обычно несколько элементов управления со схожим назначением группируются и помещаются на некоторой панели. Мы уже упоминали, что применяются панели двух типов: Uipanel и Vibuttongroup. В данном случае подойдет обычная панель Uipanel. поскольку флаги являются независимыми и могут быть включены или сброшены по отдельности. Измените размеры осей, освободив справа место для рамки. Нанесите панель на окно приложения при помощи соответствующей кнопки (рис. 10.3). По умолчанию имя панели uipanel 1, а ее заголовок Panel. В инспекторе свойств измените заголовок на Сетка, воспользовавшись свойством Title объекта Uipanel. За положение имени панели отвечает свойство Titleposition, которое по умолчанию имеет значение ’lefttop’, т. е. в левом верхнем углу панели. Изучите остальные возможные варианты самостоятельно, обратившись к инспектору свойств Property lnspe< юг или браузеру свойств графических объектов в справочной системе MATLAB На панель добавьте два флага так, как показано на рис. 11.3. Гпава 11. Конструирование интерфейса 583 Рис. 11.3. Добавление панели и флагов 584 Часть III. Приложения с графическим интерфейсом Разместите поясняющие подписи рядом с флагами и дайте им имена. Задайте свойству Тад верхнего флага значение chbxGridx, а свойству string, отвечающему за подпись флага, значение сетка по х. Аналогичным образом определите свойства нижнего флага, установите свойство Tag в chbxGridY, и string в сетка по у. Если текст не помещается рядом с флагом, увеличьте ширину области флага при помощи мыши, удерживая нажатой левую кнопку. Осталось сделать так, чтобы при нажатии пользователем кнопки Построить происходило отображение линий сетки в зависимости от установленных флагов, а нажатие на Очистить приводило к скрытию сетки. Блок обработки события Callback кнопки Построить следует дополнить проверкой состояния флагов. Свойство флага value принимает значение 1 при установке флага пользователем и, соответственно, равно нулю, если флаг сброшен. У флагов, как и у большинства элементов управления, имеется два свойства Min и мах, принимающие по умолчанию значения 0 и I соответственно. Если флаг установлен, то совпадают значения Vai ue и мах, а если сброшен, то Value и Min. Значение свойства графического объекта позволяет получить функция get, первым входным аргументом которой должен быть указатель на объект, а вторым — название свойства (применение функции get описано в главе 9). Как и в случае согласования кнопок Построить и Очистить, в подфункции обработки события Callback одного объекта (кнопки) мы должны получить указатель на другой объект (флаг). Для этого следует обратиться к полям chbxGridx И chbxGridY структуры handles И, В зависимости ОТ ИХ значений, установить свойства осей xGrid и YGrid в 'on' или 'off'. Произведите необходимые изменения в подфункции обработки события Callback кнопки Построить (листинг 11.2). ............................................................... ... ...... Листинг 11.2. Обработка соо.»тия пипки П^стооито : с учетом состояния флагоь s............................................."....л.-...... !....... function btn₽lot_Callback(hobject, eventdata, hanales) % Построение графика функции х = -2:0.2:2; у = ехр(-х.'2J; plot(х, у) % Проверка флага сетка по х if get[handles.chbxGridx, 'Value') % Флаг включен, следует добавить линии сетки Глава 11 Конструирование интерфейса 585 set(gca, 'XGrid', 'on') else % Флаг выключен, следует убрать линии сетки setfgca, 'XGrid', 'off') end % Прове! ка флага сетка по х if get(handles.chbxGiidY, 1Value1) % Флаг включен, следует добавить линии сетки set(gca, 'YGrid', 1 on1) else % Флаг выключен, следует убрать линии сетки set(gca, 'YGrid', 'off') end % Кнопка Построить должна стать недоступной после вывода графика set(hObj ect, 'Enable', 'off') % Кнопка Очистить должна стать доступной set(handles.btnClear, 'Enable1, 'on') Запустите приложение mygui и убедитесь, что установка флагов влияет на отображение сетки при нажатии на кнопку Построить Смена состояния флагов сетки не приводит к немедленным изменениям на графике. Пользователь должен перестроить график, нажимая последовательно кнопки Очистить н Построить. Для немедленного реагирования приложения на состояние флагов следует определить их события Callback. Программирование данных событий заключается в проверке состояния флага и отображении или скрытии соответствующих линий сетки. Сделайте текущим флаг сетка по х в редакторе приложений и перейдите к подфункции chbxGridx cailback при помощи всплывающего меню данного объекта. Запрограммируйте событие Callback флага. Используйте аргумент hObject соо,1'ветствующих подфункций, содержащий указатель на объект, событие которого обрабатывается в текущий момент времени. Аналогичным образом обработайте событие Callback второго флага сетка по у (листинг 11.3). Примечание Для быстрого перехода к подфункциям в редакторе М-файлов предназначена кнопка Show functions, нажатие на которую приводит к появлению списка подфункций. Выбор подфункции в этом списке влечет переход к ней в окне редактора. 586 Часть III. Приложения с графическим интерфейсом function chbxGridX_Callback(hObject, eventdata, handles) if getfhObject, 'Value') % Флаг включен, следует добавить линии сетки set(gca, 'XGrid', 'on') else % Флаг выключен, следует убрать линии сетки set(gca, 'XGrid', 'off') end function chbxGridY_Callback(hObject, eventdata, handles) if get(hObject, 'Value') % Флаг включен, следует добавить линии сетки set(gca, 'YGrid', 'on') else % Флаг выключен, следует убрать линии сетки set(gca, 'YGrid', 'off') end Модифицированные подфункции позволяют пользователю наносить и убирать сетку по каждой координате при помощи флагов без перестроения графика функции. Самостоятельно внесите дополнения в подфункцию обработки события Callback кнопки Очистить, обеспечивающие удаление не только графика функции,но и линий сетки Флаги предостав тяют пользователю возможность выбора одной или сразу нескольких опций. Одновременный выбор только одной опции осуществляется при помощи переключателей. Переключатели Модернизируйте интерфейс приложения mygui, предоставьте пользователю возможность выбирать тип маркера (кружок, квадрат или отсутствие маркера) при помощи трех переключателей. Переключатели обычно группируются по их предназначению, и пользователь может выбрать только одну опцию, т. е. всегда установлен единственный переключатель из группы Как Глава 11. Конструирование интерфейса 587 мы уже отмечали, для обеспечения такой согласованной работы переключателей служит панель Uibuttongroup. Добавьте в окно приложения панель Uibuttongroup, воспользовавшись кнопкой Button Group среды GUIDE, Задайте имя Тип маркера для этой панели аналогично тому, как вы определяли имя обычной панели при размещении флагов. Нанесите на нее три переключателя. Установите их свойствам Тад значения rbMarkCirc, rbMarkSq, rbMarkNone, a String— круги, квадраты, без маркеров соответственно (рис. 11.4). Состояние переключателя, так же как и флага, определяется его свойствами value, мах и Min, причем по умолчанию Мах установлено в 1, a Min— в 0. Для включенного переключателя совпадают значения value и Мах, а для выключенного — Value И Min. Задайте в инспекторе свойств Property Inspector значение 1 свойству value переключателя с надписью без маркеров, он будет включен при запуске программы. Значение свойства value устанавливается следующим образом. 588 Часть III. Приложения с графическим интерфейсом Выделите переключатель и отобразите его свойства в Property Inspector, нажмите кнопку в строке с value. Появляется окно Value, изображенное на рис. 11.5. Рис. 11.5. Окно Value для установки значения Выделите при помощи мыши строку со значением 0.0 и перейдите в режим редактирования значения двойным щелчком мыши. Измените 0.0 на 1 и нажмите ОК. Обратите внимание, что в инспекторе свойств Property Inspector значение value изменилось на единицу, и включился переключатель без маркеров на заготовке окна приложения. Остальные переключатели панели Тип маркера выключены. Предположим, что пользователь установил один из переключателей. Происходит обращение к соответствующей подфункции обработки события Callback переключателя, которая должна изменить тип маркеров линии. Обсудим программирование этого события, поскольку оно связано с решением общей проблемы — обменом данными между подфункциями. Изменение типа маркеров линии не представляет труда — если известен указатель на линию, то достаточно обратиться к свойству линии Marker при помощи функции set и установить его в нужное значение. Указатель на линию возвращает функция plot в выходном аргументе, его следует записать в некоторую переменную, например. Line. Использовать указатель на линию придется в других подфункциях, обрабатывающих событие Callback пере Гпава 11. Конструирование интерфейса 589 ключателей. Очень важно понять, что переменная Line инициализируется при вызове подфункции btnPiot Caiiback и после ее завершения становится недоступной, поскольку все переменные, определенные в подфункции, являются локальными и по окончании работы подфункции не определены. Обмен данных между подфункциями проще всего осуществить при помощи структуры handles. Подфункция, передающая данные, должна содержать запись данных в новое поле и сохранение структуры функцией guidata. Тогда входной аргумент— структура handles всех подфункций будет содержать добавленное поле, в которое занесено соответствующее значение. Например, в некоторой подфункции можно сохранить массив в поле datl структуры handles handles.dat! = [1.2 3.2 0.1]; guidata(gcbo, handles) а затем, использовать его в другой подфункции max(handles.datl) В нашем случае данные, подлежащие сохранению, являются указателем на линию, созданную в результате работы подфункции btnPiot_caiiback. Внесите необходимые изменения в подфункцию btnPlot_Callback и запрограммируйте обработку событий Callback переключателей в подфункциях rbMarkCirc_Callback, rbMarkSq_Callback, rbMarkNone_Callback(ЛИСТИНГ 11.4): □ сохраните указатель на линию в поле Line структуры handles при построении графика командой plot и сохраните обновленную структуру при ПОМОЩИ функции guidata; □ добавьте операторы обработки событий Callback переключателей, каждый из которых наносит на линию соответствующие маркеры или убирает их. ............. . " - ; . ; • ...l-V'V..д’....; . Листинг 11.4. Обработка событий переключателей в myguipxog function varargout = btnPlot_Callback(hobject, eventdata, handles) % Построение графика функции x = -2:0.2:2; у = ехр(-х.л2); % Запись указателя в поле line 'труктуры handles handles.Line = plotfx, у); i Сохранение структуры handles для использования в других подфункциях guidata(gcbo, handles); 590 Часть III Приложения с графическим интерфейсом f-mction varargout = rbMarkCirc_Callback(hObject, eventdata, handles) % Выбран переключатель маркеры-круги set(handles.Line, 'Marker', 'o') % размещение маркеров-кругов на линии function varargout = rbMarkSq_Callback(hObject, eventdata, handles) % Выбран переключатель маркеры-квадраты set(handles.Line, 'Marker*, 's') % размещение маркеров-квадратов на линии function varargout = rbMarkNone_Callback(hObject, eventdata, handles) % Выбран переключатель без маркеров set(handles.Line, 'Marker', 'none') % удаление маркеров с линки Запустите приложение mygui, отобразите график функции, нажав Построить. и убедитесь в том, что возможна установка только одного из переключателей и она приводит к появлению соответствующих маркеров на графике функции или их удалению. Однако пока еще интерфейс mygui имеет ряд недостатков. □ Если пользователь использует Очистить для удаления графика, а затем устанавливает любой переключатель, то производится обращение к несуществующему объекту линии (сообщение об ошибке выводится в командное окно). □ Нажатие на Построить приводит к получению линии без маркеров вне зависимости от установленного переключателя. □ Повторный щелчок по области переключателя приводит к его выключению, но всегда один из переключателей должен быть установлен. Конечно, первый недостаток является существенным — приложение должно работать без ошибок! Проще всего запретить доступ к переключателям, если нет линии на графике, и разрешить после ее появления. Очевидно, что следует внести изменения в соответствующие подфункции myguiprog, обрабатывающие события Callback кнопок. Нажатие на Построить должно открывать доступ к группе переключателей, а очистка осей кнопкой Очистить— запрещать доступ. Итак, следует найти указатели на переключатели и установить их свойство Enabled в нужное значение 'or.' или 'off При запуске приложения все переключатели должны быть недоступны, т. к. пользователь еще не построил график функции. Редактор свойств позволяет одновременно установить значение общих свойств, например, Enable, целой группы объектов. Выделите щелчком мыши один из переключателей, а остальные добавляйте в группу щелчком мыши, удерживая нажатой <Ctrl>. В результате должны быть выделены все три переключателя. Теперь перейдите в редактор свойств при помощи Глава 11. Конструирование интерфейса 591 всплывающего меню. Вверху окна редактора свойств размещена надпись Multiply objects selected, означающая, что проделываемые установки произойдут для свойств сразу всех выделенных объектов. Установите Enable в •off', при запуске приложения mygui переключатели недоступны. Осталось дополнить подфункции обработки события callback кнопок Построить и Очистить для программного управления свойством Enable. Обратитесь к листингу 11.5, содержащему требуемые операторы. •“ • ............г.» ..... ............................... : Пи ззоешение и запрещение доступа к группе переключателей ..... .... . ...... . rt'. .. . ....Лг.ШлЗамС.Л.Ль. .................... function btnPlot-Callback(hObject, eventdata, handles) % Все переключатели должны стать доступными после появления графика set(handles.rbMarkCirc, ’Enable', ' on') set(handles.rfcMarkSq, 'Enable', 'on') set(handles.rbMarkNone, 'Enable', ' on') function btnClear_Callback(hObject, eventdata, handles) % Все переключатели должны стать недоступными после очистки осей set(handles.rbMarkCirc, 'Enable', 'off') set(handles.rbMarkSq, 'Enable', 'off’) set(handles.rbMarkNone, 'Enable', 'off') Первый недостаток интерфейса приложения mygui устранен. Теперь необходимо сделать так, чтобы при построении графика гип маркера отвечал установленному переключателю. Очевидно, что после вывода графика следует найти переключатель со значением value, равным единице, и установить соответствующий тип маркера (листинг 11.6). Листинг . 1.6. Изменение маркероз при построении графика ..... ............................ •>. .. ...ч.... ...... function btnPlot_Callback(hob]ect, eventdata, handles) if get(handles.rbMarkCirc, 'Value') % Установлен переключатель маркеры-круги set(handles.Line, 'Marker', 'o') end if get(hai.dles.rfcMarKSq, 'Value') 592 Чгсто III. Приложения с графическим интерфейсом % Установлен переключатель маркеры-круги set(handles.Line, 'Marker', ’s') eiid Теперь тип маркеров определяется установленным переключателем при построении графика. Осталась нерешенной одна проблема. При повторном щелчке по области переключателя он выключается, но всегда должен быть установлен единственный переключатель. Данный недостаток устраняется с привлечением еще одного возможного значения inactive свойства Enable. Переключатель со значением inactive является неактивным, он выглядит в работающем приложении как доступный переключатель (со значением on), но попытка изменить состояние данного переключателя не приводит к успеху. Усовершенствуйте обработку событий согласно следующему алгоритму. 1. Свойство Enabled переключателя, событие Callback которого обрабатывается, должно иметь значение inactive, а для остальных двух on. Если не задать on для других переключателей, то все они станут неактивными. 2. При нажатии на Построить свойству Enable всех переключателей присваивается on, а затем определяется установленный в данный момент переключатель и В Enable заносится значение inactive. Дополните подфункции btnPlot_Callback, rbMarkCirc_Callba :k, rbMarkSq_Callback И rbMarkNnne_Callback необходимыми операторами (листинг 11.7). • ..................... “ л-лт,.—• • ......................; ..............у .......................... Листинг 11.7. Предотвращение выключения переключателя повторным щелчком мыши ...............ч...»Л...................... ............................ Л» function btnPlot_Callback(hObject, eventdata, handles) % Поиск установленного переключателя и определение его, как неактивного if get(handles.rbMarkCirc, ‘Value1) set(handles.rbMarkCirc, 1 Enable', 'inactive *) end if get(handles.rbMarkSq, 1Value') set(handles.rbMarkSq, 'Enable', 'inactive') end if get(handles.rhMarkNone, 'Value') set(handles.rhMarkNone, 'Enable', 'inactive') end Гпава 11. Конструирование интерфейса Ь93 function rtMarkCirc_Callback(hobject, eventdata, handles) Переключатель, событие которого обрабатывается, должен стать % неактивным, а остальные — активными set(hobject, 'Enable', 'inactive'} set(handles,rbMarkSq, 'Enable', 'on') set(handles.rbMarkNone, 'Enable', 'on') function rbMarkSq_Callback(hobject, eventdata, handles) % Переключатель, событие которого обрабатывается, должен стать % неактивным, а остальные — активными set(hObj ect, 'Enable', 'inactive') set(handles.tcMarkCirc, 'Enable', 'on1) set(handles.rbMarkNone, 'Enable', 'on') function rbMarkNone_Callback(hobject, eventdata, handles) % Переключатель, событие к< торого обрабатывается, должен стать % неактивным, а остальные — активными set(hobject, 'Enable', 'inactive') set(handles.rbMarkSq, ’Enable', 'on') set(handles.rbMarkCirc, 'Enable', 'on') Правильная обработка переключателей (см. листиши 11,4—11,7) требует учета всех ситуаций, которые могут возникнуть при взаимодействии пользователя с приложением. Использование кнопок-переключателей ничем не отличается от переключателей, Альтернативный способ выбора пользователем только одной из предлагаемых опций реализуют раскрывающиеся списки Списки Модернизируйте интерфейс приложения mygui, предоставьте пользователю возможность выбора цвета линии графика из раскрывающегося списка (синий, красный, зеленый). Перейдите в режим редактирования и добавьте при помощи панели управления раскрывающийся список (рис. 11.6). Установите в инспекторе свойств Property Inspector Tag в значение pmcoior. 514 Часть III. Приложения с графическим интерфейсом Элементами раскрывающегося списка являются строки, которые вводятся в инспекторе свойств Property Inspector. Нажмите кнопку в строке со свойством string раскрывающегося списка, появляется окно String. В области ввода текста замените текст "Pop-up Menu" на строки "синий", "красный", "зеленый" (без кавычек), разделяя их при помощи <Enter> (рис. 11.7) и нажмите ОК Запустите mygui и убедитесь, что раскрывающийся список содержит требуемые строки. Выбор различных строк пока не приводит к изменению цвета линии — требуется запрограммировать событие Callback раскрывающегося списка. Обработка события Callback раскрывающегося списка состоит в определении выбора пользователя и соответствующем изменении цвета линии. Свойство списка value содержит номер выбранной строки, которые нумеруются с единицы. Перейдите к подфункции pmColor Callback и запрограммируйте обработку выбора пользователя. Используйте оператор switch для установки цвета линии в зависимости от номера выбранной строки списка (листинг 11.8). Глава 11. Конструирование интерфейса 595 Рис. 11.7. Окно String Гистинг *11°- Обработка выбора пользователя из раскрывающегося списка function pmColor_Callback(hObject, eventdata, handles) % Определение номера выбранной строки Num - get(hObject, 'Value'); switch Num case 1 % Выбрана первая строка, следует сделать линию синей set(handles.Line, 'Color', 'b'); case 2 % Выбрана вторая строка, следует сделать линию красной set(handles.Line, 'Color', 'г‘); case 3 % Выбрана третья строка, следу» т сделать линию зеленой set(handles.Line, 'Color', 1 g'); end Запустите приложение, постройте график, нажав на Построить, и убедитесь в том, что раскрывающийся список позволяет изменять цвет линии графика функции. 20 Зек 130 Ь9Р Часть III. Приложения с графическим интерфейсом Несложно заметить, что интерфейс mygui еще имеет ряд недостатков: □ повторное построение графика не учитывает текущий выбор цвета в раскрывающемся списке; □ выбор цвета при отсутствии линии на графике приводит к ошибке (handles.Line указывает на несуществующий объект); П рядом со списком требуется разместить текст, поясняющий назначение списка. Устраните первый недостаток, поместите в подфункции btnPlot_Callback обработки нажатия кнопки Построить блок switch для задания цвета построенной линии в зависимости от состояния раскрывающегося списка (листинг 11.9). .'. • •"*.— “• .—-—...... .д... Листинг 11.9. Учет состояния раскрывающегося списка при построении графика function varargout = btnPlot_Callback(hObject, eventdata, handles) % Определение номера выбранной строки Num = get Jhandles.pmColor, 'Value'); 3 Установка требуемого цвета линии switch Num case 1 set(handles.Line, ’Color', 'b'); case 2 set(handles.Line, 1 Color', 'r'); case 3 set(handles.Line, 'Color’, 'g'); end Изменение цвета линии при отсутствии графика лишено смысла, поэтому следует запретить доступ пользователя к раскрывающемуся списку, и, напротив, разрешить, при построении графика. В начале работы приложения список должен быть недоступен для пользователя. Установите в инспекторе свойств Property Inspector для раскрывающегося списка Enable в значение off. Внесите необходимые дополнения в подфункции btnPiot Callback и btnciear_Callback, соответствующие нажатию на кнопки, используйте свойство списка Enable (листинг 11.10). гпава 11. Конструирование интерфейса 597 г:--* .......................................... ..................... —.................................. Листинг 11.10. Развешение и запрещение доступа к раскрывающемуся списку , .. ................ — . .» ....... „.*.,.1*,, I ...... .... . . ... ,, ...... .»|» ....Ь ... function varargout = btnPlot_Callback(hobject, eventdata, handles) % Разрешение доступа к раскрывающемуся списку set(handles.pmColor, 'Enable', 'on') function varargout = btnClear_Callback(hCbject, eventdata, handles) % Запрещение доступа к раскрывающемуся списку set(handles,pmColor, 'Enable', 'off') Рис. 11.8. Добавление текста Многие элементы интерфейса, в частности, раскрывающиеся списки, следует сопровождать поясняющим текстом. Перейдите в режим редактирования 538 Часть III. Приложения с графическим интерфейсом и при помощи панели управления разместите текстовую область (Static Text) над списком. Установите в инспекторе свойств Property Inspector String В Цвет линии, a HorizontalAlignmcnt В left ДЛЯ добавленного объекта, используйте кнопки в строках с названиями свойств. Теперь работающее приложение имеет более наглядный интерфейс (рис. 11.8). Программирование события CallBack обычных списков (Listbox) производится практически аналогично. Отличие состоит в том, что в обычных списках может быть выделено несколько элементов, массив номеров которых будет являться значением свойства Vatue. Разрешение выбора нескольких элементов определяется значениями свойств мах и Min. Если разность Мах - Min больше единицы, то пользователь может выделить несколько строк. Содержимое списков может быть установлено или изменено из программы, для чего формируется массив строк и устанавливается в качестве значения свойства string. Значением свойства string может также быть массив ячеек, содержащих строки, или одна строка, в которой элементы списка разделены символом вертикальной черты |. Полосы скроллинга Усовершенствуйте интерфейс приложения mygui, предоставив пользователю возможность устанавливать ширину линии при помощи полосы скроллинга. Добавьте полосу скроллинга (Slider) в окно приложения и задайте ей имя scrwidth в свойстве Tag. Снабдите полосу скроллинга текстовым пояснением "Толщина линии" так же, как и раскрывающийся список (рис. 11.9). Простой щелчок мышью в окне приложения при добавлении полосы скроллинга приводит к появлению вертикально расположенной полосы. Вертикальное или горизонтальное направление зависит от соотношения ширины и высоты полосы скроллинга. Измените размер для получения горизонтально расположенной полосы. Проше всего сразу нарисовагь прямоугольник полосы скроллинга, удерживая нажатой левую кнопку мыши Теперь следует определить соответствие между положением бегунка полосы и числовым значением ее свойства Value. Проделайте следующие установки из редактора свойств. 1. В мах занесите десять, а в Min— единицу. Свойства Мах и Min полосы скроллинга отвечают за границы значений, записываемых в Value, при перемещении бегунка. Гпава 11. Конструирование интерфейса 599 2. Определите начальное положение, записав в value единицу. Нажмите кнопку в строке с названием свойства, и в появившемся окне Value (см. рис. 11.5) измените значение на единицу. 3. Обратитесь к свойству sliderstep. Его значением является вектор из двух компонент, первая из которых определяет относительное изменение value при нажатии на кнопки со стрелками полосы скроллинга, а вторая — при перетаскивании бегунка мышью. Для того чтобы нажатие на кнопки полосы изменяло value на десять процентов, а щелчок мыши справа или слева от бехунка на двадцать, следует установить значение [0.10.2] свойства SliderStep. Раскройте строку Sliderstep щелчком мыши по знаку плюс слева от названия свойства и в появившихся строках х и у введите 0.1 и 0.2 (рис. 11.10). Осталось запрограммировать событие Callback полосы скроллинга с именем scrwidth, которое состоит в задании ширины линии, равной округленному значению value. Перейдите к подфункции scrwidth caiiback и добавьте в ней оператор установки ширины линии (листинг 1111). 600 Ч: сть III, Приложения с графическим интерфейсом £ SliderStep (0.1 0.2| — X 0.1 *-У 02 Рис. 11.10, Ввод значений SliderStep Листинг 11.11. Обработка события callback полосы скроллинга .......л ............ ............. ... .............................................................................. ........... function scrVJidth_Callback (hObject, eventdata, handles) % Получение ширины линии в зависимости от положения бегунка % на полосе скроллинга width = get(hObject, 'Value'); % Установка толщины линии set(handles.Line, 'LineWidth', round(width)) Запустите mygui и убедитесь, что полоса скроллинга позволяет легко изменять толщину линии построенного графика. Устраните самостоятельно некоторые недочеты интерфейса. Полоса скроллинга должна быть недоступной после очистки осей кнопкой Очистить, построение графика при помощи Построить произведите с учетом установленной ширины линии. Данные недостатки исправляются внесением соответствующих изменений в обработку событий callback перечисленных кнопок так же, как и в предыдущих разделах. Область ввода текста Обычные текстовые области (Static Text), использовавшиеся на протяжении предыдущих разделов, позволяют лишь вывести некоторый текст в окно приложения. Обмен текстовой информацией между пользователем и приложением осуществляется при помощи областей ввода текста Предоставьте пользователю возможность ввести выражение для функции, график которой требуется построить. Добавьте в окно приложения область ввода текста, установите ее свойство Тад в значение editFun и снабдите ее пояснением в текстовой области, расположенной выше так. как показано на рис. I l.l I. При запуске приложения mygui строка для ввода функции должна быть пустой, поэтому в редакторе свойств удалите из String строку Edit Text. Набранная строка в области ввода должна содержать выражение для функции с учетом правил записи поэлементных операций. Содержимое этой строки является значением свойства string области ввода, его надо будет Гпава 11. Конструирование интерфейса 601 преобразовать в inline-функцию при программировании события кнопки Построите, и вычислить вектор значений функции (создание inline-функций описано в разд. "Встраиваемые и анонимные функции" главы 6). Рис. 11.11. Добавление области ввода текста С другой стороны, если курсор находится внутри области ввода, то на’жагие <Fnter> вызовет возникновение ее события CaliBack. Разумно предусмотреть, чтобы в этом случае построился график функции и произошли все события, запрограммированные в подфункции обработки события callback кнопки Пос троить. Для этого вовсе не требуется копировать операторы подфункции btnPiot Caiiback в подфункцию editFun_CaliBack — достаточно просто вызвать btnPiot Callback. Первым ее входным аргументом должен быть указатель на кнопку Построить, поскольку hobject является указателем на тот объект, событие которого обрабатывается, а в данном случае мы программно моделируем нажатие кнопки пользователем. Листинг 11.12 содержит операторы для построения графика функции, введенной пользователем. 602 Часть III. Приложения с графическим интерфейсом f :Чё'л' .КГУ*'"'жду ^у- 'дка^тж^|^||ва11г г • •• • •"'1 ”Т‘ТУ ЦТJ Листинг 11.12. Обработка событий Callback кнопки Построить. и Области вво- да текста function btnPlotCallback(hObject, eventdata, handles) X = -2:0.2:2; funstr = get(handles.editFun, 'String'); fun = iniine(funstr}; у - fun(x); handles.Line = plot(x, y); function editFun_Callback(hObject, eventdata, handles) btnPlot_Callback(handles.btnPiot, eventdata, handles) Доработайте интерфейс приложения, обеспечив согласованное поведение кнопок и области ввода iтекста. Вышеописанный пример демонстрирует использование области ввода, состоящей из одной строки. Разность значений свойств Мах и Min области ввода определяет, позволяет ли данная область ввод многострочного текста. Если разность больше единицы, то заносимый пользователем текст записывается в массив ячеек текстовых строк, который хранится в string. Свойства приложения Приложения с графическим интерфейсом имеют ряд свойств, отвечающих за взаимодействие приложения с пользователем и рабочей средой MATLAB. Для доступа к основным опциям следует выбрать в меню Tools визуальной среды пункт GUI Options. Появляется одноименное диалоговое окно, изображенное на рис. 11.12. Обсудим возможности по настройке графического приложения средствами данного окна. Изменение размеров приложения Раскрывающийся список Resize behavior окна GUI Options, приведенного на рис. 11.12, предназначен для выбора способа изменения размеров работающего приложения. По умолчанию установлено Non-resizable, что не позво Глава 11. Конструирование интерфейса 603 ляет пользователю менять размеры окна приложения и часто оказывается удобным. Выбор Proportional приводит к пропорциональному изменению размеров и положения всех элементов управления, в том числе и тех, которые хотелось бы сохранить постоянными (размеры кнопок, ширина и длина областей ввода и полос скроллинга, размеры панелей и расположение флагов и переключателей в них). Более гибкого управления размерами позволяет добиться опция Other (Use ResizeFcn), ее и следует выбрать. Рис. 11.12. Диалоговое окно GUI Options с основными настройками приложения Мы рассмотрим обработку только нескольких элементов управления нашего приложения mygui, поскольку поведение остальных программируется аналогичным образом. В окне приложения есть два флага: сетка по х и сетка по у с именами chbxGridY и chbxGridY, размещенные на панели Сетка с именем uipaneli. Сделаем так, чтобы расстояние между левым краем рамки и правым краем окна всегда было 180 пикселов, между нижним ее краем и верхним краем окна— 90 пикселов, а ширина и высота рамки составляли бы 160 и 70 пикселов соответственно. Флаги будут сохранять свое положение и размеры относительно неизменяющейся рамки, поскольку являются ее потомками. При изменении размеров окна возникает событие окна ResizeFcn. которое программируется по своему усмотрению. Для перехода к подфункции figure] ResizeFcn следует раскрыть всплывающее меню заготовки окна приложения и в пункте View Callbacks выбрать подпункт ResizeFcn. W4 Часть III Приложения с графическим интерфейсом Сам процесс программирования, приведенный в листинге 11.13. состоит из пяти этапов. 1. Запоминание единиц измерения размеров и положения всех необходимых объектов. 2, Приведение единиц измерения объектов к единой системе (в нашем случае удобно взять пикселы). 3. Получение текущего положения и размера окна приложения. 4. Задание положения и размеров интересующих нас элементов управления в окне приложения. 5. Возврат к старым единицам измерения. function figurel_ResizeFcn(hobject, eventdata, handles) i Запоминание единиц измерения графического окна % и панели Сетка с флагами u_fig = get(gcbo, ’Units'); u_uipanell = get(handles.uipanell, 'Units'); % Установка единиц измерения - пиксела % для графического окна и панели Сетка set(hObj ect, 1Units’, 'pixels') set(handles.uipanell, 'Units', 'pixels') % Определение положения и размеров графического окна p_fig = get(hobject, 'Position'}; % Установка положения и размеров рамки fc в окне приложения в пикселах х = p_fig(3) - 180; У = p_fig(4) - 90; width = 160; height = 70; set(handles.uipanell, 'Position', [x, y, width, height]) Ч Возврат к прежним единицам измерения % графического окна и панели Сетка set(hobject, 'Units', u_fig) set(handles.uipanell, 'Units', u_u ц:апе11) Глава 11. Конструирование интерфейса 605 Убедитесь, что изменение размеров спущенного приложения не влияет ни на размер рамки и флагов, ни на их положение. Самостоятельно запрограммируйте схожее поведение кнопок, переключателей и других объектов. Учтите, что в ряде случаев имеет смысл допускать автоматическое увеличение некоторых объектов, например, осей или области ввода текста. Взаимодействие приложения со средой MATLAB Приложение является графическим окном со своими объектами и при его создании важно решить, сможет ли пользователь менять вид приложения собственными командами, например, из командной строки. Наше приложение mygui содержит оси, однако попытка построить график из командной строки приведет к появлению нового графического окна со своими осями. Дело в том, что по умолчанию в раскрывающемся списке Command-lir,e accessibility диалогового окна GUI Options (см. рис. 11.12) выбрана опция Callback (GUI becomes ( urreni figure within Callbacks), соответствующая значению "callback' свойства Handlevisibility графического окна приложения. Графическое окно становится доступным только при выполнении какого-либо события Callback, в частности, на его оси может быть выведен график. Эта опция должна быть установлена, если предполагается графический вывод на оси окна приложения. Выбор Off (GUI never becomes Current Figure) приводит к тому, что указатель на него становится скрытым, т. е. его свойство Handievisibility принимает значение 'off и все выполняемые графические команды приведут к созданию новых окон. Проверьте это, установив данное свойство нашему приложению mygui. Нажатие на кнопку Построить приведет к появлению отдельного окна с графиком функции. Третья опци». On (GUI may become Current Figure from Command I ine) предназначена для тех приложений, которые допускают изменение свойств внешними командами: из командной строки или другого приложения. Выбор последней опции Other (Use settings from Property Inspector) дает возможность произвести нужные установки в инспекторе свойств Property Inspector или изменять их в ходе выполнения приложения. Каждая лз перечисленных опций соответствует открытому либо скрытому указателю на графическое окно, смысл которых обсуждался в разд. "Управление объектами, копирование, поиск, скрытые указатели" главы 9. Таблица этих соответствий приведена в справочной системе MATLAB, (см. разд. Creating Graphical User Interfaces: Laying Out GUIs and Setting Properties: Selecting GUI (iptions: Command-Line Accessibility). 606 Часть III. Приложения с графическим интерфейсом Первый запуск приложения с графическим интерфейсом вызывает появление на экране его окна. При повторном наборе имени приложения в командной строке возможны две ситуации; либо окно приложения становится активным (по умолчанию), либо запускается копия приложения. Для разрешения запуска нового окна приложения следует сбросить флаг GUI Allows Only One Instance to Run (Singleton). Флаг Using the System Background Colors отвечает за цветовое оформление приложения. Если он включен, то по умолчанию цвета элементов управления будут совпадать с определенными в операционной системе. При работе в Windows вы можете изменить цветовую схему оформления в диалоговом окне Display Properties на вкладке Appearance и проследить за изменением цветами элементов управления приложения при различных состояниях флага Using the System Background Colors. Впрочем, используя свойство графических объектов BackgroundColor, всегда можно задать любой цвет элементу управления. Способы программирования событий Работая над рассмотренным выше приложением mygui вы использовали самый простой, но эффективный способ, при котором для нового элемента управления автоматически генерируется заголовок подфункции обработки события Cal lback ИЛИ ResizeFcn И остается лишь запрограммировать подфункцию. Таким образом, само приложение хранится в двух файлах — с расширениями fig и гл. М-файл содержит основную функцию, которая запускается при наборе имени приложения в командной строке и подфункции обработки событий элементов управления. Информация о расположении и свойствах графических объектов, составляющих приложение, записана в файле с расширением fig. Такая структура приложения обеспечивается включенным переключателем Generate Fig-file and M-file в диалоговом окне GUI Options (см. рис. 11.12). Включенный переключатель обеспечивает доступ к трем флагам, включение первого из них Generate Callback Function Prototypes приводит к автоматической генерации заголовков подфункций обработки событий. Альтернативный способ конструирования приложения предполагает использование только одного файла с расширением fig, что достигается установкой переключателя Generate FIG-file only в диалоговом окне GUI Options. При этом свойства каждого из элементов управления, отвечающие за соответствующее событие (например, свойство callback для одноименного события), должны содержать строку с командой, файл-функцией или файл-программой, в которой запрограммированы соответствующие действия. Обратитесь к нашему приложению mygui, которое было создано с привлечением как fig, так и М-файла, и изучите в редакторе свойств значение свой Глава 11 Конструирование интерфейса 607 ства Callback, например, кнопки Построить. Этим значением является следующее обращение к файл-функции приложения: mygui(’ btnHot_Callback1, gcbc, [ ], guidata(gcbo)) Интерфейс файл-функции mygui предполагает обращение к ней с произвольным числом входных аргументов, например, как в данном случае (см разд. "Файл-функииы с переменным, числом аргументов " главы 8). В основной функции mygui работает блок операторов, приведенный в листинге 11.14, который при помощи встроенной функции str2func формирует обращение к соответствующей подфункции btnPiot Caiiback с подходящими входными аргументами. if nargin & isstr(varargin{l}) gui_State.gui_Callback = str2func(varargin{1}); end Кроме Callback и ResizeFcn имеется еще ряд событий, назначение которых мы обсудим в главе 13. Порядок обхода элементов управления клавишей <ТаЬ> В работающем приложении пользователь осуществляет переход к элементам управления при помощи мыши или клавиши <ТаЬ>. При использовании <ТаЬ> элементы управления обходятся в порядке их создания, что не всегда желательно. Для изменения порядка обхода служит редактор Tab Order Editor, который запускается выбором в меню Tools пункта Tab Order Editor. Появляется окно редактора, изображенное на рис. 11.13. Работа в нем достаточно проста — нужный элемент управления выделяется в окне редактора и при помощи кнопок Move Up, Move Down перемещается на нужное место в списке очередности. Для определения порядка обхода флагов, переключателей и других элементов управления, находящихся на одной панели, следует сделать ее текущей в среде GT4DE и обратиться к редактору Tab Order Editor. Его окно будет содержать только элементы данной панели, очередность их обхода так же устанавливается кнопками Move Up и Move Down. 608 Часть III. Приложения с графическим интерфейсом Tab Older Editor И uicontrol (btnPlot "Построить") И uicontrol (btnClear "Очистить") E3 uicontrol (pmColor "синий") uicontrol (sciWidth "Slider'') feI’ uicontrol (editFun) Lzl uicontrol (btnFromFile'W файла") Рис. 11.13. Редактор Tab Order Editor Следующая глава посвящена созданию диалоговых окон, конструированию меню приложения и контекстного меню. Глава 12 Диалоговые окна и меню приложения Данная глава освещает использование диалоговых окон и принципы создания собственных и контекстных меню при разработке приложения в MATLAB. Описано конструирование меню и программирование действий, выполняемых при выборе пункта меню пользователем. Изложение ведется на гримере приложения mygui, созданию которого посвящены главы 10 и 11. Виды диалоговых окон Удобный интерфейс приложения во многом определяется диалоговыми окнами. облегчающими работу с файлами, или предназначенными для предостережения пользователя о событиях, которые могут повлечь его действия MATLAB предоставляет разработчику приложения возможность использовать стандартные диалоговые окна. Окно подтверждения Некоторые действия приложения требуют повторного подтверждения пользователя. Например, пользователь приложения mygui может случайно нажать кнопку Очистить, предназначенную для очистки осей. Следует вывести диалоговое окно, в котором пользователь укажет, действительно ли требуется очистить оси. Диалоговое окно подтверждения создается функцией questdig, которая в самом простом случае имеет два входных параметра— строку с текстом внутри диалогового окна (или массив строк или ячеек для мноюстрочного текста) и строку с заголовком окна. Окно, создаваемое таким образом, имеет три кнопки— Yes, No и Cancel. Выбор пользователя возвращается в ею Часть III. Приложения с графическим интерфейсом строковом выходном аргументе функции questdig, его значение совпадаете надписью на кнопке- Усовершенствуйте обработку события Callback кнопки Очистить так, чтобы соответствующие операторы выполнялись только в том случае, если пользователь нажал кнопку Yes в появляющемся диалоювом окне с текстом Очист ить оси? и заголовком mygui. Используйте условный оператор if и функцию str стр для сравнения выходного аргумента questdig со строкой Yes’.(листинг 12.1). button = questdig('^чистить оси?’, 'mygui'); if strcmp (button, 'Yes') % здесь p а:мешаются все операторы, % обрабатывающие нажатие на кнопку Clear end Нажатие на Очистить приводит к появлению диалогового окна, изображенного на рис. 12.1. Выбор пользователя определяет дальнейшие действия приложения mygui. Рис. 12.1. Диалоговое окно подтверждения По умолчанию нажатие <Enter> приведет к выбору Yes. Функция questdJ g позволяет управлять видом диалогового окна. Строка с названием кнопки, переданная в третьем дополнительном аргументе, определяет кнопку окна, которая может быть нажата пользователем при помощи <Enter>. Например, вызов burton = questdig('Очистить оси?', 'mygui', 'No'); предполагает, что в диалоговом окне нажатие <Enter> эквивалентно выбору No. Гпава 12. Диалоговые окна и меню приложения 611 Число кнопок и надписи на них определяются создателем приложения, например. следующая форма обращения к функции questdig button = questdig('Очистить оси?’, 'mygui', 'Да', 'Нет', 'Нет') приводит к появлению диалогового окна с текстом Очистить оси?, заголовком mygui и двумя кнопками Да и Нет, причем нажатие <Enter> заменяет выбор Нет. Диалоговое окно mygui является модальным — оно не дает пользователю перейти к окну приложения, другим 1рафическим окнам или в командное окно MATLAB, пока оно открыто, т. е. не сделан выбор между Yes, No и Cancel. Любое графическое окно можно сделать модальным, для чего следует установить его свойство windowstyle в значение 'modal'. Значение 'normal' служит для перехода к обычному поведению окна. Кроме использования функции questdig, возможен второй способ создания модального диалогового окна и использования его в приложении. В окне GUIDE Quick Start (которое появляется при запуске среды GUIDE командой guide или при переходе в меню File среды GUIDE к пункту New) следует выбрать создание модального диалогового окна (ем. разд. "Среда GUIDE” главы IQ). После формирования модального окна в среде GUIDE оно сохраняется в файле, к примеру, в modaldlg.fig. При этом соответствующая ему файл-функция с подфункциями запишется в файл modaldlg.m. Когда требуется отобразить на экране модальное окно, в основном приложении вызывается эта файл-функция. Ее выходной аргумент содержит строку с надписью на нажатой кнопке, и эти значение применяется для выполнения соответствующего блока операторов. Заметьте, что надписи Yes и No на кнопках модального окна можно изменить на другие (например. Да и Нет), обращаясь К ИХ СВОЙСТВУ String. Этот способ подробно описан в справочной системе MATLAB на примере диалогового окна с подтверждением закрытия приложения (см. разд. Creating Graphical L’ser Interfaces: Programming GUIs: Example: Using the Modal Dialog to Confirm an Operation). При наличии определенного опыта программирования событий в заготовке для модального окна можно расположить дополнительные элементы управления, например, флаг Не показывать это окно в дальнейшем, и получить его состояние в выходных аргументах файл-функции модального окна. Окна открытия и сохранения файла 1кредача данных из файла в приложение сопряжена с заданием имени файла и пути к нему. Наиболее простой способ состоит в использовании диалогового окна открытия файла, которое создается функцией uigetfiie. Дан . Ч)сГЬ филожения с графическим интерфейсом ная функция приводит к появлению диалогового окна открытия файла и возвращает в первом выходном аргументе имя, а во втором — путь к файлу, выбранному пользователем. Выходные аргументы равны нулю, если пользователь отменил открытие, или при открытии файла произошла ошибка. Дополните приложение mygui кнопкой Из файла, нажатие на которую вызывает диалоговое окно открытия файла Пользователь выбирает файл, содержащий два столбика чисел одинаковой высоты — таблично заданную функцию. Данные считываются из файла в матрицу с двумя столбцами и визуализируются при помощи plot. Используйте strcat для сцепления строк с путем к файлу и его именем для образования полного имени файла. Полное имя задается в качестве входного аргумента функции load, которая производит считывание данных из файла в массив. Не забудьте сохранить указатель на линию в пиле Line структуры handles. Операторы простейшей обработки нажатия кнопки Из файла приведены в листинге 12 2. • «j...................... • о**.....w...... ........... Листинг 12.2. Программирование считывания данных из файла [fname, pname] = uigetfile; % получение имени и пути к файлу % Проверка, был ли открыт файл if fname ~= О % Образование полного имени файла fullname = strcat(pname, fname); % Считывание данных из файла в массив Mas = load(fullname); % Графическое отображение данных handles.Line = plot(Mas(:, 1), Mas(;, 2)); % Сохранение обновленной структуры guidata(gcbo, handles); end Создайте файл с данными в нужном формате, назовите его, например, my.dat. Запустите приложение mygui и нажмите на кнопку Из файла. Обратите внимание, что в диалоговом окне открытия файла в раскрывающемся списке Files of type установлен фильтр M-tilc »(*.m). Выберите АП files!*.*) и откройте my.dat. На осях строится график данных. Обработку нажатия кнопки Из файла следует производить так же, как и Построить с учетом взаимодействия с остальными элементами интерфейса. После появления графика должны быть доступны переключатели, флаги, раскрывающийся список и область ввода текста. Произведите требуемую доработку самостоятельно. Глава 12. / иагогорые окна и меню приложения 613 Приложение, которое предназначено для работы с файлами определенного типа, например с расширением dat, проще в использовании, если в диалоговом окне открытия файла автоматически устанавливается определенный фильтр. Функция uigetfile предусматривает задание стандартного расширения во входном аргументе, например, вызов [ fname, pname] - uigetfile (’ *.dat1) ; соответствует диалоговому окну с фильтром для файлов с расширением dat. Указание приводит к отображению файлов всех типов в диалоговом окне открытия файла. Функция uiputfiie предназначена для создания диалогового окна сохранения файла. Входные и выходные аргументы uiputfiie имеют то же назначение. что у функции uigetfile. В качестве входною аргумента uiputfiie можно указать не только фильтр, но и полное имя файла, предла!аемого для записи. Команды save и load для работы с файлами, содержащими числа, описаны в разд. "Считывание и запись данных" главы 2. Ьолее подробно считывание и запись текста и чисел разобраны в разд. "Текстовые файлы” главы 8. Функции uiputfiie и uigetfile позволяют задать заголовок диалоговых окон во втором дополнительном входном аргументе — строке. Окно с сообщением об ошибке Некоторые действия пользователе, в частности, открытие файла с данными в неизвестном формате, могут привести к ошибке в работе приложения. Такие исключительные ситуации следует предусматривать при написании алгоритма приложения и сопровождать их сообщением об ошибке, которое выводится в отдельном окне. Функция errordig предназначена для создания диалогового окна с сообщением об ошибке. Входными аргументами errordig являются строки с текстом и заголовком окна. Дополните построение графика данных, считанных из файла (см. листинг 12 2), проверкой на размерность и тип содержимого массива Mas при помощи функций size, ndims и isnumeric, и выведите сообщение в случае несоответствующего формата данных. Заключите считывание и визуализацию данных в блок try...catch для предотвращения ошибки при обращении к load (листинг 12.3). г4................................... и Листинг 12.3. Обработка исключит эльных ситуаций с сообщением об ошчбке try % Считывание данных из файла в массив Mas = load(fullname); 614 Час ть III Приложения с графическим интерфейсом % Определение размеров массива SMas = size(Mas); % Проверка массива данных if (SMas(2) -= 2) I (ndims(Mas) ~= 2) | -isnumeric(Mas) errordlg('Неизвестный формат файла с данными', 'Ошибка!') else % Графически е отображение данных handles.Line = plot(Mas(:,1), Mas(:,2)); % Сохранение обновленной структуры guidata(gcbo, handles); end catch % Произошла ошибка при выполнении load errordig('Неизвестный формат файла с данными', 'Ошибка!') end Меню графического окна Приложение MATLAB может использовать стандартное меню графического окна. Среда GUIDE позволяет программисту дополнять стандартное меню или создать собственные меню. Свойство мепиваг окна приложения (объекта figure) отвечает за наличие стандартных меню File, Edit, Tools, Window и Help в работающем приложении. Значение figure данного свойства соответствует отображению стандартных меню, а попе приводит к приложению без строки с меню. Вне зависимости от значения свойства Мепиваг разработчик приложения имеет возможность размещать собственные меню, но в случае значения figure они добавляются к стандартным меню графического окна. Размещение и программирование меню производится при помощи редактора меню. Меню является графическим объектом Uimenu — потомком графического окна. Редактор меню Продолжите работу над приложением mygui, начатую при чтении глав К) u II. Перейдите в режим редактирования приложения в среде GUIDE. Принцип конструирования меню проще всего понять, создавая новое меню— убедитесь, что свойство мепиваг графического окна установлено в попе. Запустите редактор меню из панели управления (см рис. 10.5) или выбрав в меню Tools пункт Menu Editor. Появляется окно редактора Menu Editor, изображенное на рис. 12.2. Гпава 12. Диалоговые окна и меню приложения 615 добавление создание управление удаление Рис. 12.2. Редактор меню Menu Editor Окно редактора меню содержит две вкладки: Menu Ваг, предназначенную для создания строки меню приложения, и Context Menus для контекстного меню. Сейчас нам понадобится вкладка Menu Ваг, ее область навигатора и панель Propei ties свойств элементов меню (справа от вкладки) пока пустые. При выбранной вкладке Menu Ваг создайте новое меню, нажав кнопку New Menu на панели инструментов редактора меню, в навигаторе появилась строка I Entitled 1, сделайте ее текущей щелчком мыши. Обратите внимание (рис. 12.3), что в области свойств появились элементы управления для настройки меню. Строка Label служит для задания надписи меню или пункта меню, a Tag для определения имени (тэга) созданного объекта Uimenu, об использовании остальных элементов панели Properties сказано ниже. Введите слово "График" в строку Label (без кавычек) и задайте имя mnGraph в строке Tag. Запустите приложение mygui и убедитесь в наличии меню График. Выбор меню График в работающем приложении не приводит к раскрытию меню, поскольку необходимо еще создать пункты меню. Закройте работающее приложение. В режиме редактирования сделайте текущей строку График в навигаторе редактора меню и добавьте пункт, нажав кнопку New Menu Item (см. рис. 12.2). Установите надпись пункта Построить и дайте ему имя mnGraphPlot. Добавьте еще один пункт меню, сделав предварительно текущей строку График в навигаторе. Аналогичным образом задайте надпись Очистить и имя 616 Часть III. Приложения с графическим интерфейсом mnGraphCiear. Навигатор меню должен содержать структуру, изображенную на рис. 12.4. Меню График имеет первый уровень, а пункты Построить Очистить — второй. Рис. 12.3. Задание свойств меню в редакторе Е ^График I- *=• Построить 1=1 Очистить Рис. 12 4. Иерархия элементов меню Гпава 12. Диалоговые окна и меню приложения 617 Запустите приложение mygui, выбор меню рафик приводит к раскрытию меню. Разумеется, при обращении к пунктам Построить и Очистить ничею не происходит, следует запрограммировать события Callback пунктов меню. Событие Callback самого меню I рафик не требует обработки, т. к. происходит автоматическое раскрытие меню. Разумеется, если выбор меню должен повлечь некоторые действия приложения, то их необходимо запрограммировать в обработке события Callback самого меню. Программирование пунктов меню Выбор элемента меню в навигаторе редактора меню приводит к отображению его свойств на панели UIMenu Properties. Строка ввода Callback предназначена для вызова подфункции М-файла приложения, содержащего обработку событий элементов интерфейса. Для перехода к соответствующей подфункции в редакторе М-файлов следует нажать кнопку View. Сделайте активной строку с пунктом Построить меню График и обратитесь к подфункции mnGraphPlot callback обработки его события Callback. Заметьте, что выбор пункта Построито должен приводить к тому же самому результату, что и нажатие одноименной кнопки. Поэтому в подфункции mnGraphPlotcallback достаточно ВЫЗВЗТЬ подфункцию btnPlot_Callback обработки события Callback кнопки Построить. Аналогичным образом обстоит дело и при программировании пункта Очистить. При вызове функций btnPlot Caiiback и btndear Caiiback следует учесть, что их первый входной аргумент является указателем на тот объект, событие cal iback которого будет выполняться (листинг 12.4). ....о .........’.............. " " ’ ’ - Листинг 12.4. Программирование события Callback пунктов меню function mnGraphPlot_Callback(hObject, eventdata, handles) btnPlot_Callback(handles.btnPiot, eventdata, handles) function mnGraphClear_Callback(hObject, eventdata, handles) btnClear_Callback(handles.btnClear, eventdata, handles) Запустите приложение mygui, выбор пунктов Построить и Очистить меню График приводит к отображению графика функции и, соответственно, очистке осей. Внесите дополнения в подфункции btnPlot_CalIback и btndear Caiiback для обеспечения согласованной работы пунктов меню и кнопок. Именно после выбора пользователем пункта Построить он должен стать недоступным вместе с одноименной кнопкой, а пункт и кнопка Очистить— доступными, и наоборот. Используйте свойство Enable пунктов меню, указатели на них содержатся в структуре handles (листинг 12.5). 618 Часть III Приложения с Iрафииеским интерфейсом Криме того, в начале работы приложения пункт Очистить должен быть недоступным. Этого можно добиться сбросом флага Enable this item в окне редактора меню, что эквивалентно установке свойства Enable пункта меню в значение off. Примечание Три флага Separator above this item, Check mark this item и Enable this item позволяют установить значения соответствующим свойствам separator, checked и Enable пункта меню, т. е. объекта Uimenu (про назначение первых двух свойств сказано ниже). Остальные свойства объекта Uimenu доступны в инспекторе свойств, для вызова которого следует воспользоваться кнопкой More Options. .. Й.. ............ й... .............................. « Листинг 12.5. Согласованное программирование пунктов меню и кнопок function btnPlot_Callback(hObject, eve,.tdata, handles) set(handles.mnGraphPlot, ’Enable', 'off') set(handles.mnGraphClear, 'Enable', 'on') function btnClear_Callback(hObject, eventdata, handlss) button = questdig('Очистить оси?', 'mygui'); if strcmp(button, 'Yes') set(handies.mnGraphPlot, 'Enable', 'on') set(handles.mnGraphClear, 'Enable', 'off') end Запустите приложение mygui. Теперь поведение кнопок Построить и Очистить согласовано с поведением одноименных пунктов меню График. В качест вс упражнения вы можете добавить пункт Из файла в меню График приложения mygui, предназначенный для графического отображения таблицы данных, л связать его с одноименной кнопкой. Оформление меню Быстрый доступ к меню или его пунктам производится при помощи заданного сочетания клавиш. Для меню или пункта, выделенного в редакторе, желаемое сочетание определяется в раскрывающемся списке 4cceierator; Ctrl + Гпава 12. Диалоговые окна и меню приложения 619 Как следует из названия списка, вы можете назначать комбинации <Ctri> с любой буквенной клавишей Некоторые пункты меню могут находиться в одном из положений — включено или выключено, о чем свидетельствует флаг рядом с надписью пункта. Например, при создании меню для управления сеткой на графике с двумя пунктами, каждый из которых наносит или убирает сетку по выбранной координате, следует снабдить пункты меню флагами. Кроме того, между пунктами меню можно помещать разделительную линию для удобства использования меню с большим числом пунктов. Пункты меню с флагами состояния При помощи кнопок New menu и New Menu Item редактора меню добавьте в приложение mygui меню Сетка с тэгом mnGrid, содержащее пункты Сетка по х и Сетка по у с тэгами mnGridX и mnGridY соответс гвенно. Навигатор должен иметь вид, представленный на рис. 12.5. Й График - к- Построить *— М Очистить В- J] Сетка М Сетка по х Сетка по у Рис. 12.5. Иерархия элементов меню I рафик и Сетка Теперь следует запрограммировать события Callback пунктов меню так, чтобы, например, при выборе пункта Сетка по х включался флаг и наносились линии сетки, а при повторном обращении к данному пункту убиралась сетка и выключался флаг. Свойство пункта меню Checked отвечает за наличие флага рядом с названием пункта меню, значение on приводит к включению флага, a off — к выключению. Алгоритм достаточно простой, следует проверить текущее состояние флага, которое определяет предыдущий выбор пользователя, перевести флаг в противоположное положение и нанести или скрыть сетку. Перейдите к заготовкам подфункций, обрабатывающих события callback пунктов Сетка по х и Сетка по у меню Сетка, и занесите в них необходимые операторы (листинг 12.6). 620 Часть III. Приложения с графическим интерфейсом Листинг 12.6. Программирование пунктов меню с флагами function mnGridX_Callback(hobject, eventdata, handles) if strcmp(get(hobject, 'Checked'), 'on') % Флаг пункта Сетка по у был установлен, % теперь следует выключить его и убрать сетку set(hobject, 'Checked', 'off') % выключение флага set(handles.axMain, 'XGrid', 'off') % скрытие сетки else % Флаг пункта Сетка по у не был установлен, % теперь следует включить его и нанести сетку set(hobject, 'checked', 'on') % включение флага set<handles.axMain,'XGrid', 'on') % нанесение сетки end %-------------------------------------------------------------------- function mnGridY_Callback(hobject, eventdata, handles) if strcmp(get(hobject, 'Checked'), 'on') % Флаг пункта Сетка no x был установлен, % теперь следует выключить его и убрать сетку set(hobject, 'Checked', 'off') % выключение флага set(handles.axMain, 'YGrid', 'off') % скрытие сетки else % Флаг пункта Сетка по х не был установлен, % теперь следует включить его и нанести сетку set(hobject, 'Checked', 'on') % включение флага set(handles.axMain, 'YGrid', 'on') % нанесение сетки end Если некоторые пункты меню должны быть включены сразу после запуска приложения, то следует установить для них флаг Item is checked в редакторе меню MATLAB. Добавьте самостоятельно операторы, которые обеспечивают согласованную работу пунктов меню Сетка и одноименных флагов окна приложения. Разделительные линии Разделительные линии между пунктами меню применяются для выделения групп пунктов, объединенных по смыслу (например, меню File рабочей среды MATLAB). Разделительную полосу можно добавить как при создании Гпава 12. Диалоговые окна и меню приложения 621 пункта меню, так и между существующими пунктами меню. Редактор меню позволяет определить положение линии при помогли флага Separator above this item. Линия размещается над текущим пунктом меню. Разделительная линия также добавляется при установке свойству Separator пункта меню (т. е. объекта Uimenu) значения 'on' в работающем приложении. Упорядочение меню Удобная организация меню очень часто выявляется только в ходе работы над приложением. Возникает необходимость в перегруппировке пунктов меню и изменении их уровня. Предположим, что требуется включить в меню График приложения mygui пункт Сетка вместе с подпунктами Сетка по х и Сетка по у, а пункт Очистить выделить в отдельное меню. Процесс переработки меню можно разбить на три этапа. 1. В навигаторе меню выделите пункт Очистить и при помощи кнопки Move Selected item Down сдвиньте его в самый низ. 2. При выделенном пункте Очистить нажмите кнопку Move Selected item Backward, это приводит к переводу пункта на один уровень вверх в иерархии и пункт становится отдельным меню. 3. Поскольку меню Сетка расположено в навигаторе сразу за меню График, то для того, чтобы Сетка стало пунктом меню График, достаточно перевести меню Сетка на один уровень вниз в иерархии. Для этого выделите меню Сетка и воспользуйтесь кнопкой Move Selected item Forward. В результате меню и пункты расположены в нужной иерархии, что отражено в навигаторе меню (рис. 12.6). & График КН построить В- *=• Сетка - Сетка по х *— Сетка по у *— Й Очистить Рис. 12.6. Изменение структуры меню Вид меню в работающем приложении mygui приведен на рис. 12.7. 622 Часть III. Приложения с графическим интерфейсом Рис. 12.7. Строка меню приложения после изменения структуры меню Итак, назначение кнопок панели инструментов редактора меню следующее. П Move Selected item Backward. — перевод пункта на один уровень вверх в иерархии. Для меню эта кнопка недоступна, поскольку они расположены на самом верхнем уровне. П Move Selected item Forward.— перевод пункта на один уровень вниз в иерархии. О Move Selected item Down — сдвиг меню или пункта меню вниз с сохранением уровня. Сдвиг меню вниз означает, что в строке меню работающего приложения оно переместится вправо. Сдвиг пункта меню приводит к перемещению в пределах текущего меню. □ Move Selected item Up— сдвиг меню или пункта меню вверх с сохранением уровня. Сдвиг меню вверх означает, что в строке меню работающего приложения оно переместится влево. Сдвиг пункта меню приводит к перемещению в пределах текущего меню. Аналогичные операции могут быть осуществлены в работающем приложении. Поскольку меню (объект Uimenu) является потомком графического окна, пункты меню (также объекты Uimenu) есть потомки меню, а подпункты— потомки пунктов, то для реорганизации меню следует найти указатели на нужные объекты и воспользоваться их свойствами Parent И Children (поиск объектов с заданными свойствами описан в разд. "Управление объектами, копирование, поиск, скрытые указатели" гчавы 9). Контекстное меню объектов Объекты, в том числе и созданные в ходе работы приложения, могут иметь собственное контекстное меню, которое активизируется щелчком правой кнопкой мыши. Контекстое меню позволяет получить быстрый доступ к часто используемым свойствам объекта. Конструирование контекстного меню состоит в создании его в редакторе меню, определении событий Гпава 12. Диалоговые окна и меню приложения 623 callback пунктов меню и последующем связывании меню с объектом. Данный раздел освещает вопрос создания контекстного меню выбора цвета линии графика на примере приложения mygui. Создание контекстного меню в редакторе Перейдите к вкладке Context Menus в редакторе меню и нажмите кнопку создания контекстного меню (рис. 12.2), в навигаторе меню появляется строка для меню. Задайте ему тэг cmLine. Обратите внимание, что на панели свойств нет строки ввода Label, т. к. раскрывающееся меню не должно иметь надписи. Создайте три пункта меню при помощи кнопки New Menu Item, той же, что применяется для добавления пунктов меню окна приложения. Определите для них надписи синий, красный, зеленый и имена cmLineBlue, cmLineRed, cmLineGreen соответственно. В результате навигатор меню должен содержать структуру, приведенную на рис. 12.8. B-ij] cmLine ~ Н=и синий — М красный L Н зеленый Рис. 12.8. Отображение контекстного меню в навигаторе объектов Флаги Separator above this item, Check this item и Enable this item имеют тот же самый смысл, что и для элементов меню приложения, конструирование которою мы обсудили выше. В работающем приложении щелчок правой кнопкой мыши по линии графика не приводит к отображению контекстного меню. Сейчас контекстное меню cmLine присутствует в приложении как объект, но другой объект — линия, создаваемая при нажатии, например, на кнопку Построить, "не знает" о том, что у нее есть собственное контекстное меню. Следующий этап состоит В связывании ЛИНИИ С СОЗДаННЫМ меню cmLine. 624 Часть III. Приложения с графическим интерфейсом Связывание контекстного меню с объектом Графические объекты MATLAB имеют свойство UiContextMenu, значением которого может являться указатель на имеющееся контекстное меню. Для того чтобы созданный объект, т. е. линия графика, обладал контекстным меню, следует установить его свойство UiContextMenu в значение указателя на меню cmLine сразу после создания линии. Этот указатель записан в поле cmLine структуры handles. В нашем приложении линия графика рисуется в подфункциях обработки события Callback кнопок Построить и Из файла. Указатель на линию записывается в поле Line структуры handies, после чего обновленная структура сохраняется при помощи функции guidata (см. листинги 11.4 и 12.2). Итак, после этих строк в двух подфункциях btnPlot_Callback И btnFromFile_CalIback следует обратиться К свойству uiContextMenu созданного объекта — линии: set(handles.Line, 'UiContextMenu', handles.cmLine) Запустите приложение mygui, постройте линию любым из доступных способов и убедитесь, что щелчок правой кнопкой мыши по линии приводит к появлению контекстного меню с пунктами синий, красный, зеленый. Выбор пунктов не обеспечивает изменение цвета линии— очевидно, следует запрограммировать событие Callback каждого пункта. Программирование контекстного меню Обработка событий Callback пунктов контекстного меню производится аналогично программированию меню приложения. В редакторе меню перейдите последовательно к подфункциям обработки событий Callback пунктов контекстного меню, и в каждой из них установите свойство Color линии в соответствующее значение (листинг 12.7). Запрограммированное и связанное с линией контекстное меню разрешает быстрый доступ пользователя к цвету линии. i Листинг 12.7. Программирование событий Callback пунктов контекстного = меню function cmLineBlue_Callback(hObject, eventdata, handles) % Задание синего цвета линии set(handles.Line, 'Color', 'b') %---------------------------------------------------------------------- function cmLineRed._CalIback(hObject, eventdata, handles) % Задание красного цвета линии Гпава 12. Диалоговые окна и меню приложения Ь25 set(handles.Line, 'Color', 'г') %----------------------------------------------------------------------- function cmLineGreen Callback(hObject, eventdata, handles) % Задание зеленого цвета линии set.handles.Line, 'Color', 'g') Пункты контекстного меню являются объектами Uimenu. следовательно, к ним применимы подходы для пунктов меню, рассмотренные нами выше В частности, каждый пункт контекстного меню может быть снабжен флагом, который включается при первом выборе пункта и сбрасывается при последующем. Пункты меню могут быть доступны или нет и разделены линиями. В нашем приложении mygui осталось обеспечить согласованную работу контекстного меню со списком Цвет липни с именем pmColor. Выбор цвета из меню должен приводить не только к изменению цвета линии, но и к появлению соответствующей строки в раскрывающемся списке. В каждую подфункцию обработки события Callback пункта контекстного меню следует добавить операторы, устанавливающие нужное значение (1, 2 или 3) свойства value раскрывающегося списка (листинг 12.8). Листи нг 12.8 Согласование работы контекстного меню и списка для выбора function cniLineBlue_Callback(hObject, eventdata, handles) % Задание синего цвета линии set(handles.Line, 'Color', ' b') % Установка строки "синий” в раскрывающемся списке set(handles.pmColor, 'Value', 1) %----------------------------------------------------------------------- function crhLineRed_Callback(hObject, eventdata, handles) % Задание кра:ного цвета линии set(handles.Line, 'Color', 'r') % Установка строки "красный" в раскрывающемся списке set(handles.pmColor, 'Value', 2) %----------------------------------------------------------------------- function cmLineGreen—Callback(hObject, eventdata, handles) % Задание зеленого цвета линии set/handles.Line, 'Color', 'g') %, Установка строки "зеленый" в раскрывающемся списке set(handles.pmColor, 'Value', 3) 626 Часть III. Приложения с графическим интерфейсом Совершенно аналогично контекстное меню создается и для других элементов приложения, например, осей или 1рафического окна. В качестве упражнения снабдите оси контекстным меню, которое позволяет добавить или удалить линии сетки и стерег ь линию графика функции. В лой и предыдущих двух главах мы сосредоточились в основном на назначении события Callback и его программировании для элементов управления различных типов. Исключение составляет только разд. "Изменение размеров приложения" главы 11, в котором обсуждалось согласованное изменение размеров и положения элементов управления при уменьшении или увеличении окна приложения. Для этого нам пришлось обратиться к событию ResizeFcn графического окна В главе 13 мы рассмотрим еще ряд событий, которые оказываются полезными при написании собственных приложений с графическим интерфейсом. Глава 13 Программирование событий В предыдущих главах мы рассмотрели программирование события callback элементов интерфейса, которое возникает, например, при нажатии на кнопку или установке флага. Кроме того, мы обсудили программирование события ResizeFcn графического окна, происходящего при изменении размеров приложения. В этой главе мы опишем события графических объектов и продемонстрируем способы программирования обработки некоторых из них на простых примерах, включая создание приложения с графическим интерфейсом без среды GUIDE. Мы также уделим внимание свойствам графических объектов, полезным при написании собственных приложений, например, задание формы курсора в пределах окна или получение текущих координат в графическом окне или осях. События графических объектов Три события могут быть связаны со всеми графическими объектами: □ ButtonDownFcn — возникает при щелчке левой кнопкой мыши по объекту или не далее чем в пяти пикселах от объекта; □ CreateFcn — возникает при создании объекта; □ DeleteFcn —возникает при удалении объекта. Событию ButtonDownFcn мы уделим достаточное внимание ниже при создании приложения для рисования многоугольных областей при помощи мыши. Событие CreateFcn полезно для инициализации некоторых данных или предварительной настройки создаваемого объекта. Например, если при запуске приложение должно считать данные из файла или занести значения в некоторые переменные, то эти действия следует запрограммировать в файл-функции обработки события CreateFcn графического окна приложения. 21 зыс 130 628 Часть III. Приложения с графическим интерфейсом Перед удалением объекта часто целесообразно произвести некоторые действия, например, вывести модальное диалоговое окно с подтверждением об удалении или сохранить данные (создание модальных диалоговых окон описано в главе 12). Графическое окно поддерживает еще ряд событий кроме трех вышеперечисленных и ResizeFcn, обработка которого рассмотрена в главе 11: □ cioseRequestFcn — возникает перед закрытием окна; □ KeyPressFcn — возникает при нажатии пользователем клавиши; □ WindowButtonDownFcn— возникает при нажатии пользователем кнопки мыши; □ wlndowButtonMotionFcn — возникает при движении мышью в пределах окна; П windowButtonUpFcn— возникает, когда пользователь отпускает кнопку мыши. Следует иметь в виду, что событие KeyPressFcn возникает только в том случае, если ни один из элементов управления (например, флаг или переключатель) не выделен. Аналогично, WindowButtonDownFcn появляется только, если при нажатии кнопки мыши курсор находится в свободной области окна, незанятой другими элементами управления. При обработке этих событий оказываются необходимыми следующие свойства графического окна: □ currentcharacter — содержит символ последней нажатой клавиши: □ SeiectionType— содержит информацию о типе щелчка мышью (двойной, правой или левой кнопкой); □ Currentpoint — координаты курсора мыши в момент последнего нажатия кнопки мыши в пределах окна. В качестве единиц измерения берутся установленные в свойстве unit графического окна. В качестве примера программирования ряда событий графического окна рассмотрим создание приложения, предназначенного для вывода ASCII-кода символов при нажатии на клавиши. Приложение для получения ASCII-кода символа Иаша цель — написать приложение, которое при нажатии на клавишу выводит в графическое окно символ и его ASCII-код, например, нажагие на <t> должно приводить к появлению строки "I - 116". В среде GUIDE соз Глава 13. Программирование событий 629 дайте окно приложения с размещенным в ней объектом Static Text, который мы будем использовать для вывода информации. В инспекторе свойств Property Inspector присвойте текстовому объекту тэ1 txtwin и удалите содержимое СВОЙСТВа String. Создайте теперь заготовку для подфункции обработки события KeyPressFcn графического окна, например, при помощи его всплывающего меню. Как уже было сказано, это событие возникает при нажатии пользователем одной из клавиш. Подфункция figureiKeyPressFcn должна считывать значение свойства Currentcharacter графического окна, преобразовывать его в ASCII-код, формировать строку с символом, знаком равно и кодом и выводит ь ее. Для получения ASCII-кода служит функция double, котора^гбоз-' вращает число. Поэтому придется применить еще функцию num2str перед заполнением строки с результатом (листинг 13.1). j................-......................;........................................................-. : j Листинг 13.1. Обработка события KeyPressFcn графического окна *............. .*....... *,<.,а . .....а 11.Ч.. ... . . ... .... *. ..... ... „ нН*. •*....” .1.... .- I.* function figurel_KeyPressFcn(hObject, eventdata, handles) % Считывание текущего символа ch - get(hObject, ’Currentcharacter'); % Получение ASCII-кода текущего символа code = double(ch); % Преобразование числового значения в строковое strcode = nuiri2str (code) ; % Считывание текущей текстовой информации объекта Static Text str=get(handles.txtWin,'String'); % Добавление нового символа и его кода str = [str, ' ', ch,'=', strcode],- % Вывод обновленной и:1фср:1ации set(handles.txtWin, 'String1, str); Сохраните приложение, например, с именем asciicode, и запустите его — при нажатии на клавишу выводится ASCII-код соответствующего символа. Заметьте, что нажатие на <Ctrl>, <Alt> или <Shift> приводит к выводу только знака равно, а сочетание клавиш <Ctrl> или <Alt> с символьной обрабатывается неверно. Этот недостаток приложения вы сможете устранить при чтении следующего раздела, в котором рассматриваются способы вызова подфункций обработки событий. 630 Часть HI Приложения с графическим интерфейсом Как вызываются подфункции обработки событий При работе в среде GUIDE у нас не возникало такого вопроса. Выбор пункта меню с нужным событием приводил к автоматическому созданию заголовка подфункции, в которой требовалось реализовать желаемый алгоритм. Обсудим теперь способы обработки событий более подробно. Вернитесь к приложению asciicode и в инспекторе свойств Property Inspector посмотрите значение свойства KeyPressFcn графического окна. Оно является строкой: adciicode('figurel_KeyPressFcn', gcbf, [ ], guidata(gcbf)) обеспечивающей вызов основной функции asciicode приложения от нескольких аргументов. Основная функция имеет заголовок function varargout = asciicode(varargin) и может быть вызвана с произвольным числом входных и выходных аргументов (интерфейс таких функций описан в разд. "Файл-функции с переменным числом аргументов"главы 8). Функция asciicode определяет, что она была вызвана с входными аргументами и при помощи str2fun формирует обращение к подфункции f igurel KeyPressFcn от трех входных аргументов: □ hobject принимает значение gcbf, т. е. указателя на графическое окно, событие которого в данный момент времени выполняется; □ eventdata становится равным пустому массиву; О в handles передается структура данных приложения, которую возвращает функция guidata. Допустим альтернативный способ вызова подфункции обработки события. Значением свойства KeyPressFcn графического окна может быть указатель па требуемую функцию или имя М-файла. По умолчанию предполагается, что функция обработки события вызывается с двумя обязательными входными аргументами: первый аргумент есть указатель на объект, событие которого выполняется, а второй аргумент содержит информацию о событии. В случае события KeyPressFcn второй аргумент является структурой с полями Character, Modifier И Key. СМЫСЛ ЭТИХ ПОЛеЙ Следующий: □ Character — отображаемый на экране символ; О Modifier — массив ячеек, который может содержать одну или несколько строк ('control', 'shift' или 'alt') если дополнительно была нажата одна или несколько функциональных клавиш; Гпава 13. Программирование событий 631 П кеу — символ, если была нажата символьная или цифровая клавиша, или строка с названием клавиши, например: 'subtract* для <->, ’iruitipiy' для <*>. Учет содержимого этой структуры позволит расширить возможности нашего приложения asciicode. Однако в нем для обработки события KeyPressFcn предусмотрен ВЫЗОВ функции figurel KeyPressFcn С тремя входными аргументами, причем третий (структура handles) используется для получения указателя на текстовый объект. Поэтому мы не будем изменять ее интерфейс, а при указании значения свойству KeyPressFcn графического окна применим следующий способ вызова по ссылке — сформируем массив ячеек {&figurel_KeyPressFcn, handles} Его первая ячейка содержит указатель на подфункцию обработки события, а вторая — значение дополнительного аргумента. Этот массив ячеек мы зададим в качестве значения свойства KeyPressFcn в подфункции asciicode_OpeningFcn (листинг 13.2), которая автоматически выполняется после запуска приложения и перед выводом его окна на экран. Заметьте, что в инспекторе свойств Property Inspector значение для KeyPressFcn уже недействительно, т. к. оно изменится после запуска приложения. function asciicode. OpeningFcn(hObject, eventdata, handles, varargin) handles.output = hObject; % Следующую строку мы добавили для установки свойства KeyPressFcn в % значение массива структур с указателем на подфункцию обработки события % KeyPressFcn и дополнительным аргументом со струн- урой данных приложения set(handles.figurel, 'KeyPressFcn1, {@figurel_KeyPressFcn, handles}) guidata(hobject, handles); Теперь входной аргумент eventdata подфункции figurelKeyPressFcn является структурой С полями Character, Modifier И Key, СМЫСЛ которых мы только что разобрали. Пока можно вывести их значения в командное окно для проверки работы приложения, а потом учесть их в алгоритме обработки нажатия клавиши. Для этого просто добавьте в подфункцию figurel_KeyPressFcn присваивание значений полей некоторым переменным, например, character, modifier И key (ЛИСТИНГ 13.3). 632 Часть /// Приложения с графическим интерфейсом ..——;........"4CS ЧГ.......................................'""ЖМ№ Листинг 13 3. Вывод ДАННЫХ стоуктуры с ventdata в подфункции figurel_KeyPreBsFcn i ch-eventdata.Character mdf=evei.tdata .Modifier key=eventdata.Key Приложение asciicode работает так же, как и со стандартным способом вызова подфункции обработки события KeyPressFcn, однако теперь входной аргумент eventdata подфункции figurel_KeyPressFcn содержит подробную информацию о событии. Используйте ее для устранения следующего недостатка приложения — при нажатии на клавиши <Ctrl>. <Shift> и <Alt> без символьных клавиш выводи гься ничего не должно, а при сочетании одной или нескольких из них с символьной клавишей об этом выдается сообщение, например: "shift+ctrl+h=8". Очевидно, что если символьная клавиша не была нажата, то требуется выйти из подфункции. Иначе следует проверить, была ли нажата одна или несколько функциональных клавиш <Ctrl>, <Shift> и <Alt>, т. е. выяснить длину массива ячеек mdf, извлечь из него строки с названиями нажатых клавиш и сформировать текстовый результат. Один из возможных вариантов реализации этого алгоритма приведен в листинге 13.4. J................ .......... ... . : Листинг 13.4. Обработка нажатия на клавишу с учетом структуры ev*snt function figurel_KeyPressFcn(hobject, eventdata, handles, % Считываем отображаемый на экране символ ch = eventdata.Character; % Считываем массив ячеек, содержащий строки с нажатыми % функциональными клавишами mdf = even tdata. Modifier ; % Считываем символ клавиши key = eventdata.Key; % Проверка, Сила ли нажата символьная клавиша if length(ch) == О % Символьная клавиша нажата не была, выходим из подфункции return end % Получение ASCII-кода символа code = double(ch); Глава 13. Программирование событий 633 % Преобразование числового значения в строку strcode = num2str(code); % Считывание содержимого текстового объекта Static Text str - get(handles.txtWin, 'String'); % Проверка, была ли нажата функциональная клавиша i£ isempty(mdf) % Была нажата только символьная клавиша % Формируем строку для вывода str = [str, 1 ', ch, '=', strcode]; % Выводим результат set(handles,txtWin, 1 String', s tr); % Завершаем работу подфункции return end % Была нажата одна или несколько функциональных клавиш switch length (mdf) case 1 % Была нажата одна функциональная клавиша, считываем ее название fkey = md£ {1); % Формируем строку для вывода str = [str, ' ', fkey, ' + ', key, ' = ', strcode]; case 2 % Были нажаты две функциональные клавиши, считываем их названия fkeyl = mdf(1]; fkey2 = mdf(2]; % Формируем строку для вывода str = [str, ' ', fkeyl, ' + ', fkey2, ' + key, ' = strcode]; case 3 % Были нажаты три функциональные клавиши, считываем их названия fkeyl = mdftl); £key 2 - mdf(2); f кеуЗ - mdf{3); $ Формируем строку для вывода str = [str, ’ ', fkeyl, '+', £кеу2, ' + ', £кеуЗ, 634 Часть III. Приложения с графическим интерфейсом key, 1=1, strcode]; end % Выводим результат set(handles.txtWin, 'String', str); Следующий раздел посвящен примеру приложения, использующему событие ButtonDownFcn, которое происходит при щелчке мышью по объекту. Событие ButtonDownFcn Оси служат для вывода графической информации на экран, однако возможно реализовать и обратную задачу— позволить пользователю задавать данные щелчком мыши по области осей, сразу же отображать их на экране и заносить в массивы. В качестве примера напишем приложение для рисования многоугольных областей при помощи мыши, в котором щелчок мыши по осям приводит к появлению новой вершины (маркера) и соединению ее с предыдущей отрезком. Событие ButtonDownFcn осей Для того чтобы понять способ обработки события ButtonDownFcn, начните с создания более простого приложения, в котором щелчок мышью по осям приводит к появлению маркера. В среде GUIDE на заготовке окна приложения разместите оси с именем axes. Заданное по умолчанию автоматическое масштабирование осей в нашем примере нежелательно, т. к. при появлении первого маркера пределы осей изменятся. Следовательно, имеет смысл установить свойства осей XLimMode И YLimMode В значение manual. Каждый щелчок мышло должен добавлять маркер на оси. поэтому свойство осей NextPlot должно иметь значение 'add'. Проделайте эти действия в инспекторе свойств Property Inspector. Перейдите к подфункции axes_ButtonDownFcn обработки события ButtonDownFcn осей. В ней требуется определить координаты точки, в которой был произведен щелчок мышью, и вывести в нее маркер. Свойство осей currentpoint содержит матрицу размера два на три с информацией о положении указателя мыши в момент щелчка в системе координат осей. Предполагается, что оси трехмерны и точка находится на линии, перпендикулярной экрану. Линия проходит через оси, пересекая Глава 13 Программирование событий 635 параллелепипед осей в двух точках (рис. 13.1), координаты которых хранятся в матрице xb yb zb *f yf rf Поскольку приложение предназначено для описания геометрии плоских фигур, го оси двумерны и, следовательно, точки с координатами (xb, yb, zb) и (xf, yf, zf) совпадают. Более того, третья координата не понадобится. Рис. 13.1. Координаты точек, хранящиеся в CurrentPoint Итак, алгоритм подфункции axes_ButtonDownFcn простой — считываются координаты точки, например, из второй строки матрицы, и в нее выводится маркер (листинг 13.5). ... ж—-ж. ........................................ ......W I................................ Листинг 13.5. Обработка события ButtonDownFcn осей function axes_ButtonDownFcn(hObject, eventdata, handles) % Получение матрицы с координатами точки Coord = get(hObject, ’CurrentPoint’) % Определение абсциссы и ординаты х = Coord(2, 1}; у = Coord(2, 2); % Вывод маркера plot(x, у, 'о') 636 Часть III. Приложения с графическим интерфейсом Сохраните приложение с именем mypiot и запустите ею— щелчок мышью по осям приводит к появлению маркера. Вернемся теперь к исходной задаче рисования многоугольной области. При первом возникновении события ButtonDownFcn осей мы должны вывести маркер, а при каждом последующем необходимо соединять текущую вершину с предыдущей отрезком, образуя границу многоугольника. По всей видимости, представление всей границы одним графическим объектом даст определенные преимущества по сравнению с набором объектов для каждой стороны многоугольника (так и окажется впоследствии). При запуске приложения мы инициализируем линию (объект Line) при помощи функции line и установим ее свойства XData и YData в значения пустых массивов (см. разд. "Объекты Rectangle и Line, блок-схемы и диаграммы " главы 9). При возникновении каждого события ButtonDownFcn осей будем добавлять к этим массивам абсциссу и ординату новой точки, увеличивая число отрезков ломаной линии. В предыдущем разделе мы обсуждали способ инициализации в подфункции обработки события OpeningFcn, которое возникает после запуска приложения и перед появлением его на экране. Создайте в подфункции mypiot_OpeningFcn линию, сохранив указатель на нее в поле Line структуры handles (не забудьте сохранить измененную структуру handles) и измените обработку события ButtonDownFcn осей (ЛИСТИНГ 13.6). : Листинг 13.6. Инициализация объекта Line и обработка события Ё ButtonDownFcn осей function varargout = myplot_OpeningFcn(hObject, eventdata, handles) varargout{1} = handles.output; ?, Создание линии с пустыми массивами данных % и круглыми маркерами в вершинах, запись указателя на нее в поле Line % структуры handles handles.Line = line(’XData', [ ], 'YData', [ ], 'Marker', 'o'); t Сохранение модифицированной структуры handles guidata(hObject, handles); function axes_ButtuiXownFcn(hObject, eventdata, handles) % Получение матрицы с координатами точки Coord - get(hObject, ‘CurrentPcLnt') 1 Определение абсциссы и ординаты х = coord(2, 1); y=Cocrd(2,2) ; Гпава 13. Программирование событий 637 % Считывание аЬсцисс предыдущих точек X = get'handles.Line, ’XData'); % Считывание ординат предыдущих точек Y = get{handles.Line, 'YData'}; Добавление координат новой точки X = [X х] ; Y = [Y у] ; % Модификация значений свойств XData и YData линии set{handles.Line, 'Xdata', X, 'Ydata', Y) Теперь приложение myedit позволяет рисовать ломаную линию, но имеег один существенный недостаток— при попытке замкнуть границу многоугольника ничего не происходит. Точно так же не удается разместить новую вершину на уже нарисованной границе. Очевидно, что при щелчке мышью по линии возникает событие ButtonDownFcn, которое пока не запрограммировано. Событие ButtonDownFcn линии Основное отличие в программировании события ButtonDownFcn для линии по сравнению с тем же событием осей, состоит в том, что в среде GUIDE заготовка приложения не содержит объект линию, она создается только после запуска приложения. Поэтому необходимо, во-первых, в редакторе М-файлов самостоятельно создать заголовок соответствующей подфункции и запрограммировать ее и, во-вторых, связать эту подфункцию с линией Назовем подфункцию обработки события ButtonDownFcn ДЛЯ ЛИНИИ Line_ButtonDownFcn и будем считать, что она имеет три входных аргумента (так же как и стандартные подфункции): hobject, eventdata и handles. Алгоритм функции Line ButtonDownFcn не отличается от обработки события ButtonDownFcn осей (листинг 13.7). Листинг 13.7. Подфункция обработки события ButtonDownFcn ЛИНИИ ______________________________ —----------------.................. ....... tunction Lrne_ButtonDownFcn(hobject, eventdata, handles) Coord - get{handles.axes, 'CurrentPoint') x = Coord(2, 1); у = Coordfl, 2); X - get(handles.Line, 'XData') Y = get(handles.Line, 'YData') X = [X x] Y = [Y y] set(handles.Line, 'Xdata', X, 'Ydata', Y) 638 Часть III. Приложения с графическим интерфейсом Теперь надо связать подфункцию Line_ButtonDownFcn с событием ButtonDownFcn ЛИНИИ, ДЛЯ чего СВОЙСТВО ЛИНИИ ButtonDownFcn установим в значение массива ячеек {PLineButtonDownFcn, handles}. Мы обсуждали вызов подфункции обработки события при помощи указателя в разд. "Как вызываются подфункции обработки событий"этой главы. Операцию связывания следует выполнить сразу после создания объекта линии в подфункции myplot OpeningFcn, которая может реализоваться в соответствии с листингом 13.8. •*:*”***“_ ч.---j •• .... ..... Листинг 13.8. Звязь подфункции Line_ ButtonDownFcn с событием ButtonDownFcn линии function myplot_OpeningFcn(hObject, eventdata, handles, varargin) handles.output = hObject; % Создание линии с пустыми массивами данных % и круглыми маркерами в вершинах, запись указателя на нее в поле Line % стру к гуры handles handles.Line = line('XData', [ J, 'YData', [ ], 'Marker', 'o') % Связь события ButtonDownFcn линии с подфункцией Line_ButtonDownFcn set(handles.Line, 'ButtonDownFcn', {@Line_ButtonDownFcn, handles)) % Сохранение модифицированной структуры handles guidata(hObject, handles); После проделанных изменений приложение mypiot позволяет рисовать произвольные замкнутые многоугольные области. Рассмотренные выше способы программирования событий наводят на мысль, что приложения с графическим интерфейсом могут быть созданы без обращения к среде визуального программирования GUIDE. Создание приложений с GUI без среды GUIDE В качестве примера создадим файл-функцию simplegui, вызов которой приводит к появлению окна приложения с двумя парами осей. Под каждой парой осей расположена кнопка Нос.роьгь для вывода на нее столбцевой диаграммы некоторых данных (рис. 13.2). В основной функции simplegui следует разместить операторы, создающие графические окно, оси и кнопки с заданными свойствами. Среди этих свойств следует задать те, которые содержат указатели на подфункции обработки событий. Сами подфункции размещаются в одном М файле после I пира 1‘ Программировании co6t пии 63V основной функции. Мы приводим листинг 13.9 файл-функции simplequi вместе с подфункциями, снабженный подробными комментариями. Рнс. 13.2. Окно приложения simplegui function simplegu % Основная функция, создающая окно приложения и его компоненты % Указатели на все графические объекты заносятся в ctj уктуру handles % Создание графического окна без меню с заголовком "simplegui” handles.F = figure('MenuBar', 'none', 'Name*, 1simplegui', ... 'NuiriberTitle1, ' off') ; % Связь события ClosexequestFcn с подфункцией Close set(handles.F, 'CloseRequestFcn', (@Clos€,handj.es}) 140 Часть III 1филожения с графическим интерн ейсом % Создание левой пары осей handles.Al = axes('Position', [0.05 0.2 0.4 0.7]); % Создание правой пэры осей handles.А2 = axes('Position', [0.55 0.2 0.4 0.7]); % Создание левой кнопки "Построить" и связь ее события Callback % с подфункцией PlotBtnl handles.PlotBtnl = uicontrol('Style', 'pushbutton', 'Units', ... 'Normalized', 'Position', [0.05 0.05 0.3 0.05], ... _____ String1, 'Построить', 'Callback', (SPlotBtnl,handles}); % Создание правой кнопки "Построить" и связь ее события Callback % с подфункцией PlotBtn2 handles.PlotBtn2 = uicontrol(’Style', 'pushbutton', 'Units', ... 'Normalized', 'Position', [0.55 0.05 0.3 0.05], ... 'String', 'Построить', 'Callback', {@PlotBtn2,handles}); function PlotBtnl(hobject, eventdata, handles) % Подфункция обработки события Callback левой кнопки % Делаем текущими левые оси axes(handles.Al) гг Выводим на них вертикальную столбцевую диаграмму вектора bar(rand(1, 4)) function PlotBtn2(hobject, eventdata, handles) % Подфункция обработки события Callback правой кнопки % Делаем текущими правые оси axes(handles.А2) % Выводим на них горизонтальную столбцевую диаграмму вектора barh(rand(l, 4)) function Close(hobject, eventdata, handles) % Подфункция обработки события CloseRequestFcn окна приложения % Вывод модального диалогового окна с подтверждением закрытия q = questdig('Закрыть приложение', 'simplegui', 'Да', 'Нет', 'Нет'); % Проверка выбора пользователя if strcmp(q, 'Да') Глава 13. Программирование событий 641 % Пользователь подтвердил чакрытие приложения, % удаляем окно приложения dele te t handles.F) end Свойства объектов, полезные при программировании событий Программирование событий различных объектов может потребовать привлечения ряда их свойств. Например, выше мы рассмотрели использование свойства Currentpoint осей для получения координат точки, в которой был сделан щелчок мыши. Свойство Currentcharacter графического окна позволило нам определить символ нажатой клавиши. Перечислим еще ряд свойств графических объектов, к которым приходится прибегать при программировании приложений с графическим интерфейсом. Прерывание обработки событий Если обработка некоторого события занимает достаточно много времени, то имеет смысл позаботиться о том, как на его выполнение повлияет возникновение нового события. Каждый графический объект имеет два свойства BusyAction и interruptible, установка значений которых позволяет выбрать различные способы согласования событий. Для запрета прерывания исполняемого события объекта следует установить его свойство interruptible в значение 'off. Тогда выполнение обработки следующего события определяется значением свойства BusyAction. Если оно принимает значение 'cancel', то обработка следующего события отменяется, а если ’ queue' (по умолчанию), то следующее событие ставится в очередь. По умолчанию свойство interruptible принимает значение 'on', при этом обработка события может прерываться при наличии в выполняемой функции одной ИЗ команд drawnow, figure, getframe, или pause. Для различных объектов имеются свои особенности при использовании свойств interruptible и BusyAction, которые приведены в справочной системе (см. описание свойств графических объектов в разд. MATLAB: Handle Graphics Property Browser и MATLAB: Creating Graphical User Intel Face: Interruming Executing Callbacks). 642 Часть III. Приложения с графическим интерфейсом Изменение формы курсора Тип указателя мыши задается свойством Pointer графического окна, которое может принимать значения: □ crosshair — перекрестие; □ arrow — обычная стрелка (по умолчанию); □ watch — песочные часы; □ ibeam—вертикальный курсор. Перечень всех возможных значений приведен в справочной системе MATLAB. Значение custom позволяет определить собственную квадратную пиктограмму размером 16 пикселов для курсора мыши в матрице и задать ее в качестве значения свойства PointerShapeCData. Единица означает черный цвет, двойка — белый, а прозрачность пиксела достигается установкой Нан в соответствующие элементы матрицы. Последовательность команд, приведенная в листинге 13.10, приводит к курсору мыши в виде квадратной прозрачной рамки. Листинг 13.1Q. Генерация указателя мыши i виде свадратн й прозрач» й рамки Р = ones(16); №(2:15,2:15) = NaN; set(gcf, 'Pointer', 'custom') set(gcf, ’PointerShapeCData1, MP) Среда GUIDE позволяет достаточно просто написать приложение для проведения собственных исследований. Основное преимущество визуальной среды GUIDE по сравнению со многими другими современными языками программирования состоит в том, что разработчик может использовать большой набор готовых функций МАТ1 АВ, которые реализуют алгоритмы решения широкого спектра задач. Функции, предназначенные для простейших вычислений и визуализации данных, были описаны в первой части книги. Как уже упоминалось, функции, направленные на решение специальных задач, собраны в пакеты, называемые Toolbox. Использованию некоторых Toolbox посвящена следующая часть книги. ЧАСТЬ IV Использование Toolbox и решение ПРИКЛАДНЫХ ЗАДАЧ Глава 14 Решение задач математической физики Большинство задач механики, теплопроводности, течения жидкости, электростатики и электродинамики сводятся к дифференциальным уравнениям в частных производных в областях сложной формы. Данная глава посвящена описанию возможностей Partial Differential Equations Toolbox (PDE Toolbox), предназначенного для решения граничных задач для дифференциальных уравнений в частных производных в двумерных областях методом конечных элементов. В состав данного Toolbox входит приложение pdetool с графическим интерфейсом пользователя, использование которого не требует глубокого понимания метода конечных элементов. Кроме того, PDE Toolbox обладает набором функций, полезных при написании собственных приложений для решения граничных задач методом конечных элементов. Следующий раздел посвящен основам работы с pdetool. Простой пример Среда pdetool позволяет задать геометрию области, тип и коэффициенты дифференциального уравнения, граничные и начальные условия, произвести разбиение области на конечные элементы (триангуляцию), решить получающуюся систему линейных уравнений и визуализировать результат. Пользователь должен сформулировать задачу, т. е. написать уравнение и граничные условия, и последовательно выполнять вышеописанные действия. Изучите основы работы в pdetool на примере задачи теплопроводности в простой области. 646 часть IV Использование Гoolbox и решение прикладных задач Постановка задачи Требуется найти распределение температуры Т в области, изображенной на рис. 14.1. Круговое отверстие расположено в центре прямоугольника. Правая и левая границы прямоугольной области теплоизолированы. Внутри области нет источников тепла и коэффициент теплопроводности к равен 200. Распределение температуры описывается дифференциальным уравнением кУ-УТ = 0; граничные условия на правой и левой границе задают нулевой поток тепла (л —вектор нормали к границе) л *V7' = 0; на верхней и нижней границе Т = 600, а на окружности Т = 500 . Размерности единиц не указываются. Поставленная задача просто решается при помощи среды pdetooi. Инструкции, приведенные в следующих разделах, помогают освоить работу в pdetooi. Более подробному описанию возможностей посвящен отдельный раздел. Среда pdetooi, конструирование области Начните работу, выполнив команду pdetooi в командном окне, появляется окно PDE Toolbox среды pdetooi, изображенное на рис. 14.2. Глава 14 Решение задач математической физики 647 Рис. 14.2. Среда pdetool Данное окно содержит следующие основные элементы: П строку меню, каждое меню соответствует определенному этапу решения задачи; □ панель инструментов рисования геометрических примитивов, определяющих область; О панель инструментов для задания граничных условий, коэффициентов уравнения, триангуляции, решения и визуализации результата; □ область ввода Set formula для конструирования области из геометрических примитивов; □ оси для создания области. Конструирование области, приведенной на рис. 14.1, включает в себя создание прямоугольника и круга заданных размеров и вычитание круга из прямоугольника. Удобно расположить область так, чтобы центр прямоугольника совпал с началом координат, тогда координаты нижнего левого утла 648 Часть IV. Использование Toolbox и решение прикладных задач прямоугольника будут (-1, 0.5), а его высота и ширина 1 и 2 соответственно. Центр круга также совпадает с началом координат. Начните с создания прямоугольника. Выберите в меню Draw пункт Rectangle/square или воспользуйтесь соответствующим инструментом (его пиктограмма содержит прямоугольник). Нарисуйте мышью требуемую прямоугольную область на осях от угла, удерживая нажатой левую кнопку. Скорее всею, точно выдержать размеры и положение не удалось. Двойной щелчок мыши по прямоугольнику приводит к появлению диалогового окна Object Dialog (рис. 14.3), предназначенного для установки заданных размеров и положения объекта. Рис. 14.3. Диалог овое окно Object Dialog Введите в строках Left и Bottom координаты нижнего левого угла прямоугольника: -1 и -0.5, в Width и Height задайте ширину и высоту: 2 и 1 соответственно. Поле Name предназначено для определения названия объекта, в данном случае прямоугольника. По умолчанию имена создаваемых прямоугольников состоят из буквы R (от Rectangle) и порядкового номера. При конструировании области с простой геометрией нет необходимости изменять имена объектов. Нажмите кнопку ОК и убедитесь, что прямоугольник принял нужное положение и размеры на осях. Нарисуйте круг с центром в точке (0,0) и радиусом 0.25. Выберите в меню Draw пункт EUipse/circle (centered) или воспользуйтесь соответс гвующим инструментом, его пиктограмма — эллипс с перекрестием. Гпава 14. Решение задач математической физики 649 Перекрестие на пиктограмме инструмента, или слово "centered" в названии пункта меню Draw означают, что соответствующий объект рисуется на осях из центра при нажатой левой кнопке мыши. Поместите курсор мыши в начало координат осей и нарисуйте окружность при помощи мыши с одновременным удержанием <Ctrl>. Клавиша <Ctrl> позволяет рисовать геометрические примитивы квадрат и круг, если активны, соответственно, инструменты Rectangle/square. Rectangle/square (centered), Ellipse/circle, Ellipse/circle (centered). Перейдите к свойствам круга двойным щелчком мыши и уточните в диалоговом окне Object Dialog его положение и радиус. В строки X-center, Y-center следует занести нули, а в Radius— величину радиуса 0.25. Круг имеет название С1 (от Circle). Геометрические примитивы для задания области созданы. Сейчас установлен режим рисования (переход в него происходит при использовании инструментов рисования или выборе пункта Draw Mode меню Draw), поэтому на осях присутствуют все добавленные объекты. Следующий этап состоит в определении взаимосвязи между примитивами, образующими область, — круг должен быть удален из прямоугольника. Связь между примитивами определяется в строке Set Formula среды pdetooi. Знак плюс означает объединение объектов, а минус — вычитание. Области, изображенной на рис. 14.1, соответствует формула Rl - С1, из большего объекта вычитается меньший по размерам. Область, в которой решается дифференциальное уравнение, сконструирована, теперь задайте коэффициенты уравнения и граничные условия. Определение уравнения и граничных условий Меню Options содержит подменю Application, которое позволяет задать тип решаемой задачи. Пункт Heat Transfer соответствует задаче о распределении тепла. Выберите данный пункт, слева от названия появится флаг— среда pdetooi теперь настроена на решение задачи теплопроводности. Использование раскрывающегося списка, размещенного на панели инструментов, приводит к аналогичному результату. Установите режим дифференциального уравнения, выбрав пункт PDE Mode в меню PDE. На экране теперь отобразится область с отверстием. Именно для этой области и следует определить коэффициенты и правую часть дифференциального уравнения. Перейдите к пункту PDE Specification... меню PDE или примените двойной щелчок по области, появляется диалоговое окно PDE Specification, изображенное на рис. 14.4. Обратите внимание, что вверху диалогового окна на 650 Часть IV, Использование Toolbox и решение прикладных задач панели Equation содержится общин вид уравнения теплопроводности, которое может быть решено в среде pdetool: -div(k*grad(Т)) = Q + h*(Text - T) Значения коэффициентов устанавливаются в строках ввода, расположенных на правой панели диалогового окна. Левая панель служит для выбора типа уравнения, переключатель Elliptic соответствует задаче о стационарном распределении тепла, описываемой эллиптическим дифференциальным уравнением, a Parabolic — нестационарному случаю Решение нестационарных задач описано ниже. Убедитесь в том, что включен Elliptic, и задайте в строках ввода коэффициенты уравнения рассматриваемой задачи. Рис. 14.4. Диалоговое окно PDE Specification Выбор подходящих коэффициентов позволяет свести дифференциальное уравнение, записанное в общем виде, к уравнению, которое описывает задачу, поставленную в начале данного раздела. Установите коэффициенту теплопроводности к значение 200. Поскольку в рассматриваемой задаче нет распределенных источников тепла, то Q равняется нулю. Коэффициент конвективного теплообмена h и внешняя температура, входящие в общий вид дифференциального уравнения, также должны иметь нулевое значение. Нажмите ОК для сохранения проделанных изменений. Перейдите к заданию граничных условий. Выберите пункт Boundary Mode меню Boundary, среда pdecool находится в режиме установки граничных условий, в окне отображаются только границы области. Обратите внимание, что прямоугольник имеет четыре границы, по числу сторон, и окружность также составлена из четырех ду1. Гпава 14. Решение задач математической физики 651 Сделайте текущей верхнюю границу прямоугольника щелчком мыши и выберите f меню Boundary пункт Specify Boundary Conditions.... появляется диалоговое окно Boundary Condition, предназначенное для выбора типа граничного условия (рис. 14.5). Рис. 14.5. Диалоговое окно Boundary Condition Граничное условие предлагается в общем виде, выбор коэффициентов позволяет получить требуемый частный случай. На верхней границе прямоугольника задано значение температуры, равное 600 (см. рис. 14.1). Это граничное условие Дирихле. Убедитесь, что на панели C ondition type окна Boundary Condition включен переключатель Dirichlet, соответствующий условию Дирихле. Вверху окна на панели Boundary condition equation присутствует общий вид условия ь*т = г, где h — весовой коэффициент, аг — заданная температура. Установите при помощи строк ввода (доступны только две строки для данного положения переключателя) значение h в единицу, а г приравняйте 600. Сохраните значения, нажав ОК, и проделайте аналогичную операцию для нижней стороны прямоугольника, предварительно сделав ее текущей щелчком мыши. Граничные условия можно задавать по отдельности на каждой части границы, или объединить несколько частей и определить одинаковые граничные условия сразу для всей группы. Добавление части границы в группу производится щелчком мыши с одновременным удержанием <Shift>. Двойной щелчок мышью по части границы или по группе частей дает быстрый доступ к диалоговому окну Boundary Condition. Установите температуру 500 на границе отверстия, сгруппировав предварительно четыре части окружности. На правой и левой стироне прямоугольной области поток тепла равен нулю, поскольку данные границы теплоизолированы (см. рис. 14.1). Равенство нулю потока есть частный случай условий Неймана. Объедините две грани 652 Часть IV. Использование Toolbox и решение прикладных задач цы в группу и откройте диалоговое окно Boundary Condition. Установите переключатель (Condition type в положение Neumann, соответствующее граничным условиям Неймана. Вверху окна отобразился общий вид условия Неймана n*k*grad(T) + q*T = g, отвечающего конвективному теплообмену через границу с окружающей средой. Очевидно, что для получения теплоизолированных границ требуется задать коэффициенты g и g равными нулю. В режиме установки граничных условии границы с условиями Дирихле отображаются красным цветом, а синий цвет выделяет границы, на которых задано условие Неймана. Доступ к диало<овым окнам Boundary Condition и PDE Specification осуществляется не только двойным щелчком мыши или из меню, но и при помощи кнопок панели инструментов с надписями Эй и PDE. Уравнение и граничные условия определены, следующим этапом является решение задачи и визуализация результата. Решение и визуализация результата Первый шаг состоит в триангуляции— покрытии области сеткой, состоящей из треугольников. Триангуляция и установка ее параметров производятся в меню Mesh. Перейдите в режим триангуляции, выбрав пункт Mesh Mode область разбивается на достаточно крупные треугольные элементы, причем считается, что граница области составлена из сторон некоторых элементов (рис. 14.6). Рис. 14.6. Начальная триангуляция Глава 14.1 'еизение задач математической физики 653 Инициализация триангуляции может быть произведена кнопкой с треугольником. Для получения решения с приемлемой точностью начальной триангуляции недостаточно, следует уменьшить uiai разбиения области. Выберите пункт Refine Mesh или нажмите кнопку с треугольником, разделенным на четыре части. Каждый выбор данного пункта приводит к равномерному уменьшению размеров треугольников. Учтите, что выбор слишком мелкой сетки может привести к значительным затратам времени на решение системы линейных уравнений методом конечных элементов. Для возврата к начальной триангуляции служит пункт Initialize Mesh. Уменьшите треугольники исходной сетки в несколько раз. Обратите внимание, что уменьшение размеров ячеек сетки улучшает вид границ области (рис. 14.7). Рис. 14.7. Расчетная триангуляция Решение задачи на расчетной сетке производится выбором пункта Solve PDE меню Solve или нажатием на кнопку со знаком "равно”. Используется способ решения задачи, установленный по умолчанию (выбор различных способов решения описан в разд. "Параметры триангуляции и управление процессом решения" дайной главы). Найденное распределение температуры отображается в окне среды pdetool контурным графиком с цветовой заливкой, рядом с которым расположен столбик с информацией о соответствии цвета значению температуры (рис. 14.8). Изменение геометрии области, граничных условий, типа уравнения и его коэффициентов может быть выполнено, даже если решение уже найдено. Следует перевести среду pdetool в соответствующий режим и произвести требуемые действия. Сохранение работы производится в М-файле из пункта Save as... (или Save для сохранения в существующем М-файле с тем же именем) меню File. М-файл содержит функции PDE Toolbox, которые вызыва 654 Часть IV Использование Foolbox и решение прикладных задач ются в среде pdetool в соответствии с последовательностью действий пользователя. Данный М-файл содержит не только геометрию области, тип и коэффициенты уравнения и граничных условий, но и текущие установки среды, что позволяет впоследствии продолжить решение задачи Рис. 14.8. Графическое представление результата Среда pdetool позволяет распечатать график решения. Выбор пункта Print... меню File приводит к появлению диалогового окна печати. Для установки параметров страницы следует нажать кнопку Page Setup..., отображается одноименное диалоговое окно, работа с которым описана ранее (см. разд. "Сохранение, экспорт и печать" главы 4). Возможности среды pdetool не исчерпываются решением стационарной задачи теплопроводности. Следующие разделы посвящены подробному описанию допустимых классов задач, некоторым приемам, полезным при конструировании геометрии области, управлению процессом решения и видом получающихся графиков. Описание возможностей PDE Toolbox Интерфейс среды pdetool облегчает доступ пользователя к функциям, входящим в состав PDE Toolbox. Читатель, знакомый с методом конечных элементов и владеющий навыками программирования в MATLAB, может ГлалЗ-л Щ Решение згдач математической физики 65о использовать функции этого Toolbox для написания собственных приложений или реализовывать разнообразные алгоритмы решения задачи, создавая новые функции. Стандартный набор функций PDE loolbox позволяет решать достаточно широкий спектр двумерных заоач в ограниченных областях, включая: П задачи теории упругости; □ стационарные и нестационарные задачи теплопроводности; □ течения в пористых средах; □ задачи диффузии; □ ламинарное течение жидкости; □ электростатические задачи; □ распространение акустических и электромагнитных волн; □ определение собственных колебаний конструкций. Обобщая приведенный список, можно сказать, что практически любая задача, описываемая уравнением или системой уравнений в частных производных, может быть решена при помощи PDE Toolbox. В следующих разделах приведены типы граничных задач для уравнений в частных производных, решение которых может быть найдено с использованием PDE Toolbox. Область обозначена через £2, а ее граница — Э£2. Эллиптическое уравнение Стационарная задача теплопроводности, постановке и решению которой посвящены предыдущие разделы, описывается эллиптическим дифференциальным уравнением. Эллиптическое дифференциальное уравнение в общем случае имеет вид: — V ’(сУиУ+аи = f в £2. Граница Э£2 области может быть поделена на несколько участков, на каждом из них ставятся либо условия Дирихле hu = г, либо обобщенное условие Неймана п- (cVh)+ qu = g , где п — вектор внешней нормали к границе. В примере, приведенном в предыдущем разделе (см. рис. 14.1), коэффициенты уравнения и граничных условий были постоянны, однако PDE Toolbox способен решать задачи с переменными коэффициентами с(х, у), «(х, у) и правой частью /(х, у) уравнения и /i(x, у), г(х, у), qlx, у), g(x, у) граничных условий. Более того, нелинейные задачи, в которых коэффициенты зависят от искомой функции и(х, у), также могут быть решены в PDF Toolbox. Допустимы комплексные значения всех коэффициентов. п'56 Ч 1сть IV Использование Tnnlbox ирешение прикладных задач Настройка среды pdetool на решение эллиптического уравнения осуществляется выбором пункта Generic Scalar подменю Application меню Options или при помощи раскрывающегося списка, размещенного на панели инструментов среды pdetool. В диалоговом окне PDE Specification следует установить переключатель Elliptic на панели Type of PDE. Диалоговое окно PDE Specification настроено на ввод коэффициентов эллиптического уравнения. Переменные коэффициенты и правая часть уравнения Разберем решение дифференциального уравнения с переменной правой частью (переменные коэффициенты уравнения задаются аналогично), зависящей от .г и у на примере уравнения V-VM = 16(x2+/). Область является кругом единичного радиуса с центром в начале координат, на границе которого задано условие Дирихле и = 1. Нарисуйте единичный круг в среде pdetool, используйте диалоговое окно Object Dialog для точного определения радиуса и центра. Выберите эллиптический тип уравнения, задайте коэффициенты а = 1 и с =0, а для правой части f введите выражение в соответствии с правилами поэлементных операций с массивами, используя переменные х и у (поэлементные операции с массивами описаны в главе 2). Требуемое выражение должно выглядеть так: -14* (х.Л2 + у.Л2), знак минус соответствует общему виду дифференциального уравнения, приведенного в предыдущем пункте. Инициализируйте триангуляцию и решите задачу на первой предлагаемой сетке. Полученное прибчиженное решение можно сравнить с точным (г2 + у2У, построив их разность в области. Среда pdetool позволяет выводить график не только приближенного решения, но и функции, в которую это решение входит. В нашем случае такой функцией является погрешность, т. е. разность приближенного и точного решений. Выберите в меню Plot пункт Paiameiers..., появляется диалоговое окно Plot Selection (рис. 14.9), которое позволяет выбрать тип и вид визуализируемого результата. Верхняя панель окна Plot Selection организована в виде таблицы, левая колонка которой содержит флаги, соответствующие способу визуализации результатов. Поле Property состоит из раскрывающихся списков, предназначенных для выбора отображаемой функции от приближенного решения. Опция user entry делает доступной строку ввода в колонке User entry. Введи Гпава 14. Решение задач математической физики 657 те в ней выражение для вычисления погрешности и~(х.Л2 + у.А2). Л2. Нажатие кнопки Plot приводит к отображению залитого цветом контурного графика погрешности. Раскрывающийся список Plot style позволяет получать графики с плавным изменением цвета на каждом элементе (опция interpolated shad) или выбрать постоянный цвет на элементе (опция flat shading!. Решайте задачу, поставленную в начале раздела, уменьшая ячейки сетки, и наблюдайте за изменением погрешности решения. Рис. 14.9. Диалоговое окно Plot Selection Переменные коэффициенты уравнения задаются с использованием переменных х и у и поэлементных операций. Коэффициенты, входящие в граничные условия, могут зависеть либо от х и у, либо от значения s параметра части границы В начальной точке границы s равно нулю, в конечной — единице. Направление границы определяется стрелкой в режиме задания граничных условий. Значение параметра пропорционально длине части границы. Параболическое и гиперболическое уравнения Параболическое и гиперболическое уравнения, которые могут быть решены в PDE Toolbox, выглядят следующим образом: -ч d~-V-(cVu) + au = f d-^~--V-(cVu)+au= f. 658 Часть IV Использование Toolbox и решение приклэдных задач Коэффициенты d, с, а и правая часть f могут зависеть как от л и jy, так и от времени t. Граничные условия, как и в случае эллиптического уравнения, на одних частях границы являются условиями Дирихле, а на других— Неймана. Допускается зависимость коэффициентов граничных условий от времени и координат или параметр® границы. Задача, описываемая параболическим и гиперболическим уравнениями, требует определения начальных условий в нулевой момент времени. Решение при I = О может зависеть от лс и у. PDE Toolbox позволяет найти решение только в ограниченной области Q. Среда pdetooi предоставляет пользователю возможность получения наглядных графиков полученного приближенного решения. Можно визуализировать решение в любой момент времени либо проследить за развитием процесса в отдельном графическом окне, в которое выводится последовательность слайдов, содержащих залитые контурные графики решения в различные моменты времени. Пример нестационарной задачи В качестве примера рассмотрим нестационарную задачу о распределении тепла в области, изображенной на рис. 14.10. Гранины прямоугольника теплоизолированы, а края отверстия подвергаются нагреву, температура изменяется линейно со временем. Внутри области нет распределенных источников тепла, в начальный момент времени температура равна нулю во всей области. Нас будет интересовать изменение температуры на протяжении пятнадцати секунд. о нестационарном распределении температуры Глава 14. Решение задач математической физики 659 Задайте геометрию области и настройте среду pdetool на решение задачи теплопроводности. Перейдите к диалоговому окну PDE Specification и выберите параболический тип уравнения, установив переключатель Parabolic. Введите единицы в строки, соответствующие плотности rho, теплоемкости с и коэффициенту теплопроводности k, a Q, h и Text обнулите. На границах прямоугольника поставьте условия равенства нулю потока тепла, а для окружности введите формулу ioo*t, переменная t используется для обозначения времени. Задайте распределение температуры в начальный момент времени и значения времени, в которые следует найти приближенное решение. Выберите пункт Parameters... в меню Solve. Появляется диалоговое окно Solve Parameters. вид которого соответствует типу решаемой задачи. Для нестационарной задачи теплопроводности, описываемой параболическим уравнением, окно Solve Parameters (рис. 14.11) позволяет установить в строке Time вектор моментов времени, а в строке u(tO) — начальное распределение температуры, которое в общем случае может зависеть от х и у. Рис. 14.11. Диалоговое окно Solve Parameters для нестационарной задачи Введите ноль для начального распределения и задайте вектор моментов времени от нуля до пятнадцати с шагом 0.5, примените двоеточие для генерации вектора значений. 22 Зак 130 660 Часть IV. Использование Toolbox и решение прикладных задач Часто требуется найти решение не в равноотстоящие моменты времени. Больший интерес может представлять начало процесса распределения тепла. Можно задать в u(tO) вектор значений, например, [0 0.1 0.2 0.3 0.5 ! 4 10 15], или логарифмическую шкалу времени командой logspace (-2, logic (15), 20), которая генерирует 20 равноотстоящих в логарифмической шкале точек от 102 до 15. Инициализируйте триангуляцию, уменьшите шаг сетки в несколько раз и решите задачу. Решение может занять достаточно много времени, в зависимости от производительности компьютера. Процесс решения сопровождается выводом информации в командное окно. В окне pdetool появляется распределение температуры в области в конечный момент времени при I = 15 . Для того чтобы проследить за динамикой процесса, следует установить в диалоговом окне Plot Selection флаг Animation и воспользоваться кнопкой Options для определения параметров анимированных результатов. Нажатие на Options приводит к открытию окна Animation Options, изображенного на рис. 14.12. Рис. 14.12. Диалоговое окно Animation Options Строка ввода Animation rate (fps) служит для задания числа кадров в секунду (frames per second), которое будет использоваться при отображении распределения температуры в зависимости от времени. Число повторов анимации устанавливается в строке Number of repeats. Введите желаемые значения или оставьте те, что используются по умолчанию, закройте Xnimation Options и нажмите кнопку Plot в окне Plot Selection. Динамическое распределение температуры в области отображаегся в отдельном графическом окне. Гпава 14. Решение задач математической физики 661 Задача на собственные значения PDE Tootbox предоставляет возможность решения задачи на собственные значения —V • (cVw) + an — Xdu, причем коэффициенты с, а и d могут зависеть от х и у в области £2. В задаче на собственные значения допустимы только однородные граничные условия Дирихле и=0 или Неймана n-(cVw)+=0. Решением задачи являются собственные значения и собственные функции. Настройка среды pdetooi на решение задачи на собственные значения производится установкой переключателя Eigenmodes в диалоговом окне PDE Specification. Интервал поиска собственных значений определяется в окне Solve Parameters, которое в данном случае содержит единственную строку ввода Eigenvalue search range. Интервал задается вектор-строкой или вектор-столбцом из двух элементов. Когда решение найдено, в окне pdetooi отображается график собственной функции, отвечающей первому найденному значению из введенного интервала. Диалоговое окно Plot Selection содержит раскрывающийся список Eigenvalue, ког орый позволяет выбрать собственное значение и отобразить в окне среды pdetooi график соответствующей собственной функции. Системы дифференциальных уравнений Функции, входящие в состав PDE Toolbox, позволяют решить систему дифференциальных уравнений произвольной размерности. Среда pdetooi оперирует только с системой второго порядка: -V(c11Vw1)-V-(c12Vm2) + °11u1 +"12»2 =/b -V (с21 Vl?] ) - V • (c22 Vn2 ) + «2 1MI + a22u2 ~ ’ Граничные условия на различных частях Эй могут быть трех типов: Дирихле AIl«l+/l12H2=rh Л21«1 +A22z/2 =г2; Неймана и (q .Vq ) + и (c12Vi/2 )+91 1ul + 912ы2 = gi; Л • (с21 Vl/[)+ П • (с22Vh2 )+ Я2Щ + q22u2 = S2 662 Часть IV. И'чн мьзоьаниг Toolbox и решение прикладных задач или смешанные граничные условия +hl2u2 = г,; » ’ (С11 Vw1) + и (c12Vw2 ) + ql ]Н] + 9I2w2 - g, + Л, П (c21Vm1 ) + « • (c22Vw2) + 021«1 + ft>2u2 = &2 +^12Д. Нестационарные задачи, описываемые системами дифференциальных уравнений, также могут быть решены в PDE Toolbox. Выбор опции Generic System в подменю Application меню Options (или в раскрывающемся списке на панели инструментов) настраивает среду pdetool на решение подобной системы уравнений. Рис. 14.13. Диалоговое окно PDE Specification, насгроенное на решение системы параболических уравнений Диалоговое окно PDE Specification позволяет задать коэффициенты стационарных и нестационарных систем (рис. 14.13) или перейти к решению задачи на собственные значения. Окно Boundary Condition содержит переключатели Neumann, Dirichlet и Mixed для выбора одного из трех типов условий, перечисленных выше, и строки ввода для задания коэффициентов граничных условий. Решением системы является вектор-функция из двух компонент [w](x, у), w2(a, у)]. Раскрывающиеся списки диалогового окна Plot Selection предоставляют возможность визуализировать первую или вторую компо- Гпава 14. Речение задач математической физики 663 ленты решения (они обозначены через и и v), вывести график заданной пользователем функции от компонент решения (опция user entry) или отобразить решение векторным полем (фляг Arrows). Параметры триангуляции и управление процессом решения Начальная триангуляция области достаточно грубая, дальнейшее уменьшение шага сетки производится выбором пункта Refine Mesh меню Mesh или нажатием соответствующей кнопки на панели инструментов среды pdetool. Диалоговое окно Mesh Parameters, открывающееся при переходе к пункту Parameters... меню Mesh, предназначено для задания параметров триангуляции, в частности, максимальная длина стороны элементов вводится в строке Maximum edge size. Среда pdetool позволяет пользователю выбирать некоторые алгоритмы решения в диалоговом окне Solve Parameters, доступ к которому производится выбором пункта Parameters... меню Solve. Вид данного окна зависит от типа уравнения. Если решается задача для эллиптического уравнения, то окно имеет вид, приведенный на рис. 14.14 (для наглядности включены флаги вверху каждой панели). Левая панель окна Solve Parameters предназначена для решения эллиптических задач в адаптивном режиме, смысл которого заключается в автоматическом уменьшении шага сетки в ходе решения с целью повышения эффективности вычислений Установка флага Adaptive mode настраивает среду pdetool на решение в адаптивном режиме и разрешает доступ к элементам управления, расположенным на данной панели. Строка Maximum number of triangles позволяет определить максимальное количество треугольников, а задание inf, наоборот, не ограничивает нижний предел шага сетки. Наибольшее число попыток уточнения вводится в строке Maximum number of refinements. Уточнение сетки может происходить на основе одного из трех критериев: □ по наихудшим треугольникам (переключатель Worst triangles), в строке Worst triangle fraction можно установить условный критерий качества от нуля до единицы; □ по относительной погрешности (переключатель Relative tolerance), в одноименной строке следует ввести погрешность; □ по критерию пользователя (переключатель User-defined function», дополнительная информация содержится в справочной системе МАП АВ по PDE Toolbox. 664 Часть IV. Использование Toolbox и решении прикладных задач Рис. 14.14. Диалоговое окно Solve Parameters для эллиптического уравнения Способ уменьшения шага сетки выбирается в раскрывающемся списке Refinement method, допустимо либо регулярное уточнение (regular), при котором каждая сторона треугольника делится пополам, образуя четыре малых треугольника, либо по наибольшей стороне треугольника (longest). Решение нелинейных граничных задач для эллиптических уравнений требует применения нелинейного солвера, который включается флагом Use nonlinear solver, расположенным на правой панели окна Solve Parameters. Описание нелинейного солвера выходит за рамки данной книги, подробная информация приведена в справочной системе MATLAB no PDE Toolbox. Главъ /4. Решение задач математической физики 665 Конструирование геометрии области Создание плоских областей сложной формы в среде pdetool требует понимания принципов конструктивной блочной геометрии или CSG (constructive solid geometry). Среда pdetooi предлагает пользователю ряд средств, облегчающих задание геометрии области. Геометрические примитивы Плоская ограниченная область является объединением, пересечением или разностью геометрических примитивов. В режиме рисования из меню Draw или панели инструментов доступны инструменты рисования: □ прямоугольника от угла (пункт RectantJe/square); □ прямоугольника из центра (пункт Rectangle/squarе (centered)); □ эллипса от угла прямоугольной рамки, содержащей эллипс (пункт Ellipse/circle); □ эллипса из центра (пункт Ellipse/circle (centered)); □ многоугольника (пункт Polygon). Использование первых четырех инструментов при удержании <Ctrl> позволяет нарисовап квадрат или круг соответственно. Многоу! ольник обязательно должен быть замкнут, выбор другого инструмента при разомкнутом контуре прямоугольника приводит к исчезновению контура. Треугольник является простейшим видом многоугольника. Каждый геометрический примитив при создании получает имя, состоящее из типа примитива и номера, определяемого порядком создания. Символы е и с означают эллипс и круг, к и so — прямоугольник и квадрат, ар — многоугольник. Характеристики размеров примитивов и их положение устанавливаются в диалоговом окне Object Dialog, которое позволяет точно определить соответствующие величины и, кроме того, задать любое имя. Окно Object Dialog появляется при двойном щелчке по области объекта. Если требуемый объект накрывается более крупным, то следует применить двойной щелчок в области имени мелкого объекта. Вид окна Object Dialog зависит от типа объекта, например, прямоугольник и квадрат задаются координатами левого нижнего угла, шириной и высотой (см. рис. 14.3). Круг определяется координатами центра и радиусом, эллипс— координатами центра и величинами полуосей; кроме того, в свойства эллипса включен угол поворота против часовой стрелки в градусах. Диалоговое окно Object Dialog, соответствующее многоугольнику, приведено на рис. 14.15. Раскрывающийся спи 666 Часть IV. Использование Toolbox и решение прикладных задач сок Coordinates предназначен для выбора вершины, координаты которой помещаются в строки ввода X-value edit box и Y-value edit box и становятся доступны для изменения. Рис. 14.15. Диалоговое окно Object Dialog со свойствами многоугольника Любой созданный объект можно повернуть на заданный угол, для чего следует выделить объекз и перейти в меню Draw к пункту Rotate.... Появляется диалоговое окно Rotate, содержащее строку ввода Rotation (degrees) для значения в градусах угла поворота против часовой стрелки и флаг Use center-of-mass. Установленный флаг приведет к повороту объекта вокруг его центра масс, а выключенный— делает доступным строку ввода Rotation center, предназначенную для определения центра вращения. Задание структуры области Структура области, составленной из геометрических примитивов, определяется формулой в проке Set formula среды pdetool, в которую входят имена примитивов, знаки плюс, минус, умножить и скобки. Все создаваемые примитивы по умолчанию объединяются, между их именами ставится знак плюс. При редактировании формулы следует придерживаться перечисленных ниже правил: □ минус предназначен для вычитания примитива, операция имеет наивысший приоритет; □ плюс означает объединение примитивов, а умножить— пересечение, операции имеют одинаковый приоритет; О для изменения приоритета используются круглые скобки. Гпава 14. Решение задач математической физики 667 Создайте прямоугольник с отверстиями, изображенный на рис. 14.16, нарисуйте прямоугольник R1 и три круга 01, С2, сз и введите в строку Set formula выражение Rl - (Cl + С2 + СЗ) и нажмите <Enter>. Рис. 14.16. Прямоугольник с отверстиями В режиме рисования на области присутствуют все созданные примитивы, даже если они вычитаются из других примитивов. Для отображения реальной геометрии области перейдите в режим дифференциального уравнения (пункт PDE Mode в меню PDE). Примечание Редактирование формулы доступно только в режиме рисования, в который можно перейти в любой момент, даже после того, как решение найдено, и внести изменения в геометрию области. Нарисуйте прямоугольник со скругленными углами, такой как изображен на рис 14.17. Очевидно, что следует вычесть из прямоугольника четыре небольших квадрата, целиком расположенных внутри прямоугольника, вершины которых совпадают с вершинами прямоугольника. Рис. 14.17. Прямоугольник со скругленными углами 668 Часть IV. Использование Toolbox и решение прикладных задач Для получения скругленных углов осталось объединить полученную область с четырьмя кругами, центры которых расположены в ближайших к центру прямоугольника вершинах удаленных квадратов, а радиусы равны стороне этих квадратов. Начинающему пользователю следует иметь в виду, что при конструировании геомегрии области многие действия, в частности, удаление примитива, необратимы. Пункт Undo меню Edit позволяет только отменить последнюю нарисованную линию многоугольника. Хорошим решением проблемы является периодическое сохранение геометрии области, в случае неудачных изменений можно воспользоваться резервной копией. Объединение объектов позволяет просто задать геометрию области, однако следует иметь в виду, что при объединении сохраняются внутренние границы. Если область однородна, то следует удалить ненужные границы при помощи пункта Remove Subdomain Border меню Boundary, предварительно выделив их в режиме границ (пункт Boundary Mode меню Boundary). Все внутренние границы удаляются выбором пункта Remove АП Subdomain Borders. Задачи в областях, составленных из материалов с разными свойствами, не предполагают удаления внутренних границ. Композитные материалы Исследуем стационарное распределение тепла в сечении теплоизолирующей оболочки с двумя нагревающимися стержнями, коэффициенты теплопроводности оболочки и стержней различны (рис. 14.18) Внешняя граница оболочки поддерживается при температуре ноль градусов, в оболочке нет источников тепла, а плотность источников тепла в сечении стержней равна 1000. Составьте область из трех кругов, формула должна иметь вид cl + С2 + сз. Выберите тип решаемой задачи (Heat transfer). В режиме задания граничных условий установите нулевую температуру на внешней границе, не удаляйте внутренние границы! Перейдите в режим дифференциального уравнения и для каждой области задайте коэффициент теплопроводности и плотность источников тепла. Двойной щелчок мыши по каждому из примитивов приводит к появлению диалогового окна PDE Specification, служащего для задания коэффициентов и правой части именно для данного примитива. Можно объединить несколько примитивов в группу щелчком мыши с одновременным удержанием клавиши <Shift> и произвести установки для группы подобластей. Выберите подходящую триангуляцию и решите задачу. В окне среды pdetool отображается искомое распределение температуры в сечении рассматриваемой конструкции (рис. 14.19). Гпава 14. Решение задач математической физики 669 Рис. 14.18. Задача о распределении температуры в теплоизолирующей оболочке Рис. 14.19. Распределение температуры в теплоизолирующей оболочке Использование сетки Среда pdetool предоставляет пользователю возможность изменять пределы осей, наносить вспомогательную сетку и использовать ее при рисовании и перемещении объектов. Отображение сетки в окне среды производится выбором пункта Grid меню Draw. Параметры сетки задаются в диалоговом окне Grid Spacing, которое выводится при выборе одноименного пункта в меню Options. Строки ввода X-axis linear spacing и Y-axis linear spacing предназначены для задания координат линий сетки по соответствующим направлениям. Используется либо вектор с постоянным шагом (при помощи двоеточия), либо координаты, разделенные пробелом. Равномерной сетки может быть недостаточно, координаты дополнительных линий вводятся в строках X-axis extra ticks и Y-axis extra ticks. 670 Часть IV. Использование Toolbox и решение прикладных задач Пределы осей устанавливаются в диалоговом окне Axes limits, которое появляется при выборе соответствующего пункта меню Options. Область проще конструировать, когда оси имеют равный масштаб; тогда не происходит, например, искажения кругов. Для обеспечения равного масштаба следует выбрать пункт Axes Equal. Рисование сложных областей по заданному чертежу облегчается, если включить привязку к сетке, для чего следует выбрать в меню Options пункт Snap. Теперь вершины прямоугольников и квадратов, центры окружностей и эллипсов при перетаскивании и рисовании могут находиться только на линиях сетки. Рамки, ограничивающие эллипсы и окружности, также размещаются на линиях сетки. Вершины многоугольников при их рисовании допустимы только в узлах. Выбор шага сетки, соответствующего размерам мелких элементов чертежа, позволяет существенно ускорить создание области. Использование функций PDE Toolbox Среда pdetooi с графическим интерфейсом пользователя предназначена лишь для облегчения доступа к ядру PDE Toolbox — набору более чем из пятидесяти функций, реализующих основные этапы решения задачи от задания области, уравнения и граничных условий до визуализации результата. Механизм вызова данных функций скрыт от пользователя при работе в среде. Многие функции имеют достаточно сложный интерфейс, их использование требует понимания метода конечных элементов. Следующие разделы посвящены описанию функций, связанных с основными этапами решения граничных задач для дифференциальных уравнений. Задание геометрии области Имеются два способа определения геометрии области, в которой решается задача. Первый заключается в параметрическом задании частей границ области в файл-функции, имеющей определенный формат. Второй, более простой способ, состоит в задании области в среде pdetooi, последующем экспорте информации в переменные рабочей среды и преобразовании в формат, понятный другим функциям Toolbox. Нарисуйте в среде pdetooi прямоугольник шириной два и высотой один, центр которого расположен в начале координат. Выберите в меню Draw пункт Export Geometry Description, Set Formula, Labels..., появляется диалоговое окно Export, изображенное на рис. 14.20. Данное окно предлагает со Глава 14. Решение зада“ математической физики 671 хранить CSG-модель (конструктивную блинную геометрию) в глобальных переменных рабочей среды, а именно: □ матрицу геометрии области (Geometry description matrix) в массиве gd; П формулу связи геометрических примитивов в строке sf; П соответствие между столбцами gd и названиями областей в sf в массиве ns. Нажмите ОК и займитесь изучением содержимого экспортированных массивов. Рис. 14.20. Диалоговое окно Export Число столбцов матрицы геометрии области gd совпадает с числом геометрических примитивов, составляющих область. В рассматриваемом примере матрица состоит из одного столбца, соответствующего прямоугольнику. Выведите содержимое gd в окно рабочей среды; » gd gd = 3.0000 4.0000 -1.0000 1.0000 1.0000 -1.0000 0.5000 0.5000 -0.5000 -0.5000 Первый элемент столбца определяет принадлежность определенному ieo-метрическому примитиву. Всего допустимы четыре типа геометрических 672 Часть IV. Использование Toolbox и решение прикл адных задач примитивов: круг, многоугольник, прямоугольник и эллипс. Первый элемент, равный трем, означает, что данный столбец соответствует прямоугольнику, элемент второй строки равен числу сторон. Очевидно, что в прямоугольнике четыре стороны, но прямоугольник является частным случаем многоугольника, формат хранения которого описан ниже. В остальные элементы столбца записаны координаты вершин прямоугольника. Первый элемент столбца матрицы геометрии области, соответствующей кругу, равен единице, второй и третий являются координатами центра, а четвертый— радиусом. В случае эллипса первый элемент равен четырем, далее хранятся координаты центра и величины полуосей, а последний шестой элемент содержит угол поворота. Многоугольник идентифицируется двойкой в первом элементе вектора, число сторон записало во второй элемент, а далее следуют координаты вершин в порядке их создания. Функции, связанные с триангуляцией и заданием граничных условий, используют другой формат описания геометрии области — матрицу декомпозиционной геометрии (Decomposed Geometry matrix). В данном формате хранится информация о частях границы области, которыми могут быть: отрезок, часть дуги окружности или эллипса. Переход от конструктивной блочной геометрии к декомпозиционной производится при помощи функции decsg, во входных аргументах которой задаются переменные с информацией о конструктивной блочной геометрии, в рассматриваемом случае gd, sf и ns. Выходным аргументом decsg является матрица декомпозиционной геометрии. Каждый столбец матрицы декомпозиционной геометрии отвечает элементу границы. Преобразуйте экспортированные величины, вызвав decsg, например, из командной строки: dl = decsg(gd, sf, ns) dl = 2.0000 2.0000 2.0000 2.0000 -1.0000 1.0000 1.0000 -1.0000 1.0000 1.0000 -1.0000 -1.0000 0.5000 0.5000 -0.5000 -0.5000 0.5000 -0.5000 -0.5000 0.5000 0 0 0 0 1.0000 1.0000 1.0000 1.0000 Очевидно, что прямоугольник представляется четырьмя отрезками. Двойка в первом элементе столбца означает, что столбец соответствует отрезку, второй и третий элементы содержат абсциссы начала и конца отрезка, а четвертый и пятый— ординаты. Преобразование в декомпозиционную геометрию предполагает, что вся область разбивается на некоторые непере-секающиеся шнималъные подобласти. Идентификаторы подобластей, расположенных слева и справа от части границы (в данном случае отрезка). Глава 14. Решение задач математической физики 673 записаны в шестом и седьмом элементе. Положение определяется движением от начала части Гранины до ее конца, в случае области из одного прямоугольника он же и является минимальной подобластью, поэтому слева от частей границ (отрезков) нег подобластей. Столбцы матрицы декомпозиционной геометрии, соответствующие дугам эллипса или окружности, содержат в остальных элементах информацию о центре и радиусе окружности или величине полуосей эллипса и угле поворота. Функция pdegpiot предназначена для вывода области в отдельное графическое окно, входным аргументом pdegpiot является матрица или файл-функция декомпозиционной геометрии. В рассматриваемом примере pdegpiot (dl) отображает оси, содержащие прямоугольник. Структуру файл-функции с описанием декомпозиционной геометрии проще всего понять, автоматически создав ее при помощи функции wgeom. Входными аргументами wgeom являются матрица декомпозиционной геометрии и имя М-файла, в который следует записать файл-функцию. Выходной аргумент принимает значение минус единица при неудачной попытке записи в файл. Сгенерируйте файл-функцию irecgeom, КОТОрЙЯ ОПИСЬГВйСТ ПрЯМОуГОЛЬНуЮ область, задаваемую матрицей dl. Убедитесь, что в глобальной переменной dl содержится матрица декомпозиционной геометрии области, создание которой описано выше. В командном окне выполните wgeom(dl, 'reegeom'). В текущем каталоге MATLAB появился файл recgeom.m, структура котового приведена в листинге 14.1. Листинг 14.1. Файл-функция reegeom геометрии области function [х, у] = reegeom(bs, s) %RECGEOM Gives geometry data for the reegeom PDE model. % NE = RECGEOM gives the number of boundary segments % D = RECGEOM(BS) gives a matrix with one column for each boundary % segment specified in BS. % Row 1 contains the start parameter value. % Row 2 contains the end parameter value. % Row 3 contains the number of the left-hand regions. % Row 4 contains the number of the right-hand regions. % [X, Y] = RECGEOM(BS, S) gives coordinates of boundary points. % BS specifies the boundary segments and S the corresponding parameter % values. BS may be a scalar. nbs - 4 if nargin == 0, 674 Часть IV. Использование Toolbox и решение прикладных задач х - ribs; % number of boundary segments return =nd d = [ 0000% start parameter value 1 1 1 1 % end parameter value 0 0 0 0 % left hand region 1 1 1 1 % right hand region 1; bsl = bs(:) ’ ; if find(bsl < 1 | bsl > nbs)', error('Non-existent boundary segment number') end if nargin == 1, X = d(: , bsl) ; return end x = zeros(size(s)); у = zeros(size(s)); (m, n] = size(bs); if n == 1 & n == 1, bs = bs*ones(size(s)); % expand bs eiseif m ~= size(s, 1) | n -= size(s, 2), error('bs must be scalar or of same size as s’); end if -isempty(s), ? boundary segment 1 li = findtbs == 1); if length(ii) x(ii) = (1 - (-l))*(s(ii) - d(l, 1)) / (d(2, 1) - d(l, 1)) + (-1); y(ii) = (0.5 - (0.5))*(s(ii) - d(l, 1)) / (d(2, 1) - d{l, 1)) + (0.5); end % boundary segment 2 ii = findfbs == 2); if length(ii) x(ii) = (1 - (1))*(s(ii) - d(l, 2)) / (d(2, 2) - d(l, 2)) + (1); y(ii) = (-0.5 - (0.5))*(s(ii) - d(l, 2)) / (d(2, 2) - d(l, 2)) + (0.5); end Глава 14 Решение задач математической физики 675 % boundary segment 3 ii = findfbs == 3); if length(ii) x(ii) = (-1 - (l))*(s(ii) - d(l, 3)) / (d(2, 3) - d(l, 3)) + (1) ; y(ii) = (-0.5 - (-0.5)>*(s(ii) - d(l, 3)1 I (d(2, 3) - d(l, 3)) + (-0.5); end % boundary segment 4 ii - find(bs == 4) ; if length(ii) x(ii) = (-1 - (-l))*(s(ii) - d(l, 4)) / (d(2, 4) - d(l, 4)) + (-1); y(ii)=(0.5 - (-0.5))*(s(ii) - d(l, 4)) I (d(2, 4) - d{l, 4)) + (-0.5); end end Файл-фунхция recgeom предназначена для получения координат х и у точек части границы с номером bs, соответствующих значению параметра s. Локальная переменная nbs содержит число частей границы, а матрица d — информацию о параметризации. Число столбцов d равно числу у частков границы, в первый и второй элементы каждого столбца занесены начальное и конечное значения параметра ноль и единица, в третьем и четвертом элементе записаны номера примитивов, расположенных по левую и правою сторону от участка границы (по направлению возрастания параметров). В рассматриваемом случае имеется один примитив — сам прямоугольник — с номером один В блоках, которым предшествуют комментарии % boundary segment 1 - % boundary segment 4, происходит поиск нужной части границы, вычисление значений параметрически заданных функций и запись их в массивы х и у. Длины массивов х, у совпадают с длиной входного массива s, содержащего значения параметра. Умение создавать файл-функции с декомпозиционной геометрией области необходимо в том случае, когда область не может быть сконструирована только с использованием стандартных геометрических примитивов, таких как круг, эллипс, квадрат, прямоугольник или многоугольник. Один из возможных подходов, удобный для начинающих пользователей, описан ниже. В качестве примера рассмотрим написание файл-функции для области, приведенной на рис. 14.21. Область является криволинейным четырехугольником с верхней границей, задаваемой параболой >| = ®5х2. Нижние углы прямые. 676 Часть IV. Использование Toolbox и решение прикладных задач Последовательность действий, направленных на получение файл-функции с декомпозиционной геометрией, приведена ниже. I. Нарисуйте прямоугольник с центром в начале координат, шириной два и высотой один в среде pdetool. 2. Экспортируйте геометрию области из среды pdetool в глобальные массивы gd, sf и ns. 3. Перейдите к матрице декомпозиционной геометрии при помощи dl = decsg(gd, sf, ns). 4. Сгенерируйте файл-функцию my dr,ma in с декомпозиционной геометрией области, используя ВЫЗОВ wgeom (dl, 'mydomain'). 5. Откройте файл mydomain.m в редакторе М-файлов. Найдите нужный условный оператор if, в котором определяется параметрическое задание верхней стороны прямоугольника, и замените операторы присваивания на те, которые обеспечивают требуемый вид части границы. Вызов функции mydomain из командной строки с первым аргументом, равным номеру части границы, и со вторым — значением параметра из интервала от нуля до единицы (например, 0.5)— позволяет установить номер нужной части границы. Последовательно задавайте номера границ и следите за значениями х и у. Получение координат х и у точки, принадлежащей искомому участку, означает, что найден номер части границы, подлежащей изменению. В рассматриваемом примере верхняя сторона прямоугольника имеет номер, равный единице: » [х, у] - rnydomainfl, 0.5) х = 0 У = 0.5000 Гпава 14. Решение задач м тематической физики 677 Блок операторов, описывающих верхнюю сторону прямоугольника, снабжен в автоматически сгенерированной файл-функции mydomain комментариями % boundary segment 1. В данном блоке содержится линейная зависимость абсцисс и ординат точек от параметра s. Первый столбец матрицы d, инициализируемой в начале файл-функции, свидетельствует о том, что начальное значение параметра равно нулю, а конечное — единице. Направление границы, соответствующее увеличению параметра, легко устанавливается из параметрического задания (в данном случае слева направо). Измените операторы присваивания в блоке % boundary segment 1, обеспечив требуемую криволинейную границу в виде параболы. Очевидно, что параболический участок границы задается параметрическими зависимостями л = 2л-1, у = 0.5(25-I)3. Операторы присваивания приведены в листинге 14.2. Листинг 14.2. Параметрическое задание параболического участкч границы x(ii) - 2*s(ir) - 1; y(ii> = 0.5*(2*s(ii) - 1). л2 Сохраните файл-функцию и убедитесь, браженной на рис. 14.21. Постройте pdegpiot. Вызов pdegpiot('mydomain') го окна с границей (рис. 14.22). что она соответствует области, изогеометрию области при помощи приводит к появлению графическо- Рис. 14.22. Геометрия области (pdegpiot ('mydomain')) 678 Часть IV. Использование Toolbox и решение прикладных задач Вышеописанный подход позволяет просто создать файл-функцию с декомпозиционной геометрией области, изменяя автоматически сгенерированную файл-функцию для нарисованной заготовки в среде pdetool. Наличие матрицы декомпозиционной геометрии или файл-функции открывает доступ ко многим возможностям PDE Toolbox, в частности, к автоматической триангуляции и уменьшению шага сетки. Триангуляция Функция initmesh триангулирует плоскую область, ее входным аргументом является матрица декомпозиционной геометрии. Три выходных аргумента (массива) содержат информацию о триангуляции. Вызов (р, е, t] = initmesh (dl) ; приводит к заполнению трех матриц р, е и t. В матрицу р, состоящую из двух строк, заносятся координаты узлов сетки. Матрица е содержит информацию об узлах, расположенных на границах минимальных подобластей, в матрице t хранится соответствие между локальной и глобальной нумерациями узлов. Понять структуру массивов р, е и t проще всего следующим образом. В среде pdetool следует инициализировать сетку, например, для прямоугольника, причем лучше установить достаточно крупный размер стороны элемента в диалоговом окне Mesh Parameters. Пронумеровать узлы и элементы позволяет выбор пунктов Show Node Labels и Show Triangle Labels меню Mesh. Далее необходимо экспортировать сетку в глобальные массивы при помощи пункта Export Mesh..., их содержимое можно посмотреть в рабочей среде. Функция initmesh может содержать дополнительные аргументы, задаваемые парами: название свойства, значение. Например, свойство нтах означает максимально допустимое значение длины стороны треугольного элемента. Полученную сетку можно отобразить в отдельном окне при помощи pdamesh, входными аргументами которой являются вышеперечисленные массивы. Последовательность команд, приведенная ниже [р, е, t] = initmeshfdl, ’нтах', 1.0); pdemesh(p, е, t) инициализирует и выводит сетку, приведенную на рис. 14.23. Гпава 14. Решение задач математической физики 679 Рис. 14.23. Сетка с максимально допустимой длиной стороны элемента, равной единице Функция refinemesh служит для уменьшения шага сетки. Первым входным аргументом является матрица декомпозиционной геометрии, далее задаются массивы с информацией о триангуляции, в выходных аргументах возвращаются массивы, соответствующие измельченной сетке. По умолчанию сторона каждого элемента делится пополам, каждый треугольный элемент исходной сетки разбивается на четыре части. Команды, приведенные ниже, производят вышеописанное уменьшение шага сетки (сравните рис. 14.23 и рис. 14.24). [pl, el, tl] = refinemesh(dl, p, e, t); pdemesh(pl, el, tl) Функция refinemesh позволяет задать ряд дополнительных параметров, управляющих процедурой дробления сетки, в частности, делить только некоторые треугольные элементы или минимальные подобласти Кроме того, можно выбрать другой алгоритм уменьшения шага сетки, который делит на две равные части наибольшую сторону конечного элемента. Первым входным аргументом может быть не только матрица декомпозиционной геометрии, но и имя файл-функции, описывающей декомпозиционную геометрию области. 580 Часть IV. Использование Toolbox и решение прикладных задач Рис. 14.24. Сетка с уменьшенным шагом (refinemesh) Г раничные условия и коэффициенты уравнения Граничные условия в PDE Toolbox задаются двумя способами, либо при помощи матрицы граничных условий (Boundary Condition matrix), либо в файл-функции. Число столбцов матрицы граничных условий совпадает с числом столбцов в матрице декомпозиционной геометрии, т. е. каждый столбец отвечает части границы области. На каждой части границы может быть задано условие одного типа: Дирихле hu =г, или обобщенное условие Неймана и • (cVz/) + qu = g. Разберем структуру матрицы храничных условий. Убедитесь, что среда pdetooi настроена на решение эллиптического уравнения общего вида. Поставьте на всех границах прямоугольника граничное условие Дирихле, правая часть которого зависит от координат, например, х2 + у2. Не забудьте использовать поэлементные операции, т. е. в диалоговом окне Boundary Condition следует ввести единицу в строку h и х.Л2 + у. "2 в строку г. Экспортируйте в рабочую среду матрицу граничных условий, выбрав в меню Boundary пункт Export Decomposed Geometry, Boundary Cond's. Появляется диалоговое окно Export, в котором по умолчанию стоит массив ь для хра I лава 14. Решение задач математической физики 681 нения матрицы граничных условий и, одновременно, предлагается сохранить декомпозиционную геометрию в д. Получение декомпозиционной геометрии из матрицы геометрии области при помощи функции decsg было описано выше. Сейчас нам понадобится матрица ь граничных условий Нажмите ОК, в рабочей среде появился двумерный массив Ь Ь = 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 9 9 9 9 48 48 48 48 48 48 48 48 49 49 49 49 120 120 120 120 46 46 46 46 94 94 94 94 50 50 50 50 43 43 43 43 121 121 121 121 46 46 46 46 94 94 94 94 50 50 50 50 Структура матрицы граничных условий достаточно сложная, она приспособлена для хранения граничных условий в задачах, описываемых системой дифференциальных уравнений. Каждый столбец соответствует части границы. В рассматриваемом случае, когда область является прямоугольником с граничными условиями Дирихле с г = х2 + у2 и h = 1 на каждой стороне, матрица состоит из четырех одинаковых столбцов. Столбец условно делится на две части, в нижней части записаны формулы коэффициентов 1ранич-ных условий, причем каждый символ строки с формулой для коэффициента хранится в последовательно идущих элементах. Верхняя часть столбца матрицы граничных условий содержит информацию о типе граничных условий и длинах формул. Обратите внимание, что в нижней части столбца содержатся коды символов, составляющих формулы Для того чтобы отобразить в командное окно сами символы, следует применить функцию char. В случае уравнения (а не системы) формулы хранятся в элементах столбца, начиная с 682 Часть IV. Использование Toolbox и решение прикладных задач седьмого, в чем несложно убедиться, преобразовав элементы нижней части матрицы из кодов в символы: » char(Ь(7:end,:)) ans _ 0000 0000 1111 хххх 2222 + +++ УУУУ 2222 Первые два элемента зарезервированы под коэффициенты условия Неймана (равны нулю, поскольку поставлено условие Дирихле). Третий элемент содержит значение Л, а остальные (см. сверху вниз)— символы выражения х.Л2 + у.Л2. Формат матрицы граничных условий описан в документации к PDE Toolbox, содержащейся в файле pde.pdf. Впрочем, достаточно легко разобраться в данном формате, задавая граничные условия Дирихле и Неймана и отображая символы матрицы граничных условий в командном окне. Коэффициенты уравнения и правая часть задаются несколькими способами, в частности, для эллиптического уравнения коэффициенты a , b и с мщут быть: D константами: □ строками формул, содержащими переменные х и у и знаки поэлементных операций (для коэффициентов нелинейных уравнений используется переменная и); П массивами со значениями для каждого конечного элемента. При решении систем уравнений коэффициенты системы и граничных условий являются матрицами. Солверы Приближенным решением граничной задачи является вектор значений в узлах сетки. Следует иметь в виду, что предварительно должна быть задана Глава 14. Решение задач математической физики 683 матрица или файл-функция граничных условий ь. триангуляция в массивах р, е, t и коэффициенты уравнения (разумеется, переменные могут называться по-другому). Если решается нестационарная задача, то необходимо указать решение в начальный момент времени и вектор со значениями времени, в которые следует найти решение. Некоторые солверы требуют задания декомпозиционной геометрии. Солверы реализованы в файл-функциях с доста точно сложным интерфейсом. PDE Toolbox обладает несколькими солверами для нахождения решения различных типов задач: □ assempde — для эллиптических уравнений и систем; □ parabolic — для параболических уравнений и систем; П hiperbolic — для гиперболических уравнений и систем; □ pdenonlin — для нелинейных стационарных уравнений; □ adaptmesh — для адаптивной генерации сетки и нахождения решения эллиптических уравнений и систем с заданной точностью; П pdeeig — для решения эллиптических задач на собственные значения. Интерфейс солвера assempde является наиболее универсальным, он позволяет не только решить систему линейных уравнений метода конечных элементов, исключая граничные условия Дирихле, но и получить матрицу жесткости, матрицу масс и вектор нагрузки, или все составные части матрицы и вектора системы метода конечных элементов. Первым входным аргументом assempde задается матрица граничных условий, например ь, или имя файл-функции с граничными условиями, например boundcond, далее указываются матрицы с информацией о триангуляции и коэффициенты уравнения. Вызовы файл-функции с одним выходным аргументом u = assempde(Ь, р, е, t, с, а, £); u = assempde('bouncond', р, е, t, с, а, £); приводят к записи в вектор и значений решения в узлах сетки, координаты которых храня гея в р. Сборка матрицы и вектора системы без ее решения происходит при обращении к assempde с двумя выходными аргументами: [К, F] = assempde(b, р, е, t, с, a, f); [К, F] = assempdef'bouncond', р, е, t, с, a, f); Остальные способы вызова assempde подробно описаны в документации по PDE Toolbox. Использование всех возможностей assempde требует понимания того, как учитываются граничные условия при вычислении магриц и векторов правых частей элементов. Файл pde.pdf содержит разд. "The Finite Element Method" с необходимой информацией. 684 Часть IV. Использование Toolbox и решение прикладных задач Солверы parabolic и hyperbolic сразу выдают матрицу с решением. Входные аргументы данных солверов такие же, как у assempde; кроме того, задаются вектор значений решения иО в начальный момент времени (в случае гиперболического уравнения еще и вектор uto со значением производной решения), вектор tiist моментов времени, в которые требуется нанги решение, и коэффициент d уравнения при производной по времени. Каждый столбец матрицы и есть вектор со значениями приближенного решения в узлах сетки в соответствующий момент времени, указанный в tiist: u = parabolic(uO, tiist, b, p, e, t, c, a, f, d) u = hiperbolicfuO, utO, tiist, b, p, e, t, c, a, f, d) При решении задач на собственные значения солвером pdeeig требуется указать вектор г длины два с границами интервала; на котором разыскиваются собственные значения. Левая граница интервала может быть минус бесконечностью (-inf) (v, 1] = pdeeig (b, p, e, t, c, a, d, r) Выходным аргументом pdeeig являются матрица, каждый столбец которой содержит значения собственной функции в узлах сетки, определяемых массивом р, и 1 — вектор собственных значений. Солвер pdenonlin, предназначенный для решения нелинейных стационарных задач, имеет те же входные параметры, что и assempde [u, res] = pdenonlinfb, р, е, t, с, a, f) Выходными аргументами являются вектор решения и норма вектора невязки при решении нелинейной задачи методом Ньютона. Допотнительные аргументы солвера pdenonlin, управляющие вычислительным процессом, задаются парами: название, значение. Таблица возможных значений приведена в документации к PDE Toolbox. Панель диалогового окна Solve Parameters среды pdetool, соответствующая нелинейному солверу, позволяет получить представление о возможных дополнительных опциях солвера pdenonlin. Эффективное нахождение решения, имеющего большие градиенты, требует адаптивного изменения сетки. Солвер adaptmesh реализует адаптивный алгоритм решения эллиптического уравнения. Простой вызов солвера с указанием декомпозиционной геометрии д, матрицы граничных условий ь, коэффициентов уравнения с, а и правой части f [и, р, е, с] - adaptmesh(g, b, с, a, f) Гпава 14. Решение задач математической физики 685 приводит к поиску решения с установками солвера, принятыми по умолчанию. Дополнительные аргументы, задаваемые парами свойство, значение, позволяют определить максимально допустимое число конечных элементов, начальную триангуляцию, способ дробления элементов и использование нелинейного солвера. Солвер adaptmesh возвращает в выходных аргументах вектор решения и и массивы р,е и t, содержащие информацию о расчетной сетке. Визуализация результата Функции pdegpiot и pdemesh предназначены для графического отображения геометрии области и сетки, их использование описано в предыдущих разделах. Основной функцией для визуализации решения является pdeplot, которая позволяет управлять видом получаемых графиков ггрй помощи ряда дополнительных параметров. Функции pdecont и pdesurf. строящие линии уровня решения или трехмерный график, реализуют частные случаи обращения к pdeplot. Входными аргументами pdecont и pdesurf являются матрица р с координатами узлов, матрица t соответствия глобальной и локальной нумераций и вектор и со значениями решения в узлах. Четвертым дополнительным аргументом pdecont может являться вектор значений, которые требуется отобразить линиями уровня, или их число. Интерфейс функции pdeplot достаточно универсален Первые три входных аргумента являются массивами р, е и t с информацией о триангуляции. Далее задаются пары: свойство, значение (табл. 14.1). Таблица 14.1, Дополнительные параметрыpdeplot Свойство Значение xydata Вектор co значениями решения в узлах для построения двумерного графика xystyle off, flat, interp (по умолчанию) — способы заливки контуров contour on, off (по умолчанию) — отображение или скрытие контурных линий zdata Вектор со значениями решения в узлах для построения трехмерного графика colormap cool, hot, gray, bone,... — цветовые палитры mesh on, off (по умолчанию) — отображение конечнозлементной сетки colorbar off, on (по умолчанию) — вывод шкалы соответствия цвета и значения 686 Часть IV. Использование Toolbox и решение прикладных задач Таблица 14.1 (окончание) Свойство Значение title Строка с заголовком levels Число линий уровня или вектор со значениями решения, отображаемого линиями уровня Пример использования pdepiot приведен в следующем разделе, посвященном решению некоторой модельной задачи с использованием функций PDE Toolbox. Решение модельной задачи Рассмотрим решение модельной задачи для эллиптического уравнения д2и д2и 2 . —г-н---х- = -5я smra-sm2ny Эх2 а/ в прямоугольнике с центром в начале координат, высотой единица и шириной, равной двум. На сторонах прямоугольника поставлены однородные условия Дирихле. Известно точное решение и(х, у)-sin га-sin2ny. Требуется последовательно уменьшать шаг сетки и решать задачу, пока приближенное решение не будет отличаться от точного менее чем на 0.01. Задайте геометрию области и граничные условия в среде pdetooi и экспортируйте их в глобальные массивы g и ь из меню Boundary. Сгенерируйте два М-файла с декомпозиционной геометрией myg.m и граничными условиями myb.m при помощи функций wbound и wgeom. Алгоритм оформите в виде файл-функции modelexam, входными аргументами которой являются: имена файлов с геометрией области и граничными условиями и точность решения. В М-файл включите подфункцию для вычисления точного решения. Учтите, что данная подфункция предназначена для нахождения решения в узлах сетки и вызывается от массивов с координатами узлов, поэтому следует использовать поэлементное умножение. Листинг 14.3 содержит текст основной файл-функции modelexam и подфункции exsol, снабженный подробными комментариями. ........................ Ристмнг 14.3. Решение модельной задачи function modelexam(gfile, bfile, err) % Файл-функция находит решение модельной граничной % Задачи Дирихле для эллиптического дифференциального I лава 14. Решение задач математичек кой сЬизики 687 % уравнения в прямоугольной области, % Использование: % modelexani('файл с декомп. геом.', 'файл с гран, услов.', err) % Инициализация сетки с максимальной стороной элемента 0.2 [р, е, tl = initmesh(gfile, 'Hmax', 0.2); % Задание коэффициентов уравнения а = 0; С = 1; % Определение строки с формулой правой части уравнения f = ' 5*pi,’2*sin(pi*x) . *sin(2*pi*y) * ; % Организация циклического измельчения сетки, пока % не достигнута требуемая точность erhelp = 1; while erhelp > err % Измельчение сетки [р, е, t] = refinemesh(gfile, р, е, t); % Решение уравнения u = asseirpde(bfile, р, е, t, с, a, f) ; % Вычисление точного решения в узлах сетки, % абсциссы и ординаты узлов хранятся в строках матрицы р uex = exsol(р(1, :), р(2, :)); % Вычисление нормы погрешности приближенного решения (и является % вектор-столбцом, а подфункция exsol вызывается от строк, поэтому % вектор с точным решением необходимо транспонировать) erhelp = norm(u - uex', Inf); end % Решение найдено с требуемой точностью % Визуализация расчетной триангуляции и вывод контурного графика % решения, залитого цветом figure subplot(2, 1, 1) I demesh (p, e, t) subplot(2, 1, 2) pdeplcttp, e, t, 'xydata', u, 'colormap', 'gray', 'colorbar', 'off’) function z = exuol(x, y) % Подфункция для вычисления точного решения z ~ sin(pi*x).*sin(2*pi*y); 688 Часть IV Использование Toolbox и решены > гг укладных задач Вызов файл-функции niodelexamt'ixiyg', 'myb', 1.0е-02) приводит к появлению графического окна, в которое выводятся расчетная сетка и залитый цветом контурный график решения модельной задачи с требуемой точностью (рис, 14.25). Рис. 14.25. Расчетная сетка и решение модельной задачи PDEToolbox содержит несколько демонстрационных файлов: pdedemol.m— pdedemo8.m с решением различных задач. Данные примеры позволяют самостоятельно разобраться в возможностях PDE Toolbox. М-файл pdedeir.os.nl является файл-программой с интерфейсом командной строки, облегчающей доступ к каждому из примеров. Функции PDE Toolbox PDE Toolbox предоставляет в распоряжение пользователя около пятидесяти функций, предназначенных для реализации этапов решения задачи от задания геометрии области до визуализации результата. Данный раздел посвящен описанию функций, служащих для конструирования области и разбиения ее на конечные элементы. Информацию о функции всегда можно получить при помощи команды help. Детальное описание всех функций и реализованных в них алгоритмов имеется в справочной системе MATLAB по PDE Toolbox. Гпава 14. Решение задач математической физики 689 Создание геометрических примитивов Геометрический примитив может быть создан либо из меню среды pdetooi, либо при помощи соответствующей функции. Вызов функции приводит к добавлению соответствующего примитива в окно среды (если pdetooi не запущена, то появляется окно pdetooi и примитив отображается в нем). Последним дополнительным аргументом каждой функции может являться название примитива, заключенное в апострофы. Если название не задано, то используются стандартные имена: Cl, El, R1,... CJ pdecirc(xc, ус, г), pdecirc(хс, ус, г, label) —круг сЦвнгром В хс, ус и радиусом Г. □ pdeellip(xc, ус, a, b, phi), pdeellip(хс, ус, a, b, phi, label) — эллипс с центром в хс, ус и полуосями а и ь, повернутый вокруг центра на угол phi (задаваемый в радианах). □ pdepoly(vx, vy), pdepoly(vx, vy, label) — многоугольник с вершинами, абсциссы и ординаты которых указываются в vx и vy □ pderect([xmin xmax ymin ymax)), pderect([xmin xmax ymin ymax], label) — прямоугольник, определяемый координатами вершин. Геометрия области и триангуляция Некоторые функции преобразования геометрии области и разбиения области на конечные элементы были описаны ранее. Ниже приведен список всех имеющихся функций, реализующих геометрические алгоритмы. □ gstat = csgchk(gd) — проверка правильности задания матрицы gd геометрии области. Выходной аргумент является вектор-строкой, каждый элемент которой содержит информацию о соответствующем примитиве (структура матрицы геометрии области описана в разд "Заоание геометрии области”данной главы). □ dl = descsgtgd, sf, ns) — генерация матрицы di декомпозиционной геометрии области из матрицы геометрии gd, строки с формулой связи геометрических примитивов sf и матрицы соответствия столбцов gd с именами примитивов в формуле. Вызов desceg с двумя выходными аргументами [dl, bt] = descsgfgd, sf, ns) приводит к записи в bt информации о соответствии минимальных подобластей геометрическим примитивам. □ [newdl, newbtl] = csgdel(dl, bt)—удаление из матрицы dl декомпозиционной геометрии области всех границ между минимальными подобластями. Выходные аргументы содержат обновленную матрицу newdl декомпозиционной геометрии и таблицу связей примитивов и минимальных подобластей. 690 Часть IV. Использование Toolbox и решение прикла дныхз$ ^ач □ [р, е, t] = initmesh(gl), [р, е, t] = initmesh('mygeom') —инициализация сетки области, декомпозиционная геометрия которой задается матрицей или М-файлом. Возможно управление процессом инициализации сетки при помощи пар дополнительных параметров: свойство, значение. Параметр нтах устанавливает максимальную длину стороны треугольных элементов. Начальная триангуляция области создается с учетом геометрии области, вблизи более мелких объектов сетка гуще, чем в крупных. Значение параметра Hgrad определяет скорость роста размеров элементов при отдалении от мелких объектов. Значения Hgrad, близкие к единице (100%), приводят к медленному росту размеров, напротив, значения близкие к двум (200%), соответствуют достаточно быстрому увеличению размеров (рис. 14.26). Ряд параметров initmesh предназначен для визуализации этапов алгоритма построения триангуляции и улучшения ее качества, подробная информация об их использовании приведена в документации к PDEToolbox. Кроме того, функция jigglemesh реализует алгоритм улучшения триангуляции. Рис. 14.26. Влияние параметра Hgrad на размеры элементов О Функции poimesh (gl, nx, ny), poimesh('mygeom', nx, ny) служат для инициализации регулярной сетки на прямоугольной области, декомпозиционная геометрия которой задается матрицей или М-файлом. Число узлов по каждой из координат задается в пх и пу. Последовательность команд для прямоугольника, декомпозиционная геометрия которого описана файл-функцией myg {р, е, L] = poimesh('myg', 15, 10); pdemesh(р,е,t) приводит к регулярной сетке, изображенной на рис. 14.27. Функция poimesh предназначена только для прямоугольных областей. Глава 14. Решение задач математической физики 691 Рис. 14.27. Регулярная сетка в прямоугольнике □ [pl, el, tl] = refinemesh(р, е, t) — уменьшение шага сетки, задаваемой массивами р, е, t делением каждого треугольного элемента на четыре части. Массивы, соответствующие новой сетке, возвращаются в р, е, t. Возможно указание четвертого дополнительного аргумента ’longest' для измельчения сетки делением наибольшей части треугольника на две части, по умолчанию используется 'regular'. Исходная и преобразованные каждым из описанных способов сетки приведены на рис. 14.28. Рис. 14.28. Способы уменьшения шага сетки 23 Зад 130 Глава 15 Разреженные матрицы Матрицы, содержащие достаточно большое число нулевых элементов, называются разреженными. Разреженные матрицы часто встречаются в самых различных областях, например, при решении дифференциальных уравнений методом конечных элементов или конечных разностей, обработке изображений, в криптографии и оптимизационных задачах. Использование специальных способов размещения в памяти разреженных матриц и алгоритмов выполнения операций над ними существенно снижает затраты компьютерных ресурсов и уменьшает время вычислений. Строго говоря, матрица является разреженной, если специальные алгоритмы в сочетании с компактной схемой хранения ее элементов дают выигрыш по сравнению с обычными методами, применяемыми к полностью заполненным матрицам. Работа с разреженными матрицами Разреженные матрицы содержат значительное число нулевых элементов по сравнению с ненулевыми. При большой размерности матрицы хранить все элементы, включая нулевые, нет смысла. Достаточно записать в память только ненулевые значения и информацию об их положении в матрице. Очевидно, эффект будет достигаться лишь тогда, когда для запоминания значений ненулевых элементов и дополнительных данных потребуется меньше памяти и время выполнения алгоритмов, использующих эти данные, будет меньше времени выполнения операций над полностью заполненными матрицами. В качестве примера рассмотрим одну из возможных схем хранения, реализованную в MATLAB Схема хранения Разреженные матрицы в MATLAB помещаются в специальные переменные типа double array (sparse). Ненулевые элементы матриц хранятся по столбцам сверху вниз, для каждого элемента запоминается номер строки и Глава 15. Разреженные матрицы 693 столбца, соответствующие его положению в исходной полностью заполненной матрице. Задайте из командной строки прямоугольную матрицу размера пять ча шее ть‘ » А = [5 0 -3 0 0 0 0 -2 0 0 2 0 0 0 1 0 0 0 0 0 0 0 0 0 9 7 0 0 0 0]; Компактное представление an полностью заполненной матрицы а позволяет получить функция sparse: » AN = sparse(А) AN = (1, 1) 5 (5, 1) 9 (2, 2) -2 (5, 2) 7 (1, 3} -3 (3, 3) 1 (2, 5) 2 Первый столбец an содержит пары (i, j) с номерами строк и столбцов, а второй— значения ненулевых элементов исходной матрицы A(i, j). Функция sparse последовательно просматривает элементы каждого столбца, начиная с первого, и записывает в an найденные ненулевые элементы вместе с соответствующими парами индексов. Схему хранения на примере одного элемента матрицы поясняет рис. 15.1. Рис. 15.1. Схема хранения Обратите внимание, что вышеописанная схема существенно экономит память, выделяемую под хранение матрицы. Действительно, под массив а от- 694 Часть IV. Использование Toolbox и решение прикладных задач водится 5 6 = 30 ячеек с вещественными числами, каждая размера 8 байт, итого для записи а требуется 30 8 = 240 байт. Массив an содержит 7 • 2 - 14 ячеек с целыми числами (индексами) и 7 — с вещественными. Поскольку целое число занимает 4 байта, то для хранения an выделяется 14-4 + 7- 8 = 112 байт, т, е. более чем в два раза меньше, чем для а. Можно было и не производить вычисление затрат памяти, а посмотреть информа- цию о массивах в окне Workspace ваться командой whos: » whos A AN Name Size A 5x6 AN 5x6 браузера рабочей среды или воспользо- Bytes Class 240 double array 112 double array (sparse) Для pea пьных вычислительных задач часто оказывается, что число ненулевых элементов имеет порядок квадратного корня из общею числа всех элементов матрицы, поэтому разреженная форма хранения дает существенные преимущества по сравнению с обычным представлением матрицы. Функция full позволяет вернуться к обычному представлению разреженной матрицы. Очевидно, что результат совпадает с исходной матрицей а: » Af = full(AN) Af = 5 0 -3 0 0 0 0 -2 0 0 2 0 0 0 1 0 0 0 0 0 0 0 0 0 9 7 0 0 0 0 Разумеется, для инициализации компактного представления не требуется сначала создавать заполненную матрицу, указывая нулевые и ненулевые элементы, а затем переходить к разреженной структуре при помощи sparse. Информация о расположении ненулевых элементов и их значения достаточны ДЛЯ создания массива типа double array (sparse). Создание разреженных матриц Функция sparse предоставляет возможность непосредственного создания массива типа double array (sparse), соответствующего разреженной матрице. ()бращение к sparse выглядит следут >щим образом: AN = sparse(irow, jeol, nzer, m, n) Здесь irow— вектор строчных индексов ненулевых элементов матрицы, а jeol— вектор столбцевых индексов ненулевых элементов матрицы, которые помещены в вектор nzer. В последних аргументах m и п задаются разме Глава 15 Разреженные матрицы 695 ры исходной полностью заполненной матрицы. Сконструируйте компактное представление прямоугольной матрицы А размера пять на шесть, определенной в предыдущем разделе. Обратите внимание, что порядок элементов в массивах irow, jeci и nzer должен быть одинаковым. Очевидно, что следует выполнить последовательность команд, приведенную ниже: » irow = [1 5 2 5 1 3 2J; » jcol =[1122335]; » nzer =[59-27-31 2]; » AN = sparse(irow, jcol, nzer, 5, 6) AN “ (1, 1) 5 (5, 1) 9 (2, 2) -2 (5, 2) 7 (1, 3) -3 13, 3) 1 (2, 5) 2 Произведите проверку, выведите полное представление для an, используя full (AN). Обход по столбцам в заполненной матрице при поиске ненулевых элементов является необязательным. Можно просматривать каждую строку и формировать требуемые векторы irow, jcol и nzer, результат будет тот же самый. » irow = [1122355); » jcol = [1325312]; » nzer =[5-3-2219 7]; » AN = sparse{irow, jcol, nzer, 5, 6); Более того, можно просматривать элементы разреженной матрицы в произвольном порядке, важно только правильно указать номера строковых и столбцевых индексов ненулевых элементов в массивах irow, jcol. Следующий способ инициализации компактного представления an матрицы а эквивалентен приведенным выше вариантам. » irow = [1 232155]; » jcol = [3235121]; » nzer =[-3-212579]; » AN = rparse(irow, jcol, nzer, 5, 6); Задание аргументов функции sparse имеет ряд особенностей. Если какие-либо ненулевые элементы имеют одинаковые позиции, т. е. соогветсзвую-щие им пары с номерами строк и столбцов совпадают, го происходит сложение данных элементов и запись их суммы в указанную парой индексов позицию. Например, при конструировании компактной формы хранения в 696 Час: ь IV. Использование Toolbox и решение прикладных задач пятую строку первого столбца кроме девяти добавьте элемент, равный десяти, занеся в массивы irow, jcol и nzer соответствующие числа, в результате элемент матрицы с индексами пять и один будет равен девятнадцати: >> irow » jcol » nzer » AN = » full' = [12321555]; = [32351211]; =[-3-212579 10],- sparse(irow, (AN) jcol. nzer. 5, 6) ; ans = 5 0 -3 0 0 0 0 -2 0 0 2 0 0 0 1 0 0 0 0 0 0 0 0 0 19 7 0 0 0 0 Нулевые элементы, записанные в nzer, пропускаются при создании функцией sparse компактной формы хранения разреженной матрицы. В этом можно убедиться при помощи функции find, которая допускает вызов не только от массивов типа double array, но и double array (sparse! и возвращает строчные и столбцевые индексы ненулевых элементов и их значения: » irow = [1524345132]; » jcol = [1 1 2 5 2 6 2 3 3 5); » nzer = [5 9 -2 0 0 0 7 -3 1 2); » AN = sparse(irow, jcol, nzer, 5, 6) ; » [ir, jr, nz] = find(AN) Интерфейс функции sparse поддерживает обращение к ней с переменным числом входных аргументов. Если размеры матрицы m и п не указаны, то в качестве них будут использоваться максимальные значения компонентов векторов irow и jcol. Однако при таком вызове sparse следует соблюдать осторожность. Попытка создать, например, квадратную матрицу размера два, в которой ненулевые элементы расположены только в первой строке, при помощи следующих команд приведет к неверному результату: » irow = [1 1] ; >> jcol - [12]; » nzer = [2 3] ; » SN = sparse(irow, jcol, nzer) » fuLl(SN) ans - 2 3 Гпава 15. Разреженные матрицы 697 Вместо квадратной матрицы получилась прямоугольная размером один на два, поскольку максимальный элемент вектора irow равен единице. Можно воспользоваться тем обстоятельством, что нулевые элементы в nzer игнорируются, и добавить один фиктивный элемент, равный нулю, который расположен в правом нижнем углу матрицы: » irow = [1 1 2]; » jeol = [122]; » nzer =[230]; » SN = sparse,irow, jeol, nzer); » full(SN) ans = 2 3 0 0 Дополнительный шестой аргумент sparse указывает на количество элементов, выбираемых из irow, jeol и nzer, для конструирования компактной формы. Матрица, записанная в компактной форме в текстовом файле, может быть считана командой load и затем преобразована функцией speonvert в массив типа sparse array. Файл должен состоять из трех столбцов, в первых двух записаны строковые и столбцевые индексы ненулевых элементов, а в третьем — их значения. Содержимое текстового файла spmatr.dat для матрицы а из данного раздела приведено в листинге 15.1. .................—.................. — .... • • " ’-J--............... Листинг 15.1. Текстовый файл с компактной формой хранения разреженной матрицы ................; 115 5 19 2 2-2 5 2 7 13-3 3 3 1 2 5 2 Считайте данные из файла spmatr.dat в некоторый массив и преобразуйте их в компактною форму хранения: » s = load('spmatr.dat'); » А = speonvert(s); 698 Часть IV. Использование Toolbox и решение прикладных задач Примечание Элементы матрицы могут быть комплексными. Использование sparse аналогично случаю вещественных матриц, вектор п*ег в функции sparse должен содержать комплексные элементы. Импортирование комплексной матрицы из файла имеет одну особенность — файл должен иметь четыре столбца, причем первые два содержат строчные и столбцевые индексы ненулевых элементов матрицы, а третий и четвертый — их вещественную и мнимую части. Матрицы, ненулевые элементы которых расположены на главных или побочных диагоналях, часто хранят по диагоналям, записывая их в столбцы вспомогательной матрицы меньшего размера. Например, магрицу '5 0-3 0 О' 13 0-10 0 -2 22 0 1 8 можно упаковать следующим образом. Занесите в столбцы матрицы В диагонали А, начиная с нижней. Недостающие элементы побочных диагоналей следует дополнить нулями, помещая их в конец столбца для нижних диагоналей (поддиагоналей) и в начало столбца для верхних диагоналей (наддиагоналей): » В = [1 5 0 13 0 17-3 1 22 -1 0 8 -2]; Теперь создайте вектор d с информацией о соответствии столбца матрицы В номеру диагонали в Д, учтите, что главная диагональ имеет номер ноль, нижние диагонали нумеруются отрицательными числами, а верхние положительными. В рассматриваемом примере вектор d состоит из трех элементов: » d = [-1 0 2] ; Для перехода от формы хранения матрицы по диагоналям к компактной форме служит функция spdiags. Аргументами spdiags являются: массив ь с диагональными элементами, вектор d с номерами диагоналей и размеры формируемой матрицы: >> А = spdiags (В, d, 5, 5); Гпава 15. Разреженные матрицы 69ь Поскольку диагонали могут быть разной длины, то функция spdiags использует не все элементы столбцов матрицы В. При заполнении поддиа-1 оналей выбираются элементы, начиная сверху столбца, а при заполнении наддиагоналей — снизу. Убедитесь в правильности результата, выведите заполненную и разреженную формы матрицы Д. Указание в качестве входного аргумента в spdiags исходной матрицы Д приводит к решению обратной задачи, состоящей в записи диагоналей А в матрицу В, а информации об их расположении в вектор d: » [В, d] = spdiags (А) В = 15 0 13 0 17-3 1 22 -1 0 S -2 d = -1 0 2 Отображение шаблона матрицы, т. е. расположения ненулевых элементов, существенно облегчает исследование больших разреженных матриц. Функция spy выводит шаблон матрицы в графическое окно (см. разд. "Визуализация матриц " главы 2). Для просмотра отдельных блоков следует воспользоваться инструментом увеличения масштаба, расположенным на панели инструментов графического окна. Операции с разреженными матрицами Представление матрицы, хранящейся в массиве А, в полной форме имеет очевидную связь с соответствующими векторами irow, jcol и nzer. Для нахождения значения элемента исходной матрицы а с произвольными индексами i и j в ее компактном представлении требуется произвести поиск вспомогательного индекса к, удовлетворяющего условию: 1 = irow{к), j = jcol (к). Если такого номера к нет, то элемент матрицы нулевой, иначе A(i, j) = A(irow(k), jcol(к)) = nzer(к). MATLAB производит поиск автоматически, позволяя получать доступ к элементам матриц, хранящихся 700 Часть IV. Использование Toolbox и решение прикладных задач в массивах типа double array (sparse), так же как к обычным матри цам — при помощи двух индексов, заключаемых в круглые скобки. Например » AN(5, 1) ans = 9 » AN(4, 3) ans ~ О Реализация матричного сложения, вычитания и умножения для компактной формы хранения скрыта от пользователя. Данные операции производятся над разреженными матрицами так же, как над обычными, и в результате получается разреженная матрица, хранящаяся в массиве типа double array (sparse). Примечание Работа с разреженными массивами double array (sparse) с точки зрения пользователя не отличается от работы с обычными массивами double array, хотя на самом деле используются другие алгоритмы. Выполнение разных алгоритмов для полностью заполненных матриц и разреженных достигается за счет того, что sparse является разновидностью (атрибутом) double array. Если одна из матриц хранится в обычном массиве double array, то результат будет также переменной типа double array. Поэлементное умножение матрицы на матрицу приводит к разреженной матрице, если хотя бы один из множителей записан в компактной форме. Результатом поэлементного деления разреженной матрицы на полностью заполненную является разреженная матрица. Значения математических функций от разреженных матриц также являются разреженными, например, sin (an). Математические функции применяются поэлементно, так же как и к обычным матрицам. Обратите внимание на то, что после вычисления функции от разреженной матрицы или выполнения других операций с разреженными матрицами можно потерять преимущества компактного хранения и дальнейшей обработки этих матриц специальными алгоритмами. Рассмотрим пример вычисления функции cos от раннее введенной матрицы an, после чего преобразуем ее в полностью заполненную матрицу и сравним память, требуемую для хранения обоих массивов. » CAN=COS(AN) ; » whos CAN Name CAN Size 5x6 Byres Class 388 double array (sparse) Grand total is 30 elements using 388 bytes ''л^ва 15. Разреженные матрицы 701 » са = full(CAN); » whos са Name Size Bytes Class ca 5x6 240 double array Grand total is 30 elements using 240 bytes В резуль гате оказалось, что для хранения разреженной матрицы требуется больше памяти. Это связано с тем, что после вычисления косинуса матрица стала полностью заполненной, но хранится в форме разреженной матрицы, т. е. с избыточной информацией о номерах строчных и столбцевых индексов каждого элемента. В том случае, когда необходимо вычислить значения только от ненулевых элементов- следует использовать spfun. Входными аргументами spfun являются указатель на файл-функцию или встроенную математическую функцию (или ее имя, или inline-функция) и массив типа double array (sparse) с компактной формой хранения матрицы. Функция size возвращает число строк и столбцов матрицы, компактное представление которой указано во входном аргументе. 1 акие функции, как max, min и sum, возвращают разреженный вектор, т. е. матрицу из одной строки. Данные функции производят те же вычисления, что и над обычными матрицами, а тип результата соответствует типу входного аргумента. Рассмотрим пример с ранее построенной матрицей А: » gn = sparse(А) » max(gn) ans = (1. 1) 5 (1, 2) 3 (1, 3) 7 (1, 4) 22 (1, 5) 8 >> min(gn) ans = (1, 3) -3 (1, 4) -1 (1, 5) -2 Результат функции min объясняется тем, что в первых столбцах минимальные элементы нулевые. Конструирование блочных разреженных матриц и индексация при помощи вектора значений индексов не отличаются от случая полностью заполненных матриц. 702 Часть IV. Использование Toolbox и решение прикладных задач Структура разреженной матрицы определяет наиболее удобный способ ее формирования. Справочная система MATLAB содержит пример генерации симметричной разреженной матрицы, соответствующей разностной аппроксимации второй производной. На главной диагонали матрицы стоят числа-2, а на побочных диагоналях единицы. Сначала создаются векторы с диагональными элементами, затем на их основе — две разреженные матрицы, диагональная и с одной побочной диагональю. Искомая матрица является суммой диагональной матрицы, матрицы с побочной диагональю и транспонированной к ней. Создайте в качестве упражнения такую трехдиа-гональнуго матрицу (см. разд. Mathematics: Sparse Matrices: Creating Sparse Matrices справочной системы MATLAB). Информацию о разреженной матрице можно получить при помощи нескольких функций MATLAB. Как было упомянуто выше, функция find производит обратную операцию, по отношению к sparse — она заполняет векторы с номерами строк и столбцов ненулевых элементов и вектор ненулевых элементов. Вызов find с двумя выходными аргументами обеспечивает заполнение массивов индексов строк и столбцов: [irow, jcol] = find(AN), указание третьего выходного аргумента приводит к записи в него ненулевых элементов: [irow, jcol, nzer] = find (AN). Если требуется получить только ненулевые элементы, то проще воспользоваться функцией nonzeros, которая возвращает вектор ненулевых элементов разреженной матрицы, упорядоченных по столбцам. Количество ненулевых элементов устанавливается при помощи функции nnz. В приложениях часто встречаются ленточные матрицы, все ненулевые элементы которых расположены достаточно близко к главной диагонали. Важная характеристика ленточной матрицы В — ширина ее ленты b, которая определяется как 6 = max|z-y|. a, z*0 Возникает вопрос, как найз и ширину ленты матрицы, хранящейся в компактной форме, к примеру в массиве bn. Очевидно, что для вычисления ширины ленты достаточно обратиться к функции find и max: [irnw, jcol] = find(BN) ,-b - max(irow - jcol); При программировании собственных алгоритмов полезно убедиться, что матрица является разреженной, т. е. массивом типа double array (sparse). Данную проверку производит функция issparse, возвращая логическую единицу для разреженной матрицы и ноль — в противном случае. Глава 15. Разреженные матрицы 703 Задачи линейной алгебры Ряд функций MATLAB предназначен для решения задач линейной алгебры, таких как: факторизация матриц, решение систем линейных уравнений прямыми и итерационными методами, нахождение собственных чисел и векторов. Алгоритмы, реализованные в файл-функциях, учитывают разреженность матриц, благодаря чему являются очень эффективными. Данный раздел посвящен обзору основных алгоритмов, приведен пример использования профайлера MATLAB для получения воеменных загоат алгоритмов. Факторизация матриц MATLAB предлагает несколько классических способов факторизации разреженных матриц: полное и неполное разложение Холецкого, LtZ-разло-жение, -разложение. Факторизация разреженных матриц имеет свои особенности— следует стремиться к тому, чтобы получить как можно более разреженные множители, входящие в разложение. Продемонстрируем технику разложения разреженных матриц на примере разложения Холецкого симме гричной положительно определенной матрицы '4 1 0 0 1 0" 1 4 1 0 0 0 0 1 4 0 0 0 в = 0 0 0 4 0 1 • 1 0 0 0 4 1 0 0 0 1 1 4 к При помощи функции sparse создай! е массив bn с разреженной матрицей В. » irow = [1112223344555666]; » jeol = [1251232346156456]; » nzer = [4111411441141114]; » BN = sparse(irow, jeol, nzer, 6, 6) Найдите разложение Холецкого RTR = B данной матрицы, используя функцию choi, которая возвращает верхнюю треугольную матрицу R в компактной форме. >> R = Choi(BN); Отобразите шаблон матрицы R, используя команду spy, получающееся расположение ненулевых элементов приведено на рис. 15.2. Матрица Л, входящая в разложение, имеет довольно большой разброс ненулевых элементов относительно главной диагонали. На практике стремятся свести 704 Часть IV. Использование Toolbox и решение прикладных задач ширину ленты множителя разложения к минимуму, подбирая подходящие перестановки строк и столбцов в исходной матрице. Перед разысканием разложения Холецкого разреженной матрицы следует применить алгоритм упорядочения, обеспечивающий уменьшение ширины ленты. Данный алгоритм реализует функция symrcm, ее входным аргументом является разреженная матрица, подлежащая упорядочению, а выходным — вектор с перестановками номеров строк и столбцов. В рассматриваемом примере получается следующий вектор » rind = symrcm(BN) rind = 3 2 1 5 6 4 Рис. 15.2. Разложение Холецкого без переупорядочения Сама матрица В, естественно, не изменяется в ходе алгоритма, осуществляется только соответствующая перенумерация. Предлагаемые перестановки исходной матрицы действительно уменьшают ширину ленты, в чем несложно убедиться, отобразив полную форму матрицы В с переставленными строками и столбцами. Используйте индексацию при помощи вектора rrna: » full(ВЛ(rind, rind)) ans = 4 1 0 0 0 0 14 10 0 0 Глава 1Б Разреженные матрицы 705 0 14 10 О 0 0 14 1 О 0 0 0 1 4 1 0 0 0 0 1 4 Произведите разложение Холецкого для матрицы с переставленными строками и столбцами и отобразите шаблон матрицы R. Используйте индексацию при помощи вектора. » R = chol(BN(rind, rind)); >> spy(R) Расположение и количество ненулевых элементов, обозначенное nz в графическом окне с шаблоном, в матрице R (рис. 15.3) свидетельствует об эффективности предварительных перестановок в исходной матрице с целью уменьшения ширины ленты. Рис. 15.3. Разложение Холецкого с переупорядочением Заметьте, что поскольку в исходной матрице были произведены перестановки, то множитель R разложения Холецкого соответствует измененной матрице. Для факторизации исходной матрицы следует выполнить обратные перестановки. Проверьте это, вычислив: » (Rfrind, rind))1*R(rind, rind) Перед разложением Холецкого В = RTR разреженных матриц имеет смысл попытаться уменьшить ширину ленты факторизуемой матрицы за счет сим 706 Часть IV. Использование Toolbox и решение прикладных задач метричной перестановки строк и столбцов, поскольку разложение не приводит к образованию новых ненулевых элементов вне лен гы матрицы, т. е. ширина ленты магрицы Rr + R не больше ширины ленты В. Заметим, что функция symrcm основана на алгоритме Катхилла—Макки с обратным упорядочением, который уменьшает не только ширину ленты матрицы, но и ее профиль. Профильная схема является обобщением ленточной — допускается переменная ширина ленты в каждой строке матрицы, а количество всех элементов матрицы, входящих в такую ленту переменной ширины (оболочку), называется профилем. Разложение Холецкого сохраняет профиль Ят + R такой же, как у исходной матрицы, т. е. новые ненулевые элементы вне оболочки не появляются. Выполните разложение Холецкого матрицы, приведенной ниже, без предварительного уменьшения профиля, затем примените алгоритм Катхилла— Макки с обратным упорядочением для уменьшения профиля и сравните количество ненулевых элементов в множителях разложения Холецкого. в= 'т 1 1 1 Г 1 7 0 0 0 1 0 7 0 0 1 0 0 7 0 J 0 0 0 7, Предварительное упорядочение строк и столбцов с целью уменьшения профиля или ширины ленты симметричной матрицы не гарантирует минимальное заполнение множителя разложения Холецкого, поскольку возможно появление достаточно большого количества ненулевых элементов внутри лен гы в множителях разложения. Более эффективное упорядочение производят функции symamd и syiranmd, основанные на алгоритме минимальной степени. Сравнение symmmd и symrcm приведено в справочной системе MATLAB на примере матрицы размера 60 (см. описание функции symmird, к которому легко перейти из разд. MATLAB Functions: 1 unctions - By Category: Sparse Matrices с гиперссылками на функции. Несколько примеров расположено также в разд. MATLAB: Matrices: Sparce Matrices. Для перехода к нему следует выбрать вкладку Demo окна справочной системы MATLAB). Примечание Алгоритмы Катхилла—Макки и минимальной степени являются эвристическими. Они не дают гарантии, что найденные перестановки строк и столбцов приведут к наименьшей ширине ленты, профилю или заполнению множителей разложения Холецкого. Однако для многих практически важных задач они обеспечивают хорошие результаты и широко используются в вычислительной практике. Гпава 15. Разреженные матрицы 707 Мы рассмотрели примеры разложения Холецкого симметричных положительно определенных матриц. Перейдем теперь к обзору остальных функций, предназначенных для факторизации разреженных несимметричных матриц. L(7-разложение матрицы находится при помощи функция lu. Если разреженная матрица А хранится в компактной форме в массиве an, то обращение [L, и, р, Q] = lu(AN) приводит к записи в выходные аргументы соот-ветствующих матриц разложения— нижней унитреугольной L, верхней треугольной U и матриц перестановок Р и Q таких, что PAQ-LU. Все выходные аргументы функции lu принадлежат типу double array (sparse). Матрица Р соответствует перестановкам строк, обеспечивающим устойчивое гь вычислительного процесса, a Q — перестановкам столбцов, уменьшающим заполнение множителей разложения. При Ы(-разложении требуется найти компромисс между двумя требованиями: вычислительной устойчивостью и, по возможности, сохранением разреженности множителей разложения. Для обеспечения вычислительной устойчивости производится перестановка строк так, чтобы на диагонали текущей строки разложения оказался достаточно большой го модулю элемент. По умолчанию строки переставляются, если модуль диагонального элемента в 10 раз меньше, чем максимальный модуль элементов того же столбца, лежащих ниже диагонали. В этом случае алгоритм 1и пытается одновременно минимизировать заполнение множителей. Функция 1и позволяет установить другие значения этого коэффициента, для чего ее следует вызвать с дополнительным вторым входным аргументом (по умолчанию он равен 0.1, что соответствует десятикратному превосходству). Второй аргумент может принимать значения от 0 до 1, причем чем он меньше, тем более разреженными могут получиться множители И7-разложения, возможно, за счет потери вычислительной устойчивости. Напротив, увеличение значения второго аргумента улучшает вычислительную устойчивость, однако может повлечь существенное возрастание количества ненулевых элементов в матрицах L и U. Кроме L(/-разложения в матричных вычислениях применяются и другие способы факторизации матриц, в частности, (ZR-разложение. Для заданной матрицы А требуется найти верхнюю треугольную матрицу /? и ортогональную Q (т. е. QrQ — единичная матрица) такие, чтобы выполнялось равенство А = QR. Эта задача решается при помощи функции qr. Отметим, что функции lu и qr позволяют выполнить соответствующие разложения прямоугольных ма гриц и комплексных матриц. Функции luinc и choline вычисляют неполное £(/-разложечие и неполное разложение Холецкого. которые могут использоваться для ускорения сходимости и герационных методов при решении системы линейных уравнений с исходной матрицей. Особенности применения qr, luinc и luinc подробно описаны в справочной системе MATLAB. 708 Часть IV. Использование Toolbox и решение прикладных задач Функции lu, choi и qr применимы и к матрицам, хранящимся в полной форме в массивах типа double array, однако если матрица разрежена, то для эффективной факторизации следует привлечь компактную форму записи в массивах double array (sparse). Все алгоритмы MATLAB для разреженных матриц, хранящихся в массивах типа double array (sparse), работают с учетом структуры матрицы, обеспечивая значительное ускорение вычислений по сравнению с обычными матрицами. Профайлер MATLAB позволяет убедиться в вышесказанном на примере LL-разложения. Профайлер Профайлер MATLAB служит для получения информации о временных затратах на выполнение команд пли М-файлов и является удобным средством для оптимизации алгоритмов. Профайлер помогает выявить блок операторов, работа которых занимает неоправданно большое время. Статистика временных затрат представляется в виде под! обного отчета или наглядной столбцевой диаграммой. Выбор пункта Profiler в меню Desktop рабочей среды либо пункта Open Profiler меню Tools редактора М-файлов приводит к появлению окна профайлера. Ускорению программ в МАТ! АВ посвящена глава 23. Для использования средств профайлера следует указать имя М-файла в строке ввода раскрывающегося списка Run this code (если М-файл содержит файл-программу) или занести в нее вызов функции (если М-файл содержит файл-функцию) и нажать кнопку Start Profiling. После завершения работы в окне профайлера отображается собранная и обработанная статистика по выполнению этого файла. Используйте профайлер для того, чтобы установить преимущество использования разреженной структуры матрицы на примере разложения Холецкого. Задана симметричная матрица S размера « = 2000 с большим числом нулевых элементов '3 -1 0 •• • 0 1 -1 3 -1 •• • 0 0 0 -1 3 •• • 0 0 $= Z 0 0 0 •• • 3 - 1 0 0 •• • -1 3 Паша задача состоит в сравнении временных затрат на разложение Холецкого матрицы S, записанной в компактной форме в массиве sn и в обычном массиве s типа double array. При конструировании массива sn типа double array (sparse) учтите, что матрица S отличается от трехдиагональной только двумя элементами, поэтому сначала сформируйте трехдиагоналъную Гпава 15. Разреженные матрицы 709 матрицу при помощи функции spdiags, а затем измените значения элементов S',, ! и 5( „. Файл-программа prof_sp, приведенная в листинге 15.2, обеспечивает заполнение массива sn. п = 2000; % dimension of matrix е = ones(n, 1); % define unit column % compose three-diagonal matrix in compact form SN = spdiags([-e 3*e -e], -1:1, n, n); % change two elements in matrix by 1 SN{1, n) = 1; SN(n, 1) = 1; % factorization sparse matrix RN = chol(SN); В примере использованы комментарии на английском языке, поскольку в версии 7 пакета MATI АВ профайлер не поддерживает альтернативные кодовые страницы. Рис. 15.4. Окно профайлера после выполнения М-файла prof_sp.m 710 Часть IV. Использование Toolbox и решение прикладных задач Откройте окно профайлера, наберите prof_sp в строке ввода раскрывающегося списка Run this code и нажмите кнопку Start Profiling. После завершения работы М-файла в окне профайлера, представленном на рис. 15.4, появляется таблица с накопленной статистикой. Поля таблицы содержат: имена функций (Function name), количество вызовов (Calls), суммарное время работы файла для всех вызовов, включая выполнение вызываемых функций (Total Time), чистое время работы функции для всех вызовов (Self Time) и столбцевую диаграмму относительных затрат времени на выполнение вызываемых М-файлов, в которой более темным цветом выделено чистое время (lotal Time Plot). Интерфейс окна профайлера достаточно прозрачный, поэтому отметим самое существенное. Для получения детальной информации о работе файл-программы prof_sp щелкните по гиперссылке с ее именем в таблице. Окно профайлера принимает вид, изображенный на рис. 15.5. ~ Примечание и Вид окна профайлера может немного отличаться от приведенного на рис. 15.5, поскольку его содержимое определяется ранее сделанными установками флагов, о которых пойдет речь далее. Примечание На панели инструментов профайлера расположены кнопки Back, Forward, Refresh, предназначенные для листания страниц с информацией о работе М-файлов, так же как и в любом браузере. Окно условно состоит из нескольких частей. В верхней части окна размещена общая информация и две гиперссылки. Щелчок по гиперссылке с именем файла приводит к его открытию в редакторе М-файлов. Гиперссылка Сору to new window for comparing multiple runs позволяет создать копию окна профайлера для сравнения результатов при дальнейшем тестировании М-файла. Далее расположены флаги, определяющие содержимое окна, и кнопка Refresh, используемая для изменения его вида после переустановки флагов. Флаг Show M-Lint results отвечает та вывод информации средства M-Lint О диагностике М-файлов с помощью M-Lint см. главы 5 а 21 Содержимое окна на рис. 15.5 определяется установкой двух флагов. Флаг Show busy line управляет отображением информации о текущем файле. Табличная часть содержит временные затраты на выполнение операторов, упорядоченные в порядке убывания суммарного времени. Флаг Show child tiles обеспечивает вывод краткой информации о вызываемых функциях в разделе Children, расположенном ниже таблицы. Имена М-файлов, являющиеся одновременно гиперссылками, предназначены для перехода к страницам со сведениями о них. В данном случае в разделе Children находится ссылка на единственный М-файл spdiags.m. Хотя наша файл-программа обращается Глава 15 Разреженные матрицы 711 еще и к функции choi. но ее имя не выводится, поскольку chol является встроенной функцией со скрытым кодом. Флаг Show parent files обеспечивает вывод раздела Parents с таким же содержанием, что и раздел Children, только с информацией о М-файле, из которого произошло обращение к текущему. В приводимом примере флаг отключен. Рис. 15.5. Окно профайлера с таблицей о ла гратах времени при выполнении М-файла prof_sp.m 712 Часть IV. Использование Toolbox и решение при1 тг/дных задач Б разд. "Пидф) нкции" главы 5 описано, как при помощи специальной функции exist получить информацию о том, является ли некоторая функция встроенной или нет. Рис. 15.6. Окно профайлера с листингом М-файла prof_sp.m I лива 15. Pa^pe>Ke>-ii.»*j матрицы 713 На рис. 15.6 приводится окно профайлера, если установлены другие флаги: Show file coverage и Show file listing. Первый из них обеспечивает вывод суммарной информации в раздел Coverage results о текстовых строках файла, включая их общее количество, сколько из них комментариев, сколько исполняемых строк, сколько строк выполнились при текущем вызове профайлера и сколько строк не выполнялось. После раздела Coverage results сформир >ван раздел Hie listing, за отображение которого отвечает флаг Show file listing. Этот раздел содержит листинг файл-программы prof_sp. Листинг расцвечен специальным образом, определяемым значением в списке Color highlight code according to (по умолчанию значение time). В приведенном примере выделены цветом операторы, выполнение которых потребовало наибольшего времени. Можно выбрать и другие критерии выделения цветом: по числу вызовов оператора (numcalls), выполнялся или нет оператор (coverage или noncoverage), по наличию диагностики средства M-Lint (mlint), или вообще отказаться от выделения цветом (пипе). Слева от каждого оператора указаны время его выполнения (столбец time), числе обращений к нему (столбец calls) и гиперссылка с номером строки программы (столбец line), щелчок по которой приводит к переходу к этой строке в редакторе М-файлов. Разложение Холецкого разреженной матрицы на нашем компьютере при помощи специального алгоритма, реализованного в функции chol, потребовало 0.016 с (на разных компькнерах может получиться разное время счета). Сравните теперь это время со временем разложения матрицы, хранящейся в полной форме. Перед внесением изменений в файл-программу prof_sp удобно сделать копию окна профайлера при помощи гиперссылки вверху окна так, как было описано выше. Приведите массив SN к полной форме при помощи функции full, сохраните его в s и вызовите от нею функцию chol. Запустите из профайлера на выполнение файл-программу prof_sp и посмотрите на существенную разницу во времени по сравнению с разложением Холецкого разреженной матрицы. На нашем компьютере (6.734 с) результаты различались примерно в 400 раз, и это для не очень больших размеров матрицы, поскольку в приложениях встречаются матрицы, размеры которых исчисляются миллионами. Кроме того, 0.125 с составило время преобразования разреженной матрицы в обычную. Очевидно, нет смысла комментировать эти результаты. Среда профайлера является удобной оболочкой для всесторонней оценки работы программы, поиска неэффективных блоков и их оптимизации. Профайлер может быть открыт не только при помощи .пеню рабочей среды или редактора М-файлов, но и командой profile с опцией viewer » profile viewer 714 Часть IV. Использование Toolbox и решение прикладных задач Fenn к моменту выполнения команды profile viewei предыдущие статистические данные не очищены, то будет открыто окно профайлера с суммарной собранной статистической информацией, о которой см. donee е том pcudeie. Мы упомянули об этой возможности не только для того, чтобы описать альтернативный способ вызова профайлера. Функция profile имеет достаточно большой набор опций, позволяющих оценивать характеристики программы, причем ее возможности шире, чем те, которые предоставляет среда профайлера. Например, по завершении сбора информации генерируется отчет в формате HTML, который открывается в установленном по умолчании браузере Web-сз раниц и может быть сохранен. Для активизации профайлера предназначен параметр on. Команда » profile on приводит к началу сбора статистики временных затрат. Однако при использовании параметра on будут учитываться только обращения к подфункциям и внешним программам или функциям, за исключением встроенных В нашем примере встроенной функцией является choi. Для получения дополнительной информации о работе всех вызываемых функций следует использовать еще опцию -detail со значением builtin (по умолчанию используется папех): » profile on -detail builtin После запуска профайлера следует выполнять программы, операторы или вызывать функции, время работы которых подлежит определению: » profile on -detail builtin » prof_sp » profile off Команда profile off приостанавливает сбор информации. Команда profile resume возобновляет работу профайлера с сохранением ранее накопленной статистики, а команда profile clear возобновляет работу профайлера без сохранения статистики. Отметим, что команда повторной активизации профайлера приводит к очистке статистики. Приведенные команды целесообразно использовать в своих программах для определения эффективности работы ее отдельных блоков. Вывод отчета, изображенного на рис. 15.7, в браузер осуществляется командой profsave (либо командой profile viewer в окно профайлера). Таблица содержи г информацию о времени работы каждой из функций, выполняемых после инициализации профайлера и до создания отчета. Обратите внимание, что команда profile с опцией -detail builtin выводит сведения обо всех встроенных функциях, которые были вызваны в процессе работы про Гпава 15. Разреженные матрицы 715 граммы prof_sp. Этим обстоятельством можно пользоваться для получения набора встроенных функций,, используемых в алгоритмах различных файл-функций MATLAB. В столбце Total Time записано общее время, а в Self Time — время работы операторов функции без учета временных затрат на вызов из нее других встроенных функций. Детальную информацию о каждой функции можно получить, перейдя по ссылке с именем функции. Рис. 15.7. Суммарный отчет о временных затратах 716 Часть IV. Использование Toolbox и решение прикладных задач Отчет можно получить в виде совокупности файлов формата HTML в заданном подкаталоге (например, ’html_report') текущего рабочего каталога MATLAB, создаваемом командой protsave (stat data, 'html report'). Предварительно структура с именем stat data должна быть создана при помощи stat_data = prof ile ('info'). Решение систем уравнений и исследование спектра Методы решения систем линейных уравнений делятся на два класса: прямые и итерационные. Прямые методы основаны на предварительной факторизации матрицы системы и последующем решении двух систем с треугольными матрицами. Данный подход позволяет, в частности, эффективно решить несколько систем с одной матрицей и различными векторами правых частей. В MATLAB операция реализует прямой метод решения системы линейных уравнений Ах = Ь, причем в случае нескольких систем Ах=Ь^, ..., Ах = Ь^ векторы правых частей записываются в столбцы некоторой вспомогательной матрицы В. В общем случае находится решение системы АХ = В. где В= Ь®,..., 1 Каждый столбец матрицы X содержит решение соответствующей системы линейных алг ебраических уравнений. Операция АВ реализует решение системы уравнений с разреженной матрицей А с использованием специальных алгоритмов, учитывающих структуру матрицы (применение обратной косой черты для решения систем общего вида было описано в главе 6). В приложениях часто встречаются системы линейных уравнений, для решения которых итерационные методы оказываются наиболее эффективными. MATLAB обладает достаточно большим набором функций, которые реализуют основные итерационные алгоритмы: предобусловленный метод сопряженных градиентов (peg), метод бисопряженных градиентов (bieg), метод обобщенных минимальных невязок (gmres) и другие методы. Обсуждение алгоритмов перечисленных итерационных методов выходит за рамки данной книги. Справочная система MATLAB содержит некоторые классические примеры, в частности, решение системы линейных уравнений, соответствующей пятиточечной разностной аппроксимации оператора Лапласа при помощи ме Гпава 15. Разреженные матрицы 717 тода предобусловленных сопряженных 1радиентов. Предобусловливагель ..трои гея на основе неполного разложения Холецкого исходной магрицы (см. разд. Mathematics: Sparse Matrices: Simultaneous Linear Equations) Пользователь может выбрать любую подходящую матрицу в качестве пре-добусловливателя, запрограммировать быстрое решение системы линейных уравнений с данной матрицей в файл-функции и указать имя файл-функции в соответствующем аргументе peg вместо предобусловливателя. Гибкость интерфейса peg предоставляет вычислителю широкие возможности для проведения исследований с целью написания эффективных солверов для определенных классов задач. Частичная алгебраическая проблема собственных значений — простая Ах = Хг или обобщенная Ах = ХВх —решается при помощи функции eigs. которая позволяет разыскать заданное число собственных значений (в том числе и комплексных). Интерфейс функции eigs допускает нахождение собственных значений, начиная с наибольшего или наименьшего по модулю или вблизи некоторого числа. Например, вызов Lambda = eigs (А, к) приводит к занесению в вектор lambda первых к наибольших по модулю собственных значений. Для нахождения первых к наименьших по модулю собственных значений применяется обращение: lambda - eigs(А, к, 0) В общем случае, когда требуется определить несколько собственных значений вблизи заданного числа s, следует указать его третьим аргументом в eigs: lambda = eigs(A, k, s) Одновременное нахождение собственных векторов происходит при вызове eigs с двумя выходными аргументами, что аналогично использованию функции eig, которая предназначена для решения полной алгебраической проблемы собственных значений (см. разд. "Собственные числа и векторы матрицы, функции матриц" главы 6). При решении обобщенной задачи на собственные значения с симметричной положительно определенной матрицей В следует указывать ее вторым входным аргументом после матрицы А. Функция eigs допускает задание ряда дополнительных параметров, управляющих вычислительным процессом. Глава 16 Оптимизация В состав MATLAB входит Optimization Toolbox, предназначенный для решения линейных и нелинейных оптимизационных задач. Функции этого Toolbox реализуют основные алгоритмы оптимизации, причем понимание алгоритма позволяет настроить выбранную функцию на эффективное решение поставленной задачи, что продемонстрировано на примере системы нелинейных уравнений. Optimization Toolbox не имеет приложений с графическим интерфейсом. Последний раздел данной главы содержит пример приложения, облегчающего доступ к нужной функции Toolbox и управление вычислительным процессом. Optimization Toolbox При чтении главы 6 вы использовали ряд функций Optimization Toolbox для решения уравнений (fzero), минимизации функции одной переменной на отрезке (fminbnd) и минимизации функций нескольких переменных без ограничений на независимые переменные (fminsearch). Данный раздел посвящен более сложным задачам с ограничениями, которые могут быть решены с использованием вычислительных функций Optimization Toolbox. Интерфейс этих функций достаточно гибкий, все они допускают обращение с переменным числом входных и выходных аргументов в зависимости от данных задачи и искомых величин. Кроме того, большинство функций Toolbox позволяют исследование задач, зависящих от одного или нескольких параметров. Линейное и нелинейное программирование Линейное программирование Задача линейного программирования состоит в нахождении вектора х, который минимизирует целевую линейную функцию /Тх, (16.1) Глава 16 Оптимизация 719 где / — вектор коэффициентов, и удовлетворяет заданным линейным ограничениям: неравенствам Ах-Ь (16.2) и равенствам AeqX ~ fyiq • (16.3) Кроме того, могут быть поставлены двусторонние покомпонентные ограничения в векторной форме lb<x<ub. О 6.4) В задачах оптимизации могут быть заданы не все типы ограничений, например, ограничения-равенства могут отсутствовать. Для решения задач линейного программирования предназначена функция linprog. Первым аргументом linprog всегда является вектор f, далее задаются матрица а и вектор ь. При наличии ограничений в виде равенств дополнительными аргументами могут быть Aeq и beq, наконец, двусторонние ограничения являются шестым и седьмым аргументами linprog. Решите классическую задачу линейного программирования о составлении рациона питания. Имеются три продукта ТП, П2, ПЗ разной цены, каждый из которых содержит определенное количество питательных ингредиентов И1, И2, ИЗ, И4 (табл. 16.1). Известно, что в день требуется: И1 — не менее 250, И2— не менее 60, ИЗ— не менее 100 и И4— не менее 220. Требуется минимизировать затраты на приобретение продуктов. Очевидно, что количество приобретаемых продуктов не может быть отрицательным. Таблица 16.1. Питательность и цена продуктов П1 П2 ПЗ И1 4 6 15 И2 2 2 0 ИЗ 5 3 4 И4 7 3 12 Цена 44 35 100 Запишите целевую функцию, матрицу А, векторы b и lb ограничений в соответствии с требованиями Toolbox, обозначив искомые количества продуктов через X], х2 и х3 соответственно. Поскольку линейные ограничения содержат "меньше или равно", а количество ингредиентов в рационе не 72Q Часть IV. Использование Toolbox и решение прикладных задач должно быть менее заданных величин, то следует изменить знаки обеих частей системы. Для решения задачи составьте файл-программу ration. При вызове 1 inprog вместо неиспользуемых аргументов (нет ограничений в ваде равенств) задайте пустые массивы, обозначаемые в MATLAB квадратными скобками. Верхнее ограничение вида x<ub отсутствует, а функция linprog поддерживает обращение с переменным числом входных аргументов, поэтому седьмой входной аргумент не нужен. Листинг 16.1 содержит операторы файл-программы ration. Листинг 16.1. Файл-программа ration ........-. - >ы.................................................................•... •«*•... >••........... л...............» % Зтданио матрицы и вектора правой части системы неравенств А = [4 6 15 2 2 0 5 3 4 7 3 12] ; А = -А; Ь = [250; 60; 100; 220]; Ь = -Ь; % Определение коэффициентов целевой функции f = [44; 35; 100]; % Задание ограничений снизу на переменные 1Ь = [0; 0; 0]; % Решение и вывод результата в командное окно х = linprogff. А, Ь, [ ], [ ], 1Ь) Bi шолнение файл-программы ration приводит к следующему результату: » Optimization terminated successfully. х = 13.2143 16.7857 6.4286 i п^ва 16 ’зацря 721 Обращение к linprog с двумя выходными аргументами позволяет не только получить вектор решения, но и значение целевой функции, т. е. минимальную стоимость рациона в рассматриваемой задаче: » [х, р] = linprogtf, a, b, [ ], [ ], lb, [ ]),- Optimization terminated successfully. » p P = 1.8118e+003 Квадратичное программирование В задачах квадратичного программирования целевая функция имеет вид |хтЯх + /гх, (16.5) а ограничения в общем случае совпадают с ограничениями (16.2—16.4) в задаче линейного программирования. Для решения задач квадратичного программирования предназначена функция quadprod. Интерфейс quadprog практически не отличается от linprog, за исключением того, чти первыми двумя входными параметрами являются массив н и вектор-столбец f, соответствующие матрице /7 и вектору f целевой функции. Вместо матриц и векторов отсутствующих ограничений задаются пустые массивы. Проиллюстрируем использование функции quadprog на примере задачи Марковица об определении состава инвестиционного портфеля рискованных ценных бумаг. Инвестор предполагает вложить свободные денежные средства в рыночные активы (ценные бумаги, акции) с целью получения дохода в будущем периоде. Для уменьшения рисков он выбрал для вложения четыре различных акции, которые обозначим А1, А2, АЗ. А4. Перед инвестором стоит задача определить, какую часть своих средств вложить в каждый актив так, чз обы получить желаемую доходность портфеля с наименьшим риском. Портфель определяется вектором долей от суммы инвестиций для покупки акций: х = (х], х2, х3, х4)Т, X] + х2 + х3 + х4 =1, х,->0 (i = l,2, 3,4). Риск оценивается как величина среднеквадратического отклонения ожидаемой доходности. Будем считать, что инвестор каким-либо способом произвел оценку ожидаемой доходности для каждой ценной бумаги, т. е. построил вектор доходностей у ~ (_у], _у2, Уз’ У4)Т и вычислил матрицу ковариации К. 722 Часть IV. Использование Toolbox и решение прикладных задач Если вектор у и мат рица V известны, то доходность портфеля и его дисперсия вычисляются по формулам: Ур = уТх = лт у; <ур = лт Vx. Формальная постановка задачи Марковица приводит к задаче квадратичного программирования: найти минимум функции j(r)-.vTV.r (16.6) при ограничениях: т У х = а, (16.7) етх = 1, ет =(1,1,1,1) (16.8) х>0. (16.9) Величина желаемой доходности портфеля а должна быть не меньше минимальной и не больше максимальной доходности выбранных для инвестирования ценных бумаг. Неравенство (16.9) — одностороннее покомпонентное ограничение типа (16.4). Ограничения (16.7) и (16.8) —это ограничения вида (16.3), поэтому их следует объединить в одно, построив матрицу и вектор Пусть заданы следующие значения для матрицы И, вектора у и желаемой доходности портфеля а: '102.0 27.1 -52.3 66.5 ' 11.3' 27.1 148.8 42.1 -66.4 13.2 V = ; у = « = 15 -52.3 42.1 246.5 56.9 16.1 66.5 -66.4 56.9 272.3 17.4 Тогда в обозначениях, принятых для описания функции quadprog, построим матрицы и век гора, связанные с ограничениями: 11.3 13.2 16.1 17.4 1111 1Ь = [О О О 0]Т I лав > 16. Оптимизация 723 Для решения задачи о формировании портфеля с фиксированной доходностью составьте файл-программу risk_asset. Возможный вариант исходного текста файл-про1раммы risk_asset приведен в листинге 16.2. у - T.'-V1’"”’" **" ”----------------- ---------------- Листинг 16.2. Файл-программа risk_asset -•... ~_________ _______________________________ . _ __j-________ ?_s Ею ' ... % Задание матрицы коэффициентов целевой функции V = [ 102.0 27.1 -52.3 66.5; 27.1 148.8 42.1 -66.4; -52.3 42.1 246.5 56.9; 66.5 -66.4 56.9 272.3i; % Задание ограничений типа равенств Aeq = (11.3 13.2 16.1 17.4; 1 1 1 И; beq = [15; 1] ; % Задание ограничений снизу на переменные 1Ь = [0; 0; 0; 0]; % Решение и вывод результата в командное окно х = quadprog( V, [ J, [ ], [ ], Aeq, beq, lb) Выполнение файл-программы risk_asset даст ответ о распределении денежных средств в выбранные для вложений активы: » risk_asset Warning: Large-scale method does not currently solve this problem formulation, switching to medium-scale method. > In C:MATLAB65toolboxoptimquadprog.m at line 213 Optimization terminated successfully. x = 0.1626 0.4359 0.1439 0.3575 При этом в командное окно вывелось сообщение о применении Mediumscale алгоритма вместо Large-scale, принятого по умолчанию (см. разд. "Па-р я ъетрч опт? смизации " данной главы). 24 3ai ВО 724 Часть IV. Использование Toolbox и решение прикладных задач Примечание Обобщение приведенного примера, интерпретация результатов и специальные средства пакета MATLAB для решения задач такого класса приведены в главе 18. Нелинейное программирование Optimization Toolbox позволяет решать ряд оптимизационных задач, в которых минимизируемая функция нелинейна, и к линейным ограничениям добавляются нелинейные. Общая постановка задачи нелинейного программирования такова: требуется разыскать min/(х) (16.10) среди всех векторов х, удовлетворяющих системе линейных ограничений (16.2—16.4) и дополнительных неравенств и равенств с(х)<0; се?(х) = 0. (16.11) Решение поставленной задачи производится при помощи функции fmincon. Основное отличие интерфейса fmincon от linprog и quadprog состоит в том, что нелинейные ограничения с(х)<0 и се?(х) = 0 задаются в файл-функции. Обращение к fmincon в достаточно общем случае выглядит следующим образом: х = frruncon(fun, хО, A, b, Aeq, beq, lb, ub, nonIcon, options, Pl, P2, ...) Указание второго дополнительного выходного аргумента позволяет получить значение функции в точке минимума, а третьего — информацию о результате. Если третий аргумент больше нуля, то результат найден с требуемой точностью, ноль — достигнуто максимальное число итераций или количество вызовов исследуемой функции в процессе решения, меньше нуля — решение не найдено. Первый входной аргумент fun является указателем на файл-функцию (или ее именем), вычисляющую минимизируемую функцию f (х), которая может зависеть от нескольких параметров. Значения параметров, в случае их наличия, передаются в последних аргументах Pl, Р2,... начиная с 11-ой позиции в списке входных аргументов. Исследование математических функций, зависящих от некоторых параметров, описано в разд. "Дополнительные возможности исследования функций" главы 6. Входным аргументом файл-функции fun должен быть вектор, длина которого совпадает с числом переменных, т. е. компонент вектора х. Неиспользуемые векторы и матрицы ограничений заменяются в списке входных ар Глава 16. Оптимизация 725 гументов fmincon квадратными скобками (пустым массивом). Начальное приближение к решению указывается в хО. Список входных аргументов fmincon содержит управляющую структуру options, предназначенную для задания опций вычислительных алгоритмов. Для большинства функций Tolbox Optimization набор опций существенно больше, чем для рассмотренных в г wee 6 функций fzero, fminbnd и fminsearch, поэтому изучению данного вопроса посвящено несколько разделов этой главы (см. разд. "Параметры оптимизации" и "Решение большой системы нелинейных уравнений" данной главы j. Нелинейные ограничения (16.11) (неравенства и равенства) программируются в файл-функции, указатель на нее (или ее имя) указывается в аргументе nonicon. Входным аргументом nonicon является вектор х, соответствующий искомому вектору х, а двумя выходными аргументами — векторы с и сед левых частей нелинейных ограничений с и cctj. Последние идущие подряд входные аргументы функции fmincon могут быть опущены, если они не используются. Папример, при отсутствии нелинейных ограничений и параметров применяется следующий вызов fmincon: х = fmincon(fun, хО, A, b, Aeq, beq, lb, ub) Поскольку в данном случае управляющая структура options не задана, то вычисления будут производиться с принятыми по умолчанию опциями, узнать о которых можно при помощи функции optimset. Для этого достаточно вызвать ее от строки с именем вычислительной функции Optimization Toolbox, например, выполнение команды » optimset(’fmincon') приводит к выводу информации о всех настройках алгоритма функции fmincon, в том числе и точности 106 по аргументу и функции. Найдите решение следующей простой задачи (очевидно, что решение— нулевой вектор): min3(х, )2 + 2(х2 )2; (Л] )2 + (х2 )2 < 1. Обратите внимание, что имеется только одно нелинейное ограничение в виде неравенства, которое следует преобразовать к виду с(г) < 0, перенеся единицу в левую часть. Написание файл-функции, вычисляющей 3(х,)2+2(л2)! , не представляет труда (листинг 16.3). При программировании нелинейного ограничения учтите, что соответствующая файл-функция возвращает два вектора левых частей нелинейных ограничений (листинг 16.4). В рассматриваемом примере первый вектор состоит только из одной компоненты, а второй должен быть пустым, поскольку нет ограничений в виде равенств. 726 Часть IV, Использование Toolbox и решение прикладных задач i Листинг 16.3. Минимизируемая функции •Л. fit > * '. 'I _ .-_3 ' ▼ ’’л) -. • <•/ L^’WLeX ’г. ••!» • * * ’. • ’ function f = myfun(х) % Вычисление минимизируем )й функции f = 3*х(1)А2 -г 2*к(2)А2; Пистинг 16.4. Файл-функция с огоаничениями function [с, ceq] = mycon(x) % Задание ограничений с(1) = х(1)А2 + х(2)А2 - 1; % ограничения в виде неравенства % Правая часть ограничений-равенств является пустым массивом, % поскольку данных 'граничений нет req = [ ]; Выполнение fmincon, например, из командной строки » х = fminc 3nvGinyfun, [0.7 0.7], [ ], [ ], [ ], [ ], [ ], [ ], @пгусоп) приводит к аыводу некоторой информации о ходе вычислений и результата X = 1.0е-004 * 0.1895 -0-0235 Обращение к fmincon с тремя выходными аргументами позволяет получить значение функции в точке минимума: » [х, f, flag] = fmincoi. (©myfun, [0.7 0.7], [ ], [ ], [ ], ... [ 1, [ ],[ ], ©mycon) x = l.Ce-004 * 0.1895 -0.0235 f = 1.0882e-009 flag = 1 Значение flag большее нуля свидетельствует о том, что решение успешно найдено. Глава 16. Оптимизация 727 Нелинейные задачи Нелинейное программирование не исчерпывает класс нелинейных задач, которые могут быть решены в Optimization Toolbox. Функции Toolbox fgoaiattain, tminmax, fseminf позволяют исследовать задачи о достижении границы, находить решение в задаче о минимаксе. Ниже приведены формулировки задач и интерфейс функций, предназначенных для их решения. Область допустимых значений независимых переменных может задаваться как линейными, так и нелинейными ограничениями, в общем случае они совпадают с ограничениями в задаче нелинейного программирования, описанной выше. Задача о достижении границы Б задаче о достижении границы задана вектор-функция F(x) и два вектора w и g. Требуется найти х из области допустимых значений, для которого величина у будет минимальной при выполнении условий F, (х) - иуу < gf для всех компонент F{x), w и g. Поставленная задача решается при помощи функции fgoaiattain, обращение к которой в достаточно общем случае имеет вид: х = fgoaiattain(fun, хО, g, w, A, b, Aeq, beq, lb, ub, nonIcon, options, Pl, P2, ...) Входной аргумент fun является указателем на файл-функцию (или ее именем). вычисляющей вектор-функцию F(x). Аргументы g и w — векторы, длина которых совпадает с числом значений вектор-функции. Использование остальных аргументов аналогично fmincon. Интерфейс функции fgoaiattain, так же как и других функций Optimization Toolbox, допускает вызов с переменным числом входных и выходных аргументов в зависимости от условий, опредепяющих область допустимых значений, и требуемого результата. Так, например, в случае нелинейных ограничений и необходимости вычислить не только х, но F(x) и у, следует указать три выходных аргумента, а неиспользуемые входные сделать пустыми массивами: [х, F, gamma] = fgoaiattain(fun, хО, g, w, [ ], [ ], ( ], [ ], [ ], [ ], nonicon) Четвертый дополнительный выходной аргумент функции fgoaiattain служит для получения информации о вычислительном процессе. Положительное его значение свидстельс грует об успешном завершении вычислений, ноль — вычисления остановлены из-за достижения максимального числа итераций или превышения максимально возможного числа вызовов иссле 728 Часть IV. Использование Toolbox и решение прикладных задач дуемой функции, а отрицательное значение сигнализирует о том, что решение не найдено. В справочной системе MATLAB по Optimization Toolbox приведен пример конструирования регулятора с обратной связью с привлечением функции fgoaiattain (см разд. Optimization 1оо1чо t: Tutorial: Multiobjective Examples). Минимизация функции с полубесконечными ограничениями Постановка задачи заключается в поиске минимума функции нескольких переменных (16.10) в области, задаваемой в общем случае линейными uipa-ничениями (16.2—16.4), нелинейными (16.11) и полубесконечными ограничениями вида Ki (х, мл)<0, i-1.п, (10.12) где w, — векторы дополнительных переменных размерности не более двух, компоненты которых изменяются в заданном интервале. Для решения этой задачи предназначена функция fseminf со следующим интерфейсом: X = fseminf(fun, хС, ntheta, seminfcon. A, b, Aeq, beq, lb, ub, options, Pl, P2, . . . ) причем могут быть указаны дополнительные выходные аргументы. Во второй из них запишется значение функции в точке минимума, а в третий — информация о вычислительном процессе. Смысл значений третьего выходного аргумента тот же самый, что и для функции fmincon, рассмотренной выше. Входные аргументы функции fseminf: fun, хО, a, b, Aeq, beq, lb, ub предназначены для указания минимизируемой функции, начального приближения, матриц и векторов, определяющих линейные ограничения типа нгравенст в и равенств (16.2—16.4). Обсудим назначение параметров, непосредственно связанных с нелинейными ограничениями (16.11) и полубесконечными (16.12). Количество ограничений вида (16.12) задается в ntheta, а все нелинейные ограничения, включая полубесконечные, программируются в файл-функции, указатель на которую (или ее имя) передается в seminfcon. Эта файл-функция должна иметь специальный интерфейс и структуру (листинг 16.5). function [с, ceq, KI, К2,..., Kntheta, S] = sem_con(x, S) % Проверка, Был ли инициализирован массив шагов S fлава 16 Оптимизация 729 % для дополнительных переменных if isnan(S(1, 1)} % Это nej вый вызов sem_con, следует иницьализировать массив S S(l, 1) = S(l, 2} = S(ntiieta ,1) = . ..; S(ntheta, 2) = end % Генерация сетки значений дополнительных переменных % Если дополнительная переменная является вектором с двумя компонентами, % то следует использовать meshgrid wl “ . ..; wntheta = . ..; % Вычисление левых частей полубесконечных ограничений (16.12) % в узлах сетки К1 = . ..; Kr.theta = . ..; % Вычисление левых частей нелинейных ограничений % (равенств и неравенств) типа (16.11) с = . . . сед = ... Для заданного х файл-функция sem con должна возвращать значения век-тор-функций с(х) и ceq (л), входящих в левые части нелинейных ограничений (16.11). При отсутствии ограничений этого типа следует присвоить с и сед пустые массивы в теле файл-функции. Список выходных аргументов sem con включает в себя также значения левых частей АГ( (х, иу) полубесконечных ограничений (16.12), вычисленных для некоторого набора значений каждой из переменных Wj. Эти значения выбираются на сетке с постоянным шаго и, причем шаг для му записан в i-ой строке массива s. Если иу — скаляр, то выходной аргумент, соответствующий ATf(x, иу), будет вектором и шаг определяется значением S(i, 1), а элемент S(i, 2) не используется. В случае, когда аргумент иу функции А’Дл, му) является вектором длины 2, для иу генерируется сетка значений с шагами S(i, 1) и S(i, 2) по каждой ИЗ КОМПОНеНТ При ПОМОЩИ фуНКЦИИ meshgrid. 730 Часть IV. Использование Toolbox .1 решение прикладных задач В ходе вычислений функция fseminf обращается к sem_con с рекомендуемыми значениями шагов, но при первом вызове sem con массив s должен быть инициализирован. Первый вызов sem con легко отличить от последующих, поскольку входной аргумент s содержит NaN (не числа) Поэтому в начале файл-функции sem con размещен условный оператор if, который позволяет инициализировать массив шагов. Рассмотрим на простом примере минимизацию нелинейной функции с полубесконечными ограничениями. Пусть требуется найти минимум функции: /1(x1,x2) = xl2+2xf при отсутствии линейных и нелинейных ограничений, но с заданным полу-бесконечным ограничением вида: , . COsfx.W.) К, (*1. х2, ) =--kJ_LZ_o.] <0. х2^! Для решения поставленной задачи требуется написать файл-функции для вычисления ./(*! <х2) и (х(, х2, щ). Целевая функция npoi рам миру ется просто (листинг 16.6). При создании файл-функции для полубесконечного ограничения следуйте приведенным выше соглашениям относительно ее интерфейса и алгоритма. В нашем примере всего одно полубесконечное ограничение, причем дополнительная независимая переменная является скаляром В слу чае возникновения затруднений обратитесь к листингу 16 7. Листинг 1,6.6. Минимизируемая функция решения задачи с полубесконечными ограничениями function f = myfuns(х) % целевая функция f = х(1)л2 + 2*х(2)л2; .......... ЦЦШЦШИ|----------------------------- Листинг 16.7. Функция вычисления ограничений решения задачи с полубесконечными ограничениями ....—..—...................................—...........— ......... function [с, ceq, KI, S] = sem_con(X, S) if isnan(S(l, 1)) % Иницидлизация шага сетки 0.2 для скалярной переменной wl % (вторая компонента не будет использоваться) S = [0.2 0]; end Глава 16.4 Оптимизация 731 % Генерация сетки на отрезке [0, 100] для полубесконечных ограничений wl = 1:S(1, 1):100г % Вычисление полубесконечного ограничения в узлах сетки KI = cos(wl*X{l))./(wl*X(2)) - 0.1; % Нелинейные ограничния отсутствуют, задаем пустой массив с = [ ]; сед = [ ]; Для решения задачи осталось задать начальное приближение » хО = ю.5; 0.2] ; и вызвать функцию fseminf, установив число полубесконечных ограничений в 1: » [х, fval] = fseminf(Smyfuns, x0, 1, @sern_con) x = 1.3512 2.1785 fval = 11.3175 Минимаксная задача Постановка минимаксной задачи заключается в нахождении min пах {/ (х)} для нелинейной вектор-функции /(х) = (/| (х), ЛС*)’ —'fn С*)) ПРИ огРа* ничениях (16.2—16.4) и (16.11) тех же самых, что и в рассмотренной выше задаче нелинейного программирования. Для решения данной задачи предназначена функция fminimax, применение которой в достаточно общем случае выглядит следующим образом: х = fminimax (fun, х0, A, b, Aeq, beg, lb, ub, nonIcon, options, Pl, ₽2, .. .) Первый входной аргумент fminimax является файл-функцией, возвращающей вектор значений {f] (х)}. Смысл остальных входных аргументов такой же, как и для fmincon, применение которой обсуждалось выше. Интерфейс функции fminimax, как и большинства функций Optimization Toolbox, допускает переменное число входных и выходных аргументов, причем в качестве неиспользуемых входных аргументов указывается пустой массив. Во 732 Часть IV. Использование Toolbox и решение прикладных задач втором дополнительном выходном аргументе fminimax возвращаются значения вектор-функции f(x), в третьем— максимальное из них, а четвертый выходной аргумент содержит информацию о причине останова вычислений Смысл его значений тот же, что и для функции fmincon. Рассмотрим модельную задачу для демонстрации обращения к функции fminimax, в которой надо найти независимые переменные и х2 из условия min max{/| (х,, ) /2(*г*г) /з^ъ)}, {Al, Л2}{/;} где /| (-4 • х2) = (¥1 "О + (х2 ” 2) “2, f2 (х|,Х2 ) = Л'11 3 + 2х2°’9 -!• /з (*Р*г) = 1-7х1 +х2 “ 3-5- при линейных ограничениях Х| >0, х2 > 0, З.Г] + 2х2 < 2.2, и нелинейном ограничении -еЛ| + е'2 =1.5. Для решения задачи напишите файл-функцию для вычисления минимизируемой вектор-функции, файл-функцию для задания нелинейных ограничений и файл-программу, реализующую обращение к fminimax. В листингах 16 8—16.10 приведены тексты программ. ..„..„..ж................................. ,........................... .....— Листинг 16.8. Минимизируемая функция решения садами о минимаксе function f = vectfun3(x) % Вычисление минимизируемой вектор-функции f(1) = (x(l> - 1)л2 + (x(2) - 2)л2 - 2.1; f (2) = х(1)л1.3 + 2*x(2)'"0.9 - 1; f (3) - 1.7*x(l) + x(2) - 0.25; function [c, ceq] = nonlinear(x) % Задание нелинейных ограничений % ограничений-неравенств нет с — [ ] ; 733 Глава 16. Оптимизация % ограничения-равенства ceq(l) - -ехр(х(1)) + ехр(х(2)) - 0.5; Листинг 16.10. Файл-функция test_nni решения задачи о минимаксе ....-Ла а .'.И ... Г! >1 .Л. .fit. f.. Л . . . а ... *3^аТлТ I I . > >'i aa.iaaa. , I ЛГХ ... а. ..'а.а. . . ^.,1 а ............. 1 ..... . .а' % начальное приближение хО = [1; 0]; % задание ограничений-равенств А = [3 2]; Ь = 2.2; % Задание ограничений снизу на переменные 1Ь = [0; 0]; [х, fval] = fminimax(@vectfun3, х0. A, b, [ ], [ ], lb, [ ], Snonlinear) При вызове файл-функции test mm получается результат: X = 0.2U48 0.5466 fval = 0.6448 0.2885 0.6448 Решение нелинейных уравнений Optimization Toolbox позволяет решить системы нелинейных уравнений, общий вид которых задается при помощи нелинейной вектор-функции: F(x) = 0, а покомпонентная запись имеет вид ^1(х1,х2,...,х„) = 0; J'2(xl,x2,...,x„) = 0; Д(х1’ х2....ХЛ = °- Первым аргументом fsolve является указатель на файл-функцию (или ее имя), вычисляющую F(x). Данная файл-функция принимает на входе вектор аргументов и возвращает вектор значений F(x). Начальное приближение указывается во втором аргументе fsolve. 734 Часть IV Использование Toolbox и решение прикладных задач В достаточно общем случае вызов fsoive выглядит следующим образом: х = fsolvetfun, хО, options, Pl, Р2, ...) где options — управляющая структура, а необязательные аргументы Pl, Р2,... есть значения параметров, от которых может зависеть левая часть системы уравнений. Если в списке входных аргументов f solve всего два входных аргумента, то в командное окно выводится предупреждение, связанное с тем, что в версии 2.0 Optimization Toolbox алгоритм fsoive был модифицирован. Для подавления этого предупреждения следует вызывать fsoive с управляющей структурой, которую можно сформировать, например, со всеми принятыми по умолчанию настройками при помощи optimset: х - fsoive(fun, хО, optimset('fsoive')) Функция fsoive может быть вызвана с несколькими выходными аргументами Второй выходной аргумент содержит значения вектор-функции для найденного решения, а третий — сведения о работе алгоритма. Отрицательное значение третьего аргумента говорит о том, что решение не найдено из-за расходимости вычислительного процесса. Ноль означает досрочное прерывание вычислений при достижении максимально допустимого числа итераций или обращений к вектор-функции системы. Нахождение решения с заданной точностью подтверждается положительным значением третьего выходного аргумента fsoive. Решите систему из двух нелинейных уравнений с двумя неизвестными х. (2-x7)-cos,v. -eX1 =0; 7 (6.13) 2 + Х] — х2 -cosX| -е*2 =0 Файл-функция, соответствующая левой части системы, программируется просто (листинг 16.11). i Листинг 16.11. Фаил-сьункция, пычисляющая левую части системы i уравнений (6.13) function F = mysys(х) F(l) = х(1)*(2 - х(2)) - cos(х(1))*ехр(х(2)); F(2) = 2 + х(1) - х(2) - cos(x(l)) - ехр(х(2)); Указание начальной точки (0,0) в функции fsoive приводит к следующему результату: » [х, f] = fsoive(@mysys, [0 0], optimset('fsoive1)) Optimization terminated successfully: Relative function value ^hanging by less than OPTIONS.TolFun Гпава 16. Оптимизация 735 х = 0.7391 0.4429 f = 1.0е-011 * -0.4702 -0.6404 Мы рассмотрели пример, в котором число неизвестных совпадает с числом уравнений системы. Алгоритмы, заложенные в функцию fsolve, допускают несовпадение числа неизвестных и уравнений. В качестве упражнения решите системы: ’ . х* —2x2 =_1> • -Зх2 + *2 = _2; х^+х2 =2; Х| 2хг 4" х^ — 1; -Зх2 + xf + х3 = -2. При исследовании первой системы задавайте различные начальные приближения и убедитесь, что возможно найти приближенное решение, достаточно близкое к точному х( = х2 = 1. Для второй системы выбор начального приближения определяет, для какого точного решения разыскивается приближенное — сравните, например, начальные приближения [1 1 1] и [0 1 1]. Алгоритмы, реализованные в функции fsolve, основаны на минимизации некоторых критериев, связанных с исходной системой нелинейных уравнений, в частности, суммы квадратов компонент вектор-функции. Решением считается та точка, в которой значение критерия мало, что не гарантирует существования корней системы в окрестности найденной точки. В этом легко убедиться на простом примере — примените функцию fsolve для системы из одного уравнения х2 4-Ю-6 =0, не имеющего вещественных корней. Используйте для сравнения fzero с некоторым начальным приближением к корню. Функция fzero пытается отделить интервал, на границах которого непрерывная функция х2 +10-6 имеет разные знаки для гарантии существования корня. Разумеется, такого интервала не существует и работа fzero прерывается. Одним из алгоритмов функции fsolve является метод наименьших квадратов, который также используется для решения ряда оптимизационных задач, в частности, подбора параметров. Метод наименьших квадратов Метод наименьших квадратов применяется, например, для решения систем линейных уравнений, в которых число неизвестных не совпадает с числом уравнений (см. разд. "Переопределенные и недоопределенные системы" главы 6). 736 Часть IV. Использование Toolbox и решение прикладных задач Функция Isgnonneg предназначена для поиска только неотрицательных решений систем Сх = d, т. е, векторов х, все компоненты которых больше либо равны нулю. По существу, при помощи метода наименьших квадратов решается задача на нахождение минимума min [Сх - rf||2 среди всех х, >0. Через || || обозначена втирая векторная норма, являющаяся квадратным корнем из суммы квадратов компонентов вектора. Достаточно общий вариант вызова isqnonneg выглядит следующим образом: [х, resnorm, residual, flag] = lsqnonneg(C, d, xO) где первые два входных аргумента содержат матрицу и вектор системы, хО — начальное приближение, в х возвращается решение, а в дополнительных выходных аргументах возвращаются норма невязки (resnorm), вектор невязки (flag) и информация о завершении процесса вычислений (flag). Положительное значение переменной flag подтверждает сходимость итерационного процесса к решению, а нулевое значение предупреждает о превышении максимально допустимого числа итераций или вычислений квадрата нормы невязки, установленных по умолчанию. Выходные аргументы и хО являются необязательными параметрами, если значение хО не указано, то по умолчанию используется нулевое начальное приближение. Функция isqlin позволяет найти решение более общей задачи rnin ||Сх - <7||2 с линейными ограничениями на решение (16.2—16.4). Подбор параметров Предположим, что в некоторый физический закон у = л2, а3, а4, л) входят неизвестные параметры а,, а2, а3 и а4. Проделан ряд экспериментов и получено п опытных данных (xdath ydat^ с целью установления значений параметров. Возникает вопрос, как выбрать параметры физического закона так, чтобы результаты эксперимента соответствовали ему некоторым наилучшим образом. Решение задачи о подборе параметров в Optimization Toolbox основано на методе наименьших квадратов, который в данном случае состоит в нахождении минимума выражения 1 ” г "|2 2XLF(°1’ °2’ °3’ °4’ xdat,}~yda(i J Глава 16. Оптимизация 737 по всевозможным значениям at, a2, п3 и а4. Функция isqcurvefit предназначена для решения задачи о подборе параметров (число параметров может быть произвольным). Обращение к ней практически не отличается от вызова других функций Toolbox и в самом простом случае имеет вид: х - Isqcurvefit{fun, аО, xdat, ydat) где fun— указатель на файл-функцию (или ее имя), которая вычисляет F(alt а2, а2, а4, х), Список ее входных аргументов должен содержать массив для передачи значений параметров в файл-функцию и независимую переменную х. Дополнительно могут быть поставлены ограничения на параметры, которые в векторной записи имеют вид lb < а < ub. В этом случае векторы lb и ub задаются в пятом и шестом аргументах isqcurvefit: х = Isqcurvefit(fun, аО, xdat, ydat, lb, ub) Определите параметры в следующем примере. Пусть F = ^е"2* + п3 sinn4x, а в результате эксперимента получены следующие значения: xdat = [0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0]; = [1.1 2.1 3.5 3.9 4.3 5.1 4.2 4.0 3.3 2.2 2.1]. Известно, что значение каждого из параметров может находиться в промежутке [-10, 10]. Первым шагом является создание файл-функции (листинг 16.12). Параметры в fitfun передаются через вектор а. ........ Листинг 16.12. Файл-функция, зависящая от вектора параметр зв и аргумента ._ .. .. . ... ..... ........................... . ......... function у = fitfun(а, х) у = а (1) *exj;ia (2) *х) + а(3) *sin(a(4) *х) ; Теперь следует задать векторы xdat и ydat, отобразить данные на графике, выбрать начальное приближение аО, построить график при начальном приближении, задать 1раницы и вызвать isqcurvefit. После отыскания параметров необходимо вывести график функции и убедиться, что функция с найденными параметрами достаточно точно описывает данные. Последовательность команд, приведенная в листинге 16.13, реализует вышеописанные действия, в результате получается график, изображенный на рис. 16.1. В командное окно выводится вектор найденных значений параметров: а = 1.0959 1.167В 2.7003 3.7505 738 Часть IV. Использование Toolbox и решение прикладных задач Рис. 16.1. Результат подбора параметров Листинг 16.13. Подбор параметров % Ввод данных xdat = 0:0.1:1; ydat = [1.1 2.1 3.5 3.9 4.3 4.6 4.2 4.0 3.3 2.2 2.1]; % Отображение данных на графике plot(xdat, ydat, 1 о ‘; grid on % Выбор начального приближения аО = [0.0 0.0 4.0 1.0]; % Построение графика функции от начального приближения х = 0:0.05:1; уаО = fitfunlaO, х) ; hold on; plotfx, уаО, 1—b‘) % Задание границ области параметров LB - [-10 -10 -10 -10] ; LIB = [10 10 10 10]; % Подбор параметров, точка с запятой в конце команды не ставится для % вывода результата в командное окно Глава 16 Оптимизация 739 а = lsqcurvefit(@fitfun, аО, xdat, ydat, LB, UB) % Визуализация функции с найденными значениями параметров ya = fit fun (а, х) ; Hfit = plotfx, ya); set(Hfit, 'Linewidth', 2) legend('данные', 'начальное приближение', ’результат’, 4) Обратите внимание, что начальное приближение оказывает существенное влияние на получаемый результат. Если, к примеру, в качестве начального приближения к искомым параметрам взять вектор аО = [4.0 -1.0 о.о 0.0], то подбор параметров не приведет к хорошему результату (рис. 16.2). Рис. 16.2. Результат подбора параметров при плохом начальном приближении Параметры оптимизации Задачи оптимизации условно разделены в Optimization Toolbox на два класса: Medium-scale (средние) и Large-scale (большие), в зависимости от размерности задачи, т. е. числа переменных. Для решения каждого из классов задач реализованы соответствующие численные методы, объяснение кото 740 Часть IV. Использование Toolbox и решение прикладных задач рых выходит за рамки данной книги. Впрочем, краткая информация об алгоритмах содержится в справочной системе MATLAB по Toolbox. Последняя версия документации в формате PDF доступна на сайте производителя MATLAB. Пользователь имеет возможность отслеживать ход вычислительного процесса и задавать параметры, управляющие вычислениями. Для установки параметров следует сформировать структуру options при помощи функции optimset и затем указать данную структуру в качестве входного аргумента функции Optimization Toolbox, выбранной для решения поставленной задачи (формирование структуры options для функций fzero, fminbnd и fminsearch описано в разд. "Задание дополнительных параметров" главы б). Функции, предназначенные для решения задач оптимизации, обладают достаточно большим набором параметров. Команда optimset, вызванная с именем функции в качестве входного аргумента, выводит в командное окно структуру с информацией о текущих опциях вычислительного алгоритма данной функции. Обращение к optimset без входных аргументов позволяет отобразить в командном окне все возможные значения каждого из параметров. Подробная информация о назначении каждого параметра приведена в справочной системе MATLAB (см. разд. Optimization Toolbox: Function Reference: Optimization Parameters, где приведена таблица co всеми параметрами и описаны функции Toolbox). Получите установки функции fsolve, использовав обращение optimset ('fsolve'l. В командном окне отображаются параметры и их значения, ниже приведены параметры, используемые в данном разделе. ans = Diagnostics: 'off' Display: 'final1 Jacobian: 'off' LargeScale: 1 on1 Ma xFunrva1s: 110 0 *numberOf Variables' Maxlter: 400 MaxPCGIter: 'max(l, floor(numberOfVariables/2))' PrecondBandWidth: 0 TolFun: 1.0000e-006 TolPCG: 0.1000 TolX: 1.0000e-006 Назначение параме гров Disp] ay, MaxFunEvals, Maxlter, TolFun, Toix такое же, как И У функций fzero, fminbnd И fminsearch (см.табл. 6.1 в разд. "Задание дополнительных параметров' главы 6). Глава 16. Оптимизация 741 Следует иметь в виду, что все параметры делятся на при группы в зависимости от размерности задачи. П Параметры установки Large-scale алгоритмов. □ Параметры установки Medium-scale алгоритмов. □ Общие параметры для Large- и Medium-scale алгоритмов. Применяемый алюритм зависит от значения LargeScale, 'on' разрешает использование Large-scale алгоритма, если он допустим для решаемой задачи. Имеются некоторые ограничения на область применения Large-scale ал-горипмов, в частности, получающаяся в ходе решения система уравнений не должна быть недоопределенной, т. е. число уравнений не может превосходить число неизвестных. Такие параметры, как JacobPattern, LevenbergMarquardt, MaxPCGIter, TolPCG, PrecondBandWidth, соответствуют Large-scale алгоритмам. Получающиеся в процессе вычислений системы линейных уравнений решаются итерационным методом — методом предобусловленных сопряженных градиентов (PCG). По умолчанию выбирается диагональный предобусловливатель, т. е. ширина верхней полуленты равна нулю. В ряде случаев возможно добиться ускорения сходимости итерационного процесса за счет увеличения ширины ленты предооусловливателя. Параметр PrecondBandWidth служит для задания ширины верхней полуленты ленты в исходной матрице, на основе которой строится предобусловливатель. Максимальное число итераций в методе сопряженных градиентов определяется значением MaxPCGIter, а критерий останова — TolPCG. Задание матрицы Якоби вектор-функции исследуемой задачи значительно ускоряет вычисления. Файл-функция, вычисляющая левую часть исследуемой системы нелинейных уравнений (например, в случае fsolve), может иметь два выходных аргумента, во втором возвращается матрица Якоби системы. Соответствующий пример разобран ниже. Вместо аналитического вычисления матрицы Якоби левой части системы нелинейных уравнений можно задать его шаблон, т. е. расположение ненулевых элементов, в JacobPattern, тогда в процессе вычислений только ненулевые элементы матрицы Якоби будут аппроксимироваться конечными разностями, что значительно ускорит вычисления. Примеры Следующие разделы посвящены применению некоторых опций, управляющих вычислительным процессом, на примере решения большой системы 742 Часть /И Использование Toolbox и решение прикладных задач нелинейных уравнений. Разобрано создание приложения с графическим интерфейсом пользователя, облегчающее использование возможностей Optimization Toolbox. Решение системы нелинейных уравнений Рассмотрим пример решения системы нелинейных уравнений, в котором задание аналитических выражений для элементов матрицы Якоби существенно уменьшает время вычислений. Необходимо решить приведенную ниже систему нелинейных уравнений F(x) = 0 для и = 1000. 2х2 -х2 =1; -х|+2Д-л3=1; (614) хп-1 = 1. Файл-функция largesys вычисляет значения компонент F2 (х),..., Fll_l (х) вектор-функции в цикле for (листинг 16.14). Листинг 16.14. Файл-функция, вычисляющая левую чао истемы уравнений (6.14) function F = largesys(х) n = length(х); F = rand(n, 1); F(l) = 2*х(1)л2 - х(2) - 1; for i = 2:n-l F(i) = -x(i - 1) + 2*х(1)л2 - x(i + 1) - 1; end F(n) = -x(n - 1) + 2*x(n)''2 - 1; Размерность задачи достаточно большая, и, как мы увидим, ее решение может занять значительное время, если не принимать во внимание разреженную структуру исходной системы. В данном примере вычисление матрицы Якоби цает существенный выигрыш во времени. Матрица Якоби решаемой системы a>JA7-i.2. Глава 16. Оптимизация 743 имеет достаточно простую структуру— она является сильно разреженной (трехди агон альнои): । 1 >— О О 1 -1 4х2 0 0 J = 0 0 4x„_, -1 0 0 -1 4хп Напомним, что разреженные матрицы создаются при помощи функции sparse (работа с разреженными матрицами описана в главе 15). Очевидно, что матрица Якоби представляется суммой J = D + D1 + DlT разреженных матриц D и D1, где D = ’4Х] 0 0 4х2 0 0 0 ' 0 ; £>1 = 0 0 -1 0 0 0 О' 0 0 0 4л„-1 0 0 0 0 -1 0 0 0 4х„ 0 0 0 Дополните файл-функцию largesys нахождением разреженного представления для матрицы Якоби, которая вычисляется и возвращается во втором выходном аргументе, если файл-функция вызывается с двумя выходными аргументами. Используйте услоьный оператор if и переменную nargout для проверки числа выходных аргументов (проверка числа пара-мегров, с которыми вызвана файл-функция, описана в разд. "Условный оператор if' главы 7). Текст модернизированной файл-функции largesysj приведен в листинге 16.15. Листинг 16.15. Файл-функция largesysj, возвращающая матрицу Якоби function [F, J] - largesysj(х) % Файл-функция для вычисления левой части система нелинейных уравнений % и матрицы Якоби % Вычисление компонент вектор-функции F П = length(х); F = randtn,1); F(l) = 2*х(1)л2 - х(2) - 1; 744 Часть IV. Использование Toolbox и решение прикладных задач for i = 2:п - 1 F{i} = -x(i - 1) + 2*x(i)A2 - x(i + 1) - 1; end Ftn) = -x(n - 1) + 2*x(n)''2 - 1; % Если число выходных аргументов более единицы, то требуется найти % разреженное представление матрицы Якоби if nargout > 1 % Матрица Якоби является суммой трех матриц J = D + Dl + D1' % Формирование диагонали матрицы D d = 4*х; % Инициализация разреженного представления для матрицы D Diag = sparse(l:n, l:n, d, n, n); % Формирование вектора побочной диагонали d2 = -ones (1, n - 1) ,- % Инициализация разреженного представления для матрицы D1 Dl = sparse(2:n, 1:п - 1, d2, в, п); % Вычисление разреженной матрицы Якоби J = Diag + Dl + Dl1; end Рец'ение системы нелинейных уравнений оформите в файл-программе (листинг 16.16), в которой задаются число переменных и вектор начального приближения и используется fsolve для поиска корней. Наша цель состоит в исследовании эффективности применения явных формул для элементов матрицы Якоби, поэтому сначала обратитесь к fsolve со значением 'off параметра Jacobian (оно установлено по умолчанию) Заметьте, что в этом случае fsolve будет вызывать файл-функцию largesysj с одним выходным аргументом и матрица Якоби вычисляться не будет. Затем модифицируйте управляющую структуру, установив параметр Jacobian в значение в ’on', и снова примените fsolve. Для контроля за временем счета удобно задействовать встроенные функции tic и toe. = Листинг 16.16. Файл-программа для решения большой системы нелинейных iуравнений п = ЮОО; % число переменимте хО = ones(l, п) ; % начальное приближение % Решение системы без использования явных формул % для элементов матрицы Якоби Глава 16. Оптимизация 745 options = optimset('Display', 'iter', 'Diagnostics', 'on'); tic x = fsoive(Slargesysj, xO, options); toe s Решение системы с использованием явных формул % для элементов матрицы Яко^и options = optimset(options, 'Jacobian', 'on'); tic x = fsoive(@largesysj, xO, options); toe Выполнение операторов листинга 16.16 свидетельствует об эффективности использования явных формул для вычисления элементов матрицы Якоби по сравнению с аппроксимацией их конечными разностями — время счета отличается примерно в 50 раз. Поскольку параметр Diagnostics имеет значение ' on’, то в командное окно сначала выводится информация о количестве неизвестных, способе вычисления частных производных и применяемом алгоритме (в данном случае— метод доверительной области). Работа fsoive сопровождается отображением сведений о каждом шаге вычислительного процесса (опция Display установлена в 'iter'). Сведения представлены в виде таблицы: Norm of First-order Trust-region Iteration Fjnc-count f(х) step optimality radius 1 1 998 3 1 2 2 871.767 1 2.38 1 3 3 567.03 2.5 2.13 2.5 4 4 36.9426 6.25 0.932 6.25 5 5 0.0498932 1.87805 0.0273 15.6 б 6 6.87172е-008 0.0643166 Зе-005 15.6 7 7 1.31898е-019 7.56621е-005 4e-011 15.6 Столбик iteration содержит номер итерации; Func-count — число вызовов функции; f (х) — сумма квадратов значений левых частей уравнений системы для текущего приближения; Norm of step— норма шага на текущей итерации; First-order optimality— бесконечная норма градиента, вычисленного для текущего приближения; Trust-region radius — радиус дове-рительний области. Данный раздел описывает только решение системы нелинейных уравнений методом доверительных областей при помощи fsoive. В функции fsoive реализованы и другие алгоритмы решения, которые выбираются лри по 746 Часть IV. Использование Toolbox и решение прикладных задач мощи опций NonlEqnAlgorithm, LargeScale, LineSearchType управляющей структуры. Перед решением задач в Optimization Toolbox полезно обратиться к информации о настройках алгоритмов выбранной функции. Эти сведения могут быть почерпнуты из справочной системы Toolbox, Функции п допустимые параметры для них описаны в разделе Optimization Toolbox: Function Reference, задание параметров— в Optimization Toolbox: Function Reference: Optimization Parameters, а сами алгоритмы— в Optimization Toolbox: Standard Algorithms и Optimization foolbox: Large-Scale Algorithms. Мь. рекомендуем также изучить примеры решения оптимизационных задач, приведенные в справочной системе по Optimization Toolbox, Пример приложения с GUI Optimization Toolbox не имеет приложений с графическим интерфейсом пользователя для доступа к функциям оптимизации. Решение оптимизационных задач значительно упростилось бы при наличии соответствующего приложения. Текущий раздел посвящен написанию приложения с графическим интерфейсом для решения задачи о подборе параметров. Задача состоит в таком подборе параметров некоторой функции, чтобы она нанлучшим образом удовлетворяла набору данных. Решение задачи о подборе параметров с использованием Isqcurvefit описано выше на примере функции F - alea-x + «з sina4x (см. разд. "Подбор параметров”данной главы). Регулярное использование файл-программы, приведенной в листинге 16.13, для различных данных и функций не очень удобно— требуется изменять имя файла и файл-функции. При выборе начального приближения и задании допустимых интервалов для параметров также необходимо вносить изменения в файл-программу. Создание приложения с 1рафическим интерфейсом позволит существенно экономить время при подобной многократной обработке набора данных. Приложение должно предоставлять пользователю контроль над начальными установками, производить процедуру подбора параметров и отображать графическое представление результата. Приложение Подбор параметров, окно которого изображено на рис. 16.3, обладает вышеописанными возможностями. Кнопка Считать данные приводит к появлению диалогового окна открытия файла, в котором пользователь выбирает нужный файл с данными, имя файла заносится в область Файл с данными. Считанные данные отображаются маркерами на осях в окне приложения. Имя файл-функции, вычисляющей функцию с параметрами, пользователь задает в строке ввода Файл-фхнкция Соответствующие строки позволяют выбрать начальное приближение, верхнюю и нижнюю границы параметров. График начального при Глава 16 Оптимизация 747 ближения строится при нажатии на кнопку График для нач. нрибл. Кнопка ПОДБОР служит для запуска процедуры подбора параметров. Найденные значения выводятся в область Оптимальные параметры. Удаление графиков производится при помощи кнопки Очистить оси. Рис. 16.3. Окно приложения Подбор параметров Создание вышеописанного приложения Подбор параметров не представляет большого труда. Основные вопросы, связанные с программированием приложений с графическим интерфейсом пользователя, разобраны в части III книги. Подфункции обработки событий содержатся в листинге 16.17. Имена основных объектов, расположенных в окне приложения, помещены в табл. 16.2. Таблица 16.2. Имена объектов приложения Подбор параметров Объект Имя Кнопка < читать данные LoadBtn Кнопка График для нач. прибл. GuessBtn 748 Часть IV. Использование Toolbox и решение прикладных задач Таблица 16.2 (окончание) Объект Имя Кнопка ПОДБОР - FitBtn Кнопка Очистить оси ClearBtn Область Файл с, (анными DataFileEdt Область Файл-функция FunEdt Область Начальное приближение GuessEdt Область Нижняя граница LBEdt Область Верхняя граница UBEdt Область Оптимальные параметры ParEdt function LoadBtn_Callback(hObject, eventdata, handles) % Нажата кнопка "Считать данные" % Вывод диалогового окна открытия файла DataFileStr = uigetfile('*.dat', 'Открыть файл с данными'); if DataFileStr ~= О % Запись в эбласть ввода "Файл с данными" имени файла set(handles.DataFileEdt, 'String', DataFileStr); % Извлечение данных из файла и запись их в поля структуры handles data = load(DataFileStr) ; handles.xdat = data(:, 1)‘ ; handles.ydat = data(:, 2)' ; % Сохранение тгруктуры handles guidata(gcbo, handles) % Построение графика данных маркерами Hdata = plot(handles.xdat, handles.ydat, '.r'); set(Hdata, 'Markersize', 15); hold on % Очистка области ввода значений параметров "Оптимальные параметры" set(handles.ParEdt, 'String', '') end Глава 16. Оптимизация 749 function GuessBtn_Callback(hObject, eventdata, handles) % Считывание вектора начального приближения для параметров из % области ввода "Начальное приближение" ParStr = L'parO=', get(handles.GuessEdt, 'String'), ';']; % Выполнение строки, запись начального приближения в вектор рагО eval(ParStr) % Построение исследуемой функции от начального приближения % Задание вектора значений абсцисс х = (min(handies.xdat) : (irax (handles,xdat) -... min(handles.xdat))/3 0:max(handles.xdat)); % Вычисление файл-функции, имя которой пользователь ввел в строке % ввода " ^аил-функция" FunName = get(handles.FunEdt, 'String', ';') у = feval (FunName, parO, x) ; % Отображение графика для начального приближения plot(x, у, '—b') function FitBtn_Callback(hObject, eventdata, handles) % Задание установок для подбора параметров options = optimset('Display', 'iter'); % Формирование строки с командой для засылки в вектор рагО % начального приближения ParStr = CparO=', get(handles.GuessEdt, 'String'), 1;1]; % Выполнение строки, запись начального приближения в вектор рагО eval(ParStr) % Считывание нижней и верхней границы из областей ввода "Нижняя % граница" и "Верхняя граница" и занесение их в векторы LB и UB eval(['LB=', get (handles. LBEdt, 'String'), ';']),• eval(['UB=', get(handles.UBEdt, 'String', ';')]); % Занесение в FunName имени функции из области ввода "Файл-функция" FunName = get(handles.FunEdt, 'String'); % Вызов функции Ibgcurvefit для подбора параметров par = Isqcurvefit(FunName, parO, handles.xdat, handles.ydat, LB, ... UB, options); % Запись результатов в строку "Оптимальные параметры" ParStr = mat2str(par, 3); set (handles. Parbdr, ' String', ParStr),- 750 Часть IV. Использование Toolbox и решение прикладных задач % Построение исследуемой функции от найденных параметров х = (min(handles.xdat}:(max(handles.xdat) . min(handles,xdat))/3 0:max(handles.xdat)); у - feval UunName. par, x); Hplot = plotix, y, '-g'); set(Hplotfl), 'LineWidth', 2 ) function ClearBtn_Callback(hobject, eventdata, handles) % Очистка осей cla; Усовершенствуйте приложение, добавив элементы управления для задания параметров для управления вычислительным процессом: точности, максимально допустимого числа итераций и обращений к функции, выбора алгоритма. Перед вызовом isqcurvefit следует выяснить выбор пользователя и сформировать подходящую структуру options. Схожие приложения с графическим интерфейсом могут быть созданы и для решения дру: их задач оптимизации. Глава 17 Символьные вычисления В состав MATLAB входит Symbolic Math Toolbox, предназначенный для вычислений в символьном виде. Преобразование выражений, разыскание аналитического решения задач линейной алгебры, дифференциального и интегрального исчисления, получение численного результата с любой точностью — вот далеко не полный перечень возможностей, предоставляемых данным Toolbox. Функции Symbolic Math Toolbox реализуют интерфейс между средой MATLAB и библиотекой функций, являющихся вычислительным ядром Maple, причем работа в MATLAB не требует установки Maple. Расширение Toolbox позволяет пользователям, имеющим опыт работы в Maple, использовать ресурсы ядра Maple практически в полном объеме. включая и программирование в Maple. Символьные переменные и функции Объектно-ориентированный подход, реализованный в MATLAB позволил сделать работу с символьными выражениями простой и удобной. Если вы освоили работу с арифметическими выражениями, то символьные преобразования не должны вызвать затруднений. Определение переменных и функций и работа с ними Символьные переменные и функции являются объектами класса sym object, в отличие от числовых переменных, которые содержатся в массивах double array. Символьный объект создается при помощи функции syms. Команда » syms х а Ь создает три символьные переменные х, а и ь. Размер памяти, отводимый по умолчанию под символьные переменные, достаточно большой — посмот- 752 Часть IV Использование Toolbox и решение прикладных задач рите информацию об определенных только что переменных в окне Workspace браузера рабочей среды или вызовите команду whos: » whos x a b Maine Size Bytes Class a 1X1 126 sym object b 1X1 126 sym object X 1x1 126 sym object Grand total is 6 elements using 378 bytes Конструирование символьных функций от переменных класса sym object производится с использованием обычных арифметических операций и обозначений для встроенных математических функций, например: » f = (sin(x) + a)"2*(cos(x) + b) Л2/здгГ(abs(а + b)) f = (sin(x) + a)A2*(cos(x) + b)A2/abs(a + b)''(l/2) Запись формулы для выражения в одну строку не всегда удобна, более естественный вид выражения выводит в командное окно функция pretty: » pretty(f) 2 2 (sin(x) + a) (cos(x) + b) 1/2 I a + b ) Определенная функция f также является символьной переменной тина sym object, в чем несложно убедиться при помощи браузера переменных. Имеющиеся символьные переменные и функции позволяют образовывать новые символьные выражения: » syms у » g = (ехр(-у) + 1)/ехр(у) g _ (ехр(-у) + 1)/ехр(у) » h = f*g h = (sin(x) + a)A2*(cos(x) + b)A2/abs(a + b) Л (1/2) * (exp (-y) + l)/exp(y) » pretty(h) 2 2 (sin(x) + a) (cos(x) + b) (exp(-y) + 1) 1/2 | a + b | exp(y) Глава 17. Символьные вычисления 753 Символьную функцию можно создать без предварительного объявления переменных при помощи sym, входным аргументом которой является строка с выражением, заключенная в апострофы: » z - sym('cA2/{d + 1)') z = сл2/(d + 1) » pretty{z) 2 с d + 1 Для объявления символьных переменных может быть использована функция sym. Команда syms а, ь, с эквивалентна последовательности а = sym('a');b = sym('b');c = sym('c'). При работе в области комплексных чисел следует указать, что определяемые переменные являются, в общем случае, комплексными Комплексные символьные переменные задаются командой syms с опцией unreal. Опция real означает, что переменные интерпретируются как вещественные. Убедитесь, что результат символьных вычислений зависит от того, какие символьные переменные используются— вещественные или комплексные. Объявите две вещественные переменные а и ь, образуйте комплексное число, считая, что а является действительной частью, а ь — мнимой, и найдите сопряженное к нему при помощи conj: » syms а Ь real » р = conj(а + i*b) Р = а - i*b Произведите аналогичные действия, предварительно объявив а и t как комплексные переменные: » syms a b unreal » q = conj(а + i*b) Q = conj (a + i’b} Обратите внимание на значения символьных переменных р и д. Использование одних и тех же операторов в символьных и числовых выражениях возможно благодаря тому, что пакет MATLAB является объектно- 754 Часть IV Использование Toolbox и решение прикладных задач ориентированной системой. Мы не будем описывать идеологию объектно-ориентированного программирования, а поясним сказанное на примере операции сложения. Для сложения чисел и числовых массивов в MATLAB зарезервирован знак +, который приводит к вызову встроенной функции plus, расположенной в подкаталоге toolboxmatlabops основного каталога MATLAB. Проверьте, что 1.3 + 2.9 и plus(1.3, 2.9) приводят к одинаковому результату. Для символьных переменных и функций используется файл-функция с тем же именем plus, находящаяся в подкаталоге toolboxsymbolic@sym основного каталога MATLAB. Изучите ее содержимое, открыв файл plus.m в редакторе MATLAB (не вносите в него изменений!). В начале оба ее входных аргумента приводятся к символьному типу данных при помощи функции sym, что позволяет складывать символьную переменную с числовой и получить символьный результат. Далее проверяется совпадение размеров входных аргументов, которые могут быть массивами. Последняя строка содержит вызов функции maple, служащей для обращения к соответствующей функции или оператору из ядра пакета Maple — в данном случае символьному сложению. Говоря на языке объектно-ориентированного программирования, числовые переменные типа double array образуют класс со своими методами (в том числе plus). Для класса символьных объектов sym метод plus переопределен, MATLAB определяет по типу аргумента соответствующий метод класса и выполняет его. Пользователь MATLAB может создавать собственные классы и определять их методы, в том числе и переопределять методы предка класса. Выполнение подобных действий требует понимания основ объектно-ориентированного программирования. Создание классов в MATLAB описано в справочной системе в разд MATLAB: Classes and Objects. Матрицы и векторы Символьные переменные могут являться элементами матриц и векторов. Элементы строк матриц при вводе отделяются пробелами или запятыми, а столбцов — точкой с запятой, так же как и для обычных матриц. В результате образуются символьные матрицы и векторы, к которым применимы матричные и поэлементные операции и встроенные функции. » syms abcdefgh » А = (а Ь; с d] А - [ а, Ь] Глава 17. Символьные вычисления 755 [ с, d] » В - [е, f; g. И, В = [ е, £] t g. h] » С = A*B С = [ a*e + b*g, a*f + b*h] [ c*e + d*g, c*f + d*h] » F = A. *B F = [ a*e, b*f] [ g*c, d*hj Конструирование бло 1ных символьных матриц не отличается от числовых, требуется следить за размерами соответствующих блоков: » D = [С А; В С] D = [ а*е + b*g, a*f + b*h, a, b] [ с*е + d*g, c*f + d*h, c, d] [ e, f, a*e + b*g, a*f + b*h] [ g, h, c*e + d*g, c*f + d*h] Обращение к элементам символьных матриц и векторов производится при помощи индексации, в том числе двоеточием и вектором со значениями индексов: » d2 = D(2, d2 = [ с*е + d*g, » d = d2([l d = [ c*e + d*g. :} c*f + d*h, 3 4]) c, c, d] d] Для удаления строк или столбцов символьных матриц используется пустой массив » D(l:2, :) = [ 1 D = [ е, f, а*е + b*g, a*f + b*h] [ g, h, c*e + d*g, c*f + d*h] 25 Зак. во 756 Часть IV. Использование Toolbox и решение прикладных задач Вычисления с символьными переменными Символьные операции позволяют находить точные значение выражений или значения со сколь угодно большой точностью. Для преобразования значения числовой переменной в символьную служит функция sym. Введите массив типа double array » А = [1.3 -2.1 4.9 6.9 3.7 8.5]; и образуйте соответсз вующий ему символьный массив » В - sym (А) в = [ 13/10, -21/10, 49/10] [ 69/10, 37/10, 17/2] При переходе от числовых к символьным выражениям по умолчанию используется запись чисел в виде рациональной дроби. Возможны и другие формы представления чисел в символьном виде, которые определяются значением второго входного аргумента функции sym (см. разд. MATLAB: Symbolic Math Toolbox: Function Reference справочной системы). Создайте вектор-столбец » с = [3.2; 0.4; -2.1]; и занесите в вектор d его символьное представление » d = sym(c); Умножьте матрицу в на вектор d— результат является символьной переменной, причем все вычисления проделаны над рациональными дробями. » е = B*d е - [ -697/100] [ 571/100] Использование рациональных дробей при выполнении символьных вычислений означает, что всегда получается точный результат, не содержащий погрешность округления. Убедиться в вышесказанном можно на простом примере. Установите формат long е для отображения максимально возможного числа значащих цифр для значений числовых переменных и найдите сумму чисел I010 и 1010. » format long е » 1.Се+10 + 1.0е-10 ans = 1.000000000000000е+010 Глава 17. Символьные вычисления 757 Запишите каждое из чисел в символьные переменные и сновс вычислите сумму » large = sym(l.OelO); » small “ sym(l.Oe-lO); » s - large + small s = 100000000000000000001/10000000000 Рациональная дробь является точным значением суммы. Разумеется, символьные вычисления требуют больших затрат компьютерных ресурсов по сравнению с обычными. Вычисления с рациональными дробями позволяют получить значение символьного выражения с любой степенью точности, т. е. найти сколь угодно много значащих цифр результата. Для вычисления символьных выражений предназначена функция vpa: » с = sym(’sqrt(2)’); » cn = vpa(с) СП = 1.4142135623730950488016887242097 По умолчанию удерживается 32 значащие цифры. Второй дополнительный входной параметр vpa служит для задания точности: >> cn = vpa(c, 70) СП = 1.414213562373095048801688724209696078569671875376948073176679737990732 Второй аргумент vpa задает удерживаемое число значащих цифр только для данного вызова vpa. Для глобальной установки применяется функция digits, во входном аргументе которой указывается зребуемое количество цифр. Важно понимать, что выходной аргумент функции vpa является символьной переменной: » whos сп Name Size Bytes Class cn 1x1 266 sym object /’58 Часть /V Использование Toolbox и решение прикладных задач Для перевода символьных переменных в числовые, т. е. переменные типа double array, используется функция double: » спит = double (сп) спит = 1.41421356237310 Графическое представление функций Визуализация символьной функции одной переменной осуществляется при помощи ezplot. Самый простой вариант использования ezplot состоит в указании символьной функции в качестве единственного входного аргумента, при этом в графическое окно выводится график функции на отрезке [-2л, 2л] >> f = sym] ' x,‘2*sin (х) ' ) ; » ezplot(f) Обратите внимание (рис. 17.1), что автоматически создается соответствующий заголовок. По умолчанию в качестве отрезка, на котором строится график- принимается промежуток пересечения области определения функции и интервала [-2л. 2я]. Вторым аргументом может быть задан вектор с границами отрезка, на котором требуется построить график функции » ezplot(f, [-3 2]) Функция ezplot имеет некоторые отличия от своего аналога— функции fpiot, применяемой к числовым функциям. В частноети, возможно указание символьной функции, зависящей от двух аргументов: » z = вут('хЛ2 + уА3'); » ezplot(z, [-2 1-34]) В данном случае выведется линия, на которой исследуемое выражение равно нулю Пределы изменения определяются названиями аргументов. Первые два числа соответствуют первому по алфавиту аргументу, а последние — второму, например в ezplot (z, [-2 1 -3 4]),гдег = зуш('хЛ2 + аЛ3'), считается, что а изменяется от -2 до 1, а х — от -3 до 4. При помощи ezplot возможно так же отображение параметрически заданных функций. Глава 17. Символьные вычисления 759 Нис. 17.1. График символьной функции Рис. 17.2. График символьной функции двух переменных Symbolic Math Toolbox предоставляет пользователю целый набор средств для визуализации СИМВОЛЬНЫХ функций: ezmesh, ezmeshc, ezplot, ezplot3, 760 Часть IV. Использование Toolbox и решение прикладных задач ezpoiar, ezsurf, ezsurfс Функция ezsurf отображает график символьной функции только для допустимых значений аргументов, остальные значения отбрасываются, что позволяет исследовать область определения функции двух переменных. Например, обращение » ezsurf('asin(хЛу)', [0 6 -7 7]) приводит к графику, изображенному на рис. 17.2. Упрощение, преобразование и вычисление выражений Сложные алгебраические и тригонометрические выражения нередко могут быть приведены к эквивалентным путем упрощения. Symbolic Math Toolbox имеет ряд сервисных функций, предназначенных для различных преобразований символьных выражений. Пользователь может производить как стандартные операции над полиномами, так и использовать более общий алгоритм, предназначенный для упрощения выражений, которые содержат встроенные символьные функции. Операции с полиномами реализуют четыре функции: collect, expand, homer и factor. Вычисление коэффициентов при степенях независимой переменной производится с использованием функции collect. Введите полином и отобразите его в командном окне пои помощи pretty. » р = sym(1 (х + а) Л4 + (х - 1) Л3 - (х - а) Л2 - а*х + х - 3 1); » pretty(р) 4 3 2 (х + а) + (х — 1) — (х — а) — а х + х — 3 Преобразуйте р к виду, содержащему степени х с соответствующими коэффициентами: » pc = collect(р); » pretty(рс) 4 3 2 2 3 4 2 х + (1 + 4 а) х + (-4 + б а ) х + (4+а + 4а)х + а — 4 — а По умолчанию в качестве переменной выбирается х, однако можно было считать, что а — независимая переменная, а х входит в коэффициенты полинома, зависящего от а. Второй аргумент функции collect предназначен для указания переменной, при степенях которой следует найти коэффициенты » pea = collect(р, ’а'); » pretty(рса) 43 223 4 32 а + 4 х а + (-1 + 6 х ) а + (4 х + х) а + х + (х — 1) —х —3+х Глава 17 Символьные вычисления 761 Функция tixoand представляет полином суммой степеней без приведения подобных слагаемых: » ре = expand(р); » pretty (ре) 4 322 3432 2 х + 4 а х + 6 х а + 4 ха +а +х — 4 х + 4 х — 4 + а х-а Аргументом expand может быть не только полином, но и символьное выражение, содержащее тригонометрические, экспоненциальную и логарифмическую функции, например » f = cym{ 'sin(arccos{3*x)) + exp(2*log(x))'); » fe = expand{f); » pretty(fe) 2 1/2 2 (1 - 9 x ) + x Символьные полиномы разлагаются на множители функцией factor, если получающиеся множители имеют рациональные коэффициенты » р = sym('хЛ5 + 13*хЛ4 + 215/4*хЛ3 + 275/4*хЛ2 - 27/2*х - 18'); » pf = factor(р); » pretty(pf) 1/4 (2 х + 1) (2 х - 1) (х + 6) (х + 4) (х + 3) Представление числа в виде произведения простых чисел также выполняется при помощи factor: » syms а » а = sym{’230010'); » s — factor(а) s = (2) * (3) * (5) * (11) * (17) * (41) Обратите внимание, что обращение » sl = factor(230010) sl = 2 3 5 11 17 41 выводит в командное окно аналогичный результат, но переменная s является символьной, a si — вещественной, поскольку для объектов класса sym метод factor переопределен. Упрощение выражений общего вида производится при помощи функций simple и simplify, которые основаны на разных подходах. Функция simplify реализует мощный алгоритм упрощения выражений, содержащих 762 Часть IV. Использование Toolbox и решение прикладных задач как тригонометрические, экспоненциальную и логарифмическую функции, так и специальные: гипергеометрическую, Бесселя и гамма-функцию. Кроме того, simplify способна преобразовывать выражения, содержащие символьное возведение в степень, суммирование и интегрирование. Алгоритм, заложенный в simple, пытается получить выражение, которое представляется меньшим числом символов, чем исходное, последовательно применяя все функции упрощения Toolbox. Функция subs позволяет произвести подстановку одного выражения в другое. В общем виде subs вызывается с тремя входными аргументами: именем символьной функции, переменной, подлежащей замене, и выражением, которое следует подставить вместо переменной. Функция subs, в частности, облегчает ввод громоздких символьных выражений, имеющих определенную структуру: » f = sym('(аЛ2 + ЬЛ2)/(аЛ2 - Ьл2) + ал4/Ьл4'),- » f = subsif, 'а', '(ехр(х) + ехр(-х))'); » f = subs(f, 'b', '(sin(x) + cos(x))’); » pretty(f) 2 2 4 (<=:qo(x) + exp(-x)) + (sin(x) + cos(x)) (exp(x) + exp{-x)) 2 2 4 (exp(x) + exp(-x)) — (sin(x) + cos(x)) (sin(x) + cos(x)) Заметим, что необязательно было производить подстановку сначала для а и затем для ь. Одновременная замена переменных соответствующими выражениями требует указания массивов ячеек в фигурных скобках (работа с массивами ячеек описана в разд. "Массивы структур и массивы ячеек" главы 8). Последовательность команд » f = 5ут('(аЛ2 + Ь/'2)/(а/'2 - ЬЛ2) + аЛ4/Ь''4|); » f=subs(f, {’а“, ’Ъ'}, {'(ехр(х) + ехр(-х))', 1(sin(x) + cos(x))'}); » pretty(f) обеспечивает тот же самый результат. Подстановка вместо переменной ее числового значения приводит к вычислению символьной функции от значения аргумента, например: » f = sym('ехр(хЛ3 + 2*хА2 + х + 5)'); » q = subs(f, ’х‘, 1.1) q - 1.8977е+004 Глава 17. Символьные вычисления 763 Число можно заменить его символьным представлением и затем найти значение функции с произвольной точностью при помощи vpa: » q = subsff, 'х', '1.1') q = ехр(1.1Л3 + 2*1.1Л2 + 1.1 + 5) » vpa(q, 50) ans - 18977.322639183802289522844472139578548863931041740 Решение задач Решение систем линейных и нелинейных уравнений, разыскание пределов и производных, нахождение определенных и неопределенных интегралов, поиск аналитических решений дифференциальных уравнений и систем, словом, все основные математические задачи могут быть исследованы при помощи Symbolic Math Toolbox. Разумеется следует учитывать, чти далеко не все задачи имеют аналитическое решение. Задачи линейной алгебры Функции Symbolic Math Toolbox выполняют в символьном виде операции с ма грицами и векторами. Все задачи, описанные в главе 6, могут быть решены в символьной форме, причем соответствующие функции имеют те же названия, что и функции для численного решения, поскольку соответствующие методы переопределены для класса sym. Вычисление определителя в символьной форме производится с использованием aet, например: » А = sym(' [а b с; de f; g h j)1); » D = det(A) D = j*a*e - a*f*h - j*d*b + d*c*b + g*b*f - g*c*e Функция inv предназначена для символьного обращения матриц. Найдите обратную к магрице А, определенной выше. » Al = inv (А) ; » pretty(AI) [ -1 е + f h [-------------- [ %1 I ib — ch bf — се] ---------- -----------------] %1 %1 ] 1 764 Часть IV. Использование Toolbox и решение прикладных задач [ -id + fg i а — eg a f — cd] [--------- ----------- ------------] [ %1 %1 %1 ] [ ] [-dh+eg ah— b g a e — b d] [--------- ----------- ------------] [ %1 %1 %1 ] %1 :=-iae+afh+idb—dch—gbf+gee Обратите внимание на форму отображения результата в командном окне. Знаменатель каждого элемента обратной матрицы ai одинаков для всех элементов, поэтому используется подстановка %1, соответствующее выражение для %1 приведено ниже матрицы. Характеристический полином матрицы, зависящий от переменной х, находит функция poly: » рА = poly (А) ; » pretty (рА) ; 3 2 2 2 х - i х — ex + ixe — xfh — ах + iax + aex — iae + afh — dbx + idb — dch — gbf — gex + gee Второй дополнительный аргумент poly позволяет указать, от какой переменной должен зависеть характеристический полином матрицы. Элементы символьных матриц могут быть не только символьными переменными, но и выражениями, и рациональными числами. В качестве примера найдите собственные числа матрицы Гильберта пятнадцатого порядка, используя сначала символьное представление элементов матрц^ы, а затем сравните их с результатом численного алгоритма. Определите временные затраты этих способов, сгенерировав отчет при помощи профайлера (см. разд. "Профайлер"главы 15). Файл-программа для нахождения собственных чисел матрицы Гильберта двумя способами и замера времени приведена в листинге 17.1. Листинг 17.1 На хождвни собственных чисел матрицы Гильберта .......... . ........... . ............................. profile on -detail builtin АЗ = sym(hilb{15)); vs = eig(AS) A = hilb(15) ; v = eig(A) profile report Глава 17. Символьные вычисления 765 Решение систем линейных алгебраических уравнений в символьном виде производится при помощи знака обратной косой черты. Следующий пример демонстрирует нахождение линейных базисных функций треугольного конечною элемента в виде, пригодном для помещения в сооственн^ю программу. Задача сосгоит в получении формул для вычисления трех линейных функций N1 (х, у), N2 (х, у), из (х, у), каждая из которых равна единице в одной из вершин треугольника, а в двух остальных обращается в ноль (рис. 17.3). Вершины треугольника имеют координаты (xl, yl), (х2, у2), (хЗ, уЗ}. Достаточно записать общее выражение для линейной функции двух переменных с коэффициентами а, Ь и с, а затем разыскать их для каждой функции, решая соответствующую систему линейных уравнений. Листинг 17.2 содержит файл-программу basis для нахождения формул, по которым вычисляются требуемые функции. Обратите внимание, что Symbolic Math Toolbox позволяет сгенерировать выражения в виде, пригодном для занесения в собственную программу на Fortran или С. В файл-про1рамме basis использована функция ссоЛе, разработчикам программ на Fortran следует использовать fortran вместо ccode. Рис. 17.3. Линейные базисные функции Листинг 17.2- Файл-программа basis для получения бгзисных линейных syms а Ь с х у % Задание общего вида линейной функции N = а + Ь*х + с*у; % Определение символьной матрицы системы уравнений М = sym (’I1 xl yl; 1 х2 у2; 1 хЗ уЗ ] 1) 766 Часть IV. Использование Toolbox и решение прикладных задач % Нахождение N1 г = sym(' [1; 0,- 0] '); % правая часть системы уравнений для N1 v = Мг; % решение системы % Подстановка выражений Nl = subs(N, a, v(l)); Nl = sabs(Nl, b, v(2)); Nl = subs(Nl, c, v(3}); для коэффициентов а. Ь, с Nl = simplify(Nl); % упрощение N1 pretty(Nl) % вывод N1 в командное окно cccde(Nl) % генерация С-кода для N1 % Нахождение N2 r = sym('[Or 1; 0]'); % правая часть системы уравнений для N2 V = Mr; % решение системы % Подстановка выражений N2 = subs(N, a, v(l)); N2 = subs(N2, b, v(2)); Ы2 = subs(N2, c, v(3)); для коэффициентов а. Ь, с N2 = simplify (N2) ; % упрощение N2 pretty(N2) % выв эд N2 в командное окно ccode(N2) % генерация С-кода для N2 % Нахождение N3 r = sym('[0; 0; 1]'); % правая часть системы уравнений для N3 v = Mr; % Подстановка выражений N3 = subs(N, a, v(l)); N3 = subs(N3, b, v(2)); N3 = subs(N3, c, v(3)); для коэффициентов а, Ь, с N3 = simplify(N3); % упрощение N3 pretty(N3) % вывод N3 в командное окно ccode(N3) % генерация С-кода для N3 В результате работы файл-программы basis в командное окно выводятся выражения для трех базисных функций Nl, N2 и N3 и их представление в формате С, Ниже приведен результат только для первой базисной функции: -хЗ у2 хЗ yl + t0 = (-хЗ*у2 + х2*уЗ - х*уЗ х1*уЗ + х1*у2) + х2 уЗ — х уЗ + х у2 + у хЗ — у х2 х2 уЗ — х2 yl — хЗ у2 — xl уЗ + xl у2 + х*у2 + у*хЗ - У*х2) / (хЗ*у1 + х2*уЗ - х2*у1 - хЗ*у2 - Глава 17 Символьные вычисления 767 Соответствующие строки можно легко поместить из командного окна в собственную программу при помощи буфера обмена Windows. Суммирование и разложение в ряд Разложение математических функций в ряд Тейлора позволяет проделать фу нкция taylor, например- » f = sym(’1/(1 + х)1); » tf = taylor(f); » pretty(tf) 2 3 4 5 1 — X + X — X + X — X По умолчанию выводится шесть членов ряда разложения в окрестности точки ноль. Число членов разложения можно задать во втором дополнительном параметре taylor. Третий параметр указывает, по какой из переменных следует производить разложение в том случае, когда символьная функция определена от нескольких переменных: » syms у » д = sym('1/ (х + у)1); » tg = taylor(g, 7, у); » pretty(tg) 2 3 4 5 6 У У У У У У 1/х —-----+------------+------------+------ 2 3 4 5 6 7 X X X X X X Точка, в окрестности которой проводится разложение, указывается в четвертом входном аргументе taylor. В качестве функций, подлежащих разложению в ряд, могут выбираться в том числе и встроенные математические функции, например: » pretty{taylor!'ехр(х)1, 4, х, 1/2)) 2 ехр(1/2) + ехр(1/2) (х - 1/2) + 1/2 ехр(1/2) (х - 1/2) 3 + 1/6 ехр(1/2) (х - 1/2) В состав Symbolic Math Toolbox входит приложение tayiortool с графическим интерфейсом, предназначенное для наглядной демонстрации разложения в ряд различных функций, в том числе и определенных пользователем. 768 Часть IV. Использование Toolbox и решение прикладных задач Команда tayiortool приводит к появлению окна приложения, изображенного на рис. 17.4. Рис. 17.4. Приложение tayiortool Пользователь может вводить формулы различных функций в строке f(x)= в соответствии с правилами MATLAB и исследовать приближение функции на произво льном интервале отрезком ряда Тейлора, содержащим различное число членов разложения. Интерфейс приложения tayiortool достаточно простой и не требует дополнительных пояснений. Нахождение символьных выражений для сумм, в том числе и бесконечных, позволяет осуществить функция symsum. Обращение к symsum в общем виде предполагает задание четырех аргументов: слагаемого в символьной форме, зависящего от индекса, самого индекса и верхнего и нижнего предела суммы. Сумма ж И)* Глава 17. Символьные вычисления 769 вычисляется при помощи следующих команд: » Tyros к » s - syr'sum( * (-1) Лк/кЛ2 ’, к, 1, Inf) з = -l/12*piA2 Возможно суммирование слагаемых, зависящих не только от индекса, но и от некоторой символьной переменной. Если я слагаемые входит факториал, то следует применить к выражению для факториала функцию sym. Найдите значение бесконечной суммы, являющейся разложением функции sin х в ряд «о 2Л+1 л=о (2Л + 1)! Используйте команды: » syms к х » s = symsum((-1)Л(к)*хЛ(2*к + 1)/sym(1(2*к + 1) ! ’), к, 0, Inf) s = sin(x) Пределы, дифференцирование и интегрирование Ряд функций Symbolic Math Toolbox предназначен для решения задач дифференциального и интегрального исчисления. Функция limit находит предел функции в некоторой точке, включая и плюс или минус бесконечность. Первым входным аргументом limit является символьное выражение, вторым — переменная, а третьим — точка, в которой разыскивается предел. Пусть, например, требуется вычислить z . час lim [1-1— | , X I Для получения ответа определите а и х, как символьные переменные, и используйте inf в качестве точки предела: » syms а х » limit((1 + 1/х)Л(х*а), х. Inf) ans = exp (а) 770 Часть IV. Использование Toolbox и решение прикладных задач Функция limit позволяет находить односторонние пределы, для нахождения предела справа следует указать четвертый дополнительный аргумент right ’, а слева — 1 left1. Найдите решение следующих двух задач lim (IO + jc)^*; lim (1()1 х)1/Л. л-»0+ ' ' л->0_ ' Очевидно, что следует выполнить следующие команды: » syms b х » limit((10 + х)Л(1/х), х, 0, ’left') ans = О » limit({10 + х)Л(1/х), х, 0, 'right') ans = inf Обратите внимание, что обычный предел в точке ноль в предыдущем примере не существует: » limit((10 + х)Л(1/х), х, 0) ans = NaN Определение производной через предел позволяет применять limit для дифференцирования функций. Найдите первую производную функции arctgx, используя равенство d arctg(x + /?)-arctg х —arctg л - lim-------------------; dx h-to h >> syms h x » L = limitf(atan{x + h) - atan(x))/h, h, 0) ; » pretty(L) 1 2 1 + x Вычисление производных любого порядка проще производить при помощи функции diff. Символьная запись функции указывается в первом входном аргументе, переменная, по которой производится дифференцирование — во втором, а порядок производной — в третьем. Применение diff для вычис Глава 17. Символьные вычисления 771 ления производной в предыдущем примере, разумеется, приводит к эквивалентному результату: » Р = diff('atan(x)’, х, 1); » pretty(Р) 1 2 1 + х Налищите файл-функцию tangent для исследования скорости роста функций. Входными аргументами tangent являются строка с символьным представлением функции одной переменной х и числовое значение абсциссы точки, в которой следует провести касательную. Файл-функция tangent выводит в одно графические окно графики функции и касательной к пей в заданной точке. К примеру, вызов » tangent('sin(х)*хл21, 2) должен приводить к графикам, изображенным на рис. 17.5. Риг. 17.5. Графики функции и касательной 772 Часть IV. Использование Toolbox и решение прикладных задач Алгоритм файл-функции включает: 1. Определение символьной функции по строке при помощи sym. 2. Нахождение производной. 3. Формирование символьного выражения для касательной и подстановки в него значения производной, абсциссы и ординаты точки, в которой проводится касательная. Для построения касательной линии используйте ezplot. Отображение графика исследуемой функции жирной линией выполните при помощи plot, для чего предварительно сгенерируйте вектор со значениями аргумента и получите вектор соответствующих численных значений символьной функции. В качестве границ отрезка, на котором выводятся графики функции и касательной к ней, выберите точки, отстоящие на единицу вправо и влево от заданной. Файл-функция tangent не требует выходных аргументов. Обратитесь к листингу 17.3 за дополнительной информацией в случае возникновения затруднений при программировании. ......... ~ • Листинг 17.3. Файл-функция t ang ant function tangent(funstr, XO) % Файл-функция для построения касательной % к графику функции funstr в точке ХО % funstr — строка с символьным выражением функции % Использование: % tangent('ехр(х)', 0) % Задание символьной функции syms х f “ sym( funstr); % Вычисление функции в точке ХО YO = substf, 'х', ХО) % Определение интервала для построения графиков % функции и касательной А = ХО - 1; В = ХО + 1,- % Вывод графика функции жирной линией % Генерация вектора значений аргумента X = [А: (В - А)/100:В]; % Подстановка вектора в символ! ное представление функции % и образование вектора значений функции Глава 17 Символьные вычисления 773 F = subs(f, 'х' , X); % Вывод графика и установка толщины линии Hline = plottX, F); set{Hline, 'LineWidth', 2) % Нахождение символьного выражения для первой производной k = diff(f, х, 1); % Вычисление коэффициента касательной К = subs(к, ’х', ХО) % Символьное задани > уравнения касательной yt = symt'yO + k*(х - хС)‘); % Подстановка коэффициента, абсциссы и ординаты % в уравнение касательной yt = subsfyt, 'k', KJ; yt = subs(yt, ’ xO', XO); yt = subs{yt, 'yO', YO); % Вывод графика касательной на те же оси, где находится % график функции hold on ezplotfyt, [А В]) % Точка касания отмечается маркером-кружком plotfXO, YO, ’o’) grid on hold off Символьное интегрирование является значительно более сложной задачей, чем дифференцирование. Symbolic Math Toolbox позволяег работать как с неопределенными интегралами, так и с определенными. Неопределенные интегралы от символьных функций вычисляются при помощи int, в качестве входных аргументов указываются символьная функция и переменная, по которой происходит интегрирование, например: » syms х >> f - sym('хл3*ехр(х)'); » I = int(f, x) I - хл3*ехр(х) - 3*x~2*exp(x) + 6*x*exp(x) - 6*exp(x) » pi etty (I) 3 2 x exp(x) — 3 x exp(x) + 6 x exp(x) — 6 °.xp(x) 774 Часть IV. Использование Toolbox и решение прикладных задач Произведите проверку, продифференцировав полученную первообразную: » х, 1} ana - хЛ3*ехр(х) Разумеется, функция int не всегда может выполнить интегрирование. В некоторых случаях int возвращает выражение для первообразной через специальные функции, например, получите значение интеграла jesin х cos х с/х. Определите подынтегральную функцию и вызовите int: » syms х » f = sym('exp(sin(x)A2)*cos(x)'); » I = int(f, x); » pretty(I) 1/2 — 1/2 i pi erf(i sin(x)) Ответ содержит так называемую функцию ошибки, которая определяется интегралом с переменным верхним пределом: с/л 0 Кроме того, в полученное выражение входит комплексная единица, хотя подынтегральная функция вещественна. Требуются дополнительные преобразования для достижения окончательного результата, функции simple и simplify не смогут упростить данное выражение. Для нахождения определенного интеграла в символьном виде следует задать нижний и верхний пределы интегрирования, соответственно, в третьем и четвертом аргументах int: » syms х a b » f = sym('(x~3 + l)/(x - 1)’); » I = int(f, x, a, b) ; » pretty(I) 3 2 3 2 1/3 b + 1/2 b + b + 2 log(b - 1) - 1/3 a - 1/2 a - a - 2 lcg(a - 1) Глава 17. Символьные вычисления 775 Двойные интегралы вычисляются повторным применением функции int Найдите, например, интеграл db ff ysinx dxdy. c a Определите символьные переменные а, ь, с, d, х, у, подынтегральную функцию f от х и у и проинтегрируйте сначала по х, а затем по у: » syms a b с d х у » f = sym('y*sin(x)'); » lx = int(f, x, a, b) lx = —y*cos(b) + y*cos(a) » ly = int(Ix, y, c, d) ly = 1/2* (-cos (b) + cos(a))*(бЛ2 - сЛ2) » pretty(ly) 2 2 1/2 (-cos(b) + cos(a)) (d — c ) Аналогичным образом в символьном виде вычисляются любые кратные интегралы. Решение уравнений и систем Алгебраические уравнения до четвертого порядка включительно решаются точно, функция solve выводит ответ в степенях рациональных чисел. Результат решения уравнения третьего порядка, к примеру, отображается в командном окне с использованием подстановок: » syms х » f = зут('хЛ3 - хЛ2 - 5*х + 1'); » г = solve(f, х); » pretty(г) 1/3 %2 + 16/3 %1 + 1/3 ] [ ] [ 1/2 ] [- 1/6 %2 - 8/3 %1 + 1/3 +1/213 (1/3 £2 - 16/3 %1)] 776 Часть IV. Использование Toolbox и решение прикладных задач Г 1/2 ] [- 1/6 %2 - 8/3 %1 + 1/3 - 1/2 i 3 (1/3 %2 - 16/3 %1) ] 1 %1 ---------------------- 1/2 1/3 (10 + 6 1 111 ) 1/2 1/3 %2 := (10 + 6 i 111 ) Корни уравнения записываются в символьный массив г. Проверьте, что корни найдены верно, вычислите значение f от первого корня. Используйте функцию 51рИТуДля преобразования результата: » simplify(subs(f, 'х', r(l))) ans = 0 Допустимо использование символьных переменных в выражении для левой части уравнения. Функция solve позволяет, например, вывести в окно рабочей среды формулы для нахождения корней алгебраического уравнения четвертой степени общего вида. » syms х » f = sym('а*хл4 + Ь*хл3 + с*хл2 + d*x + с’); » pretty(solve(f, х)) Результат занимает достаточно много места, несмотря на использование подстановок, и в книге не приводится. Алгебраические уравнения высших порядков и трансцендентные уравнения, как правило, не могут быть разрешены точно. В этом случае выводятся приближенные значения корней. Решение системы нелинейных уравнений также находится при помощи solve. Входными аргументами solve являются в данном случае левые части уравнений и переменные, по которым требуется разрешить систему. Например, для системы из двух уравнений с правыми частями, которые определены В СИМВОЛЬНЫХ фуНКЦИЯХ fl И f2, ЗаВИСЯЩИХ ОТ xl И х2, ВЫЗОВ solve выглядит так: з = solve (fl, f2, xl, x2). Результатом является структура s с полями xi и х2, каждое из которых содержит символьное представление решения (работе со структурами данных посвящен разд. "Массивы структур и массивы ячеек"главы 8). [лава 17. Символьные вычисления 777 Решите систему нелинейных уравнений axf +Х|Х2 11-0; « Х[2 + Ьх2 = 0 и подстановкой проверьте полученные пары корней (при необходимости используйте simplify для уЛрощения результата^ » syms xl х2 » fl = зут('а*х1Л2 + xl*x2 + 1'); » f2 = sym('xlA2 + Ъ*х2’); » s - solve(fl, f2, xl, x2); » rl = subsffl, {xl,x2}, {s.xl(l), s.x2(l)}) » simplify(rl) » r2 = subs(f2, {xl,x2}, {s.xl(l), s.x2(l)}) » rl = subslfl, {xl,x2J, {s.xl(2), s.x2(2)}) » simplify(rl) » r2 = subs(f2, {xl,x2}, {s.xl(2J, s.x2(2)}) Итак, найденные пары корней точно удовлетворяют системе уравнений Если аналитическое решение невозможно, то возвращаются численные значения корней. Решите приведенную ниже систему уравнений и сравните ответ с приближенным решением, полученным при помощи fsolve в разд. "Решение нелинейных уравнений"главы 16: X] (2-х2 ) = cosX] е*2; 2 + Х| - х2 = cosX| + еХ2. Определите две символьные функции и переменные и вызовите solve с одним выходным аргументом: » syms xl х2 » fl = sym('xl*(2 - х2) - cos(xl)*ехр(х2)'); » f2 = sym('2 + xl - x2 - cos(xl) - exp(x2)1); » s - solve(fl, f2, xl, x2); Выведите в окно рабочей среды значения полей структуры s, обратите внимание. чго поля структуры содержат символьные векторы: » s.xl ans = I .73908513321516064165531208767387J I .67379203946718009639325125311984 - 1.3390702694949181314704735832283*1] 778 Часть IV. Использование Toolbox и решение прикладных задач >> s.x2 ans = [ -latribertw(2)) +2] [ log(.67179203946718009639325125311984 - 1.3390702694949181314704?35832283*i)] Функция solve нашла две пары решений: вещественные s.xl(1), s.x2(1) и комплексные s.xl (2), s.x2(2). Первая компонента вектора s.x2 выражена через функцию Ламберта w=L(x), которая определена как зависимость решения х трансцендентного уравнения we^^x от параметра w, входящего в уравнение. Вещественное решение совпадает с решением, полученным в главе 16 при помощи fsolve. Кроме того, функция solve нашла комплексные корни, решая систему нелинейных уравнений в символьном виде. Интерфейс функции solve допускает использование символьных переменных в качестве выходных аргументов, вместо струкгуры. Эквивалентное обращение к solve в предыдущем примере имеет вид: » [xl, х2] = solve(fl, f2, xl, х2); Задание левых частей уравнений символьными функциями не является обязательным. Входными аргументами solve могут быть строки с уравнениями, заключенные в апострофы, причем не обязательно переносить все слагаемые в левую часть. Независимые переменные можно так же не указывать, например, обращение » Ixl, х2] = solve('xl*(2 - х2) = cos(xl) *ехр(х2) ', '2 + xl - х2 = cos(xl) + ехр(х2)') аналогично приведенному выше. Решение дифференциальных уравнений и систем Symbolic Math Toolbox позволяет разыскать решение дифференциальных уравнений и систем в аналитическом виде. Возможно нахождение как общего решения, зависящего от констант, так и решения, удовлетворяющего поставленным граничным условиям. Решение дифференциальных уравнений и систем производится при помощи функции dsoive, входными аргументами которой являются строки с уравнением, граничными условиями, при их наличии, и независимой переменной. Если независимая переменная не указана, то по умолчанию используется t. Производные в строках задаются так: Dy, D2y,... Граничные условия могут содержать производные от неизвес гной функции. В качестве примера найдите аналитическое решение уравнения Глава 17. Символьные вычислении 779 Риккати (для некоторого частного случая значений коэффициентов), удовлетворяющее граничному условию /+у2=х"2; у(0.5) = -1. Отобразите полученное решение на отрезке [0.5,7] и сравните его с приближенным решением, полученным при помощи солвера ode45 (использование солверов описано в рая). "Решение дифференциальных уравнений" главы 6). Вызов функции dsolve в рассматриваемом примере выглядит следующим образом: » у = dsolve('Dy + уЛ2 = хЛ(-2)', 'у(0.5) = -1', 'х'); Выведите в командное окно полученное решение, используя pretty: » pretty(у) 1/2 1/2 1/2 5-1 1-5 tanh(- 1/2 5 log(x) + 1/2 log(-------------)) 1/2 5 +1 1/2------------------------------------------------- . x Теперь решите уравнение Риккати численно, создайте файл-функцию rikkaty (листинг 17.4). вычисляющую правую часть уравнения у' = 2-2 = -у +х , и задайте ее имя в качестве входного аргумента солвера ode45 вместе с отрезком и граничным условием: » [X, Y] = ode45('rikkaty', [0.5 7], -1) ; Листинг 17.4. Файл-функция, вычисляющая правую часть уравнения Рикка1 и function F = rikkaty(х, у) F = [1/хл2 - у(1)л2); Отобразите полученные приближенное и точное решения на одних осях: » ezp] ot (у) » hold on » plot(X, Y, 'o') » grid on 780 Часть IV. Использование Toolbox и решение прикладных задач Проверка (рис. 17.6) показывает совпадение аналитического и численного решений. Рис. 17.6. Точное и приближенное решение уравнения Риккати Поиск аналитического решения системы дифференциальных уравнений требует указания во входных аргументах dsoive строк, содержащих дифференциальные уравнения с тем же обозначением D для производных, и строк с граничными условиями при их наличии. Найдите общее решение системы из двух дифференциальных уравнений первого порядка /' = е g; g' = e-/. В данном случае dsoive можно вызвать с двумя входными аргументами, по умолчанию считается, что независимой переменной является t (если бы в уравнения явно входила переменная х, то ее следовало бы указать во входных аргументах гак же, как и в предыдущем примере). Используйте в каче I лава 17 Символьные вычислении 781 стве выходного аргумента вектор значений, каждый элемент которого станет символьной переменной: » [f, g) = dsolve('Df = exp(-g)1, 'Dg - exp(-f)'); Выведите полученное решение в командное окно: » pretty{f) exp(t Cl + C2 Cl) - 1 log(---------------------) Cl » pretty(g) exp(t Cl + C2 Cl) Cl -log(--------------------) exp(t Cl + C2 Cl) - 1 Произведите проверку, подставив найденные символьные функции в дифференциальные уравнения системы: » syms t » ul = diff(f, t) - exp(-g) ul = 0 » u2 = diff(g, t) - exp(-f) u2 = -(Cl~2*exp(t*Cl + C2*C1)/(exp(t*Cl + C2*C1) - 1) -exp(t*Cl + C2*C1)Л2/(exp(t*Cl + C2*C1) - l)'*2*ClA2)/exp(t*Cl + C2*C1) * (exp(t*Cl + C2*C1) - 1)/C1 -l/(exp(t*Cl + C2*C1) - 1)*C1 » simplify(u2) ans = 0 Аналитическое решение найдено верно. Найдите решение системы, удовлетворяющее граничным условиям /'(5) = 1, g'(5) = 3. Очевидно, что следует обратиться к dsoive со следующими аргументами: » [f, g] - dsolve('Df = exp(-g)1, ’Dg = exp(-f)', 'Df(5) = 1', ’Dg<5) = 3’); /82 Часть IV. Использование Toolbox и решение прикладных задач Допустима запись уравнений в одну строку через запятую и граничных условий, также в одну строку: » [£, g] = dsolvef'Df = ехр(-д), Dg = exp(-f)', *Df(5) = 1, Dg(5) - 3'); Дифференциальные уравнения высших порядков решаются аналогично. Рассмотрим один пример, демонстрирующий использование функций Maple. Требуется найти аналитическое решение дифференциального уравнения - 2х^+п(н + 1)у = 0. ' ' dx ax Обращение к dsoive с двумя входными аргументами — уравнением и независимой переменной — приводит к решению, выраженному через почином Лежандра и функцию Лежандра второго рода: » у = dsolve(’(l - xA2)*D2y - 2*x*Dy + n*(n - 1)*у = 0', ’xr) У = Cl*LegendreP(n - 1, x) + C2*LegendreQ(n - 1, x) Попытка получить сведения MATLAB О функциях Legendre? И LegandreQ при помощи встроенной справки приводит к сообщению об отсутствии одноименных М-файлов. Функции Symbolic Math Toolbox на самом деле реализуют интерфейс между средой MATLAB и библиотекой основных функций Maple. Функции LegendreF и LegandreQ не определены в MATLAB. Для доступа к информации о функциях Maple предназначена команда mhelp, использование которой схоже с командой help, например, указание в качестве параметра имени функции » mhelp LegendreP выводит определение функции LegendreP (и связанной с ней LegendreQ), варианты вызова и подробное описание с примерами использования: LegendreP, LegendreQ — The Legendre functions and associated Legendre functions of the first and second kinds Calling Sequence: LegendreP(v, x) LegendreQ(v, x) LegendreP(v, u, x) LegendreQ(v, u, x) глава 17. Символьные вычисления 783 Для получения списка специальных математических функций Maple доступных из MATLAB, служит команда mfunlist. Функция MATLAB mtun позволяет вычислить значение функций Maple, к примеру » rufunf ’LeqeiidreP’, 5, 0.7) ans = -0.3652 Вышеописанное обращение является одной из возможностей, предоставляемых Symbolic Math Toolbox пользователю, который желает использовать ресурсы вычислительного ядра Maple при работе в MATLAB с символьными выражениями. Если вы имеете опыт работы в Maple, то существенную пользу принесет Extended Symbolic Math Toolbox. Данное расширение основного Symbolic Math Toolbox позволяет оперировать как со всеми функциями Maple (исключая графические), так и создавать и выполнять приложения, написанные на языке программирования, встроенном в Maple. Глава 18 Работа со сплайнами в Spline Toolbox Область применения сплайнов весьма широка: они используются при аппроксимации одномерных и многомерных данных и функций, во многих других вычислительных задачах, а также в двумерной и трехмерной графике. Средства Spline Toolbox позволяют конструировать одномерные и многомерные сглайны (как интерполяционные, так и сглаживающие), удовлетворяющие различным условиям гладкости, и применять их для решения разнообразных задач. Входящие в состав Toolbox приложения с графическим интерфейсом служат для получения наглядного представления о поведении сплайнов и эксгериментов с ними. Сплайны и формы их представления Рассмотрим сначала задачу приближения табличной функции одной переменной с помощью сплайнов. Напомним основные определения и термины. Для решения задачи должны быть заданы две последовательности: точки Л|, х2,..., xN (сетка) и значения аппроксимируемой функции в этих точках yg, >’2 > Ух (сеточная функция). Сетка считается упорядоченной, т. е. х,- < х;+1. Если аппроксимирующая функция проходит через заданные точки, то опа называется интерполирующей, а иначе— сглаживающей. Функция S (х) называется сплайном степени к — 1 (порядка к ), если на каждом из отрезков [х(, х1+1], где / = 1, 2,..., 7V-1, эта функция является полиномом степени не выше к-1. Точки х, (i-2,..., 7V-1) называются точками разрыва, в них полиномы "сшиваются" так, что сохраняется непрерывность до производной некоторого порядка < к -1 (в разных точках условия гладкости могут быть различными). Используются две основные формы пред Глава 1В, Работа со сплайнами в Spline Toolbox 785 ставления сплайна: кусочно-полиномиальная (до-форма) и В-форма. выражающая сплайн через базисные сплайны. Примечание В русскоязычной литературе вместо термина "точки разрыва", как правило, используется термин "узлы". Мы будем придерживаться терминологии, принятой в пакете MATLAB. Кусочно-полиномиальная форма (рр-форма) На каждом участке [х,, x^+1J с номером j приближающая функция 5(х) представляется в виде полинома 1=0 до-форма удобна для вычисления значений сплайна, его дифференцирования, интегрирования и других операций с ним. Построение сплайнов в рр-форме, т. е. определение множества коэффициентов , сопряжено с решением системы зинейных уравнений и изменение любого значения в табличных данных з ребует пересчета всех коэффициентов. В-форма (разложение по базисным сплайнам) В-форма опирается на понятие базисных сплайнов. Несколько менее очевидный смысл их представления (по сравнению с до-формой) компенсируется тем, что внесение изменений в з абличные данные требует меньшего объема вычислений для перестроения сплайна. Сплайн в В-форме представляется суммой S(x)=f Вд(х)а;, j=i i де к — порядок сплайна; Bj к (х) — базисные сплайны (В-сплайны); aj — массив коэффициентов; к — порядок сплайна. Отметим, что базисный сплайн Bj к (х) положителен и отличен от нуля только в промежутке [tj, tj+k), ко- 7BU Часть IV. Использование Toolbox и решение прикладных задач торый называется носителем сплайна. Также выполняется условие норми- Л ровки: *= 1 ДЛЯ хе [/*' Cj+i]- Каждый j-ый базисный сплайн, в свою очередь, является кусочно-полиномиальной функцией степени меньше к с точками разрыва ..., tj+k . Последовательность точек tt <t2 на- зывается узлами В-формы. Для обеспечения единственности сплайна заданных условий гладкости в точках разрыва и значений сеточной функции, как правило, недостаточно, поэтому дополнительно задают еще условия на концах рассматриваемого отрезка [xj, xN ] — граничные (краевые) условия. Интерполяционные сплайны Мы уже обсуждали аппроксимацию функций одной и нескольких переменных средствами MATLAB fcjw. разд. "Интерполирование и сглаживание"главы 6). Обратимся теперь к рассмотрению возможностей, предоставляемых Spline Toolbox, и обсудим построение интерполяционных сплайнов, отличающихся порядками, формой представления и граничными условиями. Интерполяционный сплайн S(x) строится таким образом, чтобы для таблично заданной функции у выполнялись условия интерполяции: 5’(х,) = у(х( ) для / = 1.N. Построение кубического сплайна Рассмотрим сначала кубическую сплайн-интерполяцию средствами Spline Toolbox, поскольку кубические сплайны наиболее широко используются для приближения функций. При аппроксимации сплайнами существенную роль играют краевые условия. Стандартные краевые условия Подютовим данные для приближения. Зададим последовательность равноотстоящих точек на промежутке [-1,1] с шагом 0.2 и поместим их в массив х, Гпава 18. Работа со сплайнами в Spline Toolbox 787 введем inline-функцию, затем вычислим значения функции у(х) = е"х в этих точках и запишем их в массив у: » х = -1:0.2:1; >> fun - inline('exp(-х.'2)'); » у = funix); Построим теперь кубический интерполяционный сплайн при помощи функции csapi: » s = csapi(х, у) s = form: 'рр' breaks: [1x11 double) coefs: [10x4 double] pieces: 10 order: 4 dim: 1 Функция csapi конструирует кубический интерполяционный сплайн, т. е. сплайн третьей степени (четвертого порядка), с так называемыми условиями "otcj тствия узла" или "запрета стыка" (not-г knot condition), т. е. условиями неразрывности третьей производной сплайна в точках х2и xN_y. Требование непрерывности третьей производной в точке х2 фактически означает, что на участках [хр х2] и [Л2-Лз] имеется единый интерполяционный полином Ру (х) и при этом выполняются условия Ру (х;) = у; при i = 1, 2, 3. Аналогичная ситуация на участках [xw_2, xw_]] и [xw_,,xw]. Таким образом, вместо N-1 полинома мы будем иметь /V — 3. Входными аргументами функции csapi являются массивы точек разрыва и значений аппроксимируемой функции. В выходном аргументе возвращается структура s, содержащая описание кусочно-полиномиальной формы сплайна (работа со структурами описана в разд. "Простые стру ктуры" главы 8). При работе в Spline Toolbox умение оперировать структурами не является обязательным. Получению структуру s можно использовать в качестве входного аргумента других функций Toolbox для построения графика сплайна, вычисления его значений, интегрирования, дифференцирования и ряда других действий. 26 Зи. 130 788 Часть IV. Использование Toolbox и решение прикладных задач Операции над сплайнами Сконструировав сплайн и записав информацию о ним в структуру, вы можете использовать целый набор функций Spline Toolbox для получения различных характеристик сплайнов и их визуализации. Каждая функция вызывается от структуры с описанием сплайна, например, » fnplt(S) приводит к выводу графика сплайна. Отобразите исходные данные на этих же осях для проверки правильности результата. Для вычисления сплайна в некотором наборе точек служит функция fnval: » Y = fnval(s, [0.1 0.2]) Y = 0.9900 0.9608 Интегрирование и дифференцирование осуществляют, соответственно, функции fnint и fnder, которые возвращают структуру с описанием первообразной или производной требуемого порядка от заданного сплайна, например, » s2 = fnder(з, 2); находит вторую производную. Вызов fnder с одним входным аргументом (структурой с описанием сплайна) приводит к вычислению первой производной. Наличие первообразной сплайна, которая получается с помощью функции fnint, позволяет интегрировать табличные функции — достаточно найти разность значений функции fnint в граничных точках. Проинтегрируйте сплайн з для нашего примера по его области определения и сравните с интегралом от функции у(х): » S = fnint(s); » I = fnval(S, x(end)) - fnval(S, x(l)) I = 1.4936 >> quadi(fun, x(l), x(end)) ans = 1.4936 Для поиска минимального значения сплайна и его корней предназначены, соответственно, функции fnmin и fnzeros. Если они вызываются с одним входным аргументом (структурой с описанием сплайна), то поиск производится на всей области определения сплайна. Для вычисления корней или минимального значения на определенном промежутке следует задать его границы во втором дополнительном входном аргументе— векторе Ф^нк- Гпава 18 Работы со сплайнами в Spline Toolbox 789 ция fnmin возвращает минимальное значение, а при обращении к ней с двумя выходными аргументами еще и абсциссу минимума: » [mval ,mx] - fnmin{s, [-1 0.5]) mval “ 0.3679 mx = -1 Выходным аргументом функции fnzeros является мазрица из двух строк, число столбцов которой совпадает с числом корней сплайна. Содержимое столбца содержит информацию о корне— элементы столбца интерпретируются как границы интервала, которые могут: совпадать (если сплайн принимает в этой точке малое значение), быть примерно равны (если сплайн меняет знак на этом интервале) и отличаться друг от друга (если сплайн равен нулю на всем интервале). Все доступные операции над сплайнами описаны в справочной системе MATLAB по Toolbox (см. разд. Spline Toolbox: Functions — Categorical List: Operators). Воспользуемся ими для вычисления погрешности. Для получения наглядной информации о поведении сплайна и погрешности аппроксимации функции построим график сплайна и исходной функции на одних осях, а на других — график погрешности: » subplot(2, 1, 1) » х = -1:0.05:1; » у = iun(x); » plot! х, у, 'гр') » hold on » fnplt(s) >> title('Графики функции и сплайна’) » legend('функция’, 1 сплайн',0) >> хе = -1:0.01:1; » ye = abs(fnval(s, хе) - fun(xe)); » subplot(2, 1, 2) » plot(хе, ye) >> title(1 График ошибки') Получающийся результат приведен на рис. 18.1. 790 11асть IV Использование Toolbox и решение прикладных задач Рис. 18.1. Представление кубического сплайна 2 и погрешности интерполяции для функции у = е Интерфейс функции csapi позволяет вместо конструирования сплайна в виде структуры вычислить его значения в заданных точках. Создадим вектор с абсциссами точек » xl ----0.9:0.2:0.9; и укажем его при обращении к csapi в качестве третьего входного аргумента: » value = csapi(х, у, xl) ; В вектор value занесены значения кубического сплайна в заданных точках. Обращение csapi (х, у, xl) дает тот же результат, что и fnval(csapi(х, у), xl). Построение сплайна для вектор-функции Spline Toolbox позволяет конструировать сплайны для вектор-функции. Для построения, например, кубического сплайна используется рассмотрен чая выше функция csapi. В случае вектор-функцич она вызывается о г второго входного аргумента— матрицы, строки которой содержат значения функции в узлах. Продемонстрируем приближение табличных одномерных данных, каждому значению аргумента которых соответствует два значения функции. Эти зна Глава 18 Работа со сплайнами в Spline Toolbox 791 чения являются координатами точек, лежащих на кривой, которая назива-ется "улиткой Паскаля" и задается параметрическими зависимостями: х = a cos21 + b • cos/, у ~ a cost sin t+b • sin t, где 0< т<2л, a > 0, b>0. Листинг 18.1 содержит текст файл-функции ulitkaZ, которая строит улитку Паскаля при помощи кубических сплайнов. Листинг 18.1. Файл-функция для построения улитки Паскаля ...........а.....;........................... .♦.7-,,,,......... function ulitka2(а, Ь) % Построение улитки Паскаля кубическими сплайнами % Задание шага изменения параметра h = pi/20; % Задание значений параметра t = 0:h:2*pi; % Вычисление таблицы значений х = a*cos(t>.*cos(t) + b*cos(t); у = a*cos(t).*sin(t) + b*sin(t) s Формирование матрицы co значениями табличной функции R = [х ; у] ; % Создание сплайна рр — csapi(t ,R); % Вывод графика сплайна на оси с одинаковым масштабом figure fnplt (рр) axis equal Вызов файл-функции » ulitka2(2, 1) приводит к появлению улитки Паскаля (рис. 18.2). Входными аргументами файл-функции uiitka2 являются геометрические параметры улитки Паскаля а и Ь. Меняя эти величины, можно получить различные формы улитки. Исходными данными для построения сплайна являются равноотстоящие точки с шагом h, помещенные в t, и соответствующие им координаты х, у точек на кривой — координаты радиус-вектора улитки г. Функция csapi строит кусочно-полиномиальную форму кубического сплайна, который затем отображается графически при помощи fnplt. 792 Часть IV. Использование Toolbox и решение прикладных задач Рис. 18.2. Улитка Паскаля, построенная с помощью применения кубического сплайна, при значениях параметров a = 2, b = 1 Для некоторых функций, в том числе и для рассмотренной csapi, происходит усреднение значения функции, если приближаемая функция многозначна, т. е. таблица содержит несколько одинаковых значений аргумента. Произвольные краевые условия Как уже отмечалось выше, функция csapi строцт сплайн с условиями "отсутствия узла". Эти условия дают наиболее точное представление интерполируемой функции, если нет информации об ее производных на границах рассматриваемого отрезка. При наличии каких-либо дополнительных данных о приближаемой функции, зачастую, целесообразно поставить другие краевые условия. Для этого применяется функция csape. Она допускает различные варианты обращения. Первый способ s = csape(х, у) приводит к построению кусочно-полиномиальной формы интерполяционного кубического сплайна с краевыми условиями, заданными по умолчанию (ниже мы скажем, что это за условия). Вызов csape с 1ретьим входным аргументом s = csape(х, у, conds) Глава 18. Работа со сплайнами в Spline Toolbox 793 позволяет выбрать краевые условия из довольно обширного списка, представленного в табл. 18.1. При этом может потребоваться расширение массива у для указания значений производной сплайна на границах отрезка. Возможно также задание собственных граничных условий, но тогда параметр conds должен быть не текстовой строкой, а вектор-строкой из двух элементов. При таком способе можно определить различные краевые условия. При этом значение первого элемента соответствует левой границе отрезка, а второго — правой. В массив у при этом добавляются дополнительные значения в начало и конец массива. Приняты следующие правила: если значение элемента вектора строки conds равно 1, то дополнительный элемент в у задает значение первой производной, если в conds элемент равен 2, то дополнительный элемент в у задает значение второй производной. В случае периодических условий conds задается массивом [0 0] и обращения sl = csape(x, у, 'periodic') И sl = csape(x, у, [0 0]) приводят К одинаковому результату. Строковое значение 'variational' параметра conds эквивалентно заданию вектора [2 2] одновременно с записью дополнительных нулевых элементов в массив у. ЕСЛИ conds (j) (для j = 1 в/иди j = 2) не задается или принимает значения, отличные от 0, 1, 2, то conds(j) принимается равным 1, а соответствующее значение в массиве у принимается по умолчанию следующим образом. Значением по умолчанию для дополнительных элементов у является производная кубического интер-полянта, построенного по ближайшим четырем точкам. Таблица 18.1. Параметры функции csape Значения параметра conds Пояснения Добавочные значения в массиве у ’complete’ или 'clamped' Условие закрепления. Совпадение тангенсов углов наклона (производных) на границах отрезка [jq, xN ] со значениями, заданными в расширенном массиве у Значения производных интерполируемой функции в X] и xN по умолчанию принимаются такими, как в "default" 'not-a-knot' Условие "отсутствия узла", описанное выше Не требует-ся/игнорируется 'periodic' Условие периодичности. Совпадение значений первой и второй производных на г раницах промежутка [xj.JcJ Не требуется 794 Часть IV. Использование Toolbox и решение прикладных задач Таблица 18.1 (окончание) Значения параметра conds Пояснения Добавочные значения в массиве у 'second' Совпадение значений вторых производных на границах отрезка [xj, xN ] со значениями, заданными в массиве у Значения в точках х( и xN вторых производных по умолчанию предполагаются равными 0 'variational' Устанавливает вторые производные в точках X] и xN равными 0 Игнорируется Рассмотрим пример приближения с помощью сплайнов периодической функции j = cos(2nx) с последующим вычислением разности ее первых производных на концах Х] = 0, xN = 1 » х = 0:0.05:1; у = cos(2*pi*x); » s = csapi(х, у); » si = csapelx, у, 'periodic'); » diff(fnval(fnder(s), [0 1])) ans = -0.0665 » diff(fnval(fnder(si), [0 1])) ans = -3.7C07e-016 В приведенном примере задаются исходные данные и строятся сплайны в рр-форме: s с условиями "отсутствия узла", и si — с периодическими условиями. Затем вычисляется разность значений производных на концах промежутка, т. е. через период, равный 1. Здесь используются следующие функции Sphne Toolbox, fnder позволяет вычислить первую производную сплайна. Результатом fnder(s) является структура с полями, аналогичными s. Функция fnval вычисляет значения первой производной сплайна в точках, указанных во втором ее входном аргументе В данном случае он является массивом из двух элементов [0 1], т. е. вычисления проводятся в точках X] - 0, xw =1. В завершение с помощью функции MATLAB diff вычисляется разность полученных значений первой производной. Затем те же действия по вычислению разности значений первых производных в начале и конце периода проводятся для структуры si. Из полученных резуль Глада 18. Рабата со сплайнами в Spline Toolbox 795 татов видко, что в первом случае, т. е. при наложении условий "отсутствия узла", разность полученных значений производной в начале и конце периода довольно велика по сравнению со вторым случаем задания периодических граничных условий при построении сплайна. Чтобы еще раз подчеркнуть важность корректного задания граничных условий, вычислим упоминавшуюся разность значений первой прои {водной сплайна, вторые производные которого на границах отрезка обращаются в ноль, т. е. "естественного сплайна": » s2 = csapefx, [0 у 0], [22]); » diff(fnval(fnder(s2) , [0 1])) ans = 1.1490 Как видно, здесь результат получился существенно хуже. Таким образом, искусственное наложение условий y'(x|)=0, y'(xw) = 0 при построении сплайна может привести к ощутимой погрешности. Нетрудно также проверить, ЧТО ВЫЗОВЫ s2 = csape(x, у, ’variational') И s2 = csape(x, [0 у 0], [2 2)) эквивалентны. Другие примеры содержатся в справочной системе MATLAB по Toolbox (см. разд. Splint Toolbox: Functions - Categorical List: Construction of Splines). Использование сплайнов в В-форме Обратимся теперь к работе со сплайнами в В-форме, которая была определена выше (см. разд. "В-форма (разложение по базисным сплайнам)" этой главы). Напомним, что сплайн порядка к с узлами tn+k в В-фирме представляется суммой В-сплайнов В(- к , каждый из которых отличен от нуля на интервале [г,-, Узлы в последовательности могут совпадать и количество повторений узла определяет гладкость соединения между собой кусочных полиномов, сосгавляющих В-еплайн. При формировании массива узлоз должно выполняться следующее правило: количество повторений узла в по-слеоователъности узлов равно разности между порядком сплайна и количеством условий гладкости Iнепрерывности функции и ее нроизвооных). накладываемых в данной точке. Следовательно, ^-кратный узел в некоторой точке соответствует отсутствию условий непрерывности вообще, а простой узел предполагает непрерывность функции и ее производных до порядка к - 2 включительно. 796 Часть IV. Использование Toolbox и решение прикладных задач В результате может быть реализовано приближение функций с различной степенью гладкости. В-форма может иметь разрывы в производных не только во внутренних, но и в граничных узлах. Принято выбирать начальные и конечные узлы так: I] = ... = l/!=xl, t„+i = ... =^n+*:=xw- Последовательность узлов может быть построена вручную или с помощью функции augknt. При обращении augknt(х, к) генерируется последовательность, у которой первый и последний узлы имеют кратность /с: » knots = augknt)[1 234 5],4) knots ~ Columns 1 through 7 11112 3 4 Columns 8 through 11 5 5 5 5 Второй способ вызова augknt (x, k, mults) позволяет с помощью параметра mults указать желаемую кратность каждого внутреннего узла. При этом если mults является постоянной, то все внутренние узлы имеют одинаковую кратность. »knots = augknt ([1 2 3 4], 3, 2) knots = Columns 1 through 7 1 1 1 2 2 3 3 Columns 8 through 10 4 4 4 Для задания желаемой кратности в каждом внутреннем узле следует сформировать подходящий массив mults со значениями кратности: »knots = augknt) [1 2 3 4], 3, [12]) knots = Columns 1 through 7 1 1 1 2 3 3 4 Columns 8 through 9 4 4 Следует отметить, что вне базового промежутка , r„ ] В-форма дает нулевое значение, в то время как рр-форма слева от базового промежутка даст значение, определяемое кусочным полиномом на первом участке Р}, а ci |рава от базового участка — полиномом на последнем участке PN_}. Глава 18 Работа со сплайнами в Spline toolbox 797 Для изучения влияния узлов на вид и порядок В-сплайна в Spline Toolbox включено приложение с графическим интерфейсом пользователя bspiigui. После вызова » bspiigui откроется окно Experiment with a B-spline as a function of its knots (рис. 18.3), в котором изображен В-сплайн и его первые три производные. С помощью кнопок Add a knot (Добавить узел), Mark a knot by (left) clicking near it (Отметить узел щелчком мыши), Delete the marked knot (Удалить помеченный узел), Move the marked knot with the slider (Передвинуть помеченный узел с помощью бегунка) можно экспериментировать с количеством узлов, их положением и кратностью. В верхней части окна появляется информация о порядке В-сплайна и количестве полиномиальных кусков, составляющих его. Рис 18.3. Эксперименты с В-сплайнами с помощью функции bspiigui ,’98 Часть IV Использование Toolbox и решение прикладных задач Рассмотрим пример интерполяции сплайнами функции, имеющей разрыв первой производной в некоторой точке. Пусть функция задана следующим образом: (х +1)2 |х < 0; (х-1)2|х>0. Построим сплайн третьего порядка (квадратичный). В качестве значений аргумента выберем следующие: х = [-1 -0.25 о 0.25 ^.Рассматриваемая функция имеет разрыв первой производной в точке х = 0. Для построения сплайн-функции может быть использована функция spapi в следующей форме: spapi (knots, хх, уу). Здесь массив knots содержит узлы, необходимые для построения сплайна, количество их равно n + k , где к — порядок сплайна; п — количество значений в массиве хх. В массиве уу записаны значения функции от соответствующих элементов массива хх. Предупреждение^ Если при использовании функции spapi некоторое значение в массиве хх повторяется г раз, то соответствующими элементами массива уу должны быть значения функции и ее первых (г - 1) производных. В нашем примере для определения сплайна единственным образом требуется дополнительно к значениям функции задать значения производных в каких-либо точках слева и справа от точки разрыва х=0. Следующая последовательность команд реализует поставленную задачу » хх = [-1 -0.5 -0.5 О 0.5 0.5 1J; » уу = [0 0.25 1 1 0.25 -1 0]; » kr.ots = [-1 -1 -1 -0.5 0 0 0.5 1 1 1]; » s = spapi(knots, хх, уу) » fnplt (S) Согласно приведенному выше правилу построения последовательности узлов, в массиве knots значение узла t = 0 повторяется дважды, т. к. в этом узле нарушается непрерывность первой производной (порядок сплайна равен трем, в узле f = 0 только одно условие — непрерывность функции). В массиве хх значения -0.5 и 0.5 повторяются дважды, значит, в массиве значений функции уу им должны соответствовать значения самой функции и ее первой производной. Отметим, что дополнительные значения производных должны быть взяты с разных сторон от точки разрыва функции. Гпава 18. Работа со сплайнами в Spline Toolbox 799 В командное окно выводится содержимое структуры s с информацией о построенном сплайне: получена S-форма с десятью узлами, количеством коэффициентов, равным семи, сплайн третье! о порядка размерности один form: 'В-' knots: 11x10 double] coefs: [1x7 double] number: 7 order: 3 dim: 1 Результат работы функции fnplt представлен на рис. 18.4. Рис. 18.4. Построение сплайн-функци и с разрывом производной с помощью функции spapi Обращение к spapi в форме sp = spapi (к, х, у) позволяет строить сплайны различных порядков. В качестве первого аргумента указывается порядок интерполяционною сплайна. Следующими аргументами являются массивы х и у, пр едет авляющие собой входные данные для построения сплайна — массив координат точек разрыва и значений функции соответственно. В выходном аргументе (структуре) возвращается информация о сплайне. При таком вызове функции spapi подходящая последовательность узлов формируется автоматически с помощью функции aptknt (х, к). JOO Часть IV Использование Toolbox и решение нриип-щных з^цач Рассмотрим построение сплайнов разных порядков по одним и тем же данным. В первом случае строится сплайн третьего порядка (квадратичный), а во втором — второго порядка. При этом, как следует из приведенных результатов, формируются разные массивы узлов: » х = 0:4; » у - х.*ехр(-х.*х); » s2 = spapi(3, х, у) » fnplt(s2, 1) » hold on » sl = spapi(2, x, y) » fnplt(sl, '+’, 2) s2 = form: 'B-' knots: [000 1.5000 2.5000 444] coefs: [1x5 double] number: 5 order: 3 dim: 1 sl = form: 'B-' knots: [0012344] coefs: [0 0.3679 0.0366 3.7023e-004 4.5014e-007] number: 5 order: 2 dim: 1 Графики первого и второго сплайнов приведены на рис. 18.5. Сплошной линией показан сплайн третьего порядка, а крестиками —второго. Поскольку в сгенерированных массивах узлов knots каждый внутренний узел встречается лишь один раз, то это означает, что наложено максимально возможное для данного сплайна количество условий гладкости в каждом узле. В этом можно убедиться, отобразив график первой и второй производных сплайна: >> fnplt(fnder(s2), » hold on >> fnplt(fnder(s2 , 2), * — — ' ) Для сплайна третьего порядка максимально возможное количество условий в узле— непрерывность самой функции и ее первой производной, о чем Глава 18. Pa6o~i со сплайнами в Spline Toolbox 801 свидетельствует рис. 18.6 (сплошная линия — график первой производной, а штриховая — второй). Рис. 18.5. Сплайны разных порядков, пос гроенные по одним и тем же данным Рис. 18.6. Графики первой и второй производных для сплайна третьего порядка 802 Часть IV Использование Toolbox и решение прикладные задач Сглаживающие сплайны На практике часто значения аппроксимируемой функции yt известны с некоторой погрешностью у = у; + Е,, где i = 1,.... N, например, являются данными эксперимента. Поэтому построение интерполяционного сплайна, т. е. точное удовлетворение этим данным становится неэффектявным, особенно в тех случаях, когда погрешность в данных может быть велика В этом случае применяются сглаживающие сплайны. Сглаживающий сплайн сообщает минимум функционалу: JG)=p^wi{у/-*U))2+О-р) f (О) &> где ре [0,1] — параметр; и’( — неотрицательные весовые множители, которые нередко выбираются равными 1; Л(г)— неотрицательная весовая функция, как правило, полагается постоянной и равной единице. Для кубического сплайна m = 2. Сгенерируем данные со случайным возмущением ("шумом"), а затем по ним — кубический сглаживающий сплайн с помощью функции csaps (х, noisy}, первым параметром которой является массив координат, а вторым— значений возмущенной функции. £ Примечание j Данные с "шумом” получены путем добавления к значениям функции из предыдущего примера случайной сос гавляющей с помощью следующих команд х = 0:0.1:3;у = 2*х.*ехр(-х.*х); noisy = у + .2*(rano(size(x)) - .5). Для повторяемости результатов переменные записаны в Файл set 18.mat и содержатся на прилагаемом к книге компакт-диске. Для их использования указанный файл следует скопировать в текущий каталог (способы считывания и записи двоичных данных разобраны в аллее /, а установка текущего катал ока в разд. "Установка путей” главы 5). Следующая последовательность команд приводит к построению сглаживающего сплайна и его графическому отображению. На рис. 18.7 сплошной линией показан сглаживающий сплайн, а кружками — исходные данные >> load set!8 .mat » scs = csaps(x, noisy); » fnplt(scs) » hold on Глава 18. Ргбота со сплайнами в Spline Toolbox 803 » plot(x, noisy, ’го') » legend('сплайн','данные') >> hold off Рнс.18.7 Кубический сглаживающий сплайн Чтобы "регулировать", насколько близко сглаживающий сплайн должен подходить к исходным данным, можно использовать функцию csaps в другой форме csaps (х, у, р), где р—параметр сглаживания. Крайние значения р = 1 и р = о приводят, соответственно, к интерполяционному кубическому сплайну и полиному первой степени (прямой), построенному по методу наименьших квадратов. » load set16 .mat » scsl = csaps(x, noisy, 1) » scsO = csaps(x, noisy, 0) » plot(x, noisy, 'ro') >> nold on » Enplt(scsl) » fnplt(scsO, 'b*-') » 1eqend('данные 1, 'интерполяция', 'MHK') » hold off 804 Часть IV. Использование Toolbox и решение прикладных задач Структура scsi содержитрр-форму интерполяционного кубического сплайна, a scso — данные для построения прямой по методу наименьших квадратов (МНК). Графики полученных сглаживающих сплайнов приведены на рис. 18.8. Рис. 18.8. Случаи предельных значений параметра сглаживания Существуют некоторые рекомендуемые значения параметра р, так, по умолчанию принимается значение где h — усредненное расстояние между абсциссами данных. Можно проводить эксперименты, меняя значение р. Узнать текущее значение р позволяет обращение isp, р] = csapsix, у). Кроме того, сглаживающий сплайн можно строить с помощью функции spaps, которая возвращает сплайн в В-форме: sp = spaps(x, у, tol). Два первых входных аргумента задают исходные данные, а параметр tol определяет допустимое отклонение построенною сплайна от исходных данных: >> load setlB.mat » scspl = spaps(x, noisy, 0.05); Глава 18. Работа со сплайнами в Spline Toolbox 805 » scsp2 = spaps(x, noisy, 0.01); » hold on » plot(x, noisy, 1 ro') » fnplt(scspl, 'tn—') >> fnplt(scsp2) » legend('данные', 'сплайн-грубее', 'сплайн-точнее') Приведенная последовательность команд приводит к конструированию двух сглаживающих сплайнов с разными допустимыми отклонениями от исходных данных (рис. 18.9). Рис. 18А Сглаживающие сплайны при различных допустимых отклонениях от исходных данных В Spline Toolbox имеется возможность построения В-формы сплайнов различных порядков, минимизирующих функционал: j(v) = XlVi.(yj-5(x/)) , 1=1 т. е. применяется взвешенный метод наименьших квадратов в стандартной форме. Для этого используется функция зрарг. При обращении к ней 806 Часть IV. Использование Toolbox и решение прикладных задач sp = spap2(knors, к, х, у) весовые множители полагаются равными единице. Здесь knots — массив узлов, х, у — массивы исходных данных, к— порядок сплайна. Массив у может содержать скалярные, векторные или матричные данные. Для указания весовых множителей, отличных от 1, следует записать их в вектор w. длина которого совпадает с длиной х, и задать в пятом входном аргументе: sp = spap2 (knots, k, x, у, w). Примечание । Данные в массиве у для функции spap2, соответствующие повторяющейся координате, усредняются. Возможно избежать составления последовательности узлов, прибегнув к обращению s = spap2 (L, k, x, у) . При этом последовательность узлов строится автоматически с помощью функции aptknt. Параметр ь должен быть целым и положительным, он определяет количество участков для построения сплайна. Если l > (length(x) - к), то находится интерполяционный сплайн, иначе— сглаживающий. В любом случае сплайн имеет к - 2 непрерывных производных. При построении сглаживающего сплайна точки разрыва определяются автоматически. С помощью функции newknt(s), где s— структура с информацией о сконструированном сплайне, можно попытаться улучшить предложенную последовательность узлов и перестроить сплайн, снова обратившись к функции spap2: si = spap2 (newknt(s), k, x, у). Применение этих возможностей иллюстрируется следующими командами, выполнение которых приводит к сплайнам, представленным на рис. 18.10. » load setlS.mat » s = spap2(3, 3, x, noisy); >> hold on » plot(x, noisy, 'ro') » £nplt(s, 'b+-'} >> si - spap2(newknt(s), 3, x, noisy); » fnpltlsl, 2); » legend('исходные данные', 'начальный сплайн', 'перестроенный') » hold off Более подробно о возможностях функции spap2 можно узнать в справочной системе MATl АВ по Toolbox (см. разд. Spline Toolbox: Functions - Categorical List: Construction oi Splines). Гпава 18. Работа со сплайнами в Spline Toolbox 807 Рис. 18.10. Построение сплайна с помощью функции ьрат 2 и его коррекция Интерактивное построение кривых В Spline Toolbox возможно построение кривых в интерактивном режиме. Для что! о используется приложение с графическим интерфейсом getcurve. При его запуске » getrnrve открывается окно, в котором с помощью мыши требуется отметить точки на осях (рис. 18.11). Щелчок мышью вне осей означает завершение ввода и приводит к созданию кривой (рис. 18.12). При этом координаты точек записываются в стандартную переменную ans и выводя гея в командное окно: ans = -0.7903 -0.4032 -0.0115 0.3848 0.5922 -0.2193 0.2076 -0.0029 0.2076 0.0088 808 Часть IV. Использование Toolbox и решение прикладных задач Гис. 18.12. Результат работы функции getcurve Гпава 1S. Работа со сплайнами в Spline Toolbox <Ю9 Приложение splinetool В состап Spline Toolbox входит приложение с графическим интерфейсом пользователя splinetool, которое позволяет провести наглядные эксперименты по аппроксимации сплайнами. Пользователь может взять данные из имеющегося набора или задать собственные, а также выбрать: Л способ аппроксимации— интерполяционные сплайны или сглаживающие сплайны; О различные типы граничных условий; □ порядок используемого сплайна. Рассмотрим работу с интерполяционными кубическими сплайнами. При обращении » splinetool открывается окно приложения Spline Tool, приведенное на рис. 18.13, с кнопками для выбора данных. Нажмите первую кнопку Provide your own data or an m-file that does, предназначенную для ввода собственных данных или имени М-файла, в котором они создаются. Откроется окно Please provide data, показанное на рис. 18.14, в котором введены данные для демонстрационного примера приближения функции cos х. Ознакомьтесь сначала с предлагаемым вариантом. Ничего не изменяя, нажмите кнопку ОК. Откроется окно Spline Tool (рис. 18.15). В окне Spline Tool, показанном на рис. 18.15, демонстрируется приближение функции cos г интерполяционным кубическим сплайном с условиями "отсутствия узла". В правой части окна выводится графическая информация. На верхнем графике справа сплошной линией показан кубический сплайн, а кружками — исходные данные. На нижнем (вспомогательном) графике приведена ошибка, возникающая при замене исходной функции сплайном. Примечание График ошибки может быть выведен, если известно аналитическое выражение аппроксимируемой функции. Если же функция табличная и задается массивом своих значений в точках разрывов, то и ошибка будет выводиться там же, т. е. при интерполирован: m она получится нулевой, с точностью до погрешности округления. 810 !а~т IV HaicjitiiBahHti Гсо1Ьс>л и решение прики 1ДН1 кззда- Рис. 18.13. Окно Spline Tool Рис. 18.14. Окно Please provide data Глава 18 Раоотасо сплайнами в Spline Тслио* 811 Рис. 18.15. Окно Spline Tool, демонстрирующее приближение функции cosx На вспомогательном графике также могут быть построены первая и вторая производные сплайна. Выбор отображаемой информации на этом графике производится в меню View. По умолчанию осуществляется вывод графика ошибки (пункт Show Error). Для отображения графиков первой или второй производной следует выбрать, соответственно, пункты Show 1st Derivative или Show 2nd Derivative В расположенных слева от графиков полях предлагаются различные возможности для проведения экспериментов. Для кубического интерполяционного сплайна это эксперименты с изменением граничных условий. В поле 812 Часть IV. Использование Toolbox и решение прикладных задач Approximation method находя гея два списка: первый предлагает выбрать способ аппроксимации, а второй — задать граничные условия. В первом списке указывается тип сплайна, по умолчанию Cubic Spline Interpolation (Интерполяция кубическим сплайном). Второй список End conditions служит для постановки граничных условий, по умолчанию это условия "отсутствия узла" (not-a-knot). График для этого случая уже выведен. Поле Data, breaks/knots, weights содержит данные и параметры приближения, которые могут быть изменены. В самой нижней части окна Spline Tool в строке Bot-tomiine приведена запись функций Spline Toolbox, использовавшихся дтя построения сплайна. Можно вывести одновременно графики сплайнов с различными граничными условиями. Для создания новою сплайна и вывода его графика щелкните по кнопке New в поле List ol approximations. Затем в поле Approximation method выберите из списка другой вид граничных условий End conditions, например, second (т. е. условия на вторые производные на концах). В областях ввода, расположенных под списком End conditions, задаются значения вторых производных на концах промежутка. В данном случае, поскольку функция cosx задана аналитически, то вычисление вторых производных будет выполнено автоматически. Для выбора порядка производной, значение которой необходимо задать, служат кнопки, расположенные над соответствующими областями ввода. Если на кнопке написано 2nd deriv., то нажатие на нее изменит надпись на 1st deriv. и в отвечающую ей область ввода заносится значение первой производной. Новый график сразу же выводится на экран. Текущий график обозначается жирной линией. Поэкспериментируйте самостоятельно с другими типами граничных условий, перечисленных в списке End conditions. Результаты работы можно вывести в отдельное графическое окно, выбрав в меню File пункт Print to Figure. Для экспорта исходных данных и результата аппроксимации в рабочую среду следует выбрать в меню File пункты Export Data и Export Spline. При выборе первого варианта открывается окно Copy data to workspace, а второго — Copy spline to workspace, в которых предлагается ввести имена для экспортируемых данных или согласиться с назначаемыми по умолчанию. Пункт Save M-file меню File предназначен для генерации М-файла с командами, которые реализуют создание присутствующих в данный момент на экране графиков, включая функции для построения соответствующих сплайнов. Опишем приближение сплайнами произвольной функции, например, хе ', в приложении splinetool. Предварительно следует создать файл-функцию для вычисления исследуемой (листинг 18.2). Гпава 18. Работа со сплайнами в Spline Toolbox 813 function Гу] = хехр(х) у = х,*ехр(-х) После этого перейдите в основное окно Spline Tool приложения splinetool, выбрав в меню File пункт Restart и нажав ОК в окне Do you want to restart?. В основном окне нажмите кнопку Provide your own data or an m-file that does и в появившемся окне Please provide data в первой строке ввода задайте вектор координат точек разрыва 0:0.2:4, а в третьей— имя файл-функции хехр (рис. 18.16). >Jt Ptease provide data Give • value or an expression тог the d<rta sites (or »he nam like tltaniun, wl юзе outp it, [x,y], p ovides both da' a s’ies arv in wh.ch case vou can ^ore the request for data values be |0:0^4| ' Give a corresponding label for the x -axis (default is ''ata site Give a value w an expression тог tne rnrrevponcting data v« furctim whose values at the datasites are to be used as' |xexp Give a corresponding label for the у-axis (default is data vali OK Cancel Рис. 18.16. Занесение данных в окно Please provide data Результаты приближения приведены на рис. 18.17. Вид основного окна Spline Tool с результатами приближения функций приведен по версии Spline Toolbox 3.1.1, входящей в релиз R13, поскольку в период работы над книгой доступный релиз R14 с версией 3.2.1 содержал ошибку, связанную с построением графика погрешности для интерполяционного сплайна. Я14 Часть IV. Использование Toolbox и решение прикладных задач Рис. 18.17. Приближение кубическим сплайном функции х • е Сплайны для поверхностей В Spline Toolbox реализована работа с функциями многих переменных. При этом строится тензорное произведение сплайнов одной переменной. Для функций многих переменных реализованы обе формы представления —рр-форма и В-форма. Все функции, использовавшиеся для построения сплайнов, могут работать с сеточными данными любого количества переменных. Гпава 18. Работа со сплайнами в Spline Toolbox 815 Поясним применение тензорного произведения на примере др-формы для функции двух переменных. Пусть дана сеточная функция, определенная на прямоугольной области с сеткой узлов (х,, ук ), где i «= 1,л!, к = 1,«2. Сеточная функция для z(x, у) задана двумерным массивом zik. Тогда двумерный сплайн в виде тензорного произведения строится по формуле: S(x,y) = g(x)®ft(y) = ^£c!/,(y-yjl)/(x-xJ.)‘, хе[ху,х7+1],уе[уЛ,уЛ+1], где #(х) и Л (у) — сплайн-функцни одной переменной, которые могут отличаться порядком и количеством определяющих их промежутков. Коэффициенты находятся либо из условий интерполяции S(x,-, ук} = Z, к (i = l.«j, £ = 1..я2) и требуемой гладкости, либо из условий сглажива- ния, аналогичных одномерному случаю. В общем случае требуется аппроксимировать сеточную функцию га-пе-ременных F(x1,xm). Сохраним ту же нотацию для обязательных входных параметров функций Spline Toolbox, обозначая х —узлы сетки, а у — значения сеточной функции. В многомерном случае массив х= txl, х2, ..., хш}, определяющий сетку, должен быть массивом ячеек, каждая ячейка которого содержит вектор с координатами узлов сетки по соответствующему направлению. Работа с массивами ячеек описана в разд. "Массивы ячеек " главы 8. Если массивы xl, х2, ..., хш имеют длины пх, п2 пм, го в случае скалярной табличной функции массив у должен быть га-мерным с размерами Л| хп2 х...хпга. При аппроксимации вектор-функции с d компонентами массив у с табличными значениями — (га+ 1)-мерный размера </хи] хл2 x...xnm. В целом, приближение многомерных данных осуществляется аналогично одномерному случаю. В листинге 18.3 приведен пример файл-функции surf pp с подфункцией rung, в которой происходит обращение к csapi. Ее входные параметры сформированы с учетом приведенного выше правила. Листинг 18.3. Фаил-функция surf рр постпоения сплайна для поверхности nl^X<.7/.~«лЯЯММКз3ДА*.ЭЯRS?. ЛММННПМШИННИММ*......‘; function surf—рр i Построение поверхности при помощи сптйнн 816 Часть IV. Использование Toolbox и решение прикладных задач % Задание координат узлов сетки xl = 1:1:9; х2 = 1.5:1:9.5; % Вычисление значений функции в узлах у = rung(80, xl, х2) ; % Конструирование сплайна bcs = csapi({xl, х2}, у); % Визуализация поверхности figure fnplt(bcs) axis([1 10 1 10 -30 80]); function u = rung(a, x, y) % Подфункция для вычисления значений функции двух переменных vl = а*(1./(1 + 2.5*(х - 4).Л2))'*(1./(1 + 1.5*(у - 6.5).Л2)); v2 = -а*(1./(1 + 2.5*{х - 6.5) .Л2))'*(1./(1 + 0.5*(у - 5).Л2)); u = vl + V2; Выполнение файл-функции surf pp приводит к результату, представленному на рис. 18.18. Рис. 18.18. Построение поверхности функцией csapi Глава 18. Работа со сплайнами в Spline Toolbox 817 Для получения В-формы тензорного произведения интерполяционны сплайнов предназначена функция spapi. Возможны два способа вызов; функции: s = spapi({kl, k2, . .., km}, x, у). или s = spapi({knotl, knot2, knotm}, x, y). Входные аргументы x и у задаются так, как описано выше в этом разделе. При первом способе обращения каждый из элементов kj массива ячеек (kl, k2, ..., km} определяет порядок сплайна по переменной ху , и функция spapi автоматически строит подходящую последовательность узлов. При втором способе вызова предусматривается указание последовательности узлов knotj по каждой переменной Ху, передаваемых в массиве ячеек (knotl, knot2, ...» knotm}. Пример использования spapi для построения сплайнов разных порядков для аппроксимации функции двух переменных приведен в листинге 18.4. Достаточно редкая сетка выбрана для наглядной демонстрации зависимости гладкости поверхности от порядка сплайна (рис. 18.19). Листинг 18.4. Файл-функция eurf_B для построения поверхности . функцией epapi function surf_B % Демонстрация использования функции spapi % Здание координат узлов сетки xl = 1:1:9; х2 = 1.5:1:9.5; % Вычисление функции в узлах у = rung(SO, xl, х2); % Построение сплайна, линейного по каждой переменной spl = spapi({2, 2}, {xl, х2}, у); % Вывод графика поверхности figure subplot(2, 1, 1) fnplt(spl) axis([0 8 1 10 -25 50]) title('линейный-линейный') % Построение сплайна, квадратичного по х и линейного по у sp2 = spapi({3, 2}, (xl, х2}, у); 818 Часть IV Использоьание Toolbox и решение прикладных задач % Вив„д графика поверхности subplot(2, 1, 2) fnplt(sp2) axis([0 8 1 10 -25 50]) title('квадратичный-линейный') function u - rung(a, x, y) % Подфункция для вычисления значений функции двух переменных vl = а*(1./(1 + 2.5*(х - 4).Л2))*(!./(1 + 1.5*(у - 6.5).Л2)); v2 = -а*{1./(1 + 2.5*(х - б. 5) . Л2)) ' * (1. / (1 + 0.5*(у - 5).Л2)); u - vl + v2; Рис. 18.19. Прибчижение поверхности сплайнами разных порядков функцией spapi Возможности Spline Toolbox не ограничиваются рассмотренными в данной главе функциями и типами сплайнов. В частности, информация о рациональных сплайнах и сплайнах в .«-форме доступна в справочной системе MATLAB по Toolbox (см. разд. Spline Toolbox: Tutorial: NLRBS and other rational splines и Spline Toolbox: Tutorial: The stform, а также Spline Toolbox: F unctions - Categorical List: Construction of Splines). Глава 19 Приближение данных и подбор параметров в Curve Fitting Toolbox При чтении предыдущих глав вы неоднократно встречали описание различных способов приближения функций и табличных данных как стандартными функциями MATLAB (polyfit, interpl и др.), так и средствами специализированных Toolbox. Предыдущая глава была посвящена Spline Toolbox, включающему набор функций и приложения с графическим интерфейсом для приближения сплайнами и оценки качества полученного результата. Часть функций Optimization Toolbox также позволяют решать задачи, связанные с аппроксимацией данных, например, нелинейную задачу подбора параметров (см разд. "Подбор параметров"главы 16). Часто процесс приближения состоит из нескольких этапов: предварительной обработки данных, выбора одного или нескольких методов приближения и анализа полученных результатов. Эта работа может быть проведена в Curve Fitting Toolbox, содержащем приложение с графическим интерфейсом Curve Fitting Tool и набор функций. Приложение Curve Fitting Tool позволяет: □ применить регрессионный анализ и другие методы для начальной фильтрации значений табличной функции, задавать весовые значения в узлах табличных данных; □ выбрать различные способы приближения, такие как: параметрические, связанные с подбором параметров моделей (одной из стандартных, например, полиномиальной, или определение собственной модели), сглаживающие и обычные сплайны; □ провести анализ результатов, включающий экстраполяцию, интегрирование и дифференцирование. Выполнение каждого этапа сопровождается визуализацией результата. Кроме того, имеется возможность сгенерировать файл-функцию, содержащую обращения к функциям Toolbox, и использовать ее как независимое приложение или как часть собственного. 27 За* 130 820 Часть IV. Испг'пыив у че Toolbox и решение прикладных задач Мы рассмотрим работу с приложением Curve Fitting Tool, после освоения которого использование функций Toolbox не составит затруднений. Начнем изучение средств Toolbox с загрузки массивов данных для обработки, которые содержатся на компакт-диске в файле set!9.mat. Скопируйте его в рабочий каталог и воспользуйтесь командой load » load set 19.mat ч либо соответствующими инструментами рабочей среды для чтения данных (способы считывания и записи двоичных данных разобраны в главе 1). В рабочей среде должны появиться массивы fl, f2, f3, f 4 и x. Естественно, если данные были сформированы в течение сеанса работы в MATLAB и хранятся в переменных рабочей среды, то предварительного считывания не требуется — они могут быть сразу обработаны средствами Curve Fitting Toolbox. Приложение Curve Fitting Tool и его средства Приложение Curve Fitting Tool запускается командой cf tool: » cftool Рис. 19.1. Ochophoc окно приложения Curve Fitting Tool I ) з •i Глава 19. Приближение данных и подбор параметров в Curve Fitting Toolbox 821 В результате открывается диалоговое окно Curve Fitting Tool, представленное на рис. 19.1. Можно обратиться к функции cftocl, задав в качестве параметров массивы узлов и значений функции, которую требуется аппроксимировать подбором параметров: » cftool(массив_узлов, массив_узловых_значений_функции) В этом случае при открытии окна Curve Fitting Tool данные загружаются автоматически. Набор кнопок, расположенных под панелью инструментов, позволяет выбрать один из инструментов Curve Fitting Toolbox. Нажатие на каждую кнопку приводит к появлению одноименного диалогового окна: □ Data — для создания одного или нескольких множеств данных на основе переменных рабочей среды и их предварительной обработки до анализа; □ Fitting — для выбора метода подбора параметров; □ Exclude — для исключения части исходных данных из анализа, □ Plotting — для указания г рафиков, выводимых в окне Curve Fitting Tool: □ Analysis — для анализа результатов подбора параметров данных, включающего: экстраполяцию, интегрирование и дифференцирование. Сеанс работы с приложением Curve Fitting Tool называется сессией. Сохранение, загрузка или начало новой сессии выполняются в меню File. Для сохранения результатов служит пункт Save Session, загрузки — Load Session. Если вы начинаете новую сессию, выбрав пункт Clear Session, то появляется запрос для подтверждения или отказа сохранения текущей сессии. Для иллюстрации отдельных аспектов работы в Curve Fitting Tool мы будем начинать новую сессию, используя одни и те же массивы данных рабочей среды. Создание множества данных для приближения Curve Fitting Toolbox оперирует с элементом данных, называемым множеством и содержащим значения табличной функции, узлов и весовых коэффициентов. Если весовые коэффициенты не заданы, они полагаются равными единице. Каждое множество снабжается именем. Для определения множества следует перейти к диалоговому окну Data, нажав одноименную кнопку в 822 Часть IV. Использование Toolbox и решение прикладных задач основном окне Curve Fitting Tool. Вы получаете возможность определить данные для приближения (предполагаем, что в рабочую среду загружены массивы из файла set!9.mat— массив узлов к и массивы табличных функций fl, £2, f3, f 4). В раскрывающихся списках X Data, Y Data и Weights окна Data, содержащих переменные рабочей среды, выбираются массивы данных (весовые коэффициенты можно не задавать). При этом в области Preview отображается выбранная табличная функция (рис. 19.2). До момента создания множества при помощи кнопки Create data set можно изменить массивы данных или стандартно генерируемое имя множества в поле Data set name. Рис. 19.2. Диалоговое окно Data для определения множества После создания множеств их имена заносятся в поле Data sets и при выборе одного из них становятся доступны кнопки для работы с этими множествами: View (Графическое представление), Rename (Переименование), Delete (У даление). Гпава 19. Приближение данных и подбор параметров в Curve Fitting Toolbox 823 Создайте четыре множества из табличных функций, образованных парами (х, fl), (х, f2), (х, f3), (х, f4), и дайте им, соответственно, имена fl vs. х, f2 (х), speed (time} и f4 vs. x. Эти множества понадобятся нам для приближения и последующего анализа. После закрытия диалогового окна Data в основном окне Curve Fitting Tool, приведенном на рис. 19.3, отображаются графики всех определенных множеств Первоначально зависимости изображаются только точками, как для множества f2(x) Использование контекстного меню (рис. 19.3) позволяет изменить стиль графиков данных, как это сделано для множеств fl vs. х, speed(time) Иf4 vs. x. Рис. 19.3. Диалоговое окно Curve Fitting Tool после определения множеств и контекстное меню изменения свойств графика 824 Часть IV Исполь зование Toolbox и решение прикладных задач Предварительная обработка данных До начала приближения табличной функции иногда целесообразно предварительно обработать исходные данные. Приложение Curve Fitting Tool предоставляет две возможности: исключить часть табличных значений и произвести сглаживание табличной функции. Рассмотрим каждую из них. Исключение данных из таблицы Для каждого множества можно сформулировать несколько правил. Каждое из них включает либо логические условия для исключения точек из таблицы, либо в таблице или на графике просто отмечаются те точки, которые не должны учитываться при приближении табличной функции. Каждому правилу присваивается идентификатор, по которому на него делается ссылка. Для доступа к диалогу формулирования правил исключения точек из таблицы значений в основном окне Curve Fitting Tool нажмите кнопку Exclude. Рис. 19.4. Диалоговое окно Exclude для предварительной обработки данных Глава 19. Приближение данных и подбор параметров в Curve Fitting Toolbox 825 Рассмотрим пример для множества fl vs. х, созданного в предыдущем разделе. В диалоговом окне Exclude в области ввода Exclusion rule name задайте имя bound, правилу в списке Select data set выберите множество fl vs. х (рис. 19.4). Исключим, к примеру, из таблицы те значения, которые выходят за полуинтервал [0.25, 2.4). Для пою в полях ввода Exclude X и Exclude Y определите верхнюю и нижнюю границы значений, как для узлов, так и для узловых значений табличной функции. Кроме этого, можно исключить отдельные точки вручную, отметив их в таблице Check to exclude point или воспользоваться кнопкой Exclude graphically для выбора исключаемых точек на графике в появляющемся окне. Для завершения создания правила следует нажать кнопку Create exclusion rule. Имена определенных правил помещаются в окно Exiting exclusion rules. Для просмотра некоторого правила надо выделить его имя в окне Exiting exclusion rule? и нажать кнопку View. Обратитесь к только что созданному правилу bound. Появится окно просмотра правила, изображенное на рис. 19.5. Цветом выделены отбракованные точки. Рис. 19.5. Просмотр правила bound Для одного множества можно сформировать несколько правил и использовать их при дальнейшей работе. 826 Часть IV. Использование Toolbox и решение прикладных задач Начальная фильтрация табличной функции Несмотря на то, что это средство относится к предварительной обработке данных перед подбором параметров, его можно использовать и независимо для получения требуемого результата. Например, построение скользящей средней для табличной функции может рассматриваз ься как конечная цель приближения (характерно, в частности, для изучения динамики цен). Для выполнения предварительного сглаживания (будем называть этот процесс фильтрацией, поскольку на этапе приближения также используются методы сг заживания) следует перейти в окне Data на вкладку Smooth (рис. 19.6). Рис. 19.6. Диалоговое окно Data для фильтрации табличных функций В раскрывающемся списке Original data set следует выбрать имя ранее определенно! о множества, в поле ввода Smoothed data set можно изменить стене- Гпава 19. Приближение данных и подбор параметров в Curve Fitting Toolbox 827 рированное имя для обработанного множества данных, которое будет получено в результате выполнения выбранной процедуры. Список Method позволяет указать метод фильтрации, а поля Span и Degree предназначены для ввода параметров, используемых в методах. В приведенном на рис. 19.6 варианте создано одно дополнительное множество с именем f 1 vs, х (ма> . Полученное множество имеет тот же статус, что и созданные ранее, поэтому для него строится график в основном окне приложения Curve Fitting Tool, Применение каждого метода фильтрации или одного с использованием разных наборов параметров сопровождается выводом соответствующего графика. Выбрав одно или несколько множеств для дальнейшего анализа, ненужные можно удалить. Для предварительной фильтрации данных доступны следующие методы □ Moving Average—- метод скользящей средней: значения отфильтрованной табличной функции вычисляются как среднее арифметическое соседних точек, т. е. используется формула: | К+л /к “ X 2-Л+1 t=K-n где величина п (должна быть нечетным числом) является параметром усреднения и задается в поле Span. Для граничных точек усреднение не производится, а для примыкающих к границам параметр усреднения берется наибольшим допустимым. П Lowess (linear fit)— метод основан на динеином регрессионном анализе. На локальном промежутке, определяемом в поле Span параметром п аналогично со сглаживанием, для каждой точки вычисляется вес по формуле: з W; = 1- Ук-yj max.|xt-x,.| и строится полином первого порядка с применением техники линейного регрессионного анализа. В отличие от предыдущего метода для дочек, прилежащих к граничным, параметр усреднения п не меняется. □ Loess (quadratic fit) — метод также использует технику линейного регрессионного анализа. Отличие от Lowess в том. что строится полином второго порядка. П Robust Lowess (linear fit) и Robust Loess (quadratic fit) — методы робастной фильтрации. В отличие от базовых методов Lowess и I oess. они состоят из двух этапов: первый такой же, как в базовом методе. Затем в ка 828 Часть IV. Использование Toolbox и решение прикладных задач ждой точке вычисляются компоненты вектора невязки ц и находятся новые весовые коэффициенты: После чего снова строится сглаживающий полином с применением техники линейного регрессионного анализа. Рис. 19.7. Результаты фильтрации данных для табличной функции f2 Гпава 19. Приближение данных и подбор параметров в Curve Fitting loolbox 829 □ Savilzky-Golav - метод фильтрации Савицкого—Голая. Для интервала усреднения, определяемого параметром и (нечетное число), методом наименьших квадратов без взвешивания строится сглаживающий полином степени, меньшей п (задается в поле Desiree) Значение в центральной точке принимается за значение сглаженной табличной функции. Приведенная характеристика методов фильтрации дает самое общее представление о них. Для понимания их возможностей и границ применимости следует ознакомиться со специальной литературой. На рис 19.7 приведены примеры некоторых методов фильтрации с одинаковым параметром л = 15 для множества f4 vs. х. В методе Савицкого--Голая используется полином второй степени. Для более наглядного различия результатов фильтрации представлена только часть данных из отрезка [3, 5.5]. Установка в меню Tools фла1 a Axis Limit Control приводит к появлению списков для изменения пределов координатных осей и отображения точных их значений, что полезно при изменении масштаба инструментами Zoom in и Zoom out Пункт Default Axis Limit меню Tools позволяет вернуться к исходным пределам при условии, что не один из инструментов Zoom in или Zoom out не выбран. Приближение табличных функций Как мы уже упоминали, приложение Curve Fitting Tool позволяет использовать различные способы приближения данных — как параметрические, так и нет. Выбор любого из них (кроме интерполирования обычными сплайнами) означает решение соответствующей задачи оптимизации, поскольку алгоритмы аппроксимации данных Curve Fitting Toolbox основаны на методе наименьших квадратов. Имеется несколько возможностей: от простейшей минимизации суммы квадратов невязок и взвешенных невязок до выбора алгоритма, устойчивого по отношению к "выбросам" в данных. При этом доступны несколько методов решения возникающей оптимизационной задачи, указание желаемой точности, границ интервалов для нахождения параметров и ряда других опций. Качество полученных приближений оценивается как визуально, так и по некоторым критериям, проверяемым cpeflvrBdMH приложения Curve Fitting Tool. В этом разделе разбираются все эти вопросы. Создание приближений Для перехода к приближению табличных функций следует в основном окне приложения Curve Fitting Tool нажать кнопку Fitting. Появляется одно 830 Часть IV. Использование Toolbox и решение прикладных задач именное диалоговое окно для управления процессом приближения данных (рис. 19.8), в котором для начала процесса следует нажать кнопку New fit, определить имя нового приближения и ввести его в поле Fit Name вместо предлагаемого по умолчанию (мы будем указывать имя табличной функции и аббревиатуру используемого метода). Рис. 19.8. Диалоговое окно Fitting для подбора параметров Гпава 19. Приближение данных и подбор параметров в Curve Fitting Toolbox Б31 В раскрывающемся списке Data set выбирается определенное ранее множество, а тип приближения для него — в списке Type ol fit. Имеется несколько возможностей: выбор одной из предопределенных параметрических моделей, в гом числе линейной и отношением полиномов (искомые параметры являются коэффициентами полиномов), задание собственной модели и интерполяция сплайнами. Далее в этом разделе дана краткая характеристика типов реализованных приближений Выбор типа в списке Type of fit определяет содержимое поля, расположенного ниже и принимающего имя типа приближения. В этом поле могут отображаться: список предопределенных моделей, степень полинома или тип сплайна или средства для создания собственной модели. До выполнения приближения в списке Exclusion rule можно указать одно из определенных ранее правил для исключения части данных (см. разд. "Исключение данных из таблицы"данной главы). Рис. 19.9. Окно приложения Curve Fitting Tool после построения приближений 832 Часть IV. Использование Toolbox и решение прикладных задач Щелчок по кнопке Apply приводит к вызову процедуры приближения и выводу результата в окно Results. При установленном флаге Immediate apply вычисления начинаются автоматически после выбора модели. При чтении предыдущих разделов вы создали множество fl vs. х для загруженной табличной функции fl и правило bound для исключения чагти табличных данных. Аппроксимируйте fl полиномами второй, третьей и шестой степеней по методу наименьших квадратов (далее мы обсудим другие типы приближений). При создании каждого следующего приближения нажимайте кнопку New fit. иначе текущее приближение заменится новым. Дайте имена приближениям в соо гвет< твии со степенью аппроксимирующего полинома fi_p2, fl_p3, fi_p6. Процесс приближения сопровождается выводом результатов в поле Result (рис. 19.8) и добавлением графиков приближений в окно Curve Fitting Tool. На рис. 19.9 приведены графики после изменения стилей линий из контекстного меню. Результаты вычислений содержат различные критерии, характеризующие качество приближения. В начале окна выводятся аналитический вид приближения и найденные значения параметров, включая границы доверительного интервала (этот вопрос кратко обсуждается в следующем разделе). Контроль качества приближений Приложение Curve Fitting Tool предоставляет возможность оценить приближения с использованием графических средств. Для управления отображаемыми в основном окне Toolbox объектами следует воспользоваться кнопкой Plotting. В открывшемся окне (рис. 19.10) графики разбиты на две группы. В левой части перечислены графики множеств, а в правой — построенных приближений. В нашем случае имеется одно множество и три приближения. Сброс флага с левой стороны от имени множества или приближения позволяет скрыть соответствующий график. На рис. 19.10 представлено окно Plotting, в котором определено, что следует скрыть отображение приближения fl_p3. При необходимости восстановить изображение графика флаг надо установить. Для скрытия графика можно воспользоваться контекстным меню в основном окне Curve Fitting Tool (см. рис. 19.3), однако восстановить изображение можно только в диалоговом окне Plotting. Гпава 19. Приближение данных и подбор параметров в Curve Fitting Toolbox 833 Рис. 19.10. Диалоговое окно Plotting Установка флага Clear associated fits when clearing data sets запрещает выводить графики приближений, если сбрасывается флаг для отображения соответствующего множества, т. е. автоматически сбрасываются флат и у всех приближений для этого множества. Оставьте два приближения fi_p2 и fi_p6 и проанализируйте невязки приближений. Для вывода графика невязки перейдите в основное окно Curve Fitting fool и в меню View в пункте Residuals выберите Line Plot. При этом в окне приложения размещаются новые оси, содержащие графики невязки (рис. 19.11). При наведении мыши на точку графика и нажатии левой кнопки появляется информация об исходных данных (номер точки и ее координаты). При нахождении параметров определяются также интервалы, которым они принадлежат с некоторой доверительной вероятностью, равной по умолчанию 95%. Значения доверительной вероятности выбираются в меню View в пункте Confidence Level окна приложения Curve Fitting Tools. Пункт Pred".-поп Bounds служит для отображения доверительной полосы. На рис: 19.12 доверительная полоса приведена для наглядности при доверительной вероятности 80%. 834 Часть IV. Использование Toolbox и решение прикладных задач Гис. 19.11. Окно приложения Curve Fitting Tool с графиком ошибок для приближений Кроме визуального контроля ошибки в пакете рассчитывается ряд критериев, выводимых в областях Results и Table of Fits окна Fitting (см. рис. 19.8). Рассмотрим эти критерии. □ SSE (Sum of Squares due to Error) — величина, равная значению целевой функции, построенной на основе метода наименьших квадратов, которая вычисляется по формуле: SSE = ’ i=l где /V — общее число точек, используемых для приближения; — узловые значения исходной табличной функции; у, — полученные узловые Гпава 19. Приближение данных и подбор параметров в Curve Fitting Toolbox 835 значения для приближения; Wj —весовые коэффициенты (по умолчанию равны единице). Рис. 19.12. Границы доверительного интервала. □ R-square— метод использует оценку, вычисляемую следующим образом. Вычисляется величина SSR (Sum of Squares of the Regression) по формуле: N > SSR = Ywi(yi-y)> i=l где у — среднее значение регрессии (математическое ожидание, если табличные значения рассматривать как выборку случайных величин). Затем рассчитывается SST = SSR + SSE. 836 Часть /'/ Использование Toolbox и решение прикладных задач Окончательно’ - square = SS/? t SSE SST SST R Значение R-square южиз в инт ервале [О,1] и чем оно больше, тем лучше считается приближение. П Adjusted R-square (в приложении используется сокращение Adj R-sq) — это скорректированный критерий R-square. Имеет смысл учитывать, если его значение положительно и не превосходит единицы. Он рассчить’вает-ся на основе числа степеней свободы, обозначаемого в пакете DFE и равного разности между числом точек N, используемых для построения приближения, и числом параметров Р, определяющих приближение. Для полинома это число равно количеству его коэффициентов, т. е. на единицу больше степени. Если величину DFE обозначить L = N - Р, то: Adj R-sq = l- SSE(N-l) SST(L) П RMSE (Root Mean Squared Error) — по этому критерию вычисляется вели- чина. RMSE = SSE L и ее близость к нулю соответствует хорошему приближению. Желаемые критерии задаются в диалоговом окне Table Options, которое появляется после нажатия на кнопку Table Options. Имена флагов совпадают с именами критериев, # Coeff, которое соответствует ранее введенной величине Р. Значения выбранных критериев отображаются в окне Results для приближения, выделенного в области Table of Fits. Типы аппроксимации для подбора параметров В Curve Fitting Tool реализовано несколько широко используемых линейных и нелинейных параметрических моделей для приближения одномерных табличных функций Тип модели задается в списке Type of fit окна Fitting, а в расположенном ниже поле выбирается одна из предопределенных моделей данного типа. Для выбранного типа аппроксимации табличных данных Глава 19. Приближение данных и подбор параметров в Curve Fitting Toolbox 837 можно определить ряд дополнительных опций, используя кнопку Fit Options для вызова соответствующего диалогового окна. Заголовок окна содержит название модели и информацию о количестве параметров, например, дтя полиномиального приближения второй степени это окно называется Fit Options for poly2 и имеет вид, представленный на рис. 19.13. В приведенном примере при аппроксимации данных полиномом второго порядка можно указать ограничения на верхнюю и нижнюю границы значений каждого коэффициента в столбцах Upper и Lower таблицы Раскрывающийся список Robust позволяет указать, надо ли использовать метод приближения, устойчивый по отношению к "выбросам" данных и выбрать: LAR (минимизация суммы модулей невязок) или Bisquare (итерационное уменьшение веса данных, удаленных от аппроксимирующей кривой). Выбор Off означает минимизацию суммы квадратов невязок. Полиномиальная модель является линейной, набор ее опций меньше, чем у нелинейных моделей, которые мы рассмотрим далее. Рис. 19.13. Диалоговое окно для уточнения опций выбранного типа приближения 838 Часть IV. Использование Toolbox и решение прикладных задач Библиотека параметрических моделей Curve Fitting Toolbox (доступная и в приложении Curve Fitting Tool) содержит следующие широко используемые предопределенные модели для аппроксимации табличных функций. О Polynomials— подбираются коэффициенты полинома, степень которого может варьироваться от 1 до 9 включительно. Этот тип аппроксимации использовался в ранее приведенных примерах. □ Exponentials — в качестве аппроксимирующей функции выбирается одна из следующих: у (х) = аеЬх; у (х) = aebx + сеА. □ Fourier - данные приближаются отрезками ряда Фурье для 1 < п < 8: п у(х) = а0 + У, (о, sin йох+bj cos кш ). ;=1 □ Gaussian — модель содержит следующий набор функций (1 < л < 8): □ Power — используются степенные функции: y(x) = axb; y(x) = a + bxc. □ Rationals — табличная функция аппроксимируется отношением двух полиномов степеней не выше 5 (не обязательно равных): и £р1хп~' у(х)=^--------’ %=L i=0 □ Sum of Sin Functions— аппроксимирующая функция является отрезком следующего ряда (1 < п < 8 ): У W = X ais’n (bix + ci) i=i □ Weibull — подбираются параметры распределения Вебула: у(х) = «2>х6 *е ; Гпава 19 Приближение данных и подбор параметров в Curve Fitting Toolbox 8t)9 □ C ustom Equations— пользователь Toolbox может сам определить вид параметрической модели. В следующем разделе поясняется, как это сделать. Кроме параметрического приближения данных доступны также и другие способы: □ Smoothing Spline— построение сглаживающего сплайна g(x), минимизирующего функционал: N , , •/и) = р£м',(у( -«(х;)) +(1-р)/(^'(л)) dx, )=1 где Wj — заданные веса (равные единице по умолчанию) а сглаживающий параметр р может изменяться от 0 до 1 (р = 0 соответствует интерполяционному кубическому сплайну, а р = 1 — приближению полиномом первой степени в смысле наименьших квадратов). По умолчанию параметр р выбирается равным 1Д1 + Л3/б), где h—среднее расстояние между точками данных. В окне Fit Options для этой модели можно задать другое допустимое значение. □ Interpolant — применяется один из следующих способов и 1тер тонирования. • Linear — интерполяция кусочно-линейной функцией, т. е. отрезками прямых, соединяющих две соседние точки (интерполяционный сплайн первого порядка дефекта один); • Nearest neighbor— интерполяция ступенчатой функцией, значение которой совпадает со значением табличной функции в ближайшем узле; • Cubic spline — обычный кубический интерполяционный сплайн; • Shape-preserving — кусочно-кубическая эрмитова инт ерполяция. Перечисленные способы интерполирования мы обсуждали в разд. "Интер-нотяция сплайнами"главы 6. При необходимости получить более детальное представление о методах приближений, используемых в пакете, следует воспользоваться специализированной литературой. 840 Часть IV. Исп жьзованне Toolbox и решение прикладных задач Определение собственной параметрической модели Вы можете определить собственную модель, зависящую от параметров, и с ее помощью выполнить приближение табличной функции, подбирая параметры средствами Curve Fitting Toolbox. Поясним это на примере приближения табличных функций f2 и f3 (соответствующие множества данных f2(x), speed (time) вы создали в начале чтения этой главы) (см. разд. "Создание множества данных для приближения " данной главы). Для создания собственной параметрической модели можно либо в меню Tools основного окна Curve Fitting Tool выбрать пункт Custom Equation, либо в диалоговом окне Fitting в раскрывающемся списке Туре of fit указать тип приближения Custom Equations и щелкнуть по кнопке New equation. В обоих случаях открывается диалог Create Custom Equation, содержащий две вкладки для создания линейной параметрической модели (Linear Equations) и нелинейной (General Equations). Создайте две параметрические модели- одну линейную, а другую — нелинейную. Откройте диалоговое окно Create Custom Equation и перейдите на вкладку General Equations. В полях Equation, определяющих вычислительную формулу, запишите выражение для функции у(х) = деЬх sin(c-x-t-d), зависящей от четырех параметров, как показано на рис. 19.14. Дополнительно в таблице можно указать стартовые значения параметров, начиная с которых будет выполняться итерационный алгоритм поиска параметров, основанный на минимизации целевой функции (как правило, это взвешенная сумма квадратов невязок), и указать верхнюю и нижнюю границы изменения каждого параметра. В поле Equation name можно ввести собственное имя параметрической модели, но удобно оставить имя, сгенерированное МА FLAB в виде формулы. Нажатие кнопки ОК завершает создание модели, соответствующее выражение или имя добавляется в список Custom Equations окна Fitting. Теперь определим линейную параметрическую модель, которая в общем случае записывается в виде конечной суммы: y(x) = n0 + X«/Z(Jf). (=1 где f; — любая функция одного аргумента. Задайте следующую модель: у(х) = л0+й]СО5х + а2еХ +Яз1пх. Для этого перейдите на вкладку Linear Equations, в поле Terms введите функцию cos (х), нажмите кнопку Add a term и во вновь появившемся поле Terms введите ехр(х), как показано на рис. 19.15. Аналогично задайте последнее слагаемое линейной параметрической модели (помните, что имя Глава 19. Приближение данных и подбор параметров в Curve Fitting Toolbox 841 функции для натурального логарифма log). Для включения в модель неизвестного аддитивного параметра (в нашем примере это а0) флаг Unknown constant coefficient должен быть установлен, его сброс приводит к отсутствию данного слагаемого в модели. После подтверждения нажатием кнопки ОК будет создана параметрическая модель. Рис. 19.14. Диалоговое окно для определения параметрической функции общего вида При конструировании линейной модели не допускается использодать функции, зависящие от искомых параметров. После создания собственной параметрической модели для нее определяется стандартный список опций в диалоговом окне bit options for custom (к его заголовку также добавляется имя параметрической модели или описывающее ее выражение), которое появляется после выбора модели в окне Fitting и нажатия кнопки Fit Options. Наборы опций произвольной линейной модели <342 Часть IV. Использование Toolbox и решение прикладных задач и рассмотренной выше поли.зомиальной (частного случая линейной модели) совпадают — имеется возможность выбора метода приближения в раскрывающемся списке Robust и задания границ параметров {см. paid. "Типы аппроксимации для подбора параметров"данной главы). Рис. 19.15. Диалоговое окно для определения линейной параметрической функции Нелинейные модели (предопределенные или собственные) допускают ряд дополнительных настроек, связанных с итерационным методом минимизации целевой функции — невязки приближения, построение которой зависит от выбора в списке Robust. Этот вопрос мы обсуждали при построении полиномиального приближения. Вид диалогового окна для настройки алгоритма поиска параметров нелинейной модели представлен на рис. 19.16. Предлагаемые опции имеют следующий смысл. □ Algorithm— метод минимизации целевой фvнкции. Рекомендуется вначале применить метод доверительных областей (Trust-Region), установленный по умолчанию, а если не удалось получить удовлетворительное решение, то метод Левенберга—Марквардта (Levenberg—Marquardt) при Глава 19. Приближение данных и подбор параметров в Curve Fitting Toolbox 843 условии, что на искомые параметры нет ограничений. Метод Ньютона— Гаусса (Gauss—Newton) включен для учебных цепей. □ DiffMinChange и DiffMaxChange— минимальное и максимальное изменение коэффициентов матрицы Якоби при аппроксимации их конечными разностями (но умолчанию 10-8 и 0.1 соответственно). □ Maxi unEvals— максимальное количество вычислений значений функции, описывающей модель. П Maxiter— максимальное количество итераций. П TolFun — точность для завершения вычислений по значению функции. О То1Х — точность для завершения вычислений по значению искомых па-раме гров. Рис. 19.16. Диалоговое окно для задания опций алгоритма поиска параметров Выполните подбор параметров для множества speed (time), используя созданную линзйную параметрическую модель, а для множества f2(x) — не 844 Часть IV. Использование Тоо№>ох и решение прикладных задач линейную. Для этого откройте диалоговое окно Fining и постройте приближения так, как было описано в разд. "Создание приближений" данной главы. На рис. 19.17 представлены полученные результаты. Очевидно, что линейная параметрическая модель дает менее удовлетворительную аппроксимацию, несмотря на то, что разброс в табличной функции меньше. Мы намеренно привели этот пример, который показывает, что количество свободных параметров не всегда определяет качество приближения. Примените теперь нелинейную модель для приближения множества speed (time). Рис. 19.17. Приближение данных с использованием собственных параметрических моделей Гпава 19. Приближение данных и подбор параметров в Curve Fitting Toolbox 345 Анализ построенных приближений Построенное приближение имеет смысл подвергнуть не только визуальному анализу, но и получить ряд его численных характеристик. Мы уже обсуждали получение значений основных критериев качества приближения (см. разд. "Контроль качества приближений"данной главы). Для дополнительного исследования приближения, включающего восполнение данных, дифференцирование и интегрирование табличной функции служит диалоговое окно Analysis (рис. 19.18), которое открывается нажатием одноименной кнопки в основном окне приложения Curve Fitting Tool. Средства диалогового окна Analysis позволяют использовать найденное приближение для получения информации о данных в некотором наборе точек. Имя приближения выбирается в раскрывающемся списке lit to analyze, а вектор значений аргумента в списке ввода Analyze at Xi =, причем его элементы могут лежать и вне области определения табличной функции. После выбора одной из операций, доступных для проведения в окне Analysis, следует нажать кнопку Apply для ее выполнения. Перечислим эти операции. □ Восполнение значений табличной функции в заданном наборе точек при установленном флаге Evaluate fit at Xi. При этом способ получения результата определяется значением переключателя Prediction or confidence bounds. • None — вычисление по найденному приближению; • For function— вычисление (раниц области значений с учетом рассчитанных допустимых интервалов, определяемых уровнем доверительной вероятности (ее значение указывается в поле ввода Level), для параметров модели; • For new observation— при определении границ области значений предполагается наличие ошибок во входных данных, распределенных по нормальному закону с нулевым средним и постоянной дисперсией, оцененной по исходным данным □ Вычисление производных от приближения. Можно определить первую и гтооую производные, установив соответственно флаги 1st derivative at Xi и 2st derivative at Xi. О Вычисление интегралов приближения. Верхними пределами являются узлы из набора Xi, а нижним либо наименьший узел (при установленном переключателе Start from min(Xi)), либо заданное значение, которое г водится при установке переключателя Start from в расположенное рядом поле. Интегрирование выполняется, если установлен флаг Integrate to Xi. 846 Часть IV. Использование Toolbox и решение прикладных задач Для представления результатов в графическом виде в отдельном окне следует установить флаг Pio. results, а для одновременного отображения исходных данных—- флаг Plot data set. Графики изображаются на отдельных осях. После задания всех параметров для проведения анализа и щелчка по кнопке Apply производятся расчеты и выводятся результаты. Создайте полиномиальное приближение 5-ой степени с именем f2-anaiis-p5 для оанее введенной табличной функции f2, и проведите анализ приближения, например, для установок, показанных на рис. 19.18. Рис. 19.18. Диалоговое окно Analysis с результатами Графически результаты отображаются в окне редактора графиков как показано на рис. 19.19. Используя средства, рассмотренные в главе 4, ьы можете должным образом оформить результаты. Глава 19. Приближение данных и подбор параметров в Curve Fitting Toolbox 847 Рис. 19.19. Графическое представление результатов анализа Глава 20 Решение экономических задач Пакет MATLAB содержит ряд Toolbox, связанных с финансовыми и экономическими расчетами для реального бизнеса или обучения и исследований Центральное место занимает Financial Toolbox позволяющий рассчитывать потоки плаз ежей и их анализировать, в том числе, оценивать инвестиционные проекты, вычислять и анализировать цены, доходности и чувствительности отдельных финансовых активов и их портфелей, прогнозировать и оценивать экономические показатели, выявлять риски и управлять ими. Функции этого Toolbox реализуют основные алгоритмы финансовых вычислений. Financial Toolbox предоставляет множество различных функций, ориентированных на решение как конкретных задач, так и задач в общей постановке. Financial Der.vatives Toolbox является расширением Financial Toolbox и позволяет оценивать фиксированный доход производных финансовых инструментов и пакетов ценных бумаг на основе различных моделей, описывающих поведение процентных ставок в будующих периодах. Financial Time Series Toolbox представляет собой набор функций для анализа данных на различных финансовых рынках, близких по идеологии техническому анализу рынка ценных бума]. В настоящей главе основное внимание уделено Financial Toolbox. В этой главе рассматриваются приемы использования средств Financial Toolbox для решения модельных задач предметной области. Вопросы, связанные с адекватностью моделей, условий их применимости или справедливости гипотез относительно состояния финансовых рынков и аналогичные вопросы выходят за рамки настоящей книги. Более того, применение средств пакета в некоторых случаях может приводить к неверным результатам с точки зрения бизнес-приложений. Проблема анализа полученных данных и их дальнейшего применения лежит на польловаз еле пахета и требует дополнительного экономического образования. Гпава 20 I- ^шение экономических зад-ч 849 f Примечание j При использовании ряда функций Financial Toolbox, например, для анализа портфелей ценных бумаг, требуется, чтобы был установлен также Optimization TolIBox. Функции для работы с датами и временем Многие функции работы с датами и временем, описываемые в этом разделе, определены, как в самом MATLAB, так и пакете Financial Toolbox. Несмотря на их бо тьшое количество, принципы использования легко продемонстрировать на ограниченном множестве (некоторых) основных функций. Представление времени и дат в MATLAB Финансовые вычисления оперируют с интервалами времени между рассматриваемыми событиями, поэтому практически все они используют даты и время. В пакете MATLAB используется следующий способ внутреннего хранения времени. Текущий момент времени представляется в форме десятичного числа, при этом целая часть определяет номер дня после 01 января 0000 г. от рождества Христова, а дробная — время, отсчитанное от полуночи (00 часов 00 минут 00 секунд текущих суток). Для получения текущего момента времени во внутреннем формате можно использовать функцию now: » format long g » mom = now mom = 732088.579040787 Таким образом, в момент обращения к функции был 7 32088-ой день от рождества Христова, а время составило 0.579040787 часть от 24 часов. Такая форма удобна для вычислительных целей, поскольку дает возможность быстро найти интервал между разными моментами времени, но неприемлема для восприятия человеком. Общепринятое представление момента времени в пакете MATLAB обеспечивается в текстовой (строка символов) или векторной форме (массив, элементы которого являются составляющими момента времени: год, месяц, час и т. п.). Для получения текстовой формы предназначена функция datestr, обращение к которой имеет вид: текстовый_формат =datestr(внутренний_формат, шаблон) 850 Часть IV. Использование Toolbox и решение прикладных задач Первый входной параметр функпии определяет значение момента времени во внутреннем представлении, а второй (может быть либо числом, либо строкой) — текстовую форму результата. В табл. 20.1 приведены некоторые значения этого параметра. В качестве примера представлен результат для ранее приведенного момента времени. Таблица 20.1. Шаблоны и текстовый формат даты Шаблон преобразования Текстовый формат Числовой Строковый 0 'dd-mmm-yyyy НН:ММ:SS' 21-May-2004 13:53:49 1 'dd-mmm-yyyy ' 21-May-2004 2 ' mm/dd/yy ’ 05/21/04 3 ’ питал’ May 4 М 5 ’шт1 05 6 ' тт/dd ' 05/21 7 'dd' 21 8 'ddd' Fri 9 'd' F 10 ’УУУУ’ 2004 11 ' УУ1 04 12 ’штату у* May 04 13 'HH:MM:SS' 13:53:49 14 •HH:MM:SS PM' 1:53:49 PM 15 'HH:MM' 13:53 16 'HH:MM:SS PM' 1:53 PM 17* *QQ—yy* Q2-04 18* ' QQ’ <22 19 'dd/mm' 21/05 20 'dd/mm/yy' 21/05/04 21 'mmm.dd.yyyy HH:MM:SS' May.21.2004 13:53:49 Гпава 20. Решение экономических задач 651 Таблыиа 20.1 (окончание) Шаблон П) сидра юваниь Текстовый Числовой Строковый формат 22 'mmm.dd.уууу' May.21.2004 23 'mm/dd/yyyy' 05.21.2004 24 'dd/mm/yyyy' 21/05/2004 25 'уу/mm/dd' 04/05/21 26 'yyyy/mm/dd’ 2004/05/21 27 'QQ-yyyy' Q2-2004 28 ’mmmyyyу’ May2004 29 'yyyy-mm-dd' 2004-05-21 31 'yyyy-mm-dd HH:MM:SS' 2004-21-May 13:53:49 *QQ — обозначает квартал. Для получения векторной формы момента времени используется функция datevec, обращение к которой имеет вид: векторный_формат = datevec (внутренний_формат или текстовый_форма-’) или [уууу, mmm, dd, hh, mm, ss] = datevec(внутренний_формат или текстовый_формат). Результат в первом случае заносится в массив размерности 1x6, во втором— в переменные (массивы 1x1) с указанными именами (аббревиатура соответствует символьному формату полного текстового представления момента времени). Функция datenum делает обратное преобразование момента времени, записанного в допустимой текстовой или векторной форме (aouble array 1x6, несколько double array 1x1) во внутреннее представление и допускает разные варианты вызова: внутренний_формат =datenum(текстовый_формат или векторный_формат) ИЛИ внутренний_формат = aatenumfyyyy, mmm, dd) ИЛИ вчутренний_формат = datenum(уууу, mmm, dd, hh, mm, ss) 2S 3л 130 852 Часть IV. Использование Toolbox и решение прикладных задач Этой функцией следует пользоваться осторожно, поскольку она не проверяет допустимость числовых значений. Следующий пример это иллюстрирует (смоделирована ошибка, когда при обращении к функции переставлены месяц и день): >> datel - datenum(2004, 21, 05) datel = 732560 » date2 - datestr(datel,1) date2 = 05-Sep-2005 Однако при использовании текстового аргумента проверка осуществляется: > datel = datenum('21/05/2004') ??? Error using ==> datevec 21 is too large to be a month. Если год опущен, то используется значение из системной даты, установленной на компьютере. Еще одна особенность при использовании текстовой строки состоит в том, что допустимым является американский формат даты так, что 01/12 эт о 12 января, а не 1 декабря. Ранее рассмотренная функция now позволяла получить внутреннее представление текущего системного момента времени. Для получения системной даты можно использовать две функции: today — дает системную дату во внутреннем формате и date — получает результат для системной даты в текстовом формате. Функции определения числа дней между датами Очень часто при проведении экономических расчетов интересуют не конкретные моменты времени, а интервалы между датами. Однако число дней зависит от принятой для вычислений структуры календарного года. В типовых расчетах используется понятие бсооеын период, в качестве которого принимается один год с определенным числом дней в месяце. Вазовый период может рассматриваться как реальный год с 365-ю или 366-ю календарными днями, как абстрактный год, состоящий из 12-ти месяцев по 30 дней в каждом и 360-ю днями в году или как комбинированный год. При различных расчетах при решении одной задачи могут использоваться разные Глава 20. Решение экономических задач 853 представления о структуре года, поэтому пакет использует несколько типов базовых периодов. Для идентификации базового периода будем использовать флаг с именем базис (в справочной системе MATLAB — basis). В табл. 20.2 приведены возможные значения этого флага и характеристики соответствующего базового периода. Таблица 20.2. Параметры базового периода Значение флага basis Число дней в году Число дней в месяце 0 (по умолчанию) Фактическое: 365 или 366 Фактическое: 30, 31, 28 или 29 1 360 30 2 360 Фактическое: 30, 31, 28 или 29 3 365 Фактическое: 30,31,28 или 29 В зависимости от выбранного базового периода интервалы между двумя датами могут отлииаться. Для вычисления количества дней в некотором периоде можно использовать функцию daysdif: число_дней = daysdif(начальная_дата, конечна я_да та, базис) Входными аргументами являются даты (в текстовом виде или во внутреннем формате) и флаг, определяющий структуру года. Следующий пример это демонстрирует. » datel = datenum(105/21/20041); » date2 = datenum(101/13/2003'),- » n_fact - daysdif (datel, date2, 0) n_fact = -494 » n_365 = daysdif (datel, date2, 3) n_365 = -493 >> r._360 = daysdif (datel, date2, 1) n_360 = -488 8Ь4 Часть IV. Использование Toolbox и решение прикладных задач Отрицательное число дней означает, что конечная дата предшествует начальной. ' Примечание Для вычисления количества дней между двумя датами можно использовать дополнительно Три функции daysact, days360, days365, имеющие одинаковое обращение с двумя датами в качестве входных параметров, но использующие разную структуру года (соответственно из расчета фактического количества дней в году, 360 дней и 365 дней). Кроме фактического количества дней между двумя датами интерес представляет количество рабочих дней между датами. Для этого сначала формируется массив дополнительных выходных дней в текстовом или числовом формате, кроме суббот и воскресений. Этот массив используется в качестве аргумента функции, учитывающей эти праздничные дни. Наиболее удобно использовать средства пакета. В файл-функции holidays (подкаталог ...toolboxfinancecalendar) содержится перечень нерабочих дат для NYSE (Нью-Йоркской фондовой биржи) 101 января 1950 года по 31 декабря 2030 года во внутреннем формате записи дат. Для специфической настройки можно внести изменения в его текст и сохранить под тем же именем в рабочем каталоге, не изменяя исходного файла. В соответствии с правилом поиска М-файлов будет вызываться наша собственная файл-функция holidays (установка последовательности просмотра каталогов в MATLAB при обращении к М-файлам описана в главе 5). Например, для 2004 г. в этой функции содержатся строки: 731947 ;... 731965 ; . . . % 01-Jan-2004 New Year's Day % 19-Jan-2004 Martin Luther King Jr. Day 731993 ; . . . % 16-Feb-2004 Washington's Birthday 732046 ;... % 09-Apr-2004 Good Friday 732098 ;... % 31-May-2004 Memorial Day 732133 ;... % 05-Ju1-2004 Independence Day 732196 ;... % 06-Sep-2004 Labor Day 732276 % 25-NOV-2004 Thanksgiving 732305 ;... % 24-Dec-2004 Christmas Используя, например, редактор М-файлов, можно заменить их, предварительно вычислив даты праздников во внутреннем формате, следующими: 731947 ;... % 01-Jan-2004 Новый год 731948 ;... % 02-Jan-2004 Новый год Гпава 20 Р ким-ие экономических задач 855 731953 ;... % 07-Jan-2004 Рождество 732000 ; ... % 23-Feb-2004 День армии 732014 ;... % 08-Mar-2004 Женский день 732070 ; . . . % 03-Мау-2004 перенос 01-Мау 732071 ;... % 04-Мау-2004 перенос 02-Мау 732077 ;. . . % 10-Мау-2004 перенос 09-Мау 732112 ;. . . % 14-Jun-2004 перенос 12-Jun 732259 % OS-Nov-2004 перенос 07-Nov 732294 % 13-Dec-2004 перенос 12-Dec Функция holidays формирует требуемый массив дней во внутреннем формате: праздничные_дни = holidays(начальная_дата, конечная_дата) Стандарты пакета не позволяют учесть российские особенности типа "черные субботы" и непредсказуемые переносы праздничных дней, если они приходятся на общевыходные дни. В этих случаях, если рассматриваются разные варианты, после вычисления числа рабочих дней можно это число изменить "в ручную". После изменения файла holidays.m можно получить список праздничных дней между двумя датами для российского календаря: » rest-days = datestr(holidays('Ol-Jan-2004 ', 'ОЗ-Мау-2004 ’)) rest-days = 01-Jan-2004 02-Jan-2004 07-Jan-2004 23-Feb-2004 0B-Mar-2004 03-May-2004 Функция wrkdydif вычисляет число рабочих дней с учетом праздников: число_раСэчих_дней = wrkdydb f(начальная_дата, конечнаядата, праздничные_дни) Применение других функций работы с датами и временем будут поясняться по мере необходимости. 856 Часть IV. Использование Toolbox и решение прикладных задач Расчеты денежных потоков Вычисления, связанные с потоками платежей (CF), используются при решении большинства экономических задач, при этом получаемые суммы считаются положительными, а выплачиваемые — отрицательными. Иногда различают входящий поток платежей (CIF), т. е. получение средств, и исходящий поток платежей (COF), т. е, оплата своих обязательств. Стоимость товаров и услуг, следовательно, и ценность денег, как их эквивалента, меняется с течением времени. Для проведения экономического анализа приходится пересчитывать цены или денежные суммы, приводя их к определенной дате (прошлой, текущей или будущей). При вычислении стоимости платежа в прошлом (по отношению к сроку платежа) — текущей стоимости (pv), применяется коэффициент дисконтирования, рассчитываемый по процентной ставке (г) или по учетной (дисконтной) ставке (</). При вычислении стоимости платежа в будущем — будущей стоимости (jv). используется коэффициент наращивания средств, являющийся обратной величиной к коэффициенту дисконтирования. Приведем некоторые формулы, используемые при расчетах денежных потоков. Знание этих формул не обязательно, важно правильно использовать функции пакета MATLAB. Однако понимание вопроса упрощается, если он математически формализован. Годовая учетная ставка (d) и годовая процентная ставка (г) связаны соотношением: rf=-2-, (20.1) 1 + г поэтому коэффициент наращивания или дисконтирования суммы можно выразить через любую величину. Будем применять чаще используемую процентную ставку. Будущая стоимость (Д’) и текущая стоимость одного платежа (pv) в момент времени lk -n-T + t, где Т — базовый период и / <Т , связаны с годовой процентной ставкой (г ) соотношением: _/v = pv(l + r)''(l + y/^. (20.2) Часто принимаются условия, что платеж производится в конце (или начале) базового периода. Поэтому / = 0 и формула (20.2) упрощается. Если по формуле (20.2) вычисляется величина fv, то говорят о наращивании текущей суммы pv, если определяется величина pv, то говорят о дисконтиро Гпава 20. Решете экономических зада-1 857 вании суммы fv Из формулы (20.2) может находиться также параметр г, который в этом случае обозначают у, и он имеет смысл ставки доходности вложения pv при условии получения дохода fv. При начислении процентов т раз в году следует использовать номинальную процентную ставку г0 и вместо базового периода Т период начисления То: количество начислений будет равно не п, а пт, и t < То. Рассмотрим следующую модельную задачу, на которой проиллюстрируем применение функций пакета MATLAB. Инвестор оценивает следующий проект: на протяжении п лет он вкладывает в начале каждого i-ro базового периода сумму , а в конце каждого периода получает доход С,-. Тек} щая процентная ставка г (или учетная ставка d ). В частном случае некоторые величины или С,- могут быть равны нулю. Надо произвести оценку такого проекта. Для упрощения модели считается, что конец предыдущего периода совпадает с началом следующего. С учетом формулы (20.2) можно записать текущую нетто стоимость проекта в виде потока платежей- Величины Cft со своим знаком определяют поток платежей проекта. Можно также использовать будущую стоимость потока платежей: п п . Л = S(Q - )(1 + г Г - Ро (1 + г)" = 2 CFt (1 + г)”-' (20.5) Инвестор может оценить проект, используя разные критерии. MATLAB позволяет использовать более сложные модели вычисления нетто стоимости потока платежей — нерегулярных потоков (не обязательно периодические), когда выплаты производятся в заранее известные сроки. Для этого нет необходимости выписывать формулы типа (20.4) и (20.5), нужно просто воспользоваться функциями MATLAB. 858 Часть IV. Использование Toolbox и решение прикладных задач Если применить критерий nvp, то надо убедиться, что нетто стоимость проекта положительна, т. е. проект не убыточен. Для этого можно воспользоваться функцией pwar. Можно руководствоваться аналогичным критерием, если вычислить буду-luj ю стоимость fv г.роекта и убедиться, что она не отрицательна. Функция fwar позволяет произвести такие расчеты. Часто используемым критерием является критерий IRR, при котором определяется норма внутренней доходности из условия, что текущая нетто стоимость потоков CIF (входящих) и COF (исходящих) проекта совпадает. При условии выплат и поступлений в конце (начале) года норма внутренней доходности вычисляется с помощью функции 1ГГ. Рассмотрим конкретное наполнение модельной задачи: при текущей процентной ставке 10% анализируются два проекта, оба рассчитанные на 5 лет, начиная с конца 2004 г. Платежи происходят в последний рабочий понедельник месяца. Потоки платежей оцениваются по-разному для каждого проекта. □ Проект 1. Начальное вложение 100 млн руб. и получение ежегодных доходов, начиная с конца второго года в размерах соответственно: 47, 53, 30, и 20 млн руб. □ Проект 2. Начальное вложение 80 млн руб., дополнительное вложение 40 млн руб. в начале 4-го года и получение ежегодных доходов, начиная с конца первого года в размерах 25, 15, 20,30,80 млн руб. В последний год доход ожидается получить двумя равными поступлениями в конце каждого полугодия. Представим данные в виде табл. 20.3 для более легкого восприятия потоков платежей по проектам, считая, что все расчеты производятся в последний понедельник месяца. Таблица 20.3. Параметры инвестиционных проектов Дата поступления Сумма поступления Проект 1 Проект 2 27-Dec-2004 -100 -80 26-Dec-2005 0 25 25-Dec-2006 47 15 31-Dec-2007 53 -20 29-Dec-2008 30 30 Гпава 20. Решение экономических задач 859 Таблица 20.3 (окончание) Дата поступления Сумма поступления Проект 1 Проект 2 29-Jun-2009 0 40 28-Dec-2009 20 40 Если не учитывать зависимость стоимости платежей от времени, то доход по обоим проектам равен 50 млн руб. Оценим эти проекты по критерию npv. Составьте потоки платежей для каждого проекта с учетом их знаков и воспользуйтесь функцией pwar для вычисления настоящей нетто стоимости проектов, которая вызывается: npv = pwar (поток_платежей, процентная_ставка, даты_платежей) и функцией fwar для определения будущей нетто стоимости потока платежей fv = fwar(поток_платежей, процентная_ставка, даты_платежей) Массив дат платежей может содержать либо числовые, либо текстовые данные Примите в качестве дат платежей последний рабочий понедельник месяца. Обращение к функции xirr, вычисляющей ставку внутренней доходности потока непериодических выплат и поступлений, имеет вид: внутренняя_доходность = xirr(поток_платежей, даты_платсжей, начальное_приОлижение, ... число_итераций) Первых два входных параметра имеют тот же смысл, что и для функций pwar и fwar. Два последних параметра необязательны и задают начальное приближение (по умолчанию 0.1) для решения уравнения вида C1F = СОF (совпадение текущей стоимости суммарных поступлений и платежей) и число итераций (по умолчанию 50) для решения этого уравнения. Для учета дня расчета (последнего понедельника месяца) следует использовать функцию iweekdate, возвращающую дату во внутреннем формате и имеющую три числовых входных параметра: номер дня недели, год и месяц. В МАП АВ дни недели нумеруются от 1 до 7, начиная с воскресенья. В листинге 20.1 содержится файл-программа для расчета различных критериев по анализируемым проектам. 860 Часть IV. Использование Toolbox и решение прикладных задач .................... —г - --................ Листинг 20,1 Файл-программа для оценки инвестлцис иных проекте^ % задание денежных потоков cfl = [-100 0 47 53 30 20]; cf2 = [-80 25 15 -20 30 40 40]; % определение дат платежей первого проекта for i = 1:6 date_flow (i) = lweekdate(2, 2004 + i, 12); end % определение дат платежей второго проекта date_flow2 = date_flowl; date_flow2(6) = lweekdate(2, 2009, 6); date_flow2(7) = date_flowl(6); % Сравнение по критерию npv npvl = pwar(cfl, 0.1, date_flowl) npv2 = pwar(cf2, 0.1, date_flow2) % Расчет будущей стоимости проектов fvl = fwar(cfl, 0.1, date_flowl) fv2 = fwar(cf2, 0.1, date_flow2) % Расчет внутренней ставки доходности проектов (критерий IRR) int_ratel = xirr(cfl, date_flowl, 0.13, 100) int_rate2 = xirr(cf2, date_flow2, 0.13, 100) В листинге по-разному учтены отсутствующие поступления по первому проекту на те даты, где по второму проекту они не нулевые. В нервом случае платеж равен нулю, а дата задана, а во втором — пропущена дата. С одной стороны, это демонстрирует возможности использования функций, а с другой, имеет определенный смысл, который будет понятен при описании функции payuni. После выполнения файл-программы из листинга 20.1 получим следующие значения критериев: npvl = 11.5500 npv2 = 11.4774 fvl = 18.6050 Гпава 20. Решение экономических задач 861 £v2 = 18.4881 int_ratel = 0.1403 int_rate2 = 0.1429 Проект 1 по критериям нетто стоимостей оказывается чуть лучше проекта 2 (особенно если провести сравнение в процентах), но по внутренней норме доходности второй проект кажется предпочтительнее. Сравните эти проекты еще, заменив их эквивалентными проектами с равномерными ежегодными выплатами. Для чего воспользуйтесь функцией payuni: поступление = payuni (поток_платежей, процентная_ставка) Учтите, что во втором проекте надо первый платеж привести на колец года. Чтобы не вдаваться в тонкости процентных начислений, считайте, что его надо нарастить по ставке 10% в течение половины года, т. е. первый поток платежей следует предварительно модифицировать. И хотя очевидно, что этот показатель будет лучше для проекта 1, значения эквивалентных платежей дают дополнительный материал для анализа. >> cifl = payuni(cfl, 0.1) cifl = 3.0525 » cf20 = cf2(l:5); » cf20(6) = 40 + 40*(l + 0.5*0.1); » cif2 = payuni(cf20, 0.1) cif2 = 3.0346 Инвестор может ограничиться проведенными расчетами для принятия решения или провести дальнейший анализ на основе дополнительной информации о проектах. Мы не ставим своей задачей обосновывать выбор проекта для реализации. Параметрами чувствительности к процентной ставке для однонаправленного потока платежей (например, только поступлений от проекта) являются дюоация Маколея (или просто дюрация) и выпуклость. Обозначим текущую стоимость положительного потока платежей Р. Если Р рассматривать как достаточно гладкую функцию процентной ставки г, то дри малых изменениях величины г на 8г будет справедливо разложение цены в ряд Тейлора: Р(г + 5г) = Р(г) +ДР(г)=Р(г) + Р'(г)8г+^/у'(г)(5г)2 +о((8г)3). (20.6) 862 Часть IV. Использование Toolbox и решение прикладных задан Удерживая два члена в приращении ДР(г), можно выразить ДР(г) через модифицированную дюрацию D,„ (г), выпуклость V(r) и значение Р(г): ДР(г) = P(r) -Dm (r)5r +1V (r)(5r)2 (20.7) и, таким образом, зная модифицированную дюрацию и выпуклость потока платежей, легко оценить изменение стоимости ДР(г) потока платежей при изменении ее доходности на величину 5г. Если значение 5г невелико, то можно ограничиться всего одним линейным членом. Модифицированная дюрация Оп,(г) выражается через дюрацию Маколея £>(г) и ставку г формулой: °т(г) = (! + г) (20.8) Дюрация (Маколея) и выпуклость рассчитываются через параметры потока платежей. Так, дюрация, имеющая смысл средневзвешенного времени полного платежа, определяется как: » pv(CF). * = р(7) * P(r) = Epv(C^), (20.9) В формулах (20.9) тек) щая стоимость отдельного платежа потока, дисконтированная по ставке г с учетом времени платежа, обозначена pv(C7; ), а для того, чтобы подчеркнуть временной фактор для времени г-го поступления, использовано обозначение ti. Первая из формул (20.9) остается справедливой и при несовпадении платежей с началом или концом периода. Используя обозначения в формулах (20.9), выпуклость этого потока выражается следующим образом: ] ( п v(r) = -------у I^ + D(r) . (1 + r) V<=1 J (20.10) Для вычисления параметров чувствительности потока платежа к процентной ставке г предназначены функции cfdur и cfconv, имеющие одинаковые входные параметры: [дюрация, мод_дюрация] = cfdur(поток, доходность) и выпуклость - cfconv(поток, доходность) Гпава 20 Решение экономических задач 863 где поток — массив последовательных платежей в конце каждого периода и доходность — ставка доходности для одного периода. Дюрация и модифицированная дюрация измеряются в количестве периодов, а выпуклость — в периодах в квадрате (для согласования размерностей). Посчитайте дюрацию и выпуклость поступлений по двум ранее рассмотренным проектам на начало инвестирования. Для этого сначала модифицируйте потоки, а затем примените описанные функции. Для второго потока поступлений в качестве периода приходится выбирать цолгода (поскольку в последний год доход планируется получать дважды). Поэтому следует в поток добавить нулевые поступления в середине каждого предыдущего года. Дюрация будет рассчитана в количестве шести месячных периодов, т. е. в два раза превышающем количество 12-месячных (годовых) периодов. Значит и для первого денежного потока следует вычислять дюрацию в той же размерности. То же самое справедливо и для выпуклости. При расчете дюрации для первого потока в полугодиях надо задать нулевые поступления в середине каждого года. Остальные суммы дохода приведены в табл. 20.3 (выплаты по проекту учитывать не следует, т. к. они имеют противоположную направленность). Для второго денежного потока только в последнем году присутствует полугодовое поступление. При вычислениях для полугодового периода начислений надо учесть и то, что доходность (с точностью до величин малого порядка) в два раза меньше. Результаты вычисления также дают дополнительную информацию для сравнения проектов: » cfll = [ 0 0 0 47 0 53 0 30 0 20]; » durl = cfdur(cfll, 0.1/2) » cxl = cfconvfcfll, 0.1/2) durl = 6.1118 cxl “ 42.9530 » cf21 =[ 0 25 0 15 0 0 0 30 40 40]; » dur2 = cfdur(cf21,0.1/2) » cx2 = cfconv(cf21,0.1/2) dur2 = 6.9540 cx2 = 58.9449 864-1асть iV. Использование Гс nibox и решение прикладных задач Примечание ’ Казалось бы, можно воспользоваться очевидным фактом, что один юд состоит из двух полугодий и, естественно, число полугодий при вычислении дюрации в два раза больше, чем число лет. Однако если после расчетов перевести полугодия в годы и сравнить с полученной дюрациеи для исходного денежного потока в годах, то результаты будут отличаться на величину порядка о ((5г)2), поскольку при дисконтировании применяются нелинейные множители. Проверьте это для рассматриваемого примера. Из расчета видно, что второй поток чувствительнее, чем первый, к изменению процентной ставки (для него дюрация и выпуклость больше), и значит, имеет больший риск, связанный с возможными ее изменениями в период осуществления проекта. Расчеты по обслуживанию кредитов Рассмотр им функции пакета для обслуживания долгов и кредитов. Пусть требуется принять решение о погашении долга 150 тыс. руб. в течение трех лет. На кредитном рынке процентная ставка по долгосрочному кредиту составляет 20% годовых. Рассмотрим схему погашения равными ежегодными платежами. При равных выплатах 20% от суммы составляют проценты по сумме оставшегося долга, а остальная часть идет в счет погашения суммы займа. В табл. 20.4 приведен расчет структуры таких выплат. Для иллюстрации частичного погашения кредита срочными платежами (одинаковыми суммами за год) возьмем сумму платежа, равную 70 тыс. руб. Хотя такой суммы недостаточно для полного погашения ссуды, но зато все расчеты прозрачны, и можно продемонстрировать более широкие возможности функций пакета. Таблица 20.4. Динамика погашения займа равными выплатами. Год Остаток по займу, тыс. руб. Платеж по сумме займа, тыс. руб Проценты по остатку, тыс. руб. Полный платеж за год, тыс. руб. 1 150 40 30 70 2 110 48 22 70 3 62 57,6 12,4 70 ИТОГИ 4,4 145,6 64,4 210 Глава 20. Решение экономических задач вбЬ Для анализа можно использовать несколько функций, например: amortize, annurate, раурег. МнО1Ие параметры этих функций имеют одинаковый смысл, поэтому пояснение дается только, когда они встречаются первый раз. Вся структура погашения кредита может быть вычислена с помощью функции amortize: (за_кредит, за_проценты, долг, платеж) = amortize(ставка, периодов, сумма, остаток, момент) Первых гри входных аргумента обязательны и задают: а ставка — процентную ставку по кредиту за один период; □ периодов — полное число периодов расчета по займу; □ сумма — сумма полученных заемщиком денежных средств. Два последних параметров необязательны и в нашем случае не требуются. Их значение следующее: □ момент (по умолчанию 0) — флаг, равный 1 при выплатах в начале периода и 0 — в конце; □ остаток (по умолчанию 0) — та сумма, которая останется неоплаченной, если задается отрицательная величина (по табл. 20.4 это -4.4) или сумма, которую будет должен кредитор заемщику после погашения долга (например, если кредитором выступает банк и у заемщика открыт счет, то эта сумма будет зачислена на клиентский счет). Первых три выходных параметра являются одномерными массивами размерности входного пара метра периодов и содержат: □ за кредит — платежи по сумме кредита за каждый период; □ за проценгы— выплаты по начисленным процентам за остаток кредита в каждый период; □ долг — оставшийся долг после текущего платежа; □ платеж — сумму общей разовой выплаты. Вычислим эту структуру, для примера, по данным табл. 20.4: ISC, SI, в, Payment] = amortize(0.2, 3, 150, -4.4) SC = 40.0000 SI = 48.0000 57.6000 30.0000 в = 22.0000 12.4000 110.0000 62.0000 4.4000 866 Часть IV. Использование Toolbox и решение прикладных задач Payment — 70.0000 Можно вычислить величину процентной ставки платежа за один период, воспользовавшись функцией annurate с тем же смыслом входных и выходных параметров: ставка = annurate(периодов, платеж, сумма, остаток, момент) Например, для платежа 70 тыс. руб. имеем ставку по кредиту меньше 20% поскольку остается неоплаченный долг 4.4 тыс. руб.: » annurate(3, 70, 150 ) ans - 0.1891 Расчет только суммы одноразовою платежа дает функция раурег с теми же параметрами: платеж = раурег(ставка, периодов, сумма, остаток, момент) Например, чтобы погасить полностью кредит, остаток надо положить нулем или опустить (значение по умолчанию 0): >> раурег(0.2, 3, 150) ans = 71.2088 Пересчитайте структуру обслуживания рассмазриваемого займа со срочным платежом 71.2088 тыс. руб. и убедитесь, что кредит полностью покрывается. Рассмотрим еще функции, позволяющие определить будущие накопления, например, в банке при периодических вкладах. Функция annuterm позволяет определи! ь, за какое время накопится требуемая сумма: периодов = annuterm(ставка, платеж, сумма, вклад, момент) Значения одноименных параметров имеют тот же смысл, что и оанее описанных. Значение переметра сумма — величина вклада на начало периода накопления, а вклад — сумма вклада на конец всего периода. Например, рассчитаем срок, когда была бы накоплена сумма 150 тыс. руб. из предыдущего примера, если бы не брался кредит, а ежегодно вносился вклад в размере 50 тыс. руб. при ставке 10% годовых (заметим, что на финансовых рынках ставки кредитования выше ставок вложения): > annuterm(0.1, 50, 0, 150 ) ans ~ 2.7527 Глава 20. Решение экономических задач 867 Еще одна функция бывает полезна для планирования будущих выплат сумм, когда известно число периодов и сумма одного взноса: вклад = fvfix(cTaBKa, периодов, платеж, сумма, момент) При ежеквартальных вкладах по 15 условных единиц и годовой ставке 10% в течение грех лет накопления без начальной суммы составят: » fvfix(0.1/4, 3*4, 15) ans = 206,9333 11 Примечание j В приведенных выше функциях период начисления необязательно совпадает с базовым периодом (календарным годом по умолчании?). Для расчета применяется формула начисления по сложным процентам с использованием номинальной процентной ставки г0 (20.3). Поэтому число периодов и норма начисления должны быть заданы с учетом этого факта. Расчеты по долговым ценным бумагам Для целей иллюстрации возможностей MATLAB будем различать только бескупонные и купонные облигации, хотя сегмент рынка долговых ценных бумаг включает финансовые инструменты, называемые по разным причинам иначе (векселя, зеро, бонны, коты и др.). Более того, не будем делать различия между государственными, банковскими и корпоративными бумагами и вникать в нюансы обращения рыночных активов. Пакет MATLAB предоставляет большое количес гво функций для анализа рынка облигаций, детальное обсуждение которых требует отдельного изложения. Здесь рассмотрим примеры типовых расчетов. Дисконтные активы Все финансовые инструменты, доход по которым выплачивается при погашении актива по номиналу, будем называть бескупонными облигациями или зеро, хотя это и не совсем корректно. Для привлекательности бескупон-ных облигаций их доходность должна быть больше банковских проценз пых ставок для накопления вложений, и тем больше, чем больше срок обращения. Бескупонные облигации погашаются по номиналу и размещаются со скидкой (дисконтом), поэтому при их анализе часто применяется учетная сзавка, а в именах функций используется префикс или постфикс disc: 8с'8 Чашь IV Использование Toolbox и решение прикладных задач discrate, fvdisc, prdisc, ylddisc. Все эти функции вычисляют одну из величин входящих в формулу (20.6), через другие: p=f Sf (20.11) 1+--У V J I T J где P — цена; 5 — номинальная стоимость или будущая стоимость; у — доходность к погашению; d — годовая учетная (дисконтная) ставка; Т — базисный период; 1 — число дней до погашения или реализации. Примечание В зависимости от того, какое значение рассчитывается, параметры могут иметь разный смысл, понятный пользователю, например, цена может быть рыночной или "справедливой" (теоретической). Более того, под рыночной ценой расчетчик может также понимать следующие величины средневзвешенная за некоторый период, цена последней сделки, цена закрытия торговой сессии на выбранной им бирже и т. п. Дополнительно этими функциями можно пользоваться и для расчетов при начислении по простым процентам, задавая нужные входные параметры. К перечисленным ранее функциям можно обратиться следующим образом: дисконт = discrate(дата, погашение, номинал, цена, базис) стоимость = fvdisc(дата, реализация, цена, дисконт, базис) цена = prdisc(дата, погашение, номинал, дисконт, базис) доходность = ylddisc(дата, погашение, номинал, цена, базис) Входные и выходные параметры этих функций имеют следующий смысл: □ дата — дата, на которую производится расчет; □ погашение — дата погашения ценной бумаги; □ реализация — дата реализации ценной бумаги до срока погашения; □ номинал — номина тьная стоимос гь актива; Г) цена — цена актива на дату расчета; О дата, доходность — годовая норма доходности финансового инструмента; О стоимость — будущая стоимость актива при заданной учетной ставке; □ бззис флаг, определяющий структуру календарного года (необяза-тельный параметр, 0 по умолчанию). Гпава 20. Решение экономических задач 869 Рассмотрим небольшой пример на использование функций этого ряда При этом возьмем актив со сроком обращения меньше одного базового периода, на котором более рельефно проявляются особенности вычислений с использованием формулы (20.11). Инвестор имеет пакет абстрактных бескупонных облигаций номиналом 5 = 100000, выпущенных в обращение 10 декабря 2003 г. со сроком погашения 10 октября 2005 г., которые он планирует реализовать до даты погашения. Облигации были размещены по цене Ро =87 иОО, т. е. со скидкой 13% (курсовая стоимость 87%). Воспользуйтесь функцией discrate для вычисления годовой дисконтной ставки для актива: » сЮ = discrate(,10-dec-2003', 110-oct-20041, 100000, 87000, 0) d0 - 0.1560 Расчетная годовая дисконтная ставка больше 13%, поскольку она учитывает фактор времени (12 месяцев в году по сравнению с 10 месяцами обращения облигации). Такая большая скидка при размещении финансового инструмента выбрана для большей наглядности результатов вычислений. На рынке облигаций обычно оперируют с курсовыми стоимостями актива, выраженными в процентах от номинала (будем обозначать эти величины К ). Пусть текущая дата 7 июля 2004 г., и на рынке уровень цен следующий: цена спроса (лучшая котировка на покупку— bid price) Кь =95.5%, цена предложения (лучшая котировка на продажу — ask price) Ка = 96.5 % и цена последней сделки /С);(=96%. Требуется оценить, насколько рыночные цены отличаются от справедливой (в процентах от номинала), найти доходность и дисконтную ставку для каждой цены на момент расчета. Для решения этой задачи напишите функцию, в которой определите следующие входные параметры: дату реализации и рыночную цену. В этом случае можно решать такую задачу неоднократно для разных дат и уровней цен. Воспользуемся линейной моделью справедливой цены Р{, определяемой из условия, что она линейно растет от цены размещения PQ в момент выпуска актива в обращение до номинала в момент погашения: 'о 'о где Pfj — период обращения с момента выпуска до момента погашения; t — число дней, оставшихся до погашения. Получить эту цену можно с использованием функции prdisc. Пример функции для оценки рассматриваемого финансового инструмента приведен в листинге 20.2. 870 Часть IV. Использование Toolbox и решение прикладных задач Листинг 20.2. Файл-Функция prof it_zero расчета по дисконт -й элигацйи . ... “ .................................................. function fyld, disc, prof] = profit_zero(c_date, c_price) %задание постоянных параметров для облигации M_Da*-.e - “10-oct-2004' ; I_Date = '10-dec-2003'; pO = 87000; face = 100000; b = 0; %расчет исходной ставки дисконта d0 = discrate(I_Date, M_Date,face, pO, b); % расчет справедливой цены pt = prdisc(c_date, M_Date, 100000, dO, b) ; %вычисление рыночной цены актива price = face*c_price/100; %доходность yld = 100*ylddisc(c_date, M_Date, face, price, b) ; ^годовая дисконтная ставка disc = 100*discrate(c_date, M_Date,face, price, b) ; ^отклонение от справедливой цены в процентах от номинала prof = 100*(price - pt)/face; Для проверки функции profit zero воспользуйтесь программой из листинга 20.3. J' ' ХИ" “ 7 "у - Пистинг 20.3. Файл-ripoi рамма zero_ format short g now_date = '07-jul-2004'; Km - 96 Ka =96.5 Kb = 95.5 [yldbid, discbid, profbid] = profit_zero(now_date, Kb) [yldask, discask, profask] - profit_zero(now_date, Ka) [yldm, discm, profm] - profit_zero(now_date, Km) Глава SG. Решение зкономи'еских задач 871 После выполнения прспраммы из листинга 20.3 получаются следующие оценки: » zero_test yldLid = 18.154 dis ibid - 17.337 profbid - -0.45082 yldask = 13.973 discask = 13.484 profask = 0.54918 yldm = 16.053 discm = 15.411 profm = 0.04918 Отрицательное значение profbid показывает, что рыночная цена, соответствующая ко гировке на покупку актива, меньше справедливой цены. Е Примечание В этом разделе рассмотрены функции, применяемые для краткосрочных активов, т. к. на практике формула (20.11) для начисления по простым процентам используется в течение одного базового периода. Для долгосрочных облигаций, когда используется методика начисления по сложным процентам, следует применять функции из следующего раздела, задавая нулевую купонную ставку. Купонные облигации Обращение купонных облигаций предусматривает промежуточные выплаты их владельцу помимо номинальной стоимости в момент погашения. Дополни гельные доходы определятся купонной ставкой и периодичностью вы 872 Часть IV Использование Toolbox и решение прикладных задач платы доходов. При расчетах по купонным облигациям надо учитывать, что стоимость купона раьномерно возрастает в межкупонный период. Поэтому полная стоимость ("грязная цена") облигации в момент, не совпадающий с датой купонного платежа, складывается из двух частей: накопленного купона к расчетной дате и чистой (или "очищенной") цены. Это важно учитывать, например, при уплате налога с дохода. Если речь идет о купле-продаже облигации, то стоимость накопленного купона является доходом продавца и не включается в доход покупателя. Для иллюстрации возможностей пакета рассмотрим облигации с постоянной купонной ставкой и выплатой m раз в году. Будем всюду далее использовать следующие обозначения: □ 5 — номинальная стоимость облигации (номинал), т. е. сумма, выплачиваемая эмитентом владельцу облигации при погашении; Ос — годовая купонная ставка (десятичная дробь или %), определяет процент от номинала для общей суммы годовых дополнительных выплат по облигации, равную 5С; □ m — число выплат по купону в году (определяет периодичность, например, «1 = 12 — ежемесячно, «1 = 4— ежеквартально, т = 2— полугодовые выплаты, ш = 1 — ежегодные); _ с О ст =— —процент выплаты по одному купону; m □ — межкупонный период (число дней между двумя последовательными купонными платежами); □ у — доходность облигации к погашению (стандартно эту величину обозначают YTM), □ t — количество дней, оставшихся до ближайшего купонного платежа; □ п — число оставшихся купонных платежей до погашения; ПР — текущая цена облигации (так же как и ранее, может иметь различный смысл в зависимости от типа расчета). Цена облигации Р выражается формулой: (20.12) Гпавг 2G. Решение экономических задач 873 где i — номер купонного периода, отсчитываемый от расчетной даты; т( — фактор времени для дисконтирования бу цущего платежа на заданный момент. Для простейшего случая расчет? Р на начало купонного периода и т = 1 временной фактор т, = i (сравните с формулой (20.4) при у = г). В общем случае, если Т — число дней в базисном периоде, применяется формула • Тс~‘ ---(20.13) В пакете MATLAB большинство функций ориентировано на американский стандарт SIA, при котором в качестве расчетного (с точки зрения процентных начислений — базового) берется половина календарного года. Поэтому формула (20.13) внутри функций пакета используется в модифицированном виде, и далее в этом разделе приводится краткое разъяснение этого вопроса. Основная часть функций MATLAB также ориентирована на указанный стандарт. Большинство функций для расчета ценных бумаг с фиксированными платежами использует одни и те же параметры, для которых будем использовать одни и те же имена при вызове функций (в скобках указаны ранее введенные математические обозначения): □ цена ( Р ) — цена облигации; □ доходность( у) — доходность к погашению; □ с_дата — текущая или расчет ная дата, относительно которой осуществляется расчет; О м_дата — дата погашения облигации; □ г дата — дата начала обращения облигации; □ г_дата— дата первой купонной выплаты по облигации (используется для расчета дат купонных платежей); О ь дата — дата последней купонной выплаты по облигации (по умолчанию совпадает со значением м_дата и используется для расчета дат купонных платежей, если не задана Гдата); О з лата — дата начала начислений по облигации (она используется для определения поступлений в будущем периоде, напримео. если планируется приобретение облигации, т. е. фактически для форвардного финансового инструмента — по умолчанию совпадает со значением с_дата); □ номинал (S) — номинальная стоимость, т. е. сумма, выплачиваемая при погашении облигации без учета купонного платежа; 874 Часть IV. Использование Toolbox и решение прикладных задач □ купон (с) — годовая купонная ставка; □ периодов (/и) — число купонных периодов в календарном году; □ базис — флаг, задающий структуру календарного года; О правило — флаг, задающий правило: 1 (по умолчанию) — учитывать последний день месяца, 0 — не учитывать. Если дата погашения является последним числом месяца длительностью менее 31 дня (30 иди 28/29), и этот флаг установлен в 1, то даты платежей по купонам будут последними днями месяца. В противном случае выплаты приходятся на одно и го же число месяца. Для пояснения принципов использования функций возьмем модельную купонную облигацию номиналом 1000у.е. с годовой купонной ставкой 8% (0.08) сроком обращения 1 год, ежеквартальной выплатой по купону, датой начала обращения 01 декабря 2003 г. и сроком погашения 30 ноября 2004 г. Для определенности будем использовать фактическую структуру года (базис = 0). Функция cfdates позволяет найти даты платежей но купонам: даты_выплат = cfdates(С_дата, М_дцата, периодов, базис, правило,,,. 1_дата, К_дата, L_дата, Э_дата) Функция возвращает массив дат выплат по облигации во внутреннем формате следующих после расчетной даты. Входные параметры соответствуют ранее введенным обозначениям. Обязательными параметрами являются первых два, но, как правило, функция вызывается минимум с тремя параметрами. В листинге 20.4 приведен пример использования функции cfdates для иллюстрации использования правила конца месяца. Для вычисления всех дат платежей в качестве расчетной даты можно взять любую дату в первом периоде, например, дату начала обращения. Для наглядности все параметры задаются до обращения к функции. В листинге функция используется дважды с разным значением флага правило. "" -Я ........" Листинг 20 4. Файл-программа bond dates расчёта дат выплат го облигации ... ... . ---....... —.. ............... . ------------ .... ----------- ^Задание: дат для расчета I_Date = 101-dec-2003'; М. Date = 130-nov-2004'; iЧисло купонных платежей ш = 4; ^Фактическая структура года Ь = 0; Глава 20. Решение экономических задач 875 S: Учитывать правило последнего дня месяца m_end = 1; CFDates = cfdates(I_Date, M_Date, m, b, m_end); Dates_l = datestr(CFDates, 1) % He учитывать правило последнего дня месяца m_end = 0; CFDates = ctdates(I_Date, M_Date, m, b, rrcend); Dates_0 = datestr(CFDates, 3) После выполнения файл-программы получим даты платежей по облигации: Dates_i = 29-Feb-2004 31-Мау-2004 31-Aug-2004 30-NOV-2004 Dates_0 = 29-Feb-2С04 30-May-2004 30-Aug-2004 30-Nov-2004 Рассмотрим далее облигацию со сроками платежей, совпадающими с последними календарными днями месяца (массив Dates l). Возьмем для дальнейшей иллюстрации расчетную дату 15 мая 2004 г. Функции cpndaten и cpnt'atар находят ближайшую дату следующего или предыдущего платежа, а функции cpndaysn и cpndatep— число дней до ближайшей будущей и прошлой купонной даты. Функция cpncount позволяет найти число оставшихся купонных периодов. Все они имеют одинаковую форму вызова: След_дата = српбагеп(С_дата, М_дата, периодов, оазис, правило, ... 1_дата, F дата, Ь_дата} Пред_дата - cpndatep(С_дата, М_дата, периодов, базис, правило, ... 1_дата, Р_дата, Ь_дата) след_дней = cpndaysn(С_дата, М_дата, периодов, базис, правило, ___ 1_дата, Р_дата, Ь_дата) пред_дней = српс1ау5р(С_дата, М_дата., периодов, базис, правило, ... 1_дата, Р_дата, Ь_дата) ЧислоЕ.чплат = cpncount(С_дата, М_дата, периодов, базис, правило, ... 1_дата, У_дата, L_дата) 876 Часть IV. Использование Toolbox и решение прикладных задач Значения параметров и правила их использования такие же, как и для функции cfdates. Для рассматриваемого примера имеем: » next = datestr(cpndaten('15-may-2004', '30-nov-2004', 4)) next = 31-May-2004 prev = datestr(cpndatep(115-may-2004', '30-nov-2004', 4)) prev = 29-Feb-2004 days_N = cpndaysn(’15-may-2004', '30-nov-2004', 4) daysJN = 16 days_P = cpndayspt'15-may-2004', '30-nov-2004’, 4) days_P = 76 periods = cpncount('15-may-2004', '30-nov-2004‘, 4) periods = 3 Теперь обратимся к функциям для расчетов стоимостных параметров. Наша модельная облигация, обладая годовой купонной ставкой 8%, должна приносить доход по купону - 20 у. е. Сведем параметры облигации в табл. 20.5. Таблица 20.5. Параметры мооелыюй облигации Дата платежа Тип платежа Сумма платежа, у. е. 0i -dec-2003 Размещение 29-Feb-2004 Купон 1 20 15-Мау-2004 Расчетная дата 31-May-2004 Купон 2 20 31-Aug-2004 Купон 3 20 30-Nov-2004 Купон 4 и погашение 1020 Ключевую роль при вычислениях по облигациям с фиксированными поступлениями играет функция cfamounts, которая рассчитывает параметры облигации, связанные с потоком выплат: [выплаты, даты, факторы_времени, флаги] = cfamounts(купон, С_дата, М_дата, периодов. Оазис, правило, ... 1_дата, Г_дата, Ь_дата, 5_дата, номинал] Глава 20. Решение экономических задач 877 Все входные параметры описаны ранее. Вместо необязательных входных параметров при обращении к функции cfamounts можно задать пустые массивы. Выходные параметры представляют собой массивы размерностью на единицу больше, чем число оставшихся купонных платежей. Они определяют; П выплаты — величины платежей на дату выплаты; О даты — расчетная дата и следующие за ней даты выплат; О факторы времени— временные дисконтирования на расчетный день для каждой суммы; П флаги — определяют тип каждого платежа. Составьте функцию bond cf для расчетов стоимостных параметров модельной облигации, например так, как представлено в листинге 20.5. Листинг 20.5. Файл-программа bond_cf расчета платежей по облигации I_Date = '01-dec-2003'; C_Date = '15-may-2004'; M_Date = 130-nov-20041; b = 0; m = 4; C = 0.08; S = 1000; m_end = 1; [payrn, CFDates, d_fact, flags] = cfamounts(c, C_Date, M_Date, m, ... b, m_end, [ ], [ ], [ ], [ ], S); Dates_l = datestr(CFDates, 1} fprintf(*n payment n'); fprintf (' %12.3f ' ,paym) fprintf('n d_factors n') ; fprintf(’ %10.5f',d_fact); fprintf('n flags n1); fprintf(' %6.2fflags); После ее выполнения получим следующий результат: Dates_l = 15-Мау-2004 31-Мау-2004 31-Aug-2004 30-Nov-2004 878 Часть IV Использование Toolbox « ржание прикп здных аэда-. payment -16.522 20.000 20.000 1020.000 d_factors 0.00000 0.08743 0.58696 1.08743 flags 0.00 3.00 3.00 4.00 Моменты времени, на которые произведены расчеты, и суммы поступлений, кроме первого, очевидны (табл. 20.5). Значение первого платежа показывает сумму накопленного текущего купона на расчетную дату. Знак минус тоже имеет смысловую нагрузку. Если в расчетную дату происходит сделка купли-продажи, то эта сумма является доходом продавца (например, для учета налогообложения), но заплачена покупателем продавцу как часть цены. Она будет возмещена при погашении купона в ближайшую дату выплаты. Элементы массива d_factors представляют величины Tf. Для пояснения расчета этих величин приведем табд. 20.6, где указана дата начала обращения облигации, необходимая для понимания расчета. Таблица 20.6. К рас четг факторов времени для облигации Даты в расчете Смысл даты Число дней до платежа, База расчета, т, Фактор времени, Формула расчета 01-Dec-2003 Начало обращения 15-Мау-2004 Расчетная дата 31-Мау-2004 Купон 2 16 183 0.0874317 = — 7j 31-Aup-2004 Купон 3 108 184 0.5869565 1 Т2 = ~ 2 т 30-NOV-2004 Погашение, купон 4 199 183 1.0874317 Т3 = 1 + Tj Число дней до платежа определяется стандартно, как интервал между двумя датами. Глава 20. Решение экономических задач 879 В качестве базы расчета (базы начисления) берется полугодовой период в соответствии со стандартом SIA. Поэтому продолжительность базы начисления не одинакова: она равна реальному числу дней в шести месяцах, заканчивающихся датой ближайшей выплаты по купону. Например, если бы ближайшая выплата состоялась 10 июня 2004 г., то полугодовой период начинался бы с 10 декабря 2003 г. Первоначально факторы времени рассчитываются только в пределах начального полугодового периода, т. е. величины меньшие 1. Для нашего случая это первых два фактора. Для каждого следующего периода они циклически увеличиваются на единицу. В нашем случае фактор времени для 30 ноября 2004 г. определяется как первый фактор для начального полугодия плюс 1. Если бы потребовалось рассчитывать факторы времени далее, то формулы расчета были бы следующими: т4=1 + т2, t5=2+Tj, т6 =2 + т2, т7 =3 + Т| ит. д. Флаги указывают на тип каждого вычисленного поступления: 0 — выплаты не производятся, 3 — получение купонной суммы, 4— погашение по номиналу с купонным платежом (если дала погашения совпадает с датой купонного платежа). Хотя функция cfamouncs дает все необходимые величины для определения текущей нетто стоимости платежей (справедливой цены облигации), для ее вычисления лучше использовать функцию bndprice, не требующую знания расчетной формулы: [цена, накопление] = bndprice(доходность, купон, С_дата, М_дата, _ периодов, базис, правило,Т_дата, Р_дата, Ь_дата, Б_дата, номинал) Последний и четыре первых входных параметра являются обязательными. Для остальных можно задать пустые массивы, и они примут значения по умолчанию. Выходной параметр цена содержит очищенную цену облигации. Второй выходной параметр дает накопленную сумму на расчетную дату по текущему купону (это та же величина, что и первый элемент массива в параметре функции cfamouncs, но с положительным знаком). Для модельной облигации (при условии, что ранее использованные переменные определены и доходность к погашению оценивается как 9%) имеем: » [price, accrue] = bndprice(0.09, с, C_Date, M_Date, m, b, ... m_end, [ ], [ ], [ ], [ ], S) price = 995.2187 accrue- 16.5217 880 Часть IV. Использование Toolbox и решение прикладных задач На рынке облигаций важной является задача определения доходности к погашению по цене, смысл которой может быть разным, о чем говорилось ранее в этой главе. Для этого предназначена функция yldbond: доходность = bndyield(цена, купон, С_дата, М_дата, периодов, ... базис, правило, I_дата, F_дата, Ь_дата, S_дата, номинал) Эта функция из уравнения (20.12) находит у. Вычислите, какова доходное! ь модельной облигации, если ее рыночная цена 975 у, е: » Yield - bndyield(975, с, C_Date, M_Date, m, b, iri_end, [ ], [ ], ... [ ], [ 1, S) Yield = 0.1303 Для инвестора с точки зрения принятия решений нужны показатели чувствительности цены облигации к изменению ее доходности: дюрация (либо модифицированная дюрация) и выпуклость потока поступлений в период обращения облигации (см. формулы (20.6—20.10), в которых г следует заменить на у). Для вычисления дюрации и выпуклости потока платежей были рассмотрены функции cfdur и efeonv, но они предназначены для вычис-яения характеристик аннуитетов и не подходят для рыночных активов. Для облигаций можно использовать несколько разных функций с префиксом bnd, имеющих схожий интерфейс. Дюрацию при заданной доходности можно вычислить функцией bnddury: [мод_дюрация, год_дюрация, пол_дюрация] = bnddury(доходность, купен, С_дата, М_дата,периодов, базис, ... правило, 1_дата, F_дата, Ь_дата, 3_дата, номинал) Входные параметры имеют тот же смысл, что и для ранее описанных функций. Три выходных параметра рассчитывают разные дюрации: □ год_дюрация — дюрация Маколея при годовом расчетном периоде; □ пол дюрация — дюрация Маколея при полугодовом расчетном периоде; П мод дюрация — модифицированная дюрация для полугодовой доходности. Выпуклость рассчитывается с помощью функции bndconvy с теми же входными параметрами [год_выпуклость, пол_выпуклость] = Bndconvy (доходность, купон, С_дата, М_дата,периодов, базис, ... правило, 1_дата, К_дата, L_лата, 3_дата, номинал) / лава 20. Решение экономических задач 881 Выходные параметры год_выпуклость и пол_выпуклость дают значение выпуклости в расчете на годовой и полугодовой расчетные периоды. Для модельной облигации имеем: »[HodDur, YearDur, PerDur] = bnddury(0.09, c, C_Date, M_J>ate, ... m, b, m_end, [J, [ ], [ ], [ ], S) ModDur _ 0.5063 Yea cDur = 0.5290 PerEur = 1.0561 >> [YearConv, PerConv] = bndconvy(0.09, c, C_Date, M_Date, ... m, b, m_end, [ ], [ ], [ ], [ ], S) ZearConv = 0.5040 PerConv = 2.0158 To, что полугодовая дюрация примерно в два раза больше годовой, а выпуклость соответственно в четыре, объясняется тем, что они являются коэффициентами при линейном и квадратичном слагаемых в представлении ДР (у) от Sy (формула (20.7) при замене 8г на 8у). Все рассмотренные функции допускают в качестве исходных аргументов задавать массивы и тем самым одновременно рассчитывать параметры для пакета разных облигаций. Выходными параметрами также будут массивы, содержащие поэлементно характеристики каждой облигации. Портфельный анализ рисковых активов В заключение раздела рассмотрим средства пакета для анализа портфелей ценных бумаг средствами пакета MATLAB. Основные функции портфельного анализа основаны на моделях Марковица и Тобина и их модификациях. Вначале кратко поясним суть вопроса. В главе 16 рассматрива юя иллюстративный пример для определения одной точки на эффективной границе Марковица В общей постановке задача портфельного инвестирования для инвестора формулируется так. Инвестор рассматривает возможность вложения капи- о82 Часть IV. Использование Toolbox и решение прикладных задач тала в некоторый набор акций (рисковых активов), выбранный им из личных соображений, и желает составить портфель ценных бумаг так, чтобы его доходность была бы наибольшей при фиксированном риске или риск был бы наименьшим при выбранной доходности портфеля. В рассматриваемой модели за меру риска принимается среднеквадратическое отклонение доходности ценных бумаг или портфеля от ее математического ожидания. На выбор портфеля влияет также отношение инвестора к риску, т. е. насколько он готов увеличить рискованность вложения с целью получить большую доходность. В простейшем случае поиск наилучшего портфеля состоит из двух шагов: построение эффективной границы Марковица с использованием функций front con или portopt и выбор портфеля с помощью функции portal 1ос в соответствии с отношением инвестора к риску и значениями процентных ставок для безрискового вложения и заимствования. Для решения поставленной задачи инвестор должен сделать оценки ожидаемой доходности для каждой акции и матрицы ковариаций для выбранных акций на период инвестирования. Расчетная модель опирается на ряд гипотез, например, что активы сколь угодно делимы, в конце периода портфель реализуется, горизонт инвестирования для всех участников рынка одинаков, операционные издержки отсутствуют или ими можно пренебречь и ряд других. Соответственно при анализе полученных результатов следует делать соответствующие поправки. Пусть инвестор рассматривает вопрос о составлении портфеля из п рисковых активов, ожидаемые доходности которых представлены вектором у, а их ковариации — матрицей V: Портфель определяется вектором х = {х(} (i = l.п), компоненты которо- го указывают долю средств для покупки акций, поэтому условие Л 1=1 означает вложения всех выделенных для инвестирования средств в портфель. Обычно предполагается, что инвестор не имеет возможности осуществлять короткие продажи (продажи без покрытия), т. е. продавать заимствованные бумаги. Тогда компоненты вектора х должны быть неотрицательными (х,>0). Однако если такая возможность существует, то указанное ограничение не ставится, либо оно может быть сформулировано для каких-то отдельных ценных бумаг. Более того, МАТ1 АВ имеет средства Гпава 20 Решена экономических задач 88? формировать более сложные ограничения на компоненты л,-, которые будут рассмотрены далее. Ожидаемая доходность портфеля ур и его среднеквадратическое отклонение (риск) определяются формулами: Ур=хТу, ср=у/хтУх. Если yrain и утах — наименьшая и наибольшая доходность акций в портфеле, то ype[ymin, у^. J. Если для каждого значения доходности из указанного интервала решить задачу, рассмотренную в главе 16 и построить график Ур{^р}, то получится выпуклая кривая (см. рис 20.1), называемая пулей" Марковица, часть которой, лежащая между точками 2 и 3, является эффект ивной границей (или эффективным фронтом). Каждой точке ча этой границе (у^, соответствует оптимальный портфель в том смысле, что при фиксированной доходности у° невозможно составить портфель с меньшим риском или при фиксированном риске о° невозможно найти портфель с большей доходностью. Т очки, лежащие на участке 1 - 2, не отвечают оптимальному портфелю, поскольку при том же риске (ор) есть портфель с большей доходностью для вышележащей точки на участке 2-3. В силу этого точка 2 (y'|OW) определяет нижнее значение для доходности портфеля. Построение эффективной границы рисковых активов Для большей наглядности возьмем модельный пример, в котором активы имеют существенный разброс параметров, не характерный для реального рынка. Все процентные величины будем затавать десятичными дробями, как того требуют функции пакета при их вызове. Пусть имеется шесть рисковых активов. Поименуем их акции Cl, El, Е2, ЕЗ, Ml, М2 и пронумеруем от 1 до 6, так, что 3-й финансовый инструмент это акции Е2. Для каждого актива инвестор оценил ожидаемую доходность у,-, риск Grf (среднеквадратическое отклонение) и коэффициенты корреляции р,у. 29 Зак ВО 884 Часть IV Использование Toolbox и решено прикладных задач Запишем данные в матричной форме: 0.108 0.12 ’ 1 0.32 0.4 -0.3 0.31 -0.18 0.136 0.135 0.32 1 0.45 0.43 0.29 0.3 0.144 0.15 0.4 0.45 1 0.4 0.46 -0.29 У = 0.151 ; о = 0.18 ; Р = -0.3 0.43 0.4 1 0.41 0.4 0.187 0.20 0.31 0.29 0 46 0.41 1 0.25 0.191 0.205 -0.18 0.3 -0.29 0.4 0.25 1 Функции пакета для анализа портфелей используют матрицу ковариаций, а не коэффициентов корреляции. Для получения матрицы ковариаций воспользуйтесь функцией corr2cov: А_ковариации = corr2cov(А_СрКвОтклонений, А_корреляции) выходным параметром которой является матрица ковариаций случайных величин А ковариации, построенная по вектору среднеквадратических отклонений А_СрКвОтклонений и матрице коэффициентов корреляции А-Корреляции. Далее, при описании функций одинаковым параметрам будем давать одни и те же имена и пояснять их при первом использовании. Поскольку названия величин для портфелей и активов могут быть одноименными, будем снабжать параметры функций префиксом, например, а— для актива, п— для портфеля. Примечание Если первоначально оценена матрица ковариаций, то никаких предварительных преобразиваний исходных данных не требуется Воспользуйтесь листингом 20.6 и сформируйте в рабочей среде для дальнейшего использования вектор доходностей и матрицу ковариаций для активов, выбранных для примера. Листинг 20.6. Файл-программа Tesr_portf подготовки данных для анализа портфеля рисковых активов >п rrt.t. •.« .... . ..«»« . ...... * .... . □. . ^Ожидаемые доходности активов A_yld = [0.1пВ 0.136 0.144 0.151 0.187 0.191]; %Среднеквадратич<=ские отклонена я активов A_dev = [0.12 0.135 0.15 0.18 0.20 0.205); ^Матрица коз ^ициёнтов корреляции A_corr = [1 0.32 0.4 -0.3 0.31 -0.18; Гпава 20. Решение экономических задач 835 0.32 1 0.45 0.43 0.29 0.3; 0.4 0.45 1 0.4 0.46 -0.29; -0.3 0.43 0.4 1 0.41 0.4; 0.31 0.29 0.46 0.41 1 0.25; -0.18 0.3 -0.29 0.4 0.25 И; вычисление матрица ковариа; [ий активов A_cov = corr2cov(Ajev, A_corr) ; При конструировании собственных тестов помните, что матрица коэффициентов корреляции (и ковариаций) должна быть симметричной и положительно определенной. Такая проверка в фvнкцияx пакета МАТТ АВ отсутствует, и, если вы ошибетесь при вводе данных, то можете получить результаты, противоречащие здравому смыслу. Построение эффективной границы Марковица состоит в нахождении двух массивов точек для доходности и риска, а также для каждой пары "доходность-риск’1 векторы долей вложений в каждый актив. Для нахождения границы можно использовать две функции frontcon и portopt, отличающиеся только способом задания дополнительных ограничений на доли активов в портфеле. Поскольку функция f rontcon использует portopt, то начнем с функции portopt, которая вызывается следующим образом: [П_риск, П_доходности, П_доли] = portopt (А_доходности, А_ковариации, П_число, П_доходности, ... Множество_ограничений) Аналогичное обращение к функции f rontcon: [П_риск, П_доходности, П_доли] = frontcon(А_доходности, Аковариации, П_число, П_доходности, ... А_ограничения, Г_активов, Г_ограничения] Обязательными входными параметрами являются два первых: вектор ожидаемых доходностей активов А_доходности и их матрица ковариаций А ковариации. Два следующих параметра определяют точки для расчета эффективной границы, причем один из них должен быть пустым массивом, если определен второй. Если задан параметр п_число, определяющий число точек на эффективной границе, то рассчитываются равноотстоящие точки на интервале [у^<Утах]- Если определить массив точек из интервала [ylow, упшх]. го будут рассчитаны точки эффективной 1раницы для этих значений. Если опущены оба параметра или для них заданы пустые значения, то по умолчанию расчет проводится для десяти равноотстоящих точек 886 Часть IV Итпльяюания Tpnlbnx и решение прикладных задач интервала [v|ow, y^]. Поскольку первоначально не известно значение J’lcw то его можно рассчитать, обра гившись к функции со значением п_число = 2. Другой способ получения >jow продемонстрирован в приводимом ниже примере. Последний параметр множество_ограничений для portopt представляет матричную форму дополнительных ограничений на весовые коэффициенты активов л, в портфеле. Долевые ограничения на состав портфеля в frontcon разбиты на два вида: двусторонние на каждый вес .4 (для каждого актива в отдельности) и на сгруппированные активы по разным признакам. Параметр Г активов определяет состав группы, а параметр Г ограничения — задает ограничения для группы (задание дополнительных ограничений рассмотрено далее в разд. "Дополнительные ограничения при анализе портфелей"этой главы) Выходные параметры у функций одинаковы и содержат характеристики портфелей на эффективной границе: □ п_риск — вект ор рисков для каждого портфеля (среднеквадратические отклонения доходности от ожидаемой); □ п_доходности — вектор ожидаемых доходностей для каждого портфеля; □ п_доли — массив, каждая строка которого представляет доли активов в портфеле. Если не использовать дополнительных ограничений, вызов любой функции одинаков, поэтому рассмотрим функцию portopt для нахождения точек эффективной границы для модельной задачи. В нашем случае ymin =10.8% и =191%. Попытаемся рассчитать четыре портфеля с доходностями от 12% с шагом в 2%: » P_Ret = [0.12 0.14 0.16 0.18]; » [P_Risk, P_Ret, P_Ass] = portopt(A vid. A_cov, [ ], P_Ret) ??? Error using ==> portopt One or more requested returns are less than the return 0.131667 of the least risky portfolio Полученное сообщение об ошибке информирует, что эффективною портфеля с доходностью, меньшей 0.131667. нет. Указанное значение есть ylow в наших обозначениях. Надо либо изменить вектор заданных доходностей портфелей, либо использовать другую форму вызова функции. Воспользуемся другим способом расчета четырех портфелей на эффективной границе: » [PRisk, P_Ret, PAss] = portopt(A _yld, A _cov, 4) P_Risk = 0.0805 Гпава 20. Решение экономических задач 887 0.0884 0.1126 0.2050 P_Ret = 0.1317 0.1514 0.1712 0.1910 P_Ass = 0.574.7 -0.0000 0.0487 0.2336 0.0000 0.1430 0.2592 -0.0000 0.3822 0.0020 0 0.3566 0.0000 -0.0000 0.4088 -0.0000 0.1411 0.4501 -0.0000 0 0 0 0 1.0000 Обратите внимание, что для нашего примера второй актив (Е1) не вошел ни в один портфель. Последний портфель состоит только из одного актива с наибольшей доходностью, что вполне предсказуемо. Оптимальный выбор портфеля Построение эффективной границы дает инвестору множество эффективных портфелей. Инвестор выбирает тот из них, который соответствует его отношению к риску: портфель с большей доходностью имеет больший риск. Моделирование отношения инвестора к риску в пакете MATLAB осуществляется с помощью функции полезности Неймана—Монгерштерна: (20.14) Постоянная а называется индексом неприятия риска. Уравнение (J = const описывает линию безразличия, т. е. полезность для инвестора одинакова на всех точках этой кривой. Множество этих линий образуют непересекающе-еся семейство, при этом, чем больше полезность, тем выше (по отношению к доходности ур) и левее (по отношению к риску стр) кривая расположена на графике. Инвестор стремится максимизировать значение функции (20.14) на множестве допустимых портфелей. Поэтому оптимальным для инвестора является портфель, отвечающий единственной точке эффективной границы, в которой она касается одной из линий безразличия (на рис. 20.1 эта точка обозначена Т |. Эта линия безразличия, которую будем называть рациональной, отвечает наибольшей достижимой полезности, ибо малейшее ее увеличение приведет к отсутствию общих точек на допустимом множекгве 888 Часть IV. Использование Toolbox и решение прикладных задач портфелей и выбранном уровне полезности. Точка 3 эффективной границы является угловой, поэтому условие касания линий (совпадение тангенсов углов наклона касательных прямых к кривой безразличия и эффективной границе) может не выполняться. Рис. 20.1. Выбор оптимального портфеля на эффективной границе Марковица Однако в пакете используется модифицированная модель инвестирования, когда инвестор может вкладывать средства не только в рисковые активы, но и в безрисковый актив, который является единственным для выбранного срока (горизонта) инвестирования, характеризуемым процентной ставкой rf . Дополнительно инвестор может привлекать заемные средства по ставке rb (rb>r, ), поэтому эффективная граница может состоять из трех частей (см. рис. 20.2, сплошная жирная линия): 1. Отрезок прямой 1-2, начинающийся в точке (б, zy) и касающийся в точке 2 границы Марковица. 2. Луч 3 - 4 (4 — не конечная точка) есть часть касательной прямой к границе Марковица, исходящей из точки (0, гь ). 3. Часть границы Марковица между точками 2 и 3. Глава 20. Решение экономических задач 889 Рис. 2и.2. Эффективная граница при наличии безрисковых вложений и заимствований В зависимости от того, какого участка эффективной границы будет касаться кривая безразличия, инвестор сформирует свой портфель ценных бумаг. Точка касания будет единственной, поскольку линия безразличия является выпуклой функцией. Если рациональная кривая безразличия соприкасается с границей 2-3, то инвестору следует вложить все собственные средства в рисковый портфель, соответствующий точке соприкосновения, как в модели Марковица. Если рациональная кривая безразличия соприкасается с какой-либо частью допустимой прямой (отрезком 1 - 2 или лучом 3 - 4), то получается коэффициент вложения средств в касательный портфель, соответствующий точке касания прямой с границей Марковица: = (20.15) где ст( — риск, отвечающий найденной точке на эффективной границе, а — риск касательного портфеля либо для точки 2, либо для точки 3. 890 Часть IV. Использование Toolbox и решение прикладных задач Для луча 3-4 этот коэффициент больше 1, следовательно, инвестору следует занять недостающие средства по ставке гь для увеличения объема второго касательного портфеля, соответствующего точке 3. Это можно интерпретировать как вложения с отрицательным весом (1-£) в безрисковый актив, т. е. заимствование. Для отрезка 1 -2 коэффициент Е, (20.15) меньше 1, поэтому инвестор должен разделить свой капитал и вложить часть (1-£) в безрисковый актив по ставке г?, а часть £ в рискованный портфель с долевым составом, отвечающим точке 2 (первый касательный портфель). В последнем случае окончательный портфель будет содержать не только рисковые финансовые инструменты, но также и безрисковый актив, в то время как в первых двух — только рисковые ценные бумаги. Примечание Возможны и другие варианты эффективной границы. Если /у = rh (модель Тобина), то эффективной границей является прямая (точки 2 и 3 совпадают) Если отсутствует возможность заимствования, то не будет луча 3-4, и эффективная граница состоит только из двух участков: отрезка 1 - 2 и части границы Марковица от точки 2 до конечной точки 5. Возможно, что отсутствует безрисковое вложение. Тогда можно считать Г[ =0, т. е. средства некуда вкладывать без риска, и точка на первом участке определяет часть средств для вложения в рисковый портфель, а остальную часть, соответствующую нулевой ставке "безрисковых вложений", следует вывести с рынка рисковых ценных бумаг. Для расчета рационального портфеля предназначена функция portal loc: [КПриск, КП_доходность, КП_доли, коэффициент, ОП_риск, ... ОП_доходность] = portalloc(Приск, Пдоходности, П_доли, ... Бр_вложение, Бр_заимствование, Инд_риска) Первые три входных параметра — это массивы характеристик портфелей на эффективной границе Марковица, рассчитанные с помощью ранее рассмотренных функций frontcon и portopt. Два следующих параметра— это ставка вложения в безрисковый актив Бр_вложение и процентная ставка безрискового заимствования Бр заимствование. Последний параметр Инд риска есть индекс неприятия риска инвестором. Рекомендуемые значения 4 — для осторожного инвестора и 2 — для готового к риску. Чем больше это значение, гем меньший риск выбирается. Глава 20 Решение экономических задач 891 Выходные параметры дают характеристики касательною портфеля (кп_ригк, кп_доходность, кп_доли), коэффициент вложения средств в касательный портфель (коэффициент), риск и доходность оптимального портфеля (ОП_риск, ОП_доходность). Если эта функция вызывается без выходных параметров, то она выводит графическое окно, в котором иллюстрируется положение оптималиного портфеля на эффективной границе. Фактически возможны три варианта, которые обсуждались ранее. Для того чтобы проанализировать возможные случаи работы функции portalloc, выполните файл-программу из листинга 20.7. Вначале она содержит команды программы из листинга 20.6 для формирования исходных данных рисковых активов. Далее с помощью функции находится эффективная граница Марковица и задаются общие значения для безрисковых ставок вложения и заимствования. Затем для трех разных индексов неприятия риска ищется оптимальный портфель. Чтобы получить и графическое, и численное представление результатов, функция вызывался дважды: без выходных параметров для построения графика, а потом выводятся численные значения характеристик оптимального портфеля. Листинг 20.7. Получение оптимального портфеля в зависимости от отношения инвестора к риску »»»•«;«• а ..........--..i...................... %Ожидаемые доходности активов A_yld = [0.108 0.136 0.144 0.151 0.187 0.191]; % Среднеквадратические отклонения активов A_dev = [0.12 0.135 0.15 0.18 0.20 0.205]; %Матрица коэффициентов корреляции A_corг = [1 0.32 0.4 -0.3 0.31 -0.18; 0.32 1 0.45 0.43 0.29 0.3; 0.4 0.45 1 0.4 0.46 -0.29; -0.3 0.43 0.4 1 0.41 0.4; 0.31 0.29 0.46 0.41 1 0.25; -0.18 0.3 -0.29 0.4 0.25 1]; %вычисление матрицы ковариаций активов A_cov = corr2cov(A dev, A_corr); %нахпадение эффективной границы [P_Risk, P_Ret, P_Ass] - portopr.(A_yld, A_cov, 25) ^Процентные ставки Безрисковых активов RFreeasset = 0.095; R_Borrow = 0.13; 892 Часть IV. Использование Toolbox и решение прикладных задач % Оптимальный портфель инвестора % с высоким уровнем неприятия риска Index_Risk = 7 ,- [TP_Riskl, TP_Retl, TP_Assl, R_Fractionl, ... OP_Riskl, OP_Retl] = port_alloc(P_Risk, P_Ret, P Ass, ... R_Fieeasjet, R_Borrow , Index_Risk) port_alloc(P .Risk, P_Ret, P_Ass, ... R_Freeasset, R_Borrow, Index_Risk); % Оптимальный портфель инвестора % с низким уровнем неприятия риска Index_Risk = 2,- [TP_Risk2, TP_Ret2, TP_Ass2, R_Fraction2, ... OP_Risk2, OP_Ret2] = port_alloc(P_Risk, P_Ret, P^Ass, ... R_Freeasset, R_Borrow , Index_Risk) port_alloc(P_Risk, P_Ret, P_Ass, ... R_Freeasset, R_Borrow, Index_Risk); % Оптимальный портфель инвестора % co среднем уровнем неприятия риска Index_Risk = 3; [TP_Pisk3, TP. Ret3, TP_Ass3, R_Fraction3, ... OP_Risk3, OP_Ret3] = port_alloc(P_Risk, P_Ret, P_Ass, ... R_Freeasset, R_Borrow, Index_Risk) port_alloc(P_Risk, P_Ret, P_Ass, ... R_Freeasset, F_Borrow, Index_Risk); В результате выполнения программы из листинга 20.7 получатся оптимальные портфели для инвесторов с разным уровнем неприятия риска. Для осторожных, не склонных к риску, инвесторов выбор оптимального портфеля представлен на рис. 20.3. Оптимальный пор гфель лежит на отрезке, соединяющем безрисковый актив для вложения и первый касательный портфель. Численные результаты для этого случая таковы: TP_Riskl -0.1078 TF_Retl = 0.1683 Гпава 20 Решение экономических задач 893 Ti’.jLSril - 0.0072 -0.0000 0.4636 -0.0000 0.0905 0.4387 R_Fractionl = 0.9003 OPRiskl = 0.0971 OP_Retl = 0.1609 Рис. 20.3. Оптимальный портфель инвестора с высоким уровнем неприятия риска Наиболее показательной величиной является параметр RFractioni (формула (20.15», показывающий долю касательного портфеля в оптимальном. В данном случае он меньше единицы. Это показывает, что оптимальный портфель лежит на участке 1 - 2 эффективной границы в соответствии с обозначениями на рис. 20.2. Он также указывает инвестору, что 90% собственных средств надо вложить в касательный портфель, доли каждого актива представлены параметром TP Assl. Оставшиеся 10% следует вложить в безрисковый актив. Если величина index Risk будет больше, то и процент вложений в безрисковый актив будет больше. Параметры op_Reti и op_Riski дают расчетные значения для ол<идаемой доходности и риска оптимального портфеля. 894 Часть IV. Использование Toolbox и решение прикладных задач Оптимальный портфель инвестора, готового рискнуть для получения большей доходности, представлен на рис 20.4. Рис. 20.4. Оптимальный портфель инвестора с низким уровнем неприятия риска Оптимальный портфель лежит на луче 3 - 4 (в соответствии с обозначениями рис. 20.2), а рассчитанные величины таковы: TP_Risk2 = 0.1298 TP_Ret2 = 0.1789 TP_Ass2 = 0.0000 -0.0000 0.2340 -0.0000 0.2870 0.4790 R_Fraction2 = 1.4503 OP_Risk2 = 0.1882 OP_Ret2 = 0.2009 Гпава 20. Решение экономических задач 895 Параметр R_Fraction2 показывает, что инвестору следует увеличить собственные инвестиции на 45% за счет заемных средств. Эта величина будет тем большей, чем меньше индекс неприятия риска index_Risk. Все средства вкладываются в касательный портфель с долями активов, которые определяются параметром tp_ass2. Инвестор со средним уровнем неприятия риска на нашем модельном рынке ценных бумаг выберет портфель на границе Марковица (на ее части 2-3 в обозначениях рис. 2(1 2), и функция отобразит это в виде, представленном на рис. 20.5. Рис. 20.5. < )птимальный портфель инвестора со средним уровнем неприятия риска Численные результаты для этого случая будут следующими: TP_Risk3 = 0.1284 TP_Ret3 = 0.1783 TP_Ass3 - 0.0000 -0.0000 0.2461 -0.0000 0.2769 0.4770 896 Часть IV. Использование Toolbox и решение прикладных задач R_Fraction! - 1 OP_Risk3 = 0,1284 OP_Ret3 = 0,1783 Поскольку параметр R_Fraction3 равен 1, то характеристики касательного портфеля и оптимального одинаковые, Примечание Важно осознать, что отношение инвестора к риску определяется параметром коэффициент в функции portalloc, а не тем, на каком участке эффективной границы расположен оптимальный портфель. Рыночная конъюнктура может быть такой, что для всех инвесторов оптимальные портфели будут лежать на одном из трех основных участков эффективной границы и отличаться будут только долями. В теории считается, что осторожный инвестор имеет индекс неприятия риска в окрестности 4 и более, инвестор, готовый рисковать, вблизи 2 и менее. Инвестор со средним уровнем неприятия риска имеет этот параметр в окрестности 3. Дополнительные ограничения при анализе портфелей При расчете эффективной границы мы обратили внимание, что второй актив не вошел ни в один портфель. Однако если инвестор выбрал для вложения этот рыночный инструмент, то он желает включить его в свой портфель, руководствуясь состоянием рынка. Функции пакета MATLAB дают пользователю возможность сформировать дополнительные ограничения на весовые коэффициенты для активов в портфеле. Любые дополнительные ограничения сужают множество допустимых портфелей и, следовательно, приводят к получению менее эффективного портфеля. Эти ограничения по-разному передаются в рассмотренные ранее функции frontcon и port opt. Для функции frontcon они передаются с использованием параметров А_ограничения, г_активов, г_ограничения. Простейшие двусторонние ограничения на активы формулируются для каждой ценой бумаги независимо и имеют вид: (20.16) Для передачи этих ограничений функции frontcon в качестве параметра следует с<] ормировать массив из двух строк, содержащих индивидуальные ограничения для каждой ценной бумаги. Пусть в рассматриваемом примере Г лава 20. Решение экономических задач 897 инвестор предполагает в каждый актив вложить не менее 5% и не более 37% собственного капитала. Тогда ограничения на активы запишутся в массив как: '0.05 0.05 0.05 0.05 0.05 0.051 ЛС= . (20.17) 0.37 0.37 0.37 0.37 0.37 0.37J Далее, в листинге 20.8, иллюстрируется использование этого массива. Другой тип ограничений, который будем называть ограничениями на группу активов, задается для функции frontcon двумя параметрами г_активов и Г_ограничения. Первый из них определяет группы активов. Он представляет собой матрицу, состоящую из такого количества строк, сколько групп выделил в своем портфеле инвестор. Каждая строка состоит из нулей и единиц и содержит количество элементов, равное числу активов в портфеле. Значение 1 указывает, что ценная бумага входит в группу, а 0 — нет. Инвестор самостоятельно руководствуется признаками для включения финансовых инструментов в группу. Второй параметр г_ограничения является массивом, состоящим из двух столбцов размерности количества введенных групп для нижней и верхней границы суммы весов активов, входящих в группу. Если матрицу, задающую состав групп, обозначить G, нижние и верхние ограничения для каждой группы записать в векторы gt и gu , то математически эти условия запишутся в форме: gl<Gx<gu. (20.18) Определим для ранее рассмотренного примера группы, сформированные по двум признакам: □ сектор экономики, к которому принадлежит эмитент; О ориентация на внутренний или внешний рынки. Будем считать, что ценные бумаги Ml, М2 и М3 выпущены в обращение машиностроительными корпорациями, Е1 и Е2— энергетическими. С1 — предоставляющими услуги связи. Эмитенты акций Е2 и М3 ориентированы на внешние рынки. Пусть инвестор имеет намерения вкладывать средства в активы, руков< щствуясь следующими соображениями: □ для энергетических компаний вложения должны быть не менее 22% и не более 64%; □ для машиностроительных компаний вложения должны быть не менее 26% и не более 71%; □ для компаний, ориентированных на внутренний рынок, вложения должны быть не менее 14% и не более 56%; 898 Часть IV. Использование Toolbox и решение прикладных задач □ для компаний, ориентированных на внешний рынок, вложения должны быть не менее 25% и не более 84%. Toi да для параметров г_активов и г_ограничения надо сформировать массивы, которые соответственно обозначим GA и BG, в виде; 0 1 I 0 0 О’ 0 0 0 1 1 1 0 0 1 0 0 1 110 110 и 0.12 0.46 0.1 0.52 0.24 0.63 (20.19) (20.20) 0.25 0.53 Для определенности будем относить себя к инвестору с индексом неприятия риска 2. Рассчитайте эффективную границу при наличии дополнительных условий на вес активов в портфеле, воспользовавшись листингом 20.8. Вначале рассчитывается состав портфеля только с ограничениями вида (20.16), потом только с ограничениями типа (20.18) и окончательно со всеми условиями. .ними а им •• . • м . ка,... .. >.............. Листинг 20.8. Использов шие ограни^: ний при поиске опти аль эго эртфеля функцией frontcon ^Ожидаемые доходности активов Ayld = [0.108 0.136 0.144 0.151 0.107 0.191]; ^Среднеквадратические отклонения активов A_dev - [0.12 0.135 0.15 0.18 0.20 0.205]; ^Матрица коэффициентов корреляции Acorr = [1 0. 32 0.4 -0.3 0.31 -0.18; 0.32 1 0.45 0.43 0.29 0.3; 0.4 0.45 1 0.4 0.46 -0.29; -0.3 0.43 0.4 1 0.41 0.4; 0.31 0.29 0.46 0.41 1 0.25; -0.18 0.3 -0.29 0.4 0.25 11; ^вычисление матрицы ковариаций активов A cov == corr2cov(A_dev, Acorr); лав i 20. Решение экономических задач 899 'Матрица для ограничений на активы АС = [0.05 0.05 0.05 0.05 0.05 0.05; 0.37 0.37 0.37 0.37 0.37 0.37]; Данные для ограничений на гоуппк активов ЗА = [0 1 1 0 0 0; 0 1 1 0 0 0; 0 0 1 0 0 1; 1 1 0 1 1 0]; BG = [0.12 0.46; 0.1 0.52; 0.24 0.63; 0.25 0.53]; %0.25 0.52 при таких значениях - ошибка ^Процентные ставки безрисковых активов R_Freeasset = 0.095; R Harrow = 0.13; ¥ Инвестор с низким уровнем неприятия риска I«dex_Risk = 2; ^нахождение эффективной границы [P_Risk, P_Ret, P_Ass] = frontcon(A_yld, A_cov, 5) ^Процентные ставки безрисковых активов R_Freeasset = 0.095; R Borrow = 0.13; ^Инвестор с низким уровнем неприятия риска IndexRisk =2; ^нахождение эффективной границы с ограничь ниями на активы [P_Risk, P_Ret, P_Ass] - frontcon(A_yld, A_cov, 25, [ ], AC) ; ^Оптимальный портфель инвестора с ограничением на активы disp('Оптимальный портфель инвестора') disp('с ограничениями на активы') [CondA_TP_Risk2, CondA_TP_Ret2, CondA_TP_Ass2, CondA_R_Fraction2, ... CondA„OP_Risk2, CundA OP_J<et2] = port_alloc(P_Risk, P_Ret, P__Ass, ... R_Freeasset, R_Borrow, Index_Risk) ^нахождение эффективной границы с ограничениями на группы активов [P_Risk, P^Ret, P„Ass] = frontcon(Д_уId, A. cov, 25, [ ], [ ], GA, BG) ; 900 Часть IV. Использование Toolbox и решение прикладных задач tОптимальный портфель инвестора с ограничениями на группы активов disp(' .лтимальный портфель инвестора’) disp(’ с ограничениями на группы активов ') [CondG_TP_Risk2, CondG_JTP_Ret2, CondG_TP^Ass2, CondG_R_Fraction2, ... CondG_0P_Risk2, CondG_OP_Ret2] = port_alloc(P_Risk, P_Ret, P_Ass, ... K_Freeasset, R_Borrow, Index_Risk) «нахождение эффективной границы co всеми ограничениями [CondA_TP_Risk2, CondA_TP_Ret2, CondA_Tr_Ass2, R_Fraction2, ... P_Risk, P_Ret, P_Ass] = fiontcon(A_yld, A_cov, 25, [ ], AC, GA, BG); ^Оптимальный портфель инн стора со всеми огр ^потениями disp('Оптимальный портфель инвестора’) disp('со всеми ограничениями') [CondF_TP_Risk2, CondF_TP_Ret2, CondF_TP_Ass2, CondF_R_Fracticn2, ... CondF_0P_Risk2, CondF_OP_Ret2] = port_alloc(P_Risk, P_Ret, P^Ass, ___ R_Freeasset, R_Borrow, Index_Risk) После выполнения программы из листинга 20.8 получите следующие результаты: Оптимальный портфель инвестора с ограничениями на активы CondA_TP_Risk2 = 0.1266 CondA_TP_Ret2 = 0.1741 CondA_TP_Ass2 = 0.0500 0.0500 0.1408 0.0500 0.3392 0.3700 CondA_R_Fraction2 = 1.3767 CondA_OP_Risk2 = 0.1743 CondA_OP_Ret2 -0.1907 Оптимальный портфель инвестора с ограничениями на группы активов CondG_TP_Risk2 _ 0.1380 Гпава 20 Решение экономических задач 901 CondG_TP_Ret2 = 0.1818 londG TPJss2 - 0.0000 0 0.1646 -0.0000 0.3700 0.4654 CondG_R_Fraction2 = 1.3604 CondG_OP_Risk2 = 0.1877 CondG_OE>_Ret2 = 0.2004 Оптимальный портфель инвестора со всеми ограничениями CondF_TP_Risk2 = 0.1272 CondF_TP_Ret2 = 0.1743 CondF_TP_Ass2 = 0.0500 0.0500 0.1362 0.0508 0.3430 0.3700 2ondF_R_Fraction2 = 1.3686 CondF_OP_Risk2 = 0.1741 dondF_OP_Ret2 = 0.1906 По результатам вычислений легко увидеть, какие ограничения внесли изменения на формирование эффективной границы. Для этого надо проанализировать состав касательного портфеля. Как правило, инвестор проводит многовариантные расчеты для подбора удовлетворяющего его портфеля. Примечание Поскольку многочисленные ограничения могут привести к отсутствию допустимых портфелей, рекомендуется поочередно вводить новые ограничения В тестовом примере дополнительные условия выбраны так, чтобы избежать такой ситуации. Для функции portopt формирование ограничений происходит иначе. Для нее вся совокупность ограничений передается параметром Множест 902 Часть IV. Ид i<>nb.iuedHne Toolbox и решение прикладных задач во ограничений. Для того чтобы этот параметр определить, надо воспользоваться другой функцией пакета portcons, имеющей переменное число однотипных аргументов и вызываемой следующим образом для формирования одного типа ограничений: Множество ограничений = portcons('тип_ограничеия', данные_1, данные_Ы) В табл. 20.7 представлены типы ограничений и требуемые для их формирования данные. Таблица 20.7. Дополнительные ограничения на активы Тип ограничения Назначение Число элементов данных Описание данных Default Стандартные ограничения на веса: х(>0 5>i=l 1 1. число_активов (обязательный). Количество активов в портфеле — скаляр PortValue Нормировка портфеля 2 1. коэффициент (обязательный), задает сумму весов активов в портфеле — скаляр. 2. числоактивов (обязательный). Количество активов в портфеле — скаляр AssetLims Ограничения на активы 3 1. нижняя_граница (обязательный), вектор из Ц в обозначениях формулы (20 16). Размерность — числоактивов. 2. верхняя граница (обязательный), веК1Ориз и, в обозначениях формулы (20.16). Размерность — число_активов. 3. число_активов (необязательный), количество активов в портфеле — скаляр Глава 20. Решение экономических задач 903 Таблица 20.7 (продолжение) Тип ограничения Назначение Число элементов данных Описание данных GroupLims Ограничения на группы ак1ивов 4 1. г активов (обязательный), матрица типа G в обозначениях формулы (20.18). Размерность — число_групп на число_активов. 2. нижняя_граница (обязательный), вектор gt в обозначениях формулы (20.18). Размерность — число_групп. 3. верхняЯ—граница (обязательный), вектор gu в обозначениях формулы (20.18). Размерность — число_групп. 4. число_групп (необязательный), количество определенных групп — скаляр Group Comparison Ограничения на сумму весов в двух множествах групп (сравнение попарное) 5 1. Множество_1_групп (обязательный), матрица типа G в обозначениях формулы (20.18). Размерность — число_групп на число_активов. 2. Множество_2_групп (обязательный), матрица типа G в обозначениях формулы (20.18) Размерность — число_групп на число_активов. 3. минимальное_отношение (обязательный), скаляр или вектор, определяющий минимальное отношение суммы весов в Множество_1_групп к сумме весов в Множество_2_групп. Размерность— 1 или число_групп. 904 Часть IV. Использование Toolbox и решение прикладных задач Таб шца 20.7 (окончание) Тип ограничения Назначение Число элементов данных Описание данных 4. максимальное_отношение (обязательный), скаляр или вектор, определяющий максимальное отношение суммы весов в Множество_1_групп к сумме весов в Множество_2_групп. Размерность— 1 или число_групл. 5. Число групп (необязательный), количество определенных групп в каждом множестве (одинаковое для каждо! о множества) — скаляр Custom Произвольные линейные ограничения. Неравенства: Ах < b 2 1. матрица_А (обязательный), матрица коэффициентов матричного неравенсгва Ал <Ь. Размерность — числО—Ограничений на число_активов. 2. вектор Ь (обязательный), век ор правых частей матричного неравенства Ах<Ь. Размерность — число_ограничений Выходной параметр мнс,жество_ограничений представляет прямоугольную матрицу, число столбцов которой на I больше числа активов в портфеле. При построении выходной матрицы ограничений условия их совместимости не проверяются. Поясним это на следующем простейшем примере: >> Restr_Set = portcons('PortValue', 1.25, 3, 'Default' , 3) Restr_set = l.OOOu l.uOOO 1.0000 1.2500 -1.0000 -1.0000 -1.0000 -1.2500 1.0000 1.0000 1.0000 1.0000 -1.0000 -1.0000 -].0000 -1.0000 -1.0000 0 0 0 0 -1.0000 0 0 0 n -1.0000 0 Гпава 20 i-ешпние экономических задач 905 Первые две строки являются условием нормировки суммы весов портфеля на величину 1.25. Следующие строки формируют неравенства, соответствующие ограничениям по умолчанию: нормировка суммы весов портфеля па 1 и л,i-О (i = l, 2,3). Только при дальнейшем использовании ограничений выяснится их несовместность. Для использования функции детальное знание структуры выходной матрицы не требуется. Типы ограничений AssetLims и GroupLims соответствуют ранее рассмотренным ограничениям для функции frontcon и пояснений истребуют. Фактически и формирование ограничения типа Custom тоже прозрачно. Поясним, как формируется ограничение типа GroupComparison. Для его создания надо определить два множества, состоящие из одинакового количества групп Принцип их задания такой же, как и для ранее рассмотренного параметра г_активов функции frontcon. Пусть для определенности минимальное_отношение И максимальноеотношение представляют собой векторы. Обозначим G-^ и = J = 1............л —номер актива) строки маз риц Множество_1_групп и Множество_2_групп, определяющие сравниваемые i руппы (сравниваются группы с одинаковым порядковым номером во множествах). Пусть далее компоненты векторов мини-мальное_отношение И максимальное_отношение обозначены И и( , а вектора число активов— II. Тогда составляется цвойное неравенство: или два ограничения-неравенства: -14% <0. <0. В заключение в листинге 20.9 представим программу расчета гех же портфелей, что и в листинге 20.8, только с применением функции portopt. В качестве результатов выведем только доходность и риск оптимального портфеля, а также коэффициент вложения в касательный портфель. Листинг 20.9. Использование ограничений при поиске оптимального портфеля функцией yorti/pt ^Ожидаемые доходности активов A-yld = [0.108 0.136 0.144 0.151 0.187 0.191]; 906 Часть IV Использование Toolbox и решение прикладных задач %?реднеквадратические отклонения активов A_dev = [0.12 0.135 0.15 0.18 0.20 0.205); ^Матрица коэфф., {центов корреляции A_corr - [1 0.32 0.4 -0.3 0.31 -0.18; 0.32 1 0.45 0.43 0.29 0.3; 0.4 0.45 1 0.4 0.46 -0.29; -0.3 0.43 0.4 1 0.41 0.4; 0.31 0.29 0.46 0.41 1 0.25; -0.18 0.3 0.29 0.4 0.25 1]; вычисление матрицы ковариаций активов A_cov = con2cov(A_dev, A_corr); ^Процентные ставки безрисковых активов R_Freeasset = 0.095; R_Borrow = 0.13; % Инвестор с низким уровнем неприятия риска Index_Risk = 2; %Прсцентные ставки безрисковых активов R_Freeasset = 0.095; R_Borrow = 0.13; % Инвестор с низким уровнем неприятия риска Index_Risk = 2; ^нахождение эффективной границы с ограничениями на активы %Матрица для ограничений на активы АСтах = [0.37 0.37 0.37 0.37 0.37 0.37]; ACmin = [0.05 0.05 0.05 0.05 0.05 0.05); Restr_Set = portcons('Default’, 6, 'AssetLims', ACmin, ACmax, 6); [P_Risk, P_Ret, PAss] = porLopt (A_yld, h_cov, 25, [ ], Restr_Set); %Оптимальный портфель инвестора с disp('Оптимальный портфель инвестора') disp (' с ограничения!.™ на активы 1) [CondA_TP_Ribk2, CondA_TP_Ret2, CondA_TP_Ass2, CondA_R_Fraction2, ... CondA_OP_Risk2, CondA_OP_Pet2] - port_alloc(P_Risk, P_Ret, P_Ass,... R_Fr<=>easset, R_Borrow, Index_Risk) ; CondA_R_Fraction2 CondA_GP_Risk2 CondA_OP_Ret2 ^нахождение эффективной границы с ограничениями на группы активов сДанные для ограничений на группы активов Гпава 20. Решение экономических задач 907 GA = [0 1 1 0 0 0,- 0 1 1 0 0 0; 0 0 1 0 0 1; 1 1 0 1 1 0] ; GRmax - [0.46 ; 0 .52 ; 0.63 ; 0.53],- GBmin = [0.12 ; 0.1 ; 0.24 ; 0.25]; Restr_Set = portcons (1 Default', 6, 'GroupLims', GA, GEmin , CBmax) ,-[P_Risk, P_Ret, P_Aas] = portopt (A_yld, A_cov, 25, [ ], Restr_Set) ,-%Оптимальный портфель инвестора с ограничениями на группы активов disp('Оптимальный портфель инвестора*) disp(1 с ограничениями на группы активов ’) [UondG_TP_Risk2, CondG_TP_Ret2, CondG_TP_Jss2, CondG_R_Fraction2, ... Y>r,dG_OP_Risk2, CondG_OP_Ret2] = port_alloc(P_Risk, P_Ret, P_Ass, ... R.Freeasset, R_Borrow, Index_Risk); CondG_R_Fraction2 CondG_OP_Risk2 CondG_OP_Ret2 Ьнахождение эффективной границы co всеми ограничениями Restr_Set = portcons('Default', 6, 'AssetLims', ACmin, ACmax, 'GroupLims', GA, GBmin , GBmax); [P_Risk, P_Ret, P. Ass] = portopt(A_yld, A_cov, 25, [ ], Restr_Set); %Оптимальный портфель инвестора co всеми ограничениями disp(’Оптимальный портфель инвестора*) disp(1 со всеми ограничениями *) [CondF_TP_Risk2, CondF_TP_Ret2, CondF_TP_Ass2, CondF_R_Fraction2, ... Cord!_OP_Risk2, CondF_OP_Ret2] - port_alloc(P_Risk, P_Ret, P^Ass,... R_Freeasset, R__Eorrow , Index_Risk); CcndF R_Fraction2 CondF_OP_Risk2 GondF_OP_Ret2 После выполнения программы получим те же результаты, что и ранее (поскольку решалась та же задача). » Оптимальный портфель инвестора с ограничениями на активы CondA JR _Fraction2 = 1.3767 908 Часть IV. Использование Toolbox и решение прикладных задач CondA_OP_Risk2 = 0.1743 CondA_OP_Ret2 - 0.1907 Oni има-ii .ный портф< ль инвестора с ограничениями на группы активов CondG_R_Fraction2 = 1.3604 CondG_OP_Risk2 = 0.1877 CondG_OP_Ret2 = 0.2004 Оптимальный портфель инвестора со всеми ограничениями CondF_R_Fraction2 = 1.3686 CondF_OP_Risk2 = 0.1741 CondF_OP_Ret2 = 0.1906 В заключение обратим ваше внимание на необходимость осторожно относиться к полученным численным результатам, даже если они вполне правдоподобны. Задача определения оптимального портфеля чувствительна к исходным данным и ошибкам вычислений. ЧАСТЬ V Дополнительные возможности MATLAB Глава 21 Связь MATLAB и MS Office Среда М ATLAB допускает интегрирование с MS Word и MS Excel, которое позволяет достаточно просто подготовить отчет по результатам исследований в MATLAB и получить файл в одном из распространенных форматов, включая MS Word и MS Power Point. Отчеты могут являться документами MS Word, которые позволяют выполнить блоки команд MATLAB и сразу же вывести в документ текстовые или графические результаты. Сочетание этой возможности со средствами MS Word по оформлению документ оз образует удобную среду для разработки, например, интерактивных учебных пособий. Обработка данных облегчается при сочетании работы в MATLAB и MS Excel. Надстройка MS Excel Link, входящая в доставку MATLAB, снабжает пользователя MS Excel доступом ко всем функциям MATLAB, которые значительно расширяют возможности электронных таблиц. Публикация результатов работы Для обмена информацией с другими пользователями с целью представления своей работы зачастую недостаточно предъявить соответствующий М-файл, даже снабженный подробными комментариями. Наглядная демонстрация должна включать формулы, блоки команд, графические и текстовые результаты в одном из распространенных форматов. Используя, например, MS Word, можно написать отчет по работе, сопроводив его комментариями, текстовыми данными, скопированными из командного окна, и рисунками, экспортированными из графических окон. Однако эту работу можно переложить на MATLAB и, затрачивая минимальные усилия, получить данный отчет в одном из форматов: документ MS Word, презентация PowerPoint, HTML или LaTeX. Справочная система MATLAB содержит ссылку на видеодемонсгацию (на английском языке) процесса публикации результатов, которая длится около 912 Часть V. Дополнительные возможности MATLAB 5 мин. Для ее запуска перейдите к содержимому вкладки Demos интерактивной справочной системы MATLAB, и в разд MATLAB: Desktop Tools and Development Environment: Publishing M Code from the Editor щелкните по гиперссылке Run this demo. Мы не будем рассматривать все возможности для публикации результатов работы, а опишем только основные подходы. Прежде всего следует организовать расчеты в файл-программе, разбитой на ячейки. Работу в этом режиме мы рассматривали выше (см. разд. "Разбиение М-файла на ячейки" главы 5). Предположим, что наша работа состояла в вычислении интеграла J|a| mdx. -1 Ьго точное значение составляет 200/99, но прямое применение функции quadi не позволяет вычислить этот интеграл из-за особенности подынтегральной функции (численное интегрирование описано в разд. "Вычисление определенных интегратов" главы 6). Мы разбиваем интеграл по отрезку [-1,1] на два: [-1,0] и [0,1], находим их значения при помощи quadi и затем складываем для получения ответа. В отчет желательно поместить формулы, графики подынтегральных функций, команды MATLAB и их результат. Для этого подготовьте М-файл integral.tn, разбитый на ячейки в соответствии с листингом 21.1. Заголовки ячеек станут разделами отчета. Если в ячейку требуется поместить текст, то строку с текстом следует начинать со знака %, т. е. закомментировать. Для получения в отчете жирного шрифта следует заключить текстовую строку символами звездочка, а моноширинного — символами вертикальной черты. Формулы набираются в формате LaTeX и окружаются двумя знаками доллара (примеры набора формул приведены в разд. "Оформление графика" главы 3 и "Вывод математических формул в формате LaTeX" главы 9). Примечание Меню Cell редактора М-файлов содержит подменю Insert Text Markup. Fro пункты служат для размещения в тексте М-файла заготовок для формул и оформления текста различными стилями. Те операторы MATLAB, которые выводят нужную нам информацию в командное окно, мы не завершаем точкой с запятой для включения результатов в отчет. Гпава 21. Связь MATLAB и MS Office 913 %% Calculation of the integral % $$int_{-l}~l |x| '’{-frac{l}{100}}dx = frac{200}{99}5$ %% First step. Introduce integrand. run - inline(’abs(x). A-0.011); %% Second step. Direct integration using |quadi| I = quadi(fun, -1, 1) %% % *It is not very good idea!* %% Just look at integrand fplot(fun, [-1 1]) %% Splitting % $$int_{-l}Al |x|~{-frac{l}{100}}dx = $$ % $$ int_{-l}"0 (-x)л{-frac{1}{100}}dx + int_0-l x'{-frac{l}{100}}dx$$ % % First integral % $$ 1пЬ_{-1}л0 (-x) л{-Сгас{1}{100}}dx$$ fpiot(fun, [-1 0]) Il = quadi(fun, -1, 0) %% Second integral % $$ МпГ_0л1 x"{-frac{l}{100}}dx$$ fpiot(fun, [0 1]) 12 = quadi(fun, 0, 1) %% Result I = Il + 12 lex = 200/99 После создания и сохранения М-файла integral.m в редакторе М-файлов в меню File выберите пункт Publish to html. По завершении процесса создания отчета он открывается в окне браузера MATLAB. Отчет содержит оглавление, гиперссылки которого позволяют быстро перейти к нужному разделу. Все созданные файлы (документ в формате HTML и рисунки) размещены в подкаталоге html каталога, содержащего М-файл. Для опубликования отчета в других форматах следует в меню File редактора М-файлов перейти к подменю Publish to и задать желаемый формат выбором одного из его пунктов. Перечислим некоторые важные настройки процесса публикации, которые устанавливаются в диалоговом окне Preferences, появляющемся после выбо- 914 Часть У. Дополнительные возможности MATLAB ра в меню редактора File пунк га Preferences. В левой части окна перейдите к разделу Publishing. В правой час ги окна флаг Evaluate code юлжен быть установлен для автоматического выполнения ячеек М-фай ia при создании отчета, а за включение в отчет самих команд отвечает флаг Display code in output Для задания графического формата для экспорта графиков следует перейти к разделу Publishing images и выбрать желаемый формат в раскрывающемся списке Image file type. Описанная в этом разделе публикация отчета позволяет получить готовый документ в одном из широко распространенных форматов и внести в него необходимые дополнения по мере надобности. В следующем разделе мы рассмотрим другой способ— создание интерактивных документов MS Word (М-книг), которые не только содержат результаты работы, но и позволяют повторить их прямо из документа, открытого в MS Word. М-книги М-книги могут содержать как текст, таблицы, рисунки и другие элементы оформления документа MS Word, так и команды MATLAB ирезультаты их выполнения. Причем набираемые команды активизируются прямо из документа (М-книги) и результат помещается также в документ. Пользователь имеет возможность работать со средой MATLAB, сопровождая свои действия текстовыми комментариями, набором формул в редакторе Microsoft Equation, словом, оперируя всеми средствами MS Word. Получающиеся интерактивные документы могут, например, использоваться в качестве учебных пособий для изучения различных разделов математики, физики и других дисциплин или при составлении отчетов о решении задач в MATLAB. Настройка MATLAE и создание М-книги Перед началом работы над М-книгой необходимо произвести некоторые настройки MATLAB на конфигурацию и версию MS Word, установленного на компьютере. Действия, описанные ниже, производятся только один раз при создании первой М-книги. Продолжение работы над существующими М-кни! ами и разработка новых не требуют повторных настроек. Разумеется, при переустановке MS Word или MATLAB придется произвести процесс настройки сначала. Суть настройки состоит в том, что создается шаблон документа (М-книги) с необходимыми стилями форматирования и макросами. Создание М-книги в MS Word на основе этого шаблона приведет к встраиванию в интерфейс редактора MS Word средств для связи с МАТ1 АВ. Гпава 21 Свьзь MATLAB и MS Office 915 До начала настройки определите каталог, в который будет помещен шаблон для М-книги. В этот каталог следует поместить и копию шаблона normal.dot. Будем для определенности считать, что выполнена стандартная установка MS Office и создан каталог C:Program FilesMicrosoft Office Templates, где будем размещать файлы шаблонов (далее этот катало! именуется просто Templates). Для пакета MS Office 2000 или старше, установленного в ОС, базирующейся на сетевой платформе, файл шаблона normal.dot находится в каталоге поль-зова геля. C:Documents and SettingsnMfl_nonb30BaTeaaApplication Data в подкаталоге Шаблоны или Templates (в зависимости от локализации версии). Запустите MATLAB и наберите в командном окне notebook ('-setup'). Запрашивается номер версии MS Word, установленной на вашем компьютере. Выберите нужную цифру и следуйте появляющимся инструкциям. При правильной установке программного обеспечения выводится сообщение о том, что после нажатия на любую клавишу появится диалоговое окно для указания пути к шаблону normal.dot. В каталоге Templates появился файл m-book.dot, являющийся шаблоном для создания М-книг. Запустите MS Word и установите уровень безопасности, позволяющий подключать макросы. Для русифицированного пакета MS Office 2000 или старше соответствующее диалоговое окно открывается при выборе в меню Сервис пункта Параметры, в котором следует перейти к вкладке Безопасность. Имеется несколько способов, позволяющих начать работу над новой М-книгой. Команда notebook приводит к появлению в MS Word нового файла, основанного на шаблоне m-book.dot. Если MS Word не был открыт, то он запускается после выполнения данной команды. Аналогичный результат получается при создании нового файла при помощи пункта Создать меню Файл MS Word. В диалоговом окне Создание документа на вкладке Общие следует выбрать m-book.dot, установить переключатель документ на панели Создать и нажать ОК. В MS Word создалось меню Notebook, предназначенное для управления и редактирования интерактивной М-книги (рис. 21.1). Далее поясняется использование элементов этого меню. В меню Файл добавился пункт New M-book; кроме того, всплывающее меню приобрело дополнительные пункты (рис. 21.2). В список стилей включены стили, определенные в m-book.dot: Autolait, Calc, Error, input, NoGraph, Output. По умолчанию используется стиль Обычный. то зви .зо 916 Часть V. Дополнительные возможности MATLAB Рис. 21.1. Дополнительное меню Notebook в MS Word EvAiate Cells £ырсзать Evaluate Calc ’one t-fe Копировать Evaluate M-buok Purge Cutout Cells e Вставить А Шрифт... =f Абзац... liz Список... Гиперссыл»a Chhuhmmli ► Рис. 21.2. Новый вид контекстного меню в MS Word гпава 21. Связь MATLAB и MS Office 917 Вне зависимости от локализации версии MS Word, все элементы, добавляемые при подключении шаблона m-book.dot, имеют англоязычные названия. Наберите в документе какую-нибудь команду MATLAB, к примеру f = sin(3/4*pi)*ехр(-1) Поместите курсор в набранную строку и выберите в меню Notebook пункт Define Input Cell. Обратите внимание, что стиль набранного текста изменился на Input, сам текст заключен в квадратные скобки, а цвет шрифта изменился на зеленый: f = sin(3/4*pi)*ехр(-1) Образовалась так называемая ячейка ввода (Input Cell). Для выполнения команды MATLAB, содержащейся в ячейке ввода, следует убедиться, что данная ячейка является текущей, т. е. в ней находится курсор, и выбрать в меню Notebook пункт Evaluate Cell. Ниже ячейки ввода в документе появляется ячейка вывода с результатом в привычном для пользователя MATLAB виде f = 0.2601 Абзацы ячейки вывода имеют стиль Output, начало и конец ячейки ограничены квадратными скобками, а цвет шрифта синий. Группировка ячеек Решение задачи линейной оптимизации о составлении рациона, описанное в главе 16, может быть наглядно продемонстрировано в М-книге. Сначала следует привести условие задачи и вспомогательную таблицу, а затем набрать операторы файл-программы ration (см. листинг 16.1) в тексте документа. Каждый оператор следует заключить в ячейку ввода, выбирая в меню Notebook пункт Define Input Cell либо используя комбинацию клавиш <Alt>+<D>. Содержимое М-книги должно соответствовать листингу 21.2. Листинг 21.2. Задание ячеек ввода А = [4 6 15 2 2 0 5 3 4 7 3 121,- А = -А; 918 Часть V. Дополнительные возможности MATLAB Ь = [250; 60; 100; 220]; Ь = —Ь; f = [44; 35; 100]; 1Ь =[0; 0; 0]; х - linprog(f, A, b, [ ], [ ], lb, [ ]) Несколько команд, выполняемых последовательно, лучше заключить в группу ячеек ввода (Cell Group). Выделите ячейки, подлежащие объединению в группу (в данном случае это все ячейки листинга 21.2) и в меню Notebook выберите пункт Group Cells. Команды образовавшейся группы выполняются из пункта Evaluate Cell меню Notebook или Evaluate Cells всплывающего меню. Сочетание клавиш <Alt>+<Enter> также приводит к активизации команд группы. В результате содержимое М-книги дополняется ячейкой вывода с решением задачи линейного программирования (листинг 21.3). Г............. Листинг 21.3. Группе звода ячеек и результат ее выполнения А = [4 6 15 2 2 0 5 3 4 7 3 12] ; А = -А; b = [250; 60; 100; 220]; Ь = -Ь; f = [44; 35; 100]; lb =[0; 0; 0] ; х = linprog(f, A, b, [ ], [ ]. lb, [ ]) Optimization terminated, x - 13.2143 16.7857 6.4286 Создание группы ячеек имеет ряд особенностей. Группа не должна содержать текст и другие объекты MS Word или ячейки вывода. Текст, разделяющий ячейки перед их объединением, помещается после группы. Ячейки вывода прогадают, но зато соответствующие им ячейки ввода добавляются в группу. Продолжите работу над М-книгой, создайте группу ячеек ввода с командами. обеспечивающими отображение круговой диаграммы полученного ре Гпава 21. Связь MATLAB и MS Office 919 шения, и выполните ее (листинг21.4). Соответствующая ячейка вывода содержит область графического окна с диаграммой (рис. 21.3). Важно понимать, что рисунок в ячейке вывода, заключенной в большие квадратные скобки, является объектом MS Word. Данное обстоятельство позволяет обращаться с ним, как с обычным рисунком, внедряемым в документ. .......... • *4“........................................ , Листинг 21.4. Использование гоафических команд MATLAB .... . - i . -........ ....... ' > i i. ..... № . - ... . ....... ... ._ а. . а ... а I pie3(х) нт = title('Пропорции продуктов в смеси'); set(НТ, 'Fontsize’, 16) [здесь размещается рис. 21,3] Рис. 21.3. Рисунок в ячейке вывода листинга 22.4, являющийся объектом MS Word М-книга может содержать сколь угодно много групп ячеек ввода и отвечающих им ячеек вывода. Ячейки вывода можно перемещать в произвольное место документа, выделив их и перетащив при помощи мыши как обычные абзацы документа MS Word. Повторное выполнение команд, находящихся в соответствующих ячейках ввода, не нарушит расположения ячеек. Работа с М-книгой большого объема становится проще, если предусмотреть разбиение ее на разделы (Calc Zone). Выделенный фрагмент книги выносится в отдельный раздел выбором пункта Define Calc Zone меню Notebook. Выполнение команд всех ячеек или групп ячеек ввода раздела производится при помощи пункта Evaluate Calc Zone, а сразу всей М-книги — Evaluate М- Л>0 Часть V. Дополнительные возможности MATLAB Book. Ошибка в командах ячеек ввода, возникающая в процессе выполнения всей М-книги, приводит к останову вычислений. Для автоматического перехода к выполнению следующей ячейки необходимо установить флаг Stop evaluating on error в диалоговом окне Notebook Options (рис. 21.4), появляющемся при выборе одноименного пункта в меню Notebook. Переменные различных разделов являются общими, к примеру, если в ячейке одного раздела переменной х было присвоено некоторое значение, то х можно использовать и в остальных разделах. Все переменные М-книги — глобальные. Более того, если в редакторе MS Word открыто несколько М-книг, то их переменные определены в одной рабочей среде. Открытие М-книги в MS Word не приводит к автоматическому выполнению содержимого ячеек ввода. Часто требуется инициализировать некоторые переменные без вмешательства пользователя. Команды ячеек, имеющих стиль Autolnit, запускаются сразу после открытия М-книги. Полезно включить в первую такую ячейку команду clear для очистки рабочей среды. Для установки стиля Autolnit служит пункт Define Autoinit Cell меню Notebook. Содержимое ячейки или группы можно выполнить циклически, для чего следует выделить нужные ячейки или сделать текущей группу и выбрать в меню Nutebook пункт Evaluate Loop, или нажать <Alt>+<L>. Появившееся диалоговое окно Evaluate 1 гор позволяет установить число повторов в поле Stop After и выбрать скорость кнопками Slower и Faster. Управление М-книгой Разработчик М-книги имеет возможность изменять вид ячеек вывода как с текстовой, так и графической информацией. Меню Notebook содержит пункт Notebook Options, выбор которого приводит к появлению одноименного диалогового окна, изображенного на рис. 21.4. Панель Numeric Format содержит раскрывающийся список для выбора формата и переключатели Loose и Compact для добавления промежуточных пустых строк при отображении числовых значений в ячейках вывода. Панель Figure Options предназначена для управления видом графических результатов, помещаемых в ячейки вывода. Установленный флаг Embed Figures in M-book обеспечивает размещение графиков в ячейках вывода, а сброшенный — приводит к визуализации результатов в отдельных графических окнах. Размер и единицы измерения графиков, помещаемых в ячейки ввода, определяются в строках Width и Height и раскрывающемся списке Units. Ячейки вывода с окончательными результатами преобразовываются в текст выбором пункта Undefine Cells меню Notebook. Пользователь может переопределить стили шаблона m-book.dot так же, как и любого другого стиля, Гпава 21. Связь MATLAB и MS Office 921 выбрав в меню Форма! пункт Стили и форматирование и произведя нужные установки в появившемся диалоговом окне. Рис. 21.4 Диалоговое окно Notebook Options Квадратные скобки, ограничивающие ячейки и группы ячеек, пропадают яри выборе пункта Hide Cell Markers меню Notebook. Пункт Show Cell Markers служит для отображения скобок в документе. При леиати М-книги скобки не выводятся. Совместная работа в MATLAB и MS Excel Интегрирование MATLAB и MS Excel расширяет возможности электронных таблиц благодаря доступу к многочисленным функциям MATLAB для обработ ки данных, различных вычислений и визуализации результата. Надстройка excllink.xla реализует совместную работу в MATLAB и MS Excel. Для связи с MS Excel в MATLAB определен ряд специальных функций. 922 Часть V. Дополнительные возможности MATLAB В состав MATLAB может входить также MATLAB Builder for MS Excel, который позволяет создавать COM-объекты дтя использования их в MS Excel, однако в следующих разделах мы о.’раничимся только обзором MS Excel Link. Конфигурирование MS Excel Перед тем как настраивать MS Excel на совместную работу с MATLAB, следует убедиться, что MS Excel Link входит в установленную версию MATLAB. В подкаталоге exlink основного каталога MATLAB или подкаталога toolbox должен находиться файл с надстройкой excllink.xla. Запустите MS Excel и в меню Сервис выберите пункт Надстройки Открывается диалоговое окно (рис, 21.5), содержащее информацию о доступных в данный момент надстройках. Рис. 21.5. Диалоговое окно MS Excel Надстройки Используя кнопку Обзор укажите путь к файлу excllink.xla. В списке надстроек диалогового окна появилась строка MS Excel Link 2.2 for use with Глава 21. Связь MATLAB и MS Office 923 MATLAB с установленным флагом. Нажмите ОК, требуемая надстройка добавлена в MS Excel, Обратите внимание, что в MS Excel присутствует панель инструментов MS Excel Link, содержащая кнопки: startmatlab, putmatrix, getmatrix, evalstring. Данные кнопки реализуют основные действия, требуемые для осуществления взаимосвязи между MS Excel и MATLAB — обмен матричными данными и выполнение команд MATLAB из среды MS Excel. При повторных запусках MS Excel надстройка excllink.xla подключается автоматически. Избежать подключения надстройки можно сбросом соответствующего флага в диалоговом окне Надстройки. Обмен данными между MATLAB и MS Excel Запустите MS Excel, проверьте, что проделаны все необходимые настройки так, как описано в предыдущем разделе. Введите в ячейки с А1 по СЗ матрицу (рис. 21.6), для отделения десятичных знаков используйте запятую в соответствии с требованиями MS Excel. _A_j в i С 1 5.5 1.6 -0.8 2 2.3 6.1 0.2 3 0.1 0.4 3,9 Рис. 21.6. Ввод матрицы в ячейки Выделите на листе данные ячейки и нажмите кнопку putmatrix, появляе гея диалоговое окно MS Excel со строкой ввода, предназначенной для определения имени переменной рабочей среды MATLAB, в которую следует экспортировать данные из выделенных ячеек MS Excel. Введите, к примеру, М и закройте окно при помощи кнопки ОК Перейдите к командному окну MATLAB и убедитесь, что в рабочей среде создалась переменная м, содержащая массив три на три: » м м = 5.5000 1.6000 -0.В000 2.3000 6.1000 0.2000 0.1000 0.4000 3.9000 Проделайте некоторые операции в MATLAB с матрицей М, например, обратите ее: » IM = inv(M); 924 Часть V. Дополнительные возможности MATLAB Примечание j Вызов inv для обращения матрицы, как и любой другой команды MATLAB, можно осуществить прямо из MS Excel. Нажатие на кнопку evalstring, расположенную на панели MS Excel Link, приводит к появлению диалогового окна, в строке ввода которого следует набрать команду MATLAB in = inv(M). Результат аналогичен полученному при выполнении команды в среде MATLAB. Вернитесь в MS Excel, сделайте текущей ячейку А5 и нажмите кнопку getmatrix. Появляется диалоговое окно со строкой ввода, в которой требуется ввести имя переменной, импортируемой в MS Excel. В данном случае такой переменной является im. Нажмите ОК, в ячейки с А5 по С7 заносятся элементы обратной матрицы. MATLAB производит вычисления с двойной точностью. Если требуется отобразить в MS Excel все значащие цифры, то выделите нужные ячейки и перейдите в меню Формат к пункту Ячейки. В открывшемся диалоговом окне Формат ячеек выберите Числовой в списке Формат ячеек и установите 15 в строке ввода Число десятичных знаков. Итак, для экспорта матрицы в MATLAB следует выделить подходящие ячейки листа MS Excel, а для импорта достаточно указать одну ячейку, которая будет являться верхним левым элементом импортируемого массива. Остальные элементы запишутся в ячейки листа согласно размерам массива, переписывая содержащиеся в них данные, поэтому следует соблюдать осторожность при импорте массивов. Вышеописанный подход является самым простым способом обмена информацией между приложениями — исходные данные содержатся в MS Excel, затем экспортируются в MATLAB, обрабатываются там некоторым образом, и результат импортируется в MS Excel. Пользователь переносит данные при помощи кнопок панели инструментов MS Excel Link. Информация может быть представлена в виде матрицы, т. е. прямоугольной или квадратной области рабочего листа. Ячейки, расположенные в строку или столбец, экспортируются, соответственно, в вектор-строки и вектор-столбцы MATLAB. Аналогично происходит и импорт вектор-строк и вектор-столбцов в MS Excel. Наряду с числовыми массивами, объектами, подлежащими обмену между MATLAB и MS Excel, могут быть текстовые данные. Введите в ячейки некоторый текст (рис. 21 7). Выделите ячейки с Al по С4 и экспортируйте данные в переменную mounth рабочей среды MATLAB при помощи кнопки putmatrix. Выясните тип переменной mounth, используя команду whos: » whos mounth Name Size Bytes Class Гпава 21. Связь МА TLAB и MS Office 925 mcunth 4x3 1252 cell array Grand total is 86 elements using 1252 bytes А . в ! c_ 1 January February March 2 April May June 3 July August September 4 October November December Рис. 21.7. Ввод в ячейки текстовой информации Оказывается, текстовая информация из ячеек MS Excel записывается в массив ячеек (cell array) MATLAB. Экспорт в MATLAB текста только одной ячейки рабочего листа MS Excel приводит к помещению ее содержимого в символьный массив типа char array (работа с символьными массивами и массивами ячеек подробно описана в главе 8). Импорт массива ячеек в MS Excel приводит к заполнению прямоугольной области на рабочем листе, размеры которой совпадают с размерами импортируемого массива. Символьный массив импортируется в одну ячейку листа MS Excel. Обмен данными между приложениями может быть осуществлен не только при помощи кнопок панели инструментов MS Excel Link, но и с использованием функций, определенных в надстройке MS Excel Link. Обращение к основным функциям MS Excel Link Всего в MS Excel Link определено тринадцать функций, распадающихся на две категории: функции для обмена данными между MATLAB и MS Excel и функции, предназначенные для установления связи между приложениями. Данные функции могут вызываться как из ячеек рабочего листа книги MS Excel, так и из приложений на Visual Basic. При обращении к функциям MS Excel Link из ячеек рабочего листа используется функциональная форма, т. е. аргументы заключаются в круглые скобки. Вызов функций из приложений на Visual Basic требует командной формы записи, в которой аргументы задаются через пробел после имени функции. Для начала работы необходимы три основные функции, которые фактически дублируются кнопками панели инструментов MS Excel Link. Функция MLPutMatrix служит для помещения данных из ячеек листа MS Excel в массив рабочей среды MATLAB. Первым входным аргументом 926 Часть V Дополнительные возможности MATLAB MLPutMatrix является имя переменной, заключенное в кавычки, а вторым — пределы области ячеек. Обратную операцию производит функция MLGetMatrix, в первом аргументе которой указывается имя переменной рабочей среды MATLAB с данными, а во втором— пределы области ячеек рабочего листа. Обращение из MS Excel к командам MATLAB производится при помощи функции MLEvalstring. Команды, подлежащие выполнению, задаются в единственном входном аргументе MLEvalstring, который заключается в кавычки Возможно указание строки с несколькими командами, разделенными точкой с запятой, но все равно в кавычки берегся вся строка, а не отдельные команды. ВХОДНОЙ аргумент у MLEvalstring только один. Наберите в ячейках квадратную матрицу (рис. 21.6), затем поместите в ячейку Е2 вызов функции =MLPutMatrix ("м"; А1:СЗ). Обращение к функции из ячейки рабочего листа начинается со знака "равно". Нажатие на <Enter> для завершения ввода в ячейку приводит к выполнению ее содержимого. В данном случае происходит считывание содержимого области ячеек с А1 по СЗ в числовой массив м. Занесите в ячейку Е4 вызов -MLEvalstring("IM = inv(M)"). После выхода из Е4 MATI АВ обращает матрицу м и записывает результат в хм. Вызовите из ячейки Е6 функцию =MLGetMatrix("хм"; "А5:С7"), импортирующую обратную матрицу в ячейки MS Excel с А5 по СТ. Вид рабочего листа приведен на рис. 21.8, в ячейках с формулами отображаются нули, содержимое каждой из трех ячеек указано на рисунке отдельно. Е2 ▼J 1 =MLPutMalrixfM";A1C3) А в 1 С | 0 Е | F 1 5,5 1.6 -OJB _=MLPutMatrix ("М”; А1 :СЗ) 2 2.3 6.1 0.2 ок— 3 0.1 0.4 3.9 1 А о-< =MLEvalString("IM=inv(M)"] £ 0,204684 •0,056631 0.044891 6 -0.077284 0,185865 -0Д25380 0-Ч—- _ 7 0.002676 -0,017611 0,257862 =MLGetMatrix("IM”;"A5:C7") Рис. 21.8. Содержимое рабочс-i о листа Пользователи, имеющие опыт программирования на Visual Basic, могут использовать функции MS Excel Link в своих программах. Листинг 21.5 содержит текст модуля с процедурой Myinv, выполняющей те же действия, что и последовательный вызов из ячеек рабочего листа трех функций MLPutMatrix, MLEvalstring И MLGetMatrix. При написании Данной процедуры в среде Microsoft Visual Basic следует установить ссылку на excllink.xla при помощи пункта Ссылки меню Сервис Гпава 21. Связь MATLAB и MS Office 927 Листинг 21.5. Процедура MyJnv Function МуInv(Mrange, IMrange) MLPutMatrix "M", Mrange MLEvalString "IM = inv(M)" MLGetMatrix "IM" , IMrange End Function Вызов процедуры Myinv производится из свободной ячейки рабочег о листа И ВЫГЛЯДИТ следующим образом: =MyInv(Al:C3; "А5:С7"). Функции MS Excel Link могут оперировать с различным заданием области ячеек, в том числе и по имени. Подробные сведения содержатся в справочной системе MS Excel в разд. Справочник по Visual Basic. Несколько примеров, касающихся интегрирования MATLAB и MS Excel, включены в книгу ExliSamp.xls, которая находится в том же подкаталоге MATLAB, что и надстройка excllink.xla. Функции MS Excel Link Как мы упоминали выше, имеется две группы функций MS Excel Link: функции для обмена данными между MATLAB и MS Excel и функции для связи между приложениями. В MS Excel Link определено девять функций, обеспечивающих экспорт и импорт данных при совместной работе в MATLAB и MS Excel. Три из них: MLPutMatrix, MLEvalString и MLGetMatrix описаны в предыдущем разделе. Функция matiabfcn вычисляет указанную в ней функцию MATLAB от массива данных, заданного диапазоном ячеек. Результат возвращается в ячейку, содержащую вызов matiabfcn. Если результат— массив, то следует прибегнуть к функции matlabsub, которая позволяет задать диапазон ячеек для вывода. Эти функции используются только в ячейках рабочего листа. Функция MLAppendMatrix так же, как и MLPutMatrix, предназначена для экспорта данных в MATLAB. Основное отличие состоит в том, что в случае экспорта данных из ячеек в массив, существующий в рабочей среде, функция MLAppendMatrix пытается добавить данные к содержимому массива. Способ занесения данных требует совпадения числа строк или столбцов в массиве и области ячеек. В случае неоднозначности, т. е. когда содержимое ячеек может быть добавлено как строки, так и столбцы, создаются новые строки. Если же размеры области ячеек не соответствуют массиву, то MLAppendMatrix возвращает ошибку. Во внимание принимается также тип данных 328 Часть V. Дополнитель возможности MATLAB Удаление массива рабочей среды MATLAB производится при помощи функции MLDeleteMatrix, входным аргументом которой является имя массива. заключенное в кавычки. В случае отсутствия массива ь рабочей среде выдается сообщение. При программировании на Visual Basic (VBA) оказывается полезной функция MLPutVar, которая предназначена для экспорта значения переменной из процедуры на VBA в рабочую среду MATLAB. Первым аргументом MLPutVar является имя переменной MATLAB, а вторым — имя переменной в процедуре на VBA. Импорт данных из рабочей среды в переменную процедуры осуществляет функция MLGetvar. Порядок аргументов MLGetVar такой же, как и у MLPutVar. Очевидно, что две эти функции используются только при программировании на VBA. Четыре функции: matlabinit, MLAutoStart, MLClose, MLOpen, обеспечивающие согласованную работу MATLAB и MS Excel, образуют вторую группу функций MS Excel Link. Функция matlabinit служит для инициализации MS Excel Link и запуска MATLAB. Для запуска только MATLAB следует обратиться к MLOpen. Функция MLAutoStart позволяет задать или отменить автоматический запуск MATLAB при открытии MS Excel. Для закрытия MATLAB вызывается MLClose. 'лава 22 Модернизация приложений с GUI версии 5.3 В этой глаье описан процесс перевода приложения с графическим интерфейсом пользователя, которое было создано в среде GUIDE MATLAB 5.3, в формат, принятый в новых версиях MATLAB, включая и версию 7. Переход на новую версию MATLAB требует некоторой переработки старых приложений с графическим интерфейсом пользователя для того, чтобы их можно было использовать в последующих версиях. Приложение с графическим интерфейсом в версии 5.3 содержится в двух файлах с расширениями m и mat. Обработка событий может быть запрограммирована в файл-функции в отдельном М-файле, создаваемом программистом. Начиная с версии 6 0 в MATLAB принят другой формат хранения — с приложением связаны файлы с расширениями fig и т, причем М-файл создается автоматически в среде GUIDE и содержит файл-функцию с подфункциями. Заголовки нужных подфункций генерируются при описании событий элементов управления. Данная глава посвящена описанию способа модернизации приложений с GUI, написанных в MATLAB 5.3, позволяющего работать с ними в более новой версии МАП АВ. Пример приложения для MATL AB 5.3 Данный раздел содержит пример простого приложения myplot с GUI, созданного в среде GUIDE версии 5.3. Приложение myplot хранится в файлах myplot.mat и myplot.m. Окно запушенного приложения приведено на рис. 22.1. Пользователь определяет в строке ввода функцию переменной х в соответствии с правилами MATLAB, нажимает кнопку Построить график и получает график функции на отрезке [О,1]. Кнопка Очистить оси позволяет убрать линию ’’рафика. Приложение myplot достаточно простое, оно предназначе 930 Часть V. Дополнительные возможности MATLAB но для демонстрации способа модернизации приложений с графическим интерфейсом, написанных в MA'ILAB 5.3, для более новых версий. С приложением связана файл-функция myplotprog, в которой запрограммирована обработка событий callback элементов управления: нажатне на кнопки и завершение ввода в строку при помощи <Enter>. Текст файл-функции myplotprog содержится в листинге 22.1. Имена объектов окна приложения и вызовы myplotprog при возникновении событий Callback данных объектов приведены в табл. 22.1. Рис. 22.1. Окно приложения myplot Таблица 22.1. Имена объектов приложение myplot Объект Имя Событие Callback Строка ввода FunEdt myplotprog(1SetFun') Кнопка 1 встроить график PlotBtn myplotprog(1 Pressplot') Кнопка Очистить оси ClearBtn myplotprog('PressClear1} Гпава 22. Модернизация приложений с GUI версии 5.3 931 function myplotprog(event) global FunStr switch event case 1SetFun' % Поиск указателя на строку ввода и занесение его в HFunEdt HFunEdt = findobj('Tag', 'FunEdt'); % занесение в глобальную переменную FunStr содержимого строки ввода FunStr = get(HFunEdt, 'String'); case ’PressPlot1 % Задание вектора аргументов для построения графика х = 0:0.01:1; % Конструирование и выполнение строки для вычисления вектора значений % аргумента eval([’y=‘ FunStr ';']) plot(x, у, 'LineWidth', 3, 'Color', 'k') % Построение графика case 'PressClear1 cla % очистка осей end Сведения, изложенные в следующем разделе, предполагают понимание принципов конструирования приложений с графическим интерфейсом пользователя как в версии 5.3, так и в следующих. Обратитесь при необходимости к соответствующим разделам книги, посвященным дескрипторной графике и созданию приложений в MATLAB (использование дескрипторной графики описано в главе 9. часть III книги освещает вопросы написания приложений с GUI). Модернизация приложения Приложение версии 5.3 с графическим интерфейсом пользователя, как правило, содержится в файлах с расширением mat и т. Пример такого приложения myplot приведен в предыдущем разделе. Данный раздел описывает основные этапы перевода файлов приложения в формаз ы FIG и М, свойственные более новым версиям MATLAB, и изменения связанной с приложением файл-функции обработки событий. Приложение приводится к такому виду, который обеспечивает дальнейшую работу над ним в среде GUIDE более новых версий MATLAB без каких-либо особенностей. Процесс мо 932 Часть К Дополнительные возможности I1ATLAB дернизации не требует установленной версии 5.3, необходимо иметь только файлы приложения. Всюду дальше под MATLAB мы будем понимать версию старше 5.3. Сохранение приложения в формате FIG Сохраните файлы mypiot.m, mypiot.mat и myplotprog.m в текущем каталоге MATLAB и запустите приложение, набрав mypiot в командной строке MATLAB. Появляется окно приложения, причем оно функционирует так же, как и в версии 5.3. Пользователь может задавать формулы в строке ввода и отображать графики функций. Следующий этап состоит в получении указателя на окно приложения mypiot. Убедитесь, что кроме окна приложения больше нет открытых графических окон Свойство HandieVxsibility окна mypiot может быть установлено в off, что воспрепятствует нахождению требуемого указателя. Поэтому сначала следует указать MATLAB, что все указатели на объекты должны быть доступны. Данная установка производится выбором значения on свойства showHiddenHandles объекта Root. Указатель на объект Root равен нулю. Используйте функцию set для требуемого изменения значения: » set(0, 'ShowHiddenHan Hrs", 'on1) Теперь все указатели доступны. В данный момент открыто только одно графическое окно приложения, которое является потомком Root (иерархия объектов и их свойства описаны в главе 9). Свойство Children объекта Root содержит указатели на открытые графические окна. Примените функцию get, возвращающую значение свойства объекта: » h - get(0, 1 Children') Переменная ь содержит значение указателя на окно приложения. Укажите h во входном аргументе guide для перехода к визуальной среде GUIDE. Команда » guide(h) приводит к появлению среды GUIDE, в которой уже открыто mypiot. < )бра-тите внимание, что приложение mypiot осталось запущенным, поскольку открыто его графическое окно. Данное окно следует закрыть и продолжить работу в среде GUIDE. Выберите в меню File среды GUIDE пункт Save as, появляется диалоговое окно Save Figure As, в котором следует указать имя файла myplot.fig. Можно сохранить приложение и под другим именем, но тогда для его запуска придется набирать в командной строке уже не mypiot, а новое имя. Прежние Глава 22 Модернизация приложений с GUI версии 5.3 933 имена приложений облегчат работу, особенно, если модернизации подлежит несколько часто используемых ранее приложений. Закройте среду Gl [IDE и перейдите к изучению содержимого текущего каталога. В текущем каталоге MATLAB появился файл mvplot.fig. Наберите в командной строке myplot и убедитесь, что приложение работает так же, как и в старой версии. Запуск приложения обеспечивается наличием файла myplot.m, в котором записана файл-функция myplot, обеспечивающая инициализацию приложения при запуске. Часть текста файл-функции myplot приведена в листинге 22.2. Обратите внимание, что первым оператором является загрузка файла myplol mat при помощи load. Отсутствие расширения файла в load приводит к загрузке именно двоичного mat-файла. После команды load следуют вызовы функций, создающих объекты с заданными свойствами: графическое окно (функция figure), оси (функция axes) и т. д. Листинг 22.2. Содержимое файла myplotm (файл-функция myplot) function fig = myplot() load myplot % загрузка файла myplot.mat % Создание объектов hO = figure('Color', [0.8 0.S 0.8], ... 'Colormap', matO, ... •FileName', 'C:MATIJiBRllworkGtn53to60rnyplot.m', ... 'KenuBar', ’none', ... 'Name', 'myplot', ... 'NumberTitle', 'off, ... 'PaperPosition', [18 180 576 432], ... 1 Paperunits', 'points', ... 'Position', [446 284 560 420], ... 'Tag', 'Figi', ... 'ToolBar', 'none'); В„жно понимать, что запуск приложения командой myplot не требует наличия файла myplot.fig. На самом деле работает старая комбинация файлов с расширениями mat и гл. Запустить файл myplot.fig можно с использованием open: » open('myplot.fig') Обработка событий происходит в файл-функции, хранящейся в myplotprog.m, т. к. myplot.fig содержит соответ стзующие обращения к файл-функции myplotprog. Такой способ работы с приложениями не очень удо 934 Часть V. Дополнительные возможности /WATLAB бен. Следующий раздел описывает модернизацию приложения для версии 5.3. которая направлена на полный отказ от файлов старой версии и переход к форматам FIG и М. Переход к форматам FIG и М Приложение с графическим интерфейсом пользователя представляется в MATLAB либо комбинацией файлов с расширениями fig и гл, либо только fig. М-файл содержит файл-функцию, инициализирующую приложение и подфункции обработки событий элементов интерфейса. Программирование событий удобнее производить, если с приложением ассоциирован М-файл. Сделайте доступными указатели на объекты так, как описано в предыдущем разделе, использовав set(O, 'ShowHiddenHandles’, ’on’). Запустите приложение myplot из командной строки (запускается файл myplot.m) и получите указатель на графическое окно приложения ь = get(O, ’Children’), предварительно закрыв все лишние окна. Откройте в среде GUIDE MATLAB приложение при помощи guide (h). Выберите в меню Tools среды GUIDE пункт GUI Options, появляется диалоговое окно GUI Options, позволяющее настроить приложение. Поставьте переключатель в положение Generate .fig and .in file, становятся доступными флаги в нижней части окна. Флаг Generate callback function prototypes должен быть включен для автоматической генерации подфункций обработки событий. В раскрывающемся списке Command-line accessibility следует установить Callback (GUI becomes Current Figure within Callbacks). Сохраните приложение с именем myplot.fig в среде GUIDE, выбрав в меню File пункт Save as. Если вы ранее осуществили действия, описанные в предыдущем разделе, то появится окно с предупреждением о том, что файл myplot.fig уже существует— перепишите его, нажав Yes. Далее снова появится окно с сообщением о существовании файла myplot.m. Предтьгается либо заменить старый файл на новый (кнопка Replace}, либо добавить к нему новый файл myplot m (кнопка Append). Прежний файл содержит файл-функцию myplot (см. листинг 22.2), инициализирующую приложение в стиле версии 5.3. Поскольку требуется полностью отказаться от формата версии 5.3, то следует выбрать Replace. Нажагие на Replace приводит к запуску редактора М-файлов, в котором открыт новый файл myplot.m, содержащий автоматически сгенерированную файл-функцию myplot. В среде GUIDE выделите щелчком мыши строку ввода и в контекстном меню, активизируемом правой кнопкой мыши, в пункте View Callbacks выберите подпункт Callback. Обратите внимание, что в файле myplot.m появилась подфункция FunEdt Caiiback обработки события oaiibaci строки ввода. Аналогичным образом последовательно создай Гпава 22. Модернизация приложений с GUI версии 5 3 935 те подфункции PlotBtn_Callback И ClearBtn_Callback, соответствующие кнопкам Пострпт ь график и Очистить оси. Разместите в теле каждой из этих подфункций обращение к mypiotprog с соответствующим входным аргументом. В результате файл mypiot.m должен иметь структуру, приведенную в листинге 22.3 (автоматически созданные комментарии не приводятся для экономии места). Запустите из среды GUIDE приложение и убедитесь, что оно работает правильно. Листинг 22.3. Содержимое сгенерированного файла mypiot с подфункциями • ".<< . , >•••••••••• ,ГЧ • Т’Ж» .. ••••««iiмини *•••••• function varargout - mypiot(varargin) gui_Singleton = 1; gui_State = struct(' gui.Name’, mfilename, ... ' gui_Singleton1, gui_Singleton, ... 'gui_OpeningFcn', @myplot_OpeningFcn, ... 'gui_OutputFcn’, @myplot_OutputFcn, ... 'gui_LayoutFcn’, [ ], ... ’gui_CalIback', [ ]); if nargin && ischar(varargin(l}) gui_State.gui_Callback = str2func(varargin{1}); end if nargout [varargout{l:nargout}] = guijnainfcn(gui_State, varargin{:}); else gui. mainfcn(gui_State, varargin{:}); end function mypiot.OpeningFcn(hObject, eventdata, handles, varargin) handles.output = hObject; guidata(hObj ect, handles); function varargout = nyplot_OutputFcn(hObject, eventdata, handles) varargout11} = handles.output; function FunEdt—CalIback(hObject, eventdata, handles) . mypiotprog(1SetFun') 936 Часть V. Дополнительные возможности MATlAB function PlotBtn.Callback(hobject, eventdata, handles) myplotprog('PressPlot1) function ClearBtn_Callback(hobject, eventdata, handles) myplotprog (' PressClear ’) Изучите три полученные подфункции обработки событий. Каждая подфункция содержит единственный оператор вызова файл-функции myplotprog с соответствующим входным аргументом. При возникновении события callback от любого из элементов управления происходит обращение К подфункции myplotprog, в которой выполняются команды одного из блоков case оператора switch. Последний этап модернизации приложения заключается в программировании подфункций обработки событий. Данные подфункции должны выполнять те же действия, что и блоки case в myplotprog, разумеется, с учетом принципов написания приложений в среде GUIDE MATLAB. Указатели на графические объекты содержатся в полях структуры handles, имена которых совпадают со значениями свойства Тад данных объектив. Обмен данными между подфункциями производится при помощи создания дополнительных полей в структуре handles. После занесения в поле handles нужного значения следует сохранить структуру, используя функцию guidata (пример использования структуры handles приведен в разд. "Переключатели " главы 1 ]). Подфункции обработки событий элементов интерфейса обновленного приложения myplot приведены в листинге 22.4. ..Ш’ММ».............................................................. Ё Листинг 22.4. Подфункции обработки событий обновленного приложения i myplot function FunEdt_Callback(hObject, eventdata, handles) % Образование нового поля FunStr структуры handles и занесение в него % содержимого строки ввода handles.FunStr = get(hobject, ’String'); % Сохранение обновленной структуры handles guidata(gcbo, handles) function PlotBtn_Callback(hobject, eventdata, handles) % Задание вектора аргументов для построения Iрафика х = 0:0.01:1; I лава 22 Модернизация приложений с GUI версии 5.3 937 % Конструирование и выполнение строки для вычисления вектора значений % аргумента eval([ ’ у =' handles.FunStr '; ' ]) % Построение графика plot{x, у, 'LineWidth', 3, 'Color', 'k') function ClearBtn_Callback(hObject, eventdata, handles) % очистка осей cla Запустите приложение myplot и проверьте его работу. Файлы myplot.mat и myplotprog.m, ассоциированные со старой версией приложения, больше не нужны, их можно удалить. Модернизированное приложение с графическим интерфейсом пользователя содержится в двух файлах myplot.fig и myplot.m. Глава 23 Повышение производительности приложений MATLAB Данная глава описывает основные принципы эффективной разработки приложений в MATLAB, которые позволяют снижать время счета и экономить память. На достаточно простом уровне объяснено использование программного интерфейса MATLAB API для вызова внешних процедур, написанных на других языках программирования. Ускорение работы М-файлов, экономия памяти MATLAB интерпретирует команды, записанные в М-файлах, в машинный код и последовательно выполняет их. Процесс интерпретации занимает много времени в том случае, когда алгоритм обработки большого объема данных содержит циклы, поскольку каждая строка цикла интерпретируется столько раз, сколько выполняется цикл. Следовательно, при разработке приложений MATLAB необходимо свести использование циклов к минимуму. Эффективность приложений также определяется распределением памяти под создаваемые большие массивы. Поэлементные операции Достаточно часто требуется произвести преобразование элементов массива, к примеру, разделить все элементы одной матрицы на соответствующие элементы другой. Данную операцию можно осуществить двумя способами: перебразь все элементы матрицы во вложенных циклах for и поделить на соответствующие значения, либо использовать операцию поэлементного деления. Первый вариант реализован в файл-программе testl (лис Глава 23. Повышение производительности приложений MATLAB 939 тинг 23.1), а второй — в файл-программе test2 (листинг 23.2). Для примера выбраны квадратные матрицы див одинаковых размеров, заполняемые при помощи функции ones, требуется записать результат в матрицу А, т. е. A(i, j) = A(i, j)/B(i, j). Пистмнг 23Л Файл-программа testl (перебор и цикле) i,. .. ...J... . .**.. J и- -.маЛк A = ones(400); В - 5*ones(400); for i = 1:400 for j = 1:400 A(i, j) = A(i, j)/B(i, j); end end J • ’ • : СЛЛ»a•«*.*.«-* II.WVWU < Листинг 23.2. Файл-программа test2 (использование поэлементных операций) А = ones(400); В = 5*ones(400); А = А./В; Сравните время, затрачиваемое на работу testl и test?. Можно воспользоваться, например, профайлером для получения детальной информации о работе файл-программ (ель разд. "Профайлер"главы 16). В рассматриваемых примерах требуется определить только время работы каждого из М-файлов testl.m и test2.m, поэтому проще применить последовательность команд tic и toe, которая предназначена для установления временных затрат на выполнение М-файла или нескольких коротких команд Определите время вычисления по первому и второму способам: >> tic. testl, toe elapsed_time = 3.2500 » tic, test2, toe elapsed_time = 0.0940 Обратите внимание, что поэлементные операции уменьшают временные затраты в десятки и сотни раз! 940 Ча^ть V. Дополнительные возможности MA^LAe I. Значения времени, полученные на различных компьютерах, могут не совпадать с приведенными в книге, но соотношение остается приблизительно тем же. 2. Функции tic и toe служат для определения реальною времени выполнения команд. Процессорное время возвращается функцией eputime, например: Tl = eputime; testl; Т2 = eputime - Tl. Следующая задача имеет менее очевидное решение. Предположим, что требуется преобразовать элементы матрицы по формулам: A(i, j) = A(i, j)/(i*j). Деление всех элементов матрицы А во вложенных циклах не представляет труда (листинг 23.3). Листинг 23.3, Файл-программа test3 (деление элементов во вложенных ................. .................. ........ ............. ...... А = ones(400); for i = 1:400 for j = 1:400 A(i, j) =A(i, j) / (i*j); end end Для применения поэлементных операций требуется сформировать квадратную матрицу того же размера, что и а, элементы которой являются произведением номера строки на номер столбца. Вспомогательная матрица и является внешним произведением подходящего столбца и строки (листинг 23.4). 1истинг23.4. Файл-программа tost4 (поэлементное деление на вспомогательную матрицу) .................. ....... А - ones (400) row = 1:400; М = row'*row; А = А./И; Сравнение временных затрат убеждает в эффективности способа, реализованного в файл-программе test4: » tic, test3, toe elapsed_time = 3.1410 Глава 23. Повышение прочзвсцительности приложений MATLAB 941 » tic, test4, toe elapsed_time = 0,0780 Заметьте, что после поэлементного деления массив м не нужен — его следует удалить из памяти. Основные приемы работы с памятью описаны в следующем разделе. Экономия памяти Один из самых очевидных способов экономии памяти заключается в удалении тех переменных, которые больше не понадобятся. Для этого существуют два способа. Во-первых, одна или несколько переменных выделяются в окне Workspace и удаляются при помощь <Delete> или одноименного пункта контекстного меню. Второй способ, пригодный в приложениях, состоит в использовании команды clear. Удаляемые переменные заносятся в список ее параметров, например: clear hipi tmp3. Если эти переменные были созданы в файл-программе или из командной строки, то они удаляются из основной среды MATLAB. Переменные файл-функции удаляются из среды файл-функции. Однако если они были объявлены как глобальные, то они останутся в памяти и будут доступны для остальных функций (работа с глобальными переменными описана в разд. "Подфункции'' главы 5). Для удаления глобальных переменных следует в качестве перво! о параметра clear указать global, например: clear global alpha beta. Команда clear может быть вызвана и в функциональной форме: clear (’ hlpi, ' tmp3 ’), что удобно, если имена удаляемых переменных хранятся в некоторых строковых переменных. Удаление переменных не всегда желательно. Возможно, что в одном блоке программы массив с вычисленными значениями не нужен, но он понадобится в другом ее блоке. Если этот массив занимает много памяти, то имеет смысл записать содержащиеся в нем данные на диск, удалить его из памяти и за!ружагь по мере надобности. Для этого служат команды save и load. При чтении главы 1 вы применяли их для сохранения значений сразу всех переменных рабочей среды, а при чтении главы 2 — для сохранения числовых данных в текстовом файле и считывания Обсудим возможности этих команд более подробно. Как save, так и load могут быть вызваны в командной и функциональной формах. Например: save filename АВИ save (filename, ’А', 'В'), где filename — имя файла, приводят к одинаковому результату- При функциональном способе вместо имени переменной в апострофах можно указывать строковую переменную, что иногда оказывается удобным. По умолчанию 942 Часть V. Дополнительные возможности MATLAB переменные сохраняются в двоичных файлах с расширением mat, которые занимают меньше места, чем текстовые, и записываются быстрее. Для того чтобы mat-файлы читались в версиях 6.x, следует в качестве последнего параметра save установить опцию -v6, например: save(1DataFile', ’A', '-v6'). Для записи значений переменных приложения можно использовать всего один файл. Если запись происходит в нескольких местах, т. е. значения добавляются в файл, то указывается опция -append, например: А = rand(100); save(‘DataFile', 'А') В = А.Л2; save('DataFile’, 'В1, ’-append1); clear('А', 'В') Для последующей загрузки переменных применяется lead, например, load (’ DataFile', ' А’) приводит к появлению массива а в рабочей среде. В приведенных примерах мы не указывали расширение файла данных — оно задавалось mat по умолчанию. Предположим, что переменные были записаны в файле с другим расширением, например, myvars.dat при помощи save('myvars.dat', ’А', 'в'). Тогда при считывании их значений необходимо принять во внимание следующее обстоятельство. Файл myvars.dat является двоичным, поскольку при сохранении не была задана опция -ascii. С другой стороны, load интерпретирует все файлы с расширением, отличным от mat, как текстовые. Поэтому обращение load('myvars.dat', 'а1, 1 в1) приведет к ошибке— вместо этого следует задать дополнительный параметр -mat: load('myvars.dat*, 'А', ‘В’, '-mat'). Увеличения доступной памяти можно добиться за счет процедуры, которую принято называть "сборкой мусора". Для этого следует воспользоваться командой pack, которая размещает переменные MATLAB в памяти оптимальным образом. Дело в том, что во время сеанса работы данные не упорядочиваются в памяти и это часто приводит к наличию свободных несмежных фрагментов, каждого из которых недостаточно для размещения большою массива. Команда pack записывает переменные во временный файл в текущем каталоге (по умолчанию в pack.tmp), полностью освобождает память рабочей среды и затем снова загружает переменные, так что становится доступной непрерывная область памяти. При такой организации памяти в MATLAB предпочтительнее вводить первыми самые большие массивы (см. пример в разделе справочной системы MATLAB: Programmine: < ггэда 23. Повышение производительности приложений MATLAB 943 Improving Performance and Memory Usage: Making Efficient Use of Memory: Working with Variables). Существенной экономии памяти и времени счета можно добиться при учете структуры данных. Например, матрицы с большим количеством нулевых элементов следует хранить в разреженном виде (работа с разреженными матрицами описана в главе 15). Не менее важно принимать во внимание и тип данных. Так, если данные содержат только целые значения, то имеет смысл использовать для их хранения целочисленные массивы подходящего типа (int8, dints, intl6, uintic, int32, uint32) в зависимости от макси мяльного и минимального значений данных. Числа 8, 16 или 32 в названии типа говорят о том, сколько бит занимает одна переменная данного типа. Допустимые значения переменных для каждого из типов приведены в справочной системе MATLAB (см., например, разд. MATLAB; Programming: Data Types: Numeric Types) Для инициализации подходящего массива данных можно применить следующее обращение к одной из функций ones, eye или zeros: » i8A = ones(1900, ’int8‘; » whos i8A Name Size Bytes Class i8A 1000x1000 1000000 int8 array Grand total is 1000000 elements using 1000000 bytes Дальнейшие операции с массивом чисел типа int8 сохраняют тип данных, что необходимо учитывать для избежания ошибок: » i8A( :, :) = 200; » whos i8A Маше Size Bytes Class i8A 1000x1000 1000000 int8 array Grand total is 1000000 elements using 1000000 bytes » i8A(l, 1) ans - 127 При работе с вещественными данными не всегда оправданно применение двойной точности, т. е. массивов типа double, которые используются по умолчанию. В ряде случаев для экономии памяти в два раза целесообразно ограничиться обычной точностью и преобразовать массив данных к типу single при помощи одноименной функции: >> dA = ones(1000); >> sA = single(dA); =М4 Часть V. Дополнительные гозмомности MATLAB » whos dA sA Name Size Bytes Class dA 1000x1000 8000000 double array sA 1000x1000 4000000 single array Grand total is 2000000 elements using 12000000 hytes Вместо преобразования массива данных к типу single можно было сразу начать работу с этим типом, инициализировав нулевой массив » sA = zeros(1000, 'single'); » SA(:, :) = 0.33; » sA = sA/2; » sA = sA.^2; » sA = sin(sA); » whos sA Name Size Bytes Class sA 1000x1000 4000000 single array Grand total is 1000000 elements using 4000000 bytes Предварительная инициализация массивов, которую мы только что рассмотрели, позволяет сократить время расчетов и уменьшает фрагментацию памяти по сравнению с динамическим выделением памяти под создаваемый массив. Выделение памяти под массивы Массивы среды МАП АВ не требуют предварительного объявления в отличие от многих других языков программирования, а размеры массива динамически изменяются по мере присвоения новым его элементам некоторых значений. К примеру, оператор присваивания, заполняющий матрицу а » А = [-3 4; 9 71; и последовательность команд, приведенная ниже, приводят к одинаковым матрицам айв (предполагается, что переменные А и в до этого не были инициализированы в рабочей среде). » В(1, 1) = —3; » В(1, 2) = 4; » В{2, 1) = 9; » В (2, 2) = 7; Гпава 23 Повышение производительности приложений MATLAB 945 Работа с небольшими массивами не приводит к заметному увеличению временных затрат, однако оперирование большими объемами данных делает существенной разницу между двумя перечисленными способами заполнения массивов. Составьте две файл-процедуры для заполнения квадратной матрицы размером 400. Элементы матрицы вычисляются во вложенных циклах по i и j по формуле 1/ (1л2 + jA2), причем в начале одной файл-процедуры создайте нулевую квадратную матрицу при помощи функции zeros (листинги 23.5 и 23.6). for i = 1:400 for j = 1:400 B(i, j) = l/(i''2 + j-2) ; end end A = zeros(400); for i = 1:400 for j = 1:400 A(i, j) = l/(i,'2 + ]л2); end end Теперь найдите затраты машинного времени на выполнение каждого из М-файлов: test5.m и test6.m. Учтите, что перед использованием tic и toe следует очистить рабочую среду MATLAB командой clear all, поскольку массив в мог быть создан ранее, а в этом случае под него уже была выделена память. » clear all » tic, test5, too elapsed_time - 7.8900 » tic, test6, toe elapsedtime - 3.4060 За счет предварительного выделения памяти под заполняемый массив достигнута существенная экономия времени более чем в два раза. Важно по- 946 Часть V. Дополнительные возможности MATLAB нимагь, что первый запуск tests приводит к последовательному отведению места в памяти под массив, а по завершении работы файл-программы весь массив находится в памяти. Следовательно, повторная работа tests (без очистки рабочей среды) займет столько же времени, сколько и teste: » tic, tests, toe elapsed_time - 3.4060 Анализ кода файл-програм.мы tests при помощи M-Lint сопровождается появлением того же самого совета по предварительной инициализации массива (запуск M-Lint описан в разд "Диагностика М-файлов" главы 5). Принципиально иной способ ускорения выполнения приложений MATLAB за счет вызова внешних процедур на других языках программирования описан в следующем разделе. Связь MATLAB с другими языками программирования Довольно часто встречается ситуация, когда имеются модули, написанные на С или Fortran, и требуется использовать их в приложении MATLAB Пакет MATLAB предоставляет возможность вызова внешних программ благодаря Application Program Interface (API), т. e. программному интерфейсу приложения. Функции MATLAB API делятся на две категории: функции, обеспечивающие создание и доступ к массивам MATLAB, и функции, позволяющие оперировать в рабочей среде MATLAB. Создание МЕХ-файлов из процедур Fortran заключается в написании интерфейсной процедуры с использованием функций MATLAB API и последующей генерации МЕХ-файла при помощи команды тех. В среде Windows МЕХ-файл является динамически подключаемой библиотекой и имеет расширение dlL Генерация МЕХ-файлов из процедур Fortran требует установки подходящего компилятора, например, одного из: Digital Visual Fortran или Compaq Visual Fortran. Встроенный компилятор Fortran не входит в пакет MATLAB в отличие от компилятора Lee для приложений на С. Пи сравнению с подходами по повышению эффективности приложений MATLAB, которые мы рассмотрели выше, МЕХ-файлы предоставляют принципиально другой способ повышения быстродействия программ. Он состоит в написании внешней процедуры на Fortran или С, создании МЕХ-файла и обращении к нему из среды и приложений MATLAB. Простой пример такой внешней процедуры рассмотрен в последнем разделе этой главы. Гпава 23. Повышение производительности приложений MATLAB 947 Конфигурирование MATLAB Compiler Перед компиляцией программ необходимо произвести некоторые установки, связанные с выбором компилятора. Если компилятор не выбран, то по умолчанию используется встроенный Lee для приложений на С. Приступим к конфигурированию MATLAB Compiler Наберите в командной строке >> тех -setup Предупреждение^ Некоторые антивирусные программы могут конфликтовать с процедурой конфигурирования или компиляцией. Если после набора команды тех вывелось сообщение об ошибке, то следует временно отключить антивирусную про] рамму. Запускается программа с интерфейсом из командной строки и предлагается ав соматический поиск всех компиляторов, имеющихся на компьютере. Please choose your compiler for building external interface (MEX) files: Would you like mex to locate installed compilers [y]/n? Введите у (подтверждение) на запрос об автоматическом поиске. Появляется список доступных компиляторов С и Fortran (который может отличаться от приведенного ниже): Select a compiler: [1] Compaq Visual Fortran version 6.1 in C:Program FilesVMicrosoft Visual Studio [2) Lee C version 2.4 in C:MATLAB7syslcc [3] Microsoft Visual C/C++ version 6.0 in C:Program FilesXMicrosoft Visual Studio [0] None Compiler: Поскольку далее мы разберем использование внешних процедур на Fortran, то следует ввести номер соответствующего компилятора (в данном случае первый) и нажать <Enter>. Далее предлагается подтвердить сделанный выбор: Please verify your choices: Compiler: Compaq Visual Fortran 6.1 Location: C:Program FilesMicrosoft Visual Studio Are these correct?({y]/n): Введите у и нажмите <Enter>. Конфигурирование MATLAB Compiler завершено. Перейдите к изучению некоторых примеров, разобранных в следующих разделах. 31 3ut 130 948 Часть V. Дополнительные возможности MATLA" Простой пример, сложение двух чисел Начните изучение создания МЕХ-файлов с самого простого примера. Предположим, что из среды MATLAB требуется вызвать процедуру sum, написанную на Fortran 90. Процедура sum складывает два вещественных числа а и ь и записывает результат в с (листинг 23.7). Будем считать, что процедура sum содержится в файле mysum.f90. Листинг 23.7. Исходная процедура вши на Fortran 90 {файл mysum.f90) subroutine sum(a, b, с) ! Процедура sum складывает два вещественных числа а и b ! и возвращает результат в с real*8 а, Ь, с с = а + b end Непосредственно вызвать процедуру sum из среды MATLAB, разумеется, не удастся. Необходимо написать интерфейсную процедуру на Fortran с использованием функций MATLAB API, которая будет точкой входа МЕХ-файла mysum.dll при вызове функции mysum из среды MATLAB. Интерфейсная процедура должна называться mexFunction и иметь четыре аргумента типа integer*4: 1. nrhs — число входных аргументов, с которыми будет происходить обращение к МЕХ-функции mysum из среды MATLAB. 2. prhs — массив указателей на входные аргументы mysum. 3. nibs — число выходных аргументов, с которыми будет происходить обращение к МЕХ-функиии mysum из среды MATLAB. 4. pihs — массив указателей на выходные аргументы mysum. Обмен данными между процедурой sum и средой MATLAB посредством интерфейсной процедуры mexFunction осуществляется только при помощи вышеперечисленных аргументов. Для выделения данных из prhs и занесения результата в pihs предназначены специальные функции MATLAB API. Интерфейсная для sum процедура mexFunction приведена в листинге 23.8, назовите файл с ней mysumg.f90. Итак, интерфейсная процедура имеет четыре параметра типа integer*4, два массива pihs, prls и два скаляра nihs, nrhs. В mexFunction использованы две функции MATLAB API; mxCreateDoubleMatrix И mxGetPr, возвращающие значения типа integer*4. Функция mxCreateDoubleMatrix выделяет память под массив и возвращает Гпава 23. Повышение производительности пс- пожений МА TLAB 949 указатель на массив. В рассматриваемом примере этот массив служит для возврата результата (суммы двух чисел) в рабочую среду MATLAB и будет иметь размеры один на один. Функция mxGetPr служит для получения указателя на первый вещественный элемент в массиве. Целочисленные переменные а_рг, ь_рг и с_рг понадобятся для хранения указателей на массивы, содержащие входные аргументы и выходной аргумент. Для записи значений аргументов определены вещественные переменные а, ь и с. Процедура mexFunction начинается с получения указателей на первые (а в данном случае и единственные) вещеет венные элементы массивов, на которые указывают первый и второй элементы prhs. Важно понимать, что массив prhs содержит указатели на массивы специального типа mxArray. Данный тип определен в MATLAB API и является единственно возможным способом обмена данными между средой MATLAB и процедурой на Fortran. Все данные MATLAB передаются при помощи mxArray, в зависимости от типа передаваемых данных следует применять соответствующие функции для извлечения указателей. Для извлечения указателей на вещественной массивы, содержащие значения входных аргументов МЕХ-функции, например, а_рг и Ь_рг, используется функция mxGetPr MATLAB API. Следующий шаг состоит в записи значений входных аргументов в вещественные переменные а и ь. Процедура MATLAB API, которая называется mxCopyPtrToReaie, заносит вещественные данные в массив, объявленный в процедуре Fortran. Первым входным аргументом mxCopyPtrToRealB является указатель, вторым— имя массива, а третьим— количество записываемых элементов (в рассматриваемом примере требуется записать только один элемент). Процедура вызывается два раза для занесения значений входных аргументов МЕХ-функции в переменные а и ь интерфейсной процедуры mexFunction. На данный момент в интерфейсной процедуре известны значения аргументов, от которых была вызвана МЕХ-функция в среде MATI ,АВ. Данное обстоят ельство позволяет обратиться к процедуре sura, ее использование и было основной задачей. Результат, т. е. сумма а и ь (см. листинг 23.7), занесен в переменную с. Остались обеспечить возвращение МЕХ-функцией в выходном аргументе значения переменной с. Предварительно необходимо создать массив размера один на один при помощи функции mxCreateDoubleMatrixJ MATLAB API. Первыми двумя ВХОДНЫМИ аргументами mxCreateDoubleMatrix является число строк и столбцов создаваемого массива, а третьим —- ноль или единица. Ноль, указанный в третьем аргументе, соответствует вещественному массиву, а единица— комплексному. Функция mxCreateDoubleMatrix возвращает указатель на созданный массив, который следует записать в plhs(l). Выше было сказано, что массив pihs должен содержать указатели на массивы с результатом, поскольку именно pihs используется для переда 950 Часть V. Дополнительные возможности MATLAB чи значений в рабочую среду MATLAB. Последним действием является занесение в массив значения вещественной переменной с, для чего применяется процедура mxCopyRealSToPtr MATLAB API Первый входной архумент mxCopyRealSToPtr является переменной, второй— указателем на массив, подлежащий заполнению, а третий — количеством записываемых элементов массива. subroutine mexFunction(nlhs, plhs, nrhs, prhs) ! Интерфейсная процедура для sum ! Описание типов аргументов integer nlhs, nrhs, plhs(*), prhs(*) ! Описание типов используемых функций из MATLAB API integer mxCreateDoubleMatrix, mxGetPr 1 Описание типов указателей на используемые переменные integer a_pr, Ь_рг, с_рг ! Описание типов используемых переменных real*8 а, Ь, с ! Получение указателей на первый и второй ьхидные аргументы, с которыми ! вызывается МЕХ-функция, указатели хранятся в массиве prhs, ! используется функция MATLAB API a_pr = mxGetPr(prhs(1)) b_pr = mxGetPr(prhs(2}) ! Запись значений первого и второго входных аргументов с указателями ’ a jpr и Ь_рг в переменные а и Ь при помощи процедуры MATLAB API call mxCopyPtrToRealS(a_pr, a, 1> call mxCopyPtrToReal8(b_pr, b, 1) ! Вызов процедуры sum, которая заносит в переменную с сумму а и b call sum(a, b, с) ! Создание выходного аргумента — вещественного массива размера один на ! один при помощи функции MATLAB API, выходной а[гумент есть указатель ! на массив plhs(l) = rnxCreatt=EcubleMatrix(l, 1, 0) c_pr = mxGetPr(plhs(1)) Гпава 23. Повышение производительности приложений MATLAB 951 ! Копирование значения с в массив с указателем с_рг call mxCopyRfal8ToPtr(c, c_pr, 1) end Использование процедуры sum в MATLAB станет возможным только после создания МЕХ-функции из sum, хранящейся в файле mysum.f90, и интерфейсной процедуры mexFunction, которая записана в файле mysumg.fQO. Для создания МЕХ-функции служит команда тех. Напомним, что перед применением тех следует определить, каким компилятором Fortran будет пользоваться MAI LAB для генерации МЕХ-функции (см. разд. "Конфигурирование МА TLAB Compiler"данной главы). После настройки MATLAB на использование компилятора Fortran можно приступать к окончательному этапу — созданию МЕХ-функции. Убедитесь, что файлы mysum.fSJO и mysumg.f90 находятся в текущем каталоге МА TLAB и выполните команду тех, указав в качестве ее параметров имена файлов: » тех mysum.f90 mysumg.f90 Обратите внимание, что имя файла с интерфейсной процедурой является вторым параметром тех. В текущем каталоге появился файл mysum.dll, который и содержит требуемую МЕХ-функцию. Проверьте ее работу, обратившись к ней из командной строки: » s = mysum(l, 2) s = 3 После вызова МЕХ-функция остается в памяти. Если она не нужна, то имеет смысл выгрузить ее при помощи команды clear: » clear mysum Пример создания МЕХ-функции из простейшей процедуры Fortran, приведенный выше, демонстрирует основные принципы использования интерфейса приложений MATLAB API. Пользователю MATLAB, не имеющему достаточного опыта в области разработки интерфейса приложений, но желающему вызывать процедуры Fortran из среды MATLAB, достаточно знать небольшой набор функций MATLAB API. Требуются только функции, которые позволяют обмениваться основными типами данных. Интерфейсные процедуры, как правило, принципиально не отличаются для различных процедур на Fortran и состоят из трех частей: 1. Получение значений входных аргументов. 2. Вызов процедуры на Fortran. 3. Возвращение значений в среду MATLAB. 95? Часть V. Дополнительные возможности MATLAB В следующих разделах показаны особенности реализации интерфейсных процедур и соответствующие функции MATLAB API для обмена данных различных типов. Работа с комплексными переменными Использование процедуры на Fortran, оперирующей с комплексными переменными, требует соответствующей организации обмена данных в интерфейсной процедуре. Кроме функции mxGetPr, придется испоччзовать mxGetPi, которая возвращает указатель на комплексную часть первого элемента массива. Получение и запись значения переменной по указателю производятся при ПОМОЩИ процедур mxCopyPtrToCoinplexl6 И ^nxCopyComplexlGToPtr, причем входным аргументом, кроме указателя на вещее гвенную, является еще и указатель на комплексную часть. При создании массива функцией mxcreate-Doubi eMatrix следует задать единицу в качестве третьего аргумента, поскольку предполагается хранение комплексных чисел. Текст исходной процедуры на Fortran приведен в листинге 23.9, а отвечающая ей интерфейсная процедура в листинге 23.10. ..... .. “ ......................................................-... Листинг 23.9. Процедура сложения комплексных чисел (файл mycsum.f90) • •*. I • • 1 . .. . . *4 *| . . ..««• , . , . t > - t . . . । A ! •. . . « fr I • « i > . I .. i . > > . >.....I.. «.... . at I el Л1И.1 subroutine sum(a, b, c) ! Процедура sum складывает два комплексных числа а и b I и возвращает результат в с complex*16 а, Ь, с с = а + b end Листинг 23. * 0. Интерфейсная процедура mexFuncexon (файл mycsumg.f90) subroutine mexFunction(nlhs, pihs, nrhs, prhs) ! Интерфейсная процедура для sum ! Описание типов аргументов integer nlhs, nrhs, plhs(*), prhs(*) 1 Описание типов используемых функций из MATLAB API integer mx ZreateFull, mxGetPr, mxGetPi ! Описание типов указателей на используемые переменные integer a_pr, b_pr, c_pr, a_pi, b_pi, c_pi ! Описание типов используемых переменных complex*16 а, Ь, с Гл 1ва 23. Повышение '/ Д- ,еодительнссти приложений MATLAB 953 ! Прлуианйе указателей на вещественные и мнимые части первого и второго I входных аргументов, с которыми вызывается МЕХ-функция, указатели хранятся в массиве prhs, используется функции MATLAB API a_pr = mxGecPr(prhs(1)) a_pi = mxGetPi(prhs(1)) b_pr = mxGetPr {prhs (2 >) b_pi = mxGetPi{prhs(2)) ! Запись значений первого и второго входных аргументов с указателями ! a_pr, a_pi и b_pr, b_pi в переменные а и b при помощи ! процедуры MATLAB API call mxCopyPtrToCornplexl6(a_pr, a_pi, a, 1) call mxCopyPtrToCompxexlo(b_pr, b_pi, b, 1) 1 Вызов процедуры sun, которая заносит в переменную с сумму а и b call sum(а, Ь, с) 1 Создание выходного аргумента — комплексного массива размера один на ! один при помощи функции MATLAB API, выходной аргумент есть указатель ! на массив plhs(l) = mxCreateDoubleMatrix(1, 1, 1) c_pr = rnxGetPr(plhs(1)) c_pi = mxGetPi(plhs(1)) ! Копирование значения с в массив с указателями ! с_рг (на вещественную часть) и c_pi (на мнимую часть) call rnxCopyComplexl6ToPtr(с, c_pr, c_pi, 1) end Создайте в текущем каталоге MATLAB файлы mycsum.Г90 и mycsumg.f90 и скомпилируйте МЕХ-функцию при помощи команды тех, рассмотренной в предыдущем разделе: » тех mycsum. €90 mycsumg.ESO Убедитесь в том, что полученная МЕХ-функция mycsum работает верно. » s = irrycsum(l + 2i, 3 - 5i) s = 4.0000 - 3-OOOOi Разумеется, mycsum правильно вычисляет сумму не только комплексных, но и вещественных аргументов: » s = mycsumfl, 3) s = 4 954 Часть V. Дополнительные возможности МА ТlAB Обмен массивами данных Передачу массивов данных в процедуру на Fortran и возвращение их в рабочую среду MATLAB проиллюстрируем на примере перемножения двух матриц. Создание процедуры для нахождения произведения двух матриц на Fortran не предъявляет груда, ее текст приведен в листинге 23.11. Листинг 23.11. Процедура перемножения матриц (фгйл myimult.F90 ! «>. «> • .. •«. •. < • ।> н» •«/г ь"«. •.. ।«Л • * 11 «1,. । • <Г«| * ! Тл «TWti * ГГ «Л^твл^Тв < subroutine multmtr(nl, n2, n3, X, Y, Z) ! Вычисление Z = X*Y, где X — п1хп2, Y — п2хпЗ, Z — п1ХпЗ integer nl, n2, пЗ, i, j, k real*8 X(nl, n2), Y(n2, n3), Z(nl, n3) do i = 1, nl do j = 1, n3 Z(i, j) = O.OdC do k = 1, n2 Z(i, j) = Z(i, j) + X(i, k)*Y(k, j> enddo enddo enddo end Требуется сгенерировать МЕХ-функцию mymult для вычисления произведения двух матриц, причем лучшим вариантом обращения к mymult из среды MATLA В было бы указание во входных аргументах только исходных матриц (без их размеров) и получение в выходном аргументе результата. Следовательно, работу по определению размеров перемножаемых матриц должна взять на себя интерфейсная процедура mexFunction (листинг 23.12). В интерфейсной процедуре необходимо объявить указатели на массивы, соответствующие исходным матрицам и их произведению, и сами массивы. Поскольку размеры массивов заранее неизвестны, то можно ограничить их, к примеру, пятьюдесятью (в следующем разделе приведен пример использования динамических массивов). Получение количества строк и столбцов во входных аргументах МЕХ-функции производится при помощи функций mxGetM и mxGetN MATLAB API. Данные функции вызываются от указателя на входной аргумент МЕХ-функции, те. от элемента массива prhs, и возвращают количество строк или столбцов. Перед нахождением произведения матриц процедурой mymult целесообразно проверить соответствие размеров перемножаемых матриц, а именно сов Гпава 23 Повышение производите/, мости приложений MATLAB 955 падение п и q. В случае, когда п не равно q, необходимо прекратить работу программы и вывести соответствующее сообщение в командное окно MATLAB, Процедура mexErrMsgTxt MATLAB API служит для останова по ошибке. Строка с сообщением об ошибке указывается в качестве входного аргумента mexErrMsgTxt. Примечание Все функции и процедуры MATLAB API делятся на две группы. Префикс тх в имени означает, что данная функция или процедура предназначена для оперирования с данными рабочей среды MATLAB. Функции и процедуры, имя которых начинается с префикса тех, позволяю’’’ выполнять команды MATLAB, выводить сообщения в командное окно, словом, взаимодействовать с самой средой MATLAB. Описание всех функций и процедур содержится в разд. Application Program Interface справочной системы MATLAB. После проверки входных аргументов необходимо извлечь указатели на соответствующие массивы и вызвать процедуру mxCopyPtrToRealS для заполнения массивов лив, определенных в интерфейсной процедуре. Третьим аргументом mxCopyPtrToReaie является количество записываемых данных в каждый массив, т. е. произведение числа строк на число столбцов. Вызов процедуры mymult приводит к занесению результата в массив с. Для возвращения результата в рабочую среду MATLAB осталось сформировать вещественный массив размера m на q при помощи функции mxCreateDoubleMatrix, записать указатель на него в первый элемент массива pihs И воспользоваться mxGetPr И mxCopyRealSToPtr. ; Листинг 23.12. Интерфейсная процедура (файл mymultg.f90) subroutine mexFunction(nlhs, pihs, nrhs, prhs) ! Интерфейсная процедура для mymult 1 Описание типов аргументов integer nlhs, nrhs integer pihs(*), prhs(*} ! Описание типов используемых функций из MATLAB API integer mxGetM, mxGetN, mxGetPr, mxCreateDoubleMatrix ! Описание типов указателей на используемые переменные integer А_рг, Ь_рг, С_рг ! Переменные m, n, р, q используются для записи размеров матриц integer m, n, р, q ! Предполагается, что матрицы не могут иметь размер, больший 50 real*8 А(50, 50), В(50, 50), С(50, 50) 956 Часть У. Дополнительные возможности MATLAB ! Получение размеров матриц — входных аргументов МЕХ-функцин m = mxGetM(prhs(1)) n = mxGetN(prhsd)) p = mxGetM(prhs(2)) q = mxG >tN(prhs (2)) ! Проверка соответствующих размеров матриц if (n.ne.p) then call mexErrMsgTxt('Matrix dimensions must argee!1) endif 1 Проверка размеров матриц на выход за допустимые пределы (<=50) if ((m.gt.50).or.(n.gt.50).or.(p.gt.50).or.(q.gt.50)) then call mexErrMsgTxt('Size of martix >50') end; f 1 Запись указателей на матрицы в соответствующие переменные А_рг и В_рг A_pr = mxGetPr(prhs(1)) B_pr = mxGetPr(prhs(2)) 1 Занесение данных из матриц в массивы А и В call mxCopyPtrToReal8(A_pr, A, m*n) call mxCopyPtrToReal8(B_pr, B, p*q) ! Вызов процедуры multmtr, которая заносит в массив С произведение А*В call multmtr (m, n, q, А, В, C) ! Создание выходного аргумента — вещественного массива размера m на q ! при помощи функции MATLAB API, выходной аргумент является указателем ! на массив plhs(l) = mxCreateDoubleMatrix(m, q, 0) C_pr = mxGetPr(plhs(1)) ! Копирование значений С в массив с указателем С_рг call mxCopyReal8ToPtr(С, C_pr, m*q) end Сгенерируйте МЕХ-функцию mymult, поместив файлы mymuk.f% и mymuItg.fPO в текущий каталог MATLAB, и проверьте ее работ): » тех mymult.f90 mymultg.f90 » А = [1 2 3; 4 5 6; 7 8 9]; » В = [1 1 0 2; 3 -1 -2 0; 5 -2 -1 2] ; » С = mymult(А, В) С = 22 -7 -7 8 Гпава 23. Повышенны производительности приложений МА П.АВ 957 49 -13 -16 20 76 -19 -25 32 » A* В ans - 22 -7 -7 8 49 -13 -16 20 76 -19 -25 32 Обратите внимание. что МЕХ-функция mymult вычисляет произведение не только матриц, но и чисел, поскольку числа в MATLAB представляются в виде массивов размера один на один: » c=mymult(3, -7} с = -21 Ограничение на размеры матриц является существенным недостатком ин* терфейсной процедуры mexFunction, текст которой содержится в листинге 23.12, поскольку процедура multmtr (см. листинг 23.1 Г) перемножает матрицы без ограничения на их размеры. Объявление динамических массивов в интерфейсной процедуре, приведенной в листинге 23.13, позволяет решить эту проблему. Создайте МЕХ-файл, используя улучшенную интерфейсную процедуру, и проверьте его работу. ^V'A'JUVVlUUllU..... VUULUM I UXfXJULV<IUJIA*XUJUZU .«4. .................. : Листинг 23.13. Интерфейсная процедура с динамическими массивами i mymultg2.f90 subroutine mexFunction(nlhs, pihs, nrhs, prhs) integer nlhs, nrhs integer pihs(*), prhs(*) integer mxGetM, mxGetN, mxGetPr, mxCreateDoubleMatrix integer A_pr, B_pr, C_pr integer m, n, p, q ! Объявление вещественных динамичееккх массивов А, В и С real*8, allocatable :: А(:, :),В(:, :), С(:, :) ш - mxGetM(prhs(1)) n = mxGetN(prhs(1)) p - mxGetM(prhs (2) ) q - mxGetNIprhs(2) ) if (n.ne.p) then 958 Часть I/. Дополнительные возможности MATLAB call mexErrMsgTxt(‘Matrix dimensions must argee! ') endif ! Выделение памяти для записи значений первого входного 1 аргумента МЕХ-функции в массив А allocate(A(m, n) ) A__pr = mxGetPr(prhs(1)) call raxCvpyPtrToReal8(A_pr, A, m*n) ! Выделение памяти для записи значений второго входного ! аргумента МЕХ-функции в массив В allocate(B(p, q)) B_pr = mxGetPr(prhs(2)) call mxCopyPtrToReal8(B_pr, B, p*q) I Выделение памяти под результат процедуры multmtr allocate(С(m, q)) call multmtr(m, n, q, А, В, C) 1 Высвобождение памяти, занятой под массивы А и В deallocate(А, В) plhs(l) = mxCreateDoubleMatrix(m, q, 0) C_pr = mxGetPr(pihs(1)) call mxCopyRealSToPtr(C, C_pr, m*q) 1 Высвобождение памяти, занятой под массив С «reallocate (С) end Ускорение работы при использовании циклов Использование внешних процедур в MATLAB позволяет ускорить работу приложений MATLAB, содержащих циклы, особенно вложенные. Например, М£Х-функцня mymult для перемножения матриц, описанная в предыдущем разделе, работает намного быстрее, чем аналогичная функция, написанная на встроенном языке программирования MATLAB. Проверьте это, создав файл-функцию mymuitfun, которая так же как и mymult, находит произведение матриц в трех вложенных циклах. Примечание Мы приводим этот пример только для демонстрации ускорения работы приложения с вложенными циклами. Оператор * все равно быстрее вы Гпава 23 Повышение производительности приложений MATLAB$59 числит произведение матриц в MATLAB. Программирование внешней функции имеет смысл, если в MATLAB нет соответствующего оператора или функции и в циклах требуется обработать данные большого объема. Текст файл-функции mymultfun приведен в листинге 23.14. Алгоритм очевиден, мы привели его только для того, чтобы подчеркнуть, что использованы рекомендации по ускорению работы файл-функций. Например, перед заполнением массива с он сначала инициализируется (си. разд. "Выоепение памяти под массивы" данной главы). Пистинг23,14 файл-санкция mymltfun для перемножения матриц ;............1'.................... : .л;.............•. ............ ............ function С = mymultfun(А, В) [m. n] = size(A) (р. q] = size(B); С = zeros (in, q) ; for i = l:m for j = l:q C(i, j) = 0; for k = l:n C(i, j) = C(i, j) + A(i, k)*B(k, j); end end end Сразимте время работы МЕХ-функции mymult и файл-функции mymuitfun: » А = rand(400); » В = rand(400); » tic, С = mymultfun(A, В); toe Elapsed time is 8.500000 seconds. » tic, C = mymult(A, B) ,- toe Elapsed time is 1.594000 seconds. Для разных компьютеров временные затраты могут различаться, но соотношение остается примерно тем же— МЕХ-фуикциг в несколько раз экономит время счета. В заключение этой главы отметим, что вы имеете возможность вызывать функции MATLAB из собственных программ на Fortran или С (см. разд. MATLAB: External Interfaces: Calling MATLAB from C and Fortran Programs справочной системы MATLAB). Приложения Приложение 1 Основные команды и функции MATLAB и Toolbox Приложение содержит основные функции и команды MATL АВ. сгруппированные но разделам. Приведено описание различных вариантов вызова функций, имеются примеры использования некоторых функций и команд. Даны ссылки на соответствующие главы и разделы книти, в которых подробно разобрано применение функций и команд MATLAB и Toolbox. Управление средой, файлами и переменными Получение справочной информации □ demo — получение доступа к демоне грационным файлам в окне Help. □ doc — запуск справочной системы по всем разделам MATLAB. В качестве параметра может быть указано имя функции или команды, для которой требуется получить справочную информацию: doc plot или имя Toolbox: doc toolboxpde П help — вывод разделов встроенной справки в командное окно • help elfun — содержимое раздела elfun с информацией о встроенных элементарных математических функциях. В тексте названия функций и команд приведено заглавными буквами, но при работе надо набирать команды и функции строчными буквами. • help floor -—описание функции floor. 964 Приложения • help / — информации об операторах и специальных символах. • help syntax —справка о синтаксисе команд и функций MATLAB. □ helpwin — запуск краткой справочной системы по разделам MATLAB в окне Help. □ lookfor— поиск М-файлов, в которых первая строка комментариев одержит заданный текст, например: lookfor integral Просматриваются файлы, находящиеся в путях поиска MATLAB (подробнее про пути поиска написано в разд. "Установка путей"главы 5). □ ver— вывод в командное окно версий MATLAB, Toolbox и дополнительных пакетов, входящих в установленную версию. □ version — вывод в командное окно версии MATLAB. □ whatsnew— вывод в окно Help информации о новшествах, отличающих данную версию от предыдущей. Управление средой MATLAB П addpath — добавление каталога в пути поиска MAT LAB (подробнее про пути поиска написано в разд. "Установка путей" главы 5). Примеры* • addpath c:userigormywork • addpath c:userigormyworkl c:userigormywork2 • addpath('с:userVigormyworkl', 'c:userigormywork2') • addpath c:userigormyworkl c:userigormywork2 -end — добавление в конец списка; • addpath c:userigormyworkl c:userigormywork2 -begin -—добавление в начало списка. П cic — очистка содержимого командного окна. □ echo — управление отображением строк выполняемого М-файла в командном окне. • echo on -— вывод строк. • echo off — подав гение вывода строк. Л format — определение формата вывода чисел в командное окно (см. разд. "Форматы вывода результата вычислений'' главы /). • format short — формат с плавающей точкой с 4-мя цифрами после десятичной точки. Приложение 1 Основные команды и функции MATLAB и Toolbox 965 • format long — формат с плавающей точкой с 14-ю цифрами после десятичной точки (для одинарной точности — с 7-ю). • format short е — экспоненциальный формат с 5-ю значащими цифрами • format long е—экспоненциальный формат с 15-ю значащими цифрами (для одинарной точности — с 8-ю). • format short g — наиболее подходящий из экспоненциального формата и формата с плавающей точкой с 4-мя цифрами. • format long g— наиболее подходящий из экспоненциального формата и формата с плавающей точкой с 15-ю цифрами (для одинарной точности — с 7-ю). • format hex — шестнадцатеричный формат. • format + — положительные, отрицательные или нулевые числа отображаются знаками плюс, минус или пробел, мнимая часть игнорируется. • format bank — формат с двумя десятичными знаками. • format rat — числа приближенно представляются отношением двух целых чисел. • format compact — подавление вывода пустых строк между строками результата. • format loose — вывод пустых строк между строками результата. П path — управление путями поиска. Вызов path без аргументов приводит к выводу всех i [утей в командное окно, • р = path — занесение в строковую переменную р путей поиска. • path (pathdef) — установка путей, принятых по умолчанию. Возможно, также, добавление путей в начало и конец списка путей поиска: • path ('с: userigormywork*, path) — добавление в начало списка; • path (path, 'c:userigormywork')—добавление в конец списка. П rmpath — удаление одного или нескольких каталогов из путей поиска: • rmpath c:userigormywork • rmpath c:userigormyworkl c:userxgormywork2 • rmpath(с:userigormyworkl, c:userigormywork2) □ pathtool — запуск диалогового окна навигатора путей (работа с навигатором путей описана в разд. "Установка путей" главы 5). 966 Приложения П lasterr, lastwarn— возвращают строку с последним сообщением об ошибке или предупреждением. Вызовы lasterr (’') и lastwarn (") приводят к очистке последнего сообщения об ошибке или предупреждения. □ miint — анализатор кода М-файла (работа с графической оболочкой М-Lint описана в разд. "Диагностика М-файлов" главы 5). • miint ('тургод.т’) — выводит информацию о замеченных ошибках и неточностях в М-файле и способах повышения его производительности. • miint ({ 'myprogl .m'; 'myprog2.m'; 'тургодЗ,m*})— одновременный анализ нескольких файлов (имена задаются в массиве ячеек, работа с массивами ячеек описана в разд. "Массивы структур и массивы ячеек"главы 8). • info = miint ('myprog.m1)— запись информации о каждом обнаруженном замечании в массив структур с полями: line, column (для указания строки с замечанием и позиции в строке) и message — текст замечания (работа с массивами сруктур описана в разд. “Массивы структур и массивы ячеек” главы 8). □ profile— управление профайлером (основы работы с профайлером описаны в разд. "Профайлер" главы 15). Команда profile on приводит к запуску профайлера. Общий вид команды для старта профайлера: profile on -detail level -history Значения level: mmex (сбор статистики временных затрат на выполнение М- и МЕХ-файлов), builtin (то же, что mmex, дополнительно находятся временные затраты на выполнение встроенных функций), operator (аналогично builtin, но с учетом времени на арифметические и другие встроенные операции). Опция -history служит для запоминания последовательности вызова функций. • profile report — остановка профайлера, генерация отчета в формате HTML, и отображение его в браузере. • profile report myreport — остановка профайлера, генерация отчета в myreport.html и нескольких связанных с ним файлах и отображение отчета в браузере. • profile plot — остановка профайлера и построение столбцевой диаграммы временных затрат. • profile oft — прекращение сбора информации. • profile resume — возобновление процесса сбора информации. Приложение 1. Основные команды и функции MATLAB и Toolbox 967 • profile clear— уничтожение накопленной профайлером информации. • profile status — отображение структуры с установками профайлера. П prof report — остановка профайлера, генерация отчета в формате HTML и отображение его в браузере. profreport (myreport) — остановка профайлера, генерация отчета в myreport.html и нескольких связанных с ним файлах и отображение отчета в браузере. □ type — вывод содержимого текстового файла в командное окно ( уре filename □ guit — окончание сеанса MATLAB. □ what — вывод содержимого текущего каталога (файлов с расширениями m, mat. тех) в командное окно. • what dimame — вывод содержимого каталога dirname (файлов с расширениями т, mat, тех) в командное окно. • w = what (’dirname') — запись информации о каталоге dirname и его содержимом в структуру w (работа со структурами описана в разд. "Простые структуры"главы 8). □ which — вывод пути к функции, например >> which fzero С: MAr"LAB'’toolboxmatlabfunfunfzero.m • which funname -all — отображение путей ко всем функциям с именем funname. • w = which (' funname') — занесение в строковую переменную w пути к ФУНКЦИИ С именем funname. • w = which (’ funname ’, ’ -all') — занесение в массив ячеек w пу гей к функциям с именем funname (см. разд. "Массивы структур и массивы ячеек”главы 8). Управление переменными □ clear — удаление переменных рабочей среды (ел/, разд. "Просмотр и удаление переменных, выбор имен переменных "главы /). • clear A m R — удаление переменных a, m и R из рабочей среды. • clear global — удаление всех глобальных переменных. 968 Приложения • clear functions — удаление всех откомпилированных М-функций. • clear тех — удаление ссылок на МЕХ-файлы и М-функции. • clear all — удаление переменных и ссылок на МЕХ-файлы и М-функнии. □ disp — вывод текста или значения переменной в командное окно (см. разд. "Проверка входных аргументов"главы 7). □ length— нахождение длины вектор-строки или вектор-столбца (см. разд. 'Ввод, сложение и t ычитание векторов"главы 2). □ load — считывание значений переменных с диска (см. разд. "Сохранение и восстановление рабочей среды" главы 1 и "Считывание и запись данных" главы 2). П miock— предотвращение удаления переменных работающего в данный момент М-файла командой clear. □ muniock — разрешение удаления переменных работающего в данный момент М-файла командой clear. П openvar— запуск редактора М-файлов со специальным окном, позволяющим интерактивное редактирование значений переменных. openvar а — редактирование переменной А (см. разд. "Организация вывода текстовых результатов" главы 2). □ pack — создание виртуальной памяти на диске в файле pack.tmp. в которую заносятся значения всех имеющихся переменных, и очистка рабочей среды. Значения используемых переменных считываются из файла pack.tmp. Используется при обработке большого объема данных (см. разд. "Экономия памяти"главы 23). □ save — запись значений переменных на диск (см. разд. "Сохранение и восстановление рабочей среды" главы 1 и "Считывание и запись данных" главы 2). □ saveas — сохранение графического окна с указателем h в файле определенного формата. • saveas (h, filename.ai') — формат Adobe Illustrator. • saveas(h,'filename.bmp‘) • saveas(h,'filename.emf1) • saveas(h,'filename.eps‘) • saveas(h, 'filename.fig') —графическое окно MATLAB. • saveas(h, 1 filename.jpg') Приложение 1. Основные команды и функции MATLAB и Toolbox 969 • saveas (h, 1 filenami L.m') — М-фаЙЛ MATLAB. • saveas{h,'filename.pcx') • saveas(h,'filename,tif1) □ size— определение размеров массива (см., например, разд. "Ввод, сложение и вычитание векторов"главы 2). □ who — вывод имен всех определенных в рабочей среде переменных. □ whos — получение информации о переменных рабочей среды (см. разд. "Просмотр и удаление переменных, выбор имен переменных" главы Г). □ workspace — вызов браузера рабочей среды MATLAB. Браузер рабочей среды является приложением с графическим интерфейсом, которое позволяет просматривать и изменять значения переменных рабочей среды. Манипулирование файлами и каталогами □ cd — установка текущего каталога, например: • cd c:userigormyworkl • cd — вывод текущего каталога в командное окно. • cd .. — переход на один уровень вверх. □ copyfile — копирование файла. • copyfile('с:myworkltest.m', 'c:nibtlabworkmyplot.m')— копирование файла c:myworkltest.m в c:matlabworkmyplot.rn. • copyfile('c:myworkltest.m', 'c:matlabworkmyplot.m', 'writable') — запись файла c:myworkltest.rn в c:matlabworkmyplot.m с проверкой возможности копирования. • s = copyfile('с:myworkltest.m', 'c:matlabworkiryplot.m')— возвращает единицу, если копирование прошло успешно, и ноль в противном случае. • [s, mes] = copyfile]'c:myworkltest.m', ' с: matlabworkmyplot .m') — дополнительно заносит в mes строку С сообщением об ошибке, если таковая возникла в процессе копирования. □ delete — удаление файлов и графических объектов (см. разд. "Удаление и очистка объектов"главы 9). delete с: myworkitest .т — удаление файла c:myworkltest.nL 970 Приложения • delete{‘с: myworkitest-m') — удаление файла c:myworkltest.m, такую форму вызова delete удобно использовать, когда имя файла хранится в строковой переменной. • delete (h) — удаление графического объекта с указателем h. О diary — ведение дневника сеанса работы в MATLAB (см. разд. "Сохранение и восстановление рабочей среды" главы 1). □ dir — вывод содержимого текущего каталога. • dir dirname — вывод содержимого каталога dimame. • DIRMAS = dir ('dirmame') — запись содержимого каталога dirname в массив структур dirmas. Каждая структура имеет четыре поля name — имя файла или подкаталога, date — дата изменения, bytes — размер, флаг isdir — принимает значение единица для подкаталога и ноль для файла (работа с массивами структур описана в разд. "Массивы структур и массивы ячс ек " главы 8). П edit — запуск редактора М-файлов, в котором создается новый файл. • edit filename — открытие в редакторе М-файлов файла filename.m • fileparts — возвращает путь к файлу, имя и расширение, использование: [path, name, ext] = fileparts('имя файла') □ fullfile— конструирование полного имени файла из иерархии подкаталогов и имени файла, результат заносится в строковою переменную, использование: fn = fullfile('с:', 'user', 'igor1, 'work', 'myfun.m’) □ inmem— отображает функции MATLAB, загруженные з память. • mmas = inmem— занесение в массив ячеек mmas имен загруженных М-функций. • [mmas, mxmas] = inmem— занесение в массивы ячеек mmas и mxmas имен загруженных М- и МЕХ-функций. □ matiabroot — имя каталога, в который установлена MATLAB. □ mkdir — создание подкаталога, примеры: • mkdir (’ work2 ’) — создание подкаталога work2 в текущем каталоге; • mkdir('work*, 'work2')— создание подкаталога work2 в существующем на диске каталоге work; Приложение 1. Основные команды и функции MATLAB и Toolbox 971 • [stat, msg] = mkdir (’ work2') —создание подкаталога, stat равен единице в случае успешного выполнения функции, двойке, если подкаталог существует, и нулю при невозможности создания подкаталога: • [stat, msg] = mkdir('work’, 'work2') — строка msg содержит сообщение об ошибке в случае неудачной попытки создания каталога. П open — открытие файла или содержимого переменной, способ открытия зависит от расширения. • open (’а' ) — запуск редактора М-файлов и отображение в нем значений массива а. Возможно редактирование значений элементов. • open ('my. fig' j —- открытие графического окна my.fig. • open('myfun.т')— запуск редактора М-файлов и открытие в нем myfun m. • open ('mymod.mdl') — открытие модели mymod.md! в среде Simuiink. Пользователь имеет возможность определить способ открытия файлов с другими расширениями, создав подходящую файл-функцию. Например, файлы с расширениями myl требуют наличия функции openmyl. П pwd — отображение имени текущего каталога. s = pwd — запись в строковую переменную s имени текущего каталога. □ tempdir— отображение имени каталога, предназначенного для хранения временных файлов. s = tempdir — запись в строковую переменную имени каталога, предназначенного для хранения временных файлов. □ tempname — отображение имени текущего временного файла. s = tempname— запись в строковую переменную имени текущего временного файла. □ 1 —выполнение команды операционной системы, например: ! help — вывод разделов справочной системы Windows. Операторы и специальные символы Использованию арифметических и логических операций, в том чисче и применению их к массивам, посвящены отдельные разделы книги (см. главы 1,2 и 7) Арифметические и матричные операции приведены в табл. П1. 972 Приложения Таблица П1, Арифметические и матричные операции Операция Назначение + j — Унарные плюс и минус, сложение и вычитание для скаляров и массивов. Массивы должны быть одинаковых размеров. Один из операндов может быть скаляром Перемножение скаляров или матриц подходящих размеров. Один из операндов может быть скаляром kron Кронекеровское или тензорное произведение матриц С = kron (А, В) / Деление скаляров. Поэлементное деление матрицы на скаляр. Если оба операнда — матрицы, то д/в = A*inv(B) л Возведение скаляра в степень. Вычисление степени квадратной матрицы Левое матричное деление. Если дявляется квадратной матрицей, то дв = inv (А) *в. Если а— квадратная матрица размера п, в— вектор-столбец из п элементов, то х = дв содержит решение системы линейных уравнений ах = в. Допускаются переопределенные и недоопределенные системы (см. разд. "Задачи линейной алгебры"главы б) * Поэлементное умножение массивов одинаковых размеров, например, С = А. *В приводит К С (i, j) = A(i, j)*B(i, j) ./ Поэлементное деление массивов одинаковых размеров, например, с = А. /в приводит к с(i, j) = A(i, j)/B(i, j) л Поэлементное левое деление массивов одинаковых размеров, например, с = А. в приводит кс (i, j) = B(i, j)/A(i, j) л Поэлементное возведение матрицы в степени, являющиеся элементами другой матрицы тех же размеров, например, с - А.лв приводит к С(i, j) = A(i, j)AB(i, j) 1 Нахождение сопряженной матрицы 1 Транспонирование матрицы. Для вещественных матриц ' и . ’ приводят к одинаковым результатам Логические операции и операторы Логические операции применимы к массивам одинаковых размеров или к массиву и скаляру, в последнем случае скаляр расширяется до размеров массива (см. разд, "Логические выражения с массивами и числами" главы 7). Приложение 1. Основные команды и функции MATLAB и Toolbox 973 Опера -оры отношения представлены в табл. П2. Таблица П2. Операторы отношения Оператор Назначение > Больше: а > Ь >= Больше или равно: а >= b < Меньше: а < b <= Меньше или равно: а < Ь == Равно: а == Ь Не равно:а -= Ьы Логические операторы имеют некоторые особенности по сравнению со многими языками программирования. Логические операции (табл. ПЗ) могут применяться к массивам (см. разд, "Логические выражения с массивами и числами"главы 7). Таблица ПЗ. Логические операции Оператор На течение & Логическое И:а>ь&а<с && Логическое И: k <= length(х) &s х(к) >0 если первое условие к <= length (х) не выполняется, то второе х(к) >0 не проверяется I Логическое ИЛИ: а > Ь ' а < с II Логическое ИЛИ: а > b | | а < с, если первое условие а > b выполняется, то второе а < с не проверяется хог Логическое исключающее ИЛИ: хог(а > Ь, а == с) - Логическое отрицание: ~ (а == 0) Побитовые операции □ bitand — поразрядное И. с = bitand (а, b) — возвращает результат побитового И для двух целых неотрицательных чисел, меньших bitmax (см. bitmax ниже), например: » с = bitand(79S, 336) 974 Приложения с - 272 Функция dec2bit позволяет убедиться в правильности полученного результата (см. рам "Преобразование системы счисления" этого приложения). Пример использования поразрядного И: » dec'zbin (7 98) ans = 1100011110 » dec2bin{336) ans = 101010000 » dec2bin(272) ans = 100010000 □ bitcmp — поразрядное дополнение. с = bitcmp (a, n) — возвращает поразрядное дополнение целого неотрицательного числа а, состоящее из п разрядов, например: » bitcmp(598, 10) ans = 425 » dec2bin(598) ans = 1001010110 » bitcmp(598, 10) ans = 425 » dec2bin(425) ans = 110101001 П bitor — поразрядное ИЛИ. с = bitor (a, b) — возвращает результат побитового ИЛИ для двух целых неотрицательных чисел, меньших bitmax (см. bitmax ниже), например: » dec2bin(24) ans = 11000 » dec2bin(89) Приложение 1. Основные команды и функции MATLAB и Toolbox 975 ans = 1011001 » с - bitor(24,89) с = 89 » dec2bin(c) ans = 1011001 □ bitmax — возвращает максимально допустимое целое без знака. □ bitset — установка разряда. с = bitset (a, bit) или с = bitset (a, bit, 1) —установка в единицу двоичного разряда с номером bit (не более 52) целого неотрицательного числа а, например: » dec2bin(257) ans = 100000001 » с = bitset(257, 3) с = 261 » dec2bin(261) ans = 100000101 с - bitset (a, bit, 0) — установка в ноль двоичного разряда с номером bit целого неотрицательного числа а. □ bitshift — сдвиг разрядов. • с = bitshift (а, к, п) — результат является поразрядным сдвигом целого неотрицательного числа а (не превосходящего bitmax) на к бит. Если выходной аргумент представляется числом бит, большим п, то происходит отбрасывание лишних разрядов. • с = bitshiftfa, к)— эквивалентное = bitshiftfa, к, 53). Положительные значения к приводят к сдвигу влево, а отрицательные— вправо. Пример вызова bitshift: » с = bitshift(272, 5) с _ < 8704 » dec2bin(272) 976 Приложения ans -100010000 » decZbin(8704) ans -10001000000000 □ bitget — получение значения разряда. vai = bitget (a, bit) — в выходном apiумейте val возвращается значение (ноль или единица) разряда с номером bit (не более 52) целого неотрицательного числа а. П bitxor — поразрядное исключающее ИЛИ. с = bitxor (а,Ь) — возвращает результат исключающего побитового ИЛИ для двух целых неотрицательных чисел, меньших bitmax (см. bitmax выше), например: » dec2bin(139) ans = 10001011 » dec2bin(116) ans = 1110100 » с = bitxor(139, 116) с = 255 >> dec2bin(255) ans = 11111111 В табл. П4 приведены специальные символы, использующиеся в выражениях MATLAB. Таблица П4. Специальные символы Символы Назначение Оператор присваивания [] Квадратные скобки используются для формирования вектор-строк, вектор-столбцов и массивов, например: а = [1 2 3]; Ь = [1 + 2i, 3 - 9iJ; с = [0.2; -3; - 4; 8] ; А = [1 2 3; 4 5 6; 7 8 9]; Приложение 1. Основные команды и функции MATLAB и Toolbox 977 Таблица П4 (окончание) Символы Назначение Конструирование блочных матриц гак же производится при помощи квадратных скобок: М = [А В; С D] ; Пустые квадратные скобки используются для определения пустого массива и удаления строк или столбцов: а (2, :) = [ ]; Квадратные скобки позволяют вызвать функцию с несколькими выходными аргументами: [т, к] = тах(х) {) Фигурные скобки предназначены для заполнения массивов ячеек (см. разд. "Массивы ячеек" главы 8) () Круглые скобки определяют порядок выполнения арифметических и логических операций. Кроме того, индексы массивов и входные аргументы функций заключаются в круглые скобки Двоеточие позволяет обратиться к сечению массива: в = А(2:5, 4:7) и создать вектор, компоненты которого изменяются с постоянным шагом: а = -1:0.05:2 - Десятичная точка, отделение поля структуры от имени Переход на один каталог выше в команде cd Продолжение команды на следующей строке. Используется как при наборе в командной строке, так и в редакторе М-файлов t Запятой отделяются индексы массива и аргументы функций. Несколько команд, набранных в одной строке, так же отделяются запятой, например,а = 1, с = 2 t Точка с запятой отделяет строки матрицы при наборе элементов внутри квадратных скобок. Завершение выражения точкой с запятой приводит к подавлению вывода результата в командное окно % Начало строки комментариев в М-файле %{ Начало блока коммен гариев в М-файле %) Конец блока комментариев в М-файле 978 iir глажения Логические функции П all — проверка на наличие нулевого элемента в массиве. f = all iа) -— возвращает логическую единицу, если в массиве а все элементы ненулевые, и ноль, если хотя бы один элемент массива равен нулю. П any— проверка на наличие ненулевого элемента в массиве. f = any (А) — возвращает логическую единицу, если в массиве а есть хотя бы один ненулевой элемент, и ноль, если все элементы массива равны нулю. □ exist — проверка существования переменной или файла. а = exist (' name') — возвращает тип проверяемого объекта: • 0, если name не существует; • 1, если name является переменной рабочей среды; • 2, если name — имя М-файла из каталога, находящегося в путях поиска, или тип файла неизвестен; • 3, если в каталоге, находящемся в путях поиска, есть файл name.mex; • 4, если в каталоге, находящемся в путях поиска, есть файл narne.mdl; • 5, если name является именем встроенной функции MATLAB; • 6, если существует P-файл с именем name в каталоге, имеющемся в путях поиска; • 7, если name является именем каталога. □ find — нахождение индексов и значений ненулегых элементов массива. • k = find(x) —в вектор к заносятся номера ненулевых элементов массива х. Если х является матрицей, то она трактуется как вектор, составленный из ее столбцов. • [1, j] = find(x) — в векторы i и j записываются индексы ненулевых элементов матрицы х, что удобно, например, при работе с разреженными матрицами (см. разд. "Логическое индексирование" главы 2, "Логические операции с числами и массивами" главы 7 и "Работа с раз-ре женнъши матрицами " главы 15). • [i, j. v] = find(x) — в дополнительном выходном аргументе v возвращаются значения ненулевых элементов матрицы к. Приложение 1. Основные команды и функции МА TLAB и Toolbox 979 □ is... — выявление типа и 'значений переменной. • к = iscell (с) — возвращает логическую единицу, если с— массив ячеек, и ноль — в противном случае (работа с массивами ячеек описана в разд. "Массивы структур и массивы ячеек" главы 8). • k = iscellstr(S) — возвращает логическую единицу, если s— массив ячеек сзрок, и ноль — в противном случае. • k = ischar(S) — возвращает логическую единицу, если S— массив символов, и ноль — в противном случае. • k = isempty (а) — возвращает логическую единицу, если а— пустой массив, и ноль — в противном случае. Пустым считается массив, у которого хотя бы один размер равен нулю. • k = isequal (А, в, ...) — возвращает логическую единицу, если входные массивы одинаковы (т. е. одних размеров и соответствующие элементы совпадают), и ноль — в противном случае. • k = isfield (s,' field')— возвращает логическую единицу, если field является одним из полей структуры s, и ноль — в противном случае (работа со структурами описана в разд. "Простые структ) ры" главы 8). • tf = isfinite(A) — возвращает массив tf, в котором логические единицы соответствуют числам массива а, а нули — inf, -inf или NaN BA. • k = isglobal (name) — возвращает логическую единицу, если name объявлена как глобальная переменная, и ноль — в противном случае. • tf = ishandle(H) — возвращает массив tf, в котором логические единицы соответствуют элементам массива н, которые являются указателями на существующие графические объекты. Остальные элементы tf нулевые (дескрипторной графике и указателям посвящена глава 9). • k = ishold — возвращает логическую единицу, если hold установлено в on, т. е. при выводе графиков в текущие оси происходит их добавление в текущее окно, ноль соответствует hold off. • tf = isj nf (A) — возвращает массив tf, в котором логические единицы соответствуют элементам inf, -inf массива А, а нули — остальным значениям. • tf = isletter (• str ) -— возвращает массив tf, в котором логические единицы соответствуют символам алфавита в строке str, а нули -— остальным значениям. 32 3« 130 980 Приложения • к = islogical (А) — возвращает логическую единицу, если а—логический массив, и ноль — в противном случае. • tf = isnan (а) — возвращает массив те, в котором логические единицы соответствуют элементам NaN массива А. а нули — остальным значениям. • k = isnumeric (А) — возвращает логическую единицу, если а— числовой массив (т. е. double array ИЛИ sparse array), и НОЛЬ — В противном случае. • k = isobject(A) — возвращает логическую единицу, если а является объектом, и ноль — в противном случае. • tf = isprime(A) — возвращает массив tf, в котором логические единицы соо гветст вуют простым числам (не имеющим делителя, кроме единицы и самого числа) массива а, а нули — остальным значениям • k = isreal (А) — возвращает логическую единицу, если все элементы а являются вещественными числами, и ноль — в противном случае. Поскольку строковые переменные входят в подкласс double array, то для строк isreal возвращает логическую единицу. • tf = isspace(’str') — возвращает массив tf, в котором логические единицы соответствуют пробелам, символам табуляции и пустой строки в str, а нули — остальным значениям. • k = issparse(S) — возвращает логическую единицу, если s является разреженной матрицей, т. е. массивом типа sparse array, и ноль — в противном случае (работа с разреженными матрицами описана в главе 15). • k = isstruct(S) — возвращает логическую единицу, если s является структурой, и ноль — в противном случае (работа со структурами описана в разд. "Простые структуры" главы 8). □ isa — определение принадлежности объекта классу. isa(obj, ' ciass_name') — возвращает логическую единицу, если obj есть объект класса class name, и ноль — в противном случае. Возможны следующие варианты вызова: • isa(cbj,'double'): • isa(obj,'sparse*); • isa(obj,'struct'); • isa(obj,'cell’); • isa(obj,’char; '1рилоыение 1, Основные команды и функции MATLAB и Toolbox 981 • isa(obj,'uintS'); • isa(obj,'класс пользователя'), □ logical— преобразование числового массива в логический, который может быть использован для индексации (см. разд. "Логическое индексирование " главы 2). О misiocked— проверка на возможность удаления из рабочей среды переменных М-файла. • k = misiocked— возвращает логическую единицу, если можно удалить переменные выполняемого в данный момент М-файла, и ноль -в противном случае. • k = mislocked (’filename')—производит аналогичную проверку для М-файла с именем filename Программирование Конструкции языка Программированию алгоритмов на встроенном языке MATLAB посвящены две главы книги (см. главы 7 и 8). Ниже приведены все конструкции языка программирования MATLAB, предназначенные для определения последовательности выполняемых команд. П break — ВЫХОД ИЗ ЦИКЛОВ while И for. □ сазе — начало блока в операторе переключения switch. П catch— начало блока конструкции try.. .catch, соответствующего исключительной ситуации. О continue — переход к следующему шагу цикла for или while. □ elae — ветвь оператора if, работающая при невыполнении всех условий. □ eiseif— ветвь оператора if, работающая при выполнении некоторого условия О end —завершение конструкций for, while, switch, try и if, □ error— отображение в командное окно сообщения об ошибке и прекращение работы файл-функции или файл-программы. пример: error('ошибка ввода’) □ for — оператор для организации цикла с известным числом повторов. 982 Приложения □ function — объявление файл-функции или подфункции (см. разд. ’'Файл-функции" главы 5 и разд. "Подфункции" главы 8). □ global — раздел объявления глобальных переменных в файл-функции □ if — условный оператор. П otherwise — начало блока оператора переключения switch, выполняющегося в случае, когда ни один из блоков case не был выполнен. □ persistent— раздел объявления перманентных переменных в файл-функции. П return — возврат в точку вызова функции или прекращение режима ввода с клавиатуры. П swi tch — оператор переключения. О try — начало конструкции обработки исключительных ситуаций. □ warning — вывод предупреждения в командное окно, например: warning('деление на ноль') □ while— организация цикла с неизвестным числом повторений, выполняющегося при истинности условия цикла. Сервисные функции и переменные □ ans — автоматически создаваемая переменная для хранения значения выражения или результата функции, если не применяется оператор присваивания. □ builtin — вызов исходной функции в файл-функции, определяющей перегруженный метод. Работает так же, как и fevai, но обращается к исходному, а не перегруженному методу. Используется при создании методов класса. Общий вид обращения: [yl,...,yn] = builtin('fun' , xl,....xk) Г) computer — вывод информации о компьютере. • сэтр = computer— в строковую переменную заносится pcwin, если компьютер работает под управлением операционной системы Windows. • [comp, maxsize] = computer— дополнительный ВЫХОДНОЙ аргумент maxsize содержит максимально допустимое число элементов массива в данной версии MATLAB. П eps — точность вычислений по умолчанию при использовании арифметических операций и ряда вычислительных функций. Некоторые функ Приложение 1. Основные команды и функции MATLAB и Toolbox 983 ции по умолчанию находят результат с меньшей точностью (см., например , разд. "Решение произвольных уравнений " главы 6). □ eval — выполнение содержимого строки или строковой переменной, как команды MATLAB (см. разд. "Формирование и исполнение команд, функция eval”главы 8), например: » eval('у = sin(x).*cos(x)') ИЛИ » у - eval('sqrt(log(1.2))*) eval (si, s2) — выполнение содержимого строки si, если в процессе выполнения возникает ошибка, то управление передается командам строки з2 (анало! конструкции try.. .catch). □ evaic— выполнение содержимого строки или сгроковой переменной, как команды MATLAB, результат возвращается в выходном аргументе, который является символьным массивом, примеры: Т = evaic(s), Т = evaic(si, s2) □ evalin — выполнение содержимого строки или строковой переменной, как команды MATLAB, с использованием переменных рабочей среды или локальных переменных вызывающей функции. • evalin('base', s) — выполнение содержимого строковой переменной s, как команды MATLAB, с использованием переменных рабочей среды. • evalin(’caller’, s)— выполнение содержимого строковой переменной s, как команды MATLAB, с использованием локальных переменных вызывающей функции. Аналогично с функцией eval могут быть заданы две строки: evalin('base', si, s2), evalin('caller', si, s2) □ feval — вычисление функции, имя которой задано в строке или в строковой переменной (см. разд. "Функции от функций"главы 8), например: [m, k] = fevalf'max', х). П flops — подсчет числа флопов (операций с числами с плавающей точкой). • f = flops — в переменную f заносится число выполненных к настоящему времени флопов. • flops (0) — обнуление счетчика флопов. П nargcnk — проверка количества входных аргументов, с которыми вызвана файл-функция. Используется внутри файл-функции 984 Приложения msg - nargchkilow, high, num) — занесение в строковую переменную msg сообщения об ошибке, если num больше high или меньше low. П nargin — определение количества входных аргументов, с которыми вызвана файл-функция (см. разд. "Условный оператор if главы 7). • num = nargin — в переменную num заносится число входных аргументов, с которыми была вызвана файл-функция. Используется внутри файл-функции. • num = nargin(’fun') — в переменную num заносится число входных аргументов, определенное для файл-функции с именем fun. Если fun является файл-функцией с переменным числом входных аргументов, го возвращается отрицательное число. □ nargout— определение количества выходных артументов, с которыми вызвана файл-функция (сл/. разд. "Проверка входных аргументов"главы 7). • num = nargout — в переменную num заносится число выходных аргументов, с которыми была вызвана файл-функция. Используется внутри файл-функции. • num = nargout ('fun') — в переменную num заносится число выходных аргументов, определенное для файл-функции с именем fun. Если fun является файл-функцией с переменным числом выходных аргументов, то возвращается отрицательное число. П raaimax — возвращает максимально допустимое в MATLAB вещественное положительное число. □ realmin— возвращает минимально допустимое в MATLAB вещественное положительное число. П varargin — определение переменного числа входных аргументов в заголовке файл-функции. Из массива ячеек varargin следует извлекать аргументы для их использования в файл-функции (см. разд. "Файл-функции с переменным числом аргументов" и "Массивыячеек"главы 8). Г1 varargout— определение переменного числа выходных аргументов в заголовке файл-функции. В массив ячеек varargout следует занести аргументы для возвращения файл-функцией их значений (см. разд. "Файл-функции с переменным числом аргументов"и "Массивыячеек"главы 8). Интерактивный ввод П input — запрос на ввод с клавиатуры. Используется при создании приложений с интерфейсом из командной строки (см. разд. "Приложения с интерфейсом из командной строки"главы 8). • р = inpur (1 Введите значение р') — ожидание ввода пользователем значения р с клавиат уры и занесение введенного значения в р. Приложение 1. Оснсвные команды и функции MATLAB и Toolbox 985 • name = input ('Введите Ваше имя', ’s') —ожидание ВВОДЯ пользователем строки с клавиатуры и занесение введенных символов в строковую переменную name. Вывод многострочного текста осуществляется при помощи п. Команда р = input('Выберите цвет: п 1-синий п 2-красный п 3-зеленый п’| приводит к появлению следующего текста в командном окне: Выберите цвет: 1-синий 2-красный 3-зеленый □ keyboard— передает управление клавиатуре, используется в М-файлах. Для продолжения работы М-файла следует набрать return в командной строке. П menu — вывод диалогового окна с возможностью выбора. Входными эргу ментами являются строки или строковые переменные. Первый входной аргумет определяет заголовок окна, а остальные— названия кнопок. Команда р = menu(’Выбор цвета', 'синий', 'красный', 'зеленый') приводит к появлению диалогового окна (рис. П1). Нажатие на кнопку синий заносит в р единицу и закрывает окно. Кнопки красный или зелёный соответствуют значениям два и три переменной р. Рис. Ш. Диалоговое окно выбора □ pause — приостанавливает выполнение М-файла. • pause — ожидание нажатия пользователем любой клавиши. • pause (t) — задержка выполнения команд на t секунд. 986 Приложения Объектно-ориентированное программирование и преобразование типов П class — создание объекта или определение, какому классу принадлежит объект. □ double — преобразование к двойной точности. □ inferiorto, superiorto — задание иерархии классов и методов. О inline — определение встраиваемой функции. □ inte, inti6, int32 — преобразование к целому числу со знаком. □ isa— проверка на принадлежность объекта классу. Использование ана-логично функции isobject. П loadobj — расширение функции load на объекты, определяемые пользователем. □ saveobj — расширение функции save на объекты, определяемые пользователем. П single — преобразование к одинарной точности. □ uinte, uintie, uint32 — преобразование к целому без знака. Функции даты и времени П calendar — календарь любого месяца года: • calendar — отображение календаря текущего месяца в командное окно в виде таблицы; • calendar (у, т) — отображение календаря месяца с номером m года у в командное окно в виде таблицы; • с = calendar— занесение дат текущего месяца в матрицу с размера шесть на семь; • с = calendar (у, т) — занесение дат месяца с номером ш года у в матрицу с размера шесть на семь. □ clock — получение даты и времени: с = clock— занесение в вектор с даты и времени в формате [год месяц день час минута секунда] □ cputime— вычисляет процессорное время с момента предыдущего обращения к данной функции. Примеры использования: Т = cputime; Приложение 1 Основные команды и функции MATLAB и Toolbox 987 • В = inv(hadamard(20)) ; • Т = cputime-T □ date — получение текущей даты, пример: str = date—- в строковую переменную str заносится текущая дата в формате 'дд-ммм-ггтг'. □ datenum— преобразование строки с датой в серийную дату (см. функцию now). П datestr —преобразование серийной даты (см. функцию now) в строку. П datevec— преобразование даты В формат [год месяц день час минута секунда]. Использование: с = datevec (d), [у, m, d, h, mi, s] = datevec (d) — ВХОДНОЙ аргумент может быть строкой с датой (результат date, datestr) или серийной датой (результат num, datenum). Задание массива дат во входном аргументе приводит к пол) ченню соответствующего преобразованного массива. □ eomday — завершающий день любого месяца года: d = eomdayfy, tn). □ etine —вычисление количества секунд во временном интервале. t=etime(tl,to) — возвращает время в секундах между tl и t2, которые представлены В формате [год месяц день час минута секунда]. П now — получение текущей даты и времени. d = now— информация о текущей дате и времени кодируется вещественным числом (серийная дата). □ tic, toe— запуск секундомера и вывод времени, набираются в одной строке, пример: » tic, В = inv(hadamard(20)); toe О weekday — возвращает день недели. [dnum, dname] = weekday (d) —В dnum заносится порядковый номер ДНЯ недели (начиная с воскресенья), а в строковую переменную dname — аббревиатура дня. Входной аргумент задается так же, как и в datevec. Двоичные и текстовые файлы П fclose — закрытие файлов (см. разд. "Текстовые файлы"главы 8). • status = fclose(fid) —закрытие файла с идентификатором fid. Если файл закрыт успешно, то staus=o. если нет, то staus=-i. • status - fclose ('all') — закрытие всех файлов, кроме файлов с идентификаторами о,1 и 2. 388 Приложения □ fopen— открытие файла и получение информации о файлах (см. разд. "Текстовые файлы"главы 8). • fid = fopen (filename, permission) — открытие файла С Именем filename, в переменную fid заносится идентификатор файла, который используется для указания на файл в других низкоуровневых функциях. Если файл не может быть открыт, то fid = -1. Аргумент permission означает способ доступа к файлу: О 1 г' — открытие двоичного файла для чтения; О г+' — открытие двоичного файла для чтения и записи; О ’ы’ — открытие нового двоичного файла для записи (если файл с таким же именем существует, то его содержимое будет удалено); О 'w+'— открытие нового двоичного файла для чтения и записи (если файл с таким же именем существует, то его содержимое 6} дет удалено); О ’ а' — создание нового двоичного файла или открытие существующего для записи, происходит добавление в конец файла: О *а+’ — создание нового двоичного файла или открытие существующего для чтения и записи, происходит добавление в конец файла; О ’ rt' — открытие текстового файла для чтения; О ' rt+' — открытие текстового файла для чтения и записи; О ’wt' — открытие нового текстового файла для записи (если файл с таким же именем существует, то его содержимое будет удалено); О ‘wt+' — открытие нового текстового файла для чтения и записи (если файл с таким же именем существует, то его содержимое будет удалено); О 'at' — создание нового текстового файла или открытие существующего для записи, происходит добавление в конец файла; О 'at+' — создание нового текстового файла или открытие существующего для чтения и записи, происходит добавление в конец файла. • [fid, message] = fopen(filename, permission) — если файл открыть не удалось (fid = -1), то строковая переменная message содержит дополнительную информацию. □ freed — чтение двоичных файлов. [A, count] = fread(fid, size, precision) —чтение ДВОИЧНЫХ данных из файла с идентификатором fid и запись их в матрицу а. Необязательный входной аргумент size задает размер матрицы, возможны значения: п — чтение п элементов в вектор-столбец (inf — до конца файла); Приложение 1. Основные команды и функции MATLAB и Тоо/Ьох 989 • [т п] — чтение в матрицу а по столбцам, size (А) = [m n], п может быть inf. Выходной аргумент count возвращает число считанных элементов. Чип считываемых данных определяется значением входного аргумента precision, который может принимать значения: • ’uchar' или 'unsigned char' —символ без знака, 8 битов; • 'schar' или 'signed char'— символ со знаком, 8 битов; • ' int8' или ' integer*!' — целое, 8 битов; • 'inti6'или 'integer*?'—целое, 16битов; • ' int32' или ' integer*^ ’ — целое, 32 бита; • 'int64' или'integer*8'—целое,64бита; • 'uint8' или 'integer*!'—целое без знака. 8 битов; • 'uintl6' или'integer*?'—целое без знака, 16 битов; • 'uint32 • или ' integer*4' — целое без знака, 32 бита; • 'uint64' или ’integer*8' —целое без знака, 64 бита; • 'single' или ’геа!*4' или 'float32' — вещественное с плавающей точкой, 32 бита; • 'double' или 'float64' или 'геа!*8' — вещественное с плавающей точкой, 64 бита. П fwrite — запись двоичных данных в файл count = fwrite (fid, a, precision) — запись элементов матрицы а по столбцам в файл с идентификатором fid. Использование precision такое же, как в f read. Выходной аргумент возвращает количество записанных элементов. О fgetl — получение следующей строки текстового файла без символа перевода строки (см. разд. "Открытие файла, считывание данных и закрытие файла " главы 8). line = fgetl (fid) — возвращает следующую строку файла с идентификатором fid в строковой переменной line. Если достигнут конец файла, то выходной аргумент равен -1. □ fgets — получение следующей строки файла с символом перевода строки. line = fgets (fid) — возвращает следующую строку файла с идентификатором fid в строковой переменной line, которая завершается символом перевода строки. Если достигнут конец файла, то выходной аргумент равен -1. d90 Приложения □ fprintf — форматный вывод в текстовый файл (см. разд. "Запись в текстовый файл"главы 8). П fscanf — чтение данных из текстового файла, записанных в определенном формате (см. разд. "Считывание информации из текстового файла" главы 8). □ feof — проверка достижения конца файла (см. разд. "Открытие файла, считывание данных и закрытие файла"главы 8). feof (fid) — возвращает единицу, если обнаружен конец файла, и ноль — в противном случае. □ terror — получение сведений об ошибках при работе с файлами. • message = terror (fid)—возвращает последнюю возникшую ошибку ввода-вывода при работе с файлом, идентификатор которого fid. • [message, errnum] = ferror(fid) —дополнительный выходной аргумент errnum, содержит номер ошибки. • f error (fid, 'clear') — очистка списка ошибок для файла с идентификатором fid. □ frewind — переход на начало файла. frewind(fid) — установка текущей позиции файла с идентификатором fid на начало файла. □ f seux — установка текущей позиции в файле. status = tseek(fid, offset, origin)—перемещение текущей позиции в файле с идентификатором fid на offset байт относительно origin. Допустимые значения offset и origin: • offset >0 — передвижение к концу файла; • offset = о — текущая позиция не изменяется; • offset <0 — передвижение к концу файла. • origin = 'bof' или -1 — смещение на offset байтов от начала файла; • origin = ' cof' или о — смещение на offset байтов от гекущей позиции; • origin = 1 eof' или 1 — смещение на offset байтов от конца файла. О f tell — получение текущей позиции в файле position = ftell(fid). □ eprintf, secanf — форматная запись данных в строку и форматное чтение данных из строки. Приложение 1. Основные команды и функции MATLAB и Toolbox 991 Использование sprintf и sscanf аналогично fprintf и fscanf, за исключением того, что результат помещается в строковую переменную, а не записывается в файл. О dlmread — чтение числовых данных с разделителями из текстового файла в матрицу. • м = dlmread(filename) — чтение чисел из текстового файла и занесение их в матрицу м. Элементы строк матрицы в текстовом файле должны быть отделены друг от друга запятой, а сами строки — символом перевода строки. • м = dlmread(filename, dim) — чтение чисел из текстового файла и занесение их в матрицу м. Элементы строк матрицы в текстовом файле должны быть отделены друг от друга разделителем, указанным в dim, например: м = dlmread(filename, ':'), а сами строки— символом перевода строки. Если элементы строки матрицы в файле разделены табуляцией, ТО следует применить вызов М = dlmread (filename, 't') - • М = dlmread(filename, dim, nrow, ncol) — чтение чисел из файла, начиная со строки с номером nrow и стобца ncol. Нумерация строк и столбцов в файле начинается с нуля. • М = dlmread (filename, dim, rng) — чтение прямоугольной области из файла в матрицу. Вектор rng задает область rng = [rowstart colstart rowend colend]. Возможно указание границ области в стиле MS Excel: rng = ’А5.. D4 ’. Если в текстовом файле между разделителями пропущено число, то соответствующие элементы матрицы будут равны нулю. □ dimwrite — запись содержимого матрицы в текстовый файл с разделителями. • dimwrite(filename, и) — запись элементов матрицы м через запятую в текстовый файл с именем filename. Строки матрицы в файле отделяются символом перевода строки. • dimwrite(filename, м, dim) — запись элементов матрицы м «ерез разделитель dim в текстовый файл, например, dimwrite(filename, м, ' #'). Если требуется разделить табуляцией элемен гы строки матрицы В файле, ТО следует применить ВЫЗОВ dimwrite (filename, м, t’}. • dimwrite (filename, М, dim, nrow, ncol) — запись матрицы M В файл, начиная со строки nrow и столбца ncol. Нумерация строк и столбцов в файле начинается с нуля. 992 Приложения Примечание Нулевые значения элементов матрицы пропускаются при записи в текстовый файл, соответствующие разделители добавляются для сохранения табличной структуры данных. П textread — импорт данных из текстового файла, имеющего табличную структуру. Примечание Для импорта данных из различных форматов можно также выбрать в меню File рабочей среды пункт Import Data и в появившемся диалоговом окне Import Wizard выбрать способ импортирования. [а, Ь, с, ...] = textread( filename, format)—чтение всех данных из файла с именем filename в массивы а, Ь, с и т. д. Число и тип переменных определяются спецификаторами форматов, указанных в строковой переменной или строке format: • %d— чтение целого со знаком, соответствующий выходной аргумент является вещественным массивом; • %nd — чтение п цифр целого со знаком; • %и — чтение целого числа, соответствующий выходной аргумент является вещественным массивом; • %nu — чтение п цифр целого числа; • %f —чтение вещественного числа, соответствующий выходной аргумент является вещественным массивом; • %nf — чтение п цифр вещественного числа; • %n.pf— чтение п цифр вещественного числа, из них р после десятичной точки; • %s— чтение строки, отделенной пробелами, символами табуляции или перевода строки (размечающими символами), соответствующий выходной аргумент является массивом ячеек; • 4ns — чтение п символов строки; • %q — то же, что и %s, но если строка заключена в кавычки, то в ячейки массива кавычки не заносятся; • 4nq — чтение п символов строки; • % с — чтение символов, в том числе и пробелов, соответствующий выходной аргумент является массивом символов; 11риложение !. Основные команды и функции MATLAB и Toolbox 993 • %пс — чтение п символов строки; • %[...] — чтение ст роки, которая содержит символы, заключенные в квадратных скобках, соответствующий выходной аргумент является массивом ячеек; • %['*.,.] — чтение строки, которая не содержит символы, заключенные в квадратные скобки, соответствующий выходной аргумент является масслвом ячеек. Все вышеперечисленные спецификаторы могут использоваться и для пропуска соответствующей позиции при считывании дачных, что достигается заменой символа % на %*. Следующий пример демонстрирует использование спецификаторов формата при чтении из текстового файла staff.dat с табличной структурой, содержимое которого приведено ниже. Баш 23 US 83.278 р231 Hike 24 UK 102.22 kl8N Требуется считать содержимое файла staff.dat: первое поле— в массив ячеек names, второе— в числовой массив аде, третье поле необходимо пропустить, а четвертое и пятое занести в числовой массив dat и массив ячеек code соответственно. Следующее обращение к textread приводит к образованию массивов и заполнению их нужной информацией. » [names, age, dat, code] = textread(’staff .dat1, ’%s %d i‘s %f %s ’ ) names = ‘Sam’ 'Nike' age = 23 24 dat = 83.2780 102.2200 code = 'p231' 'kl8N' Спецификатор формата может предваряться строкой, общей для полей файла. В этом случае указанная строка не счИ1Ывается, а происходит занесение следующих за ней данных в элементы подходящего по типу массива. Например, пусть в файле table.dat хранится информация: book part 4 pages400 article part2 pages20 Общие части полей part и pages, не под.[ежащие считыванию, указываются перед соответствующими специфика горами: » [kind, s, р] = textreadf'printed.dat', *%s parL%d pages%d') kind = book ’ 1 article' s - 4 2 P = 400 20 Функция textread позволяет указывать параметры, управляющие чтением из файла. Названия параметров и их значения задаются парами в конце списка входных аргументов: [...] = textread(..., paraml, valuel, param2, value2, ...) Возможно указание следующих параметров: • 'whitespace’ — вектор из символов, которые считаются размечающими. Допустимы значения ь (backspace), f (form feed), n (новая строка), r (символ возврата каретки), t (табуляция), (обратная косая черта), W ' или ' ’ (апостроф), %% (знак процента). По умолчанию установлен вектор 1[ь r n t]'; • 'delimiter' — символы, использующиеся в качестве разделителя (по умолчанию не установлены); • 'expchars' — символы, применяемые для экспоненциальной записи чисел. По умолчанию 'eEdD'; • 'bufsize' — максимальная длина строки в байтах (по умолчанию 4095); • 'headerlines — число пропускаемых строк от начала файла при чтении; • ’commentstyle’ — задание символов, определяющих пропуски при чтении. Возможны значения: 'matlab’ (игнорируются символы послед), 'shell' (игнорируются символы после#), 'с' (игнорируются символы между /* и */), ’с++’ (игнорируются символы после //). Приложение 1. Основные команды и функции MATLAB и Toolbox 995 Функции для работы с массивами ячеек Работа с массивами ячеек описана в разд. "Массивы ячеек" главы в. □ cell — создание пустого массива ячеек заданного размера. с = cell (п> — ячейки массива с размера п на п являются пустыми массивами. Возможно также создание прямоугольных массивоь ячеек и массивов произвольной размерности: cell (m, n), cell (m, n, p, ...), например: » A = ones(2, 6); >> C = cell(size(A)) C = I ] ( J ( ] ( 1 [ ] [ ] [ J •[ ] ( ) ( ] [ 1 [ ] П cellfun — применение функции к содержимому массива ячеек. • а = cellfun (fun, с)—вызов одной из нижеперечисленных функций от каждой ячейки массива с и запись результата в числовой массив а, причем size (А) - size (С). Входной аргумент fur. может быть: О ’isreal’ — если содержимое ячейки состоит из вещественных чисел, то в соответствующий элемент а заносится единица, и ноль — ‘ в противном случае; О 1 isempty' — если ячейка является пустым массивом, то в соответствующий элемент А заносится единица, и ноль — в противном случае; О ’ islogical' — если ячейка является логическим массивом, то в соответствующий элемент а заносится единица, и ноль— в противном случае; О 1 length' — элементы массива а, соответствующие каждой ячейке из с, принимают значения длин ячеек; О 'ndims' — число размерностей ячеек, в с помещаются в соответствующие элементы а; О 'prodofsize' — значения элементов массива А равны количеству элементов в ячейках массива с. Пример использования cellfun: » С = {ones(3, 5, 2) 'fsfhsfh',-... rand(10) strvcat('alsd', 'hhh')} C = [ jx5x2 double] 'fsfhsfh' [10x10 double] [2x4 char] 996 Приложения » А = cellfun('prodofsize', С) А = 30 7 100 8 • а = cellfun ('size', с, к)—в массиве а возвращаю гея размеры содержимого ячеек вдоль к-ой размерности, например, для определенного выше массива ячеек с: >> А = cellfun('size', С, 2) А = 5 7 10 4 • А — cellfun('isclass', С, classname) — логические единицы В массиве а соответствуют тем ячейкам, содержимое которых является объектом класса classname, Например, проверка ячеек инициализированного выше массива с на принадлежность классу char осуществляется так: » А = cellfun('isclass', С, 'char') А = О 1 0 1 Входной аргумент classname может также принимать значения 'double', sparse', 'struct', 'cell' или являться именем класса, определенного пользователем. □ cellstr— преобразование массива символов в массив ячеек (работа с массивами символов описана в разд. "Массивы строк" главы 8). с = cellstr (strmas) — ячейки массива с образуются из строк массива символов strmas, пример: >> strmas = ['аааааа'; 'bbbbbb'; 'сссссс']; » С - cellstr(strmas) С - 'аааааа' 'bbbbbb' 'сссссс' □ ceii2struct — преобразование массива ячеек в массив структур (работа с массивами структур описана в разд. "Массивы структур и массивы ячеек” г швы 8) Приложение 1. Основные команды и функции MATLAB и Toolbox 997 struct = cell2struct (с, fields, dim) —содержимое ячеек массива с (вдоль размерности dim) записывается в поля структур массива struct. Названия полей определяются элементами массива fields, который может быть либо массивом симвопов, либо массивом ячеек из с^юк. Пример использования се112struct: » С = {'March' 12 '10-30'; 'April' 26 '17-45'; 'May' 10 '12-00'}; » fields = {'Month' 'Day' 'Time'}; » struct = cell2struct(C, fields, 2) struct = 3x1 struct array with fields: Month Day Time » struct(1) ans = Month: 'March' Day: 12 Time: '10-30' Неправильное указание размерности, вдоль которой происходит преобразование, приводит к несоответствующему преобразованию массива ячеек в массив структур (в случае совпадения числа элементов в fields с длиной с вдоль данной размерности): » struct = cell2struct(С, fields, 1); » struct(1) ans = Month: 'March' Day: 'April' Time: 'May' В случае несовпадения числа полей в fields и размера с вдоль dim выводится сообщение об ошибке: » fields = {'Month' 'Day'}; » Struct = cell2struct(C, fields, 2); ??? Error using ==> cell2struct Number of field names must match number of fields in new structure. 998 Приложения □ cexidisp — вывод содержимого массива ячеек в командное окно. • ceiidisp(c) — последовательный вывод содержимого каждой ячейки массива с: » С = {'Мау' 10 ones (2)},- » celldisp(C) С{1} = Мау С{2} = 10 С{3> = 1 1 1 1 • celldisp(C, name) — при выводе имя массива заменяется на строку name. □ cexipiot— отображение содержимого массива ячеек в графическом окне (см. разд. "Массивы ячеек " главы 8). Информация о соответствии цвета типу содержимого ячейки выводится при указании второго дополнительного входного аргумента: cellplot(С, 'legend'). □ num2ceii — преобразование числового массива в массив ячеек. • с = num2ceii (А) — элементы числового массива а помещаются в отдельные ячейки массива с, например: » А = [1 2 3 4; 5 б 7 8] ; » С = num2cell(A) С = [1] [2] [3] [4] [5] [6] [7] [8] Размеры образующегося массива ячеек с совпадают с размерами а. • с = num2ceii(A, dim) — числа массива а вдоль размерности dim помещаются в отдельные ячейки: » С = num2cell(А, 2); » celldisp(C) С{1} = 12 3 4 С{2) = 5 6 7 8 Приложение 1, Основные команды и функции МАТ1 АВ и Toolbox 999 Функции для работы со структурами Работа со структурами и массивами структур описана в разд. "Простые структуры" и "Массивы структур и массивы ячеек" главы 8. П deal — копирование одних переменных в другие, или запись содержимого одной переменной в несколько. Данная функция оказывается полезной для организации доступа к полям массивов структур. Ниже приведены варианты вызова deal с примерами. • [s.field] = deal(x) — присвоение значения х полям field структур массива s, например: [s.name] = deal ('Bill1) - Если массив структур s не существует, то следует использовагь обращение: [S(l:n) .name] = deal ('Bill'), где n— число структур в создаваемом массиве s. • [С{:}] = deal (s. field)—копирование значений полей field структур массива s в массив ячеек с. Если массив ячеек с не существует, то следует использовать обращение: [C(l:n).name] = deal (S. field), где n — число ячеек в создаваемом массиве с. • [а, ь, с, ...] = deal(s.field)— копирование значений полей field структур массива S в отдельные переменные а, Ь, с, ... □ fieldnames — получение названий полей структуры. с = fieldnames (S) — массив ячеек из строк с содержит имена полей структур массива s (работа с массивами ячеек описана в разд. "Массивы ячеек " главы 8). Например: » S(l).name = 'Bill'; » S(1}.age = 30; » S(2).name = 'Smith'; » S(2).age = 32; » C = fieldnames(S) C = 'name' ' age' □ getfieid — получение содержимого определенных полей структуры. f = getfieid(s,' field’j — возвращает содержимое полей с именем field структуры s. Входной аргумент s должен быть структурой, а не массивом, т. е. size (S) = [1 1]. Например, для структуры s, определенной выше, следует вызывать getfieid в цикле for: S(l).name = 'Bill'; S(1).age = 30; 1000 Приложения S (2) .name = 'Smi th'; S(2).age - 32; for i=l:2 fage(i)=getfield(S(i),’age') ; enJ fage В командное окно выводится fage = 30 32 Запись значений одноименных полей следует согласовывать с типом массива, в который заносится результат. Например, попытка выполнения цикла for i = 1: 2 f(i) = getfield(S(i), 'name'); end приведет к ошибке, поскольку строки в полях name имеют разную длину, и образовать из них символьный массив не удается. Выход состоит в занесении значений полей в массив ячеек for i = 1:2 fn^me{i} = getfield(S(i), 'name'); end □ rmfieid — удаление полей структуры. s = rmfield(s, 'field') — удаление поля с именем field из структур массива s, например, для заполненного выше массива s, поле name удаляется при помощи обращения: » S = rmfield(S, 'name') S = 1x2 struct array with fields: age structure array S. Возможно удаление сразу нескольких полей: s = rmfield(s, f), здесь f должен быть массивом символов или ячеек из строк и содержать имена удаляемых полей (работа с массивами символов описана в разд. "Массивы строк" главы 8, а с массивами ячеек в разд. "Массивы ячеек” г павы 8). Приложение 1. Основные команды и функции MATLAB и Toolbox 1001 □ setfield — присвоение значения полю структуры. s = setfield(S, 'field',v) — в поле с именем field структуры S заносится значение переменной v. Входным аргументом s должна быть именно структура, а не массив, т. е. size(S) = [11]. Заполнение массива структур производится при помощи цикла (см. getfield). □ struct — создание структур и массива структур. Общий вид обращения к struct выглядит следующим образом: S = struct(1fieldl', vail, 'field2'r val2,..,). Размеры выходного аргу мента s определяются способом указания значений vail, val2,... полей fieldl, field2, ... >> myS = struct('month','May','dat',10,'time','12-00') myS = month: 'May' dat: 10 time: '12-00' Если vail, val2,... являются массивами ячеек одинаковой длины, то в результате s будет массивом структур: >> myS = struct('month', {'May' 'June'}, 'dat', {10 12},... 'time', {'12-00' '23-30'}); » myS(1) ans = month: 'May' dat: 10 time: '12-00' » myS{2) ans = month: 'June' dat: 12 time: '23-30' Указание в качестве значения vail, val2 и т. д. одной ячейки приводит к заполнению данным значением полей всех структур выходного массива, например: >> mySl = struct('month', {'May'}, 'dat', {10 12}, ’time',... {'12-00' '23-30'}); 1002 Приложения » mySl(l).month ans = May » myS? (2).month ans ‘ May □ struct2ceii — преобразование массива структур к массиву ячеек (работа с массивами ячеек описана ьpaid. "Массивы ячеек"главы 8). с = struct2celi (s) — содержимое полей структур массива s заносится в ячейки массива с. Если входной аргумент имеет размеры size(S) = [m п] и каждая структура массива s состоит из р полей, то size(S) = [р m п]. » S(l,l) = struct('name', ' Sam' , 'age'r 16) >> S(l,2) = struct('name’, 'Nik', *age’, 18) >> S(l,3) = struct('name', 'Dan', 'age', 17) » S S = 1x3 struct array with fields: name age >> C=struct2cell(S) C{:,:,1) = ’ Sam' I 16] C( :,2) = Nik' [ 18] C(:,:,3) = ' Dan’ [ 17] » size(C) ans - 2 1 3 Положение 1. Основные команды и функции MATLAB и Toolbox 1003 Звуковые и графические файлы Чтение, запись и преобразование звуковых данных □ lin2mu — мю-кодирование. Ми = 11п2ши(у) — логарифмическое кодирование сигнала с амплитудой от -1 до 1, записанного в вектор у. Элементами вектора mu являются целые числа из диапазона [0, 255]. □ mu2iin — обратное по отношению к lin2mu преобразование. у = mu2iin(mu) — входной аргумент (вектор с целыми числами от 0 до 255) преобразуется в вектор у, элементы которого принадлежат интервалу [-32124/32768, 32124/32768]. □ sound — воспроизведение звука. • sound (у, fs) — воспроизведение дискретизованного звукового сигнала у с частотой дискретизации fs. Амплитуда у должна принадлежать [-1,1]. Значения с большей амплитудой усекаются до -1 или 1. Размер size (у) = [п 2] отвечает стереофоническому звуку. • sound (у) — воспроизведение сигнала с частотой дискретизации, равной по умолчанию 8192 Гц. • sound (у, fs,bits) — воспроизведение сигнала с частотой дискретизации f s и разрядностью bits. □ soundsc — воспроизведение звука с предварительным масштабированием. • sound(y, fs), sound(y), sound(y, bits) — работают аналогично sound, но амплитуда сигнала предварительно масштабируется и приводится к отрезку [-1,1] так, чтобы звук был максимальной громкости без усечения амплитуды (т. е. без потери качества). • soundsc(у, ..., slim) — проигрывание звукового сигнала с предварительным масштабированием к [-1,1] тех значений у, которые принадлежат отрезку, заданному вектором slim = [slow shigh]. □ wavread — считывание звука из WAV-файла. • у = wavreadt filename) — в массив у заносятся амплитуды отсчетов (масштабированные к [-1,1]) дискретизованного звука из WAV-файла с именем filename. Вектор у соотве гствует монофоническому звуку, а 1004 Приложения матрица с двумя столбцами — стереофоническому, первому каналу отвечает у (:, 1), второму — у (:, 2). • [у, fs, nbits] = wavread(filename) —В дополнительных ВЫХОДНЫХ параметрах содержится информация о дискретизованном звуке (см, функцию sound). • [...]= wavread( filename, n) — считывание первых п сэмплов каждого канала из WAV-файла filename. • [..,]= wavread(filename, [nl n2])—считывание сэмплов от nl до п2 каждого канала из WAV-файла filename. • siz = wavread(filename, 'size')—возвращает размер дискретизованного звука, записанного в файле filename. Выходной аргумент являемся вектором, первый элемент которого равен числу сэмплов, а второй — числу каналов. • [у, fs, nbits, opts] = wavread(...) — возвращает сэмплы в массиве у, частоту дискретизации в fs, разрядность в bits и структуру opts, поля которой содержат информацию о формате файла. □ wavwrite — запись звуковых данных в формате WAV. • wavwrite(у, fs, nbits, wavefile)—В WAV-фаЙЛ С Именем filename записываются звуковые данные из массива у. Частота дискретизации указывается в fs (в Гц), а разрядность в bits (допустимы только значения 8 и 16). Стереофонический звук представляется массивом размера size(y) = [n 2]. Значения амплитуды должны принадлежать отрезку [-1,1], остальные значения усекаются до -1 или 1. • wavwrite(у, fs, wavefile) — запись по умолчанию происходит с разрядностью 16 битов. • wavwrite (у, wavefile) — запись по умолчанию происходит с разрядностью 16 битов и частотой дискретизации 8192 Гц. Г рафические файлы □ imf info — получение информации о графическом файле. info = imfinfo (filename, fmt) — возвращает структуру, содержащую информацию о графическом файле с именем filename и типом fmt (работа со структурами описана в разд. "Простые структуры"главы 8). Поддерживаются широко используемые форматы файлов, которым соответствуют следующие значения входного аргумента fmt: 'bmp’, 'jpg’ (или ’jpeg'), 'рсх', 'png', 'tif (или 'tiff'). Следует иметь в виду, что Приложение 1. Основные команды и функции MATLAB и Toolbox 1005 если файл в формате TIFF содержит несколько изображений, то информация возвращается в массиве структур. Доступ, к свойствам, например, второго изображения производится при помощи указания номера структуры массива: info (2) (работа с массивами структур описана в разд. "Массивы структур"главы 8). Первые девять полей структуры не зависят от формата графического файла и содержат следующую информацию: • Filename — строка с именем файла, если файл находится не в текущем каталоге, то в строку заносится полное имя; • FileModDate — строка со временем последнего изменения файла; • Filesize — размер файла в байтах; • Format —- строка из трех символов, содержащая формат файла; • Formatversion — строка или числовая переменная с версией формата; • width — ширина изображения в пикселах; • Height — высота изображения в пикселах; • BitDepth — глубина цвета (бит/пиксел); • ColorType— тип изображения: ’truecolor', 'grayscale' или 'indexed1. Остальные поля структуры info зависят от формата представления изображения. Формат файла можно не указывать: info = imfinfo(filename). В этом случае функция imfinfo пытается определить формат хранения графических данных, исходя из структуры файла. О imread — чтение графической информации из файла в массив или массивы MATLAB. • а = imread(filename, fmt) —запись в массив А графической информации из файла с именем filename формата fmt (см. функцию imfinfo). Размерность массива а зависит от типа изображения. Если файл содержит изображение в оттенках серого (функция infinfo возвращает ’grayscale' в поле ColorType), то а является двумерным массивом. Размеры массива определяются шириной и высотой изображения. Если info = imfinfo!filename, fmt), TO size(A) = [info.Height info.width]. Цветное изображение (функция infinfo возвращает 'truecolor1 в поле ColorType) заносится в трехмерный массив А, size (А) = [info.Height info.width 3]. Третье измерение представляет информацию о цвете: A (i, j, :) = [RGB]. 1006 Приложения • [А, мар] - imread]filename, fmt)—запись в массив А графической информации из файла с индексированным цветом. Массивы а и мар являются двумерными, причем значения мар масштабированы от нуля до единицы. Формат 1рафических данных можно не указывать. Функция imread пытается определить формат хранения графических данных и считать их, исходя из структуры файла. П imwrite — запись графических данных из матрицы в файл. • imwriteJa, filename, fmt) — запись графических данных, содержащихся в матрице а, в файл с именем filename типа fmt (см. функцию imfinfo). Если тип массива А есть double array, а его элементы имеют значения от нуля до единицы, то происходит предварительное преобразование к 8-битовым целым числам. Указание массива а класса unite приводит к получению изображения либо в оттенках серого, либо цветного, в зависимости от размерности массива (см. функцию imread). • imwrite (A, map, filename, fmt)—запись индексированных графических данных, содержащихся в матрицах а и мар в файл с именем filename Типа fmt (см. функцию imfinfo). Если А есть double array, то он предварительно преобразовывается: а = unite (А - 1). Если а класса unite или unitie, то преобразования не происходит. Массив мар должен являться цветовой палитрой, поддерживаемой MATLAB. Формат графических данных можно не указывать. Функция imwrite выбирает формат, исходя из расширения файла, указанного в filename. Запись в графические файлы форматов TIFF, JPEG и PNG может потребовать установки дополнительных параметров. В данном случае используется ВЫЗОВ imwrite вида imwrite(..., paraml, vail, param?, val2, ...). Формат JPEG позволяет указать один параметр 'Quality', определяющий качество изображения. Значением 'Quality' может быть число от единицы до ста, причем ббльшие значения соответствуют лучшему качеству при сжатии изображения (соответственно увеличивается размер файла). Запись в формате TIFF управляется тремя параметрами: • ’Compression' —значения: 'none', 'packbits', 'ccitt'; • ' Description' — СТрОКЭ С описанием файла (см. поле ImageDescription выходного аргумента imfinfo); • 'Resolution'—вектор [XResolution YResolution]. Приложение 1 Основные команды и функции MATLAB и Toolbox 1007 Операции со строками См. разд. "Работа со строками"главы 8. Обработка строк П deblank — удаление пробелов в конце строки (см. разд. "Массивы строк" главы 8). • snew = deblank(s) — удаление пробелов в конце строки или строковой переменной s. • masnew = deblank (mas) — удаление пробелов в конце каждой строки массива ячеек из строк mas (работа с массивами ячеек описана в разд. "Массивыячеек"главы 3). П findstr— поиск подстроки в строке (см. разд. "Сервисные функции для работы со строками"главы й). k = findstr (si, s2) —выходной аргумент вектор к содержит позиции, с которых подстрока начинается в строке. Входными аргументами si и s2 являются строки или строковые переменные. Подстрокой считается входной аргумент меньшей длины. П lower— преобразование в строчные буквы (см. разд. "Сервисные функции для работы со строками"главы 8). snew = lower (s) — преобразование символов строки s в строчные буквы. Допускается применение функции lower к массиву ячеек, состоящих ИЗ строк (СМ, функцию deblar.k). П strcat — сцепление строк (см. разд. "Ввод и сцепление строк"главы 8). s = strcat (si, s2, s3, ...)—горизонтальное сцепление строк si, s2, s3,... и запись результата в строку s. Завершающие пробелы в каждой сцепляемой строке игнорируются. Если входные аргументы являются массивами символов, то выходной аргумент также массив символов. Указание в качестве входных аргументов массивов ячеек из строк приводит к образованию нового массива ячеек из строк (работа с массивами ячеек описана в разд. "Массивы ячеек" главы 8). Каждая ячейка нового массива содержит результат сцепления строк, входящих в соответствующие ячейки каждого из массивов. Массивы должны быть одинаковых размеров, например: >> S - strcat({'Мау’, 'June'}, {'12', '23'}) S = 'Мау121 1June231 1008 Приложения Допустимо указание массива, состоящего из одной ячейки: » S = strcat({'Мау', 'June'}, {'12'}) S - 'Мау12' 'Junel2' □ strcmp — сравнение ст рок (см. разд. "Сервисные функции для работы со строками " главы 8). flag = strcmp(sl, s2) — возвращает единицу в случае совпадения строк sl и s2, и ноль — в противном случае. Входными аргументами могут быть массивы (одинаковых размеров) ячеек из строк (работа с массивами ячеек описана в разд. "Массивы ячеек" главы 8). В данном случае выходной аргумент является массивом тою же размера, что и исходные, состоящий из единиц и нулей, например: » flag = strcmp({'MaylO', 'Мау14‘, 'JuneOZ'} , ... {'Mayll', ’Mayl4', 'JuneOZ'}) flag = Oil Если один из входных массивов имеет размер, равный единице (или является строкой или строковой переменной), то происходит поэлементное сравнение: >> flag = strcmp({'MaylO', 'Мау14', ’June02'}, {'Мау14'}) flag = 0 10 □ strcmpi — сравнение строк, прописные и строчные буквы не различаются. Использование strcmpi аналогично strcmp. □ str just — выравнивание элементов в строке. • news = strjust(s) ИЛИ news = strjust(s, 'right') —выравнивание no правому краю: » news = strjust(‘ text ') news = text • news = strjust(s, 'left')—выравнивание по левому краю: » news = strjust(' text ', 'left') news = text Приложение 1. Основные команды и функции MATLAB и Toolbox 1009 • news = strjust(s, 'center')—выравнивание по центру: » news = strjust{' text ', 'center') news = text □ strmatch— поиск в массиве символов или ячеек из строк совпадений с заданной строкой (см. разд. "Массивы строк"главы 8). • k = strmatch (str, MAS) — поиск в массиве символов или массиве ячеек из строк mas строки, начинающейся с str. Выходной аргумент к является массивом с номерами подходящих строк в mas. • k = strmatch(str, mas, 'exact')— возвращает номера строк из mas, в которые str входит как целая строка: » k = strmatch)'Ma', {'March', 'April', 'May'}) к = 1 3 » к = strmatch(’Ma', {'March', 'April', 'May'}, 'exact') к = [ ] □ strncmp — сравнение первых n символов двух строк (см. разд. "Сервисные функции для работы со строками" главы *?). flag = strncmp(sl, s2, n) — возвращает единицу, если первые п символов в строках si и з2 совпадают, и ноль — в противном случае. Входными аргументами могут быть массивы (одинаковых размеров) ячеек строк. В данном случае возвращается массив из нулей и единиц, единицы соответствуют строкам, первые п символов которых совпадаю^, например: » flaci = stmcmp) {'March', 'April', 'May'},... {'May', 'May', 'May'), 2) flag = 10 1 □ strrep — замена в строке одной подстроки на другую (см. разд. "Сервисные функции для работы со строками"главы 8). new = strrep (str, subold, subnew) — замена в строке str подстрок subold на подстроки subnew. Входные аргументы могут быть массивами (одинакового размера) ячеек из строк, например: » new = strrep({'March', 'April', 'May'},... {'ar', 'pr', 'ay'}, {'AR', 'PR', 'AY'}) 1010 Приложения strnew = 'MARch' ’APRil* ’MAY* Возможно указание массива из одной ячейки в качестве входного аргумента: >> strnew = strrep({'March’, 'April', 'May'},... {'ar', 'pr', 'ay'}, {'###'}) strnew - 'M###ch' ’A###il’ 'M###' ИЛИ » strnew = strrep({'March', 'April', 'May'}, {'Ma'}, {'##'}) strnew = '##rch' 'April' '##y' ИЛИ » strnew = strrep({'March', 'April', 'May'},... {'Ma'}, {’##', '**', '&&'}) strnew = ##rch' 'April' '&&y' □ strtok — поиск первой подстроки, отделенной пробелами в строке. • tok = strtok (str)—возвращает в строковой переменной tok первую подстроку из строковой переменной или строки str, отделенную пробелами или табуляцией. Пробелы (табуляция) справа и слева игнорируются, например: » tok = StrtokC ABC DEFG Н') tok = АВС • tok = strtok (str, delim)—возвращает в строковой переменной tok первую подстроку из строковой переменной или строки str, отделенную одним из символов, входящим в delim: » tok = strtok('ABC-DEFG H‘, '-') tok = ABC • [tok, rem] = strtokt...) — второй дополнительный аргумент содержит остаток строки после tok: » [tok, rem] = strtok('ABC-DEFG H', '-') tok - ABC Приложение 1, Основные команды и функции MATLAB и Toolbox 1011 rem ~ -DEFG Н Г) etrvcat — вертикальное сцепление строк. mas = strvcat(strl, str2, str3, ...}— формирование двумерною массива символов, каждая строка которого содержит strl, str2, str3,... ('троки mas автоматически дополняются пробелами до нужной длины. » mas = strvcat('March', 'April', 'May') mas = March April May » whos spring Name Size Bytes Class spring 3x5 30 char array П upper — преобразование в прописные буквы. snew = upper (s) — преобразование символов строки s в прописные буквы. Допускается применение функции upper к массиву ячеек, состоящих из строк (см. функцию deblank). Поеобразования "строка-число" □ char — получение символа по ASCII-коду и создание массива символов или строки. • ch = char (code) —преобразование массива code, содержащего целые числа, в массив символов. Целые числа от 32 до 127 соответствуют печатаемым символам: » ch = char(32:127); » ch(1:70) ans = I "#$%&’()*+,- ./0123456789:;<=>?@ABCPEFGHIJKLMNOPQRSTUVWXY2[]Л_"abcde » ch(71:end) ans = fghijklmnopqrstuvwxyz{|}~ Символы, соответствующие целым числам, ббльшим 127, зависят от шрифта, установленного в командном окне. Например, для шрифта Courier 33 Зм. 130 1012 Приложения » ch = char(224:256) ch = абв гдежзийклмнопрстуфхцчшщъыьэюя Входным аргументом может быть массив ячеек из строк mas, в этом случае функция char образует из каждой строки ячейки mas строку символьного массива chinas (работа с массивами ячеек описана в разд. "Массивы ячеек " главе 8). • chmas = char (si, s2, s3, ..) — формирование массива символов chmas из строк или строковых переменных si, s2, s3,... Каждая строка дополняется пробелами справа для приведения к одинаковым размерам. Пустые строки, указанные во входных аргументах, учитываются при конструировании массива символов (см. разд. "Массивы строк"главы 8). Пример: » chmas = char (' AAAAJiAAAAAAA1 , ''ВВВВВВВВВ') chmas = aaaaaa/uJaa;. ВВВВВВВВВ Входные аргументы могут быть массивами символов- >> chmasl = charf'AAAA', 'ВВ'); » chmasZ = char('CCC', 'DDDDDD'); » chmas = char(chmasl ,chmas2) chmas = АААЛ BB ccc DDDDDD □ mt2str — преобразование чисел в массив символов. chmas = int2str (А) — округление элементов матрицы а и запись результата в массив символов. □ mat2str — преобразование матрицы в строку. • str = mat2str (А) — строковая переменная str содержит представление матрицы а в том виде, в котором матрица задается из командной строки или в М-файле, например: » А = pi*eye(2); » str = mat2str(A) Г 1риложзние 1. Основные команды и функции MATLAB и Toolbox 1013 str = [3.14159265358979 0;0 3.14159265358979] При преобразовании матрицы в строку округления элементов матрицы не происходит. • str = mat2str (А, и) — округление до п цифр после десятичной точки. □ num2str— преобразование матрицы в массив символов (см. разд. "Простой пример. программа-калькулятор"главы 8). • chinas = num2str(A) — элементы строк малицы а образуют строки массива символов chinas. Удерживаегся четыре цифры после десятичной точки и при необходимости используется экспоненциальная форма записи числа (аналогично формату short е). • chinas = num2str (А, п) — округление происходит до п цифр после десятичной точки. • chmas = num2str(A, format) — форматное преобразование, строка format формируется из спецификаторов аналогично sprintf. □ sprintf — форматная запись в строку. • str = sprintf (format, А) — конструирование строки str из вещественных данных, содержащихся в матрице А, на основе формата, который указан в строке format. Спецификаторы формата аналогичны тем, которые используются в fprintf (подробная информация о форматной записи в файл с примерами использования содержится в разд. "Текстовые файлы"главы 8). Пример использования sprintf: » А = [1.1 3.2; 0.7 -4.2]; » str - sprintf(’а=%8.Id b=%8.ldnc=%8.Id d=%8.1d', A) str - a = l.le+000 b = 7.0e-001 c = 3.2e+0D0 d = -4.2e+000 • [str, errmsg] = sprintf (format, A) — если при форматной записи произошла ошибка, то выходной аргумент errmsg содержит соответ ствующее сообщение. □ sscanf — чтение данных из строки или строковой переменной в заданном формате. Использование sscanf во многом схоже с fscanf, за исключением того, что считывание производится из строки, а не из файла (см. разд. "Текстовые файлы"главы 8). 1014 Приложения П str2doubie — преобразование чисел, записанных в строках, в числовой массив. • а = str2doubie (str) — из строки str извлекается число и заносится В переменную а. Строка str может содержать цифры, точку, знаки плюс или минус, символ е или 1 и запятую для разделения знаков тысяч, например: » а = str2double( ' 1, 485,000.00') а = 1485000 » а = str2double('-1. 2е-21) а = -0.0120 » а = str2double('-2 + 3*i') а = -2.0000 + 3.00001 Если строка не может быть преобразована в число, то возвращается NaN. • А = str2double (masstr) — содержимое массива ячеек из строк masstr преобразуется в элементы числового массива а того же размера, что и masstr (работа с массивами ячеек описана в разд. "Массивы ячеек" главы 8). Пример: » А = str2double({1-7' '3*i' 'FFF' '3.19'}) А = -7.0000 0 + 3.00001 NaN 3.1900 О str2num — преобразование массива символов в массив чисел (см раза "Простой пример, программа-калькулятор"главы 8). А = str2num (chmas) — строки массива символов chinas должны состоять из тех же символов, что и в str2double, например: » chmas = ['1.3 0.4 3 + 2*i'; '1 - 3*i 29 0.05']; » А = str2num(chmas) A = 1.3000 0.4000 3.0000 + 2.0000i 1.0000 - 3.0000i 29/0000 0.0500 Если строки в chmas не могут быть преобразованы в числа, то возвращается пустая матрица а. Пробелы в строках chmas существенны и определяют количество элементов в А, например: Приложение 1. Основные команды и функции MATLAB и Tootbox 1015 » А = str2num('-l - 21') А = -1.0000 - 2.00001 » А = str2num('-l - 21') А = -1.0000 О - 2.00001 Преобразование системы счисления □ Ып2с1ьс— преобразование строки с двоичным числом в десятичное число, например: » а = hin2dec('1110001101010 *) а = 7274 □ dec2bin — преобразование десятичного числа в строку с двоичным представлением, например: » str = dec2bin(7274) str = 1110001101010 Входной аргумент может быть только целым неотрицательным числом, не превосходящим 252, □ deckhex— преобразование десятичного числа в строку с шестнадцатеричным представлением, например: » str = dec2hex(7274) str = 1С6А Входной аргчмент может быть только целым неотрицательным числом, не превосходящим 252. □ hex2dec — преобразование строки с шестнадцатеричным представлением в десятичное число, например: » а = hex2dec('1С6А') а - 7274 □ hex2num— преобразование шестнадцатеричного представления вещественного числа двойной точности (в стандарте IEEE) в число: » format long » а = hex2num(411а243774442а28') 1016 Приложения 4,203О18635412776е+ОО5 Строка, длина которой меньше шестнадцати, дополняется нулями справа. Если входной аргумент является массивом строк, то обрабатывается каждая строка и результат записывается в вещественный массив. Работа с матрицами и массивами Работе с матрицами посвящено достаточно много глав и разделов книги (см., например, главу 2, разд. "Задачи линейной алгебры"главы 6, главу 15). Создание матриц и массив ов Г) bikdiag — конструирование блочно-диагональных матриц. м = bikdiag (А, в, с)—занесение в м блочно-диагональной матрицы; о о с О В О А О О м = □ compan — создание сопровождающей матрицы. а = compan (v) — возвращает сопровождающую матрицу для полинома, заданного вектором коэффициентов v. □ eye — создание единичной матрицы. • т = eye (nj—г содержит квадратную единичную матрицу размера n. • I = eye (m, n) — i содержит прямоугольную матрицу размера ш на п с единицами на главной диагонали. □ gallery — функция, позволяющая получать более пятидесяти различных стандартных матриц. Использование: [Al, А2, ...] = gallery(name, pl, р2, ...J Как правило, pl и р2 задают размеры матрицы, и функция вызывается с одним выходным аргументом, возвращающим матрицу. Аргумент name является именем матрицы, например 'cauchy', 'oithog'. □ hadamard— создание матрицы Адамара, например, н = hadamard (п). □ hankei — создание матрицы Ганкеля, например, н = hankei(n). □ hiib — создание матрицы Гильберта, например, н = hiib(n). Приложение 1. Основные команды и функции MATLAB и Toolbox 1017 □ invhxib — вычисление матрицы, обратной к матрице Гильберта, например, н = invhilb(n). О linspace — генерация вектора, значения элементов которого изменяются с постоянным ша^ом (см., например, разд. "Решение граничных задач" главы 6). • v = linspace (а, Ь)—в вектор v заносится 100 значений от а до ь. • v = linspace (а, Ь, п) —в вектор v заносится п значений от а до ь. □ logspace — генерация вектора, значения элементов которого изменяются с постоянным шагом в логарифмической метрике (см., например, разд. "Перманентные переменные"главы 8). • v = logspace (a, b)—в вектор v заносится 50 значений от 10а до 10ь. • v= logspace (а, ь, п)—в вектор v заносится п значений от 10d до Юь. П magic — со здание "магического квадрата". м = magic (п) — квадратная матрица м размера п, состояшая из чисел от 1 до п2, обладает следующим свойством: сумма элементов любой строки совпадает с суммой элементов любого столбца и диагонали. □ ones — создание массива, элементы которого являются единицами. • а = ones (п) —а содержит квадратную матрицу из единиц размера п. • а = ones (m, n) — а содержит прямоугольную матрицу размера m на п, состоящую из единиц. • а = ones (m, n, k) — а содержит ма< сив трех измерений размера m на п на к, состоящий из единиц. Допускается создание массивов большего числа измерений. □ pascal — генерация матрицы Паскаля, например, р = pascal (п). Структура матрицы соответствует треугольнику Паскаля. П rand — создание массивов равномерно распределенных случайных чисел. Использование аналогично ones. О randn— создание массивов, состоящих из чисел, распределенных по нормальному закону. Использование аналогично ones. □ toepiitz — создание теплицевой матрицы, элементы которой равны вдоль каждой из диагоналей. • т = toepiitz (с, г) — создание несимметричной теплицевой матрицы при помощи вектор-столбца с и вектор-строки г. • т = toepiitz (г) —создание симметричной теплицевой матрицы при помощи вектор-строки г. 1018 Приложения □ zeros — создание массивов, состоящих из нулей. Использование аналогично ones. □ Wilkinson — создание матрицы Уилкинсона, ко горая имеет близкие пары собственных значений. Операции с массивами □ cat— сцепление массивов, соответствующие размеры должны совпадать. Если айв матрицы, то возможны следующие варианты вызова cat; • м = cat(l, а, в}— сцепление айв вдоль первого измерения (массивы айв расположены в столбик); • м = cat (2, а, в) — сцепление айв вдоль второго измерения (массивы айв расположены в строку); • м = cat(3, а, в)—образование трехмерного массива. □ diag — выделение диагонали и конструирование диагональной матрицы. • А = diag(а) — создание диагональной матрицы а, на диагонали которой стоят элементы вектора а. • а = diag (а, к) — создание диагональной матрицы а, на побочной к-ой диагонали которой стоят элементы вектора а. • а = diag (А) — выделение диагонали матрицы а в вектор а (см. разд. "Создание матриц специального вида " главы 2). □ flipir— перестановка столбцов матрицы слева направо, возвращает измененную матрицу. □ flipud— перестановка строк матрицы сверху вниз, возвращает измененную матрицу. О repraat — создание блочной матрицы или многомерного блочного массива из одинаковых блоков. • М = repmat i'A,m,n) — матрица М состоит из m блоков по вертикали и п по горизонтали, каждый блок является матрицей а. • М = repmat (A, [m п])—аналогичном = repmat (А, т, п). • м = repmat (а, [т п р ...])— конструирование многомерного блочного массива. □ reshape —- изменение формы матрицы или массива. • а = reshape(х, т, п)—формирование матрицы m на п из элементов массива х длины m*n. Элементы х выбираются последовательно, образуя столбцы А. Приложение 1. Основные команды и функции MATLAB и Toolbox 1019 • а = reshape (х, m, n, р)—- формирование трехмерного массива та на л на р из элементов массива х длины m*n*p. Аналогичным образом создаются многомерные массивы. □ rot90— поворот матрицы (см. разд. "Применение функций обработки данных к матрицам"главы 2). • в = rot90 (А) — в образуется из а поворотом против часовой стрелки на 90". • в = rot90 (А, к) — в образуется из а поворотом против часовой стрелки на 90” к раз. □ trii — выделение нижнего треугольника из матрицы (см. раза. "Создание матриц специального вида"главы 2). • l = tril(A) — в матрицу ь тех же размеров, что и а. заносятся элементы нижнего треугольника а с диагональю. • l = tri КА, к) — в матрицу ь тех же размеров, что и а, заносятся элементы, находящиеся ниже к-ой поддиаюнали и на ней (нумерация поддиагопалей такая же, как и в diag). □ triu — выделение верхнего треугольника из матрицы (аналогично tril). Математические функции Элементарные математические функции подробно описаны в начале книги (см. разд. "Встроенные элементарные функции"главы 1). Специальные функции □ airy— функции Эйри первого и второго порядков, являющиеся решениями дифференциального уравнения w* - = О. • w = airy(z) — функция Эйри первого порядка. • w = airyd, z)—производная функции Эйри первого порядка. • w = airy (2, z) —функция Эйри второго порядка. • w = airy(3, z) — производная функции Эйри второго порядка. Если z является массивом, то результат w будет массивом той же размерности со значениями функции Эйри от соответствующих элементов z. 1020 Приложения • [w, ierr] = airy (к, z) — во второй, дополнительный, аргумент заносится информация о нахождении значения функции Эйри: О ierr = 1 — неверно заданы входные аргументы; О ierr = 2 — переполнение, ответ будет inf; О ierr = 3 — частичная потеря точности при вычислениях; О ierr = 4 — полная потеря точности при вычислениях, z слишком большое; О ierr = 5 — вычислительный процесс не сходится, о гвет будет мам. □ besselh — функции Ганкеля первого и второго рода, выражающиеся через функции Бесселя (см. соответствующее дифференциальное уравнение ниже). • f = besseih(nu, k, z) — функция Ганкеля первого (для к = 1) и второго (для к = 2) рода. • [w, ierr] = besselh(nu, к, z)—аналогично обращению к airy. • f = besseih(nu, 1, z, 1)—то же самое, что besselhtnu, 1, z)*exp(-i*z). • f = besselh(nu, 2, z, 1) — то же самое, ЧТО besselh(nu, 2, z)*exp(i*z). □ besseij, bessely— функции Бесселя, являющиеся решениями дифференциального уравнения z2 у"+zy'+(z2 -v2 jy — О для вещественных г. • f = besseij (nu, z)—функция Бесселя первого рода. • f = besseij (nu, z, 1)—то же самое, что besseij(nu, z)*exp(-abs(imag(z))). • f = bessely (nu, z)—функция Бесселя второго рода. • f = besseiy(nu, z, 1)—то же самое, что bessely(nu, z)*exp(-abs(imag(z))). Возможны вызовы co вторым дополнительным выходным аргументом, аналогично функции airy. Допустимы комплексные значения для z. Если z и пи — массивы одинаковых размеров, то результат f будет массивом того же размера с соответствующими значениями функции Бесселя. В случае, когда один из входных аргументов z или пи — число, а второй — массив, скалярный аргумент расширяется до массива и результатом является массив f. Таблица значений для различных пи и z получает Приложение 1. Основные команды и функции MATLAB и Toolbox 1021 ся, если один из аргументов z или пи — вектор-строка, а второй — вектор-столбец. П besseli, besseik— модифицированные функции Бесселя, являющиеся решениями дифференциального уравнения z2y*+zy' + (z2 + v2)y =0 для вещественных, v. • f = (nu, z)—модифицированная функция Бесселя первого рода. • f = besseli (nu, z, 1) —TO же Самое, ЧТО besseli(nu, z)*exp(-abs(real(z))). • f = oesselk (nu, z) — модифицированная функция Бесселя второго рода. • f = besselk(nu, z, 1) •—то же самое, что besselk(nu, z)*exp(-abs(real(z))). Интерфейс функций besseli, besselk такой же, как у besselj, bessely. □ beta, betainc, betain— бета-функция, неполная бета-функция и логарифм бета-функции. Интегральные представления бета-функции B(z, w) и неполной бета-функции Вх (г, и/) выглядят следующим образом: В(г. »)=р=-'(1-гГ'л; В,(г. w). о oJZ’No • f = beta(z, w) —вычисление бета-функции. • f = beta(x, z, w) — вычисление неполной бета-функции, x должен принадлежать отрезку [0,1]. • f = betainfz, w) — вычисление натурального логарифма от бета-функции с использованием более эффективного алгоритма, чем log(beta(z, w)). Аргументы w и z могут быть вещественными и комплексными числами или массивами одинаковой размерности. Один из аргументов может быть скаляром, в данном случае он расширяется до размеров массива. □ el lip j— эллиптические функции Якоби тп(м), cn(u), dn(u), порождаемые обращением эллиптического интеграла ? rf<P ц = ] / . 2 • о^/1-znsin ф 1022 Приложения • [sn, cn, dn] = eilipj(u, m) -—одновременное вычисление всех эллиптических функций Якоби для ш из отрезка [0,1]. Размеры входных аргументов влияют на результат так же, как в beta. • [sn, cn, dn] = eilipj (u, m, tol) — одновременное вычисление всех эллиптических функций Якоби для m из отрезка [О,1] с заданной точностью (по умолчанию ерз). Часто имеет смысл уменьшить точность для сокращения времени вычислений. □ elixpke— полные эллиптические интегралы первого К(т) и второго Е(т) рода, которые определяются следующим образом: п/2 ”/2 j--------- K(rn) = j .— =; E(«i)= j 1-wisin2(prfcp. о i/l-msin2<p о • k = eilipke(m) —вычисление эллиптического интеграла первого порядка для m из отрезка [0,1]. • [k, е] = ellipke(m) — одновременное вычисление эллиптических интегралов первого и второго порядков для m из отрезка [0,1]. • [k, е] = eilipkefm, tol) — одновременное вычисление эллиптических ин гегралов первого и второго порядков для m из о'грезка [0.1] с заданной точностью (по умолчанию eps). Часто имеет смысл уменьшить точность для сокращения времени вычислений. О erf, erf о, erfcx, erfinv — вычисление функции ошибок, дополните дьно-го интеграла вероятностей и обратной к функции ошибок 2 д erf г = -т=|е dt: erfcx = 1-erf х; erfcxx = e erfcx. • у = erf(x) —вычисление функции ошибок. • у = erfc(x) —вычисление дополнительного интеграла вероятностей. • у = erfcx (х) —вычисление масштабированно] о дополнительно! о интеграла вероятностей, • х = erf (у) — вычисление функции ошибок, у должен принадлежать отрезку [-1,1]. Приложение 1. Основные команды и функции MA TLAB и Toolbox 1023 □ expint — интегральная показательная функция' Ег(х) = J-—clt. X I Ei = expint(х). □ factorial — факториал. р = factorial (п) — нахождение факториала целого числа п, точный ответ подучается только для п, меньших, чем 22, для остальных — приближенный. □ gamma, gammainc, gamrualn —гаММа-фуНКЦИЯ Г(ос) , Неполная ГаММИ-фуНКЦИЯ Гх (а) и логарифм гамма-функции. Г(а) = f e‘ta-xdt; Гл (а)=-L- J dt. о 1 Wo у = gamma (а), у = gammainc (х, a), у = gammain (a). □ legendi e — присоединенные функции Лежандра первого рода Р™ (х) и полунормированные присоединенные функции Лежандра S™(x), определяемые формулами V (л)=(-1)” (1 - J )* Р„ (Д; S„" (ж)=(-1)” (>). где fjj(x) —полиномы Лежандра. • р = iegendre(n, х) — вычисление присоединенных функций Лежандра первого рода для всех m = о, 1, ..., п. Ограничения на входные аргументы: m— целое число, менышее 256, х принадлежит отрезку [-1,1]. Если х— скаляр, то р является вектором, длина которого на единицу больше п. В случае, когда х — вектор, в выходном аргументе р возвр ццается матрица, столбцы которой содержат присоединенные функции Лежандра первого рода для всех m = о, 1, .... п, вычисленные для каждого элемента вектора х. • р = legei-dre in, х, 'sch')—вычисление полунормированных присоединенных функций Лежандра первого рода для всех m = о, 1, ..., п. Интерфейс аналогичен legendre (п, х). 1024 Приложения □ pow2 — нахождение степеней двойки. • х = рои2 (у) — в векторе х возвращается результат возведения числа 2 в степень, записанную в соответствующем элементе у. • х = pow2(f, е)— элементы вектора х вычисляются по формуле x(i) = f(i)*2Ле(i). а rat, rats — приближение вещественных чисел отношением двух целых чисел (рациональной дробью). • [п, d] = rat (х, tol) — возвращает два целых числа п и d таких, что n/d приблизительно равно х (с точностью tol) в следующем смысле: abs (n/d - х) <= toi*abs (х). Если х — массив, то п и d являются массивами того же размера, содержащими соответствующие значения числителя и знаменателя для каждого элемента х. • [n, d] = rat(x) — использует по умолчанию точность tol = 1.e-6*ncrm(X(:), 1). • s = rat(x), s = rat(x, tol) — возвращают ответ в строковой переменной S. • s = rats (х, len) — использует rat для приближенного представления числа х рациональной дробью со строкой длиной len. Преобразование координат □ cart2poi — переход от декартовых координат к полярным или цилиндрическим. • [th, г] = cart2pol(x, у)—переход от декартовых координат к полярным по формулам th = atan2(y, х), г = sqrt{x.~2 + у.л2). • [th, г, z] = cart2pol(x, у, z) — переход от декартовых координат к цилиндрическим по формулам th = atan2(y, х), г = зцгЬ(х.Л2 + у.Л2),г = z. Угол th возвращается в радианах. Входные аргумен сы могут быть массивами одинаковых размеров, в этом случае выходные аргументы являются массивами тех же самых размеров и содержат полярные или цилиндрические координаты для соответствующих пар элементов из х и у или троек х, у и z. О cart2sph — переход от декартовых координат к сферическим. [ th, phi, г] = cart2sph(x, у, z)—переход от декартовых координат к сферическим по формулам: rh = atan2(у, х); Приложение 1. Основные комгнды и функции MATLAB и Toolbox 102о • phi - atan2(z, sqrt(x."2 + у.л2)); • г - sqrt(x."2 + y.~2 + г.л2). Углы th и rho возвращаются в радианах. Интерфейс аналогичен cartZpol. □ pol2cart— переход от полярных или цилиндрических координат к декартовым. • [х, у] = pol2cart (th, г)— переход от полярных координаг к декартовым. • [х, у, z] = pol2cart (th, г, z)— переход от цилиндрических координат к декартовым. Угол th задается в радианах. Входные аргументы могут быть массивами одинаковых размеров (см. функцию cart2pol). □ sph2cart — переход от сферических координат к декартовым. [х, у, z] = sph2cart(th, phi, г) Уголы th и phi задаются в радианах. Интерфейс аналогичен pol2cart. Решение различных математических задач Решению задач линейной алгебры и матричного анализа посвящены отдельные разделы и главы книги (см., в частности, разд. "Решение систем линейных уравнений" главы 2, разд. "Задачи линейной алгебры" главы 6, главу 15). Матричный анализ П cond—нахождение числа обусловленности по отношению к различным матричным нормам (слг. разд. "Системы с плохо обусловленными матрицами" главы б, а также функцию norm). • с = cond (л) или с = cond(А, 2) — число обусловленности по отношению к спектральной матричной норме, т. е. norm (A) *norm(inv (а) }. • с = cond (А, 1) — число обусловленности по отношению к первой матричной норме, Т. е. ПОПП (А, 1) *norm(inv(A) , 1). • с = cond (a, 'fro') — число обусловленности по отношению к евклидовой матричной норме (норме Фробениуса), т. е. norm (А, ’ fro') *ncrir (inv (А), 'fro'). 1026 Приложения • с = cond(a, inf) — число обусловленности по отношению к бесконечной матричной норме, т. е. norm (A, Inf) *norm (inv (А), Inf). □ condeig— вычисление косинусов углов между правыми и соответствующими левыми собственными векторами. • с = condeid(A) — вектор с содержит косинусы углов между соответствующими собственными векторами. • [v, D, с) = condeid(A) — дополнительно возвращаемся матрица v, состоящая из нормированных собственных векторов А, и диагональная матрица D, на диагонали которой записаны собственные значения А. □ det — вычисление определителя матрицы d = det (A) (cjw. разд. "Системы с плохо обусловленными матрицами " главы 6). □ norm — векторные и матричные нормы. Матричные нормы: • n = norm (A), n = norm (А, 2) —спектральная норма, т. е. max (svd (А)) для прямоугольных матриц и max(sqrt (eig (А*А‘))) для квадратных; • n - norm (А, 1) — максимальная столбцевая норма, равная max(sum(abs(А))); • n = norm (A, inf) — максимальная строчная норма, равная max (sum(abs (А'))); • n - norm (A, 'fro') — евклидова норма (или норма Фробениуса), равная sqrt (sum(sum(abs (А) . л2) ) ). Векторные нормы: • n = norm(x) •— евклидова векторная норма, т. е. sqrt (sumfabs (х) . л2)); • n = norm(x, р) — норма Гельдера с показателем р от единицы до бесконечности, равная sum(abs (х) . лр) л (1/р); • n = norm(x, inf) — бесконечная векторная норма, равная max(abs(х)); □ null — нахождение ортонормированного базиса ядра матрицы. к = null (А) — столбцы матрицы к образуют ортонорм ированный базис ядра А, т. е. таких векторов х, что А*х = zeros (m, 1), где sxze(A) = [m n],size(x) = [n, 1]. □ orth— нахождение ортонормированного базиса области значений матрицы. Приложение 1 Основные команды и функции MATLAB и Toolbox 1027 r = orth(A) — столбцы матрицы r образуют ортонормированный базис области значений а, т. е. таких векторов у, что у = а*х для любых х. Верно R'*R = eye (rank (А)). Cl rank — вычисление ранга матрицы, т. е. наибольшего числа линейно независимых столбцов. Алгоритм основан на нахождении сингулярных чисел матрицы. • г = rank (А) — возвращает количество сингулярных чисел магрицы а, которые больше, чем max (size (А)) *norm(A) *eps. • г = rank (A, tol) — возвращает количество сингулярных чисел матрицы А, которые больше, чем tol. □ rcond— оценка обусловленности матрицы. с = rcond (А) — вычисляет оценку для обратного к числу обусловленности по отношению к максимальной столбцевой норме. □ rref, rrefmovie— нахождение приведенно-ступенчатой формы матрицы исключением по Гауссу—Жордану с выбором главного элемента. • r = rref (А) — в r содержится приведенно-ступенчатая форма А, при вычислениях элементы, меньшие max (size (А)) *eps*norm(A, inf), полагаются равными нулю. • [R, jb] = rref (А) — вектор jb содержит номера связанных компонент решения системы линейных уравнений с матрицей a; length(jb) является рангом а, найденным при помощи исключения; столбцы матрицы а (:, jb) составляют базис области значений а. R(1:length(jb), jb) = eye(length(jb)). • [r, jb] = rref (A, tol)— при вычислениях элементы, меньшие tol, полагаются равными нулю. • rrefmovie (А) — отображение каждого шага процесса исключения в командном окне MATLAB. П subspace — вычисление угла между двумя подпространс гвами. phi = subspace (А, в) — возвращает угол между двумя подпространствами, базисными векторами которых являются столбцы матриц айв. □ truce — след матрицы. t = trace (А) — нахождение следа А, Т. е. sum(diag (А)). ЗА Злг. 130 1028 Приложения Решение спектральных задач □ balance — масштабирование элементов матрицы при помощи балансировки. Масштабирование применяется для предварительной обработки матрицы в случае сильного разброса абсолютных значений элементов. Балансировка матрицы а заключается в нахождении диагональной матрицы D такой, чтобы в одноименных строках и столбцах в = inv(Dl *a*d суммы модулей элементов были примерно одинаковы. Балансировка не изменяет спектр матрицы. Использование: В = balance (A), [D, В) = balance (А) — элементы D являются целыми степенями двойки. Если А есть симметричная матрица, то балансировки не происходит И В = A, D = eye (size (А) ). Предварительная балансировка матрицы не всегда оправдана. Например, если относительно малые элементы исходной матрицы есть ошибки округления, то после балансировки они будут сравнимы с остальными элементами матрицы, что заведомо приведет к неверному результату при дальнейших вычислениях. □ eig — решение обычной и обобщенной проблемы на собственные значения (см. разд. "Собственные числа и векторы матрицы, функции матриц" главы б). • d = eig (А) — в векторе d возвращаются собственные значения матрицы а, т. е. A*u = d(i)*u. Исходная матрица предварит алчно балансируется. • [v, D] = eig(А) — столбцы матрицы v являются собственными векторами a, D есть диагональная матрица, состоящая из собственных значений, д*и = d*u. Исходная матрица предварительно балансируется. • [V, D] = eig(A, 'nobalance') — ТО же, ЧТО и [V, D] = eig(A), НО без предварительной балансировки. • d = eig (А, В) —в векторе d возвращаются обобщенные собственные значения, являющиеся решением a*u = d(i)*B*u, используется QZ-алгоритм. • [V, D] = eig (а, В)— дополнительно возвращаются обобщенные собственные векторы. П gsvd — обобщенное сингулярное разложение (см. также функцию svd). • [и, v, х, с, S] = gsvd (А, в)—нахождение унитарных матриц и и V, квадратной х и диагональных матриц сиз таких, что: а = и*с*х’, в = v»s*x’, а С'*С + s'*s является единичной. Если size (А) = [т р]. Приложение 1. Основные команды и функции МА ILAB и Toolbox 1029 size(B) = [n р], ТО size(U) = [tn in], size(V) - [n n], size(X) = = [m min (m + n, p) ]. • [U, V, X, C, S] = gsvd (A, B, 0) — ВСЛИ m >= p ИЛИ n >= p, TO U И V имеют не более р столбцов, а с и s — не более р строк. Обобщенные сишулярные значения есть diag (С) . /diag (S). • s - gsvd (А, в) — возвращает вектор обобщения сингулярных значений, определяемый как diag(C'*C)./ciag(S'*S)). □ schur — разложение Шура. • [и, т] = schur (X)—для квадратной матрицы х находятся матрица г и унитарная матрица и такие, что х = и*т*и' ии’*и = eye (size (U)). • т - schur (X)—возвращает только матрицу т разложения Шура. □ svd— сингулярное разложение и нахождение сингулярных чисел. • [□, d, v] = svd(А) — нахождение матрицы D с неотрицательными диагональными элементами, расположенными в порядке убывания, и унитарных матриц и и v таких, что А == u*p*v'. Если size (А) = [т п], ТО size(D) = [m n],size(U) = [m m],size(V) = [n nJ. • d = svd (A) — в векторе d возвращаются сингулярные числа матрицы А. • [U, D, V] = svd (А, 0)—если size (А) = [т п] и т > п, то вычисляются только п первых столбцов и и si г.е (D) = [п п]. Решение линейных уравнений, разложение и обращение матриц □ choi — разложение Холецкого положительно определенных эрмитовых (симметричных» матриц. • r = chol (А) — возвращает верхнюю треугольную матрицу r такую, что r'*r = А. Если входной аргумент не является положительно определенной матрицей, то выводится сообщение об ошибке. • [R, р] = chol (А) — второй дополнительный выходной аргумент позволяет избежать сообщения об ошибке в случае неположительно определенной а, возвращая в р целое положи гельное число, а в R — верхнюю треугольную матрицу такую, что R'*R = А(1:р-1, 1:р-1). В случае положительно определенной матрицы р = о и результат аналогичен r = chol(А). Функция chol применима к разреженным матрицам (см. разд. "Факторизация матриц" главы 15). 1030 I1рИЛ0Жвг1ИЙ □ inv— обращение матрицы {см. разд. "Обращениематриц"главы 6). в =» inv (а) — возвращает матрицу, обратную к квадоатний матрице а. В случае плохой обусловленности а выдается предупреждение. Задание в качестве входного аргумента символьной матрицы приводит к поиску обратной к ней также в символьной форме (см. разд. "Задачи линейной алгебры" главы 17). □ lu— LU-разложение квадратной матрицы. • (L, и] = 1и(А) — возвращает верхнюю треугольную матрицу и и матрицу ь, которая может быть сведена к нижней треугольной перестановками. • [L, и, в] = lu (А)—дополнительно возвращает матрицу перестановок в такую, что в*а = ь*и. • [L, и] = lu(A, tresh)— входной аргумент tresh (из отрезка [0,1]) позволяет управлять процессом выбора главного элемента при нахождении LU-разложения разреженных матриц. Перестановка производится, если модуль диагонального элемента в tresh раз меньше модуля любох о поддиагонального элемента в столбце. Функция lu применима к разреженным матрицам {см. разд. "Факторизация матриц" главы 15). □ isqnonneg— нахождение положительного решения системы линейных алгебраических уравнений (не обязательно с квадратной матрицей) методом наименьших квадратов {см. разд. "Метод наименьших кваоратов" главы 16). • х = isqnonneg (С, d) — возвращает вектор х с неотрицательными компонентами, которые минимизируют norm (С’Х - d). • х = isqnonneg(с, d, хо) — вектор хо>о используется в качестве начального приближения. • х = isqnonneg(С, d, хо, options)—процесс вычислений управляется при помощи задания параметров в структуре options функцией optimset (см. разд. "Параметры оптимизации"главы 16). • [X, resnorm] = Isqnonneg (...) — В выходном аргументе resnorm возвращается квадрат нормы невязки norm(c*x - d) '2. • [X, resnorm, residual] = Isqnonneg]...) — В ВЫХОДНОМ аргументе residual возвращается невязка с*х - d. • (X, resnorm, residual, exitflag] =Isqnonneg(...) — значение единица выходного архумента exitflag свидетельствует об успешном на- Приложение 1. Основные команды и функции MATLAB и Toolbox 1031 хождении решения, а ноль означает, что превышено максимально допустимое чй(сло итераций. • [X, resnorm, residual, exitflag, output] = Isqnonneg(...) — структура output содержит информацию о процессе вычислений. • [X, resnorm, residual, exitflag, output, lambda] = Isqnonneg(...} — возвращает двойственный вектор lambda, lambda(i) <= 0, если X(i) приближенно равно нулю и lambda(i) = о,еслих(г) > о. □ peg — предобусловленный и обычный метод сопряженных градиентов. • х = peg (А, Ь) —решение системы линейных алгебраических уравнений А*х=ь методом сопряженных градиентов. Здесь а — симметричная положительно определенная матрица. Начальным приближением является нулевой вектор. Сходимость считается достигнутой, если в процессе итераций norm(b - A*b)/NORM(b) < 1е-6. Число итераций по умолчанию min(n, 20). По окончании работы выводится сообщение о нахождении решения или о причине останова вычислений. • peg (A, b, tol) —в дополнительном входном аргументе tol задается точность вычислений вместо le-б, установленной по умолчанию. • рсд<А, ь, tol, maxit) — задание максимально допустимого числа итераций. • peg (А, ь, tol, maxit, м)—решение системы а*х = ь предобуслов-ленным мегодом сопряженных градиентов. В качестве предобуслов-ливателя используется матрица м. Вместо матрицы и можно задать имя файл-функции, эффективно решающей систему линейных уравнений с матрицей м. • peg (А, ь, tol, maxxt, Ml, м2) — предобуславливатель задается в факторизованной форме М1*М2. • peg (А, ь, tol, maxit, ml, m2, xO) — указание хО в качестве начального приближения. □ ptnv — нахождение псевдообратной матрицы (см. разд. "Обрашение матриц" главы 6). • р = pinv(A)—возвращает матрицу р такую, что size (₽) = size (а*), А*Р*А = А, Х*Р*Х = Р, а А*Р и р*а являются эрмитовыми. • р = pinv (a, tol)—производит вычисления с заданной точностью. □ qr — QR-разложение матрицы. • [Q, R] = qr(A)— нахождение верхней треугольной матрицы R (size(R) = size (А)) И унитарной Q (Q'*Q = eye (size (Q))) таких, ЧТО А = Q*R. 1032 Приложения • [Q, r, E] = qr (a)—дополнительно возвращает матрицу перестановок Е, А*Е = Q*R. • [Q, R] = QR(A, 0) -—если size (А) = [тп п] и m > п, то возвращаются только первые п столбцов Q. • [Q, R, Е] = QR(A, 0) —ТО Же, ЧТО И [Q, R] = QR (А, 0) , НО ВОЗВра-щается матрица перестановок е такая, что q*r = А(:, Е). Вычисление функций от матриц См. разд. "Вычисление математических функций от элементов матриц" главы 2. Г) ехрш — матричная экспонента, использование: F = ехрт(А). □ funm — вычисление произвольной функции от матрицы. • г = funm(A, 'funname') — вычисление функции от матрицы А, объявленной В файл-функции funname. Если исходная матрица имеет близкие собственные значения, то выдается предупреждение о том, что результат может быть найден неточно. Для эрмитовых (симметричных) положительно определенных матриц результат, как правило, получается достаточно точный. • [F, errest] = funm(A, 'funname') —выходной аргумент errest содержит грубую оценку результата. □ logm—матричный логарифм. • L = logm (А) — вычисление логарифма матрицы А. Если а имеет отрицательные собственные значения, то результат будет комплексным. Если результат не может быть найден достаточно точно, то выдается предупреждение (см. функцию funm). • [L, esterr] = logm(A) — ВЫХОДНОЙ аргумент errest СОДерЖИТ грубую оценку результата. □ sqrtm — квадратный корень из матрицы. • х = sqrtm(A) — возвращает матрицу х такую, что х*х = А. Если а является вырожденной матрицей, то выдается предупреждение. • [X, resnorm] =sqrtm(A)—возвращает в reznorm относительную погрешность norm(А - ХЛ2, ’fro')/norm(A, 'fro'). Приложение I Основные команды и функции MATLAB и Toolbox 1033 Поиск корней □ fsoive — решение нелинейных уравнений и систем вида f(x) = о. Левая часть уравнения или системы f (х) = о должна быть запрограммирована в файл-функции funname (см, разд, "Решение нелинейных уравнений" главы 16). • х = fsoive(funname, хО) — возвращает решение, используя хО в качестве начального приближения. • х = fsoive(funname, хО, options) — процесс решения управляется параметрами, задаваемыми в структуре options. • х = fsoive(funname, хО, options, pl, p2, ...) — решение нелинейных уравнений и систем при фиксированных значениях параметров pl, р2, ..., от которых зависит левая часть системы f (х, pl, Р2, ...). Применение fsoive для исследования функций, зависящих от параметров, может быть организовано при помощи вложенных и анонимных функций так, как описано в разд. "Исследование функций зависящих от параметров" главы 6. Программированию вложенных функций посвящен разд. "Вложенные функции" главы 5. • [х, fval] = fsoive(funname, хО, ...) — возвращает значение f, вычисленное от приближенного решения. • [х, fval, exitflag] = fsoive(funname, xO, ...) — значение ВЫХОДНОГО аргумента exitflag содержит информацию о завершении вычислений. Если exitflag > 0, то процесс сошелся и решение найдено, если exitflag < о, то вычислительный процесс оказался расходящимся, a exitflag = о свидетельствует о прекращении вычислений из-за превышения максимально допустимого количссва вычислений функции f. • [х, fval, exitflag, output] = fsoive(funname, xO, ...) —структура output содержит подробную информацию о ходе вычислений. • [х, fval, exitflag, output, jacob] = fsoive(funname, xO, ...) —-в выходной аргумент jacob заносится якобиан левой части системы, вычисленный от приближенного решения х. О fzero — нахождение корня функции одной переменной f (х). Левая часть уравнения f(x) = о должна быть запрограммирована в файл-функции funname (см.разд. "Решение произвольных уравнений" главы 6). • х = fzero(fun, хО) — возвращает решение, используя хО в качестве начального приближения. 1034 Приложения • х = fzero(fun, [а ь ]}—- возвращает решение на промежутке [а, ы, используя хс в качестве начального приближения. Предполагается, что f(a)*f(b) < о. Следующие варианты вызова аналогичны fsolve: • х = fzero(fun, xO, options) • х = fzero(fun, xO, options, pl, p2, . . .) Применение fzero для исследования функций, зависящих от параметров, описано в разд. "Исследование функций, зависящих от параметров “ главы 6. Программированию влогкенных функций посвящен разд. 'Вложенные функции"главы 5, • [х, fval) = fzero(fun, ...) • [х, fval, exitflag, output] = fzero(...) Использование exitflag несколько отличается от случая fsolve. [х, fval, exitflag] = fzero(...) — если exitflag > 0, то решение найдено, если exitflag < о, то либо не определен интервал, на границах которого функция имеет разные знаки, или были получены inf, NaN при вычислении функции. □ roots — вычисление всех корней полинома. г = roots (р) — вектор г содержит корни полинома, задаваемого вектором р (сл. разд. "Вычисление всех корней полинома"главы 6) □ solve— символьное решение уравнений и систем (см. разд. "Решение уравнений и систем"главы 17). • г = solve(f) — нахождение символьного решения уравнения, заданного строкой f. Входным аргументом может быть символьная функция. По умолчанию в качестве независимой переменной выбирается результат findsym(f). • г = solve (f, t)—второй аргумент указывает на независимую переменную. • г = solve (fl, f2, ..., fn) — решение системы уравнений, задаваемых строками fl, f2, fn. Входными переменными могут быть символьные функции. По умолчанию неизвестными переменными являются те, которые возвращает findsym. Поля структуры г содержат компоненты решения. • [ri, г2, ..., rn] = soivetfi, f2, ..., fn) —решение записывается в символьные переменные rl, г2,..., гп. Приложение 1. Основные команды и функции MATLAB и Toolbox 1035 • г = soive(fl, f2, fn, tl, t2, ..., tn)—дополнительные входные аргументы tl, t2, tn указывают на переменные, подлежащие определению. • [rl, r2, ..., rn] = solve(fl, f2, ...» fn, tl, t2, ..., tn) — решение записывается в символьные переменные rl, r2,..., m. Интерполяция и приближение данных Примеры, связанные с интерполяцией и приближением данных, приведены в разд. "Полиномы и интерполяция" главы 6. Интерполяция сплайнами в Spline Toolbox описана в главе 18, а в главе 19 обсуждается приближение при помощи параметрических моделей средствами Curve Fitting Toolbox. Л polyfit — приближение табличной функции одной переменной полиномом заданного порядка по методу наименьших квадратов (см. разд, "Приближение по методу наименьших квадратов"главы 6). П griddata— приближение неравномерно распределенных трехмерных данных поверхностью, построенной на регулярной сетке. • zi = griddata(х, у, z, xi, Yl) — построение поверхности, наилучшим образом проходящей через точки с координатами (x(i), у (i), z (i)). Векторы х, у и z содержат неравномерно распределенные данные. Матрицы xi и yi задают равномерную сетку (они могут быть сгенерированы при помощи meshgrid). Результатом является матрица со значениями интерполирующей функции в узлах равномерной сетки. • zi = griddata(х, у, z, XI, Yl, 'linear') — приближение линейными функциями. • ZI = griddata (х, у, z, XI, YI, 'cubic') — приближение кубическими функциями. • zi = griddata (х, у, z, xi, yi, 'nearest')— приближение по ближайшему соседу. О interpl, interpz, interpB, interpn— интерполяция одномерных, ДВу-мерчых, трехмерных и многомерных данных различными способами (см разд. "Интерполяция сплайна ми" и "Интерполяция двумерных и многомерных данных"главы б). □ intexpft — одномерная интерполяция с использованием быстрою преобразования Фурье. у = interpft (х, п) — предполагается, что вектор х содержит равноотстоящие друг от друга на шаг dx элементы, length (х) = ш. Находится преобразование Фурье от х, затем оно дополняется точками с шагом 1036 Приложения dx*m/n. Вычисляется обратное преобразование Фурье и возвращается в векторе у. □ spline — интерполяция кубическими сплайнами. yi = spline (х, у, xi)—табличные данные, заданные векторами х и у, интерполируются кубическими сплайнами. Возвращаемый векюп yi содержит значения сплайна в абсциссах, определяемых вектором xi. Минимизация и оптимизация Функции MATLAB, предназначенные для решения задач минимизации и оптимизации, входят в состав Optimization Toolbox (см. главу 16, где приведены формулировки основных задач и примеры использования функций). П fgoaiattain — решение задачи о достжении границы (см. разд. "Задача о достижении границы"главы 16). П fminbnd— нахождение локального минимума функции одной иеосмен-ной на заданном интервале (см. разд. "Нахождение экстремумов функций " главы б). П fmincon — решение задач нелинейного программирования (см. разд. "Нелинейное программирование" главы 16). П fminimax — решение минимаксной задачи (см. разд. "Минимаксная задача” главы 16). □ fminsearch— поиск локального минимума функции нескольких пере-менных(сл<. разд. "Нахождение экстремумов функций"главы 6). О fma nunc — поиск минимума нелинейной функции без ограничения на переменные. П linprog— решение задач линейного программирования (см. разд. "Линейное программирование” главы 16). П isqcurvefit-— подбор параметров (см. разд. "Подбор параметров" главы 16). □ isqiin— метод наименьших квадра.ов для решения систем линейных уравнений с линейными ограничениями на решение (см. разд. "Метод наименьших квадратов” главы 16). П isqnoniin — нелинейный подбор параметров. □ optimget— получение параметров, определяющих работу функций минимизации и оптимизации (см. разд. "Управление ходом вычислений" главы 6). Приложение 1. Основные hi манды и функции MATLAB и Toolbox 1037 П optimset — задание параметров, управляющих минимизацией и оптимизацией (см. например, разд. "Управление ходом вычислений" главы 6 и "Решение системы нелинейных уравнений"главы 16). □ quadpxog— решение задач квадратичного программирования (см. разд. "Квадратичное программирование" главы 16). Дифференцирование и конечные разности □ dei2 — вычисление разностного аналога оператора Лапласа. Предполагается, что матрица и содержит значения некоторой функции в точках сетки. • l = del 2 (U) — возвращается матрица со значениями для внутренних узлов L(i, j) = 0.25*(U(i + 1, j) + U(i - 1, j) + U(i, j + 1) + + U(i, j - 1)) - U(i, j} При вычислении граничных значений используется кубическая экстраполяция. По умолчанию сетка квадратная с шагом, равным единице. Для задания сеток с другими шагами следует применять вызовы: L = del2(U, h),L = del2’(U, hx, hy). Генерация прямоугольной сетки производится при помощи функции meshgrid (см. разд. "Графики функций двух переменных"главы 2). • L = del2(u, hx, hy, hz, ...)—аппроксимация оператора Лапласа и в многомерном случае. Для построения многомерных сеток предназначена ndgrid. □ diff — нахождение конечных разностей и символьное вычисление производных (символным вычислениям посвящена глава 17). • D = diff(X) — по вектору х строит вектор d = IX(2) - х<1), ..., Х(п) - х(п - 1)],гдеп = length(X), причем length(D) = п - 1. Если входной аргумент является матрицей, то происходит вычисление для каждого столбца х. • Dk = diff(x, k) — вычисление конечных разностей k-го порядка. Например, вычисление k - 3diff(x, 3) и diff(diff(diff(X))) при-водет к одинаковым результатам. • fl = diff(f) — нахождение первой производной в аналитическом виде от символьной функции f. По умолчанию в качестве независимой переменной выбирается результат findsym(f). Выходной аргумент является символьной функцией. 1038 Приложения • fl = diffff, t)—нахождение первой производной в аналитическом виде от символьной функции f по переменной t. Переменная t должна быть объявлена как символьная при помощи syms или sym. Аналитическое выражение для производной n-го порядка возвращается при обращениях: diff (f, n),diff(f, t, n) (см. разд. "Пределы, дифференцирование и ин,пегрирование" главы 17). П gradient — вычисление градиента сеточной функции. • [fx, fy] = gradient (F)—возвращает компоненты градиен.а для сеточной функции, значения которой в узлах сетки представлены в матрице F. По умолчанию сетка считается квадратной с единичным шагом. Для вычисления градиента на произвольной прямоугольной сетке следует применять обращение [FX, FY] = gradient(F, hx, hy). • [fx, fy, fz, ...] = dei2(F, hx, hy, hz, ...)—нахождение компонент градиента функции нескольких переменных. Для построения многомерных сеток предназначена ndgrid. Интегрирование □ dblquad— вычисление двойных интегралов (см. разд. "Вычисление двойных интегралов"главы 6). • result = dblquad('fun', inmin, inmax, outmin, outmaxJ • result = dblquad('fun', inmin, inmax, outmin, outmax, tol) • result = dblquad('fun', inmin, inmax, outmin, outmax, tol, method) П int— нахождение определенных и неопределенных интегралов в символьном виде (см. разд. "Пределы, дифференцирование и интегрирование" главы 17). int(f), int(f, t),int(f, a, b),int(f, t, a, b). П quad, quadi— вычисление определенных интегралов по квадратурным формулам Симпсона и Ньютона—Котеса с автоматическим подбором шага интегрирования (см. разд. "Вычисление определенных интегралов" главы 6, где также обсуждается применение анонимных функций для интегрирования функций, зависящих от параметров). • q = quadf'f1, а, b) • q = quad('f‘, a, b, tol) • q = quad{’f', a, b, tol, trace) • q = quad('f’, a, b, tol, trace, pl, p2, ...) Приложение 1 С гневные команды и функции MATLAB и Toolbox 1039 Решение дифференциальных уравнений и систем Аппроксимация решения стационарных и нестационарных задач, описываемых дифференциальными уравнениями в частных производных, по методу конечных элементов реализована в функциях PDE Toolbox (см. главу 14). П dsoive— аналитическое решение дифференциальных уравнений и систем (см. разд. "Решение дифференциальных уравнений и систем" главы 17). □ ode45, ode23, odell3, ode!5s, ode23s, ode23t, ode23tb — численное решение задачи Коши для дифференциальных уравнений и систем произвольных порядков. Задание параметров, управляющих вычислительным процессом, производится при помощи odeset. П dde23 — решение дифференциальных уравнений с запаздывающим аргументом. Задание параметров, управляющих вычислительным процессом, производится при помоши ddeset. □ odeisi — решение дифференциальных уравнений, не разрешенных относительно производной, и дифференциально-алгебраических уравнений. □ bvp4c— численное решение граничных задач для обыкновенных дифференциальных уравнений произвольного порядка и систем (см. раз') "Решение дифференциальных уравнений"главы 6). Графика и визуализация данных Интерактивная среда для построения и редактирования графиков □ plottools — запуск интерактивной среды со всеми ее компонентами (см главу 4). П figurepalette— управление окном ligure Palette с шаблонами графиков. • figurepalette(1 show') — отображение окна с шаблонами графиков для текущего графического окна. • figurepalette('hide') — скрытие окна с шаблонами графиков для текущего графического окна. • figurepalette ('toggle') —переключение между режимами 'show' и 'hide' для текущего графического окна. • figurepalette (hF, ...) — то же самое, но для графического окна с указателем hF. 1040 Приложения □ plotbrowser — управление окном браузера объектов Plot Browser. • plDtbrowser ('on') — отображение окна браузера объектов для текущего графического окна. • plotbrowser (’off ’) — скрытие окна браузера объектов для текущего графического окна. • plotbrowser('toggle')— переключение между режимами 'on1 и ’ off' для текущего графического окна. • plotbrowser (hr, ...) — то же самое, но для графического окна с указателем hF. • propertyeditor — управление окном редактора свойств графических объектов Property Editor. Использование аналогично plotbrowser. Двумерные графики Использование низкоуровневой графики для задания свойств графических объектов объясняется в главах Зи9. П bar— вертикальная столбцевая диаграмма матричных или векторных данных (см разд. "Диаграммы и гистограммы"главы 3), примеры: • bar (rancid, 10)), bar(rand(l, 10) , 1.2), bar(rand(3, 4)); • bar (hA, ...) — вывод диаграммы на оси с указателем ьа вместо текущих; • h = bar (...) — возвращает вектор указателей на созданные рисованные объекты Barseries; • h = bar ('v6'...) — возвращает век гор указателей на созданные базовые полигональные объекты (Patch) для совместимости с предыдущими версиями MATLAB (базовые и рисованные объекты описаны в разд. "Графические объекты"главы 9). □ barh - горизонтальная столбцевая диаграмма матричных или векторных данных, примеры: • barh(rand(l, 10)), barh(rand(1, 10), 1.2), barh(rand(3, 4)); • Lar(hA, ...), h = barhd..) И h = barh(' v6' . . .) — аналогично функции bar. □ comet — анимированный график плоской линии (ел/, разд. "Анимированные графики " главы /) • comet (х, у) — отображение анимированного графика в виде движения кометы по кривой, проходящей через точки с координатами (х(1), y(i))- Приложение 1 Основные команды и функции MATLAB и Toolbox 1041 • comet (х, у, р) — дополнительный третий аргумент задает длину хвоста кометы p*iength (y) . по умолчанию используется р = 0.1. • comet (hA, ...) —- вывод анимированного графика на оси с указателем hA вместо текущих. □ ezplot— построение графика функции одной переменной, в том числе заданной неявно и параметрически с автоматическим подбором шага по аргументу и выводом заголовка графика (см. разд. "Графическое представление функций" главы 17). • ezplot (f; — построение графика функции на отрезке [—2л, 2л], где £ — строка с исследуемой функцией, указатель на нее, inline-функция, либо анонимная функция. Задание анонимной функции или указателя требует использования поэлементных операций при определении функции. I [ример для функции f (х) = х“ sin х: » f = @ (х) х. л2 . *sin (х) ; » ezplot(f) Функция может у быть задана неявно: /(х, у) = 0, например: » f = inline('х.' 2 + у.л2-9'); » ezplot(f) В этом случае по умолчанию график строится в квадрате [-2л, 2л] х х [-2л, 2л]. • ezplot (х, у) — вывод графика параметрически заданной функции *('). у (г): >> ezplot(1t*sin(t)1, 't*cos(t)') Для параметрически !аланных функций по умолчанию te [0, 2л]. • ezplot(f, [min, max)) —построение графика явной у = /(х) и неявной /(х,у) = 0 функции на отрезке [min, max]. • ezplot (f, [xmin, xmax, ymin, ymax]) — построение графика неявной функции f (х, у) В квадрате [xmin, xmax] х [xmin, ушах]. • ezplot tx, у, [tmin,tmax]) — построение графика параметрически заданной функции х(/). y(z) для значений параметра из отрезка [twin, tmax]. 1042 Приложения • ezpiot (hA, ...) — вывод графика на оси с указателем hA. • h = ezpiot (...) — запись в h указателя на линию графика. Свойства линии могут быть изменены в дальнейшем при помощи set (см. главу *>)• □ ezpolar— построение кривой в полярных координатах с автоматическим подбором шага по аргументу и выводом заголовка графика. • ezpolar (fi) — построение кривой г = ф(б) для 0е[О, 2л], где fi— строка с исследуемой функцией, указатель на нее, inline-функция либо анонимная функция. Задание анонимной функции или указателя требует использования поэлементных операций при определении функции. • ezpolar (f, [а, Ь]) —ТО же, ЧТО И ezpolar (fi), НО ДЛЯ 0е [о, &]. • ezpolar(hA, ...), h = ezpolar(...) — аналогично ezpiot. П fill — построение двумерного закрашенного многоугольника. • fillfx, у, с)—векторы х и у одинаковой длины содержат координаты вершин многоугольника. В случае незамкнутого многоугольника последняя вершина соединяется с первой. Цвет определяется значением третьего входного аргумента с: •r*, 'д1, 'Ь', 'с', ‘т’, 'у', 'и', 'к' или вектором из грех элементов в формате [г д Ь], например: » fill([-3 0120 -5], [23219 -1], 'с') » fill([-3 0120 -5], [23219 -1], [0.4 0.2 0.1]) Плавное изменение цвета заливки в пределах текущей палитры цвета требует указания вектора значений, соответствующих цвету вершин, т. е. size (с) = size (х). Указанные значения сначала масштабируются (см. функцию caxis), а затем происходит билинейная интерполяция цвез а внутри многоугольной области, например: fill(X, Y, с>— построение сразу нескольких многоугольников, число многоугольников равно столбцам матриц х и Y (предполагается, что матрицы одинаковых размеров). Третий аргумент с, задающий цвет заливки, может быть вектором, длина которого совпадает с числом столбцов в матрицах х и Y. Указание матрицы с, такой что size (С) = size(x), приводит к плавной заливке каждого многоугольника. Одним из входных аргументов (х или Y) может быть матрица, а вторым — вектор, число элементов которого равно числу строк матрицы. Такое обращение к fill эквивалентно обычному, в котором вместо вектора указана матрица, столбцы матрицы одинаковы и совпадают с вектором. Приложение 1 Основные команды и функции MATLAB и Toolbox 1043 Функция till допускает построение многоугольных объектов при помощи указания соответствующих гроек аргументов с координатами и цветом, например: fill(xl, yl, 'у1, х2, у2, 'д') Выходной аргумент, возвращаемый fin, является вектором указателей на все построенные многоугольные объекты типа Patch, h = fill (...) Свойства каждого из графических объектов могут быть изменены в дальнейшем при помощи set (см. главу 9). □ fpiot — построение функции одной переменной с автоматическим подбором шага по аргументу (см. разд. "Файл-функции с одним входным аргументом " главы 5 и разд "Более подробно о fpiot" главы б). П hist — гистограмма матричных или векторных данных (см. разд. "Гис-тограммы векторных данных"главы 3). • hist (у) — отображение гистограммы данных, записанных в векторе у, для построения гистограммы используется десять интервалов равной длины. • n = hist (у) — выходной аргумент п является вектором и содержит число элементов из у, попавших в каждый из десяти интервалов. Гистограмма нс отображается. • [n, xout] = hist(...) — возвращает в векторе п число элементов, попавших в каждый из интервалов, а в векторе xout — границы интервалов. Гистограмма не отображается. • hist (у, ш) — отображение гистограммы данных, записанных в векторе у, для построения гистограммы используется m интервалов равной длины. • hist (у, х) — отображение гистограммы данных, записанных в векторе у, для построения гистограммы используются интервалы, центры которых определяются значениями элементов вектора х. • hist (hA, ...) — вывод гистограммы на оси с указателем hA вместо текущих. П loglog, semilogx. semiiogy — Построение графиков В логарифмическом и полулогарифмическом масштабах. Используются так же. как plot (см. разд. "Графики в логарифмических масштабах"главы 3). □ pie— отображение данных в виде круговой диа1раммы (см. разд. "Диаграммы векторных данных"главы 3). 1044 Приложения • pie(x) — площадь сектора круговой диаграммы, отвечающего х{1), пропорциональна х (i) /sum{x). Если sum(x) < 1, то получается неполная круговая диаграмма. • pie(x, parts)—ненулевые компоненты вектора parts (входные аргументы должны быть одинаковой длины length (parts) = length(х)) соответствуют секторам, немного выдвинутым из круга диаграммы. • piet..., labels) — при построении круговой диаграммы добавляются надписи рядом с каждым сектором. Ячейки массива labels должны содержать строки с текстом надписей. • pie(hA, ...) — вывод круговой диаграммы на оси с указателем hA вместо текущих. • h = pie (...) — возвращает вектор h с указателями на графические объекты patch и text, образующие круговую диаграмму. Свойства каждого из графических объектов могут быть изменены в дальнейшем при помощи set (см. главу 9). П р_еЗ — построение объемной круговой диаграммы (см. разд. "Диаграммы векторных данных" главы 3 и пример в разд. "Управление объектами, копирование, поиск, скрытые указатели" главы 9). П plot— визуализация функций одной переменной, векторных и матричных данных (см., например, разд. "Построение графиков функции одной переменной” главы 2 и раза. "Графики в линейном масштаое"главы 3). • plot (у) — график зависимости значения элементов вектора с вещественными числами от их номеров, точки с координатами (i, у (i)) соединяются отрезками прямых. Если среди элементов у есть комплексные, то данная команда аналогична вызову plot с двумя входными аргументами (см. ниже): plot (real (у), imag(y)). • plot (х, у) — график зависимости элементов вектора у от элементов вектора х, точки с координатами (x(i), y(i)) соединяются отрезками прямых, пример: О >> х = -pi:pi/30:pi; О >> у = sin(х); О » plot(х,уI Вторым аргументом plot может быть матрица, число строк или столбцов которой совпадает с длиной вектора х. При этом выводится несколько графиков. Пример: » х = -10:0.1:10; >> у =; [sin(x) ; cos(x) ; sin(x) . Л2 ; cos(x) .Л2] ; » plot(х, у) Приложение 1. Основные команды и функции MATLAB и Toolbox 1045 Дополнительный строковый аргумент задает цвет и стиль линии, и тип маркеров,например: plot(х, у, 'г:о'). Возможно построение нескольких графиков на одних осях, указывая пары вектора значений аргумента и вектора значений функции: plot(x, yl, х, у2, х, уЗ, ...) ИЛИр1о1(х1, yl, х2, у2, хЗ, уЗ, ..С каждой парой может быть указан строковый аргумент (см. разд. "Изменение свойств линий " главы 3). • plot(х, у, 'PropName', 'PropVale', 'PropName', ’PropVale’, . ..)— указание свойств линии каждого графика парами, содержащими название свойства и его значение (свойства линий описаны в разд. "Свойства линий и поверхностей"главы 9), пример: » plot(x, у, 'Marker', 'o', 'Markersize', 5, 'MarkerEdge-Color', 1 g1, 'MarkerFaceColor', 'y') • piot(hA, ...) — вывод графиков на оси с указателем ид вместо текущих. • h = plot (...) — возвращает вектор указателей на созданные рисованные объекты Lineseries. Свойства каждого из графических объектов могут быть изменены в дальнейшем при помощи set (см. главу °). • h = plot ('v6', ...) — возвращает вектор указателей на созданные базовые объекты Line для совместимости с предыдущими версиями MATLAB (базовые и рисование объекты описаны в разд. "Графические объекты”главы 9) П polar — построение графика в полярных координатах. • polar (theta, rho) — отображение зависимости элементов вектора rho от соответствующих значений элементов вектора theta, заданных в радианах. На график наносится сетка. • pioiar(theta, rho, 'r:o') — свойства линии и маркеров определяются дополнительным строковым аргументом (см. функцию plot). П stem — визуализация данных в виде черенковой диаграммы. • stem(x) —- отображение зависимости элементов вектора х от его номеров. • stem(x, у) — вывод значений массива у с абсциссами, указаными в векторе х, пример: » х = (0:0.1:10)’; » у = [sin{x) cos(x)]; >> stem(x, у) Число строк массива у должно равняться длине вектора х. 1046 Приложения • stemfx, у, 1 г*—1) — вывод с указанием цвета и стиля линий и типа маркера. • stem(hA, ...)—вывод на оси с указателем hA. • h = srem(...) -— возвращает вектор указателей на созданные рисованные объекты Stemseries (их число равно количеству столбцов в у). • h = stem(’v6', ...) — возвращает вектор указателей на созданные базовые объекты линии (их число равно количеству столбцов в у). Для совместимости с предыдущими версиями. Базовые и рисованные объекты описаны в разд. "Графические объекты" главы 9. Трехмерные и контурные графики Использование низкоуровневой графики для задания свойств графических объектов объясняется в главах 3 и 9. □ ЬагЗ— вертикальная столбцевая трехмерная диаграмма матричных и векторных данных, пример: ЬагЗ (rand (3,4)). • ЬагЗ (hA, ...) — вывод диаграммы на оси с указателем hA вместо текущих. • h = ЬагЗ (...) — возвращает вектор указателей на созданные полигональные объекты. Свойства полигональных объектов могут быть изменены в дальнейшем при помощи set (еле главу 9). П Ьагзн— горизонтальная столбцевая трехмерная диаграмма матричных и векторных данных, пример: bar3h (rand(3, 4)). bar3h(hA, ... )Hh = bar3h(...) —аналогично ЬагЗ. П comet3— анимированный график трехмерной линии (см. разд. "Анимированные графики"главы 3) • comnt3(x, у, z) — отображение анимированного графика в виде движения кометы по кривой, проходящей через точки с координатами (x(i), у(i), z(i)). • comet3 (х, у, z, р) — дополнительный четвертый аргумент задает длину хвоста кометы p*length(z), по умолчанию используется р = 0.1. comet3 (hA, ...) — вывод анимированного графика на оси с указателем hA вместо текущих. Приложение 1 J^hobh^ib команды и функции MATLAB и Toolbox 104/ П contour— построение линии уровня функции двух переменных (см. разд. "Контурные графики" г павы 3). • contour (X, y, z)—отображение функции, значения koiорой на сетке, определяемой матрицами х и Y, записаны в матрицу z. Линии уровня отображаются при автоматически подбираемых значениях функции. • contour(z)—- в качестве области построения выбирается прямоугольник: х = 1:п, у = 1:т, где [n т] = size (Z). • contour (Z, N) И contour (X, Y, z, n) — отображаются линии уровня, соответствующие N постоянным значениям исследуемой функции, число линий уровня может быть больше ы. • contour (Z, vec) и contour (X, Y, Z, vec) — линии уровня строя гея при значениях, являющихся элементами вектора vec. Число линий уровня равно length (vec). Для отображения только одной линии уровня, на которой функция принимает заданное значение v, следует использовать вызовы: contour (Z, [v v]) или contour (X, Y, z, [v v]). • [c, h] = contour (...) — выходными аргументами являются матрица с информацией о линиях уровня (см. функцию contourc) и указатель на построенные линии (рисованный объект Contourgroup) (см. разд. "Рисованные объекты (Plot Objects) "главы 9). • [С, h] = contour (’v6*...)— выходными аргументами являются матрица с информацией о линиях уровня (см. функцию contourc) и вектор указателей на построенные линии (полигональные объекты). Для совместимости с предыдущими версиями MATLAB. Информация, содержащаяся в матрице с, позволяет расположить рядом с каждой линией уровня соответствующее значение функции при помощи clabel (см. разд. "Контурные графики"главы 3). • Contour(X, Y, Z, ’к:'), (С, h) =contour(X, Y, Z, 'к:') —цвети стиль всех линий уровня задаются при помощи дополнительного строкового входного аргумента (см. функцию plot). П contourc — получение информации о линиях уровня функции двух переменных. • с = contourc (х, Y, z) — матрица с является блочной с = (Cl С2 ...), число блоков совпадает с числом линий j ровня, каждый блок имеет следующий формат (на примере cl): • Cl = [levell xl х2 хЗ ...; pairsl yl у2 уЗ] Значение функции на данной линии уровня содержится в levels, а число пар точек, описывающих линию уровня, как многоугольник 1048 Приложения (объект patch) — в pairsi. Вершинами многоугольника являются точки (xl, yl), (х2, у2) ит. д. Способы задания входных аргументов contourc совпадают с contour. □ contourf— залитый цветами контурный график, использование аналогично функции contour (см. разд. "Контурные графики"главы 3). □ cylinder— отображение цилиндра и 1еиерация точек, лежащих на поверхности цилиндра. • cylinder — построение части цилиндрической поверхности единичного радиуса и высоты. • cylinder 1г, п) — построение части цилиндрической поверхности единичной высоты. Входной аргумент г является вектором значений радиусов поверхности в зависимости от высоты, ап — число точек для построения окружности отрезками прямых, пример: cylinder (10.1 0.3 0.5 1.3 1.8 1.6 0.1], 100). • cylinder (г) — по умолчанию используется двадцать точек вдоль окружности. • cylinder(hA, ...) — вывод цилиндрической поверхности на оси с указателем hA вместо текущих. • [х, у, z] = cylinder(...)— выходными аргументами являются матрицы, определяющие поверхность. Сама поверхность не отображается, ее можно получить при помощи, например: mesh[x, Y, Z), surf(X, У, Z),surfi(X, Y, Z). □ ezcontour — отображение линий уровня функции двух переменных с автоматическим подбором сетки для их нахождения. Заголовок получаемого графика содержит выражение, задающее исследуемую функцию. • ezcontour (fun) — построение лини уровня функции fun, где fun — строка с исследуемой функцией, указатель на нее, inline-функция либо анонимная функция. Задание анонимной функции или указателя требует применения поэлементных операций при определении функции. По умолчанию считается, что область определения — квадрат [-2л, 2л]х[-2л, 2л]. (Использование inline-функций и анонимных функций обсуждается в разд. "В< траиваемые и анонимные функции" главы 6. Обращение к функции по указателю описано в разд. "Файл-функции с ооним входным аргументом” главы 5.) Пример: » fun = inline ( 1 x'*2*cos (у)+уЛ2*з!п (х); » ezcontour(fun) Приложение 1 Основные команды и функции MATLAB и Toolbox 1049 • ezcontour (fun, [xl x2 yl y2])-—областью определения считает ся прямоугольник [xl, x2]X[yl, у2]. • ezcontour (,.., п)— построение линий уровня с использованием сетки с п узлами по каждому направлению. • ezcontour (hA, ...) — вывод линий уровня на оси с указателем иа. • h = ezcontour (...) — запись в вектор h указателей на созданные полигональные объекты. Свойства полигональных объектов могут быть изменены в дальнейшем при помощи set (см. главу 9). □ ez con tour f — получение залитых цветом контурных графиков функции двух переменных. Использование аналогично ezcontour. П ezmesh— построение каркасной модели поверхности функции двух переменных. Использование аналогично ezcontour; кроме того, имеется возможность построения поверхности, заданной параметрически, и отображать функцию на круговой области определения. Вызов ezmesh с выходным аргументом приводит к записи в него указателя на созданную поверхность (см. разд. "Графическое представление функций"главы 17). Пример отображения функции z (х, у) = х2 - у2 на круговой области определения. Переменные х и у принадлежат кругу, вписанному в квадрат [-1,1]х[-1,1]: » z = inline('х^г-у^г’) ; » ezmesh(z, [-5.3 5.3), 'circ') Пример построения параметрически заданной поверхности x(s, r) = scos/, y(s, t)=ssinl, z(s, t) — s/2: » x = inline('s*cos(t)') ; > > у = inline!'s*sin(t); » z = inline('s/2'); » ezmesh(x, y, z) По умолчанию значения параметров t и s принадлежат [-2л. 2л]. Для задания других интервалов следует указать их в четвертом входном аргументе— векторе [ti t2 si s2): > > ezmesh(x, у, z, [-0.9*pi 0.9*pi -0.7*pi O.S*pi]j или, если параметры принадлежат одному интервалу, то > > ezmeshfx, у, z, [-0.6*pi 0.9*pi]) 1050 Приложение П ezmeshc — построение каркасной модели поверхности функции двух переменных и линий уровня на плоскости лу. Использование аналогично ezmesh (см. разд. "Графическое представление функций"главы 17). □ ezpiot3 — отображение параметрически заданной линии в трехмерном пространстве (см. разд. "Графическое представление функций"главы 17). • ezpiot3(x, у, z) — построение параметрически заданной кривой х(г), у(г), z(f) для I из отрезка [0, 2л], где х, у, z — строки с исследуемыми функциями, указатели на них, inline-функции либо анонимные функции. Задание анонимных функций или указателей требует использования поэлементных операций при определении функций. • ezplot3(x, у, z, [train, tmax]) —то же самое, что и ezplot3 (х, у, z), но для значений параметра из отрезка [tmin, tmax]. • ezpiot3 (..., 'animate') — анимированный график, например: » ezplot3('sin(t)1,'cos(t)','t',[0 100],'animate') • ezplot3(hA, . . .), h = ezplot3(...) — аналогично ezcontour. О ezeurf— построение каркасной модели поверхности функции двух переменных. Использование аналогично ezmesh (c.w. разд. "Графическое представление функций"главы 17). П ezsurfc— построение каркасной модели поверхности функции двух переменных и линий уровня на плоскости ху. Использование аналогично ezmesh. П fiii3 — рисование закрашенного цветом многоугольника в трехмерном пространстве (см. разд. "Графическое представление функций" главы 17). • fiii3(x, у, z, с) — рисует закрашенный цветом многоугольник. Вершины многоугольника (x(i), y(i), z(i)) содержатся в трех первых входных аргументах, причем length(x) = length(y) = length(z). Многоугольник должен иметь замкнутую границу, поэтому при необходимости последняя точка соединяется с первой. Четвертый входной аргумент определяет цвет и способ заливки. Заливка многоугольника одним цветом происходит при указании одного из сокращений для иг ста’ 'г', 'д', 'Ь', 'с', 'т', 'у', 'w', 'к1, или вектора из трех элементов в формате [г д ы, например: » fi!13([1 2 -3 1], [011 0], [-1 7 0 -1], 'г') » fill3([l 2 -3 1], [0 11 0], [-1 7 0 -1] , [0.8 0.9 0.3]) Плавное изменение цвета заливки в пределах текущей палитры цвета требует указания вектора значений, соответствующих цвету вершин, Приложена J Основные команды и функции MATLAB и Toolbox 1051 т. е. size (с) = size (а). Указанные значения сначала масштабируются (см. функцию caxis), а затем происходит билинейная интерполяция цвета внутри многоугольной области, например: » fill3([l 2-31], [0110], [-170-1], ... [0.8 0.9 0.3 0.7]) • fill3(x, Y, 2, С)—построение сразу нескольких многоугольников, число многоугольников равно столбцам матриц х, у и z (предполагается, что size(X) = size(Y) = size(Z)). Четвертый аргумент с, задающий цвет заливки, может быть вектором, длина которого совпадает с числом столбцов в матрицах х, Y и z. У казание матрицы с, такой что size (С) = size(X), приводит к плавной заливке каждого многоугольника. • fill3(X, У, Z, C, 'PropName', 'PropVale', 'PropName', ’PropVale1, . . . ) —- пары 'PropName','PropVale' ПОЗВОЛЯЮТ Задать всевозможные свойства многоугольника как полигонального объекта patch, например: » fill3([l 2-31], [0110], [-170 -1], 'у', ... 'EdgeColor', 'д’, 'Linewidth', 4) Функция fili3 допускает построение многоугольных объектов при помощи указания соответствующих четверок аргументов с координа тами и цветом, например: fill3[xl, yl, zl, 'у', х2, у2, z2, 'д') Выходной аргумент, возвращаемый fiii3, является вектором указателей на все построенные многоугольные объекты типа patch. h = fil!3(...) Свойства каждого из графических объектов могут быть изменены в дальнейшем при помощи set (см. главу 9). □ bidder - удаление или отображение частей каркасных поверхностей, скрытых от наблюдателя (см. разО. "Трехмерные графики функций" главы 3). • hidden on — удаление невидимых частей. • hidden off — отображение невидимых частей. • hidden — переключение между режимами on и off. П mesh — построение каркасной поверхности (см. разд. "Iрафики функций двух переменных "главы 2 и разд. "Трехмерные графики функций" главы 3). • meshfx, y, Z) — построение каркасной поверхности, высота в каждом узле каркасной сетки плоскости ху (сетка задается матрицами х и 1052 Приложений у), содержится в соответствующем элементе матрицы z. Матрицы х, Y и z должны быть одинаковых размеров. Цвет линий изменяется в пределах текущей палит ры в зависимости от высоты точек поверхности. Точка обзора устанавливается при помощи функции view (см. разд. "Поворот графика, изменение точки обзора"главы 3). Размет ка осей по умолчанию выбирается так, чтобы обеспечить наилучший вид графика. Изменение разметки осей производится с использованием axis. Поверхность может соответствовать не только однозначной, но и многозначной функции. Соответствующие примеры приведены в раза. "Построение параметрически заданных поверхностей и линий" главы 3. • mesh(x, у, Z) — первые два входных аргумента могут быть векторами. В данном случае узлами каркасной поверхности являются точки (х (j), у (i), z (i, j)), причем длины векторов должны соответствовать размерам матрицы: size (Z) = [length(y) length(x)]. • mesh (Z) — в качестве векторов к и у (см. предыдущий вариант вызова) выбираются х = [1:п],у = [1:т],где [т, n] = size(Z). • mesh(..., С)— для определения цвета поверхности используется матрица с (см. функцию surf). • mesh(..., 'PropName', PropValue, 'PropName', PropValue) — отображение поверхности, свойства которой принимают заданные значения, например: >> [X, Y] = meshgrid(-3*pi:pi/5:3*pi, -5:0.5:4); » Z = sin (X) . *(Y + 5).*(4 - Y); » mesh(X, Y, Z, 'LineStyle', 'none*, 'Marker', '.') • h = mesh (...) — возвращает указатель на построенную поверхность (объект surface). Свойства поверхности в дальнейшем изменяются при помощи set (см. главу 9). П meshc— построение каркасной поверхности вместе с линиями уровня на плоскости ху. Использование аналогично mesh (см. разд. "Трехмерные графики функций"главы 3). □ meshz — построение каркасной поверхности вместе с линиями уровня на поверхности. Использование аналогично mesh. □ piot3 — построение линий в трехмерном пространстве (см. разд. "Построение параметрически заданных поверхностей и линий" главы 3). • piot3(x, у, z)—отображение линии, проходящей через точки с координатами (x(i), y(i), z(i)), где х, у и z являются векторами Приложение 1. Основные команды и функции MATLAB и Toolbox 1053 одинаковой длины. Дополнительный строковый аргумент (см. функцию plot) задает цвет и стиль линии, а также тип маркеров, например: plot(x, у, z, 'г:о'). • ₽lot3 (х, у, z)—отображение линий, проходящих через точки с координатами (Х(х, :), Y(i, z(i, :)), где число линий совпадает с числом столбцов матриц. Матрицы х, у и z должны быть одинаковых размеров. Возможен вызов plot с четвертым дополнительным аргументом, определяющим цвет и стиль сразу всех линий и тип маркеров. Для установки свойств линий по отдельности следует использовать обращение; plot3 (xl, yl, zi, si, x2, y2, z2, s2, ...),где входные аргументы xl, yl, zi, x2, y2, z2 и т. д. могут быть либо векторами, либо матрицами одинаковых размеров, а строковые аргументы sl, s2 и т. д. задают стиль линий. • plot3(х, у, z, 'PropName', 'PropVale', 'PropName', 'PropVale', ...) — указание свойств линии каждого графика парами, содержащими название свойства и его значение (см. функцию plot). • h = plots (...) — выходной аргумент вектор h содержит указатели на все созданные линии (рисованные объекты Lineseries). Свойства каждого из графических объектов могут быт ь изменены в дальнейшем при помощи set (см. главу 9). □ slice — визуализация функции трех переменных при помощи отображения значений на различных плоскостях или поверхностях. • slice(X, У, z, v, sx, sy, sz) — значения функции должны быть вычислены в точках трехмерной сетки, определяемой матрицами х, у и z одинаковых размеров, и записаны в трехмерный массив V. Векторы sx, sy и sz задают плоскости, которые образуют срезы трехмерного пространства. Если, например sx(l) = -2.5, то па плоскости х = -2.5 будет отображаться залитый цветом контурный график исследуемой функции. Цзет в каждой точке определяется при помощи линейной интерполяции. Исследование поведения функции (х2 +y2Jz в объеме хе [-1,1], уе[-2,2] , ze[-l, 1] на срезах, образуемых плоскостями х = ±0.4, у = 0, z = 0,±0.8 , производится при помощи следующих команд: » [X, Y, Z] = meshgrid(-l:0.1:l, -2:0.2:2, -1:0.1:1); » V = (Х.л2 + У.л2).*Z; » slicefx, Y, Z, V, [-0.4 0.4], [0], [-0.8 0 0.8]) Объем можно срезать не только плоскостями, но и различными поверхностями. Матрицы, задающие поверхность, указываются вместо 1С54 Приложения векторов во входных аргументах slice. Отображение функции, определенной выше, на сфере производится при помощи следующих команд: » [XI, YI, ZI] = sphere; » slice(X, Y, Z, V, XI, YI, ZI) Первые три входные аргумента, задающие координаты точек со значениями V, могут быть опущены: slice (v, sx, sy, sz), slice (v, xi, yi, zi). Предполагается по умолчанию, чти x = i:n, y = l:m, Z = l:p, где [n m p] = size (V). • slicet.. method) — способ интерполяции определяется в последнем дополнительном входном аргументе и может быть: ’nearest’, 'linear' (по умолчанию) ИЛИ 'cubic'. • slice (hA, ...) — графический вывод производится на оси с указателем hA. • h = slice (...) — в выходном аргументе возвращается вектор указателей на созданную поверхность. Свойства каждой поверхности могут быть изменены в дальнейшем при помощи set (см. главу 9). □ sphere — отображение сферы и генерация точек, лежащих на поверхности сферы. • sphere — построение в графическом окне единичной сферы. • [х, y, z] = sphere— генерация матриц х, Y и z, соответствующих единичной сфере, причем size(X) = size(Y) = size(Z) = [21 21]. Сама поверхность не отображается, ее можно получить при помощи, например:mesh(X, Y, Z),surf(X, Y, Z),surfl(X, Y, Z). • [x, Y, z] = sphere(n) — выходные матрицы имеют размеры n + 1 на n + 1, поверхность не отображается. • sphere (n) — построение в графическом окне единичной сферы с использованием п + 1 точек по каждому из направлений осей координат. □ stem3 — отображение трехмерных данных в виде черенковой диаграммы. • stem3(Z) — построение зависимости z(i, j) от i и j. Каждое значение Z(i, j) представляется в виде отрезка, начинающегося на плоскости z = о и оканчивающегося круглым маркером. • stem3(x, у, г)—отрезки высоты г (г) начинаются в точках плоскости z = о с координатами (х(1), у (1)), пример: О >> t = 0:pi/10:2*pi; О » х = sin(t); Приложение 1. Основные команды и функции MATLAB и Toolbox 1055 О » у = cos (t) ; О » z = ехр(-х- у); О » stem3(х, у, z) • stem3 filled') — отрезки оканчиваются сплошными круглыми маркерами. Указание четвертого дополнительного входного аргумента позволяет определить цвет и стиль линии и тип маркера (см. функцию plot), например: stem3 (х, у, Z, 'г*'). • h = stems;...) — выходной вектор h содержит указатели, h (1) является указателем на линии, h(2) — на маркеры. Свойства линий и маркеров можно затем изменить при помощи set, например: » h = stem3(x, у, z, 'г*') >> set(h(l), 'Color', 'д') » set(h(2), 'Color', 'b') □ waterfall — построение каркасной поверхности линиями по одному из направлений. • waterfall(X,у,z) — отображается каркасная поверхность (аналогично mesh), но без линий, соответствующих столбцам матриц х, у сетки. Линии, образующие поверхность, направлены вдоль оси х. • waterfail (Z) — аналогично mesh с одним входным аргументом. Для построения каркасной поверхности, линии которой соответствуют столбцам матриц, следует использовать транспонирование: waterfall (X, Y, Z),waterfall(Z). П peaks — функция, предназначенная для демонстрации и изучения графических возможностей MATLAB. Генерируемые значения соответствуют масштабированному двумерному распределению Гаусса. • z = peaks — генерация матрицы значений z, size(Z) = [49 49]. • z = peaks (n)—генерация матрицы значений z, size(Z) = [n nJ. • Z = peaks(v)—генерация матрицы значений Z, size (Z) = length(v). • z = peaks (X, Y) — генерация матрицы значений в узлах сетки, описываемой матрицами х и у. Для получения матриц сетки удобно использовать meshgrid. Вызов peaks без выходных аргументов приводит к отображению каркасной Залитой цветом поверхности функции peaks: peaks, peaks (n), peaks(v), peaks(X, Y). Указание в качестве выходных аргументов матриц х, у и z приводит к записи координат узлов сетки в матрицы х и у и значений peaks в z. 1056 Приложения П surf—построение залитой цветом каркасной модели. Входные аргументы с координатами узлов каркасной сетки и значениями высоты и матрица, определяющая цвет поверхности, задаются в таком же порядке, как и в mesh (см. выше), например: surf (х, Y, z, с) (см. разд. "Трехмерные графики функций”главы 3). Управление способом заливки цветом ячеек каркасной поверхности производится при помощи команды shading, задавемой после вызова surf. Параметры facetd (по умолчанию) или flat задают постоянный цвез ячейки, a shading обеспечивает билинейную интерполяцию цвета между значениями в четырех узлах ячейки. Цвета узлов ячеек определяются значениями элементов матрицы с такого же размера, как и остальные матрицы х, y и z. Процесс заливки цветом ячейки проще всего понять на примере поверхности, состоящей из одной ячейки: » [X, Y] = meshgrid ([-1 1]) X = - 1 1 - 1 1 Y = - 1 -1 1 1 > > Z = X + Y; » С = [0 0; 0 1]; > > colormap(jet) » surf(X, Y, Z, C) > > shading interp Нулевые элементы матрицы с соответствуют синему (в палитре jet) цвету узлов сетки с координатами (-1, -1), (-1,1), (1, -1), а элемент матрицы с, равный единице, отвечает красному цвету в вершине (1,1). Внутри ячейки цвет выбирается при помощи билинейной интерполяции между четырьмя вершинами. Если элементы матрицы с не принадлежат [0,1], то происходит их линейное преобразование к отрезку [О,1]. Функция caxis позволяет устанавливать соответствие между цветом и значением функции для данных осей, a colormap — выбирать произвольные цветовые палитры. Обращение к surf без четвертого аргумента, являющегося ма грицей с цветами узлов, приводит к выбору в качестве с матрицы z, т. е. surf (X, y, z) эквивалентно surf (х, Y, z, z). П surface — низкоуровневая функция для создания поверхностей (слг разд. "Освещение объектов, объект Light (источник света) "главы 9). Приложение 1. Основные команды и функции MATLAB и Toolbox 1057 surface(’PropName', 'PropValue', 'PropName', 'PropValue', . — общий вид вызова surface, позволяющий построить поверхность с заданными свойствами. Ниже перечислены наиболее часто используемые свойства и их возможные значения с необходимыми комментариями. Следует иметь в виду, что поверхность, отображаемая функцией surface, выводится на текущие оси графического окна. Если текущих осей (или окна, нет, то создаются оси, содержащие график поверхности. Однако по умолчанию оси являются двумерными, т. е. наблюдатель смотрит на них с точки, имеющей азимут 90° и угол склонения 0°. Высокоуровненевые графические функции, напротив, выводят график, видимый с точки обзора, азимут которой равен -37.5°, а угол склонения 30е. Для получения привычного вида графика поверхности при помощи surface, следовательно, требуется установить точку обзора, используя функцию view: view(-37.5, 30) (см.разд. "Поворот графика, изменение точки обзора" главы 3). Задание визуализируемых данных производится установкой свойств XData, YData и zData. Значениями данных свойств являются матрицы х, Y и z с координатами узлов каркасной сетки и значениями высоты в соответствующей точке поверхности (см. функцию mesh). Цвет каждого узла сетки задается матрицей в свойстве CData (см. функцию surf выше). Последовательность команд, приведенная ниже, отображает поверхность в одном графическом окне при помощи surf, а в другом — с использованием эквивалентного (за исключением вывода линий сетки) обращения к surface. >> [X, Y] = meshgrid(-3:0.5:3); >> Z = sin(X).*COS(Y).*exp(abs(X.*Y/10)); » surf(X, Y, Z) » figure » surface('XData', X, 'YData', Y, 'ZData', Z, 'CData', Z) ; » view(-37.5, 30) Значение свойства CData может быть матрицей с такого же размера, как х, Y и z. В данном примере с = z. Линейное преобразование значений матрицы к отрезку [0,1] устанавливает соответствие между цветами текущей палитры и значениями матрицы с (индексированный цвет). Способ определения соответствия элементов с цвету зависит от значения свойства поверхности CDataMapping. По умолчанию значение равно 'scaled', что как раз и обеспечивает линейное преобразование. Установка свойству CDataMapping значения 'direct* приводит к интерпретации значений с как номеров цветов текущей палитры, поэтому элементы С(1, j ) ДОЛЖНЫ Принадлежать отрезку [1, length (colormap) ]. 1058 Приложения Цвет каждого узла каркасной сетки поверхности можно задавать напрямую, не привязываясь к цветовой палитре. Значением свойства CData должна быть не матрица, а трехмерный массив размера size (С) = [m n 3J, где [т п] =• size(X), а С(:, 1), С(:, 2), С(: , 3) ЯВЛЯЮТСЯ числами от нуля до единицы, определяющими пропорции красного, зеленого и синего цвет а для каждого узла каркасной сетки. Способ изменения цвета линий каркасной поверхности определяется значением свойства Edgecolor. Заначение 'flat' приводит к постоянному цвету границы в пределах каждой ячейки, 'interp' — обеспечивает плавное изменение от вершины к вершине (используется линейная интерполяция). Фиксированный цвет задается одним из сокращений: 'с', 'т'. 'у', 'к' (по умолчанию), 'г', 'д', 'Ь', 'w', или вектором из трех элементов в RGB. Значение ' попе' приводит к тому, что линии каркасной поверхности не отображаются. Способ заливки ячеек устанавливается при помощи свойства FaceColor. Постоянное значение FaceColor, равное одному из сокращений для цвета или вектору из трех элементов, приводит к заливке всех ячеек одним цветом. Заливка ячейки не производится, если свойство FaceColor имеет значение 'попе'. Изменение цвета в пределах ячейки зависит от 'flat' или 'interp' (см. функцию surf). Значение texturemap позволяет использовать матрицу с размера, отличного от х, Y и г. Следующий гример демонстрирует отображение текстурированной поверхности, сама текстура содержится в графическом файле texture.bmp размера 300 на 300 пикселов, цвет каждого пиксела представляется 24 битами. » С = imread('texture.bmp'); » whos С Name Size Bytes Class C 300x300x3 270000 uintS array Grand total is 270000 elements using 270000 bytes Массив с является трехмерным, третье измерение соответствует цвету в RGB. Перед использованием массива цвета в качестве текстуры его следует преобразовать к типу double и масштабировать элементы: » С = double(С); » С( : , :, 1) = С(:, : , 1)/255; » СС, 2) = С(:, 2)/255; » С(:, 3) = С(:, :, 3)/255; Теперь трехмерный массив вещественных чисел можно использовать для задания цвета поверхности. » surface('XData', X, 'YData', Y, 'ZData', Z, 'CData', C, ... 'FaceColor', 'texturemap', 'CDataMapping', 1 direct'); >> view(-37.5, 30) Приложение 1. Основные команды и функции MATLAB и Tr'olbox 1U59 Исходная текстура и текстурированная поверхность приведены на рис. П2. Рис. П2. Текстура и текстурированная поверхность Стиль и толщина линий каркасной поверхности устанавливаются при помощи свойств Linestyle и Linewidth. Значением Linestyle может быть: ' или a Linewidth — вещественное число, равное толщине линий в пунктах (1 пункт = 1/72 дюйма). Тип, размер и способ закраски границ и внутренности маркеров, помещаемых в узлах каркасной сетки, определяют свойства Marker, MarkerSize, MarkerEdgeColor, MarkerFaceColor. Можно также освещать поверхность и управлять свойствами, определяющими взаимодействие поверхности со светом. Ниже перечислены свойства поверхности, отвечающие за освещение. • Ambientstrengrh— интенсивность ненаправленного окружающего света, который освещает всю поверхность. Значением может быть вещественное число от нуля до единицы, по умолчанию используется 0.3. Цвет определяется значением свойства AmbientLigthCoior осей (объекта axes). • BackFacfeLighting — определение способа частей поверхности в зависимости от направления нормали к поверхности и расположения наблюдателя. Значение reverselit (установленное по умолчанию) соответствует освещению внутренних поверхностей, нормаль к которым направлена от наблюдателя, гак же как и внешних. Внутренние поверхности не освещаются, если свойство BackFaceLighting имеет значение unlit. Освещение границы замкнутых объектов убирается при помощи lit. 35 3w во 1060 Приложения • Diffusestrength— интенсивность рассеиваемого поверхностью света, излучаемого источником. Значение свойства Diffusestrength может принимать вещественные значения от нуля до единицы, по умолчанию используется 0.6. • EdgeLighting И FaceLighting — способ освещения границ и ячеек каркасной поверхности светом, идущим от источника. Свет не оказывает влияния на границы или ячейки каркасной поверхности, если соответствующее свойство установлено в 'попе'. Самым простым способом является равномерное освещение границ ячеек и самих ячеек. Равномерное освещение задается значением 'flat'. Ьолее сложным, но дающим лучший эффект, является способ Гуро, который используется при выборе ' gouraud'. Интенсивность света вычисляется в узлах каркасной сетки, затем интерполируется вдоль границ каждой ячейки. Интенсивность света в точках ячейки определяется при помощи интерполяции вдоль отрезка прямой, соединяющего ребра. Самое естественное освещение поверхности обеспечивается выбором значения ’ phong', соответствующего способу Фонга. Способ Фонга состоит в интерполяции нормали сначала вдоль границ ячейки, а затем внутри ячейки. Зчая нормаль в каждой точке поверхности (в каждом пикселе), можно определить, как она освещена внешним источником света. Метод Фонга требуег достаточно большого объема вычислений по сравнению с другими методами. Листинг П1 содержит пример использования функции surface для построения параметрически заданной поверхности, освещенной одним источником света, кроме ненаправленного света. u = (-2*pi:0.02*pi:2*pi)'; V = -2*pi:0.02*pi:2*pi; X - 0,3*u*cos(v); Y = 0.3*u*sin(v); Z = 0.6*u.z'2*ones (size(v) ) ; figure; axes ; view(-37.5,30) surface('XData', X,'YData', Y, 'ZDat-a', Z, 'CData', Z, .. 'BackFaceLighting', 'reverselit', 'Linestyle1, 'none', 'FaceLj ght ing', 1phong') Приложение 1. Основные команды и функции MATLAB и Toolbox 1061 camlight(30, -50) view(-37.5, 30) colormap(copper) □ surfc— построение залитой цветом каркасной поверхности и линий уровня на плоскости ху. Использование surfc аналогично surf и meshc (см. разд. "Трехмерные графики функций"главы 3). □ surfi — построение освещенной поверхности (см. разд. "Построение осве-гценной поверхности" главы 3). • surfi(Z), surfi(х, Y, z) — отображение равномерно освещенной поверхности окружающим светом. Входные аргументы имеют тот же смысл, что и в mesh или surf surfi(z, s),surfi(x, y, z, s)—дополнительный аргумент s указывает на направление источника света. Допускается указание либо координат в векторе из трех элементов: s = [sx, sy, sz], либо азимута и угла склонения: s = [az, el]. Источник света (по умолчанию) расположен под углом 45° в направлении против часовой стрелки от текущей точки обзора. • surfi (..., 'light’) — помещает источник света (объект light). • h = surfi (...) — возвращает вектор указателей на поверхность и источник света. Визуализация векторных полей П compass — отображение радиус-векторов (см. ра зд. "Визуализация векторных полей”главы 3). • compass (hA, ...) — построение графика на осях с указателем ьа. • h = compass (...) — в вектор h записываются указатели на созданные объекты линии, свойства которых можно изменить при помощи set (см гзаву 9). □ coneplot — визуализация трехмерных векторных полей. Векторное поле задается двумя наборами трехмерных массивов х, y, z и и, v, w (все шесть массивов должны быть одинакового размера). • х, y и z — координаты точек трехмерного пространства, из которых исходя г векторы; • и, v и w — величины проекций век торов на оси х, у и f. W62 Приложения Функция coneplot позволяет указать начальные точки для построения векторов, которые не обязаны совпадать с точками, определенными массивами х, у и z. Координаты этих точек задаются массивами Сх, Су и Cz. • he = coneplot (х, y, z, и, v, w, Cx, Cy, Cz) —визуализация векторного поля конусами, длина каждого конуса пропорциональна длине соответствующего вектора. Выходной аргумент he содержит указатель на созданный полигональный объект (состоящий из конусов). Работа с полигональными объектами описана в главе 9. • he = coneplot (х, y, z, и, v, w, ex, cy, Cz, s) —то же самое, что и предыдущее обращение, но длина каждого конуса увеличивается в з раз (если s не указано, то оно принимается равным 1). Значение з=о отменяет автоматическое масштабирование. Использование функции coneplot, как правило, требует установки некоторых свойств осей. Листинг П2 содержит пример визуализации векторного поля, заданного вектор-функцией u(x,y,z) F(x,y,z) = v(x,y,z) w(x,y,z) V z v{x,y,z^~j—^ и'(х,у,г)=л , - V' + _v" + Z~ y]X~ + y- + z на трехмерной сетке (л,, ур zt)( 7д=| 2 я, которая содержит л =41 узел по каждому из направлений: , 1-1 , /-1 к-1 х,=1 +---; у,=-1 + ----; г* =--------. 20 7 20 20 Точки, из которых исходят конусы, заданы на более редкой сетке (СХ(, СУ’;, CZ.k ),• j=i 2 р; 1=1. 2 q ’ гДе Р ~ 11 С1 ~ ’ УЗЛЫ КОТОрОЙ НС СОВ-падают с (х,-, yj, z^)( j,k=i. 2 п • Для получения значений вектор-функции на сетке (ex,, су}, cz.k), м 2 4=1.2.. ..9 по умолчанию используется линейная интерполяция. ..................................-------------------------------------------- ------------------------- ......................................... Листинг П2. Пример использования функции aoneplot ............................................... • .... ..............-................ ................................... .................................................................. % Задание границ области определения вектор-функции XL - 1; xR - 3; yL = -1; yR - 1; Приложение 1. Основные комаццы и функции MATLAB и Toolbox 1063 zL = 0; zR = 2; % Генерация матриц, содержащих координаты узлов мелкой сетки [X, Y, Z] = meshgrid(xL:0.05:xR, yL:0,05:yR, zL:0.05:zR); % Вычисление компонент вектор-функции на этой сетке U = Х./здгГ(Х.Л2 + У.Л2 + г.Л2); V = Y./sqrt(Х.Л2 + У.Л2 + Z.~2); W = Z./sqrt(X.~2 + У.Л2 + г.Л2); % Генерация матриц, содержащих координаты узлов редкий сетки [Сх, Су, Cz] = meshgrid(xL:(xR - xL)/3:xR, yL:(yR - yL)/3:yR,... zL:(zR - zL)/7:zR); % Создание графического окна figure % Построение векторного поля с увеличением автоматически % масштабированного конуса в 4 раза и запись указателя на порученный % полигональный объект в переменную hC hC = coneplot (X, Y, Z, U, V, W, Cx, Cy, Cz, 4) % Задание зеленого цвета для граней полигонального осъекта % и скрытие ребер (выполняется для каждого конуса) set(hC,'FaceColor','д','EdgeColor','none') % Установка пределов осей, точно соответствующих границам % изменения данных axis tight % Задание точки обзора view(31,28) $ Добавление источника света light % Нанесение подписей к осям xlabel('х') ylabel(’y’) zlahel('z') Функция coneplot допускает другие варианты вызова. • coneplot (и, v, w, сх. Су, Cz) — по умолчанию принимается, что [X, y, z] = meshgrid(l:n, l:m, 1 :р), гдеm, п и р являются размерами массива и (т. е. [m, n, р] = size (и)). • coneplot (..., 'quiver') — вместо конусов рисуются стрелки (см. ниже ФУНКЦИЮ quiver3). 10Ь4 Приложения • coneplot (. . ., 'nearest') ИЛИ coneplot(..., ’cubic ') — вместо линейной интерполяции применяется, соответственно, интерполяции по ближайшим соседям или кубическая (ел/, разд. "Интерполяция двумерных и многомерных данных" г завы о, а также описание функции ini-егрЗ в справочной системе MATLAB). • coneplot(х, y, z, и, v, w, 'nointerp') — то же самое, что и coneplot (X, y, z, u, v, w, Cx, Cy, Cz), но в качестве массивов ex, Су и Cz соответственно принимаются массивы х, Y и z (интерполяция не требуется). • coneplot (hA, ...) — осуществляет графический вывод на оси с указателем hA. • he = coneplot (...) — возвращает указатель на созданный полигональный объект. Этот указатель используется для изменения свойств полигонального объекта. П feather— отображение векторов исходящими из равноотстоящих точек на одной прямой (см. разд. "Визуализация векторных попей"главы 3). feather (hA, . ..JHh = feather (...) —аналогично compass. □ quiver— визуализация двумерного вектороного поля (см. разд. "Визуализация векторных полей"главы 3). • quiver (hA, ...) —аналогично compass. • h = quiver (...) — возвращает указатель на рисованный объект Quivergroup, свойства которого могут быть изменены при помощи set (см. главу 9). • h = quiver('v6', ...) -— возвращает вектор указателей на созданные базовые объекты Line для совместимости с предыдущими версиями MATLAB (базовые и рисованные объекты описаны в разд. "Графические объекты " главы 9). □ quiver3 — визуализация вектор-функции от трех переменных, определенной на некоторой поверхности (ем. разд. "Визуализация векторных попей" главы 3). • quiver3 (X, y, z, и, v, w)—построение вектор-функции [u, v, w], где и = и(х, у, г), v = v(x, у, z), и(л, у, z). Матрицы х, Y и z описывают поверхность, а и, v и w содержат компоненты вектор-функции в соответствующих точках пространства. Требуется, чтобы size(X) = size(Y) = size(Z) = size(U) = size(V) = si2e(W). Приложение 1 Основные команды и функции МА ПАВ и Toolbox 1065 Происходит автоматическое масштабирование длины стрелок, представляющих вектор-функцию в каждой точке для обеспечения наилучшего вида графика. Пример использования: » [X, Y, Z] - sphere; » [U, V, W] = sarfnorm(X, Y, Z),- » mesh(X, Y, Z) » hold on » quiver3(X, Y, Z, U, V, W) • quiver3(X, Y, z, u, v, w, s) —после автоматического масштабирования длин стрелок их длина увеличивается в s раз. Значение s = о предотвращает предварительное масштабирование, и длина стрелок определяется соответствующими элементами матриц х, Y и z. • quiver3(Z, U, V, W), quiver3(Z, U, V, W, s) —построение BeKTOp-функции на поверхности, определяемой матрицей z. • quiver3(..., 'g*-.')— дополнительный последний аргумент позволяет указать стиль и цвет линии, а также тип маркера (см. функцию plot). • h = quiver3 (...) — выходной вектор h содержит указатели, h (1) является указателем на линии, h (2) — на маркеры. Свойства линий и маркеров можно затем изменить при помощи set (см. главу 9). например: » h = quiver3 (X, Y, Z, U, V, W) >> set(h(l), 'Color1, 'r') » set(h(2), 'Color', 'k') Визуализация функции на непрямоугольной области □ deiaunay — триангуляция Делане. tri = deiaunay(х, у) — построение треугольников, координаты вершин которых задаются в векторах х и у. Выходным аргументом является матрица tri с гремя столбцами, каждая строка матрицы соответствует некоторому треугольнику. Строка содержит индексы i, j и к такие, что вершинами треугольника являются точки с координатами (х (i), у (i)), (х (j), у (j)), (х (k), у(k)). Множество треугольников выбирается таким образом, что внутри окружности, описанной вокруг любого треугольника, не лежит ни одной из заданных точек, кроме вершин. 1066 Приложения Пример: » х = [010-10]; » у = [-10100]; >> tri = delaunay(х, у) 4 5 1 5 2 1 4 3 5 3 2 5 Фу нкция rielaundy основана на программе Qhull и допускает задание тех же самых параметров алгоритма триангуляции, что и Qhull (см. http://www.qhull.org/). Функция delaunay используется, например, для задания треугольной сетки при визуализации функций, область определения которых не прямоугольная (см. функции trimesh И trisurf ниже). □ trimesh — построение каркасной поверхности функции на произвольной (не обязательно прямоугольной) области. Область задается сеткой из треугольников. Сетка генерируется при помощи функции delaunay (см. выше). • trimesh (tri, х, у, z)—построение каркасной модели поверхности на треугольной сетке с координатами узлов, заданных в векторах х и у, и значениями функции в векторе z. Матрица tri содержит информацию о триангуляции. Поверхность графика функции является полигональным объектом (Patch) (свойства полигональных объектов и работа с ними описаны в роад. "Объект Patch, цветовое оформление объектов"главы 9). • trimesh (tri, х, у, z, с)—указание цвета полигонального объекта в матрице с. Задание свойств поверхности производится при помощи функции set или непосредственно во входных аргументах: • trimesht..., 'PropName', 'PropValue', 'PropName', 'PropVaiue', • h = trimesh (...) — возвращает указатель на созданный полигональный объект. Применение set для изменения свойств графических объектов рассматривается в главе 9. Приложение 1. Основные команды и функции MATLAB и toolbox 1067 Листинг ПЗ содержит пример построения функции на шестиугольной области. Векторы х и у с координатами узлов сетки генерируются при помощи параметрически заданных окружностей с достаточно большим шагом изменения параметра. Результат приведен на рис. ПЗ. Листинг ПЗ. Построение функции на непрямоуго льной обла ....... ..........X....;....5>.T.4h!..*.~ ...........................................л.:..?..'.;. .......... % Задание вектора со значениями параметра t = 0:pi/3:2*pi; % Генерация внешних узлов области (вершин шестиугольника) х = sin(t); у - cos(t); 5 Генерация двух слоев внутренних узлов х = [х 2/3*sin(t)]; у = [у 2/3*cos(t)]; х = [х l/3*sin(t)]; у = [у l/3*cos(t)]; % Задание дополнительного узла в центре начала координат xdength(x) + 1) = О,-у(length(у) +1) = 0; в Построение сетки tri = delaunay(х, у); % Вычисление значений функции в узлах сетки и запись значений в вектор z z = -х.''2 - у."2; subplot(1, 2, 1) % Отображение графика функции на треугольной сетке и подпись осей Hsurf = trimesh(tri, х, у, z); set(Hsurf, 'EdgeColor', 'k', 'LineWidth', 2) xlabel('x'); ylabel('у1); % Вывод сетки в то же графическое окно на другие оси и подпись осей subplot (1, 2, 2) % Указание в качестве четвертого аргумента нулевых значений приводит к % построению сетки Hfflesh = trimesh(tri, х, у, zeros(size(х))); set(Hmesh, 'EdgeColor', 'k', 'LineWidth', 2) xlabel('x'); 1068 Приложения ylabel('у'); % Определение двумерных осей view(2) Рис. ПЗ. График функции на треугольной сетке и сетка □ trisurf — построение каркасной закрашенной поверхности функции на произвольной (не обязательно прямоугольной) области. Использование аналогично trimesh (см. выше). Оформление графиков □ clabel — помещение подписей к линиям уровня на контурных графиках. • clabel(с, h) — входными аргументами являются: матрица с с информацией о линиях уровня и вектор указателей h на сами линии, являющиеся многоугольниками (графическими объектами типа patch) Данные аргументы инициализируются при соответствующем обращении к contour, contourf или contour3 (см. разд. "Контурные графики" главы 3). • clabel (С, h,v)— маркируются только линии уровня, указанные в векторе v. • clabel (С, h, ‘manual’) — переход в режим ручной разметки линий уровня. Щелчок мышью по линии уровня приводит к появлению на Приложение 1. Основные команды и функции MATLAB и Toolbox 1069 ней подписи со значением функции. Нажатие на <Enter> останавливает режим разметки. • clabel (С), clabel (С, v) ИЛИ clabel (С, 'manual') — практически ТОТ же результат, что и при указании h, но линия уровня отмечается маркером (знаком плюс), рядом с которым помещается значение функции. • hmark = clabel (...) — выходной аргумент является вектором с указа гелями на созданные объекты типа text (и lines, если в качестве входного ар1умента не задавался указатель h на линии уровня). Свойство UserData каждого текстового объекта содержит значение функции на линии уровня. • clabel (. . ., 1 PropName1, ’ PropValue', . . .) — пары ВХОДНЫХ аргументов позволяют задать любое свойство текстовых объект ов, т. е. подписей к линиям уровня. Дополнительное свойство 'Labelspacing' предназначено для определения расстояния в пунктах между подписями, по умолчанию используется 144 пункта (1 пункт = 1/72 дюйма). □ datetick — разметка оси, по которой откладывается время. datetick(tickaxis,dateform)— первый ВХОДНОЙ аргумент tickaxis предназначен для указания оси и может принимать значения 'х‘, 'у' или 'z'. Второй аргумент определяет формат разметки, например: ' dd-пятил-уууу НН:ЫМ:9₽, 'HH:MM:SS' (все возможные значения dateform приведены в справочной системе MATLAB). Для корректной разметки оси времени данные, откладываемые по ней, должны соответствовать серийному времени (СМ. фуНКЦИИ datenum и now). О grid— отображение или скрытие линий координатной сетки (см. разд. "Оформление графиков"главы 3). • gri d on — отображение сетки на текущих осях. • grid off — скрытие сетки на текущих осях. • grid— если линии сетки отсутствуют, то они отображаются, а если присутствуют, то скрываются. Полное управление сеткой осуществляется при помощи свойств XGrid, YGrid EGrid, XMinorGrid, YMinorGrid И ZMinorGrid координатных Осей (см. разд. "Свойства осей"главы 9). □ gtext— режим интерактивного размещения текстовых подписей в пределах графического окна. • gtext ('string1) —- после выполнения данной команды щелчок мыши по области текущего графического окна приводит к помещению текста в выбранную позицию В случае отсутствия графических окон создается новое окно. 1070 Приложения • gtext ((* stringi1, 1 string? ’, ...}) — указание в качестве входного аргумента вектор-строки ячеек из текстовых строк позвочяет вводить многострочный текст. • gtext (|' stringi'; 1 string?'; ...}) — указание в качестве входно- го аргумента вектор-столбца ячеек из текстовых строк позволяет разместить текст за несколько щелчков мышью. • gtext (. . ., ’ PropName ’ , PropValue, . . . ) — пары ВХОДНЫХ аргументов определяют свойства добавляемого текста, как объекта text (свойства текстовых объектов описаны в разд. "Вывод текстовой информации" главы 9). □ hold— управление выводом нескольких графиков в одно окно (слс разд. "Вывод нескольких графиков на одни оси" главы 3 и "Влияние команд hold, cla. elf и reset на свойства окна и осей" главы 9). • hold on — каждый новый график добавляется в текущее графическое окно. • hold off — каждый новый график отображается в текущем т-рафиче-ском окне, переписывая содержимое окна. • held— переключение между режимами добавления графика и выводом нового графика с потерей предыдущих. □ legend— помещение легенды на график (см. разд. "Оформление графиков" главы 5). • legend (stringi, string?, string3, ...) — входные аргументы ЯВЛЯЮТСЯ строками или строковыми переменными, содержащими пояснения для графических объектов, расположенных на текущих осях. • legend(h, stringi, string?, string3, ...)—первый входной аргумент является вектором указателей на графические объекты,.информация о которых должна содержаться в легенде. Объекту с указателем Ь(1) соответ) твует stringi, h(?) —string? и т. д. Текст легенды может задаваться не только в строках или строковых переменных, но и в массиве строк : legend (М) ИЛИ legend(h, Ml (работа с массивами строк описана в разд "Массивы строк" главы 9). • legend (Нах, ...)—размещение легенды на оси с указателем нах. • legend off — удаление легенды с текущих осей. • legend (нах, 'off') — удаление легенды с осей, указатель на которые Нах. Приложение 1. Основные команды и функции MATLAB и Toolbox 1071 • Hleg = legend — возвращает указатель на легенду текущих осей, если легенды нет, то Hleg = [ ]. • legend(. . ., 'Location', location) — «адание ПОЛОЖЕНИЯ легенды В векторе location = [х у width height], где х И у— координаты нижнею лево! о угла в системе координат графического окна, a width и height — ширина и высота легенды. Единицы измерения определяются в нормализованных единицах (елг разд. "Размещение окон, осей и текста"главы 9). Параметр location может принимать одно из предопределенных текстовых значений, например: 'North', 'South' и др. (см. разд. "Оформление графика"главы 3). Произволоное положение легенды определяется в режиме редактирования графиков (c.w. главу 4). Программное изменение положения и свойств объектов легенды производится при помощи обращения [hLeg, hO, hP, txt] = legend]...), которое возвращает: указатель на оси легенды (hLeg), указатели на графические и текстовые объекты легенды (ьо), указатели на объекты графика (hP), массив ячеек из текстовых строк легенды (txt). Свойства данных объектов могут быть изменены при помощи функции set (см. главу 9). □ subplot— разбиение графического окна на несколько подграфиков и определение текущего подграфика (см. разд, "Несколько графиков в одном графическом окне"главы 3). □ title — добавление заголовка на график (см. разд. "Оформление графика" главы 3). • title (str) — текст, содержащийся во входном аргументе (строке или строковой переменной) помещается в графическом окне вверху осей. Текст может быть представлен в формате ТеХ. Список всех символов, которые могут быть заданы при помощи команд ТеХ, содержится в справочной системе MATLAB в разделе со свойствами объекта типа text (см. свойство string). • title (str, 'PropName', PropValue,...) — помещаемый заголовок (объект text) имеет свойства, определяемые парами входных аргументов. Например, для использования интерпретатора LaTeX следует установить свойство interpreter в значение ' latex' (см. разд. "Вывод математических формул в формате LaTeX"главы 9): » h = title (' $$f (х) = 1п1Ит1ЬЕ_0лх t sin t dt$$', 'Interpreter1, 'latex') 1072 Приложения • h = title (...)— возвращает указатель на создаваемый заголовок (текстовый объект), свойства которого могут быть изменены при помощи функции set (саг. разд. "Вывод те каповой информации" главы 9). 3 xiabei, yiabei и ziaoei — подписи к осям (см. разд. "Оформление графика " главы 3). • xiabei (str) — текст, содержащийся во входном аргументе (строке или строковой переменной), используется в качестве подписи к оси х (для остальных осей аналогично). • xiabei (str, PropName, PropValue, — помещаемая ПОДПИСЬ К оси (объект text) имеет свойства, определяемые парами входных аргументов (см разд. "Вывод текстовой информации"главы 9). • h = xiabei (...) — возвращает указатель на создаваемую подпись к оси (объект text), для изменения его свойств следует воспользоваться функцией set (см главу 9). Управление видом графика, камера Несколько разделов книги посвящены описанию способов, предлагаемых М'Х'П .АВ для изменения вида графиков (см. разд "Поворот графика, изменение точки обзора" главы 3 и разд. "Обзор графиков и поверхностей" главы 7). Ниже приведены основные функции MATLAB, предназначенные для установки требуемого вида осей графического окна. Объектом в данном разделе будет называться содержимое осей (то, на что направлена камера), которое может состоять из нескольких графических объектов МА TLAB, к примеру, поверхности (Surface) и многоугольника (Patch). Г) camdoily — изменение положения камеры и объекта. • camdolly (dx, dy,dz) — перемещение камеры и объекта на dx, dy и dz в системе координат камеры. Перемещение вправо или влево определяется значением dx, вверх или вниз — dy, вдоль оси камеры — dz. Единицы измерения должны соответствовать видимой области, например. camdolly(1, -1, 0) приводит к перемещению объекта в левый верхний угол. • camdolly (dx, dy, dz, targetmode) — дополнительный четвертый входной аргумент targetmode позволяет задать раздельное перемещение камеры и объекта. Значение ‘movetarget' (используемое по умолчанию) соответствует перемещению и камеры, и объекта, а ’ f ixtarget' — ТОЛЬКО камеры. Приложение 1. Основные команды и функции MA1LAB и Toolbox 1073 camdolly (dx,dy,dz, targetmode, coordsys) — ПЯТЫЙ дополнительный аргумент coordsys предназначен для указания системы координат и единиц измерения перемещений, задаваемых dx, dy и dz. По умолчанию используется значение 'camera', которое обеспечивает передвижение в системе координат камеры (см. функцию camdoJ ly(dx, dy, dz) выше). Для изменения положения камеры на плоскости экрана следует использовать 'pixels', причем первые два входных аргумента dx и dy задают смещение в пикселах, a dz игнорируется. Часто удобно определять величины перемещений в системе координат осей, для чего следует в качестве пятого входного аргумента указать 'data'. • camdolly (нах, ...) — перемещение камеры и объекта осуществляется на осях с указателем Нах. □ camiookat— направление камеры на нужный графический объект или объекты. Применяется в том случае, когда на осях расположено несколько графических объектов и требуется укрупнить вид одного или нескольких из них. camiookat (h) — направление камеры на графический объект, указателем на который является h (в случае нескольких объектов используется вектор указателей). Последовательность команд, приведенная ниже, обеспечивает noci роение двух каркасных сферических поверхностей на одних осях и последовательное направление камеры сначала на первую сферу, а затем на вторую: » [X, Y, Z] = sphere; »Х1=Х-1; » Yl = Y - 1; » Z1 = Z - 1,- » Х2 = X + 1; » Y2 = Y+1; » Z2 = Z + 1; » Hl = mesh(Xl, Yl, ZI); » hold on » H2 = mesh(X2, Y2, Z2) ; » camiookat(Hl) » camiookat(H2) □ camorbit — поворот камеры вокруг объекта. • camorbit (dtheta, dphi) — поворот камеры вокруг объекта текущих осей на угол dtheta по горизонтали и dphi по вертикали (значения указываются в градусах). Листинг П4 содержит пример использова- 1074 Приложения ния camorbit во вложенных циклах с целью осмотра поверхности со всех сторон. *1" V'" ' — ------------Т-- ' Листинг П4. Fрай.1' figure surf(peaks(40)) for i = 1:4 pause(1) for j ~ 1:36 camorbi t(10, 0 J pause(0.01) end camorbit(0, 90) end Возможно указание различных способов поворота камеры вокруг объекта. • camorbit (dtheta, dphi, coordsys, direction) — дополнительные входные аргументы coordsys и direction предназначены для указания системы координат и направления, вокруг которого происходит поворот. Возможны два значения для coordsys: 'data* (используется по умолчанию) и 'camera'. Если указано 'data', то поворот камеры происходит вокруг линии, идущей вдоль выбранного направления от точки, на которую нацелена камера. Направление задается во входном аргументе direction и может быть вектором из трех координат [х у z] или символами 'х', 'у' или 'z' для указания поворота вокруг определенной координатной оси. Выбор в качестве coordsys значения camera' приводит к повороту на угол dtheta по горизонтали и dphi по вертикали относительно точки объекта, на которую нацелена камера. • camorbit (Нах, ...) — поворот камеры применяется к объектам, расположенным в пределах осей с указателем Нах. □ campan— поворот объекта вокруг камеры. Использование аналогично camorbit. □ campos — установка или определение положения камеры. Положение камеры определяется вектором из трех элементов в декартовой системе координат. • с = campos — выходной аргумент вектор с содержит координаты камеры в декартовой системе координат текущих осей. Приложение 1. Основные команды и функции MATLAB и Toolbox 1075 • campos ([х у z]) •— задание положения камеры в декартовой системе координат осей. • cpmode = campos('mode') —- выходной api умент является строковой переменной и может быть 'auto' или 'manual' в зависимости от значения свойства осей CameraPositionMode (см. разд. "Управление камерой” главы 4). • campos(mode) — установка свойства осей CameraPositionMode. ВХОДНОЙ аргумент может принимать значения 'auto' или 'manual'. • campos (Нах, ...) — управление положением камеры на осях с указателем Нах. □ c=unproj — установка или определение типа проекции осей трехмерных графиков на экран. • proj = camproj — выходной аргумент proj содержит тип проекции трехмерных осей на экран. Возможны два варианта: 'orthographic* или 'perspective', в зависимости от значения свойства Projection осей координат. • camproj (projection) — задание типа проекции трехмерных осей на экран ('orthographic* или 'perspective'). • camproj (Нах, ...) — установка или определение типа проекции осей с указателем Нах на экран. □ camroll — поворот камеры вокруг ее оси (взаимное расположение камеры и объекта описано в разд. "Управление камерой" главы 4). • camroll (dtheta) — поворот камеры на угол dtheta (в градусах) по часовой стрелке. Пример содержится в листинге П5. Листинг П5. Поворот камеры вокруг ее оси г...........—.......................... sphere hold on cylinder for i = 1:60 pause(O.Ol) camroll(6) end 1076 Приложения Применение поворота камеры к осям с указателем нах производится при ПОМОЩИ обращения camroll (Нах, dtheta). □ camtarget — позиционирование камеры. • с = camtarget — возвращает вектор с координатами точки, на которую направлена камера, в декартовой системе координат текущих осей. • camtarget ([х у z]) — устанавливает положение точки, на которую направлена камера в декартовой системе координат текущих осей, т. е. свойство CameraTarget принимает значение [х у z] (см. разд. "Управление камерой" главы 4). • ctmode = camtarget ('mode') — выходной аргумент является строковой переменной и содержит значение 'auto' или ’manual' свойства CameraTargetMode. • camtarget (mode) — устанавливает режим позиционирования камеры, т. е. СРОЙСГВО CameraTargetMode принимает значение mode ('auto' ИЛИ 'manual'). • camtarget (Нах, ...) — позиционирование камеры на осях с указателем Нах. П сатир — установка или получение направления вектора камеры. • v = сатир — выходной аргумент v является вектором камеры в декартовой системе координат текущих осей (см. разд. "Управление камерой" главы 4). • сатир([х у г]) — входной аргумент задает вектор камеры в декарт о-вой системе координат текущих осей. Длина вектора не имеет значения, важно определяемое им направление. Свойство cameraupvector принимает значение [х у z], • upmode = сатир (1 mode’)— выходной аргумент является строковой переменной и содержит значение 'auto' или 'manual ' свойства CameraUpVectorMode. • сатир (mode) — устанавливает режим выбора направления вектора камеры, Т. е. СВОЙСТВО CameraUpVectorMode принимает значение mode ('auto' ИЛИ ’manual'). • сатир(Нах, ...)— установка или получение направления вектора камеры осей с указателем Нах. Приложение 1. Основные команды и функции MATLAB и Toolbox 1077 □ camva — установка и получение угла обзора объекта камерой. • с = camva — выходной аргумент с является углом обзора (в градусах) объекта камерой на текущих осях (см. разд. "Управление камерой" главы 4). • camva(а) — входной аргумент а задает угол обзора (в градусах) объекта камерой на текущих осях. Свойство CameraViewAngle принимает значение с. • cvamode = =amva ('mode') — выходной аргумент является строковой переменной и содержит значение ('auto' или 'manual') свойства CameraViewAngleMode. • camva (mode) — устанавливает режим выбора угла обзора, т. е. свойство CameraViewAngleMode принимает значение mode ("auto' ИЛИ ’manual"). • camva (ах,...) — установка и получение угла обзора объекта камерой на осях с указателем Нах. □ camzoom — изменение угла обзора об ьекта камерой. • camzoom (р) — значение входного аргумента р, большее единицы, приводит к увеличению угла обзора, если р меньше единицы, но больше нуля, то угол обзора уменьшается. Свойство CameraViewAngleMode принимает значение "manual •, а значение earneraVxawAngle изменияет-ся соответствующим образом. Пример применения camzoom приведен в листинге Пб. ........ - ..................................•.......................... Листинг Пб. Изменение угла обзора объекта ....................... и....... Пи.. ................................. sphere for i = 10:-1:3 pause(0.05) camzoom (1/10) end for i = 3:10 pause(0.05) camzoom(10) end 1078 Hpi, u>;em И шгнение угла обзора камерой объекта, расположенного на осях с указателем Нах производится При ПОМОЩИ обращения camzoom (Нах, р). □ dasp. ct— изменение или получение масштаба осей. • d = daspect — возвращает вектор d, определяющий масштаб текущих осей. • daspect ([х у z])— установка соотношения масштабов текущих осей, важна пропорция элементов вектора, например: daspect([l 2 1]) Hdaspect([10 20 10]) приводят К одинаковым результатам. Свойство DataAspectRatio принимает значение [х у z], a DataAspectRatioMode— 'manual1. При отображении реальных геометрических объектов для сохранения соотношения i ео-метрических размеров следует устанавливать [ 1, 1, 1], например: >> sphere » daspect([1 1 1]) • darmode = daspect ('mode') — выходной аргумент является строковой переменной и содержит значение ("auto1 или ’manual") свойства DataAspectRatioMode. • daspect (mode) — устанавливает режим выбора масштаба осей, т. е. СВОЙСТВО DataAspectRatioMode принимает значениеmooe ("auto’ или "manual ’). • daspect (Нах, ...) — изменение или получение масштаба осей с указателем Нах. □ poaspect — установка или определение соотношения длин осей. • v = pbaspect — в вектор v записывается соотношение длин текущих осей. • pbaspect ([х у z])— установка соотношения длин текущих осей, важна пропорция элементов вектора, например: pbaspect ([1 1 1]) и pbaspect([io ю 10]) приводят к одинаковым результа там. Свойство piotBoxAspectRatio принимает значение [х у z], а PlotBoxAspectRatioMode — "manual'. • pbarmode = pbaspect ( "mode") -—ВЫХОДНОЙ аргумент pbarmode ЯВЛЯет-ся строковой переменной и содержит значение ("auto1 или "manual") свойства PlotBoxAspectRatioMode. • pbaspect (mode) — устанавливает режим выбора соотношения длин осей, Т. е. свойство PlotBoxAspectRatioMode принимает значение mode ("auto" ИЛИ "manual"). Приложение 1. Основные команды и функции MATLAB и Toolbox 1079 • pbaspectux, ...)— изменение или получение соотношения длин осей с указателем нах. □ view — установка или определение точки обзора. • view (az, el) или view ([az, el]) — задание положения точки обзора при помощи азимута и угла склонения, выраженных в 1радусах (см. разд. 'Поворот графика, изменение точки обзора”главы 3). • view(2) — задание двумерных осей с az = о. el = 90 (наблюдатель смотрит на оси сверху, вдоль оси z). • view(3) — изменение вида осей с азимутом и углом склонения, выбираемыми по умолчанию: az = -37.5, EL = 30. • [az, el] = view — получение текущих значений азимута и угла склонения. • view(T) — установка точки обзора при помощи матрицы преобразования Т, size(Т) = [4 4] (см. функцию viewmtx). • т = view— получение текущей матрицы преобразования значений азимута и угла склонения. □ viewmtx — вычисление матрицы преобразования. • т = viewmtx(az, el) — возвращает матрицу ортогонального проектирования для отображения трехмерных объектов на плоскости (экране мониз ора) в соответствии с точкой обзора, определяемой азимутом и углом склонения (см. функцию view). Сама точка обзора на текущих осях не изменяется. Для получения матрицы проектирования, соответствующей текущему положению точки обзора, следует использовать обращение г = view. • т = viewmtx(az, el, phi) — возвращает матрицу проектирования, обеспечивающую перспективное изображение. Третий входной аргумент phi определяет величину перспективы, значение phi = 0 соответствует эргогональной проекции Матрица т преобразует векторы длины четыре [х у z 1]' к векторам, первые две компоненты которых, поделенные на четвертую, являются искомыми проекциями на плоскость экрана. Листинг П7 содержит пример изображения куба с различной перспективой. 1080 Приложения figure % Задание координат вершин куба х = [0 11 0 00 1 100 1 1 1 10 0]; у = [0 011000110001 11 1]; z = [0 00001111110011 0]; % Циклическое изменение значения перспективы for phi = 0:10:90 % Получение матрицы проектирования Т = viewmtx(-37.5, 30, phi); % Нахождение проекций V = Т*[х; у; z; ones(size(х))]; xl = v(l, :)./v(4, :); yl = v(2, :)./v(4, :); % Вывод результата на двумерные оси plot(xl, yl) pause(1) end Приложение 2 Описание компакт-диска К книге приложен компакт-диск, который содержит листинги программ и команды, приведенные в тексте. Диск организован следующим образом. В корневом каталоге находятся папки с именами Work_XX, где XX — номер главы. Каждая папка содержит М-файлы и файл readme txt, в котором описано соответствие между именами М-файлов и номерами листингов программ данной главы. Папки с номерами Work_10, Work_l 1, Work_12, Work_13 и Work_22 отвечают тем главам, которые посвящены созданию приложений с графическим интерфейсом пользователя. Изучая эти главы, вы будете программировать подфункции обработки событий и модифицировать их. Многие файлы содержат подфункции, предназначенные для вставки в основную функцию обработки событий. Поэтому имена М-файлов с подфункциями называются listing_x.m, где х— номер листинга в тексте. Это же замечание касается одного файла listing_17.m в папке Work_16 с набором подфункций для приложения с графическим интерфеисом. В каждый каталог Work_XX помещен файл summaryXX.m, представляющий из себя М-файл, разбитый на ячейки, который содержит основные с точки зрения авторов команды и функции из текста книги, не оформленные в виде листингов. Используя редактор М-файлов, их можно исполнять одновременно с чтением книги, не набирая в командной строке. Рекомендуется последовательное выполнение ячеек, т. к. команды ячейки могут использовать ранее созданные переменные среды (организация работы в М-файле, разбитом на ячейки, описана в розД "Разбиение М-файла на ячейки"главы 5). Другая возможность состоит в открытии файлов summaryXX.m текстовым редактором (можно изменить расширение для упрощения вызова на txt) и копировании исполняемого кода в командную строку MATLAB Для использования прилагаемых М-файлов следует либо скопировать их в текущий каталог MATLAB, либо скопировать целиком подкаталог и сделать его текущим (установка текущего каталога описана в разд. "Установка путей” главы 5, которая целиком посвящена работе с М-файлами и редактору М-файлов). После этого вы можете запустить М-файл из командной строки или редактора М-файлов или вызвать как файл-функпию (в зависимости от содержимого М-файла). Список литературы 1. Ануфриев И, Е. Самоучитель MatLab 5.3/б.х.— СПб.; БХВ-Петербург, 2002. — 736 с. 2. Дьяконов В. П. Matlab 6/6.1/6.5+Simulink 4/5. Основы программирования Руководство пользователя. — М.: Солон-Пресс, 2002. — 768 с. 3. Мэтьюз Д., Финк К. Численные методы. Использование MATLAB (3-е издание). — СПб.: Вильямс, 2001. — 720 с. 4. Чен К., Джиблин П., Ирвинг A. MATLAB в математических исследованиях. — М.: Мир, 2001. — 346 с. 5. Черных И. В. Simulink: среда создания инженерных приложений. — М.: Диалог-МИФИ, 2004. — 496 с. 6. Kwon Y.W. The Finite Element Method using MATLAB. — Boca Raton a. o.: CRC Press, 1997. —519 p.
ОтложитьЧитал
00
добавлено 2023-04-18 15:15:24
В сжатой форме проанализированы принципы построения сообщений, формируемых протоколами транкинговых сетей радиосвязи на …
ОтложитьЧитал
00
добавлено 2022-12-06 22:05:20
Пособие знакомит с основами программирования в программном комплексе Matlab. С использованием большого числа примеров ра…
ОтложитьЧитал
00
добавлено 2022-09-28 13:33:12
Изложены необходимые для освоения курса сведения – краткий конспект лекций, методические указания к выполнению лаборатор…
ОтложитьЧитал
00
добавлено 2022-05-31 19:06:27
В работе приведены эффективные приемы работы с распространенными программными средствами математического и имитационного…
ОтложитьЧитал
00
добавлено 2021-12-09 13:36:09
Рассмотрены вопросы построения моделей Matlab систем спектрального анализа в пространстве частот Фурье и Меллина, а такж…
ОтложитьЧитал
00
добавлено 2021-10-01 16:24:34
В статье рассматриваются математическая основа и имитационное моделирование процессов насыщения трансформаторов тока апе…
ОтложитьЧитал
00
добавлено 2021-08-31 10:50:22
Предложен метод предварительной оценки прагматической ценности информации в задаче классификации состояния объекта на ос…
ОтложитьЧитал
00
добавлено 2021-03-24 16:12:09
Учебное пособие посвящено моделированию и обработке сигналов в программах Matlab 9.6 и Mathcad 14. Рассмотрены наиболее …
ОтложитьЧитал
00
добавлено 2021-03-24 15:24:31
Учебное пособие содержит изложение теоретических и практических основ разработки приложений в среде MATLAB + Simulink в …
ОтложитьЧитал
00
добавлено 2020-01-10 12:36:09
В данной статье рассматривается проблема разработки систем технического зрения предварительной обработки изображений с ц…
ОтложитьЧитал
00
добавлено 2019-10-29 14:11:19
В работе представлено описание математических моделей различных технических объектов и систем, а также технологические т…
ОтложитьЧитал
00
добавлено 2019-10-29 19:23:50
Самоучитель по массовой матричной системе MATLAB, занимающей лидирующее место в области научно-технических вычислений, р…
ОтложитьЧитал
00
добавлено 2019-10-29 19:14:36
Данная книга предлагает практическое введение в MATLAB – пакет прикладных программ для решения задач технических вычисле…
ОтложитьЧитал
00
добавлено 2019-10-25 12:58:04
Данная книга посвящена изложению вопросов совместного использования богатой библиотеки визуальных компонент Borland C++ …
ОтложитьЧитал
00
добавлено 2019-08-28 18:05:21
Данная книга посвящена изложению вопросов совместного использования богатой библиотеки визуальных компонент Borland C++ …
ОтложитьЧитал
00
добавлено 2019-07-19 12:55:03
В статье изложено построение экспертно-диагностической системы для анализа предкризисного состояния предприятий металлур…
ОтложитьЧитал
00
добавлено 2019-04-04 19:21:05
Книга для новичков и продвинутых трейдеров, желающих раздвинуть горизонты традиционного анализа рынка. Пошаговая инструк…
ОтложитьЧитал
00
добавлено 2019-04-16 16:43:11
Изложены основные вопросы курса «Математическое моделирование систем автоматического управления» по программному пакету …
ОтложитьЧитал
00
добавлено 2018-11-09 12:24:52
Учебное пособие представляет собой базовый курс по цифровой обработке сигналов с традиционными темами: линейные дискретн…
ОтложитьЧитал
00
добавлено 2018-09-27 17:43:01
Практикум содержит методические рекомендации для выполнения практических занятий по ознакомлению и получению навыков раб…
ОтложитьЧитал
00
добавлено 2018-06-19 19:09:52
Описаны результаты экспериментальных исследований производственных образцов красного шлама и получены параметры, необход…
ОтложитьЧитал
00
добавлено 2018-03-23 10:07:00
Постоянный прогресс в области информационных технологий изменяет методы и подходы к их использованию. Увеличивается объе…
ОтложитьЧитал
00
добавлено 2017-06-30 10:06:18
Представлены многомерные методы идентификации нелинейных динамических объектов (НДО) с использованием операторов Гаммерш…
ОтложитьЧитал
00
добавлено 2017-06-22 22:55:12
Авторами разработано устройство, включая программное обеспечение для обработки данных, отслеживающее функционирование се…
ОтложитьЧитал
00
добавлено 2017-05-31 23:21:00
Рассматриваются модели, методы и алгоритмы анализа данных, используемые в современных системах обработки информации. При…
ОтложитьЧитал
00
добавлено 2017-01-30 10:18:26
Всех, кто работал с системой MATLAB, поражает удивительная легкость написания программ на языке MATLAB для решения самых…
ОтложитьЧитал
00
добавлено 2016-06-29 20:15:21
В учебное пособие, ориентированное на семестровый курс лекций, включены классические разделы теории кодирования: линейны…
ОтложитьЧитал
00
добавлено 2016-01-16 12:44:04
Рассмотрены методы построения разностных схем для дифференциальных уравнений в частных производных и средства их компьют…
ОтложитьЧитал
00
добавлено 2015-06-23 18:08:52
Предлагаемая читателю книга может служить учебником по теории вейвлетов и их применениям в системе MATLAB. Она предназна…
ОтложитьЧитал
00
добавлено 2016-04-04 03:36:51
Книга является вторым изданием первого тома 5-томной серии книг по системе MATLAB+Simulink. Впервые в одной книге описан…
ОтложитьЧитал
00
добавлено 2016-06-25 03:48:36
В книге описаны пакеты расширения Control System Toolbox и Robust Control Toolbox системы MATLAB 7, предназначенные для …
ОтложитьЧитал
00
добавлено 2016-06-25 19:45:29
В книге представлена современная практическая технология компьютерного моделирования экономики в программных системах MA…
ОтложитьЧитал
00
добавлено 2015-10-21 19:36:19
Пятая книга в серии книг, посвященных последним реализациям мощных матричных систем компьютерной математики MATLAB 6.5 S…
ОтложитьЧитал
00
добавлено 2015-10-21 18:41:44
В этой второй, но вполне самостоятельной справочной монографии по новейшим системам MATLAB 6.5 SP1/7 + Simulink 5/6 опис…
ОтложитьЧитал
00
добавлено 2015-05-29 03:12:19
Третья книга в серии работ, посвященных двум последним реализациям мощных матричных систем компьютерной математики MATLA…
ОтложитьЧитал
00
добавлено 2015-05-29 02:38:10
Первый том трехтомной справочной монографии впервые описывает две новейшие версии мощной матричной системы MATLAB (6.5 S…
ОтложитьЧитал
00
добавлено 2015-05-29 02:14:02
Практическое руководство по новой перспективной системе визуального блочного математического моделирования VisSim 3/4.5/…
ОтложитьЧитал
00
добавлено 2015-04-04 01:23:52
В этой второй, но вполне самостоятельной справочной монографии по новейшим системам MATLAB 6.5 + Simulink 5 описано их п…
ОтложитьЧитал
00
добавлено 2014-06-27 16:12:49
В книге рассматриваются основные разновидности адаптивных фильтров и их применение в радиотехнических системах и система…
ОтложитьЧитал
00
добавлено 2015-02-18 02:37:52
Излагаются теоретические основы численных методов, включая теорию погрешностей, особенности машинной арифметики, коррект…