I have a very complicated function of two variables, let's call them x and y. I want to create a Python program where the user can input two values, a and b, where a is the value of that complicated function of x and y, and b = math.atan(y/x). This program should then output the values of x and y.
I am clueless as to where to start. I have tried to make the function into that of just one variable, then generate many random values for x and pick the closest one, but I have learnt that this is horribly inefficient and produces a result which is only accurate to about 2 significant figures, which is pretty horrible. Is there a better way to do this? Many thanks!
(P.S. I did not reveal the function here due to copyright issues. For the sake of example, you can consider the function
a = 4*math.atan(math.sqrt(math.tan(x)*math.tan(y)/math.tan(x+y)))
where y = x * math.tan(b).)
Edit: After using the approach of the sympy library, it appears as though the program ignores my second equation (the complicated one). I suspect it is too complicated for sympy to handle. Thus, I am asking for another approach which does not utilise sympy.
You could use sympy and import the trigonometric functions from sympy.
from sympy.core.symbol import symbols
from sympy.solvers.solveset import nonlinsolve
from sympy import sqrt, tan, atan
y = symbols('y', real=True)
a,b = 4,5 # user-given values
eq2 = a - 4*atan(sqrt(tan(y/tan(b))*tan(y)/tan((y/tan(b))+y)))
S = nonlinsolve( [eq2], [y] )
print(S)
It'll return you a series of conditions ( ConditionSet object ) for possible adequate results.
If that wasn't clear enough, you can read the docs for nonlinsolve.
Related
I have a function of two variables, R(t,r), that has been constructed using a list of values for R, t, and r. This function cannot be written down, the values are found from solving a differential equation (d R(t,r)/dt). I require to take the derivatives of the function, in particular, I need
dR(t,r)/dr, d^2R(t,r)/drdt. I have tried using this answer to do this, but I cannot seem to get an answer that makes sense. (note that all derivatives should be partials). Any help would be appreciated.
Edit:
my current code. I understand getting anything to work without the `Rdata' file is impossible but the file itself is 160x1001. Really, any data could be made up to get the rest to work. Z_t does not return answers that seem like the derivative of my original function based on what I know, therefore, I know it is not differentiating my function as I'd expect.
If there are numerical routines for using the array of data I do not mind, I simply need some way of figuring out the derivatives.
import numpy as np
from scipy import interpolate
data = np.loadtxt('Rdata.txt')
rvals = np.linspace(1,160,160)
tvals = np.linspace(0,1000,1001)
f = interpolate.interp2d(tvals, rvals, data)
Z_t = interpolate.bisplev(tvals, rvals, f.tck, dx=0.8, dy=0)
Consider the following sympy code:
from sympy import Add
from sympy.abc import x
t1 = 2+2*x
t2 = x
myeq = sp.UnevaluatedExpr(Add(sp.UnevaluatedExpr(t1), sp.UnevaluatedExpr(t2), evaluate=False))
# BUG! Will print: x + 2*x + 2
# Yet it should print: 2+2*x+x
print(myeq)
This code snippet was adapted from this answer. There the terms are simpler, so Add preserved the order. But how can I make Add preserve the order in this case as well?
(Remark: If we change the terms to t1=x and t2=x**2 my approach with using the sp.UnevaluatedExpr works, but the original answer that did not have those terms does not. Alas, for my specific case, not even using sp.UnevaluatedExpr works.)
This is not a bug...
... but more a missing feature. All of it being documented.
Here is what SymPy means by unevaluated.
By unevaluated it is meant that the value inside of it will not
interact with the expressions outside of it to give simplified
outputs.
In your example, the terms 2*x and x were not simplified, as is expected.
Order of input
What you are seeing is SymPy not preserving the order in which you input your terms. This is documented under the expression tree section.
The arguments of the commutative operations Add and Mul are stored in
an arbitrary (but consistent!) order, which is independent of the
order inputted.
This should not be a problem since Add and Mul are commutative.
Although, if for some reason you want to preserve the order of input due to non-commutativity of multiplication, you can do so.
In SymPy, you can create noncommutative Symbols using Symbol('A',
commutative=False), and the order of multiplication for
noncommutative Symbols is kept the same as the input)
As for now, there does not seem to be non-commutative addition.
I'm using sympy v1.0 in a Jupyter Notebook. I'm having trouble getting expression to simplify how I'd like. Here's a toy example; it does the same thing my more complicated expressions do...
import sympy
sympy.init_printing(use_latex='mathjax')
x, y = sympy.symbols("x, y", real=True, positive=True)
sympy.simplify(sqrt(2*x/y))
gives me...
But I would prefer...
How can I get sympy to group things in this way? Ive tried some of the other simplify functions, but they all give me the same result. Or am I missing something else?
Use "symbol trickery" for numbers that you want to behave like symbols and "vanilla symbols" when you don't want simplifications (as #asmeurer pointed out):
>>> _2,x,y = list(map(Symbol,'2xy'))
>>> sqrt(_2*x/y)
sqrt(2*x/y)
sympy really wants to simplify by pulling terms out of sqrt, which makes sense. I think you have to do what you want manually, i.e., get the simplification you want without the sqrt call, and then fudge it using Symbol with a LaTex \sqrt wrap. For example:
from sympy import *
init_printing(use_latex='mathjax')
# Wanted to show this will work for slightly more complex expressions,
# but at the end it should still simplify to 2x/y
x, y = symbols("x, y", real=True, positive=True)
z = simplify((2*2*3*x)/(1*2*3*y))
Symbol("\sqrt{" + latex(z) + "}", real=True, positive=True) # Wrap the simplified fraction in \sqrt{}
This really isn't ideal, but I looked through the docs for about an hour, and just couldn't find support for what you want directly. The sympy library is more about actual symbolic manipulation, less about printing, so I can hardly blame them.
What I want is a program that can determine the value of x from an equation when x is not yet defined i.e. not a python variable.
Just an example below, not the real thing.
sol = eval("input please type the equation: ")
#i.e sol = 32x - 40
print(sol)
I am not aware of any built in way to do that but Sympy library is built exactly for this stuff. Solvers module in Sympy can be used to solve linear equations. (Here) is a link to its docs.
An explicit example using sympy
import sympy
from sympy.abc import x
print sympy.solve(32*x-40,"x")
print sympy.solve(2*x+23-7*x,"x")
Gives as output:
[5/4]
[23/5]
Note that there is the separate question of parsing user input. That is, how do we take the string "32x-40" and turn it into the expression 32*x-40. This can be a non-trivial task depending on the complexity of the equations you are looking to model. If you are insterested in that, I would look into pyparsing.
You can just use sympy. Then you can do it in the print command. It looks like this.
import sympy
from sympy.abc import x
print sympy.solve(nub1*x+nub2-nub3*x,"Whatever you want here.")
I face a problem in scipy 'leastsq' optimisation routine, if i execute the following program it says
raise errors[info][1], errors[info][0]
TypeError: Improper input parameters.
and sometimes index out of range for an array...
from scipy import *
import numpy
from scipy import optimize
from numpy import asarray
from math import *
def func(apar):
apar = numpy.asarray(apar)
x = apar[0]
y = apar[1]
eqn = abs(x-y)
return eqn
Init = numpy.asarray([20.0, 10.0])
x = optimize.leastsq(func, Init, full_output=0, col_deriv=0, factor=100, diag=None, warning=True)
print 'optimized parameters: ',x
print '******* The End ******'
I don't know what is the problem with my func optimize.leastsq() call, please help me
leastsq works with vectors so the residual function, func, needs to return a vector of length at least two. So if you replace return eqn with return [eqn, 0.], your example will work. Running it gives:
optimized parameters: (array([10., 10.]), 2)
which is one of the many correct answers for the minimum of the absolute difference.
If you want to minimize a scalar function, fmin is the way to go, optimize.fmin(func, Init).
The issue here is that these two functions, although they look the same for a scalars are aimed at different goals. leastsq finds the least squared error, generally from a set of idealized curves, and is just one way of doing a "best fit". On the other hand fmin finds the minimum value of a scalar function.
Obviously yours is a toy example, for which neither of these really makes sense, so which way you go will depend on what your final goal is.
Since you want to minimize a simple scalar function (func() returns a single value, not a list of values), scipy.optimize.leastsq() should be replaced by a call to one of the fmin functions (with the appropriate arguments):
x = optimize.fmin(func, Init)
correctly works!
In fact, leastsq() minimizes the sum of squares of a list of values. It does not appear to work on a (list containing a) single value, as in your example (even though it could, in theory).
Just looking at the least squares docs, it might be that your function func is defined incorrectly. You're assuming that you always receive an array of at least length 2, but the optimize function is insanely vague about the length of the array you will receive. You might try writing to screen whatever apar is, to see what you're actually getting.
If you're using something like ipython or the python shell, you ought to be getting stack traces that show you exactly which line the error is occurring on, so start there. If you can't figure it out from there, posting the stack trace would probably help us.