I'm trying to make some program which involves typing formulas in input by a user.
My code for now looks like so:
import numpy as np
n = int(input('Dim = '))
g = np.zeros((n, n))
for a in range(0, n):
print('Define the metric. \n g_', a, a,'=')
metric_component = 'lambda x, y: ' + str(input())
g[a, a] = eval(metric_component)
print(g)
I tried to search for answers but those i found didn't work. eval() function gives me error there: float() argument must be a string or a number, not 'function': sympify() gives basically the same "can't convert expression to float"
Also i want to work on those constants not their numeric values, so i'm interesting to keep them through all program and have the final output expressed by them. Is it even possible?
input() will return a string
>>> type(input()) # I type 1
1
<class 'str'>
So if you are expecting numeric input from the user and it can be non-integer, then just wrap the input with float.
import numpy as np
n = int(input('Dim = '))
g = np.zeros((n, n))
for a in range(0, n):
print('Define the metric. \n g_', a, a,'=')
g[a, a] = float(input())
print(g)
It's hard to tell what you want to be able to interpret from the user. If the user is going to give some expression of x and y and you are going to replace both those values with a you would either have to build a lambda that could be evaluated or do a substitution into a sympified expression:
>>> eval('(lambda x,y:'+'x + 2*y'+')(%s,%s)'%(a,a))
3*a
>>> sympify('x+2*y').subs(dict(x=a,y=a))
3*a
If you want the user to input expressions and then do something to them later, SymPy is ideally suited for this. Here, the user is prompted to fill items in a list and then those items are differentiated wrt x. It's just a toy example:
>>> from sympy import S # shortcut for sympify
>>> from sympy.abc import x
>>> [S(input('?')) for i in range(2)]
?R**2
?R**2*sin(x)**2
[R**2, R**2*sin(x)**2]
>>> [i.diff(x) for i in _]
[0, 2*R**2*sin(x)*cos(x)]
Related
I have this code:
from sympy import *
x = Symbol('x')
f = exp(x)+exp(x-0.1)+exp(-x-1) #Random Function
d = diff(f,x) #Differentiate f w.r.t x
a = d.subs({x:2}) #Put x=2
print(a)
The output is:
-exp(-3) + 1.90483741803596*exp(2)
But here, I don't want exp() to appear as a symbol. Rather, I want the numerical value of it.
Expected Output:
14.025163472842058
How do I replace the exp() symbol to fetch the numerical value?
Here is the Documentation for it: Documentation
But essentially a is an expression-object, in order to evaluate it you have to call something like evalf on it. Since you already did the substitution step you just need to call a.evalf() to get a number.
There are also other methods but those might need other dependencies.
For Example:
from sympy import *
x = Symbol('x')
f = exp(x)+exp(x-0.1)+exp(-x-1) #Random Function
d = diff(f,x) #Differentiate f w.r.t x
a = d.subs({x:2}) #Put x=2
print(a.evalf()) # prints: 14.0251634728421
I was working on a program that takes an input, and solves it. I used Sympy. I assumed because this works:
from sympy import symbols, Eq, solve
x, y = symbols("x y")
eq1 = Eq(5 + x)
eq2 = Eq(5 + y)
sol = solve((eq1, eq2),(x, y))
print(sol)
Gives the result:
{x: -5, y: -5}
This should work too, because I'm splitting it, formatting the code correctly, and it has the inputs of "a" and "z":
from sympy import symbols, Eq, solve
Input = input("Please give the two variables the names 'a' and 'z': ").replace("x", "*").replace("^", "**").upper().split(" = ")
a, z = symbols("a z")
othersol = solve((Input[0], Input[1]),(a, z))
print(othersol)
Though, when given the input:
5 + a = 5 + z
It gives the result:
[]
I want to know why it is not solving, why it doesn't work, and how I can make a program that takes an input and solves the equation given. If I need to, I will even switch my Python Library. If not, can you give the code that takes an input, and solves that equation?
Can anybody do that?
Thanks.
You see what is wrong in here when you compare what you are giving as first parameter to your solve function.
In your working code you do like this:
eq1 = Eq(5 + x)
eq2 = Eq(5 + y)
sol = solve((eq1, eq2),(x, y))
First parameter is two Eq objects.
Let's see what is going on in your non-working code.
>>> Input = input("Please give the two variables the names 'a' and 'z': ").replace("x", "*").replace("^", "**").upper().split(" = ")
Please give the two variables the names 'a' and 'z': a+1 = zx3
>>> Input
['A+1', 'Z*3']
>>> type(Input[0])
<class 'str'>
>>> solve((Input[0], Input[1]),(a, z))
[]
There first parameter is tuple of two strings.
So you'd need to parse your Input-strings to Eq objects. Then you'd have working code. It may be challenging task though if you want to allow your user enter freetext input. Input in polish notation or some other more strcutured way would be much easier to parse.
--- EDIT ----
With exec it could be something like this. I Added a function to secure input a bit. This will fail if there is unknown characters in input.
from sympy import symbols, Eq, solve
A, Z = symbols("A Z")
def secure_input(inputstring):
known_symbols = {" ","A","Z","+","*","**","-"}
if not all([x in known_symbols or x.isdigit() for x in inputstring]):
raise Exception("Illegal strings in input %s"%inputstring)
return inputstring
Input = input("Please give the two variables the names 'a' and 'z': ").replace("x", "*").replace("^", "**").upper().split(" = ")
i1 = secure_input(Input[0])
i2 = secure_input(Input[1])
exec("eq1 = Eq(%s)" % i1)
exec("eq2 = Eq(%s)" % i2)
solve((eq1,eq2),(A, Z))
Also, you used lower-case variable names but you said upper() for your input string. I changed that as well, now the code should work.
from sympy import symbols, Eq, solve
A, Z = symbols("A Z")
def secure_input(inputstring):
known_symbols = {" ","A","Z","+","*","**","-"}
if not all([x in known_symbols or x.isdigit() for x in inputstring]):
raise Exception("Illegal strings in input %s"%inputstring)
return inputstring
Input = input("Please give the two variables the names 'a' and 'z': ").replace("x", "*").replace("^", "**").upper().split(" = ")
i1 = secure_input(Input[0])
i2 = secure_input(Input[1])
exec("eq1 = Eq(%s)" % i1)
exec("eq2 = Eq(%s)" % i2)
A = solve((eq1,eq2),A)
Z = solve((eq1,eq2),Z)
print(str(A).replace("{","").replace("}", ""))
print(str(Z).replace("{","").replace("}", ""))
Im trying to build a constrained optimization calculator in python using the sympy module. The idea is that a user can enter two functions, "f" and "g", which then are put together to form the equation "L".
I want SymPy to give me the partial derivatives of x, y and lambda in "L", however my code does not seem to be working. When trying to get their partial derivatives i get the following results:
0
0
-x - 4*y + 500
I used x+100*y-y**2 as function 1 and x+4*y-500 and function 2.
Heres the code so far:
import sympy as sp
from sympy.parsing import sympy_parser
x, y = sp.symbols("x y", real=True)
lam = sp.symbols('lambda', real=True)
insert = input("Insert function 1:") #function 1
f = sympy_parser.parse_expr(insert) #transforming the function into a sympy expression
print(f)
insert2 = input("Insert function 2:") #function2
g = sympy_parser.parse_expr(insert2) #transforming function 2
L = f - lam*g #getting the equation "L"
xx = sp.diff(L, x) #partial derivative L'x
yy = sp.diff(L, y) #partial derivative L'y
ll = sp.diff(L, lam) #partial derivative L'lam
print(xx)
print(yy)
print(ll)
I have tried both the "parse_expr" and "simpify" commands to transform the functions input by the user from string to sympy expressions. I might be missing something else.
Your local x and y are real but those that the parser returns are vanilla, they have not assumptions. Since symbols match by name and assumptions, your input functions don't have (the same) x and y:
>>> f.has(x)
False
So either don't make your local symbols real
>>> var('x')
x
>>> f = sympy_parser.parse_expr(insert)
>>> f.has(x)
True
Or pass your local symbols to the parser so it can use them to build your functions:
>>> f = sympy_parser.parse_expr(insert, dict(x=x,y=y))
>>> f.has(x)
True
And once you are using the same symbols, the rest of your issues should move to a new level :-)
I was wondering if it is somehow possible to set the domain of a math. function. For example, when I define the following expression
>>> import sympy as syp
>>> x = syp.Symbol('x')
>>> miles_to_km = x * 1.609344
>>> miles_to_km.evalf()
1.609344*x
Is it possible to limit the domain so that x is in the range [0, inf)? So the goal is that I could then use the sympy.plot function that produces a graph that starts at 0 and only includes positive x-values in contrast to
If we check the manual by doing:
help(syp.plot)
You will get:
...
expr : Expression representing the function of single variable
range: (x, 0, 5), A 3-tuple denoting the range of the free variable.
...
So, you can:
>>> import sympy as syp
>>> x = syp.Symbol('x')
>>> miles_to_km = x * 1.609344
>>> syp.plot(miles_to_km, (x,0,10))
which will give you the following output:
I'm currently doing a maths course where my aim is to understand the concepts and process rather than crunch through problem sets as fast as possible. When solving equations, I'd like to be able to poke at them myself rather than have them solved for me.
Let's say we have the very simple equation z + 1 = 4- if I were to solve this myself, I would obviously subtract 1 from both sides, but I can't figure out if sympy provides a simple way to do this. At the moment the best solution I can come up with is:
from sympy import *
z = symbols('z')
eq1 = Eq(z + 1, 4)
Eq(eq1.lhs - 1, eq1.rhs - 1)
# Output:
# z == 3
Where the more obvious expression eq1 - 1 only subtracts from the left-hand side. How can I use sympy to work through equalities step-by-step like this (i.e. without getting the solve() method to just given me the answer)? Any pointers to the manipulations that are actually possible with sympy equalities would be appreciated.
There is a "do" method and discussion at https://github.com/sympy/sympy/issues/5031#issuecomment-36996878 that would allow you to "do" operations to both sides of an Equality. It's not been accepted as an addition to SymPy but it is a simple add-on that you can use. It is pasted here for convenience:
def do(self, e, i=None, doit=False):
"""Return a new Eq using function given or a model
model expression in which a variable represents each
side of the expression.
Examples
========
>>> from sympy import Eq
>>> from sympy.abc import i, x, y, z
>>> eq = Eq(x, y)
When the argument passed is an expression with one
free symbol that symbol is used to indicate a "side"
in the Eq and an Eq will be returned with the sides
from self replaced in that expression. For example, to
add 2 to both sides:
>>> eq.do(i + 2)
Eq(x + 2, y + 2)
To add x to both sides:
>>> eq.do(i + x)
Eq(2*x, x + y)
In the preceding it was actually ambiguous whether x or i
was to be added but the rule is that any symbol that are
already in the expression are not to be interpreted as the
dummy variable. If we try to add z to each side, however, an
error is raised because now it is unclear whether i or z is being
added:
>>> eq.do(i + z)
Traceback (most recent call last):
...
ValueError: not sure what symbol is being used to represent a side
The ambiguity must be resolved by indicating with another parameter
which is the dummy variable representing a side:
>>> eq.do(i + z, i)
Eq(x + z, y + z)
Alternatively, if only one Dummy symbol appears in the expression then
it will be automatically used to represent a side of the Eq.
>>> eq.do(2*Dummy() + z)
Eq(2*x + z, 2*y + z)
Operations like differentiation must be passed as a
lambda:
>>> Eq(x, y).do(lambda i: i.diff(x))
Eq(1, 0)
Because doit=False by default, the result is not evaluated. to
evaluate it, either use the doit method or pass doit=True.
>>> _.doit == Eq(x, y).do(lambda i: i.diff(x), doit=True)
True
"""
if not isinstance(e, (FunctionClass, Lambda, type(lambda:1))):
e = S(e)
imaybe = e.free_symbols - self.free_symbols
if not imaybe:
raise ValueError('expecting a symbol')
if imaybe and i and i not in imaybe:
raise ValueError('indicated i not in given expression')
if len(imaybe) != 1 and not i:
d = [i for i in imaybe if isinstance(i, Dummy)]
if len(d) != 1:
raise ValueError(
'not sure what symbol is being used to represent a side')
i = set(d)
else:
i = imaybe
i = i.pop()
f = lambda side: e.subs(i, side)
else:
f = e
return self.func(*[f(side) for side in self.args], evaluate=doit)
from sympy.core.relational import Equality
Equality.do = do