Свернуть /1 не переставляет порядок решений
Для Observatorio Fiscal из Колумбии [1] я кодирую простую проблему минимизации налогов, используя CLP(R) (в SWI-Prolog). Я хочу использовать свернуть /1, чтобы сначала найти наименьшее решение. Вместо этого он сначала перечисляет большее решение. Вот код:
:- use_module(library(clpr)).
deduction(_,3). % Anyone can take the standard deduction.
deduction(Who,D) :- itemizedDeduction(Who,D). % Or they can itemize.
income(joe,10). % Joe makes $10 a year.
itemizedDeduction(joe,4). % He can deduct more if he itemizes.
taxableIncome(Who,TI) :-
deduction(Who,D),
income(Who,I),
TI is I - D,
minimize(TI).
Вот как выглядит интерактивная сессия:
?- taxableIncome(joe,N).
N = 7 ;
N = 6 ;
false.
Если я переключаю слово "минимизировать" на "максимизировать", оно ведет себя одинаково. Если я не включил предложение свернуть или развернуть, он не ищет третьего решения, но в остальном он ведет себя так же:
?- taxableIncome(joe,N).
N = 7 ;
N = 6.
[1] Observatorio Fiscal - это новая организация, которая стремится моделировать колумбийскую экономику, чтобы предвидеть последствия изменений в законодательстве, аналогично тому, что делают Бюджетное управление Конгресса или Центр налоговой политики в Соединенных Штатах.
2 ответа
Сначала добавим следующее определение в программу:
: - op (920, фу, *). *_.
С помощью (*)/1
Мы можем обобщить отдельные цели в программе.
Например, давайте обобщим minimize/1
цель путем размещения *
спереди:
taxableIncome (Кто,TI):- дедукция (Кто,D), доход (Кто,I), TI #= I - D, *минимизировать (TI).
Теперь мы получаем:
? - налогооблагаемый доход (X, Y). Х = Джо, Y = 7; Х = Джо, Y = 6
Это показывает, что CLP(R) на самом деле не имеет ничего общего с этой проблемой! Эти ответы показывают, что все уже создано в то время minimize/1
называется, так что нечего минимизировать.
Чтобы действительно извлечь выгоду из minimize/1
Вы должны выразить задачу в форме CLP(R) - или лучше: CLP(Q) - ограничения, затем применить minimize/1
на ограниченном выражении.
Также обратите внимание, что в SWI-Prolog и CLP(R), и CLP (Q) имеют элементарные ошибки, и вы не можете доверять их результатам.
Согласно ответу Мата, я переписал программу, выражающую ограничения, используя CLP. Сложность заключалась в том, что мне пришлось сначала собрать все (оба) возможных значения для вычета, а затем преобразовать эти значения в домен CLP. Я не мог заставить это преобразование работать в CLP(R), но я мог в CLP(FD):
:- use_module(library(clpfd)).
deduction(_,3). % Anyone can take the same standard deduction.
deduction(Who,D) :- % Or they can itemize.
itemizedDeduction(Who,D).
income(joe,10).
itemizedDeduction(joe,4).
listToDomain([Elt],Elt).
listToDomain([Elt|MoreElts],Elt \/ MoreDom) :-
MoreElts \= []
, listToDomain(MoreElts,MoreDom).
taxableIncome(Who,TI) :-
income(Who,I)
, findall(D,deduction(Who,D),DList)
, listToDomain(DList,DDomain)
% Next are the CLP constraints.
, DD in DDomain
, TI #= I-DD
, labeling([min(TI)],[TI]).