Medium numbers in Broyden1 - python

I used broyden1 in Python resolver. The question was answered here, I need to use a bit larger numbers, but not newton_krylov. If I use numbers over 100, then it starts throwing errors.
The code is here:
import numpy as np
import scipy.optimize
from scipy.optimize import fsolve
from functools import partial
from itertools import repeat
small_data=[100,220,350,480]
def G(small_data, x):
return np.cos(x) +x[::-1] - small_data
G_partial = partial(G, small_data)
approximate=list(repeat(1,period))
y = scipy.optimize.broyden1(G_partial, approximate, f_tol=1e-14)
print(y)
The error is:
Warning (from warnings module):
File "C:\Python\Python38\lib\site-packages\scipy\optimize\nonlin.py", line 1004
d = v / vdot(df, v)
RuntimeWarning: invalid value encountered in true_divide
Traceback (most recent call last):
File "read_data.py", line 176, in <module>
y = scipy.optimize.broyden1(G_partial, approximate, f_tol=1e-14)
File "<string>", line 6, in broyden1
File "C:\Python\Python38\lib\site-
packages\scipy\optimize\nonlin.py", line 350, in nonlin_solve
raise NoConvergence(_array_like(x, x0))
scipy.optimize.nonlin.NoConvergence: [ 99.49247662 219.22593164 350.14354166 480.95722345]

I found that the best method is changing the equation in Boryden1 to :
y = scipy.optimize.broyden1(G_partial, approximate, f_tol=5000e-14)
instead of:
f_tot=1e-14
so larger values will be accepted with a good accuracy

Related

sin(y) results in "can't convert expression to float" error

I created a very simple MWE to illustrate my problem. When I type y**(2), the program works. But when I type sin(y) or cos(y), it results in the error TypeError: can't convert expression to float. I discuss attempts to fix this error below.
from vpython import *
from scipy.optimize import fsolve
import math
import numpy as np
import sympy as sp
from sympy import Eq, Symbol, solve
import matplotlib.pyplot as plt
y = Symbol('y')
i = input()
i = ''.join(i).split(',')
for x in range(0, len(i)):
i[x] = i[x].strip()
userMediums = i
def refIndexSize(medium):
def refractiveProfile(y):
return eval(medium, {'y': y, 'np': np})
lowerProfile = Eq(eval(medium), 1)
upperProfile = Eq(eval(medium), 1.6)
bounds = [abs(round(float(solve(lowerProfile)[0]),5)),
abs(round(float(solve(upperProfile)[0]),5))]
lowerBound = np.amin(bounds)
upperBound = np.amax(bounds)
return lowerProfile
refIndexSize(userMediums[0])
Error:
sin(y)+1
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_48/825631216.py in <module>
29 return lowerProfile
30
---> 31 refIndexSize(userMediums[0])
/tmp/ipykernel_48/825631216.py in refIndexSize(medium)
20 return eval(medium, {'y': y, 'np': np})
21
---> 22 lowerProfile = eval(medium)
23 upperProfile = Eq(eval(medium), 1.6)
24 bounds = [abs(round(float(solve(lowerProfile)[0]),5)),
<string> in <module>
/srv/conda/envs/notebook/lib/python3.7/site-packages/sympy/core/expr.py in __float__(self)
357 if result.is_number and result.as_real_imag()[1]:
358 raise TypeError("can't convert complex to float")
--> 359 raise TypeError("can't convert expression to float")
360
361 def __complex__(self):
TypeError: can't convert expression to float
I've looked at other questions regarding TypeError: can't convert expression to float, such as this and this. As a result, I have tried changing the order of my imports, although I can do nothing to change the wildcard from vpython import *, as it is the only way to import vpython (to my understanding), but this did not work. I've also tried inputting sp.sin(y) after looking at a different SO answer, but this did not help either. Once again, any tips or assistance is appreciated.
Your problem lies in this line:
bounds = [abs(round(float(solve(lowerProfile)[0]),5)),
abs(round(float(solve(upperProfile)[0]),5))]
Specifically this part:
abs(round(float(solve(upperProfile)[0]),5))
Here the solve() function returns complex solutions in a list.
See this:
[1.5707963267949 - 1.04696791500319*I, 1.5707963267949 + 1.04696791500319*I]
So, when you pick the 0 index it will be a complex result like this one:
1.5707963267949 - 1.04696791500319*I
So, you are trying to cast float() to this solution which results in error. Instead you can remove the bounds for solutions having complex results by using try-except block like this:
try:
bounds = [abs(round(float(solve(lowerProfile)[0]),5)),
abs(round(float(solve(upperProfile)[0]),5))]
lowerBound = np.amin(bounds)
upperBound = np.amax(bounds)
except:
print("The solutions are complex. Cant find a result")
Also import like this:
from vpython import *
from scipy.optimize import fsolve
import math
import numpy as np
import sympy as sp
from sympy import *
import matplotlib.pyplot as plt
In an ipython session, with the most relevant imports:
In [1]: import numpy as np
...: import sympy as sp
...: from sympy import Eq, Symbol, solve
Modify your function to return the bounds as well.
In [2]: def refIndexSize(medium):
...:
...: def refractiveProfile(y):
...: return eval(medium, {'y': y, 'np': np})
...:
...: lowerProfile = Eq(eval(medium), 1)
...: upperProfile = Eq(eval(medium), 1.6)
...: bounds = [abs(round(float(solve(lowerProfile)[0]),5)),
...: abs(round(float(solve(upperProfile)[0]),5))]
...: lowerBound = np.amin(bounds)
...: upperBound = np.amax(bounds)
...:
...: return lowerProfile, bounds
...:
Define the symbol, and call the function with a string. In the interactive session I don't need to go through the input complications.
In [3]: y = sp.Symbol('y')
y**2 gives the bounds that you claim in a comment:
In [4]: refIndexSize("y**(2)")
Out[4]: (Eq(y**2, 1), [1.0, 1.26491])
Errors due to sin definition
Using a sin expression gives a NameError. sin hasn't been imported or defined.
In [5]: refIndexSize("sin(y)+1")
Traceback (most recent call last):
File "<ipython-input-5-30c99485bce7>", line 1, in <module>
refIndexSize("sin(y)+1")
File "<ipython-input-2-6fea36c332b7>", line 6, in refIndexSize
lowerProfile = Eq(eval(medium), 1)
File "<string>", line 1, in <module>
NameError: name 'sin' is not defined
Import sin from math gives your error:
In [6]: from math import sin
In [7]: refIndexSize("sin(y)+1")
Traceback (most recent call last):
File "<ipython-input-7-30c99485bce7>", line 1, in <module>
refIndexSize("sin(y)+1")
File "<ipython-input-2-6fea36c332b7>", line 6, in refIndexSize
lowerProfile = Eq(eval(medium), 1)
File "<string>", line 1, in <module>
File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 359, in __float__
raise TypeError("can't convert expression to float")
TypeError: can't convert expression to float
math.sin expects a float value, so does not work with symbol y.
But import sin from sympy, and it works:
In [8]: from sympy import sin
In [9]: refIndexSize("sin(y)+1")
Out[9]: (Eq(sin(y) + 1, 1), [0.0, 0.6435])
Errors due to complex values
Originally your question showed the use of sin(y), which gives the complex error that #Prakash discusses
In [10]: refIndexSize("sin(y)")
Traceback (most recent call last):
File "<ipython-input-10-d470e7448a68>", line 1, in <module>
refIndexSize("sin(y)")
File "<ipython-input-2-6fea36c332b7>", line 9, in refIndexSize
abs(round(float(solve(upperProfile)[0]),5))]
File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 358, in __float__
raise TypeError("can't convert complex to float")
TypeError: can't convert complex to float
Let's simplify your function to get rid float call that seems to be giving problems
In [11]: def refIndexSize(medium):
...: lowerProfile = Eq(eval(medium), 1)
...: upperProfile = Eq(eval(medium), 1.6)
...: bounds = [solve(lowerProfile),
...: solve(upperProfile)]
...: return lowerProfile, bounds
...:
Run on sin(y)+1), we get the [0.0, 0.6435] values as before:
In [12]: refIndexSize("sin(y)+1")
Out[12]: (Eq(sin(y) + 1, 1), [[0, pi], [0.643501108793284, 2.49809154479651]])
Run on sin(y), we see that the 'raw' bounds includes complex values:
In [13]: refIndexSize("sin(y)")
Out[13]:
(Eq(sin(y), 1),
[[pi/2],
[1.5707963267949 - 1.04696791500319*I,
1.5707963267949 + 1.04696791500319*I]])
If you really need a rounded float from such an answer, you need to either extract the real part first, or use abs first:
In [15]: bounds = _[1][1]
In [17]: abs(bounds[0])
Out[17]: 1.88773486361789

Dimension mismatch error in python while evaluating a function of two arguments

The function evaluates if I input a pair of arguments. But when I try to evaluate the function at grid points, it fails, saying "ValueError: dimension mismatch". I paste the code below. Could anyone help with the problem?
import numpy as np
from qutip import*
import pylab as plt
from numpy import eye,pi,kron,random,vdot,absolute,power,sqrt,matmul
from numpy import exp,arange
from pylab import meshgrid,cm,imshow,contour,clabel,colorbar,axis,title,show
j0= tensor(sigmaz(),identity(2),identity(2))
def otoc(k0,n):
u0=(-1j*k0/6 *(tensor(sigmaz(),sigmaz(),identity(2)))).expm()
jn= u0.inv()**n*j0*u0**n
return ((commutator(jn,j0)* commutator(j0,jn)).tr()/8)
k0 = np.arange(0,4,0.1)
n = np.linspace(0,50,50)
X,Y = meshgrid(k0, n)
Z = otoc(X, Y)
The error showing is the following
Traceback (most recent call last):
File "/Users/sreerampg/Dropbox/myself/programs/levy's lemma/untitled8.py", line 27, in <module>
Z = otoc(X, Y)
File "/Users/sreerampg/Dropbox/myself/programs/levy's lemma/untitled8.py", line 20, in otoc
u0=(-1j*k0/6 *(tensor(sigmaz(),sigmaz(),identity(2)))).expm()
File "/Applications/anaconda3/lib/python3.7/site-packages/qutip/qobj.py", line 599, in __rmul__
return other * self.data
File "/Applications/anaconda3/lib/python3.7/site-packages/scipy/sparse/base.py", line 550, in __rmul__
return (self.transpose() * tr).transpose()
File "/Applications/anaconda3/lib/python3.7/site-packages/cvxpy/interface/scipy_wrapper.py", line 31, in new_method
return method(self, other)
File "/Applications/anaconda3/lib/python3.7/site-packages/scipy/sparse/base.py", line 516, in __mul__
raise ValueError('dimension mismatch')
ValueError: dimension mismatch

Python matplotlib error: Supplied function does not return a valid float

from __future__ import division
import functools
import warnings
import numpy as np
import scipy as sp
from scipy import integrate
from numpy import exp, pi
import matplotlib.pyplot as plt
warnings.simplefilter("ignore", np.ComplexWarning)
def legendrePoly(a,n):
def integrand(t):
return ( ((a + exp(2j*pi*t))**2 - 1)/(2*exp(2j*pi*t)) )**n
return sp.integrate.quad(integrand,0,1)[0]
basisDim = 6
legendreBasis = [functools.partial(legendrePoly, n=i) for i in range(basisDim)]
integrand = [lambda x,i=i: exp(x) * legendreBasis[i](x) for i in range(basisDim)]
normalizingConst = [lambda x,i=i: legendreBasis[i](x)**2 for i in range(basisDim)]
basisCoeff = [sp.integrate.quad(integrand[i],-1,1)[0]
/sp.integrate.quad(normalizingConst[i],-1,1)[0] for i in range(basisDim)]
approxPoly = lambda x: sum(basisCoeff[i]*legendreBasis[i](x) for i in range(basisDim))
t = np.arange(-1, 1, 1e-3)
plt.plot(t,exp(t),'b')
plt.plot(t,approxPoly(t),'r')
plt.show()
I'm using Legendre polynomials as a basis for a polynomial approximation to the exponential function. I'm also using Cauchy's Integral Formula to evaluate them, rather than importing them directly from numpy.
Everything runs fine up to and including defining approxPoly, and approxPoly returns the expected value for any input I enter. But for some reason when I try to plot approxPoly(t), it returns the error: Supplied function does not return a valid float.
This error seems to suggest that when my functions in legendreBasis call to scipy.integrate.quad, that something goes wrong there, but if that was the case then approxPoly wouldn't work, yet if you evaluate it at 2000 points between -1 and 1 manually, and plot these points, everything works fine, but is that not exactly what plt.plot doing when it tries to graph my function?
Traceback:
Traceback (most recent call last):
File "/private/var/folders/mb/yyp8v3_95l538z3g7jsttq540000gn/T/Cleanup At Startup/Exercise-413072597.643.py", line 34, in <module>
plt.plot(t,approxPoly(t),'r')
File "/private/var/folders/mb/yyp8v3_95l538z3g7jsttq540000gn/T/Cleanup At Startup/Exercise-413072597.643.py", line 29, in <lambda>
approxPoly = lambda x: sum(basisCoeff[i]*legendreBasis[i](x) for i in range(basisDim))
File "/private/var/folders/mb/yyp8v3_95l538z3g7jsttq540000gn/T/Cleanup At Startup/Exercise-413072597.643.py", line 29, in <genexpr>
approxPoly = lambda x: sum(basisCoeff[i]*legendreBasis[i](x) for i in range(basisDim))
File "/private/var/folders/mb/yyp8v3_95l538z3g7jsttq540000gn/T/Cleanup At Startup/Exercise-413072597.643.py", line 18, in legendrePoly
return sp.integrate.quad(integrand,0,1)[0]
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/quadpack.py", line 247, in quad
retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/quadpack.py", line 312, in _quad
return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
quadpack.error: Supplied function does not return a valid float.
logout
scipy.integrate.quad doesn't integrate functions that return arrays. That means when you try to call approxPoly(t), t gets passed around until it ends up in this function:
def legendrePoly(a,n):
def integrand(t):
return ( ((a + exp(2j*pi*t))**2 - 1)/(2*exp(2j*pi*t)) )**n
return sp.integrate.quad(integrand,0,1)[0]
integrand returns an array, and sp.integrate.quad chokes. The same problem occurs a number of times in your code. Everything seems to be written assuming scalar arguments.
You can probably fix this by calling vectorize on approxPoly:
plt.plot(t,np.vectorize(approxPoly)(t),'r')
NumPy will then call approxPoly on each element of t separately.

Interpolate a discontinuous function with Scipy

I am having problems interpolating some data points using Scipy. I guess that it might depend on the fact that the function I'm trying to interpolate is discontinuous at x roughly 4.
Here is the code I'm using to interpolate:
from scipy import *
y_interpolated = interp1d(x,y,buonds_error=False,fill_value=0.,kind='cubic')
new_x_array = arange(min(x),max(x),0.05)
plot(new_x_array,x_interpolated(new_x_array),'r-')
The error I get is
File "<stdin>", line 2, in <module>
File "/Library/Frameworks/EPD64.framework/Versions/7.1/lib/python2.7/site-packages/scipy/interpolate/interpolate.py", line 357, in __call__
out_of_bounds = self._check_bounds(x_new)
File "/Library/Frameworks/EPD64.framework/Versions/7.1/lib/python2.7/site-packages/scipy/interpolate/interpolate.py", line 415, in _check_bounds
raise ValueError("A value in x_new is above the interpolation "
ValueError: A value in x_new is above the interpolation range.
These are my data points:
1.56916432074 -27.9998263169
1.76773750527 -27.6198430485
1.98360238449 -27.2397962268
2.25133982943 -26.8596491107
2.49319293195 -26.5518194791
2.77823462692 -26.1896935372
3.07201297519 -25.9540514619
3.46090507092 -25.7362456112
3.65968688527 -25.6453922172
3.84116464506 -25.53652509
3.97070419447 -25.3374215879
4.03087127145 -24.8493356465
4.08217147954 -24.0540196233
4.12470899596 -23.0960856364
4.17612639206 -22.4634289328
4.19318305992 -22.1380894034
4.2708234589 -21.902951035
4.3745696768 -21.9027079759
4.52158254627 -21.9565591238
4.65985875536 -21.8839570732
4.80666329863 -21.6486676004
4.91026629192 -21.4496126386
5.05709528961 -21.2685401725
5.29054655428 -21.2860476871
5.54129211534 -21.3215908912
5.73174988353 -21.6645019816
6.06035782465 -21.772138994
6.30243916407 -21.7715483093
6.59656410998 -22.0238656166
6.86481948673 -22.3665921479
7.01182409559 -22.4385289076
7.17609125906 -22.4200564296
7.37494987052 -22.4376476472
7.60844044988 -22.5093814451
7.79869207061 -22.5812017094
8.00616642549 -22.5445612485
8.17903446593 -22.4899243886
8.29141325457 -22.4715846981
What version of scipy are you using?
The script you posted has some syntax errors (I assume due to wrong copy and paste).
This script works, with scipy.__version__ == 0.9.0. .
import sys
from scipy import *
from scipy.interpolate import *
from pylab import plot
x = []
y = []
for line in sys.stdin:
a, b = line.split()
x.append(float(a))
y.append(float(b))
y_interpolated = interp1d(x,y,bounds_error=False,fill_value=0.,kind='cubic')
new_x_array = arange(min(x),max(x),0.05)
plot(new_x_array,y_interpolated(new_x_array),'r-')

Python and Scipy programming

I'm getting this error message:
Traceback (most recent call last):
File "C:/Python27/test", line 14, in <module>
tck = interpolate.bisplrep(X,Y,Z)
File "C:\Python27\lib\site-packages\scipy\interpolate\fitpack.py", line 850, in bisplrep
raise TypeError('m >= (kx+1)(ky+1) must hold')
TypeError: m >= (kx+1)(ky+1) must hold
The error says that len(X) = m is <=(kx+1)(ky+1). How can I solve this? Here's my program:
import scipy
import math
import numpy
from scipy import interpolate
x= [1000,2000,3000,4000,5000,6000]
y= [1000]
Y = numpy.array([[i]*len(x) for i in y])
X = numpy.array([x for i in y])
Z = numpy.array([[21284473.74,2574509.71,453334.97,95761.64,30580.45,25580.60]])
tck = interpolate.bisplrep(x,y,Z)
print interpolate.bisplev(3500,1000,tck)
Have you read the documentation?
If you don't specify kx and ky, default values will be 3:
scipy.interpolate.bisplrep(x, y, z, w=None, xb=None, xe=None, yb=None, ye=None,
kx=3, ky=3, task=0, s=None, eps=1e-16, tx=None, ty=None,
full_output=0, nxest=None, nyest=None, quiet=1)
And of course, len(X) = 6 < 16 = (3+1)(3+1).
Even if you give kx=1 and ky=1 explicitly while calling, you have another problem. Your (x,y) values form a line, and you can not define a surface from a line. Therefore it gives you ValueError: Invalid inputs.. First, you should fix your data. If this is your data, as you have no variation in Y, skip it and do a spline in 2D with X and Z.

Categories