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

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(:));

Related

The Simpson's 1-3 (h / 3) method in Matlab

The C code that finds the following integral according to the Simpson's 1-3 (h / 3) method is given below. Fill in the blanks on the code appropriately.
I want to solve this question below in Matlab but i didn't do it. This is simple question but i can't do it. If someone will help me, i will be very happy.
C code version
[C code version2
I tried this code block in Matlab:
% Ask for user input
% Lower bound (a)
a = input('What is your lower bound (a)?')
% Upper bound (b)
b = input('What is your upper bound (b)?')
% Subintervals
N = input('How many subintervals (N)?')
% Defining function
f = #(x,e) (e*x+sin(x))
% Finding h
h=(b-a)/N;
% Finding the values of x for each interval
x=linspace(a,b,N);
% Calculating the integral
for i = 1:N-1
I(i)= (h/3)*(f(x(i))+(4*f((x(i)+x(i+1))/2))+f(x(i+1)));
end
answer1 = sum(I)
disp(I)
% adding f(b) to sum
val2=ff(length(xx));
sum=val1+val2+sum;% set sum
% set result
result=sum*h/3;
Note that MATLAB does not use the symbol e as Neperian Number (Euler's number). To produce Euler's number in MATLAB, you can use exponential function exp(x), e = exp(1),
Therefore, First, correct your function definition:
F = #(x) exp(1).^x + sin(x) % Always try to use Upper-Case letters for your variable/function name
Then, you can use the following snippet to calculate the Integral using Simpson's 1/3:
a = 0; b = 3; N = 1e4;
F = #(x) exp(1).^x + sin(x);
h = ((b-a)/2)/N;
x = linspace(a,b,N);
I = 0;
for i = 1:N-1
I = I + h/3*(F(x(i)) + 4*F((x(i)+x(i+1))/2) + F(x(i+1)));
end
disp(I)
% To compare your result:
Itz = trapz(x, F(x))

How can I plot this Octave\Matlab function output?

I everyone,
I am pretty new in Octave\MatLab and I have the following doubt. I have this code calculating a sigmoid function for a parameter z:
function g = sigmoid(z)
%SIGMOID Compute sigmoid function
% g = SIGMOID(z) computes the sigmoid of z.
% You need to return the following variables correctly
g = zeros(size(z));
% ====================== YOUR CODE HERE ======================
% Instructions: Compute the sigmoid of each value of z (z can be a matrix,
% vector or scalar).
g = 1 ./ (1 + exp(-z));
% =============================================================
end
z could be a scalar, a vector or a matrix.
For example doing something like this:
>> X = [1 2; 0 5]
X =
1 2
0 5
>> g = 1 ./ (1 + exp(-X));
>> g
g =
0.73106 0.88080
0.50000 0.99331
Given the matrix X having 2 features X1 and X2 (the 2 column) how can I plot this function? The output is a three dimensional function?
The output is not a 3D function because you have one input X, and one output g, it's 2D.
You can display it column by column , displaying each column as a separate function on the same plot:
plot(X, g)
which is equivalent to:
figure
hold on
for i = 1:size(X,2)
plot(X(:,i), g(:,i))
end
hold off
You can display it row by row, displaying each row as a separate function on the same plot:
plot(X', g')
which is equivalent to:
figure
hold on
for i = 1:size(X,1)
plot(X(i,:), g(i,:))
end
hold off
You can display it as an array:
plot(X(:), g(:))

Problems with Cubic Hermite polynomial in Matlab

I am having trouble with this code for a piecewise cubic Hermite polynomial. In my assignment we are not allowed to use pchip. We are supposed to write a function which takes as it's input arguments an integer n and a 3 by n matrix which contains the x values, the values of a function evaluated at each x, and the values of the derivative evaluated at each x; in the first, second and third rows of the matrix respectively.
With this information we are supposed to calculate the coefficients for each Hermite polynomial on each subinterval of the interval given by the first row of the input matrix, then piece it altogether using mkpp.
Unfortunately, my code produces a very poor interpolating polynomial and I am having trouble figuring out why. For example for the function x^2 we have for instance n = 4 and M = [0,1,2,3; 0,1,4,9; 0,1,4,6] and when plugged into my function produces the following graph
I would really appreciate help with this, it's driving me nuts.
Here is my code:
function [ HP ] = HermiteInter( n,M )
%HermiteInter
% This function constructs a peicewise cubic Hermite polynomial.
% The input areguments are an integer n and M a 3 by n matrix, whose
% first row contains the values of x which a given function will be
% evaluated at. The second row contains the values of a function
% evaluated at those
% points and the third row contains the value of the derivative of
% the function evaluated at those points.
% Divided differences using these values are found by calling the
% function HermiteDD. These divided differences are then passed into the
% function mkpp to create the peicewise polynomial.
X = M(1,:);
Y = M(2,:);
Z = M(3,:);
Q = zeros(n-1,4);
for i = 1 : n-1
Q(i,:) = HermiteDD([X(i),X(i),X(i+1),X(i+1)],[Y(i),Y(i+1)],[Z(i),Z(i+1)]);
end
HP = mkpp(X,Q);
end
function [ HDD ] = HermiteDD(X,Y,Z)
%HermiteDD
% This function creates a table of divided differences for
% Hermite polynomials. The input arguments are X, the values at
% which a function was evaluated at, Y the values of the function at
% these points and Z the values of the derivative of the function at
% these points.
DD = zeros(4, 4);
DD(1, 1) = Y(1);
DD(2, 1) = Y(1);
DD(3, 1) = Y(2);
DD(4, 1) = Y(2);
DD(1, 2) = Z(1);
DD(2, 2) = (Y(1)-Y(2))/(X(1)-X(3));
DD(3, 2) = Z(2);
for j = 3 : 4
for i = 1 : (4 - j+1)
DD(i,j) = (DD(i + 1, j - 1) - DD(i, j - 1)) / (X(i + j-1) - X(i));
end
end
HDD = DD(1,:);
end

Discrete probability distribution calculation in Matlab

I have given P(x1...n) discrete independent probability values which represent for example the possibility of happening X.
I want a universal code for the question: With which probability does happening X occur at the same time 0-n times?
For example:
Given: 3 probabilities P(A),P(B),P(C) that each car(A,B,C) parks. Question would be: With which probability would no car, one car, two cars, and three cars park?
The answer for example for two cars parking at the same time would be:
P(A,B,~C) = P(A)*P(B)*(1-P(C))
P(A,~B,C) = P(A)*(1-P(B))*P(C)
P(~A,B,C) = (1-P(A))*P(B)*P(C)
P(2 of 3) = P(A,B,~C) + P(A,~B,C) + P(~A,B,C)
I have written the code for all possibilities, but the more values I get, of course the slower it gets due to more possible combinations.
% probability: Vector with probabilities P1, P2, ... PN
% result: Vector with results as stated above.
% All possibilities:
result(1) = prod(probability);
shift_vector = zeros(anzahl_werte,1);
for i = 1:anzahl_werte
% Shift Vector allocallization
shift_vector(i) = 1;
% Compute all unique permutations of the shift_vector
mult_vectors = uperm(shift_vector);
% Init Result Vector
prob_vector = zeros(length(mult_vectors(:,1)), 1);
% Calc Single Probabilities
for k = 1:length(mult_vectors(:,1))
prob_vector(k) = prod(abs(mult_vectors(k,:)'-probability));
end
% Sum of this Vector for one probability.
result(i+1) = sum(prob_vector);
end
end
%%%%% Calculate Permutations
function p = uperm(a)
[u, ~, J] = unique(a);
p = u(up(J, length(a)));
end % uperm
function p = up(J, n)
ktab = histc(J,1:max(J));
l = n;
p = zeros(1, n);
s = 1;
for i=1:length(ktab)
k = ktab(i);
c = nchoosek(1:l, k);
m = size(c,1);
[t, ~] = find(~p.');
t = reshape(t, [], s);
c = t(c,:)';
s = s*m;
r = repmat((1:s)',[1 k]);
q = accumarray([r(:) c(:)], i, [s n]);
p = repmat(p, [m 1]) + q;
l = l - k;
end
end
%%%%% Calculate Permutations End
Does anybody know a way to speed up this function? Or maybe Matlab has an implemented function for that?
I found the name of the calculation:
Poisson binomial distribution
How about this?
probability = [.3 .2 .4 .7];
n = numel(probability);
combs = dec2bin(0:2^n-1).'-'0'; %'// each column is a combination of n values,
%// where each value is either 0 or 1. A 1 value will represent an event
%// that happens; a 0 value will represent an event that doesn't happen.
result = NaN(1,n+1); %// preallocate
for k = 0:n; %// number of events that happen
ind = sum(combs,1)==k; %// combinations with exactly k 1's
result(k+1) = sum(prod(...
bsxfun(#times, probability(:), combs(:,ind)) + ... %// events that happen
bsxfun(#times, 1-probability(:), ~combs(:,ind)) )); %// don't happen
end

Vectorizing MATLAB function

I have double summation over m = 1:M and n = 1:N for polar point with coordinates rho, phi, z:
I have written vectorized notation of it:
N = 10;
M = 10;
n = 1:N;
m = 1:M;
rho = 1;
phi = 1;
z = 1;
summ = cos (n*z) * besselj(m'-1, n*rho) * cos(m*phi)';
Now I need to rewrite this function for accepting vectors (columns) of coordinates rho, phi, z. I tried arrayfun, cellfun, simple for loop - they work too slow for me. I know about "MATLAB array manipulation tips and tricks", but as MATLAB beginner I can't understand repmat and other functions.
Can anybody suggest vectorized solution?
I think your code is already well vectorized (for n and m). If you want this function to also accept an array of rho/phi/z values, I suggest you simply process the values in a for-loop, as I doubt any further vectorization will bring significant improvements (plus the code will be harder to read).
Having said that, in the code below, I tried to vectorize the part where you compute the various components being multiplied {row N} * { matrix N*M } * {col M} = {scalar}, by making a single call to the BESSELJ and COS functions (I place each of the row/matrix/column in the third dimension). Their multiplication is still done in a loop (ARRAYFUN to be exact):
%# parameters
N = 10; M = 10;
n = 1:N; m = 1:M;
num = 50;
rho = 1:num; phi = 1:num; z = 1:num;
%# straightforward FOR-loop
tic
result1 = zeros(1,num);
for i=1:num
result1(i) = cos(n*z(i)) * besselj(m'-1, n*rho(i)) * cos(m*phi(i))';
end
toc
%# vectorized computation of the components
tic
a = cos( bsxfun(#times, n, permute(z(:),[3 2 1])) );
b = besselj(m'-1, reshape(bsxfun(#times,n,rho(:))',[],1)'); %'
b = permute(reshape(b',[length(m) length(n) length(rho)]), [2 1 3]); %'
c = cos( bsxfun(#times, m, permute(phi(:),[3 2 1])) );
result2 = arrayfun(#(i) a(:,:,i)*b(:,:,i)*c(:,:,i)', 1:num); %'
toc
%# make sure the two results are the same
assert( isequal(result1,result2) )
I did another benchmark test using the TIMEIT function (gives more fair timings). The result agrees with the previous:
0.0062407 # elapsed time (seconds) for the my solution
0.015677 # elapsed time (seconds) for the FOR-loop solution
Note that as you increase the size of the input vectors, the two methods will start to have similar timings (the FOR-loop even wins on some occasions)
You need to create two matrices, say m_ and n_ so that by selecting element i,j of each matrix you get the desired index for both m and n.
Most MATLAB functions accept matrices and vectors and compute their results element by element. So to produce a double sum, you compute all elements of the sum in parallel by f(m_, n_) and sum them.
In your case (note that the .* operator performs element-wise multiplication of matrices)
N = 10;
M = 10;
n = 1:N;
m = 1:M;
rho = 1;
phi = 1;
z = 1;
% N rows x M columns for each matrix
% n_ - all columns are identical
% m_ - all rows are identical
n_ = repmat(n', 1, M);
m_ = repmat(m , N, 1);
element_nm = cos (n_*z) .* besselj(m_-1, n_*rho) .* cos(m_*phi);
sum_all = sum( element_nm(:) );