How to solve an equation in Python 3 with Sympy? - python-3.x

I new with Python and much more with Sympy, I'm trying to solve an equation; the user introduces the equation and the value of 'x'. Example: eq: x**2+x*3+1, x = 4, so the 4 should be replaced on the 'x' of the equation and calculate the result.
This is what I have been trying:
import sympy
from sympy.solvers import solve
from sympy.core.function import Derivative
from sympy.core.relational import Eq
from sympy.core.symbol import Symbol
x = Symbol('x')
info = input("Introduce the equation and the value of /'x' \nEg: x**3+x**2+1 9\n")
infoList = info.split()
equation = infoList[0]
x_value = infoList[1]
expr = equation
eqResult = expr.subs(x, x_value)
print(eqResult)
The error is that the expr, which is an str object, has no attribute subs.
Any help is appreciated.
UPDATE
The function eval() works fine, but is there a solution less risky?
I have been doing other stuff and tried to calculate the Derivative of the function:
x = Symbol('x')
info = input("Introduce the equation and the value of /'x' \nEg: x**3+x**2+1 9\n")
infoList = info.split()
equation = infoList[0]
x_value = infoList[1]
exprDerivada = Derivative(equation, x)
resultDerivate = exprDerivada.doit().subs({x:x_value})
The code above gives the result of the first derivate of a function, but the equation is accepted as it comes without the function: eval()
Again, any help is appreciated.

You are sending a string object that indeed doesn't have a subs property
Use eval(expr).subs(.....) to convert the string to the math expression.
However eval() is a risky stuff to use as it will execute pretty much anything. So be sure to properly secure the user input or you could get you system destroyed by malicious user input. See this answer for a detailed explanation.

Related

Passing Numbers to a Sympy function in Python

I am practicing Python from Codewars. One of the questions was to take a function as an input given in string from, differentiate it and use the other input given as an integer and return the result. For example lets say the inputs are
stringf=x**2+2x
inputint=3
def differentiate(stringf,inputint) should return 8. I managed to do this by using Sympy and eval. However when I take the derivate of the function with sympy.diff it converts a regular lambda function to something else which you cannot pass arguments. For example you can do f(1) in below code but you cannot do deffunc(1) it throws the error "TypeError: 'Add' object is not callable" because the type of deffunc becomes "<class 'sympy.core.add.Add'>" after sympy.diff.
def differentiate(equation, point):
import sympy as sym
f=lambda x:equation #turn the string into a formula with x
x= sym.symbols('x')
deffunc=sym.diff(f(x),x) #differentiate with respect to x
strfunc=str(deffunc) #convert the function to a string to be used in eval
x=point
f=eval(strfunc)
return f
I found a workaround by simply converting it to string then using eval but I was wondering is there a better way to pass the 'point' into the 'deffunc'?

Can I use where in Haskell to find function parameter given the function output?

This is my program:
modify :: Integer -> Integer
modify a = a + 100
x = x where modify(x) = 101
In ghci, this compiles successfully but when I try to print x the terminal gets stuck. Is it not possible to find input from function output in Haskell?
x = x where modify(x) = 101
is valid syntax but is equivalent to
x = x where f y = 101
where x = x is a recursive definition, which will get stuck in an infinite loop (or generate a <<loop>> exception), and f y = 101 is a definition of a local function, completely unrelated to the modify function defined elsewhere.
If you turn on warnings you should get a message saying "warning: the local definition of modify shadows the outer binding", pointing at the issue.
Further, there is no way to invert a function like you'd like to do. First, the function might not be injective. Second, even if it were such, there is no easy way to invert an arbitrary function. We could try all the possible inputs but that would be extremely inefficient.

How can i subs or replace a sympy function to a sympy symbol

Im trying to replace the sympy function x(t) to the sympy symbol x.
It should be like something like this:
Before the replace:
funcion0=t**2*sp.cos((x(t)/2))
After the replace:
funcion1=t**2*sp.cos((x/2))
import sympy as sp
t = sp.Symbol('t')
x = sp.Function('x')
funcion=t**2*sp.cos((x(t)/2))
def replace(funcion):
funcion1=funcion.subs(x(t), x)
return funcion1
I know that doesnt work, but maybe it helps to understand what im saying hahaha.
Thanks!!!!
When working with SymPy, it's best to keep in mind the differences between functions, symbols and physical numbers like floats or ints. Here, you want the function x (evaluated at t) to be substituted with the symbol x. If you are uncertain at any point, it is best to add what the type of the variable to its name as I have done below:
import sympy as sp
t, x_sym = sp.symbols('t x')
x_func = sp.Function('x')
function = t**2*sp.cos((x_func(t)/2))
def replace(funcion):
function1 = funcion.subs(x_func(t), x_sym)
return function1
print(replace(function))
It should give you the desired result.

Using `functools.partial` and `map` with built-in `getattr`?

I apologize if am completely missing something obvious or if I have not dug into the documentation hard enough, but after 30 mins or so I found a work around (without having understood the error I was getting) and ... hence the question here. Suppose I have a class:
class RGB(object):
def __init__(self, r, g, b):
super(RGB, self).__init__()
self.red = r
self.blue = b
self.green = g
and I define a list of RGB instances as follows:
from random import random
rr, gg, bb = [[random() for _ in range(20)] for _ in range(3)]
list_of_rgbs = [RGB(*item) for item in zip(rr, gg, bb)]
why can't I extract a list of red values by doing:
from functools import partial
*reds, = map(partial(getattr, name="red"), list_of_rgbs)
or
*reds, = map(partial(getattr, "red"), list_of_rgbs)
I know I can make it do what I want by saying reds = [x.red for x in list_of_rbgs] but that would be difficult if the list of attributes to extract comes from elsewhere like: attribs_to_get = ['red', 'blue']. In this particular case I can still do what I want by:
reds, blues = [[getattr(x, attrib) for x in list_of_rgbs] for attrib in attribs_to_get]
but my question is about what causes the error. Can someone explain why, or how to make it work using partial and map? I have a hunch it has something to do with this behavior (and so maybe the partial function needs a reference to self?) but I can't quite tease it out.
For reference I was on Python 3.7.
Partial can only set positional arguments starting at the first argument. You can't set the second argument as positional, but only as a keyword argument. As the first one for getattr is the object, it won't work well together with map and partial.
What you can use however is operator.attrgetter():
from operator import attrgetter
*reds, _ = map(attrgetter("red"), list_of_rgbs)

Passing Variables in Function and compare each?

I'm trying to practice Haskell returns and datatypes. I'm trying to pass the following information into the program:
worm = 1:2:3:worm
eel = [1,2,3,1,2,3,1,2,3]
snake = 3:2:1:snake
whale = [1..100]
And i want to create a function that has a switch function to get the data and match it to its definition. For example, in Python:
def compare(str): #for one case and using string to clarify
if str == "1:2:3:worm":
return "worm"
I know the datatypes are lists but causes a lot of confusion. My code is giving me an error of Could not deduce (Num Char) Arising from use of worm
My code:
which :: [a] -> String
which x | x == [1,2,3,1,2,3,1,2,3] = "worm" | x == 3:2:1:snake = "snake" | otherwise = "F"
Is there another approach i'm missing? and why is my function giving me that error?
Two problems:
You can't have a function that returns a list of numbers sometimes and a string other times. That's literally the entire point of a strongly typed language. If you want something like that, you need to use a sum type.
You can't compare infinite lists. You can try, but your program will never finish.

Resources