ads2_2022/code/python/src/algorithms/rucksack/display.py

135 lines
4.5 KiB
Python
Raw Normal View History

#!/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})';