diff --git a/ws2019/ana/lectures/analysis.pdf b/ws2019/ana/lectures/analysis.pdf index ab22b70..7443f69 100644 Binary files a/ws2019/ana/lectures/analysis.pdf and b/ws2019/ana/lectures/analysis.pdf differ diff --git a/ws2019/ana/lectures/analysis.tex b/ws2019/ana/lectures/analysis.tex index abdafa5..a6310b1 100644 --- a/ws2019/ana/lectures/analysis.tex +++ b/ws2019/ana/lectures/analysis.tex @@ -33,5 +33,6 @@ \input{analysis16.tex} \input{analysis17.tex} \input{analysis18.tex} +\input{analysis19.tex} \end{document} diff --git a/ws2019/ipi/uebungen/board.hh b/ws2019/ipi/uebungen/board.hh new file mode 100644 index 0000000..a33423d --- /dev/null +++ b/ws2019/ipi/uebungen/board.hh @@ -0,0 +1,138 @@ +#include + +struct BoundaryCondition +{ + virtual bool boundary(Board& board, int i, int j) = 0; +}; + +class Board { + public : + // Konstruktor, erzeuge bool* _fields + Board(int width, int height, BoundaryCondition cond); + + // Desktruktor, raeume bool* _fields auf + ~Board(); + + // copy constructor, intializes by copying from 'other' + Board(Board& other); + + // assignment operator + Board& operator=(Board& other); + + // gibt die Breite des Bretts zurueck + double width(); + + // gibt die Hoehe des Bretts zurueck + double height(); + + // schreibe value an den Pixel (i,j) + // Ueberlegen Sie wie aus (i,j) den flachen Index bei row-major bekommen + void updateField(int i, int j, bool value); + + // Zugang zum Pixel (i,j) im 1D Array + // Ueberlegen Sie wie aus (i,j) den flachen Index bei row-major bekommen + int operator()(int i, int j); + + // Gibt zurueck ob Feld am Rand liegt + bool touchesBoundary(int i, int j); + + // Gibt Zahl der lebenden Zellen zurueck, die das Feld umgeben + int livingCells(int i, int j); + + // Prueft ob Zelle lebt oder nicht + bool isLiving(int i, int j); + + // Gibt die BoundaryCondition zurueck + BoundaryCondition boundaryCondition(); + + private : + int _width; + int _height; + bool* _fields; + void copy(Board& other); + BoundaryCondition _boundCond; +}; + +Board::Board(int width, int height, BoundaryCondition cond) { + // initialize all values + _width = width; + _height = height; + _boundCond = cond; + _fields = new bool[width * height]; +} + +Board::~Board() { + _fields = 0; +} + +void Board::copy(Board& other) { + _width = other.width(); + _height = other.height(); + _boundCond = other.boundaryCondition(); + _fields = new bool[_width * _height]; + for (int i = 0; i < _height; i++) { + for (int j = 0; j < _width; j++) { + updateField(i, j, other.isLiving(i, j)); + } + } +} + +Board::Board(Board& other) { + copy(other); +} + +Board& Board::operator=(Board& other) { + if (this == &other) { + return *this; + } + copy(other); + return *this; +} + +double Board::width() { + return _width; +} + +double Board::height() { + return _height; +} + +BoundaryCondition Board::BoundaryCondition() { + return _boundCond; +} + +void Board::updateField(int i, int j, bool value) { + // i = Zeile und wegen row-major Konvention muss i mit der Breite + // multipliziert werden + _fields[i * _width + j] = value; +} + +bool Board::touchesBoundary(int i, int j) { + return i == _height - 1 || i == -1 || j == _width - 1 || j == -1; +} + +int Board::livingCells(int i, int j) { + bool surround[8] = { isLiving(i+1, j+1), isLiving(i, j+1), isLiving(i-1, j+1) + , isLiving(i+1, j), isLiving(i-1, j) + , isLiving(i+1, j-1), isLiving(i, j-1), isLiving(i-1, j-1)}; + int numLiving = 0; + for (int i = 0; i < 8; i++) { + if (surround[i] == true) { + numLiving += 1; + } + } +} + +bool Board::isLiving(int i, int j) { + if (touchesBoundary(i, j)) { + return _boundCond.boundary(i, j); + } else { + return _fields[i * _width + j]; + } +} + +int Board::operator()(int i, int j) { + // i = Zeile und wegen row-major Konvention muss i mit der Breite + // Pixel multipliziert werden + return _fields[i * _width+ j]; +} diff --git a/ws2019/ipi/uebungen/canvas.hh b/ws2019/ipi/uebungen/canvas.hh new file mode 100644 index 0000000..4441c7d --- /dev/null +++ b/ws2019/ipi/uebungen/canvas.hh @@ -0,0 +1,116 @@ +#include +#include "pgm.hh" + +// Komplexe Zahl +struct Complex +{ + double real; + double imag; +}; + +class Canvas +{ +public : + // Konstruktor, erzeuge int* _pixels + Canvas(double center_x, double center_y, + double width, double height, + int horPixels, int vertPixels); + + // Desktruktor, raeume int* _pixels auf + ~Canvas(); + + // gibt die Breite des Bildes zurueck + double width(); + + // gibt die Hoehe des Bildes zurueck + double height(); + + // gibt die Anzahl an horizontalen Pixeln + int horPixels(); + + // gibt die Anzahl an vertikalen Pixeln + int vertPixels(); + + // gebe die Koordinaten des Pixels (i,j) als Complex zurueck + Complex coord(int i, int j); + + // schreibe value an den Pixel (i,j) + // Ueberlegen Sie wie aus (i,j) den flachen Index bei row-major bekommen + void writePixel(int i, int j, int value); + + // Zugang zum Pixel (i,j) im 1D Array + // Ueberlegen Sie wie aus (i,j) den flachen Index bei row-major bekommen + int operator()(int i, int j); + + // schreibe Bild mit Dateinamen filename + void write(std::string filename); +private : + double _center_x; + double _center_y; + double _width; + double _height; + int _horPixels; + int _vertPixels; + int* _pixels; +}; + +// diese Methode ist bereits implementiert +void Canvas::write(std::string filename) +{ + write_pgm(_pixels,_horPixels,_vertPixels,filename); +} + +Canvas::Canvas(double center_x, double center_y, double width, double height, int horPixels, + int vertPixels) { + // initialize all values + _center_x = center_x; + _center_y = center_y; + _width = width; + _height = height; + _horPixels = horPixels; + _vertPixels = vertPixels; + _pixels = new int[horPixels * vertPixels]; +} + +Canvas::~Canvas() { + _pixels = 0; +} + +double Canvas::width() { + return _width; +} + +double Canvas::height() { + return _height; +} + +int Canvas::horPixels() { + return _horPixels; +} + +int Canvas::vertPixels() { + return _vertPixels; +} + +Complex Canvas::coord(int i, int j) { + Complex c; + // Bringe die Pixel mit den echten Laengen ins Verhaeltnis + double y = i * (_height / _vertPixels) - _height / 2; + double x = j * (_width / _horPixels) - _width / 2; + // Gebe die Koordinaten in Relation zum gewuenschten Zentrum aus + c.imag = y + _center_y; + c.real = x + _center_x; + return c; +} + +void Canvas::writePixel(int i, int j, int value) { + // i = Zeile und wegen row-major Konvention muss i mit der Zahl der horizontalen + // Pixel multipliziert werden + _pixels[i*_horPixels + j] = value; +} + +int Canvas::operator()(int i, int j) { + // i = Zeile und wegen row-major Konvention muss i mit der Zahl der horizontalen + // Pixel multipliziert werden + return _pixels[i*_horPixels + j]; +} diff --git a/ws2019/ipi/uebungen/gameoflife.cc b/ws2019/ipi/uebungen/gameoflife.cc new file mode 100644 index 0000000..775e947 --- /dev/null +++ b/ws2019/ipi/uebungen/gameoflife.cc @@ -0,0 +1,125 @@ +#include +#include // needed for usleep +#include +#include + +#include "board.hh" + +// Basisklassen +struct Regel +{ + virtual void anwenden(Board& board) = 0; +}; + +class TorusCondition : public BoundaryCondition +{ + bool boundary(Board& board, int i, int j) { + if (i == board.height() - 1) { + return board.isLiving(0, j); + } else if (i == -1) { + return board.isLiving(board.height() - 1, j); + } else if (j == board.width() - 1) { + return board.isLiving(i, 0); + } else if (j == -1) { + return board.isLiving(i, board.width() - 1); + } + } +}; + +class AliveCondition : public BoundaryCondition +{ + bool boundary(Board& board, int i, int j) { + return true; + } +}; + +class DeadCondition : public BoundaryCondition +{ + bool boundary(Board& board, int i, int j) { + return false; + } +}; + +class GameOfLifeRules : public Regel +{ + public : + //void anwenden(Board& board) { + // // copy new board from old board + // Board updated = Board(board.width(), board.height()); + // for (int i = 0; i < board.height(); i++) { + // for (int j = 0; i < board.width(); i++) { + // int n = board.livingCells(i, j); + // int self = board.isLiving(i, j); + // if (self && n < 2) { + // updated.updateField(i, j, false); + // } else if (!self && n == 3) { + // updated.updateField(i, j, true); + // } else if (self && n > 3) { + // updated.updateField(i, j, false); + // } else { + // updated.updateField(i, j, self); + // } + // } + // } + // board = updated; + //} +}; + +// Ein zellulaerer Automat, der Regeln und Datenstrukturen von aussen bekommt +class Automat +{ + public : + // der Datentyp fuer das 2D Bool Array + Automat(Board& board, Regel& regel) + : _board(board) + , _regel(regel) + {} + + // mache n Schritte + void doSteps(int n=1) + { + for (int i=0; i " << std::endl; + return 1; + } + + Board board = Board(2, 2, AliveCondition); + board.updateField(1,1, true); + board.livingCells(1,1); + + // Initialisiere Datenstruktur des 2D Bool Array + // TODO + // Ueberlegen Sie sich wie Sie einen Startzustand in das 2D Bool Array bekommen + // Lesen Sie ggf. + // (1) eine solche Textdatei mittels Filestream ein + // (2) ueberladen Sie Operatoren operator<< oder operator>> + + // TODO + // - legen Sie eine Instanz der Randbedingung an + // - legen Sie eine Instanz des Regelsystems an + // - Initialisieren Sie den zellulaeren Automaten + + // Experimentieren Sie hier mit Ihrem Automaten + + return 0; +} diff --git a/ws2019/ipi/uebungen/ipi9.pdf b/ws2019/ipi/uebungen/ipi9.pdf new file mode 100644 index 0000000..18b7528 Binary files /dev/null and b/ws2019/ipi/uebungen/ipi9.pdf differ diff --git a/ws2019/ipi/uebungen/ipi9.tex b/ws2019/ipi/uebungen/ipi9.tex new file mode 100644 index 0000000..8e61768 --- /dev/null +++ b/ws2019/ipi/uebungen/ipi9.tex @@ -0,0 +1,44 @@ +\documentclass[uebung]{../../../lecture} + +\title{IPI: Übungsblatt 9} +\author{Samuel Weidemaier, Christian Merten} + +\usepackage[]{listings} + +\usepackage{xcolor} + +\lstdefinestyle{mystyle}{ + commentstyle=\color{gray}, + language=C++, + keywordstyle=\color{blue}, + numberstyle=\tiny\color{gray}, + stringstyle=\color{black}, + basicstyle=\ttfamily\footnotesize, + breakatwhitespace=false, + breaklines=true, + captionpos=b, + keepspaces=true, + numbers=left, + numbersep=5pt, + showspaces=false, + showstringspaces=false, + showtabs=false, + tabsize=2 +} + +\lstset{style=mystyle} + +\begin{document} + +\begin{aufgabe}[Mandelbrot-Menge] + (a) und (b) siehe \textit{mandelbrot.cc} und \textit{canvas.hh}. + + (c) Je höher \lstinline{threshold}, desto heller wird das Bild, allerdings ist bereits zwischen 100 und 1000 + kein großer Unterschied mehr zu erkennen. Bei sehr kleinen \lstinline{threshold}s werden die Randbereiche + wieder schwarz. + + Bei geringen \lstinline{maxIt}s ist die Genauigkeit sehr gering, je höher desto feiner wird das Bild. + Allerdings ist auch hier zwischen 100 und 1000 bereits kein Unterschied mehr zu erkennen. +\end{aufgabe} + +\end{document} diff --git a/ws2019/ipi/uebungen/mandelbrot.cc b/ws2019/ipi/uebungen/mandelbrot.cc new file mode 100644 index 0000000..f9f4b1e --- /dev/null +++ b/ws2019/ipi/uebungen/mandelbrot.cc @@ -0,0 +1,61 @@ +#include +#include +#include + +// Datentyp Complex in der Datei canvas.hh +#include "canvas.hh" + +// Summiert zwei komplexe Zahlen z und c und schreibt das Ergebnis in z +void add_complex(Complex& z, Complex& c) { + z.real += c.real; + z.imag += c.imag; +} + +// Multipliziert zwei komplexe Zahlen z und c und schreibt das Ergebnis in z +void multiply_complex(Complex& z, Complex& c) { + double re = z.real*c.real - z.imag*c.imag; + double im = z.real*c.imag + z.imag*c.real; + z.real = re; + z.imag = im; +} + +// Betrag einer komplexen Zahl +double betrag(Complex z) +{ + return std::sqrt(std::pow(z.real, 2) + std::pow(z.imag, 2)); +} + +// Generiert die Mandelbrot Menge und speichert sie in canvas mit threshold als Entfernung, ab dem +// ein Punkt ,,entkommt'', mit maxIt als maximale Anzahl an Iterationen, die für +// die Folge durchgeführt werden soll. Wird als PGM Bild unter filename gespeichert +void mandelbrot(Canvas& canvas, double threshold, int maxIt, std::string filename) { + for (int i = 0; i < canvas.vertPixels(); i++) { + for (int j = 0; j < canvas.horPixels(); j++) { + Complex c = canvas.coord(i, j); + Complex z; + z.real = 0; + z.imag = 0; + int neededIterations = -1; + for (int k = 1; k <= maxIt; k++) { + multiply_complex(z, z); + add_complex(z, c); + if (betrag(z) > threshold) { + neededIterations = k; + break; + } + } + if (neededIterations == -1) { + canvas.writePixel(i, j, 0); + } else { + canvas.writePixel(i, j, std::log(neededIterations)*100); + } + } + } + canvas.write(filename); +} + +int main() +{ + Canvas canvas = Canvas(-1, 0, 4, 3, 4000, 3000); + mandelbrot(canvas, 1000, 10000, "mandelbrot.pgm"); +} diff --git a/ws2019/ipi/uebungen/pgm.hh b/ws2019/ipi/uebungen/pgm.hh new file mode 100644 index 0000000..e9f50ff --- /dev/null +++ b/ws2019/ipi/uebungen/pgm.hh @@ -0,0 +1,64 @@ +#include +#include +#include + +void write_pgm(int* pixels, int horPixels, int vertPixels, std::string filename) +{ + if(horPixels == 0 || vertPixels == 0) + { + std::cerr << "Leeres Pixel Array" << std::endl; + return; + } + + // write file + // unfortunately we cannot use C++-11 which would simplify our life in that case + std::ofstream outfile; + outfile.open(filename.c_str()); + + outfile << "P2" << std::endl + << horPixels << " " << vertPixels << std::endl; + + // renormalize if necessary + int maxVal = 0; + for(int entry=0; entry 65535) + { + outfile << 65535 << std::endl; + for(int j=0, entry=0; j