mirror of
https://github.com/kuhyx/WUT_Computer_Science.git
synced 2026-07-06 22:03:14 +02:00
feat: Adding code
This commit is contained in:
parent
55992c8232
commit
8ef8c675f7
26
ENUME/projectC/QRDecomposition.m
Normal file
26
ENUME/projectC/QRDecomposition.m
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
function [Q, R, invqtq] = QRDecomposition(A)
|
||||||
|
% initialize empty matrices
|
||||||
|
Q = zeros(size(A));
|
||||||
|
R = eye(size(A, 2));
|
||||||
|
invqtq = zeros(size(A, 2));
|
||||||
|
|
||||||
|
% modified Gram-Schmidt, use each column to orthogonalize the ones in front of it
|
||||||
|
for col = 1:size(A, 2)
|
||||||
|
% by the time we've reached this column, it's already been orthogonalized
|
||||||
|
Q(:, col) = A(:, col);
|
||||||
|
|
||||||
|
% calculate current column dot product for R
|
||||||
|
coldot = dot(Q(:, col), Q(:, col));
|
||||||
|
invqtq(col, col) = 1 / coldot;
|
||||||
|
|
||||||
|
% orthogonalize further columns
|
||||||
|
for next = (col + 1):size(A, 2)
|
||||||
|
% calculate R cell for this column pair
|
||||||
|
R(col, next) = dot(Q(:, col), A(:, next)) / coldot;
|
||||||
|
|
||||||
|
% orthogonalize column
|
||||||
|
A(:, next) = A(:, next) - R(col, next) * Q(:, col);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
16
ENUME/projectC/backSubstitution.m
Normal file
16
ENUME/projectC/backSubstitution.m
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
% solves system with triangular matrix
|
||||||
|
function result = backSubstitution(eqsys)
|
||||||
|
for col = size(eqsys, 1):-1:1
|
||||||
|
% normalize diagonal coefficients to 1
|
||||||
|
eqsys(col, :) = eqsys(col, :) / eqsys(col, col);
|
||||||
|
|
||||||
|
% eliminate factor from other rows
|
||||||
|
for row = (col - 1):-1:1
|
||||||
|
reductor = eqsys(row, col) / eqsys(col, col);
|
||||||
|
eqsys(row, :) = eqsys(row, :) - eqsys(col, :) * reductor;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% rightmost column is now the result
|
||||||
|
result = eqsys(:, size(eqsys, 2));
|
||||||
|
end
|
||||||
31
ENUME/projectC/rk4.m
Normal file
31
ENUME/projectC/rk4.m
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
% solve ODE system using RK4 with constant step size
|
||||||
|
function [x, derivs] = rk4(functs, init, interval, stepsize, maxsteps)
|
||||||
|
% set initial values as start points of output
|
||||||
|
x = init;
|
||||||
|
|
||||||
|
% build derivatives table
|
||||||
|
derivs = zeros(size(x));
|
||||||
|
for eqnum = 1:size(functs, 1)
|
||||||
|
derivs(eqnum, 1) = functs{eqnum}(x(:, 1));
|
||||||
|
end
|
||||||
|
|
||||||
|
% build output based on preceding values
|
||||||
|
stepcount = ceil((interval(2) - interval(1)) / stepsize);
|
||||||
|
if nargin >= 5; stepcount = min(stepcount, maxsteps - 1); end
|
||||||
|
for step = 1:stepcount
|
||||||
|
% obtain the preceding function values
|
||||||
|
stepval = x(:, step);
|
||||||
|
|
||||||
|
for eqnum = 1:size(functs, 1)
|
||||||
|
% generic single-step iteration
|
||||||
|
phi = rk4phi(functs{eqnum}, stepval, stepsize);
|
||||||
|
x(eqnum, step + 1) = x(eqnum, step) + stepsize * phi;
|
||||||
|
|
||||||
|
% update derivatives table
|
||||||
|
derivs(eqnum, step + 1) = functs{eqnum}(x(:, step + 1));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% append arguments to output
|
||||||
|
x = [interval(1):stepsize:(stepcount * stepsize); x];
|
||||||
|
end
|
||||||
61
ENUME/projectC/rk4auto.m
Normal file
61
ENUME/projectC/rk4auto.m
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
% automatic step size variant of RK4
|
||||||
|
function [x, sizes, errors] = rk4auto(functs, init, interval, initstep, eps_rel, eps_abs)
|
||||||
|
% set start points of output
|
||||||
|
args = interval(1);
|
||||||
|
x = init;
|
||||||
|
|
||||||
|
% initialize output plots
|
||||||
|
sizes = double.empty();
|
||||||
|
errors = double.empty();
|
||||||
|
|
||||||
|
% integrate function until end of interval reached
|
||||||
|
stepsize = initstep;
|
||||||
|
step = 0;
|
||||||
|
while 1
|
||||||
|
% obtain the preceding function values
|
||||||
|
step = step + 1;
|
||||||
|
stepval = x(:, step);
|
||||||
|
|
||||||
|
% advance output function
|
||||||
|
for eqnum = 1:size(functs, 1)
|
||||||
|
% generic single-step iteration
|
||||||
|
phi = rk4phi(functs{eqnum}, stepval, stepsize);
|
||||||
|
x(eqnum, step + 1) = x(eqnum, step) + stepsize * phi;
|
||||||
|
end
|
||||||
|
|
||||||
|
% stop algorithm if function integrated over the whole interval
|
||||||
|
args(step + 1) = args(step) + stepsize;
|
||||||
|
if args(end) >= interval(2); break; end
|
||||||
|
|
||||||
|
% also calculate next step using two half-steps
|
||||||
|
for substep = 1:2
|
||||||
|
for eqnum = 1:size(functs, 1)
|
||||||
|
phi = rk4phi(functs{eqnum}, stepval, stepsize / 2);
|
||||||
|
stepval(eqnum) = stepval(eqnum) + (stepsize / 2) * phi;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% calculate step correction factor
|
||||||
|
alpha = Inf;
|
||||||
|
for eqnum = 1:size(functs, 1)
|
||||||
|
% calculate approximation error
|
||||||
|
delta = abs(stepval(eqnum) - x(eqnum, step + 1)) / 15;
|
||||||
|
errors(step) = delta;
|
||||||
|
|
||||||
|
% calculate equation-specific alpha
|
||||||
|
epsilon = abs(stepval(eqnum)) * eps_rel + eps_abs;
|
||||||
|
eqalpha = epsilon / delta;
|
||||||
|
|
||||||
|
% minimum alpha wins
|
||||||
|
if eqalpha < alpha; alpha = eqalpha; end
|
||||||
|
end
|
||||||
|
alpha = alpha ^ (1/5);
|
||||||
|
|
||||||
|
% correct step size with safety factor
|
||||||
|
stepsize = 0.9 * alpha * stepsize;
|
||||||
|
sizes(step) = stepsize;
|
||||||
|
end
|
||||||
|
|
||||||
|
% append arguments to output
|
||||||
|
x = [args; x];
|
||||||
|
end
|
||||||
8
ENUME/projectC/rk4phi.m
Normal file
8
ENUME/projectC/rk4phi.m
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
% calculate the phi for RK4 algorithms
|
||||||
|
function phi = rk4phi(fun, stepval, stepsize)
|
||||||
|
k1 = fun(stepval);
|
||||||
|
k2 = fun(stepval + 0.5 * stepsize * k1);
|
||||||
|
k3 = fun(stepval + 0.5 * stepsize * k2);
|
||||||
|
k4 = fun(stepval + stepsize * k3);
|
||||||
|
phi = (k1 + 2 * k2 + 2 * k3 + k4) / 6;
|
||||||
|
end
|
||||||
78
ENUME/projectC/task1lsapprox.m
Normal file
78
ENUME/projectC/task1lsapprox.m
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
% define function data points
|
||||||
|
taskfunc = (-5:5)';
|
||||||
|
taskfunc(:, 2) = [
|
||||||
|
-6.5743
|
||||||
|
0.9765
|
||||||
|
3.1026
|
||||||
|
1.8572
|
||||||
|
1.3165
|
||||||
|
-0.6144
|
||||||
|
0.1032
|
||||||
|
0.3729
|
||||||
|
2.5327
|
||||||
|
7.3857
|
||||||
|
9.4892
|
||||||
|
];
|
||||||
|
|
||||||
|
% perform the task
|
||||||
|
for polydeg = 0:3
|
||||||
|
% obtain factors of approximating polynomial
|
||||||
|
[factors, error, gramcond] = approximate(taskfunc, polydeg);
|
||||||
|
|
||||||
|
% print error and condition number
|
||||||
|
disp(['Approximation degree ', num2str(polydeg), ':']);
|
||||||
|
disp(['Error: ', num2str(error)]);
|
||||||
|
disp(['Condition number: ', num2str(gramcond)]);
|
||||||
|
|
||||||
|
% plot data points
|
||||||
|
figure;
|
||||||
|
grid on;
|
||||||
|
hold on;
|
||||||
|
title(['Polynomial approximation of the function (degree ', ...
|
||||||
|
num2str(polydeg), ')']);
|
||||||
|
scatter(taskfunc(:, 1), taskfunc(:, 2));
|
||||||
|
|
||||||
|
% plot approximation
|
||||||
|
x = taskfunc(1):0.05:taskfunc(end, 1);
|
||||||
|
y = evalapprox(factors, x);
|
||||||
|
plot(x, y);
|
||||||
|
|
||||||
|
% finish and print graph
|
||||||
|
hold off;
|
||||||
|
set(gcf, 'PaperPosition', [0 0 6 4]);
|
||||||
|
set(gcf, 'PaperSize', [6 4]);
|
||||||
|
%print(['report/approx', num2str(polydeg)], '-dpdf');
|
||||||
|
end
|
||||||
|
|
||||||
|
% find the approximating polynomial of the given degree
|
||||||
|
function [factors, error, gramcond] = approximate(func, polydeg)
|
||||||
|
% define the A matrix used for solving the error minimization problem
|
||||||
|
A = zeros(size(func, 1), polydeg + 1);
|
||||||
|
|
||||||
|
% calculate cells of A using natural basis
|
||||||
|
for row = 1:size(A, 1)
|
||||||
|
for col = 1:size(A, 2)
|
||||||
|
A(row, col) = func(row, 1) ^ (col - 1);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% solve least-square problem using QRdash decomposition
|
||||||
|
[Q, eqsys, invqtq] = QRDecomposition(A);
|
||||||
|
eqsys(:, end + 1) = invqtq * Q' * func(:, 2);
|
||||||
|
factors = backSubstitution(eqsys);
|
||||||
|
|
||||||
|
% calculate error and condition number of Gram's matrix
|
||||||
|
error = norm(func(:, 2) - A * factors);
|
||||||
|
gramcond = cond(A' * A);
|
||||||
|
end
|
||||||
|
|
||||||
|
% evaluate the value of an approximation at the given x
|
||||||
|
function y = evalapprox(factors, xarray)
|
||||||
|
y = zeros(1, size(xarray, 2));
|
||||||
|
|
||||||
|
for xi = 1:size(xarray, 2)
|
||||||
|
for i = 1:size(factors, 1)
|
||||||
|
y(xi) = y(xi) + factors(i) * xarray(xi) ^ (i - 1);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
104
ENUME/projectC/task2ode.asv
Normal file
104
ENUME/projectC/task2ode.asv
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
% functions of the ODE system and initial values
|
||||||
|
sysfuncts = {
|
||||||
|
@(x) x(2) + x(1) * (0.5 - x(1)^2 - x(2)^2);
|
||||||
|
@(x) -x(1) + x(2) * (0.5 - x(1)^2 - x(2)^2)
|
||||||
|
};
|
||||||
|
initvalues = [0; 12];
|
||||||
|
interval = [0; 15];
|
||||||
|
|
||||||
|
% define available algorithms
|
||||||
|
algorithms = {
|
||||||
|
'RK4', @rk4, [0.01, 0.013408];
|
||||||
|
'Adams PC', @adamspc, [0.002, 0.01305]
|
||||||
|
};
|
||||||
|
|
||||||
|
% solve ODE using different algorithms and step sizes
|
||||||
|
for alg = 1:size(algorithms, 1)
|
||||||
|
[algname, algfunc, stepsizes] = algorithms{alg, :};
|
||||||
|
|
||||||
|
% solve using the given algorithm for each step size
|
||||||
|
stepresults = cell(size(stepsizes, 2), 3);
|
||||||
|
stepnames = {'optimal step', 'larger step'};
|
||||||
|
for stepno = 1:size(stepsizes, 2)
|
||||||
|
result = algfunc(sysfuncts, initvalues, interval, stepsizes(stepno));
|
||||||
|
stepresults(stepno, :) = { ...
|
||||||
|
stepsizes(stepno), ...
|
||||||
|
stepnames{stepno}, ...
|
||||||
|
result};
|
||||||
|
end
|
||||||
|
|
||||||
|
% plot each component against time
|
||||||
|
for eqnum = 1:size(sysfuncts, 1)
|
||||||
|
% begin plot
|
||||||
|
figure; grid on; hold on;
|
||||||
|
title([algname, ', x_', num2str(eqnum), ' against time']);
|
||||||
|
set(gcf, 'PaperPosition', [0 0 6 4]);
|
||||||
|
set(gcf, 'PaperSize', [6 4]);
|
||||||
|
|
||||||
|
% plot component for each step size
|
||||||
|
for stepresult = stepresults'
|
||||||
|
plot(stepresult{3}(1, :), stepresult{3}(eqnum + 1, :));
|
||||||
|
end
|
||||||
|
|
||||||
|
% finish plot
|
||||||
|
hold off;
|
||||||
|
legend(stepresults{:, 2});
|
||||||
|
% %print(['report/', func2str(algfunc), 'x', num2str(eqnum)], '-dpdf');
|
||||||
|
end
|
||||||
|
|
||||||
|
% plot first two components against each other
|
||||||
|
figure; grid on; hold on;
|
||||||
|
title([algname, ' trajectory plot (x_2 against x_1)']);
|
||||||
|
set(gcf, 'PaperPosition', [0 0 6 4]);
|
||||||
|
set(gcf, 'PaperSize', [6 4]);
|
||||||
|
|
||||||
|
% plot for each step size
|
||||||
|
for stepresult = stepresults'
|
||||||
|
plot(stepresult{3}(2, :), stepresult{3}(3, :));
|
||||||
|
end
|
||||||
|
|
||||||
|
% finish plot
|
||||||
|
hold off;
|
||||||
|
legend(stepresults{:, 2});
|
||||||
|
% %print(['report/', func2str(algfunc), 'traj'], '-dpdf');
|
||||||
|
end
|
||||||
|
|
||||||
|
% solve ODE using RK4 with automatic step size
|
||||||
|
[result, sizes, errors] = rk4auto(sysfuncts, initvalues, interval, ...
|
||||||
|
1e-5, 10e-10, 10e-10);
|
||||||
|
|
||||||
|
% plot trajectory
|
||||||
|
figure;
|
||||||
|
plot(result(2, :), result(3, :));
|
||||||
|
grid on;
|
||||||
|
title('RK4 auto-step trajectory plot (x_2 against x_1)');
|
||||||
|
set(gcf, 'PaperPosition', [0 0 6 4]);
|
||||||
|
set(gcf, 'PaperSize', [6 4]);
|
||||||
|
%%print(['report/', 'rk4autotraj'], '-dpdf');
|
||||||
|
|
||||||
|
% plot statistics
|
||||||
|
stats = {
|
||||||
|
"RK4 auto-step step size", "rk4sizes", sizes;
|
||||||
|
"RK4 auto-step approximation error", "rk4errors", errors
|
||||||
|
};
|
||||||
|
for stat = stats'
|
||||||
|
figure;
|
||||||
|
plot(result(1, 2:(end - 1)), stat{3});
|
||||||
|
grid on;
|
||||||
|
title(stat{1});
|
||||||
|
set(gcf, 'PaperPosition', [0 0 6 4]);
|
||||||
|
set(gcf, 'PaperSize', [6 4]);
|
||||||
|
% %print(strcat("report/", stat{2}), '-dpdf');
|
||||||
|
end
|
||||||
|
|
||||||
|
% compare results with ODE45
|
||||||
|
odefun = @(t, x) [ sysfuncts{1}(x); sysfuncts{2}(x) ];
|
||||||
|
odeoptions = odeset('RelTol', 10e-10, 'AbsTol', 10e-10);
|
||||||
|
[t, x] = ode45(odefun, interval, initvalues, odeoptions);
|
||||||
|
figure;
|
||||||
|
plot(x(:, 1), x(:, 2));
|
||||||
|
grid on;
|
||||||
|
title('ODE45 trajectory plot (x_2 against x_1)');
|
||||||
|
set(gcf, 'PaperPosition', [0 0 6 4]);
|
||||||
|
set(gcf, 'PaperSize', [6 4]);
|
||||||
|
%print('report/ode45', '-dpdf');
|
||||||
104
ENUME/projectC/task2ode.m
Normal file
104
ENUME/projectC/task2ode.m
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
% functions of the ODE system and initial values
|
||||||
|
sysfuncts = {
|
||||||
|
@(x) x(2) + x(1) * (0.5 - x(1)^2 - x(2)^2);
|
||||||
|
@(x) -x(1) + x(2) * (0.5 - x(1)^2 - x(2)^2)
|
||||||
|
};
|
||||||
|
initvalues = [0; 12];
|
||||||
|
interval = [0; 15];
|
||||||
|
|
||||||
|
% define available algorithms
|
||||||
|
algorithms = {
|
||||||
|
'RK4', @rk4, [0.01, 0.013408];
|
||||||
|
'Adams PC', @adamspc, [0.002, 0.01305]
|
||||||
|
};
|
||||||
|
|
||||||
|
% solve ODE using different algorithms and step sizes
|
||||||
|
for alg = 1:size(algorithms, 1)
|
||||||
|
[algname, algfunc, stepsizes] = algorithms{alg, :};
|
||||||
|
|
||||||
|
% solve using the given algorithm for each step size
|
||||||
|
stepresults = cell(size(stepsizes, 2), 3);
|
||||||
|
stepnames = {'optimal step', 'larger step'};
|
||||||
|
for stepno = 1:size(stepsizes, 2)
|
||||||
|
result = algfunc(sysfuncts, initvalues, interval, stepsizes(stepno));
|
||||||
|
stepresults(stepno, :) = { ...
|
||||||
|
stepsizes(stepno), ...
|
||||||
|
stepnames{stepno}, ...
|
||||||
|
result};
|
||||||
|
end
|
||||||
|
|
||||||
|
% plot each component against time
|
||||||
|
for eqnum = 1:size(sysfuncts, 1)
|
||||||
|
% begin plot
|
||||||
|
figure; grid on; hold on;
|
||||||
|
title([algname, ', x_', num2str(eqnum), ' against time']);
|
||||||
|
set(gcf, 'PaperPosition', [0 0 6 4]);
|
||||||
|
set(gcf, 'PaperSize', [6 4]);
|
||||||
|
|
||||||
|
% plot component for each step size
|
||||||
|
for stepresult = stepresults'
|
||||||
|
plot(stepresult{3}(1, :), stepresult{3}(eqnum + 1, :));
|
||||||
|
end
|
||||||
|
|
||||||
|
% finish plot
|
||||||
|
hold off;
|
||||||
|
legend(stepresults{:, 2});
|
||||||
|
% %print(['report/', func2str(algfunc), 'x', num2str(eqnum)], '-dpdf');
|
||||||
|
end
|
||||||
|
|
||||||
|
% plot first two components against each other
|
||||||
|
figure; grid on; hold on;
|
||||||
|
title([algname, ' trajectory plot (x_2 against x_1)']);
|
||||||
|
set(gcf, 'PaperPosition', [0 0 6 4]);
|
||||||
|
set(gcf, 'PaperSize', [6 4]);
|
||||||
|
|
||||||
|
% plot for each step size
|
||||||
|
for stepresult = stepresults'
|
||||||
|
plot(stepresult{3}(2, :), stepresult{3}(3, :));
|
||||||
|
end
|
||||||
|
|
||||||
|
% finish plot
|
||||||
|
hold off;
|
||||||
|
legend(stepresults{:, 2});
|
||||||
|
% %print(['report/', func2str(algfunc), 'traj'], '-dpdf');
|
||||||
|
end
|
||||||
|
|
||||||
|
% solve ODE using RK4 with automatic step size
|
||||||
|
[result, sizes, errors] = rk4auto(sysfuncts, initvalues, interval, ...
|
||||||
|
1e-5, 10e-10, 10e-10);
|
||||||
|
|
||||||
|
% plot trajectory
|
||||||
|
figure;
|
||||||
|
plot(result(2, :), result(3, :));
|
||||||
|
grid on;
|
||||||
|
title('RK4 auto-step trajectory plot (x_2 against x_1)');
|
||||||
|
set(gcf, 'PaperPosition', [0 0 6 4]);
|
||||||
|
set(gcf, 'PaperSize', [6 4]);
|
||||||
|
%%print(['report/', 'rk4autotraj'], '-dpdf');
|
||||||
|
|
||||||
|
% plot statistics
|
||||||
|
stats = {
|
||||||
|
"RK4 auto-step step size", "rk4sizes", sizes;
|
||||||
|
"RK4 auto-step approximation error", "rk4errors", errors
|
||||||
|
};
|
||||||
|
for stat = stats'
|
||||||
|
figure;
|
||||||
|
plot(result(1, 2:(end - 1)), stat{3});
|
||||||
|
grid on;
|
||||||
|
title(stat{1});
|
||||||
|
set(gcf, 'PaperPosition', [0 0 6 4]);
|
||||||
|
set(gcf, 'PaperSize', [6 4]);
|
||||||
|
% %print(strcat("report/", stat{2}), '-dpdf');
|
||||||
|
end
|
||||||
|
|
||||||
|
% compare results with ODE45
|
||||||
|
odefun = @(t, x) [ sysfuncts{1}(x); sysfuncts{2}(x) ];
|
||||||
|
odeoptions = odeset('RelTol', 10e-10, 'AbsTol', 10e-10);
|
||||||
|
[t, x] = ode45(odefun, interval, initvalues, odeoptions);
|
||||||
|
figure;
|
||||||
|
plot(x(:, 1), x(:, 2));
|
||||||
|
grid on;
|
||||||
|
title('ODE45 trajectory plot (x_2 against x_1)');
|
||||||
|
set(gcf, 'PaperPosition', [0 0 6 4]);
|
||||||
|
set(gcf, 'PaperSize', [6 4]);
|
||||||
|
%print('report/ode45', '-dpdf');
|
||||||
Loading…
Reference in New Issue
Block a user