Параллельное и распределенное программирование на С++ - Хьюз Камерон
Шрифт:
Интервал:
Закладка:
// Листинг 12.11. Класс performance_statement
bool performance_statement::operator()(void) {
bool Satisfactory = false;
list<performance_statement>::iterator I;
I = UniverseOfDiscourse.begin();
while(I != UniverseOfDiscourse.end() && !Satisfactory) {
if(((*I).bays() >= Bays) || ((*I).sales() >= Sales)
|| ((*I).perHour() >=PerHour)){ Satisfactory = true;
}
I++;
}
return(Satisfactory);
}
Оператор operator () для каждого класса proposition играет «свою» роль в способности класса агента делать логические выводы. В листинге 12.6 показано, как вызывается оператор operator () при каждом вычислении оператора " || " или "&&" для класса proposition или для одного из его потомков. Именно такое сочетание методов operator (), определенных в proposition-классах, и методов класса agent образует стратегии логического вывода для класса agent. В дополнение к операторам "||" и "&&", определенным в классе proposition, классы trip_announcement и performance_statement содержат свои определения.
friend bool operator||(bool X,trip_announcement &Y); friend bool operator&&(bool X,trip_announcement &Y);
Эти friend -объявления позволяют использовать предположения в более длинных выражениях. Сделаем следующие объявления.
//. . .
trip_announcement А, В, С; bool X;
X = А || В || С;
//.. .
При этом объекты А и В будут объединены с помощью операции ИЛИ, а результат этой операции будет иметь тип bool. Затем мы попробуем с помощью той же операции ИЛИ получить значение типа bool и объект типа trip_announcement: bool || trip_announcement
Без приведенных выше friend -объявлений такая операция была бы недопустимой. Определение этих функций-«друзей» показано влистинге 12.12.
// Листинг 12.12. Перегрузка операторов "||" и "&&"
bool operator||(bool X,trip_announcement &Y) {
return(X | | YO) ;
}
bool operator&&(bool X,trip_announcement &Y) {
return(X && Y());
}
Обратите внимание на то, что в определении этих функций-«друзей» (благодаря ссылке на элемент Y ()) также используется вызов функции operator (). Эти функции определяются и в классе performance_statement. Наша задача — сделать использование proposition-классов таким же простым, как использование встроенных типов данных. В классе proposition также определен другой оператор, который позволяет использовать предположение естественным образом. Рассмотрим следующий код.
//.. .
trip_announcement А; if(A) {
//... Некоторые действия.
}
//.. .
Как в этом случае компилятор тестирует объект А? При выполнении инструкции if () компилятор стремится найти в скобках значение целочисленного типа данных или типа bool. Но тип объекта А совсем другой. Мы хотим, чтобы ко м пилятор восприни м ал объект А как высказывание, которое м ожет быть либо истинны м, либо ложны м. При таких обстоятельствах функция operator () не вызывается. Поэто м у для получения нужного эффекта м ы определяем оператор void*. Эту функцию-оператор можно определить следующим образом.
template<class C> proposition<C>::operator void*(void) {
return((void*)(TruthValue));
}
Это определение позволяет предположение любого типа, представленное «в единственном числе», протестировать как значение истинности. Например, когда наш класс agent собирается отправить по электронной почте владельцу фирмы сообщение, содержащее путь следования, агенту нужно определить, какой маршрут отвечает заданным требованиям. В листинге 12.13 представлен еще один фрагмент из методов обработки автобусных маршрутов.
// Листинг 12.13. Метод displayTravelPlan()
void agent::displayTravelPlan(void) {
stack<trip_announcement> Route;
if(Tripl){
Route = Tripl.candidates();
}
if(Trip2){
Route = Trip2.candidates();
}
if(Trip3){
Route = Trip3.candidates();
}
while(!Route.empty()) {
cout << Route.top().origin() << " TO "« Route.top().destination() « endl; Route.pop();
}
Обратите внимание на то, что объекты Tripl, Trip2 и Trip3 тестируются так, как будто они имеют тип bool. Метод candidates () просто возвращает путь следования, соответствующий заданному маршруту. Таким образом, разработка стратегий логического вывода и когнитивных структур данных становится проще благодаря использованию перегрузки операторов и С++-шаблонов. Именно стратегии логического вывода и когнитивные структуры данных делают объект рациональным. C++-программист для разработки агентов использует конструкцию класса, а для реализации когнитивных сгруктур данных (CDS) — контейнерные объекты в сочетании со встроенными алгоритмами. Класс, который содержит CDS-структуры, становится рациональным, а рациональный класс — агентом.
Простая автономность
Поскольку наш простой класс агента не требует выполнения традиционного «цикла активизации», нам нужны другие средства, которые бы периодически активизировали агент без вмешательства человека. Возможны ситуации, когда агент нужно запускать на выполнение лишь иногда или только при определенных условиях. Среды UNIX/Linux оснащены утилитой crontab, которая представляет собой пользовательский интерфейс «хрон-систе м ы» (xpon— это де м он ОС UNIX, исполняющий предписанные команды в соответствии со строго определенными значениями даты и времени, указанными в спе циально м файле с именем crontab). Утилита crontab позволяет организовать периодическое выполнение одной или нескольких программ. Задания для утилиты crontab можно назначать с указанием месяца, дня недели, дня (месяца), часов и минут. Для использования утилиты crontab в нашем случае необходимо создать текстовый файл, который будет содержать график активизации агента. Записи этого файла должны иметь следующий формат:
м инуты часы день м есяц день недели ко м анда
Каждый эле м ент записи м ожет прини м ать следую щ ие значения:
минуты 0-59
часы 0-23
день 1-31
месяц 1-12
день недели 1-7 (1 — понедельник, 7 — воскресенье)
команда может быть любой UNIX/Linux-командой, а также именем файла,
который содержит агенты
Созданный в таком формате текстовый файл передается «хрон-системе» с помощью слелующей команды:
$crontab NameOfCronFile
Например, предположи м, у нас есть файл activate.agent, содержи м ое которо г о и м еет такой вид.
15 8 * * * agentl
0 21 * * 6 agent2
* * 1 12 * agent3
После выпол н ения crontab-ко м анды $crontab activate.agent
агент agentl будет активизироваться каждый день в 8:15, агент agent2 — каждое воскресенье в 21:00, а агент agent3— каждый раз при наступлении первого декабря. Хрон-файлы можно при необходимости добавлять или удалять. Хрон-файлы могут содержать ссылки на другие хрон-задания, позволяя таким образом агенту «самому» перепланировать свою работу. Так, для обеспечения чрезвычайно гибкой, динамичной и надежной процедуры активизации агентов можно использовать сценарии оболочки в сочетании с утилитой crontab. Чтобы получить полное описание утилиты crontab, обратитесь к оперативным страницам руководства (manpages— г ипертекстовые страницы консультативной инфор м ации, поясняю щ ие действие конкретных ко м анд): $man crontab или $man at