2

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

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

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

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

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

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

+0

Благодаря, но его не ко то будет несвязанным в этом сценарий, но и V и N – fafner

+0

К сожалению, я читал «привязанный», а не «несвязанный». В этом случае вы не можете использовать 'is'. Левая должна быть единственной, несвязанной переменной, а справа должны быть все связанные переменные. Prolog не будет перечислять возможные решения выражения 'is/2'. – lurker

+0

ОК, спасибо, я не знал, что :) Возможно ли, что я могу проверить, связаны ли переменные перед тем, как сделать это/2? – fafner

ответ

0

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

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

2

Использование 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. 
+0

Спасибо :) Но я не думаю, что мне разрешено использовать любые внешние библиотеки для этого проекта: / – fafner