The function np.linalg.inv() doesn't work correctly - arrays

I actually work on some matrices and when I inverse it, the inverse is wrong. I use np.linalg.inv() to inverse my square matrix.
My example his:
import numpy as np
M = np.array([[9.0, 5.329070518200756e-17, -7.199999999999999, -5.3999999999999995, 0.0, 0.0], [5.329070518200756e-17, 9.0, 5.3999999999999995, -7.199999999999999, 0.0, 0.0], [-7.199999999999999, 5.3999999999999995, 11.422222222222222, 1.6653345369377363e-17, -2.4222222222222225, -7.266666666666667], [-5.3999999999999995, -7.199999999999999, 1.6653345369377363e-17, 11.422222222222222, 7.266666666666667, -2.4222222222222225], [0.0, 0.0, -2.4222222222222225, 7.266666666666667, 24.22222222222222, 0.0], [0.0, 0.0, -7.266666666666667, -2.4222222222222225, 0.0, 24.22222222222222]])
M_inv = np.linalg.inv(M)
# It's not the Identity!
print( M_inv # M)
Do you have clues ?
Thank you for your answers!

Check numpy.linalg.inv because Rank defective matrices cannot be inverted, need to supply a square or it can also be a valid numpy.matrix instance, the linalg.inv method processes M = np.array([...]) numpy.linalg.inv(M) incorrectly.

Related

Julia Language: How to create an array of structs inside a for loop

here in this code, I am trying to create an array of struct called Linestruct
but I am getting this error "bound error, attempts to access0-element array..."
using CSV
df=CSV.read("F:/B/Mayar/lineData.CSV")
struct Linestruct
buses::Vector{Int}
res::Float64
ind::Float64
imp_mag::Float64
imp_angle::Float64
p::Float64
q::Float64
state::String
end
CREATE_Linestruct() = Linestruct([0,0], 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, "overloaded")
Linestruct(buses_line, res_line, ind_line) = Linestruct(buses_line, res_line,
ind_line, 0.0, 0.0, 0.0, 0.0, "overloaded")
l2 = Linestruct([1,2,3], 0.0, 0.0)
l3=CREATE_Linestruct()
number_lines=size(df,1)
array_lines=Array{Linestruct,1}()
for x in 1:N
l4=CREATE_Linestruct()
array_lines[x]=l4
end
The issue is that the line
array_lines=Array{Linestruct,1}()
creates an empty array (i.e an array of size 0).
Afterwards, the line
array_lines[x]=l4
does not make the aray grow (unlike what would happen in a language like Matlab): it tries to change the value at index x in the array. Since the array is empty, you get an error.
A minimal example reproducing this situation might be (note that I'm using a vector of Int values here, since your problem is not really related to the array storing structs rather than native types):
julia> a = Array{Int, 1}()
0-element Array{Int64,1}
julia> a[1] = 1
ERROR: BoundsError: attempt to access 0-element Array{Int64,1} at index [1]
A way to fix this could be to make the array grow using push! to insert new values at the end of it:
julia> for i in 1:3
push!(a, i)
end
julia> a
3-element Array{Int64,1}:
1
2
3
Let's consider this simple struct:
struct Mine
a::Int
b::String
end
Vectorization is the most concise form - usually when creating Arrays of structs I try to avoid loops:
julia> a = Mine.([1,2,3],["b1","b2","b3"])
3-element Array{Mine,1}:
Mine(1, "b1")
Mine(2, "b2")
Mine(3, "b3")
Comprehension is also nice:
julia> [Mine(a,b) for (a,b) in [(1,"b1"),(2,"b2"),(3,"b3") ]]
3-element Array{Mine,1}:
Mine(1, "b1")
Mine(2, "b2")
Mine(3, "b3")
If there is no other way create an empty Array and push! or append! elements to it:
julia> ar = Mine[]
0-element Array{Mine,1}
julia> push!(ar, Mine(1,"a1"));
julia> append!(ar, [Mine(2,"b1"),Mine(3,"b3")])
3-element Array{Mine,1}:
Mine(1, "a1")
Mine(2, "b1")
Mine(3, "b3")

How can I directly modify the weight values in the Julia library Flux?

In the Julia library Flux, we have the ability to take a neural network, let's call it network m and extract the weights of network m with the following code:
params(m)
This returns a Zygote.Params type of object, of the form:
Params([Float32[0.20391908 -0.101616435 0.09610984 -0.1013181 -0.13325627 -0.034813307 -0.13811183 0.27022845 ...]...)
If I wanted to alter each of the weights slightly, how would I be able to access them?
Edit:
As requested, here is the structure for m:
Chain(LSTM(8,10),Dense(10,1))
You can iterate on a Params object to access each set of parameters as an array, which you can manipulate in place.
Supposing you want to change every parameter by 1‰, you could do something like the following:
julia> using Flux
julia> m = Dense(10, 5, σ)
Dense(10, 5, σ)
julia> params(m)
Params([Float32[-0.026854342 -0.57200056 … 0.36827534 -0.39761665; -0.47952518 0.594778 … 0.32624483 0.29363066; … ; -0.22681071 -0.0059174187 … -0.59344876 -0.02679312;
-0.4910349 0.60780525 … 0.114975974 0.036513895], Float32[0.0, 0.0, 0.0, 0.0, 0.0]])
julia> for p in params(m)
p .*= 1.001
end
julia> params(m)
Params([Float32[-0.026881196 -0.5725726 … 0.3686436 -0.39801428; -0.4800047 0.5953728 … 0.32657108 0.2939243; … ; -0.22703752 -0.0059233364 … -0.5940422 -0.026819913; -0.
49152592 0.60841304 … 0.11509095 0.03655041], Float32[0.0, 0.0, 0.0, 0.0, 0.0]])

Connecting the points of design envelope in JFreeChart

Is there a way to get JFreeChart to connect all the point in this series
x = [0.0, 38.0, 60.0, 80.0, 100.0, 123.0, 165.0, 165.0, 0.0]
y = [0.25, 0.25 ,0.6 ,1.1 ,1.75 ,2.65 ,2.65 ,0.25, 0.25]
to form an envelope?
After several attempts I could not get the beginning and the end of the plot to connect since both of them are zero on the x-axis.
Any hint will be greatly appreciated.

scipy curve_fit with arrays TypeError: only length-1 arrays can be converted to Python scalars

I am trying to create the curve fit with scipy for the energy eigenvalues calculated from a 4x4 Hamiltonian matrix. In the following error "energies" corresponds to the function in which I define the Hamiltonian, "xdata" is an array given after and out of the function and corresponds to k and "e" is the energy eigenvalues that a get.
The error seems to be at the Hamiltonian matrix. However if I run the code without the curve_fit everything works fine.
I have also tried using np.array according to other questions I found here but again it doesn't work.
If a give a specific xdata in the curve fit, like xdata[0], the code works but it doesn't help me much since I want the fit using all values.
Does anyone know what is the problem? Thank you all in advance!
Traceback (most recent call last):
File "fitest.py", line 70, in <module>
popt, pcov = curve_fit(energies,xdata, e)#,
File "/eb/software/Python/2.7.12-intel-2016b/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 651, in curve_fit
res = leastsq(func, p0, args=args, full_output=1, **kwargs)
File "/eb/software/Python/2.7.12-intel-2016b/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 377, in leastsq
shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
File "/eb/software/Python/2.7.12-intel-2016b/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 26, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
File "/eb/software/Python/2.7.12-intel-2016b/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 453, in _general_function
return function(xdata, *params) - ydata
File "fitest.py", line 23, in energies
[ 0.0, 0.0, 0.0, ep-2*V4*cos(kpt*d) ]],dtype=complex)
TypeError: only length-1 arrays can be converted to Python scalars
Code:
from numpy import sin, cos, array
from scipy.optimize import curve_fit
from numpy import *
from numpy.linalg import *
def energies(kpt, a=1.0, b=2.0, c=3.0, f=4.0):
e1=-15.0
e2=-10.0
d=1.0
v0=(-2.0/d**2)
V1=a*v0
V2=b*v0
V3=c*v0
V4=d*v0
basis=('|S, s>', '|S,px>', '|S, py>', '|S,pz>')
h=array([[ e1-2*V1*cos(kpt*d), -2*V2*1j*sin(kpt*d), 0.0, 0.0 ],
[ 2*V2*1j*sin(kpt*d), e2-2*V3*cos(kpt*d), 0.0, 0.0],
[ 0.0, 0.0, e2-2*V4*cos(kpt*d), 0.0],
[ 0.0, 0.0, 0.0, e2-2*V4*cos(kpt*d) ]],dtype=complex)
e,psi=eigh(h)
return e
print energies(kpt=0.0)
k2=0.4*2*pi/2.05
print energies(kpt=k2)
xdata = array([0.0,k2])
print xdata
popt, pcov = curve_fit(energies, xdata, e)
print " "
print popt
print " "
Your problem has nothing to do with your fit, you run into the same problem, if you perform
print energies(xdata)
The reason for this error message is that you put an array kpt into h as an array element and then tell numpy, to transform this array kpt into a complex number. Numpy is kind enough to transform an array of length one into a scalar, which then can be transformed into a complex number. This explains, why you didn't get an error message with xdata[0]. You can easily reproduce your problem like this
import numpy as np
#all fine with an array of length one
xa = np.asarray([1])
a = np.asarray([[xa, 2, 3], [4, 5, 6]])
print a
print a.astype(complex)
#can't apply dtype = complex to an array with two elements
xb = np.asarray([1, 2])
b = np.asarray([[xb, 2, 3], [4, 5, 6]])
print b
print b.astype(complex)
Idk, what you were trying to achieve with your energies function, so I can only speculate, what you were aiming at, when constructing the h array. Maybe a 3D array like this?
kpt = np.asarray([1, 2, 3])
h = np.zeros(16 * len(kpt), dtype = complex).reshape(len(kpt), 4, 4)
h[:, 0, 0] = 2 * kpt + 1
h[:, 0, 1] = kpt ** 2
h[:, 3, 2] = np.sin(kpt)
print h

How can I subtract an array of values in a MongoDB query?

I have a collection of documents, where one of the fields is an array of 64 numbers. I would like to construct a query that returns these documents, where this array has been subtracted and summed, however, I cannot figure out how to do even the subtraction portion of this task.
An example document might look like this.
{
"_id" : ObjectId("577be558033ad33f66684974"),
"syntactic_fingerprint" : [
0.921382546424866,
0.048630952835083,
-0.251873761415482,
-0.0470362603664398,
0.0,
0.0296048410236835,
0.0319229736924171,
-0.0332595892250538,
-0.0694081708788872,
-0.117949850857258,
-0.0555221512913704,
-0.176394507288933,
0.0160530339926481,
-0.0234932824969292,
-0.0148191852495074,
0.0816841721534729,
0.0323052480816841,
0.0,
0.0,
0.0142431678250432,
0.0,
0.0,
0.0189650449901819,
0.0386682450771332,
0.0308650359511375,
0.0,
0.0310780759900808,
0.0361337624490261,
0.0,
0.0,
0.0,
0.0128832636401057,
-0.0125190699473023,
0.0,
-0.0282401368021965,
-0.0348126254975796,
-0.0154333971440792,
-0.0173368379473686,
-0.0443549081683159,
-0.0181444175541401,
-0.0224117543548346,
0.0,
-0.0689809918403625,
0.0,
-0.0300765186548233,
0.0,
0.0,
-0.0184972882270813,
0.0,
0.0,
0.0,
-0.0128712980076671,
0.0,
0.0,
0.0183296073228121,
-0.017868610098958,
0.0,
0.0,
-0.0145018044859171,
0.0134829748421907,
-0.0138665018603206,
0.0,
0.0,
0.0
]
}
I am trying to construct a query that will take one of the 64 element "syntactic_fingerprint" vectors (as a constant), and subtract it from the fingerprint of every other document, then sum the values of the subtracted fingerprints into a single number.
This seems like it ought to be possible somehow with the aggregate pipeline... but I can't seem to find an elegant way to do it.
You will indeed need to use an aggregation pipeline to do this. It should be relatively simple, you just need to $unwind the array, which will create a document for each element in the array for the next stage in the pipeline. You can then group that down into a single result and accumulate the sum of values in the document, as well as subtracting your constant from each element.
Example(mongoshell js):
db.myCollection.aggregate([
{
$match: {syntactic_fingerprint: myConstant}
},
{
$unwind: '$syntactic_fingerprint'
},
{
$group: {
_id: null,
sum: {$sum: {$subtract: ['$syntactic_fingerprint', myConstant]}}
}
}
]);
Grouping with an _id of null means it will accumulate into a single object.
Documentation:
$subtract
$sum
$group
$unwind
If the arithmetic operations are calculated between two select documents, there might be a way to aggregate what you need. However, given that you mention you will query with the array [1, 4, 1, 1], I think it is unlikely for it to be possible without some javascript/application level query. I have a crude way of doing it, but it'll return you an array instead of a document.
//input would be from query, output would be the result, of course.
var input = [1,4,1,1];
var output = [];
var count = 0;
//unwind the fingerprints
db.fingerprint.aggregate([
{$unwind : "$fingerPrint" }
]).forEach(function(doc){
id = doc._id.valueOf();
output.push(doc.fingerPrint - input[count]);
count++;
})
print(output);
Using sample from your discussion above, the result from this would be [1, 0, 0 1]
If you are going to do the arithmetic using two documents however, I might be able to aggregate them using query.

Resources