Создание ограничений декомпозиции для ограничений
Рассмотрим следующую схему:
:- use_module(library(chr)).
:- chr_constraint
a/1,
b/1.
% really there will be many of these, possibly 100s
% some rules about how to replace as with bs, e.g.,
a(1),a(1) <=> b(2).
% a way to decompose, e.g., b(2) <=> b(1), b(1)
a(X) <=> X #> 1, Y #= X-1 | a(Y), a(1).
b(X) <=> X #> 1, Y #= X-1 | b(Y), b(1).
% except I have to write these for all 100+ variables
Я знаю, что пролог способен к метапрограммированию, и считаю, что его можно использовать для генерацииx(X)
разложения выше, но я совсем не знаю, как это сделать. Я был близок однажды, используя=..
чтобы разобрать и собрать звонки, но потом мне пришлось написать что-то вроде n(a(2))
везде. В идеале я бы написалn(a)
один раз, и будет добавлено правильное правило ограничения (утверждено?):
Было бы разумнее сделать что-то вроде
n(X) <=> %... or possibly :-
n(a).
n(b).
% a(X) <=> ... and b(X) <=> ... are added to the "database" of rules
Если бы это была шепелявка, я бы мог написать макрос для этого, я думаю. И пролог должен быть гомоиконным, как шепелявый, так что это теоретически достижимо. Я просто не знаю как.
Как мне написать "макрос" декомпозера в стиле, похожем на приведенный выше?
1 ответ
Думаю, это просто решает проблему.
:- chr_constraint mycon/2, fuel/0, ore_add/1, total_ore/1.
mycon(a,1),mycon(a,1) <=> mycon(ore,9).
mycon(b,1),mycon(b,1),mycon(b,1) <=> mycon(ore,8).
mycon(c,1),mycon(c,1),mycon(c,1),mycon(c,1),mycon(c,1) <=> mycon(ore,7).
mycon(ab,1) <=> mycon(a,3),mycon(b,4).
mycon(bc,1) <=> mycon(b,5),mycon(c,7).
mycon(ca,1) <=> mycon(c,4),mycon(a,1).
fuel <=> mycon(ab,2),mycon(bc,3),mycon(ca,4).
%Decompose foo/N into foo/1s
mycon(Type,X) <=> X>1,Y#=X-1|mycon(Type,Y),mycon(Type,1).
total_ore(A), total_ore(Total) <=> NewTotal #= A + Total, total_ore(NewTotal).
ore_add(A) ==> total_ore(A).
mycon(ore,1) <=> ore_add(1).
Более чистый вид с оператором:
:- op(900, xfx, (of)).
:- chr_constraint fuel/0, ore_add/1, total_ore/1,of/2.
1 of a,1 of a <=> 9 of ore.
1 of b,1 of b,1 of b <=> 8 of ore.
1 of c,1 of c,1 of c,1 of c,1 of c <=> 7 of ore.
1 of ab <=>3 of a,4 of b.
1 of bc <=> 5 of b,7 of c.
1 of ca <=> 4 of c,1 of a.
fuel <=> 2 of ab,3 of bc,4 of ca.
%Decompose foo/N into foo/1s
X of Type <=> X>1,Y#=X-1|Y of Type,1 of Type.
total_ore(A), total_ore(Total) <=> NewTotal #= A + Total, total_ore(NewTotal).
ore_add(A) ==> total_ore(A).
1 of ore <=> ore_add(1).