init
This commit is contained in:
12
P1/CMakeLists.txt
Executable file
12
P1/CMakeLists.txt
Executable file
@@ -0,0 +1,12 @@
|
||||
# Set the minimum required version of CMake
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
|
||||
# Set the project name
|
||||
project(HM_P1)
|
||||
|
||||
# Specify the C++ standard
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Add all source files
|
||||
add_executable(HM_P1 main.cpp CMyVektor.cpp)
|
||||
199
P1/CMyVektor.cpp
Executable file
199
P1/CMyVektor.cpp
Executable file
@@ -0,0 +1,199 @@
|
||||
#include "CMyVektor.h"
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
|
||||
int CMyVektor::getDimension() {
|
||||
return dimension;
|
||||
}
|
||||
|
||||
// Vektor Element bei index i
|
||||
double& CMyVektor::operator[](int i) {
|
||||
return werte.at(i);
|
||||
}
|
||||
|
||||
// Betrag des Vektors
|
||||
double CMyVektor::length() {
|
||||
double l = 0.0;
|
||||
for (int i = 0; i < werte.size(); i++)
|
||||
l += pow(werte.at(i), 2);
|
||||
|
||||
return(sqrt(l));
|
||||
}
|
||||
|
||||
// Ausgabe im Vektorformat
|
||||
std::ostream& operator<< (std::ostream& os, CMyVektor& vektor) {
|
||||
os << "(";
|
||||
for (int i = 0; i < vektor.getDimension(); i++) {
|
||||
os << vektor[i];
|
||||
if (i < vektor.getDimension() - 1) os << "|";
|
||||
}
|
||||
os << ")";
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
/* Vektor Addition
|
||||
a1 + b1 = a1+b1
|
||||
a2 + b2 = a2+b2
|
||||
: : :
|
||||
ai + bi = ai+bi
|
||||
*/
|
||||
CMyVektor operator+(CMyVektor a, CMyVektor b) {
|
||||
// Vektoren addierbar?
|
||||
if (a.getDimension() != b.getDimension())
|
||||
return a;
|
||||
|
||||
CMyVektor sum(a.getDimension());
|
||||
|
||||
for (int i = 0; i < a.getDimension(); i++)
|
||||
sum[i] = a[i] + b[i];
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* Skalare Multiplikation
|
||||
a1 * s = v1
|
||||
a2 * s = v2
|
||||
: : :
|
||||
ai * s = vi
|
||||
*/
|
||||
CMyVektor operator*(double s, CMyVektor a) {
|
||||
CMyVektor vektor(a.getDimension());
|
||||
|
||||
for (int i = 0; i < a.getDimension(); i++)
|
||||
vektor[i] = s * a[i];
|
||||
|
||||
return vektor;
|
||||
}
|
||||
|
||||
CMyVektor gradient(double f(CMyVektor x), CMyVektor x) {
|
||||
CMyVektor grad(x.getDimension());
|
||||
CMyVektor xh(x.getDimension()); // x mit "Wackelei" an x_i
|
||||
xh = x;
|
||||
|
||||
double fx = f(x);
|
||||
double h = 1e-8;
|
||||
|
||||
// Berechnung der partiellen Ableitung nach x_i und Zusammenfassung in grad
|
||||
for (int i = 0; i < x.getDimension(); i++) {
|
||||
// xh[0] xh[1] ... xh[n]
|
||||
// x_1+h,x_2,...,x_n x_1,x_2+h,...,x_n x_1,x_2,...,x_n+1
|
||||
xh[i] += h;
|
||||
|
||||
// grad[i] = df/dx_i => numerische Ableitung nach dem jeweilige x_i
|
||||
grad[i] = (f(xh) - fx) / h;
|
||||
|
||||
// Zurücksetzen der "Wackelei"
|
||||
xh[i] -= h;
|
||||
}
|
||||
return grad;
|
||||
}
|
||||
|
||||
CMyVektor gradientenverfahren(double f(CMyVektor x), CMyVektor x, double lambda) {
|
||||
int schritt_zaehler = 0;
|
||||
CMyVektor gradfx(x.getDimension());
|
||||
CMyVektor x_neu(x.getDimension());
|
||||
gradfx = gradient(f, x);
|
||||
|
||||
while (gradient(f, x).length() >= 1e-5 && schritt_zaehler < 25) {
|
||||
x_neu = x + lambda * gradfx;
|
||||
|
||||
std::cout
|
||||
<< "Schritt " << schritt_zaehler << ": " << std::endl
|
||||
<< " x = " << x << std::endl
|
||||
<< " λ = " << lambda << std::endl
|
||||
<< " f(x) = " << f(x) << std::endl
|
||||
<< " grad f(x) = " << gradfx << std::endl
|
||||
<< " ||grad f(x)|| = " << gradfx.length() << std::endl << std::endl
|
||||
<< " x_neu = " << x_neu << std::endl
|
||||
<< " f(x_neu) = " << f(x_neu) << std::endl << std::endl;
|
||||
|
||||
// Halbierung
|
||||
if (f(x_neu) <= f(x)) {
|
||||
double lamda_test = lambda * 0.5;
|
||||
CMyVektor x_test = x + lamda_test * gradfx;
|
||||
|
||||
std::cout
|
||||
<< " ↯ f(x) = " << f(x) << " ≥ f(x_neu) = " << f(x_neu) << std::endl << std::endl
|
||||
<< " ? Test mit halbierter Schrittweite (λ = " << lamda_test << "): " << std::endl
|
||||
<< " x_test = " << x_test << std::endl
|
||||
<< " f(x_test) = " << f(x_test) << std::endl << std::endl;
|
||||
|
||||
if (f(x) < f(x_test))
|
||||
std::cout
|
||||
<< " ✓ f(x) = " << f(x) << " < f(x_test) = " << f(x_test) << std::endl
|
||||
<< " ! Übernehme Schrittweite." << std::endl << std::endl;
|
||||
|
||||
// weiter Halbieren wenn f(x_test) <= f(x)
|
||||
while (f(x_test) <= f(x)) {
|
||||
std::cout
|
||||
<< " ↯ f(x) = " << f(x) << " ≥ f(x_test) = " << f(x_test) << std::endl << std::endl;
|
||||
|
||||
lamda_test *= 0.5;
|
||||
x_test = x + lamda_test * gradfx;
|
||||
|
||||
std::cout
|
||||
<< " ? Test mit halbierter Schrittweite (λ = " << lamda_test << "): " << std::endl
|
||||
<< " x_test = " << x_test << std::endl
|
||||
<< " f(x_test) = " << f(x_test) << std::endl << std::endl;
|
||||
|
||||
// Ausgabe beim letzten Durchlauf der Schleife
|
||||
if (!(f(x_test) <= f(x)))
|
||||
std::cout
|
||||
<< " ✓ f(x) = " << f(x) << " < f(x_test) = " << f(x_test) << std::endl << std::endl
|
||||
<< " ! Übernehme Schrittweite λ = " << lamda_test << std::endl << std::endl;
|
||||
}
|
||||
|
||||
lambda = lamda_test;
|
||||
x_neu = x_test;
|
||||
}
|
||||
|
||||
// Verdopplung
|
||||
else {
|
||||
double lamda_test = lambda * 2;
|
||||
CMyVektor x_test = x + lamda_test * gradfx;
|
||||
|
||||
std::cout
|
||||
<< " ? Test mit doppelter Schrittweite (λ = " << lamda_test << "): " << std::endl
|
||||
<< " x_test = " << x_test << std::endl
|
||||
<< " f(x_test) = " << f(x_test) << std::endl << std::endl;
|
||||
|
||||
if (f(x_test) > f(x_neu)) {
|
||||
x_neu = x_test;
|
||||
lambda = lamda_test;
|
||||
std::cout
|
||||
<< " ! Übernehme verdoppelte Schrittweite λ = " << lamda_test << std::endl
|
||||
<< " ✓ f(x_neu) = " << f(x_neu) << " < f(x_test) = " << f(x_test) << std::endl << std::endl;
|
||||
}
|
||||
else {
|
||||
std::cout
|
||||
<< " ↯ f(x_neu) = " << f(x_neu) << " ≥ f(x_test) = " << f(x_test) << std::endl
|
||||
<< " ! behalte aktuelle Schrittweite λ = " << lambda << std::endl << std::endl;
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
x = x_neu;
|
||||
gradfx = gradient(f, x);
|
||||
schritt_zaehler++;
|
||||
}
|
||||
|
||||
// Zusammenfassung des Endes
|
||||
if (gradfx.length() < 1e-5)
|
||||
std::cout
|
||||
<< "Ende wegen ||grad f(x)|| < 10^-5 bei" << std::endl;
|
||||
|
||||
else
|
||||
std::cout
|
||||
<< "Ende wegen 25. Schritt" << std::endl;
|
||||
|
||||
std::cout
|
||||
<< " x = " << x << std::endl
|
||||
<< " λ = " << lambda << std::endl
|
||||
<< " f(x) = " << f(x) << std::endl
|
||||
<< " grad f(x) = " << gradfx << std::endl
|
||||
<< " ||grad f(x)|| = " << gradfx.length() << std::endl
|
||||
<< "-----------------------------------------------------" << std::endl << std::endl;
|
||||
|
||||
return x_neu;
|
||||
}
|
||||
34
P1/CMyVektor.h
Executable file
34
P1/CMyVektor.h
Executable file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
class CMyVektor {
|
||||
private:
|
||||
int dimension;
|
||||
std::vector<double> werte;
|
||||
public:
|
||||
// Vektor mit Dimension anlegen
|
||||
CMyVektor(int n) : dimension { n } {
|
||||
werte.resize(n);
|
||||
}
|
||||
|
||||
CMyVektor(std::vector<double> x) : dimension { (int) x.size() } {
|
||||
werte.resize(x.size());
|
||||
for (int i = 0; i < x.size(); i++)
|
||||
werte[i] = x[i];
|
||||
}
|
||||
|
||||
int getDimension();
|
||||
double length();
|
||||
|
||||
// Komponente von Vektor übergeben
|
||||
double& operator[](int index);
|
||||
};
|
||||
|
||||
CMyVektor operator+(CMyVektor a, CMyVektor b);
|
||||
CMyVektor operator*(double lambda, CMyVektor a);
|
||||
|
||||
std::ostream& operator<< (std::ostream& os, CMyVektor& vektor);
|
||||
|
||||
CMyVektor gradient(double f(CMyVektor x), CMyVektor x);
|
||||
CMyVektor gradientenverfahren(double f(CMyVektor x), CMyVektor x, double lambda = 1.0);
|
||||
36
P1/main.cpp
Executable file
36
P1/main.cpp
Executable file
@@ -0,0 +1,36 @@
|
||||
#include <math.h>
|
||||
#include "CMyVektor.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// f( [x,y] ) = sin(x * y) + sin(x) + cos(y)
|
||||
double f(CMyVektor X) {
|
||||
double x = X[0];
|
||||
double y = X[1];
|
||||
|
||||
return (sin(x * y) + sin(x) + cos(y));
|
||||
}
|
||||
|
||||
// g( [x,y,z] ) = -(2x^2 - 2xy + y^2 + z^2 - 2x - 4z)
|
||||
double g(CMyVektor X) {
|
||||
double x = X[0];
|
||||
double y = X[1];
|
||||
double z = X[2];
|
||||
|
||||
return -(2 * pow(x,2) - 2 * x * y + pow(y,2) + pow(z,2) - 2 * x - 4 * z);
|
||||
}
|
||||
|
||||
int main() {
|
||||
CMyVektor X0(std::vector<double>{1,3,5});
|
||||
CMyVektor gradX0 = gradient(f, X0);
|
||||
cout << "grad f" << X0 << "=" << gradX0 << std::endl;
|
||||
|
||||
CMyVektor X1(std::vector<double>{0.2,-2.1});
|
||||
gradientenverfahren(f, X1);
|
||||
|
||||
CMyVektor X2(std::vector<double>{0,0,0});
|
||||
gradientenverfahren(g, X2, 0.1);
|
||||
|
||||
system("pause");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user