master > master: code py - pad ones/zeros für einelementige Fälle
This commit is contained in:
parent
56a93bbac9
commit
f45781be71
@ -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;
|
||||
|
@ -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)]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user