diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d4a7e6342aadfa4c073470fe8ecd841964757105
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+test.py
+test?.py
\ No newline at end of file
diff --git a/README.md b/README.md
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7f0d7b78ed9991be9421112887b4f03ae79cf2fc 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1,48 @@
+# Backend
+
+## Project Structure
+
+    APPALGO-SOSE24
+    Backend
+    │
+    └── src
+        |
+        ├── main.py
+        │
+        └── requirements.txt
+
+## Setup
+
+1. **Install Python**: go to [python.org](https://wiki.python.org/moin/BeginnersGuide/Download)
+
+3. **Navigate to Backend**:
+
+    ```bash
+    cd appalgo-sose24/src
+    ```
+
+4. **Create and Activate a Virtual Environment** (Optional but recommended):
+
+    ```bash
+    python3 -m venv venv
+    ```
+    In a Unix-based System run:
+    ```bash
+    source venv/bin/activate
+    ```
+    In Windows run:
+    ```bash
+    venv\Scripts\activate
+    ```
+
+5. **Install the Dependencies:**
+
+    ```bash
+    pip install -r requirements.txt
+    ```
+
+## Test Setup
+
+1. Geh sicher, dass alle Dependencies installiert sind.
+
+2.
\ No newline at end of file
diff --git a/src/README.md b/src/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ce6672d4d95b08d24d69752d49d76b70c93aed43
--- /dev/null
+++ b/src/README.md
@@ -0,0 +1,10 @@
+1. Crossing Variables C_i_j_k_l
+
+
+Entscheidungsvariablen:
+    x ij zur Angabe der Reihenfolge zwischen i und j in Menge A.
+    y ij zur Angabe der Reihenfolge zwischen i und j in Menge B.
+    c ijkl, um anzugeben, ob es eine Kreuzung zwischen den Kanten (i, j) und (k, l) gibt.
+
+xij = 1 bedeutet, dass π1(i) < π1(j) — Knoten i kommt vor Knoten j in der ersten Permutation.
+yij = 1 bedeutet, dass π2(i) < π2(j) — Knoten i kommt vor Knoten j in der zweiten Permutation.
\ No newline at end of file
diff --git a/src/backupmain.py b/src/backupmain.py
new file mode 100644
index 0000000000000000000000000000000000000000..635dfb35ba166ec4035a8922eff5d885b15fb1e8
--- /dev/null
+++ b/src/backupmain.py
@@ -0,0 +1,99 @@
+import os
+import logging
+# Konfiguriere Logging
+logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
+from pulp import *
+
+def solve_bipartite_minimization(graph_file):
+    logging.info(f"Prozess für {graph_file} gestartet")
+
+    # Extrahiere den Basisnamen der Eingabedatei
+    base_name = os.path.basename(graph_file)
+    # Erstelle den Ausgabepfad
+    output_file = os.path.join('solution_instances', base_name)
+    logging.info(f"Die Ausgabedatei wird {output_file} sein")
+
+    edges = []
+    with open(graph_file, "r") as file:
+        for line in file:
+            if line.startswith('c'):
+                continue
+            elif line.startswith('p'):
+                parts = line.split()
+                n0 = int(parts[2])  # Anzahl der Knoten in A
+                n1 = int(parts[3])  # Anzahl der Knoten in B
+                logging.info(f"Größen der Partitionen: A={n0}, B={n1}")
+            else:
+                x, y = map(int, line.split())
+                edges.append((x, y))
+    logging.info(f"{len(edges)} Kanten geladen.")
+    
+    prob = LpProblem("Minimize_Crossings", LpMinimize)
+
+    # Boolesche Variablen für relative Positionen innerhalb jeder Partition
+    x = {(i, j): LpVariable(f"x_{i}_{j}", 0, 1, cat='Binary') for i in range(1, n0 + 1) for j in range(1, n0 + 1) if i < j}
+    y = {(i, j): LpVariable(f"y_{i}_{j}", 0, 1, cat='Binary') for i in range(n0 + 1, n0 + n1 + 1) for j in range(n0 + 1, n0 + n1 + 1) if i != j}
+    logging.info("x und y geladen.")
+
+    # Crossing Variables
+    c = {}
+    for (i, j) in edges:
+        for (k, l) in edges:
+            if i < j and k < l and i < k and j != l:
+                c[(i, j, k, l)] = LpVariable(f"c_{i}_{j}_{k}_{l}", 0, 1, cat='Binary')
+    logging.info("c geladen.")
+    # Zielfunktion, die minimiert werden soll
+    prob += lpSum(c.values())
+    logging.info("Zielfunktion aufgestellt.")
+    # Crossing Constraints
+    for (i, j, k, l) in c:
+        if j < l:
+            prob += -c[(i, j, k, l)] <= y[(j, l)] - x[(i, k)] <= c[(i, j, k, l)]
+        if l > j:
+            prob += 1 - c[(i, j, k, l)] <= y[(l, j)] + x[(i, k)] <= 1 + c[(i, j, k, l)]
+    logging.info("Crossing Constraints aufgestellt.")
+    
+    # Constraints für x und y
+    for i in range(1, n0):
+        for j in range(i + 1, n0 + 1):
+            for k in range(j + 1, n0 + 1):
+                prob += 0 <= x[(i, j)] + x[(j, k)] - x[(i, k)] == 1
+    logging.info("X fest Constraints aufgestellt.")
+
+    for i in range(n0 + 1, n0 + n1):
+        for j in range(i + 1, n0 + n1 + 1):
+            for k in range(j + 1, n0 + n1 + 1):
+                prob +=  0 <= y[(i, j)] + y[(j, k)] - y[(i, k)] <= 1
+    logging.info("Y variable Constraints aufgestellt.")
+
+    # Constraints für die relative Ordnung innerhalb der Partitionen
+    for (i, j) in y:
+        prob += y[(i, j)] + y[(j, i)] == 1  # genau einer muss wahr sein
+    logging.info("Relative Ordnung muss wahr sein.")
+
+    prob.solve()
+    logging.info(f"Status der Lösung: {LpStatus[prob.status]}")
+
+    # Check if a solution exists and print the results
+    if  prob.status == LpStatusOptimal:
+        logging.info("Optimale Lösung gefunden. Ergebnisse werden gespeichert.")
+        # Berechne zuerst die Summen in einer Liste
+        position_sum = [(j, sum(y[(j, k)].value() for k in range(n0+1, n0+n1+1) if j != k)) for j in range(n0+1, n0+n1+1)]
+
+        # Nutze diese Liste dann im sorted() Aufruf
+        sorted_b = sorted(position_sum, key=lambda x: -x[1])
+
+        # Stelle sicher, dass das Verzeichnis existiert
+        os.makedirs(os.path.dirname(output_file), exist_ok=True)
+
+        # Speichere die sortierten Ergebnisse in der Ausgabedatei
+        with open(output_file, 'w') as f:
+            for b, _ in sorted_b:
+                f.write(f"{b}\n")
+        logging.info(f"Ergebnisse in {output_file} gespeichert")
+    else:
+        logging.warning("Keine optimale Lösung gefunden.")
+
+
+test_file = 'test_instances/1.gr'
+solve_bipartite_minimization(test_file)
diff --git a/src/fortesting.py b/src/fortesting.py
new file mode 100644
index 0000000000000000000000000000000000000000..6ee4ef50bb16137824b600671b193e7f93ae133e
--- /dev/null
+++ b/src/fortesting.py
@@ -0,0 +1,95 @@
+import os
+from pulp import *
+
+def solve_bipartite_minimization(graph_file):
+
+    # Extrahiere den Basisnamen der Eingabedatei
+    base_name = os.path.basename(graph_file)
+    # Erstelle den Ausgabepfad
+    output_file = os.path.join('solution_instances', base_name)
+
+    edges = []
+    with open(graph_file, "r") as file:
+        for line in file:
+            if line.startswith('c'):
+                continue
+            elif line.startswith('p'):
+                parts = line.split()
+                n0 = int(parts[2])  # Anzahl der Knoten in A
+                n1 = int(parts[3])  # Anzahl der Knoten in B
+            else:
+                x, y = map(int, line.split())
+                edges.append((x, y))
+
+    prob = LpProblem("Minimize_Crossings", LpMinimize)
+
+    # Boolesche Variablen für relative Positionen innerhalb jeder Partition
+    x = {(i, j): LpVariable(f"x_{i}_{j}", 0, 1, cat='Binary') for i in range(1, n0 + 1) for j in range(1, n0 + 1) if i < j}
+    y = {(i, j): LpVariable(f"y_{i}_{j}", 0, 1, cat='Binary') for i in range(n0 + 1, n0 + n1 + 1) for j in range(n0 + 1, n0 + n1 + 1) if i != j}
+    #print("x:",x)
+    #print("y:",y)
+    
+    # Crossing Variables
+    c = {}
+    for (i, j) in edges:
+        for (k, l) in edges:
+            if i < j and k < l and i < k and j != l:
+                c[(i, j, k, l)] = LpVariable(f"c_{i}_{j}_{k}_{l}", 0, 1, cat='Binary')
+
+    # Zielfunktion, die minimiert werden soll
+    prob += lpSum(c.values())
+
+    # Crossing Constraints
+    for (i, j, k, l) in c:
+        if j < l:
+            prob += -c[(i, j, k, l)] <= y[(j, l)] - x[(i, k)] <= c[(i, j, k, l)]
+        if l > j:
+            prob += 1 - c[(i, j, k, l)] <= y[(l, j)] + x[(i, k)] <= 1 + c[(i, j, k, l)]
+    
+    # Constraints für x und y
+    for i in range(1, n0):
+        for j in range(i + 1, n0 + 1):
+            for k in range(j + 1, n0 + 1):
+                prob += 0 <= x[(i, j)] + x[(j, k)] - x[(i, k)] == 1
+   
+    for i in range(n0 + 1, n0 + n1):
+        for j in range(i + 1, n0 + n1 + 1):
+            for k in range(j + 1, n0 + n1 + 1):
+                prob +=  0 <= y[(i, j)] + y[(j, k)] - y[(i, k)] <= 1
+
+    # Constraints für die relative Ordnung innerhalb der Partitionen
+    for (i, j) in y:
+        prob += y[(i, j)] + y[(j, i)] == 1  # genau einer muss wahr sein
+   
+    prob.solve()
+
+    print("Status:", LpStatus[prob.status])
+    
+    for v in prob.variables():
+        print(v.name, "=", v.varValue)
+
+    # Check if a solution exists and print the results
+    if  prob.status == LpStatusOptimal:
+        print("Optimal arrangement of B:")
+
+        # Berechne zuerst die Summen in einer Liste
+        position_sum = [(j, sum(y[(j, k)].value() for k in range(n0+1, n0+n1+1) if j != k)) for j in range(n0+1, n0+n1+1)]
+
+        # Nutze diese Liste dann im sorted() Aufruf
+        sorted_b = sorted(position_sum, key=lambda x: -x[1])
+
+        # Stelle sicher, dass das Verzeichnis existiert
+        os.makedirs(os.path.dirname(output_file), exist_ok=True)
+
+        # Speichere die sortierten Ergebnisse in der Ausgabedatei
+        with open(output_file, 'w') as f:
+            for b, _ in sorted_b:
+                f.write(f"{b}\n")
+                print(f"{b}")
+        print(f"Results saved to {output_file}")
+    else:
+        print("No optimal solution found.")
+
+
+test_file = 'test_instances/0.gr'
+solve_bipartite_minimization(test_file)
diff --git a/src/main.py b/src/main.py
new file mode 100644
index 0000000000000000000000000000000000000000..ecc563ac1de900d4211212b385ce095feb39394f
--- /dev/null
+++ b/src/main.py
@@ -0,0 +1,99 @@
+import os
+import logging
+# Konfiguriere Logging
+logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
+from pulp import *
+
+def solve_bipartite_minimization(graph_file):
+    logging.info(f"Prozess für {graph_file} gestartet")
+
+    # Extrahiere den Basisnamen der Eingabedatei
+    base_name = os.path.basename(graph_file)
+    # Erstelle den Ausgabepfad
+    output_file = os.path.join('solution_instances', base_name)
+    logging.info(f"Die Ausgabedatei wird {output_file} sein")
+
+    edges = []
+    with open(graph_file, "r") as file:
+        for line in file:
+            if line.startswith('c'):
+                continue
+            elif line.startswith('p'):
+                parts = line.split()
+                n0 = int(parts[2])  # Anzahl der Knoten in A
+                n1 = int(parts[3])  # Anzahl der Knoten in B
+                logging.info(f"Größen der Partitionen: A={n0}, B={n1}")
+            else:
+                x, y = map(int, line.split())
+                edges.append((x, y))
+    logging.info(f"{len(edges)} Kanten geladen.")
+    
+    prob = LpProblem("Minimize_Crossings", LpMinimize)
+
+    # Boolesche Variablen für relative Positionen innerhalb jeder Partition
+    x = {(i, j): LpVariable(f"x_{i}_{j}", 0, 1, cat='Binary') for i in range(1, n0 + 1) for j in range(1, n0 + 1) if i < j}
+    y = {(i, j): LpVariable(f"y_{i}_{j}", 0, 1, cat='Binary') for i in range(n0 + 1, n0 + n1 + 1) for j in range(n0 + 1, n0 + n1 + 1) if i != j}
+    logging.info("x und y geladen.")
+
+    # Crossing Variables
+    c = {}
+    for (i, j) in edges:
+        for (k, l) in edges:
+            if i < j and k < l and i < k and j != l:
+                c[(i, j, k, l)] = LpVariable(f"c_{i}_{j}_{k}_{l}", 0, 1, cat='Binary')
+    logging.info("c geladen.")
+    # Zielfunktion, die minimiert werden soll
+    prob += lpSum(c.values())
+    logging.info("Zielfunktion aufgestellt.")
+    # Crossing Constraints
+    for (i, j, k, l) in c:
+        if j < l:
+            prob += -c[(i, j, k, l)] <= y[(j, l)] - x[(i, k)] <= c[(i, j, k, l)]
+        if l > j:
+            prob += 1 - c[(i, j, k, l)] <= y[(l, j)] + x[(i, k)] <= 1 + c[(i, j, k, l)]
+    logging.info("Crossing Constraints aufgestellt.")
+
+    # Constraints für x und y (ZU LANGE LAUFZEIT)
+    for i in range(1, n0):
+        for j in range(i + 1, n0 + 1):
+            for k in range(j + 1, n0 + 1):
+                prob += 0 <= x[(i, j)] + x[(j, k)] - x[(i, k)] == 1
+    logging.info("X fest Constraints aufgestellt.")
+
+    for i in range(n0 + 1, n0 + n1):
+        for j in range(i + 1, n0 + n1 + 1):
+            for k in range(j + 1, n0 + n1 + 1):
+                prob +=  0 <= y[(i, j)] + y[(j, k)] - y[(i, k)] <= 1
+    logging.info("Y variable Constraints aufgestellt.")
+
+    # Constraints für die relative Ordnung innerhalb der Partitionen
+    for (i, j) in y:
+        prob += y[(i, j)] + y[(j, i)] == 1  # genau einer muss wahr sein
+    logging.info("Relative Ordnung muss wahr sein.")
+
+    prob.solve()
+    logging.info(f"Status der Lösung: {LpStatus[prob.status]}")
+
+    # Check if a solution exists and print the results
+    if  prob.status == LpStatusOptimal:
+        logging.info("Optimale Lösung gefunden. Ergebnisse werden gespeichert.")
+        # Berechne zuerst die Summen in einer Liste
+        position_sum = [(j, sum(y[(j, k)].value() for k in range(n0+1, n0+n1+1) if j != k)) for j in range(n0+1, n0+n1+1)]
+
+        # Nutze diese Liste dann im sorted() Aufruf
+        sorted_b = sorted(position_sum, key=lambda x: -x[1])
+
+        # Stelle sicher, dass das Verzeichnis existiert
+        os.makedirs(os.path.dirname(output_file), exist_ok=True)
+
+        # Speichere die sortierten Ergebnisse in der Ausgabedatei
+        with open(output_file, 'w') as f:
+            for b, _ in sorted_b:
+                f.write(f"{b}\n")
+        logging.info(f"Ergebnisse in {output_file} gespeichert")
+    else:
+        logging.warning("Keine optimale Lösung gefunden.")
+
+
+test_file = 'test_instances/0.gr'
+solve_bipartite_minimization(test_file)
diff --git a/src/requirements.txt b/src/requirements.txt
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9604acd68094003a769edd98890d88b16d19d571 100644
--- a/src/requirements.txt
+++ b/src/requirements.txt
@@ -0,0 +1,2 @@
+pulp==2.6.0
+pace2024-verifier
diff --git a/src/solution_instances/0.gr b/src/solution_instances/0.gr
new file mode 100644
index 0000000000000000000000000000000000000000..292ff76f03cd38c78e04979106e1fcb289a304c8
--- /dev/null
+++ b/src/solution_instances/0.gr
@@ -0,0 +1,3 @@
+5
+4
+6
diff --git a/src/test_instances/0.gr b/src/test_instances/0.gr
new file mode 100644
index 0000000000000000000000000000000000000000..edee319e50c97e75cd21eb46ab3a9d7c8e9877b0
--- /dev/null
+++ b/src/test_instances/0.gr
@@ -0,0 +1,4 @@
+p ocr 3 3 3
+1 5
+2 4
+3 6
\ No newline at end of file