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

Управление перебором. Отсечение

< Лекция 2 || Лекция 3: 1234 || Лекция 4 >

3.3. Предикат findall и конструкция [… || …]

Предикат findall/3 собирает значения параметра в список. Его первый аргумент — это вычисляемый параметр, второй — предикат, из которого он находится, третий — имя переменной, которая обозначает список значений параметра. Обобщением этой конструкции является конструкция [… || …]. Данная конструкция соответствует в математике заданию множества с помощью определяющего свойства, например, в виде \{x|x\in M~ или ~x\in N\}, где M и N — некоторые множества. Ниже приведены примеры использования предиката findall и конструкции [… || …].

  • Найти всех родителей:

    1. findall(X, parent(X, _), List);
    2. List = [X || parent(X, _)].
  • Найти всех персон:

    1. findall(X, (male(X); female(X)), List);
    2. List = [X || male(X); female(X)].
  • Декартово произведение множества мужчин и множества женщин:

    List = [tuple(X, Y) || male(X), female(Y)].
    

В объявлении доменов термов с функторами tuple, которые могут иметь от 2 до 12 аргументов, нет необходимости, они объявлены в классе core. Напомним, что функтор состоит из имени и арности, поэтому функторы с одинаковым именем и разной арностью являются разными функторами. Само слово "tuple" в литературе используется для обозначения кортежа, или n-ки, например, термин 4-tuple означает "четверку" — упорядоченный набор из четырех элементов.

Упражнение 1.

Найдите результат вызова последней цели (декартово произведение), если набор фактов имеет вид:

male("Иван").
male("Павел").
male("Петр").

female("Мария").
female("Анна").

Обратите внимание на порядок следования элементов в списке List.

3.4. Режимы детерминизма предикатов

Для того чтобы компилятор языка Visual Prolog проводил более быстрые вычисления, при объявлении предикатов указывается режим детерминизма.

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

Режим детерминизма определяется количеством возможных решений при вызове предиката (т. е. тем, нужен ли откат) и тем, может ли он быть неуспешным. Ключевые слова, с помощью которых указываются режимы детерминизма, перечислены в табл. 3.1.

Таблица 3.1. Режимы детерминизма
> 1 решения \leq 1 решения 0 решений
м. б. ложь nondeterm determ failure
всегда истина multi procedure erroneous

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

Предикат succeed() является примером предиката с режимом procedure, предикат fail имеет режим failure.

Предикаты с режимом детерминизма procedure, называют процедурами. Если предикат не может порождать более одного решения, то он называются детерминированным, а если может, то недетерминированным.

По умолчанию используется режим procedure, если предикат объявляется в разделе (class) predicates, и режим nondeterm, если предикат объявляется в разделе (class) facts.

3.5. Потоки параметров

В объявлении предиката требуется указывать не только режим детерминизма, но и поток параметров (flow pattern). В нем описывается, какие аргументы предиката при его вызове являются входными, а какие выходными. Используется обозначение (i) для входного аргумента и обозначение (o) для выходного. Произвольный поток параметров обозначается с помощью ключевого слова anyflow. По умолчанию все аргументы предиката являются входными. Поток параметров указывается в виде последовательности (i,o,o,…) символов i или o, соответствующих аргументам предиката, либо с помощью слова [out], которое ставится после имени домена аргумента предиката (см. листинг 3.1).

Один и тот же предикат может иметь разные потоки параметров и режимы детерминизма. В этом случае они перечисляются последовательно. Например,

parent: (string, string) nondeterm (o,o) (i,o) (o,i) determ.

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

Пример 1. "Кино". Аня, Боря, Витя, Гриша и Даша решают, пойти ли им в кино. Ситуация описывается следующими высказываниями:

  1. если пойдет Аня, то пойдет и Боря;
  2. пойдет либо Витя, либо Гриша, возможно, и оба пойдут;
  3. точно пойдет либо Боря, либо Даша, но не оба вместе;
  4. Витя c Дашей либо пойдут вместе, либо вместе не пойдут;
  5. если пойдет Гриша, то пойдут также Аня и Витя.

Нужно определить, кто пойдет в кино.

class predicates
    proposition: (integer, integer, integer) nondeterm.
    indicator: (integer Индикатор [out]) multi.
    solution: (integer, integer, integer, integer, integer)
        nondeterm (o,o,o,o,o).
clauses
    indicator(0).     % не пойдет
    indicator(1).      % пойдет

    % если А пойдет, то и Б пойдет
    proposition(1, А, Б):- А = 1, Б = 1; А = 0.
    % хотя бы кто-то из В и Г пойдет
    proposition(2, В, Г):- В = 1; Г = 1.
    % пойдет либо Б, либо Д, но не оба вместе
    proposition(3, Б, Д):- Б = 1, Д = 0; Б = 0, Д = 1.
    % В и Д либо оба пойдут, либо оба не пойдут
    proposition(4, В, Д):- В = 1, Д = 1; В = 0, Д = 0.

    solution(А, Б, В, Г, Д):-
        indicator(А), indicator(Б),
        proposition(1, А, Б),
        indicator(В), indicator(Г),
        proposition(2, В, Г),
        indicator(Д),
        proposition(3, Б, Д),
        proposition(4, В, Д),
        proposition(1, Г, А),
        proposition(1, Г, В).

    run():-
        solution(А, Б, В, Г, Д),
            write("Aня=", А, ", Боря=", Б, ", Витя=", В, ", Гриша=", Г,
                ", Даша=", Д), nl,
        fail;
        _ = readLine().
Пример 3.1. Решение задачи "Кино"

Упражнение 2. Выразите условия, которым должны удовлетворять значения переменных (см. листинг 3.1), одним равенством или неравенством для каждого высказывания. Например, условие "если А = 1, то Б = 1" для А, Б \in {0, 1} равносильно любому из условий:

А * Б = А или Б >= А.

После этого упростите программу, удалив предикат proposition.

Пример 2. "Шкатулки". Перед претендентом на руку Порции находятся три шкатулки — золотая, серебряная и свинцовая. Претендент должен угадать, не открывая шкатулок, в какой из них лежит ее портрет. На крышке каждой из шкатулок имеются два высказывания. На золотой шкатулке:

  1. "Портрет не здесь";
  2. "Портрет в серебряной шкатулке".

На серебряной шкатулке:

  1. "Портрет не в золотой";
  2. "Портрет в свинцовой".

На свинцовой шкатулке:

  1. "Портрет не здесь";
  2. "Портрет в золотой".

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

class predicates
    box: (symbol Color) multi (o).
    proposition: (symbol, integer, symbol) determ.
    statement:  (symbol, integer, symbol, integer Истинность)
        nondeterm (i,i,i,o) determ.
    solution: (symbol ЦветШкатулкиСПортретом) nondeterm (o).
clauses
    box("золото").
    box("серебро").
    box("свинец").

    proposition("золото", 1, PortraitBoxColor):- 
        PortraitBoxColor <> "золото".
    proposition("золото", 2, "серебро").

    proposition("серебро", 1, PortraitBoxColor):- 
        PortraitBoxColor <> "золото".
    proposition("серебро", 2, "свинец").

    proposition("свинец", 1, PortraitBoxColor):- 
        PortraitBoxColor <> "свинец".
    proposition("свинец", 2, "золото").

    statement(Box, Number, PortraitBoxColor, 1):-
        proposition(Box, Number, PortraitBoxColor).
    statement(Box, Number, PortraitBoxColor, 0):-
        not(proposition(Box, Number, PortraitBoxColor)).

    solution(PortraitBoxColor):-
        box(PortraitBoxColor),
        box(Color1),
        statement(Color1, 1, PortraitBoxColor, 1),
        statement(Color1, 2, PortraitBoxColor, 1),
        box(Color2), Color2 <> Color1,
        statement(Color2, 1, PortraitBoxColor, 0),
        statement(Color2, 2, PortraitBoxColor, 0),
        box(Color3), Color3 <> Color1, Color3 <> Color2,
        statement(Color3, 1, PortraitBoxColor, X),
        statement(Color3, 2, PortraitBoxColor, 1 - X).

    run():-
        solution(PortraitBoxColor),
            write("Портрет в шкатулке цвета: ", PortraitBoxColor),
        fail;
        _ = readLine().
Пример 3.2. Решение задачи "Шкатулки"
< Лекция 2 || Лекция 3: 1234 || Лекция 4 >
Жаныл Айкын
Жаныл Айкын
Rustam Inatov
Rustam Inatov

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

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

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