1 | initial version |
There is some difference between "variables" as "expressions" and "variables" as "generators" of a polynomial ring.
For instance, everything introduced with var
is in the first world, and solve
works only for this world.
For short, introduce variables via var
, build the system, ask solve
to solve it.
When dealing with polynomial rings, the world is purely algebraic, so purely algebraic solve methods apply. In this case we are inside algebraic geometry, and the terminology is slightly unexpected. We want the variety
of points satisfying the given equations, as generators of an ideal. We have such a computed variety if it is finite only. The code wants exactly so many independent variables as independent equations.
So let us compare the two possibilities...
M = matrix(QQ, 3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9])
v = vector(QQ, [1, 2, 3])
yvars = var('y0,y1,y2')
yvector = vector(yvars)
solve([eq == val for eq, val in zip(M*yvector, v)], yvars)
which gives the result:
[[y0 == r1 - 1/3, y1 == -2*r1 + 2/3, y2 == r1]]
and as seen, there is not a unique solution for it.
And we obtain a "parametrized solution".
(It is not simple or obvious to do "the natural thing" in the polynomial world.)
If we slightly change $M$ into
M = matrix(QQ, 3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 99])
then there is a unique solution:
[[y0 == (-1/3), y1 == (2/3), y2 == 0]]
Doing the same in the variety world leads to an error, so i will slightly change $M$ to be of maximal rank.
M = matrix(QQ, 3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 99])
v = vector(QQ, [1, 2, 3])
R.<x,y,z> = QQ[]
w = vector([x, y, z])
J = R.ideal(list( M*w - v ))
J.variety()
And this gives:
[{z: 0, y: 2/3, x: -1/3}]
Depending on the application, we can chose the one or the other world, or even the more structural:
sage: M
[ 1 2 3]
[ 4 5 6]
[ 7 8 99]
sage: M^-1 * v
(-1/3, 2/3, 0)
since there is no need to introduce variables.