1 | initial version |
One thing is that in mathematics we usually identify a function of two variables and a function of a two-dimensional vector variable. When programming however, these are slightly different.
So if we define:
def f(x, y):
return vector([(x^2+15*x-2) / (x+15), (x^2*y+x*y+y) / (x^2+30*x-1)])
def g(x, y):
return vector([(x^2+20*x-18) / (x+20), (x^2*y+x*y+32*y) / (x^2-31*x+14)])
then we can't do f(g(x, y))
and instead have to do f(*g(x, y))
and so we can define:
def fog(x, y):
return f(*g(x, y))
From there, there are several approaches to computing with rational functions:
One problem here is that the expressions are not simplified.
sage: x, y = var('x y')
sage: f(x, y)
((x^2 + 15*x - 2)/(x + 15), (x^2*y + x*y + y)/(x^2 + 30*x - 1))
sage: g(x, y)
((x^2 + 20*x - 18)/(x + 20), (x^2*y + x*y + 32*y)/(x^2 - 31*x + 14))
sage: f(*g(x, y))
(((x^2 + 20*x - 18)^2/(x + 20)^2 + 15*(x^2 + 20*x - 18)/(x + 20) - 2)/((x^2 + 20*x - 18)/(x + 20) + 15), ((x^2*y + x*y + 32*y)/(x^2 - 31*x + 14) + (x^2*y + x*y + 32*y)*(x^2 + 20*x - 18)^2/((x^2 - 31*x + 14)*(x + 20)^2) + (x^2*y + x*y + 32*y)*(x^2 + 20*x - 18)/((x^2 - 31*x + 14)*(x + 20)))/((x^2 + 20*x - 18)^2/(x + 20)^2 + 30*(x^2 + 20*x - 18)/(x + 20) - 1))
This is much better.
sage: R.<x, y> = PolynomialRing(QQ)
sage: S = R.fraction_field()
sage: x, y = S.gens()
sage: f(x, y)
((x^2 + 15*x - 2)/(x + 15), (x^2*y + x*y + y)/(x^2 + 30*x - 1))
sage: g(x, y)
((x^2 + 20*x - 18)/(x + 20), (x^2*y + x*y + 32*y)/(x^2 - 31*x + 14))
sage: f(*g(x, y))
((x^4 + 55*x^3 + 962*x^2 + 4930*x - 5876)/(x^3 + 55*x^2 + 982*x + 5640),
(x^6*y + 42*x^5*y + 478*x^4*y + 1419*x^3*y + 13026*x^2*y - 9172*x*y
+ 11648*y)/(x^6 + 39*x^5 - 593*x^4 - 36773*x^3 - 320694*x^2 + 486956*x
- 152264))
This is probably the best approach for studying composition of rational maps.
See the documentation.