I am trying to optimize a code that I wrote to calculate the least square for a system of equations and returns me the optimal value for the unknowns: a1,a2,a3,z1,z2 (pottemp and zlevels are know).
The system of equation is the following (https://i.sstatic.net/qlKg2.jpg):

I wrote the following code which works like a charm, but it isn't very efficient and you can see due to the number of for loops and if I increase the number of hstep and astep, my array gets really big and it takes a lot of time to compute the least square from leastsquared.
def leastsquared(zlevels,pottemp,z1,z2,a1,a2,a3):
dtot=0.0
for zi in range(len(zlevels)): #zvalue of obs points
if zlevels[zi]<=z1:
F=np.tan(a1)*zlevels[zi]+pottemp[0]
elif zlevels[zi]<=z2:
F=(np.tan(a1)*z1+pottemp[0]) + np.tan(a2)*(zlevels[zi]-z1)
else: #zlevels[zi]<=H
F=((np.tan(a1)*z1+pottemp[0]) + np.tan(a2)*(z2-z1) ) + np.tan(a3)*(zlevels[zi]-z2)
d=(pottemp[zi]-F)**2.0
dtot+=d
dtot=dtot/len(zlevels)
#print("dtot is" + str(dtot))
return dtot
def optm(hstep,astep,zlevels,pottemp):
sqdist=np.inf
for z1 in np.linspace(0,zlevels[-1],hstep):
for z2 in np.linspace(0,zlevels[-1],hstep):
for a1 in np.linspace(0,0.1,astep): # max angle
for a2 in np.linspace(0,0.01,astep):
for a3 in np.linspace(0,0.01,astep):
sqdist_new=leastsquared(zlevels,pottemp,z1,z2,a1,a2,a3)
if sqdist_new<sqdist:
sqdist=sqdist_new
optimalsetting=[z1,z2,a1,a2,a3]
return optimalsetting
The code itself is very simple but inefficient. I was trying to implement this code using scipy.optimize.minimize, but I haven't been able to run it. Does anyone have any idea how to optimize it? Perhaps, scipy.optimize.minimize would be the easiest way, but I'm not sure how to adapt my code to it.