I have some clauses where the head represents the names and values of a set of variables in a linear equation and the body the actual equation. Like so:
:-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}.
Is there a straightforward way to (indirectly) get the coefficients for this equation? I.e. a rule which returns coefficient(VARNAME, COEFFICIENT)
e.g. coefficient(x1, 0.5), coefficient(x2, 0.6)
and so on.
I know this might seem like a stupid question given that it would be easy to just put all coefficients in the head of the clause. But in my application i want the head of these clauses to strictly show the values of each variable (and not their coefficients). I.e. to avoid ambiguity.
My current solution is a convoluted and unelegant one involving member/2
, subtract/3
, maplist/2
and setting X1, X2, X3 to one or zero to figure out each slope.
Related question: Representing linear functions in prolog
Thanks!
/JC
This is my first use of
clpr
so if this is unhelpful to you I plead insanity, but to me, the key here seems to be usingdump/3
to convert the constraint back into a Prolog expression and then traversing it like any other structure. So I obtain the constraint again by doing this:I think it's worth remembering what this looks like under the hood using
write_canonical
:Traversing a polynomial you should be covered by only a few simple cases; the following may actually be overkill:
Your base case really is the X*Y case where they are both atomic. The rest of the clauses are really just there to unwrap nesting. This appears to do what you want:
To really generalize this you probably will need to use
maplist
et. al. to convert your independents/dependents lists into the variables you will need to pass todump/3
and then handle the case where you have multiple equations in the result, but I don't think this will be very challenging for you.Hope this helps!