Скачиваний:
34
Добавлен:
01.05.2014
Размер:
668.16 Кб
Скачать

Данные и предложения для тестирования

test_lee(Name,Path) 

data(Name,A,B, Obstacles).

lee_route(A,B,Obstacles,Path).

data(test, 1 - 1,5 - 5, [obstacles(2 - 3,4 - 5), obstacles(6 - 6,8 - 8)]),

Программа 17.6.Программа трассировки по алгоритму Ли.

тельные волны - это множества точек сетки, соседние с точками предыдущей волны и не попавшие в предыдущие волны. Это определение иллюстрируется изображе­нием волн на рис. 17.3тонкими сплошными линиями.

Генерация волн осуществляется с помощью предиката waves (В,WavesSoFar, Waves),который определяет список волн Waves,достигнувших конечной точкиВ. Параметр WavesSoFar -накопитель волн, образованных с начала их генерации от исходной точки к текущему шагу. Вычисления по этому предикату завершаются, когда текущая волна накроет конечную точку. В теле предложения wavesиспользуется предикат next_wave,в котором для поиска соответствующих точек сетки применены множественные выражения.

Предполагается, что препятствия являются прямоугольными блоками. Для их представления используется терм obstacle (L,R),где L-координаты левого нижнего угла, R-координаты правого верхнего угла блока. В упражнении к этому разделу предлагается изменить программу так, чтобы она допускала обработку препятствий другой формы.

Предикат find_path(А,В,Waves,Path)используется для нахождения обратного пути PathизВвАпо сгенерированным ранее волнам. При построении пути производится спуск вниз в соответствии с порядком точек отВкА.Этот порядок можно изменить, используя в предикате find_pathнакопитель.

В процессе нахождения пути по алгоритму Ли вывод даных в программе 17.6не предусмотрен. На практике пользователь может пожелать увидеть результаты текущих вычислений. Это легко осуществить добавлением соответствующих операторов writeв процедуры next_waveи find_path.

В последнем примере этого раздела решается задача поиска ключевых слов в контексте. И вновь объединение недетерминированного программирования с программированием второго порядка позволяет с помощью простой Пролог-программы решить сложную задачу.

Нахождение ключевых слов в контексте связано с поиском всех вхождений множества ключевых слов в определенный текст и выделением контекстов, в которых они встречаются. Здесь будет рассмотрен следующий вариант этой общей задачи: «Для данного списка заголовков сформировать упорядоченный список всех вхождений в данные заголовки множества ключевых слов вместе с их контекстами».

Пример входных и ожидаемых выходных данных для такой программы представлен на рис. 17.4.Контекст описывается как вращение заголовка, конец которого отмечен вертикальной чертой «|».В рассматриваемом примере использован следующий набор «нетривиальных» ключевых слов: algorithmic, debugging, logic, problem, program, programming, prologи solving.

В данной задаче подлежит вычислению отношение k^-ic(Titles,KmcTil1es},гдеTub's-список заголовков, из которых должны быть выделены ключевые слова, а

Вход: programming in prolog logic for problem solving logic programming algorithmic program debugging

Выход: algorithmic program debugging |, debugging | algorithmic program, logic for problem solving |, logic programming, |, problem solving | logic for, program debugging | algorithmic, programming in prolog |. programming | logic, prolog | programming in, solving | logic for problem

Рис17.4.Вход и выход для задачи поиска вхождений ключевых слов в контексте.

КwicTitles-отсортированный список ключевых слов в их контекстах. Предполагается, что входной и выходной тексты представлены в виде списков слов. В более общей программе должны быть предусмотрены предварительный шаг преобразования входного текста в свободной форме в списки слов, а также выдача результатов в удобном для чтения виде.

Рассмотрим поэтапное представление программы. Основа программы - недетерминированное описание вращения списка слов. С помощью предиката appendему можно дать следующее элегантное определение:

rotate(Xs,Ys)  append(As,Bs,Xs). append! Bs,As.Ys),

Декларативно: Ys - вращение Xs,если Xsсостоит из As,за которым следует Bs,аYs состоит из Bs,за которым следует As.

Следующий этап связан с идентификацией отдельных слов как потенциальных ключевых слов. Это выполняется посредством выбора слова в первом вызове предиката append.Отметим, что следующее новое правило является примером предыдущего правила rotate:

rotate(Xs,Ys)  append(As.[Key | Bs],Xs), append([Key | Bs].As,Ys).

Кроме того, это определение лучше предыдущего, поскольку в нем предусмотрено удаление одинаковых решений, когда один из расщепленных списков пуст, а другой -полон.

Следующее улучшение связано с более детальной проверкой потенциального ключевого слова. Предположим, что каждое ключевое слово Wordопределяется фактом вида keyword(Word).Решения в процессе rotateмогут быть отфильтрованы так, чтобы воспринимались только те слова, которые идентифицированы как ключевые. Соответствующая версия рассматриваемого предложения имеет вид

rotate_and_filter(Xs,Ys) 

append(As,[Key| Bs],Xs), keyword(Key), append([Key | Bs],As,Ys).

Операционное поведение данной процедуры: она рассматривает все ключевые слова, отфильтровывая нежелательные альтернативы. Для максимизации эффективности программы в данном случае важен порядок целей.

В программе 17.7,окончательной версии интересующей нас программы, предусмотрены дополнительные средства для распознавания ключевых слов. Любое слово Wordсчитается ключевым, если оно не специфицировано с помощью факта вида insignificant(Word) какнезначащее. Кроме того, в процедуре выполняется вставка в конец заголовка маркера «|»,отмечающего контекстную информацию. Это реализуется добавлением дополнительного символа во втором обращении к предикату append.Соответствующее предложение rotate_and_filterсодержится в программе 17.7.

Наконец, для получения всех решений использован множественный предикат. Квантификация необходима ло всем возможным заголовкам. Явным преиму-

kwic(Tites,КWTitles) 

КWTities-KWIC-инлскссписка заголовков Titles.

kwic(Titles.KWTilles)

set_of(Ys,Xs  (member(Xs, Titles),

rotate_and_fiIter(Xs,Ys)),KWTitles).

rotate_and_filter(Xs, Ys) 

Ys-вращение списка Xs,такое, что первое слово Ys значимо, и знак '|' вставлен после последнего слова Xs.

rotate_and_filter(Xs,Ys) 

append (As, [Key | Bs],Xs),

not insignificant(Key),

append([Key,’|’ | Bs],As,Ys).

Соседние файлы в папке prolog14_end