diff --git a/algorithm/__init__.py b/algorithm/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/algorithm/pla/__init__.py b/algorithm/pla/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/algorithm/pla/perceptron.py b/algorithm/pla/perceptron.py
new file mode 100644
index 0000000000000000000000000000000000000000..93ecac99c2bb535ba974343a99ba8d26dbe83e4b
--- /dev/null
+++ b/algorithm/pla/perceptron.py
@@ -0,0 +1,29 @@
+import numpy
+
+
+class Perceptron:
+
+    def __init__(self, start_weights: list, threshold: float, transfer_function):
+        # Das erste Gewicht ist -threshold. Hierdurch muss der Threshold nicht bei jeder Summe mitberechnet werden
+        self.weights = [- threshold] + start_weights
+        self.transfer_function = transfer_function
+
+    def classify(self, features: list):
+        """
+        Klassifiziert einen Vektor an Merkmalen.
+        Die Dimension des Merkmalsvektors muss dabei mt der Dimension des Startgewichtvektors übereinstimmen.
+        """
+
+        if len(features) != len(self.weights) - 1:
+            print("Es wurden nicht genug Features übergeben")
+            return
+
+        # Das erste Merkmal m_0 ist konstant 1
+        all_features = [1] + features
+        transposed_weights = numpy.transpose(self.weights)
+
+        # Multipliziere die transponierten mit dem Merkmalsvektor
+        result = numpy.matmul(transposed_weights, all_features)
+
+        # Wende die Aktivierungsfunktion auf das Ergebnis an
+        return self.transfer_function(result)
diff --git a/algorithm/pla/test_perceptron.py b/algorithm/pla/test_perceptron.py
new file mode 100644
index 0000000000000000000000000000000000000000..bc1ac98befe827a65aa5c2e80f5f33965ab4fceb
--- /dev/null
+++ b/algorithm/pla/test_perceptron.py
@@ -0,0 +1,33 @@
+from algorithm.pla.perceptron import Perceptron
+from algorithm.pla.transfer_functions import normalized_tanh
+from server.testserver import get_testdata, send_result
+
+
+def test_perceptron():
+    response = get_testdata("perceptron_processing")
+    results = []
+
+    for data in response['data']:
+        # Hole die einzelnen Traningsdaten
+        test_id = data['id']
+        all_weights = data['weights']
+        features = data['input']
+
+        # Der Threshold ist der erste Wert in der Liste.
+        # Der Rest sind die anderen Gewichte
+        threshold = all_weights[0] * -1
+        weights = all_weights[1: len(all_weights)]
+
+        # Klassifizere die Trainingsdaten
+        perceptron = Perceptron(weights, threshold, normalized_tanh)
+        result = perceptron.classify(features)
+
+        # Hänge das Ergebnis in der Liste an
+        results.append({'id': test_id, 'value': result})
+
+    # Sende die Ergebnis-Liste zurück an das IUL
+    send_result('perceptron_processing', {'session': response['session'], 'results': results})
+
+
+if __name__ == '__main__':
+    test_perceptron()
diff --git a/algorithm/pla/transfer_functions.py b/algorithm/pla/transfer_functions.py
new file mode 100644
index 0000000000000000000000000000000000000000..3a796314093df6e3446ab8c4a2f2284ef77c9eb7
--- /dev/null
+++ b/algorithm/pla/transfer_functions.py
@@ -0,0 +1,9 @@
+import numpy
+
+
+def normalized_tanh(value):
+    """ Der Tangens hyperbolicus hat einen Wertebereich von ]-1, 1[. Diese Funktion normiert den Wertebereich zu ]0, 1["""
+
+    # Verschiebe den Tangenz um 1 nach oben --> Wertebereich ]0, 2[
+    # Teile durch Zwei --> Wertebereich ]0, 1[
+    return (numpy.tanh(value) + 1) / 2
\ No newline at end of file