Imagine I have a numpy array in python that has complex numbers as its elements.
I would like to know if it is possible to split any matrix of this kind into a hermitian and anti-hermitian part? My intuition says that this is possible, similar to the fact that any function can be split into an even and an uneven part.
If this is indeed possible, how would you do this in python? So, I'm looking for a function that takes as input any matrix with complex elements and gives a hermitian and non-hermitian matrix as output such that the sum of the two outputs is the input.
(I'm working with python 3 in Jupyter Notebook).
The Hermitian part is (A + A.T.conj())/2, the anti-hermitian part is (A - A.T.conj())/2 (it is quite easy to prove).
If A = B + C with B Hermitian and C anti-Hermitian, you can take the conjugate (I'll denote it *) on both sides, uses its linearity and obtain A* = B - C, from which the values of B and C follow easily.
Related
Python and coding beginner here. I started learning python a couple of days ago, no prior coding experience, and I've started learning about functions. Since python is really useful for mathematical operations, I'm trying to tie this with what I'm learning in my linear algebra class. So here's the question. Beware a lot of reading ahead!
I'm trying to multiply two random matrices using python, without numpy (otherwise I can use numpy.dot and numpy.matrix). If we have 2 matrices X and Y, of dimensions axb and bxc respectively, matrix multiplication only works if the columns of X and the rows of Y are equal. In order to write a program that can do the matrix multiplication, here's what I tried.
First I defined my function as def mat.mul(A,B), with dimensions axb and bxc respectively. I then have the matrix Z as the product of the matrix A and B, which will be empty, Z = []. Here's where my thought process is a bit wobbly. I think that first I need a for loop that iterates through the columns of A, for a in range(0, len(A)):, followed by another for loop that iterates through the rows of A, for b in range(len(0, X[0])) , followed by another for loop to iterate through the columns of B, for c in range(0, len(Y)) and finally a last for loop that iterates through the rows of Y, for d in range(0, len(Y[0])). Now I should have the product matrix Z but I'm not how I should write it. Would it be Z += X[i] * Y[d]?
Sorry for the long explanation, I just thought I'd share my thought process as well.
My goal in a nutshell:
Given an 8x8 matrix C I have an algorithm which constructs another 8x8 matrix L=L(C) in physically relevant way, wherein each entry of L is given by a particular (possibly irrational) linear combination of up to 8 entries of C. I want to find a particular choice of C which is positive semidefinite and has large rank (7 or 8) but gives rise to a singular L.
Facts:
Every positive semidefinite C can be written as C=U*U for some U (where U* denotes the complex conjugate transpose of U).
In this case ker U=ker C, and so the rank of U and C are the same.
If U has a nonsingular 7x7 principle submatrix, then the rank of U is at least 7.
Naive solution:
Declare U as an 8x8 matrix of symbols and create C=U*U. This guarantees C is positive semidefinite.
Define V to be the upper-left 7x7 principle submatrix of U. Note if V is nonsingular the rank of C is at least 7.
Compute L from C.
Try to solve([ det(V)~=0, det(L)==0 ], [vars]), where vars=entries of U.
The difficulty:
One immediate problem is that not every choice of U which is rank 7 or 8 will have V nonsingular, so the matrix C I'm seeking might be missed in this regime. Ignoring this here, my issue for this forum is more to the complexity of the problem:
By setting C=U*U and using the entries of U as the variables, each entry of C becomes a sum of 8 terms, each degree 2. E.g., the c21 entry is given by
u11*conj(u12) + u21*conj(u22) + u31*conj(u32) + u41*conj(u42) + u51*conj(u52) + u61*conj(u62) + u71*conj(u72) + u81*conj(u82)
Since each entry of L is a linear combination of between 2 and 8 entries of C, we have that each entry of L is a linear combination of between 2*8=16 and 8*8=64 degree 2 terms from the entries of U (or U*). Thus det(L) is a uniform degree 2*8=16 polynomial with between 8!*16^8≈10^14 and 8!*64^8≈10^19 terms before simplification. I need this polynomial to be zero while simultaneously det(V) is nonzero (a uniform degree 7 polynomial with 7!=5040 terms).
Note that if one were to avoid using C=U*U and instead let the entries of C be the variables, then det(L) would be a uniform degree 8 polynomial with between 8!*2^8≈10^7 and 8!*8^8≈10^11 terms before simplification. I would need this polynomial to be zero while simultaneously det(V) is nonzero and some extra conditions are placed so that C is positive semidefinite (Sylvester's Criterion, etc).
My question:
Is there a smarter way to do this? Certainly the determinant is not the most efficient way to determine if L is singular, but ideally I would like an exact answer for C, rather then a numerical approximation.
I am most familiar with Matlab, but any suggestions using any system (Python, Macaulay2, ...) would be greatly appreciated. For computing power, I have access to several supercomputer clusters.
Edits:
Perhaps a bit lofty a question. More digestible sub-questions:
Is there a computationally easier, ideally symbolic, algorithm for determining if a matrix is singular (opposed to computing the determinant)?
Is there a computationally easier way of demanding the answer be positive semidefinite (opposed to setting C=U*U and using the entries of U as the variables)?
Is there a less restrictive (but still computationally easy) way to demand that C has rank 7 or 8?
Assume we have a function with unknown formula, given few inputs and results of this function, how can we get the function's formula.
For example we have inputs x and y and result r in format (x,y,r)
[ (2,4,8) , (3,6,18) ]
And the desired function can be
f(x,y) = x * y
As you post the question, the problem is too generic. If you want to find any formula mapping the given inputs to the given result, there are simply too many possible formulas. In order to make sense of this, you need to somehow restrict the set of functions to consider. For example you could say that you're only interested in polynomial solutions, i.e. where
r = sum a_ij * x^i * y^j for i from 0 to n and j from 0 to n - i
then you have a system of equations, with the a_ij as parameters to solve for. The higher the degree n the more such parameters you'd have to find, so the more input-output combinations you'd need to know. Variations of this use rational functions (so you divide by another polynomial), or allow some trigonometric functions, or something like that.
If your setup were particularly easy, you'd have just linear equations, i.e. r = a*x + b*y + c. As you can see, even that has three parameters a,b,c so you can't uniquely find all three of them just given the two inputs you provided in your question. And even then the result would not be the r = x*y you were aiming for, since that's technically of degree 2.
If you want to point out that r = x*y is a particularly simple formula, and you would like to look for simple formulas, then one approach would be enumerating formulas in order of increasing complexity. But if you do this without parameters (since ugly parameters will make a simple formula like a*x + b*y + c appear complex), then it's hard to guilde this enumeration towards the one you want, so you'd really have to enumerate all possible formulas, which will become infeasible very quickly.
I have a matrix-form data stored in a CSV file, and it looks like this,
I want to make this 6 * 6 matrix be a symmetric matrix, like this,
How to use python (or matlab) to change an n by n matrix (square matrix) to a symmetric matrix? Or are there other tools can do this?
Please give me any suggestion, thank you!
In MATLAB, for an upper-triangular matrix A you can write
>> B = A' + triu(A,1)
where triu(A,1) extract the upper-triangular part without the diagonal - you do not want that to be doubled.
I have this line of code in MATLAB, written by someone else:
c=a.'/b
I need to translate it into Python. a, b, and c are all arrays. The dimensions that I am currently using to test the code are:
a: 18x1,
b: 25x18,
which gives me c with dimensions 1x25.
The arrays are not square, but I would not want the code to fail if they were. Can someone explain exactly what this line is doing (mathematically), and how to do it in Python? (i.e., the equivalent for the built-in mrdivide function in MATLAB if it exists in Python?)
The line
c = a.' / b
computes the solution of the equation c b = aT for c. Numpy does not have an operator that does this directly. Instead you should solve bT cT = a for cT and transpose the result:
c = numpy.linalg.lstsq(b.T, a.T)[0].T
The symbol / is the matrix right division operator in MATLAB, which calls the mrdivide function. From the documentation, matrix right division is related to matrix left division in the following way:
B/A = (A'\B')'
If A is a square matrix, B/A is roughly equal to B*inv(A) (although it's computed in a different, more robust way). Otherwise, x = B/A is the solution in the least squares sense to the under- or over-determined system of equations x*A = B. More detail about the algorithms used for solving the system of equations is given here. Typically packages like LAPACK or BLAS are used under the hood.
The NumPy package for Python contains a routine lstsq for computing the least-squares solution to a system of equations. This routine will likely give you comparable results to using the mrdivide function in MATLAB, but it is unlikely to be exact. Any differences in the underlying algorithms used by each function will likely result in answers that differ slightly from one another (i.e. one may return a value of 1.0, whereas the other may return a value of 0.999). The relative size of this error could end up being larger, depending heavily on the specific system of equations you are solving.
To use lstsq, you may have to adjust your problem slightly. It appears that you want to solve an equation of the form cB = a, where B is 25-by-18, a is 1-by-18, and c is 1-by-25. Applying a transpose to both sides gives you the equation BTcT = aT, which is a more standard form (i.e. Ax = b). The arguments to lstsq should be (in this order) BT (an 18-by-25 array) and aT (an 18-element array). lstsq should return a 25-element array (cT).
Note: while NumPy doesn't make any distinction between a 1-by-N or N-by-1 array, MATLAB certainly does, and will yell at you if you don't use the proper one.
In Matlab, A.' means transposing the A matrix. So mathematically, what is achieved in the code is AT/B.
How to go about implementing matrix division in Python (or any language) (Note: Let's go over a simple division of the form A/B; for your example you would need to do AT first and then AT/B next, and it's pretty easy to do the transpose operation in Python |left-as-an-exercise :)|)
You have a matrix equation
C*B=A (You want to find C as A/B)
RIGHT DIVISION (/) is as follows:
C*(B*BT)=A*BT
You then isolate C by inverting (B*BT)
i.e.,
C = A*BT*(B*BT)' ----- [1]
Therefore, to implement matrix division in Python (or any language), get the following three methods.
Matrix multiplication
Matrix transpose
Matrix inverse
Then apply them iteratively to achieve division as in [1].
Only, you need to do AT/B, therefore your final operation after implementing the three basic methods should be:
AT*BT*(B*BT)'
Note: Don't forget the basic rules of operator precedence :)
You can also approach this using the pseudo-inverse of B then post multiplying that result with A. Try using numpy.linalg.pinv then combine this with matrix multiplication via numpy.dot:
c = numpy.dot(a, numpy.linalg.pinv(b))
[edited] As Suvesh pointed out, i was completely wrong before. however, numpy can still easily do the procedure he gives in his post:
A = numpy.matrix(numpy.random.random((18, 1))) # as noted by others, your dimensions are off
B = numpy.matrix(numpy.random.random((25, 18)))
C = A.T * B.T * (B * B.T).I