How do I create Symbols in SymPy based on user input? - python

I am trying to create a python programme that takes a function from the user (in terms of x) and returns its derivative using SymPy. However, when I enter letters other than x, SymPy throws an error of undefined symbols. I want it to treat letters apart from x as constant.
For example, if a user enters a*x**2 + bx, they should get 2*a*x + b, and if they enter z*x**2 + px, they should get 2*z*x + p. How can I treat letters apart from 'x' as constants without having to hard-code every letter as a symbol?
I hope my question is clear. Feel free to ask for any clarifications if required.

You should first parse the user input and collect all symbols. To parse string to sympy expression use sympy.sympify. I assume you want to get derivative only W.R.T x. The full code will be:
import sympy as sp
expr = sp.sympify(input('enter expression: '))
print('Derivative w.r.t x: ', sp.diff(expr, 'x'))

Related

I am writing a program that accepts user input in order to differentiate a function

In order to find the maximums and minimums of a function, I am writing a program that accepts a polynomial imputed from the user and finds where the derivative = 0.
from sympy import Symbol, Derivative
from sympy import symbols, Eq, solve
import sympy as sy
import numpy as np
import math
x= Symbol('x', real = True)
function= x**4 +7*x**2 +8
deriv= Derivative(function, x)
yprime = deriv.doit()
y = symbols('x')
eq1 = Eq(yprime,0)
sol = solve(eq1, )
The only reason that the code above is able to take the derivative and find solutions is because the coefficients and exponents are integers. If I ask for user input {e.g., function = input("What is your function: ")}, then the whole thing will become a string and SymPy can not take the derivative.
Is it possible to turn the coefficients and exponents into integers and leave the rest of the function as a string so that I can take the derivative?
If your equation can be arbitrarily complicated, you might want to use eval to parse it from Python syntax. Now, eval is generally unsafe to use on untrusted user input, but a user replying to an input() prompt is probably trusted (since they're usually sitting at the computer running the code).
So one option is:
function = eval(input("What is your function: "))
If placed just below the definition of x, it will allow that variable to be used in the equation. You could also provide a namespace for eval to use, rather than letting it use your function's local namespace (e.g. function = eval(input(...), {'x': Symbol('x', real=True)})).
If your problem space is more limited, and you only need to handle equations that are polynomials with integer coefficients, then you could write your own logic to input the equation in a much more simplified form. For instance, you could loop, asking for the coefficients in order (probably from the lowest exponent to the highest). Try something like this:
import itertools
from sympy import Symbol
x = Symbol('x', real = True)
function = 0
for exponent in itertools.count():
coef = input(f"Enter coefficient for x**{exponent} (or give an empty value to be done): ")
if not coef:
break
function += int(coef) * x**exponent
print("Polynomial so far:", function)
For the example equation in your question, you'd enter 8, 0, 7, 0, 1 and finally an empty input.
The better thing to do is to turn your string into a SymPy expression. As long as the user uses SymPy/python syntax, sympyify will convert it for you:
>>> from sympy import sympify, solve
>>> user='3*x**2-1'
>>> eq = sympify(user)
>>> x = eq.free_symbols.pop() # assuming there is 1 symbol
>>> solve(eq.diff(x))
[0]

Number eval issue python

I want to evaluate the following differential using the values in list y however I cant figure out what I am doing wrong. I am supposed to get 1.9256 for y=5, 1.9956 for y=10 and 2.1356 for y=20. What I'm trying to do is ask the user to input an equation with x as its variable, derive this equation with respect to x, ask the user to input as many values as he wants and evaluate the expression using these inputted values. Thanks for your help.
import sympy as sym
print('Sensitivity: ')
#exp = input('Enter the expression to find the sensitivity: ')
exp='(0.007*(x**2))+(1.8556*x)-1.8307'
#values=list(map(float,input('Enter the values at which you want to compute the sensitivity seperated by spaces: ').split()))
values=[5,10,20]
x=sym.Symbol('x')
differential=str(sym.diff(exp,x))
print(differential)
for i in y:
expression=differential.replace(str(x),str(values))
value=eval(expression)
print('The sensitivity at',i,'is: ',value)
What I believe you intended to write is:
import sympy as sym
exp='(0.007*(x**2))+(1.8556*x)-1.8307'
values=[5,10,20]
x=sym.Symbol('x')
differential=str(sym.diff(exp,x))
print(differential)
for value in values:
expression=differential.replace(str(x),str(value))
result=eval(expression)
print('The sensitivity at',value,'is: ',result)
...which emits as output:
The sensitivity at 5 is: 1.9256
The sensitivity at 10 is: 1.9956
The sensitivity at 20 is: 2.1356
Note the changes:
We're iterating for value in values -- values exists, y does not.
We're assigning the eval result to a separate variable (in this case, result)
This still is not by any means good code. Good code would not do string substitution to substitute values into code. Substituting repr(value) instead of str(value) would be at least somewhat less broken.

Python Sympy solve returns list vs. dictionary

I am using sympy and its solve function, but I noticed that it sometimes returns a dictionary in a list but in other cases just a dictionary, without a list.
from sympy import *
x, y = symbols('x y')
q = 16*x**0.5*y**0.5
solve((diff(q, x)/5 - diff(q, y)/20, 3200 - q))
This returns a list: [{x: 400.000000000000, y: 100.000000000000}]
x, y = symbols('x y')
q = 8*x**.5*y**0.5
solve((diff(q, x)/10 - diff(q, y)/8, 400-10*x-8*y))
This returns a dictionary, without a list: {x: 20.0000000000000, y: 25.0000000000000}
Why does this happen? Thank you for your help.
And explanation of output types has been added to the documentation. The gist is given in that exaplanation's opening paragraph:
The reasons for this are historical and are biased toward human
interaction rather than programmatic use. The type of output will
depend on the type of equation(s) (and how they are entered) and the
number of symbols that are provided (and how they are provided).
solve has two main pathways: single equations vs multiple equations. For each of those the user may accept any solution (by not providing symbols) or give the symbols of interest. The treatment of the equation(s) can also depend on whether the system is linear or not.

Solve Equation (String) with Python to every Symbol

I have to solve a equation in python, which i get as a string input. I don't know how many symbols are in the equation or what their signature is. A typical Symbol could be "mm", "cm", "x" or something like this. The function should return some kind of array/json with the solved equation.
Little Example how it should look like:
solve("x/2=4")
>> ["x=8"]
>>
solve("x + 2 = y - 1")
>> ["x=y-3", "y=x+3"]
I tried to use SymPy-Module for this, but I didn't find a way to enter a dynamic string like above. SymPy seems to only accept "hardcoded" Symbols.
Note: String comes from a "sys.argv"-Parameter.
SymPy can parse strings with sympify, but its format for equations is Eq(x/2, 4) instead of x/2 = 4. So a little preprocessing is necessary: surround the string with Eq( ) and replace "=" by a comma.
eq = "x/2=4"
sympy_eq = sympify("Eq(" + eq.replace("=", ",") + ")")
solve(sympy_eq) # [8]
and
eq = "x + 2 = y - 1"
sympy_eq = sympify("Eq(" + eq.replace("=", ",") + ")")
solve(sympy_eq) # [{x: y - 3}]
In the latter case, SymPy picked one of the variables to solve for. To choose which one it should be, you can provide a Symbol:
solve(sympy_eq, Symbol('y')) # [x + 3]
Or, to solve for every symbol:
[solve(sympy_eq, sym, dict=True) for sym in sympy_eq.free_symbols]
returns [[{y: x + 3}], [{x: y - 3}]]. The list is nested because multiple solutions could appear for each symbol. Flatten the nested list if necessary.
The options list=True and dict=True of solve are convenient for enforcing particular forms of output.
The answer is most probably two different parts.
Parsing:
Parsing means turning some input into a usable output, where in your case the input is some string and the output is something, sympy can work with. A simple parsing step for example is turning strings into integers by doing int(your_string). In your case, you should iterate through your string and find variables, units etc. for example by comparing with a dictionary or a list of strings. Parsing arbitrary input is quite hard, so the best idea is starting with a small set of options, e.g. search the string for occurences of typical variable names like x, y and z by comparing with a list variables=['x','y','z'].
Computing
Once the parsing is clean, simply plug everything into your number crunching / solvers used by sympy.
To see how such a system can work if done correctly, you can have a look at wolfram alpha. They do a quite good parsing / natural language processing and try to guess what to do from there.

Integration in python containing some parameter

I want to perform integration of an equation with one variable and few constants in the form of symblos namely, A,k,p whose values I have planned to enter after integration. Integrating equation with only one variable but with no other symbol(containing some constant value) is simple and direct, but for the case in which symbols are present, integration using quad from scipy.integrate gives an error. Actually quad() requires the values of all symbols to be pre-defined. I want a solution where I don't have to enter the values for symbols beforehand but take an input and substitue them afterwards.
To make the problem even more clear,
I want to integrate a wave equation
A * sin(kx + wt) , where A is amplitude, w is angular velocity, t is time and x is position (x is only variable )
quad() requires to define the values for A, k and p before integrating but what I want to do is first integrate A * sin(kx + wt) and then substitue the values for A, k and p in the result by taking user input
.
Please suggest a method to do so :)
We can use sympy library for integrating a function without assigning values for its symbols(having some constant real number as its value) (A,k,p and s).
Example code from one of my projects:
from sympy import *
A = symbol('A')
k = symbol('k')
p = symbol('p')
x = symbol('x')
s = symbol('s')
f = integrate(exp(-1*s*x)*A*sin(k*x+p),(x,0,oo))
f = f.subs(A,50)
print str(f)
(x,0,oo) means integrate wrt x from zero (0) to infinty(oo)
What the code requires to be done is, first define constants A, k, p and s as well as the variable x as symbols and then use integrate() to integrate the expression.
integrate() returns the integrated expression and now, f.subs(symbol,value) is used to substitue the values of symbols.
in f.subs(symbol,value) , f is the variable containing the integrated expression, symbol is the symbol defined earlier(like A,k,p) and value is the constant value for that symbol.
This method also helps to get definite integration(from x=a to x=b) of equations. What one has to do is substitute the value of x with b and store it in some variable m using m = f.subs(x,b) and then use n = f.subs(x,a) to substitute the value of x with a and store it in some variable n. Now, substract m and n using m - n to get the definite integral of the expression
There is one more possibe solution to the question.
What can be done is define a function which takes user inputs for A, k and p and then use quad() to integrate the expression, this will wipe out the need to first integrate the expression and then take user input to substitue the values of symbolic constants
It appears you are not defining the variable "A", try doing
A=15
Or anything like that, just make sure you define A before calling it.

Categories