Данная лекция посвящена базовым понятиям языка Пролог. В этой и следующей лекциях, мы будем изучать основы написания программ на Прологе.
Начнем с того, что познакомимся с так называемой нормальной формой Бэкуса-Наура (БНФ), разработанной в 1960 Джоном Бэкусом и Питером Науром и используемой для формального описания синтаксиса языков программирования. Впервые
При описании синтаксиса конструкций используются следующие обозначения:
Символ ::= читается как "по определению" ("это", "есть"). Слева от разделителя располагается объясняемое понятие, справа - конструкция, разъясняющая его. Например,
<Имя> ::= <Идентификатор>
В угловые скобки заключается часть выражения, которая используется для обозначения синтаксической конструкции языка, в частности объясняемое понятие. В приведенном выше примере это <Имя> и <Идентификатор>.
Символ | означает в нотации
Пример. Десятичную цифру можно определить следующим образом:
<цифра> ::= 0|1|2|3|4|5|6|7|8|9
Часть синтаксической конструкции, заключенная в квадратные скобки, является необязательной (может присутствовать или отсутствовать);
Пример. Запись
<Целое число> ::= [-]<Положительное целое число>
означает, что целое число можно определить через положительное целое число, перед которым может стоять знак минус.
Символ * обозначает, что часть синтаксической конструкции может повторяться произвольное число раз (ноль и более). Заметим, что иногда вместо символа * используют фигурные скобки ( {, } ).
Пример. Определить положительное целое число в нотации
<Положительное целое число> ::= <цифра>[<цифра>]*.
То есть положительное целое число состоит из одной или нескольких цифр.
Программа на языке Пролог, ее иногда называют базой знаний, состоит из
A:- B1,... , Bn.
A называется заголовком или головой B1,..., Bn - телом.
В принципе об этом уже говорилось в предыдущей лекции. Но там мы рассматривали эти понятия в основном с теоретической точки зрения, заходя со стороны математической логики, а сейчас наш подход будет больше практическим, со стороны программирования.
Например, известный нам
мама(Наташа, Даша).
Напомню, что в математической логике, с которой мы познакомились в предыдущей лекции, отношения принято называть предикатами.
Если воспользоваться нормальной формой Бэкуса-Науэра, то предикат можно определить следующим образом:
<Предикат>::=<Имя> | <Имя>(<аргумент>[,<аргумент>]*),
т.е. предикат состоит либо только из имени, либо из имени и следующей за ним последовательности аргументов, заключенной в скобки.
Аргументом или параметром предиката может быть константа, переменная или составной объект. Число аргументов предиката называется его арностью или местностью. Про переменные мы поговорим чуть-чуть позже, а подробное рассмотрение констант отложим до пятой лекции. Пока отметим, что константа получает свое значение в разделе описания констант, а переменная означивается в процессе работы программы.
В Турбо Прологе имя предиката должно состоять из последовательности латинских букв, цифр, знаков подчеркивания и начинаться с буквы или знака подчеркивания. В других версиях Пролога имя предиката может содержать символы не только из английского алфавита, но и из национального, например, из русского.
Соответственно, приведенный выше пример
mother("Наташа", "Даша").
Некоторые предикаты уже известны системе, они называются стандартными или встроенными.
В Турбо Прологе
В приведенном выше примере про то, что Наташа является мамой Даши, мама - это имя двухаргументного предиката, у которого строковая константа "Наташа" является первым аргументом, а строковая константа "Даша" - вторым.
В нотации
<Правило>::=<предикат>:-<предикат>[,<предикат>]*.
Пример. Известно, что бабушка человека - это мама его мамы или мама его папы.
Соответствующие
бабушка(X,Y):- мама(X,Z),мама(Z,Y). бабушка(X,Y):- мама(X,Z),папа(Z,Y).
Символ " :- " означает "если", и вместо него можно писать if.
Символ " ," - это логическая связка "и" или конъюнкция, вместо него можно писать and.
Первое X является бабушкой Y, если существует такой Z, что X является мамой Z, а Z - мамой Y. Второе X является бабушкой Y, если существует такой Z, что X является мамой Z, а Z - папой Y.
В данном примере X, Y и Z - это переменные.
Имя переменной в Турбо Прологе может состоять из букв латинского алфавита, цифр, знаков подчеркивания и должно начинаться с прописной буквы или знака подчеркивания. При этом переменные в теле
Переменные могут быть свободными или связанными.
Свободная переменная - это переменная, которая еще не получила значения. Она не равняется ни нулю, ни пробелу; у нее вообще нет никакого значения. Такие переменные еще называют неконкретизированными.
Переменная, которая получила какое-то значение и оказалась связанной с определенным объектом, называется связанной. Если переменная была конкретизирована каким-то значением и ей сопоставлен некоторый объект, то эта переменная уже не может быть изменена.
Областью действия переменной в Прологе является одно _ ". Анонимная переменная применяется в случае, когда значение переменной не важно. Каждая анонимная переменная - это отдельный объект.
Третьим специфическим видом
<Вопрос>::=<Предикат>[,<Предикат>]*
Программа на Прологе может содержать
Если внутренней
Если
Следует заметить, что ответ "No" на
Можно сказать, что утверждение - это
Рассмотрим несколько примеров. Пусть в программе заданы следующие отношения:
мама("Наташа","Даша").
мама("Даша","Маша").
Можно спросить у системы, является ли Наташа мамой Даши. Этот
мама("Наташа","Даша")
Найдя соответствующий
мама("Наташа","Маша")
то получим ответ "No" (то есть "Нет" ). Можно также попросить вывести имя мамы Даши:
мама(X,Даша).
Система сопоставит X значением " Наташа " и выдаст ответ:
X=Наташа 1 Solution
Наташи записывается в виде:
мама(Наташа,X).
Соответствующим ответом будет:
X=Даша 1 Solution
Можно попросить систему найти имена всех известных ей мам и дочек, задав
мама(X,Y).
Система последовательно будет пытаться согласовывать X будет означена именем матери, а переменная Y - именем ее дочери.
В итоге получим ответ:
X=Наташа Y=Даша X=Даша Y=Маша 2 solutions
Если надо получить только имена всех мам, можно воспользоваться анонимной переменной и записать
мама(X,_).
Получим ответ:
X=Наташа X=Даша 2 solutions
И, наконец, если надо получить ответ на
мама(_,_),
В данном случае нам не важны конкретные имена, а интересует, есть ли в нашей базе знаний хотя бы один соответствующий
Введем в нашу программу
бабушка(X,Y):- мама(X,Z), мама(Z,Y).
По сути дела здесь записано, что один человек является бабушкой другого, если это он является мамой его мамы. Конечно, для полноты картины не помешает записать еще и второе
Заметим, что в нашей программе нет ни одного бабушка. Тем не менее, система оказывается способна найти ответы на Наташа, то мы можем записать этот
бабушка("Наташа",X).
Для того чтобы найти ответ на бабушка. Найдя такое бабушка(X,Y):-мама(X,Z),мама(Z,Y) ), система конкретизирует переменную из заголовка X именем " Наташа ", переменную Y с переменной X из мама("Наташа",Z) и мама(Z,Y). Для этого она просматривает базу знаний в поиске мама("Наташа",Z).
Это можно сделать, конкретизировав переменную Z именем "Даша". Затем система ищет "Даша" и каким-то именем в качестве второго аргумента. Подходящим мама("Даша","Маша"). Система установила, что обе подцели мама("Наташа",Z) и мама(Z,Y) достижимы при Z="Даша", Y="Маша". Она выдает ответ:
X=Маша
Напомним, что наша переменная X из Y из
Вообще говоря,
В программе на Прологе важен порядок
Пример. Давайте создадим предикат, который будет находить максимум из двух чисел. У предиката будет три аргумента. Первые два аргумента - входные для исходных чисел, в третий
Предикат будет довольно простым. Мы запишем, что в случае, если первое число больше второго, максимальным будет первое число, в случае, если первое число меньше, максимумом будет второе число. Надо также не забыть про ситуацию, когда числа равны, в этом случае максимумом будет любое из них.
Решение можно записать в следующем виде:
max(X,Y,X):- X>Y. /* если первое число больше второго, то первое число - максимум */ max(X,Y,Y):- X<Y. /* если первое число меньше второго, то второе число - максимум */ max(X,Y,Y):- X=Y. /* если первое число равно второму, возьмем в качестве максимума второе число */
Первое
max(X,Y,X):- X>Y. /* если первое число больше второго, то первое число - максимум */ max(X,Y,Y):- X<=Y./* если первое число меньше или равно второму, возьмем в качестве максимума второе число */
Однако полученная процедура еще далека от совершенства. С одной стороны, в случае, когда первое проверяемое условие ( X>Y ) не выполнено, будет проверяться второе условие ( X<=Y ), хотя понятно, что если не выполнено X>Y, значит X<=Y. С другой стороны, в случае, если первое условие имело место и первое число оказалось больше второго, Пролог-система свяжет третий аргумент предиката max с первым аргументом, после чего попытается сопоставить второе
С использованием
max2(X,Y,X):- X>Y,!./* если первое число больше второго, то первое число - максимум */ max2(_,Y,Y). /* в противном случае максимумом будет второе число */
В случае, если сработает X>Y, Пролог-система не будет рассматривать альтернативное второе
Все случаи применения
Пример "красного" max2 (если убрать max добавить
В принципе, с помощью
Процедура
S:- <условие>,!,P. S :- P2.
будет соответствовать оператору if <условие> then P else P2, то есть если условие имеет место, то выполнить P, иначе выполнить P2. Например, в случае с максимумом, можно расшифровать нашу процедуру как "если X>Y, то M=X, иначе M=Y ".
Пример. Теперь напишем предикат, который будет находить максимум не из двух чисел, а из трех. У него будет уже четыре параметра. Первые три - входные для сравниваемых чисел, а четвертый - выходной параметр для их максимума.
Подходов к решению этой задачи может быть несколько.
Первое, что приходит в голову, это решить задачу по аналогии с нахождением максимума из двух чисел. Вариант без
max3a(X,Y,Z,X):- X>=Y,X>=Z. /* если первое число больше или равно второму и третьему, то первое число - максимум */ max3a(X,Y,Z,Y):- Y>=X,Y>=Z. /* если второе число больше или равно первому и третьему, то второе число является максимумом */ max3a(X,Y,Z,Z):- Z>=X,Z>=Y. /* если третье число больше или равно первому и второму, то максимум - это третье число */
Недостаток этой программы, кроме ее длины, еще и в том, что если какие-то из исходных чисел окажутся равными, мы получим несколько одинаковых решений. Например, если все три числа совпадают, то каждое из трех
Применение
max3b(X,Y,Z,X):- X>Y,X>Z,!. /* если первое число больше второго и третьего, то первое число - максимум */ max3b(_,Y,Z,Y):- Y>=Z,!. /* иначе, если второе число больше третьего, то второе число является максимумом */ max3b(_,_,Z,Z). /* иначе максимум - это третье число */
Число сравнений значительно сократилось за счет того, что
И, наконец, самое короткое решение можно получить, если воспользоваться уже имеющимся предикатом max2. Решение будет состоять всего из одного
max3(X,Y,Z,M):- max2(X,Y,XY), /* XY - максимум из X и Y */ max2(XY,Z,M). /* M - максимум из XY и Z */
Мы записали, что для того, чтобы найти максимум из трех чисел, нужно найти максимум из первых двух чисел, после чего сравнить его с третьим числом.
В Прологе обычно применяются две семантические модели:
Множество
При написании программы на Прологе кажется логичным в первую очередь рассматривать декларативную семантику, однако и о процедурной не стоит забывать, особенно в том случае, когда программа не работает или работает не совсем так, как предполагалось.
Следует заметить, что в некоторых случаях использование
Данная лекция посвящена базовым понятиям языка Пролог. В этой и следующей лекциях, мы будем изучать основы написания программ на Прологе.
Начнем с того, что познакомимся с так называемой нормальной формой Бэкуса-Наура (БНФ), разработанной в 1960 Джоном Бэкусом и Питером Науром и используемой для формального описания синтаксиса языков программирования. Впервые
При описании синтаксиса конструкций используются следующие обозначения:
Символ ::= читается как "по определению" ("это", "есть"). Слева от разделителя располагается объясняемое понятие, справа - конструкция, разъясняющая его. Например,
<Имя> ::= <Идентификатор>
В угловые скобки заключается часть выражения, которая используется для обозначения синтаксической конструкции языка, в частности объясняемое понятие. В приведенном выше примере это <Имя> и <Идентификатор>.
Символ | означает в нотации
Пример. Десятичную цифру можно определить следующим образом:
<цифра> ::= 0|1|2|3|4|5|6|7|8|9
Часть синтаксической конструкции, заключенная в квадратные скобки, является необязательной (может присутствовать или отсутствовать);
Пример. Запись
<Целое число> ::= [-]<Положительное целое число>
означает, что целое число можно определить через положительное целое число, перед которым может стоять знак минус.
Символ * обозначает, что часть синтаксической конструкции может повторяться произвольное число раз (ноль и более). Заметим, что иногда вместо символа * используют фигурные скобки ( {, } ).
Пример. Определить положительное целое число в нотации
<Положительное целое число> ::= <цифра>[<цифра>]*.
То есть положительное целое число состоит из одной или нескольких цифр.
Программа на языке Пролог, ее иногда называют базой знаний, состоит из
A:- B1,... , Bn.
A называется заголовком или головой B1,..., Bn - телом.
В принципе об этом уже говорилось в предыдущей лекции. Но там мы рассматривали эти понятия в основном с теоретической точки зрения, заходя со стороны математической логики, а сейчас наш подход будет больше практическим, со стороны программирования.
Например, известный нам
мама(Наташа, Даша).
Напомню, что в математической логике, с которой мы познакомились в предыдущей лекции, отношения принято называть предикатами.
Если воспользоваться нормальной формой Бэкуса-Науэра, то предикат можно определить следующим образом:
<Предикат>::=<Имя> | <Имя>(<аргумент>[,<аргумент>]*),
т.е. предикат состоит либо только из имени, либо из имени и следующей за ним последовательности аргументов, заключенной в скобки.
Аргументом или параметром предиката может быть константа, переменная или составной объект. Число аргументов предиката называется его арностью или местностью. Про переменные мы поговорим чуть-чуть позже, а подробное рассмотрение констант отложим до пятой лекции. Пока отметим, что константа получает свое значение в разделе описания констант, а переменная означивается в процессе работы программы.
В Турбо Прологе имя предиката должно состоять из последовательности латинских букв, цифр, знаков подчеркивания и начинаться с буквы или знака подчеркивания. В других версиях Пролога имя предиката может содержать символы не только из английского алфавита, но и из национального, например, из русского.
Соответственно, приведенный выше пример
mother("Наташа", "Даша").
Некоторые предикаты уже известны системе, они называются стандартными или встроенными.
В Турбо Прологе
В приведенном выше примере про то, что Наташа является мамой Даши, мама - это имя двухаргументного предиката, у которого строковая константа "Наташа" является первым аргументом, а строковая константа "Даша" - вторым.
В нотации
<Правило>::=<предикат>:-<предикат>[,<предикат>]*.
Пример. Известно, что бабушка человека - это мама его мамы или мама его папы.
Соответствующие
бабушка(X,Y):- мама(X,Z),мама(Z,Y). бабушка(X,Y):- мама(X,Z),папа(Z,Y).
Символ " :- " означает "если", и вместо него можно писать if.
Символ " ," - это логическая связка "и" или конъюнкция, вместо него можно писать and.
Первое X является бабушкой Y, если существует такой Z, что X является мамой Z, а Z - мамой Y. Второе X является бабушкой Y, если существует такой Z, что X является мамой Z, а Z - папой Y.
В данном примере X, Y и Z - это переменные.
Имя переменной в Турбо Прологе может состоять из букв латинского алфавита, цифр, знаков подчеркивания и должно начинаться с прописной буквы или знака подчеркивания. При этом переменные в теле
Переменные могут быть свободными или связанными.
Свободная переменная - это переменная, которая еще не получила значения. Она не равняется ни нулю, ни пробелу; у нее вообще нет никакого значения. Такие переменные еще называют неконкретизированными.
Переменная, которая получила какое-то значение и оказалась связанной с определенным объектом, называется связанной. Если переменная была конкретизирована каким-то значением и ей сопоставлен некоторый объект, то эта переменная уже не может быть изменена.
Областью действия переменной в Прологе является одно _ ". Анонимная переменная применяется в случае, когда значение переменной не важно. Каждая анонимная переменная - это отдельный объект.
Третьим специфическим видом
<Вопрос>::=<Предикат>[,<Предикат>]*
Программа на Прологе может содержать
Если внутренней
Если
Следует заметить, что ответ "No" на
Можно сказать, что утверждение - это
Рассмотрим несколько примеров. Пусть в программе заданы следующие отношения:
мама("Наташа","Даша").
мама("Даша","Маша").
Можно спросить у системы, является ли Наташа мамой Даши. Этот
мама("Наташа","Даша")
Найдя соответствующий
мама("Наташа","Маша")
то получим ответ "No" (то есть "Нет" ). Можно также попросить вывести имя мамы Даши:
мама(X,Даша).
Система сопоставит X значением " Наташа " и выдаст ответ:
X=Наташа 1 Solution
Наташи записывается в виде:
мама(Наташа,X).
Соответствующим ответом будет:
X=Даша 1 Solution
Можно попросить систему найти имена всех известных ей мам и дочек, задав
мама(X,Y).
Система последовательно будет пытаться согласовывать X будет означена именем матери, а переменная Y - именем ее дочери.
В итоге получим ответ:
X=Наташа Y=Даша X=Даша Y=Маша 2 solutions
Если надо получить только имена всех мам, можно воспользоваться анонимной переменной и записать
мама(X,_).
Получим ответ:
X=Наташа X=Даша 2 solutions
И, наконец, если надо получить ответ на
мама(_,_),
В данном случае нам не важны конкретные имена, а интересует, есть ли в нашей базе знаний хотя бы один соответствующий
Введем в нашу программу
бабушка(X,Y):- мама(X,Z), мама(Z,Y).
По сути дела здесь записано, что один человек является бабушкой другого, если это он является мамой его мамы. Конечно, для полноты картины не помешает записать еще и второе
Заметим, что в нашей программе нет ни одного бабушка. Тем не менее, система оказывается способна найти ответы на Наташа, то мы можем записать этот
бабушка("Наташа",X).
Для того чтобы найти ответ на бабушка. Найдя такое бабушка(X,Y):-мама(X,Z),мама(Z,Y) ), система конкретизирует переменную из заголовка X именем " Наташа ", переменную Y с переменной X из мама("Наташа",Z) и мама(Z,Y). Для этого она просматривает базу знаний в поиске мама("Наташа",Z).
Это можно сделать, конкретизировав переменную Z именем "Даша". Затем система ищет "Даша" и каким-то именем в качестве второго аргумента. Подходящим мама("Даша","Маша"). Система установила, что обе подцели мама("Наташа",Z) и мама(Z,Y) достижимы при Z="Даша", Y="Маша". Она выдает ответ:
X=Маша
Напомним, что наша переменная X из Y из
Вообще говоря,
В программе на Прологе важен порядок
Пример. Давайте создадим предикат, который будет находить максимум из двух чисел. У предиката будет три аргумента. Первые два аргумента - входные для исходных чисел, в третий
Предикат будет довольно простым. Мы запишем, что в случае, если первое число больше второго, максимальным будет первое число, в случае, если первое число меньше, максимумом будет второе число. Надо также не забыть про ситуацию, когда числа равны, в этом случае максимумом будет любое из них.
Решение можно записать в следующем виде:
max(X,Y,X):- X>Y. /* если первое число больше второго, то первое число - максимум */ max(X,Y,Y):- X<Y. /* если первое число меньше второго, то второе число - максимум */ max(X,Y,Y):- X=Y. /* если первое число равно второму, возьмем в качестве максимума второе число */
Первое
max(X,Y,X):- X>Y. /* если первое число больше второго, то первое число - максимум */ max(X,Y,Y):- X<=Y./* если первое число меньше или равно второму, возьмем в качестве максимума второе число */
Однако полученная процедура еще далека от совершенства. С одной стороны, в случае, когда первое проверяемое условие ( X>Y ) не выполнено, будет проверяться второе условие ( X<=Y ), хотя понятно, что если не выполнено X>Y, значит X<=Y. С другой стороны, в случае, если первое условие имело место и первое число оказалось больше второго, Пролог-система свяжет третий аргумент предиката max с первым аргументом, после чего попытается сопоставить второе
С использованием
max2(X,Y,X):- X>Y,!./* если первое число больше второго, то первое число - максимум */ max2(_,Y,Y). /* в противном случае максимумом будет второе число */
В случае, если сработает X>Y, Пролог-система не будет рассматривать альтернативное второе
Все случаи применения
Пример "красного" max2 (если убрать max добавить
В принципе, с помощью
Процедура
S:- <условие>,!,P. S :- P2.
будет соответствовать оператору if <условие> then P else P2, то есть если условие имеет место, то выполнить P, иначе выполнить P2. Например, в случае с максимумом, можно расшифровать нашу процедуру как "если X>Y, то M=X, иначе M=Y ".
Пример. Теперь напишем предикат, который будет находить максимум не из двух чисел, а из трех. У него будет уже четыре параметра. Первые три - входные для сравниваемых чисел, а четвертый - выходной параметр для их максимума.
Подходов к решению этой задачи может быть несколько.
Первое, что приходит в голову, это решить задачу по аналогии с нахождением максимума из двух чисел. Вариант без
max3a(X,Y,Z,X):- X>=Y,X>=Z. /* если первое число больше или равно второму и третьему, то первое число - максимум */ max3a(X,Y,Z,Y):- Y>=X,Y>=Z. /* если второе число больше или равно первому и третьему, то второе число является максимумом */ max3a(X,Y,Z,Z):- Z>=X,Z>=Y. /* если третье число больше или равно первому и второму, то максимум - это третье число */
Недостаток этой программы, кроме ее длины, еще и в том, что если какие-то из исходных чисел окажутся равными, мы получим несколько одинаковых решений. Например, если все три числа совпадают, то каждое из трех
Применение
max3b(X,Y,Z,X):- X>Y,X>Z,!. /* если первое число больше второго и третьего, то первое число - максимум */ max3b(_,Y,Z,Y):- Y>=Z,!. /* иначе, если второе число больше третьего, то второе число является максимумом */ max3b(_,_,Z,Z). /* иначе максимум - это третье число */
Число сравнений значительно сократилось за счет того, что
И, наконец, самое короткое решение можно получить, если воспользоваться уже имеющимся предикатом max2. Решение будет состоять всего из одного
max3(X,Y,Z,M):- max2(X,Y,XY), /* XY - максимум из X и Y */ max2(XY,Z,M). /* M - максимум из XY и Z */
Мы записали, что для того, чтобы найти максимум из трех чисел, нужно найти максимум из первых двух чисел, после чего сравнить его с третьим числом.
В Прологе обычно применяются две семантические модели:
Множество
При написании программы на Прологе кажется логичным в первую очередь рассматривать декларативную семантику, однако и о процедурной не стоит забывать, особенно в том случае, когда программа не работает или работает не совсем так, как предполагалось.
Следует заметить, что в некоторых случаях использование
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.