Compare commits
5 Commits
3791220cee
...
059f9d8742
Author | SHA1 | Date | |
---|---|---|---|
059f9d8742 | |||
21f61d71c3 | |||
f3db0660f2 | |||
77b2f40215 | |||
4cc4410c19 |
@ -75,20 +75,40 @@
|
|||||||
# Beispiele für Seminarwoche 11 (Blatt 10)
|
# Beispiele für Seminarwoche 11 (Blatt 10)
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
- &rucksack_1
|
- name: RUCKSACK
|
||||||
name: RUCKSACK
|
|
||||||
algorithm: GREEDY
|
algorithm: GREEDY
|
||||||
allow-fractional: false
|
allow-fractional: true
|
||||||
|
# allow-fractional: false
|
||||||
max-cost: 10
|
max-cost: 10
|
||||||
items: [a, b, c, d, e]
|
items: [a, b, c, d, e]
|
||||||
costs:
|
costs:
|
||||||
[3, 4, 5, 2, 1]
|
[3, 4, 5, 2, 1]
|
||||||
values:
|
values:
|
||||||
[8, 7, 8, 3, 2]
|
[8, 7, 8, 3, 2]
|
||||||
- <<: *rucksack_1
|
- name: RUCKSACK
|
||||||
allow-fractional: true
|
|
||||||
- <<: *rucksack_1
|
|
||||||
algorithm: BRANCH-AND-BOUND
|
algorithm: BRANCH-AND-BOUND
|
||||||
|
allow-fractional: true
|
||||||
|
# allow-fractional: false
|
||||||
|
max-cost: 10
|
||||||
|
items: [a, b, c, d, e]
|
||||||
|
costs:
|
||||||
|
[3, 4, 5, 2, 1]
|
||||||
|
values:
|
||||||
|
[8, 7, 8, 3, 2]
|
||||||
|
- name: RUCKSACK
|
||||||
|
algorithm: BRANCH-AND-BOUND
|
||||||
|
max-cost: 460
|
||||||
|
items: [
|
||||||
|
'Lakritze',
|
||||||
|
'Esspapier',
|
||||||
|
'Gummibärchen',
|
||||||
|
'Schokolade',
|
||||||
|
'Apfelringe',
|
||||||
|
]
|
||||||
|
costs:
|
||||||
|
[220, 80, 140, 90, 100]
|
||||||
|
values:
|
||||||
|
[100, 10, 70, 80, 100]
|
||||||
- name: RUCKSACK
|
- name: RUCKSACK
|
||||||
algorithm: BRANCH-AND-BOUND
|
algorithm: BRANCH-AND-BOUND
|
||||||
max-cost: 90
|
max-cost: 90
|
||||||
|
@ -22,11 +22,17 @@ options:
|
|||||||
diagonal: 0
|
diagonal: 0
|
||||||
horizontal: 1
|
horizontal: 1
|
||||||
vertical: 2
|
vertical: 2
|
||||||
|
# verbose: []
|
||||||
verbose:
|
verbose:
|
||||||
- COSTS
|
- COSTS
|
||||||
- MOVES
|
- MOVES
|
||||||
|
# show: []
|
||||||
show:
|
show:
|
||||||
# - ATOMS
|
# - ATOMS
|
||||||
- TREE
|
- TREE
|
||||||
rucksack:
|
rucksack:
|
||||||
verbose: true
|
verbose: true
|
||||||
|
# show: []
|
||||||
|
show:
|
||||||
|
- ALL-WEIGHTS
|
||||||
|
- ALL-SUMS
|
||||||
|
2
code/python/dist/VERSION
vendored
2
code/python/dist/VERSION
vendored
@ -1 +1 @@
|
|||||||
0.1.0
|
0.2.0
|
||||||
|
@ -8,7 +8,7 @@ Name | Type | Description | Notes
|
|||||||
**tarjan** | [**AppOptions_tarjan**](AppOptions_tarjan.md) | | [default to null]
|
**tarjan** | [**AppOptions_tarjan**](AppOptions_tarjan.md) | | [default to null]
|
||||||
**tsp** | [**AppOptions_tarjan**](AppOptions_tarjan.md) | | [default to null]
|
**tsp** | [**AppOptions_tarjan**](AppOptions_tarjan.md) | | [default to null]
|
||||||
**hirschberg** | [**AppOptions_hirschberg**](AppOptions_hirschberg.md) | | [default to null]
|
**hirschberg** | [**AppOptions_hirschberg**](AppOptions_hirschberg.md) | | [default to null]
|
||||||
**rucksack** | [**AppOptions_tarjan**](AppOptions_tarjan.md) | | [optional] [default to null]
|
**rucksack** | [**AppOptions_rucksack**](AppOptions_rucksack.md) | | [default to null]
|
||||||
|
|
||||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
10
code/python/docs/config/Models/AppOptionsRucksack.md
Normal file
10
code/python/docs/config/Models/AppOptionsRucksack.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# AppOptionsRucksack
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**verbose** | [**Boolean**](boolean.md) | | [optional] [default to false]
|
||||||
|
**show** | [**List**](EnumRucksackShow.md) | | [optional] [default to []]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
8
code/python/docs/config/Models/EnumRucksackShow.md
Normal file
8
code/python/docs/config/Models/EnumRucksackShow.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# EnumRucksackShow
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
@ -15,11 +15,13 @@ Class | Method | HTTP request | Description
|
|||||||
- [AppOptions](.//Models/AppOptions.md)
|
- [AppOptions](.//Models/AppOptions.md)
|
||||||
- [AppOptionsHirschberg](.//Models/AppOptionsHirschberg.md)
|
- [AppOptionsHirschberg](.//Models/AppOptionsHirschberg.md)
|
||||||
- [AppOptionsHirschbergMovePriorities](.//Models/AppOptionsHirschbergMovePriorities.md)
|
- [AppOptionsHirschbergMovePriorities](.//Models/AppOptionsHirschbergMovePriorities.md)
|
||||||
|
- [AppOptionsRucksack](.//Models/AppOptionsRucksack.md)
|
||||||
- [AppOptionsTarjan](.//Models/AppOptionsTarjan.md)
|
- [AppOptionsTarjan](.//Models/AppOptionsTarjan.md)
|
||||||
- [Config](.//Models/Config.md)
|
- [Config](.//Models/Config.md)
|
||||||
- [EnumHirschbergShow](.//Models/EnumHirschbergShow.md)
|
- [EnumHirschbergShow](.//Models/EnumHirschbergShow.md)
|
||||||
- [EnumHirschbergVerbosity](.//Models/EnumHirschbergVerbosity.md)
|
- [EnumHirschbergVerbosity](.//Models/EnumHirschbergVerbosity.md)
|
||||||
- [EnumLogLevel](.//Models/EnumLogLevel.md)
|
- [EnumLogLevel](.//Models/EnumLogLevel.md)
|
||||||
|
- [EnumRucksackShow](.//Models/EnumRucksackShow.md)
|
||||||
- [Info](.//Models/Info.md)
|
- [Info](.//Models/Info.md)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
openapi: 3.0.3
|
openapi: 3.0.3
|
||||||
info:
|
info:
|
||||||
version: 0.1.0
|
version: 0.2.0
|
||||||
title: Schemata for command instructions
|
title: Schemata for command instructions
|
||||||
servers:
|
servers:
|
||||||
- url: "."
|
- url: "."
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
openapi: 3.0.3
|
openapi: 3.0.3
|
||||||
info:
|
info:
|
||||||
version: 0.1.0
|
version: 0.2.0
|
||||||
title: Schemata for config models
|
title: Schemata for config models
|
||||||
servers:
|
servers:
|
||||||
- url: "."
|
- url: "."
|
||||||
@ -53,7 +53,7 @@ components:
|
|||||||
- tsp
|
- tsp
|
||||||
- tarjan
|
- tarjan
|
||||||
- hirschberg
|
- hirschberg
|
||||||
- rucksack-branch-and-bound
|
- rucksack
|
||||||
properties:
|
properties:
|
||||||
log-level:
|
log-level:
|
||||||
$ref: '#/components/schemas/EnumLogLevel'
|
$ref: '#/components/schemas/EnumLogLevel'
|
||||||
@ -117,12 +117,16 @@ components:
|
|||||||
default: []
|
default: []
|
||||||
rucksack:
|
rucksack:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required: []
|
||||||
- verbose
|
|
||||||
properties:
|
properties:
|
||||||
verbose:
|
verbose:
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
|
show:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/EnumRucksackShow'
|
||||||
|
default: []
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
# Enum LogLevel
|
# Enum LogLevel
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -148,8 +152,18 @@ components:
|
|||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
EnumHirschbergShow:
|
EnumHirschbergShow:
|
||||||
description: |-
|
description: |-
|
||||||
Enumeration of verbosity options for Hirschberg
|
Enumeration of display options for Hirschberg
|
||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
- TREE
|
- TREE
|
||||||
- ATOMS
|
- ATOMS
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
# Enum Rucksack - display options
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
EnumRucksackShow:
|
||||||
|
description: |-
|
||||||
|
Enumeration of display options for the Rucksack problem
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- ALL-WEIGHTS
|
||||||
|
- ALL-SUMS
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "uni-leipzig-ads-2-2022"
|
name = "uni-leipzig-ads-2-2022"
|
||||||
version = "1.0.0"
|
version = "0.2.0"
|
||||||
description = "Zusatzcode, um Algorithmen und Datenstrukturen im Kurs ADS2 zu demonstrieren."
|
description = "Zusatzcode, um Algorithmen und Datenstrukturen im Kurs ADS2 zu demonstrieren."
|
||||||
authors = [ "Raj Dahya" ]
|
authors = [ "Raj Dahya" ]
|
||||||
maintainers = [ "raj_mathe" ]
|
maintainers = [ "raj_mathe" ]
|
||||||
|
@ -57,25 +57,25 @@ def rucksack_greedy_algorithm(
|
|||||||
# führe greedy aus:
|
# führe greedy aus:
|
||||||
n = len(costs);
|
n = len(costs);
|
||||||
cost_total = 0;
|
cost_total = 0;
|
||||||
vector = [ Fraction(0) for _ in range(n) ];
|
choice = [ Fraction(0) for _ in range(n) ];
|
||||||
for i in order:
|
for i in order:
|
||||||
# füge Item i hinzu, solange das Gesamtgewicht noch <= Schranke
|
# füge Item i hinzu, solange das Gesamtgewicht noch <= Schranke
|
||||||
if cost_total + costs[i] <= max_cost:
|
if cost_total + costs[i] <= max_cost:
|
||||||
cost_total += costs[i];
|
cost_total += costs[i];
|
||||||
vector[i] = Fraction(1);
|
choice[i] = Fraction(1);
|
||||||
# falls Bruchteile erlaubt sind, füge einen Bruchteil des i. Items hinzu und abbrechen
|
# falls Bruchteile erlaubt sind, füge einen Bruchteil des i. Items hinzu und abbrechen
|
||||||
elif fractional:
|
elif fractional:
|
||||||
vector[i] = Fraction(Fraction(max_cost - cost_total)/Fraction(costs[i]), _normalize=False);
|
choice[i] = Fraction(Fraction(max_cost - cost_total)/Fraction(costs[i]), _normalize=False);
|
||||||
break;
|
break;
|
||||||
# ansonsten weiter machen:
|
# ansonsten weiter machen:
|
||||||
else:
|
else:
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
# Aspekte der Lösung speichern:
|
# Aspekte der Lösung speichern:
|
||||||
rucksack = [i for i, v in enumerate(vector) if v > 0]; # Indexes von Items im Rucksack
|
rucksack = [i for i, v in enumerate(choice) if v > 0]; # Indexes von Items im Rucksack
|
||||||
soln = Solution(
|
soln = Solution(
|
||||||
order = order,
|
order = order,
|
||||||
choice = vector,
|
choice = choice,
|
||||||
items = items[rucksack].tolist(),
|
items = items[rucksack].tolist(),
|
||||||
costs = costs[rucksack].tolist(),
|
costs = costs[rucksack].tolist(),
|
||||||
values = values[rucksack].tolist(),
|
values = values[rucksack].tolist(),
|
||||||
@ -83,7 +83,7 @@ def rucksack_greedy_algorithm(
|
|||||||
|
|
||||||
# verbose output hier behandeln (irrelevant für Algorithmus):
|
# verbose output hier behandeln (irrelevant für Algorithmus):
|
||||||
if verbose:
|
if verbose:
|
||||||
repr_rucksack = display_rucksack(items=items[rucksack], costs=costs[rucksack], values=values[rucksack]);
|
repr_rucksack = display_rucksack(items=items, costs=costs, values=values, choice=choice);
|
||||||
print('\x1b[1mEingeschätzte Lösung\x1b[0m');
|
print('\x1b[1mEingeschätzte Lösung\x1b[0m');
|
||||||
print('');
|
print('');
|
||||||
print(f'Mask: [{", ".join(map(str, soln.choice))}]');
|
print(f'Mask: [{", ".join(map(str, soln.choice))}]');
|
||||||
@ -122,24 +122,31 @@ def rucksack_branch_and_bound_algorithm(
|
|||||||
print('');
|
print('');
|
||||||
|
|
||||||
logged_steps = [];
|
logged_steps = [];
|
||||||
vector = empty_mask(n=len(costs));
|
step: Step;
|
||||||
lb_estimate = np.inf;
|
mask = empty_mask(n=len(costs));
|
||||||
|
bound = np.inf;
|
||||||
S = Stack();
|
S = Stack();
|
||||||
S.push(vector);
|
S.push(mask);
|
||||||
while not S.empty():
|
while not S.empty():
|
||||||
lb, choice, order_, pad = estimate_lower_bound(mask=S.top(), max_cost=max_cost, costs=costs, values=values, items=items);
|
# 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);
|
||||||
|
# für logging:
|
||||||
if verbose:
|
if verbose:
|
||||||
logged_steps.append((lb_estimate, lb, str(S), choice, order_, pad));
|
step = Step(bound=bound, bound_subtree=bound_subtree, stack_str=str(S), choice=choice, order=order_, indexes=A.indexes_unset, pad=pad);
|
||||||
|
S.pop();
|
||||||
# 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();
|
if bound_subtree < bound:
|
||||||
if lb < lb_estimate:
|
# Bound aktualisieren, wenn sich A nicht weiter aufteilen od. wenn sich A wie eine einelementige Option behandeln läst:
|
||||||
# Bound, wenn sich A nicht weiter aufteilen lässt od. man A wie eine einelementige Option behandeln kann:
|
|
||||||
if not A.splittable() or pad != MaskValue.UNSET:
|
if not A.splittable() or pad != MaskValue.UNSET:
|
||||||
lb_estimate = lb;
|
bound = bound_subtree;
|
||||||
# falls A als einelementige Menge betrachtet werden kann, ersetze unbekannte Werte:
|
# falls A als einelementige Menge betrachtet werden kann, ersetze unbekannte Werte:
|
||||||
if pad != MaskValue.UNSET:
|
if pad != MaskValue.UNSET:
|
||||||
A = A.pad(pad);
|
A = A.pad(pad);
|
||||||
vector = A;
|
mask = A;
|
||||||
|
# für logging:
|
||||||
|
if verbose:
|
||||||
|
step.move = EnumBranchAndBoundMove.BOUND;
|
||||||
# Branch sonst
|
# Branch sonst
|
||||||
else:
|
else:
|
||||||
B, C = A.split();
|
B, C = A.split();
|
||||||
@ -147,12 +154,17 @@ def rucksack_branch_and_bound_algorithm(
|
|||||||
# 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(costs[C.indexes_one]) <= max_cost:
|
if sum(costs[C.indexes_one]) <= max_cost:
|
||||||
S.push(C);
|
S.push(C);
|
||||||
|
# für logging:
|
||||||
|
if verbose:
|
||||||
|
step.move = EnumBranchAndBoundMove.BRANCH;
|
||||||
|
if verbose:
|
||||||
|
logged_steps.append(step);
|
||||||
|
|
||||||
# Aspekte der Lösung speichern
|
# Aspekte der Lösung speichern
|
||||||
rucksack = vector.indexes_one; # Indexes von Items im Rucksack
|
rucksack = mask.indexes_one; # Indexes von Items im Rucksack
|
||||||
soln = Solution(
|
soln = Solution(
|
||||||
order = order,
|
order = order,
|
||||||
choice = vector.choice,
|
choice = mask.choice,
|
||||||
items = items[rucksack].tolist(),
|
items = items[rucksack].tolist(),
|
||||||
values = values[rucksack].tolist(),
|
values = values[rucksack].tolist(),
|
||||||
costs = costs[rucksack].tolist(),
|
costs = costs[rucksack].tolist(),
|
||||||
@ -161,11 +173,11 @@ def rucksack_branch_and_bound_algorithm(
|
|||||||
# verbose output hier behandeln (irrelevant für Algorithmus):
|
# verbose output hier behandeln (irrelevant für Algorithmus):
|
||||||
if verbose:
|
if verbose:
|
||||||
repr = display_branch_and_bound(values=values, steps=logged_steps);
|
repr = display_branch_and_bound(values=values, steps=logged_steps);
|
||||||
repr_rucksack = display_rucksack(items=items[rucksack], costs=costs[rucksack], values=values[rucksack]);
|
repr_rucksack = display_rucksack(items=items, costs=costs, values=values, choice=mask.choice);
|
||||||
print('\x1b[1mLösung\x1b[0m');
|
|
||||||
print('');
|
|
||||||
print(repr);
|
print(repr);
|
||||||
print('');
|
print('');
|
||||||
|
print('\x1b[1mLösung\x1b[0m');
|
||||||
|
print('');
|
||||||
print(f'Mask: [{", ".join(map(str, soln.choice))}]');
|
print(f'Mask: [{", ".join(map(str, soln.choice))}]');
|
||||||
print('Rucksack:');
|
print('Rucksack:');
|
||||||
print(repr_rucksack);
|
print(repr_rucksack);
|
||||||
@ -201,7 +213,7 @@ def estimate_lower_bound(
|
|||||||
mit Greedy-Algorithmus »lösen«,
|
mit Greedy-Algorithmus »lösen«,
|
||||||
um schnell eine gute Einschätzung zu bestimmen.
|
um schnell eine gute Einschätzung zu bestimmen.
|
||||||
|
|
||||||
NOTE: Diese Funktion wird `g(vector)` im Skript bezeichnet.
|
NOTE: Diese Funktion wird `g(mask)` im Skript bezeichnet.
|
||||||
'''
|
'''
|
||||||
indexes_one = mask.indexes_one;
|
indexes_one = mask.indexes_one;
|
||||||
indexes_unset = mask.indexes_unset;
|
indexes_unset = mask.indexes_unset;
|
||||||
|
@ -9,6 +9,8 @@ from src.thirdparty.code import *;
|
|||||||
from src.thirdparty.maths import *;
|
from src.thirdparty.maths import *;
|
||||||
from src.thirdparty.types import *;
|
from src.thirdparty.types import *;
|
||||||
|
|
||||||
|
from src.setup import config;
|
||||||
|
from models.generated.config import *;
|
||||||
from src.models.stacks import *;
|
from src.models.stacks import *;
|
||||||
from src.models.rucksack import *;
|
from src.models.rucksack import *;
|
||||||
|
|
||||||
@ -62,18 +64,31 @@ def display_rucksack(
|
|||||||
items: np.ndarray,
|
items: np.ndarray,
|
||||||
costs: np.ndarray,
|
costs: np.ndarray,
|
||||||
values: np.ndarray,
|
values: np.ndarray,
|
||||||
|
choice: List[Fraction],
|
||||||
) -> str:
|
) -> str:
|
||||||
|
show_options = config.OPTIONS.rucksack.show;
|
||||||
render = lambda r: f'{r:g}';
|
render = lambda r: f'{r:g}';
|
||||||
|
choice = np.asarray(choice);
|
||||||
|
rucksack = np.where(choice > 0);
|
||||||
|
if not(EnumRucksackShow.all_weights in show_options):
|
||||||
|
items = items[rucksack];
|
||||||
|
costs = costs[rucksack];
|
||||||
|
values = values[rucksack];
|
||||||
|
choice = choice[rucksack];
|
||||||
table = pd.DataFrame({
|
table = pd.DataFrame({
|
||||||
'items': items.tolist() + ['----', '∑'],
|
'items': items.tolist() + ['----', '∑'],
|
||||||
'costs': list(map(render, costs)) + ['', f'\x1b[92;1m{sum(costs):g}\x1b[0m'],
|
'nr': list(map(str, choice))
|
||||||
'values': list(map(render, values)) + ['', f'\x1b[92;1m{sum(values):g}\x1b[0m'],
|
+ ['----', f'\x1b[92;1m{float(sum(choice)):g}\x1b[0m'],
|
||||||
|
'costs': list(map(render, costs))
|
||||||
|
+ ['----', f'\x1b[92;1m{sum(choice*costs):g}\x1b[0m'],
|
||||||
|
'values': list(map(render, values))
|
||||||
|
+ ['----', f'\x1b[92;1m{sum(choice*values):g}\x1b[0m'],
|
||||||
});
|
});
|
||||||
repr = tabulate(
|
repr = tabulate(
|
||||||
table,
|
table,
|
||||||
headers=['item', 'cost', 'value'],
|
headers=['item', 'nr', 'cost', 'value'],
|
||||||
showindex=False,
|
showindex=False,
|
||||||
colalign=('left', 'center', 'center'),
|
colalign=('left', 'center', 'center', 'center'),
|
||||||
tablefmt='rst'
|
tablefmt='rst'
|
||||||
);
|
);
|
||||||
return repr;
|
return repr;
|
||||||
@ -82,30 +97,39 @@ def display_rucksack(
|
|||||||
# METHOD display result of branch and bound
|
# METHOD display result of branch and bound
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
def display_branch_and_bound(
|
def display_branch_and_bound(values: np.ndarray, steps: List[Step]) -> str:
|
||||||
values: np.ndarray,
|
show_options = config.OPTIONS.rucksack.show;
|
||||||
steps: List[Tuple[float, float, Stack, List[Fraction], List[int], MaskValue]],
|
show_all_sums = (EnumRucksackShow.all_sums in show_options);
|
||||||
) -> str:
|
|
||||||
# füge Summen-Ausdrücke für Greedy-Alg hinzu:
|
|
||||||
rows = [];
|
rows = [];
|
||||||
used_choices = [];
|
used_choices = [];
|
||||||
for lb_estimate, lb, S, choice, order, pad in steps:
|
index_soln = max([-1] + [ i for i, step in enumerate(steps) if step.move == EnumBranchAndBoundMove.BOUND ]);
|
||||||
if choice in used_choices:
|
for i, step in enumerate(steps):
|
||||||
expr = f'{lb:g}';
|
if show_all_sums or step.choice not in used_choices:
|
||||||
|
# Füge Summen-Ausdrücke für Greedy-Alg hinzu:
|
||||||
|
used_choices.append(step.choice);
|
||||||
|
expr = display_sum(choice=step.choice, values=values, as_maximum=False, order=step.order, indexes=step.indexes);
|
||||||
else:
|
else:
|
||||||
used_choices.append(choice);
|
expr = f'{step.bound_subtree:g}';
|
||||||
expr = display_sum(choice=choice, values=values, as_maximum=False, order=order);
|
pad_str = ('' if step.pad == MaskValue.UNSET else step.pad.value);
|
||||||
rows.append((f'{lb_estimate:g}', expr, ('' if pad == MaskValue.UNSET else pad.value), S));
|
move_str = ('' if step.move == EnumBranchAndBoundMove.NONE else step.move.value);
|
||||||
|
if i == index_soln:
|
||||||
|
move_str = f'{move_str} *';
|
||||||
|
rows.append({
|
||||||
|
'bound': f'{step.bound:+g}',
|
||||||
|
'bound_subtree': expr,
|
||||||
|
'stack': step.stack_str,
|
||||||
|
'pad': f'\x1b[2m{pad_str}\x1b[0m',
|
||||||
|
'move': f'\x1b[2m{move_str}\x1b[0m',
|
||||||
|
});
|
||||||
|
|
||||||
table = pd.DataFrame(rows) \
|
table = pd.DataFrame(rows).reset_index(drop=True);
|
||||||
.rename(columns={0: 'b', 1: 'g(TOP(S))', 2: 'pad?', 3: 'S'}) \
|
|
||||||
.reset_index(drop=True);
|
|
||||||
# benutze pandas-Dataframe + tabulate, um schöner darzustellen:
|
# benutze pandas-Dataframe + tabulate, um schöner darzustellen:
|
||||||
repr = tabulate(
|
repr = tabulate(
|
||||||
table,
|
table,
|
||||||
headers=['b', 'g(TOP(S))', 'pad?', 'S'],
|
headers=['bound', 'g(TOP(S))', 'S — stack', '\x1b[2mpad?\x1b[0m', '\x1b[2mmove\x1b[0m'],
|
||||||
showindex=False,
|
showindex=False,
|
||||||
colalign=('left', 'left', 'center', 'right'),
|
colalign=('left', 'left', 'right', 'center', 'left'),
|
||||||
tablefmt='rst'
|
tablefmt='rst'
|
||||||
);
|
);
|
||||||
return repr;
|
return repr;
|
||||||
@ -118,17 +142,31 @@ def display_sum(
|
|||||||
choice: List[Fraction],
|
choice: List[Fraction],
|
||||||
values: np.ndarray,
|
values: np.ndarray,
|
||||||
order: Optional[List[int]] = None,
|
order: Optional[List[int]] = None,
|
||||||
|
indexes: List[int] = [],
|
||||||
as_maximum: bool = True,
|
as_maximum: bool = True,
|
||||||
) -> str:
|
) -> str:
|
||||||
parts = [ (u, x) for u, x in zip(choice, values)];
|
show_options = config.OPTIONS.rucksack.show;
|
||||||
|
show_all_weights = (EnumRucksackShow.all_weights in show_options);
|
||||||
|
|
||||||
|
def render(x: Tuple[bool, Fraction, float]):
|
||||||
|
b, u, value = x;
|
||||||
|
if u == 0:
|
||||||
|
expr = f'\x1b[94;2m{value:g}\x1b[0m' if b else f'\x1b[2m{value:g}\x1b[0m';
|
||||||
|
else:
|
||||||
|
expr = f'\x1b[94m{value:g}\x1b[0m' if b else f'\x1b[0m{value:g}\x1b[0m';
|
||||||
|
if not show_all_weights and u == 1:
|
||||||
|
return expr;
|
||||||
|
return f'\x1b[2;4m{u}\x1b[0m\x1b[2m·\x1b[0m{expr}';
|
||||||
|
|
||||||
|
parts = [ (i in indexes, u, x) for i, (u, x) in enumerate(zip(choice, values)) ];
|
||||||
if not (order is None):
|
if not (order is None):
|
||||||
parts = [ parts[j] for j in order ];
|
parts = [ parts[j] for j in order ];
|
||||||
value = sum([ u*x for u, x in parts]);
|
if not show_all_weights:
|
||||||
expr = '+'.join([
|
parts = list(filter(lambda x: x[1] > 0, parts));
|
||||||
f'{x:g}' if u == 1 else f'{u}·{x:g}'
|
|
||||||
for u, x in parts if u > 0
|
value = sum([ u*x for _, u, x in parts ]);
|
||||||
]);
|
expr = '\x1b[2m+\x1b[0m'.join(map(render, parts));
|
||||||
|
|
||||||
if as_maximum:
|
if as_maximum:
|
||||||
return f'{value:g} = {expr}';
|
return f'{value:g} \x1b[2m=\x1b[0m {expr}';
|
||||||
else:
|
return f'-{value:g} \x1b[2m= -(\x1b[0m{expr}\x1b[2m)\x1b[0m';
|
||||||
return f'-{value:g} = -({expr})';
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
from src.models.rucksack.mask import *;
|
from src.models.rucksack.mask import *;
|
||||||
from src.models.rucksack.solution import *;
|
from src.models.rucksack.solution import *;
|
||||||
|
from src.models.rucksack.logging import *;
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
# EXPORTS
|
# EXPORTS
|
||||||
@ -17,4 +18,6 @@ __all__ = [
|
|||||||
'MaskValue',
|
'MaskValue',
|
||||||
'Mask',
|
'Mask',
|
||||||
'Solution',
|
'Solution',
|
||||||
|
'EnumBranchAndBoundMove',
|
||||||
|
'Step',
|
||||||
];
|
];
|
||||||
|
47
code/python/src/models/rucksack/logging.py
Normal file
47
code/python/src/models/rucksack/logging.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
# IMPORTS
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
from __future__ import annotations;
|
||||||
|
|
||||||
|
from src.thirdparty.maths import *;
|
||||||
|
from src.thirdparty.types import *;
|
||||||
|
|
||||||
|
from src.models.rucksack.mask import *;
|
||||||
|
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
# EXPORTS
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'EnumBranchAndBoundMove',
|
||||||
|
'Step',
|
||||||
|
];
|
||||||
|
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
# CLASS Move
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
class EnumBranchAndBoundMove(Enum):
|
||||||
|
NONE = -1;
|
||||||
|
BOUND = 'bound';
|
||||||
|
BRANCH = 'branch';
|
||||||
|
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
# CLASS Step
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Step():
|
||||||
|
bound: float = field();
|
||||||
|
bound_subtree: float = field();
|
||||||
|
stack_str: str = field();
|
||||||
|
choice: List[Fraction] = field();
|
||||||
|
order: List[int] = field();
|
||||||
|
# the indexes upon which the greedy algorithm is carried out:
|
||||||
|
indexes: List[int] = field();
|
||||||
|
pad: MaskValue = field();
|
||||||
|
move: EnumBranchAndBoundMove = field(default=EnumBranchAndBoundMove.NONE);
|
@ -12,8 +12,10 @@ Inhaltsverzeichnis
|
|||||||
- [Vorlesungswoche 7](./woche4.md)
|
- [Vorlesungswoche 7](./woche4.md)
|
||||||
- [Vorlesungswoche 8](./woche4.md)
|
- [Vorlesungswoche 8](./woche4.md)
|
||||||
- [Vorlesungswoche 9](./woche4.md)
|
- [Vorlesungswoche 9](./woche4.md)
|
||||||
|
-->
|
||||||
- [Vorlesungswoche 10](./woche10.md)
|
- [Vorlesungswoche 10](./woche10.md)
|
||||||
- [Vorlesungswoche 11](./woche11.md)
|
- [Vorlesungswoche 11](./woche11.md)
|
||||||
|
<!--
|
||||||
- [Vorlesungswoche 12](./woche12.md)
|
- [Vorlesungswoche 12](./woche12.md)
|
||||||
- [Vorlesungswoche 13](./woche13.md)
|
- [Vorlesungswoche 13](./woche13.md)
|
||||||
- [Vorlesungswoche 14](./woche14.md)
|
- [Vorlesungswoche 14](./woche14.md)
|
||||||
|
14
protocol/woche10.md
Normal file
14
protocol/woche10.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Vorlesungswoche 10 (6.–12. Juni 2022) #
|
||||||
|
|
||||||
|
## Agenda ##
|
||||||
|
|
||||||
|
- [x] Hirschbergalgorithmus
|
||||||
|
|
||||||
|
Implementierung zum Austesten findet man in [code/python](./../code/python). _Beachte:_
|
||||||
|
|
||||||
|
- Der Code ist etwas ineffizient implementiert,
|
||||||
|
weil extra (unnötige) Informationen zwecks schöner Darstellung gespeichert wird.
|
||||||
|
Die Schritte sind jedoch korrekt.
|
||||||
|
- Man kann die Aspekte der Probleme
|
||||||
|
in dem [assets](./../code/python/assets) Ordner anpassen,
|
||||||
|
wie bspw. die Prioritäten der Bewegungen innerhalb der Editmatrix.
|
20
protocol/woche11.md
Normal file
20
protocol/woche11.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Vorlesungswoche 11 (13.–19. Juni 2022) #
|
||||||
|
|
||||||
|
## Agenda ##
|
||||||
|
|
||||||
|
- [ ] Rucksackproblem
|
||||||
|
- Greedyalgorithmus
|
||||||
|
- Branch & Bound
|
||||||
|
|
||||||
|
## Implementierung ##
|
||||||
|
|
||||||
|
Implementierung zum Austesten findet man in [code/python](./../code/python). _Beachte:_
|
||||||
|
|
||||||
|
- Der Code ist etwas ineffizient implementiert,
|
||||||
|
weil extra (unnötige) Informationen zwecks schöner Darstellung gespeichert wird.
|
||||||
|
Die Schritte sind jedoch korrekt.
|
||||||
|
- Man kann die Aspekte der Probleme
|
||||||
|
in dem [assets](./../code/python/assets) Ordner anpassen,
|
||||||
|
wie bspw. ob alle Gewichte und alle Summen angezeigt werden sollen.
|
||||||
|
|
||||||
|
In den Beispielen wird _mehr als nötig_ ausgegeben. Die extra Spalten sowie die etwas unnötig ausführlich aufgeschriebenen Summen sollen nur didaktischen Zwecken dienen. Sobald man alles kapiert hat, kann man selbstverständlich auf die zusätzlichen Teile verzichten.
|
Loading…
x
Reference in New Issue
Block a user