I want to add two 3x2 matrices, g and temp_g.
Currently g is
[[ 2.77777778e+000 6.58946653e-039]
[ 4.96398713e+173 1.64736663e-039]
[ -1.88888889e+000 -3.29473326e-039]]
And temp_g is:
[[ -5.00000000e-01 -2.77777778e+00]
[ -1.24900090e-16 -4.44444444e-01]
[ 5.00000000e-01 1.88888889e+00]]
But when I do g = g + temp_g, and output g, I get this:
[[ 2.27777778e+000 -2.77777778e+000]
[ 4.96398713e+173 -4.44444444e-001]
[ -1.38888889e+000 1.88888889e+000]]
Maybe I'm having trouble understanding long float numbers... but is this what the result ought to be? I expected that g[0][0] would get added to temp_g[0][0], and g[0][1] to temp_g [0][1] and so on...
Your addition is working fine, but your two arrays have some seriously different orders of magnitude.
Taking for example 4.96398713e+173 - 1.24900090e-16, your first number is 189 orders of magnitude bigger than the second. Floating point numbers don't have this level or accuracy, you're talking about talking a number with ~170 0s at the end of it and adding a number along the lines of 0.00000000000000001249 to it.
I would suggest looking at this to see some of the limitations of floating point numbers (in all languages, not just necessarily Python).
The Decimal library can be used for handling numbers more accurately than floats.
import numpy as np
import decimal
a = decimal.Decimal(4.96398713e+173)
b = decimal.Decimal(1.24900090e-16)
print(a+b)
# 4.963987129999999822073620193E+173
# You can also set the dtype of your array to decimal.Decimal
a = np.array([[ 2.77777778e+000, 6.58946653e-039],
[ 4.96398713e+173, 1.64736663e-039],
[ -1.88888889e+000, -3.29473326e-039]],
dtype=np.dtype(decimal.Decimal))
Related
I recently encountered a problem of the inaccuracy of the matrix product/multiplication in NumPy. See my example below also here https://trinket.io/python3/6a4c22e450
import numpy as np
para = np.array([[ 3.28522453e+08, -1.36339334e+08, 1.36339334e+08],
[-1.36339334e+08, 5.65818682e+07, -5.65818682e+07],
[ 1.36339334e+08, -5.65818672e+07, 5.65818682e+07]])
in1 = np.array([[ 285.91695469],
[ 262.3 ],
[-426.64380594]])
in2 = np.array([[ 285.91695537],
[ 262.3 ],
[-426.64380443]])
(in1 - in2)/in1
>>> array([[-2.37831286e-09],
[ 0.00000000e+00],
[ 3.53925214e-09]])
The difference between in1 and in2 is very small, which is ~10^-9
res1 = para # in1
>>> array([[-356.2361908 ],
[ 443.16068268],
[-180.86068344]])
res2 = para # in2
>>> array([[ 73.03147125],
[265.01131439],
[ -2.71131516]])
but after the matrix multiplication, why does the difference between the output res1 and res2 change so much?
(res1 - res2)/res1
>>> array([[1.20500857],
[0.40199723],
[0.98500882]])
This is not a bug; it is to be expected with a matrix such as yours.
Your matrix (which is symmetric) has one large and two small eigenvalues:
In [34]: evals, evecs = np.linalg.eigh(para)
In [35]: evals
Out[35]: array([-1.06130078e-01, 1.00000000e+00, 4.41686189e+08])
Because the matrix is symmetric, it can be diagonalized with an orthonormal basis. That just means that we can define a new coordinate system in which the matrix is diagonal, and the diagonal values are those eigenvalues. The effect of multiplying the matrix by a vector in these coordinates is to simply multiply each coordinate by the corresponding eigenvalue, i.e. the first coordinate is multiplied by -0.106, the second coordinate doesn't change, and the third coordinate is multiplied by the large factor 4.4e8.
The reason you get such a drastic change when multiplying the original matrix para by in1 and in2 is that, in the new coordinates, the third component of the transformed in1 is positive, and the third component of the transformed in2 is negative. (That is, the points are on opposite sides of the 2-d eigenspace associated with the two smaller eigenvalues.) There are several ways to find these transformed coordinates; one is to compute inv(V)#x, where V is the matrix of eigenvectors:
In [36]: np.linalg.solve(evecs, in1)
Out[36]:
array([[ 5.64863071e+02],
[-1.16208620e+02],
[ 8.55527517e-07]])
In [37]: np.linalg.solve(evecs, in2)
Out[37]:
array([[ 5.64863070e+02],
[-1.16208619e+02],
[-2.71381169e-07]])
Note the different signs of the third components. The values are small, but when you multiply by the diagonal matrix, they are multiplied by 4.4e8, giving 377.87 and -119.86, respectively. That large change shows up as the results that you observed in the original coordinates.
For a rougher calculation: note that the elements of para are ~10^8, so multiplication on that order of magnitude occurs when you compute para # x. It is not surprising then, that given the relative differences between in1 and in2 are ~10^-9, the relative differences of res1 and res2 will be ~10^-9 * ~10^8 or ~0.1. (Your calculated relative errors were [1.2, 0.4, 0.99], so the rough estimate is in the right ballpark.)
This looks like a bug ... numpy is written in C, so this could be an issue of casting number into smaller float, which causes big floating point error in this case
I have a numpy array of complex numbers. I seek to clip the real and imaginary parts of each number in the array to some prescribed minimum and maximum (same clipping applied to both the real and imaginary parts). For example, consider:
import numpy as np
clip_min = -4
clip_max = 3
x = np.array([-1.4 + 5j, -4.7 - 3j])
The desired output of the clipping operation would be:
[-1.4 + 3j, -4-3j]
I can achieve this by calling np.clip on the real and imaginary parts of the complex array and then adding them (after multiplying the imaginary clipped data by 1j). Is there a way to do this with one command?
np.clip(x, clip_min, clip_max)
doesn't yield the desired result.
There is a slightly more efficient way than clipping the real and imaginary parts as separate arrays, using in-place operations:
np.clip(x.real, clip_min, clip_max, out=x.real)
np.clip(x.imag, clip_min, clip_max, out=x.imag)
If these are just cartesian coordinates stored in complex numbers, you could clip them in a single command by keeping them as floats rather than complex.
x = array([[-1.4, 5. ],
[-4.7, -3. ]])
np.clip(x, clip_min, clip_max)
>>> array([[-1.4, 3. ],
[-4. , -3. ]])
I am trying to split up the multiplication of a dft matrix in to real and imaginary parts
from scipy.linalg import dft
improt numpy as np
# x is always real
x = np.ones(4)
W = dft(4)
Wx = W.dot(x)
Wxme = np.real(W).dot(x) + np.imag(W).dot(x)*1.0j
I would like that Wx and Wxme give the same value but they are not at all. I have narrowed down the bug a bit more:
In [62]: W[1]
Out[62]:
array([ 1.00000000e+00 +0.00000000e+00j,
6.12323400e-17 -1.00000000e+00j,
-1.00000000e+00 -1.22464680e-16j, -1.83697020e-16 +1.00000000e+00j])
In [63]: np.sum(W[1])
Out[63]: (-2.2204460492503131e-16-1.1102230246251565e-16j)
In [64]: sum(W[1])
Out[64]: (-1.8369701987210297e-16-2.2204460492503131e-16j)
Why do sum and np.sum give different values ?? addition of complex numbers should not be anything but adding the real parts and the imaginary parts seperately right ??
Adding the by hand gives me the result I would expect as opposed to what numy gives me:
In [65]: 1.00000000e+00 + 6.12323400e-17 + -1.00000000e+00 + 1.83697020e-16
Out[65]: 1.8369702e-16
What am I missing ??
Up to rounding error, these results are equal. The results have slightly different rounding error due to factors such as different summation order or different levels of precision used to represent intermediate results.
I want to plot a graph of the magnitude of 1/(1+(i)(omega)(tau)) against frequency f, where i is the imaginary number, omega=(2)(pi)(f), tau is a constant. The following is the first part of the code:
import pylab as pl
import numpy as np
f=np.logspace(-2,4,10)
tau=1.0
omega=2*np.pi*f
y=np.complex(1,omega*tau)
print y
But I get this TypeError: only length-1 arrays can be converted to Python scalars. What's the problem? Why can't I put f (which is an array right?) to y? By the way, I am using enthought canopy.
One more question: What's the difference between pylab and matplotlib? Different modules? If I'm just plotting graphs, dealing with complex numbers and matrix, which one should I use?
You can't construct numpy arrays with np.complex. In python when you put a j after a number it makes it imaginary. Thus, to make complex arrays simply do:
y = 1 + omega * tau * 1j
This is a case of having to use np.vectorize. That is,
def main():
f = np.logspace(-2,4,10)
print(f)
tau=1.0
omega=2*np.pi*f
y=np.vectorize(complex)(1,omega*tau)
print (y)
, will return first:
[ 1.00000000e-02 4.64158883e-02 2.15443469e-01 1.00000000e+00
4.64158883e+00 2.15443469e+01 1.00000000e+02 4.64158883e+02
2.15443469e+03 1.00000000e+04]
And then return:
[ 1. +6.28318531e-02j 1. +2.91639628e-01j 1. +1.35367124e+00j
1. +6.28318531e+00j 1. +2.91639628e+01j 1. +1.35367124e+02j
1. +6.28318531e+02j 1. +2.91639628e+03j 1. +1.35367124e+04j
1. +6.28318531e+04j]
This question already has answers here:
Python: Find number of occurrences of given array within two-dimensional array
(6 answers)
Closed 9 years ago.
I have a numpy array of arrays:
qv=array([[-1.075, -1.075, -3. ],
[-1.05 , -1.075, -3. ],
[-1.025, -1.075, -3. ],
...,
[-0.975, -0.925, -2. ],
[-0.95 , -0.925, -2. ],
[-0.925, -0.925, -2. ]])
And I want to determine if an array is contained in that 2-D array and return its index.
qt=array([-1. , -1.05, -3. ])
I can convert both arrays to lists and use the list.index() function:
qlist=qv.tolist()
ql=qt.tolist()
qindex=qlist.index(ql)
But I would like to avoid doing this because I think it will be a performance hit.
This should do the trick,
import numpy as np
np.where((qv == qt).all(-1))
Or
import numpy as np
tol = 1e-8
diff = (qv - qt)
np.where((abs(diff) < tol).all(-1))
The second method might be more appropriate when floating point precision issues come into play. Also, there might be a better approach if you have many qt to test against. For example scipy.spatial.KDTree.