Рекурсия в Прологе и не только

У меня есть эта база знаний в прологе авиакомпании и их рейсов:

flight(departure,arrive,day).

flight(london,paris,monday).
flight(paris,barcelona,thursday).
flight(paris,madrid,sunday).
flight(madrid,lisbon,saturday).

рекурсивные правила:

connection(Departure,Arrive):-flight(Departure,Arrive,Day).
connection(Departure,Arrive):-flight(Departure,X,Day),connection(X,Arrive).

И в связи с этим я могу задать вопрос: возможна ли связь между Лондоном и Барселоной?

вопрос: connection(london,barcelona).

И ответ будет утвердительным. Но есть ли какие-либо правила/вопросы, которые я могу задать, чтобы получить более подробную информацию?

например: связь между Лондоном и Барселоной прямая или косвенная?

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

может ли кто-нибудь помочь мне понять это?


person cdiogo7    schedule 22.09.2015    source источник
comment
Да, вы можете построить свои предикаты, чтобы определить, является ли рейс, скажем, прямым или непрямым. Один из способов — собрать маршрут в список в качестве дополнительного аргумента. Если маршрут имеет более 2 элементов, он непрямой. Это также отвечает на вопрос, какой город или города находятся между ними.   -  person lurker    schedule 23.09.2015
comment
Спасибо. но не могли бы вы привести пример? Я новичок в Прологе, и я не знаю, как его запустить.   -  person cdiogo7    schedule 23.09.2015
comment
Пожалуйста, добавьте больше данных! Прямо сейчас Weekday игнорируется... разве его нельзя как-то использовать?   -  person repeat    schedule 23.09.2015


Ответы (1)


Я создал простую программу, которая использует дни. В примере программы я предполагаю три дня.

дни_ожидания( 3 ). /* получить указанный день недели. Например 3 день с понедельника -> понедельник, вторник, среда */

Пожалуйста, скорректируйте дни ожидания_дней. И я сделал другие исправления.

Я проверил следующие программы с помощью SWI-Prolog и LPA Prolog.

/* flight_city(london,barcelona, monday). */

weekday( [sunday, monday, tuesday, wednesday, thursday, friday, saturday] ).
waiting_days( 3 ).   /* acquire the specified day of the week.  For example 3 day monday -> monday, tuesday, wednesday */


flight_city( Departure, Arrive, Day ) :-
        connection(Departure, Arrive, Day, []).

connection(Departure, Arrive, Day, City_list) :-
        flight(Departure, Arrive, Flight_Day),

        not( member( Departure, City_list ) ),

        waiting_days_get( Day, Days ),

        member( Flight_Day, Days ),
%       !,
        append( [Arrive, Departure], City_list, City_list2 ),
        reverse( City_list2, City_list3 ),

        write_city_list( City_list3 ),

        fail.

connection(Departure,Arrive, Day, City_list ) :-
        flight(Departure,X,Flight_Day),

        /* Prevention of an infinite loop */
        not( member( Departure, City_list ) ),

        waiting_days_get( Day, Days ),

        member( Flight_Day, Days ),

        append( [Departure], City_list, City_list2 ),

        connection(X, Arrive, Flight_Day, City_list2 ).


direct_check( 2, _, [] ) :- !.

direct_check( Citys_number, [_ | Result], Middle ) :-
        2 < Citys_number, !,
        middle_get( Result, Middle ).

direct_check( _, _, _ ) :- fail.


middle_get( [_], [] ) :- !.

middle_get( [First | Result], [First | Result2] ) :-
        middle_get( Result, Result2 ).


waiting_days_get( Today, Days ) :-
        weekday( Weekday ),
        waiting_days( Count ),
        ( 7 < Count -> Count2 is 7;
         Count2 is Count
        ),
        waiting_days_get_this_week( Weekday, Today, Count2, This_week_days ),
        length( This_week_days, Num2 ),
        Count3 is Count2 - Num2,
        waiting_days_get_next_week( Count3, Weekday, Next_week_days ),
        append( This_week_days, Next_week_days, Days ).



waiting_days_get_this_week( [Today |Result ], Today, Count, Days ) :-
        !,
        waiting_days_get_main( Count, [Today | Result], Days ).

waiting_days_get_this_week( [_ | Result], Today, Num, Days ) :-
        waiting_days_get_this_week(Result, Today, Num, Days ).


waiting_days_get_main( 0, _, [] ) :- !.

waiting_days_get_main( _, [], [] ) :- !.

waiting_days_get_main( Count, [Day | Result], [Day |Result2 ] ) :-
        Count2 is Count - 1,
        waiting_days_get_main( Count2, Result, Result2 ).



waiting_days_get_next_week( 0, _, [] ) :- !.

waiting_days_get_next_week( Count, [First | Result], [First | Days] ) :-
        Count2 is Count - 1,
        waiting_days_get_next_week( Count2, Result, Days ).


write_city_list( City_list3 ) :-

        length( City_list3, Citys_number ),

        direct_check( Citys_number, City_list3, Middle ),

        write( City_list3 ), nl,

        ( Citys_number == 2 -> write( 'direct' ), nl, nl;
         write( 'indirect' ), nl,
         write( Middle ), nl, nl
        ), !.



flight(london,paris,monday).
flight(paris,barcelona,thursday).
flight(paris,madrid,sunday).
flight(madrid,lisbon,saturday).
flight(london,tokyo,monday).
flight(tokyo, paris, monday).
flight(london,barcelona,monday).
flight(london,lisbon,monday).
flight(lisbon,barcelona,monday).
flight(tokyo,london,monday).
person Zimoto Yosihumi    schedule 23.09.2015