I have a code for finding the bisection (and it finally works!), but I need to include 3 more things:
output- Root History a vector containing the sequence of midpoints obtained by the algorithm
output- the absolute value of the function
f(x) at r, i.e., fRoot = f(r) input- max iterations
function [R, E] = myBisection(f, a, b, tol)
m = (a + b)/2;
R = m;
E = abs(f(m));
while E(end) > tol
if sign(f(a)) == sign(f(m))
a = m;
else
b = m;
end
m = (a + b)/2;
R = [R, m];
E = [E, abs(f(m))];
end
how do I do this? thanks!!
I have corrected indents an you can see that you've left out end from the end of the function. (it is optional but best not to leave those things out so you know you did not mean to write couple lines to the end but you forgot it.)
R and E should be returned now, if you call myBisection apropriately, that is
[R, E] = myBisection(f, a, b, tol);
If you just call
myBisection(f, a, b, tol)
it will only return R.
To add a limit on the number of iterations, you change while's condition like so:
iter=0;
while (E(end) > tol) && (iter<max_iter)
iter = iter+1;
% ...
end
or it is better to do it in a for loop, with an if plus break:
for iter=1:max_iter
if(E(end) <= tol), break, end;
% ...
end
Related
I have a 3D matrix X of size a x b x c.
I want to create a 3D matrix Y in MATLAB as follows:
X = rand(10, 10, 5);
[a, b, c] = size(X);
for i = 1 : c
for j = 1 : a
for k = 1 : b
if j<a && k<b
Y(j, k, i) = X(j+1, k, i) + X(j, k+1, i).^4;
else
Y(j, k, i) = X(a, b, i) + X(a, b, i).^4;
end
end
end
end
How can I do that by avoiding using a lot of for loops? In other words, how can I rewrite the above code in a faster way without using a lot of loops?
Indexing Arrays/Matrices
Below I added a portion to your script that creates an array Z that is identical to array Y by using indexing that covers the equivalent indices and element-wise operations that are indicated by the dot . preceding the operation. Operations such as multiplication * and division / can be specified element-wise as .* and ./ respectively. Addition and subtraction act in the element-wise fashion and do not need the dot .. I also added an if-statement to check that the arrays are the same and that the for-loops and indexing methods give equivalent results. Indexing using end refers to the last index in the corresponding/respective dimension.
Snippet:
Y = zeros(a,b,c);
Y(1:end-1,1:end-1,:) = X(2:end,1:end-1,:) + X(1: end-1, 2:end,:).^4;
Y(end,1:end,:) = repmat(X(a,b,:) + X(a,b,:).^4,1,b,1);
Y(1:end,end,:) = repmat(X(a,b,:) + X(a,b,:).^4,a,1,1);
Full Script: Including Both Methods and Checking
X = rand(10, 10, 5);
[a, b, c] = size(X);
%Initialed for alternative result%
Z = zeros(a,b,c);
%Looping method%
for i = 1 : c
for j = 1 : a
for k = 1 : b
if j < a && k < b
Y(j, k, i) = X(j+1, k, i) + X(j, k+1, i).^4;
else
Y(j, k, i) = X(a, b, i) + X(a, b, i).^4;
end
end
end
end
%Indexing and element-wise method%
Z(1:end-1,1:end-1,:) = X(2:end,1:end-1,:) + X(1: end-1, 2:end,:).^4;
Z(end,1:end,:) = repmat(X(a,b,:) + X(a,b,:).^4,1,b,1);
Z(1:end,end,:) = repmat(X(a,b,:) + X(a,b,:).^4,a,1,1);
%Checking if results match%
if(Z == Y)
fprintf("Matched result\n");
end
Ran using MATLAB R2019b
eval and str2func are both able to evaluate a function represented by a string, f.e. f='a^x+exp(b)+sin(c*x)+d':
Using eval:
y = eval(f)
or (suggested by rahnema1)
fHandle = eval(['#(x, a, b, c, d) ' f]);
y = fHandle(x, a, b, c, d);
Using str2func:
fHandle = str2func(['#(x, a, b, c, d) ' f]);
y = fHandle(x, a, b, c, d);
Which of both methods has the best performance?
Remarks
Note that this benchmark is inspired on this question.
Note that I'm aware that using eval and str2func is often bad practice[1][2] (as mentioned in the comments).
Short answer: use str2func.
Benchmark
The benchmark will evaluate the function for N different values of x.
f='a^x+exp(b)+sin(c*x)+d';
Ns = linspace(1, 1000, 20);
timeEval = zeros(size(Ns));
timeEvalHandle = zeros(size(Ns));
timeStr2func = zeros(size(Ns));
for i=1:length(Ns)
N = Ns(i);
timeEval(i) = timeit(#() useEval(f, N));
timeEvalHandle(i) = timeit(#() useEvalHandle(f, N));
timeStr2func(i) = timeit(#() useStr2func(f, N));
end
figure
plot(Ns, timeEval, 'DisplayName', 'time eval');
hold on
plot(Ns, timeEvalHandle, 'DisplayName', 'time eval');
hold on
plot(Ns, timeStr2func, 'DisplayName', 'time str2func');
legend show
xlabel('N');
figure
plot(Ns, timeEval./timeStr2func, 'DisplayName', 'time_{eval}/time_{str2func}');
hold on
plot(Ns, timeEvalHandle./timeStr2func, 'DisplayName', 'time_{eval handle}/time_{str2func}');
legend show
xlabel('N');
figure
plot(Ns, timeEvalHandle./timeStr2func);
ylabel('time_{eval handle}/time_{str2func}')
xlabel('N');
function y = useEval(f, N)
a = 1; b = 2; c = 3; d = 4;
for x=1:N
y = eval(f);
end
end
function y = useEvalHandle(f, N)
a = 1; b = 2; c = 3; d = 4;
fHandle = eval(['#(x, a, b, c, d) ' f]);
for x=1:N
y = fHandle(x, a, b, c, d);
end
end
function y = useStr2func(f, N)
a = 1; b = 2; c = 3; d = 4;
fHandle = str2func(['#(x, a, b, c, d) ' f]);
for x=1:N
y = fHandle(x, a, b, c, d);
end
end
str2func vs eval (without function handle): The results show that even for evaluating the function once, it is around 50% faster to use str2func than eval (without function handle). For a large number of evaluations, str2func may be around 100x faster (depending on the function you are evaluating).
str2func vs eval (with function handle): eval is around 100% slower than str2func for a single evaluation, but becomes are almost equally fast for a large number of evaluations (eval is ~5% slower).
eval with and without function handle: Note that for a single evaluation creating a function handle with eval is ~50% slower than evaluating it directly.
Conclusion: str2func is always faster than eval.
In the following benchmark a collection of function handles is created and performance of eval is compare to that of str2func to evaluate strings. The functions are combination of variables with +- signs.
n = 16;
op=char((dec2bin(0:2^n-1)-48)*2+43);
vars= 'a':'z';
v = vars(1:n+1);
s(1:2^n,1:2:2*n+1)=repmat(v,2^n,1);
s(:,2:2:end)=op;
h=repmat(['#(' sprintf('%c,',v(1:end-1)) v(end) ')'],2^n,1);
farray=[h,s];
tic
for k = 1:2^n
f = eval(farray(k,:));
end
toc
tic
for k = 1:2^n
f = str2func(farray(k,:));
end
toc
Result in Octave:
There is no difference between two methods.
below is my code to perform jacobi iterations to solve Ax=b.
I try this code on the matrix A =[4 -1 1; 4 -8 1; -2 1 5] and b=[7 -21 15].
and x is a first guess 1 x 3 vector. Are not these dimensions correct? It gives me the error in the code that calculates: r = b - x*A
and M\(x*N + b)
What am I missing?!? how do I fix this? please help!
function [x, error, iter, flag] = jacobi(A, x, b, maxiter, tol)
%implement jacobi iterations
%[x, error, iter, flag] = jacobi(A, x, b, maxiter, tol)
%jacobi.m solves the linear system Ax=b using the Jacobi iteration
%
%
%INPUT A the matrix of the system Ax=b
% x the first guess vector Ax=b
% b the vector in the system
% maxiter the maximum number of iteration to perform
% tol the tolerance
%
%OUTPUT x the solution vector
% error error norm
% niter the number of iterations it took
% flag indicates whether a solution was found. 0 means there was a
% solution and 1 means there was not a solution
iter = 0;
flag = 0;
bnrm2 = norm(b);
if (bnrm2 == 0)
bnrm2 = 1.0;
end
r = b - x*A;
error = norm(r) / bnrm2;
if (error<tol)
return;
end
[m,n] = size(A);
M = diag(diag(A));
N = diag(diag(A)) - A;
for iter = 1:maxiter,
oldx = x;
x = M\(x*N + b);
error = norm(x - oldx) / norm(x);
if (error <= tol)
break;
end
end
if (error > tol)
flag = 1;
end
Since, in the code, you're solving what I'll call (not sure if it's proper since I never do it) the left-multiply problem, the operator and order of matrices are, in some sense, reversed.
If you were solving the problem A*x = b with the residual r = b - A*x (i.e., x and b are column vectors), you would perform right-vector multiplies and left-matrix divides. Therefore, the update line in the loop would be
x = M \ (N*x + b);
Conversely, if you were solving the problem x*A = b with the residual r = b - x*A (i.e., x and b are row vectors), you would perform left-vector multiplies and right-matrix divides. Therefore, the update line in the loop would be
x = (x*N + b) / M;
Note that \ resolves to the function mldivide and / resolves to mrdivide. There is no function distinction for the multiply.
It appears your current updater mixes the two, which is bad news bears for dimension matching.
I should calculate this formula for large value of p, so 4 nested loops made my code very slow and inapplicable. I will so thankful if anyone can help me for better implementation with use of sum and other suitable matlab commands!
K(i,j)=sum(sum(a(m)*b(n)*A(i,j,m,n),m=1:p),n=1:p);
i,j,m,n ->1:p
and A is 4D Matrix and a,b are vector.
Thank.
I can get rid of 2 of the for loops. Perhaps one of the MATLAB wizards on this site can do better.
p = 3;
A = rand(p, p, p, p)
a = rand(p, 1)
b = rand(p, 1)
% I think your original code does something like this.
K1 = zeros(p, p);
for n = 1: p
for m = 1: p
for j = 1: p
for i = 1: p
K1(i, j) = K1(i, j) + a(m) * b(n) * A(i, j, m, n);
end
end
end
end
K1
% This gives the same result, with half the loops.
K2 = zeros(p, p);
for n = 1: p
for m = 1: p
K2 = K2 + a(m) * b(n) * A(:,:,m,n);
end
end
K2
% Verify that the two answers are the same.
all(K1(:) == K2(:))
I would like to generate the adjacency matrix of an undirected graph with N nodes.
In particular, this graph should have a fixed degree (each node is connected to a fixed number of node d).
If a set d = N-1, the solution is trivial:
A = ones(N) - eye(N);
How can I generalize it for any d?
ADD:
Here is a solution (thanks to Oli Charlesworth):
function A = fixedDegreeGraph(N, d)
A = zeros(N);
for i=1:N
b = i;
f = i;
for k=1:floor(d/2)
f = f + 1;
if (f == N + 1)
f = 1;
end
A(i, f) = 1;
A(f, i) = 1;
b = b - 1;
if (b == 0)
b = N;
end
A(i, b) = 1;
A(b, i) = 1;
end
end
For even d, here's a way to visualise the approach.
Draw the vertices out arranged in a circle.
Each vertex is connected to its immediate (d/2) left-hand neighbours, and its immediate (d/2) right-hand neighbours.
It should be fairly obvious how to turn this into an adjacency matrix (hint: it will be a circulant matrix, so you may find the toeplitz function useful).
Extending this to odd d is not much harder... (although note there is no solution if both N and d are odd)