Accuracy issues with multiplication of matrices in Matlab R2012b - matlab

I have implemented a script that does constrained optimization for solving the optimal parameters of Support Vector Machines model. I noticed that my script for some reason gives inaccurate results (although very close to the real value). For example the typical situation is that the result of a calculation should be exactly 0, but instead it is something like
-1/18014398509481984 = -5.551115123125783e-17
This situation happens when I multiply matrices with vectors. What makes this also strange is that if I do the multiplications by hand in the command window in Matlab I get exactly 0 result.
Let me give an example: If I take the vectors Aq = [-1 -1 1 1] and x = [12/65 28/65 32/65 8/65]' I get exactly 0 result from their multiplication if I do this in the command window, as you can see in the picture below:
If on the other hand I do this in my function-script I don't get the result being 0 but rather the value -1/18014398509481984.
Here is the part of my script that is responsible for this multiplication (I've added the Aq and x into the script to show the contents of Aq and x as well):
disp('DOT PRODUCT OF ACTIVE SET AND NEW POINT: ')
Aq
x
Aq*x
Here is the result of the code above when run:
As you can see the value isn't exactly 0 even though it really should be. Note that this problem doesn't occur for all possible values of Aq and x. If Aq = [-1 -1 1 1] and x = [4/13 4/13 4/13 4/13] the result is exactly 0 as you can see below:
What is causing this inaccuracy? How can I fix this?
P.S. I didn't include my whole code because it's not very well documented and few hundred lines long, but I will if requested.
Thank you!
UPDATE: new test, by using Ander Biguri's advice:
UPDATE 2: THE CODE
function [weights, alphas, iters] = solveSVM(data, labels, C, e)
% FUNCTION [weights, alphas, iters] = solveSVM(data, labels, C, e)
%
% AUTHOR: jjepsuomi
%
% VERSION: 1.0
%
% DESCRIPTION:
% - This function will attempt to solve the optimal weights for a Support
% Vector Machines (SVM) model using active set method with gradient
% projection.
%
% INPUTS:
% "data" a n-by-m data matrix. The number of rows 'n' corresponds to the
% number of data points and the number of columns 'm' corresponds to the
% number of variables.
% "labels" a 1-by-n row vector of data labels from the set {-1,1}.
% "C" Box costraint upper limit. This will constrain the values of 'alphas'
% to the range 0 <= alphas <= C. If hard-margin SVM model is required set
% C=Inf.
% "e" a real value corresponding to the convergence criterion, that is if
% solution Xi and Xi-1 are within distance 'e' from each other stop the
% learning process, i.e. IF |F(Xi)-F(Xi-1)| < e ==> stop learning process.
%
% OUTPUTS:
% "weights" a vector corresponding to the optimal decision line parameters.
% "alphas" a vector of alpha-values corresponding to the optimal solution
% of the dual optimization problem of SVM.
% "iters" number of iterations until learning stopped.
%
% EXAMPLE USAGE 1:
%
% 'Hard-margin SVM':
%
% data = [0 0;2 2;2 0;3 0];
% labels = [-1 -1 1 1];
% [weights, alphas, iters] = solveSVM(data, labels, Inf, 10^-100)
%
% EXAMPLE USAGE 2:
%
% 'Soft-margin SVM':
%
% data = [0 0;2 2;2 0;3 0];
% labels = [-1 -1 1 1];
% [weights, alphas, iters] = solveSVM(data, labels, 0.8, 10^-100)
% STEP 1: INITIALIZATION OF THE PROBLEM
format long
% Calculate linear kernel matrix
L = kron(labels', labels);
K = data*data';
% Hessian matrix
Qd = L.*K;
% The minimization function
L = #(a) (1/2)*a'*Qd*a - ones(1, length(a))*a;
% Gradient of the minimizable function
gL = #(a) a'*Qd - ones(1, length(a));
% STEP 2: THE LEARNING PROCESS, ACTIVE SET WITH GRADIENT PROJECTION
% Initial feasible solution (required by gradient projection)
x = zeros(length(labels), 1);
iters = 1;
optfound = 0;
while optfound == 0 % criterion met
% Negative of the gradient at initial solution
g = -gL(x);
% Set the active set and projection matrix
Aq = labels; % In plane y^Tx = 0
P = eye(length(x))-Aq'*inv(Aq*Aq')*Aq; % In plane projection
% Values smaller than 'eps' are changed into 0
P(find(abs(P-0) < eps)) = 0;
d = P*g'; % Projection onto plane
if ~isempty(find(x==0 | x==C)) % Constraints active?
acinds = find(x==0 | x==C);
for i = 1:length(acinds)
if (x(acinds(i)) == 0 && d(acinds(i)) < 0) || x(acinds(i)) == C && d(acinds(i)) > 0
% Make the constraint vector
constr = zeros(1,length(x));
constr(acinds(i)) = 1;
Aq = [Aq; constr];
end
end
% Update the projection matrix
P = eye(length(x))-Aq'*inv(Aq*Aq')*Aq; % In plane / box projection
% Values smaller than 'eps' are changed into 0
P(find(abs(P-0) < eps)) = 0;
d = P*g'; % Projection onto plane / border
end
%%%% DISPLAY INFORMATION, THIS PART IS NOT NECESSAY, ONLY FOR DEBUGGING
if Aq*x ~= 0
disp('ACTIVE SET CONSTRAINTS Aq :')
Aq
disp('CURRENT SOLUTION x :')
x
disp('MULTIPLICATION OF Aq and x')
Aq*x
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Values smaller than 'eps' are changed into 0
d(find(abs(d-0) < eps)) = 0;
if ~isempty(find(d~=0)) && rank(P) < length(x) % Line search for optimal lambda
lopt = ((g*d)/(d'*Qd*d));
lmax = inf;
for i = 1:length(x)
if d(i) < 0 && -x(i) ~= 0 && -x(i)/d(i) <= lmax
lmax = -x(i)/d(i);
elseif d(i) > 0 && (C-x(i))/d(i) <= lmax
lmax = (C-x(i))/d(i);
end
end
lambda = max(0, min([lopt, lmax]));
if abs(lambda) < eps
lambda = 0;
end
xo = x;
x = x + lambda*d;
iters = iters + 1;
end
% Check whether search direction is 0-vector or 'e'-criterion met.
if isempty(find(d~=0)) || abs(L(x)-L(xo)) < e
optfound = 1;
end
end
%%% STEP 3: GET THE WEIGHTS
alphas = x;
w = zeros(1, length(data(1,:)));
for i = 1:size(data,1)
w = w + labels(i)*alphas(i)*data(i,:);
end
svinds = find(alphas>0);
svind = svinds(1);
b = 1/labels(svind) - w*data(svind, :)';
%%% STEP 4: OPTIMALITY CHECK, KKT conditions. See KKT-conditions for reference.
weights = [b; w'];
datadim = length(data(1,:));
Q = [zeros(1,datadim+1); zeros(datadim, 1), eye(datadim)];
A = [ones(size(data,1), 1), data];
for i = 1:length(labels)
A(i,:) = A(i,:)*labels(i);
end
LagDuG = Q*weights - A'*alphas;
Ac = A*weights - ones(length(labels),1);
alpA = alphas.*Ac;
LagDuG(any(abs(LagDuG-0) < 10^-14)) = 0;
if ~any(alphas < 0) && all(LagDuG == zeros(datadim+1,1)) && all(abs(Ac) >= 0) && all(abs(alpA) < 10^-6)
disp('Optimal found, Karush-Kuhn-Tucker conditions satisfied.')
else
disp('Optimal not found, Karush-Kuhn-Tucker conditions not satisfied.')
end
% VISUALIZATION FOR 2D-CASE
if size(data, 2) == 2
pinds = find(labels > 0);
ninds = find(labels < 0);
plot(data(pinds, 1), data(pinds, 2), 'o', 'MarkerFaceColor', 'red', 'MarkerEdgeColor', 'black')
hold on
plot(data(ninds, 1), data(ninds, 2), 'o', 'MarkerFaceColor', 'blue', 'MarkerEdgeColor', 'black')
Xb = min(data(:,1))-1;
Xe = max(data(:,1))+1;
Yb = -(b+w(1)*Xb)/w(2);
Ye = -(b+w(1)*Xe)/w(2);
lineh = plot([Xb Xe], [Yb Ye], 'LineWidth', 2);
supvh = plot(data(find(alphas~=0), 1), data(find(alphas~=0), 2), 'g.');
legend([lineh, supvh], 'Decision boundary', 'Support vectors');
hold off
end
NOTE:
If you run the EXAMPLE 1, you should get an output starting with the following:
As you can see, the multiplication between Aq and x don't produce value 0, even though they should. This is not a bad thing in this particular example, but if I have more data points with lots of decimals in them this inaccuracy becomes bigger and bigger problem, because the calculations are not exact. This is bad for example when I'm searching for a new direction vector when I'm moving towards the optimal solution in gradient projection method. The search direction isn't exactly the correct direction, but close to it. This is why I want the exactly correct values...is this possible?
I wonder if the decimals in the data points have something to do with the accuracy of my results. See the picture below:
So the question is: Is this caused by the data or is there something wrong in the optimization procedure...

Do you use format function inside your script? It looks like you used somewhere format rat.
You can always use matlab eps function, that returns precision that is used inside matlab. The absolute value of -1/18014398509481984 is smaller that this, according to my Matlab R2014B:
format long
a = abs(-1/18014398509481984)
b = eps
a < b
This basically means that the result is zero (but matlab stopped calculations because according to eps value, the result was just fine).
Otherwise you can just use format long inside your script before the calculation.
Edit
I see inv function inside your code, try replacing it with \ operator (mldivide). The results from it will be more accurate as it uses Gaussian elimination, without forming the inverse.
The inv documentation states:
In practice, it is seldom necessary to form the explicit inverse of a
matrix. A frequent misuse of inv arises when solving the system of
linear equations Ax = b. One way to solve this is with x = inv(A)*b. A
better way, from both an execution time and numerical accuracy
standpoint, is to use the matrix division operator x = A\b. This
produces the solution using Gaussian elimination, without forming the
inverse.

With the provided code, this is how I tested:
I added a break-point on the following code:
if Aq*x ~= 0
disp('ACTIVE SET CONSTRAINTS Aq :')
Aq
disp('CURRENT SOLUTION x :')
x
disp('MULTIPLICATION OF Aq and x')
Aq*x
end
When the if branch was taken, I typed at console:
K>> format rat; disp(x);
12/65
28/65
32/65
8/65
K>> disp(x == [12/65; 28/65; 32/65; 8/65]);
0
1
0
0
K>> format('long'); disp(max(abs(x - [12/65; 28/65; 32/65; 8/65])));
1.387778780781446e-17
K>> disp(eps(8/65));
1.387778780781446e-17
This suggests that this is a displaying problem: the format rat deliberately uses small integers for expressing the value, on the expense of precision. Apparently, the true value of x(4) is the next one to 8/65 than can be possibly put in double format.
So, this begs the question: are you sure that numeric convergence depends on flipping the least significant bit in a double precision value?

Related

Directional artifacts in MATLAB randn arrays?

I'm generating 3d fractal noise in MATLAB using a variety of methods. It's working relatively well, but I'm having an issue where I see vertical striping artifacts in my noise. This happens regardless of what data type or resolution I use.
Edit: I figured it out. The solution is posted as an answer below. Thanks everyone for your thoughts and guidance!
expo = 2^6;
dims = [expo,expo,expo];
beta = -4.5;
render = randnd(beta, dims); % Create volumetric fractal
render = render - min(render); % Set floor to zero
render = render ./ max(render); % Set ceiling to one
%render = imbinarize(render); % BW Threshold option
render = render .* 255; % For greyscale
slicer = 1; % Turn on image slicer/saver
i = 0; % Page counter
format = '.png';
imagename = '___testDump/slice';
imshow(render(:,:,1),[0 255]); %Single test image
if slicer == 1
for c = 1:length(render)
i = i+1;
pagenumber = num2str(i);
filename = [imagename, pagenumber, format];
imwrite(uint8(render(:,:,i)),filename)
end
end
function X = randnd(beta,varargin)
seed = 999;
rng(seed); % Set seed
%% X = randnd(beta,varargin)
% Based on similar functions by Jon Yearsley and Hristo Zhivomirov
% Written by Marcin Konowalczyk
% Timmel Group # Oxford University
%% Parse the input
narginchk(0,Inf); nargoutchk(0,1);
if nargin < 2 || isempty(beta); beta = 0; end % Default to white noise
assert(isnumeric(beta) && isequal(size(beta),[1 1]),'''beta'' must be a number');
assert(-6 <= beta && beta <= 6,'''beta'' out of range'); % Put on reasonable bounds
%% Generate N-dimensional white noise with 'randn'
X = randn(varargin{:});
if isempty(X); return; end; % Usually happens when size vector contains zeros
% Squeeze prevents an error if X has more than one leading singleton dimension
% This is a slight deviation from the pure functionality of 'randn'
X = squeeze(X);
% Return if white noise is requested
if beta == 0; return; end;
%% Generate corresponding N-dimensional matrix of multipliers
N = size(X);
% Create matrix of multipliers (M) of X in the frequency domain
M = [];
for j = 1:length(N)
n = N(j);
if (rem(n,2)~=0) % if n is odd
% Nyquist frequency bin does not show up in odd-numbered fft
k = ifftshift(-(n-1)/2:(n-1)/2);
else
k = ifftshift(-n/2:n/2-1);
end
% Spectral multipliers
m = (k.^2)';
if isempty(M);
M = m;
else
% Create the permutation vector
M_perm = circshift(1:length(size(M))+1,[0 1]);
% Permute a singleton dimension to the beginning of M
M = permute(M,M_perm);
% Add m along the first dimension of M
M = bsxfun(#plus,M,m);
end
end
% Reverse M to match X (since new dimensions were being added form the left)
M = permute(M,length(size(M)):-1:1);
assert(isequal(size(M),size(X)),'Bad programming error'); % This should never occur
% Shape the amplitude multipliers by beta/4 which corresponds to shaping the power by beta
M = M.^(beta/4);
% Set the DC component to zero
M(1,1) = 0;
%% Multiply X by M in frequency domain
Xstd = std(X(:));
Xmean = mean(X(:));
X = real(ifftn(fftn(X).*M));
% Force zero mean unity standard deviation
X = X - mean(X(:));
X = X./std(X(:));
% Restore the standard deviation and mean from before the spectral shaping.
% This ensures the random sample from randn is truly random. After all, if
% the mean was always exactly zero it would not be all that random.
X = X + Xmean;
X = X.*Xstd;
end
Here is my solution:
My "min/max" code (lines 6 and 7) was bad. I wanted to divide all values in the matrix by the single largest value in the matrix so that all values would be between 0 and 1. Because I used max() improperly, I was stepping through the max value of each column and using that as my divisor; thus the vertical stripes.
In the end this is what my code looks like. X is the 3 dimensional matrix:
minVal = min(X,[],'all'); % Get the lowest value in the entire matrix
X = X - minVal; % Set min value to zero
maxVal = max(X,[],'all'); % Get the highest value in the entire matrix
X = X ./ maxVal; % Set max value to one

Parallel pooling on MATLAB for Bifurcation

I'm new to this concept of parallel pooling on MATLAB (I'm using the version 2019 a) and coding. This code that I'm going to share with you was available on the net, with some few modifications that I've made it for my requirements.
Problem Statement: I'm having a non-linear system (Rossler equation) & I have to plot its Bifurcation diagram, I tried to do it normally using for loop but its computation time was too much and my computer got hanged several times, so I got an advice to parallel pool my code in order to come out of this problem. I tried to learn how to parallel pool using MATLAB on the net but still I'm not able to resolve my Issues as there are still some problems since there are 2 parfor loops in my code I'm having problems with Indexing and in assignment of the global parameter (Please note: This code is written for normal execution without using parallel pooling).
I'm attaching my code below here, please excuse if I've mentioned a lot many lines of codes.
clc;
a = 0.2; b = 0.2; global c;
crange = 1:0.05:90; % Range for parameter c
k = 0; tspan = 0:0.1:500; % Time interval for solving Rossler system
xmax = []; % A matrix for storing the sorted value of x1
for c = crange
f = #(t,x) [-x(2)-x(3); x(1)+a*x(2); b+x(3)*(x(1)-c)];
x0 = [1 1 0]; % initial condition for Rossler system
k = k + 1;
[t,x] = ode45(f,tspan,x0); % call ode() to solve Rossler system
count = find(t>100); % find all the t values which is >10
x = x(count,:);
j = 1;
n = length(x(:,1)); % find the length of vector x1(x in our problem)
for i=2 : n-1
% check for the min value in 1st column of sol matrix
if (x(i-1,1)+eps) < x(i,1) && x(i,1) > (x(i+1,1)+eps)
xmax(k,j)=x(i,1); % Sorting the values of x1 in increasing order
j=j+1;
end
end
% generating bifurcation map by plotting j-1 element of kth row each time
if j>1
plot(c,xmax(k,1:j-1),'k.','MarkerSize',1);
end
hold on;
index(k)=j-1;
end
xlabel('Bifuracation parameter c');
ylabel('x max');
title('Bifurcation diagram for c');
This can be made compatible with parfor by taking a few relatively simple steps. Firstly, parfor workers cannot produce on-screen graphics, so we need to change things to emit a result. In your case, this is not totally trivial since your primary result xmax is being assigned-to in a not-completely-uniform manner - you're assigning different numbers of elements on different loop iterations. Not only that, it appears not to be possible to predict up-front how many columns xmax needs.
Secondly, you need to make some minor changes to the loop iteration to be compatible with parfor, which requires consecutive integer loop iterates.
So, the major change is to have the loop write individual rows of results to a cell array I've called xmax_cell. Outside the parfor loop, it's trivial to convert this back to matrix form.
Putting all this together, we end up with this, which works correctly in R2019b as far as I can tell:
clc;
a = 0.2; b = 0.2;
crange = 1:0.05:90; % Range for parameter c
tspan = 0:0.1:500; % Time interval for solving Rossler system
% PARFOR loop outputs: a cell array of result rows ...
xmax_cell = cell(numel(crange), 1);
% ... and a track of the largest result row
maxNumCols = 0;
parfor k = 1:numel(crange)
c = crange(k);
f = #(t,x) [-x(2)-x(3); x(1)+a*x(2); b+x(3)*(x(1)-c)];
x0 = [1 1 0]; % initial condition for Rossler system
[t,x] = ode45(f,tspan,x0); % call ode() to solve Rossler system
count = find(t>100); % find all the t values which is >10
x = x(count,:);
j = 1;
n = length(x(:,1)); % find the length of vector x1(x in our problem)
this_xmax = [];
for i=2 : n-1
% check for the min value in 1st column of sol matrix
if (x(i-1,1)+eps) < x(i,1) && x(i,1) > (x(i+1,1)+eps)
this_xmax(j) = x(i,1);
j=j+1;
end
end
% Keep track of what's the maximum number of columns
maxNumCols = max(maxNumCols, numel(this_xmax));
% Store this row into the output cell array.
xmax_cell{k} = this_xmax;
end
% Fix up xmax - push each row into the resulting matrix.
xmax = NaN(numel(crange), maxNumCols);
for idx = 1:numel(crange)
this_max = xmax_cell{idx};
xmax(idx, 1:numel(this_max)) = this_max;
end
% Plot
plot(crange, xmax', 'k.', 'MarkerSize', 1)
xlabel('Bifuracation parameter c');
ylabel('x max');
title('Bifurcation diagram for c');

The range of the coefficients of 2 level Wavelet LeGall 5/3 2D transform

As in the title, I am confused about the range of the coefficients of Wavelet LeGall 5/3 (has to be exact this filter) 2D transform (only for a 8*8 block) if the value of the input matrix are within the range from 0-255.
For the formulas, the link is here: Wavelet LeGall 5/3
Here is what I did for now:
Minus 128 for all value (easier to calculate the low frequency values, see later);
Do the transform in horizontal direction. This will generate all coefficients in all lines: the first 4 are low frequency and last 4 are high frequency. It is easy to find the range for high frequency is -255 to +255 (double the range of input). And the range for low frequency is actually -192 to +192 (1.5* the range of input).
Do the transform in vertical direction. This will do the same in vertical directions. And there are four blocks generated: LL (lowlow), LH (low high), HL, HH. It is easy to calculate the range for the HH is largest: -511 to +511 and the range for LL is 1.5*1.5 = 2.25 times of the input range (-128 to +127).
Then, here comes the question. What if I do this wavelet again for the LL block? Theoretically the range of the HH (2nd level coefficients) of the LL block should be 4 times of the LL range which becomes 10 times of the input range (-128 to +127) which is -1280 to +1270.
However, I tried many times random calculation, the max value never exceed -511 to +511 (see code at the end). I guess it is because the theoretical values cannot be reached because all calculations are based on the previous one. But this seemly easy question is difficult for me to prove theoretically. So can someone help me get out please?
Code I used (put two files in one directory and run the test file for any times you want but just the max value will not exceed 512...):
Function of waveletlegall53:
function X = waveletlegall53(X, Level)
%WAVELETLEGALL53 Le Gall 5/3 (Spline 2.2) wavelet transform.
% Y = WAVELETLEGALL53(X, L) decomposes X with L stages of the
% Le Gall 5/3 wavelet. For the inverse transform,
% WAVELETLEGALL53(X, -L) inverts L stages. Filter boundary
% handling is half-sample symmetric.
%
% X may be of any size; it need not have size divisible by 2^L.
% For example, if X has length 9, one stage of decomposition
% produces a lowpass subband of length 5 and a highpass subband
% of length 4. Transforms of any length have perfect
% reconstruction (exact inversion).
%
% If X is a matrix, WAVELETLEGALL53 performs a (tensor) 2D
% wavelet transform. If X has three dimensions, the 2D
% transform is applied along the first two dimensions.
%
% Example:
% Y = waveletlegall53(X, 5); % Transform image X using 5 stages
% R = waveletlegall53(Y, -5); % Reconstruct from Y
X = double(X);
if nargin < 2, error('Not enough input arguments.'); end
if ndims(X) > 3, error('Input must be a 2D or 3D array.'); end
if any(size(Level) ~= 1), error('Invalid transform level.'); end
N1 = size(X,1);
N2 = size(X,2);
% Lifting scheme filter coefficients for Le Gall 5/3
LiftFilter = [-1/2,1/4];
ScaleFactor =1; sqrt(2);
LiftFilter = LiftFilter([1,1],:);
if Level >= 0 % Forward transform
for k = 1:Level
M1 = ceil(N1/2);
M2 = ceil(N2/2);
%%% Transform along columns %%%
if N1 > 1
RightShift = [2:M1,M1];
X0 = X(1:2:N1,1:N2,:);
% Apply lifting stages
if rem(N1,2)
X1 = [X(2:2:N1,1:N2,:);X0(M1,:,:)]...
+floor(filter(LiftFilter(:,1),1,X0(RightShift,:,:),...
X0(1,:,:)*LiftFilter(1,1),1));
else
X1 = X(2:2:N1,1:N2,:) ...
+floor(filter(LiftFilter(:,1),1,X0(RightShift,:,:),...
X0(1,:,:)*LiftFilter(1,1),1));
end
X0 = X0 + floor(filter(LiftFilter(:,2),1,...
X1,X1(1,:,:)*LiftFilter(1,2),1)+0.5);
if rem(N1,2)
X1(M1,:,:) = [];
end
X(1:N1,1:N2,:) = [X0*ScaleFactor;X1/ScaleFactor];
end
%%% Transform along rows %%%
if N2 > 1
RightShift = [2:M2,M2];
X0 = permute(X(1:N1,1:2:N2,:),[2,1,3]);
% Apply lifting stages
if rem(N2,2)
X1 = permute([X(1:N1,2:2:N2,:),X(1:N1,N2,:)],[2,1,3])...
+ floor(filter(LiftFilter(:,1),1,X0(RightShift,:,:),...
X0(1,:,:)*LiftFilter(1,1),1));
else
X1 = permute(X(1:N1,2:2:N2,:),[2,1,3]) ...
+ floor(filter(LiftFilter(:,1),1,X0(RightShift,:,:),...
X0(1,:,:)*LiftFilter(1,1),1));
end
X0 = X0 +floor( filter(LiftFilter(:,2),1,...
X1,X1(1,:,:)*LiftFilter(1,2),1)+0.5);
if rem(N2,2)
X1(M2,:,:) = [];
end
X(1:N1,1:N2,:) = permute([X0*ScaleFactor;X1/ScaleFactor],[2,1,3]);
end
N1 = M1;
N2 = M2;
end
else % Inverse transform
for k = 1+Level:0
M1 = ceil(N1*pow2(k));
M2 = ceil(N2*pow2(k));
%%% Inverse transform along rows %%%
if M2 > 1
Q = ceil(M2/2);
RightShift = [2:Q,Q];
X1 = permute(X(1:M1,Q+1:M2,:)*ScaleFactor,[2,1,3]);
if rem(M2,2)
X1(Q,1,1) = 0;
end
% Undo lifting stages
X0 = permute(X(1:M1,1:Q,:)/ScaleFactor,[2,1,3]) ...
- floor(filter(LiftFilter(:,2),1,X1,X1(1,:,:)*LiftFilter(1,2),1)+0.5);
X1 = X1 - floor(filter(LiftFilter(:,1),1,X0(RightShift,:,:),...
X0(1,:,:)*LiftFilter(1,1),1));
if rem(M2,2)
X1(Q,:,:) = [];
end
X(1:M1,[1:2:M2,2:2:M2],:) = permute([X0;X1],[2,1,3]);
end
%%% Inverse transform along columns %%%
if M1 > 1
Q = ceil(M1/2);
RightShift = [2:Q,Q];
X1 = X(Q+1:M1,1:M2,:)*ScaleFactor;
if rem(M1,2)
X1(Q,1,1) = 0;
end
% Undo lifting stages
X0 = X(1:Q,1:M2,:)/ScaleFactor ...
- floor(filter(LiftFilter(:,2),1,X1,X1(1,:,:)*LiftFilter(1,2),1)+0.5);
X1 = X1 - floor(filter(LiftFilter(:,1),1,X0(RightShift,:,:),...
X0(1,:,:)*LiftFilter(1,1),1));
if rem(M1,2)
X1(Q,:,:) = [];
end
X([1:2:M1,2:2:M1],1:M2,:) = [X0;X1];
end
end
end
The test .m file:
clear all
close all
clc
n=100000;
maxt=zeros(1,n);
maxt2=zeros(1,n);
for it=1:n
X=floor(rand(8,8)*256);
X = X-128;
a = waveletlegall53(X,2);
maxt(it)=max(max(abs(a)));
if max(max(abs(a))) > 470
max(max(abs(a)))
end
end
[fr ind]=hist(maxt,length(unique(maxt)));
pr = length(find(maxt>512))/n
fr=fr/n;
figure()
plot(ind, fr)
grid on
Maxvalue = max(maxt)

Revised Simplex Method - Matlab Script

I've been asked to write down a Matlab program in order to solve LPs using the Revised Simplex Method.
The code I wrote runs without problems with input data although I've realised it doesn't solve the problem properly, as it does not update the inverse of the basis B (the real core idea of the abovementioned method).
The problem is only related to a part of the code, the one in the bottom of the script aiming at:
Computing the new inverse basis B^-1 by performing elementary row operations on [B^-1 u] (pivot row index is l_out). The vector u is transformed into a unit vector with u(l_out) = 1 and u(i) = 0 for other i.
Here's the code I wrote:
%% Implementation of the revised Simplex. Solves a linear
% programming problem of the form
%
% min c'*x
% s.t. Ax = b
% x >= 0
%
% The function input parameters are the following:
% A: The constraint matrix
% b: The rhs vector
% c: The vector of cost coefficients
% C: The indices of the basic variables corresponding to an
% initial basic feasible solution
%
% The function returns:
% x_opt: Decision variable values at the optimal solution
% f_opt: Objective function value at the optimal solution
%
% Usage: [x_opt, f_opt] = S12345X(A,b,c,C)
% NOTE: Replace 12345X with your own student number
% and rename the file accordingly
function [x_opt, f_opt] = SXXXXX(A,b,c,C)
%% Initialization phase
% Initialize the vector of decision variables
x = zeros(length(c),1);
% Create the initial Basis matrix, compute its inverse and
% compute the inital basic feasible solution
B=A(:,C);
invB = inv(B);
x(C) = invB*b;
%% Iteration phase
n_max = 10; % At most n_max iterations
for n = 1:n_max % Main loop
% Compute the vector of reduced costs c_r
c_B = c(C); % Basic variable costs
p = (c_B'*invB)'; % Dual variables
c_r = c' - p'*A; % Vector of reduced costs
% Check if the solution is optimal. If optimal, use
% 'return' to break from the function, e.g.
J = find(c_r < 0); % Find indices with negative reduced costs
if (isempty(J))
f_opt = c'*x;
x_opt = x;
return;
end
% Choose the entering variable
j_in = J(1);
% Compute the vector u (i.e., the reverse of the basic directions)
u = invB*A(:,j_in);
I = find(u > 0);
if (isempty(I))
f_opt = -inf; % Optimal objective function cost = -inf
x_opt = []; % Produce empty vector []
return % Break from the function
end
% Compute the optimal step length theta
theta = min(x(C(I))./u(I));
L = find(x(C)./u == theta); % Find all indices with ratio theta
% Select the exiting variable
l_out = L(1);
% Move to the adjacent solution
x(C) = x(C) - theta*u;
% Value of the entering variable is theta
x(j_in) = theta;
% Update the set of basic indices C
C(l_out) = j_in;
% Compute the new inverse basis B^-1 by performing elementary row
% operations on [B^-1 u] (pivot row index is l_out). The vector u is trans-
% formed into a unit vector with u(l_out) = 1 and u(i) = 0 for
% other i.
M=horzcat(invB,u);
[f g]=size(M);
R(l_out,:)=M(l_out,:)/M(l_out,j_in); % Copy row l_out, normalizing M(l_out,j_in) to 1
u(l_out)=1;
for k = 1:f % For all matrix rows
if (k ~= l_out) % Other then l_out
u(k)=0;
R(k,:)=M(k,:)-M(k,j_in)*R(l_out,:); % Set them equal to the original matrix Minus a multiple of normalized row l_out, making R(k,j_in)=0
end
end
invM=horzcat(u,invB);
% Check if too many iterations are performed (increase n_max to
% allow more iterations)
if(n == n_max)
fprintf('Max number of iterations performed!\n\n');
return
end
end % End for (the main iteration loop)
end % End function
%% Example 3.5 from the book (A small test problem)
% Data in standard form:
% A = [1 2 2 1 0 0;
% 2 1 2 0 1 0;
% 2 2 1 0 0 1];
% b = [20 20 20]';
% c = [-10 -12 -12 0 0 0]';
% C = [4 5 6]; % Indices of the basic variables of
% % the initial basic feasible solution
%
% The optimal solution
% x_opt = [4 4 4 0 0 0]' % Optimal decision variable values
% f_opt = -136 % Optimal objective function cost
Ok, after a lot of hrs spent on the intensive use of printmat and disp to understand what was happening inside the code from a mathematical point of view I realized it was a problem with the index j_in and normalization in case of dividing by zero therefore I managed to solve the issue as follows.
Now it runs perfectly. Cheers.
%% Implementation of the revised Simplex. Solves a linear
% programming problem of the form
%
% min c'*x
% s.t. Ax = b
% x >= 0
%
% The function input parameters are the following:
% A: The constraint matrix
% b: The rhs vector
% c: The vector of cost coefficients
% C: The indices of the basic variables corresponding to an
% initial basic feasible solution
%
% The function returns:
% x_opt: Decision variable values at the optimal solution
% f_opt: Objective function value at the optimal solution
%
% Usage: [x_opt, f_opt] = S12345X(A,b,c,C)
% NOTE: Replace 12345X with your own student number
% and rename the file accordingly
function [x_opt, f_opt] = S472366(A,b,c,C)
%% Initialization phase
% Initialize the vector of decision variables
x = zeros(length(c),1);
% Create the initial Basis matrix, compute its inverse and
% compute the inital basic feasible solution
B=A(:,C);
invB = inv(B);
x(C) = invB*b;
%% Iteration phase
n_max = 10; % At most n_max iterations
for n = 1:n_max % Main loop
% Compute the vector of reduced costs c_r
c_B = c(C); % Basic variable costs
p = (c_B'*invB)'; % Dual variables
c_r = c' - p'*A; % Vector of reduced costs
% Check if the solution is optimal. If optimal, use
% 'return' to break from the function, e.g.
J = find(c_r < 0); % Find indices with negative reduced costs
if (isempty(J))
f_opt = c'*x;
x_opt = x;
return;
end
% Choose the entering variable
j_in = J(1);
% Compute the vector u (i.e., the reverse of the basic directions)
u = invB*A(:,j_in);
I = find(u > 0);
if (isempty(I))
f_opt = -inf; % Optimal objective function cost = -inf
x_opt = []; % Produce empty vector []
return % Break from the function
end
% Compute the optimal step length theta
theta = min(x(C(I))./u(I));
L = find(x(C)./u == theta); % Find all indices with ratio theta
% Select the exiting variable
l_out = L(1);
% Move to the adjacent solution
x(C) = x(C) - theta*u;
% Value of the entering variable is theta
x(j_in) = theta;
% Update the set of basic indices C
C(l_out) = j_in;
% Compute the new inverse basis B^-1 by performing elementary row
% operations on [B^-1 u] (pivot row index is l_out). The vector u is trans-
% formed into a unit vector with u(l_out) = 1 and u(i) = 0 for
% other i.
M=horzcat(u, invB);
[f g]=size(M);
if (theta~=0)
M(l_out,:)=M(l_out,:)/M(l_out,1); % Copy row l_out, normalizing M(l_out,1) to 1
end
for k = 1:f % For all matrix rows
if (k ~= l_out) % Other then l_out
M(k,:)=M(k,:)-M(k,1)*M(l_out,:); % Set them equal to the original matrix Minus a multiple of normalized row l_out, making R(k,j_in)=0
end
end
invB=M(1:3,2:end);
% Check if too many iterations are performed (increase n_max to
% allow more iterations)
if(n == n_max)
fprintf('Max number of iterations performed!\n\n');
return
end
end % End for (the main iteration loop)
end % End function
%% Example 3.5 from the book (A small test problem)
% Data in standard form:
% A = [1 2 2 1 0 0;
% 2 1 2 0 1 0;
% 2 2 1 0 0 1];
% b = [20 20 20]';
% c = [-10 -12 -12 0 0 0]';
% C = [4 5 6]; % Indices of the basic variables of
% % the initial basic feasible solution
%
% The optimal solution
% x_opt = [4 4 4 0 0 0]' % Optimal decision variable values
% f_opt = -136 % Optimal objective function cost

How to solve a system of equations involving a tridiagonal matrix? MATLAB

I'm not sure if this typical behaviour or not but I am solving a finite-difference problem using the backward differencing method.
I populated a sparse matrix with the appropriate diagonal terms (along the central diagonal and one above and below it) and I attempted to solve the problem using MATLAB's built-in method (B=A\x) and it seems MATLAB just gets it wrong.
Furthermore, if use inv() and use the inverse of the tridiagonal matrix I get the correct solution.
Why does this behave like this?
Additional info:
http://pastebin.com/AbuEW6CR (Values are tabbed so its easier read)
Stiffness matrix K:
1 0 0 0
-0.009 1.018 -0.009 0
0 -0.009 1.018 -0.009
0 0 0 1
Values for d:
0
15.55
15.55
86.73
Built-in output:
-1.78595556155136e-05
0.00196073713853244
0.00196073713853244
0.0108149483252210
Output using inv(K):
0
15.42
16.19
86.73
Manual output:
0
15.28
16.18
85.16
Code
nx = 21; %number of spatial steps
nt = 501; %number of time steps (varies between 501 and 4001)
p = alpha * dt / dx^2; %arbitrary constant
a = [0 -p*ones(1,nx-2) 0]'; %diagonal below central diagonal
b = (1+2*p)*ones(nx,1); %central diagonal
c = [1 -p*ones(1,nx-2) 1]'; %diagonal above central diagonal
d = zeros(nx, 1); %rhs values
% Variables a,b,c,d are used for the manual tridiagonal method for
% comparison with MATLAB's built-in functions. The variables represent
% diagonals and the rhs of the matrix
% The equation is K*U(n+1)=U(N)
U = zeros(nx,nt);
% Setting initial conditions
U(:,[1 2]) = (60-32)*5/9;
K = sparse(nx,nx);
% Indices of the sparse matrix which correspond to the diagonal
diagonal = 1:nx+1:nx*nx;
% Populating diagonals
K(diagonal) =1+2*p;
K(diagonal(2:end)-1) =-p;
K(diagonal(1:end-1)+1) =-p;
% Applying dirichlet condition at final spatial step, the temperature is
% derived from a table for predefined values during the calculation
K(end,end-1:end)=[0 1];
% Applying boundary conditions at first spatial step
K(1,1:2) = [1 0];
% Populating rhs values and applying boundary conditions, d=U(n)
d(ivec) = U(ivec,n);
d(nx) = R; %From table
d(1) = 0;
U(:,n+1) = tdm(a,b,c,d); % Manual solver, gives correct answer
U(:,n+1) = d\K; % Built-in solver, gives wrong answer
The following line:
U(:,n+1) = d\K;
should have been
U(:,n+1) = K\d;
By mistake I had them the wrong way round and didn't notice it, it obviously changes the mathematical expression and hence the wrong answers.