I was trying to solve two equations for two unknown symbols 'Diff' and 'OHs'. the equations are shown below
x = (8.67839580228369e-26*Diff + 7.245e-10*OHs**3 +
1.24402291559836e-10*OHs**2 + OHs*(-2.38073807380738e-19*Diff -
2.8607855978291e-18) - 1.01141409254177e-29)
J= (-0.00435840284294195*Diff**0.666666666666667*(1 +
3.64525434266056e-7/OHs) - 1)
solution = sym.nsolve ((x, J), (OHs, Diff), (0.000001, 0.000001))
print (solution)
is this the correct way to solve for the two unknowns?
Thanks for your help :)
Note: I edited your equation per Vialfont's comments.
I would say it is a possible way but you could do better by noticing that the J equation can be solved easily for OHs and substituted into the x equation. This will then be much easier for nsolve to solve:
>>> osol = solve(J, OHs)[0] # there is only one solution
>>> eq = x.subs(OHs,osol)
>>> dsol = nsolve(eq, 1e-5)
>>> eq.subs(Diff,dsol) # verify
4.20389539297445e-45
>>> osol.subs(Diff,dsol), dsol
(-2.08893263437131e-12, 4.76768525775849e-5)
But this is still pretty ill behaved in terms of scaling...proceed with caution. And I would suggest writing Diff**Rational(2,3) instead of Diff**0.666666666666667. Or better, then let Diff be y**3 so you are working with a polynomial in y.
>>> y = var('y', postive=True)
>>> yx=x.subs(Diff,y**3)
>>> yJ=J.subs(Diff,y**3)
>>> yosol=solve(yJ,OHs)[0]
>>> yeq = yx.subs(OHs, yosol)
Now, the solutions of eq will be where its numerator is zero so find the real roots of that:
>>> ysol = real_roots(yeq.as_numer_denom()[0])
>>> len(ysol)
1
>>> ysol[0].n()
0.0362606728976173
>>> yosol.subs(y,_)
-2.08893263437131e-12
That is consistent with our previous solution, and this time the solutions in ysol were exact (given the limitations of the coefficients). So if your OHs solution should be positive, check your numbers and equations.
Your expressions do not meet Sympy requirements, including the exponential expressions. May be it is easier to start with a simpler system to solve with two unknowns and only a square such as:
from sympy.abc import a,b,x, y
from sympy import solve,exp
eq1= a*x**2 + b*y+ exp(0)
eq2= x + y + 2
sol=solve((eq1, eq2),(x,y),dict=True)
sol includes your answers and you have access to solutions with sol[0][x] and sol[0][y]. Giving values to the parameters is done with the .sub() method:
sol[0][x].subs({a:1, b:2}) #gives -1
sol[0][y].subs({a:1, b:2}) #gives -1
In Python 2, I can write:
In [5]: points = [ (1,2), (2,3)]
In [6]: min(points, key=lambda (x, y): (x*x + y*y))
Out[6]: (1, 2)
But that is not supported in 3.x:
File "<stdin>", line 1
min(points, key=lambda (x, y): (x*x + y*y))
^
SyntaxError: invalid syntax
The straightforward workaround is to index explicitly into the tuple that was passed:
>>> min(points, key=lambda p: p[0]*p[0] + p[1]*p[1])
(1, 2)
This is very ugly. If the lambda were a function, I could do
def some_name_to_think_of(p):
x, y = p
return x*x + y*y
But because the lambda only supports a single expression, it's not possible to put the x, y = p part into it.
How else can I work around this limitation?
No, there is no other way. You covered it all. The way to go would be to raise this issue on the Python ideas mailing list, but be prepared to argue a lot over there to gain some traction.
Actually, just not to say "there is no way out", a third way could be to implement one more level of lambda calling just to unfold the parameters - but that would be at once more inefficient and harder to read than your two suggestions:
min(points, key=lambda p: (lambda x,y: (x*x + y*y))(*p))
Python 3.8 update
Since the release of Python 3.8, PEP 572 — assignment expressions — have been available as a tool.
So, if one uses a trick to execute multiple expressions inside a lambda - I usually do that by creating a tuple and just returning the last component of it, it is possible to do the following:
>>> a = lambda p:(x:=p[0], y:=p[1], x ** 2 + y ** 2)[-1]
>>> a((3,4))
25
One should keep in mind that this kind of code will seldom be more readable or practical than having a full function. Still, there are possible uses - if there are various one-liners that would operate on this point, it could be worth to have a namedtuple, and use the assignment expression to effectively "cast" the incoming sequence to the namedtuple:
>>> from collections import namedtuple
>>> point = namedtuple("point", "x y")
>>> b = lambda s: (p:=point(*s), p.x ** 2 + p.y ** 2)[-1]
According to http://www.python.org/dev/peps/pep-3113/ tuple unpacking are gone, and 2to3 will translate them like so:
As tuple parameters are used by lambdas because of the single
expression limitation, they must also be supported. This is done by
having the expected sequence argument bound to a single parameter and
then indexing on that parameter:
lambda (x, y): x + y
will be translated into:
lambda x_y: x_y[0] + x_y[1]
Which is quite similar to your implementation.
I don't know any good general alternatives to the Python 2 arguments unpacking behaviour. Here's a couple of suggestion that might be useful in some cases:
if you can't think of a name; use the name of the keyword parameter:
def key(p): # more specific name would be better
x, y = p
return x**2 + y**3
result = min(points, key=key)
you could see if a namedtuple makes your code more readable if the list is used in multiple places:
from collections import namedtuple
from itertools import starmap
points = [ (1,2), (2,3)]
Point = namedtuple('Point', 'x y')
points = list(starmap(Point, points))
result = min(points, key=lambda p: p.x**2 + p.y**3)
While the destructuring arguments was removed in Python3, it was not removed from comprehensions. It is possible to abuse it to obtain similar behavior in Python 3.
For example:
points = [(1,2), (2,3)]
print(min(points, key=lambda y: next(x*x + y*y for (x,y) in [y])))
In comparison with the accepted answer of using a wrapper, this solution is able to completely destructure the arguments while the wrapper only destructures the first level. That is, you can do
values = [(('A',1),'a'), (('B',0),'b')]
print(min(values, key=lambda y: next(b for ((a,b),c) in (y,))))
In comparison to the accepted answer using an unwrapper lambda:
values = [(('A',1),'a'), (('B',0),'b')]
print(min(points, key=lambda p: (lambda a,b: (lambda x,y: (y))(*a))(*p)))
Alternatively one can also use a list instead of a tuple.
values = [(('A',1),'a'), (('B',0),'b')]
print(min(points, key=lambda y: next(b for (a,b),c in [y])))
This is just to suggest that it can be done, and should not be taken as a recommendation. However, IMO, this is better than the hack of using using multiple expressions in a tuple and returning the last one.
I think the better syntax is x * x + y * y let x, y = point, let keyword should be more carefully chosen.
The double lambda is the closest version.
lambda point: (lambda x, y: x * x + y * y)(*point)
High order function helper would be useful in case we give it a proper name.
def destruct_tuple(f):
return lambda args: f(*args)
destruct_tuple(lambda x, y: x * x + y * y)
Consider whether you need to unpack the tuple in the first place:
min(points, key=lambda p: sum(x**2 for x in p))
or whether you need to supply explicit names when unpacking:
min(points, key=lambda p: abs(complex(*p)**2)
Based on Cuadue suggestion and your comment on unpacking still being present in comprehensions, you can use, using numpy.argmin :
result = points[numpy.argmin(x*x + y*y for x, y in points)]
Another option is to write it into a generator producing a tuple where the key is the first element. Tuples are compared starting from beginning to end so the tuple with the smallest first element is returned. You can then index into the result to get the value.
min((x * x + y * y, (x, y)) for x, y in points)[1]
There may be a real solution to this, using PyFunctional!
Although not currently supported, I've submitted a tuple arg unpacking feature request to support:
(
seq((1, 2), (3, 4))
.map(unpack=lambda a, b: a + b)
) # => [3, 7]
Since questions on Stack Overflow are not supposed to contain the answer in the question, nor have explicit "update" sections, I am converting OP's original "updates" to a proper answer and making it community wiki.
OP originally claimed that this solution was "extending the idea in the answer". I cannot discern which answer that meant, or which idea. The idea is functionally the same as anthony.hl's answer, but that came years later. Considering the state of answers at the time, I think this qualifies as OP's original work.)
Make a wrapper function that generalizes the process of unpacking the arguments, like so:
def star(f):
return lambda args: f(*args)
Now we can use this to transform the lambda we want to write, into one that will receive the argument properly:
min(points, key=star(lambda x,y: (x*x + y*y))
We can further clean this up by using functools.wraps:
import functools
def star(f):
#functools.wraps(f)
def f_inner(args):
return f(*args)
return f_inner
I've been making a calculator in Swift 3, but have run into some problems.
I have been using NSExpression to calculate the users equation, but the answer is always rounded.
To check that the answer was rounded, I calculated 3 / 2.
let expression = NSExpression(format: "3 / 2");
let answer: Double = expression.expressionValue(with: nil, context: nil) as! Double;
Swift.print(String(answer));
The above code outputs 1.0, instead of 1.5.
Does anyone know how to stop NSExpression from rounding? Thanks.
The expression is using integer division since your operands are integers. Try this instead:
let expression = NSExpression(format: "3.0 / 2.0");
let answer: Double = expression.expressionValue(with: nil, context: nil) as! Double;
Swift.print(String(answer));
Consider the following code:
let answer = Double(3 / 2)
answer in this case would still be 1.0 since 3 / 2 is evaluated to 1 before being inserted in the Double initializer.
However, this code would give answer the value of 1.5:
let answer = Double(3.0 / 2.0)
This is because 3.0 / 2.0 will be evaluated based on the division operation for Double instead of the division operation of Integer.
sorry i am a bit of a newbie with programming but I am getting a float division error in a simple loop which I am not sure how to rectify.
Here is a code in python 2.7
import random
N = 100
A = []
p = 0
q = 0
k = 1
while k<=N:
x = random.random()
if x<= 0.5:
p+= 1
else:
q+=1
y = p/q
A.append(y)
k+=1
Running this code gives a zero division error. which I am not able to rectify. Can anyone tell me how to rectify this?
You are getting zero division error because of this code
if x <= 0.5:
p+=1
else:
q+=1
y= p/q
You have initialised q = 0 thus when while loop is run first time and if x <= 0.5 then p will be incremented but q will be equal to zero and in next step you are dividing p by q(which is zero). You need to put a check condition before performing division so that denominator is not zero. You can rectify it in following manner.
if x <= 0.5:
p+=1
else:
q+=1
if (q == 0):
print "Denominator is zero"
else:
y= p/q
This is just one solution since I don't know what you are trying to do in your code.
You can use numpy.nextafter(q, 1).
This gives you the next floating-point value after q towards 1, which is very small number.
I am using Numpy to obtain the roots of polynomials. Numpy provides a module 'polynomial'.
My hand calc for x^2 + 5*x + 6 = 0 is x = -2 & x = -3. (Simple)
But my code shows me the wrong answer: array([-0.5 , -0.33333333]) (Inversed?)
Could anyone please find the culprit in my code? Or is it simply a bug?
from numpy.polynomial import Polynomial as P
p = P([1, 5, 6])
p.roots()
Simply pass it in the other order,
p = P([6, 5, 1])
You could have realized this yourself if you had determined that, for a polynomial P of degree n, R(x) = x^n P(1/x) equals the reversed version of P. So, except for 0, the roots of R are the reciprocals of the roots of P.