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: if verbose:
# Umsortierung rückgängig machen: # Umsortierung rückgängig machen:
vector = [ soln.vector[i] for i in order ]; 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); permute_data(weights=weights, values=values, items=items, perm=uorder);
# Ausdrücke bestimmen: # Ausdrücke bestimmen:
expr_value = display_sum(vector=vector, values=values); expr_value = display_sum(vector=vector, values=values);
@ -135,24 +135,29 @@ def rucksack_branch_and_bound_algorithm(
S = Stack(); S = Stack();
S.push(vector); S.push(vector);
while not S.empty(): 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: if verbose:
logged_steps.append((lb_estimate, lb, u, str(S))); 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: # Update nur nötig, wenn die (eingeschätzte) untere Schranke von A das bisherige Minimum verbessert:
A: Mask = S.pop(); A: Mask = S.pop();
if lb < lb_estimate: if lb < lb_estimate:
# Branch: # Bound, wenn sich A nicht weiter aufteilen lässt od. man A wie eine einelementige Option behandeln kann:
if A.splittable(): # 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(); B, C = A.split();
# NOTE: per Wahl erfüllt mind. eine Möglichkeit in B die Kapazitätsschranke. # NOTE: per Wahl erfüllt mind. eine Möglichkeit in B die Kapazitätsschranke.
S.push(B); S.push(B);
# Nur dann C auf Stack legen, wenn mind. eine Möglichkeit in C die Kapazitätsschranke erfüllt: # 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: if sum(weights[C.indexes_one]) <= capacity:
S.push(C); S.push(C);
# Bound, wenn die Maske den Rucksack komplett bestimmt:
else:
lb_estimate = lb;
vector = A;
# Aspekte der Lösung speichern # Aspekte der Lösung speichern
rucksack = vector.indexes_one; # Indexes von Items im Rucksack 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); repr = display_branch_and_bound(values=values, steps=logged_steps);
# Umsortierung rückgängig machen: # Umsortierung rückgängig machen:
vector = [ soln.vector[i] for i in order ]; 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); permute_data(weights=weights, values=values, items=items, perm=uorder);
# Ausdrücke bestimmen: # Ausdrücke bestimmen:
expr_value = display_sum(vector=vector, values=values); expr_value = display_sum(vector=vector, values=values);
@ -223,7 +228,7 @@ def estimate_lower_bound(
weights: np.ndarray, weights: np.ndarray,
values: np.ndarray, values: np.ndarray,
items: np.ndarray, items: np.ndarray,
) -> Tuple[float, List[float]]: ) -> Tuple[float, List[float], bool]:
''' '''
Wenn partielle Information über den Rucksack festgelegt ist, Wenn partielle Information über den Rucksack festgelegt ist,
kann man bei dem unbekannten Teil das Rucksack-Problem kann man bei dem unbekannten Teil das Rucksack-Problem
@ -257,6 +262,10 @@ def estimate_lower_bound(
vector[indexes_one] = 1; vector[indexes_one] = 1;
vector[indexes_unset] = soln_rest.vector; 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): # Einschätzung des max-Wertes (Ausgabe mit -1 multiplizieren):
value_max_est = value_rucksack + value_rest; 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; vector2[self.index] = MaskValue.ONE;
return Mask(vector1), Mask(vector2); 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): def empty_mask(n: int):
return Mask([MaskValue.UNSET for _ in range(n)]); return Mask([MaskValue.UNSET for _ in range(n)]);