Fortran- Inverse Matrix result not same if Decimal is longer - matrix

My real data is first input but inverse of result is so big. They are same data when you compare with first and second input. There is only difference decimal size. Why is there different result? Because they are same data. How can they have different result? You can see result and input. It is so strange.
program test
Implicit none
double precision,allocatable,dimension(:,:) :: A
double precision,allocatable,dimension(:) :: WORK
integer ,allocatable,dimension(:) :: ipiv
integer :: n,info,M
external DGETRF,DGETRI
M=8
allocate(A(M,M),WORK(M),IPIV(M))
!!! First Input !!!!
A(1,:)=(/3.740486048842566D-4, 0.0D0, 0.0D0, 4.987315029057229D-5, 0.0D0, 0.0D0, 0.0D0, 0.0D0/)
A(2,:)=(/0.0D0 , 3.740486048842566D-4, 0.0D0, 0.0D0, 4.987315029057229D-5 ,0.0D0 ,0.0D0 ,0.0D0 /)
A(3,:)=(/0.0D0 , 0.0D0 ,3.740486048842566D-4, 0.0D0 ,0.0D0, 4.987315029057229D-5, 0.0D0 ,0.0D0/)
A(4,:)=(/4.987315029057229D-5 ,0.0D0 ,0.0D0 ,6.649753768432517D-6, 0.0D0 ,0.0D0, 0.0D0, 0.0D0 /)
A(5,:)=(/0.0D0 , 4.987315029057229D-5, 0.0D0, 0.0D0 ,6.649753768432517D-6 ,0.0D0 ,0.0D0 ,0.0D0 /)
A(6,:)=(/0.0D0, 0.0D0, 4.987315029057229D-5, 0.0D0 ,0.0D0, 6.649753768432517D-6, 0.0D0 ,0.0D0 /)
A(7,:)=(/0.0D0, 0.0D0 ,0.0D0, 0.0D0 ,0.0D0 ,0.0D0 ,1.499999910593033D-11, 0.0D0 /)
A(8,:)=(/0.0D0 ,0.0D0 ,0.0D0 ,0.0D0 ,0.0D0 ,0.0D0, 0.0D0 ,1.499999910593033D-11 /)
!!!! Second Input !!!!
!A(1,:)=(/3.74D-4, 0.0D0, 0.0D0, 4.98D-5, 0.0D0, 0.0D0, 0.0D0, 0.0D0/)
!A(2,:)=(/0.0D0 , 3.74D-4, 0.0D0, 0.0D0, 4.98D-5 ,0.0D0 ,0.0D0 ,0.0D0 /)
!A(3,:)=(/0.0D0 , 0.0D0 ,3.74D-4, 0.0D0 ,0.0D0, 4.98D-5, 0.0D0 ,0.0D0/)
!A(4,:)=(/4.98D-5 ,0.0D0 ,0.0D0 ,6.64D-6, 0.0D0 ,0.0D0, 0.0D0, 0.0D0 /)
!A(5,:)=(/0.0D0 , 4.98D-5, 0.0D0, 0.0D0 ,6.64D-6 ,0.0D0 ,0.0D0 ,0.0D0 /)
!A(6,:)=(/0.0D0, 0.0D0, 4.98D-5, 0.0D0 ,0.0D0, 6.64D-6, 0.0D0 ,0.0D0 /)
!A(7,:)=(/0.0D0, 0.0D0 ,0.0D0, 0.0D0 ,0.0D0 ,0.0D0 ,1.49D-11, 0.0D0 /)
!A(8,:)=(/0.0D0 ,0.0D0 ,0.0D0 ,0.0D0 ,0.0D0 ,0.0D0, 0.0D0 ,1.49D-11 /)
call DGETRF(M,M,A,M,IPIV,info)
if(info .eq. 0) then
Print *,'succeded'
else
Print *,'failed'
end if
call DGETRI(M,A,M,IPIV,WORK,M,info)
if(info .eq. 0) then
Print *,'succeded'
else
Print *,'failed'
end if
Print *,A
deallocate(A,IPIV,WORK)
end
!!!!! Second Input Result
!1.0e+10 *
! 0.0002 0 0 -0.0015 0 0 0 0
! 0 0.0002 0 0 -0.0015 0 0 0
! 0 0 0.0002 0 0 -0.0015 0 0
! -0.0015 0 0 0.0113 0 0 0 0
! 0 -0.0015 0 0 0.0113 0 0 0
! 0 0 -0.0015 0 0 0.0113 0 0
! 0 0 0 0 0 0 6.7114 0
! 0 0 0 0 0 0 0 6.7114
!!! First Input Result
! 1.0e+21 *
!-0.0238 0 0 0.1783 0 0 0 0
! 0 -0.0238 0 0 0.1783 0 0 0
! 0 0 0.0000 0 0 -0.0000 0 0
! 0.1783 0 0 -1.3375 0 0 0 0
! 0 0.1783 0 0 -1.3375 0 0 0
! 0 0 -0.0000 0 0 0.0000 0 0
! 0 0 0 0 0 0 0.0000 0
! 0 0 0 0 0 0 0 0.0000

Creating a matrix inverse is not a difficult problem.
I converted your earlier example to using a simple approach, based on Gaussian elimination with a shadowed identity matrix, which works well for most cases. The attached program inverts your earlier symmetric matrix, without resorting to pivoting of the rows. It does not need a "black-box".
That you get different results with different coefficients is hardly surprising. With the significant change in results for apparently small changes of input values, shows the sensitivity and possibly poor conditioning of the equation relationship you are using.
https://www.dropbox.com/s/ssotjx45yrz5sf9/dgetri.f90?dl=0
Additional response re "First Input"
https://www.dropbox.com/s/hximfoin977rmov/dgetri_piv4.f90?dl=0
This latest link (16-6) has both data sets included. In "First Input", your equations basically are rows 4:6 are rows 1:3 / 7.5 + small_noise.
This latest code example has accuracy checks both during the matrix inversion and also after. The during test checks the row changes are correct, while the after checks are "A.A^-1 - I" and "A - (A^-1)^-1", which better indicate poor accuracy.
It is interesting that "Second Input" (with more noise) reports a reasonably accurate outcome. Failing to get an inverse with 8-byte reals needs a fairly contrived matrix ! Similarly, the random number derived coefficients examples shows good accuracy.
These examples show that the accuracy tests I have presented don't always identify poorly defined equation relationships. Your inspection of the inverse to identify large variation in values is also useful.
Given the way the equations appear to have been defined, I am not sure what is the outcome you are wanting.

Related

Calculate distance between every point of matrix with each other

I want to calculate the euclidean distance between every element of an n-channeled matrix to every other and then apply the function exp(-dist) to it. My matrix is MxN so the output must be (MxN)x(MxN).
This is my code so far:
MAX=M*N;
A = zeros([MAX,MAX]);
dist= zeros([MAX,MAX]);
for x1=1:MAX
for x2=1:MAX
for i=1:M
for j=1:N
for s=1:M
for z=1:N
%every pixel is a vector rgb
dist(x1,x2) = norm((imIn(i,j)-imIn(s,z)),3);
A(x1,x2) = exp(-dist);
end
end
end
end
end
end
It's really slow and doesn't work - it gives just ones.
I would use bsxfun:
*Note that since the distance is applied to scalar values, I just use abs(a-b). There is no point in call norm(), it's just dead time.
m = 3;
n = 4;
ImIn = rand(m,n)
% first transform to vector
vector = ImIn(:)
% edit: better solution for older versions, see comments
Distances = abs(bsxfun(#minus, vector', vector))
% for latest matlab versions
Distances = abs(vector'- vector)
Ouput:
ImIn =
0.5833 0.9747 0.6369 0.6378
0.4217 0.2235 0.6486 0.4072
0.6525 0.1869 0.2085 0.5017
vector =
0.5833
0.4217
0.6525
0.9747
0.2235
0.1869
0.6369
0.6486
0.2085
0.6378
0.4072
0.5017
Distances =
0 0.1616 0.0693 0.3915 0.3597 0.3964 0.0536 0.0654 0.3747 0.0546 0.1761 0.0816
0.1616 0 0.2308 0.5530 0.1982 0.2348 0.2152 0.2269 0.2132 0.2161 0.0145 0.0800
0.0693 0.2308 0 0.3222 0.4290 0.4656 0.0156 0.0039 0.4440 0.0147 0.2453 0.1508
0.3915 0.5530 0.3222 0 0.7512 0.7879 0.3379 0.3261 0.7662 0.3369 0.5675 0.4731
0.3597 0.1982 0.4290 0.7512 0 0.0366 0.4134 0.4251 0.0150 0.4143 0.1837 0.2782
0.3964 0.2348 0.4656 0.7879 0.0366 0 0.4500 0.4618 0.0217 0.4509 0.2203 0.3148
0.0536 0.2152 0.0156 0.3379 0.4134 0.4500 0 0.0117 0.4284 0.0009 0.2297 0.1352
0.0654 0.2269 0.0039 0.3261 0.4251 0.4618 0.0117 0 0.4401 0.0108 0.2414 0.1469
0.3747 0.2132 0.4440 0.7662 0.0150 0.0217 0.4284 0.4401 0 0.4293 0.1987 0.2932
0.0546 0.2161 0.0147 0.3369 0.4143 0.4509 0.0009 0.0108 0.4293 0 0.2306 0.1361
0.1761 0.0145 0.2453 0.5675 0.1837 0.2203 0.2297 0.2414 0.1987 0.2306 0 0.0945
0.0816 0.0800 0.1508 0.4731 0.2782 0.3148 0.1352 0.1469 0.2932 0.1361 0.0945 0
Check:
>> size(ImIn)
ans =
3 4
>> size(Distances)
ans =
12 12

How to generate a matrix with a function pattern?

Background info (Optional reading):
I'm running simulations of reflections of sound waves in against boundaries. The medium conditions for the points in space are set using a matrix. Let's say the dimensions of the space is an N by N grid, and there are two speeds of sound I care about, c0 and c1.
Right now I'm using code like the following to generate barrier patterns
medium.sound_speed = c0*ones(N,N); % set the speed of sound to be c0 everywhere
medium.sound_speed(:, N/2:N) = c1; % set the right half of the grid to a different speed
medium.sound_speed(50:70, 50:70) = c1; % set a box to have a different speed
Or
% set all speeds to c0 except set the diagonal to c1
medium.sound_speed = c0*ones(N,N)-(c0*eye(N,N))+c1*eye(N,N);
However, I can't generate more complex boundaries with different curvatures.
Question
I want to programmatically create matrices with patterns reflecting functions. For instance, I want to enter f(x)=2 and for that to create a matrix that looked something like this, assuming N=6.
[ 0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
1 1 1 1 1 1
0 0 0 0 0 0
0 0 0 0 0 0 ]
Or f(x)=0.5*x+1
[ 0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 1 1
0 0 1 1 0 0
1 1 0 0 0 0
0 0 0 0 0 0]
I would also be able to generate curved patterns like f(x)=1/x, which seems to require some form of the Midpoint circle algorithm, used for drawing curvatures with pixels.
[ 1 0 0 0 0 0
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 1 0 0
0 0 0 0 1 1
0 0 0 0 0 0 ]
In reality, N is at least 128, so manually creating these matrices for shapes with some level of complexity is impractical, and I thought this was an interesting problem.
Does anyone know of some way to do this, or suggestions for alternative approaches?
Thank you in advance.
Edit:
I modified this implementation of Bresenham's algorithm to provide a matrix with the desired line given an origin and an ending point.
function M=bresenham_line(point)
if (abs(point(4)-point(2)) > abs(point(3)-point(1))) % If the line is steep
x0 = point(2);y0 = point(1); x1 = point(4);y1=point(3);% then it would be converted to
token =1; % non steep by changing coordinate
else
x0 = point(1);y0 = point(2); x1 = point(3);y1=point(4);
token = 0;
end
if(x0 >x1)
temp1 = x0; x0 = x1; x1 = temp1;
temp2 = y0; y0 = y1; y1 = temp2;
end
dx = abs(x1 - x0) ; % Distance to travel in x-direction
dy = abs(y1 - y0); % Distance to travel in y-direction
sx = sign(x1 - x0); % sx indicates direction of travel in X-dir
sy = sign(y1 - y0); % Ensures positive slope line
x = x0; y = y0; % Initialization of line
param = 2*dy - dx ; % Initialization of error parameter
for i = 0:dx-1 % FOR loop to travel along X
x_coord(i+1) = x; % Saving in matrix form for plot
y_coord(i+1) = y;
param = param + 2*dy; % parameter value is modified
if (param >0) % if parameter value is exceeded
y = y +1*sy; % then y coordinate is increased
param = param - 2*(dx ); % and parameter value is decreased
end
x = x + 1*sx; % X-coordinate is increased for next point
end
M = zeros(size(x_coord,2), size(y_coord,2));
for i=1:1:size(x_coord,2)
x = x_coord(i);
y = y_coord(i);
M(x,y) = 1;
end
M
Implemented like so:
c1 = 0;
M = bresenham_line([1 1 Nx/2+1 Ny+1]);
medium.sound_speed = c0*ones(Nx,Ny) - (c0*M) + c1*M;
No progress on curved function shapes yet.
A way to get some similar results:
f = #(x)0.5*x; %create the function (x should be written even if the function doesn't depend on x: #(x) 0*x + 2)
N = 6; %choose the size of the atrix
M = zeros(N,N); %create an empty matrix
x = (1:N);
y = round(f(x-1)); %discretization
x(y>N-1|y<0) = [];
y(y>N-1|y<0) = [];
M(sub2ind(size(M),y+1,x)) = 1;
M = flipud(M)
So you can choose your function, then the result in your matrix will look like a discretization of a normal plot.
This is a slightly 'dirty' way of getting something like this, although I you best bet might Bresenham's algorithm.
N = 128;
[X,Y] = meshgrid(1:N,1:N);
bound1 = Y<2*X;
bound2 = Y<2*X+1;
M = xor(bound1,bound2);
bound1 you can define any function y=f(x), and mark the area under it. with bound2 you select and area that is slightly higher (shifted up). Once you take and xor of the two area you get just the desired y=f(x) marked. I think that in order to get reasonable results the shift might be different for more complicated function.
For illustration I used imagesc (the flipud is just for make the (0,0) in the bottom left, instead of the top left):
imagesc(flipud(M));
Edit
Indeed for some function this might not be the best. For example for y=x^2, you have to increase the shift and still does not look great.
bound1 = Y<X.^2;
bound2 = Y<X.^2+15;
M = xor(bound1,bound2);

Efficiently unpack a vector into binary matrix Octave

On Octave I'm trying to unpack a vector in the format:
y = [ 1
2
4
1
3 ]
I want to return a matrix of dimension ( rows(y) x max value(y) ), where for each row I have a 1 in the column of the original digits value, and a zero everywhere else, i.e. for the example above
y01 = [ 1 0 0 0
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0 ]
so far I have
y01 = zeros( m, num_labels );
for i = 1:m
for j = 1:num_labels
y01(i,j) = (y(i) == j);
end
end
which works, but is going get slow for bigger matrices, and seems inefficient because it is cycling through every single value even though the majority aren't changing.
I found this for R on another thread:
f3 <- function(vec) {
U <- sort(unique(vec))
M <- matrix(0, nrow = length(vec),
ncol = length(U),
dimnames = list(NULL, U))
M[cbind(seq_len(length(vec)), match(vec, U))] <- 1L
M
}
but I don't know R and I'm not sure if/how the solution ports to octave.
Thanks for any suggestions!
Use a sparse matrix (which also saves a lot of memory) which can be used in further calculations as usual:
y = [1; 2; 4; 1; 3]
y01 = sparse (1:rows (y), y, 1)
if you really want a full matrix then use "full":
full (y01)
ans =
1 0 0 0
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0
Sparse is a more efficient way to do this when the matrix is big.
If your dimension of the result is not very high, you can try this:
y = [1; 2; 4; 1; 3]
I = eye(max(y));
y01 = I(y,:)
The result is same as full(sparse(...)).
y01 =
1 0 0 0
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0
% Vector y to Matrix Y
Y = zeros(m, num_labels);
% Loop through each row
for i = 1:m
% Use the value of y as an index; set the value matching index to 1
Y(i,y(i)) = 1;
end
Another possibility is:
y = [1; 2; 4; 1; 3]
classes = unique(y)(:)
num_labels = length(classes)
y01=[1:num_labels] == y
With the following detailed printout:
y =
1
2
4
1
3
classes =
1
2
3
4
num_labels = 4
y01 =
1 0 0 0
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0

Gabor based Texture Segmentation

I am trying to implement a gabor filter for use in textured image segmentation. I am doing this in MATLAB and consulting the concepts from paper - A level set and Gabor-based Active Contour Algorithm for Segmenting Textured Images
I am highlighing the relevant parts below: The 2D gabor function is given as
where
The frequency of the span-limited sinusoidal grating is given by F and its orientation is specified by Theta. Sigma is the scale parameter. This filter is to be used on an image and as the gabor filter consists of an imaginary component, the Gabor transform is obtained as shown below.
where, GR and GI are the real and imaginary parts obtained by convoluting it with an image u0. I need to code this part in MATLAB and generate the Gabor transformed image for the different values of theta, F and sigma
My code
clc;clear all;close all;
sigma=.0075;
m_size=7;
theta=pi/4;
F=60;
[real_g,im_g]=gabor(m_size,sigma,F,theta);
//My Gabor function
function [real_g,im_g] = gabor(m_size,sigma,F,theta)
[x,y]=meshgrid(1:m_size,1:m_size);
real_g = zeros(m_size);
im_g = zeros(m_size);
g_sigma = zeros(m_size);
for i=1:size(x,1)
for j=1:size(y,1)
g_sigma(i,j) = (1./(2*pi*sigma^2)).*exp(((-1).*(i^2+j^2))./(2*sigma^2));
real_g(i,j) = g_sigma(i,j).*cos((2*pi*F).*(i.*cos(theta)+j.*sin(theta)));
im_g(i,j) = g_sigma(i,j).*sin((2*pi*F).*(i.*cos(theta)+j.*sin(theta)));
end
end
My output
>> real_g
real_g =
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
>> im_g
im_g =
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
My gabor filter is completely wrong. Please could you guys help me to construct the correct gabor filter? Please note that the data for the parameters and the formula is taken from the paper I already referred.
Any help will be greatly appreciated. PS If anybody needs the paper I can mail it too. Thanks.
Hopefully the below codes would be of some use to what you are working on.
It demonstrate how to transform an image using your Gabor filter with varying thetas (as shown in the images). Cheers.
% get image
u0=double(imread('cameraman.tif'));
% initialize parameters
sigma = 3;
m_size = 7;
F = 1;
m_size_halfed = round((m_size-1)/2);
% make up some thetas
thetas=0:pi/5:pi;
% loop through all thetas
for i = 1:numel(thetas)
theta = thetas(i);
% setup the "gabor transform"
[x,y]=meshgrid(-m_size_halfed:m_size_halfed,-m_size_halfed:m_size_halfed);
g_sigma = (1./(2*pi*sigma^2)).*exp(((-1).*(x.^2+y.^2))./(2*sigma.^2));
real_g = g_sigma.*cos((2*pi*F).*(x.*cos(theta)+y.*sin(theta)));
im_g = g_sigma.*sin((2*pi*F).*(x.*cos(theta)+y.*sin(theta)));
% perform Gabor transform
u_0sft=sqrt(conv2(u0,real_g,'same').^2+conv2(u0,im_g,'same').^2);
subplot(1,numel(thetas)+1,i+1)
imagesc(u_0sft);
colormap('gray'); axis image; axis off;
title(sprintf('theta:%1.1f',theta));
end
% visualize image
subplot(1,numel(thetas)+1,1)
imagesc(u0);
colormap('gray'); axis image; axis off;
title('original');

Why does diag exhibit inconsistent behavior in octave

Can someone explain what's going on here?
octave:1> t = eye(3)
t =
Diagonal Matrix
1 0 0
0 1 0
0 0 1
octave:2> diag(t(3,:))
ans =
Diagonal Matrix
0 0 0
0 0 0
0 0 1
octave:3> diag(t(2,:))
ans =
Diagonal Matrix
0 0 0
0 1 0
0 0 0
octave:4> diag(t(1,:))
ans = 1
Why do the first two give back 3x3 matrices but the last one is just a number?
The problem arises because of the way t(1,:) was created, from eye(3).
If you output the rows of t individually the results are:
octave.28> t(1,:)
ans =
**Diagonal Matrix**
1 0 0
octave.29> t(2,:)
ans =
0 1 0
octave.30> t(3,:)
ans =
0 0 1
For some reason (I can't explain) t(1,:) is still recognized as a diagonal matrix, while t(2,:) and t(3,:) are vectors. When you call diag(t(:,1)) it is not receiving a vector argument, but rather a matrix. If you convert t(:,1) to vector before evaluation you get the expected result.
octave.31> diag(vec(t(1,:)))
ans =
**Diagonal Matrix**
1 0 0
0 0 0
0 0 0

Resources