Статья: О проблеме введения средств распределенного многоагентного программирования в логический язык со строгой типизацией

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

В ходе проверки структурного соответствия перечислений проверяется, что они содержат одинаковый набор элементов.

Следует отметить, что в Акторном Прологе определение типа данных может включать имена других типов данных; в этом заключается принципиальное отличие системы типов Акторного Пролога от аналогичных систем в языках Turbo / Visual Prolog [21]. Например, переменная типа ЧисловойТип, определённого ниже, может содержать как целое, так и вещественное число:

ЧисловойТип

=

INTEGER; REAL.

В общем случае, определение типа в Акторном Прологе может быть рекурсивным и ссылаться на определения других типов данных. Алгоритм структурного сопоставления типов «разматывает» рекурсивные определения типов до получения набора базовых простых и составных типов, литералов и диапазонов, а затем устанавливает парное соответствие между элементами сравниваемых типов данных.

В Акторном Прологе используются три вида базовых составных типов данных: структуры, списки и недоопределённые множества. Все эти три разновидности составных типов несопоставимы друг с другом, в частности, в отличие от стандартного Пролога, списки не являются разновидностью структур.

Определение составного типа «структура» состоит из имени (функтора) и последовательности имён типов аргументов, заключённых в круглые скобки, например:

Дата

=

date(Год,Месяц,Число).

Алгоритм проверки структурного соответствия типов данных «структура» проверяет совпадение функторов, количества аргументов, а также структурное соответствие типов всех аргументов. Равенство имён типов данных при этом, как было указано выше, не требуется.

Определение типа данных «список» включает тип элемента списка и символ «звёздочка», например:

ВажныеДаты

=

Дата*.

В ходе проверки структурного соответствия типов «список» проверяется структурное соответствие типов элементов списков.

Определение типа данных «недоопределённое множество» в Акторном Прологе представляет собой неупорядоченный набор пар «символьное имя: имя типа данных» [1,2], заключённый в фигурные скобки, например:

Дата

=

{год: Год, месяц: Месяц, день: Число}.

Алгоритм структурного сопоставления типов данных «недоопределённое множество» проверяет структурное соответствие типов данных, заданных в соответствующих парах. Проверяется, что типы данных содержат пары с одинаковыми символьными именами, порядок пар при этом не имеет значения.

В Акторном Прологе есть два экзотических типа данных - «анонимный тип данных» (простой тип данных, обозначается с помощью подчерка «_») и «любое недоопределённое множество» (составной тип данных, обозначается «{_}»). Первый используется для описания типов аргументов предикатов, обрабатывающих любые значения, например, процедур печати, а второй для описания типов аргументов предикатов, обрабатывающих любые значения, но только в форме недоопределённых множеств (никаких ограничений на символьные имена пар при этом не накладывается), например, параметры HTTP-запроса:

Параметры_HTTP_запроса

=

{ _ }.

Алгоритм проверки структурного соответствия позволяет поставить в соответствие «анонимному типу данных» только «анонимный тип данных» и типу «любое недоопределённое множество» только тип «любое недоопределённое множество».

Все правила структурного сопоставления типов, описанные выше, в равной степени пригодны как для статической, так и для динамической проверки типов данных. Отличия возникают при рассмотрении типов, содержащих имена классов. В Акторном Прологе в определении типа данных может быть указано имя класса в круглых скобках; это будет означать, что в состав структуры данных может быть включён экземпляр указанного класса. Такой тип данных мы будем называть далее тип данных «мир». Пример определения типа данных «мир»:

ОбработчикЗапросов

=

('МойКласс').

Тип данных «мир» в Акторном Прологе рассматривается как простой тип. Значением типа может быть как простой экземпляр класса, так и параллельный процесс; в определении типа ничего не говорится о том, должен ли экземпляр класса являться процессом или нет. Компилятор простого (не распределённого) Акторного Пролога проверяет, что миры данного типа строго соответствуют указанному классу или принадлежат классу, являющемуся его потомком. В распределённом Акторном Прологе это правило ослаблено.

В распределённом Акторном Прологе компилятор гарантирует, что мир соответствует указанному классу в том и только в том случае, если проверяемый мир создан в той же логической программе (а значит, указанная проверка всегда возможна технически). В случае если проверяемый мир был создан в другой логической программе, проверка не осуществляется. Это означает, например, что экземпляр класса, созданный в другом агенте, может быть присвоен любой переменной, принадлежащей некоторому типу данных, в определении которого указан какой-то произвольный класс.

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

Заметим, что описанная система типов является примером включения в номинативную систему типов элементов структурной системы типов. Кроме того, в язык со статической проверкой типов введены элементы динамической проверки типов. Далее мы будем называть систему типов распределённого Акторного Пролога комбинированной системой типов.

Очевидно, что для реализации описанного алгоритма проверки типов необходима информация о происхождении экземпляров классов. Акторный Пролог поддерживает внутреннюю таблицу экземпляров классов, созданных в ходе выполнения логической программы и переданных вовне. Другая внутренняя таблица содержит все экземпляры классов, полученные тем или иным способом из других логических программ. Эти таблицы позволяют программе различать собственные и «чужие» экземпляры классов и использовать эту информацию в алгоритме структурного сопоставления типов. В частности, логическая программа способна узнать «свой» экземпляр класса, переданный в другую логическую программу и затем полученный обратно. программа язык акторный пролог

3. Пример удалённого вызова предиката

Рассмотрим пример удалённого вызова предиката. Предположим, что существуют два агента, назовём их условно «Распознаватель» и «Наблюдатель», которые должны совместными усилиями осуществлять поиск и распознавание людей в видеопотоке. При этом «Распознаватель» способен идентифицировать людей, находящихся в указанных координатах (возможно, он управляет своей собственной pan-tilt-zoom камерой), а «Наблюдатель» анализирует поведение людей на видео и вычисляет координаты людей, которых необходимо идентифицировать. По условию задачи, агенты являются разными логическими программами. Они должны после начала работы установить связь и обмениваться информацией по мере необходимости.

Начнём с описания агента «Распознаватель». Логическая программа, приведённая ниже, создаёт экземпляр класса и записывает его во внешний файл, так чтобы его могли «увидеть» другие логические программы. Когда какая-то внешняя программа найдёт этот экземпляр класса и передаст в него координаты человека (вызовет в нём метод координаты_человека), программа просто напечатает их на экране.

Согласно семантике Акторного Пролога, исполнение агента «Распознаватель» начинается с создания экземпляра класса 'Main'. Класс 'Main' является потомком предопределённого класса 'Console', реализующего управление текстовым окном.

class 'Main' (specialized 'Console'):

внешний_файл

= ('ОбменДанными');

[

PREDICATES:

координаты_человека(REAL,REAL)

- (i,i);

MODEL:

?координаты_человека(X,Y).

Класс 'Main' содержит один слот внешний_файл, значением которого является экземпляр класса 'ОбменДанными'. С помощью класса 'ОбменДанными' реализован обмен данными через текстовую базу данных - это, пожалуй, самый простой способ управления внешним файлом в Акторном Прологе. В разделе PREDICATES описан один-единственный предикат координаты_человека; у него два входных аргумента вещественного типа. В самом агенте «Распознаватель» этот предикат нигде не вызывается, поэтому в программе пришлось создать раздел MODEL и указать в нём, что предикат координаты_человека, возможно, будет вызван (с указанным количеством аргументов); в противном случае транслятор удалит этот предикат из текста программы в ходе оптимизации исполняемого кода.

CLAUSES:

goal:-!,

внешний_файл ? insert(self),

внешний_файл ? save("g:/РазделяемыеДанные.db"),

writeln("Жду информацию...").

координаты_человека(X,Y):-

writeln("X= ",X," Y= ",Y).

]

В разделе CLAUSES реализованы предикаты goal и координаты_человека. Предикат goal вызывается автоматически при создании экземпляра класса 'Main' в начале работы программы. Он с помощью стандартного предиката insert и ключевого слова self записывает экземпляр класса 'Main' в базу данных внешний_файл, затем с помощью стандартного предиката save записывает эту базу данных в файл «g:/РазделяемыеДанные.db» и выводит на экран надпись «Жду информацию...». Предикат координаты_человека, как уже было сказано, может быть вызван извне. При этом он напечатает на экране полученные координаты X и Y.

В тексте программы «Распознаватель» определён ещё один, вспомогательный, класс 'ОбменДанными'. Этот класс является потомком предопределённого класса 'Database', предназначенного для управления простыми базами данных. В разделе DOMAINS класса определён тип данных со стандартным именем Target. Это необходимо для того, чтобы информировать систему управления базой данных 'ОбменДанными' о типе данных, которые будут в ней храниться. В данном случае объявлено, что тип данных Target включает экземпляры класса 'Main'.

class 'ОбменДанными' (specialized 'Database'):

[

DOMAINS:

Target

= ('Main').

]

Теперь опишем агент «Наблюдатель». Представим, что это логическая программа, которая считывает из внешнего файла экземпляр класса некоторого другого агента (логической программы), которая хотела бы получить координаты человека, отличающегося аномальным поведением, для анализа его изображения и идентификации. Агент «Наблюдатель» посредством удалённого вызова предиката должен послать ему некоторые координаты, после чего вывести на экран сообщение «Информация отправлена...».

Как и в предыдущем случае, исполнение агента «Наблюдатель» начинается с создания экземпляра класса 'Main'. Класс 'Main' в этой логической программе также является потомком предопределённого класса 'Console'. Класс 'Main' также содержит слот внешний_файл, значением которого является экземпляр некоторого класса 'ОбменДанными'. В разделе PREDICATES описан предикат послать_координаты. У предиката послать_координаты один входной аргумент, значением которого должен быть экземпляр класса, наследующего интерфейс 'ПринимающийАгент', описанный далее.

class 'Main' (specialized 'Console'):

внешний_файл

= ('ОбменДанными');

[

PREDICATES:

послать_координаты('ПринимающийАгент')

- (i);

CLAUSES:

goal:-

внешний_файл ? load("g:/РазделяемыеДанные.db"),

внешний_файл ? find(Помощник),!,

послать_координаты(Помощник).

послать_координаты(Помощник):-

Помощник << координаты_человека(125.009,1107.144),

writeln("Информация отправлена...").

]