WWW.DISSERS.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА

   Добро пожаловать!


Pages:     | 1 | 2 || 4 | 5 |

выполнить некоторое множество заведомо успешных предикатов, 1. Предикат fail искусственно порождает неуспех.

после чего выполнять некоторое другое множество предикатов, до 2. Предикат cut (или !) предотвращает бэктрекинг:

тех пор, пока справедливо некоторое условие.

p:-p1,p2,!,p3,.. – если достигнуты цели p1 и p2, бэктрениг не Первую и вторую группы предикатов можно, очевидно, обоосуществляется.

значить одним предикатом, p1 и p2 соответственно. Пусть p_control – предикат, проверяющий условие, а предикат repeat (ко3.4.1. Обработка условия торый может, очевидно, иметь любое другое имя) записывается в Пусть a – предикат, который может быть либо успешным, виде следующих двух правил:

либо нет. В случае успеха мы хотим выполнить предикат u, в обrepeat.

ратном случае – предикат f.

repeat:-repeat.

p:-a,!,u;f.

Тогда:

Можно и так (в случае неуспеха выполняется второе правиpravilo:-p1,repeat,p2,p_control.

ло для p):

p:-a,!,u.

Предикат p1 выполнится один раз, предикат же p2 будет p:-f.

выполняться до тех пор, пока p_control неуспешен.

23 Разберемся, как это происходит: p1 всегда успешен, затем 3.5. Списки в Прологе выполняется всегда успешное первое правило предиката repeat и 3.5.1. Примеры списков Пролог устанавливает указатель отката на второе правило. Выполняется p2. После неуспеха p_control выполняется второе праdomains вило repeat:-repeat, после чего первое правило, указатель отката list_integer=integer* устанавливается на второе правило, далее p2, p_control и т. д.

list_struct=el2* Приведем простой пример использования repeat. Требуется el=e(list_integer) загрузить факты БД со значениями, вводимыми с клавиатуры.

el2=l(integer,symbol) Предикат check_cont запрашивает пользователя о разрешении ввода группы значений факта fact, предикат vvod принимает знаpredicates чения.

p1(list_integer) database p2(list_struct) fact(string,string,string) goal predicates L1=[1,2,3,4] repeat %Списки списков check_cont L2=[e([10,40,50]),e([30,20])] vvod....................................

goal %Списки структур vvod,exit.

L3=[l(1,"Fortran"),l(2,"Algol"),l(3,"PL/1")], write("Языки программирования"),nl, clauses p2(L3), repeat.

search(3,L1), repeat:-repeat.

....................................

vvod:- retractall(fact(_,_,_)), 3.5.2. Разделение списков на "голову" и "хвост" write("Начинаем процесс ввода значений"),nl, Основным приемом работы со списками является представлеrepeat, ние списков в виде "Головы" (Head) и "Хвоста" (Tail). Для иллюстclearwindow, рации напишем правило для предиката p2 из предыдущего раздела:

write("A"),readln(A),nl, clauses write("B"),readln(B),nl, p2([]).

write("C"),readln(C),nl, p2([l(I,S)|T]):- assert(fact(A,B,C)), write(I," ",S),nl, check_cont.

p2(T).

check_cont:- write("ВВОДИТЬ ДАЛЕЕ (Y|N)"), Поиск элемента в списке:

readchar(Ans),Ans='N',!, search(H,[H,_]).

write("Процесс завершен"),readchar(_).

search(H,[_,T]):-search(H,T).

25 Получить сумму числовых элементов списка можно очевид- predicates ным способом: собрать_фио(лист_фам_им_от) sumList([],S).................

sumList([H|T],S):-S1=S+H,sumList(T,S1). goal consult(famio.txt,f1) А для иллюстрации работы со стеком применим "неочевид- ный" прием: %файл "famio.txt" содержит:

predicates %фио("Фадеев","Фиктор","Петрович") sumlist(integer*,integer) %фио("Иванов","Иван","Иванович") goal...............

L = [1,2,3,4], %фио("Гимазов","Артур","Олегович") sumlist(L,S), write(S). findall(Гриб,гриб(Гриб),Грибы), clauses findall(Имя_Языка,язык_программирования(_,Имя_Языка),С sumlist([],0). писок), sumlist([H|T],X):-sumlist(T,S),X = S+H. собрать_фио(СписокФИО).

До тех пор пока не удовлетворено первое правило, Пролог clauses будет очищать список, сбрасывая "головы" в стек. Затем он при- собрать_фио(Список):-findall(ФИО,фио(ФИО),Список).

своит 0 свободной переменной, а далее будет суммировать эле- % Список будет состоять из менты стека, присваивая значения промежуточной суммы пере- [ф("Фадеев","Фиктор","Петрович"),ф("Иванов","Иван","Ива менной X, и возвращать элементы стека в список. (По моему мне- нович"),...] нию, если уж вы выбрали Пролог, не стоит жертвовать логической ясностью ради "оптимизации".) 3.5.3. Некоторые полезные программы для работы со списками • Слияние списков Встроенный предикат findall Полагаем, что в базе данных facts содержаться два списка findall собирает компоненты факта в список.

(список1, список2), элементами которых являются целые числа.

Требуется список1 присоединить к списку2. Пусть список1 есть domains [5,6,7], а список2 есть [8,9].

фам_им_от = ф(symbol,symbol,symbol) лист_фам_им_от = фам_им_от* domains список = integer* facts – ffacts – fгриб(symbol) список1(список) язык_программирования(integer,symbol) список2(список) фио(фам_им_от) predicates объединить_списки(список,список,список) 27 goal 3.6. Ввод и вывод список1(Список1), PDC Visual prolog обладает гибкой системой ввода-вывода и список2(Список2),!, % А вдруг БД пуста! манипулирования файлами.

объединить_списки(Список1,Список2,Список3);!.

clauses 3.6.1. Файловая система объединить_списки([],L,L).

Доступ к файлу может осуществляться в двух "модах" – биобъединить_списки([H|L1],L2,[H|L3]):- нарной и текстовой. Для определения вида доступа используется объединить_списки(L1,L2,L3).



специальный предикат filemode(SymbolicFileName,Mode).

Параметр Mode принимает одно из двух значений: 0 – Что будет происходить Поскольку вначале первый список Binary Mode, 1 – Text Mode. Дальнейшее изложение имеет отноне пуст, Пролог будет пытаться удовлетворить второе правило, шение только к работе с файлами в текстовой "моде".

очищая первый список. Элементы первого списка пересылаются в Для того, чтобы работать с файлом на внешнем носителе, стек в оперативной памяти. Когда первый список окажется пусего нужно открыть или создать. Открыть файл можно для чтения, тым, становится возможным третьему списку присвоить второй записи, модификации. Прежде чем это сделать, в файле список, и первое правило окажется истинным: объединить_спис<имя_проекта>.inc в разделе global domains следует задать симвоки([],[8,9],[8,9]).

лические имена файлов, разделяя их точкой с запятой. (В том месПролог берется за второе правило, сворачивая рекурсию.

те, где написано %To be edited.). Например, уже написано:

Начиная с вершины стека, он присваивает элементы "головам" global domains первого и третьего списков. При этом на каждом шаге левая часть DB_SELECTOR = browselist_db % For treebrowser tool второго правила истинна, происходит рекурсивный вызов и так до FILE = fileselector1; fileselector2 % To be edited тех пор, пока стек не опустеет.

Вы должны добавить Ваши имена:

global domains • Сортировка списков DB_SELECTOR = browselist_db % For treebrowser tool goal FILE = fileselector1; fileselector2; filein; filein2; fileout % To sortL([5,4,7,6,11,9],LS) be edited clauses Открыть можно практически неограниченное количество sortL([],[]).

файлов, столько, сколько позволяют установки операционной сисsortL([X|T],Sorted_list):- темы (но стоит ли это делать).

sortL(T,Sorted_tail), Для перехода от одного открытого файла к другому (переinsert(X,Sorted_tail,Sorted_list).

направление потоков ввода-вывода) служат предикаты readdevice insert(X,[Y|Sorted_list],[Y|Sorted_list1]):- и writedevice.

ask_order(X,Y),!, Например:

insert(X,Sorted_list,Sorted_list1).

....................

insert(X,Sorted_list,[X|Sorted_list]).

openread(filein,"text.txt") ask_order(X,Y):-X>Y.

openread(filein2,"text2.txt") openwrite(fileout,"forwrite.txt") 29 readdevice(filein), Предикат eof(SymbolicFileName) предназначен для контроля readln(Str1), конца файла.

write(Str1) domains.................... nondeterm repeat readdevice(filein2), читать_и_обработать_строки readln(Str), обработать_строку(symbol) write(Str),....................

................. clauses closefile(filein), repeat.

closefile(filein2), repeat:-repeat.

closefile(fileout), читать_и_обработать_строки:-................. repeat, Следует помнить, что при открытии файла предикатом readln(f,S), openwrite(SimbolicFileName,OSFileName) существующий файл обработать_строку(S), очищается, несуществующий – создается. Для дозаписи сущест- eof(f),!,closefile(f);!.

вующий файл открывается предикатом......................

Файлы можно копировать, переименовывать, удалять, исopenappend(SimbolicFileName,OSFileName).

кать.

Открыть файл для чтения и записи можно предикатом copyfile(FromName, ToName) openmodify(SimbolicFileName,OSFileName).

renamefile(OldOSFileName, NewOSFileName) deletefile(OSFileName) Когда вы работаете с файлом в режиме чтения – записи, слеsearchfile(SearchPath, FileName, FoundName) дует после каждой записи использовать предикат existfile(OSFileName) flush(SimbolicFileName), который вызывает принудительную очистку буфера. Он полезен 3.6.2. Операции с именами файлов также во время отладки программы, когда вы пишите некоторую Для работы с именами файлов используются предикаты:

информацию для трассировки. (Flush существенно замедляет выfilenameext(FullName,Name,Mask)-(i,o,o),(o,i,i) полнение программы.) filenamepath(FullName,Path,Name)- (i,o,o),(o,i,i) Для реализации нелинейного ("гипертекстового") доступа к файлу используется предикат Примеры:

filepos(SymbolicFileName,FilePosition,Mode), filenameext с шаблоном (i,o,o):

filenameext("myprog.vpr",Name,Ext), перемещающий (шаблон (i,i,i)) и берущий (i,o,i) текущую позицию write("Name=",Name, "Ext=",Ext),nl, в файле.

Выход:

Параметр Mode определяет "точку отсчета" позиции:

Name=myprog Ext=.vpr 0 – от начала файла, 1 – относительно текущей позиции, 2 – относительно конца файла.

31 filenameext с шаблоном (o,i,i): Универсальный оператор записи – write. Пример:

filenameext(FullName,"prolog",".err"), write("Это значения переменных. V=",V,",C=",C),nl, write(FullName),nl, Переменные могут иметь любой тип.

filenameext(FullName1,"prolog.err",".exe"), Предикат nl служит для перевода строки.

write(FullName1),nl.

Выход: 3.7. Строки и функции работы со строками prolog.err Строка – любая последовательность символов, заключенная prolog.exe в кавычки.

Предикат concat – объединение строк.

filenamepath с шаблоном (i,o,o) Шаблоны (patterns) (i, i, o), (o, i, i), (i, o, i), (i, i, i).

filenamepath("C:\\mycatalog\\myfile.txt",Path,Name), write("Path=",Path, "Name=",Name),nl, Примеры с разными шаблонами.

Выход:

% Шаблон (i, i, o) Path=C:\mycatalog\ Name=myfile.txt Строка1="Это строка ", Строка2="И это строка", filenamepath с шаблоном (o,i,i) concat(Строка1,Строка2,ИтоговаяСтрока).





filenamepath(FullName,"C:\\mycatalog\\","anfile.txt"), write(ИтоговаяСтрока), write(FullName),nl, %Выход: Это строка И это строка Выход:

C:\mycatalog\anfile.txt % Шаблон (o, i, i) concat(X,"И это строка","Это строка И это строка") 3.6.3. Чтение и запись write(X) Основные предикаты для чтения: %Выход: Это строка file_str(OSFileName,StringVariable) – читает файл целиком.

readchar(CharVariable) – читает один символ с устройства % Шаблон (i, o, i) ввода (файл или клавиатура). concat("Это строка",X,"Это строка И это строка") readint(IntegerVariable) – читает целое число в пределах (от %Выход: И это строка -2147483648 до >2147483647 для 32 bit платформы). Ошибка воз- никает, если ввод не может быть преобразован в целое. % Шаблон (i, i, i) readln(StringVariable) – читает строку. concat("Это строка"," И это строка","Это строка И это строreadreal(RealVariable) – читает реальное число. ка") Примеры правильного задания: % Нет выхода. Утверждение истинно.

-127.457E-5 concat("Это строка"," А это строка не строка","Это строка И 0.72 это строка").99 % Утверждение ложно. "А это строка не строка" не является % подстрокой "Это строка И это строка" 33 Предикат frontchar St="МАМА", frontchar (String, StartChar, EndString) frontstr(5,St,StartS,EndS), Шаблоны (i, o, o), (i, i, o), (i, o, i), (i, i, i), (o, i, i) Предикат не успешен.

Примеры:

Предикат fronttoken %Шаблон (i, o, o) token – это правильное "имя", беззнаковое число frontchar("Я Вас люблю!",Fc,ES), (integer|real), символ write(Fc,"##",Es), (но не пробел).

%Выход: Я## Вас люблю! Можно проверить, является ли ваша строка правильным %Шаблон (i, i, o) именем, используя встроенный предикат isname. Например:

S="Я Вас люблю!", isname("75Слонов") – No (не имя), frontchar(S,'О',ES), isname("Windows_95") – Yes, %Предикат не успешен. isname("Windows-95") – No.

Ниже приводится исходный текст полной программы на %Шаблон (i, o, i) Visual Prolog'е S="Ненавижу", /********************************************** frontchar(S,X,"енавижу"), Copyright (c) My Company write(X), Project: TOKEN %Выход: Н. FileName: TOKEN.PRO Purpose: No description %Шаблон (i, i, i) Written by: Visual Prolog S="У-р-р-я-я-я!" Comments:

frontchar(S,'У',"-р-р-я-я-я!"), ************************************************/ %Предикат успешен. include "token.inc" %Шаблон (o, i, i) -добавление символа в начало строки predicates frontchar(S,'Н',"енавижу"), write(S), token() %Выход: Ненавижу.

clauses Предикат frontstr – выбор лидирующей подстроки %шаблон – (i,i,o,o) token():- frontstr(5,"ААААААА",StartS,EndS), fronttoken("all kids do fine",TOK,REST), write(SrartS,"###",EndS), write("TOK = ",TOK," REST = ",REST),nl, Выход: ААААА###AA. fronttoken("all+kids do fine",TOK1,REST1), write("TOK = ",TOK1," REST = ",REST1),nl, 35 fronttoken("22all kids do fine",TOK2,REST2), определить_нечто(symbol) write("TOK = ",TOK2," REST = ",REST2),nl, goal fronttoken("22.66all kids do fine",TOK3,REST3), assert(лексема("я","местоимение")), write("TOK = ",TOK3," REST = ",REST3),nl, assert(лексема("бы","частица")), fronttoken("-22.66all kids do fine",TOK4,REST4), assert(лексема("на","предлог")), write("TOK = ",TOK4," REST = ",REST4),nl, assert(лексема("но","союз")), fronttoken(".66all kids do fine",TOK5,REST5), assert(лексема("выходить","глагол")), write("TOK = ",TOK5," REST = ",REST5),nl, assert(лексема("вышел","глагол")), fronttoken("Иди ко мне!",TOK7,REST7), assert(лексема("идет","глагол")), write("Исходная строка >>> ","Иди ко мне!"),nl, assert(лексема("улица","существительное")), write("TOK = ",TOK7," REST = ",REST7). assert(лексема("улицу","существительное")), goal assert(лексема("дождь","существительное")), assert(знак(",","запятая")), token(). assert(знак(".","точка")), % Выход: Предл="Я бы вышел на улицу, но идет сильный дождь.", парсировать_предложение(Предл).

TOK = all REST = kids do fine clauses TOK = all REST = +kids do fine парсировать_предложение(Предл):- TOK = 22 REST = all kids do fine fronttoken(Предл,Нечто,Остаток),!, TOK = 22.66 REST = all kids do fine upper_lower(Нечто,Нечто1), % преобразование регистра TOK = – REST = 22.66all kids do fine определить_нечто(Нечто1), TOK =. REST = 66all kids do fine парсировать_предложение(Остаток);!.

Исходная строка >>> Иди ко мне! определить_нечто(X):- TOK = Иди REST = ко мне! лексема(X,Часть_речи),!, write("Слово = ",X," Часть_речи = ",Часть_речи),nl;

Последнее использование fronttoken демонстрирует, что вы знак(X,Наименование),!, можете использовать этот предикат для парсирования текстов на write("Знак препинания = ",X," Наименование = русском языке, что не позволял TurboProlog v.2.0. Давайте, мы это ",Наименование),nl;

и сделаем. write("Элемент ",X," не определен"),nl.

domains Выход:

слово=symbol Слово = я Часть_речи = местоимение часть_речи=symbol Слово = бы Часть_речи = частица facts -f1 Слово = вышел Часть_речи = глагол лексема(слово,часть_речи) Слово = на Часть_речи = предлог знак(symbol,symbol) Слово = улицу Часть_речи = существительное predicates Знак препинания =, Наименование = запятая парсировать_предложение(symbol) Слово = но Часть_речи = союз 37 Слово = идет Часть_речи = глагол 4. Простенькая экспертная система Элемент сильный не определен Слово = дождь Часть_речи = существительное Задача этого раздела заключается в том, чтобы проиллюстЗнак препинания =. Наименование = точка рировать использование Пролога для создания игрушечной экспертной системы (ЭС).

Pages:     | 1 | 2 || 4 | 5 |










© 2011 www.dissers.ru - «Бесплатная электронная библиотека»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.