НОВОСТИ   БИБЛИОТЕКА   ЮМОР   КАРТА САЙТА   ССЫЛКИ   О САЙТЕ  




предыдущая главасодержаниеследующая глава

3.6. Увеличение скорости и эффективности программ

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

  1. При определении возраста частота применения тех или иных правил зависит от того, чей возраст определяется.
  2. Последовательность размещения выводимых на печать результатов не совпадает с последовательностью размещения информации в базе данных.
  3. Последовательность размещения результатов может измениться, если изменится текущая дата. Проверить это достаточно просто; для этого необходимо следующим образом выбирать текущую дату: сначала она должна предшествовать дате какого-нибудь дня рождения, затем совпадать с ней и, наконец, следовать за ней. Но учтите, что в каждый момент времени в базе данных должна находиться только одна дата.
  4. Последовательность размещения результатов изменится, если поменять местами первое и второе утверждения отношения age.

Значительно большими диагностическими возможностями обладают специальные программы трассировки, входящие в состав системы программирования мицроПролог. Максимально возможную информацию обеспечивает, например, программа SIMTRACE. Поскольку для этой программы требуется довольно много памяти, перед ее использованием удалите из памяти все, что там было, и введите программу, приведенную ниже.

Betty born (3 5 1950)

Joe born (23 9 1917)

Вill born (22 9 1943)

Isabel born (21 9 1942)

X age Y if

X born (Z x y) and

date now (z X1 Y1) and

(either x LESS X1 and / or x leq X1 and Z leq z) and

SUM (Y у Y1)

X age Y if

X born (Z x y) and

date now (z X1 Y1) and

(either X1 LESS x and / or X1 leq x and z LESS Z) and

SUM(ZyY1)and

SUM(Y1Z1)

X leq X

X leq Y if

X LESS Y date now (22 9 1985)

Тестовый запрос для этой программы и ответы на него будут выглядеть так:

all (x у: х age у)

Betty 35

Bill 42

Isabel 45

Joe 67

No (more) answers

Даты рождения людей выбраны таким образом, чтобы они не посредственно предшествовали и следовали за текущей датой - (22 9 1985). Это будет гарантировать участие в обработке запроса всех правил. После того как у Вас появилась уверенность в правильности программы, удалите из памяти модули program-mod и errmess-mod с помощью команды KILL. Затем используйте команду LOAD для того, чтобы загрузить на свободное место программу трассировки SIMTRACE. В том случае, если памяти все же окажется недостаточно, попробуйте удалить из модуля query-mod любые из следующих отношений: which, all, one, is, lood, save, +, -, %, @, *, CONS, reserved, true-of и defined.

Естественно, после этого использовать в запросах те отношения, которые Вы удалили, будет нельзя. Для того чтобы получить полную информацию о процессе обработки запроса, введите

all-trace (x у: х age у)

Ниже приведен протокол диалога между пользователем и ЭВМ:

& all-trace (x yi x age у)

[& полная трассировка (х у: х имеет возраст у)

(1): X age Y trace ? у

[(1): X имеет возраст Y трассировка ? да]

matching (1) : X age Y with head of 1:Z age x

[сопоставление (1) i X имеет возраст Y с головой правила 1:Z имеет возраст x]

match succeeds i X age Y

[сопоставление завершено успешно :X имеет возраст Y]

new query :X born (Y Z x) and date now (y z X1) and

[новый запрос :X родился (Y Z x) и текущая дата (у z X1) и]

(either Z LESS z and/or Z leq z and Y leq y) and SUM (Y1 x X1)

[(либо Z LESS z and/либо Z меньше или равно z и Y меньше или равно у) и SUM (Y1 x X1)]

(1 1) X born (Y Z x) trace ? у

[(1 1) X родился (Y Z x) трассировка ? да]

matching (1 1) : X born (Y Z x) with head of 1 i Betty born (3 5 1950)

[сопоставление (1 1) : X родился (Y Z x) e головой правила 1 ? Бетти родилась (3 5 1950)]

match succeeds : Betty born (3 5 1950)

[сопоставление успешно завершено : Бетти родилась (3 5 1950)]

(1 1) solved : Betty born (3 5 1950)

[(1 1) результат сопоставления : Бетти родилась (3 5 1950)]

(2 1) : date now (X Y Z) trace ? у

[(2 1) : текущая дата (X Y Z) трассировка? да]

matching (2 1) : data now (X Y Z) with head of 1 : date now (22 9 1985)

[сопоставление (2 1) : текущая дата (X Y Z) с головой правила 1 : текущая дата (22 9 1985)]

match succeds : date now (22 9 1985)

[сопоставление успешно завершено : текущая дата (22 9 1985)]

(2 1) solved : date now (22 9 1985)

[(2 1) результат сопоставления : текущая дата (22 9 1985)]

(3 1) : (either 5 LESS 9 and/or 5 leq 9 and 3 leq 22) trace ? у

[(3 1) : (либо 5 LESS 9 и/либо 5 меньше или равно 9 и 3 меньше или равно 22) трассировка ? да]

(3 1) either branch

[(3 1) ветвление либо-либо]

(1 3 1) : 5 LESS 9

[(1 3 1) : 5 LESS 9]

(1 3 1) solved : 5 LESS 9

[(1 3 1) результат сопоставления : 5 LESS 9]

(231):/

[(2 3 1) :/]

(2 3 1) solved : /

[(2 3 1) результат сопоставления : /]

(3 1) solved : (either 5 LESS 9 and/or 5 leq 9 and 3 leq 22)

[(3 1) результат сопоставления : (либо 5 LESS 9 и/либо 5 меньше или равно 9 и 3 меньше или равно 22)]

(4 1) : SUM (X 1950 1985)

[(4 1) : SUM (X 1950 1985)]

(4 1) solved : SUM (35 1950 1985)

[(4 1) результат сопоставления : SUM (35 1950 1985)]

(1 1) solved : Betty age 35

[(1 1) результат сопоставления i возраст Бетти - 35]

Betty 35

[Бетти 35]

backtracking ...

[возврат для поиска альтернативных вариантов ...]

(4 1) failing : SUM (X 1950 1985)

[(4 1) неудача : SUM (X 1950 1985)]

(3 1) failing : (either 5 LESS 9 and/or 5 leq 9 and 3 leq 22)

[(3 1) неудача : (либо 5 LESS 9 и/либо 5 меньше или равно 9 и 3 меньше или равно 22)]

retrying (2 1)

[снова попробовать (2 1)]

(2 1) failing: date now (X Y Z)

[(2 1) неудача : текущая дата (X Y Z)]

retrying (1 1)

[снова попробовать (1 1)]

matching (1 1) : X born (Y Z x) with head of 2 : Joe born (23 9 1917)

[сопоставление (1 1) : X родился (Y Z x) с головой правила 2 : Джо родился (23 9 1917)]

match succeeds : Joe born (23 9 1917)

[сопоставление, успешно завершено: Джо родился (23 9 1917)]

(1 1) solved: Joe born (23 9 1917)

[(1 1) результат сопоставления : Джо родился (23 9 1917)]

(2 1) date now (X Y Z) trace?

[(2 1) : текущая дата (X Y Z) трассировка?]

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

Используемые во время трассировки утверждения и условия -помечаются номерами, заключенными в скобки. Например, (1 1) - первое утверждение в первом условии, (2 1) - второе утверждение в первом условии и т. д. Для предложений сложной структуры потребуется более двух номеров. Например, (1 3 1) - первая часть третьего утверждения в первом условии; в данном случае такой номер появляется, когда анализируется конструкция (either ... or...).

В результате проверки каждого условия формируется сообщение либо об успехе, либо о неудаче. В случае успеха решения помещаются в стек. Если весь процесс обработки запроса завершается успешно, программа выдает ответ и, используя механизм возврата, приступает к поиску альтернативных решений. В случае неудачи при проверке какого-то условия весь процесс только тогда считается неудачным, когда нет альтернативного варианта, задаваемого конструкцией (either ... or ). Управление возвратом с помощью правильно сконструированных определений отношений и запросов позволяет программисту в ряде случаев значительно увеличить эффективность работы программы.

В нашем примере возврат для поиска альтернативных вариантов осуществляется в следующих случаях.

(4 1). Здесь поиск альтернатив для SUM (X 1950 1985) сразу же заканчивается неудачей, поскольку существует единственное значение X, для которого справедливо

X + 1950 = 1985.

(2 1). Здесь производится попытка найти отличный от (22 9 1985) список (X Y Z), который содержится в предложении вида

date now (X Y Z)

Эта попытка также заканчивается неудачей, так как такой список только один - (22 9 1985). Но если было бы введено несколько предложений, определяющих отношение date now, то все они использовались бы для поиска решений, связанных с определением возраста Бетти.

(3 1). Здесь ищется альтернативное решение для первой части конструкции (either ... or...).

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

date now (X Y Z)

с соответствующим предложением программы и постоянно используется возврат для поиска альтернативных дат, которых заведомо нет. Это в принципе не слишком опасно, поскольку приводит к неудаче только один раз. Гораздо серьезнее следует относиться к возврату, который возникает в тех случаях, когда часть проверяемых условий удовлетворяется*. Отметим желательность выполнения какой-то операции, позволяющей программе оптимально организовывать доступ к текущей дате.

* (Или, что то же самое, часть подцелей удается сопоставить с утверждениями программы.- Прим. пер.)

Если проследить за работой программы в процессе определения возврата Джо с помощью первого правила отношения age, то можно увидеть причины, порождающие значительно большую неэффективность. Все в принципе хорошо до тех пор, пока не достигается условие (either ... or...). Процесс обработки запроса после достижения этого условия показан ниже:

(3 1): either branch

[(3 1) ветвление либо-либо]

(1 3 1) : 9 LESS 9

[(1 3 1) :9 LESS 9]

(1 3 1): failing : 9 LESS 9

[(1 3 1) : неудача : 9 LESS 9]

(3 1) : or branch

[(3 1) : ветвление или]

(1 3 1) : 9 leq 9 trace ? у

[(1 3 1) J 9 меньше или равно 9 трассировка ? да]

matching (1 3 1) : 9 leq 9 with head of 1 : X leq X

[сопоставление (1 3 1) : 9 меньше или равно 9 с головой правила 1 : X leq X ]

(1 3 1) solved : 9 leq 9

[(1 3 1) результат сопоставления: 9 меньше или равно 9]

(2 3 1) : 23 leq 22 trace ? у

[(2 3 1) ! 23 меньше или равно 22 трассировка ? да]

matching (2 3 1): 23 leq 22 with head of 1 : X leq X

[сопоставление (2 3 1) : 23 меньше или равно 22 с головой гравила 1 : X меньше или равно X]

match fails

[сопоставление оканчивается неудачей]

matching (2 3 1): 23 leq 22 with head of 2 : X leq Y

[сопоставление (2 3 1) : 23 меньше или равно 22 с головой [правила 2 : X меньше или равно Y]

match succeeds 23 leq 22

[сопоставление успешно завершено : 23 leq 22]

new query : 23 LESS 22

[новый запрос : 23 LESS 22]

(1 2 3 1) : 23 LESS 22

[(1 2 3 1) : 23 LESS 22]

(1 2 3 1) fails : 23 LESS 22

[(1 2 3 1) неудача : 23 LESS 22]

retrying (2 3 1)

[снова попробовать (2 3 1)]

(2 3 1) failing : 23 leq 22

[(2 3 1) неудача : 23 меньше или равно 22]

retrying (1 3 1) : 9 leq 9 with head of 2 : X leq Y

[снова попробовать (1 3 1) : 9 меньше или равно 9 с головой правила 2 ; X меньше или равно Y]

match succeeds г 9 leq 9

[сопоставление успешно завершено " 9 меньше или равно 9]

new query 9 LESS 9

[новый запрос 9 LESS 9]

(1 1 3 1) i 9 LESS 9

[(1 1 3 1) : 9 LESS 9]

(1 1 3 1) failing : 9 LESS 9

[(1 1 3 1) неудача : 9 LESS 9]

retrying (1 3 1)

[снова попробовать (1 3 1)]

(1 3 1) failing : 9 leq 9

[(13 1) неудача i 9 меньше или равно 9]

(3 1) failing : (either 9 LESS 9... etc..)

[(3 1) неудача i (либо 9 LESS 9... и т. д. ...)]

(2 1) failing ! date now (X Y Z)

[(2 1) неудача : текущая дата (X Y Z)]

retrying (1 1)...

[снова попробовать (1 l)...]

Может показаться, что хороший механизм обработки запросов в данном случае приносит больше вреда, чем пользы. Ведь программа вынуждена оценивать каждое условие в конструкции (either... or...); причем все процессы сопоставления оканчиваются неудачей. После этого управление вновь передается первому утверждению в первом условии (1 1), т. е. делается попытка найти новое значение X, которое содержится в утверждении типа

X born (Y Z х)

С помощью первого правила отношения age возраст Джо определить не удается. И то, что сопоставление некоторых подцелей в процессе использования этого правила будет успешным, только приведет к лишним затратам времени. После этого программа будет осуществлять поиск возраста Билла и Изабеллы. Для этого потребуется произвести минимальное число возвратов, поскольку решения будут найдены с помощью первого правила.

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

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

1. Можно использовать два правила age1 и age2 вместо уже имеющихся и, кроме того, ввести новое третье правило, которое даст возможность выбрать либо agel, либо age2. Это третье правило будет иметь вид

X age Y if

(either X agel Y and/or X age2 Y).

В данном случае отношение "/" позволяет предотвратить использование age2, если использование age1 завершилось успешно.

2. Можно на основе двух правил отношения age сконструировать одно. Причем сделать это надо таким образом, чтобы кандидат на решение, удовлетворяющий двум первым условиям:

X born (Z х у)

и

date now (z X1 Y1)

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

Перед тем как идти дальше, наверное, полезно проследить, как меняется содержимое стека в процессе обработки запроса (рис. 3.2 и 3.3). Изображенное на этих рисунках не следует интерпретировать как точную копию состояний памяти - скорее рисунки дают обобщенную картину выполняемых процессов. Центральный столбец на рис. 3.2 отражает структуру стека на разных этапах обработки запроса; левый столбец содержит составные номера утверждений, используемые и программой трассировки; и, наконец, правый столбец содержит информацию о последнем помещенном в стек элементе. Отметим, что, анализируя рисунки, необходимо учитывать существование специальных внутренних кодов, используемых для представления различных элементов* помещенных в стек.

Рис. 3.2. Процесс изменения состояния стека во время обработки запроса. Рис. 3.3. Изменение состояния стека в процессе реализации механизма возврата
Рис. 3.2. Процесс изменения состояния стека во время обработки запроса. Рис. 3.3. Изменение состояния стека в процессе реализации механизма возврата

Элементы попадают в стек именно в том порядке, в котором они обрабатываются программой; поэтому первым, помещенным в стек, элементом является

born 1

Это обозначает не что иное, как первое утверждение отношения born, которое в конце концов будет интерпретироваться как

Betty born (2 5 1950)

Затем в стек будет помещен элемент now 1 - первое утверждение (оно одновременно и единственное) отношения now. После него - 5 LESS 9, затем символ "/", используемый для предотвращения возврата при поиске альтернативных вариантов, и, наконец, будет получено решение 35 = 1985 - 1950. Заключительное состояние стека перед возвратом изображено в нижней части рис. 3.2. Именно последний помещенный в стек элемент обеспечивает ответ на запрос, который будет выглядеть так:

Betty age 35

На рис. 3.3 показано изменение состояний стека в результате операций, выполняемых в процессе возврата. Последний элемент, представляющий собой отношение SUM, выталкивается из стека и повторно не обрабатывается, поскольку альтернативных решений для него нет. Если бы альтернативное решение существовало, оно помешалось бы в стек и печаталось. Следующим выталкиваемым из стека элементом является условие (either ... or ...), но присутствие отношения "/" предотвращает на данном шаге выполнение возврата для поиска альтернативных вариантов. В конце концов из стека выталкивается born 1 и следом за этим в стек сразу же помещается born 2. Далее повторяется процесс, аналогичный изображенному на рис. 3.2, и так продолжается до тех пор, пока все утверждения, описывающие отношение born, не будут исчерпаны. В результате использования первого утверждения отношения age никаких новых решений, кроме

Betty born (2 5 1950)

получено не будет. После этого аналогичная процедура повторяется для второго утверждения отношения age.

Заметим, что с помощью программы трассировки пользователю удается получить очень много различной информации.

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

Ниже приведена более эффективная программа, позволяющая определить возраст по дате рождения и текущей дате:

Betty born (3 5 1950)

Joe bom (23 9 1917)

Bill bom (22 9 1943)

Isabel born (21 9 1942)

X leq X

X leq Y if

X LESS Y

X age Y if

X bom (Z x y) and

(either (either x LESS 9 and / or x leq 9 and Z leq 22 and /) and SUM (Y у 1985) and / or SUM (Y у 1984))

Возможность создания такой программы появилась только после изучения протокола трассировки первоначальной версии программы, выполняющей ту же самую функцию. Отметим главные преимущества последнего варианта программы. Во-первых, ояношение age определяется теперь с помощью только одного утверждения; во-вторых, следует определять текущую дату и, в-третьих, те люди, чьи дни рождения в текущем году еще не прошли, распознаются автоматически, поскольку данные о них не удовлетворяют первой части правила. Информацию о текущей дате можно включить в правило с помощью отношения update, использующего, в свою очередь, отношение is-told. Но если Вам необходимо провести трассировку, то лучше все же избежать хотя бы временно применения отношения update, что позволит сэкономить память. Ниже приводится часть протокола трассировки последней версии программы:

all-trace (x у: х age y)

[полная трассировка (х у: х имеет возраст у)]

(1) : X age Y trace ? у

[(1) : X имеет возраст Y трассировка ? да]

matching (1) : X age Y with head of 1 : Z age x

[сопоставление (1) : X имеет возраст Y с головой правила (1) : Z имеет возраст x]

match succeeds : X age Y

[согласование успешно завершено : X имеет возраст Y]

new query : X born (Y Z x) and (either (either Z LESS 9 and/or Z leq 9

[новый запрос : X родился (Y Z x) и (либо (либо Z LESS 9 и/либо Z меньше или равно 9]

and Y leq 22 and/) and SUM (у х 1985) and/or SUM (у х 1984))

[и Y меньше или равно 22 и /) и SUM (у х 1985) и/либо (у х 1984))]

(1 1) : X born (Y Z x) trace ? у

[(1 1) : X родился (Y Z х) трассировка ? да]

matching (1 1) : X born (Y Z x) with head of 1 : Betty born (3 5 1950)

[сопоставление (1 1) : X родился (Y Z x) с головой правила 1 : Бетти родилась (3 5 1950)]

match succeeds : Betty born (3 5 1950)

[сопоставление успешно завершено : Бетти родилась (3 5 1950)]

(1 1) solved : Betty born (3 5 1950)

[(11) результат сопоставления : Бетти родилась (3 5 1950)]

(2 1): (either (either 5 LESS 9 and/or 5 leq 9 and 3 leq 22 and /)

and

[(2 1) : (либо (либо 5 LESS 9 и / либо 5 меньше или равно 9 и 3 меньше или равно 22 и /)и ]

SUM (X 1950 1985) and/or SUM (X 1950 1984)) trace? (y/n) у

[SUM (X 1950 1985) и / либо SUM (X 1950 1894)) трассировка ? (да/нет) да]

(2 1) either branch

[(2 1) ветвление либо-либо]

(12 1): (either Б LESS 9 and/or 5 leq 9 and 3 leq 22 and/) trace ? (y/n) у

[(1 2 1) : (либо 5 LESS 9 и/либо 5 меньше или равно 9 и 3 меньше или равно 22 и /) трассировка ? (да/нет) да]

(12 1) either branch

[(1 2 1) ветвление либо-либо]

(1 1 2 1) : 5 LESS 9

[(1 1 2 1) :5 LESS 9]

(112 1) solved : 5 LESS 9

[(1 1 2 1) результат сопоставления : 5 LESS 9]

(2121):/

[(2 12 1):/]

(2 12 1) solved : /

[(2 1 2 1) результат сопоставления : /]

(1 2 1) solved : (either 5 LESS 9 and/or 5 leq 9 and 3 leq 22 and/)

[(1 2 1) результат сопоставления : либо 5 LESS 9 и/либо 5 меньше или равно 9 и 3 меньше или равно 22 и/]

(2 2 1): SUM (X 1950 1985)

[(2 2 1) :SUM(X 1950 1985)]

(2 2 1) solved : SUM (35 1950 1985)

[(2 2 1) результат сопоставления : SUM (35 1950 1985)]

(3 2 1): /

[(3 2 1):/]

(3 2 1) solved : /

[(3 2 1) результат сопоставления : /]

(2 1 solved : (either (either 5 LESS 9 and/or 5 leq 9 and 3 leq 22 and/)

[(2 1) результат сопоставления : (либо/либо 5 LESS 9 и/либо 5 меньше или равно 9 и 3 меньше или равно 22 и/)]

(1) solved : Betty age 35

[(1) результат сопоставления : Беттй имеет возраст 35]

Betty 35

[Бетти ]

backtracking ...

[возврат для поиска альтернативных вариантов ...]

(2 1) failing (either (either 5 LESS 9 and/or 5 leq 9 and 3 leq 22 and/)

[(2 1) неудача : (либо (либо 5 LESS 9 и/либо 5 меньше или равно 9 и 3 меньше или равно 22 и/)]

and SUM (X 1950 1985) and/or SUM (X 1950 1984))

[и SUM (X 1950 1985)) и/либо SUM (X 1950 1984))]

retrying (1 1)

[снова попробовать (1 1)]

Далее приводится текст отношения update, использование В которого позволяет пользователю вводить нужную ему дату:

update X if

age KILL and

(date now (YZx) is-told) and SUM (y 1 x) and

(z age X1 if z born (Y1 Z1 x1) and (either (either Z1 LESS Z and /

or Z1 leq Z and Y1 leq Y and /) and SUM (X1 x1 x) and / or SUM

(X1 x1 y))) add

Чтобы использовать отношение update, необходимо ввести

all (x: update x)

[определить все (х : модифицировать х)]

Отметим, что х - это фиктивная переменная, поэтому в результате обработки запроса никакого ответа получено не будет. Но зато данные, составляющие новую дату, будут включены в отношение age.

Анализ протокола трассировки позволяет заключить, что попытки осуществить возврат с целью поиска альтернативных решений в соответствии с конструкцией (either ... or ...) сразу игнорируются из-за присутствия отношения "/".

предыдущая главасодержаниеследующая глава








© Злыгостев А.С., 2001-2019
При использовании материалов сайта активная ссылка обязательна:
http://informaticslib.ru/ 'Библиотека по информатике'
Рейтинг@Mail.ru
Поможем с курсовой, контрольной, дипломной
1500+ квалифицированных специалистов готовы вам помочь