Компьютерный форум
Правила
Вернуться   Компьютерный форум > Форум программистов > Языки программирования > Prolog
Перезагрузить страницу Родств. связи
Ответ
 
Опции темы Опции просмотра
  (#1 (permalink)) Старый
Julli Julli вне форума
Member
 
Сообщений: 20
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 02.12.2007
По умолчанию 16.12.2007, 14:22

Нужно найти все пары отношений вида "дед-внук" и подсчитать их кол-во.
Код:
domains
    i=        integer
    s=        string
    spisok=        s*
    
predicates
    father    (s,s)
    son    (s,s)
    brother    (s,s)
    gsab    (s,s) 
    gsba    (s,s)
    be_el    (s,s,spisok)
    list    (spisok,spisok)
    length    (spisok,i)

database
    name    (s)
    
goal
    clearwindow, makewindow(1,30,30,"Лабораторная работа",0,0,25,80),
    list([],C),
    length(C,L), 
    nl, write("Всего: ",L), readchar(_), 
    retractall(name(_)).
    
clauses
    father(vladimir,alexey).
    father(ivan,anton).
    father(anatoliy,stepan).
    father(uriy,foma).
        
    son(mihail,oleg).
    son(vitaliy,vladimir).
    son(anatoliy,nikolay).
    son(sidor,fedor).
    
    brother(nikifor,victor).
    brother(cidor,nikolay).
    brother(boris,andrey).
    brother(vladimir,mihail).
    brother(foma,petra).
    brother(yakov,nicifor).
    brother(mihail,vladimir).
        brother(fedor,foma).
    brother(leonid,vitaliy).
    brother(yakov,boris).
    brother(stepan,andrey).
    brother(mihail,vladimir).
    brother(victor,stepan).
    brother(oleg,anton).
    
    be_el(X1,X2,[X1,X2|_]).
    be_el(X1,X2,[_|Tail]):-
            be_el(X1,X2,Tail).
    
    length([],0).
    length([_,_|Tail],L):-
            length(Tail,LTail),
            L=LTail+1.
            
    gsab(A,B):-
            brother(A,B).
    gsab(A,B):-
            brother (B,C), gsab(A,C);
            brother (B,C), gsab(C,A).
    
    gsba(A,B):-
            brother (A,B).
    gsba(A,B):-        
            brother (C,B), gsba(A,C);
            brother (C,B), gsba(C,A).
        
    list(SP,CS):-
        %readchar(_),
        
        father(A,B), not(be_el(A,B,SP)), assert(name(B)),
        write(A," - ",B,";\n"),!, list([A,B|SP],CS);
        
        son(B,A), not(be_el(A,B,SP)), assert(name(B)),
        write(A," - ",B,";\n"),!, list([A,B|SP],CS);
        
        son (B,A), gsba(C,B), not(be_el(A,C,SP)), assert(name©),
        write(A," - ",C,";\n"),!, list([A,C|SP],CS);
        
        son (B,A), gsba(B,C), not(be_el(A,C,SP)), assert(name©),
        write(A," - ",C,";\n"),!, list([A,C|SP],CS);
        
        father (A,B), gsba(C,B), not(be_el(A,C,SP)), assert(name©),
        write(A," - ",C,";\n"),!, list([A,C|SP],CS);
        
        father (A,B), gsba(B,C), not(be_el(A,C,SP)), assert(name©),
        write(A," - ",C,";\n"),!, list([A,C|SP],CS);

        %Вариант 1 - 1, 2 отключено.        
        %Вариант 4 - Все включены.

        son (B,A), gsab(C,B), not(be_el(A,C,SP)), not(name©),
        assert(name©), write(A," - ",C,";\n"),!, list([A,C|SP],CS);
        
        son (B,A), gsab(B,C), not(be_el(A,C,SP)), not(name©),
        assert(name©), write(A," - ",C,";\n"),!, list([A,C|SP],CS);
        
        father (A,B), gsab(C,B), not(be_el(A,C,SP)), not(name©),
        assert(name©), write(A," - ",C,";\n"),!, list([A,C|SP],CS);
        
        father (A,B), gsab(B,C), not(be_el(A,C,SP)), not(name©),
        assert(name©), write(A," - ",C,";\n"),!, list([A,C|SP],CS).
    list(CS,CS).
Эта прога должна считать отец-сын, но пишет, что стек переполнен. А до "дед-внук" даже не знаю как дойти. Плиз, помогите!
Ответить с цитированием
  (#2 (permalink)) Старый
Alison Alison вне форума
Member
 
Сообщений: 4,781
Сказал(а) спасибо: 0
Поблагодарили 119 раз(а) в 116 сообщениях
Регистрация: 17.11.2004
По умолчанию 16.12.2007, 15:56

Ну опять у Вас симпатичная задачка! Ваш преподаватель скучать Вам (и нам) не дает.

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

Здесь все сделано для пар "отец-сын", ну а для "дед-внук" - доделайте!
Код:
domains
    slist = symbol*
database - rel
    father(symbol,symbol)
    son(symbol,symbol)
    brother(symbol,symbol)
database
    determ names(slist)    
    determ count(integer)
predicates    
    nondeterm brothers(symbol,symbol)
    nondeterm k_brothers(symbol,symbol)
    nondeterm brothers1(symbol,symbol)
    nondeterm father_son(symbol,symbol)
    determ member(symbol,slist)
    determ find_father_son().
clauses
    father(vladimir,alexey).
    father(ivan,anton).
    father(anatoliy,stepan).
    father(uriy,foma).
        
    son(mihail,oleg).
    son(vitaliy,vladimir).
    son(anatoliy,nikolay).
    son(sidor,fedor).
    
    brother(nikifor,victor).
    brother(cidor,nikolay).
    brother(boris,andrey).
    brother(vladimir,mihail).
    brother(foma,petra).
    brother(yakov,nikifor).
    brother(fedor,foma).
    brother(leonid,vitaliy).
    brother(yakov,boris).
    brother(stepan,andrey).
    brother(victor,stepan).
    brother(oleg,anton).

    k_brothers(B1,B2):-
        brother(B1,B2);
        brother(B2,B1).

    brothers(B1,B2):-
        retractall(names(_)),
        assert(names([B1])),
        brothers1(B1,B2).
    
    brothers1(B,B).
    brothers1(B1,B2):- 
        k_brothers(B1,B3),
        names(List),
        not(member(B3,List)),
        retract(names(List)),
        List1=[B3|List],
        assert(names(List1)),
        brothers1(B3,B2).
        
    father_son(F,S):-
        father(F,S);
        son(S,F);
        father(F,S1),brothers(S1,S),S1<>S;
        son(S1,F),brothers(S1,S),S1<>S.    

    member(El,[El|_]):- !.
    member(El,[_|L]):- member(El,L).

    find_father_son():-
        retractall(count(_)),
        assert(count(0)),
        father_son(F,S),
            write("father - ",F,", \tson - ",S),nl,
            retract(count(N)),
            N1=N+1,
            assert(count(N1)),
        fail;
        count(X),
        write("\nКоличество пар father-son: ",X),nl.
goal
    find_father_son().
Вот что получается с отцами-сыновьями:
Код:
father - vladimir, son - alexey
father - ivan,     son - anton
father - anatoliy, son - stepan
father - uriy,     son - foma
father - oleg,     son - mihail
father - vladimir, son - vitaliy
father - nikolay,  son - anatoliy
father - fedor,    son - sidor
father - ivan,     son - oleg
father - anatoliy, son - andrey
father - anatoliy, son - boris
father - anatoliy, son - yakov
father - anatoliy, son - nikifor
father - anatoliy, son - victor
father - uriy,     son - petra
father - uriy,     son - fedor
father - oleg,     son - vladimir
father - vladimir, son - leonid

Количество пар father-son: 18
yes
Ответить с цитированием
  (#3 (permalink)) Старый
Julli Julli вне форума
Member
 
Сообщений: 20
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 02.12.2007
По умолчанию 16.12.2007, 16:10

Буду разбираться. Большое Спасибо, что помагаете, не оставляете без ответа!
Ответить с цитированием
  (#4 (permalink)) Старый
Julli Julli вне форума
Member
 
Сообщений: 20
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 02.12.2007
По умолчанию 16.12.2007, 21:02

Может я не в ту сторону думаю, но переделать мне не совсем удалось.
Дабавила вместо father_son такое правило
Код:
ded_vnuk(D,V):-
        father(D,F),son(V,F),brothers(V,V1),V<>V1;
        son(F,D),father(F,V),brothers(V,V1),V<>V1;
           father(D,F),father(F,V),brothers(V,V1),V<>V1;
    son(V,F),son(F,D),brothers(V,V1),V<>V1.
Получается 2 ответа и одинаковых. У меня других вариантов нет
Ответить с цитированием
  (#5 (permalink)) Старый
Alison Alison вне форума
Member
 
Сообщений: 4,781
Сказал(а) спасибо: 0
Поблагодарили 119 раз(а) в 116 сообщениях
Регистрация: 17.11.2004
По умолчанию 16.12.2007, 23:11

Надо исправить предикат brothers1, а то иногда факт с names удалялся, а потом не добавлялся.
Я привыкла в VIP7 с фактами-переменными, там проще все. А в Турбе надо внимательней следить за assert-retract.
В общем, надо так:
Код:
    brothers1(B,B).
    brothers1(B1,B2):- 
        k_brothers(B1,B3),
        names(List),
        not(member(B3,List)),
        retract(names(List)),
        List1=[B3|List],
        assert(names(List1)),
        brothers1(B3,B2).
Всего пар father-son будет 18 (выше я исправила). И в Никифоре была опечатка, насколько я понимаю.

Пар дед-внук там, конечно, должно быть больше. Над этим надо еще подумать.
Ответить с цитированием
Ads.
  (#6 (permalink)) Старый
Julli Julli вне форума
Member
 
Сообщений: 20
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 02.12.2007
По умолчанию 17.12.2007, 00:00

Да, с Никифором действительно ошибочка вышла. А вот по условию 2 раза повторяется "Михаил явл. братом Владимира", это тоже наверное опечатка, иначе зачем она там. И в примечании к задаче написано, что все имена уникальны (одно имя - один человек).
После исправлений уже выдает 5 пар "дед-внук" Николай и Степан, что по условию подходит, но почему 5?а брата вообще не хочет искать.
Ответить с цитированием
  (#7 (permalink)) Старый
Alison Alison вне форума
Member
 
Сообщений: 4,781
Сказал(а) спасибо: 0
Поблагодарили 119 раз(а) в 116 сообщениях
Регистрация: 17.11.2004
По умолчанию 18.12.2007, 18:24

Раз пары отец-сын все находятся, то найти все пары дед-внук уже легко, если не описывать это отношение заново, а использовать отец-сын. Проще всего здесь сделать так:
Код:
domains
    slist = symbol*
database - rel
    father(symbol,symbol)
    son(symbol,symbol)
    brother(symbol,symbol)
database
    determ names(slist)    
    determ count(integer)
    f_s(symbol,symbol)
predicates    
    nondeterm brothers(symbol,symbol)
    nondeterm k_brothers(symbol,symbol)
    nondeterm brothers1(symbol,symbol)
    nondeterm father_son(symbol,symbol)
    determ member(symbol,slist)
    nondeterm gfather_gson(symbol,symbol)
    determ find_father_son()
    determ find_gfather_gson()
clauses
    father(vladimir,alexey).
    father(ivan,anton).
    father(anatoliy,stepan).
    father(uriy,foma).
        
    son(mihail,oleg).
    son(vitaliy,vladimir).
    son(anatoliy,nikolay).
    son(sidor,fedor).
    
    brother(nikifor,victor).
    brother(cidor,nikolay).
    brother(boris,andrey).
    brother(vladimir,mihail).
    brother(foma,petra).
    brother(yakov,nikifor).
    brother(fedor,foma).
    brother(leonid,vitaliy).
    brother(yakov,boris).
    brother(stepan,andrey).
    brother(victor,stepan).
    brother(oleg,anton).

    k_brothers(B1,B2):-
        brother(B1,B2);
        brother(B2,B1).

    brothers(B1,B2):-
        retractall(names(_)),
        assert(names([B1])),
        brothers1(B1,B2).
    
    brothers1(B,B).
    brothers1(B1,B2):- 
        k_brothers(B1,B3),
        names(List),
        not(member(B3,List)),
        retract(names(List)),
        List1=[B3|List],
        assert(names(List1)),
        brothers1(B3,B2).
        
    father_son(F,S):-
        father(F,S);
        son(S,F);
        father(F,S1),brothers(S1,S),S1<>S;
        son(S1,F),brothers(S1,S),S1<>S.    

    member(El,[El|_]):- !.
    member(El,[_|L]):- member(El,L).

    find_father_son():-
        retractall(count(_)),
        assert(count(0)),
        father_son(F,S),
            write("father - ",F,", \tson - ",S),nl,
            retract(count(N)),
            N1=N+1,
            assert(count(N1)),
        fail;
        count(X),
        write("\nКоличество пар father-son: ",X),nl.

    gfather_gson(GF,GS):-
        father_son(X,Y),
            assert(f_s(X,Y)), 
        fail;
        f_s(GF,F),f_s(F,GS).

    find_gfather_gson():-
        retractall(count(_)),
        assert(count(0)),
        gfather_gson(GF,GS),
            writef("grandfather - %-10 \tgrandson - %\n",GF,GS),
            retract(count(N)),
            N1=N+1,
            assert(count(N1)),
        fail;
        count(X),
        write("\nКоличество пар grandfather-grandson: ",X),nl.

goal
find_gfather_gson().
Вот ответ:
Код:
grandfather - nikolay        grandson - stepan
grandfather - nikolay        grandson - andrey
grandfather - nikolay        grandson - boris
grandfather - nikolay        grandson - yakov
grandfather - nikolay        grandson - nikifor
grandfather - nikolay        grandson - victor
grandfather - ivan           grandson - mihail
grandfather - ivan           grandson - vladimir
grandfather - uriy           grandson - sidor
grandfather - oleg           grandson - alexey
grandfather - oleg           grandson - vitaliy
grandfather - oleg           grandson - leonid

Количество пар grandfather-grandson: 12
yes
Ответить с цитированием
  (#8 (permalink)) Старый
Julli Julli вне форума
Member
 
Сообщений: 20
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 02.12.2007
По умолчанию 19.12.2007, 00:31

Да, действительно. Я тоже думала, что нужно как-то на основе "отец-сын" делать. Большое спасибо.
Только вот несовсем понятно с правилом
Код:
gfather_gson(GF,GS):-
        father_son(X,Y),
            assert(f_s(X,Y)),
        fail;
        f_s(GF,F),f_s(F,GS).
Вносим "отец-сын" в базу и ищем новые, а f_s(GF,F),f_s(F,GS) - что значит?f_s(дед, его сын),F_s(сын, внук)? Не пойму как Пролог это находит.
Ответить с цитированием
  (#9 (permalink)) Старый
Julli Julli вне форума
Member
 
Сообщений: 20
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 02.12.2007
По умолчанию 19.12.2007, 00:31

Да, действительно. Я тоже думала, что нужно как-то на основе "отец-сын" делать. Большое спасибо.
Только вот несовсем понятно с правилом
Код:
gfather_gson(GF,GS):-
        father_son(X,Y),
            assert(f_s(X,Y)),
        fail;
        f_s(GF,F),f_s(F,GS).
Вносим "отец-сын" в базу и ищем новые, а f_s(GF,F),f_s(F,GS) - что значит?f_s(дед, его сын),F_s(сын, внук)? Не пойму как Пролог это находит.
Ответить с цитированием
  (#10 (permalink)) Старый
Julli Julli вне форума
Member
 
Сообщений: 20
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 02.12.2007
По умолчанию 19.12.2007, 00:31

Да, действительно. Я тоже думала, что нужно как-то на основе "отец-сын" делать. Большое спасибо.
Только вот несовсем понятно с правилом
Код:
gfather_gson(GF,GS):-
        father_son(X,Y),
            assert(f_s(X,Y)),
        fail;
        f_s(GF,F),f_s(F,GS).
Вносим "отец-сын" в базу и ищем новые, а f_s(GF,F),f_s(F,GS) - что значит?f_s(дед, его сын),F_s(сын, внук)? Не пойму как Пролог это находит.
Ответить с цитированием
Ads
Ответ

Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Trackbacks are Вкл.
Pingbacks are Вкл.
Refbacks are Выкл.


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
вопрос по инет связи funnycaptain Планшетные ПК 1 29.11.2011 16:16
Программист ПО для голосовой связи, г.Москва Кристина Илюхина Работа 0 25.11.2011 19:04
Access и Delphi таблицы и связи surrender Другие СУБД 7 11.10.2011 21:28
Глушилка мобильной связи Tribel Техническая поддержка 0 29.09.2011 18:28
Увеличение связи bas53 Любые вопросы от новичков 1 27.08.2011 18:17
Socket проверка связи In_spector Visual C++ 4 05.06.2011 00:33
Таблица и связи между ними Gansss MySQL 1 13.11.2007 19:54
Огранизация связи между приложениями roman83 Delphi 3 24.09.2007 18:02
Как создать межмодульные связи eugira C++ Builder 3 24.12.2006 15:45
Вакансия:Архитектор сетей связи GeneralistAgency Работа 0 20.06.2006 20:00
Разрыв связи по BlueTooth. Как устранить Thomas A. Anderson Windows CE 13 10.05.2006 20:27
Проблема с установкой связи с mysql из .jsp † Stratos † Java 2 18.12.2005 23:46



Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
Нardforum.ru - компьютерный форум и программирование, форум программистов