master > master: code py - pad ones/zeros für einelementige Fälle

This commit is contained in:
RD 2022-06-14 11:24:32 +02:00
parent 56a93bbac9
commit f45781be71
2 changed files with 32 additions and 11 deletions

View File

@ -83,7 +83,7 @@ def rucksack_greedy_algorithm(
if verbose:
# Umsortierung rückgängig machen:
vector = [ soln.vector[i] for i in order ];
rucksack = [ uorder[r] for r in rucksack ];
rucksack = sorted([ 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);
@ -135,24 +135,29 @@ def rucksack_branch_and_bound_algorithm(
S = Stack();
S.push(vector);
while not S.empty():
lb, u = estimate_lower_bound(mask=S.top(), capacity=capacity, weights=weights, values=values, items=items);
lb, u, can_add_all, can_add_none = estimate_lower_bound(mask=S.top(), capacity=capacity, weights=weights, values=values, items=items);
if verbose:
logged_steps.append((lb_estimate, lb, u, str(S)));
# Update nur nötig, wenn die (eingeschätzte) untere Schranke von A das bisherige Minimum verbessert:
A: Mask = S.pop();
if lb < lb_estimate:
# Branch:
if A.splittable():
# Bound, wenn sich A nicht weiter aufteilen lässt od. man A wie eine einelementige Option behandeln kann:
# Branch sonst
if not A.splittable() or can_add_all or can_add_none:
lb_estimate = lb;
if can_add_all:
vector = A.pad_ones();
elif can_add_none:
vector = A.pad_zeros();
else:
vector = A;
else:
B, C = A.split();
# NOTE: per Wahl erfüllt mind. eine Möglichkeit in B die Kapazitätsschranke.
S.push(B);
# Nur dann C auf Stack legen, wenn mind. eine Möglichkeit in C die Kapazitätsschranke erfüllt:
if sum(weights[C.indexes_one]) <= capacity:
S.push(C);
# Bound, wenn die Maske den Rucksack komplett bestimmt:
else:
lb_estimate = lb;
vector = A;
# Aspekte der Lösung speichern
rucksack = vector.indexes_one; # Indexes von Items im Rucksack
@ -169,7 +174,7 @@ def rucksack_branch_and_bound_algorithm(
repr = display_branch_and_bound(values=values, steps=logged_steps);
# Umsortierung rückgängig machen:
vector = [ soln.vector[i] for i in order ];
rucksack = [ uorder[r] for r in rucksack ];
rucksack = sorted([ 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);
@ -223,7 +228,7 @@ def estimate_lower_bound(
weights: np.ndarray,
values: np.ndarray,
items: np.ndarray,
) -> Tuple[float, List[float]]:
) -> Tuple[float, List[float], bool]:
'''
Wenn partielle Information über den Rucksack festgelegt ist,
kann man bei dem unbekannten Teil das Rucksack-Problem
@ -257,6 +262,10 @@ def estimate_lower_bound(
vector[indexes_one] = 1;
vector[indexes_unset] = soln_rest.vector;
# Prüfe, ob man als Lösung alles hinzufügen kann:
can_add_all = all([m == 1 for m in soln_rest.vector]);
can_add_none = all([m == 0 for m in soln_rest.vector]);
# Einschätzung des max-Wertes (Ausgabe mit -1 multiplizieren):
value_max_est = value_rucksack + value_rest;
return -value_max_est, vector.tolist();
return -value_max_est, vector.tolist(), can_add_all, can_add_none;

View File

@ -76,5 +76,17 @@ class Mask():
vector2[self.index] = MaskValue.ONE;
return Mask(vector1), Mask(vector2);
def pad_zeros(self) -> Mask:
'''
Completes mask by filling in unset values with zeros
'''
return Mask([ MaskValue.ZERO if u == MaskValue.UNSET else u for u in self.values ]);
def pad_ones(self) -> Mask:
'''
Completes mask by filling in unset values with zeros
'''
return Mask([ MaskValue.ONE if u == MaskValue.UNSET else u for u in self.values ]);
def empty_mask(n: int):
return Mask([MaskValue.UNSET for _ in range(n)]);