From 8cba2fdf13870cb8a8fb7fae02090af77a7b01e9 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Fri, 17 Jun 2022 08:04:27 +0200 Subject: [PATCH] master > master: code py - display volle loesung statt padding --- .../src/algorithms/rucksack/algorithms.py | 30 +++++++++---------- .../python/src/algorithms/rucksack/display.py | 7 ++--- code/python/src/models/rucksack/logging.py | 2 +- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/code/python/src/algorithms/rucksack/algorithms.py b/code/python/src/algorithms/rucksack/algorithms.py index 2bb5c2d..482e506 100644 --- a/code/python/src/algorithms/rucksack/algorithms.py +++ b/code/python/src/algorithms/rucksack/algorithms.py @@ -130,13 +130,13 @@ def rucksack_branch_and_bound_algorithm( while not S.empty(): # top-Element auslesen und Bound berechnen: A: Mask = S.top(); - bound_subtree, choice, order_, pad = estimate_lower_bound(mask=A, max_cost=max_cost, costs=costs, values=values, items=items); + bound_subtree, choice, order_, state = estimate_lower_bound(mask=A, max_cost=max_cost, costs=costs, values=values, items=items); # für logging (irrelevant für Algorithmus): if verbose: - step = Step(bound=bound, bound_subtree=bound_subtree, stack_str=str(S), choice=choice, order=order_, indexes=A.indexes_unset, pad=pad); + step = Step(bound=bound, bound_subtree=bound_subtree, stack_str=str(S), choice=choice, order=order_, indexes=A.indexes_unset, solution=state); if bound_subtree < bound: - if not A.splittable() or pad != MaskValue.UNSET: + if state is not None: step.move = EnumBranchAndBoundMove.BOUND; step.bound = bound_subtree; else: @@ -147,12 +147,9 @@ def rucksack_branch_and_bound_algorithm( # Update nur nötig, wenn die (eingeschätzte) untere Schranke von A das bisherige Minimum verbessert: if bound_subtree < bound: # Bound aktualisieren, wenn sich A nicht weiter aufteilen od. wenn sich A wie eine einelementige Option behandeln läst: - if not A.splittable() or pad != MaskValue.UNSET: + if state is not None: bound = bound_subtree; - # falls A als einelementige Menge betrachtet werden kann, ersetze unbekannte Werte: - if pad != MaskValue.UNSET: - A = A.pad(pad); - mask = A; + mask = state; # Branch sonst else: B, C = A.split(); @@ -207,7 +204,7 @@ def estimate_lower_bound( costs: np.ndarray, values: np.ndarray, items: np.ndarray, -) -> Tuple[float, List[Fraction], List[int], MaskValue]: +) -> Tuple[float, List[Fraction], List[int], Optional[Mask]]: ''' Wenn partielle Information über den Rucksack festgelegt ist, kann man bei dem unbekannten Teil das Rucksack-Problem @@ -229,14 +226,17 @@ def estimate_lower_bound( # Für Rest des Rucksacks (Items mit unbekanntem Status): cost_rest = max_cost - cost_rucksack; - pad = MaskValue.UNSET; + state = None; # Prüfe, ob man als Lösung alles/nichts hinzufügen kann: - if len(indexes_unset) > 0 and sum(costs[indexes_unset]) <= cost_rest: - pad = MaskValue.ONE; + if len(indexes_unset) == 0: + state = mask; + value_rest = 0; + elif sum(costs[indexes_unset]) <= cost_rest: + state = mask.pad(MaskValue.ONE); choice[indexes_unset] = Fraction(1); value_rest = sum(values[indexes_unset]); - elif len(indexes_unset) > 0 and min(costs[indexes_unset]) > cost_rest: - pad = MaskValue.ZERO; + elif min(costs[indexes_unset]) > cost_rest: + state = mask.pad(MaskValue.ZERO); choice[indexes_unset] = Fraction(0); value_rest = 0; # Sonst mit Greedy-Algorithmus lösen: @@ -259,4 +259,4 @@ def estimate_lower_bound( value_max_est = value_rucksack + value_rest; # Ausgabe mit -1 multiplizieren (weil maximiert wird): - return -value_max_est, choice.tolist(), order.tolist(), pad; + return -value_max_est, choice.tolist(), order.tolist(), state; diff --git a/code/python/src/algorithms/rucksack/display.py b/code/python/src/algorithms/rucksack/display.py index 96ca3d2..9f3fc05 100644 --- a/code/python/src/algorithms/rucksack/display.py +++ b/code/python/src/algorithms/rucksack/display.py @@ -113,7 +113,7 @@ def display_branch_and_bound(values: np.ndarray, steps: List[Step]) -> str: else: expr = ''; bound_str = f'{step.bound:+g}'; - pad_str = ('' if step.pad == MaskValue.UNSET else step.pad.value); + solution_str = f'{step.solution or ""}'; move_str = ('' if step.move == EnumBranchAndBoundMove.NONE else step.move.value); if i == index_soln: bound_str = f'* \x1b[92;1m{bound_str}\x1b[0m'; @@ -122,7 +122,7 @@ def display_branch_and_bound(values: np.ndarray, steps: List[Step]) -> str: 'bound_subtree': f'{step.bound_subtree:g}', 'bound_subtree_sum': expr, 'stack': step.stack_str, - 'pad': f'\x1b[2m{pad_str}\x1b[0m', + 'solution': f'\x1b[2m{solution_str}\x1b[0m', 'move': f'\x1b[2m{move_str}\x1b[0m', }); @@ -130,7 +130,7 @@ def display_branch_and_bound(values: np.ndarray, steps: List[Step]) -> str: # benutze pandas-Dataframe + tabulate, um schöner darzustellen: repr = tabulate( table, - headers=['bound', 'g(TOP(S))', '', 'S — stack', '\x1b[2mpad?\x1b[0m', '\x1b[2mmove\x1b[0m'], + headers=['bound', 'g(TOP(S))', '', 'S — stack', '\x1b[2msoln\x1b[0m', '\x1b[2mmove\x1b[0m'], showindex=False, colalign=('right', 'right', 'left', 'right', 'center', 'left'), tablefmt='simple' @@ -167,7 +167,6 @@ def display_sum( if not show_all_weights: parts = list(filter(lambda x: x[1] > 0, parts)); - value = sum([ u*x for _, u, x in parts ]); expr = '\x1b[2m + \x1b[0m'.join(map(render, parts)); if as_maximum: diff --git a/code/python/src/models/rucksack/logging.py b/code/python/src/models/rucksack/logging.py index 187500d..1ace2ce 100644 --- a/code/python/src/models/rucksack/logging.py +++ b/code/python/src/models/rucksack/logging.py @@ -43,5 +43,5 @@ class Step(): order: List[int] = field(); # the indexes upon which the greedy algorithm is carried out: indexes: List[int] = field(); - pad: MaskValue = field(); + solution: Optional[Mask] = field(); move: EnumBranchAndBoundMove = field(default=EnumBranchAndBoundMove.NONE);