If I have a function for example :
k=1:100
func=#(s) sum(c(k)-exp((-z(k).^2./s)))
where c and z are matrices with same size (for example 1x100) , is there any way to use fminsearch to find the "s" value?
fminsearch needs an initial condition in the second parameter, not boundary conditions (though some of the options may support boundaries).
Just call
fminsearch(func,-0.5)
Where you saw examples passing in a vector, was a multidimensional search across multiple coefficients, and the vector was the initial value of each coefficient. Not limits on the search space.
You can also use
fminbnd(func, -0.5, 1);
which performs constrained minimization.
But I think you should minimize the norm of the error, not the sum (minimizing the sum leads to a large error magnitude -- very very negative).
If you have the Optimization Toolbox, then lsqnonlin could be useful.
I guess you would like to find argmin of your symbolic function, use
Index of max and min value in an array
OR
ARGMAX/ARGMIN by Marco Cococcioni:
function I = argmax(X, DIM)
%ARGMAX Argument of the maximum
% For vectors, ARGMAX(X) is the indix of the smallest element in X. For matrices,
% MAX(X) is a row vector containing the indices of the smallest elements from each
% column. This function is not supported for N-D arrays with N > 2.
%
% It is an efficient replacement to the use of [Y,I] = MAX(X,[],DIM);
% See ARGMAX_DEMO for a speed comparison.
%
% I = ARGMAX(X,DIM) operates along the dimension DIM (DIM can be
% either 1 or 2).
%
% When complex, the magnitude ABS(X) is used, and the angle
% ANGLE(X) is ignored. This function cannot handle NaN's.
%
% Example:
% clc
% disp('If X = [2 8 4; 7 3 9]');
% disp('then argmax(X,1) should be [2 1 2]')
% disp('while argmax(X,2) should be [2 3]''. Now we check it:')
% disp(' ');
% X = [2 8 4;
% 7 3 9]
% argmax(X,1)
% argmax(X,2)
%
% See also ARGMIN, ARGMAXMIN_MEX, ARGMAX_DEMO, MIN, MAX, MEDIAN, MEAN, SORT.
% Copyright Marco Cococcioni, 2009.
% $Revision: 1.0 $ $Date: 2009/02/16 19:24:01$
if nargin < 2,
DIM = 1;
end
if length(size(X)) > 2,
error('Function not provided for N-D arrays when N > 2.');
end
if (DIM ~=1 && DIM ~= 2),
error('DIM has to be either 1 or 2');
end
if any(isnan(X(:))),
error('Cannot handle NaN''s.');
end
if not(isreal(X)),
X = abs(X);
end
max_NOT_MIN = 1; % computes argmax
I = argmaxmin_mex(X, DIM, max_NOT_MIN);
Related
I would like to generate 100 random matrices A=[a_{ij}] of size 6 by 6 in (0, 9) using matlab programming satisfying the following properties:
1. multiplicative inverse: i.e., a_{ij}=1/a_{ji} for all i,j=1,2,...,6.
2. all entries are positive: i.e., a_{ij}>0 for all i,j=1,2,...,6.
3. all diagonal elements are 1: i.e., a_{ii}=1 for all i=1,2,..,6.
4. transitive: i.e., a_{ih}*a_{hj}=a_{ij} for all i,j,h=1,2,...,6.
So far, I tried to use a matlab function rand(6)*9. But, I got wrong matrices. I was wondering if anyone could help me?
Here is my matlab code:
clc; clear;
n=6;
m=0;
for i=1:n
for j=1:n
for h=1:n
while m<100 % generate 100 random matrices
A=rand(n)*9; % random matrix in (0,9)
A(i,j)>0; % positive entries
A(i,j)==1/A(j,i); % multiplicative inverse
A(i,h)*A(h,j)==A(i,j); % transitive
if i==j && j==h
A(i,j)==1; % diagonal elements are 1
break;
end
m=m+1;
M{m}=A
end
end
end
end
M{:}
clear; clc
M = cell(1, 100); % preallocate memory
% matrix contains both x & 1/x
% we need a distribution whose multiplication with its inverse is uniform
pd = makedist('Triangular', 'a', 0, 'b', 1, 'c', 1);
for m=1:100 % 100 random matrices
A = zeros(6); % allocate memory
% 5 random numbers for 6x6 transitive random matrix
a = random(pd, 1, 5);
% choose a or 1/a randomly
ac = rand(1, 5) < 0.5;
% put these numbers above the diagonal
for i=1:5
if ac(i)
A(i, i+1) = a(i);
else
A(i, i+1) = 1 / a(i);
end
end
% complete the transitivity going above
for k=flip(1:4)
for i=1:k
A(i, i-k+6) = A(i, i-k+5) * A(i-k+5, i-k+6);
end
end
% lower triangle is multiplicative inverse of upper triangle
for i=2:6
for j=1:i-1
A(i,j) = 1 / A(j,i);
end
end
c = random(pd); % triangular random variable between (0,1)
A = A ./ max(A(:)) * 9 * c; % range becomes (0, 9*c)
% diagonals are 1
for i=1:6
A(i,i) = 1;
end
% insert the result
M{m} = A;
end
There are actually 5 numbers are independent in 6x6 transitive matrix. The others are derived from them as shown in the code.
The reason why triangular distribution is used for these numbers is because pdf of triangular distribution is f(x)=x, and pdf of inverse triangular distribution is f-1(x)=1/x; thus their multiplication becomes uniform distribution. (See pdf of inverse distribution)
A = A ./ max(A(:)) * 9; makes the range (0,9), but there will always be 9 as the maximum element. We need to shrink the result by a random coefficient to obtain the result uniformly distributed in (0,9). Since A is uniformly distributed, we can achieve this again by triangular distribution. (See product distribution)
Another solution to the range issue would be calculating A while its maximum is above 9. This would eliminate the latter problem.
Since all elements of A depends on 5 random variables, the distribution of them will never be perfectly uniform, but the aim here is to maintain a reasonable scale for them.
It took me a litte to think about your question, but I realized there is no solution.
You require your elements of A to be uniformly distributed in the (0,9) range. You also require a_{ij}*a_{jk}=a_{ik}. Since the product of two uniform distributions is not a unifrom distribution, there is no solution to your question.
I did it two ways, why is the first way(starting on line with mu=mean(X) not working? what's the difference?
function [X_norm, mu, sigma] = featureNormalize(X)
%FEATURENORMALIZE Normalizes the features in X
% FEATURENORMALIZE(X) returns a normalized version of X where
% the mean value of each feature is 0 and the standard deviation
% is 1. This is often a good preprocessing step to do when
% working with learning algorithms.
% You need to set these values correctly
X_norm = X;
mu = zeros(1, size(X, 2));
sigma = zeros(1, size(X, 2));
% ====================== YOUR CODE HERE ======================
% Instructions: First, for each feature dimension, compute the mean
% of the feature and subtract it from the dataset,
% storing the mean value in mu. Next, compute the
% standard deviation of each feature and divide
% each feature by it's standard deviation, storing
% the standard deviation in sigma.
%
% Note that X is a matrix where each column is a
% feature and each row is an example. You need
% to perform the normalization separately for
% each feature.
%
% Hint: You might find the 'mean' and 'std' functions useful.
%
%mu=mean(X)
%X_norm=X-mu;
%sigma=std(X_norm)
%X_norm(1)=X_norm(1)/sigma(1)
%X_norm(2)=X_norm(2)/sigma(2)
% Calculates mean and std dev for each feature
for i=1:size(mu,2)
mu(1,i) = mean(X(:,i));
sigma(1,i) = std(X(:,i));
X_norm(:,i) = (X(:,i)-mu(1,i))/sigma(1,i);
end
% ============================================================
end
The reason is because you try to subtract a vector from a matrix. mean(X) gives you a vector with the mean in the columns of X, dimension [1xC], and the X is dimension [RxC]. A way to solve this in a oneliner is
X = (X-repmat(mean(X,1),size(X,1),1))./repmat(std(X,0,1),size(X,1),1)
You need to loop through X. You can further verify the output of above code with normalize(X)
for i = 1: size(X, 2)
mu = mean(X(:, i));
sigma = std(X(:, i));
X_norm(:, i) = (X(:, i) - mu) ./ sigma
end
I have code of the following kind in MATLAB:
indices = find([1 2 2 3 3 3 4 5 6 7 7] == 3)
This returns 4,5,6 - the indices of elements in the array equal to 3. Now. my code does this sort of thing with very long vectors. The vectors are always sorted.
Therefore, I would like a function which replaces the O(n) complexity of find with O(log n), at the expense that the array has to be sorted.
I am aware of ismember, but for what I know it does not return the indices of all items, just the last one (I need all of them).
For reasons of portability, I need the solution to be MATLAB-only (no compiled mex files etc.)
Here is a fast implementation using binary search. This file is also available on github
function [b,c]=findInSorted(x,range)
%findInSorted fast binary search replacement for ismember(A,B) for the
%special case where the first input argument is sorted.
%
% [a,b] = findInSorted(x,s) returns the range which is equal to s.
% r=a:b and r=find(x == s) produce the same result
%
% [a,b] = findInSorted(x,[from,to]) returns the range which is between from and to
% r=a:b and r=find(x >= from & x <= to) return the same result
%
% For any sorted list x you can replace
% [lia] = ismember(x,from:to)
% with
% [a,b] = findInSorted(x,[from,to])
% lia=a:b
%
% Examples:
%
% x = 1:99
% s = 42
% r1 = find(x == s)
% [a,b] = myFind(x,s)
% r2 = a:b
% %r1 and r2 are equal
%
% See also FIND, ISMEMBER.
%
% Author Daniel Roeske <danielroeske.de>
A=range(1);
B=range(end);
a=1;
b=numel(x);
c=1;
d=numel(x);
if A<=x(1)
b=a;
end
if B>=x(end)
c=d;
end
while (a+1<b)
lw=(floor((a+b)/2));
if (x(lw)<A)
a=lw;
else
b=lw;
end
end
while (c+1<d)
lw=(floor((c+d)/2));
if (x(lw)<=B)
c=lw;
else
d=lw;
end
end
end
Daniel's approach is clever and his myFind2 function is definitely fast, but there are errors/bugs that occur near the boundary conditions or in the case that the upper and lower bounds produce a range outside the set passed in.
Additionally, as he noted in his comment on his answer, his implementation had some inefficiencies that could be improved. I implemented an improved version of his code, which runs faster, while also correctly handling boundary conditions. Furthermore, this code includes more comments to explain what is happening. I hope this helps someone the way Daniel's code helped me here!
function [lower_index,upper_index] = myFindDrGar(x,LowerBound,UpperBound)
% fast O(log2(N)) computation of the range of indices of x that satify the
% upper and lower bound values using the fact that the x vector is sorted
% from low to high values. Computation is done via a binary search.
%
% Input:
%
% x- A vector of sorted values from low to high.
%
% LowerBound- Lower boundary on the values of x in the search
%
% UpperBound- Upper boundary on the values of x in the search
%
% Output:
%
% lower_index- The smallest index such that
% LowerBound<=x(index)<=UpperBound
%
% upper_index- The largest index such that
% LowerBound<=x(index)<=UpperBound
if LowerBound>x(end) || UpperBound<x(1) || UpperBound<LowerBound
% no indices satify bounding conditions
lower_index = [];
upper_index = [];
return;
end
lower_index_a=1;
lower_index_b=length(x); % x(lower_index_b) will always satisfy lowerbound
upper_index_a=1; % x(upper_index_a) will always satisfy upperbound
upper_index_b=length(x);
%
% The following loop increases _a and decreases _b until they differ
% by at most 1. Because one of these index variables always satisfies the
% appropriate bound, this means the loop will terminate with either
% lower_index_a or lower_index_b having the minimum possible index that
% satifies the lower bound, and either upper_index_a or upper_index_b
% having the largest possible index that satisfies the upper bound.
%
while (lower_index_a+1<lower_index_b) || (upper_index_a+1<upper_index_b)
lw=floor((lower_index_a+lower_index_b)/2); % split the upper index
if x(lw) >= LowerBound
lower_index_b=lw; % decrease lower_index_b (whose x value remains \geq to lower bound)
else
lower_index_a=lw; % increase lower_index_a (whose x value remains less than lower bound)
if (lw>upper_index_a) && (lw<upper_index_b)
upper_index_a=lw;% increase upper_index_a (whose x value remains less than lower bound and thus upper bound)
end
end
up=ceil((upper_index_a+upper_index_b)/2);% split the lower index
if x(up) <= UpperBound
upper_index_a=up; % increase upper_index_a (whose x value remains \leq to upper bound)
else
upper_index_b=up; % decrease upper_index_b
if (up<lower_index_b) && (up>lower_index_a)
lower_index_b=up;%decrease lower_index_b (whose x value remains greater than upper bound and thus lower bound)
end
end
end
if x(lower_index_a)>=LowerBound
lower_index = lower_index_a;
else
lower_index = lower_index_b;
end
if x(upper_index_b)<=UpperBound
upper_index = upper_index_b;
else
upper_index = upper_index_a;
end
Note that the improved version of Daniels searchFor function is now simply:
function [lower_index,upper_index] = mySearchForDrGar(x,value)
[lower_index,upper_index] = myFindDrGar(x,value,value);
EDIT many years later: there was an error in the last two if/else blocks, fixed it.
ismember will give you all the indexes if you look at the first output:
>> x = [1 2 2 3 3 3 4 5 6 7 7];
>> [tf,loc]=ismember(x,3);
>> inds = find(tf)
inds =
4 5 6
You just need to use the right order of inputs.
Note that there is a helper function used by ismember that you can call directly:
% ISMEMBC - S must be sorted - Returns logical vector indicating which
% elements of A occur in S
tf = ismembc(x,3);
inds = find(tf);
Using ismembc will save computation time since ismember calls issorted first, but this will omit the check.
Note that newer versions of matlab have a builtin called by builtin('_ismemberoneoutput',a,b) with the same functionality.
Since the above applications of ismember, etc. are somewhat backwards (searching for each element of x in the second argument rather than the other way around), the code is much slower than necessary. As the OP points out, it is unfortunate that [~,loc]=ismember(3,x) only provides the location of the first occurrence of 3 in x, rather than all. However, if you have a recent version of MATLAB (R2012b+, I think), you can use yet more undocumented builtin functions to get the first an last indexes! These are ismembc2 and builtin('_ismemberfirst',searchfor,x):
firstInd = builtin('_ismemberfirst',searchfor,x); % find first occurrence
lastInd = ismembc2(searchfor,x); % find last occurrence
% lastInd = ismembc2(searchfor,x(firstInd:end))+firstInd-1; % slower
inds = firstInd:lastInd;
Still slower than Daniel R.'s great MATLAB code, but there it is (rntmX added to randomatlabuser's benchmark) just for fun:
mean([rntm1 rntm2 rntm3 rntmX])
ans =
0.559204323050486 0.263756852283128 0.000017989974213 0.000153682125682
Here are the bits of documentation for these functions inside ismember.m:
% ISMEMBC2 - S must be sorted - Returns a vector of the locations of
% the elements of A occurring in S. If multiple instances occur,
% the last occurrence is returned
% ISMEMBERFIRST(A,B) - B must be sorted - Returns a vector of the
% locations of the elements of A occurring in B. If multiple
% instances occur, the first occurence is returned.
There is actually reference to an ISMEMBERLAST builtin, but it doesn't seem to exist (yet?).
This is not an answer - I am just comparing the running time of the three solutions suggested by chappjc and Daniel R.
N = 5e7; % length of vector
p = 0.99; % probability
KK = 100; % number of instances
rntm1 = zeros(KK, 1); % runtime with ismember
rntm2 = zeros(KK, 1); % runtime with ismembc
rntm3 = zeros(KK, 1); % runtime with Daniel's function
for kk = 1:KK
x = cumsum(rand(N, 1) > p);
searchfor = x(ceil(4*N/5));
tic
[tf,loc]=ismember(x, searchfor);
inds1 = find(tf);
rntm1(kk) = toc;
tic
tf = ismembc(x, searchfor);
inds2 = find(tf);
rntm2(kk) = toc;
tic
a=1;
b=numel(x);
c=1;
d=numel(x);
while (a+1<b||c+1<d)
lw=(floor((a+b)/2));
if (x(lw)<searchfor)
a=lw;
else
b=lw;
end
lw=(floor((c+d)/2));
if (x(lw)<=searchfor)
c=lw;
else
d=lw;
end
end
inds3 = (b:c)';
rntm3(kk) = toc;
end
Daniel's binary search is very fast.
% Mean of running time
mean([rntm1 rntm2 rntm3])
% 0.631132275892504 0.295233981447746 0.000400786666188
% Percentiles of running time
prctile([rntm1 rntm2 rntm3], [0 25 50 75 100])
% 0.410663611685559 0.175298784336465 0.000012828868032
% 0.429120717937665 0.185935198821797 0.000014539383770
% 0.582281366154709 0.268931132925888 0.000019243302048
% 0.775917520641649 0.385297304740352 0.000026940622867
% 1.063753914942895 0.592429428396956 0.037773746662356
I needed a function like this. Thanks for the post #Daniel!
I worked a little with it because I needed to find several indexes in the same array. I wanted to avoid the overhead of arrayfun (or the like) or calling the function multiple times. So you can pass a bunch of values in range and you will get the indexes in the array.
function idx = findInSorted(x,range)
% Author Dídac Rodríguez Arbonès (May 2018)
% Based on Daniel Roeske's solution:
% Daniel Roeske <danielroeske.de>
% https://github.com/danielroeske/danielsmatlabtools/blob/master/matlab/data/findinsorted.m
range = sort(range);
idx = nan(size(range));
for i=1:numel(range)
idx(i) = aux(x, range(i));
end
end
function b = aux(x, lim)
a=1;
b=numel(x);
if lim<=x(1)
b=a;
end
if lim>=x(end)
a=b;
end
while (a+1<b)
lw=(floor((a+b)/2));
if (x(lw)<lim)
a=lw;
else
b=lw;
end
end
end
I guess you can use a parfor or arrayfun instead. I have not tested myself at what size of range it pays off, though.
Another possible improvement would be to use the previous found indexes (if range is sorted) to decrease the search space. I am skeptical of its potential to save CPU because of the O(log n) runtime.
The final function ended up running slightly faster. I used #randomatlabuser 's framework for that:
N = 5e6; % length of vector
p = 0.99; % probability
KK = 100; % number of instances
rntm1 = zeros(KK, 1); % runtime with ismember
rntm2 = zeros(KK, 1); % runtime with ismembc
rntm3 = zeros(KK, 1); % runtime with Daniel's function
for kk = 1:KK
x = cumsum(rand(N, 1) > p);
searchfor = x(ceil(4*N/5));
tic
range = sort(searchfor);
idx = nan(size(range));
for i=1:numel(range)
idx(i) = aux(x, range(i));
end
rntm1(kk) = toc;
tic
a=1;
b=numel(x);
c=1;
d=numel(x);
while (a+1<b||c+1<d)
lw=(floor((a+b)/2));
if (x(lw)<searchfor)
a=lw;
else
b=lw;
end
lw=(floor((c+d)/2));
if (x(lw)<=searchfor)
c=lw;
else
d=lw;
end
end
inds3 = (b:c)';
rntm2(kk) = toc;
end
%%
function b = aux(x, lim)
a=1;
b=numel(x);
if lim<=x(1)
b=a;
end
if lim>=x(end)
a=b;
end
while (a+1<b)
lw=(floor((a+b)/2));
if (x(lw)<lim)
a=lw;
else
b=lw;
end
end
end
It is not a big improvement, but it helps because I need to run several thousand searches.
% Mean of running time
mean([rntm1 rntm2])
% 9.9624e-05 5.6303e-05
% Percentiles of running time
prctile([rntm1 rntm2], [0 25 50 75 100])
% 3.0435e-05 1.0524e-05
% 3.4133e-05 1.2231e-05
% 3.7262e-05 1.3369e-05
% 3.9111e-05 1.4507e-05
% 0.0027426 0.0020301
I hope this can help somebody.
EDIT
If there is a significant chance of having exact matches, it pays off to use the very fast built-in ismember before calling the function:
[found, idx] = ismember(range, x);
idx(~found) = arrayfun(#(r) aux(x, r), range(~found));
I'm trying to find zeros of a function. See my code below.
Because fft expects a numerical array, I didn't define the symbolic function to use fzero.
However, this approach is not accurate and depend on step. Do you have a better idea?
step=2000;
x=0:pi/step:2*pi;
y= 4+5*cos(10*x)+20*cos(40*x)+cos(100*x);
fy = fft(y');
fy(1:8) =0;
fy(12:end-10)=0;
fy(end-6:end)=0;
ffy = ifft(fy);
t=diff(ffy);
x=0:pi/step:2*pi-pi/step;
plot(x,t)
indices= find(t<5e-4 & t>-5e-4);
You could proceed along the array t and look for points where the values change sign. That would indicate the presence of a zero.
Actaully, MATLAB's fzero function uses a similar method. You said you didn't use it because you required an array, rather than an anonymous function, but you could convert the array into an anonymous function using simple linear interpolation like so:
func = #(k) interp1(x,t,k); % value of t(x) interpolated at x=k
fzero(func,initial_value);
EDIT : Just to clarify what I mean. If you have an array t and you want to find its zeros...
f = 5; % frequency of wave in Hz
x = 0:0.01:1; % time index
t = cos( 2*pi*f*x ); % cosine wave of frequency f
zeroList = []; % start with an empty list of zeros
for i = 2:length(t) % loop through the array t
current_t = t(i); % current value of t
previous_t = t(i-1); % previous value of t
if current_t == 0 % the case where the zero is exact
newZero = x(i);
zeroList = [zeroList,newZero];
elseif current_t*previous_t < 0 % a and b have opposite sign if a*b is -ve
% do a linear interpolation to find the zero (solve y=mx+b)
slope = (current_t-previous_t)/(x(i)-x(i-1));
newZero = x(i) - current_t/slope;
zeroList = [zeroList,newZero];
end
end
figure(1); hold on;
axis([ min(x) max(x) -(max(abs(t))) (max(abs(t))) ]);
plot(x,t,'b');
plot(x,zeros(length(x)),'k-.');
scatter(zeroList,zeros(size(zeroList)),'ro');
The zeros I get are correct:
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