Browse Source

master > master: code py - display volle loesung statt padding

master
RD 2 months ago
parent
commit
8cba2fdf13
  1. 30
      code/python/src/algorithms/rucksack/algorithms.py
  2. 7
      code/python/src/algorithms/rucksack/display.py
  3. 2
      code/python/src/models/rucksack/logging.py

30
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;

7
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:

2
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);

Loading…
Cancel
Save