Как стать автором
Обновить

Немного о Prolog'е

Время на прочтение3 мин
Количество просмотров29K
Язык пролог незаслуженно обладает довольно узкой известностью, между тем это довольно интересный язык, который несомненно стоит того, чтоб познакомиться с ним.

Если честно, мне лень описывать синтаксис и особенности пролога, кому интересно, без труда найдут достаточное количество материала в интернете, благо язык довольно академичный. Скажу лишь, чем меня он заинтересовал. Дело в том, что пролог, по сути единственный язык, предлагающий качественно другой подход к программированию, чем хорошо известные императивный, ООП (который, по сути, тоже императивный, но нацелен на структурирование и модульность), функциональный. Можно назвать этот подход декларативно-логическим.
Не претендуя на точность терминологии, этот подход можно определить как такой, при котором программа представляет собой описанние теми или иными конструкциями языка программирования самого условия задачи. Роль ЯП при этом понять это описание, и сделать из него некоторый вывод, который окажется ни чем иным как правильным решением задачи.
Проиллюстрируем, что под этим подразумевается. Возьмем следующую задачу.



Условие задачи: Сократ — человек. Все люди смертны.
Найти: Смертен ли Сократ?

Запишем условие в терминах языка пролога (со знака % начинаются комментарии):
% Сократ - человек
human(sokrat).
% Платон - тоже человек
human(platon).

% Чтобы некто был смертным, он должен быть человеком
mortal(Someone) :- human(Someone).


* This source code was highlighted with Source Code Highlighter.

теперь спросим пролог систему, смертен ли Сократ:
?- mortal(sokrat).

Yes % да

?- mortal(stranger).

No % нет, поскольку пролог система не знает ничего о stranger и потому, не может ответить на вопрос

% Мы можем спросить какие смертные существа известны системе:
?- mortal(Who).

Who = platon ;

Who = sokrat


* This source code was highlighted with Source Code Highlighter.

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

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

Собственно, хочу привести для примера решение на прологе задачи о расстановке на шахматной доске 8 ферзей, так чтоб они не били друг друга, основанное на приведенном в книге Братко И. Программирование на языке ПРОЛОГ для искусственного интеллекта (кстати, очень хорошая книга, рекомендую).
% будем искать решение как набор 8 координат вида X/Y каждого из ферзей
% при этом понятно, что поскольку все вертикали так или иначе будут заняты
% задача сводится к отысканию соответствующих Y - координат
getSolution(S):-
    S=[1/_,2/_,3/_,4/_,5/_,6/_,7/_,8/_],
    solution(S).

% доска 0x0 без ферзей очевидно является решением
solution([]).

% доска NxN является решением, если является решением её под-доска (N-1)*(N-1),
% а первый ферзь не бьет ферзей на этой под-доске.
solution([X/Y | Others]) :-
    solution(Others),
    member(Y, [1, 2, 3, 4, 5, 6, 7, 8]),
    nokill(X/Y, Others).
         
% очевидно что ферзь с любыми координатами не бьет ферзей из пустого массива,
% поскольку просто некого бить
nokill(_, []).        

% ферзь не бьет набор ферзей если он не бьет первого ферзя из набора
% и не бьет остальных ферзей набора        
nokill(X/Y, [X1/Y1 | Others]) :-
    Y =\= Y1,   % на разных горизонталях  
    Y1-Y =\= X1-X, % на разных диагоналях
    Y1-Y =\= X-X1,
    nokill(X/Y, Others).


* This source code was highlighted with Source Code Highlighter.

Чтоб получить необходимые координаты ферзей, спросим у пролог системы решения, основанные на представленном описании.
1 ?- getSolution(P).

P = [1/4, 2/2, 3/7, 4/3, 5/6, 6/8, 7/5, 8/1] ;

P = [1/5, 2/2, 3/4, 4/7, 5/3, 6/8, 7/6, 8/1] ;

P = [1/3, 2/5, 3/2, 4/8, 5/6, 6/4, 7/7, 8/1] ;

P = [1/3, 2/6, 3/4, 4/2, 5/8, 6/5, 7/7, 8/1] ;

P = [1/5, 2/7, 3/1, 4/3, 5/8, 6/6, 7/4, 8/2] ;
...


* This source code was highlighted with Source Code Highlighter.


Кстати, а как это будет выглядеть на вашем любимом языке программирования? =)

Кстати, тут можно посозерцать решение той же задачи на рефале, еще одном интересном языке функционального программирования, идейно перекликающимся с прологом, кстати, создатель которого — наш соотечественник Валентин Федорович Турчин (вики).
Теги:
Хабы:
+72
Комментарии119

Публикации

Изменить настройки темы

Истории

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн