Melih Kara - 4 months ago 20

Python Question

I am trying to solve a min value problem, I could obtain the min values from two loops but, what I really need is also the exact values that correspended to output min.

`from __future__ import division`

from numpy import*

b1=0.9917949

b2=0.01911

b3=0.000840

b4=0.10175

b5=0.000763

mu=1.66057*10**(-24) #gram

c=3.0*10**8

Mler=open("olasiM.txt","w+")

data=zeros(0,'float')

for A in range(1,25):

M2=zeros(0,'float')

print 'A=',A

for Z in range(1,A+1):

SEMF=mu*c**2*(b1*A+b2*A**(2./3.)-b3*Z+b4*A*((1./2.)-(Z/A))**2+(b5*Z**2)/(A**(1./3.)))

SEMF=array(SEMF)

M2=hstack((M2,SEMF))

minm2=min(M2)

data=hstack((data,minm2))

data=hstack((data,A))

datalist = data.tolist()

for i in range (len(datalist)):

Mler.write(str(datalist[i])+'\n')

Mler.close()

Here, what I want is to see the min value of the

`SEMF`

`A`

`Z`

`A=1`

`Z=1`

`SEMF= some#`

I also don't know how to write these,

`A`

`Z`

Answer

The big advantage of numpy over using python lists is *vectorized operations*. Unfortunately your code fails completely in using them. For example the whole inner loop that has `Z`

as index can easily be vectorized. You instead are computing the single elements using python `float`

s and then stacking them one by one in the numpy array `M2`

.

So I'd refactor that part of the code by:

```
import numpy as np
# ...
Zs = np.arange(1, A+1, dtype=float)
SEMF = mu*c**2 * (b1*A + b2*A**(2./3.) - b3*Zs + b4*A*((1./2.) - (Zs/A))**2 + (b5*Zs**2)/(A**(1./3.)))
```

Here the `SEMF`

array should be exactly what you'd obtain as the final `M2`

array. Now you can find the minimum and stack that value into your `data`

array:

```
min_val = SEMF.min()
data = hstack((data,minm2))
data = hstack((data,A))
```

If you also what to keep track for which value of `Z`

you got the minimum you can use the `argmin`

method:

```
min_val, min_pos = SEMF.min(), SEMF.argmin()
data = hstack((data,np.array([min_val, min_pos, A])))
```

The final code should look like:

```
from __future__ import division
import numpy as np
b1 = 0.9917949
b2 = 0.01911
b3 = 0.000840
b4 = 0.10175
b5 = 0.000763
mu = 1.66057*10**(-24) #gram
c = 3.0*10**8
data=zeros(0,'float')
for A in range(1,25):
Zs = np.arange(1, A+1, dtype=float)
SEMF = mu*c**2 * (b1*A + b2*A**(2./3.) - b3*Zs + b4*A*((1./2.) - (Zs/A))**2 + (b5*Zs**2)/(A**(1./3.)))
min_val, min_pos = SEMF.min(), SEMF.argmin()
data = hstack((data,np.array([min_val, min_pos, A])))
datalist = data.tolist()
with open("olasiM.txt","w+") as mler:
for i in range (len(datalist)):
mler.write(str(datalist[i])+'\n')
```

Note that numpy provides some functions to save/load array to/from files, like `savetxt`

so I suggest that instead of manually saving the values there to use these functions.

Probably some `numpy`

expert could vectorize also the operations for the `As`

. Unfortunately my numpy knowledge isn't that advanced and I don't know how the handle the fact that we'd have a variable number of dimensions due to the `range(1, A+1)`

thing...