Гради Буч - Объектно-ориентированный анализ и проектирование с примерами приложений на С++ (1158635), страница 84
Текст из файла (страница 84)
В частности, нам потребуется ввести в класс следующийзащищенный объект:UnboundedOrderedCollection<Assumption*> statements;Этот объект также позаимствован нами из библиотекифундаментальных классов главы 9.Теперь обратимся к классу Alphabet (алфавит). Он содержит данныеоб алфавитах исходного текста и шифра, а также о соответствии между ними.Эта информация необходима для того, чтобы источники знаний могли узнатьо выявленных соответствиях между буквами шифра и текста и тех, которыееще предстоит найти.
Например, если уже доказано, что буква с а шифресоответствует букве и исходного текста, то это соответствие фиксируется валфавите и источники знаний уже не будут делать других предположений вотношении буквы м исходного текста. Для эффективности обработки полезнополучать данные о соответствии букв шифра и текста двумя способами: побукве шифра и по букве исходного текста. Определим класс Alphabetследующим образом:class Alphabet : public BlackboardObject {public:char plaintext (char) const;char ciphertext(char) const;int isBound(char) const;};Так же, как и в класс CipherLetter, в класс Alphabet необходимовключить защищенный объект affirmations и определить операции доступак его состоянию.Наконец, определим класс Blackboard, который является коллекциейэкземпляров класса Blackboardobject и его подклассов:class Blackboard : public DynamicCollection<BlackboardObject*>...Поскольку доска есть разновидность коллекции (тест нанаследование), мы предпочитаем образовать этот класс методомнаследования, а не с помощью включения экземпляра классаDynamicCollectlon.
Операции включения в коллекцию и исключения из неенаследуются от класса Collection, а следующие пять операций,специфичных для информационной доски, вводятся нами:Очистить доску•resetПоместить на доске начальные условия задачи•assertProblemПодключить к доске источник знании•connectИстинно, если предложение расшифровано•issolved•retriaveSolution Значение расшифрованного текстаВторая операция устанавливает зависимость между доской иисточником знании. На рис.
11-3 приведена итоговая диаграмма классов,связанных с Blackboard. Она в первую очередь отражает отношениянаследования. Отношения использования (например, между Assumption иинформационной доской) для простоты опушены.Рис. 11-3. Диаграмма классов информационной доскиОбратите внимание на то, что класс Blackboard одновременно иинстанциру-ет от шаблона DynamicCollection, и наследует от него. Крометого, становится понятным использование класса Dependent в качествепримеси.
Не привязывая этот класс жестко к иерархии Blackboard, мыповышаем шансы на его последующее повторное использование.Проектирование источников знанийВ предыдущем разделе мы выделили тринадцать источников знаний,относящихся к решаемой задаче. Теперь можно приступить к проектированиюструктур классов для них (как это было сделано для информационной доски) иобобщению их в более абстрактные классы.Проектирование специализированных источников знаний.Предположим, что существует абстрактный класс KnowledgeSource (поаналогии с классом BlackboardObject). Прежде чем определять всетринадцать источников в качестве подклассов одного общего суперкласса,нужно посмотреть, не группируются ли они каким-нибудь образом.Действительно, такие группы находятся: некоторые источники знанийоперируют целым предложением, другие - словами, фрагментами слов илиотдельными буквами.
Отразим этот факт в следующих определениях:class SentenceKnowledgeSource : public KnowledgeSource ...class WordKnowledgeSource : public KnowledgeSource ...class LetterKnowledgeSource : public KnowledgeSource ...Для каждого из этих абстрактных классов в дальнейшем мы определимспециализированные подклассы. Для класса SentenceKnowledgeSource онибудут выглядеть следующим образом:class SentenceStructureKnowledgeSource : publicSentenceKnowledgeSource ...class SolvedKnowledgeSource : publicSentenceKnowledgeSource ...Аналогично, подклассы класса WordKnowledgeSource определяютсятак:class wordStructureKnowledgeSource : publicWordKnowledgeSource ...class SmallWordKnowledgeSource : public WordKnowledgeSource...class pattemMatchingKnowledgeSource : publicWordKnowledgeSource ...Последний класс требует некоторых пояснений.
Ранее упоминалось,что его цель состоит в нахождении слов по шаблону. Для описания шаблонаможно воспользоваться системой записи регулярных выражении, принятой, вчастности, в утилите grep системы UNIX:•Любой элемент?•Не элемент~•Несколько элементов*•Начало группы{•Конец группы}Используя такие обозначения, мы можем передать объекту этогокласса шаблон ?Е~{А Е I O U}, чтобы он искал в своем словаре слово изтрех букв, начинающееся с некоторой буквы, после которой идет Е, а затем любая буква кроме гласной.Поскольку проверка по шаблону является методом, полезным как дляданной системы в целом, так и в других областях, соответствующий классцелесообразно выделить в качестве самостоятельной абстракции.
Поэтомунеудивительно, что мы воспользуемся классом из нашей библиотеки (см.главу 9). В результате наш класс для проверки по шаблону будет выглядетьследующим образом:class PatternMatchingKnowledgeSource : publicWordKnowledgeSource { public:...protected:static BoundedCollection<Word*> words;REPattemMatching pattemMatcher;};Все экземпляры этого класса разделяют общий словарь, но каждый изних может иметь собственного агента для сравнения с шаблонами.На данном этапе проектирования подробности реализации этогокласса для нас не существенны, поэтому мы не будем на них подробноостанавливаться.Определим теперь подклассы класса stringKnowledgeSourceследующим образом:class CoinmonPrefixKnowledgeSource : publicStringKnowledgesource ...class ConunonSuffixKnowledgeSource : publicStringKnowledgesource ...class DoubleLetterKnowledgeSource : publicStringKnowledgesource ...class LegalStringKnowledgeSource : publicStringKnowledgesource ...Наконец, определим подклассы класса LetterKnowledgeSource:class DirectSubstitutionKnowledgeSource : publicLetterKnowledgeSource ...class VowelKnowledgeSource : publicLetterKnowledgeSource ...class ConsonantKnowledgeSource : publicLetterKnowledgeSource ...class LetterPrequencyKnowledgeSource : publicLetterKnowledgeSource ...Общее в источниках знаний.
Анализ показал, что только две операцииопределены для всех упомянутых специализированных классов:•ResetПерезапуск источника знаний.Определение состояния информационной доски.•evaluateПричина упрощения интерфейса - в относительной автономностизнаний: мы указываем на интересующий объект информационной доски идаем источнику команду применить его правила, учитывая глобальноесостояние доски. При выполнении правил каждый из источников знанийможет осуществлять следующие действия:•Высказать предположение о подстановке.•Найти противоречие в ранее предложенных подстановках и откатитьих.•Высказать утверждение о подстановке.•Сообщить контроллеру о своем желании записать на доску что-тоинтересное.Все эти действия являются общими для всех источников знаний.Перечисленные операции образуют механизм вывода заключений.
Определиммеханизм вывода (InferenceEngine) как объект, который выполняетизвестные правила для того, чтобы либо найти новые правила (прямаяпоследовательность рассуждений), либо Доказать некоторую гипотезу(обратная последовательность рассуждений). На основании сказанного введемследующий класс:class InferenceEngine ( public:InferenceEngine<DynamicSet<Rules*>};...};Конструктор класса создает экземпляр объекта и населяет егоправилами. Лишь одна операция сделана в этом классе видимой дляисточников знании:•evaluateВыполнить правило механизма вывода.Теперь о том, как сотрудничают источники знаний: каждыйспециализированный источник определяет свои собственные правила ивозлагает ответственность за их выполнение на класс InferenceEngine.Точнее, операция KnowledgeSource::evaluate вызывает методInferenceEngine::evaluate, что приводит к выполнению одной из четырехупомянутых выше операций.
На рис. 11-4 показан сценарий такоговзаимодействия:Рис. 11-4. Взаимодействия с источником знанийЧто такое правило? Для иллюстрации приведем (в формате Lisp)правило, касающееся знаний об общеупотребительных суффиксах:((* I ? ?)(* I N G)(* I E S)(* I E D))Это правило означает, что заданному шаблону *I?? (условие antecedent) могут соответствовать суффиксы ING, IES и IED (заключение consequent). В C++ можно определить следующий класс для представленияправил:class Rule{ public:…int bind(String<char>& antecedent, String<char>&consequent);intremove(Strlng<char>& antecedent);intremove(String<char>t antecedent, String<char>&conseiruent);inthasConflict(const String<char>& antecedent)const;protected:String<char> antecedent;List<String<char> > consequents;};Смысл приведенных операций полностью понятен из ихнаименований.
Мы здесь повторно использовали некоторые классы из главы9.С точки зрения строения данного класса можно утверждать, чтоисточники знаний являются разновидностью механизма вывода. Кроме того,они ассоциированы с объектами доски, поскольку находят там приложениесвоим усилиям. Наконец, каждый источник знаний связан с контроллером ипосылает ему свои соображения. Контроллер, в свою очередь, можетактивизировать источники знаний.Выразим все сказанное следующим образом:class KnowledgeSource :public InferenceEngine,public Dependent (public:KnowledgeSource(Blackboard*, Controller*);void reset() ;void evaluate {) ;protected:Blackboard* blackboard;Controller* controller;UnboundedOrderedCollection<Assumption*> pastAssumptions;};В этот класс введен защищенный элемент данных pastAssumptions,позволяющий сохранять всю историю предположений в целях самообучения.Экземпляры класса Blackboard служат для хранения объектовинформационной доски.