Доступ к коэффициентам в числовом выражении (clpr) - PullRequest
0 голосов
/ 21 февраля 2019

У меня есть несколько предложений, где голова представляет имена и значения набора переменных в линейном уравнении, а тело - фактическое уравнение.Вот так:

:-use_module(library(clpr)).    
relation(
        independents([
            var(x1, X1),
            var(x2, X2),
            var(x3, X3)
        ]),
        dependent(
            var(y, Y)
        )
    ):- {Y = 3 + 0.5 * X1 + 0.6 * X2 + 0.7 * X3}.

Есть ли прямой способ (косвенно) получить коэффициенты для этого уравнения?Т.е. правило, которое возвращает coefficient(VARNAME, COEFFICIENT) например coefficient(x1, 0.5), coefficient(x2, 0.6) и т. Д.

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

Мое текущее решение является запутанным и нелегальным, включающим member/2, subtract/3, maplist/2 и настройкой X1, X2, X3 в единицу или ноль для определения каждого уклона.

Смежный вопрос: Представление линейных функций в прологе

Спасибо!

/ JC

1 Ответ

0 голосов
/ 21 февраля 2019

Это мое первое использование clpr, поэтому, если это не поможет вам, я умоляю о безумии, но мне кажется, что ключ здесь использует dump/3 для преобразования ограничения обратно в выражение Prolog и его обходакак и любая другая структура.Таким образом, я снова получаю ограничение, выполняя это:

?- relation(independents([var(x1,X1),var(x2,X2),var(x3,X3)]),
            dependent(var(y,Y))), 
   dump([X1,X2,X3,Y],[x1,x2,x3,y], [y=Eqn]).
Eqn = 3.0+0.5*x1+0.6*x2+0.7*x3

Я думаю, стоит вспомнить, как это выглядит под капотом, используя write_canonical:

+(+(+(3.0,*(0.5,x1)),*(0.6,x2)),*(0.7,x3))

Обходя полином, вы должныбыть покрытым только несколькими простыми случаями;следующее может фактически быть излишним:

coefficient(X=Y, Var, Coeff) :-
    coefficient(X, Var, Coeff) ; coefficient(Y, Var, Coeff).
coefficient(X+Y, Var, Coeff) :-
    coefficient(X, Var, Coeff) ; coefficient(Y, Var, Coeff).
coefficient(X-Y, Var, Coeff) :-
    coefficient(X, Var, Coeff) ; coefficient(Y, Var, Coeff).
coefficient(X*Y, X, Y) :-
    atomic(X), atomic(Y).
coefficient(X*Y, Var, Coeff) :-
    coefficient(X, Var, Coeff) ; coefficient(Y, Var, Coeff).

Ваш базовый случай действительно является случаем X * Y, где они оба атомарны.Остальные пункты на самом деле просто для того, чтобы развернуть вложенность.Это, кажется, делает то, что вы хотите:

?- relation(independents([var(x1,X1),var(x2,X2),var(x3,X3)]),
            dependent(var(y,Y))), 
   dump([X1,X2,X3,Y],[x1,x2,x3,y], [y=Eqn]), 
   coefficient(Eqn, Var, Coeff).

Eqn = 3.0+0.5*x1+0.6*x2+0.7*x3,
Var = 0.5,
Coeff = x1,
{Y=3.0+0.5*X1+0.6*X2+0.7*X3} ;
Eqn = 3.0+0.5*x1+0.6*x2+0.7*x3,
Var = 0.6,
Coeff = x2,
{Y=3.0+0.5*X1+0.6*X2+0.7*X3} ;
Eqn = 3.0+0.5*x1+0.6*x2+0.7*x3,
Var = 0.7,
Coeff = x3,
{Y=3.0+0.5*X1+0.6*X2+0.7*X3} ;
false.

Чтобы действительно обобщить это, вам, вероятно, потребуется использовать maplist et.и др.чтобы преобразовать ваши списки независимых / зависимых в переменные, которые вам нужно будет передать в dump/3, а затем обработать случай, когда у вас есть несколько уравнений в результате, но я не думаю, что это будет очень сложно для вас.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...