22 Полные системы логических функций. - ВЕ-12-05

advertisement
1) Понятие алгоритма, его свойства, логические теории алгоритмов.
Алгоритм - это определённая последовательность действий, которые необходимо выполнить, чтобы получить
результат. Алгоритм может представлять собой некоторую последовательность вычислений, а может последовательность действий нематематического характера. Для любого алгоритма справедливы общие закономерности
- свойства алгоритма.
Свойства алгоритма.
*
Дискретность.
*
Понятность
*
Детерминированность
*
Массовость
*
Результативность
Дискретность - это свойство алгоритма, когда алгоритм разбивается на конечное число элементарных действий
(шагов).
Понятность - свойство алгоритма, при котором каждое из этих элементарных действий (шагов) являются законченными
и понятными.
Детерминированность - свойство, когда каждое действие (операция. указание. шаг. требование) должно пониматься в
строго определённом смысле, чтобы не оставалась места произвольному толкованию. чтобы каждый, прочитавший
указание, понимал его однозначно.
Массовость - свойство, когда по данному алгоритму должна решаться не одна, а целый класс подобных задач.
Результативность – свойство, при котором любой алгоритм в процессе выполнения должен приводить к
определённому результату. Отрицательный результат также является результатом.
Алгоритм может быть записан различными способами: на естественном языке в виде описания; в виде графических
блок-схем; на специальном алгоритмическом языке. В школе на уроках информатики для записи алгоритмов
используется, так называемый, "школьный алгоритмический язык". Этот язык по существу является "мёртвым" языком,.
так как на нём не работают компьютеры, и мы не будем им пользоваться. Запись алгоритмов на родном языке доступна
и удобна. Примеров таких записей множество, хотя бы книга кулинарных рецептов есть не что иное, как сборник
алгоритмов, написанных на родном языке.
Существенным недостатком такой записи является недостаточная наглядность, что особенно сказывается, когда
алгоритм имеет много ветвлений. Поэтому, мы будем записывать наши алгоритмы в виде блок-схемы.
Основные блоки алгоритмов.
Все имеющиеся алгоритмы можно разделить на три вида:
*
линейные алгоритмы;
*
алгоритмы ветвления;
*
циклические алгоритмы.
1
В примере алгоритма “Телефонный разговор” имеются все три вида алгоритмов, хотя пример носит не математический
характер. Если задача решается с помощью математического аппарата, то в зависимости от степени сложности задачи,
чаще всего используется также три вида алгоритмов: линейные, ветвление и циклы. Для решения любых задач
достаточно этих трех видов алгоритмов.
Теорема Дейкстра. Алгоритм любой сложности можно реализовать, используя только три конструкции: следования
(линейные), выбора (ветвления) и повторения (циклические).
Логические теории алгоритмов вполне пригодны для решения теоретических вопросов о существовании или
несуществовании алгоритма, но они никак не помогают в случаях, когда требуется получить хороший алгоритм, годный
для практических применений. Дело в том, что с точки зрения логических теорий алгоритмы, предназначенные для
практических применений, являются алгоритмами в интуитивном смысле. Поэтому при решении проблем,
возникающих в связи с созданием и анализом таких алгоритмов, нередко приходится руководствоваться лишь
интуицией, а не строгой математической теорией. Таким образом, практика поставила задачу создания содержательной
теории, предметом которой были бы алгоритмы как таковые и которая позволяла бы оценивать их качество, давала бы
практически пригодные методы их построения, эквивалентного преобразования, доказательства правильности и т.п.
Последовательные вычислители. Машина Тьюринга, как формальная модель последовательного
вычислителя. Значение машины Тьюринга. Общие черты и отличия между машиной Тьюринга и
реальными вычислителями.
Появилась в 30-х годах 20 века.
Машина Тьюринга состоит из трех частей: ленты, считывающе-записывающей головки и логического устройства
Лента выступает в качестве внешней памяти; она считается неограниченной (бесконечной) – уже это свидетельствует о
том, что машина Тьюринга является модельным устройством, поскольку ни одно реальное устройство не может
обладать памятью бесконечного размера.
2)
2
Рис. 7.1. Схема машина Тьюринга.
Лента разбита на отдельные ячейки, однако, в машине Тьюринга неподвижной является головка, а лента передвигается
относительно нее вправо или влево. Другим отличием является то, что она работает не в двоичном, а некотором
произвольном конечном алфавите A = { , a1…a n} – этот алфавит называется внешним. В нем выделяется
специальный символ –
, называемый пустым знаком – его посылка в какую-либо ячейку стирает тот знак, который до
этого там находился, и оставляет ячейку пустой. В каждую ячейку ленты может быть записан лишь один символ.
Информация, хранящаяся на ленте, изображается конечной последовательностью знаков внешнего алфавита, отличных
от пустого знака.
Таким образом, в машине Тьюринга реализуется система предельно простых команд обработки информации. Эта
система команд обработки дополняется также предельно простой системой команд перемещений ленты: на ячейку
влево, на ячейку вправо и остаться на месте, т.е. адрес обозреваемой ячейки в результате выполнения команды может
либо измениться на 1, либо остаться неизменным. Однако, хотя фактически происходит перемещение ленты, обычно
рассматривается сдвиг головки относительно обозреваемой секции – по этой причине команда сдвига ленты влево
обозначается R («Right»), сдвига вправо – L («Left»), отсутствие сдвига – S («Stop»).
Обработка информации и выдача команд на запись знака, а также сдвига ленты в машине Тьюринга производится
логическим устройством (ЛУ). ЛУ может находиться в одном из состояний, которые образуют конечное множество и
обозначаются Q ={q1…qm, z} , причем, состояние z соответствует завершению работы, а q1 является начальным
(исходным). Q совместно со знаками R, L, S образуют внутренний алфавит машины. ЛУ имеет два входных канала (ai,
qi) и три выходных (ai+1, qi+1, Di+1)
/***********************Другой источник******************************/
По сути своей, алгоритм есть механический процесс обработки информации. Впервые Алан Тьюринг определил понятие
алгоритма исходя из понятия автоматически работающей машины; более того, он предложил формальную модель
такого устройства, которое интуитивно моделирует действия человека, решающего задачу руководствуясь некоторым
алгоритмом. Это устройство было названо мишиной Тьюринга. Как окаэывается, машина Тьюринга являетсявесьма
простым расширением модели конечного автомата. При выполнении алгоритма в интуитивном смысле мы можем
пользоваться потенциально неограниченной памятью, запоминая в процессе выполнения алгоритма по мере
необходимости нужную информацию, например, на листочке бумаги. В то же время, основным ограничением конечного
автомата является конечность числа его состояний, а значит, его памяти. Можно предположить, что именно поэтому
конечный автомат не может быть использован как модель устройства, выполняющего произвольные алгоритмы.
Если к модели КА добавить способность запоминания произвольно больших объемов информации, то его возможности
по выполнению алгоритмов расширятся, и мы получим автомат с более широкими возможностями по преобразованию
информации, иными словами, с более широким классом алгоритмов, которые могут быть выполнены автоматами этого
нового типа. Алан Тьюринг в 1936г. предложил формальную модель вычислителя, которая является результатом
простого добавления потенциально бесконечной памяти к конечному автомату.
3
Рассмотрим, чем отличается машина Тьюринга от простой модели конечного автомата. Конечный автомат можно
представить себе как устройство с конечным числом внутренних состояний, работающее с двумя лентами: входной и
выходной (рис.5.1). Конечный автомат работает по тактам. На каждом такте он читает с помощью некоторой входной
головки символ из обозреваемой ячейки входной ленты, изменяет свое состояние и печатает некоторый символ
выходного алфавита в обозреваемую ячейку выходной ленты, после чего две его головки чтения и записи перемещаются
на одну позицию вправо. Описание функционирования конечного автомата можно считать его программой: в ней
просто перечислено конечное число четверок (команд) <s,a,p,y)>, где s – текущее состояние, a - очередной входной
сигнал, р - следующее состояние и у - очередной выходной сигнал.
Программа КА - это просто перечисление аргументов и соответствующих результатов частично-определенной функции
переходов и выходов автомата .:S.X>S.Y. В своем вычислительном устройстве Тьюринг просто смоделировал
доведенный до самых элементарных операций процесс выполнения произвольного алгоритма человеком. Человек имеет
конечную память, и в этом смысле его можно представить системой с конечным числом состояний. Исходная
информация к алгоритму обычно представляется в виде цепочки символов. Можно себе представить, что эта
информация представлена в виде слова (конечной последовательности символов) конечного словаря. Выполняя
алгоритм, человек-вычислитель использует дополнительную память (которая может быть потенциально бесконечной,
например, листы бумаги) для записи информации, причем эта запись производится им последовательно, символ за
символом. При вычислениях человек может возвращаться к ранее записанной информации, стирать некоторую
информацию и т.д. Таким образом, элементарными операциями при выполнении алгоритма можно считать запись и
стирание символа, а также перенесение внимания с одного участка записи на другой. Предложенная Тьюрингом
формальная модель отличается от конечного автомата только в этих двух аспектах: она имеет одну бесконечную
рабочую ленту, с которой читает и куда пишет символы, и одну головку чтения-записи, которая может двигаться по
рабочей ленте в любую сторону (рис.5.1). Такая свобода движения головки чтения-записи по сути означает возможность
создавать и впоследствии анализировать промежуточную информацию. Как оказывается, такое простое расширение
возможностей радикально увеличивает вычислительную мощность машин Тьюринга по сравнению с обычными
конечными автоматами.
Машина Тьюринга работает по тактам. На каждом такте она читает символ из обозреваемой ячейки рабочей ленты,
изменяет свое состояние в зависимости от своего внутреннего состояния и прочитанного символа и печатает символ в
обозреваемую ячейку рабочей ленты, после чего ее головка чтения-записи может переместиться на одну позицию влево,
вправо или остается на месте. Описание функционирования МТ можно считать ее программой, которая представлена
конечным набором пятерок (команд) < s,a,p,y,D >, где s, a, р и у имеют тот же смысл, что и в конечном автомате, а D направление перемещения головки по рабочей ленте, которое может быть одним из трех значений: L -влево, R - вправо
и Н - оставаться на месте. Иными словами, программа МТ- это просто конечный список пятерок, представляющих собой
аргументы и соответствующие им результаты частично-определенной функции переходов и выходов .:S.X>S.X.Г.
4
Машина Тьюринга имеет один конечный рабочий алфавит X, в котором входные и выходные символы не различаются:
выходной символ, напечатанный на ленте, машина может прочитать в последующих тактах. Для удобства обычно
считают, что X содержит пустой символ ., находящийся во всех ячейках рабочей ленты слева и справа от конечной
цепочки “значащих” символов в начале работы.
Рассмотрим, как работает машина Тьюринга. Конфигурацией машины Тьюринга называется ее текущее состояние,
текущее состояние рабочей ленты и место расположения головки. При работе МТ в каждом такте происходит смена
конфигураций. Пусть МТ находится в состоянии s и в обозреваемой ячейке ленты находится символ a. Если в
программе МТ нет команды для пары <s,a>, то МТ останавливается. Если в программе МТ несколько команд для данной
пары <s,a>, то это - недетерминированная машина Тьюринга, в ней выполняется одна из нескольких возможных команд
с левой частью <s,a>. Очевидно, что в любой момент работы на ленте МТ находится только конечная цепочка
“значащих” символов. После останова машины Тьюринга эта цепочка является результатом переработки входной
цепочки. Таким образом, МТ является автоматом-преобразователем символьных цепочек.
Машина Тьюринга также может быть распознавателем множеств цепочек. В такой МТ выделяются специальные
заключительные состояния стоп или “!”, и если МТ, работающая как распознаватель, останавливается в одном из этих
состояний при пустой входной ленте, то она распознает входную цепочку. Если в заключительном состоянии
останавливается машина-преобразователь Тьюринга, то информация на рабочей ленте является результатом
переработки входной информации.
3) Параллельные вычислители. Однородные структуры как формальная модель параллельных
вычислителей. Статическая часть ОС-модели. Динамическая часть ОС-модели
Каждая параллельная программа содержит несколько процессов, совместно работающих над решением некоторой
задачи
Каждая программа - это совокупность последовательных ВП, которые выполняются параллельно.
Последовательный ВП => Существует 1 поток управления
Параллельный поток => Существует несколько потоков управления
Организация взаимодействия ВП
1)Посылка сообщений между ВП;
2)Применение разделяемых переменных (переменная, которая используется несколькими процессами по очереди)
Синхронизация ВП
Взаимные исключения (критические секции, которые не выполняются одновременно)
Условная синхронизация (задержка выполнения процесса) до наступления определённого условия
Классы параллельного программирования
многопоточные ВС – содержат ВП больше, чем ЦП => выполняются по очереди (здесь используются разделяемые
переменные)
Распределенные ВС – ВП выполняются на процессорах, объединенных в сеть (обмен сообщениями или удаленный
вызов)
Синхронные параллельные вычисления ЦП> ВП (й ВП выполняется на нескольких ЦП)
Существует параллелизм по данным (отдельная ВС решает разные задачи) и по задачам (все ВС решают одну и ту же
задачу)
Существует 5 парадигм параллельного программирования
Интерактивный параллелизм (циклические процессы)
Рекурсивный параллелизм (независимые рекурсивные вызовы процедур)
Конвейеры (выход одного ВП является входом другого)
Клиент-сервер
Взаимодействующие равные (работа над 1 задачей)
Это взято из лекций по ТВП
3 . Параллельные вычислители. Однородные структуры как формальная модель параллельных вычислителей.
Статическая часть ОС-модели. Динамическая часть ОС-модели
Современные тенденции развития перспективных архитектур высокопараллельной ВТ и средств микроэлектроники,
проблемы моделирования дискретных параллельных процессов, теория параллельных дискретных динамических
систем, дискретные математика и синергетика, задачи искусственного интеллекта и робототехники, параллельные
алгоритмы и обработка информации, а также целый ряд других важных предпосылок в различных областях
современного естествознания определяют в последние годы новый подъем интереса к различного рода клеточным
формальным моделям высокопараллельного образа действия, важнейшей из которых являются однородные структуры
(ОС; основной синоним - клеточные автоматы; в англоязычной терминологии соответственно - Homogeneous Structures
и Cellular Automata), рассматриваемые ниже.
5
2.1.Концепция формальных ОС-моделей.
Однородные структуры являются формализацией понятия бесконечных регулярных решеток (сетей) из идентичных
конечных автоматов, которые информационно связаны друг с другом одинаковым образом в том смысле, что каждый
автомат решетки может непосредственно получать информацию от вполне определенного для него конечного
множества соседних ему автоматов. При этом соседство понимается не в геометрическом, а в информационном плане.
Соседство автоматов устанавливается постоянным для каждого автомата решетки и определяется специальным
вектором - индексом соседства. Как правило, рассматриваются d-мерные регулярные решетки в Евклидовом
пространстве Ed, в целочисленные точки которого помещены копии некоторого автомата Мура. В качестве простого
примера ОС-модели можно представить себе бесконечную клеточную бумагу, в каждой клетке которой расположена
копия автомата Мура
ОС функционирует в дискретные моменты времени T (T=0,1,2,...) так, что каждый автомат решетки может синхронно
изменять свое состояние в дискретные моменты времени T0 как функция состояний всех своих соседей в предыдущий
момент времени (T-1). Эта локальная функция перехода может со временем меняться, но остается всегда постоянной
для каждого автомата решетки в любой конкретный момент времени T0. Одновременное применение локальной
функции перехода ко всем автоматам решетки определяет глобальную функцию перехода в структуре, которая
действует на всей решетке, изменяя текущую конфигурацию состояний автоматов решетки на новую конфигурацию.
Изменение конфигураций структуры под действием глобальной функции определяет динамику функционирования ОСмодели с течением времени, которая играет основную роль в исследованиях ее поведенческих свойств.
Состояния единичных автоматов ОС можно ассоциировать с различными понятиями, такими как: состояния
биологических клеток, команды (инструкции) клеточных микропроцессоров, символы некоторых параллельных
формальных систем и т.д. Тогда как сама история конфигураций в ОС ассоциируется с динамикой погружаемых в
структуру различного рода дискретных моделей,процессов, алгоритмов и явлений. Подобные модели могут быть
применены в таких различных областях как: распознавание образов, машинное самовоспроизведение, морфогенез,
теория эволюции и развития, адаптивные и динамические системы, искусственный интеллект и робототехника,
вычислительная техника и информатика, математика, кибернетика, синергетика,физика, космология и др. Мы можем
интерпретировать ОС не только как абстракцию биологических клеточных систем, но также как теоретическую основу
искусственных параллельных систем обработки информации и вычислений. С логической точки зрения ОС являются
бесконечными абстрактными автоматами со специфической внутренней структурой, определяющей целый ряд важных
свойств и допускающей использование ее в качестве новой перспективной среды моделирования различных дискретных
процессов, допускающих режим максимального распараллеливания. ТОС, в целом, может рассматриваться как
структурная и динамическая теория бесконечных абстрактных автоматов, наделенных специфической внутренней
организацией, носящей качественный характер. В настоящее время ТОС образует вполне самостоятельный раздел
современной кибернетики со своими методами, проблематикой и приложениями, а сами структуры служат формальной
средой для моделирования многих параллельных дискретных процессов и явлений в различных областях науки и
техники .
2.2.Основные понятия и определения ОС-моделей.
Основное изложение материала будет базироваться на понятии классических d-мерных (d 1) однородных структур (dОС), относительно которого здесь вводится ряд основных определений. Классическая d-ОС определяется как
упорядоченная четверка компонент где A - конечное непустое множество, называемое алфавитом внутренних состояний
единичных автоматов структуры и представляющее собой множество состояний, которые может принимать каждый
элементарный (единичный) автомат структуры. Алфавит A содержит так называемое состояние покоя, обозначаемое
символом “0”; суть этого особого состояния будет выяснена несколько позже. Не нарушая общности, в качестве Aалфавита будем использовать множество состояний A={0,1,2,3,...,a-1}, содержащее a элементов - чисел от 0 до (a-1).
Компонента Zd представляет собой множество всех d-мерных кортежей - целочисленных координат точек в евклидовом
Ed пространстве, т. е. Zd представляет собой целочисленную решетку в Ed, элементы которой служат для
пространственной идентификации единичных автоматов структуры. Компонента Zd определяет однородное
пространство структуры, в котором она функционирует. Можно показать [1], что другие типы регулярных решеток в
качестве однородного пространства не вносят относительно динамических свойств ОС-моделей математически ничего
нового, т.е. вполне достаточно ограничиться пространством Zd. Естественно, что в целом ряде прикладных аспектов dОС их геометрия играет, порой, существенную роль, однако здесь данный вопрос не рассматривается.
В каждую точку пространства Zd помещается копия конечного автомата Мура, алфавит внутренних состояний которого
есть A. Как известно, автомат Мура представляет собой конечный автомат, выход которого в данный момент времени T
зависит только от его внутреннего состояния в этот же момент времени T и не зависит от значения его входов. В этом
случае каждая точка Zd определяет имя или координату единичного автомата, помещенного в данную точку.
Компонента X, называемая индексом соседства структуры, есть упорядоченный кортеж n элементов из Zd,который
служит для определения автоматов-соседей любого единичного автомата структуры, т.е. тех ее автоматов, с которыми
данный единичный автомат непосредственно связан информационными каналами.
6
Каждый единичный автомат структуры в любой дискретный момент времени T может получать информацию только от
своих непосредственных соседей и передавать информацию о своем текущем состоянии также только им. Таким
образом, непосредственными соседями единичного автомата zО Zd являются автоматы z+x1,z+x2,...,z+xn, где
X={x1,x2,...,xn}; xjО Zd (j=1.. n). Индекс соседства X описывает единый шаблон соседства (геометрический образ
соседей-автоматов) для каждого единичного z-автомата структуры. Он определяет позиции автоматов-соседей
относительно каждого конкретного единичного z-автомата, который имеет с ними непосредственный информационный
интерфейс. Если индекс соседства X содержит элемент 0d={0,0,...,0}, то каждый единичный автомат структуры
принадлежит собственному шаблону соседства. В дальнейшем, не нарушая общности, будем полагать, что X-индекс
соседства содержит 0d-элемент, определяющий центральный автомат шаблона соседства. Доказано [1,4], что динамика
d-ОС (d і 1) не зависит от выбора в качестве центрального любого автомата шаблона соседства структуры.
В качестве простейшего примера структуры 2-ОС пространство Z2 можно представить себе в виде клеточной бумаги,в
каждой клетке которой расположена копия некоторого конечного автомата Мура (аМ). Тогда Xн={(0,0),(0,1),(1,0),(0,1),(-1,0)} и Xм={(i,j)} (i,jО {0,1,-1}) называются соответственно индексами соседства Джон фон Неймана и Мура. Эти
индексы соседства стали классическими и широко используются в исследованиях теоретических и прикладных аспектов
d-ОС, а определяемые ими шаблоны соседства имеют прозрачные геометрические образы . Очевидно, в одномерном
случае оба типа индексов соседства совпадают.
Первые три рассмотренные компоненты d-ОС, а именно, A-алфавит состояний единичных автоматов, однородное
пространство Zd и X-индекс соседства образуют однородную среду, являющуюся статической частью ОС-модели.
Данная часть описывает физическую организацию структуры и ее геометрию, но не специфицирует взаимодействия
(динамики) среди составляющих ее единичных автоматов. Для определения функционирования d-ОС необходимо иметь
возможность описывать текущие состояния всех единичных автоматов структуры в любой дискретный момент времени
Tі 0.
Состояние всей однородной среды называется конфигурацией (КФ) d-ОС и представляет собой набор текущих
состояний всех составляющих ее единичных автоматов. А именно, конфигурация d-ОС есть любое отображение КФ: Zd
A и C(A,d) обозначает множество всех таких конфигураций относительно Zd и A,
Специальным символом “d“ обозначается полностью нулевая КФ; я d:Zd 0, когда все единичные автоматы d-ОС
находятся в состоянии покоя “0”. Множество конфигураций C(A,d) неоднородно относительно динамики
функционирования d-ОС по причине наличия выделенного состояния покоя, поэтому определяются два основных его
подмножества конфигураций: конечных и бесконечных.
Функционирование d-ОС осуществляется в дискретной шкале времени T=0,1,2,... и определяется локальной функцией
перехода (ЛФП) s (n), которая задает состояние каждого единичного z-автомата структуры в момент времени T на
основе состояний всех соседних ему автоматов (согласно X-индекса соседства) в момент времени (T-1).
Вместе с тем, понятие классических d-ОС=<Zd,A,t (n),X обладает вполне приемлемой степенью общности для многих
важных приложений, не взирая на всю его простоту. И, если компоненты Zd, A и X структуры являются весьма
простыми и прозрачными, то о сложности ГФП t (n), определяющей собственно динамику ОС-моделей, пока ничего не
говорилось. Этот вопрос удобнее всего оказалось рассматривать в терминах теории рекурсивных функций [97-100]. Из
определения классической d-ОС нетрудно убедиться, что она представляет собой параллельный алгоритм переработки
конечных КФ (слов) из словарного множества C(A,d,f ) посредством ГФП, которую можно рассматривать как словарную
функцию, всюду определенную на множестве C(A,d,f ). На основе данного подхода было доказано [27], что
произвольная ГФП в классической d-ОС примитивно рекурсивна. Данный результат определяет не только место ГФП в
иерархии всех рекурсивных функций, но и совместно с отмеченной простотой остальных компонент структуры
позволяет говорить о том, что определяемый ими такой простой объект, как классические d-ОС, обладает достаточно
большой степенью общности и весьма сложной динамикой, позволяющей моделировать достаточно широкий класс
явлений, процессов и феноменов, имеющих место в целом ряде разделов науки и техники. Наряду с этим, он
представляет несомненный интерес для исследования как самостоятельная формальная модель параллельной обработки
информации и вычислений, обладающая свойством универсальной вычислимости. В рамках данного класса ОС-моделей
выделяются интересные подклассы структур (с рефрактерностью, с памятью и др.), хорошо отвечающие задачам
моделирования в ряде важных научно-прикладных областей современного естествознания .
4) Аналоговые вычислительные машины. Обобщенная структура
Аналоговая вычислительная машина (АВМ) — вычислительная машина, в которой каждому мгновенному значению
переменной величины, участвующей в исходных соотношениях, ставится в соответствие мгновенное значение другой
(машинной) величины, часто отличающейся от исходной физической природой и масштабным коэффициентом. Каждой
элементарной математической операции над машинными величинами, как правило, соответствует некоторый
физический закон, устанавливающий математические зависимости между физическими величинами на выходе и входе
решающего элемента (например, законы Ома и Кирхгофа для электрических цепей, выражение для эффекта Холла,
лоренцовой силы и т. д.).
В АВМ все математические величины представляются как непрерывные значения каких-либо физических величин.
Главным образом, в качестве машинной переменной выступает напряжение электрической цепи. Их изменения
7
происходят по тем же законам, что и изменения заданных функций. В этих машинах используется метод
математического моделирования (создаётся модель исследуемого объекта). Результаты решения выводятся в виде
зависимостей электрических напряжений в функции времени на экран осциллографа или фиксируются измерительными
приборами. Основным назначением АВМ является решение линейных и дифференцированных уравнений.
Достоинства АВМ:
высокая скорость решения задач, соизмеримая со скоростью прохождения электрического сигнала;
простота конструкции АВМ;
лёгкость подготовки задачи к решению;
наглядность протекания исследуемых процессов, возможность изменения параметров исследуемых процессов во
время самого исследования.
Недостатки АВМ:
- малая точность получаемых результатов (до 10%);
- алгоритмическая ограниченность решаемых задач;
- ручной ввод решаемой задачи в машину;
- большой объём задействованного оборудования, растущий с увеличением сложности задачи
Задачи
Контроль и управление. В системах автоматического управления АВМ пользуются, как правило, для определения или
формирования закона управления, для вычисления сводных параметров процесса (кпд, мощность, производительность и
др.). Если задано математическое выражение, определяющее связь сводного параметра или управляющего воздействия с
координатами объекта, АВМ служат для решения соответствующего уравнения. Результат вычислений поступает либо
на исполнительный механизм (замкнутая система), либо к оператору. Когда закон управления заранее не определён, а
заданы лишь некоторый критерий оптимальности и граничные условия, АВМ применяются в системах поиска
оптимального управления и служат математической моделью объекта.
Опережающий анализ, основанный на быстродействии. Многократно решая систему уравнений, описывающих
управляемый процесс, учитывая его текущие характеристики, АВМ за короткое время «просматривает» большое число
вариантов решений, отличающихся значениями параметров, подлежащих изменению при управлении процессом.
Намного опережая ход процесса, АВМ прогнозирует сигналы управления, которые могут обеспечить необходимое
качество протекания процесса. В режиме опережающего анализа АВМ выполняют функции либо машин-советчиков,
либо управляющих машин, автоматически учитывающих текущие характеристики процесса и управляющих им по
оптимальным показателям. Выбор наилучшего режима технологического процесса осуществляется также
самонастраивающимися математическими машинами в режиме опережающего анализа.
Экспериментальное исследование поведения системы с аппаратурой управления или регулирования в лабораторных
условиях. С помощью АВМ воспроизводится та часть системы, которая по каким-либо причинам не может быть
воспроизведена в лабораторных условиях.
Анализ динамики систем управления или регулирования. Заданные уравнения объекта решаются в выбранном
масштабе времени с целью нахождения основных параметров, обеспечивающих требуемое протекание процесса.
Решение задач синтеза систем управления и регулирования сводится к подбору по заданным техническим условиям
структуры изменяемой части системы, функциональных зависимостей требуемого вида и значений основных
параметров. Окончательный результат получается многократным повторением решения и сопоставлением его с
принятым критерием близости.
Решение задач по определению возмущений или полезных сигналов, действующих на систему. В этом случае по
дифференциальным уравнениям, описывающим динамическую систему, по значениям начальных условий, известному
из эксперимента характеру изменения выходной координаты и статистическим характеристикам шумов в измеряемом
сигнале определяется значение возмущения или полезного сигнала на входе. АВМ может также служить для построения
приборов, автоматически регистрирующих возмущения и вырабатывающих сигнал управления в зависимости от
характера и размера возмущений.
Эффективность применения
Повышение эффективности АВМ связано с внедрением в аналоговую технику цифровых методов, в частности
цифровых дифференциальных анализаторов. Их применение снижает общий объём аппаратуры, хотя в остальных
случаях они существенно уступают цифровым вычислительным машинам. Гораздо большими возможностями обладают
гибридные вычислительные системы, у которых исходные величины представлены одновременно в цифровой и
аналоговой форме.
Перспективны для полной автоматизации АВМ так называемые матричные модели. Их основной недостаток — большое
количество аппаратуры — в связи с появлением интегральных схем уже не имеет решающего значения.
Решающие элементы
АВМ состоят из некоторого числа решающих элементов, которые по характеру выполняемых математических операций
делятся на:.
8
линейные решающие элементы - выполняют операции суммирования, интегрирования, перемены знака, умножения на
постоянную величину и др.
нелинейные (функциональные преобразователи) - воспроизводят нелинейные зависимости. Различают решающие
элементы, предназначенные для воспроизведения заданной функции от одного, двух и большего числа аргументов. Из
этого класса обычно выделяют устройства для воспроизведения разрывных функций одного аргумента (типичные
нелинейности) и множительно-делительные устройства.
логические — к таким решающим элементам относятся устройства непрерывной логики, например предназначенные
для выделения наибольшей или наименьшей из нескольких величин, а также устройства дискретной логики, релейные
переключающие схемы и некоторые др. специальные блоки. Для связи устройств непрерывной и дискретной логики
широко пользуются гибридными логическими устройствами (например, компараторами). Все логические устройства
обычно объединяются в одном, получившем название устройства параллельной логики. Оно снабжается своим
наборным полем для соединения отдельных логических устройств между собой и с остальными решающими
элементами АВМ.
Вследствие не идеальности работы отдельных решающих элементов, неточности установки их коэффициентов передачи
и начальных условий, решение, найденное с помощью АВМ, имеет погрешности. Результирующая погрешность зависит
не только от перечисленных первичных источников, но и от характера и особенностей решаемой задачи. Практически
можно считать, что погрешность при исследовании устойчивых нелинейных систем автоматического управления не
превышает нескольких %, если порядок набираемой системы дифференциальных уравнений не выше 10-го.
Типы АВМ
В зависимости от физической природы машинных величин различают механические, пневматические,
гидравлические, электромеханические и электронные АВМ. Наиболее распространены электронные АВМ,
отличающиеся значительно более широкой полосой пропускания, удобством сопряжения нескольких машин между
собой и с элементами аппаратуры управления. Решающие элементы АВМ строятся в основном на базе многокаскадных
электронных усилителей постоянного тока с большим коэффициентом усиления в разомкнутом состоянии и глубокой
отрицательной обратной связью
По структуре различают АВМ с ручным и с автоматическим программным управлением. В первом случае
решающие элементы перед началом решения соединяются между собой в соответствии с последовательностью
выполнения математических операций, задаваемых исходной задачей. В машинах с программным управлением
последовательность выполнения отдельных математических операций может меняться в процессе решения задачи в
соответствии с заданным алгоритмом решения
Аналоговые вычислительные машины. Обобщенная структура.
На основе подобия или изоморфизма
Управляющая система
Система
индикации
Система
масштабирования
Система
коммутации
Операционный блок (линейный, нелинейный)
Пульт
пользователя
Операционный усилитель (ОУ) (транзистор…)
Линейные: +,-, *, 1/х, dx, любые Const
Нелинейные: /, интеграл, f (x, y, t)
АВМ – параллельный принцип
Бывают:
специального назначения
общего назначения
персональные машины
Характеристики:
9
Принцип вычислений – параллельный
Входной сигнал – значение напряжения
Набор операций – основные арифметические d и s
Точность – низкая
Область значений – должна существовать модель, описывающая диф. и интегр. уравнениями
Требования к пользователю – навыки моделирования + инженерное образование
Это взято из лекций по ТВП
5) Гибридные вычислительные машины. Обобщенная структура
Гибридная вычислительная система, аналого-цифровая вычислительная машина, комбинированная вычислительная
машина, комбинированный комплекс из нескольких электронных вычислительных машин, использующих различное
представление величин (аналоговое и цифровое) и объединённых единой системой управления. В состав Г. в. с., кроме
аналоговых и цифровых машин (АВМ и ЦВМ) и системы управления, обычно входят преобразователи представления
величин, устройства внутрисистемной связи и периферийное оборудование (см. структурную схему на рис.). Г. в. с. —
комплекс ЭВМ, в этом её главное отличие от гибридной вычислительной машины, названной так потому, что она
строится на гибридных решающих элементах, либо с использованием аналоговых и цифровых элементов.
Расчленение вычислительного процесса в ходе решения задачи на отдельные операции, выполняемые АВМ и ЦВМ в
комплексе, уменьшает объём вычислительных операций, возлагаемых на ЦВМ, что при прочих равных условиях
существенно повышает общее быстродействие Г. в. с.
Различают аналого-ориентированные, цифро-ориентированные и сбалансированные Г. в. с. В системах первого типа
ЦВМ используется как дополнительное внешнее устройство к АВМ, предназначенное для образования сложных
нелинейных зависимостей, запоминания полученных результатов и для осуществления программного управления АВМ.
В системах второго типа АВМ используется как дополнительное внешнее устройство ЦВМ, предназначенное для
моделирования элементов реальной аппаратуры, многократного выполнения небольших подпрограмм.
Создание эффективных гибридных комплексов требует в первую очередь уточнения основных областей их применения
и детального анализа типичных задач из этих областей. В результате этого устанавливают рациональную структуру
гибридного комплекса и формируют требования к его отдельным частям.
Задачи, которые эффективно решаются на Г. в. с.
1. моделирование в реальном масштабе времени автоматических систем управления, содержащих как аналоговые, так и
цифровые устройства; (пример, моделирование системы управления прокатного стана. Динамика процессов в нём
воспроизводится на аналоговой машине, а специализированная управляющая станом машина моделируется на
универсальной ЦВМ среднего класса. Вследствие кратковременности переходных процессов в приводах прокатных
станов, полное моделирование таких процессов в реальном масштабе времени потребовало бы применения
сверхбыстродействующих ЦВМ.);
2. воспроизведение в реальном масштабе времени процессов, содержащих высокочастотные составляющие и
переменные, изменяющиеся в широком диапазоне (являются задачи управления движущимися объектами, в т. ч. и
задачи самонаведения, а также задачи, возникающие при создании вычислительной части комплексных тренажеров. Для
задач самонаведения характерно формирование траектории движения в процессе самого движения. Большая скорость
изменения некоторых параметров при приближении объекта к цели требует высокого быстродействия управляющей
системы, превышающего возможности современных ЦВМ, а большой динамический диапазон — высокой точности,
трудно достижимой на АВМ При решении этой задачи на Г. в. с. целесообразно возложить воспроизводство уравнений
движения вокруг центра тяжести на аналоговую часть, а движение центра тяжести и кинематические соотношения — на
цифровую часть вычислительной системы.);
3. статистическое моделирование; моделирование биологических систем; решение уравнений в частных производных;
оптимизация систем управления (относятся задачи, решение которых получается в результате обработки многих
реализаций случайного процесса, например решение многомерных уравнений в частных производных методом МонтеКарло, решение задач стохастичемкого программирования, нахождение экстремума функций многих переменных.
Многократная реализация случайного процесса возлагается на быстродействующую АВМ, работающую в режиме
многократного повторения решения, а обработка результатов, воспроизводство функций на границах области,
вычисление функционалов — на ЦВМ. Кроме того, ЦВМ определяет момент окончания счёта. Применение Г. в. с.
сокращает время решения задач этого вида на несколько порядков по сравнению с применением только цифровой
машины).
Применение Г. в. с. эффективно также при решении нелинейных уравнений в частных производных. При этом могут
решаться как задачи анализа, так и задачи идентификации и оптимизации объектов. Примером задачи оптимизации
может служить подбор нелинейности теплопроводного материала для заданного распределения температур;
определение геометрии летательных аппаратов для получения требуемых аэродинамических характеристик;
распределение толщины испаряющегося слоя, предохраняющего космические корабли от перегрева при входе в
плотные слои атмосферы; разработка оптимальной системы подогрева летательных аппаратов с целью предохранения
их от обледенения при минимальной затрате энергии на подогрев; расчёт сети ирригационных каналов и установление
10
оптимальных расходов в них и т.п. При решении этих задач ЦВМ соединяется с сеточной моделью, многократно
используемой в процессе решения.
Развитие Г. в. с. возможно в двух направлениях: построение специализированных Г. в. с., рассчитанных на решение
только одного класса задач, и построение универсальных Г. в. с., позволяющих решать сравнительно широкий класс
задач. Структура такого универсального гибридного комплекса (рис.) состоит из АВМ однократного действия, АВМ с
повторением решения, сеточной модели, устройств связи между машинами, специального оборудования для решения
задач статистического моделирования и периферийного оборудования. Помимо стандартного математического
обеспечения ЭВМ, входящих в комплекс, в Г. в. с. требуются специальные программы, обслуживающие систему связи
машин и автоматизирующие процесс подготовки и постановки задач на АВМ, а также единый язык программирования
для комплекса в целом.
Наряду с новыми вычислительными возможностями в Г. в. с. возникают специфические особенности, в частности
появляются погрешности, которые в отдельно работающих ЭВМ отсутствуют. Первичными источниками погрешностей
являются временная задержка аналого-цифрового преобразователя, ЦВМ и цифро-аналогового преобразователя; ошибка
округления в аналого-цифровом и цифро-аналоговом преобразователях; ошибка от неодновременной выборки
аналоговых сигналов на аналого-цифровой преобразователь и неодновременной выдачи цифровых сигналов на цифроаналоговый преобразователь; ошибки, связанные с дискретным характером выдачи результатов с выхода ЦВМ.
Структурная схема универсальной гибридной вычислительной системы: сплошной линией обозначены
информационные, а пунктирной — управляющие каналы.
6. Цифровые вычислительные машины специального назначения. Микропроцессоры. Структура.
Организация вычислений.
Характеристики:
Принцип вычислений – последовательный
Входной сигнал – цифровой набор импульсов
Набор операций – основные арифметические
Точность – высокая
Область значений – любая
Популярны, так как:
Развитие микроэлектроники
Используются для решения задач в методе последовательной детализации. Подзадачи устойчивы достаточно
Большой класс стабильных задач (от калькуляторов до больших вычислительных комплексов)
Зависят от
решаемой
задачи
для
распараллеливания
данных
ПРОЦЕССОР
Устройство управления
АЛУ
Память
Общая шина
Направления
Использование как
сателлитов или
сопроцессоров
Устройство,
сопряженное с
внешней средой
11
При разработке оптических сопроцессоров
Аппаратные трансляторы
Мультиплексные каналы
Гибкие ВС для технологического производства
Микропроцессоры. Структура. Организация вычислений.
Микропроцессор – это программируемое устройство обработки информации.
Микропроцессор содержит 3 основных блока цифровой машины: схему управления (СУ), арифметико-логическое
устройство (АЛУ), запоминающие устройства (ЗУ) в виде регистров.
Эти блоки соединены шиной данных, шиной адреса и линиями управления
АЛУ предназначено для обработки инфции (+,-, сдвиг влево или вправо, инверсия, И, ИЛИ, исключающее ИЛИ)
Z-равенство 0
N-перенос
С- знак
Буферный регистр нужен для записи операндов
Регистры –это быстродействующая внутренняя память. Каждый регистр хранит 1 слово данных.
Бывают регистры общего назначения и специальные
Регистры общего назначения – (B,C,D) нужны для хранения данных
Специальные регистры :
Регистр состояния – хранит признаки операции;
Буферные регистры – для хранения операнда;
Аккумулятор – хранит результаты операций;
Регистр команд (INPUT) – хранит код выполняемой команды;
Счетчик команд (СК) –
FFFF);
Регистр адреса памяти(РАП). На входе 8 разрядная шина.
Схема управления (СУ)-поддерживает автоматическое выполнение цикла «выборка-исполнение» (обычно
микропрограммируется)
Основные функции:
Синхронизация работы МП с помощью таймера;
Управление последовательностью включения питания;
Обеспечение прерывания;
Определение кто и когда пользуется внутренней шиной данных;
Микропроцессор характеризуется:
тактовой частотой, определяющей максимальное время выполнения переключения элементов в ЭВМ;
2) разрядностью, т.е. максимальным числом одновременно обрабатываемых двоичных разрядов.
архитектурой. Понятие архитектуры микропроцессора включает в себя систему команд и способы адресации,
возможность совмещения выполнения команд во времени, наличие дополнительных устройств в составе
микропроцессора, принципы и режимы его работы.
7. СуперЭВМ. Основные характеристики. Структура. Организация вычислительного процесса.
Появление в середине шестидесятых первого компьютера класса суперЭВМ, разработанного в фирме CDC
знаменитым Сеймуром Крэем, ознаменовало рождение новой - векторной архитектуры. Начиная с этого момента
суперкомпьютером принято называть высокопроизводительный векторный компьютер. Основная идея, положенная в
основу новой архитектуры, заключалась в распараллеливании процесса обработки данных, когда одна и та же операция
применяется одновременно к массиву (вектору) значений. В этом случае можно надеяться на определенный выигрыш в
скорости вычислений. Идея параллелизма оказалась плодотворной и нашла воплощение на разных уровнях
функционирования компьютера. Более подробное обсуждение аппаратной реализации параллельной обработки
информации можно найти во второй главе, здесь же упомянем конвейерную обработку, многопроцессорность и т.д.
Основными особенностями модели параллельного программирования являются высокая эффективность программ,
применение специальных приемов программирования и, как следствие, более высокая трудоемкость программирования,
проблемы с переносимостью программ.
1 задача – работает несколько процессоров
много задач – каждый процессор решает свою задачу, а потом обмениваются информацией
12
Типы памяти
Тип передачи
данных
Общая
Распределенная
P
P
P
P
P
P
C
Шинные
сообщения
Общая и распределенная
C
M
M
M
P
P
P
C
Øèíà äàííû õ
Øèíà äàííû õ
Ìåæïðîöåñ ñîðíûé îáìåí
M
M
P
P
M
P
С
Фиксированные
перекрестные
соединения
M
P
M
С
P
P
P
M
С
P
P
С
P
M
P
P
Коммутационная
структура
P
P
Коммутатор
M
M
P
P
P
Коммутатор
M
M
M
P
P
P
M
M
M
Коммутатор
Различают:
по способу построения памяти
по способу передачи информации
Р – элементарный процессор
М – элемент памяти
С – кэш-память
К – коммутатор
Модель параллелизма данных основана на применении одной операции к множеству элементов структуры данных
(пример такой операции — "увеличить в два раза стипендию всем студентам группы 111"). Программа, написанная в
рамках данной модели, содержит последовательность таких операций. "Зернистость" вычислений мала, поскольку
каждая операция над каждым элементом данных может считаться независимой задачей. Программист должен указать
транслятору, как данные следует распределить между процессорами (т. е. между задачами). Транслятор генерирует
SPMD-код, автоматически добавляя в него команды обмена данными. Методы разработки алгоритмов и анализа
программ в модели с параллелизмом данных аналогичны тем, которые используются в модели задача/канал.
Основная идея подхода, основанного на параллелизме данных, заключается в том, что одна операция
выполняется сразу над всеми элементами массива данных. Различные фрагменты такого массива обрабатываются на
векторном процессоре или на разных процессорах параллельной машины. Распределением данных между процессорами
занимается программа. Векторизация или распараллеливание в этом случае чаще всего выполняется уже на этапе
компиляции - перевода исходного текста программы в машинные команды. Роль программиста в этом случае обычно
сводится к заданию опций векторной или параллельной оптимизации компилятору, директив параллельной компиляции,
использованию специализированных языков для параллельных вычислений. Наиболее распространенными языками для
параллельных вычислений являются Высокопроизводительный ФОРТРАН (High Performance FORTRAN) и
параллельные версии языка C (это, например, C*).
Более детальное описание рассматриваемого подхода к распараллеливанию содержит указание на следующие
его основные особенности:
Обработкой данных управляет одна программа;
Пространство имен является глобальным, то есть для программиста существует одна единственная память, а
детали структуры данных, доступа к памяти и межпроцессорного обмена данными от него скрыты;
13
Слабая синхронизация вычислений на параллельных процессорах, то есть выполнение команд на разных
процессорах происходит, как правило, независимо и только лишь иногда производится согласование выполнения
циклов или других программных конструкций - их синхронизация. Каждый процессор выполняет один и тот же
фрагмент программы, но нет гарантии, что в заданный момент времени на всех процессорах выполняется одна и та же
машинная команда;
Параллельные операции над элементами массива выполняются одновременно на всех доступных данной
программе процессорах.
Видим, таким образом, что в рамках данного подхода от программиста не требуется больших усилий по
векторизации или распараллеливанию вычислений. Даже при программировании сложных вычислительных алгоритмов
можно использовать библиотеки подпрограмм, специально разработанных с учетом конкретной архитектуры
компьютера и оптимизированных для этой архитектуры.
Подход, основанный на параллелизме данных, базируется на использовании при разработке программ базового
набора операций:
операции управления данными;
операции над массивами в целом и их фрагментами;
условные операции;
операции приведения;
операции сдвига;
операции сканирования;
операции, связанные с пересылкой данных.
Параллелизм любого рода требует одновременной работы, по крайней мере, двух устройств. Такими устройствами
могут быть: арифметико-логические устройства (АЛУ), устройства управления (УУ). В ЭВМ классической архитектуры
УУ и АЛУ образуют процессор. Увеличение числа процессоров или числа АЛУ в каждом из них приводит к
соответствующему росту параллелизма. Наличие в ЭВМ нескольких процессоров означает, что одновременно
(параллельно) могут выполняться несколько программ или несколько фрагментов одной программы. Работа нескольких
АЛУ под управлением одного УУ означает, что множество данных может обрабатываться параллельно по одной
программе. В соответствии с этим описание структур параллельных систем можно представить в виде упорядоченной
тройки:
<k,d,w>,
где k - количество устройств управления, т.е. наибольшее количество независимо и одновременно выполняемых
программ в системе;
d - количество АЛУ, приходящихся на одно устройство управления;
w - количество разрядов, содержимое которых обрабатывается одновременно (параллельно) одним арифметикологическим устройством.
Другая форма распараллеливания - конвейеризация, также требует наличия нескольких ЦП или АЛУ. В то время, как
множество данных обрабатывается на одном устройстве, другое множество данных может обрабатываться на
следующем устройстве и т.д., при этом в процессе обработки возникает поток данных от одного устройства (ЦП или
АЛУ) к следующему. В течение всего процесса над одним множеством данных выполняется одно за другим n действий.
Одновременно в конвейере на разных стадиях обработки могут находиться от 1 до n данных.
Параллелизм и конвейеризацию можно рассматривать на трех различных уровнях, представленных в таблице. Шесть
основных форм параллелизма, в широком смысле этого слова, позволяют построить схему классификации, в рамках
которой можно описать разнообразие высокопроизводительных вычислительных систем и отразить их эволюцию.
Классификация МВС по типу распараллеливания
Уровень параллелизма
Параллелизм
Конвейеризация
Программы
Мультипроцессор
Макроконвейер
УУ
УУ
АЛУ
АЛУ
...
УУ
УУ
УУ
УУ
АЛУ
АЛУ
АЛУ
АЛУ
ЗУ
ЗУ
ЗУ
ЗУ
Команды
Матричный процессор
Конвейер команд
УУ
АЛУ
АЛУ
ЗУ
АЛУ
УУ
АЛУ
ЗУ
14
Данные
Множество разрядов
УУ
АЛУ
ЗУ
Арифметический конвейер
УУ
АЛУ
ЗУ
8. Трансляторы. Основные принципы построения. Основные типы. Фазы трансляции. Обобщенная схема
компилятора. Обобщенная схема интерпретатора.
Транслятор - программа, преобразующая программу, написанную на одном языке, в программу представленную на
другом языке.
Транслятор воспринимает предложения (операторы) одного языка и вырабатывает соответствующие предложения
(операторы) другого языка. Если вторым является язык процессора, то транслятор именуют компилятором. Например,
компилятор берет программу, написанную на языке C и преобразует ее в программу на языке ассемблера.
Процессор, который последовательно анализирует предложения языка и немедленно их выполняет, а не компилирует,
называют интерпретатором.
Организация процессов трансляции, определяющая реализацию основных фаз, может осуществляться различным
образом. Это определяется различными вариантами взаимодействия блоков транслятора: лексического анализатора,
синтаксического анализатора и генератора кода. Несмотря на одинаковый конечный результат, различные варианты
взаимодействия блоков транслятора обеспечивают различные варианты хранения промежуточных данных. Можно
выделить два основных варианта взаимодействия блоков транслятора:
многопроходную организацию, при которой каждая из фаз является независимым процессом, передающим управление
следующей фазе только после окончания полной обработки своих данных;
однопроходную организацию, при которой все фазы представляют единый процесс и передают друг другу данные
небольшими фрагментами.
На основе двух основных вариантов можно также создавать их разнообразные сочетания.
Многопроходная организация взаимодействия блоков транслятора
Данный вариант взаимодействия блоков, на примере компилятора, представлен на рис 1.7.
Лексический анализатор полностью обрабатывает исходный текст, формируя на выходе цепочку, состоящую из всех
полученных лексем. Только после этого управление передается синтаксическому анализатору. Синтаксический
анализатор получает сформированную цепочку лексем и на ее основе формирует промежуточное представление или
объектную модель. После получения всей объектной модели он передает управление генератору кода. Генератор кода,
на основе объектной модели языка, строит требуемый машинный код.
К достоинствам такого подхода можно отнести:
15
Обособленность отдельных фаз, что позволяет обеспечить их независимую друг от друга реализацию и использование.
Возможность хранения данных, получаемых в результате работы каждой из фаз, на внешних запоминающих
устройствах и их использования по мере надобности.
Возможность уменьшения объема оперативной памяти, требуемой для работы транслятора, за счет последовательного
вызова фаз.
К недостаткам следует отнести.
Наличие больших объемов промежуточной информации, из которой в данный момент времени требуется только
небольшая часть.
Замедление скорости трансляции из-за последовательного выполнения фаз и использования для экономии оперативной
памяти внешних запоминающих устройств.
Данный подход может оказаться удобным при построении трансляторов с языков программирования, обладающей
сложной синтаксической и семантической структурой (например, PL/I). В таких ситуациях трансляцию сложно
осуществить за один проход, поэтому результаты предыдущих проходов проще представлять в виде дополнительных
промежуточных данных.
Однопроходная организация взаимодействия блоков транслятора
Один из вариантов взаимодействия блоков компилятора при однопроходной организации представлено на рис. 1.9.
Чаще всего в однопроходных трансляторах используется схема управления, в которой роль основного блока играет
синтаксический анализатор
Лексический анализатор и генератор кода выступают в роли вызываемых им подпрограмм. Как только синтаксическому
анализатору нужна очередная лексема, он вызывает сканер. При получении фрагмента промежуточного представления
осуществляется обращение к генератору кода. Завершение процесса трансляции происходит после получения и
обработки последней лексемы и инициируется синтаксическим анализатором.
К достоинствам однопроходной схемы следует отнести отсутствие больших объемов промежуточных данных, высокую
скорость обработки из-за совмещении фаз в едином процессе и отсутствие обращений в внешним запоминающим
устройствам.
К недостаткам относятся: невозможность реализации такой схемы трансляции для сложных по структуре языков и
отсутствие промежуточных данных, которые можно использовать для комплексного анализа и оптимизации.
Такая схема часто применяется для простых по семантической и синтаксической структурам языков программирования,
как в компиляторах, так и в интерпретаторах. Примерами таких языков могут служить Basic и Pascal. Классический
интерпретатор обычно строится по однопроходной схеме, так как непосредственное исполнение осуществляется на
уровне отдельных фрагментов промежуточного представления. Организация взаимодействия блоков такого
интерпретатора представлена на рис. 1.10.
16
Рис. 1.10 Однопроходное взаимодействие блоков интерпретатора.
Комбинированные взаимодействия блоков транслятора
Сочетания многопроходной и однопроходной схем трансляции порождают разнообразные комбинированные варианты,
многие из которых успешно используются. Кроме этого, вместо генератора кода легко подключить эмулятор
промежуточного представления, что достаточно просто позволяет разработать систему программирования на некотором
языке, ориентированную на различные среды исполнения.
На фазе лексического анализа входная программа, представляющая собой поток литер, разбивается на лексемы - слова в
соответствии с определениями языка. Основными формализмами, лежащим в основе реализации лексических
анализаторов, являются конечные автоматы и регулярные выражения. Лексический анализатор может работать в двух
основных режимах: либо как подпрограмма, вызываемая синтаксическим анализатором для получения очередной
лексемы, либо как полный проход, результатом которого является файл лексем.
Рис. 1.1
9. Генерация кода. Методы генерации кода. Внутреннее представление программ.
Заключительная фаза трансляции – генерация кода или интерпретация. Задача генератора кода – построение для
программы на входном языке эквивалентной машинной программы. Обычно в качестве входа для генератора кода
служит некоторое промежуточное представление программы.
Генерация кода включает ряд относительно независимых подзадач: распределение памяти (в частности, распределение
регистров), выбор команд, генерацию объектного (или загрузочного) модуля. Независимость этих подзадач
17
относительна: например, при выборе команд нельзя не учитывать схему распределения памяти, и, наоборот. Однако
удобно и практично эти задачи все же разделять, обращая при этом внимание на их взаимодействие.
Существует статический и динамический способ генерации кода.
Динамическая генерация кода – это прием программирования, заключающийся в том, что фрагменты кода
порождаются и запускаются непосредственно во время выполнения программы. Этот прием был известен достаточно
давно, но усложнение архитектуры компьютеров, и, что особенно важно, усложнение наборов команд процессоров
привело к тому, что в последние 10-15 лет динамическая генерация кода в некоторой степени потеряла популярность.
Целью динамической генерации кода является использование информации, доступной только во время выполнения
программы, для повышения качества исполняемого кода. В терминах метавычислений можно сказать, что динамическая
генерация кода позволяет специализировать фрагменты программы по данным, известным во время выполнения.
В некотором смысле, любой JIT-компилятор как раз использует динамическую генерацию кода: имея некоторую
программу, записанную на промежуточном языке (байт-коде), и зная, какой процессор работает в системе, JITкомпилятор динамически транслирует программу в инструкции этого процессора. При этом можно считать, что тип
процессора – эта как раз та часть информации, которая становится известной только во время выполнения программы.
Естественно, не стоит чересчур увлекаться динамической генерацией кода: этот прием далеко не всегда дает ускорение
программы. Можно сказать, что применение динамической генерации оправдано, если:
*
процесс вычислений в некотором фрагменте программы преимущественно определяется информацией,
известной только во время выполнения;
*
запуск этого фрагмента осуществляется многократно;
*
выполнение фрагмента связано с существенными затратами времени процессора.
В .NET доступно два способа организации динамической генерации кода:
*
порождение программы на языке C# и вызов компилятора C#;
*
непосредственное порождение метаданных и CIL-кода.
Статическая генерация кода – самый старый и проверенный прием. Статические генераторы кода "срабатывают" один
раз и формируют то, что мы называем исполняемым файлом. Достоинств – относительная простота реализации.
Простота эта определяется показателями качества получаемого машинного кода – статический генератор может
использовать всего несколько регистров конкретного процессора, но быстродействие получаемых с его помощью
программ будет слишком низким. Использование же всех возможностей конкретной архитектуры – дело слишком
непростое. Но даже "самый-самый" статический генератор кода принципиально не способен учесть одного нюанса –
обрабатываемых программой данных, т. е. тех данных, которые используются программой при запуске ее некоторым
конкретным пользователем в некотором конкретном случае. Здесь опять же примера не избежать. Предположим, что
где-то в теле "программы" встречается такое выражение:
...A = B/C ; // переменная A принимает значение частного переменных B и C...
Если на этапе компиляции программы значения B и C неизвестны, а они, например, задаются пользователем в ходе
исполнения уже скомпилированной программы, статический генератор кода для некоторого виртуального RISCпроцессора может сформировать такой фрагмент кода:
LD R2, &B ; Загрузить в регистр 2 значение из ячейки памяти с адресом B
LD R3, &C ; Загрузить в регистр 2 значение из ячейки памяти с адресом C
DIV R1,R2,R3 ; Поместить в регистр 1 частное содержимого регистров 2 и 3
ST &A, R1 ; Записать в память по адресу A содержимое регистра 1
Предположим, что наш виртуальный процессор выполняет команды LD и ST за два такта (это почти всегда справедливо
для хороших RISC на операциях с внешней памятью), а команду DIV – за "много" тактов (например, за 16; команды
деления вообще обычно являются "долгоиграющими"). Суммарное время (в терминах тактовой частоты) исполнения
этого фрагмента кода составит 22 такта.
А теперь представим, что при некотором запуске программы одна из переменных B или C приняла значение, равное
целой степени числа 2 (например, просто 2). Умножение на 2N равносильно сдвигу содержимого регистра на N битов и
команды сдвигов присутствуют во всех процессорах, и, наконец, эти команды очень быстрые. Типичное время
выполнения команды сдвига в RISC-процессорах – один такт. В нашем примере этот факт означает, что за общность
сгенерированной программы нам пришлось в данном конкретном случае расплатиться 15-ю совершенно
бессмысленными тактами. Цифра, казалось бы, совершенно незначительная, но если указанный фрагмент кода
исполняется в цикле ну с очень большим числом повторений...
Это один специфический и принципиально непреодолимый недостаток статической кодогенерации. Второй намного
серьезнее: если мы не располагаем исходными текстами программы P, а только ее скомпилированным исполняемым
файлом для платформы S, то, естественно, ни на какой другой платформе использовать P без эмуляционных сложностей
невозможно. К слову, решение от Transmeta или никак, или почти никак не "лечит" это хроническое заболевание – ведь
фактически Crusoe осуществляет эмуляцию чуждой архитектуры "на том, что есть". И если у процессоров семейства
18
Sparc более 200 рабочих регистров (да еще и хитро организованных), никакой эмуляцией с приемлемой
производительностью исполняемые файлы Sparc на 64-регистровом Crusoe не "погоняешь".
Для преодоления этих "болезней" есть совсем другие "лекарства" – прекрасные и вполне работоспособные разработки из
области динамической генерации исполняемого кода (ДГИК).
Большинство современных компиляторов - многопросмотровые; даже те языки программирования, которые
теоретически могли бы быть скомпилированы за один проход (например, Pascal) чаще всего анализируются в несколько
просмотров для того, чтобы улучшить качество генерируемого кода или упростить написание самого компилятора. Для
связи между различными просмотрами компилятора используется некоторый промежуточный язык (ПЯ), который
иногда также называют внутренним представлением программы в компиляторе. По ходу компиляции внутреннее
представление нагружается различной дополнительной информацией, полученной во время выполнения просмотров.
Транслятор условно разделяют на две логические части: front-end (внешний интерфейс) и back-end (внутренний
интерфейс), по степени приближенности к исходному или целевому языку компиляции. Таким образом, промежуточный
язык можно воспринимать как интерфейс между анализом и синтезом программы. Поэтому ПЯ должен отражать
функциональность исходного языка программирования и обеспечивать удобство выполнения основных задач синтеза,
таких как оптимизация программы и генерация эффективного объектного кода.
10) Оптимизация кода. Основные методы. Примеры.
Подходы, используемые при оптимизации кода, могут существенно зависеть от критериев оптимизации. Обычно
рассматривают три критерия или их комбинации с некоторыми приоритетами:
минимизация времени выполнения программы;
минимизация размера кода;
минимизация энергопотребления.
Последний критерий существен при компиляции приложений для встроенных автономных систем. Размер кода, как
правило, имеет второстепенное значение. Далее в основном будет рассматриваться критерий минимизации времени
выполнения с учетом возможных ограничений на размер кода.
Локальные методы оптимизации, применяемые в пределах линейных участков, обычно направлены на сокращение
одновременно и времени выполнения, и размера кода. Методы реорганизации кода (такие как развертка циклов,
встраивание функций и др.), направлены на ускорение работы компилируемой программы ценой увеличения размера
выходного кода.
Список мест, которые оптимизируются по скорости (то есть оптимизация по скорости - есть решающей):
Процедура окна (анализ сообщений)
Длинные вычисления при прорисовке.
Циклы автономных функций и конверторов, которые не содержат внутри вызовы Win32 API системных функций,
особенно из kernel32.dll (функций ядра)
Процедуры конвертирования чего угодно, имеющие автономное значение
Любой значимый объём кода, не имеющий вызовов Win32
Код анализа состояния в мультипотоковых системах.
Список оптимизации по размеру:
Код, насыщенный вызовами системных функций ядра
Код, выполняющийся рядом с переключением задач
Код, перенасыщенный другими тяжёлыми функциями Win32
Код, конвертирования, и других преобразований для вывода на экран, и код связанный с GUI, кроме пунктов
подходящих к предыдущей таблице.
Код процедуры диалога
Код инициализации чего угодно.
Код удаления и ининициализации
Код обработки ошибок
Код фреймов SEH и проверки ошибок.
Код мультипотоковых взаимодействий.
Оптимизировать следовало бы, отдавая предпочтение времени выполнения, нежели размеру кода. Однако в пунктах
первого списка оптимизация по скорости не имеет смысла. А раз так, то смысл имеет оптимизация по размеру. То есть:
«Если мы не можем выиграть в скорости, мы можем выиграть в размере». Причина невозможности оптимизации по
времени кроется в длительности исполнения самих функций Win32. Нет смысла оптимизировать код из 10-50 команд
(кроме чистого цикла) по скорости, если потом идёт вызов тяжёлой Win32 функции. Тяжёлыми можно считать все
функции ядра, так как в любом случае, при переходе в режим ядра тратится более 1000 тактов (как это любит писать
Джеффри Рихтер). Кроме того, тяжёлыми следует считать многие функции GDI и другие. То есть скоростной
оптимизации может подлежать только тот код, который не содержит в себе вызовов Win32. А это значит следующее:
19
Если возможно, избегайте вызовов функций внутри циклов, или делайте так, чтобы все вызовы в цикле находились в
одном месте, или в двух, но так, чтобы большая часть цикла была «чистым кодом».
Создавайте код таким образом, чтобы не смешивать Win32 API с кодом от него «независящим». Это не только даст
возможность скоростной оптимизации, но и возможность повышения степени переносимости вашего кода.
Рекомендации 7-10 второго списка характерны не только для Win32, а вообще универсальны для всего
программирования. Причина отсутствия оптимизации по скорости в процедурах инициализации, обусловлена
следующими факторами:
Выполнение этих процедур один или малое количество раз
Требования к стабильности кода в этих процедурах
Операции выделения памяти/записи в файлы не могут быть быстрыми, и соответственно нет смысла в оптимизации кода
по времени (скорости).
Области планирования
В традиционных компиляторах планирование, как правило, осуществляется в пределах линейных участков. Однако для
ILP-процессоров такой подход может приводить к потерям производительности. Характерная частота переходов в
программах нечисленных приложений, например, составляет примерно 20%, т.е. средняя длина линейного участка - 5
команд. С учетом связей по данным, которые вероятнее всего присутствуют между этими командами, степень
естественного программного параллелизма оказывается невысокой. Для того чтобы привести степень программного
параллелизма в соответствие с уровнем имеющегося аппаратного параллелизма, в компиляторах для ILP-процессоров
реализуют планирование в рамках более широких областей кода, объединяющих несколько линейных участков, так что
инструкции могут в результате перемещаться из одного участка в другие. При этом обычно стремятся максимально
ускорить выполнение вдоль наиболее часто исполняемых ветвей программы. Глобального планирования имеет
преимущества по сравнению с локальным, для приложений нечисленного характера.
Одна из идей, на которой основываются методы глобального планирования, заключается в том, что код можно
реорганизовать таким образом, чтобы сократить время выполнения вдоль одних путей за счет замедления вдоль других.
Если решения принимаются в пользу ускорения наиболее частых путей, то за счет этого можно достичь сокращения
времени выполнения программы в целом.
При формировании областей используются данные профилирования по частоте выполнения переходов, что делает
актуальной задачу эффективного получения данных профилирования. Метод профилирования передач управления для
ILP-процессоров не требует аппаратной поддержки и основан на добавлении минимального необходимого числа
дополнительных линейных участков, содержащих зондирующий код для регистрации передач управления.
Зондирующий код организуется таким образом, чтобы при выполнении обеспечивалось его максимальное
распараллеливание.
Усиление параллелизма в пределах областей планирования
Большинство из рассматриваемых в этом разделе методов применимы в той или иной степени ко всем типам ILPпроцессоров и видам областей планирования.
Преобразования циклов
Преобразования циклов, применяемые в ILP-компиляции, подробно рассмотрены в [35] и [58]. К ним относятся:
развертка циклов, слияние и разбивка циклов, подгонка циклов, конвейеризация циклов. Все они имеют смысл
независимо от наличия параллелизма в целевом процессоре, поскольку позволяют уменьшить общее число проверок
завершения цикла и операций перехода. В компиляции для ILPпроцессоров они приобретают дополнительную
значимость, поскольку позволяют усилить программный параллелизм в теле цикла.
В примерах, иллюстрирующих смысл преобразований, использован язык Си, реально же они применяются на уровне
промежуточного представления.
Развертка цикла (loop unrolling). Суть этого преобразования заключается в том, что тело цикла дублируется n раз, а
число повторений соответственно сокращается во столько же раз (рис. 6). Число n называется коэффициентом развертки
цикла.
for (i=0;i<100;i++) for (i=0;i<100;i=i+4) {
{a[i]=a[i]+c;} a[i]=a[i]+c;
==> a[i+1]=a[i+1]+c;
a[i+2]=a[i+2]+c;
a[i+3]=a[i+3]+c;}
Рис. 6. Развертка циклов
В контексте ILP-компиляции он приобретает большее значение, поскольку позволяет использовать параллелизм команд,
относящихся к разным итерациям цикла. Наиболее эффективно его применение в сочетании с другими
преобразованиями, направленными на усиление параллелизма (см. рис. 12).
Слияние циклов (loop fusion). Два расположенных последовательно цикла можно слить, если они имеют одинаковое
число итераций и отсутствуют зависимости по данным, препятствующие объединению. Если тела сливаемых циклов не
20
зависят друг от друга (рис. 7), появляется возможность спланировать параллельное выполнение команд, относящихся к
разным циклам.
for (i=0;i<100;i++) for (i=0;i<100;i++) {
b[i]=b[i]+c; ==> b[i]=b[i]+c;
for (j=0;j<100;j++) a[i]=a[i]*2;
a[j]=a[j]*2; }
Рис. 7. Слияние циклов
Если граничные значения переменных двух циклов различаются, но ненамного, то применяют слияние с
предварительной подгонкой одного из циклов.
Подгонка цикла (loop peeling). Подгонка цикла заключается в изменении граничных значений переменной цикла.
Обычно подгонка применяется для того чтобы можно было выполнить слияние (рис. 8) или развертку цикла (если число
итераций не кратно коэффициенту развертки).
for (i=0;i<100;i++) for (i=0;i<100;i++) {
b[i]=b[i+2]+c; ==> b[i]=b[i+2]+c;
for (j=0;j<102;j++) a[i]=a[i]*2;}
a[j]=a[j]*2; a[100]=a[100]*2;
a[101]=a[101]*2;
Рис. 8. Слияние циклов с подгонкой одного из них
Программная конвейеризация цикла (software pipelining). Идея конвейеризации цикла заключается в том, что
выполнение команд, относящихся к последующим итерациям, начинается раньше, чем завершается выполнение
предшествующих итераций. Конвейеризация применима в тех случаях, когда тело цикла можно разбить на группы
команд, не зависящих друг от друга на разных итерациях.
Конвейеризация, как и развертывание цикла, создает возможности для параллельного выполнения команд из разных
итераций, но обладает тем преимуществом, что не увеличивает размер тела цикла.
Разбивка циклов (loop distribution). В некоторых случаях может иметь смысл преобразование, обратное слиянию и
называемое разбивкой циклов. Это целесообразно, например, если тело цикла слишком длинное, и имеющееся число
регистров недостаточно для размещения всех используемых в теле цикла переменных. В этом случае часть
промежуточных значений приходится временно выгружать в память, а перед использованием в вычислениях загружать
на регистры (в англоязычной литературе этот процесс обозначают термином register spilling). Благодаря разбивке цикла
можно избежать дефицита регистров и выталкивания значений в память.
В примере, показанном на рис. 10, вторая команда не может быть выполнена параллельно с первой в силу зависимости
по данным. В результате разбивки создаются циклы с более короткими телами и меньшим числом зависимостей по
данным.
for (i=0;i<100;i++){ for (i=0;i<100;i++)
b[i]=b[i-1]+c; ==> b[i]=b[i-1]+c;
a[i]=b[i]+2;} for (i=0;i<100;i++)
a[i]=b[i]+2;
11 Классификация и основные характеристики языков программирования.
Языки программирования – искусственные языки. От естественных они отличаются ограниченным числом
«слов», значение которых понятны транслятору, и очень строгими правилами записи команд (операторов).
Совокупность подобных требований образуют синтаксис языка программирования, а смысл каждой команды и других
конструкций языка – его семантику. Нарушение формы записи программы приводит к тому, что транслятор не может
понять назначение оператора и выдает сообщение о синтаксической ошибке, а правильно написанное, но не отвечающее
алгоритму использование команд языка приводят к семантическим (логическим) ошибкам.
Процесс поиска ошибки в программе называется тестированием, процесс устранения ошибки – отладкой.
Существуют разные подходы к классификации языков программирования. Все они в той или иной мере
упрощают реальную картину и охватывают лишь отдельные характеристики языков. Сложность классификации
понятна: 50 лет эволюции языков программирования привели к тому, что взаимопроникновение концепций языков,
которые используют различные модели и парадигмы, достигло едва ли не своего апогея. Почти каждый новый язык
представляет собой «гремучую смесь» разных концепций и механизмов.
В течение многих лет программное обеспечение строилось на основе операционных и процедурных языков,
таких как Фортран, Бейсик, Паскаль, Ада, Си. Сегодня современные версии этих и им подобных языков (Модула, Форт)
21
доминируют при разработке прикладных программных средств. Однако по мере эволюции языков программирования
получили широкое распространение и другие, принципиально другие подходы.
Классическое операционное программирование требует от программиста детального описания того, как
решить задачу, то есть формулировки алгоритма и его специальные записи. При этом ожидаемые свойства результата
обычно не указываются. При процедурном подходе операторы объединяются в группы – процедуры. Структурное
программирование не выходит за рамки этого направления, оно лишь дополнительно фиксирует некоторые полезные
приемы технологии программирования.
Модульное программирование является развитием и совершенствованием процедурного программирования и
библиотек специальных программ. Основная черта модульного программирования — стандартизация интерфейса между
отдельными программными единицами. Модуль — это отдельная функционально-законченная программная единица,
которая структурно оформляется стандартным образом по отношению к компилятору и по отношению к объединению
ее с другими аналогичными единицами и загрузке. Как правило, каждый модуль содержит паспорт, в котором указаны
все основные его характеристики: язык программирования, объем, входные и выходные переменные, их формат,
ограничения на них, точки входа, параметры настройки и т.д. Объем модуля обычно не превышает 1000 команд ЭВМ
или операторов языка программирования. В противном случае модуль становится громоздким и трудным к восприятию
и использованию.
Модульное программирование — это искусство разбиения задачи на некоторое число различных модулей,
умение широко использовать стандартные модули путем их параметрической настройки, автоматизация сборки готовых
модулей из библиотек, банков модулей.
Основные концепции модульного программирования:

каждый модуль реализует единственную независимую функцию;

каждый модуль имеет единственную точку входа и выхода;

каждый модуль имеет единственную точку входа и выхода;

размер модуля по возможности должен быть минимизирован;

каждый модуль может быть разработан и закодирован различными членами бригады программистов и
может быть отдельно протестирован;

вся система построена из модулей;

модуль не должен давать побочных эффектов;

каждый модуль не зависит от того, как реализованы другие модули.
При таком подходе сложная система разделяется на несколько частей, одновременно создаваемых различными
программистами. Каждый модуль реализует единственную функцию. Размер модуля невелик, поэтому тестирование
управляемо и может быть проведено тщательным образом. После кодирования и тестирования всех модулей происходит
их интеграция, и тестируется вся система.
При сопровождении тестируется и отлаживается только тот модуль, который плохо работает. Очевидны
преимущества в облегчении написания и тестирования программ, уменьшается стоимость их сопровождения.
Концепция модульного программирования реализована в ряде языков, таких как Modula 2, Turbo Pascal 5.0 и
выше, C, Python,Perl.
Отличие в реализации процедурного программирования от модульного состоит в том, что модуль не виден
программе. В отличие от стандартных языков процедурного программирования, в модульных языках лишние модули
просто не прикомпановываются на этапе сборки.
22
Принципиально
иное
направление
в
программировании
связано
с
парадигмами
непроцедурного
программирования. К ним можно отнести объектно-ориентированное и декларативное программирование.
Объектно-ориентированный язык создает окружение в виде множества независимых объектов. Каждый объект
ведет себя подобно отдельному компьютеру, их можно использовать для решения задачи как «черные ящики», не
вникая во внутренние механизмы их функционирования.
Из языков объектного программирования, популярных среди профессионалов, следует назвать прежде всего
C++, для более широкого круга программистов предпочтительны среды типа Delphi и Visual Basic.
При использовании декларативного языка программист указывает исходные информационные структуры,
взаимосвязи между ними и то, какими свойствами должен обладать результат. При этом алгоритм программист не
строит. То есть при использовании декларативного языка в программах описывается способ решения поставленной
задачи, а не предписываются шаги для получения результата.
Декларативные языки подразделяются на два класса: функциональные и логические.
Функциональное программирование — парадигма программирования, в которой процесс вычисления
трактуется как вычисление значений функций в математическом понимании (то есть тех, чей единственный результат
работы заключается в возвращаемом значении, или другими словами, вычисление которых не имеет побочного
эффекта); способ решения задачи описывается при помощи зависимости функций друг от друга (в том числе возможны
рекурсивные зависимости), но без указания последовательности шагов.
Типичным представителем функциональных языков программирования является Лисп. В основе языка Лисп
лежит
лямбда-исчисление.
Лямбда-исчисление
–
формализм
для
представления
функций
и
способов
их
комбинирования. Вместе со своим эквивалентом –комбинаторной логикой, в которой не используются переменные, –
предложено около 1930 г. логиками Черчем, Шейнфинкелем и Карри.
В лямбда-исчислении Черча функция записывается в виде l (x1,x2, … , xn).fn
В Лиспе лямбда-выражение имеет вид:
(LAMBDA(x1,x2, … , xn).fn).
Символ LAMBDA означает, что мы имеем дело с определением функции. Символы xi являются формальными
параметрами, они образуют список, называемый лямбда-списком; fn – тело функции, которое может иметь
произвольную форму, допускаемую интерпретатором Лиспа. Телом функции может быть константа или композиция из
вызовов функций.
Программы на языках логического программирования выражены как формулы математической логики, а
компилятор пытается получить следствия из них. Так же как в функциональном программировании, программист
остается в неведении о методах, применяемых при вычислении, и последовательности исполнения элементарных
действий. Большая часть ответственности за эффективность вычислений в логическом и функциональном
программировании перекладывается на «плечи» транслятора используемого языка программирования.
Все сказанное выше можно отобразить следующей схемой:
23
программирование
процедурное
операционно
е
Ассемблер
Фортран
Бейсик
структурное
непроцедурное
объектное
Паскаль
Смолток
Модула
Си++
Делфи
декларативное
Си
логическое
функциональ-
Пролог
ное
Лисп
Приведем другие классификации языков программирования.
Одной из наиболее примечательных является классификация моделей языков, предложенная Дж. Бэкусом в
1977 г. В соответствии с ней выделяются три категории языков:
A.
Простые операционные модели (языки, основанные на конечных автоматах, машине Тьюринга);
B.
Аппликативные модели (языки на основе лямбда-исчисления Чёрча, системы комбинаторов Карри,
чистого Лиспа);
C.
Модели фон Неймана (традиционные языки программирования).
Джон Устерхаут предложил принцип классификации языков, в соответствии с которым высокоуровневые
языки делятся на языки системного программирования и на скриптовые.
Скриптовый язык (англ. scripting language, также называют язык сценариев) — язык программирования,
разработанный для записи «сценариев», последовательностей операций, которые пользователь может выполнять на
компьютере. Простые скриптовые языки раньше часто называли языками пакетной обработки (batch languages или job
control languages). Сценарии всегда интерпретируются, а не компилируются.
В прикладной программе, сценарий (скрипт) — это программа, которая автоматизирует некоторую задачу,
которую без сценария пользователь делал бы вручную, используя интерфейс программы.
Поскольку сценарии интерпретируются из исходного кода динамически при каждом исполнении, они
выполняются обычно значительно медленнее готовых программ, оттранслированных в машинный код на этапе
компиляции. Поэтому сценарные языки не применяются для написания программ, требующих оптимальности и
быстроты исполнения. Но из-за простоты они часто применяются для написания небольших, одноразовых
(«проблемных») программ. Также, в плане быстродействия скриптовые языки можно разделить на языки динамического
разбора (sh, command.com) и предварительно компилируемые (Perl). Языки динамического разбора считывают
инструкции из файла программы минимально требующимися блоками, и исполняют эти блоки, не читая дальнейший
код. Предкомпилируемые языки вначале считывают всю программу, компилируют её всю либо в машинный код, либо в
какой-то внутренний формат, и лишь затем — исполняют получившийся код.
Вегнер сгруппировал некоторые из наиболее известных языков высокого уровня в четыре поколения в
зависимости от того, какие языковые конструкции впервые в них появились:
24
Первое поколение (1954-1958)
FORTRAN I
Математические формулы
ALGOL-58
Математические формулы
Flowmatic
Математические формулы
IPL V
Математические формулы
25
Второе поколение (1959-1961)
FORTRAN II
Подпрограммы, раздельная компиляция
ALGOL-60
Блочная структура, типы данных
COBOL
Описание данных, работа с файлами
Lisp
Обработка списков, указатели, сборка мусора
Третье поколение(1962-1970)
PL/I
FORTRAN+ALGOL+COBOL
ALGOL-68
Более строгий приемник ALGOL-60
Pascal
Более простой приемник ALGOL-60
Simula
Классы, абстрактные данные

Потерянное поколение (1970-1980)
Языки созданные, но не выжившие. Например, PL/1 , Malboge .
Характеристики языков программирования
4.1 Элементы объектной модели
Каждый стиль программирования имеет свою концептуальную базу. Каждый стиль требует своего
умонастроения и способа восприятия решаемой задачи. Для объектно-ориентированного стиля концептуальная база —
это объектная модель. Она имеет четыре главных элемента:

абстрагирование;

инкапсуляция;

модульность;

иерархия.
Эти элементы являются главными в том смысле, что без любого из них модель не будет объектноориентированной. Кроме главных, имеются еще три дополнительных элемента:

типизация;

параллелизм;

сохраняемость.
Называя их дополнительными, мы имеем в виду, что они полезны в объектной модели, но не обязательны.
26
Без такой концептуальной основы вы можете программировать на языке типа Smalltalk, Object Pascal, C++,
CLOS, Eiffel или Ada, но из-под внешней красоты будет выглядывать стиль FORTRAN, Pascal или С. Выразительная
способность объектно-ориентированного языка будет либо потеряна, либо искажена. Но еще более существенно, что
при этом будет мало шансов справиться со сложностью решаемых задач.
Абстрагирование
Абстрагирование является одним из основных методов, используемых для решения сложных задач.
Абстракция выделяет существенные характеристики некоторого объекта, отличающие его от всех других видов
объектов и, таким образом, четко определяет его концептуальные границы с точки зрения наблюдателя.
Абстрагирование концентрирует внимание на внешних особенностях объекта и позволяет отделить самые
существенные особенности поведения от несущественных. Абельсон и Суссман назвали такое разделение смысла и
реализации барьером абстракции, который основывается на принципе минимизации связей, когда интерфейс объекта
содержит только существенные аспекты поведения и ничего больше. Существует еще один дополнительный принцип,
называемый принципом наименьшего удивления, согласно которому абстракция должна охватывать все поведение
объекта, но не больше и не меньше, и не привносить сюрпризов или побочных эффектов, лежащих вне ее сферы
применимости.
Выбор правильного набора абстракций для заданной предметной области представляет собой главную задачу
объектно-ориентированного проектирования.
По мнению Сейдвица и Старка "существует целый спектр абстракций, начиная с объектов, которые почти
точно соответствуют реалиям предметной области, и кончая объектами, не имеющими право на существование". Вот
эти абстракции:
Абстракция сущности
Абстракция поведения
Объект представляет собой полезную модель некой сущности в
предметной области
Объект состоит из обобщенного множества операций
Объект группирует операции, которые либо вместе используются более
Абстракция виртуальной машины
высоким уровнем управления, либо сами используют некоторый набор
операций более низкого уровня
Произвольная абстракция
Объект включает в себя набор операций, не имеющих друг с другом
ничего общего
Абстракция фокусируется на существенных с точки зрения наблюдателя характеристиках объекта.
Инкапсуляция
Абстракция и инкапсуляция дополняют друг друга: абстрагирование направлено на наблюдаемое поведение
объекта, а инкапсуляция занимается внутренним устройством. Чаще всего инкапсуляция выполняется посредством
скрытия информации, то есть маскировкой всех внутренних деталей, не влияющих на внешнее поведение. Обычно
скрываются и внутренняя структура объекта и реализация его методов.
Инкапсуляция, таким образом, определяет четкие границы между различными абстракциями. Возьмем для
примера структуру растения: чтобы понять на верхнем уровне действие фотосинтеза, вполне допустимо игнорировать
такие подробности, как функции корней растения или химию клеточных стенок. Аналогичным образом при
проектировании базы данных принято писать программы так, чтобы они не зависели от физического представления
27
данных; вместо этого сосредотачиваются на схеме, отражающей логическое строение данных. В обоих случаях объекты
защищены от деталей реализации объектов более низкого уровня.
Дисков утверждает, что "абстракция будет работать только вместе с инкапсуляцией". Практически это означает
наличие двух частей в классе: интерфейса и реализации. Интерфейс отражает внешнее поведение объекта, описывая
абстракцию поведения всех объектов данного класса. Внутренняя реализация описывает представление этой абстракции
и механизмы достижения желаемого поведения объекта. Принцип разделения интерфейса и реализации соответствует
сути вещей: в интерфейсной части собрано все, что касается взаимодействия данного объекта с любыми другими
объектами; реализация скрывает от других объектов все детали, не имеющие отношения к процессу взаимодействия
объектов.
Инкапсуляцию можно определить следующим образом:
Инкапсуляция — это процесс отделения друг от друга элементов объекта, определяющих его устройство и
поведение; инкапсуляция служит для того, чтобы изолировать контрактные обязательства абстракции от их реализации.
Инкапсуляция скрывает детали реализации объекта.
Модульность
По мнению Майерса "Разделение программы на модули до некоторой степени позволяет уменьшить ее
сложность... Однако гораздо важнее тот факт, что внутри модульной программы создаются множества хорошо
определенных и документированных интерфейсов. Эти интерфейсы неоценимы для исчерпывающего понимания
программы в целом". В некоторых языках программирования, например в Smalltalk, модулей нет, и классы составляют
единственную физическую основу декомпозиции. В других языках, включая Object Pascal, C++, Ada, CLOS, модуль —
это самостоятельная языковая конструкция. В этих языках классы и объекты составляют логическую структуру
системы, они помещаются в модули, образующие физическую структуру системы. Это свойство становится особенно
полезным, когда система состоит из многих сотен классов.
Согласно Барбаре Лисков "модульность — это разделение программы на фрагменты, которые компилируются
по отдельности, но могут устанавливать связи с другими модулями". Мы будем пользоваться определением Парнаса:
"Связи между модулями — это их представления друг о друге". В большинстве языков, поддерживающих принцип
модульности как самостоятельную концепцию, интерфейс модуля отделен от его реализации. Таким образом,
модульность и инкапсуляция ходят рука об руку. В разных языках программирования модульность поддерживается поразному. Например, в C++ модулями являются раздельно компилируемые файлы. Для C/C++ традиционным является
помещение интерфейсной части модулей в отдельные файлы с расширением .h (так называемые файлы-заголовки).
Реализация, то есть текст модуля, хранится в файлах с расширением с (в программах на C++ часто используются
расширения .ее, .ср и .срр). Связь между файлами объявляется директивой макропроцессора #include. Такой подход
строится исключительно на соглашении и не является строгим требованием самого языка. В языке Object Pascal
принцип модульности формализован несколько строже. В этом языке определен особый синтаксис для интерфейсной
части и реализации модуля (unit). Язык Ada идет еще на шаг дальше: модуль (называемый package) также имеет две
части - спецификацию и тело. Но, в отличие от Object Pascal, допускается раздельное определение связей с модулями
для спецификации и тела пакета. Таким образом, допускается, чтобы тело модуля имело связи с модулями, невидимыми
для его спецификации.
Правильное разделение программы на модули является почти такой же сложной задачей, как выбор
правильного набора абстракций.
Модули выполняют роль физических контейнеров, в которые помещаются определения классов и объектов при
логическом проектировании системы. Такая же ситуация возникает у проектировщиков бортовых компьютеров. Логика
электронного оборудования может быть построена на основе элементарных схем типа НЕ, И-НЕ, ИЛИ-НЕ, но можно
объединить такие схемы в стандартные интегральные схемы (модули), например, серий 7400, 7402 или 7404.
Модульность позволяет хранить абстракции раздельно.
28
В традиционном структурном проектировании модульность - это искусство раскладывать подпрограммы по
кучкам так, чтобы в одну кучку попадали подпрограммы, использующие друг друга или изменяемые вместе. В
объектно-ориентированном программировании ситуация несколько иная: необходимо физически разделить классы и
объекты, составляющие логическую структуру проекта.
Модульность — это свойство системы, которая была разложена на внутренне связные, но слабо связанные
между собой модули.
Принципы абстрагирования, инкапсуляции и модульности являются взаимодополняющими. Объект логически
определяет границы определенной абстракции, а инкапсуляция и модульность делают их физически незыблемыми.
В процессе разделения системы на модули могут быть полезными два правила. Во-первых, поскольку модули
служат в качестве элементарных и неделимых блоков программы, которые могут использоваться в системе повторно,
распределение классов и объектов по модулям должно учитывать это. Во-вторых, многие компиляторы создают
отдельный сегмент кода для каждого модуля. Поэтому могут появиться ограничения на размер модуля. Динамика
вызовов подпрограмм и расположение описаний внутри модулей может сильно повлиять на локальность ссылок и на
управление страницами виртуальной памяти. При плохом разбиении процедур по модулям учащаются взаимные вызовы
между сегментами, что приводит к потере эффективности кэш-памяти и частой смене страниц.
Иерархия
Значительное упрощение в понимании сложных задач достигается за счет образования из абстракций
иерархической структуры. Определим иерархию следующим образом:
Иерархия — это упорядочение абстракций, расположение их по уровням.
Наследование — создание новых объектов из уже существующих. Начиная с определения самых общих
абстрактных объектов, можно создавать более конкретные объекты нижнего уровня, которые не только унаследуют все
функции своих предшественников, но могут добавлять им свои собственные. Принцип наследования позволяет
упростить выражение абстракций, делает проект менее громоздким и более выразительным.
Типизация
Типизация — это способ защититься от использования объектов одного класса вместо другого, или по крайней
мере управлять таким использованием.
Типизация заставляет нас выражать наши абстракции так, чтобы язык программирования, используемый в
реализации, поддерживал соблюдение принятых проектных решений.
Идея согласования типов занимает в понятии типизации центральное место. Например, возьмем физические
единицы измерения. Деля расстояние на время, мы ожидаем получить скорость, а не вес. В умножении температуры на
силу смысла нет, а в умножении расстояния на силу — есть. Все это примеры сильной типизации, когда прикладная
область накладывает правила и ограничения на использование и сочетание абстракций.
Сильная типизация заставляет нас соблюдать правила использования абстракций, поэтому она тем полезнее,
чем больше проект. Однако у нее есть и теневая сторона. А именно, даже небольшие изменения в интерфейсе класса
требуют перекомпиляции всех его подклассов. Кроме того, не имея параметризованных классов трудно представить
себе, как можно было бы создать собрание разнородных объектов.
Полиморфизм означает, что разные объекты могут описывать различные реализации одного и того же метода.
Строгая типизация предотвращает смешивание абстракций.
Параллелизм
Есть задачи, в которых автоматические системы должны обрабатывать много событий одновременно. В других
случаях потребность в вычислительной мощности превышает ресурсы одного процессора. В каждой из таких ситуаций
естественно использовать несколько компьютеров для решения задачи или задействовать многозадачность на
многопроцессорном компьютере. Процесс (поток управления) — это фундаментальная единица действия в системе.
Каждая программа имеет по крайней мере один поток управления, параллельная система имеет много таких потоков:
век одних недолог, а другие живут в течении всего сеанса работы системы. Реальная параллельность достигается только
29
на многопроцессорных системах, а системы с одним процессором имитируют параллельность за счет алгоритмов
разделения времени.
Параллелизм — это свойство, отличающее активные объекты от пассивных.
Параллелизм позволяет различным объектам действовать одновременно.
Сохраняемость любой программный объект существует в памяти и живет во времени. Аткинсон предположил,
что есть непрерывное множество продолжительности существования объектов: существуют объекты, которые
присутствуют лишь во время вычисления выражения, но есть и такие, как базы данных, которые существуют
независимо от программы. Этот спектр сохраняемости объектов охватывает:

"Промежуточные результаты вычисления выражений.

Локальные переменные в вызове процедур.

Собственные переменные, глобальные переменные и динамически создаваемые данные.

Данные, сохраняющиеся между сеансами выполнения программы.

Данные, сохраняемые при переходе на новую версию программы.

Данные, которые вообще переживают программу" .
Традиционно, первыми тремя уровнями занимаются языки программирования, а последними — базы данных.
Этот конфликт культур приводит к неожиданным решениям: программисты разрабатывают специальные схемы для
сохранения объектов в период между запусками программы, а конструкторы баз данных переиначивают свою
технологию под короткоживущие объекты.
Языки программирования, как правило, не поддерживают понятия сохраняемости; примечательным
исключением является Smalltalk, в котором есть протоколы для сохранения объектов на диске и загрузки с диска.
Однако, записывать объекты в неструктурированные файлы — это подход, пригодный только для небольших систем.
До сих пор мы говорили о сохранении объектов во времени. В большинстве систем объектам при их создании
отводится место в памяти, которое не изменяется и в котором объект находится всю свою жизнь. Однако для
распределенных систем желательно обеспечивать возможность перенесения объектов в пространстве, так, чтобы их
можно было переносить с машины на машину и даже при необходимости изменять форму представления объекта в
памяти.
Определим сохраняемость следующим образом:
Сохраняемость — способность объекта существовать во времени, переживая породивший его процесс, и (или)
в пространстве, перемещаясь из своего первоначального адресного пространства.
Сохраняемость поддерживает состояние и класс объекта в пространстве и во времени.
4.2 Характеристики языков программирования с точки зрения элементов объектной модели
Приведем характеристики объектно-ориентированных языков программирования с точки зрения семи
основных элементов объектной модели.
Табл.1 Основные характеристики Smalltalk
30
Абстракции
Переменные
экземпляра Да
Методы
экземпляра
Переменные
класса
Методы класса
Да
Да
Да
Инкапсуляция
Переменных
Закрытые
Методов
Открытые
Модульность
Разновидности модулей
Нет
Иерархии
Наследование
Одиночное
Шаблоны
Нет
Метаклассы
Да
Типизация
Сильная
типизация Нет
Полиморфизм
Да (одиночный)
Параллельность
Многозадачность
Непрямая (посредством классов)
Сохраняемость
Долгоживущие объекты
Нет
Табл.2 Основные характеристики Object Pascal.
Абстракции
Переменные
экземпляра Да
Методы
экземпляра
Переменные
Методы класса
класса
Да
Нет
Нет
Инкапсуляция
Переменных
Открытые
Методов
Открытые
Модульность
Разновидности модулей
Модуль (unit)
Иерархии
Наследование
Одиночное
Шаблоны
Нет
31
Метаклассы
Типизация
Нет
Сильная
типизация Да
Полиморфизм
Да (одиночный)
Параллельность
Многозадачность
Нет
Сохраняемость
Долгоживущие объекты
Нет
Табл.3.Основные характеристики C++ .
Абстракции
Переменные
экземпляра Да
Методы
экземпляра Да
Переменные
класса Да
Методы класса
Да
Переменных
Открытые,
Методов
Открытые, защищенные, закрытые
Модульность
Разновидности модулей
файл
Иерархии
Наследование
Множественное
Шаблоны
Да
Метаклассы
Нет
Инкапсуляция
Типизация
Сильная
защищенные,
закрытые
типизация Да
Полиморфизм
Да (одиночный)
Параллельность
Многозадачность
Непрямая (посредством классов)
Сохраняемость
Долгоживущие объекты
Нет
Табл.4 Основные характеристики CLOS(Common Lisp Object System).
Абстракции
Переменные
экземпляра Да
Методы
экземпляра Да
Переменные
Инкапсуляция
класса Да
Методы класса
Да
Переменных
Чтение,
Методов
Открытые
запись,
доступ
32
Модульность
Разновидности модулей
Пакет
Иерархии
Наследование
Множественное
Шаблоны
Нет
Метаклассы
Да
Типизация
Сильная
типизация Возможна
Полиморфизм
Да (множественный)
Параллельность
Многозадачность
Да
Сохраняемость
Долгоживущие объекты
Нет
Табл. 5 Основные характеристики Ada
Абстракции
Переменные
экземпляра Да
Методы
экземпляра Да
Переменные
класса Нет
Методы класса
Нет
Переменных
Открытые,
Методов
Открытые, закрытые
Модульность
Разновидности модулей
Пакет
Иерархии
Наследование
Нет
Шаблоны
Да
Метаклассы
Нет
Инкапсуляция
Типизация
Сильная
(входит
закрытые
в
Ada9x)
типизация Да
Полиморфизм
Нет (входит в Ada9x)
Параллельность
Многозадачность
Да
Сохраняемость
Долгоживущие объекты
Нет
Табл. 6 Основные характеристики Eiffel.
Абстракции
Переменные
экземпляра Да
Методы
экземпляра Да
Переменные
класса Нет
33
Методы класса
Нет
Переменных
Закрытые
Методов
Открытые, закрытые
Модульность
Разновидности модулей
Блок (unit)
Иерархии
Наследование
Множественное
Шаблоны
Да
Метаклассы
Нет
Инкапсуляция
Типизация
Сильная
типизация Да
Полиморфизм
Да
Параллельность
Многозадачность
Нет
Сохраняемость
Долгоживущие объекты
Нет
12 Понятие формального языка. Основные понятия. Способы задания. Примеры.
Формальный язык
В математической логике и информатике формальный язык — это множество конечных слов (син. строк, цепочек) над
конечным алфавитом. Понятие языка чаще всего используется в теории автоматов, теории вычислимости и теории
алгоритмов. Научная теория, которая имеет дело с этими объектами, называется теорией формальных языков.
Например, если алфавит задан как {a, b}, а язык L включает в себя все слова над ним, то слово ababba принадлежит L.
Пустое слово (то есть строка нулевой длины) допускается и часто обозначается как e, ε или Λ.
Некоторые примеры формальных языков:
*
множество всех слов над {a, b}
*
множество {an}, где n — простое число, а an означает, что a повторяется n раз
*
множество синтаксически корректных программ в данном языке программирования
Формальный язык может быть определен по-разному, например:
*
Простым перечислением слов, входящих в данный язык. Этот способ, в основном, применим для определения
конечных языков и языков простой структуры.
*
Словами, порождёнными некоторой формальной грамматикой (см. иерархия Хомского)
*
Словами, порождёнными регурярным выражением
*
Словами, распознаваемыми некоторым конечным автоматом
*
Словами, порождёнными БНФ-конструкцией
Некоторые операции могут быть использованы для того, чтобы порождать новые языки из данных. Предположим, что
L1 и L2 являются языками, определёнными над некоторым общим алфавитом.
*
Связь L1L2 содержит все слова, удовлетворяющие форме vw, где v - это слово из L1, а w - слово из L2.
*
Пересечение
содержит все слова, содержащихся и в L1, и в L2.
*
Объединение
содержит все слова, содержащиеся или в L1, или в L2.
*
Дополнение языка L1 содержит все слова алфавита, которые не содержатся в L1.
*
Правое отношение L1 / L2 содержит все слова v, для которых существует слово w в L2 такое, что vw
находидось в L1.
*
Замыкание Клини
содержится в L1 и
*
Обращение
содержит все слова, которые могут быть записаны в форме w1w2...wn, где wi
. Следует помнить, что это включает и пустое слово ε, т.к. n = 0 допустимо по условию.
содержит обращенные слова из L1.
34
*
Смешение L1 и L2 содержит все слова, которые могут быть записаны в форме v1w1v2w2...vnwn, где
v1,...,vn являются такими словами, что связь v1...vn находится в L1, а w1,...,wn являются такими словами, что w1...wn
находятся в L2.
и
Другие значения:
Следует помнить, что мы можем говорить о формальном языке во многих контекстах (научном, юридическом,
лингвистическом и других), подразумевая способ выражения более осторожный и аккуратный или же более манерный,
чем повседневная речь. Смысл формального языка, подразумеваемый здесь, соответствует его определению в теории
формальных языков.
В терминологии теории моделей, язык соответствует не языку в информатике, а скорее алфавиту. Язык состоит из
множеств символов, функций и отношений вместе с их арностью, а также множество переменных. Каждое из этих
множеств может быть бесконечным. Из языка вместе с универсальными логическими символами составляются
логические высказывания.
13 Распознаватели. Задача разбора. Основные способы решения. Классификация распознавателей.
Распознаватели
Распознаватель – это очень схематизированный
алгоритм, определяющий некоторое множество. Его
можно представить в виде устройства (автомата). Этот
автомат состоит из трех частей: входной ленты,
устройства управления с конечной памятью и
вспомогательной (рабочей) памяти (рис 2.3).
Входная лента – линейная последовательность клеток
(ячеек), каждая из которых содержит один входной
символ из конечного входного алфавита. Могут
присутствовать левый и правый концевые маркеры,
может присутствовать только один концевой маркер
(левый или правый), могут отсутствовать оба маркера.
Входная головка – в каждый момент читает одну
входную ячейку. За один шаг входная головка может
сдвинуться на одну ячейку влево, вправо и остаться
неподвижной.
Распознаватель, никогда не передвигающий входную
головку влево, называется односторонним. Обычно
предполагается, что входная головка только читает. Но
могут быть такие распознаватели, у которых входная
головка и читает, и пишет.
Память – хранит информацию, построенную только
из символов конечного алфавита памяти. Может иметь
различную структуру: очередь, стек (магазин) и т. д.
Можно читать из вспомогательной памяти и писать в
нее. Для стека и очереди используются специфические операции (вталкивание, выталкивание).
Устройство управления с конечной памятью – программа, управляющая поведением распознавателя. Может являться
аналогом конечного автомата. Определяет перемещение входной головки и работу с памятью на каждом шаге (такте).
Переходит за шаг из одного состояния в другое.
Конфигурация распознавателя – мгновенный снимок, на котором изображены:
состояние устройства управления;
содержимое входной ленты;
содержимое памяти.
Начальная конфигурация – устройство управления находится в заданном начальном состоянии, входная головка
читает самый левый символ на входной ленте, память имеет заранее установленное начальное содержимое.
Заключительная конфигурация – устройство управления находится в одном из состояний, принадлежащем заранее
выделенному множеству заключительных состояний, входная головка обозревает правый концевой маркер или, если
маркер отсутствует, сошла с конца входной ленты. Иногда требуется, чтобы заключительная конфигурация памяти
удовлетворяла некоторым условиям.
35
Распознаватель допускает входную цепочку , если, начиная с начальной конфигурации, в которой цепочка записана
на входной ленте, распознаватель может проделать последовательность шагов, заканчивающуюся заключительной
конфигурацией.
Классификация распознавателей
По видам считывающего устройства распознаватели могут быть двусторонние и односторонние.
Односторонние распознаватели допускают перемещение считывающей головки по ленте входных символов
только в одном направлении. Поскольку все языки программирования подразумевают нотацию чтения исходной
программы «слева направо», то так же работают и все распознаватели. Поэтому, когда говорят об односторонних
распознавателях, то прежде всего имеют в виду левосторонние, которые читают исходную цепочку слева направо и не
возвращаются назад к уже прочитанной части цепочки.
Двусторонние распознаватели допускают, что считывающая головка может перемещаться относительно ленты входных
символов в обоих направлениях: как вперед, от начала ленты к концу, так и назад, возвращаясь к уже прочитанным
символам.
По видам устройства управления распознаватели бывают детерминированные и недетерминированные.
Распознаватель называется детерминированным в том случае, если для каждой допустимой конфигурации
распознавателя, которая возникла на некотором шаге его работы, существует единственно возможная конфигурация, в
которую распознаватель перейдет на следующем шаге работы.
В противном случае распознаватель называется недетерминированным. Недетерминированный распознаватель
может иметь такую допустимую конфигурацию, для которой существует некоторое конечное множество конфигураций,
возможных на следующем шаге работы. Достаточно иметь хотя бы одну такую конфигурацию, чтобы распознаватель
был недетерминированным.
По видам внешней памяти распознаватели бывают следующих типов:
распознаватели без внешней памяти;
распознаватели с ограниченной внешней памятью;
распознаватели с неограниченной внешней памятью.
У распознавателей без внешней памяти эта память полностью отсутствует. В процессе их работы используется
только конечная память устройства управления, доступ к внешней памяти не выполняется.
Для распознавателей с ограниченной внешней памятью размер внешней памяти ограничен в зависимости от длины
исходной цепочки символов. Эти ограничения могут налагаться некоторой зависимостью объема памяти от длины
цепочки — линейной, полиномиальной, экспоненциальной и т. д. Кроме того, для таких распознавателей может быть
указан способ организации внешней памяти — стек, очередь, список и т. п.
Распознаватели с неограниченной внешней памятью предполагают, что для их работы может потребоваться внешняя
память неограниченного объема (как правило, вне зависимости от длины входной цепочки). У таких распознавателей
предполагается память с произвольным методом доступа.
Вместе эти три составляющих позволяют организовать общую классификацию распознавателей. Например, в этой
классификации возможен такой тип: «двусторонний недетерминированный распознаватель с линейно ограниченной стековой памятью».
Чем выше в классификации стоит распознаватель, тем сложнее создавать алгоритм, обеспечивающий его работу. Разрабатывать двусторонние распознаватели сложнее, чем односторонние. Можно заметить, что недетерминированные
распознаватели по сложности выше детерминированных. Зависимость затрат на создание алгоритма от типа внешней
памяти также очевидна.
Классификация распознавателей по типам языков
Как было сказано выше, классификация распознавателей (вид входящих в состав распознавателя компонентов)
определяет сложность алгоритма работы распознавателя. Но сложность распознавателя также напрямую связана с типом
языка, входные цепочки которого может принимать (допускать) распознаватель.
В классификации Хомского было определено четыре основных типа языков. Доказано, что для каждого из этих
типов языков существует свой тип распознавателя с определенным составом компонентов и, следовательно, с заданной
сложностью алгоритма работы.
Для языков с фразовой структурой (тип 0) необходим распознаватель, равномощный машине Тьюринга —
недетерминированный двусторонний автомат, имеющий неограниченную внешнюю память. Поэтому для языков
данного типа нельзя гарантировать, что за ограниченное время на ограниченных вычислительных ресурсах
распознаватель завершит работу и примет решение о том, принадлежит или не принадлежит входная цепочка заданному
языку. Отсюда можно заключить, что практического применения языки с фразовой структурой не имеют (и не будут
иметь), а потому далее они не рассматриваются.
Для контекстно-зависимых языков (тип 1) распознавателями являются двусторонние недетерминированные
автоматы с линейно ограниченной внешней памятью. Алгоритм работы такого автомата в общем случае имеет
36
экспоненциальную сложность — количество шагов (тактов), необходимых автомату для распознавания входной
цепочки, экспоненциально зависит от длины этой цепочки. Следовательно, и время, необходимое на разбор входной
цепочки по заданному алгоритму, экспоненциально зависит от длины входной цепочки символовТакой алгоритм распознавателя уже может быть реализован в программном обеспечении компьютера — зная длину
входной цепочки, всегда можно сказать, за какое максимально возможное время будет принято решение о
принадлежности цепочки данному языку и какие вычислительные ресурсы для этого потребуются. Однако
экспоненциальная зависимость времени разбора от длины цепочки существенно ограничивает применение
распознавателей для контекстно-зависимых языков. Как правило, такие распознаватели применяются для автоматизированного перевода и анализа текстов на естественных языках, когда временные ограничения на разбор текста
несущественны (следует также напомнить, что, поскольку естественные языки более сложны, чем контекстнозависимый тип, то после такой обработки часто требуется вмешательство человека).
В компиляторах контекстно-зависимые распознаватели не применяются, поскольку скорость работы компилятора имеет существенное значение, а синтаксический разбор текста программы можно выполнять в рамках более
простого, контекстно-свободного типа языков.
Для контекстно-свободных языков (тип 2) распознавателями являются односторонние недетерминированные
автоматы с магазинной (стековой) внешней памятью — МП-автоматы. При простейшей реализации алгоритма работы
такого автомата он имеет экспоненциальную сложность, однако путем некоторых усовершенствований алгоритма
можно добиться полиномиальной (кубической) зависимости времени, необходимого на разбор входной цепочки, от
длины этой цепочки. Следовательно, можно говорить о полиномиальной сложности распознавателя для КС-языков.
Среди всех КС-языков можно выделить класс детерминированных КС-языков, распознавателями для которых являются
детерминированные автоматы с магазинной (стековой) внешней памятью — ДМП-автоматы. Эти языки обладают
свойством однозначности — доказано, что для любого детерминированного КС-языка всегда можно построить
однозначную грамматику. Кроме того, для таких языков существует алгоритм работы распознавателя с квадратичной
сложностью. Поскольку эти языки являются однозначными, именно они представляют наибольший интерес для
построения компиляторов.
Более того, среди всех детерминированных КС-языков существуют такие классы языков, для которых возможно
построить линейный распознаватель — распознаватель, у которого время принятия решения о принадлежности цепочки
языку имеет линейную зависимость от длины цепочки. Синтаксические конструкции практически всех существующих
языков программирования могут быть отнесены к одному из таких классов языков. Это обстоятельство очень важно для
разработки современных быстродействующих компиляторов. Поэтому в главе, посвященной КС-языкам, в первую
очередь будет уделено внимание именно таким классам этих языков.
Тем не менее следует помнить, что только синтаксические конструкции языков программирования допускают разбор с
помощью распознавателей КС-языков Сами языки программирования, как уже было сказано, не могут быть полностью
отнесены к типу КС-языков, поскольку предполагают некоторую контекстную зависимость в тексте исходной
программы (например, такую, как необходимость предварительного описания переменных). Поэтому кроме
синтаксического разбора практически все компиляторы предполагают дополнительный семантический анализ текста
исходной программы. Этого можно было бы избежать, если построить компилятор на основе контекстно-зависимого
распознавателя, но скорость работы такого компилятора была бы недопустима низка, поскольку время разбора в таком
варианте будет экспоненциально зависеть от длины исходной программы. Комбинация из распознавателя КС-языка и
дополнительного семантического анализатора является более эффективной с точки зрения скорости разбора исходной
программы.
Для регулярных языков (тип 3) распознавателями являются детерминированные автоматы без внешней памяти —
конечные автоматы (КА). Это очень простой тип распознавателя, который всегда предполагает линейную зависимость
времени на разбор входной цепочки от ее длины. Кроме того, конечные автоматы имеют важную особенность: любой
недетерминированный КА всегда может быть преобразован в детерминированный. Это обстоятельство существенно
упрощает разработку программного обеспечения, обеспечивающего функционирование распознавателя.
Простота и высокая скорость работы распознавателей определяют широкую область применения регулярных языков.
В компиляторах распознаватели на основе регулярных языков используются для лексического анализа текста исходной
программы — выделения в нем простейших конструкций языка, таких как идентификаторы, строки, константы и т. п.
Это позволяет существенно сократить объем исходной информации и упрощает синтаксический разбор программы.
Более подробно взаимодействие лексического и синтаксического анализаторов текста программы рассмотрено дальше, в
главе, посвященной структуре компилятора. На основе распознавателей регулярных языков функционируют ассемблеры
— компиляторы с языков ассемблера (мнемокода) в язык машинных команд.
Кроме компиляторов регулярные языки находят применение еще во многих областях, связанных с разработкой
программного обеспечения вычислительных систем. На их основе функционируют многие командные процессоры как в
системном, так и в прикладном программном обеспечении. Для регулярных языков существуют развитые,
37
математически обоснованные механизмы, которые позволяют облегчить создание распознавателей. Они положены в
основу существующих разнообразных программных средств, которые позволяют автоматизировать этот процесс.
14 Классификации языков и грамматик по Хомскому.
Пусть А = {а1,а2,…аn} – конечное множество абстрактных символов, называемое алфавит.
Строка (слово) в алфавите А – это произвольная последовательность расположенных друг за другом символов этого
алфавита, возможно бесконечная последовательность. Строки будем обозначать греческими буквами. Множество всех
возможных слов в алфавите А – А*.
A+ = {α | (α = ai1ai2…aik…) /\ (aij  A)}; A* = A+  {ε}, где ε – пустое слово.
Языком в алфавите А называется любое подмножество множества А*. Языки будем обозначать буквой L  A*. Слова,
принадлежащие языку L иногда называют правильными словами, т.к. любое слово j  L – это не любая цепочка
символов, а такая цепочка, которая конструируется по некоторым правилам (грамматике). Длина слова α будет
обозначаться символом |α|. Таким образом, если α = ai1ai2…aik, то |α|=k.
Формальная грамматика языка L – это математическая система, которая задает язык с помощью порождающих правил:
G = <Vт, VN, P, S>, где Vт = {a1,…an} – множество терминальных символов, VN = {S, A, B, C, …} – конечное множество
нетерминальных символов, V = Vт  VN - множество терминальных и нетерминальных символов данной грамматики, P
= {pi} – множество правил вывода данной грамматики, pi: α  β («β выводится из α»), α
 V , β V*.
+
Среди правил вывода обязательно должно присутствовать правило вида: S  B, где S  VN и называется начальным
символом грамматики G.
Слово w  V*, которое может быть выведено из начального символа S путем последовательного применения правил
pi  P называется сентенциальной формой.
*
pi
pj
S 
 
  ...  w  S  w
G
Сентенция – частный случай сентенциальной формы: цепочка (слово), состоящее только из терминальных символов
w  Vт* и выводимая из начального символа S.
Множество всех сентенций, выводимых из начального символа S с помощью правил грамматики G называется языком,
порожденным грамматикой G и обозначается L(G), а сама грамматика G называется порождающей грамматикой.
Порождающая грамматика G - это четверка (VT, VN, P, S), где
VT - алфавит терминальных символов ( терминалов ),
VN - алфавит нетерминальных символов (нетерминалов), не пересекающийся с VT,
P - конечное подмножество множества (VT  VN)+  (VT  VN)*; элемент (, ) множества P называется правилом
вывода и записывается в виде  ,
S - начальный символ (цель) грамматики, S  VN.
ТИП 0:
Грамматика G = (VT, VN, P, S) называется грамматикой типа 0, если на правила вывода не накладывается никаких
ограничений (кроме тех, которые указаны в определении грамматики).
Язык типа 0: L(G) = {a2
G:
bn
2
1
| n >= 1}
A

ТИП 1:
Грамматика G = (VT, VN, P, S) называется неукорачивающей грамматикой, если каждое правило из P имеет вид  ,
где   (VT  VN)+,   (VT  VN)+ и
|  | <= |  |.
Грамматика G = (VT, VN, P, S) называется контекстно-зависимой ( КЗ ), если каждое правило из P имеет вид  , где
 = 1A2;  = 12; A  VN;
  (VT  VN)+; 1,2  (VT  VN)*.
Язык типа 1: L(G) = { an bn cn, n >= 1}
G:
S aSBC | abC
CB BC
bB bb
38
bC bc
cC cc
Грамматику типа 1 можно определить как неукорачивающую либо как контекстно-зависимую.
ТИП 2:
Грамматика G = (VT, VN, P, S) называется контекстно-свободной ( КС )
, где
A  VN,   (VT  VN)+.
Грамматика G = (VT, VN, P, S) называется укорачивающей контекстно-свободной ( УКС ), если каждое правило из Р
, где A  VN,
  (VT  VN)*.
Грамматику типа 2 можно определить как контекстно-свободную либо как укорачивающую контекстно-свободную.
Язык типа 2: L(G) = {(ac)n (cb)n | n > 0}
G:
ТИП 3:
Грамматика G = (VT, VN, P, S) называется праволинейной
 VN, B  VN, t  VT.
Грамматика G = (VT, VN, P, S) называется леволинейной, если каждое пр
VN, B  VN, t  VT.
Грамматику типа 3 (регулярную, Р-грамматику) можно определить как праволинейную либо как леволинейную.
Язык типа 3: L(G) = {  |   {a,b}+, где нет двух рядом стоящих а}
G:
 | B

Соотношения между типами грамматик:
(1) любая регулярная грамматика является КС-грамматикой;
(2) любая регулярная грамматика является УКС-грамматикой;
(3) любая КС-грамматика является КЗ-грамматикой;
(4) любая КС-грамматика является неукорачивающей грамматикой;
(5) любая КЗ-грамматика является грамматикой типа 0.
(6)любая неукорачивающая грамматика является грамматикой типа 0.
15 Способы записи синтаксиса формальных языков.
Формальная грамматика
Любой естественный язык возникал как средство общения людей. Ему присущи такие особенности как:
изменчивость, которая состоит в непостоянстве словарного состава языка;
неоднозначность трактовки фраз различными людьми;
избыточность.
Естественный язык нельзя применить для записи алгоритма, поскольку одним из свойств алгоритма является его
детерминированность, т.е. однозначность выполнения шагов любым исполнителем. Для преодоления нежелательных
свойств естественных языков используется построение формальных языков - искусственных языков со строгим
синтаксисом и полной смысловой определенностью.
В любом языке можно выделить две составляющие: синтаксис и семантику. Синтаксис (грамматика языка) – это
совокупность правил, согласно которым строятся допустимые в данном языке конструкции. Семантика – смысловая
сторона языка – она соотносит единицы и конструкции языка с некоторым внешним миром, для описания которого язык
используется.
Для описания формального языка необходим другой язык, с помощью которого будут создаваться языковые
конструкции. Описываемый формальный язык называется языком-объектом, а язык, средствами которого производится
описание – метаязыком. Метаязык должен обеспечивать как описание структурных единиц языка и правил
объединения их в допустимые предложения, так и содержательную (смысловую) сторону языковых конструкций.
Любая грамматика начинается с указания алфавита, т.е. набора символов, посредством которого строятся конструкции
языка.
Формальная грамматика задается упорядоченной четверкой {T, N, S, P}, где T и N – непересекающиеся конечные
множества, образующие алфавит или словарь порождаемого формального языка; T называется множеством (словарем)
терминальных символов; N – множеством (словарем) нетерминальных (вспомогательных) символов. S – начальный
(выделенный) вспомогательный символ из множества N. P – набор правил вывода конструкций языка (подстановок) из
выделенного вспомогательного символа, имеющие вид g h, где g и h – цепочки, состоящие как из терминальных, так и
нетерминальных символов.
Способы записи синтаксиса языка
39
Существуют различные способы записи синтаксических правил, что в основном определяется условными
обозначениям и ограничениями на структуру правил, принятыми в используемых метаязыках.
Метаязык Хомского
Метаязык Хомского вышел из недр математической логики. Он имеет следующую систему обозначений:
символ “->” отделяет левую часть правила от правой (читается как "порождает" и "это есть");
нетерминалы обозначаются буквой А с индексом, указывающим на его номер;
терминалы - это символы используемые в описываемом языке;
каждое правило определяет порождение одной новой цепочки, причем один и тот же нетерминал может встречаться в
нескольких правилах слева.
Описание идентификатора на метаязыке Хомского будет выглядеть следующим образом(некоторые примеры):
18. A1 -> R
40. A1 -> n
62. A2 -> 9
19. A1 -> S
41. A1 -> o
63. A3 -> A1
20. A1 -> T
42. A1 -> p
64. A3 -> A3A1
21. A1 -> U
43. A1 -> q
65. A3 -> A3A2
Метаязык Хомского-Щутценберже
Более компактное описание возможно с применением метаязыка Хомского-Щутценберже, использующего следующие
обозначения метасимволов:
символ “=” отделяет левую часть правила от правой (вместо символа “->”);
нетерминалы обозначаются буквой А с индексом, указывающим на его номер;
терминалы - это символы используемые в описываемом языке;
каждое правило определяет порождение нескольких альтернативных цепочек, отделяемых друг от друга символом “+”,
что позволяет, при желании, использовать в левой части только разные нетерминалы.
Введение возможности альтернативного перечисления позволило сократить описание языков. Описание
идентификатора будет выглядеть следующим образом:
A1=A+B+C+D+E+F+G+H+I+J+K+L+M+N+O+P+Q+R+S+T+
U+V+W+X+Y+Z+a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+
r+s+t+u+v+w+x+y+z
A2=0+1+2+4+5+6+7+8+9
A3=A1+A3A1+A3A2
Нотации Бэкуса-Наура формы (БНФ)
Впервые использовался для описания синтаксиса реального языка программирования Алгол 60. Наряду с новыми
обозначениями метасимволов, в нем использовались содержательные обозначения нетерминалов. Это сделало описание
языка нагляднее и позволило в дальнейшем широко использовать данную нотацию для описания реальных языков
программирования. Были использованы следующие обозначения:
-символ "::=" отделяет левую часть правила от правой;
-нетерминалы обозначаются произвольной символьной строкой, заключенной в угловые скобки "<" и ">";
-терминалы - это символы, используемые в описываемом языке;
-каждое правило определяет порождение нескольких альтернативных цепочек, отделяемых друг от друга символом
вертикальной черты "|".
Пример описания идентификатора с использованием БНФ:
<буква> :: = А|В|С|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|
W|X|Y|Z|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z
<цифра> :: = 0|1|2|3|4|5|6|7|8|9
<идентификатор> ::= <буква> | <идентификатор><буква> |
<идентификатор><цифра>
Правила можно задавать и раздельно:
<идентификатор> :: = <буква>
<идентификатор> :: = <идентификатор> <буква>
<идентификатор> :: = <идентификатор> <цифра>
Расширенные Бэкуса-Наура формы (РБНФ)
Метаязыки, представленные выше, позволяют описывать любой синтаксис. Однако, для повышения удобства и
компактности описания, целесообразно ввести в язык дополнительные конструкции. Существуют различные
40
расширенные формы метаязыков, незначительно отличающиеся друг от друга. Зачастую такие языки называются
расширенными формами Бэкуса-Наура (РБНФ).
Нотации Вирта:
Для повышения удобства и компактности описания.
-Квадратные скобки "[" и "]" означают, что заключенная в них синтаксическая конструкция может отсутствовать;
-фигурные скобки "{" и "}" означают ее повторение (возможно, 0 раз);
-круглые скобки "(" и ")" используются для ограничения альтернативных конструкций;
-сочетание фигурных скобок и косой черты "{/" и "/}" используется для обозначения повторения один и более раз.
Если нетерминал состоит из нескольких смысловых слов, то они должны быть написаны слитно или через «_»
Терминальные символы обозначаются словами, написанными буквами латинского алфавита или цепочками знаков,
заключенными в кавычки.
Синтаксическим правилам предшествует знак “$” в начале строки. Каждое правило заканчивается «.». Левая часть
правила отличается от правой знаком «=», а альтернативы «|»
Диаграммы Вирта
Наряду с текстовыми способами описания синтаксиса языков широко используются и графические метаязыки, среди
которых наиболее широкую известность получил язык диаграмм Вирта, впервые примененный для описания языка
Паскаль. Метасимволы заменены следующими графическими обозначениями (рис. 2.1):
-терминальные символы и их постоянные группы располагаются в окружностях или прямоугольниках со
скругленным вертикальными сторонами;
-нетерминальные символы заносятся внутрь прямоугольников;
-каждый графический элемент, соответствующий терминалу или нетерминалу, имеет по одному входу и выходу,
которые обычно рисуются на противоположных сторонах;
-каждому правилу соответствует своя графическая диаграмма, на которой терминалы и нетерминалы соединяются
посредством дуг;
-альтернативы в правилах задаются ветвлением дуг, а итерации - их слиянием;
-должна быть одна входная дуга (располагается обычно слева и сверху), задающая начало правила и помеченная именем
определяемого нетерминала, и одна выходная, задающая его конец (обычно располагается справа и снизу).
16 Регулярные языки и грамматики. Автоматные грамматики.
Наложив некоторые ограничения на допустимые в грамматиках правила, можно получить регулярные грамматики,
пригодные для описания любых регулярных языков.
41
Регулярную грамматику, Р-грамматику можно определить как праволинейную либо как леволинейную.
Грамматика G = (VT, VN, P, S) называется праволинейной, ес
A  VN, B  VN, t  VT.
Грамматика G = (VT, VN, P, S) называется леволинейной
 VN, B  VN, t  VT.
Выбор определения не влияет на множество языков, порождаемых грамматиками этого класса, поскольку доказано, что
множество языков, порождаемых праволинейными грамматиками, совпадает с множеством языков, порождаемых
леволинейными грамматиками.
Соотношения между типами грамматик:
(1) любая регулярная грамматика является КС-грамматикой;
(2) любая регулярная грамматика является УКС-грамматикой;
Соотношения между типами языков:
(1) каждый регулярный язык является КС-языком, но существуют КС-языки, которые не являются регулярными (
например, L = {anbn | n>0}).
Грамматики типа 3 (регулярную) можно использовать для описания некоторых свойств языков программирования или
высокоуровневых языков описания аппаратуры. Например, для генерирования идентификаторов по определению
многих языков программирования можно воспользоваться следующими правилами:
I→l
I→lR
R→l
R→d
R→lR
R→dR
где буква (l) и цифра (d) обозначают терминалы (для краткости будем считать так, потому что перечисление всех
возможных букв и цифр потребовало бы написания слишком большого числа правил). Иногда удобно объединять
правые части правил, имеющих одинаковые левые части.
Выше приведенную грамматику можно также записать в виде:
I→l|lR
R→l|d|lR|dR
Вертикальную черту здесь надо понимать как "или".
Многие "локальные" средства языков программирования, например константы, ключевые слова языка и строки,
представляются с помощью грамматик типа 3. Некоторые очень простые языки описания аппаратуры также можно
описать с помощью регулярной грамматики. Однако грамматики типа 3 генерируют только строго ограниченные типы
языков –регулярные выражения.
В алфавите А к регулярным выражениям относятся следующие:
1. Элемент А (или пустая строка).
Если P и Q – регулярные выражения, то регулярными будут также и выражения
2. PQ (Q следует за P)
3. P | Q (P или Q)
4. P* (нуль или более экземпляров P)
В алфавите {a, b, c}
ab* | ca* – регулярное выражение, которое описывает язык, включающий следующие строки (помимо прочих):
abb c caaa ab ca
Пример регулярного выражения. Регулярное выражение, описывающее идентификатор, имеет вид:
L ( L | D )*, где L обозначает букву, D – цифру.
У регулярных выражений есть существенные ограничения. Например, регулярное выражение не может задавать
шаблоны скобок произвольной длины, и, следовательно, их нельзя генерировать с помощью грамматики типа 3.
Тип языка соответствует типу той грамматики, с помощью которой он может быть порожден.
Языки типа 3, которые называют автоматными языками, языками с конечным числом состояний, нашли широкое
применение в исследовании электронных схем, а также в ряде других областей (например, исследование цепей
Маркова).
Языки могут быть заданы двумя способами:
1) грамматиками (порождающее средство языка);
2) автоматами (распознающее средство языка).
42
Существует полное соответствие между регулярными выражениями (а поэтому и грамматиками типа 3) и конечными
автоматами, которые определяются следующим образом:
Конечный автомат – это устройство для распознавания строк какого-либо языка. У него есть конечное множество
состояний, отдельные из которых называются последними. По мере считывания каждой литеры строки контроль
передается от состояния к состоянию в соответствии с заданным множеством переходов. Если после считывания
последней литеры строки автомат будет находиться в одном из последних состояний, о строке говорят, что она
принадлежит языку, принимаемому автоматом. В ином случае строка не принадлежит языку, принимаемому втоматом.
Конечный автомат формально определяется пятью характеристиками:
-конечным множеством состояний ( K )
-конечным входным алфавитом ( Σ )
-множеством переходов ( δ )
-начальным состоянием ( S0 ∈K )
-множеством последних состояний ( f ∈K )
M = ( K , Σ , δ , S0 , f ).
Детерминированным автомат так называется автомат, потому что в каждом элементе таблицы переходов содержится
одно состояние. В недетерминированном конечном автомате это положение не выдерживается.
Конечный автомат можно представить графом, таблицей переходов, командами, а также матрицей переходов.
Для каждого регулярного множества существует по крайней мере одно регулярное выражение, обозначающее это
множество.
Язык, распознаваемый конечным автоматом, - это множество цепочек, читаемых автоматом при переходе из начального
состояния в одно из заключительных состояний:
L(A)={a1 a2 ... an | p0a1 > p1, p1a2 > p2, ..., pn-1an > pn; pn . F}.
Множество называется регулярным, если существует конечный детерминированный автомат, распознающий его.
Операции над регулярными языками
Так как произвольному конечному автомату однозначно соответствует детерминированный конечный автомат,
операции над конечными автоматами эквивалентны операциям над регулярными множествами, или регулярными
языками.
Известно, что для произвольного конечного автомата можно построить эквивалентный автомат без циклов в начальных
и (или) конечных состояниях.
Теорема. Для произвольного конечного автомата существует конечный автомат без циклов в начальном состоянии.
Теорема. Для произвольного конечного автомата существует эквивалентный автомат без циклов в заключительном
состоянии.
Теорема. Множество регулярных языков замкнуто относительно операций итерации, усеченной итерации, объединения,
произведения, пересечения, дополнения и разности.
На основании этой теоремы можно строить конечные автоматы, последовательно
Автоматные грамматики
Линейные грамматики (праворекурсивные и леворекурсивные) называются автоматными грамматиками, так как языки,
порождаемые ими, совпадают с языками, распознаваемыми конечными автоматами.
Рассмотрим ряд теорем.
Теорема. Для каждой праволинейной грамматики существует эквивалентный конечный автомат.
Теорема. Для произвольного конечного автомата существует эквивалентная праволинейная грамматика.
Теорема. Для каждой леворекурсивной грамматики существует эквивалентный конечный автомат.
Теорема. Для произвольного конечного автомата существует эквивалентная леворекурсивная грамматика.
Важной особенностью автоматных грамматик является возможность представления их с помощью конечных графов. По
графу грамматики легко отыскивается вывод нужной цепочки.
Любой вывод цепочки в автоматной грамматике соответствует пути в графе этой грамматики, который начинается из
вершины S (вершины, помеченной аксиомой) и заканчивается в конечной вершине.
17 Способы задания регулярных языков.
Три основных способа, с помощью которых можно задавать регулярные языки – это:
регулярные (праволинейные и леволинейные) грамматики,
конечные автоматы (КА)
регулярные множества (равно как и обозначающие их регулярные выражения).
Классификация грамматик по сложности соответствующих программ-распознавателей называется иерархией
Хомского. В ней выделены 4 класса грамматик (в порядке возрастания сложности):
а) регулярные (или автоматные). Правила имеют вид:
A : xB или A : x, где x - цепочка терминалов или e
43
б) контекстно-свободные (или КС). Правила имеют вид:
A : y, где y - цепочка из терминалов и нетерминалов
Примеры - "скобочный язык" из предыдущей лекции, язык арифметических формул
в) контекстно-зависимые (неукорачивающие). Правила имеют вид :
z : y, где z и y - цепочки из терминалов и нетерминалов, z содержит нетерминал, |z| <= |y|
nnn
Пример: a b c
г) без ограничений
Класс языка определяется классом самой простой (в смысле иерархии Хомского) из описывающих его грамматик.
Следующие вложения для классов языков очевидны, если не рассматривать КС-грамматики, содержащие так
называемые e-правила - правила с пустой правой частью.
а < б < в < рекурсивные множества < г = рек.перечислимые мн-ва
Для языка, определенного регулярной грамматикой, всегда можно написать контекстно-свободную грамматику (и даже
грамматику без ограничений!). Тем не менее, все вложения строгие: в каждом классе существуют языки, которые нельзя
задать грамматиками более простого класса.
Конечные автоматы
Конечный автомат - математическая модель устройства с конечной памятью. Рассмотрим другой способ задания
регулярных языков. (Недетерминированный) конечный автомат задается:
- алфавитом входных символов E;
- множеством состояний S;
- тернарным отношением переходов на множестве { S, E U e, S };
- начальным состоянием - выделенным состоянием в S, и
- конечными состояниями - непустым подмножеством S. Принято изображать автомат в виде ориентированного графа,
узлы которого соответствуют состояниям (конечные состояния мы будем заключать в двойную рамку), а ребра,
помеченные символами входного алфавита или е, изображают отношение переходов.
Цепочка допускается автоматом если и только если существует пусть из начального в одно из конечных состояний,
такой что, прочитав метки ребер вдоль этого пути, мы получим исходную цепочку (буква e, естественно, не читается).
Например, автомат
0
S
B
1
C
0
допускает цепочки (01)+. Этот язык можно описать регулярной грамматикой:
S:0B B:1C C:0B C:e
Несложно показать, что для каждого автомата можно построить регулярную грамматику, описывающую тот же самый
язык, и наоборот.
Детерминированный конечный автомат - частный случай недетерминированного, в котором:
- нет e-переходов,
- отношение переходов является однозначной функцией
f:( S x E U e ) -> S,
определенной, может быть, не для всех пар из SxEUe. В терминах графа это означает, что из одного состояния выходит
не более одного ребра с одинаковой меткой.
Для детерминированного автомата очень просто проверять принадлежность цепочки из E* языку. Добавив, если нужно,
еще одно "тупиковое" состояние, можно сделать функцию переходов определенной на всех парах из S x E.
S
B
C
F
0
B
F
B
F
1
F
C
F
F
s := начальное состояние
цикл для каждого символа цепочки c выполнить
s := f( s, c )
конец цикла
ответ := s - конечное состояние
44
Такая интерпретация детерминированного конечного автомата более наглядна и общепринята: KA - устройство, которое
может находится в конечном множестве состояний и переходит из одного состояния в другоe под действием внешних
событий из алфавита E.
Можно ли подобным образом интерпретировать недетерминированный автомат (или хотя бы эффективно определять
принадлежность цепочки языку)? Да, можно считать, что в том случае, когда возможен более чем один переход,
создается необходимое число экземпляров КА, которые переводятся во все возможные в этой ситуации состояния.
0
Цепочка считается допущенной, если хотя бы один из экземпляров оказался в конечном состоянии.
S
0
1
B
C
0
Заметим, что если несколько экземпляров недетерминированного КА оказались в одном состоянии, то в дальнейшем
можно рассматривать только один из них. Таким образом, максимальное количество экземпляров не превосходит числа
состояний.
Проверить, допускает ли недетерминированный конечный автомат цепочку символов, также несложно:
S := e-замыкание( { начальное состояние } )
цикл для каждого символа цепочки c выполнить
. S := e-замыкание( F( S, c ) )
конец цикла
ответ := ( S П конечные состояния ) - непусто
Здесь: S - подмножество множества состояний KA;
e-замыкание( S ) - множество состояний, достижимых из S за 0 и более e-переходов;
F( S, c ) - множество состояний, достижимых из S за один переход, помеченный символом c.
Регулярные языки и регулярные выражения
Рассмотрим специальный класс операций над языками - регулярные операции, множество языков, получаемое в
результате применения конечного числа регулярных операций из элементарных языков, - регулярные множества, способ
их описания – регулярные выражения и недетерминированные конечные автоматы, допускающие цепочки из этих
множеств.
Регулярное
Регулярное
Конечный автомат
множество
выражение
Пустая
цепочка
е
Один символ a
из E
a
e
S
a
S
pq
e
S
p|q
e
S
PQ
(конкатенация)
E
s Авт.Р е
e
PUQ
E
S
Авт.Р
e
s Авт.Q е
es
Авт.Q
E
E
45
S
P* (итерация)
p*
P (просто
скобки)
(p)
S
Авт.Р
e
s Авт.Р е
e
E
E
В регулярном выражении "*" имеет больший приоритет, чем конкатенация, а конкатенация - больший чем "|". Примеры
регулярных выражений: (0|1)*, (0|1)(0|1)*. Какие множества они описывают?
Для регулярного выражения предложен способ построения недетерминированного конечного автомата, допускающего
соответствующее выражению регулярное множество. Предложенная конструкция не является самой экономной
(автомат обычно содержит много "лишних" e-переходов), однако построенный автомат обладает следующими
полезными свойствами:
- у него только одно конечное состояние,
- в начальное состояние не входит ни одно ребро,
- из конечного состояния не выходит ни одно ребро.
Таким образом, мы доказали, что регулярные множества < регулярные языки = языки, допускаемые КА. Покажем, что
допускаемое КА множество - регулярно. (Это утверждение называется теоремой Клини).
Доказательство: Пусть S1,...Sn - состояния детерминированного КА, S1 - начальное состояние. Рассмотрим все пути в
графе переходов с началов в Si, концом в Sj, промежуточными узлами из множества {S1...Sk} (1<=i<=n, 1<=j<=n,
0<=k<=n) и множества цепочек из E - L(i,j,k), соответствующие этим путям. Докажем индукцией по k, что множества L регулярны.
L(i,j,0) - состоит из меток ребер, ведущих из Si в Sj, следовательно, регулярно.
Для 0<=k<=n-1
L(i,j,k+1) = L(i,j,k) U L(i,k+1,k) L(k+1,k+1,k)* L(k+1,j,k) получено с помощью регулярных операций из регулярных
множеств, следовательно, регулярно.
Множество цепочек, допускаемых КА, представляет собой объединение цепочек L(1,j,n), таких, что Sj - конечное
состояние КА, следовательно, регулярно. (Конец доказательства).
Мы рассмотрели 4 способа описания языков:
- регулярные (автоматные, праволинейные) грамматики,
- недетерминированные КА,
- детерминированные КА,
- регулярные выражения,
и показали, что они описывают один класс языков – регулярные языки. Этот класс языков "устроен очень хорошо" - для
всех типичных вопросов известны ответы и эффективные алгоритмы. Примеры таких вопросов :
- является ли объединение, пересечение, дополнение регулярных языков регулярным,
- является ли регулярный язык конечным, пустым,
- совпадают ли два регулярных языка,
- является ли один регулярный язык подмножеством другого,
и т.д.
(Замечание. Для других классов иерархии Хомского дела обстоят значительно хуже, например, проблема
эквивалентности для КС-языков алгоритмически неразрешима.)
Лемма о разрастании для регулярных языков
Так называмые "леммы о разрастании" для классов языков - удобный способ доказательства того, что конкретный язык
не относится к данному классу.
Лемма для регулярного языка: Существует такое число m, что любую цепочку x, |x| > m, принадлежащую языку, можно
разбить на три части: x = uvw так, что 0<|v|<=m и цепочки uv*w также будут принадлежать языку. Доказательство:
построим КА для распознавания языка. Пусть этот автомат имеет m состояний. Тогда при разборе цепочки x хотя бы
одно из состояний (например, А) проходится дважды . Разобьем цепочку x на три части - до состояния А, от А до А,
остальное. Это и есть цепочки u,v,w
18 Классы КС-языков и грамматик. Свойства КС-языков.
Свойства произвольных КС-языков (контекстно-свободных языков)
46
Класс КС-языков замкнут относительно операции подстановки. Это означает, что если в каждую цепочку символов КСязыка вместо некоторого символа подставить цепочку символов из другого КС-языка, то получившаяся новая цепочка
также будет принадлежать КС-языку.
Это основное свойство КС-языков. Формально оно может быть записано так.
Если L,La1,La2,...,Lan — это произвольные КС-языки и {a1,a2,...,an} — алфавит языка L, n > 0, то тогда язык L’ = {x1x2...xk |
aj1aj2…ajk  L, x1  Laj1, x2  Laj2, …, xk  Lajk, k>0; k  i > 0: Si>0:n  j > 0} также является КС-языком [6, т. 1].
Например:
L = {0n1n | n > 0}, L0 = {a}, L1 = {bmcm | m > 0} - это исходные КС-языки, тогда после подстановки получаем новый КСязык: L' = {anbm1cm1bm2cm2…bmncmn | n > О, i: mi>0}.
На основе замкнутости относительно операции подстановки можно доказать другие свойства КС-языков. В частности,
класс КС-языков замкнут относительно следующих четырех операций:
объединения;
конкатенации;
итерации;
гомоморфизма (изменения имен символов).
Интересно, что класс КС-языков не замкнут относительно операции пересечения. Как следствие, этот класс не замкнут и
относительно операции дополнения.
Например:
L1 = {аnbnci | n > 0, i > 0} и L2 = {аibncn | n > 0, i > 0} - КС-языки, но L = L1L2 = {аnbncn | n > 0} не является КСязыком (это можно проверить с помощью леммы о разрастании КС-языков, которая рассмотрена ниже).
Для КС-языков разрешимы проблема пустоты языка и проблема принадлежности заданной цепочки языку — для их
решения достаточно построить МП-автомат, распознающий данный язык. Но для КС-языков является неразрешимой
проблема эквивалентности двух произвольных КС-грамматик, а, как следствие, также и проблема однозначности
заданной КС-грамматики. Не разрешима даже более узкая проблема — проблема эквивалентности заданной
произвольной КС-грамматики и произвольной регулярной грамматики.
Тем не менее, хотя в общем случае проблема однозначности для КС-языков не разрешима, для некоторых КС-грамматик
можно построить эквивалентную им однозначную грамматику.
Свойства детерминированных КС-языков
Детерминированные КС-языки — это класс тех КС-языков, цепочки которых можно распознавать с помощью ДМПавтоматов. Класс детерминированных КС-языков, естественно, является собственным подмножеством всего класса КСязыков.
Как уже было сказано ранее, детерминированные КС-языки — это значительно более узкий класс, чем все КС-языки.
Класс детерминированных КС-языков не замкнут даже относительно операции объединения, равно как и операции пересечения (хотя и замкнут относительно операции дополнения, в отличие от всех КС-языков в целом).
Класс детерминированных КС-языков интересен тем, что для него разрешима проблема однозначности. Доказано, что
если язык может быть распознан с помощью ДМП-автомата (и потому является детерминированным КС-языком), то он
может быть описан на основе однозначной КС-грамматики. Именно поэтому данный класс как раз и используется для
построения синтаксических конструкций языков программирования.
Дополнительно следует заметить, что в общем случае подавляющее большинство языков программирования (таких, как
Pascal, С, FORTRAN и т. п.) формально не являются КС-языками. Причина в том, что в языках программирования
всегда присутствует контекстная зависимость, которая выражается, например, в необходимости предварительного
описания переменных, в соответствии количества и типов формальных и фактических параметров процедур и функций
и т.п. Но с целью упрощения работы компиляторов подобного рода зависимости на этапе синтаксического анализа не
учитывают, рассматривая только сами конструкции языков программирования, которые формально могут быть описаны
с помощью КС-грамматик. Соблюдение контекстных условий (зависимостей) в компиляторах проверяется уже на этапе
семантического анализа при подготовке к генерации кода.
Лемма о разрастании КС-языков
Как и для регулярных языков, лемма о разрастании для КС-языков служит для проверки принадлежности заданного
языка классу КС-языков. Доказано, что всякий язык является КС-языком тогда и только тогда, когда для него
выполняется лемма о разрастании КС-языков.
Лемма о разрастании КС-языков звучит так: если взять достаточно длинную цепочку символов, принадлежащую
произвольному КС-языку, то в ней всегда можно выделить две подцепочки, длина которых в сумме больше нуля, таких,
чтo, повторив их сколь угодно большое число раз, можно получить новую цепочку символов, принадлежащую данному
языку.
Формально ее можно определить следующим образом: если L — это КС-язык, то  k  N, k > 0, что если ||  k и   L,
то  = , где , ||  k и ii  L i > 0 (где N — это множество целых чисел).
Пользуясь леммой, докажем, что язык L = {аnbncn | n > 0} не является КС-языком.
47
Предположим, что этот язык все же является КС-языком. Тогда для него должна выполняться лемма о разрастании, и
существует константа k, заданная в этой лемме. Возьмем цепочку  = akbkck, || > k, принадлежащую этому языку. Если
ее записать в виде  = , то по условиям леммы ||  k, следовательно, цепочка  не может содержать
вхождений всех трех символов а, b и с — каких-то символов в ней нет. Рассмотрим цепочку 00 = . По
условиям леммы она должна принадлежать языку, но в то же время она содержит либо k символов а, либо k символов с
и при этом не может содержать k вхождений каждого из символов a, b и с, так как || < 3k. Значит, какой-то символ в
ней встречается меньше, чем другие — такая цепочка не может принадлежать языку L. Следовательно, язык L не
удовлетворяет требованиям леммы о разрастании КС-языков и поэтому не является КС-языков.
19 Распознаватели КС-языков. Автоматы с магазинной памятью.
Магазинные автоматы, подобно рассмотренным ранее конечным автоматам, позволяют решать для контекстносвободных языков задачу распознавания, которая заключается в том, что по заданной цепочке необходимо определить
принадлежит ли она заданному языку.
В работах, связанных с формальными языками и грамматиками, используется модель магазинного автомата (см.
рис.5.1), состоящая из
входной ленты,
устройства управления и
вспомогательной ленты, называемой магазином или стеком.
Рис.5.1. Модель магазинного автомата
Входная лента разделяется на клетки (позиции), в каждой из которых может быть записан символ входного алфавита.
При этом предполагается, что в неиспользуемых клетках входной ленты расположены пустые символы .
Вспомогательная лента также разделена на клетки, в которых могут располагаться символы магазинного алфавита.
Начало вспомогательной ленты называется дном магазина. Связь устройства управления с лентами осуществляется
двумя головками, которые могут перемещаться вдоль лент.
Головка входной ленты может перемещаться только в одну сторону - вправо или оставаться на месте. Она может
выполнять только чтение. Головка вспомогательной ленты способна выполнять как чтение, так и запись, но эти
операции связаны с перемещением головки определенным образом:
при записи головка предварительно сдвигается на одну позицию вверх, а затем символ заносится на ленту,
- при чтении символ, находящийся под головкой считывается с ленты, а затем головка сдвигается на одну позицию вниз,
т.о. головка всегда установлена против последнего записанного символа. Позицию, находящуюся в рассматриваемый
момент времени под головкой, называют вершиной магазина.
Определение. Магазинный автомат М определяется следующей совокупностью семи объектов: M={S, P, Z, , sо, hо, F },
где
S - алфавит состояний,
P - входной алфавит,
Z - алфавит магазинных символов, записываемых на вспомогательную ленту,
 - функция переходов,  : {S x P {} x H}
S x H*, если М-автомат - детерминированный, и
S x H*, если М-автомат - недетерминированный.
 : {S x P {} x H}
sо - начальное состояние, sо
.
hо- маркер дна, он всегда записывается на дно магазина , hо
.
F - множество конечных состояний. F является подмножеством S.
Функция  отображает тройки ( pi , sj , hk ) в пары ( sr
H* и hk - символ в вершине магазина, для
детерминированного автомата или в множество таких пар для недетерминированного автомата.
48
Эта функция описывает изменение состояния магазинного автомата, происходящее при чтении символа с входной
ленты и перемещении входной головки.
В дальнейшем при построении магазинных автоматов потребуются две разновидности функций переходов:
функция переходов с пустым символом в качестве входного символа:
0(s, , h) = (s', ), которая, независимо от того какой символ находится под читающей головкой входной ленты,
магазин.
2)
функция переходов с определенным входным символом:

, которая предписывает прочитать входной символ а, изменить состояние автомата на s’ и заменить
верхний символ магазина h цепочкой .
Работа магазинного автомата
Чтобы описать, как работает автомат, введем понятие конфигурации.
Определение. Конфигурацией автомата М называют тройку (s, , )S x P* x H*, где
s - текущее состояние управляющего устройства,
 - неиспользованная часть входной цепочки P*, самый левый символ этой цепочки находится под головкой. Если a
=  , то считается, что вся входная цепочка прочитана.
 - цепочка, записанная в магазине, H*, самый правый символ цепочки считается вершиной магазина. Если =, то
магазин пуст.
Работа автомата может быть представлена как смена конфигураций. Один такт работы автомата заключается в
определении новой конфигурации по заданной. Это записывается так:
(s, a, h ) ├ (s', , )
Такая смена конфигураций возможна, если функция (s, a, h ) (или (s, , h)) определена и имеет значение (s',
При
этом предполагается, что автомат
читает символ a, находящийся под головкой. Или не читает ничего, в случае входного символа .
определяет новое состояние s'
читает символ h, находящийся в вершине магазина и
записывает цепочку  в магазин вместо символа h. Если  =$, то верхний символ оказывается удаленным из магазина.
Таким образом, могут быть три случая при работе автомата:
(s, a, h) определена и выполняется такт работы,
(s, a, h) не определена, но определена функция (s, , h) и выполняется пустой такт (без чтения входной информации).
функции (s, a, h) и (s, , h) не определены, в этом случае дальнейшая работа автомата невозможна.
Начальной конфигурацией называется конфигурация (s0, , h0), где s0 - начальное состояние,  - исходная цепочка, h0 маркер дна магазина. Заключительная конфигурация – (s, , ), где s принадлежит множеству заключительных
состояний F.
Для обозначения последовательности сменяющих друг друга конфигураций условимся использовать знак ├*. Таким
образом последовательность
( s1, 
1 ) ( s2
2) ├ ... ├ ( sn
n
n)
записывается в сокращенном виде как:
(s1, 1, 1 ) ├* ( sn, n, n ).
Язык, допускаемый магазинным автоматом
Определение.
допустимой для автомата М, если существует последовательность конфигураций,
в которой первая конфигурация являе
– заключительной. (sо,
hо) ├* (s1,  ,
) , где s1 F .
Определение.Множество цепочек, допускаемых автоматом М, называется языком, допускаемым или определяемым
автоматом М, и обозначается L(М).
о,
о ) ├* ( s', , 
Чтобы лучше представить себе работу магазинного автомата, рассмотрим два примера. Пусть задан магазинный автомат
М1 в следующем виде:
М1: P = {a , b}; S = {s0 , s1 , s2}; Z = {h0 , a}; F = {s0};
 (s0 , a , h0) = (s1 , h0a),
 (s1 , a , a) = (s1 , aa),
 (s1 , b , a) = (s2 , ),
 (s2 , b , a) = (s2 , ),
 (s2 ,  , h0) = (s0 , ).
49
Этот автомат является детерминированным, поскольку каждому набору аргументов соответствует единственное
значение функции. Работу автомата при распознавании входной цепочки aabb можно представить в виде
последовательности конфигураций:
(s0,aabb,h0) ├ (s1,abb,h0a) ├ (s1,bb,h0aa) ├ (s2,b,h0a) ├ (s2,,h0) ├ (s0,,) .
Нетрудно проверить, что при задании входной цепочки aabbb автомат не сможет закончить работу. Следовательно эта
цепочка не принадлежит языку, допускаемому автоматом M 1.
Магазинный автомат М2, заданный следующим описанием:
М2: P = {a , b}; S = {s0, s1 , s2}; Z = {h0, a , b}; F = {s2};
(1)  (s0 , a , h0) = (s0, h0a),
(2)  (s0 , b , h0) = (s0, h0b),
(3)  (s0 , a , a) = {(s0,aa) , (s1 , )},
(4)  (s0 , b , a) = (s0,ab),
(5)  (s0 , a , b) = (s0 , ba),
(6)  (s0 , b , b) = {(s0 , bb) , (s1 , )},
(7)  (s1 , a , a) = (s1, ),
(8)  (s1 , b , b) = (s1, ),
(9)  (s2 , , h0) = (s2 , ),
является недетерминированным автоматом, поскольку одному и тому же набору аргументов, например (s о , a, a),
соответствуют два значения функции. Работу автомата рассмотрим для входной цепочки abba. Если использовать
последовательность команд (1),(4),(6.1),(5), то получим последовательность конфигураций:
(s0,abba,h0)
├ (s0,bba,h0a),
(1)
├ (s0,ba,h0ab),
(4)
├ (s0,a,h0abb),
(6.1)
├ (s0,,h0abba).
(5)
которая показывает, что дальнейшая работа невозможна, т.к. входная цепочка прочитана и переход (s0,,h0abba) не
определен. Если же использовать последовательность команд (1),(4),(6.2),(3),(9), то получим заключительную
конфигурацию:
(s0,abba,h0)
├ (s0,bba,h0a),
(1)
├ (s0,ba,h0ab),
(4)
├ (s1,a,h0a),
(6.2)
├ (s1,,h0),
(3)
├ (s2,,) .
(9).
Т.о. можно сделать вывод о том, что цепочка abba допускается автоматом М 2.
Построение магазинного автомата
Утверждение. Если G = { VN, VT, I, P } является КС-грамматикой, то по ней можно построить такой магазинный
автомат М, что L(M) = L(G).
В основе доказательства лежит способ построения магазинного автомата по заданной КС-грамматике. Чтобы сделать
процесс построения автомата более простым и наглядным, условимся использовать магазинные автоматы с одним
состоянием s0. Итак, пусть задана грамматика G = {VN, VT, I, P}. Определим компоненты автомата М следующим
образом:
S = {s0}, P = VT, Z = VN
T
0} , F = {s0},
в качестве начального состояния автомата примем s0 и построим функцию переходов так:
1. Для всех
N , таких что встречаются в левой части правил A
, построим команды вида:
R ),
0(s0, , A) = (s0
где R – реверс цепочки .
2. Для всех a
T построим команды вида
 ( s0, a, a) = ( s0, )
3. Для перехода в конечное состояние построим команду
 ( s0, , h0) = ( s0, )
4. Начальную конфигурацию автомата определим в виде:
( s0
h0 I),
где
исходная цепочка, записанная на входной ленте.
Автомат, построенный по приведенным выше правилам, работает следующим образом. Если в вершине магазина
находится терминал, и символ, читаемый с входной ленты, совпадает с ним, то по команде типа (2) терминал удаляется
50
из магазина, а входная головка сдвигается. Если же в вершине магазина находится нетерминал, то выполняется команда
типа (1), которая вместо терминала записывает в магазин цепочку, представляющую собой правую часть правила
грамматики. Следовательно, автомат, последовательно заменяя нетерминалы, появляющиеся в вершине магазина,
строит в магазине левый вывод входной цепочки, удаляя полученные терминальные символы, совпадающие с
символами входной цепочки. Это означает, что каждая цепочка, которая может быть получена с помощью левого
вывода в грамматике G, допускается построенным автоматом М.
Пример построения автомата
Процедуру построения автомата рассмотрим на примере грамматики с правилами:
E
E+T|T
T
T*F|F
F
E)|a
Для искомого автомата имеем:
P = {a, +, *, ), ( }, Z = {E, T, F, a, +, *) , h 0, ( }, S = {s0 }, F = {s0}
Для всех правил грамматики строим команды типа (1):
0 (s0 , , E) = {(s0 , T+E) ; (s0 , T)},
0 (s0 ,  , T) = {(s0 , F*T) ; (s0 , F)},
0 (s0 ,  , F) = {(s0 , (E) ) ; (s0 , a)},
Для всех терминальных символов строим команды типа (2):
 ( s0, a, a ) = ( s0,  ),
 ( s0 , + , + ) = (s0 ,  ),
 ( s0 , * , * ) = (s0 ,  ),
 ( s0 , ( , ( ) = (s0 ,  ),
 ( s0 , ) , ) ) = (s0 ,  ),
Для перехода в конечное состояние построим команду:
(9)  (s0 ,  , h0) = ( s0 ,  ).
Построенный автомат является недетерминированным.
Начальную конфигурацию с цепочкой a + a*a запишем так: (s0 , a+a*a , h0E).
Последовательность тактов работы построенного автомата, показывающая, что заданная цепочка допустима, имеет вид:
(s0 , a+a*a , h0E) ├ (s0 , a+a*a , h0T+E) ├ (s0 , a+a*a , h0T+T) ├ (s0 , a+a*a , h0T+F) ├
(s0 , a+a*a , h0T+a) ├ (s0 , +a*a , h0T+) ├ (s0 , a*a , h0T) ├ (s0 , a*a , h0F*T) ├
(s0 , a*a , h0F*F) ├ (s0 , a*a , h0F*a) ├ (s0 , *a , h0F* ) ├ (s0 , a , h0F) ├
(s0 , a , h0a) ├ (s0 ,  , h0) ├ (s0 ,  , ).
Отметим, что последовательность правил, используемая построенным автоматом, соответствует левому выводу входной
цепочки:
E E+T T+T F+T
a+T*F a+F*F a+a*F
a+a*a.
Если по такому выводу строить дерево, то построение будет происходить сверху вниз, т.е. от корня дерева к
листьям.
Такой способ построения дерева по заданной цепочке называется нисходящим.
Магазинные автоматы называют часто распознавателями, поскольку они определяют, является ли цепочка, подаваемая
на вход автомата, допустимой или нет, и следовательно, отвечают на вопрос, принадлежит ли эта цепочка языку,
порождаемому грамматикой, использованной для построения автомата.
Учитывая характер построения вывода в магазине, автоматы рассмотренного типа называют нисходящими
распознавателями.
51
Еще раз подчеркнем, что доказательство допустимости цепочки нисходящим магазинным автоматом (НМА)
предусматривает поиск определенной последовательности конфигураций. Такой поиск может существенно увеличить
время работы автомата.
Детерминированные автоматы не требуют поиска и работают быстрее, поэтому именно такие автоматы применяются на
практике. Детерминированные автоматы-распознаватели могут быть построены не для всех, а только для некоторых
видов КС-грамматик.
Определение. Если язык L допускается детерминированным магазинным автоматом, то он называется
детерминированным языком.
Таким образом, задачу распознавания для КС-языков решают магазинные преобразователи. В общем случае для любой
КС-грамматики можно построить магазинный распознаватель, допускающий язык, который порождается заданной
грамматикой. Однако, такой распознаватель может оказаться недетерминированным. Работа недетерминированного
распознавателя связана с поиском последовательности конфигураций, показывающей допустимость входной цепочки.
Поиск увеличивает время работы автомата, поэтому для практических применений предпочитают использовать
детерминированные автоматы
20 n-дольные графы. Сети Петри, как пример двухдольных графов. Количество долей в следующих графах:
в октаэдре, в двухмерном единичном квадрате, в трехмерном единичном кубе.
Граф является двудольным (чётный граф) тогда и только тогда, когда он не содержит цикла нечётной длины. N-дольным
называется граф вида G=(X, R), где множество вершин X разбито на совокупность непересекающихся подмножеств
X1
2
N, а из существования ребра r=(z,y) следует, что инцидентные ребру вершины принадлежат разным
Инцидентность — понятие, используемое только в отношении ребра и
вершины: если v1,v2 — вершины, а e = (v1,v2) — соединяющее их ребро, тогда вершина v1 и ребро e инцидентны,
вершина v2 и ребро e тоже инцидентны. Две вершины (или два ребра) инцидентными быть не могут. Для обозначения
ближайших вершин (рёбер) используется понятие смежности. Подмножества вида X i принято называть долями графа.
Из определения следует, что все доли являются независимыми множествами вершин.
Это граф вида G=(X1,X2,…Xn, R), где X=UXi — множество вершин, а R множество ребер. Подмножество X i принято
называть долями графа, ребра графа могут соединять только вершины разных долей. Вершины, принадлежащие одной
доле всегда являются независимым подмножеством.
Сеть Петри представляет собой двудольный ориентированный граф, состоящий из вершин двух типов — позиций и
переходов, соединённых между собой дугами, вершины одного типа не могут быть соединены непосредственно. В
позициях могут размещаться метки (маркеры), способные перемещаться по сети.
Теоретико-графовым представлением сети Петри является двудольный ориентированный мультиграф.
Структура сети Петри представляет собой совокупность позиций и переходов. В соответствии с этим граф сети Петри
обладает двумя типами вершин: "кружок" называется позицией, а "планка" - переходом. Ориентированные дуги
(стрелки) соединяют позиции и переходы, при этом некоторые дуги направлены от позиций к переходам, а другие - от
переходов к позициям. Дуга, направленная от позиции P i к переходу Tj, определяет позицию, которая называется входом
перехода. Кратные входы в переход указываются кратными дугами из входных позиций в переход. Выходная позиция
указывается дугой от перехода к позиции. Кратные выходы также представлены кратными дугами. Очевидно, что сеть
Петри является ориентированным двудольным мультиграфом, который в дальнейшем будем называть графом сети
Петри.
Определение .
Граф G сети Петри есть двудольный ориентированный мультиграф, G=(V,A), где V={v1,v2,...,vs} - множество вершин,
A={a1,a1,...,ar} - комплект дуг, ai=(vj,vk), где vj,vk
T, а
i
i=(vi,vk), то либо vj
k
v P.
Октаэдр – не двудольный, двухмерном единичном квадрате – не двудольный, в трехмерном единичном кубе –
двудольный.
21 Табличное представление логических функций. Графическое представление логических функций на
многомерных единичных кубах. Карты Карно.
Табличное и графическое представление логических функций можно показать на примере нахождения МДНФ:
1.
Задаём булеву функцию, состоящую из трёх переменных с помощью таблицы
x1
0
0
0
0
x2
0
0
1
1
x3
0
1
0
1
f
0
1
0
1
52
1
1
1
1
0
0
1
1
0
1
0
1
1
1
0
1
2.
Находим вектор носителя (Значения переменных, при которых функция равна единице)
Nf = {(001), (011), (100), (101), (111)}
Исходя из вектора носителя записываем функцию в виде СДНФ (совершённая дизъюнктивная
нормальная форма). ДНФ – это дизъюнкция элементарных конъюнкций. При этом значения
переменных, которые равны нулю надо инвертировать.
Находим обратное значение вектор носителя (Значения переменных, при которых функция равна
нулю).
Исходя из обратного значения вектора носителя записываем функцию в виде СКНФ (совершённая конъюнктивная
нормальная форма). КНФ – это конъюнкция элементарных дизъюнкций. При этом значения переменных, которые равны
единице надо инвертировать.
6.
Находим МДНФ (минимальная дизъюнктивная нормальная форма)
а.
Строим единичный куб с помощью значений полученных из вектора носителя и обратного значения
вектора носителя.
б.
Отмечаем те точки, где функция равна единице.
в.
Находим гиперплоскости. Интервал – это гиперплоскость, целиком лежащая в носителе.
г.
Находим сокращённую ДНФ.
д.
Находим Дя (Ядровая дизъюнктивная нормальная форма). Дя – это ДНФ всех ядровых интервалов.
Ядровый интервал – это интервал, который содержит вершину, которая не покрыта ни каким другим интервалом.
е.
Находим МДНФ. Дмин = Дя
Более сложном случай, при значении функции f = (01111100)
53
Карты Карно
1.
x1
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
Задаём булеву функцию, состоящую из четырёх переменных с помощью таблицы
x2
0
0
0
0
1
1
1
1
0
0
0
0
1
1
1
1
x3
0
0
1
1
0
0
1
1
0
0
1
1
0
0
1
1
x4
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
f
0
1
0
1
1
1
0
1
1
0
0
1
0
0
1
1
2.
Строим Карту Карно
а.
Указываем на карте Карно, где значения функции равно единице.
б.
Объединяем смежные клетки, содержащие единицы.
3.
Находим МДНФ
54
Примечание:
Карта Карно для трёх переменных имеет вид
Карта Карно для двух переменных имеет вид
22 Полные системы логических функций.
Задача синтеза комбинационных схем с использованием функционально полной системы логических элементов можно
построить комбинационную схему реализующую любую наперед заданную ,сколь угодно сложную булеву функцию.
Доказательство функциональной полноты некоторой системы
булевых функций можно осуществлять одним из двух способов:
С использованием теоремы о функциональной полноте .
С использованием конструктивного подхода .
Теорема о функциональной полноте (Пост - Яблонского).
Для того, чтобы система булевых функций была функционально полной необходимо и достаточно чтобы она содержала
хотя бы одну функцию не:
cохраняющую константу ноль
cохраняющую константу единица
линейную функцию
монотонную функцию
самодвойственную функцию.
Замечательные классы булевых функций.
Булева функция называется сохраняющей константу ноль , если на нулевом наборе аргументов она принимает значение
равное нулю, то есть f(0,0,0,...,0) = 0;
В противном случае функция относится к классу не cохраняющих константу ноль.
К функциям ,сохраняющим константу ноль относятся
f(x1,x2)= x1 v x2
f(x1,x2)= x1 * x2
К функциям не cохраняющим константу ноль относятся
f(x)= x и f(x1,x2)=x1x2
2.Булева функция называется сохраняющей константу единица , если на единичном наборе аргументов она
принимает значение равное единице, то есть f(1,1,1,...,1)= 1;
В противном случае функция относится к классу не cохраняющих константу единица.
55
К функциям ,сохраняющим константу единица относятся
f(x1,x2)= x1 v x2
f(x1,x2)= x1 * x2
К функциям не cохраняющим константу единица относятся
f(x)= x и f(x1,x2)=x1x2
3. Булева функция называется линейной если она представима полиномом Жегалкина первой степени.
В булевой алгебре доказывается теорема о возможности представления любой булевой функции от n
переменных с помощью полинома Жегалкина n-ой степени.
В общем случае полином имеет вид :
fn (x) = K0 K1x1 ...Kn xn ...
...Kn+1x1x2 Kn+2x1x3 ...Kn+lxn-1xn ...
...
...Kn+mx1x2...xn
K0 ,K1 ,Kn+m -являются коэффициентами и представляют собой логические константы нуля или единицы.
В алгебре Жегалкина одноименной полином можно считать канонической нормальной формой для булевой
алгебры.
Полином Жегалкина является линейным (1-ой степени) если все коэффициенты общего полинома ,начиная с
Kn+1=Kn+2 =...=Kn+m =0
В отношении функции от 2-х переменных полином Жегалкина имеет вид (линейный): f2(x)=K0K1x1K2x2
Примерами линейных функций являются:
y= x1x2 (K0=0,K1=K2=1)
_____
y= x1x2=x1x2=1x1x2 (K0=K1=K2)
y= X =1x1 (K0=K1=1 ,K2=0)
Примеры нелинейных функций:
y= x1x2
____
y= x1lx2 =x1x2=1x1x2
4.Булева функция называется монотонной если при возрастании наборов аргументов она принимает
неубывающие значения.
A=(a1,a2,...,an)>B=(b1,b2,...,bn)
f(A)f(B)
Между наборами аргументов А и В имеет место отношение возрастания в том и только том случае , если имеет
место отношение не убывания для всех компонент этого набора:
___
aibi (i=1, n )
и по крайней мере для одной компоненты имеет место отношение возрастания.
Примеры наборов ,для которых имеет место отношение возрастания: (1011)>(0011)
(1011)>(0001)
(0001)>(0000)
Пример несопоставимых наборов (1011) и (0111)
В отношении функции от 2-х переменных несопоставимыми являются наборы (01) и (10)
Пример немонотонных функций: y= X
y= x1x2
5.Две булевы функции fn(x) и gn(x) называются двойственными если для любых наборов аргументов
выполняется равенство
____
fn(x) =gn(x) то есть функции f и g на противоположных наборах аргументов х и X принимает противоположные
значения .
Два набора аргументов называются противоположными если любая из их компонент принимает
противоположные значения.
x=(0101)
X
=(1010)
56
Булева функция называется самодвойственной если она является двойственной по отношению к самой себе то
есть принимает противоположные значения на противоположных наборах аргументов.
Примером самодвойственной функции является : у= X
Примеры не самодвойственных функций: у=х1х2
у=х1vх2
у=х1х2
Принадлежность базовых булевых функций и логических констант к замечательным классам представлена
таблицей.
К0 + сохраняет константу ноль ,- не сохраняет константу ноль
К1 + сохраняет константу единица ,- не сохраняет константу
Кл + линейная ,- нелинейная
Км + монотонная , - не монотонная
Кс + самодвойственная ,- не самодвойственная
Функция
К0
К1
Кл
Км
Кс
0
+
+
+
1
+
+
+
X
х1х2
х1vх2
х1х2
х1х2
х1х2
х1х2
х1|х2
х1х2
+
+
+
+
-
+
+
-
+
+
+
+
-
-
-
Конструктивный подход к доказательству функциональной полноты некоторой системы булевых функций.
Подход основан на доказательстве реализуемости функций булева базиса с помощью функций этой системы.
При этом естественно предполагать ,и это действительно так, что булев базис образует функционально полную
систему.
Пример :S5=
_ ____
x =x  x= xx

x1x2 = x1x2 =( x1x2)( x1x2)
______
X
Пример:
1

X
=( x1x1)( x2x2)
23 Нормальные формы логических функций. Минимизация логических функций.
Нормальные формы логических функций
Простой конъюнкцией называется конъюнкция одной или нескольких переменных, при этом каждая переменная
встречается не более одного раза (либо сама, либо ее отрицание).
x1vx2=
2
xyz
Простой дизъюнкцией называется дизъюнкция одной или нескольких переменных, при этом каждая переменная
входит не более одного раза (либо сама, либо ее отрицание).
Пример:
xyz
Дизъюнктивной нормальной формой (ДНФ) называется дизъюнкция простых конъюнкций.
Пример:
xy  yz
Совершенной дизъюнктивной нормальной формой (СДНФ) называется такая ДНФ, у которой все входящие в неё
элементарные конъюнкции полны относительно данного набора переменных.
Например, выражение
x  yz
является ДНФ, но не СДНФ. Выражение
xyz  xyz  xyz
является СДНФ.
Конъюнктивной нормальной формой (КНФ) называется конъюнкция простых дизъюнкций.
Пример:
(x  y  z )( x  y )( y  z )
57
Совершенной конъюнктивной нормальной формой (СКНФ) называется такая КНФ, у которой все входящие в неё
элементарные дизъюнкции полны относительно данного набора переменных.
Пример:
(x  y  z )( x  y  z )( x  y  z )
Совершенная ДНФ и КНФ для заданной булевой функции строятся однозначно. Они получаются из таблицы
истинности булевой функции следующим образом:
Для СДНФ:
необходимо выбрать из таблицы истинности функции все наборы аргументов, на которых функция принимает значения
"1";
выписать элементарные конъюнкции, соответствующие этим наборам элементов: если
он вписывается без изменения в конъюнкцию, если
отрицание
xi
(т.е.
xi
xi
входит в данный набор как 1,
входит в данный набор как 0, то в конъюнкции вписывается
xi );
все полученные элементарные конъюнкции соединяются между собой знаками дизъюнкции (т.е. «  »).
Для СКНФ:
необходимо выбрать в таблице истинности функции все наборы аргументов, на которых функция принимает значения
"0";
выписать элементарные дизъюнкции, соответствующие этим наборам элементов: если
он вписывается без изменений в дизъюнкцию, если
отрицание (т.е.
xi
xi
входит в данный набор как 0,
входит в данный набор как 1, то в дизъюнкцию вписывается его
xi );
все полученные элементарные дизъюнкции соединяются между собой знаками конъюнкции (т.е. «·»).
Минимизация логических функций
Задача минимизации булевых функций возникает из практических потребностей построения логических схем,
различающих аналитические выражения булевых функций.
Первичной аналитической формой, получаемой из табличного представления логической функции, является СДНФ или
СКНФ. Легко понять, что в большинстве случаев значение функции в виде СДНФ и СКНФ является заведомо
неэкономной, избыточной и может быть построена эквивалентная функция, реализующая в своем представлении
меньшее число переменных и операций.
Например, обратимся к СДНФ:
f (x1 , x 2 , x 3 )  x1x 2 x3  x1x 2 x3  x1x 2 x3  x1x 2 x 3
Используя законы алгебры логики, получим:
f  x1x 2 x3  x1x 2 x3  x1x 2 (x3x3 )  x1x 2 x3  x1x 2 x3  x1x 2
Под сложностью нормальной формы следует понимать сумму рангов её составляющих, т.е. число букв в ней. Поэтому
ДНФ, имеющая наименьшую сумму рангов среди всех ДНФ, эквивалентных данной функции, называется
минимальной ДНФ (МДНФ). Если же в качестве меры сложности рассматривать число элементарных конъюнкций в
ДНФ или число элементарных дизъюнкций в КНФ, то ДНФ, имеющая наименьшую длину среди всех ДНФ,
эквивалентных данной функции называется кратчайшей ДНФ (КДНФ).
Если к исходной ДНФ применять лишь операции склеивания ( AB  AB  A ) и поглощения ( AB  A  A ), то
рано или поздно дальнейшие преобразования окажутся невозможными. В этом случае будет получаться тупиковая
ДНФ (ТДНФ), т.е. такая ДНФ, при удалении из которой любой конъюнкции, полученная в результате ДНФ не будет
эквивалентна исходной.
Среди множеств, ТДНФ должны содержаться и МДНФ. Поэтому теоретически можно искать МДНФ, сравнивая
показания ТДНФ путём последовательного перебора. Для функций, зависящих от n аргументов, при n>10 процесс
перебора оказывается длительным и практически не применяется даже с помощью ЭВМ.
Существует немало методов нахождения МДНФ, каждый из которых имеет свои достоинства и недостатки.
Например,
Графический (геометрический) метод. Наиболее нагляден и прост для отыскания МДНФ от функции трех переменных,
т.к. для отыскания МДНФ в данном случае необходимо строить n-мерный куб.
Метод Карно предназначен для минимизации функций четырех переменных. Исходным для минимизации является
представление функции на карте Карно.
58
Метод Квайна-Мак-Класки подходит для минимизации функций любого числа переменных, но он сложен в реализации
относительно предыдущих двух методов.
24. Организация вычислительных процессов в однопроцессорном компьютере (режимы однозадачный,
многозадачный, многопоточный).
Многозада́чность (англ. multitasking) — свойство операционной системы или среды программирования обеспечивать
возможность параллельной (или псевдопараллельной) обработки нескольких процессов. Истинная многозадачность
операционной системы возможна только в распределённых вычислительных системах.
Существует 2 типа многозадачности[1]:

Процессная многозадачность (основанная на процессах - одновременно выполняющихся программах). Здесь
программа - наименьший элемент кода, которым может управлять планировщик операционной системы. Более
известна большинству пользователей (работа в текстовом редакторе и прослушивание музыки).

Поточная многозадачность (основанная на потоках). Наименьший элемент управляемого кода - поток (одна
программа может выполнять 2 и более задачи одновременно).
Многопоточность - специализированная форма многозадачности[1].
Свойства многозадачной среды
Примитивные многозадачные среды обеспечивают чистое «разделение ресурсов», когда за каждой задачей закрепляется
определённый участок памяти, и задача активизируется в строго определённые интервалы времени.
Более развитые многозадачные системы проводят распределение ресурсов динамически, когда задача стартует в памяти
или покидает память в зависимости от её приоритета и от стратегии системы. Такая многозадачная среда обладает
следующими особенностями:

Каждая задача имеет свой приоритет, в соответствии с которым получает процессорное время и память

Система организует очереди задач так, чтобы все задачи получили ресурсы, в зависимости от приоритетов и
стратегии системы

Система организует обработку прерываний, по которым задачи могут активироваться, деактивироваться и
удаляться

По окончании положенного кванта времени ядро временно переводит задачу из состояния выполнения в
состояние готовности, отдавая ресурсы другим задачам. При нехватке памяти страницы невыполняющихся
задач могут быть вытеснены на диск (своппинг), а потом через определённое системой время,
восстанавливаться в памяти

Система обеспечивает защиту адресного пространства задачи от несанкционированного вмешательства других
задач

Система обеспечивает защиту адресного пространства своего ядра от несанкционированного вмешательства
задач

Система распознаёт сбои и зависания отдельных задач и прекращает их

Система решает конфликты доступа к ресурсам и устройствам, не допуская тупиковых ситуаций общего
зависания от ожидания заблокированных ресурсов

Система гарантирует каждой задаче, что рано или поздно она будет активирована

Система обрабатывает запросы реального времени

Система обеспечивает коммуникацию между процессами
Трудности реализации многозадачной среды
Основной трудностью реализации многозадачной среды является её надёжность, выраженная в защите памяти,
обработке сбоев ипрерываний, предохранении от зависаний и тупиковых ситуаций.
Кроме надёжности, многозадачная среда должна быть эффективной. Затраты ресурсов на её поддержание не должны:
мешать процессам проходить, замедлять их работу, резко ограничивать память.
59
История многозадачных операционных систем
Поначалу реализация многозадачных операционных систем представляла собой серьёзную техническую трудность,
отчего внедрение многозадачных систем затягивалось, а пользователи долгое время после внедрения предпочитали
однозадачные.
В дальнейшем, после появления нескольких удачных решений, многозадачные среды стали совершенствоваться, и в
настоящее время употребляются повсеместно.
Впервые
многозадачность
операционной
системы
была
реализована
в
ходе
разработки
операционной
системы Multics (1964 год). Одной из первых многозадачных систем была OS/360 (1966[2]), используемая для
компьютеров фирмы IBM и их советских аналогов ЕС ЭВМ. Разработки системы были сильно затянуты, и на начальное
время фирма IBM выдвинула однозадачный DOS, чтобы удовлетворить заказчиков до полной сдачи OS/360 в
эксплуатацию. Система подвергалась критике по причине малой надёжности и трудности эксплуатации.
В 1969 году на основе Multics была разработана система UNIX с достаточно аккуратным алгоритмическим решением
проблемы многозадачности. В настоящее время на базе UNIX созданы десятки операционных систем.
На компьютерах PDP-11 и их советских аналогах СМ-4 использовалась многозадачная система RSX-11 (советский
аналог — ОСРВ СМ ЭВМ), и система распределения времени TSX-PLUS, обеспечивающая ограниченные возможности
многозадачности и многопользовательский режим разделения времени, эмулируя для каждого пользователя
однозадачную RT-11 (советский аналог —РАФОС). Последнее решение было весьма популярно из-за низкой
эффективности и надёжности полноценной многозадачной системы.
Аккуратным
решением
оказалась
операционная
система VMS,
разработанная
первоначально
для
компьютеров VAX (советский аналог —СМ-1700) как развитие RSX-11.
Первый в мире мультимедийный персональный компьютер Amiga 1000 (1984 год) изначально проектировался с
расчётом на полную аппаратную поддержку вытесняющей многозадачности реального времени в ОС AmigaOS. В
данном случае разработка аппаратной и программной части велась параллельно, это привело к тому, что по показателю
квантования планировщика многозадачности (1/50 секунды на переключение контекста) AmigaOS долгое время
оставалась непревзойдённой на персональных компьютерах.
Многозадачность обеспечивала также фирма Microsoft в операционных системах Windows. При этом Microsoft выбрала
две линии разработок — на базе приобретённой ею Windows 0.9[источник не указан 514 дней], которая после долгой
доработки системы, изначально обладавшей кооперативной многозадачностью, аналогичной Mac OS, вылилась в
линейку Windows 3.x, и на основе идей, заложенных в VMS, которые привели к созданию операционных
систем Windows NT. Использование опыта VMS обеспечило системам существенно более высокую производительность
и надёжность. По времени переключения контекста многозадачности (квантование) только эти операционные системы
могут быть сравнимы с AmigaOS и UNIX (а также его потомками, такими, как ядро Linux).
Типы псевдопараллельной многозадачности
Невытесняющая многозадачность
Тип многозадачности, при котором операционная система одновременно загружает в память два или более приложений,
но процессорное время предоставляется только основному приложению. Для выполнения фонового приложения оно
должно быть активизировано.
Совместная или кооперативная многозадачность
Тип многозадачности, при котором следующая задача выполняется только после того, как текущая задача явно объявит
себя готовой отдать процессорное время другим задачам. Как частный случай, такое объявление подразумевается при
попытке захвата уже занятого объекта mutex (ядро Linux), а также при ожидании поступления следующего сообщения
от подсистемы пользовательского интерфейса (Windows версий до 3.x включительно, а также 16-битные приложения
в Windows 9x).
60
Кооперативную многозадачность можно назвать многозадачностью «второй ступени» поскольку она использует более
передовые методы, чем простое переключение задач, реализованное многими известными программами (например, DOS
Shell из MS-DOS 5.0 при простом переключении активная программа получает все процессорное время, а фоновые
приложения полностью замораживаются. При кооперативной многозадачности приложение может захватить
фактически столько процессорного времени, сколько оно считает нужным. Все приложения делят процессорное время,
периодически передавая управление следующей задаче.
Преимущества кооперативной многозадачности: отсутствие необходимости защищать все разделяемые структуры
данных объектами типа критических секций и mutex’ов, что упрощает программирование, особенно перенос кода из
однозадачных сред в многозадачные.
Недостатки: неспособность всех приложений работать в случае ошибки в одном из них, приводящей к отсутствию
вызова операции «отдать процессорное время». Крайне затрудненная возможность реализации многозадачной
архитектуры ввода-вывода в ядре ОС, позволяющей процессору исполнять одну задачу в то время, как другая задача
инициировала операцию ввода-вывода и ждет ее завершения.
Реализована в пользовательском режиме ОС Windows версий до 3.х включительно, Mac OS версий до Mac OS X, а также
внутри ядер многих UNIX-подобных ОС, таких, как FreeBSD, а в течение долгого времени — и Linux.
Вытесняющая или приоритетная многозадачность (режим реального времени)
Вид многозадачности, в котором операционная система сама передает управление от одной выполняемой программы
другой в случае завершения операций ввода-вывода, возникновения событий в аппаратуре компьютера, истечения
таймеров и квантов времени, или же поступлений тех или иных сигналов от одной программы к другой. В этом виде
многозадачности процессор может быть переключен с исполнения одной программы на исполнение другой без всякого
пожелания первой программы и буквально между любыми двумя инструкциями в ее коде. Распределение процессорного
времени осуществляется планировщиком процессов. К тому же каждой задаче может быть назначен пользователем или
самой операционной системой определенный приоритет, что обеспечивает гибкое управление распределением
процессорного времени между задачами (например, можно снизить приоритет ресурсоёмкой программе, снизив тем
самым скорость её работы, но повысив производительность фоновых процессов). Этот вид многозадачности
обеспечивает более быстрый отклик на действия пользователя.
Преимущества: возможность полной реализации многозадачного ввода-вывода в ядре ОС, когда ожидание завершения
ввода-вывода одной программой позволяет процессору тем временем исполнять другую программу. Сильное
повышение надежности системы в целом, в сочетании с использованием защиты памяти — идеал в виде «ни одна
программа пользовательского режима не может нарушить работу ОС в целом» становится достижимым хотя бы
теоретически, вне вытесняющей многозадачности он не достижим даже в теории. Возможность полного использования
многопроцессорных и многоядерных систем.
Недостатки: необходимость особой дисциплины при написании кода, особые требования к его реентрантности, к защите
всех разделяемых и глобальных данных объектами типа критических секций и mutex’ов.
Реализована в таких ОС, как:

VMS

Linux

в пользовательском режиме (а часто и в режиме ядра) всех UNIX-подобных ОС, включая версии Mac OS X,
iPod OS и iPhone OS

в режиме ядра ОС Windows 3.x — только при исполнении на процессоре 386 или старше, «задачами» являются
только все Windows-приложения вместе взятые и каждая отдельная виртуальная машина ДОС, между
приложениями Windows вытесняющая многозадачность не использовалась

Windows 95/98/ME — без полноценной защиты памяти, что служило причиной крайне низкой, на одном уровне
с MS-DOS, Windows 3.xи Mac OS версий до X — надежности этих ОС

Windows NT/2000/XP/Vista/7 и в режиме ядра, и в пользовательском режиме.
61

AmigaOS — все версии, до версии 4.0 без полноценной защиты памяти, что на практике для системных
программ почти не сказывалось на надёжности из-за высокой стандартизированности, прозрачных API и SDK.
Программы ориентированные на «железо» Амиги, наоборот не отличались надёжностью.
Проблемные ситуации в многозадачных системах
Голодание (starvation)
Задержка времени от пробуждения потока до его вызова на процессор, в течение которой он находится в списке
потоков, готовых к исполнению. Возникает по причине присутствия потоков с большими или равными приоритетами,
которые исполняются все это время.
Негативный эффект заключается в том, что возникает задержка времени от пробуждения потока до исполнения им
следующей важной операции, что задерживает исполнение этой операции, а следом за ней и работу многих других
компонентов.
Голодание создаёт узкое место в системе и не дает выжать из нее максимальную производительность, ограничиваемую
только аппаратно обусловленными узкими местами.
Любое голодание вне 100 % загрузки процессора может быть устранено повышением приоритета голодающей нити,
возможно — временным.
Как правило, для предотвращения голодания ОС автоматически вызывает на исполнение готовые к нему
низкоприоритетные потоки даже при наличии высокоприоритетных, при условии, что поток не исполнялся в течение
долгого времени (~10 секунд).
Гонка (race condition)
Недетерминированный порядок исполнения двух путей кода, работающих с одними и теми же данными и
исполняемыми в двух различных нитях. Приводит к зависимости порядка и правильности исполнения от случайных
факторов.
Устраняется добавлением необходимых блокировок и примитивов синхронизации. Обычно является легко устраняемым
дефектом (забытая блокировка).
Инверсия приоритета
Поток L имеет низкий приоритет, поток M — средний, поток H — высокий. Поток L захватывает mutex, и, выполняясь с
удержанием mutex’а, преемптивно прерывается потоком M, который пробудился по какой-то причине, и имеет более
высокий приоритет. Поток H пытается захватить mutex.
В полученной ситуации поток H ожидает завершения текущей работы потоком M, ибо, пока поток M исполняется,
низкоприоритетный поток L не получает управления и не может освободить mutex.
Устраняется повышением приоритета всех нитей, захватывающих данный mutex, до одного и того же высокого значения
на период удержания mutexa. Некоторые реализации mutex’ов делают это автоматически.
Многопоточность
Многопото́чность — свойство платформы (например, операционной системы, JVM и т. д.) или приложения, состоящее
в том, чтопроцесс, порождённый в операционной системе, может состоять из нескольких потоков, выполняющихся
«параллельно», то есть без предписанного порядка во времени. При выполнении некоторых задач такое разделение
может достичь более эффективного использования ресурсов вычислительной машины.
Такие потоки называют также потоками выполнения (от англ. thread of execution); иногда называют «нитями»
(буквальный переводангл. thread) или неформально «тредами».
62
Сутью многопоточности является квазимногозадачность на уровне одного исполняемого процесса, то есть все потоки
выполняются вадресном пространстве процесса. Кроме этого, все потоки процесса имеют не только общее адресное
пространство, но и общие дескрипторы файлов. Выполняющийся процесс имеет как минимум один (главный) поток.
Многопоточность
(как
доктрину программирования)
не
следует
путать
ни
с многозадачностью,
ни
с
многопроцессорностью, несмотря на то, что операционные системы, реализующие многозадачность, как правило
реализуют и многопоточность.
К достоинствам многопоточности в программировании можно отнести следующее:

Упрощение программы в некоторых случаях, за счет использования общего адресного пространства.

Меньшие относительно процесса временны́е затраты на создание потока.

Повышение производительности процесса за счет распараллеливания процессорных вычислений и операций
ввода/вывода.
Типы реализации потоков

Поток в пространстве пользователя. Каждый процесс имеет таблицу потоков, аналогичную таблице процессов
ядра.
Достоинства и недостатки этого типа следующие:
Достоинства
1. Возможность реализации на ядре не поддерживающем многопоточность
2. Более быстрое переключение, создание и завершение потоков
3. Процесс может иметь собственный алгоритм планирования.
Недостатки
1. Отсутствие прерывания по таймеру внутри одного процесса
2. При использовании блокирующего системного запроса для процесса все его потоки блокируются.
3. Сложность реализации

Поток в пространстве ядра. Наряду с таблицей процессов в пространстве ядра имеется таблица потоков.

«Волокна» (fibers). Несколько потоков режима пользователя, исполняющихся в одном потоке режима ядра.
Поток пространства ядра потребляет заметные ресурсы, в первую очередь физическую память и диапазон
адресов режима ядра для стека режима ядра. Поэтому было введено понятие «волокна» — облегчённого
потока, выполняемого исключительно в режиме пользователя. У каждого потока может быть несколько
«волокон».
Взаимодействие потоков
В многопоточной среде часто возникают проблемы, связанные с использованием параллельно исполняемыми потоками
одних и тех же данных или устройств. Для решения подобных проблем используются такие методы взаимодействия
потоков, как взаимоисключения (мьютексы), семафоры, критические секции и события

Взаимоисключения (mutex, мьютекс) — это объект синхронизации, который устанавливается в особое
сигнальное состояние, когда не занят каким-либо потоком. Только один поток владеет этим объектом в любой
момент времени, отсюда и название таких объектов (от английского mutually exclusive access — взаимно
исключающий доступ) — одновременный доступ к общему ресурсу исключается. После всех необходимых
действий мьютекс освобождается, предоставляя другим потокам доступ к общему ресурсу.

Семафоры представляют собой доступные ресурсы, которые могут быть приобретены несколькими потоками в
одно и то же время, пока пул ресурсов не опустеет. Тогда дополнительные потоки должны ждать, пока
требуемое количество ресурсов не будет снова доступно. Семафоры очень эффективны, поскольку они
позволяют одновременный доступ к ресурсам.

События. Объект, хранящий в себе 1 бит информации «просигнализирован или нет», над которым определены
операции «просигнализировать», «сбросить в непросигнализированное состояние» и «ожидать». Ожидание на
просигнализированном событии есть отсутствие операции с немедленным продолжением исполнения потока.
63
Ожидание на непросигнализированном событии приводит к приостановке исполнения потока до тех пор, пока
другой поток (или же вторая фаза обработчика прерывания в ядре ОС) не просигнализирует событие.
Возможно ожидание нескольких событий в режимах «любого» или «всех». Возможно также создания события,
автоматически сбрасываемого в непросигнализированное состояние после пробуждения первого же — и
единственного — ожидающего потока (такой объект используется как основа для реализации объекта
«критическая секция»). Активно используются в MS Windows, как в режиме пользователя, так и в режиме ядра.

Критические секции обеспечивают синхронизацию подобно мьютексам за исключением того, что объекты,
представляющие критические секции, доступны в пределах одного процесса. События, мьютексы и семафоры
также можно использовать в однопроцессном приложении, однако реализации критических секций в
некоторых ОС (например Windows NT) обеспечивают более быстрый и более эффективный[1][2] механизм
взаимно-исключающей синхронизации — операции «получить» и «освободить» на критической секции
оптимизированы для случая единственного потока (отсутствия конкуренции) с целью избежать любых
ведущих в ядро ОС системных вызовов. Подобно мьютексам объект, представляющий критическую секцию,
может использоваться только одним потоком в данный момент времени, что делает их крайне полезными при
разграничении доступа к общим ресурсам.

Условные переменные (condvars). Сходны с событиями, но не являются объектами, занимающими память —
используется только адрес переменной, понятие «содержимое переменной» не существует, в качестве условной
переменной может использоваться адрес произвольного объекта. В отличие от событий, установка условной
переменной в просигнализированное состояние не влечет за собой никаких последствий в случае, если на
данный момент нет потоков, ожидающих на переменной. Установка события в аналогичном случае влечет за
собой запоминание состояния «просигнализировано» внутри самого события, после чего следующие потоки,
желающие ожидать события, продолжают исполнение немедленно без остановки. Для полноценного
использования такого объекта необходима также операция «освободить mutex и ожидать условную
переменную атомарно». Активно используются в UNIX-подобных ОС. Дискуссии о преимуществах и
недостатках событий и условных переменных являются заметной частью дискуссий о преимуществах и
недостатках Windows и UNIX.

Порт завершения ввода-вывода (IO completion port, IOCP). Реализованный в ядре ОС и доступный через
системные вызовы объект «очередь» с операциями «поместить структуру в хвост очереди» и «взять
следующую структуру с головы очереди» — последний вызов приостанавливает исполнение потока в случае,
если очередь пуста, и до тех пор, пока другой поток не осуществит вызов «поместить». Главнейшей
особенностью IOCP является то, что структуры в него могут помещаться не только явным системным вызовом
из режима пользователя, но и неявно внутри ядра ОС как результат завершения асинхронной операции вводавывода на одной из дескрипторов файлов. Для достижения такого эффекта необходимо использовать
системный вызов «связать дескриптор файла с IOCP». В этом случае помещенная в очередь структура
содержит в себе код ошибки операции ввода-вывода, а также, для случая успеха этой операции — число
реально введенных или выведенных байт. Реализация порта завершения также ограничивает число потоков,
исполняющихся на одном процессоре/ядре после получения структуры из очереди. Объект специфичен для MS
Windows, и позволяет обработку входящих запросов соединения и порций данных в серверном программном
обеспечении в архитектуре, где число потоков может быть меньше числа клиентов (нет требования создавать
отдельный поток с расходами ресурсов на него для каждого нового клиента).
Однозадачность
Известно, что в каждый момент времени один процессор может выполнять лишь одну машинную команду.
Процессор выполняет команды, последовательно выбирая их одну за другой из памяти в порядке возрастания адресов.
Программист может нарушить этот порядок, вставив в программу команду условного или безусловного перехода,
команду вызова функции или цикла (bne, call, jmp, loop). Операционная система, даже однозадачная, также может
вмешаться в эту последовательность и отвлечься — временно оторваться от последовательности команд для
выполнения каких-то других более важных, системных команд. Необходимость такой операции, называемой
прерыванием, выясняется в процессе выборки очередной команды. Если система обнаруживает, что есть прерывание, то
64
она запоминает в стеке контекст выполняемой программы: адрес текущей команды, ' содержимое регистров АУ, и
переходит в режим обработки прерывания, то есть переключается на выполнение другой программы, вызвавшей
прерывание. В системе команд существуют также особые, привилегированные инструкции, которые невозможно
прервать. Они называются atomic instructions, (вы помните, что атом переводится как неделимый) и используются
системой при выполнении критических для целостности системы процедур.
В оперативной памяти (RAM), даже в случае однозадачной ОС (операционная система), могут одновременно
находиться несколько программ:



резидентная часть операционной системы; %
резидентные программы, которые запускает система или пользователь;
прикладная программа, выполняемая в данный момент.
В простейшем случае однозадачной ОС, такой как MS DOS, взаимодействие между тремя объектами,
увязываемыми ОС, может протекать так, как показано на рис. 12.1.
Рис. 12.1. Диаграмма взаимодействия ОС с прикладной программой
Системный модуль, который подготавливает запуск прикладной программы, с тем чтобы вернуть управление
обратно после ее завершения, называется program prefix segment. Он, так же как и модуль завершения программы
пользователя, занимает определенное время и другие ресурсы системы. Если в процессе выполнения пользовательской
прбграмме нужно выполнить какое-либо стандартное действие, например вывести строку символов на принтер, она
может обратиться к стандартной подпрограмме, входящей в состав операционной системы. Такие стандартные
действия, реализованные в ОС в виде отдельных процедур, принято называть системными сервисами. Обратите
внимание на тот факт, что прикладная программа сама определяет момент предоставления ей системного сервиса.
Программа при завершении, как вы знаете, может вернуть системе некий код (успех или неудача). Как программа может
узнать о наступлении какого-либо события, внешнего по отношению к ней, например такого, как нажатие
пользователем клавиши клавиатуры? Существуют два способа: по опросу готовности и с помощью механизма
аппаратных прерываний. Клавиатура является устройством, о котором можно программно, анализируя содержимое
программно-доступного регистра состояния клавиатуры, узнать, готово ли оно к обмену, то есть нажата ли клавиша.
Алгоритм процедуры обмена, соответствующий первому способу, изображен на рис. 12.2. Он обладает тем недостатком,
65
что при ожидании процессор используется неэффективно, то есть простаивает. Второй способ иллюстрируется рис.
12.3.
В результате какого-либо события: нажатия клавиши клавиатуры, движения мыши, срабатывания таймера,
вырабатывается сигнал. По этому сигналу процессор прерывает выполнение текущей программы, запоминает состояние
(контекст) прерванной программы и передает управление программе-обработчику возникшей ситуации.
Рис. 12.2. Алгоритм опроса готовности
Рис. 12.3. Алгоритм обработки аппаратного прерывания
66
Аппаратные прерывания могут возникать в произвольные моменты времени, и они прозрачны для прикладной
программы, то есть она не знает, что была прервана в ответ на какое-то событие. Почему необходимо запоминать
контекст прерванной программы и не нужно этого делать при вызове внешней функции? В последнем случае контекст
не нарушается, так как программист проектирует вызов функции и сам управляет последовательностью действий,
например передачей аргументов. В случае прерывания контекст выполняемой программы нарушается и уже сама
система должна сделать все, чтобы восстановить текущее состояние прерванной программы, так как прерывание не
было запланировано — не входило в намерения программиста. Теперь рассмотрим, как в случае прерывания прикладная
программа узнает о том, что была нажата клавиша и какая (рис. 12.4).
Рис. 12.4. Диаграмма асинхронного взаимодействия
Обработчик аппаратного прерывания от клавиатуры преобразует код нажатия клавиши в код, понятный прикладной
программе (ASCII), и помещает его в буфер. Прикладная программа не реагирует на нажатие клавиши и не замечает
вызова обработчика, но когда у нее возникает желание выяснить, нажимал ли пользователь какие-нибудь клавиши, она
вызывает системную функцию. Последняя анализирует буфер и, если он не пуст, возвращает код нажатой клавиши или
признак того, что буфер пуст.
25. Параллельные взаимодействующие процессы. Основные понятия и модели.
Каждая параллельная программа содержит несколько процессов, совместно работающих над решением некоторой
задачи
Каждая программа - это совокупность последовательных ВП, которые выполняются параллельно.
Последовательный ВП => Существует 1 поток управления
Параллельный поток => Существует несколько потоков управления
Организация взаимодействия ВП
1)Посылка сообщений между ВП;
2)Применение разделяемых переменных (переменная, которая используется несколькими процессами по очереди)
67
Синхронизация ВП
Взаимные исключения (критические секции, которые не выполняются одновременно)
Условная синхронизация (задержка выполнения процесса) до наступления определённого условия
Классы параллельного программирования
многопоточные ВС – содержат ВП больше, чем ЦП => выполняются по очереди (здесь используются разделяемые
переменные)
Распределенные ВС – ВП выполняются на процессорах, объединенных в сеть (обмен сообщениями или удаленный
вызов)
Синхронные параллельные вычисления ЦП-ами=> ВП ( ВП выполняется на нескольких ЦП)
Существует параллелизм по данным (отдельная ВС решает разные задачи) и по задачам (все ВС решают одну и ту же
задачу)
Существует 5 парадигм параллельного программирования
Интерактивный параллелизм (циклические процессы)
Рекурсивный параллелизм (независимые рекурсивные вызовы процедур)
Конвейеры (выход одного ВП является входом другого)
Клиент-сервер
Взаимодействующие равные (работа над 1 задачей)
Также смотри 24ый вопрос
26.
Оверлейная структура программ: дерево и язык оверлея, управление оверлеем и таблицы, определение
минимального раздела памяти для выполнения оверлейной программы.
Оверлей - это такой способ использования оперативной памяти, при котором в один и тот же участок памяти,
называемый оверлейным буфером, попеременно по мере надобности загружаются различные оверлейные
(перекрывающиеся) модули. При этом все оверлейные модули в готовом к работе виде хранятся на диске, а в
оперативной памяти в каждый момент находится лишь один активный модуль и, возможно, небольшое число
неактивных.
Пусть, например, программа (рис. 11.1) состоит из главной части MAIN и двух модулей А к В, a LM, LA и LB соответственно длина главной части и обоих модулей, причем LA > LB. Тогда неоверлейная программа займет в памяти
LM + LA + LB байт, в то время как- оверлейная программа - лишь LM + LA байт.
При исполнении оверлейной программы в память первоначально загружается главная часть и один из модулей,
например, модуль А. Если в процессе исполнения программы встретится обращение к модулю В, программа
приостановит свою работу, с диска в оверлейный буфер будет загружен модуль В (модуль А при этом частично
уничтожается), после чего программа продолжит свою работу. Если в дальнейшем встретится обращение к А, точно
таким же образом будет загружен модуль А, причем загрузка нужных модулей в оверлейный буфер осуществляется
автоматически и программисту не нужно об этом заботиться.
27.
Puc.11.1. Пример структуры программы: а) неоверлейная; 6) оверлейная
Описанный механизм выявляет главное преимущество оверлейной структуры: объем оперативной памяти, занимаемой
оверлейной программой, определяется длиной ее главной части и наибольшего из перекрывающихся модулей, в то
время как при неоверлейной структуре в этот объем входит суммарная длина всех модулей. Чем больше в программе
оверлейных модулей и чем меньше длина наибольшего из них, тем больший выигрыш в памяти дает оверлейная
структура. Однако совершенно очевиден и главный недостаток таких структур: на каждую-загрузку оверлейного модуля
с диска в оверлейный буфер требуется дополнительное время, поэтому оверлейная программа будет исполняться с
меньшей скоростью.
Администратор оверлеев (или подсистема управления оверлеями)
68
Borland Pascal реализуется с помощью стандартного модуля Overlay. В модуле Overlay используются
усовершенствованные методы управления буферами, что обеспечивает оптимальное выполнение программы в
имеющейся области памяти. Например, подсистема управления оверлеями сохраняет в оверлейном буфере столько
оверлеев, сколько возможно. Это позволяет уменьшить частоту считывания оверлеев с диска. После загрузки оверлея
вызов одной из его подпрограмм выполняется также быстро, как обращение к неоверлейной программе. Кроме того,
когда у администратора оверлеев возникает необходимость вывести один оверлей, чтобы освободить место для другого,
он сначала пытается вывести те оверлеи, которые не являются активными (то есть те, которые в данный момент
времени не содержат активных программ).
Для реализации улучшенных методов управления оверлеями Borland Pascal требует от вас при написании программы, в
которой используются оверлеи, соблюдать два важных правила:
1. Все оверлейные модули должны содержать директиву {$O+}, приводящую к тому, что компилятор обеспечивает
генерирование оверлейного кода.
2. При каждом обращении к оверлейной процедуре или функции вы должны обеспечить использование всеми
активными процедурами и функциями вызовов типа FAR (дальний тип вызова).
Отметим, что вы можете легко удовлетворить эти правила, поместив в начале оверлейных модулей директиву
компилятора {$O+,F+}, а в начале всех других модулей и основной программы - директиву {$F+}.
27. Как организовать в многозадачной ОС контроль лимита времени центрального процессора, выделяемого
прикладным процессам?
Планировщик - это программа, ответственная за постановку процессов в очередь-на-выполнение и управляющая этой
очередью.
Диспетчер - это программа, которая выбирает процессы из очереди-на-выполнение, переводит их в активное состояние
и передает им контроль над CPU.
Основная функция - возможность управлять действиями большого числа процессов.
Алгоритмы планирования процессов
Планирование процессов включает в себя решение следующих задач:
определение момента времени для смены выполняемого процесса;
выбор процесса на выполнение из очереди готовых процессов;
переключение контекстов "старого" и "нового" процессов.
Первые две задачи решаются программными средствами, а последняя в значительной степени аппаратно. Существует
множество различных алгоритмов планирования процессов, по разному решающих вышеперечисленные задачи,
преследующих различные цели и обеспечивающих различное качество мультипрограммирования. Среди этого
множества алгоритмов рассмотрим подробнее две группы наиболее часто встречающихся алгоритмов: алгоритмы,
основанные на квантовании, и алгоритмы, основанные на приоритетах.
В соответствии с алгоритмами, основанными на квантовании, смена активного процесса происходит, если:
процесс завершился и покинул систему,
произошла ошибка,
процесс перешел в состояние ОЖИДАНИЕ,
исчерпан квант процессорного времени, отведенный данному процессу.
Процесс, который исчерпал свой квант, переводится в состояние ГОТОВНОСТЬ и ожидает, когда ему будет
предоставлен новый квант процессорного времени, а на выполнение в соответствии с определенным правилом
выбирается новый процесс из очереди готовых. Таким образом, ни один процесс не занимает процессор надолго,
поэтому квантование широко используется в системах разделения времени. Граф состояний процесса, изображенный на
рисунке 2.1, соответствует алгоритму планирования, основанному на квантовании. Кванты, выделяемые процессам,
могут быть одинаковыми для всех процессов или различными. Кванты, выделяемые одному процессу, могут быть
фиксированной величины или изменяться в разные периоды жизни процесса. Процессы, которые не полностью
использовали выделенный им квант (например, из-за ухода на выполнение операций ввода-вывода), могут получить или
не получить компенсацию в виде привилегий при последующем обслуживании. По разному может быть организована
очередь готовых процессов: циклически, по правилу "первый пришел - первый обслужился" (FIFO) или по правилу
"последний пришел - первый обслужился" (LIFO). Другая группа алгоритмов использует понятие "приоритет" процесса.
Приоритет - это число, характеризующее степень привилегированности процесса при использовании ресурсов
вычислительной машины, в частности, процессорного времени: чем выше приоритет, тем выше привилегии. Приоритет
может выражаться целыми или дробными, положительным или отрицательным значением. Чем выше привилегии
процесса, тем меньше времени он будет проводить в очередях. Приоритет может назначаться директивно
администратором системы в зависимости от важности работы или внесенной платы, либо вычисляться самой ОС по
определенным правилам, он может оставаться фиксированным на протяжении всей жизни процесса либо изменяться во
времени в соответствии с некоторым законом. В последнем случае приоритеты называются динамическими. Существует
69
две разновидности приоритетных алгоритмов: алгоритмы, использующие относительные приоритеты, и алгоритмы,
использующие абсолютные приоритеты. В обоих случаях выбор процесса на выполнение из очереди готовых
осуществляется одинаково: выбирается процесс, имеющий наивысший приоритет. По разному решается проблема
определения момента смены активного процесса. В системах с относительными приоритетами активный процесс
выполняется до тех пор, пока он сам не покинет процессор, перейдя в состояние ОЖИДАНИЕ (или же произойдет
ошибка, или процесс завершится). В системах с абсолютными приоритетами выполнение активного процесса
прерывается еще при одном условии: если в очереди готовых процессов появился процесс, приоритет которого выше
приоритета активного процесса. В этом случае прерванный процесс переходит в состояние готовности. На рисунке 2
показаны графы состояний процесса для алгоритмов с относительными (а) и абсолютными (б) приоритетами.
а)
б)
Рис.1. Граф состояний процесса в многозадачной среде
(а) с относительными приоритетами; (б)с абсолютными приоритетами
Во многих операционных системах алгоритмы планирования построены с использованием как квантования, так и
приоритетов. Например, в основе планирования лежит квантование, но величина кванта и/или порядок выбора процесса
из очереди готовых определяется приоритетами процессов.
Вытесняющие и невытесняющие алгоритмы планирования
Существует два основных типа процедур планирования процессов - вытесняющие (preemptive) и невытесняющие (nonpreemptive).
Non-preemptive multitasking - невытесняющая многозадачность - это способ планирования процессов, при котором
активный процесс выполняется до тех пор, пока он сам, по собственной инициативе, не отдаст управление
планировщику операционной системы для того, чтобы тот выбрал из очереди другой, готовый к выполнению процесс.
70
Preemptive multitasking - вытесняющая многозадачность - это такой способ, при котором решение о переключении
процессора с выполнения одного процесса на выполнение другого процесса принимается планировщиком операционной
системы, а не самой активной задачей.
Вытесняющая и невытесняющая многозадачность - это более широкие понятия, чем типы приоритетности. Приоритеты
задач могут как использоваться, так и не использоваться и при вытесняющих, и при невытесняющих способах
планирования. Так в случае использования приоритетов дисциплина относительных приоритетов может быть отнесена к
классу систем с невытесняющей многозадачностью, а дисциплина абсолютных приоритетов - к классу систем с
вытесняющей многозадачностью. А бесприоритетная дисциплина планирования, основанная на выделении равных
квантов времени для всех задач, относится к вытесняющим алгоритмам. Основным различием между preemptive и nonpreemptive вариантами многозадачности является степень централизации механизма планирования задач. При
вытесняющей многозадачности механизм планирования задач целиком сосредоточен в операционной системе, и
программист пишет свое приложение, не заботясь о том, что оно будет выполняться параллельно с другими задачами.
При этом операционная система выполняет следующие функции: определяет момент снятия с выполнения активной
задачи, запоминает ее контекст, выбирает из очереди готовых задач следующую и запускает ее на выполнение, загружая
ее контекст. При невытесняющей многозадачности механизм планирования распределен между системой и
прикладными программами. Прикладная программа, получив управление от операционной системы, сама определяет
момент завершения своей очередной итерации и передает управление ОС с помощью какого-либо системного вызова, а
ОС формирует очереди задач и выбирает в соответствии с некоторым алгоритмом (например, с учетом приоритетов)
следующую задачу на выполнение. Такой механизм создает проблемы как для пользователей, так и для разработчиков.
Для пользователей это означает, что управление системой теряется на произвольный период времени, который
определяется приложением (а не пользователем). Если приложение тратит слишком много времени на выполнение
какой-либо работы, например, на форматирование диска, пользователь не может переключиться с этой задачи на другую
задачу, например, на текстовый редактор, в то время как форматирование продолжалось бы в фоновом режиме. Эта
ситуация нежелательна, так как пользователи обычно не хотят долго ждать, когда машина завершит свою задачу.
Поэтому разработчики приложений для non-preemptive операционной среды, возлагая на себя функции планировщика,
должны создавать приложения так, чтобы они выполняли свои задачи небольшими частями. Например, программа
форматирования может отформатировать одну дорожку дискеты и вернуть управление системе. После выполнения
других задач система возвратит управление программе форматирования, чтобы та отформатировала следующую
дорожку. Подобный метод разделения времени между задачами работает, но он существенно затрудняет разработку
программ и предъявляет повышенные требования к квалификации программиста. Программист должен обеспечить
"дружественное" отношение своей программы к другим выполняемым одновременно с ней программам, достаточно
часто отдавая им управление. Крайним проявлением "недружественности" приложения является его зависание, которое
приводит к общему краху системы. В системах с вытесняющей многозадачностью такие ситуации, как правило,
исключены, так как центральный планирующий механизм снимет зависшую задачу с выполнения. Однако
распределение функций планировщика между системой и приложениями не всегда является недостатком, а при
определенных условиях может быть и преимуществом, потому что дает возможность разработчику приложений самому
проектировать алгоритм планирования, наиболее подходящий для данного фиксированного набора задач. Так как
разработчик сам определяет в программе момент времени отдачи управления, то при этом исключаются
нерациональные прерывания программ в "неудобные" для них моменты времени. Кроме того, легко разрешаются
проблемы совместного использования данных: задача во время каждой итерации использует их монопольно и уверена,
что на протяжении этого периода никто другой не изменит эти данные. Существенным преимуществом non-preemptive
систем является более высокая скорость переключения с задачи на задачу. Примером эффективного использования
невытесняющей многозадачности является файл-сервер NetWare, в котором, в значительной степени благодаря этому,
достигнута высокая скорость выполнения файловых операций. Менее удачным оказалось использование
невытесняющей многозадачности в операционной среде Windows 3.х.
Однако почти во всех современных операционных системах, ориентированных на высокопроизводительное выполнение
приложений (UNIX, Windows NT, OS/2, VAX/VMS), реализована вытесняющая многозадачность. В последнее время
дошла очередь и до ОС класса настольных систем, например, OS/2 Warp и Windows 95. Возможно в связи с этим
вытесняющую многозадачность часто называют истинной многозадачностью.
28. Задача распределения ресурсов в ОС. Взаимная блокировка процессов, ее идентификация и способы защиты
от нее.
Важнейшей частью операционной системы, является подсистема управления процессами. Процесс - абстракция,
описывающая выполняющуюся программу. Для операционной системы процесс представляет собой единицу работы,
заявку на потребление системных ресурсов. Подсистема управления процессами распределяет процессорное время
между процессами, а также создает и уничтожает процессы, обеспечивает процессы необходимыми системными
ресурсами, поддерживает взаимодействие между процессами.
71
В многозадачной (многопроцессной) системе процесс может находиться в одном из трех основных состояний:
ВЫПОЛНЕНИЕ – процесс выполняется процессором, обладает всеми необходимыми ресурсами.
ОЖИДАНИЕ – процесс заблокирован, он не может выполняться т.к. он ждет осуществления некоторого события,
например, завершения некоторой операции или ожидает освобождения ресурса;
ГОТОВНОСТЬ - процесс заблокирован т.к. процессор занят выполнением другого процесса.
В ходе жизненного цикла каждый процесс переходит из одного состояния в другое в соответствии с алгоритмом
планирования процессов, реализуемым в данной операционной системе.
Планировщик - это программа, ответственная за постановку процессов в очередь-на-выполнение и управляющая этой
очередью.
Диспетчер - это программа, которая выбирает процессы из очереди-на-выполнение, переводит их в активное состояние
и передает им контроль над CPU.
Основная функция - возможность управлять действиями большого числа процессов.
Процессам часто нужно взаимодействовать друг с другом, например, один процесс может передавать данные другому
процессу, или несколько процессов могут обрабатывать данные из общего файла. Во всех этих случаях возникает
проблема синхронизации процессов, которая может решаться приостановкой и активизацией процессов, организацией
очередей, блокированием и освобождением ресурсов.
Рис. 9. Пример необходимости синхронизации
В режиме мультипрограммирования недоработки в вопросе синхронизации процессов приводит к неправильной работе
или даже к краху системы.
Часть программы, в которой осуществляется доступ к разделяемым данным, называется «критическая секция». Для
исключения эффекта гонок по отношению к некоторому ресурсу, необходимо обеспечить, чтобы в каждый момент в
критической секции, связанной с этим ресурсом, находился максимум один процесс. Этот прием называют взаимным
исключением. Простейший способ обеспечить взаимное исключение - позволить процессу, находящемуся в
критической секции, запрещать все прерывания. Однако этот способ непригоден, так как опасно доверять управление
системой пользовательскому процессу; он может надолго занять процессор, а при крахе процесса в критической области
крах потерпит вся система, потому что прерывания никогда не будут разрешены.
Другой способ - использование блокирующих переменных. С каждым разделяемым ресурсом связывается двоичная
переменная, которая принимает значение 1, если ресурс свободен (то есть ни один процесс не находится в данный
момент в критической секции, связанной с данным процессом), и значение 0, если ресурс занят. На рисунке 10 показан
фрагмент алгоритма процесса, использующего для реализации взаимного исключения доступа к разделяемому ресурсу
D блокирующую переменную F(D). Перед входом в критическую секцию процесс проверяет, свободен ли ресурс D.
Если он занят, то проверка циклически повторяется, если свободен, то значение переменной F(D) устанавливается в 0, и
процесс входит в критическую секцию. После того, как процесс выполнит все действия с разделяемым ресурсом D,
значение переменной F(D) снова устанавливается равным 1. Операция проверки и установки блокирующей переменной
должна быть неделимой.
72
Недостаток использования блокирующих переменных: в
течение времени, когда один процесс находится в критической
секции, другой процесс, которому требуется тот же ресурс,
будет выполнять рутинные действия по опросу блокирующей
переменной, бесполезно тратя процессорное время.
Для устранения активного ожидания процесса CPU может быть
использован так называемый аппарат событий, решающий
проблемы взаимного исключения и решающий задачи
синхронизации процессов. В разных операционных системах
аппарат событий реализуется по-разному, но всегда
используются системные функции, которые назовем WAIT(x) и
POST(x), где x - идентификатор некоторого события. На
рисунке 12 показан фрагмент алгоритма процесса,
использующего эти функции. Если ресурс занят, процесс не
выполняет циклический опрос, а вызывает системную
функцию WAIT(D), здесь D обозначает событие,
заключающееся в освобождении ресурса D.
Функция WAIT(D) переводит активный процесс в состояние
ОЖИДАНИЕ и делает отметку в его дескрипторе о том, что
процесс ожидает события D. Процесс, который в это время
использует ресурс D, после выхода из критической секции выполняет системную функцию POST(D), в результате чего
операционная система просматривает очередь ожидающих процессов и переводит процесс, ожидающий события D, в
состояние ГОТОВНОСТЬ.
Обобщающее средство синхронизации процессов предложил Дейкстра, который ввел два новых примитива. В
абстрактной форме эти примитивы, обозначаемые P и V, оперируют над целыми неотрицательными переменными,
называемыми семафорами. Пусть S такой семафор. Операции определяются следующим образом:
V(S) : переменная S увеличивается на 1 одним неделимым действием; выборка, инкремент и запоминание не могут быть
прерваны, и к S нет доступа другим процессам во время этой операции.
P(S) : уменьшение S на 1, если это возможно. Если S=0, то невозможно уменьшить S и остаться в области целых
неотрицательных значений, в этом случае процесс, вызывающий P-операцию, ждет, пока это уменьшение станет
возможным. Успешная проверка и уменьшение также является неделимой операцией.
WAIT(D) и POST(D)
В частном случае, когда семафор S может принимать только значения 0 и 1, он превращается в блокирующую
переменную. Операция P заключает в себе
потенциальную возможность перехода процесса, который
ее выполняет, в состояние ожидания, в то время как Vоперация может при некоторых обстоятельствах
активизировать другой процесс, приостановленный
операцией P (сравните эти операции с системными
функциями WAIT и POST).
Рассмотрим еще один пример тупика. Пусть двум
процессам, выполняющимся в режиме
мультипрограммирования, для выполнения их работы
нужно два ресурса, например, принтер и диск. На
рисунке 18(а) показаны фрагменты соответствующих
программ. И пусть после того, как процесс А занял
принтер (установил блокирующую переменную), он был
прерван. Управление получил процесс В, который
сначала занял диск, но при выполнении следующей
команды был заблокирован, так как принтер оказался уже
занятым процессом А. Управление снова получил
процесс А, который в соответствии со своей программой
сделал попытку занять диск и был заблокирован: диск
уже распределен процессу В. В таком положении
процессы А и В могут находиться сколь угодно долго. В
зависимости от соотношения скоростей процессов, они
могут либо совершенно независимо использовать
разделяемые ресурсы (г), либо образовывать очереди к
73
разделяемым ресурсам (в), либо взаимно блокировать друг друга (б). Тупиковые ситуации надо отличать от простых
очередей, хотя и те и другие возникают при совместном использовании ресурсов и внешне выглядят похоже: процесс
приостанавливается и ждет освобождения ресурса. Однако очередь - это нормальное явление, неотъемлемый признак
высокого коэффициента использования ресурсов при случайном поступлении запросов. Она возникает тогда, когда
ресурс недоступен в данный момент, но через некоторое время он освобождается, и процесс продолжает свое
выполнение. Тупик же, что видно из его названия, является в некотором роде неразрешимой ситуацией.
В рассмотренных примерах тупик был образован двумя процессами, но взаимно блокировать друг друга могут и
большее число процессов.
Рис. 18. (a) фрагменты программ А и В, разделяющих принтер и диск; (б) взаимная блокировка (клинч);
(в) очередь к разделяемому диску; (г) независимое использование ресурсов
Необходимые условия возникновения тупиковых ситуаций.
Процессы требуют предоставления им права монопольного управления ресурсами, которые им предоставляются
(условие взаимоисключения).
Процессы удерживают за собой ресурсы, выделенные им, в то же время ожидают выделения дополнительных ресурсов
(условие ожидания ресурсов).
Ресурсы нельзя отобрать у процесса, удерживающего их, пока эти ресурсы не будут использованы для завершения
работы (условия неперераспределенности).
Проблема тупиков включает в себя следующие задачи: предотвращение тупиков, распознавание тупиков,
восстановление системы после тупиков.
Тупики могут быть предотвращены на стадии написания программ, то есть программы должны быть написаны таким
образом, чтобы тупик не мог возникнуть ни при каком соотношении взаимных скоростей процессов. Так, если бы в
предыдущем примере процесс А и процесс В запрашивали ресурсы в одинаковой последовательности, то тупик был бы
в принципе невозможен. Второй подход к предотвращению тупиков называется динамическим и заключается в
использовании определенных правил при назначении ресурсов процессам, например, ресурсы могут выделяться в
определенной последовательности, общей для всех процессов. В некоторых случаях, когда тупиковая ситуация
образована многими процессами, использующими много ресурсов, распознавание тупика является нетривиальной
задачей. Существуют формальные, программно-реализованные методы распознавания тупиков, основанные на ведении
таблиц распределения ресурсов и таблиц запросов к занятым ресурсам. Анализ этих таблиц позволяет обнаружить
взаимные блокировки. Если же тупиковая ситуация возникла, то не обязательно снимать с выполнения все
заблокированные процессы.
Можно снять только часть из них, при этом освобождаются ресурсы, ожидаемые остальными процессами, можно
вернуть некоторые процессы в область свопинга, можно совершить "откат" некоторых процессов до так называемой
контрольной точки, в которой запоминается вся информация, необходимая для восстановления выполнения программы
с данного места. Контрольные точки расставляются в программе в местах, после которых возможно возникновение
тупика.
Управление памятью
Память является важнейшим ресурсом, требующим тщательного управления со стороны мультипрограммной
операционной системы. Распределению подлежит вся оперативная память, не занятая операционной системой. Обычно
ОС располагается в самых младших адресах, однако может занимать и самые старшие адреса. Функциями ОС по
управлению памятью являются: отслеживание свободной и занятой памяти, выделение памяти процессам и
освобождение памяти при завершении процессов, вытеснение процессов из оперативной памяти на диск, когда размеры
основной памяти не достаточны для размещения в ней всех процессов, и возвращение их в оперативную память, когда в
ней освобождается место, а также настройка адресов программы на конкретную область физической памяти.
29. Защита данных в вычислительных системах: аппаратные и программные методы. Слабые места систем
защиты. Задачи защиты от канальных программ периферийных устройств.
Под аппаратными средствами защиты понимаются специальные средств, непосредственно входящие в состав
технического обеспечения ИВС и выполняющие функции защиты как самостоятельно, так и в комплексе с другими
средствами.
Аппаратные средства защиты данных можно условно разбить на группы согласно типам аппаратуры, в которых они
используются: средства защиты процессора, памяти, терминалов, устройств ввода-вывода, каналов связи. Кратко
рассмотрим содержание средств защиты перечисленных групп аппаратуры.
Процессоры. Одним из главных условий обеспечения безопасности обрабатываемых данных является невозможность
одной программы влиять на процесс выполнения другой программы и особенно на выполнение программ ОС. Обычно
это реализуется введением так называемого привилегированного состояния процессора (в некоторых системах - режима
супервизора), характеризуемого специальными привилегированными командами. Попытки выполнить эти команды,
которые используются для управления процессом обработки заданий и для выполнения отдельных функций защиты, в
74
состоянии "задача пользователя" вызывают прерывание, обрабатываемое ОС. Для выполнения функций защиты в состав
процессора включаются программно-читаемые идентификаторы процессора и других технических устройств,
специальные биты секретности, средства контроля регистров, устанавливающих границы памяти и т.д.
Память. Многие ЭВМ и устройства, входящие в состав ИВС, содержат различные механизмы защиты памяти для
предотвращения чтения и модификации данных различными пользователями. Для защиты памяти обычно используются
следующие средства и механизмы:
*
регистры границ памяти, устанавливающие нижний и верхний адреса оперативной памяти для программы,
выполняемой в данный момент времени;
*
"замки" защиты блоков памяти фиксированного размера в ОП. Выполняемая программа заносит свой ключ в
специальный регистр. Каждая выборка и запись в ОП контролируется аппаратными средствами на подтверждение того,
что ключ соответствует замку;
*
сегментация памяти, представляющая использование дескрипторов для описания единиц данных в
оперативной памяти. Каждый дескриптор содержит начальный адрес сегмента, его длину и указатели, определяющие
вид доступа к его данным;
*
страничная организация памяти, в которой каждой программе пользователя ставится в соответствие таблица
страниц, отображающая виртуальные адреса в физические. Обычно защита страничной организации памяти реализуется
через сегментацию;
*
иерархические кольца безопасности, которые обеспечивают аппаратную изоляцию данных и программ,
относящихся к различным кольцам.
Терминалы обычно содержат замки для предотвращения несанкционированного включения, а также блокираторы,
которые могут содержать устройства установления подлинности пользователя по жетону, отпечаткам пальцев и т.п. Для
систем с высокими требованиями к обеспечению безопасности данных терминалы снабжаются встроенными схемами
шифрования данных, идентификация терминала и т.д.
Устройства ввода-вывода для решения задач защиты могут содержать:
*
регистры адресов и идентификаторов;
*
регистры границ выделенной устройству памяти, схемы проверки канала ввода-вывода;
*
регистры контроля уровня секретности канала связи;
*
схемы контроля номера канала и т.п.
Аппаратные средства защиты включают и вспомогательные устройства, которые обеспечивают функционирование
СОБД. Такими устройствами являются, например, устройства уничтожения информации на магнитных носителях,
устройства сигнализации и нарушении регистров границ памяти и т.п.
Программные средства защиты
Программными называются средства защиты данных, функционирующие в составе программного обеспечения средств
и механизмов защиты данных. Они выполняют функции защиты данных самостоятельно или в комплексе с другими
средствами защиты.
Классификация программных средств защиты по функциональному назначению приведена на рисунке.
Программные средства внешней защиты включают программные средств обеспечения функционирования физических
средств, защиты территории, помещений, отдельных каналов связи и устройств ИВС. В настоящее время выпускается
множество систем охранной сигнализации, содержащих микропроцессоры и ЭВМ. Программные средства используются
75
также в устройствах в устройствах опознания личности по различным характеристикам, таким, как голос, отпечатки
пальцев и т.д.
Программные средства внутренней защиты охватывают совокупность средств и механизмов защиты данных,
находящихся в аппаратуре ИВС. Их основным назначением является регулирование и контроль использования данных и
ресурсов системы в строгом соответствии с установленными правами доступа.
Типичная схема функционирования этих программных средств включает следующие основные этапы:
*
установление подлинности субъекта, обращающегося к ресурсам системы
*
проверка соответствия характера запроса предоставленным полномочиям данного субъекта;
*
принятие решения в соответствии с результатом проверки полномочий.
Программные средства управления защитой выполняют три основных класса задач:
*
задачи управления абонентами сети (регистрация абонентов, генерация служебной информации для абонентов,
рассылка служебной информации абонентам);
*
задачи управления СОБД (распределение ресурсов защиты, координация работы элементов и подсистем
СОБД);
*
задачи принятия решений в нештатных ситуациях (система поддержки принятия решения администратором
СОБД, выработка управляющих воздействий для компенсации нарушения функционирования СОБД).
Программные средства обеспечения функционирования СОБД включают средства, выполняющие функции контроля,
регистрации, уничтожения, сигнализации и имитации.
Средства контроля осуществляют тестирование элементов СОБД, а также постоянный сбор информации о
функционировании элементов СОБД. Эта информация служит исходными данными для средств поддержки принятия
решения и выработке управляющих воздействий.
Средства регистрации обеспечивают сбор, хранение, обработку и выдачу данных о состоянии СОБД.
Средства уничтожения предназначены для уничтожения остаточных данных и могут предусматривать аварийное
уничтожение данных в случае прямой угрозы НСД, которая не может быть блокирована системой.
Средства сигнализации предназначены для предупреждения пользователей при их обращении к защищенным данным
и для предупреждения администратора СОБД при обнаружении факта НСД к данным, искажения программных средств
защиты, выходе или выводе из строя аппаратных средств защиты и т.п.
Средства имитации имитируют работу с нарушителями при обнаружении попытки НСД к защищаемым данным.
Имитация позволяет увеличить время на определение места и характера НСД, что особенно важно в территориально
распределенных сетях, и "увести" нарушителя в сторону от защищаемых данных.
Основным методом защиты данных, передаваемых по каналам связи, является криптографическое закрытие данных,
которое реализуется программными, аппаратными и программно-аппаратными средствами. Кроме этого, используются
следующие программные средства:
*
опознание корреспондентов;
*
проверка уровня секретности канала;
*
проверка адресов корреспондентов;
*
проверка идентификаторов корреспондентов во время обмена большими объемами данных и т.д.
30.
Как ОС может определить, что произошла взаимная блокировка процессов? Как выйти из этой
ситуации, можно ли ее предотвратить?
Тупики могут быть предотвращены на стадии написания программ, то есть программы должны быть написаны
таким образом, чтобы тупик не мог возникнуть ни при каком соотношении взаимных скоростей процессов.
Второй подход к предотвращению тупиков называется динамическим и заключается в использовании
определенных правил при назначении ресурсов процессам, например, ресурсы могут выделяться в определенной
последовательности, общей для всех процессов.
В некоторых случаях, когда тупиковая ситуация образована многими процессами, использующими много ресурсов,
распознавание тупика является нетривиальной задачей. Существуют формальные, программно - реализованные методы
распознавания тупиков, основанные на ведении таблиц распределения ресурсов и таблиц запросов к занятым ресурсам.
Анализ этих таблиц позволяет обнаружить взаимные блокировки.
Если же тупиковая ситуация возникла, то не обязательно снимать с выполнения все заблокированные процессы. Можно
снять только часть из них, при этом освобождаются ресурсы, ожидаемые остальными процессами, можно вернуть
некоторые процессы в область свопинга, можно совершить "откат" некоторых процессов до так называемой
контрольной точки, в которой запоминается вся информация, необходимая для восстановления выполнения программы
с данного места. Контрольные точки расставляются в программе в местах, после которых возможно возникновение
тупика. Из всего вышесказанного ясно, что использовать семафоры нужно очень осторожно, так как одна
незначительная ошибка может привести к останову системы. Для того чтобы облегчить написание корректных
76
программ, было предложено высокоуровневое средство синхронизации, называемое монитором. Монитор - это набор
процедур, переменных и структур данных. Процессы могут вызывать процедуры монитора, но не имеют доступа к
внутренним данным монитора. Мониторы имеют важное свойство, которое делает их полезными для достижения
взаимного исключения: только один процесс может быть активным по отношению к монитору. Компилятор
обрабатывает вызовы процедур монитора особым образом. Обычно, когда процесс вызывает процедуру монитора, то
первые несколько инструкций этой процедуры проверяют, не активен ли какой-либо другой процесс по отношению к
этому монитору. Если да, то вызывающий процесс приостанавливается, пока другой процесс не освободит монитор.
Таким образом, исключение входа нескольких процессов в монитор реализуется не программистом, а компилятором,
что делает ошибки менее вероятными.
В распределенных системах, состоящих из нескольких процессоров, каждый из которых имеет собственную
оперативную память, семафоры и мониторы оказываются непригодными. В таких системах синхронизация может быть
реализована только с помощью обмена сообщениями.
Предотвращение тупиковых ситуаций
Для предотвращения тупика необходимо использовать ресурсы таким способом, при котором мы не можем войти в
тупик. В реальной жизни аналог такого решения это “левые повороты слишком опасны, так что мы делаем только
правые повороты”. Это требует больше времени, чтобы добраться до места назначения, но такой метод работает. В
терминах тупиков, мы можем удерживать использование ресурсов так, чтобы не волноваться о возможности
возникновения тупиков. Здесь мы рассмотрим эту идею на нескольких примерах.
Линейное упорядочение ресурсов
Пусть все ресурсы полностью упорядочены от 1 до r. Мы можем наложить следующее ограничение: процесс не может
запрашивать ресурс Rk, если он удерживает ресурс Rh и при этом k < h.
Просто видеть, что, используя это правило, мы никогда не будем входить в тупики. (Для доказательства применим
метод доказательства от противного).
Приведем пример того, как применяется это правило. Пусть есть процесс, который использует ресурсы, упорядоченные
как A, B, C, D, E, следующим способом:
Тогда процесс может делать следующее:
захватить (A); захватить (B); захватить (C);
использовать C;
использовать A, C;
использовать A, B, C;
освободить (A); освободить (B); захватить (E);
использовать C и E;
освободить (C); освободить (E); захватить (D);
использовать D;
освободить (D);
Стратегия этого типа может использоваться, когда мы имеем несколько ресурсов. Эту стратегию просто применять, при
этом степень параллелизма уменьшается не слишком сильно.
Иерархическое упорядочение ресурсов
Другая стратегия, которую мы можем использовать в случае, если ресурсы иерархически структурированы, должна
блокировать их в иерархическом порядке. Пусть удерживание ресурсов представлено организованным в дерево. Мы
можем блокировать любой узел или группу узлов в дереве. Ресурсы, в которых мы заинтересованы - узлы в дереве,
обычно самого нижнего уровня в древовидном представлении иерархии. Тогда следующее правило гарантирует
предотвращение тупиков: узлы, в настоящее время блокированные процессом, должны найтись на всех путях от корня
до желательных ресурсов. Пример использования этого правила, с блокировкой одиночного ресурса одновременно:
Тогда если процесс хочет использовать ресурсы e, f, i, k он должен использовать команды в следующей
последовательности:
блокировка (a);
блокировка (b);
блокировка (h);
освобождение (a);
блокировка (d);
освобождение (b);
блокировка (i);
блокировка (j);
освобождение (h);
блокировка (k);
77
освобождение (j);
блокировка (e);
блокировка (f);
освобождение (d);
Алгоритм банкира
Одна из причин, по которой этот алгоритм не используется в реальном мире широко – чтобы использовать его,
операционная система должна знать максимальное количество ресурсов, в которых каждый процесс будет нуждаться
когда-либо. Следовательно, например, запущенная на выполнение программа должна объявить, что она будет нуждаться
не более чем, скажем, 400КБ памяти. Операционная система сохранит ограничение 400КБ и будет использовать его в
вычислениях с целью предотвращения тупика.
Алгоритм Банкира пытается предотвращать тупик, путем предоставления или отказа предоставления ресурсов системы.
Каждый раз, когда процесс нуждается в каком либо неразделяемом ресурсе, этот запрос должен быть одобрен банкиром.
Банкир - консервативен. Каждый раз, когда процесс делает запрос ресурса (“просит ссуду”), банкир осторожно
рассматривает “банковские книги” и пытается определять, может или нет состояние тупика возникнуть в будущем, если
запрос ссуды будет одобрен.
Алгоритм симулирует предоставление запрошенного ресурса и затем просматривает возникающее в результате
выполнения запроса состояние системы.
После предоставления ресурса в системе останется некоторое количество этого ресурса свободным. Далее, проверяем
другие процессы в системе. Мы требовали, чтобы каждый из них установил максимальное количество всех ресурсов
системы, в которых они будут нуждаться, чтобы завершить выполнение, следовательно, мы знаем, сколько каждого
ресурса каждый процесс удерживает и требует.
Если банкир имеет достаточно свободного ресурса чтобы гарантировать, что хотя бы один процесс может завершиться,
тогда он может брать ресурс, удерживаемый этим процессом, и добавляет это к свободному объему ресурса. В этот
момент банкир может рассматривать теперь больший свободный объем и делать попытку проверки, что другой процесс
может завершиться, если требование будет выполнено. Если банкир может гарантировать, что все процессы в системе
завершатся, то он одобряет рассматриваемый запрос.
Если, с другой стороны, в данный момент банкир не может гарантировать, что любые процессы завершатся, потому что
недостаточно свободного ресурса удовлетворить самое малое требование, то может наступить состояние тупика. Это
называется небезопасным состоянием. В этом случае рассматриваемый запрос будет отклонен и запрашивающий
процесс обычно блокируется.
Эффективность алгоритма Банкира зависит значительно от его реализации. Например, если “банковские книги”
сохраняются сортированными по размерам требований процессов, то добавление новой информации о процессах к
таблице или уменьшение таблицы упрощено. Однако если таблица сохраняется в неупорядоченном виде, то добавление
новой записи приводит к снижению эффективности таблицы.
31.
Виды загрузчиков и редакторов связей, их основные функции, в том числе машинозависимые и
машинонезависимые.
Основные понятия
Определение (ГОСТ)
Загрузчик - программа, которая подготавливает объектную программу к выполнению и инициирует ее выполнение.
Более детально функции Загрузчика следующие:
-выделение места для программ в памяти (распределение);
-фактическое размещение команд и данных в памяти (загрузка);
-разрешение символических ссылок между объектами (связывание);
-настройка всех величин в модуле, зависящих от физических адресов в соответствии с выделенной
(перемещение);
памятью
-передача управления на входную точку программы (инициализация).
78
Не обязательно функции Загрузчика должны выполняться именно в той последовательности, в какой они описаны.
Опишем эти функции более подробно.
Функция распределения, по-видимому понятна из ее названия. Для размещения программы в оперативной памяти
должно быть найдено и выделено свободное место в памяти. Для выполнения этой функции Загрузчик обычно
обращается к операционной системы, которая выполняет его запрос на выделение памяти в рамках общего механизма
управления памятью.
Функция загрузки сводится к считыванию образа программы с диска (или другого внешнего носителя) в оперативную
память.
Функция связывания состоит в компоновки программы из многих объектных модулей. Поскольку каждый из объектных
модулей в составе программы был получен в результате отдельного процесса трансляции, который работает только с
одним конкретным модулем, обращения к процедурам и данным, расположенным в других модулях, в объектных
модулях не содержат актуальных адресов. Загрузчик же "видит" все объектные модули, входящие в состав программы, и
он может вставить в обращения к внешним точкам правильные адреса. Загрузчики, которые выполняют функцию
связывания вместе с другими функциями, называются Связывающими Загрузчиками. Выполнение функции связывания
может быть переложено на отдельную программу, называемую Редактором связей или Компоновщиком. Редактор
связей выполняет только функцию связывания - сборки программы из многих объектных модулей и формирование
адресов в обращениях к внешним точкам. На выходе Редактора связей мы получаем загрузочный модуль.
Функция перемещения необходимо потому, что программа на любом языке разрабатывается в некотором виртуальном
адресном пространстве, в котором адресация ведется относительно начала программной секции. При написании
программы и при ее трансляции, как правило, неизвестно, по какому адресу памяти будет размещена программа (где
система найдет свободный участок памяти для ее размещения). Поэтому в большинстве случаев в командах
используется именно адреса меток и данных. Однако, в некоторых случаях в программе возникает необходимость
использовать реальные адреса, которые определяться только после загрузки. Все величины в программе, которые
должны быть привязаны к реальным адресам, должны быть настроены с учетом адреса, по которому программа
загружена.
Существуют программы, которые при написании рассчитываются на размещение в определенных адресах памяти, так
называемые, абсолютные программы. Подготовка таких программ к выполнению значительно проще и выполняется она
Абсолютным Загрузчиком. Функции такого Загрузчика гораздо проще:
-функция распределения не выполняется, так как реальное адресное пространство, в котором размещается программа
предполагается свободным;
-функция загрузки, конечно, выполняется, но она предельно проста;
-функция связывания может быть исключена из Абсолютного Загрузчика: поскольку все адреса программы известны
заранее, адреса, по которым происходят обращения к внешним точкам, могут быть определены заранее;
-функция перемещения исключается;
-функция инициализации остается.
Доля абсолютных программ в общей массе программного обеспечения ничтожно мала. Абсолютными могут быть
системные программы самого низкого уровня, программы, записываемые в ПЗУ, программы для встраиваемых
устройств и т.п. Подавляющее же большинство системных и все прикладные программы являются перемещаемыми, то
есть, они могут загружаться для выполнения в любую область памяти, и Загрузчик для таких программ выполняет
перечисленные функции в полном объеме.
При рассмотрении Ассемблеров мы оставили без внимания обработку обращений к внешним точкам и формат
объектного модуля. Эти вопросы непосредственно относятся к функциям Загрузчика, и мы их рассмотрим здесь.
Основные типы Загрузчиков - настраивающие и непосредственно связывающие.
Настраивающие Загрузчики
Настраивающий Загрузчик является первым шагом в сторону усложнения от Абсолютного Загрузчика. Функции
связывания и перемещения решаются в нем не самым эффективным, но простейшим способом.
79
Связывание в Настраивающем Загрузчике.
Проблема связывания в Настраивающем Загрузчике решается при помощи Вектора Переходов. Вектор Переходов
включается в состав объектного модуля и содержит список всех внешних имен, к которым есть обращение в модуле с
полем адреса для каждого имени. Вектор Переходов заполняется при обработке директив типа EXT (перечисления
внешних имен). В команды программы, обращающиеся к внешним именам вставляется обращение к адресному полю
соответствующего элемента Вектора Переходов с признаком косвенного обращение. (Косвенное обращение означает,
что обращение идет не по адресу, который задан в команде, а по адресу, который записан в ячейке, адрес которой задан
в команде.)
При загрузке в оперативную память Вектор Переходов загружается вместе с кодами программы и остается в памяти все
время выполнения программы.
Когда Загрузчик компонует программу из нескольких объектных модулей, он "узнает" все фактические адреса входных
точек и в Вектора Переходов тех модулей, которые обращаются к данной входной точке вставляет эти адреса.
Обращение к внешней точке, таким образом, производится косвенное через Вектор Переходов.
Перемещенне в Настраивающем Загрузчике.
Принятые в Настраивающих Загрузчиках методы позволяют легко реализовать настройку реальных адресов,
заданных относительно начала программы. Сущность метода перемещения состоит в том, что с каждым словом кода
программы (размер слова обычно равен размеру реального адреса) связывается "бит перемещения". Значение этого бита
0/1 является признаком неперемещаемого/перемещаемого слова. Если слово является неперемещаемым, оно оставляется
Загрузчиком без изменений. Если слово является перемещаемым, то к значению в слове прибавляется стартовый адрес
модуля в оперативной памяти. Биты перемещения могут упаковываться - например, описание 8 слов в одном байте.
Непосредственно Связывающие Загрузчики
Эти Загрузчики называются непосредственно связывающими потому, что они обеспечивают обращение к внешней
точке непосредственно, а не через косвенную адресацию. Эти Загрузчики обеспечивают более высокую эффективность
кода и более гибкие возможности связывания. Такие возможности достигаются за счет того, что в объектном модуле
содержится вся необходимая для Загрузчика информация.
Формат объектного модуля
Объектный модуль, поступающий на вход Загрузчика должен в той или иной форме содержать:
размер модуля;
машинные коды;
входные точки (те адреса в модуле, к которым возможны обращения извне);
внешние точки (те имена во внешних модулях, к которым есть обращения в данном модуле);
информация о размещении в модуле перемещаемых данных.
80
32.
Организация ввода-вывода семейств IBM-370 и УУМ/ДС: каналы и канальные программы, рабочие
области каналов, очереди на обслуживание.
IBM System/370 (S/370) — серия мейнфреймов, выпущенная компанией IBM.
Впервые анонсирована 30 июля 1970 года. Эти машины обладали теми же преимуществами, что и их предшественники
System/360 : высокой управляемостью, универсальностью, масштабируемостью и надёжностью при обработке
приложений с большим объёмом данных в многопользовательской среде и были совместимы с системами System/360.
Основными новациями System/370 можно считать возможность использования нескольких процессоров в рамках одной
системы, полноценную поддержку виртуальной памяти и новый 128-разрядный блок вещественной арифметики.
УУМ/ДС — упрощенная учебная машина с дополнительными средствами, по сути же это эмулятор IBM PC. Эта
машина была спроектирована, чтобы проиллюстрировать наиболее часто встречающиеся аппаратные концепции и
возможности, избегая в то же время большинства специфических особенностей, присущих реальным машинам.
В стандартной модели УУМ ввод и вывод выполняются побайтно. Для обмена используется самый правый байт
сумматора. Каждому внешнему устройству присвоен уникальный 8-разрядный код. Существует три команды вводавывода. Каждая из этих команд в качестве своего операнда задаёт код устройства.
Команда проверки состояния устройства (TD – Test Device) проверяет, готово ли требуемое устройство передать или
принять очередной байт данных. Для индикации результата проверки используется код условия. Значение кода условия
«<» указывает на готовность устройства к обмену; значение «=» означает, что устройство занято; значение «>» означает,
что данное устройство не исправно или не подключено к машине. Программа, желающая выполнить обмен, должна
ждать до тех пор, пока устройство не будет готово, и только после этого она может выполнить команду чтения данных
(RD – Read Data) или команду записи данных (WD – Write Data). Эта последовательность действий должна быть
повторена для каждого байта данных, участвующего в обмене.
Прерывание по вводу-выводу вызывается каналами или устройствами ввода-вывода. Причиной многих таких
прерываний является нормальное завершение некоторой операции ввода-вывода; однако они могут также оповещать о
возникновении различных ошибочных ситуаций. Когда происходит прерывание, состояние ЦП сохраняется, а
управление передается стандартной программе обработки прерываний.
Пример канальных программ. Программа копирует 4096 байт записей данных с устройства 22 на устройство 14.
Имеются две канальные программы: одна для чтения и другая для записи, а также два блока состояния события. В
основном цикле программы сначала выдается запрос на чтение, а затем ожидается завершение этого чтения и
предыдущей записи. По окончании обеих операций программа создает последовательность вывода и выдает запрос на
запись.
Операции ввода-вывода выполняются независимо друг от друга, так как ими используются разные каналы. Одна
операция может быть завершена раньше другой. Возможно также, что обе операции будут выполнены фактически
одновременно. Программа в состоянии координировать взаимосвязанные операции ввода-вывода, так как им соответствуют разные ESB и следовательно каналы могут использоваться для выполнения совмещенных операций вводавывода.
Но так это работает с точки зрения пользователя, в действительности же обрабатываются машиной и операционной
системой. В аппаратуре УУМ/ДС предусмотрено наличие в памяти, соответствующей каналу ввода-вывода, рабочей
области канала. В ней содержатся стартовый адрес текущей канальной программы, если она имеется, и адрес ESB,
соответствующего текущей операции. Результат работы операции ввода-вывода после ее завершения отображается
находящимися в рабочей области канала флагами состояния, такими как нормальное завершение, ошибка ввода-вывода
или устройство недоступно. Рабочая область программы содержит также указатель на очередь запросов на ввод-вывод
для данного канала, которая поддерживается стандартными программами операционной системы.
81
Если требуемый канал занят выполнением другой операции, операционная система ставит запрос в очередь к нему. В
противном случае она запускает канал, а текущий запрос сохраняет в рабочей области канала. Возможно также, что
управление будет возвращено процессу, затребовавшему ввод-вывод, и он, пока ведется обмен, сможет продолжить
paботу.
Окончание операции ввода-вывода отмечается в ESB. Каждый ожидающий этого процесс снова переводится в
состояние готовности. Затем обработчик прерываний по вводу-выводу просматривает очередь запросов к данному
каналу и начинает выполнение следующего запроса (если он есть).
Разработка для новой УУМ:
- модели виртуальной ЭВМ с отладчиком
- модели канальных процессоров
- модели виртуальных внешних устройств (с визуализацией)
- макроассемблер
- компоновщик
- компиляторы
- интегрированные среды разработки
- консоль сисадмина с соотв. мониторингом и средствами управления процессами и ресурсами
- микроядро ОС и его оболочки
* менеджер памяти с использованием аппаратной защиты
* планировщик и диспетчер многозадачного режима
* планировщик и диспетчер многопоточного режима
* процедуры межпроцессного взаимодействия с защитой от взаимной блокировки
* менеджер ресурсов и система бюджетирования и биллинга
* модели файловых систем, в том числе, аппаратно-ориентированных
* модели API
* модели GUI
Многозадачного микроядра ОС-УУМ/ДЦ:
- тестирование и доработка виртуальной ЭВМ УУМДЦ
- создание оболочек ядра ОС (диспетчер процессов, менеджеры памяти, файловые системы, планировщики ресурсов,
мониторинг, консоль сисадмина, супервизор ввода-вывода, многопоточный режим, предотвращение блокировок
процессов, оптимизация нагрузки, защита и разграничение доступа к ресурсам, бюджетирование, анализ и
восстановление после сбоев и отказов,...см.п.1)
- развитие концепции канальных процессоров IBM/370 для УУМДЦ, отладка взаимодействия их модели с виртуальной
УУМДЦ
- создание библиотеки моделей типовых устройств ввода-вывода (с последующей анимацией из работы)
- создание библиотеки процедур ввода-вывода на ассемблере канальных процессоров и ассемблере УУМДЦ
- разработчика планировщика ввода-вывода с функциями оптимизации
- создание учебных библиотек на основе проекта УУМ-2004 и интерактивных курсов по дисциплинам "ОС", "СПО"."
Орг.ЭВМ", "Параллельные вычисления",..., их испытание на сервере МОВС (см. п.9)
- разработка тренажера сисадмина на базе УУМ-2004 и моделей из пп.2,3,4.7
33.
Планирование процессов в ОС, диаграмма переходов состояний вычислительных процессов, алгоритмы
диспетчеризации.
Процессы и потоки
Под процессом понимается программа в стадии выполнения. Процесс можно рассматривать также как единицу работы
для процессора. Для современных типов процессоров существует и более мелкая единица работы поток или нить.
Другими словами процесс может породить один и более потоков.
В чем же состоит принципиальное различие в понятиях процесс и поток. Процесс рассматривается ОС, как заявка на все
виды ресурсов (память, файлы и пр.), кроме одного - процессорного времени. Поток - это заявка на процессорное время.
В дальнейшем в качестве единицы работы ОС будут использоваться понятия процесс и поток. В тех же случаях, когда
это не играет существенной роли, они будут называться задача
Планирование процессов и потоков
Планирование процессов и потоков включает:
82
Создание-уничтожение процессов
Взаимодействие между процессами
Распределение процессорного времени
Обеспечение процессов необходимыми ресурсами (единолично, совместно)
Синхронизация (контроль за возникновением «гонок», блокировок)
После завершения процесса - «зачистка», т.е. удаление следов пребывания в системе
Каждый процесс изолируется от других своим виртуальным адресным пространством, под которым понимается
совокупность адресов, которыми может манипулировать программный модуль процесса. ОС отображает виртуальное
адресное пространство на отведенную процессу физическую память.
Для взаимодействия, процессы обращаются к ОС, которая предоставляет средства общения (конвейеры, почтовые
ящики, разделяемые секции памяти и др.)
Возможность распараллеливания вычислений в рамках процесса на потоки повышает эффективность ОС. Механизм
распараллеливания вычислений для одного приложения называется многопоточной обработкой (multithreading). Потоки
процесса имеют одно адресное виртуальное пространство. Распараллеливание ускоряет выполнение процесса за счет
отсутствия переключения ОС с одного адресного пространства на другое, которое имеет место при выполнении
процессов. Программы становятся более логичны. Особый эффект при этом достигается в мультипроцессорных
системах.
Примером многопоточной обработки может служить выполнение запросов MS SQL Server
Создание процессов
Создать процесс - это создать описатель процесса (информационная структура, содержащая сведения необходимые для
управления этим процессом)
Содержание: идентификатор, адрес исполняемого модуля, приоритет, права доступа и пр.
Примеры описателей для:
Windows NT/2000/XP - объект-процесс (object-process)
UNIX - дескриптор процесса
OS/2 - управляющий блок процесса (PCB -Process Control Block)
Кроме того создать процесс - это включает также следующие действия:
Найти программу на диске
перераспределить оперативную память
выделить память новому процессу
переписать программу в выделенную память
изменить некоторые параметры программы
Создание потоков
В многопоточной системе при создании процесса создается хотя бы один поток. Для потока ОС генерирует описатель
потока (идентификатор потока, данные о правах, приоритете, состояние потока и пр.).Исходное состояние потока приостановленное.
Поток может породить другой поток - потомок. При завершения потока-родителя используются разные алгоритмы.
Асинхронное завершение предполагает продолжение выполнения потоков-потомков после завершения потока-родителя.
Синхронное завершение потока-родителя приводит к завершению всех его потомков.
83
Планирование и диспетчеризация потоков (процессов)
Планирование означает определение момента: когда прервать выполнение активного потока и какой поток
активизировать Планирование выполняется на основе описателей потоков.
Применяются разные алгоритмы планирования. В большинстве ОС планирование динамическое, т.е. решения
принимаются во время работы ОС на основе анализа текущей ситуации. Другой тип планирования статический, в
которых весь набор одновременно выполняемых задач определен заранее (off-line), например по расписанию. Такой тип
планирования применяется в специализированных ОС, в системах реального времени
Диспетчеризация: реализация результатов планирования. Включает в себя:
переключение потоков
сохранение контекста текущего потока
загрузка контекста нового потока
запуск нового потока
Сохранение, загрузка и запуск потоков выполняются совместно с аппаратными средствами
Вытесняющие и невытесняющие алгоритмы планирования
Невытесняющие (non-preemptive) - поток выполняется, пока по собственной инициативе не отдаст управление ОС для
активизации другого потока
Вытесняющие (preemptive) - решение о переключении принимается ОС
Примеры:
Unix, Windows NT/2000/XP, OS/2, VAX - поддерживаются вытесняющие алгоритмы
NetWare 3.x, 4.x - невытесняющие (ThreadSwitch)
Вытесняющие алгоритмы планирования делятся на алгоритмы, основанные на:
квантовании
приоритетах
смешанные
Вытесняющие алгоритмы планирования, основанные на квантовании
Каждому потоку выделяется отрезок времени квант
Смена активного потока происходит, в случае:
поток завершился
произошла ошибка
поток перешел в состояние ожидания
исчерпан квант
Грубо величина кванта должна составлять менее 20млс. Кванты, выделяемые потоку, могут быть фиксированной
величины, а могут меняться со временем. Современные ОС используют кванты переменной величины.
Вытесняющие алгоритмы планирования, основанные на приоритетах
В основе этих алгоритмов лежат принципы приоритетного обслуживания
84
Каждый поток имеет приоритет, число характеризующее степень привилегированности при использовании ресурсов.
Приоритет потока связан с приоритетом процесса, который назначается при создании процесса.
Значение зависит от того, является процесс системным или пользовательским, каков статус запустившего процесс.
Приоритеты могут быть динамические, фиксированные.
Существуют две разновидности приоритетного планирования: обслуживание с относительными и абсолютными
приоритетами. В обоих случаях выбор потока на выполнение из очереди готовых, осуществляется одинаково:
выбирается поток с наивысшим приоритетом. Однако проблема определения момента смены активного потока решается
по-разному.
В системах с относительными приоритетами активный поток выполняется до тех пор пока сам не покинет процессор.
В системах с абсолютными приоритетами активный поток дополнительно к сказанному, может покинуть процессор в
том случае, если в очереди готовых потоков появился поток с более высоким приоритетом.
Смешанные алгоритмы планирования
В современных ОС планирование основано на квантовании и приоритетном алгоритмах (Windows NT/2000/XP, Unix)
На выполнение выбирается поток с наивысшим приоритетом, которому выделяется квант. Если появляется поток с
более высоким приоритетом, то текущий вытесняется
Приоритет потока повышается, если поток не использовал квант (например, при выполнении ввода-вывода).
Вытесняющие и невытесняющие алгоритмы планирования
Существует два основных типа процедур планирования процессов - вытесняющие (preemptive) и невытесняющие (nonpreemptive).
Non-preemptive multitasking - невытесняющая многозадачность - это способ планирования процессов, при котором
активный процесс выполняется до тех пор, пока он сам, по собственной инициативе, не отдаст управление
планировщику операционной системы для того, чтобы тот выбрал из очереди другой, готовый к выполнению процесс.
Preemptive multitasking - вытесняющая многозадачность - это такой способ, при котором решение о переключении
процессора с выполнения одного процесса на выполнение другого процесса принимается планировщиком операционной
системы, а не самой активной задачей.
Основным различием между preemptive и non-preemptive вариантами многозадачности является степень централизации
механизма планирования задач. При вытесняющей многозадачности механизм планирования задач целиком
сосредоточен в операционной системе, и программист пишет свое приложение, не заботясь о том, что оно будет
выполняться параллельно с другими задачами. При этом операционная система выполняет следующие функции:
определяет момент снятия с выполнения активной задачи, запоминает ее контекст, выбирает из очереди готовых задач
следующую и запускает ее на выполнение, загружая ее контекст.
При невытесняющей многозадачности механизм планирования распределен между системой и прикладными
программами. Прикладная программа, получив управление от операционной системы, сама определяет момент
завершения своей очередной итерации и передает управление ОС с помощью какого-либо системного вызова, а ОС
формирует очереди задач и выбирает в соответствии с некоторым алгоритмом (например, с учетом приоритетов)
следующую задачу на выполнение. Такой механизм создает проблемы как для пользователей, так и для разработчиков.
Для пользователей это означает, что управление системой теряется на произвольный период времени, который
определяется приложением (а не пользователем). Если приложение тратит слишком много времени на выполнение
какой-либо работы, например, на форматирование диска, пользователь не может переключиться с этой задачи на другую
задачу, например, на текстовый редактор, в то время как форматирование продолжалось бы в фоновом режиме. Эта
ситуация нежелательна, так как пользователи обычно не хотят долго ждать, когда машина завершит свою задачу.
Поэтому разработчики приложений для non-preemptive операционной среды, возлагая на себя функции планировщика,
должны создавать приложения так, чтобы они выполняли свои задачи небольшими частями. Например, программа
форматирования может отформатировать одну дорожку дискеты и вернуть управление системе. После выполнения
других задач система возвратит управление программе форматирования, чтобы та отформатировала следующую
дорожку. Подобный метод разделения времени между задачами работает, но он существенно затрудняет разработку
программ и предъявляет повышенные требования к квалификации программиста. Программист должен обеспечить
85
"дружественное" отношение своей программы к другим выполняемым одновременно с ней программам, достаточно
часто отдавая им управление. Крайним проявлением "недружественности" приложения является его зависание, которое
приводит к общему краху системы. В системах с вытесняющей многозадачностью такие ситуации, как правило,
исключены, так как центральный планирующий механизм снимет зависшую задачу с выполнения.
Однако распределение функций планировщика между системой и приложениями не всегда является недостатком, а при
определенных условиях может быть и преимуществом, потому что дает возможность разработчику приложений самому
проектировать алгоритм планирования, наиболее подходящий для данного фиксированного набора задач. Так как
разработчик сам определяет в программе момент времени отдачи управления, то при этом исключаются
нерациональные прерывания программ в "неудобные" для них моменты времени. Кроме того, легко разрешаются
проблемы совместного использования данных: задача во время каждой итерации использует их монопольно и уверена,
что на протяжении этого периода никто другой не изменит эти данные. Существенным преимуществом non-preemptive
систем является более высокая скорость переключения с задачи на задачу.
Примером эффективного использования невытесняющей многозадачности является файл-сервер NetWare, в котором, в
значительной степени благодаря этому, достигнута высокая скорость выполнения файловых операций. Менее удачным
оказалось использование невытесняющей многозадачности в операционной среде Windows 3.х.
Однако почти во всех современных операционных системах, ориентированных на высокопроизводительное выполнение
приложений (UNIX, Windows NT, OS/2, VAX/VMS), реализована вытесняющая многозадачность. В последнее время
дошла очередь и до ОС класса настольных систем, например, OS/2 Warp и Windows 95. Возможно в связи с этим
вытесняющую многозадачность часто называют истинной многозадачностью.
34.
Определение и примеры хеш-функций. Выбор оптимальных хеш-функций для доступа к табличным
данным различных компонент системного ПО.
Хеширование (иногда хэширование, англ. hashing) — преобразование входного массива данных произвольной длины в
выходную битовую строку фиксированной длины. Такие преобразования также называются хеш-функциями или
функциями свёртки, а их результаты называют хешем, хеш-кодом или дайджестом сообщения (англ. message digest).
Хеширование применяется для сравнения данных: если у двух массивов хеш-коды разные, массивы гарантированно
различаются; если одинаковые — массивы, скорее всего, одинаковы. В общем случае однозначного соответствия между
исходными данными и хеш-кодом нет в силу того, что количество значений хеш-функций меньше чем вариантов
входного массива; существует множество массивов, дающих одинаковые хеш-коды — так называемые коллизии.
Вероятность возникновения коллизий играет немаловажную роль в оценке качества хеш-функций.
Существует множество алгоритмов хеширования с различными характеристиками (разрядность, вычислительная
сложность, криптостойкость и т. п.). Выбор той или иной хеш-функции определяется спецификой решаемой задачи.
Простейшими примерами хеш-функций могут служить контрольная сумма или CRC.
MD2 - Самая медленная, оптимизирована для 8-битовых машин
MD4 - Самая быстрая, оптимизирована для 32-битных машин
MD5- Наиболее распространенная из семейства MD-функций. Похожа на MD4, но средства повышения безопасности
делают ее на 33% медленнее, чем MD4. Обеспечивает целостность данных. Считается безопасной .
SHA (Secure Создает 160-битное значение хэш-функции из исходных Hash данных переменного размера. Algorithm) Предложена NIST и принята правительством США как стандарт. Предназначена для использования в стандарте DSS.
Хеширование в некоторых случаях позволяет ускорить доступ к табличным данным, например, при записи текстовых
полей в базе данных может рассчитываться их хеш-код и данные могут помещаться в раздел, соответствующий этому
хеш-коду. Тогда при поиске данных надо будет сначала вычислить хеш-код текста и сразу станет известно, в каком
разделе их надо искать, то есть, искать надо будет не по всей базе, а только по одному её разделу (это сильно ускоряет
поиск).
Хеш-табли́ца — это обычный массив с необычной адресацией, задаваемой хеш-функцией.
Хеш-табли́ца — это структура данных, реализующая интерфейс ассоциативного массива, а именно, она позволяет
хранить пары (ключ, значение) и выполнять три операции: операцию добавления новой пары, операцию поиска и
операцию удаления пары по ключу.
86
Хеширование - это способ сведения хранения одного большого множества к более меньшему. Функция, которая
трансформирует ключ в некоторый индекс в таблице, называется хеш-функцией.
Бытовым аналогом хеширования может служить помещение слов в словаре по алфавиту. Первая буква слова является
его хеш-кодом, и при поиске мы просматриваем не весь словарь, а только нужную букву.
Существует два основных варианта хеш-таблиц: с цепочками и открытой адресацией. Хеш-таблица содержит некоторый
массив H, элементы которого есть пары (хеш-таблица с открытой адресацией) или списки пар (хеш-таблица с
цепочками).
Выполнение операции в хеш-таблице начинается с вычисления хеш-функции от ключа. Получающееся хеш-значение i =
hash(key) играет роль индекса в массиве H. Затем выполняемая операция (добавление, удаление или поиск)
перенаправляется объекту, который хранится в соответствующей ячейке массива H[i].
Важное свойство хеш-таблиц состоит в том, что, при некоторых разумных допущениях, все три операции (поиск,
вставка, удаление элементов) в среднем выполняются за время O(1). Но при этом не гарантируется, что время
выполнения отдельной операции мало́. Это связано с тем, что при достижении некоторого значения коэффициента
заполнения необходимо осуществлять перестройку индекса хеш-таблицы: увеличить значение размера массива H и
заново добавить в пустую хеш-таблицу все пары.
Как выбрать хорошую хеш-функцию. Ясно, что эта функция должна создавать как можно меньше коллизий при
хешировании, т.е. она должна равномерно распределять ключи на имеющиеся индексы в массиве. Конечно, нельзя
определить, будет ли некоторая конкретная хеш-функция распределять ключи правильно, если эти ключи заранее не
известны. Однако, хотя до выбора хеш-функции редко известны сами ключи, некоторые свойства этих ключей, которые
влияют на их распределение, обычно известны.
Примеры простейших функций:
метод деления. Некоторый целый ключ делится на размер таблицы и остаток от деления берется в качестве значения
хеш-функции. Эта хеш-функция обозначается h (key) := key mod m.
метод середины квадрата. Ключ умножается сам на себя и в качестве индекса используется несколько средних цифр
этого квадрата.
Аддитивный метод для строк (размер таблицы равен 256). Для строк вполне разумные результаты дает сложение всех
символов и возврат остатка от деления на 256.
Исключающее ИЛИ для строк (размер таблицы равен 256). Этот метод аналогичен аддитивному, но успешно различает
схожие слова и анаграммы (аддитивный метод даст одно значение для XY и YX). Метод заключается в том, что к
элементам строки последовательно применяется операция "исключающее или". В алгоритме добавляется случайная
компонента, чтобы еще улучшить результат.
Требования к хэш-функциям
Хэш-функцией называется односторонняя функция, предназначенная для получения дайджеста или "отпечатков
пальцев" файла, сообщения или некоторого блока данных.
Хэш-код создается функцией Н:
h = H (M)
Где М является сообщением произвольной длины и h является хэш-кодом фиксированной длины.
Хэш-функция Н, которая используется для аутентификации сообщений, должна обладать следующими свойствами:
Хэш-функция Н должна применяться к блоку данных любой длины.
Хэш-функция Н создает выход фиксированной длины.
Н (М) относительно легко (за полиномиальное время) вычисляется для любого значения М.
Для любого данного значения хэш-кода h вычислительно невозможно найти M такое, что Н (M) = h.
Для любого данного х вычислительно невозможно найти y x, что H (y) = H (x).
Вычислительно невозможно найти произвольную пару (х, y) такую, что H (y) = H (x).
Первые три свойства требуют, чтобы хэш-функция создавала хэш-код для любого сообщения.
Четвертое свойство определяет требование односторонности хэш-функции: легко создать хэш-код по данному
сообщению, но невозможно восстановить сообщение по данному хэш-коду.
Пятое свойство гарантирует, что невозможно найти другое сообщение, чье значение хэш-функции совпадало бы со
значением хэш-функции данного сообщения. Это предотвращает подделку аутентификатора при использовании
зашифрованного хэш-кода.
Хэш-функция, которая удовлетворяет первым пяти свойствам, называется простой или слабой хэш-функцией. Если
кроме того выполняется шестое свойство, то такая функция называется сильной хэш-функцией.
87
Простые хэш-функции
Все хэш-функции выполняются следующим образом. Входное значение (сообщение, файл и т.п.) рассматривается как
последовательность n-битных блоков. Входное значение обрабатывается последовательно блок за блоком, и создается
m-битное значение хэш-кода.
Одним из простейших примеров хэш-функции является побитный XOR каждого блока:
Сi = bi1
Где
bi2
...
bik
Сi - i-ый бит хэш-кода, 1 i n
k - число n-битных блоков входа.
bij - i-ый бит в j-ом блоке.
- операция XOR.
В результате получается хэш-код длины n, известный как продольный избыточный контроль. Это эффективно при
случайных сбоях для проверки целостности данных.
Часто при использовании подобного продольного избыточного контроля для каждого блока выполняется однобитный
циклический сдвиг после вычисления хэш-кода. Это можно описать следующим образом.
- Установить n-битный хэш-код в ноль.
- Для каждого n-битного блока данных выполнить следующие операции:
- сдвинуть циклически текущий хэш-код влево на один бит;
- выполнить операцию XOR для очередного блока и хэш-кода.
Это даст эффект "случайности" входа и уничтожит любую регулярность, которая присутствует во входных значениях.
Использование цепочки зашифрованных блоков
Существуют различные хэш-функции, основанные на создании цепочки зашифрованных блоков, но без использования
секретного ключа. Одна из таких хэш-функций была предложена Рабином. Сообщение М разбивается на блоки
фиксированной длины М1, М2, . . . , МN и используется алгоритм симметричного шифрования, например DES, для
вычисления хэш-кода G следующим образом:
Н0 = начальное значение
Нi = EMi [Hi-1]
G = HN
Это аналогично использованию шифрования в режиме СВС, но в данном случае секретного ключа нет. Как и в случае
любой простой хэш-функции,
Хэш-функция CRC
Алгоритм CRC базируется на свойствах деления с остатком двоичных многочленов, то есть многочленов над конечным
полем GF(2). Значение CRC является по сути остатком от деления многочлена, соответствующего входным данным, на
некий фиксированный порождающий многочлен.
Каждой конечной последовательности битов
взаимооднозначно сопоставляется двоичный
многочлен
, последовательность коэффициентов которого представляет собой исходную
последовательность. Например, последовательность битов 1011010 соответствует многочлену:
Количество различных многочленов степени меньшей N равно 2N, что совпадает с числом всех двоичных
последовательностей длины N.
Значение CRC с порождающим многочленом G(x) степени N определяется как битовая последовательность длины N,
представляющая многочлен R(x), получившийся в остатке при делении многочлена P(x), представляющего входной
поток бит, на многочлен G(x):
где
R(x) — многочлен, представляющий значение CRC.
P(x) — многочлен, коэффициенты которого представляют входные данные.
G(x) — порождающий многочлен.
88
— степень порождающего многочлена.
Умножение xN осуществляется приписыванием N нулевых битов к входной последовательности, что улучшает качество
хеширования для коротких входных последовательностей.
При делении с остатком степень многочлена-остатка строго меньше степени многочлена-делителя, то есть при делении
на многочлен G(x) степени N можно получить 2N различных остатков от деления. При «правильном» выборе
порождающего многочлена G(x), остатки от деления на него будут обладать нужными свойствами хеширования —
хорошей перемешиваемостью и быстрым алгоритмом вычисления. Второе обеспечивается тем, что степень
порождающего многочлена обычно пропорциональна длине байта или машинного слова (например 8, 16 или 32).
Операция деления на примитивный полином также эквивалентна следующей схеме:
Пусть выбран примитивный полином, задающий цикл де Брейна 0010111001011100… и блок данных 0111110,
построена таблица, верхняя строка заполнена блоком данных, а нижние строки — смещения на 0,1,2 бит цикла де
Брейна
Тогда контрольная сумма будет равна операции XOR тех столбцов, над которыми в
верхней строке расположена 1. В этом случае, 010 xor 101 xor 011 xor 111 xor 110 = 101
(CRC).
Хэш-функция MD5
Алгоритм получает на входе сообщение произвольной длины и создает в качестве выхода дайджест сообщения длиной
128 бит.
Логика выполнения MD5
Алгоритм MD4
Алгоритм MD4 является более ранней разработкой того же автора Рона Ривеста. Первоначально данный алгоритм был
опубликован в октябре 1990 г., незначительно измененная версия была опубликована в RFC 1320 в апреле 1992 г.
Кратко рассмотрим основные цели MD4:
Безопасность: это обычное требование к хэш-коду, состоящее в том, чтобы было вычислительно невозможно найти два
сообщения, имеющие один и тот же дайджест.
Скорость: программная реализация алгоритма должна выполняться достаточно быстро. В частности, алгоритм должен
быть достаточно быстрым на 32-битной архитектуре. Поэтому алгоритм основан на простом множестве элементарных
операций над 32-битными словами.
Простота и компактность: алгоритм должен быть простым в описании и простым в программировании, без больших
программ или подстановочных таблиц. Эти характеристики не только имеют очевидные программные преимущества, но
и желательны с точки зрения безопасности, потому что для анализа возможных слабых мест лучше иметь простой
алгоритм.
Желательна little-endian архитектура: некоторые архитектуры процессоров (такие как линия Intel 80xxx) хранят левые
байты слова в позиции младших адресов байта (little-endian). Другие (такие как SUN Sparcstation) хранят правые байты
слова в позиции младших адресов байта (big endian). Это различие важно, когда сообщение трактуется как
последовательность 32-битовых слов, потому что эти архитектуры имеют инверсное представление байтов в каждом
слове. Ривест выбрал использование схемы little-endian для интерпретации сообщения в качестве последовательности
32-битных слов. Этот выбор сделан потому, что big-endian процессоры обычно являются более быстрыми.
Эти цели преследовались и при разработке MD5. MD5 является более сложным и, следовательно, более медленным при
выполнении, чем MD4. Считается, что добавление сложности оправдывается возрастанием уровня безопасности.
Главные различия между этими двумя алгоритмами состоят в следующем:
89
MD4 использует три цикла из 16 шагов каждый, в то время как MD5 использует четыре цикла из 16 шагов каждый.
В MD4 дополнительная константа в первом цикле не применяется. Аналогичная дополнительная константа
используется для каждого из шагов во втором цикле. Другая дополнительная константа используется для каждого из
шагов в третьем цикле. В MD5 различные дополнительные константы, Т [i], применяются для каждого из 64 шагов.
MD5 использует четыре элементарные логические функции, по одной на каждом цикле, по сравнению с тремя в MD4,
по одной на каждом цикле.
В MD5 на каждом шаге текущий результат складывается с результатом предыдущего шага. Например, результатом
первого шага является измененное слово А. Результат второго шага хранится в D и образуется добавлением А к
циклически сдвинутому влево на определенное число бит результату элементарной функции. Аналогично, результат
третьего шага хранится в С и образуется добавлением D к циклически сдвинутому влево результату элементарной
функции. MD4 это последнее сложение не включает.
35.
Определение, основные функции ассемблеров, их машинозависимые и ма-шинонезависимые
характеристики.
Язык ассемблера — это машинно-зависимый язык низкого уровня, в котором короткие мнемонические имена
соответствуют отдельным машинным командам. Используется для представления в удобочитаемой форме программ,
записанных в машинном коде. Перевод программы с языка ассемблера на машинный язык осуществляется специальной
программой, которая называется ассемблером и является, по сути, простейшим транслятором.
Достоинства языка ассемблера
Использование меньшего количества команд и обращений в память, что позволяет увеличить скорость и уменьшить
размер программы.
Обеспечение максимального использования специфических возможностей конкретной платформы, что также позволяет
создавать более эффективные программы с меньшими затратами ресурсов.
При программировании на ассемблере возможен непосредственный доступ к аппаратуре, в том числе портам вводавывода, регистрам процессора, и др.
] Недостатки языка ассемблера
В силу своей машинной ориентации («низкого» уровня) человеку по сравнению с языками программирования высокого
уровня сложнее читать и понимать программу, соответственно усложняются программирование и отладка, растет
трудоемкость, велика вероятность внесения ошибок. В значительной степени возрастает сложность совместной
разработки.
Как правило, меньшее количество доступных библиотек по сравнению с современными индустриальными языками
программирования.
Отсутствует переносимость программ на ЭВМ с другой архитектурой и системой команд (кроме двоично совместимых).
Применение
Исторически можно рассматривать ассемблер как второе поколение языков программирования ЭВМ (если первым
считать машинный код). Языки ассемблера сохраняют свою нишу, обуславливаемую их уникальными преимуществами
в части эффективности и возможности полного использования специфических средств конкретной платформы.
На ассемблере пишутся программы или фрагменты программ, для которых критически важны:
быстродействие (драйверы, игры);
объем используемой памяти (загрузочные сектора, встраиваемое (embedded) программное обеспечение, программы для
микроконтроллеров и процессоров с ограниченными ресурсами, вирусы, программные защиты).
С использованием программирования на ассемблере производятся:
Оптимизация критичных к скорости участков программ написанных на языке высокого уровня, таком как C++.
Создание операционных систем (ОС). ОС часто пишут на Си, языке, который специально был создан для написания
одной из первых версий Unix. Аппаратно зависимые участки кода, такие, как загрузчик ОС, уровень абстрагирования от
железа — HAL и ядро, часто пишутся на ассемблере.
Программирование микроконтроллеров (МК) и других встраиваемых процессоров.
Создание драйверов. Некоторые участки драйверов, взаимодействующие с железом, программируют на ассемблере
Создание антивирусов и других защитных программ.
Написание трансляторов языков программирования.
Существует целый ряд основных функций, например таких, как трансляция мнемонических кодов операций в их
эквиваленты на машинном языке или присваивание машинных адресов символическим меткам, которые должны
выполняться любым ассемблером.
90
Однако за пределами этого базового уровня возможности, предоставляемые ассемблерами, а также схемы их построения
сильно зависят как от входного языка, так и от языка машины. Одним из аспектов такой машинной зависимости,
естественно, являются имеющиеся различия в форматах машинных команд и кодах операций. С другой стороны,
некоторые средства языка ассемблера (и соответствующих ассемблеров) не имеют прямой связи со структурой машины.
Их выбор является в известном смысле произвольным и определяется разработчиком языка ассемблера.
Машинно-зависимые характеристики ассемблера
1. Форматы команд и способы адресации
Рассмотрим трансляцию предложений исходной программы УУМ/ДС в соответствующее им объектное представление.
Трансляция команд вида регистр-регистр не представляет никаких новых проблем. Ассемблер должен просто
преобразовать мнемонические коды операций в их машинное представление и заменить мнемонические имена
регистров на их числовые эквиваленты. Для трансляции большинства команд вида память-регистр используется
относительный способ адресации (либо относительно счетчика команд, либо относительно базы). В любом случае
ассемблер должен вычислить смещение, которое является составной частью объектной команды. Если нельзя применить
ни один из способов относительной адресации и нет указания об использовании расширенного формата, то правильная
трансляция команды невозможна. В этом случае ассемблер должен выдать сообщение об ошибке.
Трансляция команд, в которых используются непосредственные операнды, проще, поскольку в них не нужна
организация ссылок на оперативную память. Все, что требуется, это преобразовать операнд во внутреннее
представление и занести его в команду.
Ассемблирование команд, использующих косвенную адресацию, (фактически не представляет ничего нового. Для того
чтобы получить требуемый целевой адрес, вначале обычным образом вычисляется смещение. Затем в разряд n
генерируемой команды устанавливается признак косвенной адресации. Примером использования адресации
относительно счетчика команд в комбинации с косвенной адресацией является предложение в строке 70.
2. Перемещение программ
Очень часто желательно иметь возможность одновременно выполнять несколько программ, разделяющих между собой
оперативную память и другие ресурсы машины. Если бы нам заранее было точно известно, какие программы будут
выполняться одновременно, то мы могли бы во время ассемблирования назначить каждой программе подходящие
адреса таким образом, чтобы не было ни взаимного перекрытия программ, ни потери места в оперативной памяти.
Однако чаще всего столь точное планирование выполнения программ не пригодно с практической точки зрения.
Поэтому хотелось бы иметь возможность загружать программу на любое место в оперативной памяти, где для нее
имеется достаточно пространства. В этом случае фактический начальный адрес программы не известен до момента
загрузки.
Поскольку ассемблеру не известен фактический адрес начала загрузки, он не может выполнить необходимую настройку
адресов, используемых программой. Однако ассемблер может указать загрузчику те части объектной программы,
которые нуждаются в настройке при загрузке. Объектная программа, содержащая информацию, необходимую для
выполнения подобной модификации, называется перемещаемой программой.
2. Машинно-независимые характеристики ассемблера
1. Литералы
Очень часто бывает удобно иметь возможность записывать значения константы, используемой в качестве операнда,
непосредственно в команде, где она используется. Это позволяет отказаться от использования отдельного предложения
для определения константы и соответствующей ей метки. Такой операнд называется литеральным (literal), поскольку
значение константы задается в виде строки символов.
В предложении 45 001A ENDFIL LDA =С'ЕОF' 032010 литерал определяет 3-байтовый операнд, значением
которого является строка символов EOF.
2. Средства определения имен
имя EQU значение
Данное предложение определяет некоторое имя (т. е. вносит его в SYMTAB) и присваивает ему значение. Значение
может задаваться в виде константы пли выражения, в котором могут использоваться константы и ранее определенные
имена. Одним из общих применений EQU является введение символических имен вместо числовых значений, чтобы
упростить чтение программы. Другое общее применение EQU заключается в определении мнемонических имен для
регистров.
Имеется еще одна общеупотребительная директива ассемблера, позволяющая косвенно задавать значения
символическим именам. Обычно эта директива называется ORG (от ORiGin). Она имеет следующий вид:
ORG значение
где значение представляет собой константу или выражение, в котором могут быть использованы константы и ранее
определенные имена. Если во время ассемблирования программы встречается данное предложение, то заданное им
значение заносится в счетчик размещений (LOCCTR). Поскольку для определения значений имен используется
LOCCTR, то предложение ORG распространяет свое влияние на все последующие определения меток.
91
3. Выражения
В большинстве ассемблеров наряду с одиночными термами(константы, метки и т. п.) разрешается использовать
выражения. Каждое такое выражение вычисляется ассемблером во время трансляции, а затем полученное значение
используется в виде адреса или непосредственного операнда.
Обычно допускаются арифметические выражения, которые строятся по стандартным правилам с помощью операций +,,*,/. Деление чаще всего определяется как целочисленное. В выражениях можно использовать константы, метки и
специальные термы. Одним из таких общеупотребительных специальных термов является терм, ссылающийся на
текущую величину счетчика размещений (часто обозначается как *). Значением этого терма является адрес, который
будет присвоен очередной команде или области данных.
4. Программные блоки
Многие ассемблеры предоставляют более гибкие средства обработки исходной программы и соответствующего ей
объектного кода. Одни из этих средств позволяют располагать сгенерированные машинные команды и данные в
объектной программе в порядке, отличном от порядка, в котором расположены соответствующие им исходные
предложения. Другие позволяют создавать несколько независимых частей объектной программы, Каждая из этих частей
сохраняет свою индивидуальность и обрабатывается загрузчиком отдельно от других частей. Фактически в некоторых
системах одни и те же средства языка ассемблера используются для обеспечения обеих этих логически различных
функций.
2.3.5. Управляющие секции и связывание программ
Управляющая секция - это часть программы, которая после ассемблирования сохраняет свою индивидуальность и может
загружаться и перемещаться независимо от других. В отдельные управляющие секции чаще всего выделяются
подпрограммы или другие логические подразделы программы. Программист может отдельно ассемблировать и
загружать каждую из таких управляющих секций. Достигаемая за счет этого гибкость является основным
преимуществом их использования. Поскольку управляющие секции образуют логически связанные части программы,
то, следовательно, необходимо предоставить некоторые средства для их связывания (linking) друг с другом. Например,
команды одной управляющей секции должны иметь возможность ссылаться на команды или области данных,
расположенные в другой секции. Такие ссылки нельзя обрабатывать обычным образом, поскольку управляющие секции
загружаются и перемещаются независимо друг от друга и ассемблеру ничего не известно о том, где будут расположены
другие управляющие секции во время исполнения программы. Такие ссылки между управляющими секциями
называются внешними ссылками (external references). Для каждой внешней ссылки ассемблер генерирует информацию,
которая дает возможность загрузчику выполнить требуемое связывание программ.
От программных блоков управляющие секции отличаются тем, что они обрабатываются ассемблером независимо друг
от друга.
36.
Может ли время прохождения задания в многозадачном режиме ОС быть меньше времени его
прохождения в однозадачном режиме (для одноядерных и многоядерных ЭВМ)?
Такая ситуация возможна при использовании многопоточности.
Многопоточность — свойство, заключающееся в том, что задача может выполняться в более чем 1 потоке, за счёт чего
достигается более эффективное использование ресурсов вычислительной машины. Как правило, операционные системы,
реализующие многозадачность, реализуют и многопоточность.
Сутью многопоточности является квазимногозадачность на уровне одного исполняемого процесса, то есть все потоки
выполняются в адресном пространстве процесса. На момент выполнения процесса он имеет как минимум один
(главный) поток.
К достоинствам многопоточности в программировании можно отнести следующее:
- упрощение программы в некоторых случаях, за счет использования общего адресного пространства,
- меньшие относительно процесса временные затраты на создание потока,
- Повышение производительности процесса за счет распараллелизации процессорных вычислений и операций
ввода/вывода.
Типы реализации потоков:
1. Поток в пространстве пользователя. Каждый процесс имеет таблицу потоков, аналогичную таблице процессов ядра.
Достоинства:
- возможность реализации на ядре не поддерживающем многопоточность,
- более быстрое переключение, создание и завершение потоков,
- процесс может иметь собственный алгоритм планирования.
Недостатки:
- отсутствие прерывания по таймеру внутри одного процесса,
- при использовании блокирующего системного запроса все остальные потоки блокируются,
- сложность реализации.
92
2. Поток в пространстве ядра. Наряду с таблицей процессов в пространстве ядра имеется таблица потоков.
3. Смешанная реализация. Потоки работают в режиме пользователя, но при системных вызовах переключаются в режим
ядра. Переключение в режим ядра и обратно является ресурсоемкой операцией и отрицательно сказывается на
производительности системы. Поэтому было введено понятие волокна — облегченного потока, выполняемого
исключительно в режиме пользователя. У каждого потока может быть несколько волокон. Подобный тип
многопоточности реализован в ОС Windows.
37.
Иерархическая структура ОС. Сравнение строгой и прозрачной иерархии.
ОС выполняет две по существу мало связанные функции: обеспечение пользователю-программисту удобств
посредством предоставления для него расширенной машины и повышение эффективности использования компьютера
путем рационального управления его ресурсами.
Операционные системы могут различаться особенностями реализации внутренних алгоритмов управления основными
ресурсами компьютера (процессорами, памятью, устройствами), особенностями использованных методов
проектирования, типами аппаратных платформ, областями использования и многими другими свойствами.
Структура ОС
Ядро (Kernel) — резидентная часть ОС, работающая в
режиме супервизора (обычно работает в режиме
физической адресации).
Интерфейсы системных вызовов (API –
Application Program Interface)
Динамически подгружаемые драйверы
физических и виртуальных устройств
Ядро ОС
Аппаратура
Динамически подгружаемые драйверы устройств:
• резидентные / нерезидентные
• работают в пользовательском / привилегированном режиме
Системный вызов — обращение к ОС за предоставление той или
иной функции ( возможности, услуги, сервиса).
Структура ОС
Пример структурной организации классической
системы UNIX
Программы пользователя
Уровень пользователя
Библиотеки
Интерфейс системных вызовов
Взаимодействие
между процессами
Файловая подсистема
Буфер
Планировщик
БайтБлокориентированные ориентированные
устройства
устройства
Драйверы устройств
Уровень аппаратного
обеспечения
Управление памятью
Монолитное ядро
Аппаратное обеспечение
93
Структура ОС
Управление
процессами
...
Файловая система
...
Драйвер устройства
Драйвер устройства
Микроядерная архитектура
...
Микроядро
Аппаратура
38.
Определение системы прерываний, общая схема ее реализации. Аппаратные и программные блоки
системы прерываний.
Прерывание означает временное прекращение основного процесса вычислений для выполнения некоторых
запланированных или незапланированных действий, вызываемых работой аппаратуры или программы.
Т.е. это процесс, временно переключающий микропроцессор на выполнение другой программы с последующим
возвратом к прерванной программе.
Нажимая клавишу на клавиатуре, мы инициируем немедленный вызов программы, которая распознает клавишу, заносит
ее код в буфер клавиатуры, из которого он считывается другой программой. Т.е. на некоторое время микропроцессор
прерывает выполнение текущей программы и переключается на программу обработки прерывания, так наз. обработчик
прерывания. После того, как обработчик прерывания завершит свою работу, прерванная программа продолжит
выполнение с точки, где было приостановлено ее выполнение.
Адрес программы-обработчика прерывания вычисляется по таблице векторов прерываний.
Механизм прерываний поддерживается на аппаратном уровне.
Классификация прерываний
В зависимости от источника, прерывания делятся на
аппаратные - возникают как реакция микропроцессора на физический сигнал от некоторого устройства (клавиатура,
системные часы, клавиатура, жесткий диск и т.д.), по времени возникновения эти прерывания асинхронны, т.е.
происходят в случайные моменты времени;
программные - вызываются искусственно с помощью соответствующей команды из программы (int), предназначены для
выполнения некоторых действий операционной системы, являются синхронными;
исключения - являются реакцией микропроцессора на нестандартную ситуацию, возникшую внутри микропроцессора
во время выполнения некоторой команды программы (деление на ноль, прерывание по флагу TF (трассировка)).
Общая классификация прерываний
внешние - вызываются внешними по отношению к микропроцессору событиями
(по существу - это группа аппаратных прерываний) Вложенных прерываний нет!
внутренние - возникают внутри микропроцессора во время вычислительного процесса (по существу - это
исключительные ситуации и программные прерывания).
Внешние прерывания возникают по сигналу какого-нибудь внешнего устройства.
Внешние прерывания подразделяются на немаскируемые и маскируемые.
В связи с тем, что существуют два специальных внешних сигнала среди входных сигналов процессора, при помощи
которых можно прервать выполнение текущей программы и тем самым переключить работу центрального процессора.
Это сигналы NMI (no mask interrupt, немаскируемое прерывание) и INTR (interrupt request, запрос на прерывание).
Маскируемые прерывания генерируются контроллером прерываний по заявке определенных периферийных устройств.
Контроллер поддерживает восемь уровней (линий) приоритета; к каждому уровню “привязано” одно периферийное
устройство. Именно маскируемые прерывания часто называют аппаратными прерываниями.
Немаскируемые прерывания (говорят, что оно одно, т.к. подается на вывод микропроцессора NMI) инициируют
источники, требующие безотлагательного вмешательства со стороны микропроцессора.
94
В реальном и защищенном режиме работы микропроцессора обработка прерываний осуществляется принципиально
разными методами.
Система прерываний. Аппаратные и программные средства системы прерываний
Система прерываний - это совокупность программных и аппаратных средств, реализующих механизм прерываний.
К аппаратным средствам системы прерываний относятся:
выводы микропроцессора - на них формируются сигналы, извещающие микропроцессор либо о том, что некоторое
внешнее устройство «просит уделить ему внимание» (INTR), либо о том, что требуется безотлагательная обработка
некоторого события или катастрофическая ошибка (NMI)
INTR - вывод для входного сигнала запроса на прерывание,
NMI - вывод для входного сигнала немаскируемого прерывания
INTA - вывод для выходного сигнала подтверждения получения сигнала прерывания;
программируемый контроллер прерываний 8259А (предназначен для фиксирования сигналов прерываний от восьми
различных внешних устройств; он выполнен в виде микросхемы; обычно используют две последовательно соединенные
микросхемы, поэтому кол-во возможных источников внешних прерываний до 15 плюс одно немаскируемое прер.;
именно он формирует номер вектора прерывания и выдает его шину данных);
внешние устройства (таймер, клавиатура, магнитные диски и т.п.)
К программным средствам системы прерываний Реального режима относятся:
таблица векторов прерываний.
Занимает первый килобайт ОП (адреса 00000h-003FFh).
Она содержит адреса (векторы - «векторы», т.к. два значения для указания адреса) обработчиков прерываний и состоит
из 256 (0..255) элементов по 4 байта каждый:
- 2 байта - новое значение для регистра IP 2 байта - новое значение для регистра CS.
Расположение таблицы векторов прерываний в процессорах i80286 и старше определяется значением регистра IDTR.
Таблица векторов прерываний инициализируется при запуске системы, но в принципе может быть изменена и
перемещена.
Каждый вектор имеет свой номер и называется номером прерывания.
два флага в регистре флагов flags/eflags:
IF (Interrupt Flag) - флаг прерывания. Предназначен для маскирования (запрещения) аппаратных прерываний. Если IF=1,
микропроцессор обрабатывает внешние прерывания, если = 0, то игнорирует;
TF(Trace Flag) - флаг трассировки. Если он=1, то микропроцессор переходит в режим покомандной работы. В этом
режиме в микропроцессоре генерируется внутреннее прерывание с номером 1;
машинные команды микропроцессора: int, into (прерывание по переполнению), iret, cli, sti
Обработка прерывания в реальном режиме
1) прекращение выполнения текущей программы;
Должно произойти так, чтобы потом вернуться и продолжить работу. Для этого необходимо сохранить содержимое
регистров, так как они являются ресурсами, разделяемыми между программами.
Обязательными для сохранения являются регистры cs, ip, flags (пара CS:IP содержит адрес команды, с которой
необходимо начать выполнение после возврата, flags - состояние флагов после выполнения последней команды
прерванной программы).
!!! Эти регистры сохраняются микропроцессором автоматически. Сохранение остальных регистров - должно
обеспечиваться программистом !!!
Наиболее удобным местом хранения регистров является стек.
После сохранения регистров в стеке микропроцессор сбрасывает бит флага IF (т.е.=0) (!!! В стеке при этом записан
регистр flags с еще установленным IF!!!) Этим предотвращается возможность возникновения вложенных внешних
прерываний и порча регистров исходной программы вследствие неконтролируемых действий со стороны программы обработчика вложенного прерывания. После того как необходимые действия по сохранению контекста завершены,
обработчик аппаратного прерывания может разрешить вложенные прерывания командой sti.
2) переход к выполнению и выполнение программы обработки прерывания;
Здесь определяется источник прерывания и вызывается соответствующий обработчик прерывания.
В реальном режиме микропроцессора допускается 256 источников - по кол-ву элементов таблицы векторов прерываний.
Структура элемента:
2 байта - значение смещения начала программы-обработчика прерывания от начала кодового сегмента
2 байта - значение базового адреса сегмента, в котором находится программа-обработчик.
Как определить адрес, по которому находится вектор прерывания с номером N ? смещение эл-та таблицы векторов
прерываний = N * 4
Полный размер таблицы ? 4*256=1024
Итак на втором этапе микропроцессор
По номеру источника прерывания определяет смещение в таблице векторов прерываний
95
Помещает первые два байта в регистр IP
Помещает вторые два байта в регистр CS
Передыет управление по адресу CS:IP
Далее выполняется сама программа обработки прерывания.
3) возврат управления прерванной программе.
Необходимо привести стек в состояние, в котором он был сразу после передачи управления данной процедуре. Для
этого программист должен указать необходимые действия по восстановлению регистров и очистке стека. !! Этот
участок необходимо защитить от возможного искажения содержимого регистров (в результате появления аппаратного
прерывания) с помощью команды cli.
Последние команды в в обработчике прерывания - sti, iret
sti - разрешить аппаратные прерывания (устанавливает флаг IF=1, не имеет операндов).
iret - извлечь последовательно три слова из стека и поместить их соответственно в регистры ip, cs, flags.
Схема обработки прерывания
39.
Понятие контекста процесса, операция переключения контекста. Программные и аппаратные
прерывания. Глубина вложенности прерываний.
Контекст процесса включает в себя содержимое адресного пространства задачи, выделенного процессу, а также
содержимое относящихся к процессу аппаратных регистров и структур данных ядра. С формальной точки зрения,
контекст процесса объединяет в себе пользовательский контекст, регистровый контекст и системный контекст.
Пользовательский контекст состоит из команд и данных процесса, стека задачи и содержимого совместно
используемого пространства памяти в виртуальных адресах процесса. Те части виртуального адресного пространства
процесса, которые периодически отсутствуют в оперативной памяти вследствие выгрузки или замещения страниц,
также включаются в пользовательский контекст.
Регистровый контекст состоит из следующих компонент:
Счетчика команд, указывающего адрес следующей команды, которую будет выполнять центральный процессор; этот
адрес является виртуальным адресом внутри пространства ядра или пространства задачи.
Регистра состояния процессора (PS), который указывает аппаратный статус машины по отношению к процессу. Регистр
PS, например, обычно содержит подполя, которые указывают, является ли результат последних вычислений нулевым,
положительным или отрицательным, переполнен ли регистр с установкой бита переноса и т.д. Операции, влияющие на
установку регистра PS, выполняются для отдельного процесса, потому-то в регистре PS и содержится аппаратный статус
машины по отношению к процессу. В других имеющих важное значение подполях регистра PS указывается текущий
уровень прерывания процессора, а также текущий и предыдущий режимы выполнения процесса (режим ядра/задачи).
96
По значению подполя текущего режима выполнения процесса устанавливается, может ли процесс выполнять
привилегированные команды и обращаться к адресному пространству ядра.
Указателя вершины стека, в котором содержится адрес следующего элемента стека ядра или стека задачи, в
соответствии с режимом выполнения процесса. В зависимости от архитектуры машины указатель вершины стека
показывает на следующий свободный элемент стека или на последний используемый элемент. От архитектуры машины
также зависит направление увеличения стека (к старшим или младшим адресам), но для нас сейчас эти вопросы
несущественны.
Регистров общего назначения, в которых содержится информация, сгенерированная процессом во время его
выполнения. Чтобы облегчить последующие объяснения, выделим среди них два регистра - регистр 0 и регистр 1 - для
дополнительного использования при передаче информации между процессами и ядром.
Системный контекст процесса имеет "статическую часть" (первые три элемента в нижеследующем списке) и
"динамическую часть" (последние два элемента). На протяжении всего времени выполнения процесс постоянно
располагает одной статической частью системного контекста, но может иметь переменное число динамических частей.
Динамическую часть системного контекста можно представить в виде стека, элементами которого являются
контекстные уровни, которые помещаются в стек ядром или выталкиваются из стека при наступлении различных
событий. Системный контекст включает в себя следующие компоненты:
Запись в таблице процессов, описывающая состояние процесса и содержащая различную управляющую информацию, к
которой ядро всегда может обратиться.
Часть адресного пространства задачи, выделенная процессу, где хранится управляющая информация о процессе,
доступная только в контексте процесса. Общие управляющие параметры, такие как приоритет процесса, хранятся в
таблице процессов, поскольку обращение к ним должно производиться за пределами контекста процесса.
Записи частной таблицы областей процесса, общие таблицы областей и таблицы страниц, необходимые для
преобразования виртуальных адресов в физические, в связи с чем в них описываются области команд, данных, стека и
другие области, принадлежащие процессу. Если несколько процессов совместно используют общие области, эти области
входят составной частью в контекст каждого процесса, поскольку каждый процесс работает с этими областями
независимо от других процессов. В задачи управления памятью входит идентификация участков виртуального
адресного пространства процесса, не являющихся резидентными в памяти.
Стек ядра, в котором хранятся записи процедур ядра, если процесс выполняется в режиме ядра. Несмотря на то, что все
процессы пользуются одними и теми же программами ядра, каждый из них имеет свою собственную копию стека ядра
для хранения индивидуальных обращений к функциям ядра. Пусть, например, один процесс вызывает функцию creat и
приостанавливается в ожидании назначения нового индекса, а другой процесс вызывает функцию read и
приостанавливается в ожидании завершения передачи данных с диска в память. Оба процесса обращаются к функциям
ядра и у каждого из них имеется в наличии отдельный стек, в котором хранится последовательность выполненных
обращений. Ядро должно иметь возможность восстанавливать содержимое стека ядра и положение указателя вершины
стека для того, чтобы возобновлять выполнение процесса в режиме ядра. В различных системах стек ядра часто
располагается в пространстве процесса, однако этот стек является логически-независимым и, таким образом, может
помещаться в самостоятельной области памяти. Когда процесс выполняется в режиме задачи, соответствующий ему
стек ядра пуст.
Динамическая часть системного контекста процесса, состоящая из нескольких уровней и имеющая вид стека, который
освобождается от элементов в порядке, обратном порядку их поступления. На каждом уровне системного контекста
содержится информация, необходимая для восстановления предыдущего уровня и включающая в себя регистровый
контекст предыдущего уровня.
Ядро помещает контекстный уровень в стек при возникновении прерывания, при обращении к системной функции или
при переключении контекста процесса. Контекстный уровень выталкивается из стека после завершения обработки
прерывания, при возврате процесса в режим задачи после выполнения системной функции, или при переключении
контекста. Таким образом, переключение контекста влечет за собой как помещение контекстного уровня в стек, так и
извлечение уровня из стека: ядро помещает в стек контекстный уровень старого процесса, а извлекает из стека
контекстный уровень нового процесса. Информация, необходимая для восстановления текущего контекстного уровня,
хранится в записи таблицы процессов.
На изображены компоненты контекста процесса. Слева на рисунке изображена статическая часть контекста. В нее
входят: пользовательский контекст, состоящий из программ процесса (машинных инструкций), данных, стека и
разделяемой памяти (если она имеется), а также статическая часть системного контекста, состоящая из записи таблицы
процессов, пространства процесса и записей частной таблицы областей (информации, необходимой для трансляции
виртуальных адресов пользовательского контекста). Справа на рисунке изображена динамическая часть контекста. Она
имеет вид стека и включает в себя несколько элементов, хранящих регистровый контекст предыдущего уровня и стек
ядра для текущего уровня. Нулевой контекстный уровень представляет собой пустой уровень, относящийся к
пользовательскому контексту; увеличение стека здесь идет в адресном пространстве задачи, стек ядра недействителен.
Стрелка, соединяющая между собой статическую часть системного контекста и верхний уровень динамической части
97
контекста, означает то, что в таблице процессов хранится информация, позволяющая ядру восстанавливать текущий
контекстный уровень процесса.
Рисунок Компоненты контекста процесса
Процесс выполняется в рамках своего контекста или, если говорить более точно, в рамках своего текущего контекстного
уровня. Количество контекстных уровней ограничивается числом поддерживаемых в машине уровней прерывания.
Например, если в машине поддерживаются разные уровни прерываний для программ, терминалов, дисков, всех
остальных периферийных устройств и таймера, то есть 5 уровней прерывания, то, следовательно, у процесса может быть
не более 7 контекстных уровней: по одному на каждый уровень прерывания, 1 для системных функций и 1 для
пользовательского контекста. 7 уровней будет достаточно, даже если прерывания будут поступать в "наихудшем" из
возможных порядков, поскольку прерывание данного уровня блокируется (то есть его обработка откладывается
центральным процессором) до тех пор, пока ядро не обработает все прерывания этого и более высоких уровней.
Несмотря на то, что ядро всегда исполняет контекст какого-нибудь процесса, логическая функция, которую ядро
реализует в каждый момент, не всегда имеет отношение к данному процессу. Например, если возвращая данные,
дисковое запоминающее устройство посылает прерывание, то прерывается выполнение текущего процесса и ядро
обрабатывает прерывание на новом контекстном уровне этого процесса, даже если данные относятся к другому
процессу. Программы обработки прерываний обычно не обращаются к статическим составляющим контекста процесса
и не видоизменяют их, так как эти части не связаны с прерываниями.
Операция переключения контекста
Ядро разрешает производить переключение контекста в четырех случаях: когда процесс приостанавливает свое
выполнение, когда он завершается, когда он возвращается после вызова системной функции в режим задачи, но не
является наиболее подходящим для запуска, или когда он возвращается в режим задачи после завершения ядром
обработки прерывания, но так же не является наиболее подходящим для запуска. Ядро поддерживает целостность и
согласованность своих внутренних структур данных, запрещая произвольно переключать контекст. Прежде чем
переключать контекст, ядро должно удостовериться в согласованности своих структур данных: то есть в том, что
сделаны все необходимые корректировки, все очереди выстроены надлежащим образом, установлены соответствующие
блокировки, позволяющие избежать вмешательства со стороны других процессов, что нет излишних блокировок и т.д.
Например, если ядро выделяет буфер, считывает блок из файла и приостанавливает выполнение до завершения передачи
данных с диска, оно оставляет буфер заблокированным, чтобы другие процессы не смогли обратиться к буферу. Но если
процесс исполняет системную функцию link, ядро снимает блокировку с первого индекса перед тем, как снять ее со
второго индекса, и тем самым предотвращает возникновение тупиковых ситуаций (взаимной блокировки).
Ядро выполняет переключение контекста по завершении системной функции exit, поскольку в этом случае больше
ничего не остается делать. Кроме того, переключение контекста допускается, когда процесс приостанавливает свою
98
работу, поскольку до момента возобновления может пройти немало времени, в течение которого могли бы выполняться
другие процессы. Переключение контекста допускается и тогда, когда процесс не имеет преимуществ перед другими
процессами при исполнении, с тем, чтобы обеспечить более справедливое планирование процессов: если по выходе
процесса из системной функции или из прерывания обнаруживается, что существует еще один процесс, который имеет
более высокий приоритет и ждет выполнения, то было бы несправедливо оставлять его в ожидании.
Процедура переключения контекста похожа на процедуры обработки прерываний и обращения к системным функциям,
если не считать того, что ядро вместо предыдущего контекстного уровня текущего процесса восстанавливает
контекстный уровень другого процесса. Причины, вызвавшие переключение контекста, при этом не имеют значения. На
механизм переключения контекста не влияет и метод выбора следующего процесса для исполнения.
Последовательность шагов, выполняемых при переключении контекста
Принять решение относительно необходимости переключения контекста и его допустимости в данный момент.
Сохранить контекст "прежнего" процесса.
Выбрать процесс, наиболее подходящий для исполнения, используя алгоритм диспетчеризации процессов.
Восстановить его контекст.
Текст программы, реализующей переключение контекста в системе UNIX, из всех программ операционной системы
самый трудный для понимания, ибо при рассмотрении обращений к функциям создается впечатление, что они в одних
случаях не возвращают управление, а в других - возникают непонятно откуда. Причиной этого является то, что ядро во
многих системных реализациях сохраняет контекст процесса в одном месте программы, но продолжает работу,
выполняя переключение контекста и алгоритмы диспетчеризации в контексте "прежнего" процесса. Когда позднее ядро
восстанавливает контекст процесса, оно возобновляет его выполнение в соответствии с ранее сохраненным контекстом.
Чтобы различать между собой те случаи, когда ядро восстанавливает контекст нового процесса, и когда оно продолжает
исполнять ранее сохраненный контекст, можно варьировать значения, возвращаемые критическими функциями, или
устанавливать искусственным образом текущее значение счетчика команд.
На Рисунке 6.16 приведена схема переключения контекста. Функция save_context сохраняет информацию о контексте
исполняемого процесса и возвращает значение 1. Кроме всего прочего, ядро сохраняет текущее значение счетчика
команд (в функции save_context) и значение 0 в нулевом регистре при выходе из функции. Ядро продолжает исполнять
контекст "прежнего" процесса (A), выбирая для выполнения следующий процесс (B) и вызывая функцию resume_context
для восстановления его контекста. После восстановления контекста система выполняет процесс B; прежний процесс (A)
больше не исполняется, но он оставил после себя сохраненный контекст. Позже, когда будет выполняться переключение
контекста, ядро снова изберет процесс A (если только, разумеется, он не был завершен). В результате восстановления
контекста A ядро присвоит счетчику команд то значение, которое было сохранено процессом A ранее в функции
save_context, и возвратит в регистре 0 значение 0. Ядро возобновляет выполнение процесса A из функции save_context,
пусть даже при выполнении программы переключения контекста оно не добралось еще до функции resume_context. В
конечном итоге, процесс A возвращается из функции save_context со значением 0 (в нулевом регистре) и возобновляет
выполнение после строки комментария "возобновление выполнение процесса начинается отсюда".
if (save_context()) /* сохранение контекста выполняющегося
процесса */
{
/* выбор следующего процесса для выполнения */
resume_context(new_process);
/* сюда программа не попадает ! */
}
/* возобновление выполнение процесса начинается отсюда */
Рисунок 6.16. Псевдопрограмма переключения контекста
Программные и аппаратные прерывания.
Глубина вложенности прерываний
Глубина прерывания - это максимальное число программ, которые могут прерывать друг друга. Если после перехода к
прерывающей программе и вплоть до ее окончания прием других запросов запрещается, то говорят, что система имеет
глубину прерывания, равную 1.
Глубина равна n, если допускается последовательное прерывание до n программ. Глубина прерывания обычно совпадает
с числом уровней приоритета в системе прерываний. Системы с большим значением глубины прерывания обеспечивают
более быструю реакцию на срочные запросы.
99
40.
Двухпросмотровая схема работы ассемблера, его таблицы и основные функции.
Язык ассемблера — это машинно-зависимый язык низкого уровня, в котором короткие мнемонические имена
соответствуют отдельным машинным командам. Используется для представления в удобочитаемой форме программ,
записанных в машинном коде. Перевод программы с языка ассемблера на машинный язык осуществляется специальной
программой, которая называется ассемблером и является, по сути, простейшим транслятором.
Достоинства языка ассемблера
Использование меньшего количества команд и обращений в память, что позволяет увеличить скорость и уменьшить
размер программы.
Обеспечение максимального использования специфических возможностей конкретной платформы, что также позволяет
создавать более эффективные программы с меньшими затратами ресурсов.
При программировании на ассемблере возможен непосредственный доступ к аппаратуре, в том числе портам вводавывода, регистрам процессора, и др.
] Недостатки языка ассемблера
В силу своей машинной ориентации («низкого» уровня) человеку по сравнению с языками программирования высокого
уровня сложнее читать и понимать программу, соответственно усложняются программирование и отладка, растет
трудоемкость, велика вероятность внесения ошибок. В значительной степени возрастает сложность совместной
разработки.
Как правило, меньшее количество доступных библиотек по сравнению с современными индустриальными языками
программирования.
Отсутствует переносимость программ на ЭВМ с другой архитектурой и системой команд (кроме двоично совместимых).
Применение
Исторически можно рассматривать ассемблер как второе поколение языков программирования ЭВМ (если первым
считать машинный код). Языки ассемблера сохраняют свою нишу, обуславливаемую их уникальными преимуществами
в части эффективности и возможности полного использования специфических средств конкретной платформы.
На ассемблере пишутся программы или фрагменты программ, для которых критически важны:
быстродействие (драйверы, игры);
объем используемой памяти (загрузочные сектора, встраиваемое (embedded) программное обеспечение, программы для
микроконтроллеров и процессоров с ограниченными ресурсами, вирусы, программные защиты).
С использованием программирования на ассемблере производятся:
Оптимизация критичных к скорости участков программ написанных на языке высокого уровня, таком как C++.
Создание операционных систем (ОС). ОС часто пишут на Си, языке, который специально был создан для написания
одной из первых версий Unix. Аппаратно зависимые участки кода, такие, как загрузчик ОС, уровень абстрагирования от
железа — HAL и ядро, часто пишутся на ассемблере.
Программирование микроконтроллеров (МК) и других встраиваемых процессоров.
Создание драйверов. Некоторые участки драйверов, взаимодействующие с железом, программируют на ассемблере
Создание антивирусов и других защитных программ.
Написание трансляторов языков программирования.
Существует целый ряд основных функций, например таких, как трансляция мнемонических кодов операций в их
эквиваленты на машинном языке или присваивание машинных адресов символическим меткам, которые должны
выполняться любым ассемблером.
Однако за пределами этого базового уровня возможности, предоставляемые ассемблерами, а также схемы их построения
сильно зависят как от входного языка, так и от языка машины. Одним из аспектов такой машинной зависимости,
естественно, являются имеющиеся различия в форматах машинных команд и кодах операций. С другой стороны,
некоторые средства языка ассемблера (и соответствующих ассемблеров) не имеют прямой связи со структурой машины.
Их выбор является в известном смысле произвольным и определяется разработчиком языка ассемблера.
Машинно-зависимые характеристики ассемблера
1. Форматы команд и способы адресации
Рассмотрим трансляцию предложений исходной программы УУМ/ДС в соответствующее им объектное представление.
Трансляция команд вида регистр-регистр не представляет никаких новых проблем. Ассемблер должен просто
преобразовать мнемонические коды операций в их машинное представление и заменить мнемонические имена
регистров на их числовые эквиваленты. Для трансляции большинства команд вида память-регистр используется
относительный способ адресации (либо относительно счетчика команд, либо относительно базы). В любом случае
100
ассемблер должен вычислить смещение, которое является составной частью объектной команды. Если нельзя применить
ни один из способов относительной адресации и нет указания об использовании расширенного формата, то правильная
трансляция команды невозможна. В этом случае ассемблер должен выдать сообщение об ошибке.
Трансляция команд, в которых используются непосредственные операнды, проще, поскольку в них не нужна
организация ссылок на оперативную память. Все, что требуется, это преобразовать операнд во внутреннее
представление и занести его в команду.
Ассемблирование команд, использующих косвенную адресацию, (фактически не представляет ничего нового. Для того
чтобы получить требуемый целевой адрес, вначале обычным образом вычисляется смещение. Затем в разряд n
генерируемой команды устанавливается признак косвенной адресации. Примером использования адресации
относительно счетчика команд в комбинации с косвенной адресацией является предложение в строке 70.
2. Перемещение программ
Очень часто желательно иметь возможность одновременно выполнять несколько программ, разделяющих между собой
оперативную память и другие ресурсы машины. Если бы нам заранее было точно известно, какие программы будут
выполняться одновременно, то мы могли бы во время ассемблирования назначить каждой программе подходящие
адреса таким образом, чтобы не было ни взаимного перекрытия программ, ни потери места в оперативной памяти.
Однако чаще всего столь точное планирование выполнения программ не пригодно с практической точки зрения.
Поэтому хотелось бы иметь возможность загружать программу на любое место в оперативной памяти, где для нее
имеется достаточно пространства. В этом случае фактический начальный адрес программы не известен до момента
загрузки.
Поскольку ассемблеру не известен фактический адрес начала загрузки, он не может выполнить необходимую настройку
адресов, используемых программой. Однако ассемблер может указать загрузчику те части объектной программы,
которые нуждаются в настройке при загрузке. Объектная программа, содержащая информацию, необходимую для
выполнения подобной модификации, называется перемещаемой программой.
2. Машинно-независимые характеристики ассемблера
1. Литералы
Очень часто бывает удобно иметь возможность записывать значения константы, используемой в качестве операнда,
непосредственно в команде, где она используется. Это позволяет отказаться от использования отдельного предложения
для определения константы и соответствующей ей метки. Такой операнд называется литеральным (literal), поскольку
значение константы задается в виде строки символов.
В предложении 45 001A ENDFIL LDA =С'ЕОF' 032010 литерал определяет 3-байтовый операнд, значением
которого является строка символов EOF.
2. Средства определения имен
имя EQU значение
Данное предложение определяет некоторое имя (т. е. вносит его в SYMTAB) и присваивает ему значение. Значение
может задаваться в виде константы пли выражения, в котором могут использоваться константы и ранее определенные
имена. Одним из общих применений EQU является введение символических имен вместо числовых значений, чтобы
упростить чтение программы. Другое общее применение EQU заключается в определении мнемонических имен для
регистров.
Имеется еще одна общеупотребительная директива ассемблера, позволяющая косвенно задавать значения
символическим именам. Обычно эта директива называется ORG (от ORiGin). Она имеет следующий вид:
ORG значение
где значение представляет собой константу или выражение, в котором могут быть использованы константы и ранее
определенные имена. Если во время ассемблирования программы встречается данное предложение, то заданное им
значение заносится в счетчик размещений (LOCCTR). Поскольку для определения значений имен используется
LOCCTR, то предложение ORG распространяет свое влияние на все последующие определения меток.
3. Выражения
В большинстве ассемблеров наряду с одиночными термами(константы, метки и т. п.) разрешается использовать
выражения. Каждое такое выражение вычисляется ассемблером во время трансляции, а затем полученное значение
используется в виде адреса или непосредственного операнда.
Обычно допускаются арифметические выражения, которые строятся по стандартным правилам с помощью операций +,,*,/. Деление чаще всего определяется как целочисленное. В выражениях можно использовать константы, метки и
специальные термы. Одним из таких общеупотребительных специальных термов является терм, ссылающийся на
текущую величину счетчика размещений (часто обозначается как *). Значением этого терма является адрес, который
будет присвоен очередной команде или области данных.
4. Программные блоки
Многие ассемблеры предоставляют более гибкие средства обработки исходной программы и соответствующего ей
объектного кода. Одни из этих средств позволяют располагать сгенерированные машинные команды и данные в
101
объектной программе в порядке, отличном от порядка, в котором расположены соответствующие им исходные
предложения. Другие позволяют создавать несколько независимых частей объектной программы, Каждая из этих частей
сохраняет свою индивидуальность и обрабатывается загрузчиком отдельно от других частей. Фактически в некоторых
системах одни и те же средства языка ассемблера используются для обеспечения обеих этих логически различных
функций.
2.3.5. Управляющие секции и связывание программ
Управляющая секция - это часть программы, которая после ассемблирования сохраняет свою индивидуальность и может
загружаться и перемещаться независимо от других. В отдельные управляющие секции чаще всего выделяются
подпрограммы или другие логические подразделы программы. Программист может отдельно ассемблировать и
загружать каждую из таких управляющих секций. Достигаемая за счет этого гибкость является основным
преимуществом их использования. Поскольку управляющие секции образуют логически связанные части программы,
то, следовательно, необходимо предоставить некоторые средства для их связывания (linking) друг с другом. Например,
команды одной управляющей секции должны иметь возможность ссылаться на команды или области данных,
расположенные в другой секции. Такие ссылки нельзя обрабатывать обычным образом, поскольку управляющие секции
загружаются и перемещаются независимо друг от друга и ассемблеру ничего не известно о том, где будут расположены
другие управляющие секции во время исполнения программы. Такие ссылки между управляющими секциями
называются внешними ссылками (external references). Для каждой внешней ссылки ассемблер генерирует информацию,
которая дает возможность загрузчику выполнить требуемое связывание программ.
От программных блоков управляющие секции отличаются тем, что они обрабатываются ассемблером независимо друг
от друга.
ДВУПРОСМОТРОВЫЙ АЛГОРИТМ
Начнем с некоторых упрощающих предположений. Будем считать, что наш макропроцессор функционально независим
от основного компилятора и его текст будет передаваться этому компилятору. Сначала не разрешим макровызовы и
макроопределения внутри макроопределений.
Макропроцессор, как и язык ассемблера, просматривает и обрабатывает строки текста. Но в языке все строки связаны
адресацией - одна строка может ссылаться на другую при помощи адреса или имени, которое должно быть “известно”
ассемблеру. Более того, адрес присваеваемый каждой отдельной строке зависит от содержимого, количества и адресов
предшествующих строк.
Если рассматривать макроопределение, как единый объект, то можно сказать, что строки нашего макроопределения не
так сильно взаимосвязаны. Макроопределения не могут ссылаться на объекты вовне этого макроопределения.
Предположим, что в теле макроопределения есть строка INCR X, причем перед этой командой параметр Х получил
значение 10.
Макропроцессор не производит синтаксический анализ, а производит простую текстовую подстановку вместо “Х”
подставляется “10”.
Наш алгоритм будет выполнять 2 систематических просмотра входного текста. В первый проход будут
детерминированы все макроопределения, во второй проход будут открыты все ссылки на макросы. Так же, как и язык
ассемблера не может выполнить ссылку на символ до того момента, как он встретит этот символ, язык макрокоманд не
может выполнить расширение до тех пор, пока не встретит соответствующее макроопределение. Во время первого
просмотра проверяется каждый код операции, макроопределения запоминаются в таблице макроопределений, а копия
исходного текста без макроопределений запоминается во внешней памяти, для использования ее при втором проходе.
Помимо таблицы макроопределений во время первого прохода будет также таблица имен, во второй проход она будет
использоваться для выделения макроопераций и расширения их до текста соответствующего макроопределения.
ДАННЫЕ ДЛЯ ПЕРВОГО ПРОСМОТРА
1. ВХТ - Входной текст
2. ВЫХ1 - Выходная копия текста для использования во второй проход.
3. МДТ - таблица макроопределений, в которой хранятся тела макроопределений
4. МНТ - таблица имен, необходимая для хранения имен макрокоманд, определенных в МНТ
5. МДТС - счетчик для таблицы МДТ
6. МНТС - счетчик для таблицы МНТ
7. АЛА - массив списка параметров для подстановки индексных маркеров вместо формальных параметров, перед
запоминанием определения.
ДАННЫЕ ДЛЯ ВТОРОГО ПРОСМОТРА
1. ВЫХ1 - Выходная копия текста после первого прохода
2. ВЫХ2 - Выходная копия текста после второго прохода
3. МДТ - таблица макроопределений, в которой хранятся тела макроопределений
4. МНТ - таблица имен, необходимая для хранения имен макрокоманд, определенных в МНТ
5. МДТС - счетчик для таблицы МДТ
6. МНТС - счетчик для таблицы МНТ
102
7. АЛА - массив списка параметров для подстановки индексных маркеров вместо формальных параметров, перед
запоминанием определения.
АЛГОРИТМ
Ниже приведена формальная запись соответствующих алгоритмов обработки макроопределений двухпросмотровым
способом.
Каждый из алгоритмов осуществляет построчный просмотр входного текста.
ПЕРВЫЙ ПРОСМОТР - МАКРООПРЕДЕЛЕНИЯ: Алгоритм первого просмотра проверяет каждую строку входного
текста. Если она представляет собой псевдооперацию MACRO, то все следующие за ней строки запоминаются в
ближайших свободных ячейках МДТ. Первая строка макроопределения - это имя самого макроса. Имя заносится в
таблицу имен МНТ с индексом этой строки в МДТ. При этом происходит также подстановка номеров формальных
параметров, вместо их имен.
Если в течение просмотра встречается команда END, то это означает, что весь текст обработан, и управление можно
передавать второму просмотру для обработки макрокоманд.
ВТОРОЙ ПРОСМОТР - РАСШИРЕНИЕ МАКРОКОМАНД: Алгоритм второго просмотра проверяет мнемонический
код каждого предложения. Если это имя содержится в МНТ, то происходит обработка макропредложения по
следующему правилу: из таблицы МНТ берется указатель на начало описания макроса в МДТ.
Макропроцессор готовит массив списка АЛА содержащий таблицу индексов формальных параметров и
соответствующих операндов макрокоманды. Чтение производится из МДТ, после чего в прочитанную строку
подставляются
необходимые параметры, и полученная таким образом строка записывается в ВЫХТ2. Когда встречается директива
END, текст полученного кода передается для компиляции ассемблеру.
Первый просмотр
Начало алгоритма
МДТС = 0
МНТС = 0
ФЛАГ ВЫХОДА = 0
цикл пока (ФЛАГ ВЫХОДА == 0) {
чтение следующей строки ВХТ
если !(операция MACRO) {
вывод строки в ВЫХТ1
если (операция END) ФЛАГ ВЫХОДА = 1
}
иначе {
чтение идентификатора
запись имени и индекса в МНТ
МНТС ++
приготовить массив списка АЛА
запись имени в МДТ
МДТС ++
цикл {
чтение следующей строки ВХТ
подстановка индекса операторов
добавление в МДТ
МДТС ++
} пока !(операция MEND)
}
}
переход ко второму проходу
конец алгоритма
Второй просмотр
Начало алгоритма
ФЛАГ ВЫХОДА = 0
цикл пока (ФЛАГ ВЫХОДА == 0) {
чтение строки из ВЫХТ1
НАЙДЕНО = поиск кода в МНТ
если !(НАЙДЕНО) {
запись в ВЫХТ2 строки
если (операция END) {
103
ФЛАГ ВЫХОДА = 1
}
}
иначе {
УКАЗАТЕЛЬ = индекс из МНТ
Заполнение списка параметров АЛА
цикл {
УКАЗАТЕЛЬ ++
чтение след. строки из МДТ
подстановка параметров
вывод в ВЫХТ2
} пока !(операция MEND)
}
}
переход к компиляции
конец алгоритма
2.4.1. Двухпросмотровый ассемблер с оверлейной структурой
Как мы видели, в большинстве ассемблеров процесс обработки исходной программы делится на два
просмотра. Внутренние таблицы и подпрограммы, которые используются только во время первого просмотра,
становятся ненужными после его завершения. Многие подпрограммы и таблицы используются только для одного
просмотра и никогда не требуются для другого. В то же время некоторые таблицы (например, SYMTAB) и
подпрограммы (например, поиск в SYMTAB) используются в обоих просмотрах.
На рис. 2.18 представлена общая структура двухпросмотрового ассемблера. Этот ассемблер состоит из трех
сегментов, образующих дерево. Корневой сегмент содержит простую управляющую программу, функцией которой
является поочередный вызов двух других сегментов (Просмотр 1 и Просмотр 2). Корневой сегмент содержит таблицы и
подпрограммы, необходимые для обоих просмотров.
Поскольку сегменты Просмотр 1 и Просмотр 2 никогда не требуются одновременно, то во время работы
ассемблера они могут занимать одно и то же пространство оперативной памяти. Вначале в память загружается корневой
сегмент и сегмент
Корневой
сегмент
Сегмент
Просмотр 1
Управляющая
программа
Общие
таблицы
и подпрограммы
Подпрограммы
и таблицы
первого
просмотра
Подпрограммы
и таблицы
Сегмент
второго
Просмотр 2
просмотра
Рис. 2.18. Структура двухпросмотрового ассемблера.
Просмотр 1, и ассемблер выполняет первый просмотр. После его завершения на место сегмента Просмотр 1 загружается
104
Максимальная
память, требуемая при
оверлейной
загрузке
Управляющая
программа
Общие
таблицы
и подпрограммы
Подпрограммы
первого
просмотра
Таблицы
первого
просмотра
Объем
памяти
занимаемый
всеми под
программами
и таблицами
ассемблера
Управляющая
программа
Резидентная
часть
Общие
таблицы
и подпрограммы
Подпрограммы
второго
просмотра
Загружаются
на одно и то
же место
в оперативной
памяти
второго
просмотра
Таблицы
Рис. 2.19. Двухпросмотровый ассемблер с оверлейной структурой.
сегмент Просмотр 2. После этого ассемблер выполняет второй просмотр ассемблируемой программы (или
промежуточного файла) и завершает свою работу. Этот процесс показан на рис. 2.19. Обратите внимание, что при
использовании оверлейной структуры ассемблеру требуется значительно меньше оперативной памяти, чем если бы
одновременно загружались сегменты обоих просмотров. Во многих двухпросмотровых ассемблерах этот прием
используется для сокращения требуемого объема оперативной памяти.
Программа, построенная подобным образом, называется оверлейной программой или программой с
перекрытием, так как во время ее исполнения некоторые из ее сегментов перекрывают другие. В гл. 3 мы более
подробно обсудим оверлейные программы и рассмотрим, как они обрабатываются загрузчиком и сервисными
процедурами операционной системы.
41.
Управляющие секции ассемблера: цель и способы задания в исходной программе, сохранение в формате
объектной программы.
1. Секции
Секция объектного файла должна занимать непрерывный участок памяти и является минимальным объектом, который подвергается перемещению. Координатами секции являются ее начальный адрес и
длина. В начале файла располагаются заголовки секций, описывающие все секции этого файла. В процессе обработки из секций
входных файлов вырабатываются выходные секции, которые могут
содержать команды, данные или смесь того и другого. Как между
входными, так и между выходными секциями могут быть пустоты
("дыры"), однако в пределах одной выходной секции память выделяется последовательно и с пустотами перекрываться не может.
2. Адреса
105
Применительно к редактированию внешних связей термин физический
адрес трактуется нестандартным образом. Физический адрес секции
или имени определяется как смещение относительно начала (нулевого адреса) адресного пространства. Физический адрес объекта
не обязательно совпадает с тем адресом, по которому объект будет помещен во время выполнения. Так, в системах со страничной
виртуальной памятью адрес есть смещение относительно нулевого
адреса виртуальной памяти, которое затем преобразуется аппаратурой и/или операционной системой.
3. Связывание
Часто бывает необходимо, чтобы начало секции приходилось на определенный, заранее известный адрес. Установление соответствия
между объектом и начальным адресом называется связыванием. В
таком случае говорят, что объект связан с определенным адресом.
Обычно связыванию подвергаются выходные секции, однако имеется
возможность связывать с адресами и некоторые абсолютные глобальные имена, для чего используется оператор присваивания управляющего языка ld(1).
УПРАВЛЯЮЩИЙ ЯЗЫК РЕДАКТОРА СВЯЗЕЙ
Выражения
В выражениях могут использоваться глобальные имена, константы и
большинство основных операций языка C (см. Синтаксис управляющего языка редактора связей). Как и в языке C, числовые константы считаются десятичными, если только им не предшествует 0
для восьмеричных и 0x для шестнадцатеричных. Все числа трактуются как длинные целые. Имена могут содержать прописные и
строчные буквы, цифры и символ подчеркивания, _. Если имя появляется внутри выражения, то в качестве значения используется
его адрес. Редактор связей не просматривает таблицу имен и не
пытается выяснить значения переменных, размерности массивов и
т.п.
Для распознавания имен, чисел, операций и т.п. редактор связей
использует сканер, сгенерированный с помощью утилиты lex(1).
Ниже перечислены слова, которые сканер считает зарезервированными, и которые нельзя поэтому использовать в качестве имен или
названий секций:
ADDR BLOCK GROUP
ALIGN COMMON INFO
ASSIGN COPY LENGTH
BIND DSECT MEMORY
NEXT RANGE SPARE
NOLOAD REGIONS PHY
ORIGIN SECTIONS TV
OVERLAY SIZEOF
addr block length origin sizeof
align group next phy
spare
assign l
o
range
bind len org s
В следующей таблице приведены, в порядке убывания приоритета,
знаки допустимых операций:
~------------------------Ѓ Знак операции
Ѓ
------------------------Ѓ ! ~ - (унарный минус) Ѓ
Ѓ*/%
Ѓ
Ѓ + - (бинарный минус) Ѓ
Ѓ >> <<
Ѓ
Ѓ == != > < <= >=
Ѓ
Ѓ&
Ѓ
Ѓ|
Ѓ
106
Ѓ &&
Ѓ
Ѓ ||
Ѓ
Ѓ = += -= *= /=
Ѓ
Перечисленные операции имеют тот же смысл, что и в языке C.
Операции, знаки которых находятся на одной строке, имеют одинаковый приоритет.
42.
Определение и основные функции макропроцессора, в том числе машино-зависимые и -независимые
функции.
Макроязыки и соответствующие им макропроцессоры представляют собой самостоятельную форму языков
программирования. При использовании вместе с ассемблером, макропроцессор является для программиста полезным
инструментом и по существу, позволяет ему самому определять свой язык высокого уровня.
Существуют четыре основных задачи, решаемых макропроцессором:
Распознавание макроопределений
Хранение макроопределений
Распознавание макрокоманд
Расширение макрокоманд и подстановка параметров
Макропроцессор в ассемблере может быть реализован несколькими способами:
Независимый двухпросмотровый ассемблер
Независимый однопросмотровый ассемблер
Процессор, совмещенный с первым проходом стандартного двухпросмотрового ассемблера.
Определение (не по ГОСТ)
Макропроцессор - модуль системного ПО, позволяющий расширить возможности языка Ассемблера за счет
предварительной обработки исходного текста программы.
Определение, которое дает ГОСТ не представляется удачным, так как оно говорит только о сокращении объема записи,
а это лишь одна из возможностей обеспечиваемых Макропроцессором. Хотя Макропроцессоры являются обязательным
элементом всех современных языков Ассемблеров, аналогичные модули (Препроцессоры) могут быть и для других
языков, в том числе и для языков высокого уровня. Для одних языков (Pascal, PL/1) применение средств препроцессора
является опционным, для других (C, C++) - обязательным.
Важно понимать, что Макропроцессор осуществляет обработку исходного текста. Он "не вникает" в синтаксис и
семантику операторов и переменных языка Ассемблера, не знает (как правило) имен, употребляемых в программе, а
выполняет только текстовые подстановки. В свою очередь, Ассемблер обрабатывает исходный текст, не зная, написан
тот или иной оператор программистом "своей рукой" или сгенерирован Макропроцессором.
По тому, насколько Препроцессор (Макропроцессор) и Транслятор (Ассемблер) "знают" о существовании друг друга, их
можно разделить на три категории:
107
-Независимые. Препроцессор составляет отдельный программный модуль (независимую программу), выполняющую
просмотр (один или несколько) исходного модуля и формирующую новый файл исходного модуля, поступающий на
вход Транслятора (пример - язык C).
-Слабосвязанные. Препроцессор составляет с Транслятором одну программу, но разные секции этой программы. Если
в предыдущем случае Препроцессор обрабатывает весь файл, а затем передает его Транслятору, то в этом случае
единицей обработки является каждый оператор исходного текста: он обрабатывается секцией Препроцессора, а затем
передается секции Транслятора. (Пример - HLASM для S/390).
-Сильносвязанные. То же распределение работы, что и в предыдущем случае, но Препроцессор использует некоторые
общие с Транслятором структуры данных. Например, Макропроцессор может распознавать имена, определенные в
программе директивой EQU и т.п. (Пример - MASM, TASM).
Основные термины, связанные с данными, обрабатываемыми Макропроцессором: макровызов (или макрокоманда),
макроопределение, макрорасширение.
Макровызов или макрокоманда или макрос - оператор программы, который подлежит обработке Макропроцессором
(как мы дальше увидим, Макропроцессор обрабатывает не все операторы, а только ему адресованные).
Макроопределение - описание того, как должна обрабатываться макрокоманда, макроопределение может находиться в
том же исходном модуле, что и макрокоманда или в библиотеке макроопределений.
Макрорасширение - результат выполнения макровызова, представляющий собой один или несколько операторов языка
Ассемблера, подставляемых в исходный модуль вместо оператора макровызова. Пример обработки макровызова
показан на рисунке.
Структуры данных Макропроцессора
Функцией макропроцессоров является подготовка текста для последующей обработки. Другими словами,
макропроцессоры являются частью славного семейства препроцессоров. При работе макропроцессоров из тела текста
извлекаются макроопределения, задающие имена и тела макросов, и макроподстановки с параметрами, которые
108
заменяются на тело макроса с выполнением подстановки параметров. Типичным примером макропроцессора является
препроцессор языка Cи.
Макропроцессоры позволяют достаточно просто расширить возможности языка. Добавляя директивы макропроцессора,
вы получаете возможность конфигурирования программы в зависимости от внешних условий, сокращенную нотацию
для стандартных действий и т.п. Иногда набор макро позволяет вам иметь специализированный язык для каких-либо
целей.
43.
Таблицы и основные функции двухпросмотрового процесса связывания объектных модулей.
СМОТРИ ВОПРОС 40
44.
Средства организации и управления взаимодействием параллельных процессов в современных ОС.
Важнейшей частью операционной системы, непосредственно влияющей на функционирование вычислительной
машины, является подсистема управления процессами. Процесс (или по-другому, задача) - абстракция, описывающая
выполняющуюся программу. Для операционной системы процесс представляет собой единицу работы, заявку на
потребление системных ресурсов. Подсистема управления процессами планирует выполнение процессов, то есть
распределяет процессорное время между несколькими одновременно существующими в системе процессами, а также
занимается созданием и уничтожением процессов, обеспечивает процессы необходимыми системными ресурсами,
поддерживает взаимодействие между процессами.
Поскольку процессы часто одновременно претендуют на одни и те же ресурсы, то в обязанности ОС входит
поддержание очередей заявок процессов на ресурсы, например очереди к процессору, к принтеру, к последовательному
порту.
Для того, чтобы процессы не могли вмешаться в распределение ресурсов, а также не могли повредить коды и данные
друг друга, задачей ОС является изоляция одного процесса от другого. Для этого ОС обеспечивает каждый процесс
отдельным виртуальным адресным пространством, так что ни один процесс не может получить прямого доступа к
командам и данным другого процесса.
Операционная система может не только защищать ресурсы, выделенные одному процессу, но и организовывать их
совместное использование, например разрешать доступ к некоторой области памяти нескольким процессам.
В операционной системе нет однозначного соответствия между процессами и программами. Один и тот же
программный файл может породить несколько параллельно выполняемых процессов, а процесс может в ходе своего
выполнения сменить программный файл и начать выполнять другую программу.
Для реализации сложных программных комплексов полезно бывает организовать их работу в виде нескольких
параллельных процессов, которые периодически взаимодействуют друг с другом и обмениваются некоторыми данными.
Так как операционная система защищает ресурсы процессов и не позволяет одному процессу писать или читать из
памяти другого процесса, то для оперативного взаимодействия процессов ОС должна предоставлять особые средства,
которые называют средствами межпроцессного взаимодействия.
Таким образом, подсистема управления процессами планирует выполнение процессов, то есть распределяет
процессорное время между несколькими одновременно существующими в системе процессами, занимается созданием и
уничтожением процессов, обеспечивает процессы необходимыми системными ресурсами, поддерживает синхронизацию
процессов, а также обеспечивает взаимодействие между процессами.
В многозадачной (многопроцессной) системе процесс может находиться в одном из трех основных состояний:
ВЫПОЛНЕНИЕ - активное состояние процесса, во время которого процесс обладает всеми необходимыми ресурсами и
непосредственно выполняется процессором;
ОЖИДАНИЕ - пассивное состояние процесса, процесс заблокирован, он не может выполняться по своим внутренним
причинам, он ждет осуществления некоторого события, например, завершения операции ввода-вывода, получения
сообщения от другого процесса, освобождения какого-либо необходимого ему ресурса;
109
ГОТОВНОСТЬ - также пассивное состояние процесса, но в этом случае процесс заблокирован в связи с внешними по
отношению к нему обстоятельствами: процесс имеет все требуемые для него ресурсы, он готов выполняться, однако
процессор занят выполнением другого процесса.
В ходе жизненного цикла каждый процесс переходит из одного состояния в другое в соответствии с алгоритмом
планирования процессов, реализуемым в данной операционной системе.
Планирование процессов включает в себя решение следующих задач:
определение момента времени для смены выполняемого процесса;
выбор процесса на выполнение из очереди готовых процессов;
переключение контекстов "старого" и "нового" процессов.
Среди этого множества алгоритмов наиболее часто встречаются алгоритмы, основанные на квантовании и
основанные на приоритетах.
Основанные на квантовании.
В соответствии с алгоритмами, основанными на квантовании, смена активного процесса происходит, если:
процесс завершился и покинул систему,
произошла ошибка,
процесс перешел в состояние ОЖИДАНИЕ,
исчерпан квант процессорного времени, отведенный данному процессу.
Кванты, выделяемые процессам, могут быть одинаковыми для всех процессов или различными. Кванты, выделяемые
одному процессу, могут быть фиксированной величины или изменяться в разные периоды жизни процесса. Процессы,
которые не полностью использовали выделенный им квант (например, из-за ухода на выполнение операций вводавывода), могут получить или не получить компенсацию в виде привилегий при последующем обслуживании. По
разному может быть организована очередь готовых процессов: циклически, по правилу "первый пришел - первый
обслужился" (FIFO) или по правилу "последний пришел - первый обслужился" (LIFO).
Основанные на приоритетах.
Другая группа алгоритмов использует понятие "приоритет" процесса. Приоритет - это число, характеризующее степень
привилегированности процесса при использовании ресурсов вычислительной машины, в частности, процессорного
времени: чем выше приоритет, тем выше привилегии.
Во многих операционных системах алгоритмы планирования построены с использованием как квантования, так и
приоритетов. Например, в основе планирования лежит квантование, но величина кванта и/или порядок выбора процесса
из очереди готовых определяется приоритетами процессов.
Средства синхронизации и взаимодействия процессов
Проблема синхронизации
Процессам часто нужно взаимодействовать друг с другом, например, один процесс может передавать данные другому
процессу, или несколько процессов могут обрабатывать данные из общего файла. Во всех этих случаях возникает
проблема синхронизации процессов, которая может решаться приостановкой и активизацией процессов, организацией
очередей, блокированием и освобождением ресурсов.
Ситуации подобные той, когда два или более процессов обрабатывают разделяемые данные, и конечный результат
зависит от соотношения скоростей процессов, называются гонками.
Критическая секция
Важным понятием синхронизации процессов является понятие "критическая секция" программы. Критическая секция это часть программы, в которой осуществляется доступ к разделяемым данным. Чтобы исключить эффект гонок по
110
отношению к некоторому ресурсу, необходимо обеспечить, чтобы в каждый момент в критической секции, связанной с
этим ресурсом, находился максимум один процесс. Этот прием называют взаимным исключением.
Обобщающее средство синхронизации процессов предложил Дейкстра, который ввел два новых примитива. В
абстрактной форме эти примитивы, обозначаемые P и V, оперируют над целыми неотрицательными переменными,
называемыми семафорами. Пусть S такой семафор. Операции определяются следующим образом:
V(S) : переменная S увеличивается на 1 одним неделимым действием; выборка, инкремент и запоминание не могут быть
прерваны, и к S нет доступа другим процессам во время выполнения этой операции.
P(S) : уменьшение S на 1, если это возможно. Если S=0, то невозможно уменьшить S и остаться в области целых
неотрицательных значений, в этом случае процесс, вызывающий P-операцию, ждет, пока это уменьшение станет
возможным. Успешная проверка и уменьшение также является неделимой операцией.
Тупики
Ещё одна проблема синхронизации - взаимные блокировки, называемые также дедлоками (deadlocks), клинчами (clinch)
или тупиками.
Проблема тупиков включает в себя следующие задачи:
предотвращение тупиков,
распознавание тупиков,
восстановление системы после тупиков.
В некоторых случаях, когда тупиковая ситуация образована многими процессами, использующими много ресурсов,
распознавание тупика является нетривиальной задачей. Существуют формальные, программно-реализованные методы
распознавания тупиков, основанные на ведении таблиц распределения ресурсов и таблиц запросов к занятым ресурсам.
Анализ этих таблиц позволяет обнаружить взаимные блокировки.
Для того, чтобы облегчить написание корректных программ, было предложено высокоуровневое средство
синхронизации, называемое монитором. Монитор - это набор процедур, переменных и структур данных. Процессы
могут вызывать процедуры монитора, но не имеют доступа к внутренним данным монитора. Мониторы имеют важное
свойство, которое делает их полезными для достижения взаимного исключения: только один процесс может быть
активным по отношению к монитору. Компилятор обрабатывает вызовы процедур монитора особым образом. Обычно,
когда процесс вызывает процедуру монитора, то первые несколько инструкций этой процедуры проверяют, не активен
ли какой-либо другой процесс по отношению к этому монитору. Если да, то вызывающий процесс приостанавливается,
пока другой процесс не освободит монитор. Таким образом, исключение входа нескольких процессов в монитор
реализуется не программистом, а компилятором, что делает ошибки менее вероятными.
(далее необязательно, но на случай дополнительных вопросов)
На протяжении существования процесса его выполнение может быть многократно прервано и продолжено. Для того,
чтобы возобновить выполнение процесса, необходимо восстановить состояние его операционной среды. Состояние
операционной среды отображается состоянием регистров и программного счетчика, режимом работы процессора,
указателями на открытые файлы, информацией о незавершенных операциях ввода-вывода, кодами ошибок
выполняемых данным процессом системных вызовов и т.д. Эта информация называется контекстом процесса.
Кроме этого, операционной системе для реализации планирования процессов требуется дополнительная информация:
идентификатор процесса, состояние процесса, данные о степени привилегированности процесса, место нахождения
кодового сегмента и другая информация. В некоторых ОС (например, в ОС UNIX) информацию такого рода,
используемую ОС для планирования процессов, называют дескриптором процесса.
Вытесняющие и невытесняющие алгоритмы планирования
Существует два основных типа процедур планирования процессов - вытесняющие (preemptive) и невытесняющие (nonpreemptive).
111
Non-preemptive multitasking - невытесняющая многозадачность - это способ планирования процессов, при котором
активный процесс выполняется до тех пор, пока он сам, по собственной инициативе, не отдаст управление
планировщику операционной системы для того, чтобы тот выбрал из очереди другой, готовый к выполнению процесс.
Preemptive multitasking - вытесняющая многозадачность - это такой способ, при котором решение о переключении
процессора с выполнения одного процесса на выполнение другого процесса принимается планировщиком операционной
системы, а не самой активной задачей.
Однако почти во всех современных операционных системах, ориентированных на высокопроизводительное выполнение
приложений (UNIX, Windows NT, OS/2, VAX/VMS), реализована вытесняющая многозадачность. Возможно в связи с
этим вытесняющую многозадачность часто называют истинной многозадачностью.
Нити
Многозадачность является важнейшим свойством ОС. Для поддержки этого свойства ОС определяет и оформляет для
себя те внутренние единицы работы, между которыми и будет разделяться процессор и другие ресурсы компьютера. Эти
внутренние единицы работы в разных ОС носят разные названия - задача, задание, процесс, нить. В некоторых случаях
сущности, обозначаемые этими понятиями, принципиально отличаются друг от друга.
Современные ОС предлагают использовать сравнительно новый механизм многонитевой обработки (multithreading).
При этом вводится новое понятие "нить" (thread), а понятие "процесс" в значительной степени меняет смысл.
Мультипрограммирование теперь реализуется на уровне нитей, и задача, оформленная в виде нескольких нитей в
рамках одного процесса, может быть выполнена быстрее за счет псевдопараллельного (или параллельного в
мультипроцессорной системе) выполнения ее отдельных частей. Например, если электронная таблица была разработана
с учетом возможностей многонитевой обработки, то пользователь может запросить пересчет своего рабочего листа и
одновременно продолжать заполнять таблицу. Особенно эффективно можно использовать многонитевость для
выполнения распределенных приложений, например, многонитевый сервер может параллельно выполнять запросы
сразу нескольких клиентов.
Нити, относящиеся к одному процессу, не настолько изолированы друг от друга, как процессы в традиционной
многозадачной системе, между ними легко организовать тесное взаимодействие. Действительно, в отличие от
процессов, которые принадлежат разным, вообще говоря, конкурирующим приложениям, все нити одного процесса
всегда принадлежат одному приложению, поэтому программист, пишущий это приложение, может заранее продумать
работу множества нитей процесса таким образом, чтобы они могли взаимодействовать, а не бороться за ресурсы.
СИИ и Логическое программирование
45.
Основные понятия СИИ. Методика концептуального описания и концептуальная модель задачи
принятия решений.
Основные понятия:
Предметная область (ПО) – выделенная узкая сфера деятельности человека, относящаяся к данной задаче.
Модель предметной области (МПО) – совокупность (система) знаний, необходимых для автоматического
синтеза алгоритма решения задачи в данной области.
Искусственный интеллект (ИИ) (artificial intelligence - AI) – совокупность метапроцедур - представления
знаний, рассуждений, поиска релевантной информации в среде имеющихся знаний, их пополнение, корректировка и
т.п., - имитирующих деятельность человека.
Система искусственного интеллекта (СИИ) - аппаратный и информационно-программный комплекс, действие
которого аналогично действию механизмов мышления человека и неотличимо от решений, которые принимались бы
человеком-экспертом, т.е. профессионалом в данной предметной области.
Из этих определений следует, что любую систему ИИ отличают следующие особенности:
112


наличие модели предметной области;
наличие моделей механизмов мышления, т.е. метапроцедур, работающих на системе
представленных моделью предметной области (в частности, процедур логического вывода);
 наличие естественно-языкового интерфейса, обеспечивающего взаимодействие пользователя с СИИ.
Очень часто под СИИ понимаются системы, основанные на знаниях.
знаний,
Методика концептуального описания.
Модель предметной области.
Все, что нам нужно знать для решения задачи, как раз и составляет некую предметную область (ПО), которую
мы формализуем в виде модели предметной области (МПО) следующим образом:
МПО :
X, C, R, G
,
(1.1)
где обозначено:
X = (x1, x2, ... xn) – множество имен объектов (предметов, сущностей и т.п. внешнего мира), с которыми мы
имеем дело при решении задачи.
C = (c1, c2, ... cm) – множество имен свойств (состояний) объектов, причем возможно, что c1 = (c11, c12, ... c1k), c2
= (c21, c22, ... c2r) и т.д. Эти свойства могут меняться под действием некоторых операторов.
R = (r1, r2, …rn) – множество имен отношений, в которые могут вступать объекты моделируемой ПО.
G = (g1, g2, ... gk) - множество имен операций (действий), которые допустимы с этими объектами через
изменение их свойств и отношений между ними.
Пример:
Допустим, мы описываем предметную область задачи о сборе яблок. Тогда множество Х – объекты: ЯБЛОКО,
ЛЕСТНИЦА, КОРЗИНА, ЯЩИК;
множество С – свойства (состояния) объектов:
для ЯБЛОКА – сорвано, уложено, отброшено;
для ЛЕСТНИЦЫ – лежит, стоит;
для КОРЗИНЫ – полна, пуста;
для ЯЩИКА – брошен, уложен;
множество R – отношения:
ЯБЛОКО – НА ветке, В корзине;
ЛЕСТНИЦА – У дерева, ПОД деревом;
КОРЗИНА – НА лестнице, У ящика;
ЯЩИК – У дороги;
множество G – действия (операторы):
g1 – поставить (ЛЕСТНИЦУ),
g2 – повесить (КОРЗИНУ),
g3 – сорвать (ЯБЛОКО),
g4 – положить (ЯБЛОКО в корзину),
g5 – наполнить (КОРЗИНУ),
g6 – уложить (ЯЩИК),
g7– перенести (ЯЩИК к дороге) и т.п.
Концептуальное модель задачи принятия решений.
Процедура решения задачи.
Исходя из сказанного, определим теперь понятия "задача", "решение", "алгоритм".
Обозначим начальное состояние ПО через Sн. Задача заключается в том, чтобы перевести предметную область
из состояния Sн в некоторое заданное, определяемое как целевое (Sц). Очевидно, сделать это возможно, лишь применяя
допустимые в данной предметной области действия из множества G = (g1, g2, ...gk). Какие выбрать операции gi и в
какой последовательности - неизвестно. В этом как раз и состоит решение задачи. Схема решения, таким образом,
выражается формулой:
G

Z = (Sн
Sц).
(1.4)
Допустим, оператором g1, взятым из множества G, мы перевели состояние Sн в S1, но оно не совпало с SЦ, т.е.
S1= g1(Sн), S1
Sц. Для перевода S1 в состояние S2 применим оператор g2
G: S2 = g2(S1) и, если S2 снова не совпадет


113
с Sц, обратимся к оператору g3, чтобы получить состояние S3 и оценить его, сравнивая с Sц. И так далее, пока не
найдется такой gj, что Sj = gj(Sj-1) и Sj = Sц. Описанный путь поиска решения можно отобразить следующей цепочкой:
g1
g2
Sн
S1
То же самое можно написать по-другому:


S2
g
g
3


...
1
j
 Sj
=
Sц.
(1.5)
Sц = gj(gj-1 (...(g3 (g2 (g1 (Sн)))...))).
Последовательность (g1, g2, g3, ... gj) как раз и будет представлять из себя алгоритм решения задачи.
Отметим, что перевод Sн
Sц возможен не единственным способом. В этом случае можно ставить задачу об
оптимизации решения.

Пример:
О наполнении ведра водой.
В начальный момент времени пустое ведро стоит рядом с раковиной, кран закрыт. В целевой ситуации
необходимо, чтобы ведро было полно и стояло на полу у раковины, а кран был бы закрыт. Все операции выполняет
робот. Требуется построить план его действий.
Множество X: (РОБОТ(Р), ВЕДРО(В), КРАН(К), ПОЛ(П), РАКОВИНА(РК)).
Множество С:
состояние РОБОТА – (У КРАНА);
состояние ВЕДРА – (ПУСТО, ПОЛНО);
состояние КРАНА – (ОТКРЫТ, ЗАКРЫТ).
Множество R: НА(В,П) - ведро на полу,
В(В,РК) - ведро в раковине.
Поскольку робот все время находится в одной точке, его также можно исключить из рассмотрения. Тогда
Sн = < В(ПУСТО), КРАН(ЗАКРЫТ), НА(В,П) ›.
Sц = < В(ПОЛНО), КРАН(ЗАКРЫТ), НА(В,П) >.
Рассмотрим состояния и действия.
1.
(В (ПУСТО), К (ЗАКРЫТ), НА (В,П))
(В (ПУСТО), К (ЗАКРЫТ),
2.
(В (ПУСТО), К (ОТКРЫТ),
3.
(В (ПОЛНО), К (ОТКРЫТ),
5.
(В (ПОЛНО), К (ЗАКРЫТ),
g3
НА (В,П));
НА (В,П))
(В (ПОЛНО), К (ЗАКРЫТ),
g2
НА (В,П));
НА (В,П))
(В (ПУСТО), К (ОТКРЫТ),
(В (ПОЛНО), К (ОТКРЫТ),
4.
НА (В,П));
НА (В,П))
(В (ПУСТО), К (ЗАКРЫТ),
g1
g5
НА (В,П));
НА (В,П))
g4
(В (ПОЛНО), К (ЗАКРЫТ), НА (В,П)).
Последняя ситуация является, как видим, целевой.
114
Примечание 1. Из определения Мпо следует, что отображение F описывает условия применения операторов
из множества
.
Примечание 2. Из примеров хорошо видно, как важно правильно (удачно) выбрать способ описания Sн и Sц. От этого
зависят наглядность представления и даже скорость поиска решения.
46.
Построение пространства состояний задачи. Методы поиска решений в про-странстве состояний.
Построение пространства состояния задачи.
Применение операторов к начальному и другим, промежуточным, состояниям меняет эти состояния, порождая
новые, которых вообще-то может быть много и которые образуют то, что называется пространством состояний. Среди
этих состояний, если модель построена корректно, рано или поздно появится одно, которое будет соответствовать
целевому, и процесс поиска решения на этом будет закончен. Процесс этот может быть длинным и сложным, поэтому
возникает необходимость в некотором едином методе представления множества состояний и поиска решений. Таким
методом является метод, удобной графической моделью которого стал граф.
Если отождествить состояние Sн с корнем или начальной вершиной графа-дерева, то, применяя к Sн какой-либо
оператор g1
G, мы порождаем новое состояние S1, образуя тем самым следующую вершину графа (рис. 2.1).

Sн
g1
g2
S1
g3
S2
g4
S3
S4
g6
g5
S6
g7
S7
S5
g8
Sц
Путь решения задачи:
Sц = g8(g6(g3(g1(Sн)))).
Рис. 2.1. Граф решения задачи
Эта новая вершина может быть промежуточной или целевой. Если вершина промежуточная, то процесс
порождения новых вершин (с помощью операторов gi) будет продолжен, пока не найдется целевая. Процесс применения
оператора gi к некоторой вершине называется раскрытием вершины. От каждой порожденной вершины к породившей
ее расставляются указатели, которые позволяют найти путь назад, к начальной вершине, после того, как обнаружена
целевая. Общая процедура построения дерева в пространстве состояний при этом выглядит следующим образом.
1). К корню дерева (Sн) применяются операторы gi из множества G (их может быть несколько). Полученные
при этом вершины образуют первый уровень новых вершин.
2). Каждая из вновь полученных вершин проверяется, не является ли она целевой. Если нет, то процесс
продолжается по отношению к каждой из них. Образуется второй уровень вершин. Если к какой-либо вершине никакой
оператор из G не применим, то эта вершина становится терминальной (конечной). Как видим, на каждом шаге
проводятся две операции: порождение новой вершины и проверка, не является ли новая вершина целевой, т.е.
совпадающей с целевым состоянием.
3). Когда целевая вершина найдена, в обратном направлении (от цели к началу) просматриваются указатели дуг
и выделяется путь решения. Практически этот путь удобнее отображать посредством операторов, связанных с этими
дугами (см. рис. 2.1).
В общем случае количество вершин может быть большим. Их последовательное раскрытие, анализ и пометка
пути осложняют задачу. Возникает проблема перебора вершин: в каком порядке они будут порождаться и
анализироваться. Здесь возможны следующие варианты:
1)
Вершины раскрываются в том же порядке, в котором они порождаются, то такой перебор называется
полным перебором в ширину (breadth - first process);
2)
На каждом шаге первой раскрывается вершина, которая была построена последней, такой процесс
называется полным перебором в глубину (depth - first process). В этих процессах расположение целевой вершины не
влияет на порядок раскрытия, поэтому их часто называют процессами слепого перебора.
3)
Если есть некоторая дополнительная (эвристическая) информация о предметной области, которая
позволяет делать суждения о характере графа пространства состояний и расположения цели, то такой метод построения
графа называется эвристическим ("эвристический" означает "служащий открытию"). Эвристическая информация,
опирающаяся, как правило, на предыдущий опыт, позволяет выполнять поиск в наиболее перспективных направлениях.
115
Говоря о графе, будем рассматривать только один наиболее простой его тип - граф типа "дерево". Как известно, деревом
называется граф, каждая вершина которого имеет только одну вершину, непосредственно предшествующую ей
(родительскую), за исключением вершины-корня, которая предшествующих вершин не имеет.
Метод полного перебора в ширину
Как уже было сказано, в этом методе вершины раскрываются в том порядке, в котором они строятся. Основной
алгоритм состоит в выполнении следующих действий.
1). Раскрывается начальная вершина Sн. Она раскрывается до тех пор, пока ее можно раскрыть, применяя один
и тот же оператор (или разные, смотря по условию). При этом образуются вершины первого уровня: S1, S2, S3...Они
раскрываются в свою очередь, и образуются вершины второго уровня и т.д. (рисунок 2.1 может служить примером
этого метода: S1 и S2 - вершины первого уровня, S3 и S4 - вершины второго уровня, S5 и S6 - третьего и т.д.).
2). Расставляются указатели, ведущие от новых вершин к корню. Это могут быть условные имена, буквы,
цифры, имена операторов и т.п.. Но могут быть и реальные величины, например, расстояния, стоимость, вес и т.д.
3). Проверяется, нет ли среди полученных вершин целевой. Если есть, то формируется решение на основе
соответствующего оператора. Если целевых вершин нет, то рассматривается первая порожденная вершина и к ней
применяется тот же алгоритм. После чего, переходят ко второй и т.д., пока среди получаемых вершин не окажется
целевой.
Метод полного перебора в ширину гарантируют нахождение целевой вершины как раз потому, что перебор полный. Путей достижения цели, вообще говоря, может быть много. В этом случае у нас имеется возможность выбрать
наикратчайший (или самый дешевый, или самый легкий - критериев много) путь. Но может быть случай, когда граф
поиска окажется бесконечным и тогда этот алгоритм никогда не кончит работу.
Таким образом, метод полного перебора гарантирует поиск оптимального решения, если дерево пространства
состояний не бесконечно.
Синонимами названия метода являются: метод грубой силы, метод проб и ошибок.
Sн (а,b,c,0,0)
g1
g5
(b,b,c,0,0)
(d,b,c,0,0)
g2
g3
g5
(c,c,c,0,0)
(b,b,c,1,0)
(n,b,c,0,0)
g3
g2
g1
g5
(c,c,c,1,0)
(n,n,c,0,0)
(m,b,c,0,0,)
g4
(f,f,c,0,0) g2
g3
(c,c,c,1,1) Sц
(n,n,c,1,0)
(k,k,c,0,0)
Рис. 2.2. Элемент дерева полного перебора в ширину
для примера с обезьяной и бананами
На рис. 2.2 показан элемент дерева полного перебора в ширину для примера с обезьяной и бананами (для
полноты изложения здесь применяется дополнительный оператор g5, отображающий перемещение обезьяны по
комнате из точки в точку).
Корень дерева совпадает с Sн(a,b,c,0,0,). Точки d, f, k, n, m - координаты возможной миграции обезьяны по
комнате. Таких точек, конечно, множество, но мы выбрали лишь несколько для примера. Они не приводят к решению,
но теоретически вполне допустимы. Жирной линией показан путь до целевой вершины Sц(c,c,c,1,1), которому
соответствует последовательность операторов g4, g3, g2, g1. Алгоритм решения отобразится формулой
Sц = g4(g3(g2(g1(a,b,c,0,0)))).
Метод полного перебора в глубину
В отличие от метода перебора в ширину этот метод предлагает раскрывать, прежде всего, те вершины, которые
были построены последними. Первой раскрываемой вершиной, а следовательно, и последней, является корневая, но
процесс всегда будет идти по самой левой ветви вершин. Чтобы как-то ограничить перебор, вводится понятие глубины
вершины в дереве перебора. Полагаем, что глубина корня дерева равна нулю, а глубина любой последующей вершины
равна единице плюс глубина вершины, непосредственно ей предшествующей.
Отсюда следует, что наибольшую глубину всегда будет иметь та вершина, которая должна быть в этот момент
раскрыта. Если образующийся путь оказывается бесполезным, то есть при заданной глубине раскрытия целевой
вершины не получилось, необходимо вернуться в вершину, предшествующую раскрытой и попытаться еще раз
применить к ней операцию раскрытия. И так до тех пор, пока не будет получена целевая вершина.
Sн
b
a
S1
116
S2
f
S6
l
c
g
e
S9
n
Sц
S3
S7
m
d
S5
S4
k
S10
S8
Рис. 2.3. Дерево полного перебора в глубину
Возврат осуществляется с помощью указателей. Как только в процессе порождения вершин достигается
заданная граничная глубина, раскрывается вершина наибольшей глубины, не превышающая этой границы. Общая схема
перебора в глубину показана на рис. 2.3.
Алгоритм перебора в глубину состоит в следующем.
1). Раскрывается начальная вершина соответствующая начальному состоянию Sн.
2) Раскрывается первая вершина, получаемая в результате раскрытия Sн. Ставится указатель.
3) Если она раскрывается, то следующей будет раскрываться вновь порожденная вершина. Если вершина не
раскрывается, то процесс возвращается в предыдущую вершину.
4) По получении целевой вершины, процесс раскрытия заканчивается и по указателям строится путь, ведущий
к корню. Соответствующие
дугам операторы образуют решение задачи.
5). Если для заданной глубины раскрытия целевая вершина не находится,
то весь процесс повторяется
снова, а в качестве новой вершины рассматривается самая левая из полученных на предыдущем этапе.
Эвристические методы поиска в пространстве состояний
Методы полного перебора гарантируют решение задачи, если оно существует, а при наличии нескольких
решений, гарантирует оптимальное. Однако на практике эти методы используются для решения лишь небольших по
размерности графа состояний задач. Для реальных случаев чаще всего используется дополнительная информация,
основанная на предыдущем опыте или полученная на основании теоретических выводов.
Такая информация называется эвристической, а организованная в правила - эвристическими правилами или
эвристиками. Эвристическая информация носит сугубо специальный характер и может применяться только в рамках
данной задачи, в лучшем случае, в рамках задач данного класса.
Метод разбивание задачи на подзадачи.
Идея метода состоит в следующем. Если путь решения задачи неясен (или неизвестен), то нужно постараться
найти какую-то точку опоры, от которой (или до нее) путь известен. Это точка может быть в любом месте - в начале, в
середине, в конце, но она должна быть. Этой точке, очевидно, будет соответствовать некоторое состояние Si на пути
от Sн до Sц. Если эта точка Si определена, то к ней уже можно применить какое-либо действие и этим изменить
состояние предметной области, т.е. приблизиться к возможному решению. Для нового состояния также ищется точка
опоры на оставшемся пути, к ней снова применяется какое-то (или то же самое) действие и т.д., пока не будет
решена вся задача.
Чтобы детально описать этот метод, необходимо вернуться к определению понятия задачи. Для этой цели
воспользуемся понятием пространства состояний. В более общем, чем прежде, виде задачу (Z) можно представить
следующим образом:
Z=
S, G, F
,
(3.1)
где S - множество начальных состояний, G - множество операторов, переводящих предметную область из
одного состояния в другое, F -множество целевых состояний.
При таком обозначении промежуточные состояния Si удобнее обозначать через fi, поскольку они теперь
представляют собой как бы промежуточные цели.
Конечной целью сведения задачи к подзадачам является получение таких элементарных задач, решение
которых очевидны. Элементарными считаются задачи, которые могут быть решены за один шаг, т.е. за одно
применение какого-либо оператора из множества G.
47.
Понятие "знания" и его отличия от понятия "данные". Классификация и ос-новное содержание моделей
представления знаний.
Понятие "знания" и его отличия от понятия "данные".
117
Знанием является информация, которая отражает объективные свойства и связи некоторых объектов, явлений, процессов, сущностей и
отношениями между ними как в субъективном, так и научном
(объективном) выражении.
. Под системой знаний понимается совокупность знаний, образующих целостное описание некоторой
проблемы с доступной и достаточной степенью точности. Целостность означает, что между отдельными сведениями,
входящими в знание, существуют связи и, следовательно, одни сведения могут быть выводимы из других. Это также
означает, что система знаний есть информационная система (информационная модель), отвечающая требованиям
полноты и непротиворечивости. В случае, если между отдельными сведениями явные связи не установлены, то они
превращаются в единичные факты – некоторые суждения, относительно которых можно судить об их истинности или
ложности. Такие суждения можно назвать данными. Таким образом, данное есть вырожденный случай знания.
Например, если между деталями автомобиля не указаны связи, то мы получим просто Базу Данных о деталях
автомобиля. Связность между элементами удобно отображать с помощью ориентированных графов. И тогда
результирующий связный граф можно рассматривать как модель знания о чем-то. Очевидно, что невозможно построить
модель всего знания и мы можем говорить лишь о предметно - или проблемно - ориентированном фрагменте знания для
целевого применения. Такие фрагменты мы будем называть моделями предметных областей.
В ЭВМ знания, также как и данные, отображаются в знаковой форме - в виде формул, текста, файлов,
информационных массивов и т.п.. Поэтому можно сказать, что знания - это особым образом организованные данные.
Но это было бы слишком узкое понимание. А между тем, в системах искусственного интеллекта знания
являются основным объектом формирования, обработки и исследования. База знаний, наравне с базой данных, необходимая составляющая программного комплекса ИИ. Машины, реализующие алгоритмы ИИ, называют машинами,
основанными на знаниях, а подраздел теории ИИ, связанный с построением экспертных систем, - инженерией знаний.
Так чем же отличаются знания от данных?
Обычно под данными понимают информацию, определенным образом подготовленную и представляющую
собой объект, отличный от команд. Сюда относится все, что обрабатывается программой (операнды, файлы и т.п.) по
заданному алгоритму. Этот алгоритм может быть очень сложным, существуют даже специальные системы управления
базами данных (СУБД). Но эти системы не могут делать одного, с точки зрения ИИ, самого главного. Они не могут
моделировать рассуждения, т.е., иначе говоря, проводить логический вывод. Потребовалось достаточно большое время,
прежде чем данные, постепенно эволюционируя, превратились в знания. При этом они приобрели, как минимум, шесть
обязательных свойств:
1) внутреннюю интерпретацию,
2) внутреннюю структуру связей,
3) внешнюю структуру связей,
4) шкалирование,
5) погружение в пространство с «семантической метрикой»,
6) наличие активности.
-На этом ответ этой части можно закончить-
Рассмотрим указанные свойства базы знаний подробнее.
1. Внутренняя интерпретация
Это понятие легко пояснить на следующем примере, который представляет собой, в сущности, обычную таблицу
(см. рис. 4.1).
Каждую строчку данной таблицы, также, как и столбец, будем трактовать как отдельную информационную
единицу (ИЕ), расположенную в памяти машины. Тип транзистора, указанный в начале строки, является именем ИЕстроки, имя ИЕ-столбца указано сверху.
118
 Имя m-го слота, Значение m-го слота  ).
Характеристики
Тип
прибора
Проводимость
Максим.
Максим.
ток, А
напряжение, В
КТ837А
p-n-p
7,5
80
КТ817Г
n-p-n
3
25
КП308В
n-тип
0.02
25
КП304А
p-тип
0.03
20
Рис. 4.1. Пример внутренней интерпретации данных
Информационная единица для первой строки
с именем КТ837А будет выглядеть так: ( КТ837А
 Проводимость, p-n-p   Макс. ток, 7.5 А   Макс. Напряжение, 80 В  ), для столбца с именем Проводимость
соответственно: (Проводимость  КТ837А, p-n-p   КТ817Г, n-p-n   КП308В, n-тип   КП304А, p-тип  ).
Круглые скобки, таким образом, выделяют содержание ИЕ, а угловые скобки - определенные самостоятельные части,
называемые слотами. В общем виде полная запись ИЕ будет выглядеть так: (Имя ИЕ
первого слота
 Имя первого слота, Значение
  Имя второго слота, Значение второго слота  …).
В памяти машины вся эта таблица хранится в свою очередь как отдельная информационная единица. База
данных, структурированная таким образом, еще не база знаний, но уже может ответить на некоторые вопросы,
например, выдать информацию о характеристике транзистора или подобрать транзисторы по их проводимости. Другими
словами, она уже может отвечать на вопросы, касающиеся содержимого ее памяти.
2.
Наличие внутренней структуры связей
Представим теперь, что в качестве слотов у нас выступают другие информационные единицы. В этом случае слоты
будут как бы вкладываться друг в друга, как в «матрешке». Полученная структура получила название фрейма (см. рис.
4.2).
F
S11
S12
r12 .... Sk2
rk2
S21
r21 ....
S m1
rm1
119
Рис. 4.2. Структура фрейма
На рисунке: F- имя фрейма, S11 - имя первого слота, Si2 - имя второго слота, который в свою очередь содержит k
слотов второго уровня вложенности.
Пользуясь предыдущим примером, нетрудно представить себе фрейм, скажем, с четырьмя уровнями вложений. 1й уровень - «видовое» название «Транзисторы». 2-й могли бы составить два слота - «Биполярные» и «Униполярные».
3-й уровень вложения - слоты с именами «КТ837А», «КТ817Г», «КП308В», «КП304А», а в качестве 4-го уровня - слоты,
отражающие характеристики транзисторов согласно рис. 4.1.
Между слотами различных уровней могут быть самые разные отношения. Вложенным может быть не только слот,
но и фрейм, имеющий уже свои многоуровневые вложения. Наконец, вложенной может быть команда или даже целая
программа. Все это придает фреймовым структурам большую гибкость и многосвязность.
3. Наличие внешней структуры связей
Из предыдущего следует, .что при работе с фреймами могут возникнуть такие ситуации, когда отдельные факты и
явления, входящие в структуру одного фрейма, вступают в ситуационную связь с фактами и явлениями, описанными в
структуре другого фрейма. Для отображения таких связей используются отдельные слоты. В них указываются имена
фреймов, с которыми есть связь, и имена отношений, осуществляющих их. Так возникает сеть с именами фреймов в
вершинах. С помощью дуг, над которыми написаны имена соответствующих отношений, вершины соединяются между
собой, образуя так называемую семантическую сеть. Попробуем ее построить.
Как там у Пушкина?
Вот едет могучий Олег со двора,
С ним Игорь и старые гости,
И видят: на холме, у брега Днепра,
Лежат благородные кости;
Их моют дожди, засыпает их пыль,
И ветер волнует над ними ковыль.
Вт g8
Дж
Пл
СтГ
Кв g9 g7
g1
g4
Хл
Олег
g5
g2
Игорь
g6
g3
Дв
Кос
Бг
Рис.4.3. Пример семантической сети
120
На рисунке 4.3 обозначены следующие понятия (если хотите, фреймы): СтГ - старые гости, Дв - двор, Кос - кости
(благородные), Пл - пыль, Дж - дождь, Кв - ковыль, Вт - ветер, Хл - холм, Бг - берег Днепра.
Множество G описывает систему отношений: g1 - быть вместе (двойная дужка объединяет обе части этого
соотношения), g2 - выезжать со, g3 - видеть, g4 - быть на, g5 - быть у, g6 - засыпать, g7 - мыть, g8 - волновать, g9 быть над.
«Семантический» значит «с учетом смысла слов». Указанная сеть так и построена. При серьезных задачах она
принимает весьма «запутанный» вид, связи ее усложняются. Построенные нами ранее графы решения различных задач
(см. гл. 2) вполне могли бы послужить основой для построения элементарных семантических сетей.
Обратим внимание на тип отношений G между понятиями (фреймами) одной сети. Они могут быть самыми
разными. Если, например, они отражают причинно-следственные связи, то такие сети называются сценариями. Если эти
отношения отражают связи по включению (типа «принадлежать к классу», «состоять из»), то это будут иерархические
сети. Отношения могут быть еще и такими, которые связывают аргументы и значения функции. Такие сети называются
вычислительными моделями.
4. Шкалирование
Разумной деятельности человека свойственно стремление к упорядоченности. Мы пытаемся как-то
систематизировать, «разложить по полочкам» те явления, события, факты, а точнее - информационные единицы, с
которыми мы имеем дело. Для этой цели мы используем разного рода шкалы. Это могут быть строгие метрические
шкалы, такие как шкала упорядочения людей по возрасту, шкала воинских званий или, к примеру, шкала весовых
категорий в боксе (наилегчайший вес, легчайший, полулегкий и т.д.). Но это могут быть и «размытые шкалы», такие
естественные в нашем языке. Вот как мы оцениваем частоту появления какого-то события: Никогда, Чрезвычайно редко,
Очень редко, Редко, Редко, но не очень, Не часто - не редко, Часто, но не слишком, Часто, Очень часто, Почти всегда,
Всегда. А еще есть так называемые «оппозиционные шкалы» типа Хороший - Плохой, Острый - Тупой, Сильный - Слабый
и т.п. Сюда же относится и знакомое всем нам Мы - Они.
Отображая отношения и связи реального мира, база знаний должна уметь отразить и это свойство
человеческого мышления.
5. Погружение в пространство с «семантической метрикой»
В нашем сознании это пространство образуют понятия, факты, явления, близкие по своему
(семантике). Честно говоря, «метрика» эта не слишком строгая и даже в чем-то противоречивая.
смыслу
Возьмем понятие учитель. В какое пространство (чаще говорят - кластер) мы его поместим? Это может быть
«Интеллигенция»,или
«Работники умственного труда», или «Образованные люди», или просто «Служащие». Конечно, все зависит от
конкретной типовой ситуации, но мы все-таки отметим этот факт: точки каждого кластера образуют совокупности
понятий, семантически близких между собой. Таково свойство нашего мышления. Типовая ситуация - ядро, вокруг
которого группируется информация.
Но есть и другой принцип образования кластеров. Выбор того или иного понятия из множества ему близких
подчиняется у человека еще и частоте появления. На просьбу назвать поэта почти каждый ответит: Пушкин; на просьбу
назвать фрукт - чаще всего - яблоко.
Таким образом, имеются, по крайней мере, две системы оценки близости информационных единиц. Одна
опирается на их ситуативную близость, а другая - на частоту появления тех или иных понятий в типовых ситуациях.
Разработана довольно стройная теория моделирования образования ситуационных кластеров. Мы не будем
сейчас вдаваться в подробности. Отметим лишь то, что метод погружения в пространство с семантической метрикой,
будучи, хотя и приближенно, реализованным в базе знаний, существенно повышает ее «интеллектуальный уровень».
121
6. Наличие активности
Как работает «обычная» ЭВМ? Очень просто - по заданной программе она обрабатывает те или иные данные. В
программе сосредоточено процедурное знание. Оно хранит информацию о том, как надо действовать, чтобы получить
желаемый результат. Данные представляют собой декларативные знания. Они хранят информацию о том, над чем надо
выполнять эти действия. Программа, таким образом, играет роль активатора данных.
Иное дело у человека. Очень часто в процессе мышления декларативные знания у него являются активатором
процедурных. Реализовать подобную возможность в базе знаний, как говорится, и чистом виде пока не удается.
Используются смешанные представления, в которых декларативные и процедурные знания понимаются единообразно
и могут активизировать друг друга.
В качестве примера рассмотрим фрейм, содержащий несколько слотов. Допустим теперь, что в качестве одного
из слотов выступает имя какой-либо процедуры, подлежащей исполнению. Но, как мы видели на примере
семантической сети, обращение к тому или иному слоту (или фрейму) определяется множеством разнообразных
отношений как между слотами одного фрейма, так и между другими фреймами. Все это как раз и формирует условия,
необходимые для выполнения указанной процедуры. Иными словами, декларативные знания становятся активаторами
процедур.
7. Продукционные системы
Продукционная модель представления знаний основана на системе правил, называемых продукциями. Как база
знаний, она обладает всеми известными свойствами изложены выше, но имеет своеобразную структуру:
P(x,y)
A.
Здесь P(x,y) есть логическая функция, А - некоторое суждение, выражающее рекомендацию лицу,
принимающему решение или решающей системе. То есть если для некоторых значений переменных x, y, например, x =
a, y = b, логическая функция P(a,b) принимает значение «истина», то справедливо некоторое суждение (совет) A. Иначе
продукцию можно истолковывать как суждение типа «если..., то...».
Левая часть продукции называется прототипом или образцом состояния, с которым сопоставляются реальные
состояния. Правая часть называется рекомендацией (или решением), которое следует принять в случае, если конкретное
состояние предметной области сопоставляется с образцом (интерпретируется). Совокупность таких вот правил продукций и образует базу знаний (БЗ).
Основной механизм логического вывода - это механизм сопоставления конкретных состояний предметной
области с образцами БЗ. При этом возможны две основных стратегии вывода: «снизу-вверх» (от ситуации
к цели) и
«сверху-вниз» (от цели
к ситуации).
Бабушка говорит «Красной Шапочке» (Волку): «Дерни за веревочку - дверь и откроется». Для нас это
продукция: «Если дернуть за веревочку (p), то дверь откроется (q)»: p
q. И вот возник вопрос: что будет, «если
дернуть за веревочку»? Ответ определяется путем сопоставления с левой частью продукции (образцом) p. Совпало.
Ответ: будет «q - дверь откроется» (стратегия «снизу-вверх»). Но может быть другой вопрос: «В каком случае дверь
откроется?». Ответ ищется путем сопоставления с правой частью продукции. Совпало. Ответ: «p - дернуть за
веревочку» (стратегия «сверху-вниз»).
Правила-продукции не зависят друг от друга, и поэтому такая БЗ легко пополняется и модифицируется.
1. Классификация и основное содержание моделей представления знаний.
Как организовать базу знаний с тем, чтобы она соответствовала требованиям СИИ, мы приблизительно
познакомились. Очевидно, что методы представления знаний в базе должны соответствовать изложенным требованиям.
Существуют три типа моделей представления знаний (МПЗ):
- формальные модели представления знаний,
122
неформальные (семантические, реляционные) МПЗ,
интегрированные МПЗ.
К формальным МПЗ относятся модели, построенные на основе исчисления высказываний и исчисления
предикатов.
К неформальным (реляционным, семантическим) относятся:
- продукционные модели,
- семантические сети,
- фреймовые МПЗ.
Интегрированные МПЗ совмещают в себе модели различных типов.
Неформальные модели представления знаний
Все методы представления знаний, которые мы рассматривали выше, включая продукции, относится к
неформальным моделям. В отличие от формальных моделей, в основе которых лежит строгая математическая теория,
неформальные модели такой теории не придерживаются. Каждая неформальная модель годится только для конкретной
предметной области и поэтому не обладает той универсальностью, которая присуща моделям формальным.
Логический вывод – основная операция в СИИ – в формальных системах строг и корректен, поскольку подчинен
жестким аксиоматическим правилам. Вывод в неформальных системах во многом определяется самим исследователем,
который и отвечает за его корректность.
Каждому из методов ПЗ соответствует свой язык представления знаний (ЯПЗ).. Их четыре типа: логические,
сетевые, фреймовые, продукционные. Рассмотрение сетевых, фреймовых и продукционных ЯПЗ выходит за рамки
данной книги. Достаточно сказать, что все они, в конечном итоге, приходят к использованию языков формальной
логики, что подчеркивает важность логических ЯПЗ в решении интеллектуальных задач.
Формальные модели представления знаний
Система ИИ в определенном смысле моделирует интеллектуальную деятельность человека и, в частности, логику его рассуждений. В грубо упрощенной форме наши логические построения при этом сводятся к следующей
схеме: из одной или нескольких посылок (которые считаются истинными) следует сделать "логически верное"
заключение (вывод, следствие). Очевидно, для этого необходимо, чтобы и посылки, и заключение были представлены на
понятном языке, адекватно отражающем предметную область, в которой проводится вывод. В обычной жизни это наш
естественный язык общения, в математике, например, это язык определенных формул и т.п. Наличие же языка
предполагает, во-первых, наличие алфавита (словаря), отображающего в символьной форме весь набор базовых понятий
(элементов), с которыми придется иметь дело, и, во-вторых, набор синтаксических правил, на основе которых, пользуясь
алфавитом, можно построить определенные выражения.
Логические выражения, построенные в данном языке, могут быть истинными или ложными. Некоторые из этих
выражений, являющиеся всегда истинными, объявляются аксиомами (или постулатами). Они составляют ту базовую
систему посылок, исходя из которой и пользуясь определенными правилами вывода, можно получить заключения в виде
новых выражений, также являющихся истинными.
Если перечисленные условия выполняются, то говорят, что система удовлетворяет требованиям формальной
теории. Ее так и называют формальной системой (ФС).. Система, построенная на основе формальной теории,
называется также аксиоматической системой.
Формальная теория должна, таким образом, удовлетворять следующему определению:
всякая формальная
характеризуется:
теория
F
=
(A,V,W,R),
определяющая
некоторую
аксиоматическую
систему,
наличием алфавита (словаря), А,
множеством синтаксических правил, V,
множеством аксиом, лежащих в основе теории, W,
123
множеством правил вывода, R.
48.
Исчисление высказываний как модель представления знаний. Проблема логического вывода и
алгоритмическая проблема разрешения. Доказательство общезначимости формулы с помощью метода
опровержения и метода резолюций.
Определение высказываний
Под высказыванием обычно понимают некоторое сообщение, предложение, выражение, утверждение и т.п.
Но такое широкое толкование нам не подходит, его надо конкретизировать. Если, услышав сообщение «идет
дождь», вы просто приняли его к сведению и перед выходом из дома взяли зонт, то с точки зрения ИВ это
сообщение не является высказыванием. Если же после указанных слов вы подошли к окну, чтобы удостовериться в
их истинности, то такое сообщение уже можно определить именно как высказывание. Итак, всякое высказывание
предполагает оценку его истинности (ложности).
Простые, односложные высказывания обозначаются строчными латинскими буквами a, b, m, l, r, q... Это
высказывания типа «светает», «дом белый», «сегодня холодно», «Петя любит Машу». Если установлено, что
высказывание r истинное, то пишут r = И (или r = 1), если r ложное, то r = Л (r = 0).
Каждое высказывание может быть либо истинным, либо ложным, третьего не дано - таков закон "исключенного
третьего".
Простые высказывания называют еще элементарными или атомарными.
Дадим такое определение:
аксиоматическая система, предназначенная для моделирования и изучения логики высказываний,
называется исчислением высказываний.
Алфавит исчисления высказываний
Алфавит А часто называют словарем. Этот словарь, во-первых, содержит сами высказывания a, b, m, n,... Вовторых, он содержит еще так называемые логические связки. Они хорошо известны читателю по курсам дискретной
математики, логических основ ЭВМ, программирования и др. Мы все-таки перечислим их, тем более что в ИИ они
используются в расширенном составе и в разных обозначениях (см. таблицу 1).
Таблица 1
Название
Отрицание
Конъюнкция
Дизъюнкция
Импликация
Эквивалентность
Обозначение
,
Тип
унарный
бинарный
бинарный
бинарный
бинарный
 , not, НЕ
 , &, and, И
 , +, or, ИЛИ


Тип отрицания унарный, потому что оно может быть приложено к одному высказыванию, даже если это
высказывание - сложное выражение. Остальные - бинарные, т.к. они могут соединять как минимум два
высказывания. Действия связок определяются таблицей истинности:
Таблица 2
x
y
xy
xy
x y
yx
И
И
Л
Л
И
Л
И
Л
И
И
И
Л
И
Л
Л
И
Л
И
И
И
Л
Л
И
Л
xy
И
Л
И
И
В данном пособии мы будем употреблять следующие обозначения
X;
X  Y или XY , или X  Y ;
дизъюнкции: X  Y или X  Y ;
импликации: X  Y ;
эквивалентности: X  Y .
отрицания:
конъюнкции:
С помощью связок из простых высказываний можно строить более сложные высказывания, употребляя при этом еще
и различные скобки:
124
q  p   p  q  r;
a  b  m  b a .
Не будем останавливаться на хорошо всем известных толкованиях связок конъюнкции (И) и дизъюнкции
(ИЛИ). Заметим только, что за исключением импликации все остальные связки подчиняются перестановочному закону,
т.е. не меняют своего значения, если х и y поменять местами.
Особый разговор об импликации. Условно она моделирует утверждение типа "если x..., то y...". Условность
здесь заключается в том, что не всегда поведение её очевидно. Например, выражение: "если x - ЛОЖЬ, то y -ИСТИНА"
оказывается ИСТИННЫМ. Тем не менее, эта связка широко применяется, поскольку отражает одно из основных
логических понятий.
Импликация неперестановочна. Пусть мы имеем такое высказывание: "если два слагаемых нечетные (r), то их
сумма - четная (q)". Оно представляется импликацией r  q, которая, очевидно, истинна: (r  q) = И. Попробуем
поменять местами r и q: q  r. Новая импликация означает: "если сумма двух слагаемых четная (q), то оба слагаемых
нечетные (r)", что верно только отчасти. Импликация отображает причинно-следственные связи и предостерегает нас от
широко распространенной логической ошибки, когда причину и следствие меняют местами. Первую часть импликации
называют посылкой или антецедентом, вторую - заключением или консеквентом.
Обратимся к приведенной выше таблице истинности и отметим следующее:

если посылка импликации истинна, то значение истинности импликации совпадает со значением
заключения;

если посылка ложна, импликация всегда истинна;

импликация ложна только при одном значении посылки (И) и заключения (Л);

если посылка истинна и вся импликация истинна, то и заключение истинно (правило заключения или
modus ponens).
Кстати говоря, импликацию, так же, как и эквивалентность, можно исключить:
(x  y ) = (
x
+ y); (r  p) = (r  p)(p  r) = (
r
+ p)(
p
+ r).
Первое равенство следует из сравнения соответствующих колонок таблицы 2, второе предлагаем доказать
самостоятельно.
Синтаксис исчисления высказываний
Речь идет о правилах V построения сложных высказываний. Как уже говорилось, такие высказывания строятся
(не считая скобок) с помощью логических связок - и только. Естественно назвать такие сложные высказывания
формулами. Но в ИВ в целях общности рассуждений формулами называют также и атомарные высказывания типа r, p и
т.п. Если речь идет вообще о формулах, то их обозначают через прописные латинские буквы: A, B, N, P...
Из сказанного можно сформулировать следующие синтаксические правила:
(1) всякое высказывание есть формула;
(2) формулы, построенные с помощью логических связок и скобок, называются правильно построенными
формулами (ппф).
Второе правило вводится единственно для того, чтобы подчеркнуть необходимость построения новых формул
только с помощью известных пяти связок. Стараясь подчеркнуть универсальность этих связок, их
"формулообразующие" свойства, эти связки часто называют пропозициональными.
Два указанных правила определяют синтаксис языка исчисления высказываний. В любых языках синтаксис дает
возможность распознавать фразы среди различных наборов слов. В нашем случае он определяет формулы, которые
здесь являются аналогами фраз.
Но нас интересует еще и семантика языка, т.е. определение значений, которые принимают формулы. Поскольку
каждое элементарное высказывание может принимать два значения: либо И, либо Л, то формулы, построенные на их
основе и являющиеся ппф, очевидно, также будут иметь только два значения: И или Л: значение сложной формулы есть
функция значений ее составляющих.
Рассмотрим, например, ппф импликации p  q. При значениях p = И и q = Л эта формула принимает значение
Л, при всех других - значение И. Приписать p и q какие-то определенные значения И (Л) означает задать
интерпретацию формулы.
Скажем, дизъюнкция a + b принимает значение Л только при интерпретации a = Л и b = Л.
Если некоторая формула принимает значение И при любой интерпретации входящих в нее атомарных
высказываний (формул), то она называется общезначимой, универсально-истинной, тождественной или тавтологией.
Примеры тавтологий:
a
(a + a)  a; (a + b) (b + a); (a +
).
Если формула принимает значение истины хотя бы при одной интерпретации, она называется выполнимой.
Дизъюнкция и конъюнкция - выполнимые формулы. Все элементарные высказывания выполнимы по определению.
x
Есть, однако, формулы, которые ложны при всех интерпретациях, например, конъюнкция х 
. Такие
формулы называются невыполнимыми или противоречивыми. Отрицание общезначимой формулы - невыполнимая
формула.
125
1.
Проблема логического вывода
Пусть имеется множество необщезначимых формул Е1, Е2, Е3...Еn, обладающих тем свойством, что при
некоторых интерпретациях они одновременно принимают значение И. Формула B выводима из множества {E}, если она
может быть выведена из него путем применения правила заключения. (Правило подстановки применяется только для
общезначимых формул). Технически процесс вывода будет заключаться в получении ряда последовательных формул B1,
B2, B3..., каждая из которых выводится из всех Е плюс те Bn, что уже получены прежде. Процесс длится до тех пор, пока
одна из очередных Bk не совпадет с B, т.е. когда Bk = B.
Правило заключения не меняет истинности, и потому справедливо утверждение, что если B выводима из {E}, то
она должна принимать значения И при тех же интерпретациях, что и все Ei. (Вообще-то формулы Ei могут принимать
самые разные значения. Речь идет о значениях истинности, общих для всех них и B в том числе).
Пишут:
(E1, E2, ... En)
B или короче {E}
B.
Говорят также, что B есть логическое следствие из посылок {E}. Вывод из системы аксиом теперь можно
рассматривать как частный случай, когда выполняется условие
{A}
B.
Пример. Знакомое нам правило заключения можно переписать следующим образом: (p, p  q)
q, т.e. q логическое следствие посылок p и p  q. Справедливость этого легко проверяется по таблице истинности:
высказывание q принимает значение И, как только p и
(p  q) одновременно принимают значение И.
Проблема вывода сводится, таким образом, к проблеме дедукции, которая формулируется следующим образом:
требуется определить, является ли формула B логическим следствием множества формул {E}.
Чтобы подчеркнуть, что Ei не являются аксиомами, их иногда обозначают через Hi и называют гипотезами, а
формулу B - заключением:
(H1, H2, ... Hn)
B.
(5.1)
Если гипотезы рассматривать как посылки в рассуждении, то из определения логического следствия следует, что
заключение истинно только тогда, когда все посылки истинны. Заметим также, что если для множества {E} не
существует такой интерпретации, при которой все Ei принимают значения И, то множество {E} считается
невыполнимым и обозначается
(E1, E2, ... En)
Л или (H1, H2, ... Hn)
Л
(5.2)
Сразу же отметим одно важное свойство, следующее из определения логического следствия. Если {E}
B, то
B принимает значение И как только все Ei также принимают значение истинности. Исключается, таким образом, случай,
когда B=Л при всех Ei=И (обозначим: {E}=И). Остальные варианты вполне допустимы. Сведем их в табличку, добавив
столбец с импликацией, которая нам сейчас пригодится:







{E}
И
Л
Л
И

Таблица 3
B
И
И
Л
Л

{E}B
И
И
И
Исключ.
Из таблицы 3 следует очевидный и важный вывод: если B - логическое следствие из множества {E},то
импликация {E}B - тождественно истинна.
Условие одновременной истинности всех Ei соответствует требованию конъюнкции. Следовательно, можно
написать
(Е1  Е2  Е3 ... Еn) B
И
или иначе
( H1  H2  H3... Hn) B
И.
(5.3)
Вопрос, таким образом, сводится к определению тождественности выражения (5.3).
Пример. Известное нам правило заключения может быть записано следующим образом
а) (p, p  q)
q.
Если q - логическое следствие из p и p q, то выражение
b) (p  (p q)) q
должно быть тождеством.
Покажем это. Приведем ппф b) к конъюнктивной нормальной форме (дизъюнкцию будем обозначать +).
Освободимся от импликаций и преобразуем:



 p p  q   q
p   p  q  q ;
126
p   pq  q;
с)  p  q    pq  .
К выражению c) применим распределительный закон раскрытия конъюнкции по дизъюнкции:
d)
 p  p  q p  q  q   И.
Полученная конъюнктивная форма d), очевидно, тождественна, поскольку каждый из двух ее дизъюнктов равен
И, (ибо
p  p =И, q  q =И). Что и требовалось доказать.
B данном примере мы вновь встретились с задачей определения тождественности формулы. B более общей
формулировке она будет встречаться нам и в дальнейшем: требуется определить, к какому из трех классов принадлежит
данная формула, является ли она: а) тождественной, б) невыполнимой или в) выполнимой. B этом состоит проблема
разрешения.
2.
Алгоритмическая проблема разрешения в ИВ
Задача, состоящая в отыскании процедуры, позволяющей для любой формулы выяснить, к какому из трех
вышеназванных классов она принадлежит, называется еще семантической проблемой разрешения. B соответствии с
этим, процедура, позволяющая конечным числом простых действий решить проблему разрешения, называется
разрешающей процедурой. Самое естественное решение здесь - обратиться к таблице истинности. Таблица даст
исчерпывающий ответ о поведении формулы при всех возможных интерпретациях. Но этот прием малоэффективен,
поскольку практически он применим лишь для малого числа аргументов (литер). Если формула из двух литер имеет 4
варианта интерпретаций (т.е. 4 строки), то формула из четырех литер уже 16, из пяти соответственно 32 и т.д. по степени
n
2 строк таблицы истинности. Кстати, этот прием мы применили, когда доказывали тождественность первого постулата
ИВ (А1).
Заметим, однако, что для того, чтобы получить разрешающую процедуру, достаточно найти способ,
позволяющий отличить тождественные формулы от всех остальных. Применяем эту процедуру к некоторой формуле А
и, если окажется, что А общезначима, то проблема решена. Если же выясняется, что А не общезначима, то применяем
A
A
эту процедуру для формулы
. Если
окажется тождественной, то, очевидно, А - противоречива. Если
как и А, не тождественная, то это уже значит, что формула А просто выполнима.
Существует несколько методов оценки тождественности формулы:
1) оценка с помощью таблицы истинности,
2) оценка через преобразование, упрощение и приведение к нормальным формам,
3) оценка путем логического вывода из системы аксиом,
4) оценка методом редукции,
5) оценка методом опровержения.
A , так же,
3. Доказательство общезначимости формулы с помощью метода опровержения и метода резолюций.
Метод опровержения

Вернемся к выражению (5.1) (H1, H2, ... Hn)
B и предположим, что оно выполняется, т.е. B - выводимо из {H}.
Если это так, то присоединение B к множеству {H} не влияет на полноту множества {H, B} и не приводит его к
B
противоречию. Иное дело
, которая при этих условиях невыводима. Ее присоединение к {H}, очевидно, приведет к
противоречивости, т.е. можно написать:
B 
(H1, H2, ... Hn,
)
Л.
(5.8)
При этих условиях тождественность импликации (5.3), естественно, нарушается, она становится невыполнимой.
Возьмем отрицание импликации (5.3). Теперь должно выполняться условие
H1  H 2  H 3 ...  H n   B  Л
(5.9)
Доказав невыполнимость (5.8) или (5.9), мы косвенно докажем выполнимость условия (5.1). Такой метод
доказательства "от противного" называется доказательством по методу опровержения.
Метод опровержения очень удобен. B самом деле, вместо того, чтобы кропотливо доказывать общезначимость
F
какой-либо формулы F достаточно доказать невыполнимость ее отрицания
,что в ряде случаев значительно проще.
(B 60-х годах ХХ века был открыт и разработан так называемый принцип резолюций, весьма подходящий для
доказательств подобного рода).
127
Метод резолюций
B сущности, в основе принципа лежит несложная схема рассуждений. Пусть А, B и С - формулы и имеются два
дизъюнкта:
1. ( А + С) и 2. (B +С),
которые мы будем считать истинными. Положим теперь, что С = И.
Подставив это значение в первое выражение, получим дизъюнкт вида А +И, который истинен при любом А.
Подставив С = И во второе выражение, получим дизъюнкт B + Л, из которого однозначно следует, что B = И, поскольку
принято, что весь дизъюнкт истинен.
Положим теперь С = Л. Второй дизъюнкт истинен при любом B, но первый принимает вид А + Л, откуда следует,
что А = И.
Все это означает, что, независимо от интерпретации формулы С, либо А, либо B истинны. Это можно отразить в
виде нового дизъюнкта (А + B), исключив контрарные формулы С и
Другими словами, выполняется правило
C.
C 
(А + C, B +
)
(A + B).
(5.12)
Правило особенно эффективно, если А и B дизъюнкты, а С - высказывание. Это правило называется правилом
резолюции, а вновь полученный дизъюнкт - резольвентой. Он формируется как "сумма" оставшихся формул, за
исключением контрарных, т.е. разных по знаку.
Для дизъюнктов (p + q + r ) и (m + r), например, резольвента будет иметь вид (p + q + m). Для дизъюнктов (p + r)
r ) соответственно (p), а вот в случае (p) и ( p ) обе литеры "уничтожаются". Это пример получения пустого
дизъюнкта. Еще один пример. Имеются два дизъюнкта ( x + y) и (x + y ). Получаемые здесь резольвенты (x + x ) или (y
+ y ) равны 1, информации не несут, их следует отбрасывать.
и (
B логическом плане каждый полученный дизъюнкт - резольвента равносилен обоим дизъюнктам-родителям,
участвовавшим в резолюции, (они так и называются - родители). Он становится очередной гипотезой и участвует в
резолюции на равных с другими. Это касается и пустого дизъюнкта, но будучи поставлен в ряд гипотез Нi, он делает
формулу типа (5.10) равной 0, что и является ее доказательством.
Пример. Доказать невыполнимость множества дизъюнктов:
H = (p + q, p + r,
q + r, p ). Пронумеруем гипотезы:
1. p + q,
2. p + r,
q  r,
4. p .
3.
Далее применяется правило резолюции. Полученные резольвенты присоединяются к исходному множеству, с
ними снова можно проводить резолюции. Ниже следует список резольвент, в скобках указываются номера резольвент,
участвовавших в резолюции.
5. q
(1,4),
6. r
(2,4),
7.
q
(3,6),
8. Л
(5,7).
Надо отметить, что выбранный путь порождения резольвент может быть не единственным. Например, в нашем
случае, результат можно было получить чуть быстрее, если пойти по следующему пути:
r
5. p +
(1,3),
6. p
(2,5),
7. Л
(4,6).
Как видно из примера, метод резолюций легко представим в виде несложного регулярного алгоритма. Это
предопределяет успешное применение ЭВМ в решении задач вывода, хотя здесь и возможны неожиданные трудности.
Дело в том, что машина ищет резолюцию слепо, методом перебора. При таком поиске путь к результату может быть
весьма долгим. Возможны случаи простого зацикливания машины. Простейший пример: имеется два дизъюнкта p и
p +q.
При машинной реализации резольвента q может порождаться неограниченное число раз. Предусматривая
подобные случаи, применяют специальные стратегии поиска резольвент и соответствующее программирование.
Некоторые такие стратегии мы рассмотрим в следующем разделе.
В заключение отметим такое важное обстоятельство:
Множество резольвент (вместе с родительскими дизъюнктами) образует не что иное как математическую модель
некоторой предметной области. Каждая новая резольвента добавляет новое состояние в пространство состояний Мпо, а
поиск решения в пространстве состояний представлен операцией логического вывода.
49.
Исчисление предикатов как метод представления знаний. Предикаты, виды термов в предикатах.
Квантор общности и квантор существования. Исключение кванторов, сколемизация, предваренная форма.
Логический вывод в ИП.
128
Исчисление высказываний является грубой моделью представления знаний. Основной ее недостаток в том,
что высказывание здесь рассматривается как единое целое, без анализа его внутренней структуры. Это ограничивает
возможности ИВ при моделировании сложных силлогических построений. Элементарный пример, часто
приводящийся в таких случаях. Имеется классический силлогизм:
Все люди смертны;
Сократ - человек;
Следовательно, Сократ смертен.
С точки зрения логики, вывод здесь безупречен, но он уже выходит за рамки ИВ. В самом деле, с помощью
пропозициональных связок и букв, его можно записать в виде следующей формулы:
a  b  c.
Но эта формула необщезначима! А это значит, что логика высказываний не позволяет корректно выразить
приведенный силлогизм.
1.
Исчисление предикатов как метод представления знаний.
Предикаты, виды термов в предикатах
Если высказывание отражает какой-либо факт и далее оперирует с ним как с единой формулой, не разделяя его,
скажем, на субъекты и объекты, то предикатная форма, напротив, отображает данный факт уже как взаимодействие,
отношение или свойство некоторых сущностей. Это отношение принято выделять прописными буквами перед
скобками, в которых указываются те или иные сущности, находящиеся в данном отношении.
Рассмотрим несколько предложений.
Лена и Таня сестры
грибы в лесу,
капля долбит камень,
снег белый,
мальчик послал книгу брату.
В правилах исчисления предикатов эти предложения можно записать следующим образом.
а') СЕСТРЫ (Лена, Таня),
б') В (лес, грибы),
в') ДОЛБИТЬ (капля, камень),
г') БЕЛЫЙ (снег),
д') ПОСЫЛАТЬ (мальчик, брат, книга).
В первом предложении выделено отношение родства, во втором - предлогом В - пространственные отношения.
В предложении в') выделено действие между субъектом и объектом, в предложении г') - свойство (в данном случае цвет), в предложении д') - также действие. Но рассмотрим эти примеры подробнее.
То, что стоит перед скобками и выделено прописью, называется предикатным символом (предикатной
константой). То, что стоит в скобках, называется термами. Каждый терм занимает свое место. Предикатные символы
могут быть предлогами, существительными, глаголами, прилагательными и т.п.. Терм, как правило, существительное
или то, что его заменяет. Все это вместе образует предикатную формулу (или короче - предикат).
Термов может быть несколько. По их количеству предикаты разделяются на одноместные (г'), двуместные (а',
б', в'), трехместные (д') и т.д. Предикатная формула еще называется атомом. Но и термы бывают разными. В примере а')
оба терма обозначены вполне конкретно - Лена, Таня. В этом случае они называются индивидные константы. Во
втором предикате оба терма заданы в самом общем виде: какие-то грибы в каком-то лесу. Их можно просто обозначить
через буквы x и y - они так и называются - индивидные (предметные) переменные. Сами же предикатные символы,
которые, как мы видели, много чего отображают, также обозначаются буквами - прописными, латинского алфавита: P,
R, M... Иногда к ним добавляются индексы: P1, P2, ... Pn, иногда указывают число мест: Pк1, Pк2... . Говоря о терме, мы не
упомянули еще один его вид: терм может быть выражен через функцию.
Разберем все сказанное на примерах.
1)
ПИСАТЬ (Лермонтов, "Демон"). "Лермонтов написал "Демона"" - все ясно: ПИСАТЬ - предикатная
константа, двуместный предикат, оба терма - индивидные константы. Обозначим через X множество
стихотворений Лермонтова. Тогда предикат вида: ПИСАТЬ (Лермонтов, x) означает: "Лермонтов написал
129
какое-то стихотворение". А вот предикат: ПИСАТЬ (y, x), где под y понимается какой-то человек, означает:
"кто-то написал что-то", x и y здесь - индивидные переменные.
2) Обозначим через g некоторую функциональную константу, например, "быть варёным". Если картофель
обозначить через s, то предикат НА (стол, g(s)) теперь истолкуется как "на столе варёная картошка". Пусть f
- функциональная константа "быть отцом", а m - функциональная константа "быть матерью". В этом случае
предикат P (f(Лена), m(Лена)) следует истолковать просто как РОДИТЕЛИ. (Тот же результат, впрочем,
даст и более общая формула: P(f(x), m(x)), где x - один и тот же ребенок).
Из рассмотренного можно сделать некоторые выводы. Во-первых, термы нельзя менять местами. Иначе
получится, что на картошке стоит вареный стол, а Демон написал "Лермонтова". И во-вторых: не следует путать
предикатный и функциональный символы. Предикат МАТЬ (х,y) означает: y есть мать х. Либо это правда, либо это
неправда, поэтому область значений предиката [1,0] или [И,Л]. Функция м(x) означает "быть матерью", равенство м(x) =
y - "матерью х является y". Область определения х - вообще говоря, все человечество, область значений y - все женщины
определенного возраста.
Квантор общности и квантор существования.
2.
ИП - аксиоматическая система, построенная согласно формальной теории F = (A, V, W, R).
Словарь ИП (A) содержит:
индивидные константы a, b, c...;
предметные переменные x, y, z,...;
функциональные константы f, g, h ..;
высказывания p, q, r, s,....;
предикатные константы P, Q, R,.. .
Исчисление предикатов, в определенном смысле, продолжение и расширение исчисления высказываний,
 ,  , НЕ ,  ,  . Но перечень логических
знаков в ИП расширяется еще двумя, называемых кванторами:  и  . Квантор  читается как "все", "для всех",
"всякий", "каков бы ни был" и т.п. Поэтому он называется квантором всеобщности (общности). Квантор  читается
поэтому в словарь включены все те же пропозициональные связки
как "некоторый", "хотя бы один", "существует" и т.п.. Поэтому он называется квантором существования. Так,

например, выражение
xP(x) читается: "для любого x выполняется условие P(x)". Выражение
хотя бы один y, при котором выполняется P(y) (т.е. Р(у) = И)".
 yP(y) - "существует
Множество синтаксических правил V ИВ применимо и в ИП. Правильно построенные формулы в рамках
исчисления высказываний остаются ппф и в исчислении предикатов. Добавляются правила:
атом есть формула и
если Р(х) формула и х - переменная, то
 хР(х) и  хР(х) - формулы.
Каждому квантору соответствует только одна переменная, в наших примерах x или y. Эта переменная
называется квантифицированной, она пишется сразу за квантором. Область действия квантора - формула, к которой
применяется эта квантификация. Каждое вхождение квантифицированной переменной в область действия
квантификации является связанным, любая другая переменная в данной области, не являющаяся связанной, называется
свободной.
xRx , y   yM x , y , z   Qx , y . Здесь все вхождения
переменной x связанные, т.к. попадают в область действия квантора x , которая включает в себя все предикаты: R,M
Рассмотрим формулу
и Q (следите за скобками). А вот первое вхождение переменной y (в предикате R) - свободное. В дальнейшем y попадает
в область квантификации
y
и является связанным (в предикатах M и Q). Переменная z - свободная.
130
Каждую предикатную формулу можно интерпретировать, т.е. оценить ее как И или Л. При этом можно оценить
"перекрытие" кванторов на одну и ту же переменную:
xxPx  интерпретируется как xPx  , а
xxPx  интерпретируется как xP x .
Это и понятно: вместо того, чтобы говорить " из всех х существует хотя бы один х, при котором Р истинен",
достаточно сказать просто: "существует хотя бы один х и т.д.". И наоборот, чтобы не говорить странное словосочетание
"существует хотя бы один х, такой, что для всех х Р истинен", достаточно сказать "для всех х ...". (Для запоминания: из
двух кванторов "прав" самый правый).
Будем понимать под А предикат A(x,y) и отметим важные соотношения:
xyA  yxA ,
xyA  yxA,
(6.1)
т.е. одноименные кванторы можно менять местами. Иное дело разноименные кванторы. Здесь выполняется только такое
условие:
xyA  yxA .
(6.2)
Последняя импликация поясняется следующим примером. Пусть имеем для целых чисел истинное
yxx  y  0 (для любого y найдется такой х, что выполняется равенство x + y = 0 ).
Переставим кванторы: xy  x  y  0. Получим выражение: существует такой х, при котором выполняется
условие ( x + y = 0 ) для всех y, что некорректно.
утверждение:
Система базовых аксиом W в ИП может быть принята такой же, как и в ИВ. Однако к ней необходимо
добавить аксиомы, учитывающие появление кванторов:
(A4)
xPx   P y  ,
(A5)
P y   xPx  .
A4 говорит, что если P(x) истинен для всех х, то он истинен и для некоторого y из этого же универсума (если
все яблоки в данном ящике красные, то одно-то красное уж найдется всегда).
А5 говорит, что если найдется y, при котором P(y) истинен, то верно, что найдется хотя бы один x, для
которого предикат P(x) тоже истинен (даже если x совпадает с y). (Если среди яблок в данном ящике нашлось одно
сладкое, то уже существует по крайней мере одно сладкое).
Правила вывода R здесь остаются прежними: правило подстановки и правило заключения, но они дополняются
еще одним правилом, учитывающим свойства кванторов. Это правило называется правилом специализации. Суть его в
xPx  истинна и b - некоторая константа, то формула P(b) также истинна, т.е. справедливо
xPb  P(b) . Пусть, например, имеются формулы xPb  Qx  и P(b). Если они истинны, то,
следующем: если ппф
применяя специализацию, имеем ряд теорем:
xPb  Qb,
131
Pb  Qb,
т.е.
(специализация)
(modus ponens с P(b)).
Q(b)
Исключение кванторов, сколемизация, предваренная
форма.
3.
Исключение квантора существования, сколемизация.
Если А не содержит х, то очевидно:
 xA = A и  xA = A. "Очевидно" - потому что кванторы здесь ничего не
определяют и не дают. Это элементарный пример исключения кванторов.
Рассмотрим теперь формулу
 xP(x) (существует хотя бы один
х, при котором Р(x) = И). Пусть этот х будет
равен с, тогда указанная формула запишется просто P(с). Константа с любая, однако, она не должна совпадать с другими
символами, применяемыми в других формулах. Это - второй пример исключения квантора существования. Он касается
 не находится в области действия какого-либо квантора общности.
теперь формулу  x  yP(x,y) (для всех х существует по крайней мере
случая, когда сам квантор
Рассмотрим
один y такой, что
выполняется предикат P(x,y)). Ясно, что y, удовлетворяющий этому условию, как-то зависит от х. Эту зависимость
можно отобразить с помощью некоторой функции, например, g(x). Эта функция теперь заменяет y, а квантор
существования можно просто убрать:
 xP(x,g(x)).
Функция типа g(x), отображающая каждое значение х в "тот самый y", называется функцией Сколема или
сколемовской.
Особенности:

 , то он не находится в области его действия и
1) если квантор
стоит перед квантором общности
поэтому заменяется, как в прежнем примере, некоторой константой:
 x  yP(x,y) =  yP(a,y).

2) если квантор
находится в области действия нескольких кванторов общности, то соответствующая его
переменная заменяется сколемовской функцией от соответствующего числа переменных (мест):
 x  y  r  wP(x,y,r,w) =  x  y  rP(x,y,r,g(x,y,r)) -
"собственная" переменная квантора существования w заменяется сколемовской функцией g, зависящей от всех
квантифицированных переменных, в сфере действия которых она находится.
3) Следующий пример говорит сам за себя:
 x  yP(x,y) = P(a,b).
4) Еще один пример:  x[P(x,y)   y(M(y,z)  R(y,z,q))]=  x[(P(x,y)  (M(g(x),z)  R(g(x),z,q))].
Сколемовская функция g(x) заменяет y во всех местах его вхождения в области действия квантора  .
Рассмотрим и осмыслим теперь такой обобщающий пример:
    y  r  w  s  v  qM(z,x,u,y,r,w,s,v,q).
5) Дано: z
x u
После сколемизации:
 x  y  r  vM(а,x,f(x),y,r,g(x,y,r),h(x,y,r),v,p(x,y,r,v)).
Предваренная форма
Полученная только что, после сколемизации, формула имеет вполне определенный вид. Она состоит из
цепочки кванторов, называемой префиксом и бескванторной формулы, называемой матрицей. Представить какую-либо
132
формулу в виде префикса и матрицы - это значит представить ее в предваренной форме. Особенность предваренной
формы в том, что все кванторы оказываются вынесенными влево за пределы общей формулы, а часть, оставшаяся без
кванторов, может быть подвергнута всем возможным преобразованиям, в частности, быть представленной в
конъюнктивной нормальной форме, такой необходимой нам для реализации принципа резолюции.
Для любой логической формулы существует логически эквивалентная ей предваренная форма.
Это правило вытекает из тех преобразований, которые необходимо для этого проделать - они известны и всегда
выполнимы:
 исключить связки эквивалентности и импликации;
 переименовать
(если
необходимо)
связанные
переменные
таким образом, чтобы каждый квантор имел свою переменную;
 удалить те квантификаторы, область действия которых не содержит квантифицированной переменной, как
ненужные;
 ограничить область действия отрицания;
 провести сколемизацию;
 переместить все кванторы общности в начало формулы, образовав префикс и матрицу.
К моменту последней операции перемещения кванторов связанные переменные уже разделены, каждый
квантор общности имеет свою переменную, независимые переменные заменены постоянными (конкретизация). Будучи
перемещенным в начало формулы, он и все равно распространяют влияние лишь на "свои" переменные. Широко
используются приведенные ранее равносильности (6.1) - (6.7). Может пригодиться еще и правило раскрытия
импликации:
 x(A(x)  B(x)) =  xA(x)   xB(x).
(6.8)
4.
Логический вывод в исчислении предикатов
Так же, как и в исчислении высказываний, проблема вывода в ИП сводится к проблеме дедукции, т.е. к
решению вопроса: является ли формула В логическим следствием множества формул {E}. Напомним, что ппф B
является логическим следствием множества {E}, если она принимает значение И всякий раз, как только все Еi
одновременно принимают значение И. Вопрос решался через доказательство теоремы дедукции, которая справедлива и
в ИП, с учетом, впрочем, ряда оговорок и условий, касающихся действий со связными и свободными переменными. Так
же, как и в ИВ, встает проблема определения общезначимости той или иной формулы. И решается она примерно так же,
т.е. как минимум пятью способами, каждый из которых применим в ИП:
1) оценка с помощью таблицы истинности,
2) оценка через преобразование, упрощение и приведение к нормальным формам,
3) оценка путем логического вывода из системы аксиом,
4) оценка методом редукции,
5) оценка методом опровержения.
Однако самым эффективным средством порождения и/или доказательства следствий здесь по-прежнему является метод
резолюций
50.
Программирование на языке Пролог. Основные конструкции языка. Виды термов и их синтаксис.
Функциональные термы. Использование функциональ-ных термов для моделирования состояния предметной
области.
Программирование на языке Пролог.
Пролог (англ. Prolog) — язык и система логического программирования, основанные на языке предикатов
математической логики дизъюнктов Хорна, представляющей собой подмножество логики предикатов первого порядка.
Математическая логика дает нам ясный и точный язык для явного выражения знаний, гипотез и целей. Возможность
машинного доказательства теорем, основанного на специальном выводе, названном принципом резолюций, впервые
была получена Дж. Робинсон в 1965 году. Это привело к желанию построить язык программирования, который
133
позволил бы реализовать одну из интеллектуальных сторон деятельности человека - проведение рассуждений в виде
программ.
В начале 70-х годов прошлого века группой под руководством А. Колмероэ в Марселе на Фортране была написана
программа для доказательства теорем, названная Прологом (от Programmation en Logique). Это привело в конце
десятилетия к разработке языка Пролог и в дальнейшем развитию этого языка и в целом направления, которое получило
название логического программирования.
Язык Пролог близок к модели Маркова: также основой является поиск подходящей подстановки - интерпретация
переменных. Но подстановки ищутся в правилах языка (аналог рефал-предложений), и целью является именно поиск
подстановки.
Программа на Прологе состоит из правил, которые представляют собой продукции с предикатами (относительно
объектов) в левой и правой части. Тем самым программа Пролога выражает некоторые знания о внешнем мире (задаче
или группе задач), необходимые для решения задач. Правила, не содержащие посылки в продукции, называются
фактами, а вся система правил программы образует базу знаний.
Вопрос задачи, называемый запросом, - это также некоторый предикат, истинностью которого мы интересуемся. Если
запрос не содержит переменных, то вычисление его значения дает ответ "Да" при его истинности либо ответ "Нет" при
его ложности. Если же в предикате запроса есть переменные, то ищутся их значения (интерпретация), при которых этот
предикат и все предикаты программы становятся истинными. В этом и состоят вычисления программы на Прологе.
Основные конструкции языка.
Так как каждый предикат - это функция, то Пролог является языком функционального программирования.
Итак, в языке Пролог рассматриваются объекты и 3 вида утверждений относительно объектов: факты, правила и
запросы. Единственной структурой данных является терм.
Объекты и термы Пролога
Объектами Пролога являются
1) имена (начинаются со строчной буквы), строки символов (заключаются в апострофы) и числа - константные
объекты или константы; например, автомобиль, дом, иван, 'a+b', 'X', 123;
2) переменные - могут принимать значения других объектов, и мы их будем писать прописными латинскими
буквами: например, X, A, W;
3) списки - их элементами являются любые объекты; списки мы заключаем в квадратные скобки, разделяя
элементы запятыми; например, [] - пустой список (он является константой, мы его будем обозначать также nil и
любой список завершать этим элементом, чтобы показать конец списка), [a, b, c, nil] - список, состоящий из
трех констант a, b и c; [X, [b, Y, 'X', nil], nil] - список, состоящий из двух элементов, первый из которых переменная X, а второй - список из трех элементов: имени b, переменной Y и строки 'X'.
4) Завершающий список элемент nil можно при записи опускать, подразумевая его в необходимых случаях.
Для конкатенации (соединения) списков и элементов в один список используется точка как бинарная операция
соединения левой части (головы списка) и правой части (хвоста списка). В случае операции конкатенации квадратные
скобки на нулевом уровне можно опускать. Например, a.X.Y.a при X=b, Y=c есть список [a, b, c, a], также при X=[b],
Y=[c] есть тот же список, а при X=[b, [d, e]] и Y=[[c]] есть список [a, b, [d, e], [c], a].
Теперь индуктивно введем понятие терма. Термами являются объекты Пролога. Кроме того, термами являются
составные термы. Составной терм образуется из имени функции и списка аргументов (термов Пролога) в круглых
скобках. Синтаксически составной терм имеет вид
f(t1,..., tn),
где f - имя n-арного функтора, а ti (i 1,n)- аргументы.
Примерами составных термов являются: холодный (вода), отец (иван, петр), list(d, list(b, nil)) и bintree(bintree(nil, 7, nil),
L, 12).
В первом примере составным термом является высказывание с именем булевой функции 1 аргумента-константы,
которое имеет логическое значение истина или ложь.
Во втором примере отношение "иван является отцом петра" задается как булева функция с 2 аргументами-константами.
В третьем примере бинарная функция с именем list и двумя аргументами имеет в качестве первого аргумента
константный объект d , а в качестве второго аргумента - составной терм с именем той же функции и возвращает, повидимому, список.
В четвертом примере функция с именем bintree и тремя аргументами возвращает в виде списков бинарное дерево с
корнем 7, правым сыном 12 и левым сыном, который определяется переменной L .
Термы, в которые не входят переменные, назовем основными, а термы, содержащие переменные, - неосновными. Так,
три первых примера выше являются основными термами, а четвертый пример - неосновным термом.
В логическом программировании основной структурой является предикатная функция, описываемая составным термом,
которая имеет истинностное значение (истина или ложь), возможно зависящее от значений аргументов. Такой предикат
называется атомарным, или атомом.
Факты
Факты - это простейшие утверждения относительно объектов программы, которые считаются истинными, т. е. имеют
смысл аксиом программы. Каждый факт оформляется в виде атомарного предиката и стрелки влево, которая находится
справа от него. Так, в следующем примере
мужчина (иван)
134
мужчина (петр)
отец (иван, петр)
произведение (2, 2, 4)
задается, что объекты иван и петр являются мужчинами, что иван является отцом петра и что дважды два - четыре.
Почему ставится стрелка? Общий вид записи продукции "если A, то B", где A и B - предикаты, выражается на Прологе
следующим образом:
B
A.
Факт не имеет посылки и читается "то B", т. е. утверждение B рассматривается как истинный факт.
Множество фактов образуют простейшую программу Пролога. Но атомарный предикат факта может содержать
переменные в качестве аргументов или неосновные термы. В этом случае по умолчанию считается, что добавлен
квантор всеобщности с переменными предиката. Такие факты называются универсальными: они истинны для любых
значений переменных. Например,
любит (X, яблоко)
означает, что любой объект программы "любит яблоко". Универсальные факты сокращают запись программы.
Правила
Хотя универсальные факты могут сократить запись, но все же использование только этого приема не всегда позволяет
создать обозримую базу знаний либо в принципе не позволяет ее создать.
Приведем следующий пример. Необходимо создать базу знаний для определенного круга лиц, которая могла бы
выразить родственные их связи. Рассмотрим естественный путь, при котором задаются отношения отец, мать, дочь, сын.
С одной стороны, эти отношения могут оказаться избыточными или вести к серьезным логическим ошибкам из-за того,
что некоторые факты не введены. Скажем, у двух лиц есть отношение отец, но нет симметричного отношения сын. С
другой стороны, очень непросто написать предикаты для установления родства между любыми двумя лицами при таком
задании фактов. Казалось бы, выход может быть найден, если ввести другие отношения, например, брат, сестра, кузен,
кузина, дедушка, бабушка, внук, внучка. Но и в этом случае корректность программы (совокупности фактов) в связи с
большой избыточностью будет трудно проверять, а проблемы с простым установлением родства двух любых лиц
останутся.
Выходом может быть введение помимо двух отношений отец и мать отношения предок, частным случаем которого
являются первые 2 отношения. В результате для выявления родства между любыми двумя лицами достаточно написать
предикат, который устанавливает, является ли одно из лиц предком другого либо имеется ли у этих лиц общий предок.
Это значительно проще, но надо ввести помимо фактов для отношений отец и мать правило, которое позволяет ввести
отношение предок и в то же время не заставляет описывать дополнительные факты для этого отношения.
Правило Пролога есть продукция, посылкой которой является конъюнкция атомарных предикатов, а заключением - 1
атомарный предикат. Правило имеет следующий синтаксис:
A
B1,..., Bm (m
0),
где A, Bi (i 1,m) - атомарные предикаты и запятая в правой части правила означает конъюнкцию. Читать правило
нужно так: "Если B1 и B2 и т.д. и Bm, то A." Нетрудно видеть, что факт Пролога есть правило с пустой правой частью
(m=0). Левая часть правила называется его заголовком, а правая часть - телом правила. Совокупность правил с одним и
тем же предикатом в заголовке называется процедурой.
Решение вышеописанного примера состоит в определении отношения предок следующим образом: предком лица
является либо мать, либо отец, либо мать предка, либо отец предка. Таким образом все решение сводится к следующей
процедуре из 4 правил:
предок (X, Y)
мать (X, Y)
предок (X, Y)
отец (X, Y)
предок (X, Y)
предок (Z, Y), мать (X, Z)
предок (X, Y)
предок (Z, Y), отец (X, Z)
135
Заметим, что отношение предок определено этими правилами рекурсивно. Теперь для определения родства между
двумя лицами достаточно также задать рекурсивно отношение родственники следующей процедурой из 3 правил:
родственники (X, Y)
предок (X, Y)
родственники (X, Y)
предок (Y, X)
родственники (X, Y)
предок (Z, X), предок (Z, Y)
Заметим, что обозначения переменных в правилах несущественны, лишь бы они обозначались одинаково в заголовке и
теле процедуры. Но если на все переменные левой части подразумевается наложенным квантор всеобщности , то на
все переменные правой части, которые отсутствуют в левой, подразумевается наложенным квантор существования .
Совокупность фактов и правил образует программу Пролога (или базу знаний).
Запросы
Запросы - это цели выполнения программы Пролога. Запрос является атомарным предикатом или конъюнкцией
атомарных предикатов и имеет синтаксис:
B1,..., Bm (m > 0),
где Bi (i 1,m) - атомарный предикат, а запятая, разделяющая атомы, означает операцию конъюнкции. Обозначение
переменных запроса несущественно, и при переобозначении каждой переменной запрос не изменяется.
Если запрос не имеет переменных, то ответом на запрос является значение "Да" в случае, когда истинность конъюнкции
предикатов запроса следует из истинности конъюнкции фактов и правил программы, и значение "Нет" в противном
случае.
Если запрос имеет переменные, то по умолчанию подразумевается квантор существования перед конъюнкцией
предикатов запроса для каждой переменной запроса. Если для какого-либо набора Υ значений переменных запроса и
какого-либо соответствующего переобозначения переменных в правилах и фактах и придания им согласованных с
запросом значений истинность конъюнкции предикатов запроса следует из истинности конъюнкции фактов и правил, то
такой набор Υ является ответом на запрос. Вычисления Пролога состоят в получении всех ответов Υ1, Υ,... на запрос.
Однако если не существует такого набора значений переменных запроса, который ведет к следованию истинности
запроса из истинности фактов и правил программы, то ответом на запрос является значение "Нет". Отметим лишь, что
данное определение не является достаточно четким и мы его в дальнейшем уточним.
Рассмотрим пример программы, которая образована из следующей совокупности фактов
отец (иван, петр)
отец (петр, анна)
отец (яков, мария)
мать (анна, федор)
мать (елена, иван)
мать (елена, яков)
мать (софья, вера)
Пусть имеется запрос
136
родственники (федор, мария).
Этот запрос не имеет переменных. Но правила процедуры предок позволяют установить, что предками федора являются
анна, петр, иван и елена, а предками марии являются яков и елена. Поскольку федор и мария имеют общего предка
елену, то правила процедуры родственники позволяют установить истинность запроса. Поэтому ответ на него Да.
Для запроса
родственники (вера, мария).
не удается установить его верность, так как ни вера не является предком марии, ни мария не является предком веры и
нет у них общего предка. Поэтому ответ на запрос Нет.
Пусть теперь имеется запрос
предок (X, федор).
Этот запрос требует установить всех лиц, которые являются предками федора. Ответы на запрос образуют список анна,
петр, иван, елена значений переменной X, каждое из которых логически выводится из фактов и правил.
Рассмотрим другой запрос
предок (елена, X).
Этот запрос требует установить всех лиц, для которых елена является предком (потомки елены). Ответы на запрос
образуют список иван, яков, петр, мария, анна, федор.
Наконец, для запроса
предок (вера, X)
нет ни одного значения переменной X, при котором мы могли бы вывести это отношение. Поэтому ответом на запрос
является Нет, т. е. вера не имеет потомков.
Рассмотренные примеры показывают, что вопросы (при помощи переменных) можно задавать к любой части запроса.
Однако мы не определили, как происходят вычисления в Прологе, дающие эти результаты.
51.
Программирование на языке Пролог. Основные разделы программы. Факты, правила и цели (вопросы).
Простые и списочные вопросы. Переменные, анонимные переменные. Логические связки в Прологе.
Логическая модель знаний
Логическая модель знаний состоит из фактов и правил.
Факт (от лат. factum – сделанное, свершившееся) — это частное утверждение.
Например: Земля – планета Солнечной системы.
Правило — это утверждение общего характера, справедливое для многих объектов.
Например: ЕСЛИ планета движется вокруг Солнца, ТО это планета
Солнечной системы.
В логической модели знаний факты представляют собой декларативные знания (я знаю, что…), а правила –
процедурные знания (я знаю, как…). Поэтому с помощью правил можно вывести новое знание.
Логическая модель знаний положена в основу языка логического программирования ПРОЛОГ.
1. Программирование на Prolog.
В Прологе (Prolog — PROgramming LOGic) вы получаете решение задачи логическим выводом из ранее
известных положений. Обычно программа на Прологе не является последовательностью действий, — она представляет
собой набор фактов с правилами, обеспечивающими получение заключений на основе этих фактов. Поэтому Пролог
известен как декларативный язык.
137
Пролог базируется на предложениях Хорна, являющихся подмножеством формальной системы, называемой
логикой предикатов.
Пролог включает механизм вывода, который основан на сопоставлении образцов. С помощью подбора ответов
на запросы он извлекает хранящуюся (известную) информацию, т.е. знание Пролога о мире — это ограниченный набор
фактов (и правил), заданных в программе.
Одной из важнейших особенностей Пролога является то, что, в дополнение к логическому поиску ответов на
поставленные вами вопросы, он может иметь дело с альтернативами и находить все возможные решения. Вместо
обычной работы от начала программы до ее конца, Пролог может возвращаться назад и просматривать более одного
"пути" при решении всех составляющих задачу частей.
Программист на Прологе описывает объекты (objects) и отношения (relations), а затем описывает правила (rules),
при которых эти отношения являются истинные.
База знаний на Прологе состоит из базы данных и правил.
База данных на Прологе – это совокупность фактов. В процессе работы ее можно корректировать: добавлять
факты, удалять и изменять факты, утратившие актуальность. База данных – обязательная составляющая любой базы
знаний.
2. Основные разделы Visual Prolog - программ
Обычно программа на Visual Prolog состоит из четырех основных программных разделов. К ним относятся:
 раздел clauses (предложений);
 раздел predicates (предикатов);
 раздел domains (доменов);
 раздел goal (целей).
2.1 Раздел предложений (clauses).
В раздел clauses (предложений) помещаются все факты и правила, составляющие программу.
•Факты — это отношения или свойства, о которых известно, что они имеют значение "истина".
Факт представляет либо свойство объекта, либо отношение между объектами. Факт самодостаточен. Для
подтверждения факта не требуется дополнительных сведений, и факт может быть использован как основа для
логического вывода.
Факт в Visual Prolog состоит из имени отношения и объекта или объектов, заключенных в круглые скобки. Факт
завершается точкой (.).
Т.е. предложение на естественном языке Билл любит собак. (Bill likes dogs)
на синтаксисе Visual Prolog будет выглядеть likes (bill, dogs).
Факты помимо отношений, могут выражать и свойства. Так, например, предложение естественного языка
"Kermit is green" (Кермит зеленый) на Visual Prolog, выражая те же свойства, выглядит следующим образом: green
(kermit)
• Правила — это связанные отношения; они позволяют логически выводить одну порцию информации из другой.
Правило принимает значение "истина", если доказано, что заданный набор условий является истинным.
Правило — это свойство или отношение, которое достоверно, когда известно, что ряд других отношений
достоверен. Синтаксически эти отношения разделены запятыми.
Все правила имеют 2 части: заголовок и тело, разделенные специальным знаком :-.
• Заголовок — это факт, который был бы истинным, если бы были истинными несколько условий. Это
называется выводом или зависимым отношением.
• Тело — это ряд условий, которые должны быть истинными, чтобы можно было доказать, что заголовок правила
истинен.
Ниже представлен обобщенный синтаксис правила в Visual Prolog:
заголовок: - <Подцель>, <Подцель>,..., <Подцель>.
Тело правила состоит из одной или более подцелей. Подцели разделяются запятыми, определяя конъюнкцию, а
за последней подцелью правила следует точка.
Каждая подцель выполняет вызов другого предиката Visual Prolog, который может быть истинным или ложным.
После того, как программа осуществила этот вызов, Visual Prolog проверяет истинность вызванного предиката, и если
это так, то работа продолжается, но уже со следующей подцелью. Если же в процессе такой работы была достигнута
точка, то все правило считается истинным; если хоть одна из подцелей ложна, то все правило ложно.
Ниже представлены правила, соответствующие связи "любить" (likes):
Синди любит все, что любит Билл. (Cindy likes everything that Bill likes)
Кейтлин любит все зеленое. (Caitlin likes everything that is green)
138
Используя эти правила, вы можете из предыдущих фактов найти некоторые вещи, которые любят Синди и
Кейтлин:
Синди любит собак. (Cindy likes dogs)
Кейтлин любит Кермит. (Caitlin likes Kermit)
Чтобы перевести эти правила на Пролог, вам нужно немного изменить синтаксис, подобно этому:
likes (cindy, Something):- likes (bill, Something).
likes (caitlin, Something):- green (Something).
Символ : – имеет смысл "если" (if). Однако if Пролога отличается от if, написанного в других языках, например в
Pascal, где условие, содержащееся в операторе if, должно быть указано перед телом оператора, который может быть
выполнен. Данный тип оператора известен как условный оператор если/тогда (if/then).
Visual Prolog использует другую форму логики в таких правилах. Вывод об истинности заголовка правила
Пролога делается, если (после того, как) тело этого правила истинно, т.е правило Пролога соответствует условной
форме тогда, если (then/if).
Все предложения для каждого конкретного предиката в разделе clauses должны располагаться вместе.
Последовательность предложений, описывающих один предикат, называется процедурой.
Вы можете рассматривать правило и как процедуру. Другими словами, эти правила
likes (cindy, Something):- likes (bill, Something).
likes (caitlin, Something):- green (Something).
также означают: "Чтобы доказать, что Синди любит что-то, докажите, что Билл любит это" и "Чтобы доказать,
что Кейтлин любит что-то, докажите, что это что-то зеленое".
2.2 Раздел предикатов (predicates).
Если в разделе clauses программы на Visual Prolog вы описали собственный предикат, то вы обязаны объявить
его в разделе predicates (предикатов); в противном случае Visual Prolog не поймет, о чем вы ему "говорите". В результате
объявления предиката вы сообщаете, к каким доменам (типам) принадлежат аргументы этого предиката.
Visual Prolog поставляется с большим набором встроенных предикатов (их не нужно объявлять), а интерактивное
справочное руководство предоставляет полное их описание.
Предикаты задают факты и правила. В разделе же predicates все предикаты просто перечисляются с указанием
типов (доменов) их аргументов.
Объявление предиката начинается с имени этого предиката, за которым идет открывающая (левая) круглая
скобка, после чего следует ноль или больше доменов (типов) аргументов предиката:
predicatesName (argument_typel OptionalNamel,
argument_type2 OptionalName2,...,
argument_typeN OptionalName3)
После каждого домена (типа) аргумента следует запятая, а после последнего типа аргумента - закрывающая
(правая) скобка. Отметим, что, в отличие от предложений в разделе clauses, декларация предиката не завершается
точкой. Доменами (типами) аргументов предиката могут быть либо стандартные домены, либо домены объявленные
вами в разделе domains.
Имя предиката должно начинаться с буквы, за которой может располагаться последовательность букв, цифр и
символов подчеркивания. Регистр букв не имеет значения, однако не следует использовать заглавные буквы в качестве
первой буквы имени предиката. Имя предиката может иметь длину до 250 символов.
В именах предикатов запрещается использовать пробел, символ минус, звездочку и другие алфавитно-цифровые
символы.
Аргументы предикатов должны принадлежать доменам, известным Visual Prolog. Эти домены могут быть либо
стандартными доменами, либо некоторыми из тех, что вы объявили в разделе доменов.
Т.е. если предикат my_predicate (symbol, integer) объявлен в разделе predicates следующим образом:
predicates
my_predicate (symbol, integer)
то не нужно в разделе domains декларировать домены его аргументов, т. к. symbol и integer — стандартные
домены. Однако если этот же предикат вы объявляете так:
predicates
my_predicate(name, number),
139
то необходимо объявить, что name (символический тип) и number (целый тип) принадлежат к стандартным
доменам symbol и integer:
domains
name= symbol
number = integer
predicates
my_predicate(name, number),
2.3 Раздел доменов (domains).
В традиционном Прологе есть только один тип — терм. В Visual Prolog мы объявляем домены всех аргументов
предикатов.
Домены позволяют задавать разные имена различным видам данных, которые, в противном случае, будут
выглядеть абсолютно одинаково. В программах Visual Prolog объекты в отношениях (аргументы предикатов)
принадлежат доменам, причем это могут быть как стандартные (табл. 1), так и описанные вами специальные домены.
Таблица 1. Основные стандартные домены
Домен
short
Описание
Короткое, знаковое, количественное
Реализация
Все платформы 16 бит (-32 768 - 32 767)
ushort
Короткое, беззнаковое, количественное
Все платформы 16 бит (0 — 65 535)
Long
Длинное, знаковое, количественное
Все платформы 32 бит
(-2 147 483 648 – 2 147 483 647)
Ulong
Длинное, беззнаковое, количественное
Все платформы 32 бит (0 – 4 294 967 295)
integer
Знаковое, количественное, имеет платформозависимый размер
Платформы 16 бит (-32768 – 32767) Платформы 32 бит
(-2147483648 – 2147483 647)
unsigned
Беззнаковое, количественное, имеет платформозависимый размер
Платформы 16 бит (0 – 65 535)
Платформы 32 бит (0 – 4 294 967 295)
byte
Все платформы 8 бит (0 — 55)
Word
dword
Все платформы 16 бит (0 — 65 535)
Все платформы 32 бит (0 — 4 294 967 295)
Домены типов byte, word и dword наиболее удобны при работе с машинными числами. В основном используются
типы integer и unsigned, а также short и long (и их беззнаковые аналоги) для более специализированных приложений.
В объявлениях доменов ключевые слова signed и unsigned могут использоваться вместе со стандартными
доменами типов byte, word и dword для построения новых базовых доменов. Так:
domains
i8 = signed byte
создает новый базовый домен в диапазоне от -128 до +127.
Другие базовые домены показаны в табл. 2.
Таблица 2. Основные стандартные домены
Домен
Char
Описание и реализация
Символ, реализуемый как беззнаковый byte. Синтаксически это символ, заключенный между двумя одиночными
кавычками: ' а '
Real
Число с плавающей запятой, реализуемое как 8 байт в соответствии с соглашением IEEE; эквивалентен типу double
в С.
Допустимый диапазон чисел: от 1х10-307 до 1х10+308 (от 1е-307 до 1е+308). При необходимости, целые
автоматически преобразуются в real
140
String
Последовательность символов, реализуемых как указатель на байтовый массив, завершаемый нулем, как в С. Для
строк допускается два формата:
1. Последовательность букв, цифр и символов подчеркивания, причем первый символ должен быть строчной
буквой.
2. Последовательность символов, заключенных в двойные кавычки.
Строки, которые вы пишете в программе, могут достигать длины в 255 символов, в то время как строки, которые
система Visual Prolog считывает из файла или строит внутри себя, могут достигать (теоретически) до 4 Гбайт на 32битных платформах.
symbol
Последовательность символов, реализуемых как указатель на вход в таблице идентификаторов, хранящей строки
идентификаторов. Синтаксис — как для строк.
Раздел domains служит двум полезным целям. Во-первых, вы можете задать доменам осмысленные имена, даже
если внутренне эти домены аналогичны уже имеющимся стандартным. Во-вторых, объявление специальных доменов
используется для описания структур данных, отсутствующих в стандартных доменах.
Иногда очень полезно описать новый домен — особенно, когда вы хотите прояснить отдельные части раздела
predicates. Объявление собственных доменов, благодаря присваиванию осмысленных имен типам аргументов, помогает
документировать описываемые вами предикаты.
Покажем, как объявление доменов помогает документировать предикаты:
Франк — мужчина, которому 45 лет.
Используя следующие домены, можно так объявить соответствующий предикат:
domains
name, sex = symbol
age = integer
predicates
person(name, sex, age)
2.4 Раздел цели (goal).
Этот раздел аналогичен телу правила: это просто список подцелей. Цель отличается от правила лишь
следующим:
 за ключевым словом goal не следует :-;
 при запуске программы Visual Prolog автоматически выполняет цель.
Это происходит так, как будто Visual Prolog вызывает goal, запуская тем самым программу, которая пытается
разрешить тело правила goal. Если все подцели в разделе goal истинны, — программа завершается успешно. Если же
какая-то подцель из раздела goal ложна, то считается, что программа завершается неуспешно (хотя чисто внешне
никакой разницы в этих случаях нет, — программа просто завершит свою работу).
Пример: Однократно дав языку Visual Prolog несколько фактов, мы можем задавать вопросы, касающиеся
отношений между ними. На естественном языке мы спрашиваем: Does Bill like dogs? (Билл любит собак?). По правилам
Пролога мы спрашиваем: likes (bill, dogs). Получив такой запрос, Visual Prolog ответит: yes (да), потому что Visual Prolog
имеет факт, подтверждающий, что это так.
Paздел goal является обязательным при написании
автономных Пролог-программ. При работе из оболочки ТП этот
раздел необязателен, т.к. оболочка ТП сама сгенерирует
запрос цели. При этом на экране появится окно диалога, в
котором будет находиться строка запроса цели с ключевым
словом "Goal". Пользователю необходимо только
сформулировать цель в виде одного ( или нескольких)
предикатов, определенных в программе, например:
Goal: age ( "Иванов", X)
Goal: person ( "Иванов", "Петр", 1972, man).
В первом случае Пролог-система сообщит возраст объекта
"Иванов" ( например, Х = 20) , а во втором случае ( т.к.
141
все аргументы конкретизированы, т.е. заранее определены) проверит истинность указанного предиката и сообщит
результат этой проверки (" Yes" или "No" ).
При написании автономной программы пользователь сам
должен позаботиться об отображении получаемого результата.
Для этого в цель, описываемую в разделе goal должны
быть включены предикаты вывода ( например, стандартные
предикаты ТП write или writef):
goal age ("Иванов", X), write ("Возраст",X," лет").
3. Другие разделы программ.
Теперь, когда вы ознакомились с такими разделами программ Visual Prolog, как clauses, predicates, domains и goal,
поговорим о некоторых других, часто используемых разделах программ: facts, constants и различных глобальных (global)
разделах.
3.1 Раздел фактов (facts).
Программа на Visual Prolog представляет собой набор фактов и правил. Иногда в процессе работы программы
бывает необходимо модифицировать (изменить, удалить или добавить) некоторые из фактов, с которыми она работает.
В этом случае факты рассматриваются как динамическая или внутренняя база данных, которая при выполнении
программы может изменяться. Для объявления фактов программы, рассматривающихся как части динамической (или
изменяющейся) базы данных, Visual Prolog включает специальный раздел — facts.
Ключевое слово facts объявляет раздел фактов. Именно в этой секции вы объявляете факты, включаемые в
динамическую базу данных. В Visual Prolog есть несколько встроенных предикатов, облегчающих использование
динамических фактов.
3.2 Раздел констант (constants).
В программах на Visual Prolog можно объявлять и использовать символические константы. Раздел для
объявления констант обозначается ключевым словом constants, за которым следуют сами объявления, использующие
следующий синтаксис: <Id> = <Макроопределение>
<Id> – имя символической константы, а <Макроопределение> — это то, что вы присваиваете этой константе.
Каждое <Макроопределение> завершается символом новой строки и, следовательно, на одной строке может быть
только одно описание константы. Объявленные таким образом константы могут позже использоваться в программах.
Рассмотрим следующий фрагмент программы:
constants
zero = 0
pi = 3.141592653
Перед компиляцией программы Visual Prolog заменит каждую константу на соответствующую ей строку.
На использование символических констант накладываются следующие ограничения:
 описание константы не может ссылаться само на себя:
my_number = 2*my_number/2 % не допускается
это приведет к сообщению об ошибке "Recursion in constant definition" (Peкурсия в описании константы);
 В описаниях констант система не различает верхний и нижний регистры. Следовательно, при использовании в
разделе программы clauses идентификатора типа constants, его первая буква должна быть строчной для того, чтобы
избежать путаницы между константами и переменными.
 в программе может быть несколько разделов constants, однако объявление константы должно производиться
перед ее использованием;
 идентификаторы констант являются глобальными и могут объявляться только один раз. Множественное
объявление одного и того же идентификатора приведет к сообщению об ошибке "Constant identifier can only be declared
once" (Идентификатор константы может объявляться только один раз).
3.3 Глобальные разделы (global).
Visual Prolog позволяет объявлять некоторые разделы domains, predicates, clauses глобальными (а не
локальными); сделать это вы можете, объявив в своей программе специальные разделы global domains, global predicates
и global facts.
4 Переменные.
В Visual Prolog переменные позволяют записывать общие факты и правила и задавать общие вопросы.
142
Имена переменных в Visual Prolog должны начинаться с заглавной буквы (или с символа подчеркивания), после
которой может стоять любое количество букв (заглавных или строчных), цифр или символов подчеркивания. Удобно
использовать в названии переменной буквы разного регистра: IncomeAndExpenditureAccount.
В простом запросе, чтобы найти того, кто любит теннис, можно использовать переменные. Например: likes(X,
tennis).
В этом запросе буква X используется как переменная для нахождения неизвестного человека.
Осмысленный выбор имен переменных делает программу более удобной для чтения Например:
likes(Person, tennis).
лучше, чем
likes (X, tennis).
потому что Person имеет больше смысла, чем X.
Предложение на английском языке Bill likes the same thing as Kim. (Билл любит то же, что и Ким), может быть
записано на Visual Prolog следующим образом:
likes (bill, Thing) :- likes (kim, Thing).
Thing — это переменная.
Если вам нужна только определенная информация запроса, можно использовать анонимные переменные для
игнорирования ненужных значений. В Visual Prolog анонимные переменные обозначаются символом подчеркивания (_).
Анонимная переменная может быть использована на месте любой другой переменной и ей никогда не
присваивается значение.
Анонимные переменные также можно использовать в фактах.
Следующие факты Пролога:
ows (_,shoes) .
eats(_).
могли быть использованы для выражения утверждений на естественном языке:
У каждого есть туфли. (Everyone owns shoes)
Каждый ест. (Everyone eats)
Анонимные переменные сопоставляются с любыми данными.
6 Сопоставление (matching).
В Visual Prolog имеется несколько примеров сопоставления одной вещи с другой. Ясно, что идентичные
структуры сопоставимы (сравнимы) друг с другом: parent (joe, tammy) сопоставимо с parent (joe, tammy).
Однако сопоставление (сравнение) обычно использует одну или несколько свободных переменных. Например,
если X свободна, то parent (joe, X) сопоставимо с parent (joe, tammy) и X принимает значение (связывается с) tammy.
Если же X уже связана, то она действует так же, как обычная константа. Таким образом, если X связана со
значением tammy, то parent (joe, X) сопоставимо с parent (joe, tammy), но parent (joe, X) не сопоставимо с parent (joe,
millie) .
Две свободные переменные могут сопоставляться друг с другом. Например, parent (joe, X) сопоставляется с
parent (joe, Y), связывая при этом переменные X и Y между собой. С момента связывания X и Y трактуются как одна
переменная, и в любое изменение значения одной из них приводит к немедленному соответствующему изменению
другой. В случае подобного "связывания" между собой нескольким свободных переменных все они называются
совмещенными свободными переменными.
В Прологе связывание переменных (со значениями) производится двумя способами: на входе и выходе.
Направление, в котором передаются значения, указываете в шаблоне потока параметров (flow pattern). В дальнейшем
(для краткости) будем опускать слово "шаблон" и говорить просто "поток параметров". Когда переменная передается в
предложение, она считается входным аргументом и обозначается символом (i). Когда же переменная возвращается из
предложения, она является выходньм аргументом и обозначается символом (о).
Пример программы.
Представленный листинг представляет собой законченную программу на Visual Prolog (ch03e04.pro), служащую
небольшим телефонным справочником. Так как используются только стандартные домены, раздел domains в этой
программе не нужен.
predicates
phone_number(symbol, symbol)
сlauses
phone_number ("Albert", "EZY-3665").
143
phone_number ("Betty", "555-5233").
phone_number ("Carol", "909-1010").
phone_number ("Dorothy", "438-8400") .
goal
Загрузите и запустите программу ch03e04.pro, а затем, по очереди, задайте ей следующие цели:
• phone_number("Carol", Number).
• phone_number(Who, "438-8400").
• phone_number("Albert", Number).
• phone_number(Who, Number).
Теперь измените предложения. Предположим, что Kim и Dorothy имеют один номер телефона. Добавим этот
факт в раздел clauses и введем цель:
phone_number(Who, "438-8400").
На этот запрос вы должны получить два решения:
Who=Dorothy
Who=Kim
2 Solutions
7. Использование логических связок в Прологе
Выводы, получаемые Прологом, всегда являются частью всех возможных логически правильных ответов на
заданный запрос.
Операция логическое «и» (конъюнкция) в Прологе обозначается запятой, а операция логическое «или»
(дизъюнкция) - точкой с запятой.
Например,
grandmather(X,Z):-mather(X,Y), mather(Y,Z).
«Х является бабушкой для Z, если Х является мамой для Y и Yявляется мамой для Z»
sister(Y,Z):-mather(X,Y), mather(X,Z).
«Y сестра Z, если Х мать для Y и Yмать для Z»
potomok(Y,X):-mather(X,Y); grandmather(X,Y).
«Y потомок Х, если Х мать Y или Х бабушка Y»
52.
Представление знаний в виде правил-продукций. Механизм вывода в продукционной системе.
Взаимодействие правил в процессе рассуждений.
1. Представление знаний в виде правил-продукций
Если проследить за речью человека (не ее содержанием, а структурным построением фраз), то легко заметить,
что значительная часть наших мыслей оформляется в виде правил типа «ЕСЛИ (далее следует ряд условий), ТО (далее
следует что надо сделать)».
Примеров – множество: «Если ты будешь хорошо учиться, то папа купит тебе велосипед», «Закаляйся, если
хочешь быть здоров», «(Если) Не продается вдохновенье, но (то) можно рукопись продать» и т.п.
Несмотря на то, что такая форма представления знаний чрезвычайно популярна для человека, она является
достаточно сложной для реализации в виде жестких алгоритмических схем. Проблемы появляются в связи с тем, что
знания многообразны как по уровням, так и по спектру, допускают неоднозначное толкование, чаще всего имеют
ассоциативный характер использования. Трудно четко разложить их на причины и следствия и описывать их, например,
на языке исчисления высказываний и предикатов. Добавим еще, что знания постоянно меняются, пополняются,
модифицируются и приспосабливаются к условиям среды.
144
Конструкция "Если <условия>, то <действия>" напоминает импликацию АВ (где А, В – формулы исчисления
высказываний) или
Q1x Q2y(А(x,y)  B (z), где Q1, Q2 - кванторы  или , а А(x,y), B (z) – логические функции
(исчисление предикатов).
Поиск удобной модели для представления знаний типа "Если <условия>, то <действия>" привел к идее введения
продукции в качестве эквивалента представления знаний и механизма работы СИИ.
Продукционная модель знаний
Термин «продукция» был введен американским логиком Е. Постом в 40-х годах в работах по обоснованию и
формализации алгоритмических систем. Продукцией называется правило вида b,
Где ,  - слова над некоторым алфавитом А. Совокупность правил типа  получила название системы
продукций.
Покажем этот механизм представления, интерпретируя левую и правую части правил продукций как логические
функции. Наиболее популярная форма такая:
Р(x, y)  A  D.
(1.1)
Здесь Р(x, y) – логическое выражение , А – заключение, D – действие, т.е. продукция - это пара <антецедент,
консеквент> , а «» – знак секвенции. Для простоты изложения кванторы  опущены. Выход за рамки формальной
системы осуществляется путем добавления действий. Если при замене x и y конкретными значениями aX, bY Р(а, b)
принимает значение И, то выдается заключение А и выполняется действие D. Формы заключения могут быть
различными:
Р(x, y)  A (здесь А - статическое высказывание, истинное всегда);
Р(x, y)  D (здесь D - одно или несколько действий, не требующих интерпретации);
Р(x, y)  A(x, y)  D(x, y) (здесь А(x, y) - логическая функция, истинная при Р(x, y)= N, D(x, y) - действие,
которое доопределяется путем замены x, y на а, b соответственно).
В отличие от импликации случай И→Л здесь не рассматривается. Это значит, что при истинности левой части
реализуется всё, что рекомендуется в правой. т.е. продукция истинна всегда.
В простейшем случае правая и левая части продукции могут быть простыми высказываниями. Главное
отличие продукции от логических формул – они допускают более широкий спектр интерпретации.
В наиболее общем виде под продукцией понимается выражение
<(i), Q; N; P→A; D >,
где i – уникальное имя продукции, с помощью которого продукция выделяется из всего множества. В качестве имени
может выступать любая цепочка символов или цифр, но чаще – лексема, отражающая суть (смысл) данной продукции;
Q – характеризует сферу применения данной продукции. Такие сферы легко выделяются в системах знаний
человека по принципу "полки". На одной "полочке" у нас хранятся знания, например, о том, как добраться до работы, на
другой – как варить кашу и т.п. Разделение знаний на отдельные сферы экономит время на поиск нужных
в конкретных условиях знаний.
Р  A – называется ядром продукции. Это основной элемент. Допускается форма: если Р, то А, иначе В. При
этом секвенция () истолковывается в обычном, логическом смысле как знак логического следования А из истинного Р
(в случае, если Р не является истинным, как мы уже говорили, то об А ничего сказать нельзя).
N – есть условие применимости ядра продукции. Обычно, если N принимает значение И, то ядро продукции
активизируется. В противном случае продукция не может быть применена.
145
Элемент D описывает постусловия продукции. Они активизируются лишь в случае, если ядро продукции
реализовалось. Постусловия описывают действия и процедуры, которые необходимо выполнить после реализации ядра.
Здесь тоже могут рассматриваться самые различные варианты. Например, ядра могут быть
детерминированными (точно определенными) или нет. В последнем случае А может и не выполняться при истинности
D. Ядро продукции интерпретируется тогда так: если Р, то, возможно, А. Сама возможность определяется
некоторыми оценками реализации ядра. Для формирования оценок используется вероятностный или какие-либо другие
подходы. В простейших случаях здесь продукции могут быть такими:
если Р, то с вероятностью p реализовать А, или:
если Р, то с большой долей уверенности А.
Мы столкнулись здесь с нечёткостью определения оценок, что и стало предметом изучения нечёткой логики.
Детерминированные продукции могут быть однозначными и альтернативными( связка «или»). Здесь тоже
нужен свой механизм выбора альтернативы из нескольких возможных. Это может быть, например, механизм
присваивания весов, вероятностных или экспертных оценок. Например: если Р, то чаще надо делать А1, реже А2. Для
решения задач прогнозирования могут вводиться оценки типа «с вероятностью p можно ожидать А1».
2. Механизм вывода в продукционной системе знаний
Для того, чтобы «запустить» машину вывода при наличии системы продукционных правил, очевидно
необходимы следующие компоненты:
*
*
*
задание значений переменных, используемых в продукциях;
сами правила-продукции,
механизм интерпретации правил.
Значения переменных обычно задаются в так называемой рабочей базе данных – РБД (рабочая память) в виде набора
конкретных фактов, формат которых согласуется с форматом правил. Совокупность правил-продукций является
сердцем системы и называется базой знаний или правил (БЗ). Механизм интерпретации правил как раз и является
механизмом вывода (МВ).
Рассмотрим механизм вывода в продукционной системе.
Как следует из сказанного, под продукционной системой (ПС) понимается совокупность:
ПС = < РБД, БЗ, МВ >
(1.2)
В каждом цикле интерпретации выполняется следующие процессы:
1)
2)
определяется множество означиваний, т.е. выделяется набор продукций БЗ и фактов из РБД, согласующихся
между собой;
выполняются сами означивания (сопоставления), т.е. реализация указаний из правой части продукций (здесь
тоже могут быть самые различные варианты, но о них позже).
Легко показать, что продукционные системы являются некоторым неформальным обобщении нормальных
алгоритмов А.А. Маркова. Очевидно, что в продукционной модели легко просматриваются аналогии:
РБД – с её помощью моделируются текущие состояния предметной области;
БЗ – модель самой предметной области;
МВ – модель механизма принятия решений (вывода) – прямой аналог человеческим рассуждениям.
Таким образом, обобщенный алгоритм работы состоит из:
1.
2.
3.
4.
Задания каким-либо образом модели текущего состояния предметной области (прямой диалог, моделирование,
генерация, интерполяция и т.д.);
Интерпретации текущего состояния предметной области (т.е. РБД) на БЗ и выработки вариантов решения;
выбора по какому-либо способу варианта решения и выдачи его на выход системы для пользователя;
изменения состояния модели предметной области (РБД), путем выполнения действий и процедур,
рекомендованных в послесловиях.
146
Самое замечательное в этом механизме то, что управление процессом вывода осуществляется путем изменения
состояния РБД и не затрагивает БЗ.
3.
Взаимодействие правил в процессе рассуждений
На правила можно смотреть, как на символьные структуры, которые выражают или дедуктивные, или
ассоциативные способы продвижения в процессе рассуждений ( вывода). При этом под дедуктивным способом
подразумевается то, что некоторое правило может быть использовано для проверки условий в другом правиле. Под
ассоциативным подразумевается то, что некоторое правило может инициировать запуск или выполнение других правил.
Более наглядно правила можно представить с помощью диаграммы (рис. 1.5).
ЛЧ Р
ПЧ А
Если ….(условия)
то….(заключение, или гипотеза)
D
и выполняются
действия
Рис. 1.5. Наглядное представление продукции
Продемонстрируем графически действие одного правила. Каждое правило представляет собой как бы
островок знаний, который начинает “ работать”, как только это правило становиться пригодным. Предположим, что все
условия (все строки в ЛЧ) выполнены (напомним, что формально они образуют конъюнкцию). Правило, следовательно,
может быть применено. На рис. 1.5 закрашенные элементы означают "истинно". Так как все условия истинны, то
верхняя часть ПЧ А (еще ее называют гипотеза) также истинна. Значение гипотезы, таким образом, зависит от состояния
(наличия) всех условий в ЛЧ. Значение это – булевское ("И" или "Л"). Так как гипотеза может иметь то или иное
значение, она может присутствовать в левой части какого-либо другого правила. Рассмотрим пример на рис 1.6.
m
X
n
Y
Рис. 1.6. Определение истинности недостающего условия
Для определения истинности гипотезы n правила Y в левой части Y не хватает одного условия. Положим, что
значение этого условия зависит от состояния m. Чтобы проверить, является ли m истинной, система постарается найти
правило (Х), где m было бы гипотезой и его можно было бы рассматривать как подзадачу для вычисления n.
147
Так иллюстрируется дедуктивное рассуждение, которое может проводиться на многих уровнях вложенности и
включать много правил (см. рис. 1.7).
Рис. 1.7. Пример взаимодействия правил при дедуктивном рассуждении
Для разрешения конфликтов которые, могут возникать между правилами, в систему включаются специальные
механизмы их разрешения.
Мы рассмотрели простой случай, когда ПЧ имеет одну только гипотезу. Обычно же правила имеют более
сложные ПЧ, включающие, наряду с гипотезами, и действия. На диаграмме (рис. 1.5) действия образуют нижнюю ПЧ.
Когда правило оказывается истинным,
изменение значений
создание/уничтожение
некоторых данных
некоторых объектов и связей
чтение /запись в БД
показ графиков
влияние на машину
вывода
восстановление значений
выполнение внешних
программ
действия
загрузка новых данных
Рис. 1.8. Примеры действий правой части продукции
148
применяются и действия ПЧ. Они называются действиями потому, что они вызывают некоторое изменение в
общей системе. Следующая диаграмма (рис. 1.8) иллюстрирует типы действий, которые могут происходить, когда
срабатывает правило.
Когда некоторое правило изменяет значение данных входящих в другие правила, оно может запустить
выполнение этих правил (рис. 1.9). Активное правило, изображенное черным цветом, активизирует
три других правила. Это – продвижение по вызову (evocative) или прямое (индуктивное) рассуждение. Верхнее левое
правило вычислялось, но не сработало из-за неудовлетворения условия (отмечено крестами). Таким образом, его
гипотеза оказалась ложной.
Правила могут также вызывать пересмотр других правил. На рис. 1.10 показано правило, действие которого
изменяет состояние некоторой переменной, чье текущее значение делает ложным условие в другом правиле.
Если машина вывода, управляющая этим выводом, позволит это сделать в данный момент, то правило будет
пересмотрено и потом, возможно, будет запущено в действие. В результате это могло бы перенести фокус внимания на
другое правило, как показано на следующем рисунке 1.11.
149
Всякое правило может действовать и само на себя. Например, оно может переустановить (reset) само себя, как
если бы ничего и не происходило (рис. 1.12).
Этот режим работы, называемой пересмотром (revision), является немонотонным. Система способна отменять
логические зависимости, установленные ранее, в результате изменения самой проблемы.
Дедуктивные (обратные) и индуктивные (прямые, вызывающие) механизмы вывода являются полностью
взаимозависимыми. То, каким образом работает данное правило в данное время, зависит как от событий ( если что-то
изменилось из-за некоторой внешней информации, либо из-за какого-то действия), так и от текущего фокуса внимания.
Следующий рисунок 1.13 показывает интеграцию различных механизмов.
150
Бывает, что приходиться выполнять некоторое правило заново в порядке решения изменяющейся подзадачи
или потому, что оно вдруг стало пригодным. Этот "оппортунистический" характер общей архитектуры является важным
фактором при построении систем, которые, благодаря этому, могут адаптироваться к изменяющимся обстоятельствам.
Но еще важнее, что так можно проводить очень избирательное, зависящее от цели и от данных, исследование базы
знаний, избегая исчерпывающих, дорогих режимов работы.
В этом воображаемом примере (рис. 1.13) мы рассматриваем процесс рассуждения через интервал времени  t. Фокус
внимания был обращен на верхнее левое правило, затем переведен на правило в кружочке, которое инициировало
дедуктивное рассуждение. В ходе этого дедуктивного рассуждения внимание системы привлекли новые правила, а
завершающее выполнение выпало на долю нижнего справа правила. (Правила обозначенные белым цветом, в этом
выводе оказались невостребованными). Мы лишь поверхностно исследовали на этих диаграммах механизм
рассуждений, который реализуется в продукционных системах. Мы рассчитывали просто ознакомить читателя с общим
смыслом рассуждения.
53.
Представление знаний в виде фреймов. Логический вывод на фреймах.
1. Представление знаний в виде фреймов
Из предложенных ранее моделей представления знаний в виде системы продукций, семантических сетей, а еще
ранее – в части 1 [1] – в виде формальных моделей мы видели, каким образом характер предметной области, типы задач
для решения в СИИ влияют на выбор конкретной модели организации знаний и вывода результатов. Так, в
продукционных моделях знания фокусируются на множестве характерных, или ключевых состояний, требующих
принятия решения. Соответственно, модель предметной области или БЗ, в конце концов, здесь представляется в виде
множества правил типа:
прототип состояния  решение + действия по изменению состояния ПО, соответствующие данному
решению.
Каждое правило представляет собой элементарный кирпичик знания о целом. Очевидно, что для достаточно
сложных предметных областей такие БЗ могут быть настолько сложными и запутанными, что их использование
становится проблематичным.
В семантических сетях – другой недостаток. Здесь фокус внимания сосредоточен на понятии предметной
области, отождествляемой с реальными объектами (сущностями, процессами). Однако представление в СС знаний
недекларативного характера, например, процедурного, затруднено, так же как и информации о решениях. Поэтому
естественно, что следующим началом в развитии СИИ стал поиск такого представления, который был бы, с одной
стороны, достаточно крупным фрагментом знания о мире, а с другой – сохранял бы наиболее важные достоинства
других представлений, такие как возможность использования процедурных знаний (как в процедурных моделях),
наглядность и иерархичность (как в СС), возможность моделирования правдоподобного вывода (как в формальных
системах). Поиски привели к модели представления знаний в виде фреймов.
Фрейм, его структура и свойства
151
Впервые понятие фрейма (frame – рамка, каркас, структура) было введено М. Минским в 1975 году. В основе
его лежат представления гештальтпсихологии, занимающейся изучением восприятия человеком внешнего мира в форме
целостных фрагментов. Наиболее часто центральным понятием такого фрагмента является объект внешнего мира с его
наиболее характерными свойствами и т.п. По Минскому, фрейм – это структура данных, содержащая минимально
необходимую информацию для представления класса объектов (явлений или процессов), которая однозначно
определяет эти объекты.
По определению Поспелова Д.А. [7], фрейм – это термин для обозначения описания какого-либо объекта или
явления, обладающего тем свойством, что удаление из этого описания любой его части приводит к потере
определяющих суть данного объекта или явления свойств. Еще одно определение: фрейм – это структура данных для
представления стереотипных ситуаций. Различают фреймы – прототипы ( протофреймы) и фрейм-примеры ( или
фрейм-экземпляры).
Фрейм-прототип содержит знания, общие для всех частных случаев, т.е. примеров, а фрейм-пример содержит
знания, отличающие частный случай от общего.
В наиболее простом случае фрейм представляется в следующем виде:
F = (<I>, <r1,f1>, <r2,f2>,…,<rn,fn>),
(3.1)
где I – имя фрейма,
ri –имя слота, fi - значение слота ( i=1, … n).
(Простейшее описание фрейма мы уже давали в предыдущей книге этой серии ([1], стр. 38), советуем к ней
обратиться).
В качестве имен фреймов могут фигурировать имена объектов, событий процессов и т.п. Слотами выступают
характерные свойства или атрибуты описываемых объектов с именем I.
В качестве значений слотов fi могут выступать:
- имена других фреймов,
- имена процедур,
- конкретные значения слотов.
Таким образом, существует возможность ссылки из одного фрейма в один или несколько других, что позволяет
вводить структурированные связи между фреймами. При этом возникает однородная СС со сложными вершинами,
допускающими дальнейшую развертку. Семантическую сеть можно рассматривать как частный случай фрейма, так
как очевидно, что любая СС может быть переделана во фреймовое описание и наоборот.
В случае рекурсивного вложения фреймов друг в друга, порождается иерархическая система фреймов.
Рассмотрим несколько примеров.
Пример 1.
Опишем в виде фрейма понятие "Транзисторы" (рис. 3.1).
152
Оче
видно, на рисунке показаны не все вложения, но принцип должен быть ясен. В общем случае слотами могут быть
незаполненные подструктуры фрейма, заполнение которых приводит к тому, что данному фрейму ставится в
соответствие некоторая конкретная ситуация, объект или явление.
Фрейм с не полностью заполненными слотами соответствует протофрейму. Заполнение слотов формирует,
соответственно, фрейм-пример.
153
Слоты могут быть терминальными или нетерминальными. Нетерминальные фреймы служат именами других
фреймов, составляющих содержание данного слота. Терминальные фреймы задают список соответствующих значений.
Так, слоты КУДА, ЦЕЛЬ, СРОК и др. являются терминальными, а слот КТО – нетерминальный. Кстати, фреймы типа
ДЕЛОВАЯ ПОЕЗДКА называют еще ролевыми, т.к. в качестве слотов служат указатели ролей типа: кто, что, куда, когда,
где, почему и т.п.
При этом выделяются слоты обязательные и необязательные для заполнения. Например, слот С КЕМ может
быть необязательным. Значениями слотов могут быть также присоединённые процедуры (ПП). Необходимость в них
возникает, когда активизация фрейма возможна лишь при выполнении некоторого предусловия. Проверка предусловия
осуществляется при наличии ссылки на него во фрейм. В качестве таких ПП могут фигурировать процедуры заполнения
слотов, активизации других фреймов, выполнения некоторых дополнительных действий, проверка условий, введение
новых слотов или прототипов, и т.д. Таким образом, слоты могут заполняться значениями, символами, множествами, а
также управляющей информацией, благодаря которой фреймы и организуются в структуру.
Если сравнить фрейм с СС, то очевидно, что протофрейм соответствует интенсиональному описанию СС, а фреймпример – экстенсиональнному.
Отсюда следует основной механизм соотнесения фрейм-прототипа и фрейм-примеров. Извлекается фрейм-пример и
сравнивается с множеством фрейм-прототипов. Если один из них "накладывается" на фрейм-прототип, то
соответствующий образец активизируется. При этом условие перехода к другому фрейму может записываться как в
декларативной, так и в процедурной формах. Можно выделить два типа процедур:
проверяющие некоторые условия нетерминалы ( т.е. значения слотов),
разрешающие выполнять некоторые действия (например, вычисления).
Первый тип присоединённых процедур называют процедурными слугами, вторые – демонами. Последние
активизируются при каждой попытке добавления или удаления данных из слота (по умолчанию). Очевидно, что
формирование множества присоединенных процедур (ПП) связано с поддержкой основных типов процессов обработки
фреймовых структур. Используются следующие основные типы процессов:
1) создание нового экземпляра фрейма;
2) активизация фреймов;
3) организация вывода путем последовательного поиска и активизации сети фреймов до нахождения
наиболее соответствующего и построения на его основе экземпляра фрейма.
154
ПП могут также реализовывать эвристики, направленные на поиск необходимой для заполнения слотов
информации.
2. Логический вывод на фреймах
Для организации процесса вывода используются механизмы наследования информации и присоединённых
процедур. Наиболее системная структура фрейма , удобная для описания приведена в таблице (рис. 3.3).
Здесь:
1) имя фрейма – уникальной идентификатор. Для каждого фрейма определяется слот ISA-родитель данного
фрейма, и слот дочерних фреймов, задаваемый списком имен (указателей). В список слотов включается ряд слотов,
необходимых для организации интерфейса с
пользователем, для организации внутрисистемных процессов и т.п. В их число входит, например, слоты для
определения имени пользователя, даты определения, даты изменения текста, комментария и т.п..
2) имя слота также служит его идентификатором, т.е. уникальным именем во фрейме, к которому он
принадлежит. Могут вводится специальные идентификаторы, отождествляемые с отношениями ISA, PART OF,
причина-следствие и др. Кстати, в качестве слота может выступать слот "Условие", а его значением может быть
продукционное правило. Таким образом реализуется возможность использования продукций для организации вывода.
Вводится также слоты типа: «Дата модификации фрейма», «Комментарий», «Отношение» и др. Такие слоты называются
системными и используются для редактирования БЗ и управления выводом.
3) указатели наследования необходимы только для фреймовых систем иерархического типа. Типичными
указателями могут служить: "уникальный" (unique: U), "игнорировать" (override: O), "такой же" (same: S), "установить"
(R) и т.п. Метка U показывает, что каждый фрейм может иметь слоты с различными значениями; S – все слоты должны
иметь одинаковое значение; R – значение слотов фрейма нижнего уровня должны находиться в пределах, указанных
значениями слотов фреймов верхнего уровня; О – при отсутствии указания значение слотов фрейма верхнего уровня
становится значением слота фрейма нижнего уровня.
4) указатель атрибутов слота показывает тип данных – число, указатель другого фрейма, т.е. является именем;
(FRAME (указатель), INTEGER, REAL, BOOL, LISP (присоединённая процедура), TEXT, LIST (список), TABLE
(таблица), EXPRESSION (выражение) и др.).
155
5) значение слота, очевидно, должно совпадать с указанным типом данных этого слота, а также должно
выполняться условие наследования.
6) демон – присоединённая процедура. Примеры таких ПП: IF-NEEDEP, IF-ADDED, IF-REMOVED и т.д. Эти
процедуры запускаются автоматически при выполнении некоторого условия.
ПП – слуга. Это обычно программы процедурного типа, называемые служебными ( в языке LISP ), методами (в
языке Smalltalk). Процедура запускается по сообщению из другого фрейма.
Как таковой формальный механизм вывода отсутствует и реализуется с помощью механизма наследования и
присоединённых процедур. Это позволяет объединять возможности сетевого и иерархического представления знаний.
Из данного примера видно, насколько разнообразными могут быть конкретные реализации СИИ фреймового
типа, а также их достоинства.
Приведём пример записи иерархии фреймов по отношению ISA с указанием фрейма более высокого уровня, из
которого наследуются свойства.
Значение слота ЛЕТАЕТ по умолчанию означает, что если нет специальной оговорки, все подмножества ПТИЦ
и отдельные ПТИЦЫ – летают.
Остальные свойства (ИМЕЕТ КРЫЛЬЯ), (ИМЕЕТ ПЕРЬЯ), наследуются всеми элементами, связанными
отношением ISA.
Функция значений «по умолчанию» очень популярна в представлении фреймов, поскольку позволяет
однозначно определять значения слотов на иерархии.
Например, если задать вопрос к базе фреймов: способен ли к охоте Джо? Система обращается к фрейму
СОКОЛ и выясняет, что сокол умеет охотиться. То есть это свойство наследуется из фрейма более высокого уровня.
Если мы хотим получить ответ на вопрос: летает ли ПИККОЛО, то системе приходится разрешать коллизию,
возникающую при анализе фреймов ПТИЦА (ПИНГВИН есть ПТИЦА) и ПИНГВИН. Свойство ЛЕТАТЬ не определено
во фрейме ПИККОЛО, поэтому система обращается к фрейму ПИНГВИН по указателю ISA. И здесь есть прямое
указание, что пингвин не летает. Это свойство наследуется во фрейме ПИККОЛО. И хотя указатель нас отправляет к
фрейму ПТИЦА, где по умолчанию стоит значение ДА, предпочтение отдаётся значению в слоте ПИНГВИН, откуда
была последняя ссылка.
Очень часто языки фреймового типа называют объектно-ориентированными. Таким языком является Smalltalk.
Другими примерами языков программирования фреймового типа являются языки FMS, FRL, KRL, являющиеся
надстройками над LISP-системами. Очень часто такие языки также называют объектно-ориентированными, но, во
избежание путаницы с языком Smalltalk, обычно сохраняют название «язык фреймового типа».
Своё наиболее яркое выражение представление знаний в виде фреймов получило в системах объектноориентированного программирования, которое мы рассмотрим более подробно в разделе 3.4.
54.
Представление знаний в виде семантической сети. Логический вывод на СС.
1. Представление знаний в виде семантической сети
Само название «семантическая сеть» (СС) акцентирует внимание на смысле (семантика – смысловая сторона
языка, "семантический" – связанный со смыслом), т.е. значении тех слов, предложений, ситуаций, состояний, которые
входят в модель предметной области и которые необходимо описать адекватно нашему (человеческому) пониманию
таким образом, чтобы с этим смыслом можно было работать, т.е. моделировать процессы, рассуждения, выводы,
156
сравнения, сопоставления и т.п. Очевидно, это непросто, хотя и возможно многими способами. Поэтому, не вдаваясь в
подробности языковые, психологические и другие, под семантикой будем понимать отношения между некоторыми
сущностями, в качестве которых могут выступать отдельные символы, слова, предложения, пакеты, пентограммы,
образы, т.е. всё, что необходимо для описания объектов ( процессов, состояний и т.п. ) предметной области.
Семантическая сеть (СС) является удобным способом графического описания объектов предметной области. При этом
под объектом может пониматься процесс, состояние, какая-либо сущность и т.п. Более строго определим СС как
направленный граф с помеченными вершинами и дугами. При этом вершины отождествляются с соответствующими
объектами предметной области, а дуги – с отношениями между ними. Большое разнообразие СС формируется , исходя
из следующих соображений:
является ли вершина СС простой или сложной?
сколько и какие отношения используются в СС?
какие процессы необходимо моделировать на СС?
Будем говорить, что вершина СС является простой (ординарной), если она не имеет внутренней структуры.
Другими словами, простые вершины отождествляются с терминальными ( конечными ) объектами моделируемой среды.
В качестве таких вершин могут, очевидно, фигурировать числа, лексемы, пентограммы и т.п.
Сложные вершины допускают раскрытие вплоть до семантической сети, в которой участвуют только простые
вершины. Таким образом, СС со сложными вершинами может разворачиваться, как матрёшка.
Отношения также многообразны по типу и свойствам. Основные типы отношений, используемых в СИИ:
- лингвистические (падежные или ролевые: кто, что, где, когда, зачем, почему, условие, место, время и т.п.),
- атрибутивные: форма, размер, цвет, вкус и т.п.
- отношение действия, когда каждый глагол рассматривается как отношение между объектом (субъектом)
действия и объектом, выражающим некоторую способность (летать, ходить, стоять и т.п. ), реализующуюся во
времени как процесс.
- логические: , , , ,
- квантифицированные: ,.
- теоретико-множественные (множество, подмножество, объединение, дополнение, пересечение).
Наиболее многообразна группа лингвистических отношений, в которой могут быть выделены подгруппы
временных, пространственных ( над, под, внутри, рядом и т.п. ), причинно-следственных (каузальных) и др. типов
отношений. Такая классификация важна, поскольку разные типы отношений обладают различными свойствами,
которые необходимо учитывать при построении моделей вывода в СС. Речь идёт о следующих свойствах отношений:
рефлексивность (антирефлексивность), симметричность (антисимметричность), транзитивность (антитранзитивность).
Соответственно, каждое отношение характеризуется определённым набором этих свойств.
1.
2.
В зависимости от того, какие типы отношений используются можно выделить несколько видов СС.
Однородные СС. В них используется один тип отношений (неважно какой, но один). В этом смысле любые
ориентированные графы являются примерами однородных СС.
Иерархические СС. Здесь используются отношения типов "целое–часть"(«класс–подкласс–элемент класса» –
отношения типа ISA), либо " часть– целое " (oтношения типа АКО: "элемент класса – подкласс – класс").
Каждое из этих отношений образует свою иерархию. Яркими примерами иерархических СС являются
организационные структуры, выстраиваемые по отношению "целое-часть". (Например, схема центральной
избирательной комиссии: областная, городская, окружная, районная, участковая).
157
1.
2.
Сценарные СС. Используются отношения строгого или нестрогого порядка. Сюда же могут быть отнесены СС
с отношениями времени, причина-следствие.
Функциональные СС. В них используются функциональные отношения типа "вход-выход" (рис. 2.1).
Пример 1. Представим в виде СС предметную область известной нам задачи об обезьяне (рис. 2.2).
По сравнении с известным нам условием на рисунке введен ещё один объект «комната», который у нас неявно
всегда фигурировал, но здесь он нужен явно, чтобы определить местоположение объектов О, Я, В. Указаны все
возможные отношения между объектами: над, под, в, рядом, у. Возможные координаты точек комнаты обозначены,
например, через вершины 1,2,…..,n, связанные с вершиной отношением ISA (быть элементом класса). Рассмотрены
свойства объектов, путем введения отношения КООРДИНАТЫ, определены предназначения объектов ОБЕЗЬЯНА,
ЯЩИК, БАНАНЫ через отношение «предназначен для», а также способность ДВИГАТЬСЯ, ПЕРЕНОСИТЬ через
отношение "уметь".
Очевидно, что эту СС можно усложнить, введя, например, дополнительные свойства ВЫСОТА (обезьяны,
ящика, комнаты), ВЕС (обезьяны, ящика, бананы) и т.д. Можно усложнить сеть, рассматривая вершины ОБЕЗЬЯНА,
ЯЩИК как классы, вводя их через отношения ISA (связь содержать в себе – is a …) или AKO (cвязь быть элементом
класса – a king of…).
Возникает, например, вопрос: как изобразить на СС фразы типа: все овчарки – собаки, т.е. как ввести квантор
всеобщности. Очевидно, это можно сделать через отношение АКО
158
Если рассмотреть собаку с именем «Джек», то сеть расширяется следующим образом:
Используя свойство транзитивности отношения АКО можно на этой сети вывести факт: Джек – собака. Такой
способ вывода называется выводом по наследованию. Если мы хотим зафиксировать на этой сети какое-либо состояние
предметной области, например Sн, то очевидно, что ей будет соответствовать подграф СС, который определяется
операциями простого наложения и сопоставления вершин и дуг.
Анализируя примеры, мы видим, насколько субъективными могут быть такие представления. Сколько авторов,
столько и вариантов СС.
Такая неоднозначность может рассматриваться и как достоинство, и как недостаток. Достоинство – в большой свободе
выражения и открытости подобного типа СС. А недостаток – в сложности их формального анализа и обработки.
Поэтому учёные с самого начала пытались ограничить свободу авторов и построить более строгие представления.
Рассмотрим некоторые из них.
Предикатные СС
Рассмотрим тип СС, формируемых на основе анализа текста естественного языка (ЕА). Элементарное предложение
в предикатных СС состоит из следующих компонентов:
- пропозициональная вершина, обозначающая конкретное предложение (высказывание, суждение);
- множество концептуальных вершин, число которых должно совпадать с количеством мест того предиката, который
описывается в предложении. Дуги, ведущие к концептуальным вершинам, помечаются метками, означающими порядок
записи в предикате:
Рис. 2. 3. "Ячейка" предикатной сети
Р1–обозначение предиката; в среднем кружочке – имя предикатного символа (стрелка Pred); в остальных
кружках – термы, первый – А, второй – В.
Пример 2. Москва – есть город (на языке исчисления предикатов – Город (Москва)):
159
Для объединения семантических предложений вводятся специальные вершины "И", "ИЛИ", "НЕ" (, ,  ).
Предикатная форма:
Р1( (А, В)); Р2( (D, E, F)); Р3(  G).
Лингвистический процессор приводит текст на естественном языке (ЕЯ) к виду СС, которая затем
обрабатывается системами представления и обработки знаний для получения ответов на запросы опять-таки на ЕЯ.
Перевод с ЕЯ на язык СС и обратно также осуществляется лингвистическим процессором (рис. 2.7).
Атрибутивные СС
Этот популярный тип семантических сетей определяется через систему унарных отношений. Как известно,
унарные отношения определяются одноместным предикатом или свойством, относящемуся к описываемому понятию.
Например, мы говорим: яблоко красное и вкусное. Это отношение соответствует записям: ЯБЛОКО (ЦВЕТ – красный),
ЯБЛОКО (ВКУС – сладкое). Такого рода отношения называют еще атрибутами, а соответствующие СС –
атрибутивными. Здесь предполагается известным имя объекта (класса, подкласса, единичного экземпляра), перечень его
атрибутов и область задания каждого атрибута. Например, атрибут яблока ЦВЕТ можно задать перечнем (красный,
желтый, белый, зеленый…). Совокупность атрибутов вместе с их множествами задания определяют объект как нечто
целое в виде отношения
R = {(A1= a11, a12, …a1n), (A2 = a21, a22,…a2m)…}.
При этом очевидно, что атрибуты составляют постоянную (статическую) часть определения объекта, а область
задания – переменную (динамическую) часть. Атрибутивное задание в конкретных реализациях чаще всего
осуществляется путем позиционирования атрибутов, т.е. фиксации места каждого атрибута в общем описании:
R = (ЯБЛОКО ЦВЕТ СОРТ ВКУС ВЕС)
поз. 0
поз. 1
поз. 2
поз. 3 поз. 4
А2
А3 …..).
или иначе:
R = (Имя атр.
А1
160
поз. 0
поз. 1 поз. 2 поз. 3 …
Такое представление задает как бы свёртку n унарных отношений в одном. Это чрезвычайно экономит память
для сложных описаний и существенно повышает быстродействие. Имя атрибута при этом понимается по умолчанию, на
местах значений атрибутов указываются их конкретные значения. Другими словами, мы определяем описание каждого
объекта или вершины СС как отношение с перечнем атрибутов и областями их определения. Если обозначить область
определения каждого атрибута как domen, то можно написать:
R =
{A1 DOM(A1), A2 DOM(A2)… An DOM(An)}.
Имя объек.
На основе такого представления можно построить множество конкретных описаний. Будем называть каждое
такое описание фактом (или примером). В нашем примере мы можем определить факты:
F1: ЯБЛОКО1, ЦВЕТ=ЗЕЛЕНЫЙ, ВКУС=КИСЛЫЙ,
F2: ЯБЛОКО2, ЦВЕТ=КРАСНЫЙ, ВКУС=СЛАДКИЙ .
Максимальное число фактов при 3-х значениях атрибута ЦВЕТ и 2-х – атрибута ВКУС, очевидно равно 6.
R (имя объекта) задает статическую, или интенсиональную, составляющую, конкретные факты. F1, F2 … –
динамическую, или экстенсиональную, составляющую описания. (Об интенсиональных и экстенсиональных знаниях см.
подробно п. 4.5 этой книги).
Теперь мы можем дать формальное определение атрибутивной семантической сети. Назовем схемой или
интенсионалом (INT) некоторого отношения Ri набор пар вида
INT (Ri) = Aj DOM(Aj),
где Ri – имя некоторого отношения, Aj – атрибут (j = 1,2,..n),
домен DOM(Aj) = {aij} – область значений Aj.
Экстенсионалом (EXT) отношения Ri называется выражение
EXT(Ri) = {F1, F2, …Fk…Fn)},
где Fk = (Ri Aij, aijk), т.е. Fk – есть факт, описывающий j-й атрибут отношения Ri атрибутивной парой, аijk –
значения j-го атрибута i-го отношения. Тогда атрибутивная СС описывается как множество пар вида INT(Ri), EXT(Ri),
(i = 1,2,3…n) по всему множеству отношений Ri:
СС(Ri) = INT(Ri), EXT(Ri), i = 1,2,…n.
Графически атрибутивную СС можно представить в виде звездчатых графов (рис. 4.13).
161
2.Логический вывод на семантических сетях
Многообразие СС определяет сложность процессов вывода решений, поскольку каждому типу СС (однородная,
иерархическая, сценарная, функциональная) соответствует своя модель вывода в зависимости от свойств
используемых отношений (рефлексивность, симметричность, транзитивность…). В практических реализациях
наиболее часто используется механизм вывода, основанный на наследовании свойств от класса объектов к его
конкретным представителям (класс–подкласс, класс–экземпляр класса). Более строго, наследование – это способ,
которым происходит передача значений свойств объектов друг другу.
Основным механизмом наследования является иерархия понятий, выстроенная по отношениям ISA и PART-OF.
Иерархия показывает отношение включения понятий более низкого уровня в более высокий. При этом совокупность
понятий, вносимых в конкретную СС зависит от целевого назначения системы или ее конкретного использования.
Выделяются объекты: классы, подклассы, экземпляры, свойства экземпляров. свойства значений экземпляров.
Класс – это множество объектов, имеющих несколько или большинство общих свойств, т.е. класс является
обобщением или концептом. Класс хранит информацию, присущую всем его объектам. Объекты, когда нужно, могут
наследовать от класса эту информацию.
Подкласс – это класс объектов, составляющих подмножество класса более высокого уровня. Например, класс
"пассажирский самолет" является подклассом класса "самолет", а "самолет" – подклассом класса "летательные
аппараты".
Классы и подклассы также состоят из объектов –экземпляров, наследующих свойства объектов уровнем выше.
Рисунок 2.9 описывает иерархию отношений между классом ЯБЛОКО и его подклассами БЕЛЬ, АНИС, АПОРТ и
отношения подкласс – экземпляр класса.
Наследование свойств означает, что свойства, приписываемые объекту (классу) высокого уровня, автоматически
присваиваются объектами более низкого уровня по умолчанию. Но тут есть особенность. Рассмотрим процесс
подробнее.
1. Отношение класс–подкласс. Это отношение специализации. Здесь свойства и значения свойств наследуются по
умолчанию по связям специализации (ISA). Пример: САМОЛЕТ – ТУ-104. (ТУ-104 наследует многие свойства
класса САМОЛЕТ). Обратное отношение (PART-OF) – отношение обобщения, т.е. подкласс специализирует, а класс
– обобщает.
2. Отношение класс–объект. Это также отношение ISA. Свойства наследуются вниз по умолчанию. Это отношение
классификации. Обратное отношение – отношение интеграции.
3. Отношение объект (экземпляр) – подобъект (свойства). Это отношение декомпозиции. Объект разлагается на
составляющие. Обратите внимание – свойства по этой связи не наследуются! В самом деле, если на линии ISA
МЛЕКОПИТАЮЩИЕ – КОШКИ КОШКИ– экземпляр, то дальнейшее движение по этой линии уже приводит к
разделению объекта КОШКИ на составляющие: ФОРМА УШЕЙ, ХВОСТ, ЛАПЫ и т.д.. Свойства класса
МЛЕКОПИТАЮЩИЕ здесь уже не наследуются. Обратное отношение – агригирование. Что еще интересно: если по
линии ISA (целое–часть) число экземпляров может варьироваться и не влияет на целостность класса, то в обратном
отношении PART-OF должны присутствовать все части или какой-то обязательный минимум этих частей.
Как уже говорилось, одним из наиболее распространенных методов вывода на сетях является метод сопоставления частей сетевой структуры. Рассмотрим пример сопоставления.
162
Имеется участок сети базы данных относительно класса САМОЛЕТЫ (рис. 2.10).
Требуется для начала ответить на вопрос: "Что имеет ЯК-40?".
Участок сети, соответствующий этому вопросу, показан на рис. 2.11. Для ответа на этот вопрос проводится
сопоставление. Сначала отыскивается вершина ИМЕТЬ такая, которая имеет соединение с ЯК-40. Теперь три левые
вершины совпали, и по линии "Что имеет" мы делаем вывод: "ЯК-40 имеет двигатель Д1".
Рассмотрим процесс вывода подробнее. Пусть требуется ответить на вопрос: "Существует ли самолет, имеющий
двигатель типа Д1?". Сеть, соответствующая этому вопросу, показана на рис. 2.12. Однако в таком виде она не годится
для сопоставления с базой данных. Если же ввести вершину ЯК-40 и линию, показывающую, что ЯК-40 –
ПАСС.САМОЛЕТ, то уже можно сопоставить вершину ИМЕТЬ с вершиной ИМЕТЬ-?, а вершину ДВИГАТЕЛЬ с
ДВИГАТЕЛЬ-? Отсюда следует вывод: "Да, – это ЯК-40"
163
55.
Представление нечетких знаний. Нечеткие множества и отношения. Нечеткий вывод.
1.
Представление нечетких знаний.
Для современного развития общества характерно стремление ко все более широкому применению математических методов для
описания и анализа сложных экономических, социальных, экологических, технических и других систем. Отличительной
особенностью этих систем является то, что помимо объективных законов в их функционировании существенную роль играют
субъективные представления, суждения и эмоции людей.
При анализе исследуемой сложной системы мы зачастую разбиваем ее на более мелкие системы, осуществляя тем самым ее
декомпозицию, т.е. разбиение на более мелкие части. Выделение этих частей (подсистем) определяется целями исследования и
нашими представлениями о полной системе.
Анализ выделенной подсистемы производится с учетом ее связи с другими подсистемами. Точное описание этих связей
затруднительно и, как правило, осуществляется с использованием либо своих собственных представлений об этих связях, либо при
помощи экспертов. При этом информация о границах анализируемой подсистемы зачастую бывает выражена в понятиях, имеющих
нечёткий смысл с точки зрения классической математики. Эта информация носит субъективный характер, и ее представление на
естественном языке нередко имеет большое число неопределенностей типа “много”, ”мало”, "ближе", "дальше" и т.п., которые не
имеют аналогов в языке традиционной математики. Для дальнейшего успешного применения математических методов исследования
сложных систем необходимо было разработать аппарат учета нечётких представлений и суждений людей о реальном мире.
Разработка таких методов связана с именем американского математика Л.А.Заде. В 1965 г. он предложил так называемую теорию
нечётких множеств, которая предлагалась в качестве средства математического моделирования неопределенных понятий.
Все нечеткости, имеющие место в инженерии знаний, к настоящему времени можно классифицировать по следующим признакам:
1. нечёткость, неточность или неопределенность информации;
2. недетерминированность процедур вывода решений;
3. многозначность интерпретации;
4. ненадежность данных;
5. неполнота информации.
В традиционной математике имеет место чёткость, и любая формальная логика, и том числе и булева, основана на этом принципе.
Вопрос о принадлежности некоторого элемента тому или иному множеству здесь решается вполне определенно: или принадлежит,
или не принадлежит – третьего не дано. Заслуга Л.А. Заде состоит в том, что он ввел понятие взвешенной принадлежности. Значение
функции принадлежности показывает, что элемент может принадлежать подмножеству в большой или меньшей степени, а отсюда и
появилось понятие нечеткого подмножества.
Таким образом, теория нечётких множеств – это шаг на пути к сближению точности классической математики и неточности
реального мира. Нечеткое множество – это математическая модель класса с нечеткими или, иначе, размытыми границами.
Популярность подхода, основанного на формализации нечёткостей, свидетельствует о его многочисленных практических
применениях, что способствовало формированию специального направления в области искусственного интеллекта – исследованию
нечётких систем.
Математическая теория нечетких множеств, предложенная Л.А. Заде, позволяет описывать нечеткие понятия и знания, оперировать
этими знаниями и делать нечеткие выводы. Основанная на этой теории новая методология построения компьютерных систем,
существенно расширяет области применения компьютеров. Более того, такие системы можно создавать в любой области
деятельности человека.
За последние годы разработаны новые микропроцессоры, выполняющие операции над нечеткими множествами, нечеткие
компьютеры и программные системы.
2.
Нечеткие множества.
Начнем с примера. Пусть у нас имеется множество Х пищевых продуктов. Из этого, довольно обширного, множества выберем только
те элементы, которые содержат молочный жир (молоко, сметана, сыр и т.п.). Таким образом мы образуем некоторое подмножество С
множества Х: С
Х. Совершенно очевидно, что степень принадлежности каждого из элементов х к самому этому множеству С будет
разная: молоко, например, содержит 4% жира, а сыр – 35%. Множество С, как видим, обладает весьма заметной неопределенностью
или, как говорят, нечёткостью. Степень принадлежности каждого из х, входящего в С, лучше всего обозначать в долях. Тогда мы
получаем следующее выражение для С:
С = {0.04/молоко, 0.15/творог, 0.25/сливки, 0.35/сыр, 0.40/сметана, 0,78/масло, 0,98/топленое масло}.
Нечеткое множество С, следовательно, можно представить как множество пар типа степень принадлежности/название элемента (х)
(некоторые авторы предпочитают "обратное" написание типа название элемента (х)/ степень принадлежности).
Степень принадлежности характеризует каждый из х С и в общем случае является его функцией: С(х). Если элемент хi
"стопроцентно" относится к С, то С(х)=1; если не содержится вообще, то С(х)=0.
Определение. Нечетким множеством С в Х называется совокупность пар вида (х, С(х)), где х С, а С(х)– функция
принадлежности, определенная на интервале [0, 1].



Функция принадлежности С(х) полностью характеризует х (она еще называется характеристической функцией). Поэтому
справедливо утверждение:
нечеткое множество вполне описывается своей функцией принадлежности.
Обычные (чёткие) множества составляют собой подкласс нечетких множеств. функция
В(х) =  1, если Действительно, функцией принадлежности обычного множества В
Х является его характеристическая х В и


164

 0, если х В,
так что его также можно определить как совокупность пар (х, С(х)). Таким образом, нечеткое множество представляет
собой более широкое понятие, чем обычное множество, а функция принадлежности нечеткого множества может быть произвольной.
Каждому нечеткому множеству соответствует своё множество функций принадлежности С(х). Назовем его М. Если С(х) принимает
свои значения на множестве М , то можно сказать, что Х принимает значение в М посредством С(х): хС  М.
Элементы множества М описывают те свойства элементов х Х, которые делают их элементами нечеткого множества С. Эти
свойства могут быть заданы в численном виде, как это мы видели выше, но могут быть сформулированы в виде каких-то условий.
Например:
"нечеткое подмножество чисел х, приближенно равных данному действительному числу n", или
"нечеткое подмножество чисел около нуля " или, к примеру,
"нечеткое подмножество особей, образующих род (в биологии)," и т.п. .
Не всегда удается точно определить условия, описывающие элементы
С(х). В экспертных системах, к примеру, функции
принадлежности задаются экспертами, исходя из их знаний и личного опыта.
Определение. Нечеткое множество называется пустым, если его функция принадлежности равна нулю на всем множестве Х,
т.е.

(х)=0, хХ.
Универсальное множество Х также можно описать функцией принадлежности вида:
Х(х)=1 , хХ.
Определение. Носителем нечеткого множества А (обозначение sup A) с функцией принадлежности А(х) называется
множество (в обычном смысле) вида
sup А={x/xX, A(x) > 0}.
(4.1)
Другими словами, sup А определяет верхнюю границу А при положительных значениях .
Определение. Нечеткое множество А называется нормальным, если выполнено равенство sup А(х)=1; хХ. В противном
случае нечеткое множество называется субнормальным. Например, нечеткое множество С в примере 2. Субнормальным часто
оказывается пересечение нечетких множеств. Субнормальное множество можно преобразовать к нормальному (нормализовать),
разделив функцию принадлежности (х) этого множества на величину sup (х), хХ.
Пусть А и В – нечеткие множества в Х, а А(х) и В(х) – их четкие функции принадлежности соответственно. Справедливо
утверждение, что А включает в себя В (т.е. ВА), если для любого хХ выполнено неравенство
В(х) А(х).
(4.2)
Множество А и В совпадают (эквивалентны), если В(х)=А(х) при любом хХ. Если нечеткие множества А и В таковы, что ВА, то и
sup Bsup А
3.
Отношения.
Роль отношений в представлении знаний очень велика. Мы встречались с ними неоднократно. В исчислении предикатов
мы ставили отношения на место предикатного символа, в семантических сетях обозначали дугами, соединяющими два
объекта, применяли в виде имени слота, когда строили фрейм. Но до сих пор мы еще "не проходили" операции над
самими отношениями, которые, оказывается, подчиняются и алгебраическим, и логическим законам. Специальные
логики, разработанные для операций с отношениями, носят название псевдофизических логик.
Несмотря на многочисленность пар, имя введенного отношения для них общее. Это имя внесем в базу знаний и там
запомним. Имен различных отношений в БЗ может храниться множество. Все они образуют так называемые
интенсиональные знания, содержащие интенсиональные отношения (те самые имена отношений).
Каждая из пар единственна в своей роде, каждую необходимо запомнить. Множество конкретных пар образует
экстенсиональные знания, они хранятся в базе данных. Отдельно взятая пара образует экстенсиональное отношение.
Пусть элемент х множества Х находится в отношении R с элементом у того же множества. Этот факт представим в виде
хRy. Говорят, что х и у находятся в экстенсиональном отношении R (образовали пару), имя которого (интенсиональное
отношение) R.
Положим элементы i=2 и j=4 образуют экстенсиональную пару R24 c интенсиональным отношением R'24 в качестве
имени. Полным или семантическим отношением будем называть пару r24 = (R'24,R24). В дальнейшем мы будем работать
только с семантическими отношениями.
Если элемент u под номером i некоторого множества находится в отношении rR с элементом v под номером j того же
множества, то, упрощая, пишут rij (ui,vj). Отношение R можно оговорить заранее, и тогда достаточно будет указать лишь
пары (ui,vj). Если i, j = 1,2,3…n,то подмножество отношений между ними удобно задавать в виде таблицы: ы
165
где r11 отображает отнощение для пары (u1, v1), r12 соответственно для (u1,v2) и т.д.
Таблицу можно расписать иначе, в виде "суммы", где знак + будет означать лишь факт принадлежности элемента к
подмножеству {rij}.
{rij} = (u1,v1)+(u1,v2)+(u1,v3)+(u1,v4)+
(первая строка)
(u2,v1)+(u2,v2)+(u2,v3)+(u2,v4)+… (вторая строка) и т.д.
Строки можно переписать и так:
u1(v1+v2+v3+v4)+u2(v1+v2+v3+v4)…= (или короче) =
4
4
4
4
= u1 vj + u2  vj + u3 vj + u4 vj .
j=1
j=1
j=1
j=1
Окончательно имеем:
4 4
4 4
{rij} =  ui  vj = (или, переходя к парам) =   (ui,vj).
i=1 j=1
i=1 j=1
Окончательный вывод. Если имеется некоторое полное множество U и другое полное множество V, то отношением R
между ними является подмножество, образованное произведением UV и определяемое следующим образом:
n m
R =   (ui,vj)
(4.14)
i=1 j=1
или иначе – в виде матрицы rij типа вышеприведенной таблицы, где
rij =  1, если (ui, vj)R (выполняется uiRvj) и
 0, если (ui, vj) R.
(Если имеется универсальное множество Х и на нем заданы отношение R его элементов, то, очевидно, R является
подмножеством Х, т.е. можно написать: R XX).
Рассмотрим некоторые свойства отношений.
1. Рефлексивность. Если х и у находятся в отношении R(х,у), то это отношение рефлексивно, если оно
сохраняется при замене у на х, т.е. само с собой. Отношение равно рефлексивно: R(х,у) ~ R(х,х).
2. Симметричность. Отношение R(х,у) сохраняется, если объекты поменять местами: R(x,y) ~ R(y,x) (знак ~
означает логическую эквивалентность). Пусть х брат у, но ведь и у брат х – симметричность.
3. Транзитивность. Если отношение R выполнется для х, y и z так, что R(x,y) и R(y,z), то справедливо R(x,z), т.е.
можно записать
R(x,y) & R(y,z) → R(x,z).
Например, если выполняются отношения х  у и у  z, то выполняется и отношение х  z. Или: Ваня старше Пети, Петя
старше Кати, следовательно, Ваня старше Кати.
4. Обращение отношений. Очень интересное свойство, мы часто им пользуемся. Если шляпка дороже сумочки, то
сумочка дешевле шляпки – разве не так? Иначе говоря, истинно выражение:
Ri(x,y) ~ Rj(y,x).
(4.15)
Здесь вместе с переменой мест объектов меняется и сам тип отношений (дороже – дешевле, выше – ниже, быстрее –
медленнее) . Возникает так называемая смысловая симметричность. И не надо в памяти БЗ вносить нам всевозможные
отношения. Достаточно ввести операцию обращения, а часть отношений, являющихся результатом этой операции,
можно исключить. Записывается операция обращения так: Rj = Ri–1 .
Пусть на одном и том же множестве Х заданы два отношения А и В. Множество С = А
отношений А и В:
С(х,у) = А(х,у)  В(х,у) .
(4.16)
Множество D = А
 В называется объединением
 В называется пересечением А и В:
166
D(x,y) = A(x,y)  B(x,y).
(4.17)
Говорят, что отношение В включает в себя отношение А, если для соответствующих множеств АХХ и ВХХ
выполняется АВ, откуда следует, что если выполняется хАу, то выполняется хВу.
Если отношение А задано на Х и выполняется хАу, то для обратного отношения А–1 будет верно соотношение уА–1х.
Eсли матрица А={aij}, а матрица A–1={ij}, то элементы их будут связаны между собой отношением aij=ji, т.е. матрица
А–1 получается путем транспонирования матрицы А.
4.
Нечеткие отношения.
Все рассмотренные выше отношения мы трактовали как чёткие. Характерная черта чётких отношений – их
определенность: либо есть отношение, либо его нет. Среди множества всяких отношений есть такие, которые не могут
быть нечёткими. Отношение мать, например. Если Шавка мать Бобика, то это либо так (r =1), либо не так (r = 0). Иное
дела отношение старше. Его ведь можно понимать как немного старше, старше, значительно старше и т.п. Мера
определенности здесь задается степенью принадлежности (функцией принадлежности) , о которой мы уже говорили
выше. Это значит, что прежнее отношение между х и у типа r = (x,y) заменяется на отношение r = R(x,y)/(x,y), где (х,у) –
данное отношение, R – функция принадлежности этого отношения. Выражение (4.14) для отношений заменяется на
выражение для нечётких отношений:
n m
R =   R(ui,vj)/(ui,vj),
(4.18)
i=1 j=1
а матрица отношений вообще может быть построена из одних функций принадлежности, стоящих на соответствующих
местах.
Функция R(u,v), конечно, может быть задана. Но вот вопрос: а как ее определить, если сами величины uU и vV
заданы нечётко, через свои функции принадлежности? Большинсто авторов в этом случае принимает такое
соотношение:
R(u,v) = U(u)V(v).
(4.19)
В булевой логике знак конъюнкции  соответствует выделению наименьшего из входных значений. В этом смысле он
здесь и употребляется. Поэтому можно записать:
R(u,v) = min(U(u), V(v)),
(4.20)
то есть функция принадлежности отношения равна минимальной
из функций принадлежности элементов отношения.
Подставляя (4.19) в (4.18), получаем:
n m
R =  (U(ui)V(vj)) /(ui,vj),
(4.21)
i=1 j=1
Как и прежде, R = UV, и выражение (4.21) отражает результат прямого перемножения нечётких множеств.
В логике нечётких отношений произведение нечётких множеств моделирует знание-правило "если U, то V", то есть
моделирует отношение-продукцию UV. И это очень важно, поскольку в СИИ к продукции, как об этом уже
говорилось выше, можно свести большинство интеллектуальных задач.
Пусть имеется множество U – маложирные молочные продукты: 1– сыворотка, 2 – молоко, 3 –творог, 4 – сливки и
множество V – жирные молочные продукты: 1 – сыр, 2 – сметана, 3 – масло, 4 – топленое масло. Промоделируем
продукцию: если u – маложирные, то v – очень жирные. (Будем считать, что оценки степеней принадлежности нам
определили домашние хозяйки).
Для множества U имеем:
U =1 /1 +0,8/2 +0,6/3 +0,2/4.
Для множества V имеем:
V =0,1/1 +0,5/2 +0,8/3 + 1/4.
R = UV .
Это будет матрица с элементами R(ui,vj). Строки образуются следующим образом: 1 – берется U ("числитель") первого
элемента из U и поочередно сравнивается с каждым V ("числителем") из множества V, меньшее значение заносится в
строку; 2 – берется U второго элемента из U и сравнивается с каждым V из V и т.д. Так мы моделируем выражение
(4.11), которое состоит из минимумов.
Матрица будет иметь вид:
167
Итак, отношение R = UV выполняет операцию UV, т.е. отображает нечёткое отношение из U в V. Пусть
теперь имеется некое нечёткое отношение S = VW из V в W. Нас интересует, как определить нечёткое отношение из U в
W? Другими словами, требуется промоделировать операцию UVVW. В левой части этого выражения стоит матрица
R с элементами rij = R(ui, vj), в правой части – матрица S с элементами sij = S(vi,wj). Операция RS над матрицами
нечётких отношений носит название свёртки или композиции и обозначается R○S. Результатом свёртки будет матрица P
= R○S с элементами рij = μP(μRi,μSj). Алгоритм получения матрицы Р – классический алгоритм произведения матриц
(строку на столбец). Выражение для рij для ясности распишем "поштучно":
р11 = max{min(r11, s11), min(r12, s21), min(r13, s31), min(r14, s41)}…
p32 = max{min(r31, s12), min(r32, s22), min(r33, s32), min(r34, s42)}…
(Из каждой пары выбирается меньшая величина, а затем из этих меньших берется большая – всё очень просто).
Если вспомнить, что дизъюнкция есть выделение максимальной величины, а конъюнкция – минимальной, то с
учетом (4.21) можно написать выражение для композиции:
n
m
P = R○S = ∑ ∑  (R(ui, vj)S(vj, wk))/(ui, wk).
(4.22)
i=1 k=1 vj
(Так называемая max-min формула).
5. Нечеткий вывод
Нечёткие выводы чаще всего основаны на хорошо нам известном правиле заключения (modus ponens) ([1], стр. 55). Это
правило касается импликации и говорит о том, что если вся импликация истинна и посылка истинна, то и заключение
истинно: (p, p→q)q. Иногда это правило записывают в виде дроби
p, p→q,
q
где в числителе – высказывания, истинность которых уже доказана, а в знаменателе – высказывания, истинность
которых логически следует из верхних высказываний.
Приведеная схема вывода пригодна, разумеется, и для случая операций с отношениями. Пусть имеются чёткие и
нечёткие множества: А и А', В и В'. В общем случае они необязательно совпадают, но в той мере, в которой они
совпадают их можно сопоставить и получить нечёткий результат. Если однозначно выполняется правило,
А, А→В ,
(4.30)
В
то при нечётком выводе могут возникать различные варианты. Пусть вместо А мы имеем нечеткое множество А' .
Заключение в этом случае уже будет нечётким:
А', А→В .
(4.31)
В'
Возможен случай, когда нечётко задано заключение:
А, А→В'.
(4.32)
В''
Нечёткости В' и В'' могут быть разными. В общем случае выражение (4.29) преобретает вид:
168
А', А→В' .
(4.33)
В''
Нечёткий вывод рассмотрим на примере выражения (4.30). Порядок действий здесь следующий. Вначале определяем
нечёткое отношение А→В. Для этого у нас есть формула (4.21). Получается матрица R = АВ. Далее следует свёртка S =
А'○R по формуле max-min (4.22).
Рассмотрим нечёткий вывод на вышеприведенном примере с яблоками. Имеем следующие условия:
R1: "Если вес яблок МАЛЫЙ (А), то их потребительская стоимость НИЗКАЯ (НПС) (В).
М1': "Не совсем маленькие" (А').
Что есть НПС (В')?
Этим условиям соответствует формула
А', А→В,
В'
где А→В = R1.
Отношение R1 мы уже имеем. Это матрица (4.28). Зададим нечёткое множество М1' – "Не совсем маленькие":
М1' = " Не совсем маленькие" = 0,9/50 + 0,6/150 + 0,3/250 + 0/350.
Окончательный вывод – свёртка А'○R1, определяющая В'.
Если расшифровать полученный результат, то получим:
В' = НПС = 0,9/10 + 0,8/20 + 0,1/30 + 0/40.
Низкая потребительская стоимость – цена за яблоки в пределах 10 – 20 руб. – вот, что мы получили.
В настоящее время нечеткая логика заняла важное место в СИИ, сделавшись самостоятельным направлением – нечёткие
экспертные и другого типа системы, нечеткие алгоритмы, нечёткие системы принятия решений. Существует даже общая
тенденция к переопределению известных алгоритмов, в том числе вычислительных через нечёткую алгебру. При этом
точные вычисления рассматриваются как вырожденный случай. Важнейшее место нечёткая логика занимает в научном
направлении, называемом логикой правдоподобного вывода. Все большее значение это направление приобретает в
системах контроля, обучения и др.. Конечно, имеются немалые трудности. Сюда можно отнести проблемы, связанные с
субъективностью нечётких оценок, отсутствием методов проверки их на непротиворечивость, трудности с получением
точных результатов, когда это необходимо.
56.
Понятие агента и МАС: определение, критерии целесообразности и области применения многоагентного
подхода для решения задач. Отличие агента от объекта и экспертной системы.
Агент – это система, находящаяся в некоторой среде, воспринимающая эту среду посредством рецепторов, и
воздействующая на нее посредством эффекторов (см. рис. 1).
Многоагентная система – это система, в которой поставленная задача решается за счет совместной
деятельности (кооперации, противоборства) многих агентов в некоторой среде.
Рис. 1.
169
Считается, что агент должен обладать, по крайней мере, некоторыми из следующих основных свойств [3]:
- Автономность. Агент должен работать без ежесекундного вмешательства и контроля человека.
- Обучаемость. Агент должен обучаться всему, что может освоить для компенсации неполных или неверных
исходных знаний.
- Реактивность. Агент должен оперативно реагировать на изменения в среде.
- Проактивность. Помимо оперативных реакций агент должен самостоятельно выбирать себе текущие цели и искать
способы их достижения. Для этого агент должен не только уметь распознавать сложившиеся ситуации, но и благоприятные
возможности.
- Социальность. Агент должен взаимодействовать (возможно, сотрудничать) с другими агентами в рамках
достижения целей при помощи какого-либо языка коммуникации.
- Рациональность. Агент должен быть способен находить рациональные решения задач в соответствии с
поставленными критериями.
Также выделяется ряд дополнительных свойств, которыми агенты могут обладать:
- Мобильность. Это способность агента перемещаться по вычислительной сети (или в физической среде).
- Правдивость. Агент специально не сообщает неверную информацию.
- Доброжелательность. Если агенты не имеют конфликтующих целей, то каждый из них может выполнять все, о чем
просят другие.
- Эмоциональность. Способность моделировать эмоции, для выражения своего текущего состояния.
Примерами агентов являются:
- компьютерные вирусы;
- интеллектуальные помощники;
- поисковые боты в сети интернет;
- некоторые персонажи компьютерных игр;
- роботы;
- и т.д.
В тоже время агентами не являются:
- объекты в классическом понимании объектно-ориентированного программирования (см. далее);
- отдельно взятые интеллектуальные технологии (например, системы обработки правил, нейронные сети и т.д.);
- мастера, планировщики и т.п.
Отличие агента от объекта
Различие первое
Один из основных принципов ООП – инкапсуляция – говорит о том, что только сам объект имеет
непосредственный доступ к своим переменным, описывающим его состояние. Иначе говоря, объект единолично
владеет своим состоянием, и только сам может его изменять, получив соответствующее сообщение. Однако
объект не имеет полного контроля над своим поведением. Любой публичный метод объекта, если он вызван
170
соответствующим сообщением, будет выполнен. Причем объекты обязаны иметь публичные методы, иначе из
них невозможно будет построить систему, предназначенную для достижения общих для всех объектов целей.
В противовес объектам, агенты не обязаны иметь общих целей, поскольку могут разрабатываться множеством
разнообразных организаций и частных лиц для представления их собственных интересов в некоторой
виртуальной среде. Поэтому агент «А» не должен выполнять свои методы только потому, что агент «Б» посылает
ему соответствующие сообщения. Выполнение данных методов может и не лежать в области «интересов» агента
«А». Иначе говоря, агент имеет полный контроль над своим поведением. Для организации взаимодействия
между агентами, взамен жесткого выполнения методов в ответ на полученное сообщение, используется
механизм запросов. Если агенту «А» нужно, чтобы агент «Б» выполнил некоторое действие, то он посылает
агенту «Б» запрос на выполнение данного действия, но агент «Б» на основе своего механизма принятия решений
сам решает, выполнять данное действие или нет. Различие второе
Гибкость автономного поведения агентов, обусловленная такими их свойствами как реактивность,
проактивность, социальность и т.д. – является второй отличительной особенностью агентов.
Стандартная технология ООП ничего не может сказать о том, как разработать систему, обладающую столькими
интегрированными свойствами. Эти вопросы лежат в области проектирования интеллектуальных систем,
которые обладают централизованным или иерархически организованным механизмом логического вывода. И
именно благодаря подобному механизму агенты должны решать что им делать в настоящий момент.
Различие третье
В подлинно многоагентной системе каждый агент имеет собственный поток управления или выполняется на
отдельной вычислительной машине. Иначе говоря, агенты работают параллельно, а не в режиме разделения
времени. В то время как система объектов обычно имеет общий поток управления.
Конечно, ничто не мешает нам имитировать параллельность работы посредством режима разделения времени, но
тогда мы вынуждены будем согласиться и с имитацией автономии. Подобные имитации возникают, когда
пытаются смоделировать работу многоагентной системы (и самих агентов и среду) в пределах одного
компьютера. Данный подход не требует большого количества аппаратуры, однако существенно возрастают
требования к ее качеству, т.е. вычислительной мощи. Например, увеличение количества работающих агентов,
обладающих чуть более сложным, чем рефлекторное, поведением, в таких средах как NetLogo Breve быстро
сделает модель неповоротливой и сложной для наблюдения.
Отличие агента от экспертной системы
Во-первых, классические экспертные системы, типа MYCIN, взаимодействуют только с пользователем и
получают от него всю необходимую для принятия решений информацию. Иначе говоря, у них нет датчиков,
посредством которых они автоматически воспринимают среду функционирования, т.е. среды для них фактически
не существует. Это приводит к следующим двум отличиям.
Во-вторых, классические ЭС не способны к реактивному и проактивному поведению.
В-третьих, классические ЭС не способны к самостоятельному взаимодействию с другими ЭС, т.е. кооперации,
координации, ведению переговоров и т.д.
В свою очередь, ЭС реального времени во многом очень похожи на агентов и чаще всего отличаются от них
отсутствием социального элемента поведения.
Области применения многоагентного подхода для решения задач
Примерами подобных задач являются следующие.
1. Моделирование поведения социальных систем с целью проверки теорий, описывающих это поведение:
171
- для построения планов эвакуации;
- для координации действия спасателей;
- для управления движением;
- для управления различными предприятиями, организациями, городами, странами;
- для проведения социологических исследований;
- для проведения экономического моделирования рынков;
- для проведения экологических и биологических исследований;
- и т.д.
2. Задачи логистики.
3. Задачи оптимизации поточных линий.
4. Качественный поиск информации в WEB.
5. Ведение военных действий с применением боевых роботов.
6. Автономное управление космическими аппаратами.
Все вышеперечисленное обусловило возникновение многоагентного подхода и обеспечило ему актуальность
на многие годы вперед.
МАС целесообразно применять в распределённых системах, системах в которых необходимо минимально
возможное время отклика системы.
57.
Агенты, как целеустремленные системы: BDI-модель агента, обоснование целесообразности ее
использования
В первую очередь агенты рассматриваются как посредники, делегаты, искусственные представители интересов
людей в некоторой виртуальной (или реальной) среде, и только потом это понятие распространяется на других субъектов,
например, животных.
Поэтому, когда говорят о поведении агентов и характеризуют их состояние, то употребляют такие термины как:
- убеждения (Beliefs);
- желания (Desires);
- намерения (Intentions).
Иногда к этому списку добавляют «надежды», «опасения» и другие чисто человеческие характеристики. Модель
агента, построенная с использованием перечисленных понятий, называется BDI-моделью.
Может показаться, что перенесение подобных терминов на искусственные сущности надуманно. Однако этому
есть свое рациональное объяснение.
Во-первых, когда мы описываем поведение людей, мы естественным образом используем эти термины, а поскольку
агенты должны заменять людей в некоторой деятельности, они Должны иметь модели наших убеждений, желаний и других
проявлений психической деятельности, закладываемые в них разработчиками.
Тогда зачем, спрашивается, между естественно-языковым описанием поведения и его программной моделью вносить
лишний терминологический барьер вроде переменных, процедур, методов, модулей и т.д.? Этот барьер заставляет
разработчика терять время и силы на то, чтобы решить, каким образом лучше всего отразить моделируемое понятие в
172
терминах используемого языка программирования. Поэтому многие агентные языки программирования ориентированы
именно на построение программы в терминах BDI-модели.
Во-вторых, устранение терминологического барьера - это не самая главная задача BDI-модели. Главное
заключается в том, что программирование в BDI-понятиях обязывает среду разработки обрабатывать их в соответствии
с тем содержанием, которое в них вкладывается человеком. Иначе говоря, в среде должен быть механизм логического
вывода, который моделирует принятие решений человеком на основе его убеждений, желаний и т.д. Дадим
определение основным понятиям BDI-модели.
Убеждения - это декларативные знания, которые считаются истинными с точки зрения данного агента. В связи с
этим разные агенты могут иметь разные убеждения относительно одних и тех же вещей. Кроме того, могут быть
убеждения относительно убеждений и прочих BDI-элементов. Убеждения, оказавшиеся ложными, должны быть
отвергнуты. Таким образом, агент должен действовать исходя из текущих убеждений, но допускать, что они могут
быть ложны. Следующие фразы содержат примеры убеждений:
- «Она думала, что на улице холодно» - убеждение о состоянии объекта;
- «Она была убеждена, что он сделает ей предложение» -убеждение о намерениях другого;
- «Она была уверена, что он знает ее подругу» - убеждение об убеждении другого;
- «Он думал, что она хочет в Париж» - убеждение о желаниях другого.
Желания - это цели существования агента, т.е. его целевые состояния. Желания можно понимать как убеждения,
которые нужно сформировать. Деятельность агента обычно обусловлена достижением его собственных целей
(удовлетворением желаний), что, однако, не исключает участие агента в достижении целей других агентов.
Намерения - это планы по достижению целей, принятые к исполнению. Они могут и не согласовываться с
собственными желаниями агента, а строиться на основе чужих желаний и объективных необходимостей. У агента в
настоящий момент может быть множество намерений, среди которых он должен постоянно выбирать, чем заняться в
настоящий момент.
Система Jason, предлагаемая читателю для ознакомления, работает с классическим определением BDI-модели, основные
понятия которой - это убеждения, цели и намерения.
58.
Стандартные языки взаимодействия агентов: KQML, KIF – назначение, структура сообщений, примеры
сообщений.
KQML - язык и протокол для поддержки взаимодействия агентов в распределенных приложениях. Примеры возможных
применений языка включают интеллектуальные многоагентные системы, такие как интеллектуальные агенты
планирования, поддерживающие распределенную обработку. Перед определением интерфейсов систем, основанных на
знаниях, перечислим типичные компоненты таких систем:
Приложение, рассчитанное на неподготовленного пользователя (End User Application);
Систему, основанную на знаниях (Knowledge Based System);
Хранилище специальных знаний (Knowledge Base Repository) - хранилище знаний о содержимом базы знаний используется для отслеживания истории доступа, целостности и других аспектов функционирования баз
знаний;
Система управления базами данных (Database System);
Активные сенсоры (Active Sensors) - отвечают за обмен данными (знаниями) с “внешним миром”
Возможны различные способы взаимодействия перечисленных компонент.
Разработчики KQML выделяют 3 направления, особенно важных с их точки зрения для коммуникаций
интеллектуальных агентов:
Связность (Connectivity) - фокусируется на способе связывания агентов между собой;
173
Архитектура (Architecture) - акцентирует внимание на способе построения будущей системы (будет ли
система статической, когда все компоненты известны уже на этапе проектирования/реализации или
динамической);
Коммуникации (Communication) - данное направление рассматривает синхронность/асинхронность обмена
сообщениями между агентами.
При разработке языка были сделаны специальные предположения об основных моментах его использования
для описания коммуникаций многоагентных систем:
Архитектура. Агенты - это отдельные процессы, работающие в одном адресном пространстве или на
различных машинах, соединенные посредством Internet.
Коммуникации. Язык поддерживает следующие стратегии передачи информации: point to point, multicast,
broadcast.
Синтаксис. Сообщения между уровнями содержимого, сообщений и коммуникаций представлены в виде sвыражений языка Lisp. Между процессами выражения передаются как потоки ASCII -символов.
Протокол. Для транспортной поддержки KQML был создан специальный протокол - SKTP (Simple Knowledge
Transfer Protocol).
Рассмотрим уровни языка KQML. Язык KQML состоит из трех уровней: содержимого, сообщений и
коммуникаций. KQML-выражение можно рассматривать как выражение-содержимое, помещенное в сообщениеобертку, которое, в свою очередь, помещено в коммуникационную обертку. На уровне содержимого находится
представление знаний на некотором языке. Уровень сообщений добавляет дополнительные атрибуты, такие как
описание языка, на котором выражено содержимое, его онтологию и тип используемого метода переговоров.
Коммуникационный уровень добавляет информацию об отправителе и получателе сообщения, а также указывает,
является сообщение синхронным или асинхронным.
Основу синтаксиса языка KQML составляют имена примитивных действий- сообщений, которые в английской
транскрипции называются “performatives” Тип сообщений определяет, что можно сделать с предложениями,
содержащимися в сообщении, с этим связано само название KQML-сообщений на английском языке.
Все действия-сообщения можно разделить на следующие категории:
-языка содержимого KQML, который предполагает модель баз в форме множества предложений некоторого
языка, который может быть объектным;
-контекста рассуждений - подмножества предложений (фрагмента) базы знаний; запросы и отклики должны
делаться относительно некоторого контекста, при этом сообщения данного типа должны позволять определять
контекст и переключаться между фрагментами базы знаний;
-определения, которые имеют целью активизировать и отменять определения;
-ответы на вопросы, которые позволяют задавать вопросы относительно истинности предложений;
-отклики, которые определяют набор сообщений для получения ответов на заданные вопросы.
Пример сообщения KQML:
(evaluate
:sender A
:receiver B
:language KIF
:ontology motors
:reply-with q1
174
:content (val (torque m1)))
(reply
:sender B
:receiver A
:language KIF
:ontology motors
:in-reply-to q1
:content (= (torque m1) (scalar 12 kgf)))
(stream-about
:sender A :receiver B
:language KIF :ontology motors
:reply-with q1 :content m1)
(tell
:sender B :receiver A
:in-reply-to q1 :content (= (torque m1) (scalar 12 kgf)))
(tell
:sender B :receiver A
:in-reply-to q1 :content (= (status m1) normal))
(eos
:sender B :receiver A
:in-reply-to q1)
KIF - это язык для обмена знаниями между различными программами, написанными различными людьми, на разных
языках и в разное время. Он имеет декларативную семантику (значение выражений, представленных на этом языке,
может быть понято без обращения к специальному интерпретатору); он логически полон (обеспечивает выражение
произвольных предложений логики предикатов первого порядка), обеспечивает представление знаний о представлении
знаний; обеспечивает представление немонотонных правил вывода, определение объектов, функций и отношений.
KIF не претендует на звание языка для внутреннего представления знаний (хотя и может быть использован для
этих целей). Обычно программа получает внешние знания, выраженные на языке KIF, затем транслирует их во
внутреннее представление (списки, фреймы и т.д) и выполняет все вычисления, используя эти внутренние
175
представления. KIF используется при коммуникациях с внешними программами. Цель языка KIF аналогична цели языка
Postscript - он не является языком, достаточно эффективным для представления внутренних знаний программ, но тем не
менее он удобен для независимой разработки программ, работающих со знаниями.
Перечислим основные свойства языка KIF.
1. Язык является декларативным, чем отличается от языков типа Prolog и Emycin.
2. Язык является логически полным.
3. Язык является транслируемым (translatability) - он предполагает значения для трансляции декларативных баз знаний
в/из типичных языков представления знаний.
4. Язык является хорошо читаемым, что упрощает его использование разработчиком баз знаний.
5. Язык может быть использован как язык представления знаний.
Существуют две разновидности языка KIF: линейный и структурированный. В линейном варианте все его
выражения - это строки ASCII-символов, что удобно для хранения на устройствах с последовательным доступом. В
структурированном варианте языка правильные выражения - это структурированные объекты. Структурированный язык
удобен для использования при коммуникациях программ, работающих в одном адресном пространстве. Между
линейным и структурированным представлениями одной и той же сущности существует взаимно-однозначное
соответствие.
Соответствие между линейным и структурированным представлениями определяется следующим образом:
строка ASCII-символов будет правильным выражением линейного варианта языка KIF тогда и только тогда, когда (1)
она допускается интерпретатором языка Common Lisp, и (2) структура, порожденная интерпретатором Common Lisp
будет правильным выражением структурированного KIF.
В структурированном KIF определены следующие синтаксические конструкции: word, expression, operator,
constant, term, sentence, definition, rule и т.д.
Применимость KIF в рамках разработки агентов видится следующим образом. Ядро агента, а именно:
подсистемы управления памятью, планирования, база знаний и т.д. пишутся на С++ или на одном из языков Java,
Telescript (если нас интересует способность агента к мигрированию по сетям), а KIF используется как язык для обмена
знаниями/данными с другими агентами (для этого агент должен иметь подсистему перетрансляции с языка внутреннего
представления знаний на KIF). Язык KIF можно также использовать и как язык представления собственных знаний
агента, в этом случае отпадает надобность в упомянутом выше трансляторе.
Пример сообщений KIF:
1.
Записи о сотрудниках
(salary 015-46-3946 widgets 72000)
(salary 026-40-9152 grommets 36000)
(salary 415-32-4707 fidgets 42000)
2.
Один чип больше другого:
(> (* (width chip1) (length chip1))
(* (width chip2) (length chip2)))
3.
Предположение, что возведение в чётную степень даст положительное число:
(=> (and (real-number ?x)
(even-number ?n))
(> (expt ?x ?n) 0))
Объектно-ориентированное программирование
176
59.
Объектно-ориентированные системы программирования: основные свойства и преимущества.
Объектно-ориентированное представление данных: понятие объекта; отличие понятия 'объект' от понятия
'данные' в других языках программирования.
Основные свойства:

Инкапсуляция — это принцип, согласно которому любой класс должен рассматриваться как чёрный ящик —
пользователь класса должен видеть и использовать только интерфейсную часть класса (т. е. список
декларируемых свойств и методов класса) и не вникать в его внутреннюю реализацию.

Наследованием называется возможность порождать один класс от другого с сохранением всех свойств и
методов класса-предка (прародителя, иногда его называют суперклассом) и добавляя, при необходимости,
новые свойства и методы.

Полиморфизмом называют явление, при котором функции (методу) с одним и тем же именем соответствует
разный программный код (полиморфный код) в зависимости от того, объект какого класса используется при
вызове данного метода.

Появление в ООП отдельного понятия класса закономерно вытекает из желания иметь множество объектов со
сходным поведением. Класс в ООП — это в чистом виде абстрактный тип данных, создаваемый
программистом. С этой точки зрения объекты являются значениями данного абстрактного типа, а определение
класса задаёт внутреннюю структуру значений и набор операций, которые над этими значениями могут быть
выполнены. Желательность иерархии классов (а значит, наследования) вытекает из требований к повторному
использованию кода — если несколько классов имеют сходное поведение, нет смысла дублировать их
описание, лучше выделить общую часть в общий родительский класс, а в описании самих этих классов
оставить только различающиеся элементы.
Преимущества: Эта концепция в наибольшей степени соответствует внутренней логике функционирования
операционной системы Windows. Программа, состоящая из отдельных объектов, отлично приспособлена к
реагированию на события, происходящие в операционной системе. Большая надёжность кода и возможность повторного
использования отработанных объектов.
Недостатки: Динамическое связывание методов (из-за полиморфизма), Значительная глубина абстракции (обращение
объектов высокого уровня к низким), Наследование «размывает» код, Инкапсуляция снижает скорость доступа к
данным (использование внутренних полей), Динамическое создание и уничтожение объектов (объекты находятся в
куче).
Класс является описываемой на языке терминологии (пространства имён) исходного кода моделью ещё не
существующей сущности, т. н. объекта.
Объект — сущность в адресном пространстве вычислительной системы, появляющаяся при создании экземпляра класса
(например, после запуска результатов компиляции (и линковки) исходного кода на выполнение).
Класс — это тип, описывающий устройство объектов. Понятие «класс» подразумевает некоторое поведение и способ
представления. Понятие «объект» подразумевает нечто, что обладает определённым поведением и способом
представления. Говорят, что объект — это экземпляр класса. Класс можно сравнить с чертежом, согласно которому
создаются объекты. Обычно классы разрабатывают таким образом, чтобы их объекты соответствовали объектам
предметной области.
Отличие объекта от данных в том, что кроме прочих своих достоинств, объект демонстрирует характерное поведение,
реагирует на сообщения, наделён унаследованными реакциями и управляет своим, независимым, внутренним
состоянием.
60.
Объектно-ориентированное представление данных: понятие объекта; описание объекта в системе;
внутренняя реализация и внешний интерфейс объекта; состояние, свойства и поведение объекта; принцип
скрытия реализации.
Понятие объекта. Объект — сущность в адресном пространстве вычислительной системы, появляющаяся при
создании экземпляра класса (например, после запуска результатов компиляции (и линковки) исходного кода на
выполнение).
177
Описание объекта в подсистеме. ООП ориентировано на разработку крупных программных комплексов,
разрабатываемых командой программистов (возможно, достаточно большой). Проектирование системы в целом,
создание отдельных компонент и их объединение в конечный продукт при этом часто выполняется разными людьми, и
нет ни одного специалиста, который знал бы о проекте всё.
Объектно-ориентированное проектирование состоит в описании структуры и поведения проектируемой системы, то
есть, фактически, в ответе на два основных вопроса:


Из каких частей состоит система.
В чём состоит ответственность каждой из частей.
Выделение частей производится таким образом, чтобы каждая имела минимальный по объёму и точно определённый
набор выполняемых функций (обязанностей), и при этом взаимодействовала с другими частями как можно меньше.
Внутренняя реализация объектов. Класс — это тип, описывающий устройство объектов. Понятие «класс»
подразумевает некоторое поведение и способ представления. Понятие «объект» подразумевает нечто, что обладает
определённым поведением и способом представления. Говорят, что объект — это экземпляр класса. Класс можно
сравнить с чертежом, согласно которому создаются объекты. Обычно классы разрабатывают таким образом, чтобы их
объекты соответствовали объектам предметной области.
Класс является описываемой на языке терминологии (пространства имён) исходного кода моделью ещё не
существующей сущности, т. н. объекта.
Состояние, свойства и поведение.
Инкапсуляция — это принцип, согласно которому любой класс должен рассматриваться как чёрный ящик —
пользователь класса должен видеть и использовать только интерфейсную часть класса (т. е. список декларируемых
свойств и методов класса) и не вникать в его внутреннюю реализацию. Поэтому данные принято инкапсулировать в
классе таким образом, чтобы доступ к ним по чтению или записи осуществлялся не напрямую, а с помощью методов.
Принцип инкапсуляции (теоретически) позволяет минимизировать число связей между классами и, соответственно,
упростить независимую реализацию и модификацию классов.
Сокрытие данных — неотделимая часть ООП, управляющая областями видимости. Является логическим
продолжением инкапсуляции. Целью сокрытия является невозможность для пользователя узнать или испортить
внутреннее состояние объекта.
Наследованием называется возможность порождать один класс от другого с сохранением всех свойств и методов
класса-предка (прародителя, иногда его называют суперклассом) и добавляя, при необходимости, новые свойства и
методы. Набор классов, связанных отношением наследования, называютиерархией. Наследование призвано отобразить
такое свойство реального мира, как иерархичность.
Полиморфизмом называют явление, при котором функции (методу) с одним и тем же именем соответствует разный
программный код (полиморфный код) в зависимости от того, объект какого класса используется при вызове данного
метода. Полиморфизм обеспечивается тем, что в классе-потомке изменяют реализацию метода класса-предка с
обязательным сохранением сигнатуры метода. Это обеспечивает сохранение неизменным интерфейса класса-предка и
позволяет осуществить связывание имени метода в коде с разными классами — из объекта какого класса
осуществляется вызов, из того класса и берётся метод с данным именем. Такой механизм называется динамическим (или
поздним) связыванием — в отличие от статического (раннего) связывания, осуществляемого на этапе компиляции
.
61.
Объектно-ориентированное представление данных: понятие класса. Экзем-пляры класса, общее и
различное в них; отличие понятия 'класс' от понятия 'тип данных' в процедурных языках программирования;
сообщения и методы экземпляра и класса; создание экземпляров класса.
Объе́ктно-ориенти́рованное программи́рование (ООП) — парадигма программирования, в которой основными
концепциями являются понятия объектов и классов.
Класс — это тип, описывающий устройство объектов. Понятие «класс» подразумевает некоторое поведение и способ
представления. Понятие «объект» подразумевает нечто, что обладает определённым поведением и способом
178
представления. Говорят, что объект — это экземпляр класса. Класс можно сравнить с чертежом, согласно которому
создаются объекты. Обычно классы разрабатывают таким образом, чтобы их объекты соответствовали объектам
предметной области.
Основные понятия
Инкапсуляция
Инкапсуляция — это принцип, согласно которому любой класс должен рассматриваться как чёрный ящик —
пользователь класса должен видеть и использовать только интерфейсную часть класса (т. е. список декларируемых
свойств и методов класса) и не вникать в его внутреннюю реализацию. Поэтому данные принято инкапсулировать в
классе таким образом, чтобы доступ к ним по чтению или записи осуществлялся не напрямую, а с помощью методов.
Принцип инкапсуляции (теоретически) позволяет минимизировать число связей между классами и, соответственно,
упростить независимую реализацию и модификацию классов.
Сокрытие данных
Сокрытие данных — неотделимая часть ООП, управляющая областями видимости. Является логическим продолжением
инкапсуляции. Целью сокрытия является невозможность для пользователя узнать или испортить внутреннее состояние
объекта.
Наследование
Наследованием называется возможность порождать один класс от другого с сохранением всех свойств и методов классапредка (прародителя, иногда его называют суперклассом) и добавляя, при необходимости, новые свойства и методы.
Набор классов, связанных отношением наследования, называют иерархией. Наследование призвано отобразить такое
свойство реального мира, как иерархичность.
Полиморфизм
Полиморфизмом называют явление, при котором функции (методу) с одним и тем же именем соответствует разный
программный код (полиморфный код) в зависимости от того, объект какого класса используется при вызове данного
метода. Полиморфизм обеспечивается тем, что в классе-потомке изменяют реализацию метода класса-предка с
обязательным сохранением сигнатуры метода. Это обеспечивает сохранение неизменным интерфейса класса-предка и
позволяет осуществить связывание имени метода в коде с разными классами — из объекта какого класса
осуществляется вызов, из того класса и берётся метод с данным именем. Такой механизм называется динамическим (или
поздним) связыванием — в отличие от статического (раннего) связывания, осуществляемого на этапе компиляции.
Объект — некоторая сущность в виртуальном пространстве, обладающая определённым состоянием и поведением,
имеет заданные значения свойств (атрибутов) и операций над ними (методов).
Экземпляр класса (англ. instance) — это описание конкретного объекта в памяти. Класс описывает свойства и методы,
которые будут доступны у объекта, построенного по описанию, заложенному в классе. Экземпляры используют для
представления (моделирования) конкретных сущностей реального мира.
Экземпляры класса имею одинаковые атрибуты и методы, но конкретные значения атрибутов, обычно, разные. Каждый
экземпляр имеет свое место в памяти компьютера.
Отличия классов от других абстрактных типов данных состоит в том, что при задании типа данных класс определяет
одновременно и интерфейс, и реализацию для всех своих экземпляров, а вызов метода-конструктора обязателен.
Отдельного пояснения требует понятие обмена сообщениями. Первоначально (например, в том же Smalltalk)
взаимодействие объектов представлялось как «настоящий» обмен сообщениями, то есть пересылка от одного объекта
другому специального объекта-сообщения. Такая модель является чрезвычайно общей. Она прекрасно подходит,
например, для описания параллельных вычислений с помощью активных объектов, каждый из которых имеет
собственный поток исполнения и работает одновременно с прочими. Такие объекты могут вести себя как отдельные,
абсолютно автономные вычислительные единицы. Посылка сообщений естественным образом решает вопрос обработки
сообщений объектами, присвоенными полиморфным переменным — независимо от того, как объявляется переменная,
сообщение обрабатывает код класса, к которому относится присвоенный переменной объект.
179
Однако общность механизма обмена сообщениями имеет и другую сторону — «полноценная» передача сообщений
требует дополнительных накладных расходов, что не всегда приемлемо. Поэтому в большинстве ныне существующих
объектно-ориентированных языков программирования используется концепция «отправка сообщения как вызов метода»
— объекты имеют доступные извне методы, вызовами которых и обеспечивается взаимодействие объектов. Данный
подход реализован в огромном количестве языков программирования, в том числе C++, Object Pascal, Java, Oberon-2. В
настоящий момент именно он является наиболее распространённым в объектно-ориентированных языках.
На языке Delphi класс описывается следующим образом:
TMyClass = class(TObject)
private
{Описанные в этой секции элементы не доступны извне (за пределами класса, но доступны в пределах модуля).}
{Здесь обычно находятся поля класса.}
protected
{Описанные в этой секции элементы доступны только классу и всем его потомкам.}
public
{Описанные в этой секции элементы доступны всем.}
published
{Описанные в этой секции элементы доступны всем и отображаются в Object Inspector'e.}
end;
62.
Объектно-ориентированное представление данных: наследование; иерархия классов в системе; методы
и переменные экземпляра для подклассов и суперклассов; создание новых классов и методов; поиск объектом
метода в иерархии.
Наследованием называется возможность порождать один класс от другого с сохранением всех свойств и методов классапредка (прародителя, иногда его называют суперклассом) и добавляя, при необходимости, новые свойства и методы.
Набор классов, связанных отношением наследования, называют иерархией. Наследование призвано отобразить такое
свойство реального мира, как иерархичность.
Простое наследование
Класс, от которого произошло наследование, называется базовым или родительским (англ. base class). Классы, которые
произошли от базового, называются потомками, наследниками или производными классами (англ. derived class).
В некоторых языках используются абстрактные классы. Абстрактный класс — это класс, содержащий хотя бы один
абстрактный метод, он описан в программе, имеет поля, методы и не может использоваться для непосредственного
создания объекта. То есть от абстрактного класса можно только наследовать. Объекты создаются только на основе
производных классов, наследованных от абстрактного. Например, абстрактным классом может быть базовый класс
«сотрудник вуза», от которого наследуются классы «аспирант», «профессор» и т. д. Так как производные классы имеют
общие поля и функции (например, поле «год рождения»), то эти члены класса могут быть описаны в базовом классе. В
программе создаются объекты на основе классов «аспирант», «профессор», но нет смысла создавать объект на основе
класса «сотрудник вуза».
[править]
180
Множественное наследование
Основная статья: Множественное наследование
При множественном наследовании у класса может быть более одного предка. В этом случае класс наследует методы
всех предков. Достоинства такого подхода в большей гибкости. Множественное наследование реализовано в C++. Из
других языков, предоставляющих эту возможность, можно отметить Python и Эйфель. Множественное наследование
поддерживается в языке UML.
Множественное наследование — потенциальный источник ошибок, которые могут возникнуть из-за наличия
одинаковых имен методов в предках. В языках, которые позиционируются как наследники C++ (Java, C# и др.), от
множественного наследования было решено отказаться в пользу интерфейсов. Практически всегда можно обойтись без
использования данного механизма. Однако, если такая необходимость все-таки возникла, то, для разрешения
конфликтов использования наследованных методов с одинаковыми именами, возможно, например, применить операцию
расширения видимости — «::» — для вызова конкретного метода конкретного родителя.
Попытка решения проблемы наличия одинаковых имен методов в предках была предпринята в языке Эйфель, в котором
при описании нового класса необходимо явно указывать импортируемые члены каждого из наследуемых классов и их
именование в дочернем классе.
Большинство современных объектно-ориентированных языков программирования (C#, Java, Delphi и др.) поддерживают
возможность одновременно наследоваться от класса-предка и реализовать методы нескольких интерфейсов одним и тем
же классом. Этот механизм позволяет во многом заменить множественное наследование — методы интерфейсов
необходимо переопределять явно, что исключает ошибки при наследовании функциональности одинаковых методов
различных классов-предков.
Полиморфизмом называют явление, при котором функции (методу) с одним и тем же именем соответствует разный
программный код (полиморфный код) в зависимости от того, объект какого класса используется при вызове данного
метода. Полиморфизм обеспечивается тем, что в классе-потомке изменяют реализацию метода класса-предка с
обязательным сохранением сигнатуры метода. Это обеспечивает сохранение неизменным интерфейса класса-предка и
позволяет осуществить связывание имени метода в коде с разными классами — из объекта какого класса
осуществляется вызов, из того класса и берётся метод с данным именем. Такой механизм называется динамическим (или
поздним) связыванием — в отличие от статического (раннего) связывания, осуществляемого на этапе компиляции.
63.
Объектно-ориентированное проектирование: методика концептуального описания предметной области
и объектная модель задачи; принципы программирования в объектно-ориентированной среде.
Предлагаемая методика системного анализа задачи и построения концептуальной модели предметной
области (КМПО) разработана на основе методов ситуационного управления. Она заключается в анализе по
определенному алгоритму так называемых структур действий, отражающих процессы, происходящие в
рассматриваемой ПО, или возможные в ней решения. В основе методики лежит понимание концептуальной
модели ПО как первой ступени формализации знаний, связанных с задачами в данной ПО, требующими
принятия решений. Знания в КМПО представляются в виде определенной системы понятий, связанных между
собой различными отношениями, – так называемого, понятийного пространства ПО. Анализ и раскрытие
содержания этих понятий и является тем способом приобретения и организации знаний, который позволяет
получить достаточно полную и, в то же время, не избыточную модель, необходимую для дальнейшей
181
формализации.
Понятия в КМПО по своему типу делятся на 4 основные группы:

понятия-объекты, характеризующие объекты, явления и события ПО;

понятия-свойства, характеризующие различные признаки, особенности и свойства объектов, а
также их возможные значения;

понятия-отношения, характеризующие разного рода взаимосвязи и взаимозависимости между
объектами;

понятия-действия, характеризующие различные процессы, протекающие в ПО в разные
моменты времени.
Содержание понятий каждого типа раскрывается по-разному. Под содержанием понятия-объекта
(рис.1.1) понимается:

совокупность его свойств и характерных признаков, важных для описания объекта с точки
зрения решаемой задачи,

набор различных состояний, в которых объект может находиться в процессе выполнения
действий,

множество отношений данного объекта с другими объектами ПО, которые существуют
постоянно или могут возникать во время исполнения моделируемых процессов

иерархия связей данного понятия-объекта с другими понятиями-объектами задачи,
определяющая степень общности его описания.
Рис.1.1. Содержание понятия-объекта
Содержание понятия-свойства (рис.1.2) раскрывается через область его значений, их тип и текущее
значение свойства, а содержание понятия-отношения (рис.1.3) – через совокупность объектов, с которыми это
отношение возможно, и значение его (логическая величина) для этих объектов в текущий момент времени.
Понятие-свойство
Понятие-отношение
Область значений
Объекты отношений
Тип значений
Текущее значение
Текущее значение
Рис.1.2. Содержание
Рис.1.3. Содержание
понятия-свойства
понятия-отношения
Понятие-действие является основным и наиболее сложным понятием КМПО. Его содержание (рис.1.4)
182
раскрывается через описание всех объектов, которые каким-либо образом в нем участвуют, и действий, которые
необходимо выполнить для реализации данного действия. Содержание понятия-действия включает в себя следующее:

указание на субъект действия, т.е. объект, который может выполнять данное действие;

указание на объект действия, т.е. объект, на изменение свойств и/или отношений которых направлено
данное действие;

указание на компоненты действия, т.е. другие объекты ПО, от значения свойств и/или отношений
которых зависит совершение данного действия или значения свойств и/или отношений которых также
изменяются в результате выполнения данного действия;

описание условий совершения действия и его результатов в виде совокупности значений свойств
и/или отношений связанных с ним объектов, т.е. ситуаций предусловия и постусловия данного действия;

описание действий, которые необходимо выполнить для создания условий совершения данного
действия, т.е. поддействий, или действий нижнего уровня, данного действия.
Понятие-действие
Субъекты
Условия
Объекты
Результаты
Компоненты
Поддействия
Рис.1.4. Содержание понятия-действия
На базе основных формируются производные понятия, служащие для более полного описания процессов
и решений данной ПО. К таким понятиям, в первую очередь, относятся понятия-факты и понятия-ситуации.
Под содержанием понятия-факта понимается конкретное значение или некая область значений одного
свойства или отношения объекта. Совокупность всех фактов, связанных с одним объектом, описывает состояние
этого объекта в данный момент времени. Описание состояний всех объектов из КМПО в конкретный момент
времени представляет собой описание всей ситуации в ПО в этот момент, а описание состояний какой-то части
объектов отображает определенный фрагмент этой ситуации. Состояние одного объекта тоже рассматривается
как фрагмент ситуации. Набор соответствующих понятий-фактов составляет содержание понятия-ситуации.
Согласно данной методике, каждое действие описывается через имя и набор объектов: объект, над
которым совершается действие, субъект, который его выполняет, и компоненты – другие объекты, которые в нем
участвуют. Эти объекты определяются множеством свойств и отношений, из которых формируются условия и
результаты данного действия. Все это вместе составляет концептуальную стр уктуру действия, которая изображена
на рис.1.5.
Таким образом, работая по данной методике, студент должен последовательно проанализировать
процессы, происходящие в выбранной им ПО, т.е. все действия, связанные с принятием ею различных решений.
Каждое действие описывается через имя и набор объектов: объект, над которым совершается действие, субъект,
который его выполняет, и компоненты – другие объекты, которые в нем участвуют. В результате формируется
определенное понятийное пространство соответствующей ПО, содержащее пространство объектов и
пространство действий.
183
Субъект
действия
Свойствок
Отн.m
Действие
Ком
Компонент
действия 1
...
понент
Отн.i
Свойствоi
...
Отн.j
действия 2
Объект
действия
Свойствоj
Компонент
действия N
Отн.k
Свойствоm
Свойствоn
Рис.1.5. Концептуальная структура действия
Пространство объектов представляет собой описание объектов задачи через их свойства и отношения, в
которые они могут вступать между собой. Пространство действий отражает содержание всех действий, выполняемых
объектами ПО.
Под содержанием действия при этом понимаются те изменения в значениях свойств и отношений объектов,
которые происходят в результате выполнения данного действия.
Пространство объектов порождает пространство состояний ПО, а пространство действий – пространство
решений, возможных в данной задаче.
Полученное понятийное пространство в дальнейшем может служить основой для более глубокого исследования ПО,
моделирования происходящих в ней процессов, а также для проведения логического вывода и оценки качества принимаемых
решений посредством анализа их воздействия на ПО. В настоящем лабораторном практикуме оно используется для
построения продукционной базы знаний разрабатываемой ЭС.
Таким образом, методика анализа концептуальных структур действий подразумевает выполнение
следующих шагов:
1. Определить действие (процесс), соответствующее постановке задачи (в общем случае таких действий может быть
несколько, тогда они анализируются последовательно).
2. Проанализировать его содержание и условия выполнения, на основе этого определить структуру данного действия
(т.е. выделить субъект действия, объект действия, возможные компоненты действия), свойства соответствующих объектов и
отношения между ними.
3. Проанализировать условия выполнения данного действия и на основе этого определить возможные поддействия
данного действия.
4. Последовательно анализировать поддействия до получения конечных (элементарных) действий.
Следует учесть, что если в структурах действий используются понятия различной степени общности или если объем
каких-либо понятий-объектов больше единицы, то это приводит к необходимости введения во множество действий понятия
выбрать и, соответственно, добавление в модель новых свойств и отношений, описывающих критерии выбора.
Основные принципы ООП:
184
Объектно-ориентированное программирование основано на «трех китах» - трех важнейших принципах, придающих объектам
новые свойства. Этими принципами являются инкапсуляция, наследование и полиморфизм.
Инкапсуляция:
Инкапсуляция есть объединение в единое целое данных и алгоритмов обработки этих данных. В рамках ООП данные
называются полями объекта, а алгоритмы - объектными методами.
Инкапсуляция позволяет в максимальной степени изолировать объект от внешнего окружения. Она существенно повышает
надежность разрабатываемых программ, т.к. локализованные в объекте алгоритмы обмениваются с программой сравнительно
небольшими объемами данных, причем количество и тип этих данных обычно тщательно контролируются. В результате
замена или модификация алгоритмов и данных, инкапсулированных в объект, как правило, не влечет за собой плохо
прослеживаемых последствий для программы в целом (в целях повышения защищенности программ в ООП почти не
используются глобальные переменные). Другим немаловажным следствием инкапсуляции является легкость обмена
объектами, переноса их из одной программы в другую.
Наследование:
Наследование есть свойство объектов порождать своих потомков. Объект-потомок автоматически наследует от родителя все
поля и методы, может дополнять объекты новыми полями и заменять (перекрывать) методы родителя или дополнять их.
Принцип наследования решает проблему модификации свойств объекта и придает ООП в целом исключительную гибкость.
При работе с объектами программист обычно подбирает объект, наиболее близкий по своим свойствам для решения
конкретной задачи, и создает одного или нескольких потомков от него, которые «умеют» делать то, что не реализовано в
родителе.
Последовательное проведение в жизнь принципа «наследуй и изменяй» хорошо согласуется с поэтапным подходом к
разработке крупных программных проектов и во многом стимулирует такой подход.
Полиморфизм:
Полиморфизм - это свойство родственных объектов (т.е. объектов, имеющих одного общего родителя) решать схожие по
смыслу проблемы разными способами. В рамках ООП поведенческие свойства объекта определяются набором входящих в
него методов. Изменяя алгоритм того или иного метода в потомках объекта, программист может придавать этим потомкам
отсутствующие у родителя специфические свойства. Для изменения метода необходимо перекрыть его в потомке, т.е.
объявить в потомке одноименный метод и реализовать в нем нужные действия. В результате в объекте-родителе и объектепотомке будут действовать два одноименных метода, имеющие разную алгоритмическую основу и, следовательно,
придающие объектам разные свойства. Это и называется полиморфизмом объектов.
Базы данных
64.
Трехуровневая архитектура баз данных. Схемы каждого уровня.
В процессе научных исследований, посвященных тому, как именно должна быть устроена СУБД, предлагались различные
способы реализации. Самым жизнеспособным из них оказалась предложенная американским комитетом по стандартизации
ANSI (American National Standards Institute) трехуровневая система организации БД.
Идентификация трех уровней абстракции, т.е. трех различных уровней описания элементов данных. Эти уровни
формируют трехуровневую архитектуру, которая охватывает внешний, концептуальный и внутренний уровни, как показано на
185
рис. Цель трехуровневой архитектуры заключается в отделении пользовательского представления базы данных от ее
физического представления. Ниже перечислено несколь