#include "CMyMatrix.h" #include "CMyVektor.h" #include #include #include // Konstruktor CMyMatrix::CMyMatrix(int z, int s) { zeilen = z; spalten = s; matrix.resize(zeilen); for (int i = 0; i < zeilen; ++i) matrix[i].resize(spalten); } double CMyMatrix::getZeilen() { return zeilen; } double CMyMatrix::getSpalten() { return spalten; } void CMyMatrix::setWert(double wert, int zeile, int spalte) { matrix[zeile][spalte] = wert; } double CMyMatrix::getWert(int zeile, int spalte) { return matrix[zeile][spalte]; } double& CMyMatrix::operator()(int zeile, int spalte) { return matrix[zeile][spalte]; } CMyMatrix CMyMatrix::invers() { if (this->getZeilen() != 2 || this->getSpalten() != 2) throw std::runtime_error("Keine 2x2 Matrix"); double a = this->getWert(0, 0); double b = this->getWert(1, 0); double c = this->getWert(0, 1); double d = this->getWert(1, 1); double determinate = a * d - b * c; if (determinate == 0) throw std::runtime_error("detA == 0"); double kehrwertDeterminante = 1 / determinate; CMyMatrix inverse(2,2); inverse.setWert(kehrwertDeterminante * d, 0, 0); inverse.setWert(kehrwertDeterminante * -c, 0, 1); inverse.setWert(kehrwertDeterminante * -b, 1, 0); inverse.setWert(kehrwertDeterminante * a, 1, 1); return inverse; } // Matrix-Vektor Multiplikation CMyVektor operator*(CMyMatrix A, CMyVektor x) { // M Spalten == V Zeilen if (A.getSpalten() != x.getDimension()) throw std::runtime_error("Matrix(m x n) * Vektor(i) n != i"); CMyVektor ergebnis(A.getZeilen()); for (int i = 0; i < A.getZeilen(); i++) { // Zeile for (int j = 0; j < A.getSpalten(); j++) // Spalte ergebnis[i] += A(i, j) * x[j]; // Aufsummierung } return ergebnis; } std::ostream& operator<<(std::ostream& os, CMyMatrix x) { for (int i = 0; i < x.getZeilen(); ++i) { os << "\t\t\t("; for (int j = 0; j < x.getSpalten(); ++j) j == x.getSpalten() - 1 ? os << std::fixed << std::setprecision(10) << x(i, j) : os << std::fixed << std::setprecision(10) << x(i, j) << "|"; os << ")\n"; } return os; } CMyMatrix jacobi(CMyVektor x, CMyVektor(*f)(CMyVektor)) { double const h = pow(10, -4); CMyVektor f_x = f(x); CMyVektor tmp{ x }; CMyMatrix jacobiMatrix(f_x.getDimension(), x.getDimension()); for (int i = 0; i < f_x.getDimension(); ++i) { // Zeile bzw. Teilfunktion f_i for (int j = 0; j < x.getDimension(); ++j) { // Spalte bzw. Variable x_j tmp[j] += h; jacobiMatrix(i, j) = (f(tmp)[i] - f_x[i]) / h; tmp[j] -= h; } } return jacobiMatrix; }; void newtonverfahren(CMyVektor x, CMyVektor(*f)(CMyVektor)) { int schritt = 0; CMyVektor f_x = f(x); CMyMatrix jacobi_f_x = jacobi(x, f); CMyMatrix jacobiInvers = jacobi_f_x.invers(); double funktionLaenge = f_x.length(); CMyVektor dx = -1 * (jacobiInvers * f_x); while (schritt != 50 && funktionLaenge >= 1e-5) { std::cout << "Schritt " << schritt << ":" << "\n\t ๐ฑ = " << x << "\n\t ๐‘“(๐ฑ) = " << f_x << "\n" << "\n\t โˆ‚๐‘“(๐ฑ) = \n " << jacobi_f_x << "\n\t โˆ‚๐‘“(๐ฑ)โปยน = \n" << jacobiInvers << "\n\t ฮ”๐ฑ = " << dx << "\n\t ||๐‘“(๐ฑ)|| = " << funktionLaenge << std::endl << std::endl; schritt++; x = x + dx; f_x = f(x); jacobi_f_x = jacobi(x, f); jacobiInvers = jacobi_f_x.invers(); dx = -1 * (jacobiInvers * f_x); funktionLaenge = f_x.length(); if (schritt == 50) { std::cout << "Ende wegen Schrittanzahl = 50 bei"; std::cout << "\n\t x = " << x << "\n\t ๐‘“(๐ฑ) = " << f_x << "\n\t ||๐‘“(๐ฑ)|| = " << funktionLaenge << std::endl; } else if (funktionLaenge < 1e-5) { std::cout << "Ende wegen ||๐‘“(๐ฑ)||<1e-5 bei"; std::cout << "\n\t x = " << x << "\n\t ๐‘“(๐ฑ) = " << f_x << "\n\t ||๐‘“(๐ฑ)|| = " << funktionLaenge << std::endl; } } };