From 304b8315f3d3fbc3787b020ee29ea20ec537b8f4 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Tue, 14 Jun 2022 10:09:21 +0200 Subject: [PATCH] =?UTF-8?q?master=20>=20master:=20code=20py=20-=20bei=20ou?= =?UTF-8?q?tput=20Sortierung=20r=C3=BCckg=C3=A4ngig=20machen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/algorithms/rucksack/algorithms.py | 58 +++++++++++++------ .../python/src/algorithms/rucksack/display.py | 19 +++--- 2 files changed, 51 insertions(+), 26 deletions(-) diff --git a/code/python/src/algorithms/rucksack/algorithms.py b/code/python/src/algorithms/rucksack/algorithms.py index 525d54c..189436a 100644 --- a/code/python/src/algorithms/rucksack/algorithms.py +++ b/code/python/src/algorithms/rucksack/algorithms.py @@ -9,6 +9,7 @@ from src.thirdparty.types import *; from src.thirdparty.maths import *; from models.generated.config import *; +from src.core.utils import *; from src.models.rucksack import *; from src.models.stacks import *; from src.algorithms.rucksack.display import *; @@ -43,10 +44,11 @@ def rucksack_greedy_algorithm( ''' # sortiere daten: order = resort_by_value_per_weight(weights=weights, values=values, items=items); + uorder = iperm(order); # verbose output hier behandeln (irrelevant für Algorithmus): if verbose: - repr = display_order(order=order, weights=weights, values=values, items=items, one_based=True); + repr = display_order(order=order, weights=weights[uorder], values=values[uorder], items=items[uorder], one_based=True); print(''); print('\x1b[1mRucksack Problem - Greedy\x1b[0m'); print(''); @@ -57,21 +59,19 @@ def rucksack_greedy_algorithm( n = len(weights); weight_total = 0; vector = [ 0 for _ in range(n) ]; - rucksack = []; for i in range(n): # füge Item i hinzu, solange das Gesamtgewicht noch <= Schranke if weight_total + weights[i] <= capacity: weight_total += weights[i]; - rucksack.append(i); vector[i] = 1; # sonst abbrechen. Falls Bruchteile erlaubt, füge einen Bruchteil des i. Items hinzu else: if fractional: - rucksack.append(i); vector[i] = (capacity - weight_total)/weights[i]; break; # Aspekte der Lösung speichern: + rucksack = [i for i, v in enumerate(vector) if v > 0]; # Indexes von Items im Rucksack soln = Solution( vector = vector, items = items[rucksack].tolist(), @@ -81,13 +81,19 @@ def rucksack_greedy_algorithm( # verbose output hier behandeln (irrelevant für Algorithmus): if verbose: - expr_value = display_sum(vector=soln.vector, values=values); - expr_weight = display_sum(vector=soln.vector, values=weights); - print('\x1b[1mEingeschätztes Maximum\x1b[0m'); + # Umsortierung rückgängig machen: + vector = [ soln.vector[i] for i in order ]; + rucksack = [ uorder[r] for r in rucksack ]; + permute_data(weights=weights, values=values, items=items, perm=uorder); + # Ausdrücke bestimmen: + expr_value = display_sum(vector=vector, values=values); + expr_weight = display_sum(vector=vector, values=weights); + print('\x1b[1mEingeschätzte Lösung\x1b[0m'); print(''); - print(f'Rucksack: {", ".join(soln.items)}.'); if fractional: - print(f'Vector: {soln.vector_support}'); + print(f'Mask: {soln.vector}'); + print(f' ---> {vector} (unter urspr. Sortierung)'); + print(f'Rucksack: {", ".join(items[rucksack])}.'); print(f'max. Value ≈ {expr_value}'); print(f'∑ Weights = {expr_weight}'); print(''); @@ -112,10 +118,11 @@ def rucksack_branch_and_bound_algorithm( ''' order = resort_by_value_per_weight(weights=weights, values=values, items=items); + uorder = iperm(order); # verbose output hier behandeln (irrelevant für Algorithmus): if verbose: - repr = display_order(order=order, weights=weights, values=values, items=items, one_based=True); + repr = display_order(order=order, weights=weights[uorder], values=values[uorder], items=items[uorder], one_based=True); print(''); print('\x1b[1mRucksack Problem - Branch & Bound\x1b[0m'); print(''); @@ -158,14 +165,22 @@ def rucksack_branch_and_bound_algorithm( # verbose output hier behandeln (irrelevant für Algorithmus): if verbose: - expr_value = display_sum(vector=soln.vector, values=values); - expr_weight = display_sum(vector=soln.vector, values=weights); + # NOTE: Information in Tabelle gemäß permutierten Daten: repr = display_branch_and_bound(values=values, steps=logged_steps); - print('\x1b[1mMaximum\x1b[0m'); + # Umsortierung rückgängig machen: + vector = [ soln.vector[i] for i in order ]; + rucksack = [ uorder[r] for r in rucksack ]; + permute_data(weights=weights, values=values, items=items, perm=uorder); + # Ausdrücke bestimmen: + expr_value = display_sum(vector=vector, values=values); + expr_weight = display_sum(vector=vector, values=weights); + print('\x1b[1mLösung\x1b[0m'); print(''); print(repr); print(''); - print(f'Rucksack: {", ".join(soln.items)}.'); + print(f'Mask: {soln.vector}'); + print(f' ---> {vector} (unter urspr. Sortierung)'); + print(f'Rucksack: {", ".join(items[rucksack])}.'); print(f'max. Value ≈ {expr_value}'); print(f'∑ Weights = {expr_weight}'); print(''); @@ -188,11 +203,20 @@ def resort_by_value_per_weight( n = len(weights); indexes = list(range(n)); order = sorted(indexes, key=lambda i: -values[i]/weights[i]); - weights[:] = weights[order]; - values[:] = values[order]; - items[:] = items[order]; + permute_data(weights=weights, values=values, items=items, perm=order); return order; +def permute_data( + weights: np.ndarray, + values: np.ndarray, + items: np.ndarray, + perm: List[int], +): + weights[:] = weights[perm]; + values[:] = values[perm]; + items[:] = items[perm]; + return; + def estimate_lower_bound( mask: Mask, capacity: float, diff --git a/code/python/src/algorithms/rucksack/display.py b/code/python/src/algorithms/rucksack/display.py index 5223182..38934e4 100644 --- a/code/python/src/algorithms/rucksack/display.py +++ b/code/python/src/algorithms/rucksack/display.py @@ -9,7 +9,6 @@ from src.thirdparty.code import *; from src.thirdparty.maths import *; from src.thirdparty.types import *; -from src.core.utils import *; from src.models.stacks import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -33,18 +32,16 @@ def display_order( items: np.ndarray, one_based: bool = False, ) -> str: - index = range(len(order)); - uorder = iperm(order); table = pd.DataFrame({ 'items': items, - 'index': index, + 'order': order, 'values': values, 'weights': weights, 'u': (values/weights), - }, index=index) \ - .reindex(uorder); + }) \ + .reset_index(drop=True); if one_based: - table['index'] += 1; + table['order'] += 1; # benutze pandas-Dataframe + tabulate, um schöner darzustellen: repr = tabulate( pd.DataFrame(table), @@ -62,13 +59,17 @@ def display_order( def display_sum( vector: Union[List[int], List[float]], values: np.ndarray, + as_maximum: bool = True, ) -> str: value = sum([ u*x for u, x in zip(vector,values)]); expr = '+'.join([ f'{x:g}' if u == 1 else f'{Fraction(str(u))}·{x:g}' for u, x in zip(vector,values) if u > 0 ]); - return f'{value:g} (={expr})'; + if as_maximum: + return f'{value:g} = {expr}'; + else: + return f'-{value:g} = -({expr})'; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # METHOD display result of branch and bound @@ -86,7 +87,7 @@ def display_branch_and_bound( rows.append((f'{lb_estimate:g}', f'{lb:g}', S)); else: used_vectors.append(u) - rows.append((f'{lb_estimate:g}', display_sum(vector=u, values=values), S)); + rows.append((f'{lb_estimate:g}', display_sum(vector=u, values=values, as_maximum=False), S)); table = pd.DataFrame(rows) \ .rename(columns={0: 'b', 1: 'g(TOP(S))', 2: 'S'}) \