%% MATLAB Einführung
% 
% In diesem Matlab Skript lernen wir die Grundlegenden Funktionen von MATLAB kennen. 
% Hierbei werden wir die folgenden Kapitel behandeln:
% 
%     1.Datentypen
%     2.Funktionen
%     3.Schleifen und Bedingungen
%     4.Zufallszahlen
%     5.Plotten
% 
% Am besten öffnest du ebenfalls ein Matlab Skript und wandelst die aufgeführten Beispiele nach Lust und Laune ab.
% 
% Da es laut Wikipedia (https://de.wikipedia.org/wiki/Hallo-Welt-Programm#Geschichte) 
% Tradition ist, starten wir auch diese Einführung mit einem "Hello World!" Programm.

disp('Hello World!')


% In diesem Skript wird nach jedem Abschnitt der Befehl 'clc' auftauchen.
% Dieser löscht die Einträge in der Kommandozeile und sorgt dadurch für mehr
% Übersicht. Abschnitte sind durch %% gekennzeichnet. 

% Durch 'Run Section' wird immer nur der angewählte Abschnitt(rechts neben
% dem großen grünen Pfeil 'Run') ausgeführt.



%% 1. Datentypen
clc
% In MATALAB sind dies die wichtigsten Datentypen:
% 
%     - Integer
%     - Double
%     - Complex
%     - Character 
%     - String
%     - Logical (Boolean)
%     
% ----GRUNDLEGENDES----
% Mit class() kann der Datentyp eines Objektes ausgegeben werden. Per default sind alle "Zahlen" 
% als double gespeichert, lassen sich jedoch durch z.B. int32() als (32bit) Integer umwandeln.  
% 
% ACHTUNG: In MATLAB gibt es zwei Datentypen für "Text": String und Character Strings werden 
% mit " " initialisiert und Characters mit ' '. Für die meisten Anwendungen ist es nicht wichtig,
% welche der beiden Arten benutzt wird. Jedoch ist die Verknüpfung von beiden nicht ohne zusätzliche 
% Funktionen möglich, da es verschiedene Datentypen sind. Intuitiv kann man sagen: Ein String ist 
% ein 'Wort' und ein einzelner Buchstabe ist ein Character. Dementsprechend ist ein String-Array 
% (["abc",cdf"]) ein Array voller 'Wörter' und ein Character-Array, das was wir unter einem Wort verstehen 
% würden (['a','b','c','c','d','f']='abccdf'). 


class(42)
class(42.0)
class(int32(42))
class("Zweiundvierzig")
class('Zweiundvierzig')
class(true)
class(4+2i)
%%
% In MATLAB wird jede Zeile in der Komandozeile ausgeben, wenn sie nicht
% durch ein ';' beendet wird. Diese Zeilen werden ebenfalls mit einer roten
% Wellenlinie markiert, die sonst für Fehler steht. 
% Außerdem lassens ich Kommentate mit einem %
% kennzeichnen.

clc

class(42); %keine Ausgabe
class(42)  %Ausgabe

% Werte in Variablen gespeichert werden. Dies geschieht mit =.
% So wird zum Beispiel durch x=3 eine Variable x mit dem Wert 3
% erstellt. Diese erscheint dann im Workspace. Mit dem Befehl
% disp() können Variablen an einer beliebigen Stelle im Skript ausgegeben
% werden

x=3;
disp(x)

%%
% Für numerische Datentypen funktioneren die Grundrechenarten wie zu erwarten. 
% Der Modulo-Operator wird in MATLAB mit mod(a,b) aufgerufen.

clc

3+3
16-4
7*9.1
4/2
3^2

mod(5,2)
%%
% logicals nehmen die Werte true und false, bzw. 1 und 0 an. MATLAB verfügt über die
% üblichen logischen Operatoren: "und", "oder", "nicht" und "xor". 
% "und" sowie "oder" lassen sich als %% , || sowie als & , | schreiben. Im
% skalaren Fall macht dies keinen Unterschied, jedoch wenn diese Operatoren
% auf Vektoren angewandt werden wird bei && und || eine Fehlermeldung
% geworfen. & und | führen die Operation elementweise aus.
clc
x=true;
y=false;

x&y         % und
x&&y        % anderes und

x|y         % oder
~x          % nicht
xor(x,y)    % exclusives oder

% Vergleichsoperatoren vergleichen zwei Objekte und liefern einen Boolean zurück.
% Für skalare Zahlen sind in MATLAB die folgenden Operatoren definiert.

1==1      %gleich
1~=1      %ungleich
1<2       %kleiner als
1>2       %größer als
1<=2      %kleiner oder gleich
1>=2      %größer oder gleich

% Strings lassen sich durch ein + zusammenfügen
a="Wie die Zeit verfliegt, ";
b="wenn man programmiert"; 
disp(a+b)

%%
% ----Vektoren und Matrizen----
% 
% VEKTOREN
% 
% Wie gerade schon angedeuted ist es selbstverständlich auch möglich Werte
% in Arrays zu speichern. Arrays sind ein, zwei oder n- dimensionale
% Objekte in denen sich mehrere Werte speichern lassen.  
% Aufgrund des mathematischen Schwerpunkts benutzen wir hier in dieser
% Einfühung die Worte Array und Vektor, bzw. 2D Array und Matrix synonym.
% Streng genommen sind sogar einzelne Zahlen 1x1 Arrays. Ein Vektor wird in
% Matlab durch [ ] initialisiert. Das Zusammenführen von zwei Vektoren a,b
% geschieht durch einfassen von a,b in eckige Klammern: [a,b]
clc

x=[1,2,3,4];
y=[5,6,7];

disp(x)
z=[x,y];
disp(z)


% Wie schon erwähnt sind durch ' ' initialisierte Buchstabenketten eigentlich 
% charakter arrays. Deshalb werden sie auch so zusammengefügt
a='MATLAB ';
b='macht sehr viel Spaß';
disp([a,b])


%%
% Sollen die oben beschriebenen Grundrechenarten elementweise auf Vektoren
% angewandt werden, so muss zwischen Addition und Multiplikation
% unterscheiden werden. 
% Bei der Addition (auch Subtraktion) muss nichts weiter beachtet werden.
% Bei der Mulitplikation (Divison, Potenzrechnung) jedoch muss ein '.' vor
% dem Operator plaziert werden, da dies sonst als Matrixoperation
% interpretiert wird
clc


x=[1,2,3,4];
disp(x+x)
disp(x+3)

disp(x.*x)          % elementweise Multiplikation
disp(x./x)          % elementweise Divison
disp(x*3)           % hier ist kein '.' nötig, da ein Faktor ein Skalar ist




%%
% Die grundlegenden Funktionen wie log(),exp(),min(),sin(),.. sind in  MATLAB 
% bereits implementiert und lassen sich einfach auf Vektoren anwenden. 
% Besonders nützlich ist die Funktion length(), welche die Länge des Vektors ausgibt. 
% Inforamtionen zu Funktionen können mit help ausgegeben werden oder mit
% doc lässt sich die Dokumentation öffnen.
clc

x=[1,2,3,4];
sin(x)
log(x)
max(x)
length(x)
help sqrt

%%
% Nullvektoren oder Folgen mit linearen Abständne können wie folgt erzeugt werden
clc

1:10                    %Ganzzahlige Zahlen zwischen 1 und 10
1:2:10                  %Zahlen zwischen 1 und 10 mit dem Abstand 2

zeros(1,10);            %Vektor (1x10 Matrix) mit 10 Einträgen, alle mit dem Wert 0
linspace(0,14,5)        %5 Einträge mit äquidistantem Abstand zwischen 0 und 14



%%
% Es gibt verschiedene Arten auf die Einträge von Vektoren zuzugreifen, z.B. über den Index, bzw. über Vektoren mit Indizes
% (MATLAB indiziert ab 1, d.h. auf das erste Element eines Vektors wird mit 1 zugegriffen)
% Mit dem Kommando end wird auf das letzte Element im Vektor zugegriffen
clc

x=1:10;
x(1)
x([4,7])
x(end)

% Auch mithilfe von logischen Vektoren lässt sich auf Elemente eines Vektors zugreifen. 
% Dies vereinfacht den Zugriff auf Einträge mit gewissen Eigenschaften, z.B. alle durch zwei 
% teilbaren Einträge. Hierbei wird nur auf Elemente zugegriffen bei denen der Indexvektor ture ist.


teilbar=mod(x,2)==0;      %Boolenvektor mit true an den Stellen mit Rest 0
disp(teilbar)

disp(x(teilbar))          % Ausgabe an allen trues

%%
% MATRIZEN

% Wie bereits erwähnt sind Matrizen zweidimensionale Arrays und werden deshalb auch so indiziert. 
% Getrennt werden die verscheidenen Zeilen einer Matrix durch ;
clc


telefon=[1,2,3;4,5,6;7,8,9]
eins=ones(3)

% Addition und Subtraktion funktionieren wie gewohnt elementeweise. Die
% Elementweise Multiplikation ist analog zu der von Vektoren, also mit .* zu
% verstehen. Nun können wir jedoch auch Matrizen miteinander
% multiplizieren, indem wir einfach nur *  schreiben

telefon.*telefon        %elementweise Muliplikation
telefon*telefon         %Matrixmultiplikation
telefon+eins            %Addition zweier Matrizen
telefon+1               %Addition mit Konstanten

telefon/[1,2,3]         % A/b ("Backslashoperator") löst das LGS Ax=b

%%
% Der Zugriff erfolgt entweder elementweise, oder Zeilen/spaltenweise
clc

telefon(2,3)        %2,3 Eintrag
telefon(2,:)        %2. Zeile, : heißt hier alle Einträge
telefon(:,3)

% Matrizen sind nicht nur als Zeile/Spalte indiziert, sondern auch liner,
% das heißt man kann auch mit nur einem Index auf alle Elemente einer
% Matrix zugreifen. Hier werden erst die Spalten durchlaufen, also die
% Indizierung entspricht der transponierten Telefonmatrix.

telefon(3)

% Lineare Indizierung kann sehr nützlich sein, um sich z.B. das Maximum
% einer Matrix ausgeben zu lassen, denn

max(telefon)

%liefert einen Vektor mit den spaltenweisen Maxima. Mit

max(max(telefon))
max(telefon,[],'all')
max(telefon(:))

% werden die Maximia der ganzen Matrix ausgegeben. Wobei die letzte Variante
% lineare Indizierung ausnutzt










%% 3. Funktionen

% Durch Funktionen lassen sich gewisse Operationen leichter an verscheidenen 
% Stellen ausführen und der Code wird dadurch überichtlicher. Definiert werden 
% Funktionen in einer Funktionsumgebeung und können dann an einer beliebeigen Stelle 
% im Skript aufgerufen werden. Innerhalb einer Funktion können Variablen definiert 
% werden, diese überschreiben keine gleichnamigen Variablen außerhalb der Funktion.

% Funktionen werde nach folgendem Schema aufgebaut:

%   function outputVariable = funktionsName(input1,input2)
%         [...] % diverse Rechnungen und Operationen
%         outputVariable= errechneter_Wert;
%   end

% In MATLAB müssen Funktionen jedoch am Ende des Skripts stehen, deshalb
% solltest du nach unten scrollen um die Definitionen der Funktionen zu
% sehen.
clc

a=1;
b=2;
c=3;
disp(addition(a,b,c))
disp(additionMitUeberschreiben(a,b,c))
disp(a)



%% 4. Schleifen und Bedingungen

% 4.1 IF- BEDINGUNG
% Eine If Bedigung hat eine Boolean als Input und führt je nach Zustand eine Operation aus  
%
% Die einfachste If- Bedingung hat die Gestalt
% 
%   if Bedingung
%         Anweisung
%   end
% 
% Dies lässt sich zu einem "Entweder, oder" erweitern
% 
%   if Bedingung
%         Anweisung 
%   else
%        Anweisung alternativ
%   end
% 
% Mit  else if lassen sich mehrere Fälle abfragen, wobei immer der erste Fall der zutrifft eintritt
% 
%  if Bedingung
%       Anweisung 
%   elseif Bedinung 2
%       Anweisung alternativ
%   else
%       Anweisung alternativ 2
%   end

clc

x=0;

if  x<10
    disp("Kleine Zahl")
end
    
if x<0
    disp("neativ")
else
    disp("Null oder positiv")
end
    
if x>0
    disp("positiv")
elseif x<0
    disp("negativ")
else
    disp("Bleibt nur noch Null")
end        
        

%% 4.2 For Schleife

% In einer for-Schleife läuft ein Zähler über jedes Element eines Vektors.  
% In der Regel sind dies Integer von 1 bis n, da man so auf andere Vektoren 
% und Matrizen zugreifen kann, doch ist es auch möglich über z.B. Floats, 
% Booleans oder andere Objekte zu iterieren.
clc

frucht=["Apfel","Banane","Kiwi","Birne","Mango"];

for zaehler =1:length(frucht)
    disp(frucht(zaehler))
end

for bool = [0,1,0,1,0,1,1]
    if bool
        disp("ahoi")
    end
end

for lin=0:0.1:1
    disp("Kommazahl: " + num2str(lin))
end

%% 4.3 While-Schleife

% Prinzipiell kann jede for-Schleife durch eine while-Schleife ersetzt werden 
% und umgekehrt. Jedoch gibt es durchaus Anwendungen bei dennen das eine 
% sinnvoller ist als das andere. Eine while-Schleife wiederholt so lange einen
% Prozess, bis eine Bedingung erfüllt ist.
clc

zaehler=1;

frucht=["Apfel","Banane","Kiwi","Birne","Mango"];

while zaehler<length(frucht)
    disp(frucht(zaehler))
    zaehler=zaehler+1;
end
    
zaehler=0;
bedingung=true;

while bedingung
    disp("yap")
    if zaehler==3
        bedingung=false;
    end
    zaehler=zaehler+1;
end



%% 5 Zufallszahlen

% Um plots wie Histogramme oder Boxplots zu erklären, führen wir noch kurz die 
% Generierung von Zufallszahlen ein. Einer der wichtigestsen Befehle ist hierbei  
% rand(n), welcher einen Vektor mit n Zufallszahlen auf [0,1] erzeugt. 
% Flexibler ist der Befehl  randsample(x,n,replace,prob) , welcher n Elemente aus x zieht. 
% Mit dem Boolean replace kann Zurücklegen aktiviert, bzw. deaktiviert werden. 
% Mit dem Vektor prob kann die Wahrscheinlichkeit, dass ein Element gezogen wird 
% gewichtet werden.
% 
% Alle am PC generierten Zufallszahlen sind nicht echt zufällig, siehe Wikipedia,
% (https://de.wikipedia.org/wiki/Pseudozufall)
% Sie werden mit einem Algorithmus berechnet und können nicht vom echten Zufall 
% unterscheiden werden, jedoch können sie reproduziert werden, indem der selbe 
% Startwert, der sog. Seed übergeben wird. Wird kein Seed übergeben wird
% bei Matlab
% die Systemzeit als Seed benutzt.
clc
rng('shuffle')                %muss normal nicht gesetzt werden. Hier nur um bei 
                              % Wiederholungen einen "neuen" seed zu
                              % erhalten

rand(1)                       %Zufällige Zahl zwischen 0 und 1
rand(3)                       %Zufällige 3x3 Matrix
rand(1,3)                     %Vetor mit 3 zufällligen Zahlen 


randi(10,3)                   % 3 zufällige Integer zwischen 1 und 10

%seed
rng(440)                     %Alle Werte über dieser Zeile sind bei jeder Ausführung
                             %des Skripts anders, alle unterhalb immer gleich

randsample(5:15,3,true)      %3 zufällige zahlen zwischen 5 und 15, mit zurücklegen

    
% Es können auch Zufallszahlen nach bestimmten Verteilungen erzeugt werden
clc    

%Stetige Verteilungen
betarnd(1,2)
normrnd(0,1)
exprnd(3)
%[...]

%Diskrete Verteilungen
binornd(10,0.5)
poissrnd(10)
%[...]    
    


%% 6. Plotten

% In MATLAB wird in sog. Figures geplottet. D.h. vor jedem Fenster muss der
% Befehl figure der figure(n) aufgerufen werden. Der nächste Plotbefehl
% landet sofort in dieser Figure. Sollen mehr als nur ein Befehl geplottet
% werden so markiert man dies mit dem Befehl 'hold on'

%6.1 Lineplots, Scatterplots

%In MATLAB genügt der Befehl plot() zum plotten von Lineplots. Es gibt zwar 
%auch die Möglichkeit mit dem Befehl scatter() eine Scatterplot zu erstellen, 
%doch dies ist eher unüblich
clc
close all

x=0:0.05:3*pi;
y=sin(x);
figure(1)
plot(x,y)

% mit diversen optionalen Argumenten und Befehlen kann so ein Standadplot
% aufgehübscht werden

x_line=(0:0.5:3)*pi;
y_line=sin(x_line);

figure(2)
plot(x,y,'-g','linewidth',3)
hold on
plot(x,cos(x),'--b','linewidth',2)
plot(x_line,y_line,':r','marker','o','linewidth',1.5)
xlabel('x')
ylabel('y')
xlim([0,3*pi])
ylim([-1,1])
legend('Sinus','Cosinus','Approx. Sinus')
title('Trigonometrische Funktionen')
grid on


% Wie bereits erwähnt kann ein Scatterplot mit scatter() und mit plot()
% erstellt werden. Um zu zeigen, dass beide tatsächlich zu ähnlichen Ergebnissen kommen,
% führen wir hier gleich noch subplot() ein. Mit subplot() lassen sich
% mehrere plots in einer Figure speichern. Die Plots werden in einem n x m
% Gitter angeordnet, deswegen sieht ein Funktionsaufruf von subplot auch so
% aus: subplot(n,m,k) wobei k die Position des plots ist der als nächsten
% erstellt wird

n=200;

stoerterm=(rand(1,n)-0.5)*0.5;
x=rand(1,n)*pi*3;
y=sin(x)+stoerterm;
y2=1/5*x+stoerterm-1;

figure(3)

subplot(1,2,1)
plot(x,y,'bo')
hold on
plot(x,y2,'r+')
ylim([-1,1])

subplot(1,2,2)
scatter(x,y)
hold on
scatter(x,y2,'r+')
ylim([-1,1])

sgtitle("Scatter Plots")

    
% Es lassen sich auch zwei- oder dreidimensionale plots, wie z.B contourplots erstellen. 

x=-5:0.5:5;
y=-5:0.5:5;
[X,Y]=meshgrid(x,y);
Z=sin(sqrt(X.^2+Y.^2));

figure(4)
subplot(2,2,1)
mesh(X,Y,Z)

subplot(2,2,2)
surf(X,Y,Z)


subplot(2,2,3)
contour(X,Y,Z,'ShowText','on')

subplot(2,2,4)
contourf(X,Y,Z)


    
%% 6.2 "Statistische" Plots
% Ohne viel zu erklären, hier ein paar Möglichkeiten Datensätze zu visualisieren.
clc
close all
%%
% 
geld=[normrnd(1,1.5,1000,1);normrnd(7,1,750,1)];

figure(5)
histogram(geld,20)
xlabel('Kontostand in €')
ylabel('Häufigkeit')
title('Kontostand von Studenten ;)')
   
werte=exprnd(3,1000,1);
figure(6)
boxplot(werte)

labels = {'Apfel','Banane','Birne','Erdbeere'};
sizes = [15, 30, 45, 10];
explode = [0, 0.1, 0, 0];
    
f=figure(7);
subplot(1,2,1)
bar(categorical(labels),sizes)
title('Oh, ein Balkendiagramm')
subplot(1,2,2)
pie(sizes,explode,labels)
title('Mhhhh, Torte!')

% Schlussendlich wollen wir den Plot noch speichern. 
saveas(gcf,'diagramme.png') %Hier steht gcf für `get current figure'. 
saveas(f,'diagramme2.png')  %Da wir figure(7) in die varaible f gespeichert haben, können wir diese auch 
                            % der Funktion saveas() übereben
    
    
    

%% Funktionen                         
    
function result=addition(a,b,c)
    result=a+b+c;
end

function result=additionMitUeberschreiben(a,b,c)
    a=a+b+c; % a auserhalb der Funktion wird nicht überschrieben
    result=a;
end


















