Maple, writing a Proc to caculate inverse of a Matrix - matrix

so i am working on a Problem which has two parts. I did finish part one with help of :this useful Forum. Some body already tried to do the first part of the problem and i took their code.
To the Problem:
Write a proc ( here i named it "reduced" ) in Maple that calculates reduced Echelon Form of a Matrix.
Write a proc that uses "reduced" to calculate the inverse of a Matrix.
The Code to the first Part ( the Code is tested and i claim that it runs correctly)
multiplikation:= proc(
m::posint,
a::depends(And(posint, satisfies(a-> a <= m))),
b::And({float, rational}, Not(identical(0,0.)))
)
Matrix((m,m), (i,j)-> `if`(i=j, `if`(i=a, b, 1), 0))
end proc:
addition:= proc(
m::posint,
a::depends(And(posint, satisfies(a-> a <= m))),
b::depends(And(posint, satisfies(b-> b <= m))),
c::And({float, rational}, Not(identical(0,0.)))
)
Matrix((m,m), (i,j)-> `if`(i=a and j=b, c, `if`(i=j, 1, 0)))
end proc:
perm:= proc(
m::posint,
a::depends(And(posint, satisfies(a-> a <= m))),
b::depends(And(posint, satisfies(b-> b <= m and a<>b)))
)
Matrix((m,m), (i,j)-> `if`({i,j}={a,b} or i=j and not i in {a,b}, 1, 0))
end proc:
and the main proc :
reduced:= proc(B::Matrix)
uses LA= LinearAlgebra;
local
M:= B, l:= 1, #l is current column.
m:= LA:-RowDimension(M), n:= LA:-ColumnDimension(M), i, j
;
for i to m do #going through every row item
#l needs to be less than column number n.
if n < l then return M end if;
j:= i; #Initialize current row number.
while M[j,l]=0 do #Search for 1st row item <> 0.
j:= j+1;
if m < j then #End of row: Go to next column.
j:= i;
l:= l+1;
if n < l then return M fi #end of column and row
end if
end do;
if j<>i then M:= perm(m,j,i).M end if; #Permute rows j and i
#Multiply row i with 1/M[i,l], if it's not 0.
if M[i,l] <> 0 then M:= multiplikation(m,i,1/M[i,l]).M fi;
#Subtract each row j with row i for M[j,l]-times.
for j to m do if j<>i then M:= addition(m,j,i,-M[j,l]).M fi od;
l:= l+1 #Increase l by 1; next iteration i increase either.
end do;
return M
end proc:
If you need any additional Information about the Code above, i will explain more.
for the second part i am thinking to use the Gauss Jordan Algorithmus but i have a problem:
i cannot use the identity matrix as a parameter in "reduced". because it has 0 in rows and columns.
Do you have any idea how i could implement the Gauss Jordan Algorithmus with the Help of my proc : reduced ?

The stated goal was to utilize the reduced procedure.
One way to do that is to augment the input Matrix by the identity Matrix, reduce that, and then return the right half the augmented Matrix.
The steps that transform the input Matrix into the identity Matrix also transform the identity Matrix into the inverse (of the input Matrix).
For example, using your procdures,
inv := proc(B::Matrix(square))
local augmented,m;
uses LinearAlgebra;
m := RowDimension(B);
augmented := <<B|IdentityMatrix(m)>>;
return reduced(augmented)[..,m+1..-1];
end proc:
MM := LinearAlgebra:-RandomMatrix(3,generator=1..5);
[1 4 2]
[ ]
MM := [1 5 3]
[ ]
[2 3 5]
ans := inv(MM);
[ 8 -7 1]
[ - -- -]
[ 3 3 3]
[ ]
[ 1 1 -1]
ans := [ - - --]
[ 6 6 6 ]
[ ]
[-7 5 1]
[-- - -]
[6 6 6]
ans.MM, MM.ans;
[1 0 0] [1 0 0]
[ ] [ ]
[0 1 0], [0 1 0]
[ ] [ ]
[0 0 1] [0 0 1]
ps. You might want to also consider what your reduce prodedure does when the Matrix is not invertible.

Related

How can I compute determinant of n order where n is a variable with mathematica or maple or maxima?

For example, an n*n matrix
A_n=[2 1 1 ... 1]
[1 2 1 ... 1]
[... ...]
[1 1 1 ... 2]
has determinant n+1. Can I compute this result by these softwares?
This
f[n_]:=Det[Table[1,{n},{n}]+IdentityMatrix[n]];
f[12]
returns 13 and seems to work for any modest sized matrix.
Since Maple may not easily provide a structure representing an abstract Vector or Matrix of indeterminate size you might try to recast the problem in terms of some known properties of determinants.
For example, using Sylvester's determinant theorem you could take utilize the nx1 Matrix V(n) having all entries being identically 1.
So det(A(n)) = det(Id(n) + V(n).transpose(V(n))) = 1 + det(transpose(V(n)).V(n)) = 1 + add(i,i=1..n) = 1 + n
Another way might be to consider a minor expansion along the nth row. When the nth row and nth column are removed from the initial Matrix denoted by A(n) then you obtain A(n-1). Removing the nth row and the jth column (j in 1..n-1) produces a Matrix with determinant (-1)^j. I do not show that here. But perhaps note that any of those minors are a single row-exchange away from a (n-1)x(n-1) Matrix with A(n-2) in the upper left and 1's elsewhere.
In consequence Q(n) the determinant of A(n) is given by Q(n)=2*Q(n-1)-(n-1) I believe. And Q(1)=2. Using Maple's rsolve command,
rsolve({Q(n)=2*Q(n-1)-(n-1), Q(1)=2}, Q(n));
n + 1
Another approach might be to consider row-reduction along rows 2..n. You should be able to produce a new Matrix (having the same determinant) whose diagonal entries are: 2, (i+1)/i, i=2..n. The determinant is thus a conveniently telescoping product.
simplify( 2*product((i+1)/i, i=2..n) );
n + 1
Of course it is easy enough to deal with such Matrices for size n taken at a specific value,
H:=n->1+Matrix(n,n,1):
with(LinearAlgebra):
seq(Determinant(H(i)),i=1..5);
2, 3, 4, 5, 6
U7:=LUDecomposition(H(6),output=U);
[2 1 1 1 1 1]
[ ]
[ 3 1 1 1 1]
[0 - - - - -]
[ 2 2 2 2 2]
[ ]
[ 4 1 1 1]
[0 0 - - - -]
[ 3 3 3 3]
[ ]
U7 := [ 5 1 1]
[0 0 0 - - -]
[ 4 4 4]
[ ]
[ 6 1]
[0 0 0 0 - -]
[ 5 5]
[ ]
[ 7]
[0 0 0 0 0 -]
[ 6]
# The product of the main diagonalentries telescopes.
mul(U7[i,i],i=1..6);
7

Matching between two series after manipulation

Suppose, we're given two series of integer numbers as X[..] And Y[..], which
has the same length. We can choose any position i of the series X[] and
doing the operation like , X[i]=X[i] + 3, X[i + 2] = X[i + 2] + 2 , X[i + 4] = X[i + 4] + 1.
After manipulating the series with any number of time, is it possible to
find the same series like Y[..]?
I am thinking to implement it by brute force and normal combinational matching after manipulation. Is there any other process which can make it faster?
Given two series,
X [ 1, 2, 3 ,4, 5 ,6,8 ]
Y [ 1, 5, 6 ,6, 7 ,7,9 ]
if i=2 then
X [ 1, 5, 3 ,6, 5 ,7,8 ]
Y [ 1, 5, 6 ,6, 7 ,7,9 ]
and if i=3 then
X [ 1, 5, 6 ,6, 7 ,7,9 ]
Y [ 1, 5, 6 ,6, 7 ,7,9 ]
Matches the series.
You can see that for every index p resulting cell could be represented as
Y[p] = X[p] + F(p-4) + 2 * F(p-2) + 3 * F[p]
where F[p] is number of operation at p-th index.
So you have system of p linear equations for p unknowns Fi.
This is tridiagonal (sparse) system, it could be solved with some fast methods or with usual Gaussian elimination.
System might be inconsistent - in this case there are no solutions
Since an operation at index i modifies only elements present at index i, i + 2 and i + 4, that is, all indices >= i, we can build a greedy algorithm which iterates over the array X from left-to-right and at every index i compares the value with array Y.
Case X[i] > Y[i]: Then it's not possible to update X[i] to Y[i], hence return not possible.
Case X[i] == Y[i]: Then continue iterating over the next element at i + 1
Case X[i] < Y[i]: If (Y[i] - X[i]) mod 3 != 0, then return not possible, else compute m = (Y[i] - X[i])/3 and increment X[i] by 3 * m, X[i + 2] by 2 * m and X[i + 4] by m and continue iterating.
If we reach the end of array X, then it means it's possible to construct array Y from X using these operations.
Overall time complexity of the solution is O(n).

Compressed Sparse Row (CSR): How do you store empty rows?

How do you represent empty rows in CSR?
Suppose we have the following matrices:
* MATRIX 1 *
a 0 0
0 b 0
0 0 c
val = [ a b c ]
col = [ 0 1 2 ]
row = [ 0 1 2 ] <- makes sense!
—————————————————————
* MATRIX 2 *
a b c
0 0 0
0 0 0
val = [ a b c ]
col = [ 0 1 2 ]
row = [ 0 ] <— makes sense…? but how about…
—————————————————————
* MATRIX 3 *
0 0 0
a b c
0 0 0
val = [ a b c ]
col = [ 0 1 2 ]
row = [ 0 ] <— wait… how do we differentiate between MATRIX 2 and MATRIX 3?
MATRIX 1 is intuitive, but how do we represent the difference between MATRIX 2 and MATRIX 3? Do we use a negative integer for spacing?
Thanks
Take a look at The Wikipedia page. The IA vector (or as you call it "row"), is defined as:
The array IA is of length m + 1. It is defined by this recursive definition:
IA[0] = 0
IA[i] = IA[i − 1] + (number of nonzero elements on the (i − 1)-th row in the original matrix)
Thus, the first m elements of IA store the index into A of the first nonzero element in each row of M [ ed: but only for rows that have at least one such element, i.e. IA[i+1]>IA[i] ], and the last element IA[m] stores NNZ, the number of elements in A, which can be also thought of as the index in A of first element of a phantom row just beyond the end of the matrix M. The values of the i-th row of the original matrix is read from the elements A[IA[i]] to A[IA[i + 1] − 1] (inclusive on both ends), i.e. from the start of one row to the last index just before the start of the next.
Thus, in Matrix 1:
row = [0 1 2 3]
in Matrix 2:
row = [0 3 3 3]
in Matrix 3
row = [0 0 3 3]
The answer provided is close to being a great explanation but needs to be clarified a bit:
The first two bullet points give a clear prescription for the entries in IA.
But the next part,
"Thus, the first m elements of IA store the index into A of the first nonzero element in each row of M, and the last element IA[m] stores NNZ, the number of elements in A, which can be also thought of as the index in A of first element of a phantom row just beyond the end of the matrix M. The values of the i-th row of the original matrix is read from the elements A[IA[i]] to A[IA[i + 1] − 1]
(inclusive on both ends), i.e. from the start of one row to the last index just before the start of the next."
It is difficult to parse, because the references "IA", "m", "NNZ", "M", and "A" are not defined.
Is the length of "IA" equal to one plus the number of nonzero elements in the full matrix?. I think that "A" and "M" refer to the full matrix and the sparse matrix, but there isn't enough information to determine which is which. "NNZ" may refer to the number of nonzero elements in the full matrix. And "m" may be the same as "NNZ".
Would you mind completing the explanation by providing the definitions of "IA", "m", "NNZ", "M" and "A"?
Thanks in advance, it would be much appreciated!

Gaussian elimination for lower triangular matrix

I have got a a trouble with Gaussian elimination for lower triangular matrix, I can't imagine how the loops should work right here. I tried to run loop backwards, but it didn't help. For now all I've got is Gaussian elimination for upper triangular matrix.
For[k = 1, k <= size - 1, k++,
For[i = k + 1, i <= size, i++,
If[tab[[k]][[k]] != 0,
help = tab[[i]][[k]]/tab[[k]][[k]];
For[j = k, j <= size, j++,
tab[[i]][[j]] = tab[[i]][[j]] - help*tab[[k]][[j]];
identity[[i]][[j]] = identity[[i]][[j]] - help*tab[[k]][[j]]
]
]
]
]
Can someone help me please?
#edit
I made loops like that
For[k = size, k > 1, k--,
For[i = k - 1, i >= 1, i--,
And it seems like it works, but now I've got a problem, because these two loops doesn't give invertible matrix.
Example Matrix:
[ 3 4 2 ]
[ 5 5 5 ]
[ 1 5 3 ]
Output for upper-diagonal
[3 4 2 ]
[0 -5/3 5/3 ]
[0 0 6 ]
Output for Identity-Matrix
[1 0 0 ]
[-5 -17/3 -10/3 ]
[-1 -5 -4 ]
And now, when I run loop for lower-diagonal, the output for it is not correct. It doesn't divide the main diagonal
Well, actually I found the problem, but I don't know how could I solve that - upper-triangular-matrix-loop works fine, but the problem is with lower triangular one, it doesn't divide elements on diagonal.

Filter some rows from a matrix

Suppose I have this matrix:
matrix = [2 2; 2 3; 3 4; 4 5]
And now I'd like to filter out all rows which do not begin with an even number to produce
[2 2; 2 3; 4 5]
Is there a high-level procedure for doing this, or do I have to code for it?
You can get a logical index for the rows whose first element is even, and use : to select all the columns. Here's how it's done, line by line:
octave> matrix = [2 2; 2 3; 3 4; 4 5]
matrix =
2 2
2 3
3 4
4 5
octave> ! mod (matrix(:,1), 2)
ans =
1
1
0
1
octave> matrix(! mod (matrix(:,1), 2),:)
ans =
2 2
2 3
4 5
EDIT: in the comments below it was asked for other selection methods. I'm unaware of any specific function for it, but the thing above is indexing with a function:
even_rows = matrix(! mod (matrix(:,1), 2), :) # first element is even
s3_rows = matrix(matrix(:,1) == 3, :); # first element is 3
int_rows = matrix(fix (matrix(:,1)), == matrix(:,1), :); # first element is an integer
IF there was a function, one would still have to write the function, it wouldn't be any easier shorter or easier to read. But if you want to write a function, you could:
function selec = select_rows (func, mt)
selec = mt(func (mt(:,1)),:);
endfunction
even_rows = select_rows (#(x) ! mod (x, 2), matrix);
se_rows = select_rows (#(x) x == 3, matrix);
int_rows = select_rows (#(x) fix (x) == x, matrix);
EDIT2: to have the rows that have already matched, simply keep track of them on the mask. Example:
mask = ! mod (matrix(:,1), 2); # mask for even numbers
even = matrix(mask,:);
mask = ! mask & matrix(:,1) == 3; # mask for left overs starting with a 3
s3 = matrix(mask,:);
rest = matrix(! mask, :); # get the leftovers
As above, you could write a function that does it. It would take a matrix as the first argument plus any number of function handles. It would iterate over the function handles modifying the mask everytime and filling a cell array with the matrices.

Resources