Вторая попытка

Можно избежать циклических перемещений между Ньюарком и Манхэттеном. Для этого нужно принять, что если имеется прямой маршрут между пунктами А и Б, то не следует искать какие-либо дополнительные ответы. Иными словами, если первое правило процедуры "тснр_путешествовать1" окажется успешным, то предикат "сократить" должен воспрепятствовать переходу ко второму правилу. Позабудем на время об опасностях, связанных с употреблением предиката "сократить", и попытаемся определить, устранит ли наличие этого предиката возникшие циклические перемещения. Новую версию процедуры назовем "тснр_путешествовать2":

% Либо один вид транспорта соединяет пункты А и Б:

тснр_путешествовать2 (А, Б, м (Вид_тр, Б): -

А\==Б,

сим_путешествие (А, Б, Вид_тр),!. % добавлен "! "

% Либо более чем один вид транспорта соединяет А и Б:

тснр_путешествовать2 (А, Б, м (Вид_тр1, В, Вид_тр2)): -

А\==Б,

сим_путешествие (А, В, Вид_тр1),

тснр_путешествовать2 (В, Б, Вид_тр2).

Если "сим_путешествие" и "путешествие" имеют тот же вид, что и в предыдущей программе, то ответ на тот же запрос, что и ранее, будет вполне разумным:

|?— тснр_путешествовать2 (ньюарк, куинс, М).

М = м (автобус, манхэттен, м (жел_дорога, куинс));

нет

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

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

путешествие (манхэттен, ньюарк, автобус).

путешествие (манхэттен, куинс, жел_дорога).

путешествие (ньюарк, бронкс, автомобиль).

путешествие (бронкс, куинс, автобус),

путешествие (манхэттен, бронкс, метро),

путешествие (ньюарк, принстон, автомобиль).

путешествие (манхэттен, принстон, автобус).

Эти факты можно представить графически (см. рис. 4. 5).

Результаты выполнения того же самого запроса к "тснр_путешествовать2" при расширенной базе данных опять обескураживают:

|?— тснр_путешествовать2 (ньюарк, куинс, М).

М = м (автомобиль, брокнс, м (автобус, куинс));

М=м (автомобиль, принстон, м (автомобиль, ньюарк,

м (автомобиль, брокнс, м (автобус, куинс))));

М=м (автомобиль, принстон, м (автомобиль, ньюарк,

м (автомобиль, принстон, м (автомобиль, ньюарк,

м (автомобиль, бронкс, м (автобус, куинс))))));

Добавление предиката "сократить", как кажется, позволило устранить циклические перемещения только для случая, когда в базе данных "путешествие" было всего два факта. Помимо этого, предикат "сократить" представляет опасность и в том отношении, что при его использовании могут быть отброшены и правильные ответы. Если бы между двумя пунктами курсировал более чем один вид транспорта, то процедура "тснр-путешествовать2" смогла бы найти лишь первый из них. Множество ответов также является неполным. Поскольку процедура "тснр_путешествовать2" стала циклически перемещаться между Ньюарком и Принстоном, она никогда не дойдет до более удобного маршрута из Ньюарка в Куинс через Манхэттен.

Опять-таки данные обладают цикличностью, и запрос "вязнет" в одном из циклов. Существуют два способа борьбы с таким поведением программы: либо тщательно проверить все данные на отсутствие циклов, либо сделать программу нечувствительной к цикличности данных. Второй способ предпочтителен по ряду практических соображений. В данном случае нужно сделать так, чтобы процедура "тснр_путешествовать" не возвращалась в то место, где она уже побывала.

Соседние файлы в папке Гл.0,1,2,3,4,5,Предисловие