Главная страница
Навигация по странице:

  • 3.2. Инсталляция SWI-Prologа

  • 3.3. Первое контрольное задание

  • Пример задания с решением

  • 3.4. Второе контрольное задание

  • 3.5. Третье контрольное задание

  • Логич-кое и функ-ное программ-ние_УМП. Учебные пособия по логическому и функциональ ному программированию В. М. Зюзькова. В пособие внесены изменения в 2020 г


    Скачать 2.34 Mb.
    НазваниеУчебные пособия по логическому и функциональ ному программированию В. М. Зюзькова. В пособие внесены изменения в 2020 г
    Дата06.05.2023
    Размер2.34 Mb.
    Формат файлаpdf
    Имя файлаЛогич-кое и функ-ное программ-ние_УМП.pdf
    ТипУчебные пособия
    #1111705
    страница2 из 6
    1   2   3   4   5   6

    3.
    ЛОГИЧЕСКОЕ ПРОГРАММИРОВАНИЕ
    Почти все наши ошибки, в сущности, языково-
    го характера. Мы сами создаем себе трудно-
    сти, неточно описывая факты. Так, например,
    разные вещи мы называем одинаково и,
    наоборот, даем разные определения одному и
    тому же.
    Олдос Хаксли
    3.1. Контроль обучения
    В процессе дистантного обучения дисциплине "Логическое программи- рование" студент должен выполнить три контрольных задания, курсовую ра- боту и обучение заканчивается выполнением компьютерной экзаменационной работы. Контрольные задания представлены ниже и состоят каждое из двух задач, требующих составить программы на Прологе. Составленные и отла- женные программы (обязательно с комментариями) студент по мере освоения логического программирования периодически пересылает по электронной почте диспетчеру центра дистантного обучения, который в свою очередь пе- ресылает их лектору. Лектор проверяет программы и при правильном выпол- нении программы студент получает подтверждение о том, что они зачтены.
    Если программа составлена неправильно, студент получает от лектора тек- стовый файл, в котором содержится описание ошибок программы.
    3.2. Инсталляция SWI-Prolog'а
    Интерпретатор с языка Пролог представлен в виде упакованного файла pl.arj. SWI-Prolog работает в среде Windows (3.11 или 95); для его установки на компьютере достаточно распаковать файл pl.arj вместе со всеми хранящи- мися в этом файле каталогами. Запустите файл pl.exe из каталога pl\bin и вы войдете в интерпретатор. Пролог выдает приглашение "?-" и ждет вашего ввода.
    Чтобы набирать программы, надо воспользоваться каким-либо внеш- ним текстовым редактором (SWI-Prolog не имеет собственного редактора).
    Например, вы можете пользоваться стандартной программой Notepad ("блок- нот"). Набранные программы сохраняйте в виде текстовых файлов с расши- рением pl (но можно и расширение txt) в рабочем каталоге. По умолчанию рабочим каталогом будет pl\bin, но вы можете это изменить: для этого со- здайте ярлык для pl.exe и измените рабочий каталог в свойствах этого ярлыка.
    Чтобы загрузить программу из файла c:\pl\work\name.pl, находясь в среде ин- терпретатора, вы должны в ответ на приглашение "?-" набрать имя файла в квадратных скобках

    15
    ?- [name]. если установлен рабочий каталог - pl\work, или набрать имя файла с полным путем к нему,
    ?-['c:\pl\work\name.pl']. если установлен другой рабочий каталог. Отметим следующую особенность работы в SWI-Prolog с блокнотом. После набора текста программы обяза- тельно перейдите курсором на новую строчку, иначе SWI-Prolog при загрузке файла с программой выдаст ошибку "неожиданный конец файла".
    3.3. Первое контрольное задание
    Задание состоит из двух задач, в которых требуется составить програм- мы на Прологе для написания простых предикатов. При составлении про- грамм (если не оговорено противное) можно использовать все встроенные предикаты Пролога. Тексты всех программ, если вы мыслите в духе логиче- ского программирования, получаются небольшие.
    SWI-Prolog не имеет стандартного help'а для Windows, для этого ис- пользуется предикат help. Вызов help(<имя предиката>) выдает на экран ин- формацию об этом предикате. Вызов help(7) выдает на экран список всех встроенных предикатов с комментариями. Текстовый файл руководства по
    SWI-Prolog - pl\library\manual. Отладку предикатов можно осуществлять с помощью предиката трассировки trace(<имя предиката>), трассировка преди- ката отключается - trace(<имя предиката>, -all).
    Пример задания с решением
    Задача 1
    Постройте предикат position_max(+L, -M, -N), который в списке L находит максимальное значение M и порядковый номер N этого значения.
    Задача 2
    Определите умножение целых чисел через сложение и вычитание.
    Решение
    Задача 1
    Будем использовать метод накапливающего параметра. Для этого введем вспомогательный предикат position_max(+List, +I, +M0, +N0, -M, -N), где I равен номеру рассматриваемого элемента в исходном списке, M0 - текущее значение максимума, N0 - позиция текущего максимума. position_max([X|T],M,N):- position_max(T,1,X,1,M,N). position_max([],_,M,N,M,N).

    16 position_max([A|T],I,X,_,M,N):-
    A>X,
    K is I+1, position_max(T,K,A,K,M,N). position_max([A|T],I,X,Y,M,N):-
    A= K is I+1, position_max(T,K,X,Y,M,N).
    ?- position_max([3,2,5,1,4,3],M,N).
    M = 5
    N = 3
    Yes
    Задача 2
    Определим предикат p(+X,+Y,?R), где X и Y сомножители, R - произведение.
    Делаем рекурсию по второму аргументу предиката, используя рекурсивное определение X*Y=X*(Y-1)+X. p(X,0,0). p(X,Y,R):- Y>0,
    Y1 is Y-1, p(X,Y1,R1),
    R is R1+X. p(X,Y,R):- Y<0,
    Y1 is -Y, p(X,Y1,R).
    Варианты заданий
    Вариант 1 1. Определите возведение в целую степень через умножение и деление.
    2. Напишите предикат p(+L, -N) - истинный тогда и только тогда, когда N - предпоследний элемент списка L, имеющего не менее двух элементов.
    Вариант 2 1. Напишите предикат p(+X, +N, -L) - истинный тогда и только тогда, когда L
    - список из N раз повторенных элементов X.

    17 2. Напишите предикат p(+L, -S) - истинный тогда и только тогда, когда S - список списков элементов списка L, например, p([a, b, c],[[a], [b], [c]]) - исти- на.
    Вариант 3 1. Напишите предикат p(+L, -S) - истинный тогда и только тогда, когда L - список списков, а S - список, объединяющий все эти списки в один.
    2. Напишите предикат p(+L, -S) - истинный тогда и только тогда, когда спи- сок S есть циклическая перестановка элементов списка L, например, p([f, g, h, j], [g, h, j, f]) -истина.
    Вариант 4 1. Напишите предикат p(+X, +N, +V, -L) - истинный тогда и только тогда, ко- гда список L получается после добавления X на N-е место в список V.
    2. Напишите предикат p(+N, +V, -L) - истинный тогда и только тогда, когда список L получается после удаления N-го элемента из списка V.
    Вариант 5 1. Напишите предикат p(+V, -L) - истинный тогда и только тогда, когда спи- сок L получается после удаления всех повторных вхождений элементов в список V, например, p([a, b, c, d, d, a], [a, b, c, d]) - истина.
    2. Напишите предикат p(+V, -L) - истинный тогда и только тогда, когда спи- сок L получается после удаления из списка V всех элементов, стоящих на четных местах, например, p([1, 2, 3, 4, 5, 6], [1, 3, 5]) - истина.
    Вариант 6 1. Напишите предикат p(+V, +X, -L) - истинный тогда и только тогда, когда список L получается из списка V после удаления всех вхождений X на всех уровнях, например, p([1, [2, 3, [1]], [3, 1]], 1, [[2, 3, []], [3]]) - истина.
    2. Напишите обобщение предиката member, когда ищется элемент на всех уровнях в списке.
    Вариант 7 1. Определите предикат p(+U, +V, -L) - истинный тогда и только тогда, когда список L есть список всех элементов списка U, не содержащихся в списке V.
    2. Определите предикат p(+U, +V, -L) - истинный тогда и только тогда, когда
    L - список всех элементов, содержащихся либо в списке U, либо в списке V, но не одновременно в U и V.
    Вариант 8 1. Определите предикат p(+V, -L) - истинный тогда и только тогда, когда L - список всех элементов списка V, встречающихся в нем более одного раза.

    18 2. Напишите предикат subst(+V, +X, +Y, -L) - истинный тогда и только тогда, когда список L получается после замены всех вхождений элемента X в списке
    V на элемент Y.
    Вариант 9 1. Напишите предикат p(+V, -L) - истинный тогда и только тогда, когда спи- сок L получается из списка V после удаления всех повторяющихся элементов, т. е. из списка получается множество.
    2. Напишите предикат exists(+P, +L), который проверяет "Существует ли эле- мент списка L, удовлетворяющий предикату P?"
    Вариант 10 1. Напишите предикат all(+P, +L), который проверяет "Для всех ли элементов списка L выполняется предикат P? "
    2. Напишите предикат filter(+V, +P, -L) - истинный тогда и только тогда, ко- гда список L есть список всех элементов из списка V, удовлетворяющих пре- дикату P ("фильтрация" списка).
    Вариант 11 1.
    Используя предикаты "родитель"(Родитель, Отпрыск), "женщи- на"(Человек), "мужчина"(Человек) и "супруги"(Жена, Муж), определите от- ношения теща, шурин и зять.
    2. Башня из кубиков может быть описана совокупностью фактов вида "на"(Кубик1, Кубик2), которые истинны, если Кубик1 поставлен на Кубик2.
    Определите предикат "выше"(Кубик1, Кубик2), который истинен, если Ку- бик1 расположен на башне выше, чем Кубик2. (Указание: "выше" является транзитивным замыканием отношения "на".)
    Вариант 12 1. Напишите предикат gcd(+A,+B,-D) - истинный тогда и только тогда, когда
    D -наибольший общий делитель двух целых положительных чисел A и B.
    2. Напишите программу для отношения double(+List, -ListList), в котором каждый элемент списка List удваивается в списке ListList, например, double([1,2,3],[1,1,2,2,3,2]) выполнено.
    Вариант 13 1. Напишите новую версию предиката length(+L, -N), в котором при подсчете количества элементов списка не учитывается пустой список. К при- меру, для списка [a,b,c,d,e] новая версия процедуры должна сообщить, что длина списка равна пяти, а для списка [a,[],c,d,[]] эта процедура должна да- вать длину, равную трем.
    2. Пусть имеется список структур "client":
    [client(a,29,3),client(b,29,6),client(c,40,2)].

    19
    Первым аргументом каждой структуры служит имя клиента, вторым - суточ- ный тариф, а третьим - количество дней, на которое взята автомашина.
    Напишите правило, позволяющее вычислить итоговую сумму оплаты, объ- единяющую выплаты всех клиентов, данные о которых содержатся в списке.
    Вариант 14 1. Опишите процедуру для предиката расщепить/4, которая берет список це- лых чисел L1 и целое число N и выдает списки L2 и L3 такие, что числа из исходного списка, меньшие, чем N, помещаются в список L2, а остальные - в список L3.
    2. Напишите предикат для вычисления чисел Фибоначчи, используя метод накапливающего параметра.
    Вариант 15 1. Напишите предикат digits(+N, -L) - истинный тогда и только тогда, когда L
    - список цифр натурального числа N.
    2. Напишите предикат summa_digits(+N, -S) - истинный тогда и только тогда, когда S - сумма цифр натурального числа N.
    3.4. Второе контрольное задание
    Задание состоит из двух задач, в которых требуется составить програм- мы на Прологе для написания простых программ. При составлении программ
    (если не оговорено противное) можно использовать все встроенные предика- ты Пролога. Тексты всех программ, если вы мыслите в духе логического про- граммирования, получаются небольшие.
    Пример задания с решением
    Задача 1
    Сортировка списка простым обменом (по возрастанию).
    Задача 2
    Пусть бинарное дерево задается рекурсивной структурой tree(<левое подде- рево>,<корень>,<правое поддерево>) и пустое дерево задано термом nil.
    Составьте программу subtree(+S, +T), определяющую, является ли S поддере- вом T.
    Решение
    Задача 1
    Заданный список L сортируется по следующему алгоритму:
    (1) если L содержит два соседних элемента, нарушающих требуемое упоря- дочение, то эти элементы меняются местами, после чего к полученному спис- ку применяется этот же алгоритм;

    20
    (2) если в L не встречается ни одной неупорядоченной пары соседних эле- ментов, то список L отсортирован и тем самым является искомым списком.
    Предикат ord(+L) проверяет является ли список L отсортированным. ord([]). ord([_]). ord([X,Y|T]):-
    X =< Y, ord([Y|T]). change(L,L):- ord(L),!. change(L,S):- append(L1,[X,Y|L2],L),
    X>Y,!, append(L1,[Y,X|L2],Z), change(Z,S).
    Отсечения в данном случае ликвидируют многочисленные правильные отве- ты.
    Задача 2
    Для решения используется очевидная рекурсия. subtree(X, X). subtree(X, tree(L,_,_)):- subtree(X,L). subtree(X,tree(_,_,R)):- subtree(X,R).
    Варианты заданий
    Вариант 1 1. Напишите предикат, аналогичный предикату subst (см. первое контрольное задание, вариант 8, задача 2), но производящий взаимную замену X на Y, т.е.
    X->Y, Y->X.
    2. Напишите предикат, который определяет, является ли данное натуральное число простым.
    Воспользуйтесь более общей задачей: ispr(N, M) - "Число N не делится ни на одно число большее или равное M и меньшее N".
    Имеем ispr(N, M) -истинно, во-первых, если N = M, и, во-вторых, если ис- тинно ispr(N,M+1) и N не делится на M.

    21
    Вариант 2 1. Сортировка списка простой вставкой (по возрастанию).
    2. Сортировка списка простым выбором (по возрастанию).
    Вариант 3 1. Напишите предикат p(+L, -N) - истинный тогда и только тогда, когда N - количество различных элементов списка L.
    2. Напишите предикат p(+X, +Y, -Z) - истинный тогда и только тогда, когда Z есть "пересечение" списков X и Y, т.е. список, содержащий их общие элемен- ты, причем кратность каждого элемента в списке Z равняется минимуму из его кратностей в списках X и Y.
    Вариант 4 1. Запрограммируйте предикат p(+A,+B), распознающий, можно ли получить список элементов A из списка элементов B посредством вычеркивания неко- торых элементов.
    Алгоритм: Если A - пустой список, то ответом будет "да". В противном слу- чае нужно посмотреть, не пуст ли список B. Если это так, то ответом будет "нет". Иначе нужно сравнить первый элемент списка A с первым элементом списка B. Если они совпадают, то надо снова применить тот же алгоритм к остатку списка A и остатку списка B. В противном случае нужно снова при- менить тот же алгоритм к исходному списку A и остатку списка B.
    2. Напишите предикат p(+X, +Y, +L) - истинный тогда и только тогда, когда
    X и Y являются соседними элементами списка L.
    Вариант 5.
    1. Определите отношение sum_tree(+TreeOfInteger, -Sum), выполненное, если число Sum равно сумме целых чисел, являющихся вершинами дерева
    TreeOfInteger.
    2. Определим операторы:
    :- op( 100, fy,

    ).
    :- op( 110, xfy, &).
    :- op( 120, xfy, v).
    Булева формула есть терм, определяемый следующим образом: константы true и false - булевы формулы; если X и Y - булевы формулы, то и X v Y, X &
    Y, X - булевы формулы, здесь v и & - бинарные инфиксные операторы дизъюнкции и конъюнкции, а - унарный оператор отрицания. Напишите предикат p(+T), определяющий, является ли данный терм T булевой форму- лой.

    22
    Вариант 6 1. Встроенный предикат functor(+Term, ?Functor, ?Arity) определяет для за- данного составного терма Term его функтор Functor и местность Arity.
    Встроенный предикат arg(+N, +Term, ?Value) определяет для целого числа N и заданного составного терма Term его N-ый аргумент Value.
    Определите предикаты functor1 и arg1 - аналоги предикатов functor и arg через предикат univ (=..)
    2. Напишите предикат range(?M, ?N, ?L), истинный тогда и только тогда, ко- гда L - список целых чисел, расположенных между M и N включительно
    (предикат должен допускать различное использование, когда не менее двух из трех аргументов конкретизованы).
    (Указание. Используйте предикаты var(+X) и nonvar(+X)).
    Вариант 7 1. Напишите вариант программы plus(?X, ?Y, ?Z), пригодный для сложения, вычитания и разбиения чисел на слагаемые.
    (Указание. Используйте для порождения чисел встроенный предикат between(+Low, +High, ?Value), который порождает все целые числа от нижней границы Low до верхней границы High.)
    2. Напишите программу вычисления целочисленного квадратного корня из натурального числа N, определяемого как число I, такое, что I*I  N, но
    (I+1)*(I+1) > N . Используйте определение предиката between/3 для генериро- вания последовательности натуральных чисел с помощью механизма возвра- тов.
    Вариант 8 1. Напишите новую версию процедуры "предок", которая вырабатывает спи- сок представителей всех промежуточных поколений, располагающихся меж- ду предком и потомком. Предположим, например, что Генри является отцом
    Джека, Джек - отцом Ричарда, Ричард - отцом Чарльза, а Чарльз - отцом
    Джейн. При запросе о том, является ли Генри предком Джейн, должен выдаваться список, характеризующий родственную связь этих людей, кон- кретно: [джек, ричард, чарльз].
    2. Определите предикат p(+V, +N, -L) - истинный тогда и только тогда, когда
    L - список элементов списка V, встречающихся в нем не менее N раз. Про- верьте работу этого предиката на примере [a, a, b, a, c, b, c, a, b, b, d, a, b] для
    N=1,2,5,0.

    23
    3.5. Третье контрольное задание
    Задание состоит из двух задач, в которых требуется составить более сложные программы на Прологе (как правило, требуется определить несколь- ко предикатов). При составлении программы (если не оговорено противное) можно использовать все встроенные предикаты Пролога. Текст программы, если вы мыслите в духе логического программирования и используете рекур- сию, получается небольшой.
    Пример задания с решением
    Задача 1
    Определим операторы:
    :- op( 100, fy, ).
    :- op( 110, xfy, &).
    :- op( 120, xfy, v).
    Булева формула есть терм, определяемый следующим образом: константы true и false - булевы формулы; если X и Y - булевы формулы, то и X v Y, X &
    Y, X - булевы формулы, здесь v и & - бинарные инфиксные операторы дизъюнкции и конъюнкции, а - унарный оператор отрицания.
    Напишите программу, распознающую логические формулы в конъюнктивной нормальной форме, т.е. формулы, являющиеся конъюнкцией дизъюнкций ли- тералов, где литерал - атомарная формула или ее отрицание.
    Задача 2
    Напишите предикат p(+N, -L) - истинный тогда и только тогда, когда список
    L содержит все последовательности (списки) из N нулей, единиц и двоек, в которых никакая цифра не повторяется два раза подряд (нет куска вида XX).
    Решение
    Задача 1
    Из определения операций видно, что конъюнкция и дизъюнкция являются право ассоциативными, т. е. запрос
    ?- X & Y & Z = A & B приводит к унификации X = A, Y & Z = B.
    Определим два вспомогательных предиката literal(X) и dis(X), которые прове- ряют является ли X литералом и элементарной дизъюнкцией соответственно. literal(true). literal(false). literal( X):- literal(X).

    24 dis(X):- literal(X). dis(X v Y):- literal(X), dis(Y). con(X):- dis(X). con(X & Y):- dis(X), con(Y).
    ?- con( true & ( false v true v false) & true).
    Yes
    Задача 2 p(1,[[0],[1],[2]]). p(N,R):- N>1,
    N1 is N-1, p(N1,R1), t(R1,R). t([],[]). t([X|T],Z):- t(T,R1), s(X,R), append(R,R1,Z). s([0|T],[[1,0|T],[2,0|T]]). s([1|T],[[0,1T],[2,1|T]]). s([2|T],[[0,2|T],[1,2|T]]).
    1   2   3   4   5   6


    написать администратору сайта