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

У меня есть база фактов, полная interacts отношения:

% Drug, Drug, Interaction Effect
interacts(terbinafine,tramadol,muscle_spasm).
interacts(terbinafine,triazolam,amnesia).
interacts(terbinafine,warfarin,arterial_pressure_nos_decreased).
interacts(terbinafine,warfarin,bradycardia).
interacts(terbinafine,rosiglitazone,hyperglycaemia).
interacts(terbinafine,allopurinol,arterial_pressure_nos_decreased).

И функция, которая определяет, взаимодействуют ли два препарата друг с другом:

interacts_with(D1, D2) :-
  interacts(D1, D2, _) ; interacts(D2, D1, _).

Я пытаюсь перечислить все эффекты взаимодействия двух данных препаратов. Учитывая, что два препарата взаимодействуют друг с другом (interacts_with() возвращается true), как бы я собрал побочные эффекты этих двух лекарств?

Например:

interacts_with(terbinafine, warfarin).

Должен вернуться:

[arterial_pressure_nos_decreased, bradycardia]

Я пытался с findall/3, но я получаю только то, что передаю, в списке, содержащем больше совпадений:

?- findall([terbinafine, warfarin], interacts_with(D1, D2), Foo).
Foo = [[terbinafine, warfarin], [terbinafine, warfarin], [terbinafine, warfarin], [terbinafine, warfarin], [terbinafine, warfarin], [terbinafine, warfarin], [terbinafine, warfarin], [terbinafine|...], [...|...]|...].

редактировать

Я попытался реализовать то, что предложил @false:

    interacts_with(D1, D2) :-
        interacts(D1, D2, _) ; interacts(D2, D1, _).

    print_effects(D1, D2) :-
        ( interacts_with(D1,D2)
            -> findall([D1, D2], interacts_with(D1, D2), [])
            ; write(D1), write(" does not interact with "), write(D2)
        ).

И теперь я получаю:

?- print_effects(terbinafine, warfarin).
false.

И то и другое setof а также findall возвращаются false а не список лекарств, которые были переданы в

1 ответ

Решение

Прежде всего, ваша база знаний состоит из взаимодействующих фактов /3: два наркотика и их взаимодействие. Затем вы определяете предикат Interacts_with/2, который имеет только два препарата в качестве аргументов. Взаимодействие скрыто в теле правила и поэтому недоступно для главы правила, которая по сути является его интерфейсом. Еще раз посмотрев на Interacts/3, вы можете в интерактивном режиме запросить эффекты двух препаратов вместе:

   ?- interacts(terbinafine,warfarin,I).
I = arterial_pressure_nos_decreased ? ;
I = bradycardia

Обратите внимание, что результатом запроса является один из аргументов предикатов (I), который оставлен как переменная. Пролог затем объединяет эту переменную со всеми взаимодействиями, которые соответствуют обоим препаратам. Это то, что я имел в виду выше, когда писал " доступно из головы", что по сути является его интерфейсом. Вы можете использовать findall/3 или setof/3, чтобы получить все решения для вышеуказанного запроса в виде списка:

   ?- findall(I,interacts(terbinafine,warfarin,I),AI).
AI = [arterial_pressure_nos_decreased,bradycardia]

   ?- setof(I,interacts(terbinafine,warfarin,I),AI).
AI = [arterial_pressure_nos_decreased,bradycardia]

Последний удаляет дубликаты из списка, если таковые имеются.

Другие вопросы по тегам