Правильное использование логических языков в качестве инструмента

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

Что привлекло меня к идее использования логического программирования, так это мои смутные знания об идее "объединения", но я подумал о том, чтобы использовать это так, что я не уверен, что это идиоматично или правильно. Учитывая два объекта (или деревья), я хочу сравнить два на равенство через их свойства (или листья), и что я хочу вернуть, это некоторое представление о "разнице"- то есть, учитывая способы, которыми эти два объекта являются Не отличается ли это, какие изменения должны были бы быть сделаны в одном из них, чтобы эти два понятия были одинаковыми?

Например, скажем, у меня есть два объекта chair а также stool, Предположим, что каждый состоит из списка свойств или атрибутов, я хотел бы построить систему, которая может возвращать что-то вроде "стул и стул будут равны, если стул legCount мы 4 а также hasBack мы true".

По какой-то причине, семантически я представляю это как своего рода остаток, вроде, chair минус stool равняется одному leg, Не уверен, полезно это или нет...

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

1 ответ

Решение

Возможно, вы хотите посмотреть на "Наименьшее общее обобщение" или "анти-объединение" из литературы ILP:

Вот несколько слайдов: http://soft.vub.ac.be/~cderoove/declarative_programming/decprog7.pdf

Использование кода из просто логической главы 9 http://people.cs.bris.ac.uk/~flach/SL/SL.pdf:

:-op(600,xfx,'<-').

anti_unify(Term1,Term2,Term):-
    anti_unify(Term1,Term2,Term,[],S1,[],S2).

anti_unify(Term1,Term2,Term1,S1,S1,S2,S2):-
    Term1 == Term2,!.
anti_unify(Term1,Term2,V,S1,S1,S2,S2):-
    subs_lookup(S1,S2,Term1,Term2,V),!.
anti_unify(Term1,Term2,Term,S10,S1,S20,S2):-
    nonvar(Term1),nonvar(Term2),
    functor(Term1,F,N),functor(Term2,F,N),!,
    functor(Term,F,N),
    anti_unify_args(N,Term1,Term2,Term,S10,S1,S20,S2).
anti_unify(T1,T2,V,S10,[T1<-V|S10],S20,[T2<-V|S20]).



anti_unify_args(0,Term1,Term2,Term,S1,S1,S2,S2).
anti_unify_args(N,Term1,Term2,Term,S10,S1,S20,S2):-
    N>0, N1 is N-1,
    arg(N,Term1,Arg1),
    arg(N,Term2,Arg2),
    arg(N,Term,Arg),
    anti_unify(Arg1,Arg2,Arg,S10,S11,S20,S21),
    anti_unify_args(N1,Term1,Term2,Term,S11,S1,S21,S2).

subs_lookup([T1<-V|Subs1],[T2<-V|Subs2],Term1,Term2,V):-
    T1 ==Term1,
    T2 ==Term2,!.
subs_lookup([S1|Subs1],[S2|Subs2],Term1,Term2,V):-
   subs_lookup(Subs1,Subs2,Term1,Term2,V).

Тогда вы можете запросить:

?- anti_unify(object(type=chair,legs=4,hasback=true,color=red),object(type=stool,legs=3,hasback=false,color=red),T,[],S1,[],S2).
T = object(type=_1838, legs=_1808, hasback=_1778, color=red),
S1 = [chair<-_1838, 4<-_1808, true<-_1778],
S2 = [stool<-_1838, 3<-_1808, false<-_1778] .

Это дает вам Термин, который является наименее общим обобщением наших двух объектов наряду с заменами, которые вы сделаете, чтобы получить объекты обратно.

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