#!/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 *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # 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, 'u': (values/costs), }) \ .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: table = pd.DataFrame({ 'items': items.tolist() + ['----', '∑'], 'costs': costs.tolist() + ['', f'\x1b[92;1m{sum(costs)}\x1b[0m'], 'values': values.tolist() + ['', f'\x1b[92;1m{sum(values)}\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[float], bool, bool]], order: Optional[List[int]] = None, ) -> str: # füge Summen-Ausdrücke für Greedy-Alg hinzu: rows = []; used_vectors = []; for lb_estimate, lb, S, u, can_add_all, can_add_none in steps: pad = '1' if can_add_all else ('0' if can_add_none else ''); if u in used_vectors: expr = f'{lb:g}'; else: used_vectors.append(u) expr = display_sum(vector=u, values=values, as_maximum=False, order=order); rows.append((f'{lb_estimate:g}', expr, pad, 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( vector: List[float], values: np.ndarray, order: Optional[List[int]] = None, as_maximum: bool = True, ) -> str: parts = [ (u, x) for u, x in zip(vector, 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'{Fraction(str(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})';