@@ -0,0 +1,170 @@ | |||
% | |||
% Optimization Techniques Work 2 report | |||
% | |||
% authors: | |||
% Χρήστος Χουτουρίδης ΑΕΜ 8997 | |||
% cchoutou@ece.auth.gr | |||
\documentclass[a4paper, 11pt]{AUTHReport} | |||
% Document configuration | |||
\AuthorName{Χρήστος Χουτουρίδης} | |||
\AuthorMail{cchoutou@ece.auth.gr} | |||
\AuthorAEM{8997} | |||
% \CoAuthorName{CoAuthor Name} | |||
% \CoAuthorMail{CoAuthor Mail} | |||
% \CoAuthorAEM{AEM} | |||
% \WorkGroup{Ομάδα Χ} | |||
\DocTitle{1η Εργαστηριακή Άσκηση} | |||
\DocSubTitle{Ελαχιστοποίηση συναρτήσεων πολλών μεταβλητών χωρίς περιορισμούς με χρήση παραγώγων} | |||
\Department{Τμήμα ΗΜΜΥ. Τομέας Ηλεκτρονικής} | |||
\ClassName{Τεχνικές Βελτιστοποίησης} | |||
\InstructorName{Γ. Ροβιθάκης} | |||
\InstructorMail{rovithak@auth.gr} | |||
\CurrentDate{\today} | |||
\usepackage{capt-of} | |||
\usepackage{enumitem} | |||
\usepackage{tabularx} | |||
\usepackage{array} | |||
\begin{document} | |||
\setlist[itemize]{topsep=0pt, partopsep=0pt, itemsep=3pt, parsep=3pt} | |||
\InsertTitle | |||
%\tableofcontents | |||
\sloppy | |||
\section{Εισαγωγή} | |||
Η παρούσα εργασία αφορά ... | |||
\section{Παραδοτέα} | |||
Τα παραδοτέα της εργασίας αποτελούνται από: | |||
\begin{itemize} | |||
\item Την παρούσα αναφορά. | |||
\item Τον κατάλογο \textbf{scripts/}, που περιέχει τον κώδικα της MATLAB. | |||
\item Το \href{https://git.hoo2.net/hoo2/OptimizationTechniques/src/branch/master/Work%202}{σύνδεσμο} με το αποθετήριο που περιέχει όλο το project με τον κώδικα της MATLAB, της αναφοράς και τα παραδοτέα. | |||
\end{itemize} | |||
\section{Προγραμματιστική προσέγγιση} | |||
Για τον προγραμματισμό και εκτέλεση των μεθόδων της παρούσας εργασίας έγινε χρήση της MATLAB. | |||
Στον κατάλογο \textbf{scripts}, περιέχονται όλες οι μέθοδοι με τη μορφή συναρτήσεων καθώς και scripts που τις καλούν. | |||
Το κεντρικό script που εκτελεί τον κώδικα όλης της εργασίας είναι το \textbf{Work1.m}. | |||
Στην παρούσα εργασία η υλοποίηση του κώδικα δεν ακολουθεί επακριβώς τη ροή των θεμάτων της εκφώνησης. | |||
Αντίθετα επιλέχθηκε μια διαφορετική προγραμματιστική προσέγγιση που ενοποιεί τα κοινά ζητούμενα από όλα τα θέματα. | |||
Πιο συγκεκριμένα. | |||
\subsection{Πολυμορφική κλήση μεθόδων} | |||
\label{subsec:polymorphic-calls} | |||
Εφόσον για κάθε θέμα ένα από τα ζητούμενα ήταν ο υπολογισμός και η απεικόνιση του αριθμού των κλήσεων των μεθόδων για διαφορετικές τιμές της παραμέτρου lambda, δημιουργήσαμε τη συνάρτηση \textbf{\emph{iterations\_over\_lambda()}} η οποία καλεί μια \textit{δοθείσα} μέθοδο για κάθε μία από τις αντικειμενικές συναρτήσεις και απεικονίζει τα αποτελέσματα. | |||
Ομοίως, για κάθε θέμα, ζητούμενο ήταν η απεικόνιση της σύγκλισης των διαστημάτων σε κάθε επανάληψη. | |||
Αντίστοιχα λοιπόν δημιουργήσαμε τη συνάρτηση \textbf{\emph{interval\_over\_iterations()}} η οποία ομοίως καλεί μια \textit{δοθείσα} μέθοδο για κάθε μία από τις αντικειμενικές συναρτήσεις. | |||
Τέλος το κεντρικό script της εργασίας “Work1.m” καλεί σε βρόχο την κάθε μία από τις παραπάνω συναρτήσεις, για κάθε μία από τις μεθόδους, την οποία και περνάει ως όρισμα στη συνάρτηση. | |||
\par | |||
Οι παραπάνω συναρτήσεις λοιπόν, δέχονται τις μεθόδους ως ορίσματα και τις καλούν με αγνωστικιστικό τρόπο εσωτερικά. | |||
Για το λόγο αυτό υλοποιήσαμε τις μεθόδους ώστε να έχουν \textbf{κοινό interface} ορισμάτων και επιστροφών, με αποτέλεσμα κάποιες μέθοδοι να έχουν ορίσματα που δεν χρησιμοποιούνται. | |||
Το κέρδος όμως είναι ο πολυμορφικός τρόπος κλήσης των διαφορετικών μεθόδων, που απλοποιεί και μικραίνει τον κώδικα. \\ | |||
Έτσι όλες οι συναρτήσεις που υλοποιούν τις μεθόδους υπολογισμού ελαχίστου έχουν ως ορίσματα: | |||
\begin{itemize} | |||
\item \textbf{fun\_expr}: Η αναπαράσταση της αντικειμενικής συνάρτησης ως symbolic expression. | |||
\item \textbf{alpha}: Η αρχή του διαστήματος αναζήτησης. | |||
\item \textbf{beta}: Το τέλος του διαστήματος αναζήτησης. | |||
\item \textbf{epsilon}: Η απόσταση από το μέσω του διαστήματος για τη μέθοδο της διχοτόμου και το μήκος του διαστήματος του τελικού βήματος για τη μέθοδο Fibonacci. \\ | |||
\textit{\underline{Σημείωση}}: Στις υπόλοιπες μεθόδους το όρισμα δεν χρησιμοποιείται. | |||
\item \textbf{lambda}: Η ζητούμενη ακρίβεια. | |||
\end{itemize} | |||
Επίσεις όλες οι συναρτήσεις επιστρέφουν \textbf{[a, b, k, n]}: | |||
\begin{itemize} | |||
\item \textbf{a}: Το διάνυσμα με όλες τις τιμές που παίρνει η αρχή του διαστήματος αναζήτησης σε κάθε επανάληψη. | |||
\item \textbf{b}: Το διάνυσμα με όλες τις τιμές που παίρνει το τέλος του διαστήματος αναζήτησης σε κάθε επανάληψη. | |||
\item \textbf{k}: Ο αριθμός των επαναλήψεων μέχρι να τερματιστεί ο αλγόριθμος. | |||
\item \textbf{n}: Ο αριθμός των κλήσεων της αντικειμενικής συνάρτησης. | |||
\end{itemize} | |||
\subsection{Symbolic expression functions} | |||
Μία ακόμη προγραμματιστική τεχνική που ακολουθήθηκε είναι η χρήση \textbf{symbolic expression} για την αναπαράσταση των διαφορετικών αντικειμενικών συναρτήσεων. | |||
Ο λόγος που επιλέχθηκε είναι η \textbf{δυνατότητα εξαγωγής ενός symbolic expression που αναπαριστά την παράγωγο μιας συνάρτησης} από την MATLAB, κάνοντας χρήση της εντολής diff(). | |||
Αν αντίθετα χρησιμοποιούσαμε απλές συναρτήσεις, πολυώνυμα ή lambdas για την αναπαράσταση των αντικειμενικών συναρτήσεων, τότε για τον υπολογισμό της παραγώγου θα έπρεπε: | |||
\begin{itemize} | |||
\item Είτε να υπολογίζαμε αριθμητικά την παράγωγο μέσα στη μέθοδο της διχοτόμου, κάτι που θα εισήγαγε \textit{\textbf{αχρείαστο αριθμητικό σφάλμα}}. | |||
\item Είτε να κάναμε χρήση τριών επιπλέων συναρτήσεων (ή πολυωνύμων) για την αναπαράσταση των παραγώγων των αντικειμενικών συναρτήσεων, κάτι που ουσιαστικά θα δημιουργούσε \textit{\textbf{πλεονασμό πληροφορίας}}. | |||
\end{itemize} | |||
Η αναπαράσταση όμως με χρήση symbolic expression είναι πιο “βαριά” όταν χρειάζεται να υπολογίσουμε την τιμή μιας συνάρτησης σε κάποιο σημείο (subs(expr, number)). | |||
Αυτό είναι κάτι που χρειάζεται εκτενώς στον κώδικά μας. | |||
Για το λόγο αυτό, ενώ οι συναρτήσεις δύνονται ως symbolic expressions, εσωτερικά στις μεθόδους και όταν πρέπει να καλεστούν, μετατρέπονται σε MATLAB functions. | |||
Έτσι έχουμε την ακριβή αναπαράσταση της παραγώγου ως συνάρτηση χωρίς να πληρώνουμε το κόστος της subs(). | |||
\section{Μέθοδος ...} | |||
\section{Σύγκριση των μεθόδων} | |||
Εκτελώντας όλους του αλγόριθμους για τα ίδια δεδομένα, \textbf{για τον αριθμό επαναλήψεων} έχουμε: \\ | |||
% Table with full width, centered content, and column width based on content | |||
\noindent | |||
\renewcommand{\arraystretch}{1.2} | |||
\begin{tabularx}{\textwidth}{% | |||
>{\raggedleft\arraybackslash}m{0.175\textwidth} | | |||
>{\centering\arraybackslash}m{0.175\textwidth} | | |||
>{\centering\arraybackslash}m{0.175\textwidth} | | |||
>{\centering\arraybackslash}m{0.175\textwidth} | | |||
>{\centering\arraybackslash}m{0.175\textwidth} | |||
} | |||
Εύρος αναζήτησης & Μέθ. Διχοτόμου & Μέθ. Χρυσού τομέα & Μέθ. Fibonacci & Μέθ. Διχοτόμου με Παρ. \\ | |||
\hline | |||
0.00210 & 17 & 17 & 18 & 12 \\ | |||
0.05105 & 8 & 11 & 11 & 8 \\ | |||
0.1 & 7 & 9 & 10 & 7 | |||
\end{tabularx} \\ [3ex] | |||
\par | |||
Ενώ ομοίως για τα ίδια δεδομένα για τον \textbf{αριθμό κλήσεων των αντικειμενικών συναρτήσεων} έχουμε: \\ | |||
\begin{tabularx}{\textwidth}{% | |||
>{\raggedleft\arraybackslash}m{0.175\textwidth} | | |||
>{\centering\arraybackslash}m{0.175\textwidth} | | |||
>{\centering\arraybackslash}m{0.175\textwidth} | | |||
>{\centering\arraybackslash}m{0.175\textwidth} | | |||
>{\centering\arraybackslash}m{0.175\textwidth} | |||
} | |||
Εύρος αναζήτησης & Μέθ. Διχοτόμου & Μέθ. Χρυσού τομέα & Μέθ. Fibonacci & Μέθ. Διχοτόμου με Παρ. \\ | |||
\hline | |||
0.00210 & 32 & 18 & 19 & 11 \\ | |||
0.1 & 12 & 10 & 11 & 6 | |||
\end{tabularx} \\ [3ex] | |||
\par | |||
\underline{Παρατηρήσεις:} | |||
\begin{itemize} | |||
\item H \textbf{αποδοτικότερη} μέθοδος τόσο στον αριθμό των επαναλήψεων όσο και στον αριθμό κλήσεων της αντικειμενικής συνάρτησης είναι η \textbf{μέθοδος της διχοτόμου με χρήση παραγώγου}. | |||
\item Αντίστοιχα η πιο \textbf{\emph{“αδύναμη”}} μέθοδος φαίνεται να είναι η μέθοδος της \textbf{διχοτόμου χωρίς τη χρήση παραγώγου}. | |||
\item Οι μέθοδοι του χρυσού τομέα και Fibonacci παρουσιάζουν \textbf{παρόμοια} συμπεριφορά τόσο \textbf{όσων αφορά τον αριθμό των επαναλήψεων όσο και στον αριθμό των κλήσεων} της αντικειμενικής συνάρτησης και τοποθετούνται στη μέση όσον αφορά τις επιδόσεις τους. | |||
\item Ένα ακόμη ενδιαφέρον στοιχείο είναι ότι ενώ οι δύο προαναφερθείσες μέθοδοι, θεωρητικά βελτιώνουν όχι μόνο τον αριθμό των κλήσεων των συναρτήσεων αλλά και τον αριθμό των επαναλήψεων. | |||
Αυτό όμως δεν το βλέπουμε να επιβεβαιώνεται. | |||
Βλέπουμε δηλαδή να βελτιώνεται \textbf{μόνο ο αριθμός κλήσεων} και όχι των επαναλήψεων. | |||
Τουλάχιστον αυτό συμβαίνει για το μικρό διάστημα αναζήτησης της εργασίας. | |||
\item Τέλος ενώ θεωρητικά η μέθοδος Fibonacci για μικρό αριθμό διάστημα αναζήτησης αναμένεται να έχει λιγότερες επαναλήψεις από την μέθοδο χρυσού τομέα, κάτι τέτοιο δεν φαίνεται να επιβεβαιώνεται. | |||
\end{itemize} | |||
Φυσικά, για τις τελευταίες δύο “παρεκκλίσεις” υπάρχει πάντα η περίπτωση του προβλήματος στην υλοποίηση, την οποία δεν μπορούμε να αποκλείσουμε. | |||
\section{Συμπεράσματα} | |||
Οι μέθοδοι της παρούσας εργασίας αποτελούν βασικές τεχνικές για την εύρεση του τοπικού ελαχίστου μιας κυρτής συνάρτησης σε ένα δοσμένο διάστημα. | |||
Κάθε μέθοδος έχει τα δικά της πλεονεκτήματα και περιορισμούς. | |||
Η μέθοδος διχοτόμου είναι απλή και σταθερή, αλλά απαιτεί έναν ικανοποιητικό αριθμό επαναλήψεων. | |||
Η μέθοδος χρυσού τομέα είναι πιο αποδοτική όσον αφορά τη σύγκλιση με λιγότερες κλήσεις στη συνάρτηση, αλλά εξαρτάται από τον ακριβή υπολογισμό των σημείων του διαστήματος. | |||
Η μέθοδος Fibonacci έχει σταθερή και προβλέψιμη αριθμητική συμπεριφορά, όμως η ταχύτητα σύγκλισης είναι σχετικά χαμηλότερη σε σχέση με άλλες. | |||
Η μέθοδος διχοτόμου με παράγωγο, προσφέρει γραμμική σύγκλιση, παρέχοντας τη δυνατότητα γρηγορότερης αναγνώρισης του ελαχίστου, αν και εξαρτάται από την ύπαρξη της παραγώγου και απαιτεί έναν αξιόπιστο υπολογισμό αυτής. | |||
Συνολικά, η επιλογή της κατάλληλης μεθόδου εξαρτάται από τη συγκεκριμένη εφαρμογή, την ακρίβεια και τις υπολογιστικές δυνατότητες, καθώς και την εγγύτητα της συνάρτησης στην κυρτότητα. | |||
\end{document} |
@@ -0,0 +1,22 @@ | |||
% Given environment | |||
clear; | |||
% Setup the function under test | |||
syms x y; | |||
fexpr = x^5 * exp(-x^2 - y^2); | |||
title_fun = "$f(x,y) = x^5 \cdot e^{-x^2 - y^2}$"; | |||
% Calculate the gradient and Hessian | |||
grad_fexpr = gradient(fexpr, [x, y]); % Gradient of f | |||
hessian_fexpr = hessian(fexpr, [x, y]); % Hessian of f | |||
% Convert symbolic expressions to MATLAB functions | |||
fun = matlabFunction(fexpr, 'Vars', [x, y]); % Function | |||
grad_fun = matlabFunction(grad_fexpr, 'Vars', [x, y]); % Gradient | |||
hessian_fun = matlabFunction(hessian_fexpr, 'Vars', [x, y]); % Hessian | |||
% Amijo globals | |||
global amijo_beta amijo_sigma | |||
%fixed step size globals | |||
global gamma_fixed_step |
@@ -0,0 +1,54 @@ | |||
% Define environment (functions, gradients etc...) | |||
GivenEnv | |||
% Define parameters | |||
max_iter = 300; % Maximum iterations | |||
tol = 1e-4; % Tolerance | |||
% Methods tuning | |||
amijo_beta = 0.5; % Armijo reduction factor | |||
amijo_sigma = 0.1; % Armijo condition constant | |||
m = 0.01; | |||
% Point x0 = (0, 0) | |||
% x0 = [0, 0]; | |||
% Point x0 = (0, 0) | |||
x0s = [0, 0; -1, 1 ; 1, -1]; % Initial points | |||
for i = 1:size(x0s, 1) | |||
x0 = x0s(i, :); | |||
point_str = "[" + x0(1) + ", " + x0(2) + "]"; | |||
% Find the best fixed gamma | |||
k = zeros(100, 1); | |||
j = 1; | |||
n = linspace(0.1, 1.5, 100); | |||
for g = n | |||
gamma_fixed_step = g; | |||
[~, ~, k(j)] = lev_mar(fun, grad_fun, hessian_fun, m, x0, tol, max_iter, 'fixed'); | |||
j = j + 1; | |||
end | |||
plotIterationsOverGamma(n, k, "Iteration for different $\gamma$ values", "LevMar_Iter_o_gamma_" + i + ".png"); | |||
[~, j] = min(k); | |||
gamma_fixed_step = n(j); | |||
[x_fixed, f_fixed, kk] = lev_mar(fun, grad_fun, hessian_fun, m, x0, tol, max_iter, 'fixed'); | |||
fprintf('Fixed step: Initial point (%f, %f), steps:%d, Final (x,y)=(%f, %f), f(x,y)=%f\n', x0, kk, x_fixed(end, :), f_fixed(end)); | |||
plotPointsOverContour(x_fixed, fun, [-2, 2], [-3, 3], 100, point_str + ": LevMar $\gamma$ = " + gamma_fixed_step, "LevMar_fixed_" + i + ".png"); | |||
% Minimized f | |||
[x_minimized, f_minimized, kk] = lev_mar(fun, grad_fun, hessian_fun, m, x0, tol, max_iter, 'minimized'); | |||
fprintf('Minimized f(g): Initial point (%f, %f), steps:%d, Final (x,y)=(%f, %f), f(x,y)=%f\n', x0, kk, x_minimized(end, :), f_minimized(end)); | |||
plotPointsOverContour(x_minimized, fun, [-2, 2], [-3, 3], 100, point_str + ": LevMar minimized $f(x_k + \gamma_kd_k)$", "LevMar_minimized_" + i + ".png"); | |||
% Armijo Rule | |||
[x_armijo, f_armijo, kk] = lev_mar(fun, grad_fun, hessian_fun, m, x0, tol, max_iter, 'armijo'); | |||
fprintf('Armijo step: Initial point (%f, %f), steps:%d, Final (x,y)=(%f, %f), f(x,y)=%f\n', x0, kk, x_armijo(end, :), f_armijo(end)); | |||
plotPointsOverContour(x_armijo, fun, [-2, 2], [-3, 3], 100, point_str + ": LevMar Armijo method", "LevMar_armijo_" + i + ".png"); | |||
end | |||
@@ -0,0 +1,52 @@ | |||
% Define environment (functions, gradients etc...) | |||
GivenEnv | |||
% Define parameters | |||
max_iter = 300; % Maximum iterations | |||
tol = 1e-4; % Tolerance | |||
% Methods tuning | |||
amijo_beta = 0.5; % Armijo reduction factor | |||
amijo_sigma = 0.1; % Armijo condition constant | |||
% Point x0 = (0, 0) | |||
% x0 = [0, 0]; | |||
% Point x0 = (0, 0) | |||
x0s = [0, 0; -1, 1 ; 1, -1]; % Initial points | |||
for i = 1:size(x0s, 1) | |||
x0 = x0s(i, :); | |||
point_str = "[" + x0(1) + ", " + x0(2) + "]"; | |||
% Find the best fixed gamma | |||
k = zeros(100, 1); | |||
j = 1; | |||
n = linspace(0.1, 1.5, 100); | |||
for g = n | |||
gamma_fixed_step = g; | |||
[~, ~, k(j)] = newton(fun, grad_fun, hessian_fun, x0, tol, max_iter, 'fixed'); | |||
j = j + 1; | |||
end | |||
plotIterationsOverGamma(n, k, "Iteration for different $\gamma$ values", "Newton_Iter_o_gamma_" + i + ".png"); | |||
[~, j] = min(k); | |||
gamma_fixed_step = n(j); | |||
[x_fixed, f_fixed, kk] = newton(fun, grad_fun, hessian_fun, x0, tol, max_iter, 'fixed'); | |||
fprintf('Fixed step: Initial point (%f, %f), steps:%d, Final (x,y)=(%f, %f), f(x,y)=%f\n', x0, kk, x_fixed(end, :), f_fixed(end)); | |||
plotPointsOverContour(x_fixed, fun, [-2, 2], [-3, 3], 100, point_str + ": Newton $\gamma$ = " + gamma_fixed_step, "Newton_fixed_" + i + ".png"); | |||
% Minimized f | |||
[x_minimized, f_minimized, kk] = newton(fun, grad_fun, hessian_fun, x0, tol, max_iter, 'minimized'); | |||
fprintf('Minimized f(g): Initial point (%f, %f), steps:%d, Final (x,y)=(%f, %f), f(x,y)=%f\n', x0, kk, x_minimized(end, :), f_minimized(end)); | |||
plotPointsOverContour(x_minimized, fun, [-2, 2], [-3, 3], 100, point_str + ": Newton minimized $f(x_k + \gamma_kd_k)$", "Newton_minimized_" + i + ".png"); | |||
% Armijo Rule | |||
[x_armijo, f_armijo, kk] = newton(fun, grad_fun, hessian_fun, x0, tol, max_iter, 'armijo'); | |||
fprintf('Armijo step: Initial point (%f, %f), steps:%d, Final (x,y)=(%f, %f), f(x,y)=%f\n', x0, kk, x_armijo(end, :), f_armijo(end)); | |||
plotPointsOverContour(x_armijo, fun, [-2, 2], [-3, 3], 100, point_str + ": Newton Armijo method", "Newton_armijo_" + i + ".png"); | |||
end | |||
@@ -0,0 +1,52 @@ | |||
% Define environment (functions, gradients etc...) | |||
GivenEnv | |||
% Define parameters | |||
max_iter = 300; % Maximum iterations | |||
tol = 1e-4; % Tolerance | |||
% Methods tuning | |||
amijo_beta = 0.5; % Armijo reduction factor | |||
amijo_sigma = 0.1; % Armijo condition constant | |||
% Point x0 = (0, 0) | |||
% x0 = [0, 0]; | |||
% Point x0 = (0, 0) | |||
x0s = [-1, 1 ; 1, -1]; % Initial points | |||
for i = 1:size(x0s, 1) | |||
x0 = x0s(i, :); | |||
point_str = "[" + x0(1) + ", " + x0(2) + "]"; | |||
% Find the best fixed gamma | |||
k = zeros(100, 1); | |||
j = 1; | |||
n = linspace(0.1, 1.5, 100); | |||
for g = n | |||
gamma_fixed_step = g; | |||
[~, ~, k(j)] = steepest_descent(fun, grad_fun, x0, tol, max_iter, 'fixed'); | |||
j = j + 1; | |||
end | |||
plotIterationsOverGamma(n, k, "Iteration for different $\gamma$ values", "StDes_Iter_o_gamma_" + i + ".png"); | |||
[~, j] = min(k); | |||
gamma_fixed_step = n(j); | |||
[x_fixed, f_fixed, kk] = steepest_descent(fun, grad_fun, x0, tol, max_iter, 'fixed'); | |||
fprintf('Fixed step: Initial point (%f, %f), steps:%d, Final (x,y)=(%f, %f), f(x,y)=%f\n', x0, kk, x_fixed(end, :), f_fixed(end)); | |||
plotPointsOverContour(x_fixed, fun, [-2, 2], [-2, 2], 100, point_str + ": Steepest descent $\gamma$ = " + gamma_fixed_step, "StDes_fixed_" + i + ".png"); | |||
% Minimized f | |||
[x_minimized, f_minimized, kk] = steepest_descent(fun, grad_fun, x0, tol, max_iter, 'minimized'); | |||
fprintf('Minimized f(g): Initial point (%f, %f), steps:%d, Final (x,y)=(%f, %f), f(x,y)=%f\n', x0, kk, x_minimized(end, :), f_minimized(end)); | |||
plotPointsOverContour(x_minimized, fun, [-2, 2], [-2, 2], 100, point_str + ": Steepest descent minimized $f(x_k + \gamma_kd_k)$", "StDes_minimized_" + i + ".png"); | |||
% Armijo Rule | |||
[x_armijo, f_armijo, kk] = steepest_descent(fun, grad_fun, x0, tol, max_iter, 'armijo'); | |||
fprintf('Armijo step: Initial point (%f, %f), steps:%d, Final (x,y)=(%f, %f), f(x,y)=%f\n', x0, kk, x_armijo(end, :), f_armijo(end)); | |||
plotPointsOverContour(x_armijo, fun, [-2, 2], [-2, 2], 100, point_str + ": Steepest descent Armijo method", "StDes_armijo_" + i + ".png"); | |||
end | |||
@@ -0,0 +1,26 @@ | |||
function [gamma] = gamma_armijo(f, grad_f, x0) | |||
% Calculates the best step based on amijo method | |||
% | |||
% f(xk− γk*∇f(xk)) ≤ f(xk) − σ*γk*∥∇f(xk)∥^2 | |||
% | |||
% f: Objective function | |||
% x0: Initial (x,y) point | |||
% beta: beta factor in (0, 1) | |||
% signam: sigma factor in (0,1) | |||
global amijo_beta | |||
global amijo_sigma | |||
gamma = 1; % Start with a step size of 1 | |||
grad = grad_f(x0(1), x0(2)); | |||
% Perform Armijo line search | |||
while f(x0(1) - gamma * grad(1), x0(2) - gamma * grad(2)) > ... | |||
f(x0(1), x0(2)) - amijo_sigma * gamma * norm(grad)^2 | |||
gamma = amijo_beta * gamma; % Reduce step size | |||
end | |||
end | |||
@@ -0,0 +1,12 @@ | |||
function [gamma] = gamma_fixed(~, ~, ~) | |||
% Return a fixed step | |||
% | |||
% This is for completion and code symmetry. | |||
% | |||
global gamma_fixed_step | |||
% Perform line search | |||
gamma = gamma_fixed_step; | |||
end |
@@ -0,0 +1,19 @@ | |||
function [gamma] = gamma_minimized(f, grad_f, x0) | |||
% Calculates the step based on minimizing f(xk− γ*∇f(xk)) | |||
% | |||
% | |||
% f: Objective function | |||
% grad_f: Gradient of objective function | |||
% x0: Initial (x,y) point | |||
% Define the line search function g(gamma) = f(x0 - gamma * grad) | |||
grad = grad_f(x0(1), x0(2)); | |||
g = @(gamma) f(x0(1) - gamma * grad(1), x0(2) - gamma * grad(2)); | |||
% Perform line search | |||
gamma = fminbnd(g, 0, 1); | |||
% ToDo: Check if we can use fmin_bisection_der | |||
% from the previous assigment here! | |||
end | |||
@@ -0,0 +1,49 @@ | |||
function [x_vals, f_vals, k] = lev_mar(f, grad_f, hessian_f, m, x0, tol, max_iter, mode) | |||
% f: Objective function | |||
% grad_f: Gradient of the function | |||
% hessian_f: Hessian of the function | |||
% x0: Initial point [x0, y0] | |||
% tol: Tolerance for stopping criterion | |||
% max_iter: Maximum number of iterations | |||
% x_vals: Vector with the (x,y) values until minimum | |||
% f_vals: Vector with f(x,y) values until minimum | |||
% k: Number of iterations | |||
if strcmp(mode, 'armijo') == 1 | |||
gamma_f = @(f, grad_f, x0) gamma_armijo(f, grad_f, x0); | |||
elseif strcmp(mode, 'minimized') == 1 | |||
gamma_f = @(f, grad_f, x0) gamma_minimized(f, grad_f, x0); | |||
else % mode == 'fixed' | |||
gamma_f = @(f, grad_f, x0) gamma_fixed(f, grad_f, x0); | |||
end | |||
x_vals = x0; % Store iterations | |||
f_vals = f(x0(1), x0(2)); | |||
for k = 1:max_iter | |||
grad = grad_f(x0(1), x0(2)); | |||
% Check for convergence | |||
if norm(grad) < tol | |||
break; | |||
end | |||
hess = hessian_f(x0(1), x0(2)); | |||
mI = m * eye(size(hess)); | |||
% Solve for search direction using Newton's step | |||
dk = - inv(hess + mI) * grad; | |||
% Calculate gamma | |||
gamma = gamma_f(f, grad_f, x0); | |||
x_next = x0 + gamma * dk'; % Update step | |||
f_next = f(x_next(1), x_next(2)); | |||
x0 = x_next; % Update point | |||
x_vals = [x_vals; x_next]; % Store values | |||
f_vals = [f_vals; f_next]; % Store function values | |||
end | |||
end | |||
@@ -0,0 +1,48 @@ | |||
function [x_vals, f_vals, k] = newton(f, grad_f, hessian_f, x0, tol, max_iter, mode) | |||
% f: Objective function | |||
% grad_f: Gradient of the function | |||
% hessian_f: Hessian of the function | |||
% x0: Initial point [x0, y0] | |||
% tol: Tolerance for stopping criterion | |||
% max_iter: Maximum number of iterations | |||
% x_vals: Vector with the (x,y) values until minimum | |||
% f_vals: Vector with f(x,y) values until minimum | |||
% k: Number of iterations | |||
if strcmp(mode, 'armijo') == 1 | |||
gamma_f = @(f, grad_f, x0) gamma_armijo(f, grad_f, x0); | |||
elseif strcmp(mode, 'minimized') == 1 | |||
gamma_f = @(f, grad_f, x0) gamma_minimized(f, grad_f, x0); | |||
else % mode == 'fixed' | |||
gamma_f = @(f, grad_f, x0) gamma_fixed(f, grad_f, x0); | |||
end | |||
x_vals = x0; % Store iterations | |||
f_vals = f(x0(1), x0(2)); | |||
for k = 1:max_iter | |||
grad = grad_f(x0(1), x0(2)); | |||
% Check for convergence | |||
if norm(grad) < tol | |||
break; | |||
end | |||
hess = hessian_f(x0(1), x0(2)); | |||
% Solve for search direction using Newton's step | |||
dk = - inv(hess) * grad; | |||
% Calculate gamma | |||
gamma = gamma_f(f, grad_f, x0); | |||
x_next = x0 + gamma * dk'; % Update step | |||
f_next = f(x_next(1), x_next(2)); | |||
x0 = x_next; % Update point | |||
x_vals = [x_vals; x_next]; % Store values | |||
f_vals = [f_vals; f_next]; % Store function values | |||
end | |||
end | |||
@@ -0,0 +1,42 @@ | |||
function plot3Dfun(fun, x_lim, y_lim, size, plot_title) | |||
% 3D plots a function | |||
% fun: The function to plot | |||
% x_lim: The range for x axis. ex: [-2, 2] | |||
% y_lim: The range for y axis. ex: [0, 2] | |||
% size: The number of points for each axis | |||
% plot_title: The latex title for the plot | |||
% | |||
% Generate a grid for x and y | |||
x_space = linspace(x_lim(1), x_lim(2), size); | |||
y_space = linspace(y_lim(1), y_lim(2), size); | |||
[X, Y] = meshgrid(x_space, y_space); | |||
% Evaluate the function on the grid | |||
Z = fun(X, Y); | |||
% 3D plot | |||
figure('Name', 'f(x,y)', 'NumberTitle', 'off'); | |||
set(gcf, 'Position', [100, 100, 960, 960]); % Set the figure size | |||
surf(X, Y, Z); | |||
% Customize the plot | |||
xlabel('x'); % Label for x-axis | |||
ylabel('y'); % Label for y-axis | |||
zlabel('f(x, y)'); % Label for z-axis | |||
title(plot_title, 'Interpreter', 'latex', 'FontSize', 16); % Title of the plot | |||
colorbar; | |||
% save the figure | |||
print(gcf, 'FunctionPlot.png', '-dpng', '-r300'); | |||
% Contours | |||
figure('Name', 'Contours of f(x,y)', 'NumberTitle', 'off'); | |||
set(gcf, 'Position', [100, 100, 1280, 1280]); % Set the figure size | |||
contour(X, Y, Z); | |||
xlabel('x'); % Label for x-axis | |||
ylabel('y'); % Label for y-axis | |||
title(plot_title, 'Interpreter', 'latex', 'FontSize', 20); % Title of the plot | |||
colorbar; | |||
print(gcf, 'ContoursPlot.png', '-dpng', '-r300'); | |||
end |
@@ -0,0 +1,19 @@ | |||
function plotIterationsOverGamma(gamma, iterations, plot_title, filename) | |||
% 3D plots a function | |||
% fun: The points to plot | |||
% contur_fun: The function for contour plot | |||
% x_lim: The range for x axis. ex: [-2, 2] | |||
% y_lim: The range for y axis. ex: [0, 2] | |||
% size: The number of points for each axis | |||
% plot_title: The latex title for the plot | |||
% filename: The filename to save the plot (if exists) | |||
% | |||
figure('Name', 'Iterations_over_gamma', 'NumberTitle', 'off'); | |||
set(gcf, 'Position', [100, 100, 960, 960]); % Set the figure size | |||
plot(gamma, iterations, '*r', 'LineWidth', 2); | |||
title(plot_title, 'Interpreter', 'latex', 'FontSize', 16); % Title of the plot | |||
xlabel('\gamma') ; | |||
ylabel('Iterations'); | |||
print(gcf, filename, '-dpng', '-r300'); | |||
end |
@@ -0,0 +1,40 @@ | |||
function plotPointsOverContour(points, contour_fun, x_lim, y_lim, size, plot_title, filename) | |||
% 3D plots a function | |||
% points: The points to plot | |||
% contur_fun: The function for contour plot | |||
% x_lim: The range for x axis. ex: [-2, 2] | |||
% y_lim: The range for y axis. ex: [0, 2] | |||
% size: The number of points for each axis | |||
% plot_title: The latex title for the plot | |||
% filename: The filename to save the plot (if exists) | |||
% | |||
% Generate a grid for x and y | |||
x_space = linspace(x_lim(1), x_lim(2), size); | |||
y_space = linspace(y_lim(1), y_lim(2), size); | |||
[X, Y] = meshgrid(x_space, y_space); | |||
% Evaluate the function on the grid | |||
Z = contour_fun(X, Y); | |||
% 2D plot | |||
figure('Name', '(x,y)', 'NumberTitle', 'off'); | |||
set(gcf, 'Position', [100, 100, 960, 960]); % Set the figure size | |||
plot(points(:, 1), points(:, 2), '-or'); | |||
hold on | |||
contour(X, Y, Z); | |||
% Customize the plot | |||
xlim(x_lim); | |||
ylim(y_lim); | |||
xlabel('x'); % Label for x-axis | |||
ylabel('y'); % Label for y-axis | |||
grid on | |||
title(plot_title, 'Interpreter', 'latex', 'FontSize', 16); % Title of the plot | |||
colorbar; | |||
% save the figure | |||
if strcmp(filename, '') == 0 | |||
print(gcf, filename, '-dpng', '-r300'); | |||
end | |||
end |
@@ -0,0 +1,44 @@ | |||
function [x_vals, f_vals, k] = steepest_descent(f, grad_f, x0, tol, max_iter, mode) | |||
% f: Objective function | |||
% grad_f: Gradient of the function | |||
% x0: Initial point [x0, y0] | |||
% tol: Tolerance for stopping criterion | |||
% max_iter: Maximum number of iterations | |||
% x_vals: Vector with the (x,y) values until minimum | |||
% f_vals: Vector with f(x,y) values until minimum | |||
% k: Number of iterations | |||
if strcmp(mode, 'armijo') == 1 | |||
gamma_f = @(f, grad_f, x0) gamma_armijo(f, grad_f, x0); | |||
elseif strcmp(mode, 'minimized') == 1 | |||
gamma_f = @(f, grad_f, x0) gamma_minimized(f, grad_f, x0); | |||
else % mode == 'fixed' | |||
gamma_f = @(f, grad_f, x0) gamma_fixed(f, grad_f, x0); | |||
end | |||
% Storage for iterations, begin with the first point | |||
x_vals = x0; | |||
f_vals = f(x0(1), x0(2)); | |||
for k = 1:max_iter | |||
grad = grad_f(x0(1), x0(2)); | |||
% Check for convergence | |||
if norm(grad) < tol | |||
break; | |||
end | |||
dk = - grad; | |||
% Calculate gamma | |||
gk = gamma_f(f, grad_f, x0); | |||
x_next = x0 + gk * dk'; % Update step | |||
f_next = f(x_next(1), x_next(2)); | |||
x0 = x_next; % Update point | |||
x_vals = [x_vals; x_next]; % Store values | |||
f_vals = [f_vals; f_next]; % Store function values | |||
end | |||
end | |||