Программа пролог руководство пользователя

Программа Пролог ЛОГИКА применяется для чтения данных приборов учета при выполнении работ по техническому обслуживанию узлов учета энергоносителей. Настройка программы ПРОЛОГ для опроса тепловычислителей СПТ 940, СПТ 941, СПТ 943, СПТ 944, СПТ 961, СПТ 962, СПТ 963 описана в настоящем руководстве пользователя.

Интерфейс программы

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

  1. Панель меню.
  2. Панель инструментов.
  3. Навигатор.
  4. Структура базы данных.
  5. Окно просмотра данных.

Главное окно программы ПРОЛОГ (Логика)

Изображение 1. Главное окно программы «ПРОЛОГ» (Логика)

Структура архива

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

Абоненты

Доступны три основных действия с абонентами: создание, удаление и изменение свойств. Эти действия выполняются по командам из раздела меню «Узел». Команда «Свойства» также доступна из контекстного меню, вызываемого правой клавишей мыши.

По команде «Создать абонента» на экране появляется окно «Учетная запись абонента». В данном окне пользователь вносит информацию об абоненте. Обязательно для заполнения одно свойство (поле) абонента – его наименование. Остальные поля могут заполняться по желанию пользователя.

Просмотр или изменение информации об абоненте доступны по команде «Свойства» из контекстного меню. Команда «Удалить» может быть выполнена только для абонентов, не имеющих узлов учета. Перед выполнением команды программа выдаст дополнительное предупреждение.

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

Пример сортировки в панели базы данных Пролога

Изображение 2. Пример сортировки в панели базы данных Пролога

Узлы учета

Через пункт меню «Узлы» доступны три команды, применяемые к узлам учета: 

  • «Создать узел»
  • «Удалить»
  • «Свойства»

По команде «Создать узел» вызывается окно «Учетная запись узла», в котором пользователь может внести информацию об узле учета. Обязательные для заполнения поля выделяются светло-желтым цветом.

Создание узла таким способом обязательно в двух случаях: 

  • если прибор будет опрашиваться через Интернет
  • если прибор находится в составе сети приборов.

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

Наименование узла будет содержать тип и идентификатор (номер) прибора. Сам узел будет приписан абоненту «Новые». Опцию автоматического создания новых узлов можно отключить в настройках программы.

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

При выборе команды «Свойства» появляется окно «Учетная запись узла», в котором можно просмотреть или изменить информацию об узле учета. 

Узлы можно перемещать от одного абонента к другому, для чего предусмотрены команды «Вырезать» и «Вставить», из контекстного меню.

Таблицы данных

Вся информация, полученная с приборов учета посредством накопителя, сохраняется в архиве программы в табличном виде. Эти таблицы недоступны для редактирования.

Перечень таблиц определяется прибором учета, установленном на узле. Узел учета характеризуется следующим набором таблиц:

  • часовой
  • суточный
  • месячный архивы
  • настроечные параметры (база данных) прибора
  • тотальные счетчики
  • контрольный архив.

Перемещение в окне данных осуществляется с помощью линеек прокрутки, клавиш управления курсором или панели НАВИГАТОР. При выделении в панели базы данных пункта «Архив» выводится таблица с информацией о всех зарегистрированных узлах.

Таблица "Архив" тепловычислителя в программе ПРОЛОГ. Пример - месячный архив СПТ941

Изображение 3. Таблица «Архив» тепловычислителя в программе ПРОЛОГ. Пример — месячный архив СПТ941

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

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

Узел учета «Текст»

Все текстовые файлы данных (документов), считанные из приборов с помощью накопителя АДС90 в режиме Прием, приписываются особому узлу – «Текст», не имеющему учетной записи.

Этот узел содержит только одну таблицу – «Текстовые документы». В окне данных доступны для просмотра заголовки хранящихся в таблице документов, датированные временем их загрузки в компьютер, и содержимое самих документов. К текстовым документам применимы операции «Удалить» и «Экспортировать».

Основные настройки (Сервис)

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

По команде «Настройки» откроется одноименное окно с тремя вкладками – «Общие», «Связь» и «Модемы».

Вид окна "Настройки", вкладка "Общие"

Изображение 4. Вид окна «Настройки», вкладка «Общие»

Вкладка — ОБЩИЕ

Программа Пролог версии 3.0 и выше позволяет пользователю управлять появлением заставки при старте программы. Если пункт «Отображать заставку при запуске программы» отмечен галочкой, то заставка будет появляться, в противном случае будет сразу загружаться основное окно программы.

Накопители АДС90, АДС91 и приложение НАКОПИТЕЛЬ позволяют считывать информацию с приборов с любыми идентификаторами. После переноса данных на компьютер расшифровывает идентификатор прибора. Если прибор с таким идентификатором уже зарегистрирован в архиве, то все данные будут записаны в соответствующие таблицы. Если идентификатор прибора программе не известен, то тут возможны два пути дальнейшей работы.

Первое – это игнорирование всех полученных от прибора данных. Такой вариант работает, если пункт «Автоматически создавать узлы для новых приборов» не помечен.

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

Вкладка — СВЯЗЬ

Вид окна "Настройки", вкладка "Связь"

Изображение 5. Вид окна «Настройки», вкладка «Связь»

Значение в поле «Максимальный размер журнала связи, кб» ограничивает предельный объем файла, в который записывается история соединений с узлами.

Номер СОМ-порта обязателен для назначения, если планируется получение данных при прямом подключении. Указанный в настройках порт будет использоваться для подключения накопителя АДС90.

Количество попыток связи — общее значение для всех узлов, оснащенных модемами, в том числе и GPRS-модемами.

Тайм аут чтения. Этот параметр отвечает за время ожидания ответа от приборов СПТ961, СПТ961 (мод 961.1 и 961.2), СПТ962, СПТ963, СПТ961М, СПГ761, СПГ761 (мод 761.1 и 761.2), СПГ762, СПГ762 (мод 762.1 и 762.2), СПГ763, СПГ763 (мод 763.1 и 763.2).

Значение по умолчанию – 15 секунд, минимально допустимое – 3с. Основной фактор, влияющий на назначение этого параметра – скорость на шине. При скорости 1200 бит/с время отклика прибора может достигать 30 секунд. Тайм аут следует увеличить при одновременных запросах от нескольких абонентов сети приборов.

Вкладка — МОДЕМЫ

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

Доступ к индивидуальным настройкам установленных модемов можно получить из программы, после нажатия кнопок «Телефония», «Свойства модема», «Правила набора номера».

В программе ПРОЛОГ предусмотрена возможность работы с несколькими модемами одновременно, для чего введено понятие «групп модемов».

Пользователь создает (кнопка «+») одну или несколько групп модемов с произвольными названиями. Для примера на рис.4.7 показаны две группы – группа «PTN» и группа «GSM». Далее необходимо назначить установленные в системе модемы, с использованием которых предполагается проводить опрос, членами какой-либо группы. В каждой группе может быть любое количество модемов. В примере на рисунке и в группу «PTN» и в группу «GSM» включены по два модема. Таким образом, опрос возможно осуществлять параллельно по четырем модемам.

Группы можно удалять и редактировать. Установка нового модема не потребует внесения изменений в свойства каждого узла. Потребуется только одно переназначение в группе модемов. Опрос узла учета будет производиться посредством модемов (модема) той группы, которая назначена в свойствах этого узла.

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

  • Автономный тепловычислитель СПТ 940, Логика

    Продаваемый товар

  • Автономный тепловычислитель СПТ941.20, Логика

    Продаваемый товар

  • korrektor-obyoma-gaza-spg740-logika

    Продаваемый товар

  • Тепловычислитель СПТ944, Логика

    Продаваемый товар

  • Корректор объёма газа СПГ742, Логика

    Продаваемый товар

  • Корректор объёма газа СПГ761.2, Логика

    Продаваемый товар

Видео-инструкция по настройке программы ПРОЛОГ

Вебинар — Работа с программой ПРОЛОГ

В данном видео можно узнать о том, как работать с тепловычислителем СПТ940 при помощи программы ПРОЛОГ, предназначенной для получения и хранения данных приборов учета, а также вывода данных в виде таблиц и отчетов необходимого формата, а так же:

  • С чего начать при работе с программой ПРОЛОГ?
  • Как прочитать архивы с СПТ940?
  • Как сформировать отчет?
  • Как отредактировать отчет?
  • Подключение последовательного порта. Монитор текущих значений

⚠︎ Скачать бесплатно программное обеспечение для считывания показаний и формирования отчетных форм тепловычислителей и корректоров газа ЛОГИКА можно по ссылке на сайте kipkatalog.ru

☞ Рекомендуем ознакомиться с дополнительной информацией по данной программе:

  • Загрузка данных с приборов учета ЛОГИКА
  • Подготовка отчетов в программе ПРОЛОГ
ЛЭРС УЧЁТ — Современная автоматизированная система диспетчеризации и сбора архивных данных с приборов учета
ЛЭРС УЧЁТ — Современная автоматизированная система диспетчеризации и сбора архивных данных с приборов учета
  • Поддержка более 370 типов приборов учета тепла, воды, электроэнергии и др.
  • Автоматический и ручной опрос GSM/GPRS модемов, УСПД
  • АРМ + WEB-интерфейс + мобильное приложение (Android / iOS)
  • Таблицы, графики, отчеты, карты, мнемосхема, журналы работ, профиль мощности, анализ данных и НС
  • Без абонентской платы, бесплатная лицензия

Эта информация оказалась полезной?

Prolog - самый популярный язык логического программирования

Prolog — самый популярный язык логического программирования

В этой статье:

  1. Узнаем, что такое логическое программирование (ЛП), и его области применения

  2. Установим самый популярный язык ЛП — Prolog

  3. Научимся писать простые программы на Prolog

  4. Научимся спискам в Prolog

  5. Разберем преимущества и недостатки Prolog.

Эта статья будет полезна для тех, кто:

  1. Интересуется необычными подходами и расширяет свой кругозор

  2. Начинает изучать Prolog (например, в институте)

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

В конце статьи я оставлю полезные ссылки. Если у вас останутся вопросы — пишите в комментариях!

Начнем туториал: Пролог для чайников!

Логическое программирование

Существуют разные подходы к программированию. Часто выделяют такие парадигмы программирования:

  • Императивное (оно же алгоритмическое или процедурное). Самая известная парадигма. Программист четко прописывает последовательность команд, которые должен выполнить процессор. Примеры: C/C++, Java, C#, Python, Golang, машина Тюрьнга, алгоритмы Маркова. Все четко, последовательно как надо. Синоним императивного — приказательное.

  • Аппликативное (Функциональное). Менее известная, но тоже широко используемая. Примеры языков: Haskell, F#, Лисп. Основывается на математической абстракции лямбда вычислениях. Благодаря чистым функциям очень удобно параллелить такие программы. Чистые функции — функции без побочных эффектов. Если такой функции передавать одни и те же аргументы, то результат всегда будет один и тот же. Такие языки обладают высокой надежностью кода.

  • И наконец — Декларативное (Логическое). Основывается на автоматическом доказательстве теорем на основе фактов и правил. Примеры языков: Prolog и его диалекты, Mercury. В таких языках мы описываем пространство состояний, в которых сам язык ищет решение к задаче. Мы просто даем ему правила, факты, а потом говорим, что «сочини все возможные стихи из этих слов», «реши логическую задачу», «найди всех братьев, сестер, золовок, свояков в генеалогическом древе», или «раскрась граф наименьшим кол-вом цветов так, что смежные ребра были разного цвета».

    Что такое ЛП я обозначил. Предлагаю сразу перейти к практике, к основам Prolog (PROgramming in LOGic). На практике все становится понятнее. Практику и теорию я буду чередовать. Не беспокойтесь, если сразу будет что-то не понятно. Повторяйте за мной, и вы разберетесь.

Установка Prolog

Существую разные реализации (имплементации) Пролога: SWI Prolog, Visual Prolog, GNU Prolog. Мы установим SWI Prolog.

Установка на Arch Linux:

sudo pacman -S swi-prolog

Установка на Ubuntu:

sudo apt install swi-prolog

Prolog работает в режиме интерпретатора. Теперь можем запустить SWI Prolog. Запускать не через swi-prolog, а через swipl:

[user@Raft ~]$ swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 8.2.3)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- 

Ура! Оно работает!

Теперь поставим на Windows.
Перейдем на официальный сайт на страницу скачивания стабильной версии. Ссылка на скачивание. Клик. Скачаем 64х битную версию. Установка стандартная. Чтобы ничего не сломать, я решил галочки не снимать. Ради приличия я оставлю скрины установки.

Сайт SWI Prolog - установщики последней стабильной версии

Сайт SWI Prolog — установщики последней стабильной версии

Галочки не трогаем

Галочки не трогаем

Ищу SWI-Prolog через поиск Windows. Запускаю

Ищу SWI-Prolog через поиск Windows. Запускаю

Ура! Теперь и на Windows все работает

Ура! Теперь и на Windows все работает

Основы Prolog. Факты, правила, предикаты

Есть утверждения, предикаты:

  • Марк изучает книгу (учебник, документацию)

  • Маша видит клавиатуру (мышку, книгу, тетрадь, Марка)

  • Миша изучает математику (ЛП, документацию, учебник)

  • Саша старше Лёши

С английского «predicate» означает «логическое утверждение».

Есть объекты: книга, клавиатура, мышка, учебник, документация, тетрадь, математика, ЛП, Марк, Маша, Саша, Даша, Лёша, Миша, да что угодно может быть объектом.
Есть отношения между объектами, т.е то, что связывает объекты. Связь объектов можно выразить через глаголы, например: читать, видеть, изучать. Связь можно выразить через прилагательное. Миша старше Даши. Даша старше Лёши. Получается.. связью может быть любая часть речь? Получается так.

Прекрасно! Давайте попробуем запрограммировать эти утверждения на Прологе. Для этого нам нужно:

  1. Создать новый текстовый файл, который я назову simple.pl (.pl — расширение Пролога)

  2. В нем написать простой однострочный код на Прологе

  3. Запустить код с помощью SWI Prolog

  4. Спросить у Пролога этот факт

Файл simple.pl:

study(mark, book).

Запустим. На линуксе это делается таким образом:

[user@Raft referat]$ swipl simple.pl 
Welcome to SWI-Prolog (threaded, 64 bits, version 8.2.3)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- 

На Windows я использую notepad++ для написания кода на Прологе. Я запущу SWI-Prolog и открою файл через consult.

Видим, что он скомпилировал условия. Даже написал "1 clauses", т.е один факт

Видим, что он скомпилировал условия. Даже написал «1 clauses», т.е один факт

Что мы сделали? Мы загрузили базу знаний (те, которые мы описали в простом однострочном файле simple.pl) и теперь можем задавать вопросы Прологу. То есть система такая: пишем знания в файле, загружаем эти знания в SWI Prolog и задаем вопросы интерпретатору. Так мы будем решать поставленную задачу. (Даже видно, в начале интерпретатор пишет «?- «. Это означает, что он ждет нашего вопроса, как великий мистик)

Давайте спросим «Марк изучает книгу?» На Прологе это выглядит так:

?- study(mark, book).
true.

?- 

По сути мы спросили «есть ли факт study(mark, study) в твоей базе?», на что нам Пролог лаконично ответил «true.» и продолжает ждать следующего вопроса. А давайте спросим, «изучает ли Марк документацию?»

?- study(mark, book).
true.

?- study(mark, docs).
false.

?- 

Интерпретатор сказал «false.». Это означает, что он не нашел этот факт в своей базе фактов.

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

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

% Код на прологе. Я описал 11 фактов.
% Каждый факт оканчивается точкой ".", как в русском языке, как любое утверждение.
% Комментарии начинаются с "%".
% Интерпретатор пролога игнорирует такие комментарии.
/* А это
многострочный
комментарий
*/

% Факты. 11 штук
study(mark, book). % Марк изучает книгу
study(mark, studentbook). % Марк изучает учебник
study(mark, docs). % Марк изучает доки

see(masha, mouse). % Маша видит мышь
see(masha, book). % Маша видит книгу
see(masha, notebook). % Маша видит тетрадь
see(masha, mark). % Маша видит Марка

study(misha, math). % Миша изучает матешу
study(misha, lp). % Миша изучает пролог
study(misha, docs). % Миша изучает доки
study(misha, studentbook). % Миша изучает учебник

Терминология. Объекты данных в Прологе называются термами (предполагаю, от слова «термин»). Термы бывают следующих видов:

  1. Константами. Делятся на числа и атомы. Начинаются с маленькой буквы. Числа: 1,36, 0, -1, 123.4, 0.23E-5. Атомы — это просто символы и строки: a, abc, neOdinSimvol, sTROKa. Если атом состоит из пробела, запятых и тд, то нужно их обрамлять в одинарные кавычки. Пример атома: ‘строка с пробелами, запятыми. Eto kirilicca’.

  2. Переменными. Начинаются с заглавной буквы: X, Y, Z, Peremennaya, Var.

  3. Структурами (сложные термы). Например, study(misha, lp).

  4. Списками. Пример: [X1], [Head|Tail]. Мы разберем их позже в этой статье.

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

Пролог использует методы полного перебора и обход дерева. Во время проверки условий (доказательства утверждений) Пролог заменяет переменные на конкретные значения. Через пару абзацев будут примеры.

study(mark, book). — такие конструкции называются фактами. Они всегда истинны. Если факта в базе знаний нету, то такой факт ложный. Факты нужно оканчивать точкой, так же как утверждения в русском языке.

«Задавать вопросы Прологу» означает попросить Пролог доказать наше утверждение. Пример: ?- study(mark, book). Если наше утверждение всегда истинно, то Пролог напечатает true, если всегда ложно, то false. Если наше утверждение верно при некоторых значениях переменных, то Пролог выведет значения переменных, при которых наше утверждение верно.

Давайте загрузим факты в Пролог и будем задавать вопросы. Давайте узнаем, что изучал mark. Для этого нам нужно написать «study(mark, X).» Если мы прожмем «Enter«, то Пролог нам выдаст первое попавшееся решение

?- study(mark, X).
X = book .

Чтобы получить все возможные решения, нужно прожимать точку с запятой «;«.

?- study(mark, X).
X = book ;
X = studentbook ;
X = docs.

Можем узнать, кто изучал документацию.

?- study(Who, docs).
Who = mark ;
Who = misha.

Можно узнать, кто и что изучал!

?- study(Who, Object).
Who = mark,
Object = book ;
Who = mark,
Object = studentbook ;
Who = mark,
Object = docs ;
Who = misha,
Object = math ;
Who = misha,
Object = lp ;
Who = misha,
Object = docs ;
Who = misha,
Object = studentbook.

Пролог проходится по всей базе фактов и находит все такие переменные Who и Object, что предикат study(Who, Object) будет истинным. Пролог перебирает факты и заменяет переменные на конкретные значения. Пролог выведет такие значения переменных, при которых утверждения будут истинными. У нас задача состояла только из фактов, и решение получилось очевидным.
Переменная Who перебирается среди имен mark, misha, а переменная Object среди book, studentbook, docs, lp, math.
Who не может равняться masha, потому что masha ничего не узнала согласно нашей базе фактов. Аналогично Object не может равняться tomuChevoNetuVBaze, так как такого значения не было в базе фактов. Для study на втором месте были только book, studentbook, docs, lp, math.

Короче, я старался понятным языком объяснить метод полного перебора, и что Пролог тупо все перебирает, пока что-то не подойдет. Все просто.

А теперь разберем правила в Прологе. Напишем ещё одну программу old.pl.

% Это факты
older(sasha, lesha). % Саша старше Лёши
older(misha, sasha). % Миша старше Саши
older(misha, dasha). % Миша старше Даши
older(masha, misha). % Маша старше Миши

% Это правило
older(X,Y) :- older(X, Z), older(Z,Y).

% X старше Y, если X старше Z и Z старше Y
% Проще: X > Y, если X > Z и Z > Y
%
% X, Y, Z - это переменные. 
% Вместо X, Y, Z подставляются конкретные значения: misha, dasha, sasha, lesha
% Main idea: если Пролог найдет среднего Z, который между X и Y, то X старше Y.

older(X,Y) :- older(X, Z), older(Z,Y) — такие конструкции называются правилами. Чтобы из факта получить правило, нужно заменить точку «.» на двоеточие дефис «:-» и написать условие, когда правило будет истинным. Правила истинны только при определенных условиях. Например, это правило будет истинно в случае, когда факты older(X,Z) и older(Z,Y) истинны. Если переформулировать, то получается «X старше Y, если X старше Z и Z старше Y». Если математически: «X > Y, если X > Z и Z > Y».

Запятая «,» в Прологе играет роль логического «И». Пример: «0 < X, X < 5». X меньше 5 И больше 0.
Точка с запятой «;» играет роль логического «ИЛИ». «X < 0; X > 5». X меньше 0 ИЛИ больше 5.
Отрицание «not(Какой-нибудь предикат)» играет роль логического «НЕ». «not(X==5)». X НЕ равен 5.

Факты и правила образуют утверждения, предикаты. (хорошая статья про предикаты)

Сперва закомментируйте правило и поспрашивайте Пролог, кто старше кого.

?- older(masha, X).
X = misha.

Маша старше Миши. Пролог просто прошелся по фактам и нашел единственное верный факт. Но.. мы хотели узнать «Кого старше Маша?». Логично же, что если Миша старше Саши И Маша старше Миши, то Маша также старше Саши. И Пролог должен решать такие логические задачи. Поэтому нужно добавить правило older(X,Y) :- older(X, Z), older(Z,Y).
Повторим вопрос.

?- older(masha, X).
X = misha ;
X = sasha ;
X = dasha ;
X = lesha ;
ERROR: Stack limit (1.0Gb) exceeded
ERROR:   Stack sizes: local: 1.0Gb, global: 21Kb, trail: 1Kb
ERROR:   Stack depth: 12,200,525, last-call: 0%, Choice points: 6
ERROR:   Probable infinite recursion (cycle):
ERROR:     [12,200,525] user:older(lesha, _5658)
ERROR:     [12,200,524] user:older(lesha, _5678)
?- 

Программа смогла найти все решения. Но что это такое? Ошибка! Стек переполнен! Как вы думаете, с чем это может быть связано? Попробуйте подумать, почему это происходит. Хорошее упражнение — расписать на бумаге алгоритм older(masha,X) так, как будто вы — Пролог. Видите причину ошибки?

Это связано с бесконечной рекурсией. Это частая ошибка, которая возникает в программировании, в частности, на Прологе. older(X, Y) вызывает новый предикат older(X,Z), который в свою очередь вызывает следующий предикат older и так далее…
Нужно как-то остановить зацикливание. Если подумать, зачем нам проверять первый предикат «older(X, Z)» через правила? Если не нашел факт, то значит весь предикат older(X, Y) ложный (подумайте, почему).
Нужно объяснить Прологу, что факты и правила нужно проверять во второй части older(Z, Y), а в первой older(X, Y) — только факты
Нужно объяснить Прологу, что если он в первый раз не смог найти нужный факт, то ему не нужно приступать к правилу. Нам нужно как-то объяснить Прологу, где факт, а где правило.
Это задачу можно решить, добавив к предикатам ещё один аргумент, который будет показывать — это правило или факт.

% Это факты
older(sasha, lesha, fact). % Саша старше Лёши
older(misha, sasha, fact). % Миша старше Саши
older(misha, dasha, fact). % Миша старше Даши
older(masha, misha, fact). % Маша старше Миши

% Это правило
older(X,Y, rule) :- older(X, Z, fact), older(Z,Y, _).

% X старше Y, если X старше Z и Z старше Y
% Проще: X > Y, если X > Z и Z > Y
%
% X, Y, Z - это переменные.
% Пролог перебирает все возможные X, Y, Z. 
% Вместо X, Y, Z подставляются misha, dasha, sasha, lesha
% Например: Миша старше Лёши, если Миша старше Саши и Саша старше Лёши

Нижнее подчеркивание «_» — это анонимная переменная. Её используют, когда нам не важно, какое значение будет на её месте. Нам важно, чтобы первая часть правила была фактом. А вторая часть может быть любой.

Запустим код.

?- older(masha, X, _).
X = misha ;
X = sasha ;
X = dasha ;
X = lesha ;
false.

Наша программа вывела все верные ответы.

Возможно, возникает вопрос: откуда Пролог знает, что изучает Марк и что Миша старше Даши? Как он понимает такие человеческие понятия? Почему ассоциируется study(mark, math) с фразой «Марк изучает математику»? Почему не с «математика изучает Марка»?. Это наше представление. Мы договорились, что пусть первый терм будет обозначать «субъект», сам предикат «взаимосвязь», а второй терм «объект». Мы могли бы воспринимать по-другому. Это просто договеренность о том, как воспринимать предикаты. Пролог позволяет нам абстрактно описать взаимоотношения между термами.

Напишем предикат для нахождения факториала от N.

factorial(1, 1).
factorial(N, F):-
	N1 is N-1,
	factorial(N1, F1),
  F is F1*N.

% В Прологе пробелы, табуляция и новые строки работают также, как C/C++.
% Главное в конце закончить предикат точкой.

«is» означает присвоить, т.е N1 будет равняться N-1. Присвоение значений переменным Пролога называется унификацией. «is» работает только для чисел. Чтобы можно было присваивать атомы, нужно вместо «is» использовать «=».

Зададим запросы. Здесь стоит прожимать Enter, чтобы получить первое решение и не попасть в бесконечный цикл.

?- factorial(1,F).
F = 1 .

?- factorial(2,F).
F = 2 .

?- factorial(3,F).
F = 6 .

?- factorial(4,F).
F = 24 .

?- factorial(5,F).
F = 120 .

?- factorial(10,F).
F = 3628800 .

Можно улучшить, добавив дополнительное условие, что N должно быть больше или равно 0. Тогда наше решение точно не попадет в бесконечный цикл.

factorial(1, 1).
factorial(N, F):-
  N >= 0,
	N1 is N-1,
	factorial(N1, F1),
  F is F1*N.

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

  1. Описать свое генеалогическое древо на предикатах female(X), male(X) и parent(X,Y).

  2. Написать предикат нахождения N числа ряда Фибоначчи.

  3. Описать дерево (граф без циклов) и найти, с какими вершинами связанная заданная вершина.

Списки в Prolog

Списки — важная структура в Прологе. Списки позволяют хранить произвольное количество данных. Связный список — структура данных, состоящая из узлов. Узел содержит данные и ссылку (указатель, связку) на один или два соседних узла. Списки языка Prolog являются односвязными, т.е. каждый узел содержит лишь одну ссылку. Приложу наглядную картинку.

Кстати, ещё одна хорошая статья про списки в Прологе.

Списки в Прологе отличаются от списков в C/C++, Python и других процедурных языков. Здесь список — это либо пустой элемент; либо один элемент, называемый головой, и присоединенный список — хвост. Список — это рекурсивная структура данных с последовательным доступом.

Списки выглядят так: [],[a], [abc, bc], [‘Слово 1’, ‘Слово 2’, 1234], [X], [Head|Tail].
Рассмотрим [Head|Tail]. Это всё список, в котором мы выделяем первый элемент, голову списка, и остальную часть, хвост списка. Чтобы отделить первые элементы от остальной части списка, используется прямая черта «|».
Можно было написать такой список [X1,X2,X3|Tail]. Тогда мы выделим первые три элемента списка и положим их в X1, X2, X3, а остальная часть списка будет в Tail.

В списках хранятся данные, и нам нужно с ними работать. Например, находить минимум, максимум, медиану, среднее, дисперсию. Может нужно найти длину списка, длину самого длинного атома, получить средний балл по N предмету среди студентов группы G. Может нужно проверить, есть ли элемент Elem в списке List. И так далее. Короче, нужно как-то работать со списками. Только предикаты могут обрабатывать списки (да и в целом в Прологе все обрабатывается предикатами).

Напишем предикат для перебора элементов списка, чтобы понять принцип работы списка.

% element(Список, Элемент)
element([Head|Tail], Element) :- Element = Head; element(Tail, Element). 

?- element([1,2,3,4,5,6, 'abc', 'prolog'], Elem).
Elem = 1 ;
Elem = 2 ;
Elem = 3 ;
Elem = 4 ;
Elem = 5 ;
Elem = 6 ;
Elem = abc ;
Elem = prolog ;
false.

element([Head|Tail],Element) будет истинным, если Element равен Head (первому элементу списка) ИЛИ если предикат element(Tail, Element) истинный. В какой-то момент эта рекурсия окончится. (Вопрос читателю: когда кончится рекурсия? Какое условие будет терминирующим?) Таким образом, предикат будет истинным, если Element будет равен каждому элементу списка [Head|Tail]. Пролог найдет все решения, и мы переберем все элементы списка.

Часто бывает нужным знать длину списка. Напишем предикат для нахождения длины списка. Протестим.

% list_length(Список, Длина списка)
list_length([], 0).
list_length([H|T], L) :- list_length(T, L1), L is L1+1.

?- list_length([123446,232,2332,23], L).
L = 4.

?- list_length([123446,232,2332,23,sdfds,sdfsf,sdfa,asd], L).
L = 8.

?- list_length([], L).
L = 0.

?- list_length([1], L).
L = 1.

?- list_length([1,9,8,7,6,5,4,3,2], L).
L = 9.

Мой Пролог предупреждает, что была не использована переменная H. Код будет работать, но лучше использовать анонимную переменную _, вместо singleton переменной.

В SWI Prolog имеется встроенный предикат length. Я реализовал аналогичный предикат list_length. Если встречается пустой список, то его длина равна нулю. Иначе отсекается голова списка, рекурсивно определяется длина нового получившегося списка и к результату прибавляется единица.

Чтобы лучше понять алгоритм, пропишите его на бумаге. Последовательно, так, как делает Пролог.

Последняя задача про списки в этой статье, это определить, принадлежит ли элемент списку. Например, 1, 2, 3 и 4 являются элементами списка [1,2,3,4]. Этот предикат мы назовем list_member.

mymember(Elem, [Elem|_]).
mymember(Elem, [_|Tail]) :- mymember(Elem, Tail).

Очевидно, что если список начинается с искомого элемента, то элемент принадлежит списку. В противном случае необходимо отсечь голову списка и рекурсивно проверить наличие элемента в новом получившемся списке.

Преимущества и недостатки Prolog

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

Список задач, в которых Пролог удобен:

  • Искусственный интеллект

  • Компьютерная лингвистика. Написание стихов, анализ речи

  • Поиск пути в графе. Работа с графами

  • Логические задачи

  • Нечисловое программирование

Знаменитую логическую задачу Эйнштейна можно гораздо легче решить на Прологе, чем на любом другом императивном языке. Одна из вариаций такой задачи:

Задача Эйнштейна

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

  1. Англичанин живёт в красном доме.

  2. У испанца есть собака.

  3. В зелёном доме пьют кофе.

  4. Украинец пьёт чай.

  5. Зелёный дом стоит сразу справа от белого дома.

  6. Скульптор разводит улиток.

  7. В жёлтом доме живет математик.

  8. В центральном доме пьют молоко.

  9. Норвежец живёт в первом доме.

  10. Сосед поэта держит лису.

  11. В доме по соседству с тем, в котором держат лошадь, живет математик.

  12. Музыкант пьёт апельсиновый сок.

  13. Японец программист.

  14. Норвежец живёт рядом с синим домом.

Кто пьёт воду? Кто держит зебру?

Замечание: в утверждении 6 справа означает справа относительно вас.

Научиться решать логические задачи на Пролог, можно по этой статье.
Ещё одна интересная статья. В ней автор пишет программу сочинитель стихов на Prolog.

Интересная задача, которую вы можете решить на Прологе: раскрасить граф наименьшим количеством цветов так, чтобы смежные вершины были разного цвета.

Иллюстрация к задаче

Иллюстрация к задаче

Пролог такой замечательный язык! Но почему его крайне редко используют?
Я вижу две причины:

  1. Производительность

  2. Альтернативы (например, нейросетей на Python)

Пролог решает задачи методом полного перебора. Следовательно, его сложность растет как O(n!). Конечно, можно использовать отсечения, например, с помощью «!». Но все равно сложность останется факториальной. Простые задачи не так интересны, а сложные лучше реализовать жадным алгоритмом на императивном языке.

Области, для которых предназначен Пролог, могут также успешно решаться с помощью Python, C/C++, C#, Java, нейросетей. Например, сочинение стихов, анализ речи, поиск пути в графе и так далее.

Я не могу сказать, что логическое программирование не нужно. Оно действительно развивает логическое мышление. Элементы логического программирования можно встретить на практике. И в принципе, логическое программирование — интересная парадагима, которую полезно знать, например, специалистам ИИ.

Что дальше?

Я понимаю, что статью я написал суховато и слишком «логично» (вероятно, влияние Пролога). Я надеюсь, статья вам помогла в изучении основ Логического Программирования на примере Пролога.

(Мои мысли: я часто использую повторения в статье. Это не сочинение, это туториал. Лучше не плодить ненужные синонимы и чаще использовать термины. По крайней мере, в туториалах. Так лучше запоминается. Повторение — мать учения. А как вы считаете?).

Это моя дебютная статья, и я буду очень рад конструктивной критике. Задавайте вопросы, пишите комментарии, я постараюсь отвечать на них. В конце статьи я приведу все ссылки, которые я упоминал и которые мне показались полезными.

Статью написал Горохов Михаил, успехов в обучении и в работе!

Ссылки

  1. Ссылка на скачивание SWI Prolog

  2. Синтаксис Пролога и его терминология

  3. Предикаты в Пролог

  4. Списки в Пролог

  5. Логические задачи

  6. Сочинение стихов с помощью Пролог

  7. И конечно же ссылка на Википедию

  8. Слышали о Пролог?

  9. Примеры использования Пролог

Рекомендации по настройке программы «ПРОЛОГ» Логика. Видео

◎ Видео-обзор и рекомендации по настройке и эксплуатации программы «ПРОЛОГ» для работы с приборами СПТ / СПГ Логика

В данной видео инструкции можно узнать о том, как работать с тепловычислителем СПТ940 при помощи программы «ПРОЛОГ», предназначенной для получения и хранения данных приборов учета ЛОГИКА, а также вывода данных в виде таблиц и отчетов необходимого формата.

Темы и разделы видео-инструкции

  • С чего начать работу с программой ПРОЛОГ
  • Как прочитать архивы с СПТ940
  • Как сформировать отчет
  • Как отредактировать отчет (редактор отчетов)
  • Подключение последовательного порта
  • Монитор текущих значений прибора учета
  • Тепловычислитель СПТ 940, Логика

    Скидка -3%

  • Тепловычислитель СПТ 941.20, Логика

    Скидка -3%

  • Тепловычислитель СПТ 944, Логика

    Скидка -3%

  • Корректор газа СПГ 742, Логика

    Скидка -3%

Смотреть видео-обзор

Работа с программой «ПРОЛОГ», Логика

☞ Скачать программу «ПРОЛОГ» можно на нашем сайте, здесь.

Эта информация оказалась полезной?

Евгений Орлов (Тех. менеджер)

Оцените статью

( Пока нет оценок )

Время на прочтение
14 мин

Количество просмотров 53K

Prolog - самый популярный язык логического программирования
Prolog — самый популярный язык логического программирования

В этой статье:

  1. Узнаем, что такое логическое программирование (ЛП), и его области применения

  2. Установим самый популярный язык ЛП — Prolog

  3. Научимся писать простые программы на Prolog

  4. Научимся спискам в Prolog

  5. Разберем преимущества и недостатки Prolog.

Эта статья будет полезна для тех, кто:

  1. Интересуется необычными подходами и расширяет свой кругозор

  2. Начинает изучать Prolog (например, в институте)

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

В конце статьи я оставлю полезные ссылки. Если у вас останутся вопросы — пишите в комментариях!

Начнем туториал: Пролог для чайников!

Логическое программирование

Существуют разные подходы к программированию. Часто выделяют такие парадигмы программирования:

  • Императивное (оно же алгоритмическое или процедурное). Самая известная парадигма. Программист четко прописывает последовательность команд, которые должен выполнить процессор. Примеры: C/C++, Java, C#, Python, Golang, машина Тюрьнга, алгоритмы Маркова. Все четко, последовательно как надо. Синоним императивного — приказательное.

  • Аппликативное (Функциональное). Менее известная, но тоже широко используемая. Примеры языков: Haskell, F#, Лисп. Основывается на математической абстракции лямбда вычислениях. Благодаря чистым функциям очень удобно параллелить такие программы. Чистые функции — функции без побочных эффектов. Если такой функции передавать одни и те же аргументы, то результат всегда будет один и тот же. Такие языки обладают высокой надежностью кода.

  • И наконец — Декларативное (Логическое). Основывается на автоматическом доказательстве теорем на основе фактов и правил. Примеры языков: Prolog и его диалекты, Mercury. В таких языках мы описываем пространство состояний, в которых сам язык ищет решение к задаче. Мы просто даем ему правила, факты, а потом говорим, что «сочини все возможные стихи из этих слов», «реши логическую задачу», «найди всех братьев, сестер, золовок, свояков в генеалогическом древе», или «раскрась граф наименьшим кол-вом цветов так, что смежные ребра были разного цвета».

    Что такое ЛП я обозначил. Предлагаю сразу перейти к практике, к основам Prolog (PROgramming in LOGic). На практике все становится понятнее. Практику и теорию я буду чередовать. Не беспокойтесь, если сразу будет что-то не понятно. Повторяйте за мной, и вы разберетесь.

Установка Prolog

Существую разные реализации (имплементации) Пролога: SWI Prolog, Visual Prolog, GNU Prolog. Мы установим SWI Prolog.

Установка на Arch Linux:

sudo pacman -S swi-prolog

Установка на Ubuntu:

sudo apt install swi-prolog

Prolog работает в режиме интерпретатора. Теперь можем запустить SWI Prolog. Запускать не через swi-prolog, а через swipl:

[user@Raft ~]$ swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 8.2.3)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- 

Ура! Оно работает!

Теперь поставим на Windows.
Перейдем на официальный сайт на страницу скачивания стабильной версии. Ссылка на скачивание. Клик. Скачаем 64х битную версию. Установка стандартная. Чтобы ничего не сломать, я решил галочки не снимать. Ради приличия я оставлю скрины установки.

Сайт SWI Prolog - установщики последней стабильной версии

Сайт SWI Prolog — установщики последней стабильной версии
Галочки не трогаем
Галочки не трогаем
Ищу SWI-Prolog через поиск Windows. Запускаю
Ищу SWI-Prolog через поиск Windows. Запускаю
Ура! Теперь и на Windows все работает
Ура! Теперь и на Windows все работает

Основы Prolog. Факты, правила, предикаты

Есть утверждения, предикаты:

  • Марк изучает книгу (учебник, документацию)

  • Маша видит клавиатуру (мышку, книгу, тетрадь, Марка)

  • Миша изучает математику (ЛП, документацию, учебник)

  • Саша старше Лёши

С английского «predicate» означает «логическое утверждение».

Есть объекты: книга, клавиатура, мышка, учебник, документация, тетрадь, математика, ЛП, Марк, Маша, Саша, Даша, Лёша, Миша, да что угодно может быть объектом.
Есть отношения между объектами, т.е то, что связывает объекты. Связь объектов можно выразить через глаголы, например: читать, видеть, изучать. Связь можно выразить через прилагательное. Миша старше Даши. Даша старше Лёши. Получается.. связью может быть любая часть речь? Получается так.

Прекрасно! Давайте попробуем запрограммировать эти утверждения на Прологе. Для этого нам нужно:

  1. Создать новый текстовый файл, который я назову simple.pl (.pl — расширение Пролога)

  2. В нем написать простой однострочный код на Прологе

  3. Запустить код с помощью SWI Prolog

  4. Спросить у Пролога этот факт

Файл simple.pl:

study(mark, book).

Запустим. На линуксе это делается таким образом:

[user@Raft referat]$ swipl simple.pl 
Welcome to SWI-Prolog (threaded, 64 bits, version 8.2.3)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- 

На Windows я использую notepad++ для написания кода на Прологе. Я запущу SWI-Prolog и открою файл через consult.

Видим, что он скомпилировал условия. Даже написал "1 clauses", т.е один факт

Видим, что он скомпилировал условия. Даже написал «1 clauses», т.е один факт

Что мы сделали? Мы загрузили базу знаний (те, которые мы описали в простом однострочном файле simple.pl) и теперь можем задавать вопросы Прологу. То есть система такая: пишем знания в файле, загружаем эти знания в SWI Prolog и задаем вопросы интерпретатору. Так мы будем решать поставленную задачу. (Даже видно, в начале интерпретатор пишет «?- «. Это означает, что он ждет нашего вопроса, как великий мистик)

Давайте спросим «Марк изучает книгу?» На Прологе это выглядит так:

?- study(mark, book).
true.

?- 

По сути мы спросили «есть ли факт study(mark, study) в твоей базе?», на что нам Пролог лаконично ответил «true.» и продолжает ждать следующего вопроса. А давайте спросим, «изучает ли Марк документацию?»

?- study(mark, book).
true.

?- study(mark, docs).
false.

?- 

Интерпретатор сказал «false.». Это означает, что он не нашел этот факт в своей базе фактов.

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

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

% Код на прологе. Я описал 11 фактов.
% Каждый факт оканчивается точкой ".", как в русском языке, как любое утверждение.
% Комментарии начинаются с "%".
% Интерпретатор пролога игнорирует такие комментарии.
/* А это
многострочный
комментарий
*/

% Факты. 11 штук
study(mark, book). % Марк изучает книгу
study(mark, studentbook). % Марк изучает учебник
study(mark, docs). % Марк изучает доки

see(masha, mouse). % Маша видит мышь
see(masha, book). % Маша видит книгу
see(masha, notebook). % Маша видит тетрадь
see(masha, mark). % Маша видит Марка

study(misha, math). % Миша изучает матешу
study(misha, lp). % Миша изучает пролог
study(misha, docs). % Миша изучает доки
study(misha, studentbook). % Миша изучает учебник

Терминология. Объекты данных в Прологе называются термами (предполагаю, от слова «термин»). Термы бывают следующих видов:

  1. Константами. Делятся на числа и атомы. Начинаются с маленькой буквы. Числа: 1,36, 0, -1, 123.4, 0.23E-5. Атомы — это просто символы и строки: a, abc, neOdinSimvol, sTROKa. Если атом состоит из пробела, запятых и тд, то нужно их обрамлять в одинарные кавычки. Пример атома: ‘строка с пробелами, запятыми. Eto kirilicca’.

  2. Переменными. Начинаются с заглавной буквы: X, Y, Z, Peremennaya, Var.

  3. Структурами (сложные термы). Например, study(misha, lp).

  4. Списками. Пример: [X1], [Head|Tail]. Мы разберем их позже в этой статье.

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

Пролог использует методы полного перебора и обход дерева. Во время проверки условий (доказательства утверждений) Пролог заменяет переменные на конкретные значения. Через пару абзацев будут примеры.

study(mark, book). — такие конструкции называются фактами. Они всегда истинны. Если факта в базе знаний нету, то такой факт ложный. Факты нужно оканчивать точкой, так же как утверждения в русском языке.

«Задавать вопросы Прологу» означает попросить Пролог доказать наше утверждение. Пример: ?- study(mark, book). Если наше утверждение всегда истинно, то Пролог напечатает true, если всегда ложно, то false. Если наше утверждение верно при некоторых значениях переменных, то Пролог выведет значения переменных, при которых наше утверждение верно.

Давайте загрузим факты в Пролог и будем задавать вопросы. Давайте узнаем, что изучал mark. Для этого нам нужно написать «study(mark, X).» Если мы прожмем «Enter«, то Пролог нам выдаст первое попавшееся решение

?- study(mark, X).
X = book .

Чтобы получить все возможные решения, нужно прожимать точку с запятой «;«.

?- study(mark, X).
X = book ;
X = studentbook ;
X = docs.

Можем узнать, кто изучал документацию.

?- study(Who, docs).
Who = mark ;
Who = misha.

Можно узнать, кто и что изучал!

?- study(Who, Object).
Who = mark,
Object = book ;
Who = mark,
Object = studentbook ;
Who = mark,
Object = docs ;
Who = misha,
Object = math ;
Who = misha,
Object = lp ;
Who = misha,
Object = docs ;
Who = misha,
Object = studentbook.

Пролог проходится по всей базе фактов и находит все такие переменные Who и Object, что предикат study(Who, Object) будет истинным. Пролог перебирает факты и заменяет переменные на конкретные значения. Пролог выведет такие значения переменных, при которых утверждения будут истинными. У нас задача состояла только из фактов, и решение получилось очевидным.
Переменная Who перебирается среди имен mark, misha, а переменная Object среди book, studentbook, docs, lp, math.
Who не может равняться masha, потому что masha ничего не узнала согласно нашей базе фактов. Аналогично Object не может равняться tomuChevoNetuVBaze, так как такого значения не было в базе фактов. Для study на втором месте были только book, studentbook, docs, lp, math.

Короче, я старался понятным языком объяснить метод полного перебора, и что Пролог тупо все перебирает, пока что-то не подойдет. Все просто.

А теперь разберем правила в Прологе. Напишем ещё одну программу old.pl.

% Это факты
older(sasha, lesha). % Саша старше Лёши
older(misha, sasha). % Миша старше Саши
older(misha, dasha). % Миша старше Даши
older(masha, misha). % Маша старше Миши

% Это правило
older(X,Y) :- older(X, Z), older(Z,Y).

% X старше Y, если X старше Z и Z старше Y
% Проще: X > Y, если X > Z и Z > Y
%
% X, Y, Z - это переменные. 
% Вместо X, Y, Z подставляются конкретные значения: misha, dasha, sasha, lesha
% Main idea: если Пролог найдет среднего Z, который между X и Y, то X старше Y.

older(X,Y) :- older(X, Z), older(Z,Y) — такие конструкции называются правилами. Чтобы из факта получить правило, нужно заменить точку «.» на двоеточие дефис «:-» и написать условие, когда правило будет истинным. Правила истинны только при определенных условиях. Например, это правило будет истинно в случае, когда факты older(X,Z) и older(Z,Y) истинны. Если переформулировать, то получается «X старше Y, если X старше Z и Z старше Y». Если математически: «X > Y, если X > Z и Z > Y».

Запятая «,» в Прологе играет роль логического «И». Пример: «0 < X, X < 5». X меньше 5 И больше 0.
Точка с запятой «;» играет роль логического «ИЛИ». «X < 0; X > 5». X меньше 0 ИЛИ больше 5.
Отрицание «not(Какой-нибудь предикат)» играет роль логического «НЕ». «not(X==5)». X НЕ равен 5.

Факты и правила образуют утверждения, предикаты. (хорошая статья про предикаты)

Сперва закомментируйте правило и поспрашивайте Пролог, кто старше кого.

?- older(masha, X).
X = misha.

Маша старше Миши. Пролог просто прошелся по фактам и нашел единственное верный факт. Но.. мы хотели узнать «Кого старше Маша?». Логично же, что если Миша старше Саши И Маша старше Миши, то Маша также старше Саши. И Пролог должен решать такие логические задачи. Поэтому нужно добавить правило older(X,Y) :- older(X, Z), older(Z,Y).
Повторим вопрос.

?- older(masha, X).
X = misha ;
X = sasha ;
X = dasha ;
X = lesha ;
ERROR: Stack limit (1.0Gb) exceeded
ERROR:   Stack sizes: local: 1.0Gb, global: 21Kb, trail: 1Kb
ERROR:   Stack depth: 12,200,525, last-call: 0%, Choice points: 6
ERROR:   Probable infinite recursion (cycle):
ERROR:     [12,200,525] user:older(lesha, _5658)
ERROR:     [12,200,524] user:older(lesha, _5678)
?- 

Программа смогла найти все решения. Но что это такое? Ошибка! Стек переполнен! Как вы думаете, с чем это может быть связано? Попробуйте подумать, почему это происходит. Хорошее упражнение — расписать на бумаге алгоритм older(masha,X) так, как будто вы — Пролог. Видите причину ошибки?

Это связано с бесконечной рекурсией. Это частая ошибка, которая возникает в программировании, в частности, на Прологе. older(X, Y) вызывает новый предикат older(X,Z), который в свою очередь вызывает следующий предикат older и так далее…
Нужно как-то остановить зацикливание. Если подумать, зачем нам проверять первый предикат «older(X, Z)» через правила? Если не нашел факт, то значит весь предикат older(X, Y) ложный (подумайте, почему).
Нужно объяснить Прологу, что факты и правила нужно проверять во второй части older(Z, Y), а в первой older(X, Y) — только факты
Нужно объяснить Прологу, что если он в первый раз не смог найти нужный факт, то ему не нужно приступать к правилу. Нам нужно как-то объяснить Прологу, где факт, а где правило.
Это задачу можно решить, добавив к предикатам ещё один аргумент, который будет показывать — это правило или факт.

% Это факты
older(sasha, lesha, fact). % Саша старше Лёши
older(misha, sasha, fact). % Миша старше Саши
older(misha, dasha, fact). % Миша старше Даши
older(masha, misha, fact). % Маша старше Миши

% Это правило
older(X,Y, rule) :- older(X, Z, fact), older(Z,Y, _).

% X старше Y, если X старше Z и Z старше Y
% Проще: X > Y, если X > Z и Z > Y
%
% X, Y, Z - это переменные.
% Пролог перебирает все возможные X, Y, Z. 
% Вместо X, Y, Z подставляются misha, dasha, sasha, lesha
% Например: Миша старше Лёши, если Миша старше Саши и Саша старше Лёши

Нижнее подчеркивание «_» — это анонимная переменная. Её используют, когда нам не важно, какое значение будет на её месте. Нам важно, чтобы первая часть правила была фактом. А вторая часть может быть любой.

Запустим код.

?- older(masha, X, _).
X = misha ;
X = sasha ;
X = dasha ;
X = lesha ;
false.

Наша программа вывела все верные ответы.

Возможно, возникает вопрос: откуда Пролог знает, что изучает Марк и что Миша старше Даши? Как он понимает такие человеческие понятия? Почему ассоциируется study(mark, math) с фразой «Марк изучает математику»? Почему не с «математика изучает Марка»?. Это наше представление. Мы договорились, что пусть первый терм будет обозначать «субъект», сам предикат «взаимосвязь», а второй терм «объект». Мы могли бы воспринимать по-другому. Это просто договеренность о том, как воспринимать предикаты. Пролог позволяет нам абстрактно описать взаимоотношения между термами.

Напишем предикат для нахождения факториала от N.

factorial(1, 1).
factorial(N, F):-
	N1 is N-1,
	factorial(N1, F1),
  F is F1*N.

% В Прологе пробелы, табуляция и новые строки работают также, как C/C++.
% Главное в конце закончить предикат точкой.

«is» означает присвоить, т.е N1 будет равняться N-1. Присвоение значений переменным Пролога называется унификацией. «is» работает только для чисел. Чтобы можно было присваивать атомы, нужно вместо «is» использовать «=».

Зададим запросы. Здесь стоит прожимать Enter, чтобы получить первое решение и не попасть в бесконечный цикл.

?- factorial(1,F).
F = 1 .

?- factorial(2,F).
F = 2 .

?- factorial(3,F).
F = 6 .

?- factorial(4,F).
F = 24 .

?- factorial(5,F).
F = 120 .

?- factorial(10,F).
F = 3628800 .

Можно улучшить, добавив дополнительное условие, что N должно быть больше или равно 0. Тогда наше решение точно не попадет в бесконечный цикл.

factorial(1, 1).
factorial(N, F):-
  N >= 0,
	N1 is N-1,
	factorial(N1, F1),
  F is F1*N.

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

  1. Описать свое генеалогическое древо на предикатах female(X), male(X) и parent(X,Y).

  2. Написать предикат нахождения N числа ряда Фибоначчи.

  3. Описать дерево (граф без циклов) и найти, с какими вершинами связанная заданная вершина.

Списки в Prolog

Списки — важная структура в Прологе. Списки позволяют хранить произвольное количество данных. Связный список — структура данных, состоящая из узлов. Узел содержит данные и ссылку (указатель, связку) на один или два соседних узла. Списки языка Prolog являются односвязными, т.е. каждый узел содержит лишь одну ссылку. Приложу наглядную картинку.

Кстати, ещё одна хорошая статья про списки в Прологе.

Списки в Прологе отличаются от списков в C/C++, Python и других процедурных языков. Здесь список — это либо пустой элемент; либо один элемент, называемый головой, и присоединенный список — хвост. Список — это рекурсивная структура данных с последовательным доступом.

Списки выглядят так: [],[a], [abc, bc], [‘Слово 1’, ‘Слово 2’, 1234], [X], [Head|Tail].
Рассмотрим [Head|Tail]. Это всё список, в котором мы выделяем первый элемент, голову списка, и остальную часть, хвост списка. Чтобы отделить первые элементы от остальной части списка, используется прямая черта «|».
Можно было написать такой список [X1,X2,X3|Tail]. Тогда мы выделим первые три элемента списка и положим их в X1, X2, X3, а остальная часть списка будет в Tail.

В списках хранятся данные, и нам нужно с ними работать. Например, находить минимум, максимум, медиану, среднее, дисперсию. Может нужно найти длину списка, длину самого длинного атома, получить средний балл по N предмету среди студентов группы G. Может нужно проверить, есть ли элемент Elem в списке List. И так далее. Короче, нужно как-то работать со списками. Только предикаты могут обрабатывать списки (да и в целом в Прологе все обрабатывается предикатами).

Напишем предикат для перебора элементов списка, чтобы понять принцип работы списка.

% element(Список, Элемент)
element([Head|Tail], Element) :- Element = Head; element(Tail, Element). 

?- element([1,2,3,4,5,6, 'abc', 'prolog'], Elem).
Elem = 1 ;
Elem = 2 ;
Elem = 3 ;
Elem = 4 ;
Elem = 5 ;
Elem = 6 ;
Elem = abc ;
Elem = prolog ;
false.

element([Head|Tail],Element) будет истинным, если Element равен Head (первому элементу списка) ИЛИ если предикат element(Tail, Element) истинный. В какой-то момент эта рекурсия окончится. (Вопрос читателю: когда кончится рекурсия? Какое условие будет терминирующим?) Таким образом, предикат будет истинным, если Element будет равен каждому элементу списка [Head|Tail]. Пролог найдет все решения, и мы переберем все элементы списка.

Часто бывает нужным знать длину списка. Напишем предикат для нахождения длины списка. Протестим.

% list_length(Список, Длина списка)
list_length([], 0).
list_length([H|T], L) :- list_length(T, L1), L is L1+1.

?- list_length([123446,232,2332,23], L).
L = 4.

?- list_length([123446,232,2332,23,sdfds,sdfsf,sdfa,asd], L).
L = 8.

?- list_length([], L).
L = 0.

?- list_length([1], L).
L = 1.

?- list_length([1,9,8,7,6,5,4,3,2], L).
L = 9.

Мой Пролог предупреждает, что была не использована переменная H. Код будет работать, но лучше использовать анонимную переменную _, вместо singleton переменной.

В SWI Prolog имеется встроенный предикат length. Я реализовал аналогичный предикат list_length. Если встречается пустой список, то его длина равна нулю. Иначе отсекается голова списка, рекурсивно определяется длина нового получившегося списка и к результату прибавляется единица.

Чтобы лучше понять алгоритм, пропишите его на бумаге. Последовательно, так, как делает Пролог.

Последняя задача про списки в этой статье, это определить, принадлежит ли элемент списку. Например, 1, 2, 3 и 4 являются элементами списка [1,2,3,4]. Этот предикат мы назовем list_member.

mymember(Elem, [Elem|_]).
mymember(Elem, [_|Tail]) :- mymember(Elem, Tail).

Очевидно, что если список начинается с искомого элемента, то элемент принадлежит списку. В противном случае необходимо отсечь голову списка и рекурсивно проверить наличие элемента в новом получившемся списке.

Преимущества и недостатки Prolog

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

Список задач, в которых Пролог удобен:

  • Искусственный интеллект

  • Компьютерная лингвистика. Написание стихов, анализ речи

  • Поиск пути в графе. Работа с графами

  • Логические задачи

  • Нечисловое программирование

Знаменитую логическую задачу Эйнштейна можно гораздо легче решить на Прологе, чем на любом другом императивном языке. Одна из вариаций такой задачи:

Задача Эйнштейна

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

  1. Англичанин живёт в красном доме.

  2. У испанца есть собака.

  3. В зелёном доме пьют кофе.

  4. Украинец пьёт чай.

  5. Зелёный дом стоит сразу справа от белого дома.

  6. Скульптор разводит улиток.

  7. В жёлтом доме живет математик.

  8. В центральном доме пьют молоко.

  9. Норвежец живёт в первом доме.

  10. Сосед поэта держит лису.

  11. В доме по соседству с тем, в котором держат лошадь, живет математик.

  12. Музыкант пьёт апельсиновый сок.

  13. Японец программист.

  14. Норвежец живёт рядом с синим домом.

Кто пьёт воду? Кто держит зебру?

Замечание: в утверждении 6 справа означает справа относительно вас.

Научиться решать логические задачи на Пролог, можно по этой статье.
Ещё одна интересная статья. В ней автор пишет программу сочинитель стихов на Prolog.

Интересная задача, которую вы можете решить на Прологе: раскрасить граф наименьшим количеством цветов так, чтобы смежные вершины были разного цвета.

Иллюстрация к задаче

Иллюстрация к задаче

Пролог такой замечательный язык! Но почему его крайне редко используют?
Я вижу две причины:

  1. Производительность

  2. Альтернативы (например, нейросетей на Python)

Пролог решает задачи методом полного перебора. Следовательно, его сложность растет как O(n!). Конечно, можно использовать отсечения, например, с помощью «!». Но все равно сложность останется факториальной. Простые задачи не так интересны, а сложные лучше реализовать жадным алгоритмом на императивном языке.

Области, для которых предназначен Пролог, могут также успешно решаться с помощью Python, C/C++, C#, Java, нейросетей. Например, сочинение стихов, анализ речи, поиск пути в графе и так далее.

Я не могу сказать, что логическое программирование не нужно. Оно действительно развивает логическое мышление. Элементы логического программирования можно встретить на практике. И в принципе, логическое программирование — интересная парадагима, которую полезно знать, например, специалистам ИИ.

Что дальше?

Я понимаю, что статью я написал суховато и слишком «логично» (вероятно, влияние Пролога). Я надеюсь, статья вам помогла в изучении основ Логического Программирования на примере Пролога.

(Мои мысли: я часто использую повторения в статье. Это не сочинение, это туториал. Лучше не плодить ненужные синонимы и чаще использовать термины. По крайней мере, в туториалах. Так лучше запоминается. Повторение — мать учения. А как вы считаете?).

Это моя дебютная статья, и я буду очень рад конструктивной критике. Задавайте вопросы, пишите комментарии, я постараюсь отвечать на них. В конце статьи я приведу все ссылки, которые я упоминал и которые мне показались полезными.

Статью написал Горохов Михаил, успехов в обучении и в работе!

Ссылки

  1. Ссылка на скачивание SWI Prolog

  2. Синтаксис Пролога и его терминология

  3. Предикаты в Пролог

  4. Списки в Пролог

  5. Логические задачи

  6. Сочинение стихов с помощью Пролог

  7. И конечно же ссылка на Википедию

  8. Слышали о Пролог?

  9. Примеры использования Пролог

Понравилась статья? Поделить с друзьями:
  • Винпоцетин таблетки инструкция по применению цена отзывы аналоги уколы цена
  • Ингалятор ультибро инструкция по применению цена
  • Должностная инструкция плотника в больнице рк
  • Фепразон инструкция по применению цена отзывы аналоги
  • Какой стиль руководства у директора