Опубликован: 12.02.2014 | Уровень: для всех | Доступ: платный
Лекция 7:

Списки. Предикаты высших порядков

< Лекция 6 || Лекция 7: 1234 || Лекция 8 >

7.3. Представление множеств списками

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

class predicates
    subset: (positive, A*, A*  Subset [out], A* Rest [out]) nondeterm.
clauses
    subset(0, L, [], L):- !.
    subset(N, [A | L], [A | L1], L2):-
        subset(N - 1, L, L1, L2).
    subset(N, [A | L], L1, [A | L2]):-
        subset(N, L, L1, L2).

    run():-
        subset(2, [1, 2, 3, 4, 5], L1, L2),
            write(L1, " - ", L2), nl,
        fail;
        _ = readLine().
Пример 7.1. Подмножества

Упражнение 1. Сгенерируйте все подмножества элементов списка.

В приведенной ниже программе недетерминированно генерируются перестановки элементов списка. Если список содержит n элементов, то возвращается n! перестановок.

class predicates
    permutation: (A*) -> A* nondeterm.
    select: (A [out], A*, A* [out]) nondeterm.
clauses
    permutation(L) = [A | permutation(L1)]:-
        select(A, L, L1).
    permutation([]) = [].

    select(A, [A | L], L).
    select(A, [B | L], [B | L1]):-
        select(A, L, L1).

    run():-
        write(permutation([1, 2, 3])), nl,
        fail;
        _ = readLine().
Пример 7.2. Перестановки

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

class predicates
    permutation_rep: (A*) -> A* nondeterm.
    select_uniq: (A [out], A*, A* [out]) nondeterm.
clauses
    permutation_rep(L) = [A | permutation_rep(L1)]:-
        select_uniq(A, L, L1).
    permutation_rep([]) = [].

    select_uniq(A, [A | L], L).
    select_uniq(A, [B | L], [B | L1]):-
        select_uniq(A, L, L1),
        A <> B.

    run():-
        write(permutation_rep([1, 2, 3, 2])), nl,
        fail;
        _ = readLine().
Пример 7.3. Перестановки списка с повторяющимися элементами

Отличие заключается в определении предиката select. Предикат select_uniq возвращает только попарно различные элементы списка (и список оставшихся элементов).

Для выполнения операций объединения, пересечения и разности множеств предназначены предикаты union, intersection и difference класса list.

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

differenceBy: (comparator R, A* L1,  A* L2) -> A*   
differenceEq: (predicate_dt R, A* L1, A* L2) -> A*

удаляют из списка L1 такие элементы X, для которых в списке L2 существует элемент Y, такой, что пара (X, Y) принадлежит отношению R.

Предикаты

intersectionBy: (comparator R, A* L1,  A* L2) -> A*   
intersectionEq: (predicate_dt R, A* L1, A* L2) -> A*

оставляют в списке L1 элементы X, для которых в списке L2 существует элемент Y, такой, что пара (X, Y) принадлежит отношению R.

Предикаты

unionBy: (comparator R, A* L1,  A* L2) -> A*   
unionEq: (predicate_dt R, A* L1, A* L2) -> A* 

соединяют список элементов X из L1, для которых не существует элементов Y списка L2, таких, что пара (X, Y) принадлежит отношению R, со списком L2.

open core, console, list

clauses
    run():-
        L1 = [1, 2, 3, 4, 5], L2 = [4, 2, 5],
        write(union(L1, L2)), nl,
        write(intersection(L1, L2)), nl,
        write(difference(L1, L2)), nl, nl,
        write(differenceBy({(X, Y) = compare(X mod 2, Y mod 2)},
            L1, L2)), nl,
        write(intersectionEq({(X, Y):- X mod 3 = Y mod 3}, L1, L2)),
        nl, write(unionEq({(X, Y):- X > Y}, L1, L2)),
        _ = readLine().
Пример 7.4. Операции над множествами

Упражнение 2. Определите результаты применения операций, не запуская программу, приведенную в листинге 7.4.

Предикат compare/2 сравнивает элементы произвольных доменов, но его аргументы должны принадлежать одному и тому же домену. Он возвращает значение equal, greater или less, принадлежащее встроенному домену compareResult. Аргументом продиката differenceBy/3 является процедурный предикат, а аргументом предиката intersectionEq/3 — детерминированный предикат.

< Лекция 6 || Лекция 7: 1234 || Лекция 8 >
Жаныл Айкын
Жаныл Айкын
Rustam Inatov
Rustam Inatov

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

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

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

Айдана Ахметова
Айдана Ахметова
Россия
Дмитрий Куянов
Дмитрий Куянов
Россия, Омск, ОмГТУ