Skip to content
Snippets Groups Projects
Commit 70017b24 authored by voic00's avatar voic00
Browse files

neue generation von edge dicts

parent 015034dd
No related tags found
No related merge requests found
......@@ -81,27 +81,12 @@ def add_cycle_constraints(prob, y, cycles, added_constraints):
logging.info(f"Constraint hinzugefügt für: {cycle}")
logging.info(f"Constraint hinzugefügt für alle bestehenden cycles.")
def add_edge_to_node_dict(dict : dict[int, list[int]], edge : tuple[int, int], minBPartitionValue : int) -> None:
# Find out which Value belongs to B
x, y = edge
bNode, aNode = 0, 0
# If the graph is truly bi-partite we can only check one value the other HAS TO be in the other partition
if x >= minBPartitionValue:
bNode, aNode = x, y
else:
bNode, aNode = y, x
# Add node to dict if not already there
if not bNode in dict:
dict[bNode] = []
# Append edge to dictionary of edges
dict[bNode].append(aNode)
def parse_graph_file(graph_file : str) -> tuple[int, int, list[tuple[int ,int]]]:
def parse_graph_file_for_dicts(graph_file : str) -> tuple[int, list[int], int, list[int]]:
edges = []
number_of_nodes_in_A = 0
number_of_nodes_in_B = 0
dictA = {}
dictB = {}
with open(graph_file, "r") as file:
for line in file:
if line.startswith('c'):
......@@ -113,9 +98,28 @@ def parse_graph_file(graph_file : str) -> tuple[int, int, list[tuple[int ,int]]]
else:
x, y = map(int, line.split())
edges.append((x, y))
if x <= number_of_nodes_in_A: # x ist Knoten in A
return number_of_nodes_in_A, number_of_nodes_in_B, edges
if x not in dictA:
dictA[x] = []
dictA[x].append(y)
if y not in dictB:
dictB[y] = []
dictB[y].append(x)
if x > number_of_nodes_in_A: # x ist Knoten in B
if x not in dictB:
dictB[x] = []
dictB[x].append(y)
if y not in dictA:
dictA[y] = []
dictA[y].append(x)
return dictA, number_of_nodes_in_A, dictB, number_of_nodes_in_B, edges
def solve_bipartite_minimization(graph_file):
start_time = time()
......@@ -127,26 +131,23 @@ def solve_bipartite_minimization(graph_file):
crossing_path = os.path.join('mytests/crossings', crossing_name)
logging.info(f"Die Ausgabedatei wird {solution_path} sein")
number_of_nodes_in_A, number_of_nodes_in_B, edges = parse_graph_file(graph_file)
nodes_A, number_of_nodes_in_A, nodes_B, number_of_nodes_in_B, edges = parse_graph_file_for_dicts(graph_file)
logging.info(f"Größen der Partitionen: A={number_of_nodes_in_A}, B={number_of_nodes_in_B}")
logging.info(f"{len(edges)} Kanten geladen.")
# Suche nach allen Knoten B, die nur eine Kante haben
# Als erstes: Erstelle Dict mit Keys = Knoten in B, Value = Liste aller Kanten
B_nodes_with_associated_A_nodes : dict[int, list[int]]= {}
for edge in edges:
add_edge_to_node_dict(B_nodes_with_associated_A_nodes, edge, number_of_nodes_in_A + 1)
# Erstelle Liste aller Nodes in B mit einem Grad größer 1
nodes_with_degree_higher_one = dict(filter(lambda keyValuePair: len(keyValuePair[1]) > 1, B_nodes_with_associated_A_nodes.items()))
nodes_with_degree_higher_one = dict(filter(lambda keyValuePair: len(keyValuePair[1]) > 1, nodes_B.items()))
# Erstelle Liste aller Nodes in B mit einem Grad = 1 und
nodes_with_degree_equals_one = [(bNode, aNodes[0]) for (bNode, aNodes) in B_nodes_with_associated_A_nodes.items() if len(aNodes) == 1]
nodes_with_degree_equals_one = [(bNode, aNodes[0]) for (bNode, aNodes) in nodes_B.items() if len(aNodes) == 1]
# Sortiere sie nach ihrem korrospondierenden Knoten Wert von A, dann sind alle Knoten in B mit Grad 1 so sortiert, dass ihre Kanten kreuzungsfrei sind
nodes_with_degree_equals_one.sort(key= lambda node: node[1])
# Erstelle Liste mit nur den Grad 1 Knoten aus B, erleichtert nachher das Filtern der Edges
nodes_with_degree_equals_one_bNode_only = [bNode for bNode, _ in nodes_with_degree_equals_one]
logging.info(f"{len(B_nodes_with_associated_A_nodes)} viele Knoten, davon mit Grad 1: {len(nodes_with_degree_equals_one)} und Knoten Grads > 1: {len(nodes_with_degree_higher_one)}.")
logging.info(f"{len(nodes_B)} viele Knoten, davon mit Grad 1: {len(nodes_with_degree_equals_one)} und Knoten Grads > 1: {len(nodes_with_degree_higher_one)}.")
# Erstelle die Listen der Kanten, sortiert danach, ob sie in B mit einem Knoten mit Grad 1 verbunden sind, oder höhergradig sind
edges_of_degree_one_nodes = [(x, y) for x, y in edges if x in nodes_with_degree_equals_one_bNode_only or y in nodes_with_degree_equals_one_bNode_only]
......@@ -163,16 +164,6 @@ def solve_bipartite_minimization(graph_file):
prob = LpProblem("Minimize_Crossings", LpMinimize)
# Erstelle Konstanten für die Sortierung
# Variable y(i, j) : Liegt i links von j ? Wenn ja 1, sonst 0.
# positionalVariablesForDegreeOne = {(nodes_with_degree_equals_one[i], nodes_with_degree_equals_one[i+1]) : LpVariable(f"y_{nodes_with_degree_equals_one[i]}_{nodes_with_degree_equals_one[i+1]}", 0, 1, cat='Binary') for i in range(len(nodes_with_degree_equals_one)-1)}
# crossingVariablesForDegreeOne = {(i, j, k, l): LpVariable(f"c_{i}_{j}_{k}_{l}", 0, 1, cat='Binary') for (i, j) in edges_of_degree_one_nodes for (k, l) in edges_of_degree_one_nodes}
# positionalVariablesForMultiDegree = {(nodes_with_degree_higher_one[i], nod)}
# crossingVariablesForMultiDegree = {}
# crossingVariablesBetweenMultiAndOne = {}
# Für alle Knoten {B | Knoten Grad == 1} x {B | Knoten Grad == 1}: erstelle Positions variable
positional_vars_degree_one_nodes_only = {}
for nodeX in range(number_of_nodes_in_A + 1, number_of_nodes_in_A + number_of_nodes_in_B + 1):
......@@ -199,18 +190,19 @@ def solve_bipartite_minimization(graph_file):
# for (k, l) in edges:
positionalVariables = {(i, j): LpVariable(f"y_{i}_{j}", 0, 1, cat='Binary') for i in range(number_of_nodes_in_A + 1, number_of_nodes_in_A + number_of_nodes_in_B + 1) for j in range(number_of_nodes_in_A + 1, number_of_nodes_in_A + number_of_nodes_in_B + 1) if i != j}# and not (i, j) in positional_vars_degree_one_nodes_only}
positionalVariables = {(i, j): LpVariable(f"y_{i}_{j}", 0, 1, cat='Binary') for i in range(number_of_nodes_in_A + 1, number_of_nodes_in_A + number_of_nodes_in_B + 1) for j in range(number_of_nodes_in_A + 1, number_of_nodes_in_A + number_of_nodes_in_B + 1) if i != j and not (i, j) in positional_vars_degree_one_nodes_only}
# Variable c(i,j,k,l) : Kreuzt die Kante zwischen i-j die Kante zwischen k-l (wobei i, k Knoten in A und j,l Knoten in B)
# Da sich Kanten nicht im Knoten Kreuzen können müsst man i!=k und j!=l als Bedingung einfügen
crossingVariables = {(i, j, k, l): LpVariable(f"c_{i}_{j}_{k}_{l}", 0, 1, cat='Binary') for (i, j) in edges for (k, l) in edges if (i,j)!=(k,l) and j!=l}
crossingVariables = {(i, j, k, l): LpVariable(f"c_{i}_{j}_{k}_{l}", 0, 1, cat='Binary') for (i, j) in edges_for_nodes_with_higher_degree for (k, l) in edges_for_nodes_with_higher_degree if (i,j)!=(k,l) and j!=l and i!=k and not (i in nodes_with_degree_equals_one and j in nodes_with_degree_equals_one and k in nodes_with_degree_equals_one and l in nodes_with_degree_equals_one)}
logging.info("y und c geladen.")
logging.info(f"Positions Variablen y: gesamt erwartet {number_of_nodes_in_B * (number_of_nodes_in_B - 1)}, davon wirklich gesamt {len(positional_vars_degree_one_nodes_only) + len(positionalVariables)}, für Knoten mit Grad 1: {len(positional_vars_degree_one_nodes_only)}, für Knoten mit Grad > 1: {len(positionalVariables)}")
logging.info(f"{len(crossingVariables)} viele Crossing Variablen aufgestellt. (Für Knoten mit Grad > 1). Maximal: {len(edges_for_nodes_with_higher_degree) * (len(edges_for_nodes_with_higher_degree)-1)} waren erwartet.") #TODO Funktion finden wie ich die erwarteten Anzahl an Crossings einfach errechnen kann
prob += lpSum(crossingVariables.values())
logging.info("Zielfunktion aufgestellt.")
for (i, j) in edges:
for (k, l) in edges:
for (i, j) in edges_for_nodes_with_higher_degree:
for (k, l) in edges_for_nodes_with_higher_degree:
if j==l or (i,j)==(k,l):
continue
if k > i:
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment