I am trying to use minimization to calculate coefficients of the polynomial p(x) = 1 + c(1)x + c(2)x^2 to approximate e^x. I need to use points xi = 1 + i/n for natural numbers i on [1,n], first for n=5, then n=10, etc. The approach is to minimize the 1, 2, and inf norm(p(x) - e^x) using fminsearch. So the output should be the 2 coefficients for the 3 p(x)'s. Any suggestions is appreciated.
Well, if anyone was wondering, I did figure the question out finally.
for l = [1 2 inf]
fprintf('For norm %d\n', l)
fprintf('Coefficients c1 c2\n')
for n = [5 10 100]
i = 1:n ;
x = 1 + i/n ;
c = [1 1] ;
%Difference function that we want to minimize
g = #(c) x.*c(1) + x.^2.*c(2) + 1 - exp(x);
f_norm = #(c) norm(g(c), l) ;
C = fminsearch(f_norm, c);
fprintf('n = %d ', n)
fprintf('%f %f\n', C(1), C(2))
% Compare plot of e^x and p(x).
p = #(x) C(1)*x + C(2)*x.^2 + 1;
xx = linspace(1,2,1e5);
figure;
plot(xx, p(xx), '--r', xx, exp(xx));
str = sprintf('Plot with n = %d, for norm %d', n,l);
title(str,'FontSize',24)
xlabel('x','FontSize',20)
ylabel('y','FontSize',20)
legend('p2 approximation','exponential');
end
end
This worked in the end to answer the question.
Related
Construct an experiment to study the performance of the Cramer rule (with two implementations
determinants) in relation to Gauss's algorithm.
In each iteration 10 random arrays A (NxN), and vectors b (Nx1) will be created.
The 10 linear systems will be solved using the Cramer rule ("cramer.m") using
of rec_det (A) and using det (A), and the Gaussian algorithm
(“GaussianElimination.m”), and the time for each technique will be the average of 10 values.
Repeat the above for N = 2 to 10 and make a graph of the average time
in relation to the dimension N.
This is my task. I dont know if the way that I calculate the average time is correct and the graphic is not displayed.
T1=0;
T2=0;
T3=0;
for N=2:10
for i=1:10
A=rand(N,N);
b=rand(N,1);
t1=[1,i];
t2=[1,i];
t3=[1,i];
tic;
crammer(A,b);
t1(i)=toc;
tic
crammer_rec(A,b);
t2(i)=toc;
tic
gaussianElimination(A,b);
t3(i)=toc;
T1=T1+t1(i);
T2=T2+t2(i);
T3=T3+t3(i);
end
avT1=T1/10;
avT2=T2/10;
avT3=T3/10;
end
plot(2:10 , avT1 , 2:10 , avT2 , 2:10 , avT3);
function x = cramer(A, b)
n = length(b);
d = det(A);
% d = rec_det(A);
x = zeros(n, 1);
for j = 1:n
x(j) = det([A(:,1:j-1) b A(:,j+1:end)]) / d;
% x(j) = rec_det([A(:,1:j-1) b A(:,j+1:end)]) / d;
end
end
function x = cramer(A, b)
n = length(b);
d = rec_det(A);
x = zeros(n, 1);
for j = 1:n
x(j) = rec_det([A(:,1:j-1) b A(:,j+1:end)]) / d;
end
end
function deta = rec_det(R)
if size(R,1)~=size(R,2)
error('Error.Matrix must be square.')
else
n = size(R,1);
if ( n == 2 )
deta=(R(1,1)*R(2,2))-(R(1,2)*R(2,1));
else
for i=1:n
deta_temp=R;
deta_temp(1,:)=[ ];
deta_temp(:,i)=[ ];
if i==1
deta=(R(1,i)*((-1)^(i+1))*rec_det(deta_temp));
else
deta=deta+(R(1,i)*((-1)^(i+1))*rec_det(deta_temp));
end
end
end
end
end
function x = gaussianElimination(A, b)
[m, n] = size(A);
if m ~= n
error('Matrix A must be square!');
end
n1 = length(b);
if n1 ~= n
error('Vector b should be equal to the number of rows and columns of A!');
end
Aug = [A b]; % build the augmented matrix
C = zeros(1, n + 1);
% elimination phase
for k = 1:n - 1
% ensure that the pivoting point is the largest in its column
[pivot, j] = max(abs(Aug(k:n, k)));
C = Aug(k, :);
Aug(k, :) = Aug(j + k - 1, :);
Aug(j + k - 1, :) = C;
if Aug(k, k) == 0
error('Matrix A is singular');
end
for i = k + 1:n
r = Aug(i, k) / Aug(k, k);
Aug(i, k:n + 1) = Aug(i, k:n + 1) - r * Aug(k, k: n + 1);
end
end
% back substitution phase
x = zeros(n, 1);
x(n) = Aug(n, n + 1) / Aug(n, n);
for k = n - 1:-1:1
x(k) = (Aug(k, n + 1) - Aug(k, k + 1:n) * x(k + 1:n)) / Aug(k, k);
end
end
I think the easiest way to do this is by creating a 9 * 3 dimensional matrix to contain all the total times, and then take the average at the end.
allTimes = zeros(9, 3);
for N=2:10
for ii=1:10
A=rand(N,N);
b=rand(N,1);
tic;
crammer(A,b);
temp = toc;
allTimes(N-1,1) = allTimes(N-1,1) + temp;
tic
crammer_rec(A,b);
temp = toc;
allTimes(N-1,2) = allTimes(N-1,2) + temp;
tic
gaussianElimination(A,b);
temp = toc;
allTimes(N-1,3) = allTimes(N-1,3) + temp;
end
end
allTimes = allTimes/10;
figure; plot(2:10, allTimes);
You can use this approach because the numbers are quite straightforward and simple. If you had a more complicated setup, the way to store the times/calculate the averages would have to be tweaked.
If you had more functions you could also use function handles and create a third inner loop, but this is a little more advanced.
I'm new to Octave and Matlab and I have a problem. I need to make a program, which solves a Triangular system of linear equations and making a triangular factorization with pivoting.
For example I need to do next exercise
That is my lufact function
function X = lufact (A, B)
[N, N] = size(A);
X = zeros(N, 1);
Y = zeros(N, 1);
C = zeros(1, N);
R = 1:N;
for p=1:N-1
[max1,j]=max(abs(A(p:N,p)));
C = A(p, :);
A(p, :) = A(j + p - 1, :);
A(j + p - 1, :) = C;
d = R(p);
R(p) = R(j + p - 1);
R(j + p - 1) = d;
if A(p,p) == 0
'A is singular. No unique solution'
break
endif
endfor
for k = p + 1: N
mult = A(k,p)/A(p,p);
A(k,p) = mult;
A(k, p + 1: N) = A(k, p + 1: N) - mult*A(p, p+1: N);
endfor
endfunction
Y(1) = B(R(1));
for k = 2: N
Y(k) = B(R(k)) - A(k, 1:k - 1)*Y(1:k - 1);
endfor
X(N) = Y(N)/A(N,N);
for k = N-1: -1: 1
X(k) = (Y(k) - A(k, k + 1: N)*X(k + 1: N))/A(k, k);
endfor
And that is my main function
A = [2 4 -6; 1 5 3; 1 3 2];
BA = [-4; 10; 5]
BB = [20; 49; 32]
XA = lufact(A, BA);
XB = lufact(A, BB);
disp(XA);
disp(XB);
The output of my program
What am I doing wrong and what should I do to fix that?
You don't seem to be attempting to answer the question you're asking, so your question doesn't make much sense...
But, in any case. The exercise asks you to show that given the following matrices / vectors:
A = [ 2, 4, -6; 1, 5, 3; 1, 3, 2 ];
L = [ 1, 0, 0; 1/2, 1, 0; 1/2, 1/3, 1 ];
U = [ 2, 4, -6; 0, 3, 6; 0, 0, 3 ];
show that LY = B, UX = Y, AX = B for a given B.
Ok. In octave, the best way to solve a matrix equation of the form aX = b w.r.t X for a given a and b, is to use the "matrix left-division" operator, \, i.e. x = a\b. Type help mldivide in your octave console for details.
So,
Y = L\B;
X = U\Y;
A*X % the result should be the same as B. QED.
Then there is the separate question of how can I perform LU decomposition in octave? Well, octave provides a function for this: lu.
[L, U] = lu(A)
% L = 1.0000 0 0
% 0.5000 1.0000 0
% 0.5000 0.3333 1.0000
%
% U = 2 4 -6
% 0 3 6
% 0 0 3
Then there's the implied further question of "I would like to perform LU decomposition by hand."
Great. Good luck. Your code here is a bit messy, no comments, no self-explanatory variable names ... I won't attempt to debug it here in detail. One thing to note though is, LU decomposition only takes a matrix as an input. I'm not sure why you are trying to pass the 'B' matrix to it as an input. Plus it doesn't seem like you're using it anywhere in the function. Or creating L or U matrices for that matter. Also, if the whole top part is inside an lufact.m file, then you should know that your function terminates well before the for loops; these get ignored completely. What were you trying to do exactly?
I am trying to compute the taylor series of ln(x) for any value of x.
What I have so far is:
clear
clc
n = input('Enter number of iiterations (n): ' );
x = input('enter value of x (x): ');
y = zeros(1,n);
for i = 0:n
y(i+1)=sum + (-1)^(n+1)*(x-1)^n/n;
end
But this code seems to be broken and I can't figure out why. Any suggestions on how to improve?
This is a one liner in addition to the for-loop answer provided by #farbiondriven
For 0<x<1 :
sumLn = #(x, n)(sum(((-1).^(0:n-1)).*((x-1).^(1:n))./(1:n)));
sumLn(0.5,10)
ans =
-0.6931
>> log(0.5)
ans =
-0.6931
For x>0.5 :
sumLn = #(x, n)(sum( ((x-1)/x).^(1:n) ./ (1:n) ));
sumLn(2,10)
ans =
0.6931
log(2) =
0.6931
Note: The variable x in this formula is bounded as mentioned in this link.
Try this:
clear
clc
n = input('Enter number of iterations (n): ' );
x = input('enter value of x with abs value < 1 (x): ');
y = zeros(1,n+1);
y(1)=0;
for i = 1:n
y(i+1)= y(i) + ((-1)^(i+1)*(x-1)^i/i);
end
txt = sprintf('The output is: %f', y(n+1))
I suggest using built-in function and hopefully there is one. taylor(f,var) approximates f with the Taylor series expansion of f up to the fifth order at the point var = 0.
Specify Expansion Point :
Find the Taylor series expansions at x = 1 for these functions. The default expansion point is 0. To specify a different expansion point, use 'ExpansionPoint':
syms x
taylor(log(x), x, 'ExpansionPoint', 1)
ans =
x - (x - 1)^2/2 + (x - 1)^3/3 - (x - 1)^4/4 + (x - 1)^5/5 - 1
Specify Truncation Order :
The default truncation order is 6.
syms x
f = log(x);
t6 = taylor(f, x);
Use 'Order' to control the truncation order. For example, approximate the same expression up to the orders 8.
syms x
taylor(log(x), x, 'ExpansionPoint', 1, 'Order', 8);
I want to generate array or 1 x M matrix with variables such as (please note that sum goes from i=1 to m-1):
Because I want to use Obj later as a general array depends on given M for some optimization purposes. I tried following code in MATLAB but that symbolic L does not support:
function testSymbolic
M=3;
Obj = ones(1,M);
L = sym('L', [1 M]);
tempL = log(1-L);
for m=1:M
Obj(1,m) = log((L(m))/(1+L(m))) + sum(tempL(1,1:m-1),2);
end
Obj
However, when I see that following when I run separately:
L = sym('L', [1 3])
L =
[ L1, L2, L3]
L(1)
ans =
L1
can some one please help me to fix this issue?
Try
M = 3;
for i = 1:M
L(i) = sym(['L(' num2str(i) ')'])
end
tempL = log(1-L);
for m=1:M
Obj(1,m) = log((L(m))/(1+L(m))) + sum(tempL(1:m-1));
end
This yields e.g.
Obj(3)
ans =
log(L(3)/(L(3) + 1)) + log(1 - L(1)) + log(1 - L(2))
EDIT:
Considering you want to calculate the maximum of the Obj-vector I would suggest this:
clear;
M = 3;
L = sym('L', [1 M]);
tempL = log(1-L);
for m=1:M
Obj(1,m) = real(log((L(m))/(1+L(m))) + sum(tempL(1:m-1)));
end
F = matlabFunction(Obj,'vars',{L})
ft = #(v) (max (-F(v)));
Now you can optimize ft.
I know that MATLAB works better when most or everything is vectorized. I have two set of vectors X and T. For every vector x in X I want to compute:
this is because I want to compute:
which can be easily expressed as MATLAB linear algebra operations as I wrote above with a dot product. I am hoping that I can speed this up by having those vectors, instead of computing each f(x) with a for loop. Ideally I could have it all vectorized and compute:
I've been think about this for some time now, but it doesn't seem to be a a nice way were a function takes two vectors and computes the norm between each one of them, with out me having to explicitly write the for loop.
i.e. I've implemented the trivial code:
function [ f ] = f_start( x, c, t )
% Computes f^*(x) = sum_i c_i exp( - || x_i - t_i ||^2)
% Inputs:
% x = data point (D x 1)
% c = weights (K x 1)
% t = centers (D x K)
% Outputs:
% f = f^*(x) = sum_k c_k exp( - || x - t_k ||^2)
[~, K] = size(t);
f = 0;
for k=1:K
c_k = c(k);
t_k = t(:, k);
norm_squared = norm(x - t_k, 2)^2;
f = f + c_k * exp( -1 * norm_squared );
end
end
but I was hoping there was a less naive way to do this!
I think you want pdist2 (Statistics Toolbox):
X = [1 2 3;
4 5 6];
T = [1 2 3;
1 2 4;
7 8 9];
result = pdist2(X,T);
gives
result =
0 1.0000 10.3923
5.1962 4.6904 5.1962
Equivalently, if you don't have that toolbox, use bsxfun as follows:
result = squeeze(sqrt(sum(bsxfun(#minus, X, permute(T, [3 2 1])).^2, 2)));
Another method just for kicks
X = [1 2 3;
4 5 6].';
T = [1 2 3;
1 2 4;
7 8 9].';
tT = repmat(T,[1,size(X,2)]);
tX = reshape(repmat(X,[size(T,2),1]),size(tT));
res=reshape(sqrt(sum((tT-tX).^2)).',[size(T,2),size(X,2)]).'