Применение средств логических языков для решения задач, базирующихся на знаниях: задача «О зернах на шахматной доске»

0

 

 

ОТЧЕТ

О выполнении курсовой работы по дисциплине

«Логическое и функциональное программирование»

На тему

«Применение средств логических языков для решения

задач, базирующихся на знаниях: задача «О зернах на шахматной доске»

 

 

 

 

 

Санкт-Петербург

2018 г.

 

 

 

Оглавление

 

  1. Введение. 3
  2. Постановка задачи. 4
  3. Решение задачи. 5
  4. Описание предикатов. 6
  5. Исходный код программы.. 7
  6. Тестирование. 10
  7. Литература. 13

 

 

 

1.     Введение

Пролог (англ. Prolog) – язык и система логического программирования, основанные на языке предикатов математической логики дизъюнктов Хорна, представляющей собой подмножество логики предикатов первого порядка.

 

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

 

Prolog является декларативным языком программирования: логика программы выражается в терминах отношений, представленных в виде фактов и правил. Для того чтобы инициировать вычисления, выполняется специальный запрос к базе знаний, на которые система логического программирования генерирует ответы «истина» или «ложь». Для обобщенных запросов с переменными в качестве аргументов созданная система выводит конкретные данные в подтверждение истинности обобщенных сведений и правил вывода.

 

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

 

 

2.     Постановка задачи

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

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

3.     Решение задачи

Работа программы начинается с вывода подсказки с указанием возможных режимов ее работы: классическая задача «Зерна на шахматной доске», вариант с торговцами и вариант с расчетом количества дней, необходимым, чтобы окупить сделку. Пользователь может выбрать один из этих вариантов.

При выборе задачи «о зернах на шахматной доске» происходит запрос количества клеток на доске. Далее предикат производит расчет количества зерен на каждой клетке, с выводом этой информации пользователю. В конце работы предикат показывается общая сумма зерен на доске и время работы предиката. Задача решается по формуле: при удвоении количества зерен на каждой последующей клетке их количество на всех 64 клетках определяется выражением:

что составляет 18 446 744 073 709 551 615 зерен.

При выборе задачи о торговцах происходит запрос дней действия сделки и количества денег, которые отдает второй торговец первому в день. Далее предикат подсчитывает суммы, отданные каждым торговцем в день до последнего дня, введённого пользователем.

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

 

 

4.     Описание предикатов

  1. countMoney(FirstT,FirstT2,CurBox, MaxDay, PreviousCount)

Предикат, который вычисляет сколько тратит каждый торговец в споре

  1. startSellers

Предикат, который запускает предикат countMoney в нем происходит ввод данных.

  1. countDays(FirstTraderPayment, FirstTraderSum, SecondTraderPayment, SecondTraderSum, Days)

Предикат, который вычисляет количество дней, когда первый торговец выйдет в плюс, если второй торговец будет платить N рублей в день

  1. startSellersDay

Предикат, который запускает предикат сountDays.

  1. countSeeds(CurBox,MaxBox,PreviousCount,AllSeeds)

Предикат, который вычисляет количество зерен на каждой клетке и на доске.

  1. StartCountSeed

Предикат, который запускает countSeed

  1. checkPositInput(Input, Ok)

Предикат, который проверяет на ввод неотрицательных чисел.

  1. endOfch(Num, Words)

Предикат для добавления окончания к слову в зависимости от числа.

  1. startQ Предикат для запуска всей программы.

 

 

5.     Исходный код программы

% Торговцы

% СколькоПолучилПервыйТорговец, СколькоПлатитВторойТорговец, ТекущийДень, МаксимальныйДень, СколькоПолучилВторойТорговец

countMoney(_,_,MaxDay,MaxDay, _):- !.               % если сегодня - максимальный день

countMoney(FirstT,FirstT2,CurBox, MaxDay, PreviousCount):-   % иначе

PC_2 is PreviousCount + PreviousCount,% увеличиваем сумму, которую отдал первый торговец

PC_3 is PreviousCount/100, % переводим в рубли

BN_2 is CurBox + 1,             % увеличиваем день

FT is FirstT + FirstT2,           % сколько получил первый тороговец

write ("День "),

write (BN_2),nl,

write(" Количество отданых денег 1м торговцем: "),

write(PC_3),

write(" Количество отданных денег 2м торговцем: "),

write(FirstT),nl,

countMoney(FT,FirstT2,BN_2, MaxDay, PC_2).

 

startSellers:-               

                        write("Введите количество дней сделки "),

                        read(MaxDay),

                        checkPositInput(MaxDay, Ok1),

                        Ok1 > 0,

                        write("Введите сколько платит в день второй торговец: "),

                        read(FirstT),

                        checkPositInput(FirstT, Ok2),!,

                        Ok2 > 0,

                        countMoney(FirstT,FirstT,0,MaxDay, 1),startQ.

 

% Количесво дней для выхода в плюс торговца

% Узнаем, когда второй торговец выйдет в плюс, если будет платить по N рублей в день

% ЧтоПлатитПервыйТорговецЕжедневно,СуммаКоторуюЗаплатилПервыйТорговец, ЧтоПлатитВторойТорговецЕжедневно, СуммаКоторуюЗаплатилВторойТорговец, День

countDays(_, FirstTraderSum, _, SecondTraderSum, Days):-

                        write("День: "), write(Days), nl,

                        FirstTraderSum1 is FirstTraderSum / 100,

                        write("Первый торговец отдаст: "), write(FirstTraderSum1), nl,

                        write("Второй торговец отдаст: "), write(SecondTraderSum), nl,

                        FirstTraderSum / 100 > SecondTraderSum,

                        write("Второму торговцу понадобится "), write(Days),endOfch(Days,Words),write("дн"),write(Words) ,write(" ,чтобы выйти в плюс"), !.

 

countDays(FirstTraderPayment, FirstTraderSum, SecondTraderPayment, SecondTraderSum, Days):-

                        FT_P1 is FirstTraderPayment + FirstTraderPayment,

                        FT_S1 is FT_P1 + FirstTraderSum, %торговец который платит по 1 копейке.

                        ST_S1 is SecondTraderSum + SecondTraderPayment, %торговец который платит по N сумме в день.

                        Days1 is Days + 1,

                        countDays(FT_P1, FT_S1, SecondTraderPayment, ST_S1, Days1).

 

startSellersDay:-        

                        write("Ведите сумму которую платит 2й торговец: "),

                        read(SecondTraderPayment),nl,

                        checkPositInput(SecondTraderPayment, Ok),

                        Ok > 0,

                        countDays(1, 1, SecondTraderPayment, SecondTraderPayment, 1),startQ.

                                              

%Зерная на доске                                        

countSeeds(MaxBox,MaxBox,PreviousCount,AllSeeds):-

              AllSeeds is PreviousCount - 1, !.

 

countSeeds(CurBox,MaxBox,PreviousCount,AllSeeds):-              

                        PC_2 is PreviousCount + PreviousCount,                                        %КоличествоЗерен = ВсеЗернаСПрошлыхКлеток + Столько же на этой

                        BN_2 is CurBox + 1,                                                                                                %ТекущаяКлетка ++

                        write("Номер клетки: "),

                        write(BN_2),

                        write(" Количество зерен на клетке: "),

                        write(PreviousCount),nl,                   

                        countSeeds(BN_2,MaxBox,PC_2,AllSeeds).

 

startCountSeed:-

                        write("Введите количество клеток на доске: "),

                        read(MaxBox),

                        checkPositInput(MaxBox, Ok),

                        Ok > 0,

                        get_time(T1),

                        countSeeds(0, MaxBox, 1, AllSeeds),

                        get_time(T2),

                        T3 is T2-T1,

                        T4 is T3*1000,

                        write("Общее количество семян: "),write(AllSeeds), nl,

                        write("Время подсчета: "),

                        write(T4),

                        write(" мс."),startQ.

 

checkPositInput(Input, Ok):-

            Input > 0,

            Ok is 1.

checkPositInput(_, Ok):-

            write("Вы должны вводить неотрицательные числа"), Ok is 0,nl,startQ.

 

choose(1):- startCountSeed.

choose(2):- startSellers.

choose(3):- startSellersDay.

 

day(1,"ень").

day(2,"я").

day(3,"я").

day(4,"я").

day(5,"ей").

day(6,"ей").

day(7,"ей").

day(8,"ей").

day(9,"ей").

day(0,"ей").

 

endOfch(Num, Words):-

            Num>10,Num<15, Words = "ей".

endOfch(Num, Words):-

            Num1 is Num mod 10, day(Num1,Words).

           

startQ:-nl,

                        write("Выберете вариант задачи зерна на шахматной доске"),nl,

                        write("1-Зерна на доске ориганальная версия."),nl,

                        write("2-Вариант с торговцами."),nl,

                        write("3-Вариант с торговцами, узнать количество дней для окупания сделки"),nl,

                        read(Answer), choose(Answer).

6.     Тестирование

Вариант задачи с зернами на шахматной доске, проверка времени работы предиката.

Рис. 1 Количество зерен 15

Рис. 2 количество зерен 30

Рис. 3 Вычисление дней выхода в плюс

7.     Литература

  • Хабаров, С. П. «Интеллектуальные информационные системы. PROLOG – язык разработки интеллектуальных и экспертных систем: учебное пособие для бакалавров и магистров направлений подготовки 230400 Информационные системы и технологии и 230200 Информационные системы» [Электронный ресурс]: учеб. пособие – Электрон. дан. – Санкт-Петербург: СПбГЛТУ, 2013. – 138 с. – Режим доступа: https://e.lanbook.com/book/45746.
  • Шрайнер, П. А. «Основы программирования на языке Пролог. Курс лекций» / П. А. Шрайнер. – М.: ИНТУИТ, 2005. – 176 с. – ISBN 5-9556-0034-5.
  • SWI-Prolog [Электронный ресурс]: портал. – Режим доступа: http://swi-prolog.org/, свободный. – Загл. с экрана (дата обращения 19.12.2018).

Скачать: kursovoy-proekt.zip

Категория: Курсовые / Компьютерные технологии курсовые

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