#!/usr/bin/env python3 # -*- coding: utf-8 -*- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # IMPORTS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ from src.thirdparty.code import *; from src.thirdparty.maths import *; from src.thirdparty.types import *; from src.models.stacks import *; from src.models.rucksack import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # EXPORTS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ __all__ = [ 'display_order', 'display_rucksack', 'display_branch_and_bound', 'display_sum', ]; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # METHOD display order # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def display_order( order: List[int], costs: np.ndarray, values: np.ndarray, items: np.ndarray, one_based: bool = False, ) -> str: table = pd.DataFrame({ 'items': items, 'order': order, 'values': values, 'costs': costs, 'margin': [str(Fraction(Fraction(value), Fraction(cost))) for cost, value in zip(costs, values)], }) \ .reset_index(drop=True); if one_based: table['order'] += 1; # benutze pandas-Dataframe + tabulate, um schöner darzustellen: repr = tabulate( table, headers=['item', 'greedy order', 'value', 'cost', 'value/cost'], showindex=False, colalign=('left', 'center', 'center', 'center', 'right'), tablefmt='rst' ); return repr; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # METHOD display rucksack # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def display_rucksack( items: np.ndarray, costs: np.ndarray, values: np.ndarray, ) -> str: render = lambda r: f'{r:g}'; table = pd.DataFrame({ 'items': items.tolist() + ['----', '∑'], 'costs': list(map(render, costs)) + ['', f'\x1b[92;1m{sum(costs):g}\x1b[0m'], 'values': list(map(render, values)) + ['', f'\x1b[92;1m{sum(values):g}\x1b[0m'], }); repr = tabulate( table, headers=['item', 'cost', 'value'], showindex=False, colalign=('left', 'center', 'center'), tablefmt='rst' ); return repr; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # METHOD display result of branch and bound # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def display_branch_and_bound( values: np.ndarray, steps: List[Tuple[float, float, Stack, List[Fraction], List[int], MaskValue]], ) -> str: # füge Summen-Ausdrücke für Greedy-Alg hinzu: rows = []; used_choices = []; for lb_estimate, lb, S, choice, order, pad in steps: if choice in used_choices: expr = f'{lb:g}'; else: used_choices.append(choice); expr = display_sum(choice=choice, values=values, as_maximum=False, order=order); rows.append((f'{lb_estimate:g}', expr, ('' if pad == MaskValue.UNSET else pad.value), S)); table = pd.DataFrame(rows) \ .rename(columns={0: 'b', 1: 'g(TOP(S))', 2: 'pad?', 3: 'S'}) \ .reset_index(drop=True); # benutze pandas-Dataframe + tabulate, um schöner darzustellen: repr = tabulate( table, headers=['b', 'g(TOP(S))', 'pad?', 'S'], showindex=False, colalign=('left', 'left', 'center', 'right'), tablefmt='rst' ); return repr; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # METHOD display sum # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def display_sum( choice: List[Fraction], values: np.ndarray, order: Optional[List[int]] = None, as_maximum: bool = True, ) -> str: parts = [ (u, x) for u, x in zip(choice, values)]; if not (order is None): parts = [ parts[j] for j in order ]; value = sum([ u*x for u, x in parts]); expr = '+'.join([ f'{x:g}' if u == 1 else f'{u}·{x:g}' for u, x in parts if u > 0 ]); if as_maximum: return f'{value:g} = {expr}'; else: return f'-{value:g} = -({expr})';