Опубликован: 12.02.2014 | Доступ: свободный | Студентов: 818 / 236 | Длительность: 11:22:00
Специальности: Программист
Лекция 16:

Использование PIE в Visual Prolog

< Лекция 15 || Лекция 16
Ключевые слова: visual, ПРОЛОГ

В настоящей главе рассматриваются основные отличия языка Visual Prolog от реализаций языка Пролог, удовлетворяющих стандарту (т. н. стандартного Пролога), связанные с унификацией термов. Кроме этого, приводится пример использования интерпретатора PIE в программе на языке Visual Prolog.

16.1. Унификация термов в стандартном Прологе

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

Например, в PIE ответ на запрос программы

less(0, _).

?- less(X, Y).

выглядит следующим образом:

X = 0, Y = _.

(в системе Visual Prolog в этом случае возбуждается исключение).

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

?- L = [_, _], L = [_, [2]], L = [1, _ | _].

имеет решение

L = [1, [2]].

Факты могут описывать данные с неполной информацией. Например, программа может иметь вид (см. листинг 2.3):

library(magazine("Компьютерра", 2, 2009)).
library(book(author("Чехов", _, _), "Избранное", _)).
library(book(author("Великова", "Людмила", "Викторовна"),
        "Русский язык", edition("Москва", "МЦНМО", 2003))).

?- library(book(author(X, _, _), Y, edition(_, _, 2003))).

Приведенная в программе цель имеет два решения:

X = "Чехов", Y = "Избранное";
X = "Великова", Y = "Русский язык".

В стандартном Прологе имеются предикаты для конструирования и анализа сложных термов arg/3 и functor/3. Аргументы этих предикатов имеют следующий смысл: arg(N, Term, Argument) и functor(Term, Functor, Arity), где N — позиция аргумента Argument в терме Term (позиции нумеруются с единицы), а Functor — это функтор арности Arity терма Term. Например,

?- arg(2, b(_, "Чайка", _), Y).
Y = "Чайка".

?- functor(T, b, 3), arg(1, T, "Чехов"), arg(3, T, ed("СПб", _, 2014)).
T = b("Чехов", _, ed("СПб", _, 2014)).

В стандартном Прологе станут более простыми и некоторые другие программы, рассмотренные ранее. Например, будет короче решение задачи "Кино" (см. п. 3.5). Из программы, приведенной в листинге 3.1, можно удалить предикат indicator, так что она примет вид:

proposition(1, A, B):- A = 1, B = 1; A = 0.
    proposition(2, V, G):- V = 1; G = 1.
    proposition(3, B, D):- B = 1, D = 0; B = 0, D = 1.
    proposition(4, V, D):- V = 1, D = 1; V = 0, D = 0.

    solution(A, B, V, G, D):-
        proposition(1, A, B), proposition(2, V, G), 
        proposition(3, B, D), proposition(4, V, D), 
        proposition(1, G, A), proposition(1, G, V).

?- solution(Anna, Boris, Victor, Gregory, Darya).

Можно использовать разностные списки (ниже используется префиксное обозначение):

conc(d(A, B), d(B, C), d(A, C)).
?- conc(d([1, 2, 3 | X], X), d([a, b], []), d(L, [])).
X = [a, b], L = [1, 2, 3, a, b].

Предикаты обработки списков length, member и append можно использовать для конструирования списков:

length([], 0).
    length([_ | T], N):- length(T, K), N is K + 1.
    
    member(H, [H | _]).
    member(H, [_ | T]):- member(H, T).
    
    append([], L, L).
    append([H | T], L, [H | R]):- append(T, L, R).

    ?- length(L, 2), !.
     L = [_, _].

    ?- L = [_, _], member(1, L), member(2, L).
      L = [1, 2].
      L = [2, 1].

    ?- append([_], [1, 2], L).
      L = [_, 1, 2].

Решение головоломки Эйнштейна в стандартном Прологе выглядит совсем просто.

right(A, B, [A, B | _]).
    right(A, B, [_ | L]):- right(A, B, L).
    
    next(A, B, Houses):- right(A, B, Houses).
    next(A, B, Houses):- right(B, A, Houses).    

    member(H, [H | _]).
    member(H, [_ | T]):- member(H, T).

    solve(Houses):- 
        Houses = [[_, _, _, _, _], [_, _, _, _, _], [_, _, _, _, _], 
                        [_, _, _, _, _], [_, _, _, _, _]],
        member(["red", "Englishman" | _], Houses),
        member([_, "Spaniard", "dog" | _], Houses),
        member(["green", _, _, "coffee" | _], Houses),
        member([_, "Ukrainian", _, "tea" | _], Houses),
        right(["ivory" | _], ["green" | _], Houses), 
        member([_, _, "snails", _, "Winston"], Houses),
        member(["yellow", _, _, _, "Kool"], Houses),
        Houses = [_, _, [_, _, _, "milk" | _] | _],
        Houses = [[_, "Norwegian" | _] | _], 
        next([_, _, _, _, "Chesterfield"], [_, _, "fox" | _], Houses), 
        next([_, _, _, _, "Kool"], [_, _, "horse" | _], Houses), 
        member([_, _, _, "orange juice", "Lucky Strike"], Houses),
        member([_, "Japanese", _, _, "Parliament"], Houses),
        next([_, "Norwegian" | _], ["blue" | _], Houses), 
        member([_, _, "zebra" | _], Houses),
        member([_, _, _, "water" | _], Houses).
    
    ?- solve(Houses).
Пример 16.1. Головоломка Эйнштейна в PIE

16.2. Применение интерпретатора в компиляторе

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

Ниже приводится пример использования интерпретатора PIE в программе на языке Visual Prolog. В отличие от языка Visual Prolog, в реализациях, удовлетворяющих стандарту, предикат assert используется для добавления не только фактов, но и правил. В приведенной ниже программе в базе данных хранятся примеры небольших программ вместе с примерами запросов. Правила добавляются в PIE динамически (учитывается порядок перебора фактов). Ответы на запросы находит интерпретатор. Результаты выводятся в окне консоли.

    open core, console, pfc\pie

class facts
    program: (string Clauses, string Goal).
clauses
    program(@"
        add(0, X, X).
        add(s(X), Y, s(Z)):- add(X, Y, Z).",
        "add(A, B, s(s(s(0)))).").

    program(@"
        f(0, 0).
        f(N, s(X)):- f(K, X), N is K + 1.",
        "f(2, X), f(3, Y), add(X, Y, Z), !.").

    run():-
        Pie = pie::new(),
        program(Program, Goal),
        Pie:assertClauses(Program),
            Output = outputStream_string::new(),
            Pie:outputStream := Output,
            try Pie:run(Goal),
                Answer = Output:getString(),
                writef("%\n\n?- %\n", Program, Goal),
                write(Answer), nl, nl
            catch E do
                writef("  Error % ...", E), fail
            end try,
        fail;
        _ = readLine().
Пример 16.2. Пример использования класса pfc\pie

Перед строкой (string) поставлен знак @. Благодаря этому для нее сохраняется форматирование со страницы кода (см. определение предиката program/2).

Упражнения

  1. Определите операцию линеаризации списка в PIE (см. листинг 6.9).
  2. Напишите программу, которая загружает в pie текст программы, хранящейся в текстовом файле, после того, как пользователь введет имя этого файла в окно консоли, и отвечает на запросы, которые пользователь вводит в окне консоли, до тех пор пока он не введет специальную команду.
  3. Напишите программу, которая ищет в pie ответы на запросы, выполняя "погружение" на заданную глубину. В частности, она не должна входить в бесконечный цикл при вычислении ответа на запрос q(A) к программе "q(X):- q(X). q(3)." (Указание. Используйте в pie предикат clause).
  4. Определите в программе на языке Visual Prolog предикат, принадлежащий домену invokePredicate или invokeFunction (см. Help). Приведите пример его использования в pie.
< Лекция 15 || Лекция 16
Жаныл Айкын
Жаныл Айкын
Rustam Inatov
Rustam Inatov

Доброго времени суток, подскажите пожалуйста, visual prolog examples, pie, vip7.5 - это все, где я могу скачать? (в смысле) может быть на сайте есть какой-то архив? Увы я не нашел его.

Подскажите, пожалуйста.

С уважением, Рустам.