I'm trying to implement an algorithm which involves polynomials in two variables "x" and "y", but some times I need to interpret them as univariable polynomials (that is, leaving x as a constant), for example, in order use the function gcdex (the extended euclidean algorithm). Is there a simple way to make sympy interpret "x" as a constant instead of a variable?
I've tried the following:
import sympy
x = sympy.Symbol('x', constant=True)
y = sympy.Symbol('y')
f = sympy.Poly(x*y + y**2)
g = sympy.Poly(x+y)
(s, t, gcd) = sympy.gcdex(f,g)
but it throws an error: univariate polynomials expected.
The way to do this is to specify the generators of the polynomials when you create them. For instance, to treat only y as a variable, use
f = Poly(x*y + y**2, y)
By default, Poly assumes that all the symbols in an expression should be generators.
You can also pass the generator as the third argument to gcdex
s, t, gcd = gcdex(f, g, y)
gives
(s, t, gcd) == (Poly(0, y, domain='ZZ(x)'), Poly(1, y, domain='ZZ(x)'), Poly(x + y, x, y, domain='ZZ'))
Related
Why doesn't sympy divide this polynomial?
>>> import sympy as sp
>>> x,y = sp.symbols("x y")
>>> print(sp.div(y+x,y))
(0, x + y)
I was expecting the answer to be (1,x) because the quotient is 1 and the remainder is x. How can I get sympy to divide polynomials?
What I want is to express some polynomial p as p=aq+r where r is the remainder and q is the quotient and a is the divisor. In the example above, notice that y+x=1*x+y and so it seems to me that we should be able to find that 1 is the quotient of p by x.
some more details
Say I am working over a real multivariate polynomial ring, and say I want to express some polynomial p as p=aq+r for some non zero polynomial a and for some r with deg(r)<deg(q). By degree (deg) I mean total degree, that is, the degree of the single variate polynomial that you get when you substitute all variables with x. For example, the total degree of xy^2 is 3. Although such a pair (q,r) may not exist, if it does exist, it is unique given (p,a). Here is a proof:
Say p=aq+r and p=aq'+r' for some r st. deg(r)<deg(a) and assume q≠q'.
By subtracting these equations and rearranging we have a(q-q')=r'-r.
Notice that because q-q'≠0, we have deg(a)≤deg(a(q-q'))=deg(r-r').
Thus because deg(r)<deg(a), we may conclude that deg(a)≤deg(r').
Thus if there exists such an r, this r is unique.
I point this out so as to suggest that the computation I am asking for is well defined.
It seems to me that being able to do multivariate polynomial division is a natural feature
that sympy should support. If I am wrong here, please let me know why.
See here
Given a family (𝑥𝑖) of symbols, or other suitable objects, including numbers, expressions derived from them by repeated addition, subtraction and multiplication are called polynomial expressions in the generators 𝑥𝑖.
You need to specify the generators. Because given the expression y+x, the machine can NOT figure out which variable is the generator. It can be f(y) = x+y or f(x) = x+y.
You need to tell it the order of generators is [x,y].
print(sp.div(y+x, y,gens=[x,y]))
# (0, x + y)
If you set the order of generators to be [y,x].
print(sp.div(y+x, y,gens=[y,x]))
# (1, x)
Horner's rule is used to simplify the process of evaluating a polynomial at specific variable values. https://rosettacode.org/wiki/Horner%27s_rule_for_polynomial_evaluation#Standard_ML
I've easily applied the method using SML, to a one variable polynomial, represented as an int list:
fun horner coeffList x = foldr (fn (a, b) => a + b * x) (0.0) coeffList
This works fine. We can then call it using:
- val test = horner [1.0, 2.0, 3.0] 2.0;
> val test = 17.0 : real
Where [1.0, 2.0, 3.0] is the list representing the polynomial coefficients, 2.0 is the value of the variable x, and 17.0 is the result of evaluating the polynomial.
My problem is as such: We have a two variable polynomial represented by an (int list list). The nth item in a high-level list will represent all the polynomial terms containing y^n, and the mth item in a low-level list will represent all the polynomial terms containing x^m.
For example: [[2],[3,0,0,3],[1,2]] is the polynomial
( 2(x^0)(y^0) ) +
( 3(x^0)(y^1) + 0(x^1)(y^1) + 0(x^2)(y^1) + 3(x^3)(y^1) ) +
( 1(x^0)(y^2) + 2(x^1)(y^2) )
The function needs to return the value of the polynomial at the specified x and y.
I've tried various methods using the mlton compiler.
First I tried a nested foldr function:
fun evalXY (z::zs) x y =
foldr
(fn (s, li:list) =>
s + ((foldr (fn(a, b) => a + b*x) 0 li)*y)
)
0
z:zs
You can see that I'm trying to use "s" as an accumulator, like "a" was used in the single variable example. Since each element being processed by foldr needs to be "foldr'ed" itself, i call foldr again in the function describing the outer foldr. I know hat this inner foldr works fine, I proved it above. *My problem seems to be that I cant access the element of the list that the outer foldr is on to pass that list into the inner foldr. >See where I use li in the inner foldr, thats my issue. *
Then i tried applying my single variable function to map. I came across the same issue:
fun evalXY (z::zs) x y =
map
(foldr (fn(a, b) => a + b*x) 0 ???)
z:zs
*With this attempt, i know that im getting back a list of ints. I put in an int list list, in which the inner lists were processed and returned to the outer list as ints by foldr. After this i would foldr again to apply the y value to the polynomial.
The function here should look like :: fn evalXY : (int list list) * int * int) -> ... -> int list *
I am new to SML, so maybe i'm missing something fundamental here. I know this is a functional programming language, so I'm trying to accumulate values instead of altering different variables,
You're very close. Let's begin by formalizing the problem. Given coefficients C as a nested list like you indicated, you want to evaluate
Notice that you can pull out the s from the inner sum, to get
Look closely at the inner sum. This is just a polynomial on variable x with coefficients given by . In SML, we can write the inner sum in terms of your horner function as
fun sumj Ci = horner Ci x
Let's go a step further and define
In SML, this is val D = map sumj C. We can now write the original polynomial in terms of D:
It should be clear that this is just another instance of horner, since we have a polynomial with coefficients . In SML, the value of this polynomial is
horner D y
...and we're done!
Here's the final code:
fun horner2 C x y =
let
fun sumj Ci = horner Ci x
val D = map sumj C
in
horner D y
end
Isn't that nice? All we need is multiple applications of Horner's method, and map.
Your second approach seems to be on the right track. If you have already defined horner, what you need to do is to apply horner to the result of mapping horner applied to inner list x over the outer list, something like:
fun evalXY coeffLists x y = horner (map (fn coeffList => horner coeffList x) coeffLists) y
You could replace the two calls to horner by the corresponding folds, but it would be much less readable.
Note that if you reverse the order of the two parameters in horner then you can shorted evalXY:
fun horner x coeffList = foldr (fn (a, b) => a + b * x) (0.0) coeffList
fun evalXY x y coeffLists = horner y (map (horner x) coeffLists)
The point being that the way currying works, if you use this second order then horner x is already a function of coeffList so you no longer need the anonymous function fn coeffList => horner coeffList x. The moral of the story is that when defining a curried function, you should think carefully about the order of the parameters since it will make some partial applications easier to create than others.
By the way, SML is fussy. In your discussion of horner you said that you would call it like horner list 2. It would need to be horner list 2.0. Similarly, in your second attempt, using 0 rather than 0.0 is problematic.
EDIT: I am not asking how to solve an equation in terms of a given variable (as in this supposed duplicated question), but how to represent an expression in terms of an other one, as specified in the question.
I believe it is the "duplicated" question to have a misleading title.
I am very new with SymPy. I have an expression that, once expressed in terms to an other expression, should become very nice.
The problem is that I don't know how to "force" to express the original expression in terms of the other one.
This is a basic example:
import sympy as sp
sp.init_printing(use_unicode=True)
a,b,c = sp.symbols('a b c')
A = a+b+c
B = a+c
C = A.subs(a+c,B) # Expected/wanted: C = B+b
C
A.rewrite(B)
A and B could be rather complex expressions. For reference, this is my real-case scenario:
import sympy as sp
sp.init_printing(use_unicode=True)
t, w, r = sp.symbols('t w r')
S = sp.Function('S')(t)
V = (S-w*(1+r)**t)/(((1+r)**t)-1)
V
St = -(r + 1)**t*(w - S)*sp.log(r + 1)/((r + 1)**t - 1)
St
Once I write St in terms of V, I should be able to simplify to get just
St = rS(t)+rV
But I am unable to do it in SymPy.
First note that when you do something like
a,b,c = sp.symbols('a b c')
A = a+b+c
B = a+c
variables A, B are not new Sympy symbols that Sympy can understand and operate on, rather, they are aliases for the Sympy expressions a+b+c and a+c, respectively. Therefore, A.subs(a+c,B) is essentially the same as A.subs(a+c,a+c), which is, of course, meaningless. You get the idea of why A.rewrite(B) is also of no use.
I do not think that calls like expr.subs({complicated_mutlivariable_formula: new_variable}) work in Sympy. One way to do what you want is to first solve the equation complicated_mutlivariable_formula = new_variable with respect to one of the "old" variables, and, assuming a unique solution exist, use subs() to substitute this variable.
Applying this approach for the second example:
# sympy Symbol A will be used to represent expression V
A = sp.symbols('A')
# Solve the equation V==A with respect to w, which has a unique solution as a function of A
w_A = sp.solve(sp.Eq(V,A), w)[0]
# Now substitute w
St.subs({w:w_A}).simplify()
I am trying to write a function using a list comprehension to calculate the maximum value of a function:
f(x)=x^3-x^2+3x+2 on the interval [4,12].
To define the function:
mymax(f, a, b, precision)
where precision is the precision in the value of x where the maximum occurs.
How can this be done?
assuming a, b are the ends of your interval and precision is the increment, I think this is what you are looking for:
import numpy as np
def f(x):
return x**3-x**2+3*x+2
def mymax(f, a, b, p):
max_x=float('-inf')
for x in np.arange(a,b,p):
max_x=max(max_x,f(x))
return x
OR, a in a nice one-liner:
def mymax(f, a, b, p):
return max(y for y in [f(x) for x in np.arange (a,b,p)])
I'm trying to subtract two functions(both with type real) in moscow ml. It then says "Overloaded - cannot be applied to arguments of type real -> real. So how should I write the function?
fun CircleArea x = x*x*Math.pi
fun SquareArea x:real = 4*x*x
fun Area x = SquareArea - CircleArea
You probably don't actually want to subtract one function from another, but the return values of those functions once they are applied. You could achieve this in the following way:
fun Area x = (SquareArea x) - (CircleArea x)
The parentheses are not mandatory, since function application (i.e. the space between SquareArea and x) binds tighter than any binary operator, including -.
You should consider using the following naming convention in ML: Regular functions have a lowercase starting symbol, while value constructors for algebraic types have uppercase starting symbols. For example:
fun area x = squareArea x - circleArea x
But:
datatype shape = Square of int * int
| Circle of int
Subtraction of functions like we have in mathematics isn't provided as a built-in operator. You can, however, define your own.
Mathematically speaking, we define
(f - g)(x) = f(x) - g(x)
We can replicate this definition in SML as follows:
infix 5 --
fun f -- g = fn x => f x - g x
What this does is produce an operator, --, such that f -- g produces the function corresponding to fn x => f x - g x, i.e. the function that given an x calculates f x - g x.
Note, due to the type-ambiguity in the - operator, it'll default to let you subtract 'a -> int functions. In your case you'll want to subtract 'a -> real functions, so you'll need a slight modification:
infix 5 --
fun f -- g = fn x => f x - g x : real
If you use this ---operator, you will be able to define your Area function like so:
val area = squareArea -- circleArea;
(I took the liberty of making the first letter of function names lowercase, to match the SML naming conventions.)