Пролог равен /2, аргументы недостаточно конкретизированы

Я работаю над заданием, где я создал парсер для арифметического языка префиксной записи. Мне нужно написать предикат, который строит ast для любого заданного значения V (т. е. генерирует ast A таким образом, что всякий раз, когда A оценивается, его значение равно V). Моя идея была достаточно проста:

genAst(Val, Env, Ast) :-
   ev(Ast, Env, Val).

где ev — предикат оценки. Когда я запускаю это, я получаю сообщение об ошибке в заголовке, касающемся этой части предиката ev:

ev(xer_(power(N)), Env, V) :-
   integer(N),
   V is Env^N. %THIS LINE

где и V, и N не связаны. Я изо всех сил пытаюсь придумать другой элегантный способ сделать это, кто-нибудь знает, как я могу заставить пролог генерировать целые числа для этих двух переменных?

Надеюсь, это было понятно :)


person Community    schedule 18.11.2013    source источник
comment
Ой, извините, я прочитал связанный, а не несвязанный. В этом случае вы не можете использовать is. Слева должна быть одна несвязанная переменная, а справа должны быть все связанные переменные. Пролог не будет перечислять возможные решения выражения is/2.   -  person lurker    schedule 18.11.2013
comment
Конечно, вы можете использовать var/1 или nonvar/1.   -  person lurker    schedule 18.11.2013
comment
Хорошо, я могу как-нибудь спросить Пролог, например, 4 =:= 2^X ? Это также дает мне не созданные аргументы, но я пробовал 4 == 2 ^ X и 4 = 2 ^ X безрезультатно.   -  person    schedule 18.11.2013
comment
Оператор =:= требует, чтобы все было инстанцировано. Спрашивая 4 =:= 2^X, я предполагаю, что вы имеете в виду, что хотите log2(4). Таким образом, вы можете использовать X is log10(4)/log10(2)., а затем использовать свои интерпретаторы пролога и другие арифметические функции, чтобы определить, является ли это целым числом. Или, поскольку база равна 2, вы можете легко создать предикат, который выполняет log2, используя сдвиги.   -  person lurker    schedule 18.11.2013


Ответы (2)


Как поставлено, ваша проблема кажется неразрешимой, тогда я думаю, что подошел бы ко всей проблеме по-другому, создав все AST до максимального количества токенов.

genAst(Val, Env, Ast) :-
    length(Tokens, N),
    (N > 10, !, fail ; true),
    phrase(sum(Ast), Tokens),
    ev(Ast, Env, Val).

sum(sum(A,B)) --> [+], mul(A), sum(B).
sum(N) --> mul(N).

mul(mul(N,X)) --> [*], xer(X), num(N).
mul(N) --> xer(N).

xer(exp(x,N)) --> [^,x], num(N).
xer(var(x)) --> [x].
xer(N) --> num(N).

%num(num(X)) --> [X], {var(X) -> between(1,9,X) ; integer(X)}.
num(num(X)) --> [X], {X=2;X=3}.

урожаи

?- genAst(6,2,A).
A = sum(num(3), num(3)) ;
A = mul(num(3), var(x)) ;
A = mul(num(3), num(2)) ;
A = mul(num(2), num(3)) ;
A = sum(mul(num(2), var(x)), var(x)) ;
A = sum(mul(num(2), var(x)), num(2)) ;
A = sum(mul(num(2), num(2)), var(x)) ;
A = sum(mul(num(2), num(2)), num(2)) ;
A = sum(exp(x, num(2)), var(x)) ;
A = sum(exp(x, num(2)), num(2)) ;
A = sum(var(x), sum(var(x), var(x))) ;
A = sum(var(x), sum(var(x), num(2))) ;
A = sum(var(x), sum(num(2), var(x))) ;
A = sum(var(x), sum(num(2), num(2))) ;
A = sum(var(x), mul(num(2), var(x))) ;
A = sum(var(x), mul(num(2), num(2))) ;
A = sum(var(x), exp(x, num(2))) ;
A = sum(num(2), sum(var(x), var(x))) ;
A = sum(num(2), sum(var(x), num(2))) ;
A = sum(num(2), sum(num(2), var(x))) ;
A = sum(num(2), sum(num(2), num(2))) ;
A = sum(num(2), mul(num(2), var(x))) ;
A = sum(num(2), mul(num(2), num(2))) ;
A = sum(num(2), exp(x, num(2))) ;
false.

Ограничение длины ввода в этой DCG требуется из-за правильной рекурсивной нетерминальной суммы//1

person CapelliC    schedule 18.11.2013

Используйте library(clpfd). Он содержит именно такой функционал. И нет необходимости генерировать конкретные значения, если они вам не нужны!

?- X #= Y^Z.
Y^Z#=X.

?- X #= Y^Z, [Y,Z]ins 1..3.
 Y^Z#=X,
Y in 1..3,
Z in 1..3.

?- X #= Y^Z, [Y,Z]ins 1..3, labeling([], [Y,Z]).
X = Y, Y = Z, Z = 1 ;
X = Y, Y = 1,
Z = 2 ;
X = Y, Y = 1,
Z = 3 ;
X = Y, Y = 2,
Z = 1 ;
X = 4,
Y = Z, Z = 2 ;
X = 8,
Y = 2,
Z = 3 ;
X = Y, Y = 3,
Z = 1 ;
X = 9,
Y = 3,
Z = 2 ;
X = 27,
Y = Z, Z = 3.
person false    schedule 18.11.2013