Get row of functions from a matrix of functions - matlab

Before overwhelming you with examples where I try to encapsulate every aspect of my issue I'll try to just state the problem as simply as possible:
If f11 , ... , fnm is n*m real valued funtions that I wish to evaluate m at a time in n steps, through some higher order function b i.e.
v = []
f1 = #(x) [f11(x) f12(x) ... f1m(x)]
v = [v b(f1)]
f2 = #(x) [f21(x) f22(x) ... f2m(x)]
v = [v b(f2)]
How would I solve this through iteration? i.e. something like this:
f = #(x) [f11(x) ... f1m(x) ; ... ; fn1(x) ... fnm(x)];
% now iterate over the rows of f
for i=1:n
v = [v b(f(i,:)) ]
end
Here's an example of what I have (it grew in order to not miss out any details of my actual real-world problem but I have tried to make it as small as possible):
% 4 functions that take a 1x2 real valued vector as argument
% and return a real value
f11 = #(x) x(1) + x(2);
f12 = #(x) x(1) - x(2);
f21 = #(x) x(2) - x(1);
f22 = #(x) x(1) * x(2);
% we'll run function b for 2 steps, then 4 steps
steps = [2 4];
% start value
x = [1 2];
% vector to hold results
v = []
% get the result of passing the 1:st 2 functions to b with steps(1)
f1 = #(x) [f11(x) f12(x)];
v = [v ;b(x, f1, steps(1))]
% update x
x = v(end,:)
% add the result of passing the 2:nd 2 functions to b with steps(2)
f2 = #(x) [f21(x) f22(x)];
v = [v ;b(x, f2, steps(2))];
% update x
x = v(end,:)
Where b is a function defined as follows:
function [ X ] = b( x, f, n )
% #param:
% x = an 1x2 real valued vector
% f = a real valued function returning
% a 1x2 real valued vector
% n = an integer defining the rows of return matrix
%
% #return:
% X = an nx2 real valued matrix defined as below
X = zeros(n,2);
for i=1:n
% apply the functions on x
a = f(x+1);
b = f(x+2);
% update x
x = a+b
% add x to return matrix
X(i,:) = x;
end
end
The above code could be generalized as:
% n*m functions that take a 1xm real valued vector as argument
% and return a real value
f11 = #(x) ... ;
f12 = #(x) ... ;
.
.
.
fnm = #(x) ... ;
% we'll run function b for a1 steps, then a2 steps, ... , then an steps
steps = [a1 a2 ... an];
% start value
x = [1 2 ... m];
% vector to hold results
v = []
% get the result of passing the 1:st m functions to b with steps(1)
f1 = #(x) [f11(x) ... f1m(x)];
v = [v ;b(x, f1, steps(1))]
% update x
x = v(end,:)
% add the result of passing the 2:nd m functions to b with steps(2)
f2 = #(x) [f21(x) ... f2m(x)];
v = [v ;b(x, f2, steps(2))];
% update x
x = v(end,:)
.
.
.
% add the result of passing the n:ed m functions to b with steps(n)
fn = #(x) [fn1(x) ... fnm(x)];
v = [v ;b(x, fn, steps(n))];
% update x
x = v(end,:)
Where b is any function that returns an steps(i) x m matrix.
I wonder if both the small concrete example and the general example should be solvable through a general iteration, something like this:
% let f hold all the functions as a matrix
f = #(x) [f11(x) ... f1m(x) ; ... ; fn1(x) ... fnm(x)];
% now iterate over the rows of f
for i=1:n
v = [v ; b(x, f(i,:), steps(i)) ]
end

So the trick is in defining your functions as a cell matrix and then using some vectorization to solve the problem. This is the code that I came up with:
%First define your functions in a cell matrix
fn_mat = {#(x) x(1) + x(2), #(x) x(1) - x(2); ...
#(x) x(2) - x(1), #(x) x(1) * x(2)};
%Store the sixe of this matrix in two variables
[n, m] = size(fn_mat);
%Number of steps
steps = [2, 4];
% start value
x = [1 2];
% vector to hold results
v = [];
%This will run the required code for n iterations
for ii = 1:n
%This is the tricky part. What I have done is used arrayfun to run over
%all the functions in the row defined by ii and pass x as an argument
%each time. The rest is same as before
fn = #(x) arrayfun(#(a, b) fn_mat{ii, a}(b{:}), 1:m, repmat({x}, 1, m));
v = [v; b(x, fn, steps(ii))];
x = v(ii, :);
end
For the current values, the output is:
v =
12 -2
26 28
-28 -13
30 610
1160 38525
74730 89497060
The for loop is general enough to accommodate any size of fn_mat.

Related

Sigmoid function in Logistic Regression

function g = sigmoid(z)
g = zeros(size(z));
data = load('ex2data1.txt');
y = data(:, 3);
theta = [0;1;2];
m = length(y);
one = ones(m,1);
X1 = data(:, [1, 2]);
X = [one X1];
zz = theta' * X';
ztr = zz';
g = 1/ (1 + exp(-ztr));
end
No matter what value i give z i am getting a 1x100 matrix with 1 being the first entry and rest are 0s, how is this supposed to work, is this working correctly ?
your function sigmoid is not dependent on the input z since it is used only in the line g = zeros(size(z)); and g is re-assigned again at the end of the function.

Plot solution of second order equation in MATLAB

Could you please help me with the following question:
I want to solve a second order equation with two unknowns and use the results to plot an ellipse.
Here is my function:
fun = #(x) [x(1) x(2)]*V*[x(1) x(2)]'-c
V is 2x2 symmetric matrix, c is a positive constant and there are two unknowns, x1 and x2.
If I solve the equation using fsolve, I notice that the solution is very sensitive to the initial values
fsolve(fun, [1 1])
Is it possible to get the solution to this equation without providing an exact starting value, but rather a range? For example, I would like to see the possible combinations for x1, x2 \in (-4,4)
Using ezplot I obtain the desired graphical output, but not the solution of the equation.
fh= #(x1,x2) [x1 x2]*V*[x1 x2]'-c;
ezplot(fh)
axis equal
Is there a way to have both?
Thanks a lot!
you can take the XData and YData from ezplot:
c = rand;
V = rand(2);
V = V + V';
fh= #(x1,x2) [x1 x2]*V*[x1 x2]'-c;
h = ezplot(fh,[-4,4,-4,4]); % plot in range
axis equal
fun = #(x) [x(1) x(2)]*V*[x(1) x(2)]'-c;
X = fsolve(fun, [1 1]); % specific solution
hold on;
plot(x(1),x(2),'or');
% possible solutions in range
x1 = h.XData;
x2 = h.YData;
or you can use vector input to fsolve:
c = rand;
V = rand(2);
V = V + V';
x1 = linspace(-4,4,100)';
fun2 = #(x2) sum(([x1 x2]*V).*[x1 x2],2)-c;
x2 = fsolve(fun2, ones(size(x1)));
% remove invalid values
tol = 1e-2;
x2(abs(fun2(x2)) > tol) = nan;
plot(x1,x2,'.b')
However, the easiest and most straight forward approach is to rearrange the ellipse matrix form in a quadratic equation form:
k = rand;
V = rand(2);
V = V + V';
a = V(1,1);
b = V(1,2);
c = V(2,2);
% rearange terms in the form of quadratic equation:
% a*x1^2 + (2*b*x2)*x1 + (c*x2^2) = k;
% a*x1^2 + (2*b*x2)*x1 + (c*x2^2 - k) = 0;
x2 = linspace(-4,4,1000);
A = a;
B = (2*b*x2);
C = (c*x2.^2 - k);
% solve regular quadratic equation
dicriminant = B.^2 - 4*A.*C;
x1_1 = (-B - sqrt(dicriminant))./(2*A);
x1_2 = (-B + sqrt(dicriminant))./(2*A);
x1_1(dicriminant < 0) = nan;
x1_2(dicriminant < 0) = nan;
% plot
plot(x1_1,x2,'.b')
hold on
plot(x1_2,x2,'.g')
hold off

Output argument not assigned during call (MATLAB)

I'm having a bit of difficulty with this function in MATLAB and I can't figure out what the issue is. The error is,
Output argument "x" (and maybe others) not assigned during call to "SDLS".
Error in NO_wk4_Q3c (line 7)
x = SDLS( A, x0, b, 1e-3 );
So as far as I know, it's something to do with the output for 'x', yet I have assigned 'x' in the function file. Is it something to do with the 'while' loop?
Below is the function file:
function [ x, k ] = SDLS( A, x0, b, tol )
% Steepest descent with exact line search.
% A is the input matrix, x0 is the initial guess, b is a vector, tol is the
% tolerence level for convergence.
if nargin < 4
tol=eps;
end
g = A*x0+b; % Derivative of Q(x)=(1/2)x'Ax+b'x+c;
p = zeros(1,1);
k = 0;
x=zeros(1,1);
while norm(g,2)>=1e-3
g = A*x0 + b;
p = -g; % direction vector
alpha = -(transpose(g)*p)/(transpose(p)*A*p); % step length
x = x0 + alpha*p; % updates approximation
x0 = x;
k = k+1;
end
end
The script file that calls the function is as follows:
clear all;
A = [4 2; 2 3]; % Matrix
x0 = [ -1; -1]; % Initial guess
b = [ 3; 1];
[ x, k] = SDLS( A, x0, b, 1e-3 );
Any advice would be great :-)

vectorization Matlab - how to vectorize Gauss function ( code ) without loop

i wrote a function to calculate the integral using gaussian quadrature rule. I need to vectorize the last 2 lines, without using a loop. Any ideas?
function Q = gauss5(f,a,b,n)
% Divide the interval into n parts
y = linspace(a,b,n);
% Create function to use arrayfun
% Sum up the result from the arrayfun with function Fun on particular
% intervals, the first argument is array y without the last value, and
% the second argument is the array y without the first value
a = (y(1:end-1));
b = (y(2:end));
% coefficients - some random numbers
c = [1 2 3 4 5];
% nodes - random numbers too
x = [1 1 1 1 1];
% calculate b-a
w = b-a;
% sum up the result
Q = 0;
for i=1:n-1
Q = Q + sum((w(i)*c.*feval(f,((w(i)*x)+a(i)))));
end
end
If your f can get an array as input, you can replace this:
% sum up the result
Q = 0;
for i=1:n-1
Q = Q + sum((w(i)*c.*feval(f,((w(i)*x)+a(i)))));
end
by this:
wxa = bsxfun(#plus,bsxfun(#times,w,x(:)),a);
Qs = bsxfun(#times,w,c(:)).*feval(f,wxa);
Q = sum(Qs(:))
Or, if you have Matlab 2016b or later, just:
Qs = w.*c(:).*feval(f,w.*x(:)+a);
Q1 = sum(Qs(:));

Plotting a function of x over a range of D

I am trying to plot this function in MATLAB:
f(x) = (1./(2*b))*((erf(1./(2*D)+((x/b)-2*n)/D)+ erf(1./(2*D)-((x/b)-2*n)/D)));
The function is to plotted as a sum of n values from 0 to N, where N is a real number and b is a constant; for a range of D values. I am supposed to have different plots for each value in range D representing the function. How can I go about this please?
The different ranges of D can be done like this:
f = #(x, D)(x + D);
x = -10:10; %// pick a good range
D = 1:5; %// pick a good range
figure()
hold all
for d = D
plot(x, f(x, d))
end
I'm not 100% sure what you mean about the summing 0:N bit but maybe it's something of this form:
figure()
hold all
x= -10:10;
for d = 1:5
y = zeros(size(x)); %// Preallocation of memory for speed
for n = 0:10
y = y + n*x + d
end
plot(x, y)
end