Compare commits

..

2 Commits

Author SHA1 Message Date
92f038d4dd master > master: code py - darstellung
- erzwinge `+`-Vorzeichen
- Spaltennamen ausführlicher (`b` -> `bound`)
- pad-Spalte ganz rechts, um als optional zu verdeutlichen
2022-06-14 20:10:54 +02:00
a9eb961eec master > master: code py - commands, bsp. aus VL 2022-06-14 20:02:38 +02:00
69 changed files with 97 additions and 2158 deletions

View File

@@ -72,25 +72,23 @@
once: false
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Beispiele für Seminarwoche 11 (Blatt 10)
# Beispiele für Vorlesung + Seminarwoche 11 (VL + Blatt 10)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- name: RUCKSACK
- &rucksack_1
name: RUCKSACK
algorithm: GREEDY
allow-fractional: true
# allow-fractional: false
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
- <<: *rucksack_1
allow-fractional: true
- <<: *rucksack_1
algorithm: BRANCH-AND-BOUND
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
@@ -101,8 +99,10 @@
'Schokolade',
'Apfelringe',
]
costs: [220, 80, 140, 90, 100]
values: [100, 10, 70, 80, 100]
costs:
[220, 80, 140, 90, 100]
values:
[100, 10, 70, 80, 100]
- name: RUCKSACK
algorithm: BRANCH-AND-BOUND
max-cost: 90
@@ -113,88 +113,7 @@
'Hirse',
'Sellerie',
]
costs: [30, 10, 50, 10, 80]
values: [17, 14, 17, 5, 25]
- name: RUCKSACK
algorithm: BRANCH-AND-BOUND
max-cost: 900
items: [
'Sellerie',
'Sonnenblumenkerne',
'Rote Beete',
'Hirse',
'Buchweizen',
]
costs: [600, 100, 800, 100, 200]
values: [10, 15, 20, 5, 15]
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Beispiele für Seminarwoche 12
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- name: RANDOM-WALK
algorithm: GRADIENT
one-based: true
coords-init: [3, 3]
landscape: &ref_landscape1
neighbourhoods:
radius: 1
# metric: MANHATTAN
metric: MAXIMUM
labels:
- x
- y
values:
- [5, 2, 1, 3, 4, 7]
- [8, 4, 3, 5, 5, 6]
- [9, 1, 2, 6, 8, 4]
- [7, 4, 4, 3, 7, 3]
- [6, 4, 2, 1, 0, 7]
- [4, 3, 5, 2, 1, 8]
optimise: MAX
- name: RANDOM-WALK
algorithm: ADAPTIVE
one-based: true
coords-init: [3, 3]
landscape: *ref_landscape1
optimise: MAX
- name: RANDOM-WALK
algorithm: METROPOLIS
annealing: false
temperature-init: 3.
one-based: true
coords-init: [5, 3]
landscape: *ref_landscape1
optimise: MAX
- name: RANDOM-WALK
algorithm: METROPOLIS
annealing: false
temperature-init: 3.
one-based: false
coords-init: [0]
landscape:
neighbourhoods:
radius: 1
metric: MANHATTAN
labels:
- x
values: [4, 6.5, 2]
optimise: MAX
- name: GENETIC
population:
- [3, 5, 4, 1, 6, 7, 2, 8, 9]
- [4, 5, 3, 2, 1, 6, 7, 8, 9]
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Beispiele für Seminarwoche 13
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- name: EUKLID
numbers:
- 2017
- 58
- name: POLLARD-RHO
growth: LINEAR
# growth: EXPONENTIAL
number: 534767
x-init: 5
costs:
[30, 10, 50, 10, 80]
values:
[17, 14, 17, 5, 25]

View File

@@ -22,25 +22,11 @@ options:
diagonal: 0
horizontal: 1
vertical: 2
# verbose: []
verbose:
- COSTS
- MOVES
show: []
# show:
# - ATOMS
# - TREE
show:
# - ATOMS
- TREE
rucksack:
verbose: *ref_verbose
show: []
# show:
# - ALL-WEIGHTS
# - ALL-SUMS
genetic:
verbose: *ref_verbose
random-walk:
verbose: *ref_verbose
euklid:
verbose: *ref_verbose
pollard-rho:
verbose: *ref_verbose
verbose: true

View File

@@ -1 +1 @@
0.3.1
0.1.0

View File

@@ -1,10 +0,0 @@
# CommandEuklid
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | [**EnumAlgorithmNames**](EnumAlgorithmNames.md) | | [default to null]
**numbers** | [**List**](integer.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)

View File

@@ -1,10 +0,0 @@
# CommandGenetic
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | [**EnumAlgorithmNames**](EnumAlgorithmNames.md) | | [default to null]
**population** | [**List**](array.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)

View File

@@ -1,12 +0,0 @@
# CommandPollard
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | [**EnumAlgorithmNames**](EnumAlgorithmNames.md) | | [default to null]
**number** | [**Integer**](integer.md) | | [default to null]
**growth** | [**EnumPollardGrowthRate**](EnumPollardGrowthRate.md) | | [default to null]
**xMinusinit** | [**Integer**](integer.md) | | [optional] [default to 2]
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -1,16 +0,0 @@
# CommandRandomWalk
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | [**EnumAlgorithmNames**](EnumAlgorithmNames.md) | | [default to null]
**algorithm** | [**EnumWalkMode**](EnumWalkMode.md) | | [default to null]
**landscape** | [**DataTypeLandscapeGeometry**](DataTypeLandscapeGeometry.md) | | [default to null]
**optimise** | [**EnumOptimiseMode**](EnumOptimiseMode.md) | | [default to null]
**coordsMinusinit** | [**List**](integer.md) | Initial co-ordinates to start the algorithm. | [optional] [default to null]
**temperatureMinusinit** | [**Float**](float.md) | | [optional] [default to null]
**annealing** | [**Boolean**](boolean.md) | | [optional] [default to false]
**oneMinusbased** | [**Boolean**](boolean.md) | | [optional] [default to false]
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -3,7 +3,6 @@
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | [**EnumAlgorithmNames**](EnumAlgorithmNames.md) | | [default to null]
**algorithm** | [**EnumRucksackAlgorithm**](EnumRucksackAlgorithm.md) | | [default to null]
**allowMinusfractional** | [**Boolean**](boolean.md) | | [optional] [default to false]
**maxMinuscost** | [**BigDecimal**](number.md) | Upper bound for total cost of rucksack. | [default to null]

View File

@@ -1,11 +0,0 @@
# DataTypeLandscapeGeometry
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**neighbourhoods** | [**DataTypeLandscapeNeighbourhoods**](DataTypeLandscapeNeighbourhoods.md) | | [default to null]
**labels** | [**List**](string.md) | | [default to null]
**values** | [**DataTypeLandscapeValues**](DataTypeLandscapeValues.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)

View File

@@ -1,10 +0,0 @@
# DataTypeLandscapeNeighbourhoods
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**radius** | [**BigDecimal**](number.md) | | [optional] [default to 1]
**metric** | [**EnumLandscapeMetric**](EnumLandscapeMetric.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)

View File

@@ -1,8 +0,0 @@
# DataTypeLandscapeValues
## 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)

View File

@@ -1,8 +0,0 @@
# EnumLandscapeMetric
## 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)

View File

@@ -1,8 +0,0 @@
# EnumPollardGrowthRate
## 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)

View File

@@ -1,8 +0,0 @@
# EnumWalkMode
## 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)

View File

@@ -13,23 +13,13 @@ Class | Method | HTTP request | Description
## Documentation for Models
- [Command](.//Models/Command.md)
- [CommandEuklid](.//Models/CommandEuklid.md)
- [CommandGenetic](.//Models/CommandGenetic.md)
- [CommandHirschberg](.//Models/CommandHirschberg.md)
- [CommandPollard](.//Models/CommandPollard.md)
- [CommandRandomWalk](.//Models/CommandRandomWalk.md)
- [CommandRucksack](.//Models/CommandRucksack.md)
- [CommandTarjan](.//Models/CommandTarjan.md)
- [CommandTsp](.//Models/CommandTsp.md)
- [DataTypeLandscapeGeometry](.//Models/DataTypeLandscapeGeometry.md)
- [DataTypeLandscapeNeighbourhoods](.//Models/DataTypeLandscapeNeighbourhoods.md)
- [DataTypeLandscapeValues](.//Models/DataTypeLandscapeValues.md)
- [EnumAlgorithmNames](.//Models/EnumAlgorithmNames.md)
- [EnumLandscapeMetric](.//Models/EnumLandscapeMetric.md)
- [EnumOptimiseMode](.//Models/EnumOptimiseMode.md)
- [EnumPollardGrowthRate](.//Models/EnumPollardGrowthRate.md)
- [EnumRucksackAlgorithm](.//Models/EnumRucksackAlgorithm.md)
- [EnumWalkMode](.//Models/EnumWalkMode.md)
<a name="documentation-for-authorization"></a>

View File

@@ -8,11 +8,7 @@ Name | Type | Description | Notes
**tarjan** | [**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]
**rucksack** | [**AppOptions_rucksack**](AppOptions_rucksack.md) | | [default to null]
**randomMinuswalk** | [**AppOptions_tarjan**](AppOptions_tarjan.md) | | [default to null]
**genetic** | [**AppOptions_tarjan**](AppOptions_tarjan.md) | | [default to null]
**euklid** | [**AppOptions_tarjan**](AppOptions_tarjan.md) | | [default to null]
**pollardMinusrho** | [**AppOptions_tarjan**](AppOptions_tarjan.md) | | [default to null]
**rucksack** | [**AppOptions_tarjan**](AppOptions_tarjan.md) | | [optional] [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)

View File

@@ -1,10 +0,0 @@
# 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)

View File

@@ -1,8 +0,0 @@
# 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)

View File

@@ -15,13 +15,11 @@ Class | Method | HTTP request | Description
- [AppOptions](.//Models/AppOptions.md)
- [AppOptionsHirschberg](.//Models/AppOptionsHirschberg.md)
- [AppOptionsHirschbergMovePriorities](.//Models/AppOptionsHirschbergMovePriorities.md)
- [AppOptionsRucksack](.//Models/AppOptionsRucksack.md)
- [AppOptionsTarjan](.//Models/AppOptionsTarjan.md)
- [Config](.//Models/Config.md)
- [EnumHirschbergShow](.//Models/EnumHirschbergShow.md)
- [EnumHirschbergVerbosity](.//Models/EnumHirschbergVerbosity.md)
- [EnumLogLevel](.//Models/EnumLogLevel.md)
- [EnumRucksackShow](.//Models/EnumRucksackShow.md)
- [Info](.//Models/Info.md)

View File

@@ -1,4 +1,4 @@
# set shell := [ "bash", "-uc" ]
set shell := [ "bash", "-uc" ]
_default:
@- just --unsorted --choose
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -44,6 +44,4 @@ def enter(*args: str):
if __name__ == '__main__':
sys.tracebacklimit = 0;
# NOTE: necessary for Windows, to ensure that console output is rendered correctly:
os.system('');
enter(*sys.argv[1:]);

View File

@@ -1,6 +1,6 @@
openapi: 3.0.3
info:
version: 0.3.1
version: 0.1.0
title: Schemata for command instructions
servers:
- url: "."
@@ -115,14 +115,11 @@ components:
Instructions for execution of Branch & Bound-Algorithm for the Rucksack-Problem
type: object
required:
- name
- algorithm
- max-cost
- costs
- values
properties:
name:
$ref: '#/components/schemas/EnumAlgorithmNames'
algorithm:
$ref: '#/components/schemas/EnumRucksackAlgorithm'
allow-fractional:
@@ -149,150 +146,6 @@ components:
items:
type: string
default: []
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Algorithm: Random Walk
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CommandRandomWalk:
description: |-
Instructions for execution of random walks to determine local extrema in a fitness landscape
type: object
required:
- name
- algorithm
- landscape
- optimise
properties:
name:
$ref: '#/components/schemas/EnumAlgorithmNames'
algorithm:
$ref: '#/components/schemas/EnumWalkMode'
landscape:
$ref: '#/components/schemas/DataTypeLandscapeGeometry'
optimise:
$ref: '#/components/schemas/EnumOptimiseMode'
coords-init:
description: Initial co-ordinates to start the algorithm.
type: array
items:
type: integer
minItems: 1
temperature-init:
type: float
default: 1.
annealing:
type: boolean
default: false
one-based:
type: boolean
default: false
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Algorithm: Genetic Algorithm
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CommandGenetic:
description: |-
Instructions for execution of the Genetic algorithm
type: object
required:
- name
- population
properties:
name:
$ref: '#/components/schemas/EnumAlgorithmNames'
population:
type: array
items:
type: array
items:
type: string
minItems: 2
# maxItems: 2 # FIXME: does not work!
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Algorithm: Euklidean algorithm
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CommandEuklid:
description: |-
Instructions for execution of the Euklidean gcd-algorithm
type: object
required:
- name
- numbers
properties:
name:
$ref: '#/components/schemas/EnumAlgorithmNames'
numbers:
type: array
items:
type: integer
exclusiveMinimum: 0
minItems: 2
maxItems: 2
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Algorithm: Pollard's rho
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CommandPollard:
description: |-
Instructions for execution of the Pollard's rho algorithm
type: object
required:
- name
- growth
- number
properties:
name:
$ref: '#/components/schemas/EnumAlgorithmNames'
number:
type: integer
exclusiveMinimum: 0
growth:
$ref: '#/components/schemas/EnumPollardGrowthRate'
x-init:
type: integer
default: 2
minimum: 2
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Data-type Landscape Geometry, Landscape Values
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DataTypeLandscapeGeometry:
description: |-
Structure for the geometry of a fitness landscape
type: object
required:
- neighbourhoods
- labels
- values
properties:
neighbourhoods:
$ref: '#/components/schemas/DataTypeLandscapeNeighbourhoods'
labels:
type: array
items:
type: string
minItems: 1
values:
$ref: '#/components/schemas/DataTypeLandscapeValues'
DataTypeLandscapeNeighbourhoods:
description: |-
Options for the definition of discrete neighbourhoods of a fitness landscape
type: object
required:
- metric
properties:
radius:
type: number
minimum: 1
default: 1
metric:
$ref: '#/components/schemas/EnumLandscapeMetric'
DataTypeLandscapeValues:
description: |-
A (potentially multi-dimensional) array of values for the fitness landscape.
oneOf:
- type: array
items:
type: number
- type: array
items:
$ref: '#/components/schemas/DataTypeLandscapeValues'
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Enum Algorithm Names
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -305,10 +158,6 @@ components:
- TSP
- HIRSCHBERG
- RUCKSACK
- RANDOM-WALK
- GENETIC
- EUKLID
- POLLARD-RHO
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Enum Optimise Mode
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -329,44 +178,3 @@ components:
enum:
- GREEDY
- BRANCH-AND-BOUND
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Enum Type for choice of growth rate in Pollard Algorithm
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EnumPollardGrowthRate:
description: |-
Via the 'tail-chasing' period finding method in Pollard's rho algorithm,
the difference between the indexes of the pseudo-random sequence
can be chosen to growth according to different rates, e.g.
- `LINEAR` - choose `x[k]` and `x[2k]`
- `EXPONENTIAL` - choose `x[k]` and `x[2^{k}]`
type: string
enum:
- LINEAR
- EXPONENTIAL
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Enum Type of walk mode for fitness walk algorithm
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EnumWalkMode:
description: |-
Enumeration of walk mode for fitness walk algorithm
- `ADAPTIVE` - points uniformly randomly chosen from nbhd.
- `GRADIENT` - points uniformly randomly chosen amongst points in nbhd with steepest gradient.
- `METROPOLIS` - points uniformly randomly chosen from nbhd. or by entropy.
type: string
enum:
- ADAPTIVE
- GRADIENT
- METROPOLIS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Enum for metric for neighbourhoods in fitness landscape
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EnumLandscapeMetric:
description: |-
Enumeration of mode for Rucksack problem
- `MAXIMUM` - `Q` is a neighbour of `P` <==> `max_i d(P_i, Q_i) <= r`
- `MANHATTAN` - `Q` is a neighbour of `P` <==> `sum_i d(P_i, Q_i) <= r`
type: string
enum:
- MAXIMUM
- MANHATTAN

View File

@@ -1,6 +1,6 @@
openapi: 3.0.3
info:
version: 0.3.1
version: 0.1.0
title: Schemata for config models
servers:
- url: "."
@@ -53,11 +53,7 @@ components:
- tsp
- tarjan
- hirschberg
- rucksack
- random-walk
- genetic
- euklid
- pollard-rho
- rucksack-branch-and-bound
properties:
log-level:
$ref: '#/components/schemas/EnumLogLevel'
@@ -120,42 +116,6 @@ components:
$ref: '#/components/schemas/EnumHirschbergShow'
default: []
rucksack:
type: object
required: []
properties:
verbose:
type: boolean
default: false
show:
type: array
items:
$ref: '#/components/schemas/EnumRucksackShow'
default: []
random-walk:
type: object
required:
- verbose
properties:
verbose:
type: boolean
default: false
genetic:
type: object
required:
- verbose
properties:
verbose:
type: boolean
default: false
euklid:
type: object
required:
- verbose
properties:
verbose:
type: boolean
default: false
pollard-rho:
type: object
required:
- verbose
@@ -188,18 +148,8 @@ components:
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EnumHirschbergShow:
description: |-
Enumeration of display options for Hirschberg
Enumeration of verbosity options for Hirschberg
type: string
enum:
- TREE
- ATOMS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Enum Rucksack - display options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EnumRucksackShow:
description: |-
Enumeration of display options for the Rucksack problem
type: string
enum:
- ALL-WEIGHTS
- ALL-SUMS

View File

@@ -1,6 +1,6 @@
[project]
name = "uni-leipzig-ads-2-2022"
version = "0.3.1"
version = "1.0.0"
description = "Zusatzcode, um Algorithmen und Datenstrukturen im Kurs ADS2 zu demonstrieren."
authors = [ "Raj Dahya" ]
maintainers = [ "raj_mathe" ]

View File

@@ -1,16 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.algorithms.euklid.algorithms import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'euklidean_algorithm',
];

View File

@@ -1,97 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.types import *;
from src.thirdparty.maths import *;
from models.generated.config import *;
from src.core.utils import *;
from src.models.euklid import *;
from src.algorithms.euklid.display import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'euklidean_algorithm',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD euklidean algorithm
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def euklidean_algorithm(
a: int,
b: int,
verbose: bool = False,
) -> Tuple[int, int, int]:
'''
Führt den Euklideschen Algorithmus aus, um den größten gemeinsamen Teiler (ggT, en: gcd)
von zwei positiven Zahlen zu berechnen.
'''
################
# NOTE:
# Lemma: gcd(a,b) = gcd(mod(a, b), b)
# Darum immer weiter (a, b) durch (b, gcd(a,b)) ersetzen, bis b == 0.
################
steps = [];
d = 0;
while True:
if b == 0:
d = a;
steps.append(Step(a=a, b=b, gcd=d, div=0, rem=a, coeff_a=1, coeff_b=0));
break;
else:
# Berechne k, r so dass a = k·b + r mit k ≥ 0, 0 ≤ r < b:
r = a % b;
k = math.floor(a / b);
# Speichere Berechnungen:
steps.append(Step(a=a, b=b, gcd=0, div=k, rem=r, coeff_a=0, coeff_b=0));
# ersetze a, b durch b, r:
a = b;
b = r;
################
# NOTE:
# In jedem step gilt
# a = k·b + r
# und im folgenden gilt:
# d = coeff_a'·a' + coeff_b'·b'
# wobei
# a' = b
# b' = r
# Darum:
# d = coeff_a'·b + coeff_b'·(a - k·b)
# = coeff_b'·a + (coeff_a' - k·coeff_b)·b
# Darum:
# coeff_a = coeff_b'
# coeff_b = coeff_a' - k·coeff_b
################
coeff_a = 1;
coeff_b = 0;
for step in steps[::-1][1:]:
(coeff_a, coeff_b) = (coeff_b, coeff_a - step.div * coeff_b);
step.coeff_a = coeff_a;
step.coeff_b = coeff_b;
step.gcd = d;
if verbose:
step = steps[0];
repr = display_table(steps=steps, reverse=True);
expr = display_sum(step=step);
print('');
print('\x1b[1mEuklidescher Algorithmus\x1b[0m');
print('');
print(repr);
print('');
print('\x1b[1mLösung\x1b[0m');
print('');
print(f'a=\x1b[1m{step.a}\x1b[0m; b=\x1b[1m{step.b}\x1b[0m; d = \x1b[1m{step.gcd}\x1b[0m = {expr}.');
print('');
return d, coeff_a, coeff_b;

View File

@@ -1,56 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.code import *;
from src.thirdparty.maths import *;
from src.thirdparty.types import *;
from src.models.euklid import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'display_table',
'display_sum',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD display table
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def display_table(
steps: List[Step],
reverse: bool = False,
) -> str:
if reverse:
steps = steps[::-1];
table = pd.DataFrame({
'a': [step.a for step in steps],
'b': [step.b for step in steps],
'div': ['-' if step.b == 0 else step.div for step in steps],
'gcd': [step.gcd for step in steps],
'expr': [f'= {display_sum(step=step)}' for step in steps],
}) \
.reset_index(drop=True);
# benutze pandas-Dataframe + tabulate, um schöner darzustellen:
repr = tabulate(
table,
headers=['a', 'b', 'floor(a/b)', 'gcd(a,b)', 'gcd(a,b)=x·a + y·b'],
showindex=False,
colalign=('right', 'right', 'right', 'center', 'left'),
tablefmt='simple'
);
return repr;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD display table
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def display_sum(step: Step) -> str:
return f'\x1b[1m{step.coeff_a}\x1b[0m·a + \x1b[1m{step.coeff_b}\x1b[0m·b' ;

View File

@@ -1,16 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.algorithms.genetic.algorithms import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'genetic_algorithm',
];

View File

@@ -1,38 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.types import *;
from src.thirdparty.maths import *;
from models.generated.config import *;
from src.core.log import *;
from src.core.utils import *;
from src.models.genetic import *;
from src.algorithms.genetic.display import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'genetic_algorithm',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD genetic algorithm
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def genetic_algorithm(
individual1: List[str],
individual2: List[str],
verbose: bool,
):
'''
Führt den genetischen Algorithmus auf 2 Individuen aus.
'''
log_warn('Noch nicht implementiert!');
return;

View File

@@ -1,30 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.code import *;
from src.thirdparty.maths import *;
from src.thirdparty.types import *;
from src.core.log import *;
from src.models.genetic import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'display_table',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD display table
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def display_table(
) -> str:
log_warn('Noch nicht implementiert!');
return '';

View File

@@ -6,6 +6,7 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.algorithms.hirschberg.algorithms import *;
from src.models.hirschberg.penalties import *;
from src.algorithms.hirschberg.display import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -1,17 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.algorithms.pollard_rho.algorithms import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'pollard_rho_algorithm_linear',
'pollard_rho_algorithm_exponential',
];

View File

@@ -1,144 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.types import *;
from src.thirdparty.maths import *;
from models.generated.config import *;
from src.core.utils import *;
from src.models.pollard_rho import *;
from src.algorithms.pollard_rho.display import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'pollard_rho_algorithm_linear',
'pollard_rho_algorithm_exponential',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD pollard's rho algorithm - with linear grwoth
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def pollard_rho_algorithm_linear(
n: int,
x_init: int = 2,
verbose: bool = False,
):
steps = [];
success = False;
f = lambda _: fct(_, n=n);
d = 1;
x = y = x_init;
steps.append(Step(x=x));
k = 0;
k_next = 1;
while True:
# aktualisiere x: x = f(x_prev):
x = f(x);
# aktualisiere y: y = f(f(y_prev)):
y = f(f(y));
# ggT berechnen:
d = math.gcd(abs(x-y), n);
steps.append(Step(x=x, y=y, d=d));
# Abbruchkriterien prüfen:
if d == 1: # weitermachen, solange d == 1
k += 1;
continue;
elif d == n: # versagt
success = False;
break;
else:
success = True;
break;
if verbose:
repr = display_table_linear(steps=steps);
print('');
print('\x1b[1mEuklidescher Algorithmus\x1b[0m');
print('');
print(repr);
print('');
if success:
print('\x1b[1mBerechneter Faktor:\x1b[0m');
print('');
print(f'd = \x1b[1m{d}\x1b[0m.');
else:
print('\x1b[91mKein (Prim)faktor erkannt!\x1b[0m');
print('');
return d;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD pollard's rho algorithm - with exponential grwoth
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def pollard_rho_algorithm_exponential(
n: int,
x_init: int = 2,
verbose: bool = False,
):
steps = [];
success = False;
f = lambda _: fct(_, n=n);
d = 1;
x = y = x_init;
steps.append(Step(x=x));
k = 0;
k_next = 1;
while True:
# aktualisiere x: x = f(x_prev):
x = f(x);
# aktualisiere y, wenn k = 2^j: y = x[j] = f(y_prev):
if k == k_next:
k_next = 2*k_next;
y = f(y);
# ggT berechnen:
d = math.gcd(abs(x-y), n);
steps.append(Step(x=x, y=y, d=d));
# Abbruchkriterien prüfen:
if d == 1: # weitermachen, solange d == 1
k += 1;
continue;
elif d == n: # versagt
success = False;
break;
else:
success = True;
break;
if verbose:
repr = display_table_exponential(steps=steps);
print('');
print('\x1b[1mEuklidescher Algorithmus\x1b[0m');
print('');
print(repr);
print('');
if success:
print('\x1b[1mBerechneter Faktor:\x1b[0m');
print('');
print(f'd = \x1b[1m{d}\x1b[0m.');
else:
print('\x1b[91mKein (Prim)faktor erkannt!\x1b[0m');
print('');
return d;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# AUXILIARY METHOD function for Pollard's rho
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def fct(x: int, n: int) -> int:
return (x**2 - 1) % n;

View File

@@ -1,65 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.code import *;
from src.thirdparty.maths import *;
from src.thirdparty.types import *;
from src.models.pollard_rho import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'display_table_linear',
'display_table_exponential',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD display table - linear
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def display_table_linear(steps: List[Step]) -> str:
table = pd.DataFrame({
'i': [i for i in range(len(steps))],
'x': [step.x for step in steps],
'y': [step.y or '-' for step in steps],
'd': [step.d or '-' for step in steps],
}) \
.reset_index(drop=True);
# benutze pandas-Dataframe + tabulate, um schöner darzustellen:
repr = tabulate(
table,
headers=['i', 'x(i)', 'y(i) = x(2i)', 'gcd(|x - y|,n)'],
showindex=False,
colalign=('right', 'right', 'right', 'center'),
tablefmt='simple',
);
return repr;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD display table - exponential
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def display_table_exponential(steps: List[Step]) -> str:
table = pd.DataFrame({
'i': [i for i in range(len(steps))],
'x': [step.x for step in steps],
'y': [step.y or '-' for step in steps],
'd': [step.d or '-' for step in steps],
}) \
.reset_index(drop=True);
# benutze pandas-Dataframe + tabulate, um schöner darzustellen:
repr = tabulate(
table,
headers=['i', 'x(i)', 'y(i) = x([log₂(i)])', 'gcd(|x - y|,n)'],
showindex=False,
colalign=('right', 'right', 'right', 'center'),
tablefmt='simple',
);
return repr;

View File

@@ -1,18 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.algorithms.random_walk.algorithms import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'adaptive_walk_algorithm',
'gradient_walk_algorithm',
'metropolis_walk_algorithm',
];

View File

@@ -1,247 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.maths import *;
from src.thirdparty.plots import *;
from src.thirdparty.types import *;
from models.generated.config import *;
from models.generated.commands import *;
from src.core.log import *;
from src.core.utils import *;
from src.models.random_walk import *;
from src.algorithms.random_walk.display import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'adaptive_walk_algorithm',
'gradient_walk_algorithm',
'metropolis_walk_algorithm',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CONSTANTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MAX_ITERATIONS = 1000; # um endlose Schleifen zu verhindern
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD adaptive walk
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def adaptive_walk_algorithm(
landscape: Landscape,
r: float,
coords_init: tuple,
optimise: EnumOptimiseMode,
verbose: bool,
):
'''
Führt den Adapative-Walk Algorithmus aus, um ein lokales Minimum zu bestimmen.
'''
# lege Fitness- und Umgebungsfunktionen fest:
match optimise:
case EnumOptimiseMode.max:
f = lambda x: -landscape.fitness(*x);
case _:
f = lambda x: landscape.fitness(*x);
nbhd = lambda x: landscape.neighbourhood(*x, r=r, strict=True);
label = lambda x: landscape.label(*x);
# initialisiere
steps = [];
x = coords_init;
fx = f(x);
fy = fx;
N = nbhd(x);
# führe walk aus:
k = 0;
while k < MAX_ITERATIONS:
# Wähle zufälligen Punkt und berechne fitness-Wert:
y = uniform_random_choice(N);
fy = f(y);
# Nur dann aktualisieren, wenn sich f-Wert verbessert:
if fy < fx:
# Punkt + Umgebung + f-Wert aktualisieren
x = y;
fx = fy;
N = nbhd(x);
step = Step(coords=x, label=label(x), improved=True, changed=True);
else:
# Nichts (außer logging) machen!
step = Step(coords=x, label=label(x));
# Nur dann (erfolgreich) abbrechen, wenn f-Wert lokal Min:
if fx <= min([f(y) for y in N], default=fx):
step.stopped = True;
steps.append(step);
break;
steps.append(step);
k += 1;
return x;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD gradient walk
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def gradient_walk_algorithm(
landscape: Landscape,
r: float,
coords_init: tuple,
optimise: EnumOptimiseMode,
verbose: bool,
):
'''
Führt den Gradient-Descent (bzw. Ascent) Algorithmus aus, um ein lokales Minimum zu bestimmen.
'''
# lege Fitness- und Umgebungsfunktionen fest:
match optimise:
case EnumOptimiseMode.max:
f = lambda x: -landscape.fitness(*x);
case _:
f = lambda x: landscape.fitness(*x);
nbhd = lambda x: landscape.neighbourhood(*x, r=r, strict=True);
label = lambda x: landscape.label(*x);
# initialisiere
steps = [];
x = coords_init;
fx = landscape.fitness(*x);
fy = fx;
N = nbhd(x);
f_values = [f(y) for y in N];
fmin = min(f_values);
Z = [y for y, fy in zip(N, f_values) if fy == fmin];
# führe walk aus:
k = 0;
while k < MAX_ITERATIONS:
# Wähle zufälligen Punkt mit steilstem Abstieg und berechne fitness-Wert:
y = uniform_random_choice(Z);
fy = fmin;
# Nur dann aktualisieren, wenn sich f-Wert verbessert:
if fy < fx:
# Punkt + Umgebung + f-Wert aktualisieren
x = y;
fx = fy;
N = nbhd(y);
f_values = [f(y) for y in N];
fmin = min(f_values);
Z = [y for y, fy in zip(N, f_values) if fy == fmin];
step = Step(coords=x, label=label(x), improved=True, changed=True);
else:
# Nichts (außer logging) machen!
step = Step(coords=x, label=label(x));
# Nur dann (erfolgreich) abbrechen, wenn f-Wert lokal Min:
if fx <= min([f(y) for y in N], default=fx):
step.stopped = True;
steps.append(step);
break;
steps.append(step);
k += 1;
return x;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD metropolis walk
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def metropolis_walk_algorithm(
landscape: Landscape,
r: float,
coords_init: tuple,
T: float,
annealing: bool,
optimise: EnumOptimiseMode,
verbose: bool,
):
'''
Führt den Metropolis-Walk Algorithmus aus, um ein lokales Minimum zu bestimmen.
'''
# lege Fitness- und Umgebungsfunktionen fest:
match optimise:
case EnumOptimiseMode.max:
f = lambda x: -landscape.fitness(*x);
case _:
f = lambda x: landscape.fitness(*x);
nbhd = lambda x: landscape.neighbourhood(*x, r=r, strict=True);
label = lambda x: landscape.label(*x);
# definiere anzahl der hinreichenden Schritt für Stabilität:
n_stable = 2*(3**(landscape.dim) - 1);
# initialisiere
x = coords_init;
fx = f(x);
fy = fx;
nbhd_x = nbhd(x);
steps = [];
step = Step(coords=x, label=label(x));
# führe walk aus:
k = 0;
n_unchanged = 0;
while k < MAX_ITERATIONS:
# Wähle zufälligen Punkt und berechne fitness-Wert:
y = uniform_random_choice(nbhd_x);
fy = f(y);
p = math.exp(-abs(fy-fx)/T);
u = random_binary(p);
# Aktualisieren, wenn sich f-Wert verbessert
# oder mit einer Wahrscheinlichkeit von p:
if fy < fx or u:
# Punkt + Umgebung + f-Wert aktualisieren
x = y;
fx = fy;
nbhd_x = nbhd(x);
n_unchanged = 0;
step = Step(coords=x, label=label(x), improved=(fy < fx), chance=u, probability=p, changed=True);
else:
# Nichts (außer logging) machen!
n_unchanged += 1;
step = Step(coords=x, label=label(x));
# »Temperatur« ggf. abkühlen:
if annealing:
T = cool_temperature(T, k);
# Nur dann (erfolgreich) abbrechen, wenn f-Wert lokal Min:
if n_unchanged >= n_stable:
step.stopped = True;
steps.append(step);
break;
steps.append(step);
k += 1;
if verbose:
for step in steps:
print(step);
return x;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# AUXILIARY METHODS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def cool_temperature(T: float, k: int, const: float = 2.) -> float:
harm = const*(k + 1);
return T/(1 + T/harm);

View File

@@ -1,30 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.code import *;
from src.thirdparty.maths import *;
from src.thirdparty.types import *;
from src.core.log import *;
from src.models.random_walk import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'display_table',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD display table
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def display_table(
) -> str:
log_warn('Noch nicht implementiert!');
return '';

View File

@@ -57,25 +57,25 @@ def rucksack_greedy_algorithm(
# führe greedy aus:
n = len(costs);
cost_total = 0;
choice = [ Fraction(0) for _ in range(n) ];
vector = [ Fraction(0) for _ in range(n) ];
for i in order:
# füge Item i hinzu, solange das Gesamtgewicht noch <= Schranke
if cost_total + costs[i] <= max_cost:
cost_total += costs[i];
choice[i] = Fraction(1);
vector[i] = Fraction(1);
# falls Bruchteile erlaubt sind, füge einen Bruchteil des i. Items hinzu und abbrechen
elif fractional:
choice[i] = Fraction(Fraction(max_cost - cost_total)/Fraction(costs[i]), _normalize=False);
vector[i] = Fraction(Fraction(max_cost - cost_total)/Fraction(costs[i]), _normalize=False);
break;
# ansonsten weiter machen:
else:
continue;
# Aspekte der Lösung speichern:
rucksack = [i for i, v in enumerate(choice) if v > 0]; # Indexes von Items im Rucksack
rucksack = [i for i, v in enumerate(vector) if v > 0]; # Indexes von Items im Rucksack
soln = Solution(
order = order,
choice = choice,
choice = vector,
items = items[rucksack].tolist(),
costs = costs[rucksack].tolist(),
values = values[rucksack].tolist(),
@@ -83,7 +83,7 @@ def rucksack_greedy_algorithm(
# verbose output hier behandeln (irrelevant für Algorithmus):
if verbose:
repr_rucksack = display_rucksack(items=items, costs=costs, values=values, choice=choice);
repr_rucksack = display_rucksack(items=items[rucksack], costs=costs[rucksack], values=values[rucksack]);
print('\x1b[1mEingeschätzte Lösung\x1b[0m');
print('');
print(f'Mask: [{", ".join(map(str, soln.choice))}]');
@@ -122,34 +122,24 @@ def rucksack_branch_and_bound_algorithm(
print('');
logged_steps = [];
step: Step;
mask = empty_mask(n=len(costs));
bound = np.inf;
vector = empty_mask(n=len(costs));
lb_estimate = np.inf;
S = Stack();
S.push(mask);
S.push(vector);
while not S.empty():
# top-Element auslesen und Bound berechnen:
A: Mask = S.top();
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):
lb, choice, order_, pad = estimate_lower_bound(mask=S.top(), max_cost=max_cost, costs=costs, values=values, items=items);
if verbose:
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 state is not None:
step.move = EnumBranchAndBoundMove.BOUND;
step.bound = bound_subtree;
else:
step.move = EnumBranchAndBoundMove.BRANCH;
logged_steps.append(step);
S.pop();
logged_steps.append((lb_estimate, lb, str(S), choice, order_, pad));
# 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 state is not None:
bound = bound_subtree;
mask = state;
A: Mask = S.pop();
if lb < lb_estimate:
# 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:
lb_estimate = lb;
# falls A als einelementige Menge betrachtet werden kann, ersetze unbekannte Werte:
if pad != MaskValue.UNSET:
A = A.pad(pad);
vector = A;
# Branch sonst
else:
B, C = A.split();
@@ -159,10 +149,10 @@ def rucksack_branch_and_bound_algorithm(
S.push(C);
# Aspekte der Lösung speichern
rucksack = mask.indexes_one; # Indexes von Items im Rucksack
rucksack = vector.indexes_one; # Indexes von Items im Rucksack
soln = Solution(
order = order,
choice = mask.choice,
choice = vector.choice,
items = items[rucksack].tolist(),
values = values[rucksack].tolist(),
costs = costs[rucksack].tolist(),
@@ -171,11 +161,11 @@ def rucksack_branch_and_bound_algorithm(
# verbose output hier behandeln (irrelevant für Algorithmus):
if verbose:
repr = display_branch_and_bound(values=values, steps=logged_steps);
repr_rucksack = display_rucksack(items=items, costs=costs, values=values, choice=mask.choice);
print(repr);
print('');
repr_rucksack = display_rucksack(items=items[rucksack], costs=costs[rucksack], values=values[rucksack]);
print('\x1b[1mLösung\x1b[0m');
print('');
print(repr);
print('');
print(f'Mask: [{", ".join(map(str, soln.choice))}]');
print('Rucksack:');
print(repr_rucksack);
@@ -204,14 +194,14 @@ def estimate_lower_bound(
costs: np.ndarray,
values: np.ndarray,
items: np.ndarray,
) -> Tuple[float, List[Fraction], List[int], Optional[Mask]]:
) -> Tuple[float, List[Fraction], List[int], MaskValue]:
'''
Wenn partielle Information über den Rucksack festgelegt ist,
kann man bei dem unbekannten Teil das Rucksack-Problem
mit Greedy-Algorithmus »lösen«,
um schnell eine gute Einschätzung zu bestimmen.
NOTE: Diese Funktion wird `g(mask)` im Skript bezeichnet.
NOTE: Diese Funktion wird `g(vector)` im Skript bezeichnet.
'''
indexes_one = mask.indexes_one;
indexes_unset = mask.indexes_unset;
@@ -226,17 +216,14 @@ def estimate_lower_bound(
# Für Rest des Rucksacks (Items mit unbekanntem Status):
cost_rest = max_cost - cost_rucksack;
state = None;
pad = MaskValue.UNSET;
# Prüfe, ob man als Lösung alles/nichts hinzufügen kann:
if len(indexes_unset) == 0:
state = mask;
value_rest = 0;
elif sum(costs[indexes_unset]) <= cost_rest:
state = mask.pad(MaskValue.ONE);
if len(indexes_unset) > 0 and sum(costs[indexes_unset]) <= cost_rest:
pad = MaskValue.ONE;
choice[indexes_unset] = Fraction(1);
value_rest = sum(values[indexes_unset]);
elif min(costs[indexes_unset]) > cost_rest:
state = mask.pad(MaskValue.ZERO);
elif len(indexes_unset) > 0 and min(costs[indexes_unset]) > cost_rest:
pad = MaskValue.ZERO;
choice[indexes_unset] = Fraction(0);
value_rest = 0;
# Sonst mit Greedy-Algorithmus lösen:
@@ -259,4 +246,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(), state;
return -value_max_est, choice.tolist(), order.tolist(), pad;

View File

@@ -9,9 +9,6 @@ from src.thirdparty.code import *;
from src.thirdparty.maths import *;
from src.thirdparty.types import *;
from src.core.utils import *;
from src.setup import config;
from models.generated.config import *;
from src.models.stacks import *;
from src.models.rucksack import *;
@@ -39,10 +36,10 @@ def display_order(
) -> str:
table = pd.DataFrame({
'items': items,
'order': iperm(order),
'order': order,
'values': values,
'costs': costs,
'margin': [f'{value/cost:.6f}' for cost, value in zip(costs, values)],
'margin': [str(Fraction(Fraction(value), Fraction(cost))) for cost, value in zip(costs, values)],
}) \
.reset_index(drop=True);
if one_based:
@@ -65,31 +62,18 @@ def display_rucksack(
items: np.ndarray,
costs: np.ndarray,
values: np.ndarray,
choice: List[Fraction],
) -> str:
show_options = config.OPTIONS.rucksack.show;
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({
'items': items.tolist() + ['----', ''],
'nr': list(map(str, choice))
+ ['----', 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'],
'costs': list(map(render, costs)) + ['', f'\x1b[92;1m{sum(costs):g}\x1b[0m'],
'values': list(map(render, values)) + ['', f'\x1b[92;1m{sum(values):g}\x1b[0m'],
});
repr = tabulate(
table,
headers=['item', 'nr', 'cost', 'value'],
headers=['item', 'cost', 'value'],
showindex=False,
colalign=('left', 'center', 'center', 'center'),
colalign=('left', 'center', 'center'),
tablefmt='rst'
);
return repr;
@@ -98,42 +82,31 @@ def display_rucksack(
# METHOD display result of branch and bound
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def display_branch_and_bound(values: np.ndarray, steps: List[Step]) -> str:
show_options = config.OPTIONS.rucksack.show;
show_all_sums = (EnumRucksackShow.all_sums in show_options);
def display_branch_and_bound(
values: np.ndarray,
steps: List[Tuple[float, float, Stack, List[Fraction], List[int], MaskValue]],
) -> str:
# füge Summen-Ausdrücke für Greedy-Alg hinzu:
rows = [];
used_choices = [];
index_soln = max([-1] + [ i for i, step in enumerate(steps) if step.move == EnumBranchAndBoundMove.BOUND ]);
for i, step in enumerate(steps):
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);
for lb_estimate, lb, S, choice, order, pad in steps:
if choice in used_choices:
expr = f'{lb:g}';
else:
expr = '';
bound_str = f'{step.bound:+g}';
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';
rows.append({
'bound': f'{bound_str}',
'bound_subtree': f'{step.bound_subtree:g}',
'bound_subtree_sum': expr,
'stack': step.stack_str,
'solution': f'\x1b[2m{solution_str}\x1b[0m',
'move': f'\x1b[2m{move_str}\x1b[0m',
});
used_choices.append(choice);
expr = display_sum(choice=choice, values=values, as_maximum=False, order=order);
rows.append((f'{lb_estimate:+g}', expr, S, ('' if pad == MaskValue.UNSET else pad.value)));
table = pd.DataFrame(rows).reset_index(drop=True);
table = pd.DataFrame(rows) \
.rename(columns={0: 'bound', 1: 'g(TOP(S))', 2: 'S', 3: 'pad?'}) \
.reset_index(drop=True);
# benutze pandas-Dataframe + tabulate, um schöner darzustellen:
repr = tabulate(
table,
headers=['bound', 'g(TOP(S))', '', 'S — stack', '\x1b[2msoln\x1b[0m', '\x1b[2mmove\x1b[0m'],
headers=['bound', 'g(TOP(S))', 'S — stack', 'pad?'],
showindex=False,
colalign=('right', 'right', 'left', 'right', 'center', 'left'),
tablefmt='simple'
colalign=('left', 'left', 'right', 'center'),
tablefmt='rst'
);
return repr;
@@ -145,30 +118,17 @@ def display_sum(
choice: List[Fraction],
values: np.ndarray,
order: Optional[List[int]] = None,
indexes: List[int] = [],
as_maximum: bool = True,
) -> str:
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)) ];
parts = [ (u, x) for u, x in zip(choice, values)];
if not (order is None):
parts = [ parts[j] for j in order ];
if not show_all_weights:
parts = list(filter(lambda x: x[1] > 0, parts));
expr = '\x1b[2m + \x1b[0m'.join(map(render, parts));
value = sum([ u*x for u, x in parts]);
expr = '+'.join([
f'{x:g}' if u == 1 else f'{u}·{x:g}'
for u, x in parts if u > 0
]);
if as_maximum:
return f'\x1b[2m=\x1b[0m {expr}';
return f'\x1b[2m= -(\x1b[0m{expr}\x1b[2m)\x1b[0m';
return f'{value:g} = {expr}';
else:
return f'-{value:g} = -({expr})';

View File

@@ -40,12 +40,4 @@ def run_command(command: Command) -> Result[CallResult, CallError]:
return endpoint_hirschberg(command);
elif isinstance(command, CommandRucksack):
return endpoint_rucksack(command);
elif isinstance(command, CommandRandomWalk):
return endpoint_random_walk(command);
elif isinstance(command, CommandGenetic):
return endpoint_genetic(command);
elif isinstance(command, CommandEuklid):
return endpoint_euklid(command);
elif isinstance(command, CommandPollard):
return endpoint_pollard_rho(command);
raise Exception(f'No endpoint set for `{command.name.value}`-command type.');

View File

@@ -9,10 +9,6 @@ from src.endpoints.ep_algorithm_hirschberg import *;
from src.endpoints.ep_algorithm_tarjan import *;
from src.endpoints.ep_algorithm_tsp import *;
from src.endpoints.ep_algorithm_rucksack import *;
from src.endpoints.ep_algorithm_genetic import *;
from src.endpoints.ep_algorithm_random_walk import *;
from src.endpoints.ep_algorithm_euklid import *;
from src.endpoints.ep_algorithm_pollard_rho import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
@@ -23,8 +19,4 @@ __all__ = [
'endpoint_tarjan',
'endpoint_tsp',
'endpoint_rucksack',
'endpoint_random_walk',
'endpoint_genetic',
'endpoint_euklid',
'endpoint_pollard_rho',
];

View File

@@ -1,34 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.code import *;
from models.generated.commands import *;
from src.core.calls import *;
from src.setup import config;
from src.algorithms.euklid import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'endpoint_euklid',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ENDPOINT
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@run_safely()
def endpoint_euklid(command: CommandEuklid) -> Result[CallResult, CallError]:
result = euklidean_algorithm(
a = command.numbers[0].__root__,
b = command.numbers[1].__root__,
verbose = config.OPTIONS.euklid.verbose,
);
return Ok(CallResult(action_taken=True, message=result));

View File

@@ -1,34 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.code import *;
from models.generated.commands import *;
from src.core.calls import *;
from src.setup import config;
from src.algorithms.genetic import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'endpoint_genetic',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ENDPOINT
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@run_safely()
def endpoint_genetic(command: CommandGenetic) -> Result[CallResult, CallError]:
result = genetic_algorithm(
individual1 = command.population[0],
individual2 = command.population[1],
verbose = config.OPTIONS.genetic.verbose,
);
return Ok(CallResult(action_taken=True, message=result));

View File

@@ -1,46 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.code import *;
from models.generated.commands import *;
from src.core.calls import *;
from src.setup import config;
from src.algorithms.pollard_rho import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'endpoint_pollard_rho',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ENDPOINT
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@run_safely()
def endpoint_pollard_rho(command: CommandPollard) -> Result[CallResult, CallError]:
match command.growth:
case EnumPollardGrowthRate.linear:
result = pollard_rho_algorithm_linear(
n = command.number,
x_init = command.x_init,
verbose = config.OPTIONS.pollard_rho.verbose,
);
pass;
case EnumPollardGrowthRate.exponential:
result = pollard_rho_algorithm_exponential(
n = command.number,
x_init = command.x_init,
verbose = config.OPTIONS.pollard_rho.verbose,
);
pass;
case _ as growth:
raise Exception(f'No algorithm implemented for \x1b[1m{growth.value}\x1b[0m as growth rate.');
return Ok(CallResult(action_taken=True, message=result));

View File

@@ -1,75 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.code import *;
from models.generated.commands import *;
from src.core.calls import *;
from src.setup import config;
from src.models.random_walk import *;
from src.algorithms.random_walk import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'endpoint_random_walk',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ENDPOINT
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@run_safely()
def endpoint_random_walk(command: CommandRandomWalk) -> Result[CallResult, CallError]:
# Compute landscape (fitness fct + topology) + initial co-ordinates:
one_based = command.one_based;
landscape = Landscape(
values = command.landscape.values,
labels = command.landscape.labels,
metric = command.landscape.neighbourhoods.metric,
one_based = one_based,
);
if isinstance(command.coords_init, list):
coords_init = tuple(command.coords_init);
if one_based:
coords_init = tuple(xx - 1 for xx in coords_init);
assert len(coords_init) == landscape.dim, 'Dimension of initial co-ordinations inconsistent with landscape!';
else:
coords_init = landscape.coords_middle;
match command.algorithm:
case EnumWalkMode.adaptive:
result = adaptive_walk_algorithm(
landscape = landscape,
r = command.landscape.neighbourhoods.radius,
coords_init = coords_init,
optimise = command.optimise,
verbose = config.OPTIONS.random_walk.verbose
);
case EnumWalkMode.gradient:
result = gradient_walk_algorithm(
landscape = landscape,
r = command.landscape.neighbourhoods.radius,
coords_init = coords_init,
optimise = command.optimise,
verbose = config.OPTIONS.random_walk.verbose
);
case EnumWalkMode.metropolis:
result = metropolis_walk_algorithm(
landscape = landscape,
r = command.landscape.neighbourhoods.radius,
coords_init = coords_init,
T = command.temperature_init,
annealing = command.annealing,
optimise = command.optimise,
verbose = config.OPTIONS.random_walk.verbose
);
case _ as alg:
raise Exception(f'No algorithm implemented for {alg.value}.');
return Ok(CallResult(action_taken=True, message=result));

View File

@@ -50,5 +50,5 @@ def endpoint_rucksack(command: CommandRucksack) -> Result[CallResult, CallError]
verbose = config.OPTIONS.rucksack.verbose,
);
case _ as alg:
raise Exception(f'No algorithm implemented for {alg.value}.');
raise Exception(f'No algorithm implemented for {alg.value}.')
return Ok(CallResult(action_taken=True, message=result));

View File

@@ -44,12 +44,4 @@ def interpret_command(command: Command) -> Command:
return CommandHirschberg(**command.dict());
case EnumAlgorithmNames.rucksack:
return CommandRucksack(**command.dict());
case EnumAlgorithmNames.random_walk:
return CommandRandomWalk(**command.dict());
case EnumAlgorithmNames.genetic:
return CommandGenetic(**command.dict());
case EnumAlgorithmNames.euklid:
return CommandEuklid(**command.dict());
case EnumAlgorithmNames.pollard_rho:
return CommandPollard(**command.dict());
raise Exception(f'Command type `{command.name.value}` not recognised!');
raise command;

View File

@@ -1,16 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.models.euklid.logging import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'Step',
];

View File

@@ -1,30 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.types import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'Step',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CLASS Step
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@dataclass
class Step():
a: int = field();
b: int = field();
gcd: int = field();
div: int = field();
rem: int = field();
coeff_a: int = field();
coeff_b: int = field();

View File

@@ -1,16 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.models.pollard_rho.logging import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'Step',
];

View File

@@ -1,26 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.types import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'Step',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CLASS Step
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@dataclass
class Step():
x: int = field();
y: Optional[int] = field(default=None);
d: Optional[int] = field(default=None);

View File

@@ -1,18 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.models.random_walk.landscape import *;
from src.models.random_walk.logging import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'Landscape',
'Step',
];

View File

@@ -1,124 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from __future__ import annotations;
from src.thirdparty.maths import *;
from src.thirdparty.misc import *;
from src.thirdparty.types import *;
from models.generated.commands import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'Landscape',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD fitness function -> Array
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class Landscape():
_fct: np.ndarray;
_labels: list[str];
_metric: EnumLandscapeMetric;
_radius: float;
_one_based: bool;
def __init__(
self,
values: DataTypeLandscapeValues,
labels: List[str],
metric: EnumLandscapeMetric = EnumLandscapeMetric.maximum,
one_based: bool = False,
):
self._fct = convert_to_nparray(values);
assert len(labels) == self.dim, 'A label is required for each axis/dimension!';
self._labels = labels;
self._metric = metric;
self._one_based = one_based;
return;
@property
def shape(self) -> tuple:
return self._fct.shape;
@property
def dim(self) -> int:
return len(self._fct.shape);
@property
def coords_middle(self) -> tuple:
return tuple(math.floor(s/2) for s in self.shape);
@property
def values(self) -> np.ndarray:
return self._fct;
def fitness(self, *x: int) -> float:
return self._fct[x];
def axis_label(self, i: int, x: int) -> str:
if self._one_based:
x = x + 1;
name = self._labels[i];
return f'{name}{x}';
def axis_labels(self, i: int) -> str:
s = self.shape[i];
return [ self.axis_label(i, x) for x in range(s) ];
def label(self, *x: int) -> str:
if self._one_based:
x = tuple(xx + 1 for xx in x);
expr = ','.join([ f'{name}{xx}' for name, xx in zip(self._labels, x)]);
if self.dim > 1:
expr = f'({expr})';
return expr;
def neighbourhood(self, *x: int, r: float, strict: bool = False) -> List[tuple]:
r = int(r);
sides = [
[ xx - j for j in range(1, r+1) if xx - j in range(s) ]
+ ([ xx ] if xx in range(s) else [])
+ [ xx + j for j in range(1, r+1) if xx + j in range(s) ]
for xx, s in zip(x, self.shape)
];
match self._metric:
case EnumLandscapeMetric.maximum:
umg = list(itertools_product(*sides));
case EnumLandscapeMetric.manhattan:
umg = [
(*x[:i], xx, *x[(i+1):])
for i, side in enumerate(sides)
for xx in side
];
case _:
umg = [ x ];
if strict:
umg = [ p for p in umg if p != x ];
return umg;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# AUXILIARY METHODS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def convert_to_array(values: DataTypeLandscapeValues) -> list:
return [
x if isinstance(x, float) else convert_to_array(x)
for x in values.__root__
];
def convert_to_nparray(values: DataTypeLandscapeValues) -> np.ndarray:
try:
list_of_lists = convert_to_array(values);
return np.asarray(list_of_lists, dtype=float);
except:
raise ValueError('Could not convert to a d-dimensional array! Ensure that the dimensions are consistent.');

View File

@@ -1,32 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.types import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'Step',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CLASS Step
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@dataclass
class Step():
coords: tuple = field();
label: str = field();
improved: bool = field(default=False);
chance: bool = field(default=False);
probability: float = field(default=0.);
changed: bool = field(default=False);
stopped: bool = field(default=False);

View File

@@ -7,7 +7,6 @@
from src.models.rucksack.mask import *;
from src.models.rucksack.solution import *;
from src.models.rucksack.logging import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
@@ -18,6 +17,4 @@ __all__ = [
'MaskValue',
'Mask',
'Solution',
'EnumBranchAndBoundMove',
'Step',
];

View File

@@ -1,47 +0,0 @@
#!/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();
solution: Optional[Mask] = field();
move: EnumBranchAndBoundMove = field(default=EnumBranchAndBoundMove.NONE);

View File

@@ -8,12 +8,8 @@
from fractions import Fraction;
import math;
import numpy as np;
from numpy.random import binomial as random_binomial;
random_binary = lambda p: (random_binomial(1, p) == 1);
import pandas as pd;
import random;
from random import uniform;
from random import choice as uniform_random_choice;
from tabulate import tabulate;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -24,11 +20,7 @@ __all__ = [
'Fraction',
'math',
'np',
'random_binomial',
'random_binary',
'pd',
'random',
'uniform',
'uniform_random_choice',
'tabulate',
];

View File

@@ -7,7 +7,6 @@
from datetime import datetime;
from datetime import timedelta;
from itertools import product as itertools_product;
import lorem;
import re;
from textwrap import dedent;
@@ -17,10 +16,9 @@ from textwrap import dedent;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'lorem',
'datetime',
'timedelta',
'itertools_product',
'lorem',
're',
'dedent',
];

View File

@@ -1,22 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from matplotlib import pyplot as mplt;
from matplotlib import animation as mplt_animation;
from matplotlib import colors as mplt_colours;
from matplotlib import patches as mplt_patches;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'mplt',
'mplt_colours',
'mplt_patches',
'mplt_animation',
];

1
notes/.gitignore vendored
View File

@@ -16,7 +16,6 @@
!/notes.tex
!/notes.pdf
!/woche*.pdf
!/*.csv
################################################################
# Git Keep

View File

@@ -1,34 +0,0 @@
;;;i (Kosten);;;;;;;;;;;;;;;;;
j;Objekt[j];;0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17
;;value;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
;;cost;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-
;;;;;;;;;;;;;;;;;;;;
1;A;value[i cost[j]];;;;0;1;2;3;4;5;6;7;8;9;10;11;12;13;14
cost[j];3;… + value[j];;;;4;4;4;8;8;8;12;12;12;16;16;16;20;20;20
value[j];4;besser?;;;;WAHR;WAHR;WAHR;WAHR;WAHR;WAHR;WAHR;WAHR;WAHR;WAHR;WAHR;WAHR;WAHR;WAHR;WAHR
;;best-value;0;0;0;4;4;4;8;8;8;12;12;12;16;16;16;20;20;20
;;best-object;-;-;-;A;A;A;A;A;A;A;A;A;A;A;A;A;A;A
;;;;;;;;;;;;;;;;;;;;
2;B;value[i cost[j]];;;;;0;1;2;3;4;5;6;7;8;9;10;11;12;13
cost[j];4;… + value[j];;;;;5;5;5;9;10;10;13;14;15;17;18;19;21;22
value[j];5;besser?;;;;;WAHR;WAHR;;WAHR;WAHR;;WAHR;WAHR;;WAHR;WAHR;;WAHR;WAHR
;;value;0;0;0;4;5;5;8;9;10;12;13;14;16;17;18;20;21;22
;;cost;-;-;-;A;B;B;A;B;B;A;B;B;A;B;B;A;B;B
;;;;;;;;;;;;;;;;;;;;
3;C;value[i cost[j]];;;;;;;;0;1;2;3;4;5;6;7;8;9;10
cost[j];7;… + value[j];;;;;;;;10;10;10;14;15;15;18;20;20;22;24
value[j];10;besser?;;;;;;;;WAHR;;;WAHR;WAHR;;WAHR;WAHR;;WAHR;WAHR
;;value;0;0;0;4;5;5;8;10;10;12;14;15;16;18;20;20;22;24
;;cost;-;-;-;A;B;B;A;C;B;A;C;C;A;C;C;A;C;C
;;;;;;;;;;;;;;;;;;;;
4;D;value[i cost[j]];;;;;;;;;0;1;2;3;4;5;6;7;8;9
cost[j];8;… + value[j];;;;;;;;;11;11;11;15;16;16;19;21;22;23
value[j];11;besser?;;;;;;;;;WAHR;;;;;;;WAHR;;
;;value;0;0;0;4;5;5;8;10;11;12;14;15;16;18;20;21;22;24
;;cost;-;-;-;A;B;B;A;C;D;A;C;C;A;C;C;D;C;C
;;;;;;;;;;;;;;;;;;;;
5;E;value[i cost[j]];;;;;;;;;;0;1;2;3;4;5;6;7;8
cost[j];9;… + value[j];;;;;;;;;;13;13;13;17;18;18;21;23;24
value[j];13;besser?;;;;;;;;;;WAHR;;;WAHR;;;;WAHR;
;;value;0;0;0;4;5;5;8;10;11;13;14;15;17;18;20;21;23;24
;;cost;-;-;-;A;B;B;A;C;D;E;C;C;E;C;C;D;E;C
1 i (Kosten)
2 j Objekt[j] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
3 value 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
4 cost - - - - - - - - - - - - - - - - - -
5
6 1 A value[i – cost[j]] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
7 cost[j] 3 … + value[j] 4 4 4 8 8 8 12 12 12 16 16 16 20 20 20
8 value[j] 4 besser? WAHR WAHR WAHR WAHR WAHR WAHR WAHR WAHR WAHR WAHR WAHR WAHR WAHR WAHR WAHR
9 best-value 0 0 0 4 4 4 8 8 8 12 12 12 16 16 16 20 20 20
10 best-object - - - A A A A A A A A A A A A A A A
11
12 2 B value[i – cost[j]] 0 1 2 3 4 5 6 7 8 9 10 11 12 13
13 cost[j] 4 … + value[j] 5 5 5 9 10 10 13 14 15 17 18 19 21 22
14 value[j] 5 besser? WAHR WAHR WAHR WAHR WAHR WAHR WAHR WAHR WAHR WAHR
15 value 0 0 0 4 5 5 8 9 10 12 13 14 16 17 18 20 21 22
16 cost - - - A B B A B B A B B A B B A B B
17
18 3 C value[i – cost[j]] 0 1 2 3 4 5 6 7 8 9 10
19 cost[j] 7 … + value[j] 10 10 10 14 15 15 18 20 20 22 24
20 value[j] 10 besser? WAHR WAHR WAHR WAHR WAHR WAHR WAHR
21 value 0 0 0 4 5 5 8 10 10 12 14 15 16 18 20 20 22 24
22 cost - - - A B B A C B A C C A C C A C C
23
24 4 D value[i – cost[j]] 0 1 2 3 4 5 6 7 8 9
25 cost[j] 8 … + value[j] 11 11 11 15 16 16 19 21 22 23
26 value[j] 11 besser? WAHR WAHR
27 value 0 0 0 4 5 5 8 10 11 12 14 15 16 18 20 21 22 24
28 cost - - - A B B A C D A C C A C C D C C
29
30 5 E value[i – cost[j]] 0 1 2 3 4 5 6 7 8
31 cost[j] 9 … + value[j] 13 13 13 17 18 18 21 23 24
32 value[j] 13 besser? WAHR WAHR WAHR
33 value 0 0 0 4 5 5 8 10 11 13 14 15 17 18 20 21 23 24
34 cost - - - A B B A C D E C C E C C D E C

View File

@@ -12,10 +12,9 @@ Inhaltsverzeichnis
- [Vorlesungswoche 7](./woche4.md)
- [Vorlesungswoche 8](./woche4.md)
- [Vorlesungswoche 9](./woche4.md)
-->
- [Vorlesungswoche 10](./woche10.md)
- [Vorlesungswoche 11](./woche11.md)
- [Vorlesungswoche 12](./woche12.md)
- [Vorlesungswoche 13](./woche13.md)
- [Vorlesungswoche 14](./woche14.md)
- [Vorlesungswoche 15](./woche15.md)
-->

View File

@@ -1,14 +0,0 @@
# 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.

View File

@@ -1,20 +0,0 @@
# Vorlesungswoche 11 (13.19. Juni 2022) #
## Agenda ##
- [x] 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.

View File

@@ -1,6 +0,0 @@
# Vorlesungswoche 12 (20.26. Juni 2022) #
## Agenda ##
- [x] Adaptive, Gradient, Metropolis Walks
- [x] Motivation und Erklärung der Bestandteile

View File

@@ -1,29 +0,0 @@
# Vorlesungswoche 13 (27. Juni 3. Juli 2022) #
## Agenda ##
- [x] ein wenig Algebra:
- [x] modulare Arithmetik
- [x] zyklische (Unter)gruppen; Anwendung `ф(n) := ord((/n)ˣ)`.
- [x] der kleine Fermat: `a^ф(n) ≡ 1 mod n`.
- [x] Euklid:
- [x] Rekursives Ausrechnen von `d := ggT(a,b)`.
- [x] Extrahieren der Koeffizienten für die Gleichung `d = xa + yb`.
- [x] Anwendung auf Sonderfall `d = 1` für Inversion modulo `n`.
- [x] Pollard-Rho
- [x] Was liefert der Algorithmus?
- [x] Was garantiert das?
- Referenzen:
- Algorithmus im Kurs (exp-Abstände), siehe:
</br>
<http://staff.ustc.edu.cn/~csli/graduate/algorithms/book6/chap33.htm>
- Andere Variante (lineare Abstände), siehe:
</br>
<https://link.springer.com/article/10.1007/BF01933667>
und
</br>
<https://www.cambridge.org/core/journals/mathematical-proceedings-of-the-cambridge-philosophical-society/article/theorems-on-factorization-and-primality-testing/6762E84DBD34AEF13E6B1D1A8334A989>
### Nächste Woche/n ###
- Wiederholung zur Klausurvorbereitung

View File

@@ -1,15 +0,0 @@
# Vorlesungswoche 14 (4.10. Juli 2022) #
## Agenda ##
- Wiederholung
- Netze/Flüsse: Restgraphen, Push, Relabel.
- Gomory-Hu
- Branch & Bound: Rucksack, TSP.
- Matrixmultkiplikation
- Matroiden, Greedy
- Genetischer Algorithmus
### Nächste Woche/n ###
- Wiederholung zur Klausurvorbereitung

View File

@@ -1,83 +0,0 @@
# Vorlesungswoche 15 (11.17. Juli 2022) #
## Agenda ##
- Wiederholung
- Alle genetischen Algorithmen im Kurs, inkl. letzter VL, Bsp. aus freiwilligen Übungsblättern.
- Branch & Bound: Rucksack, TSP.
- Dynamisches Programmieren.
- Matroiden: Versprecher letzte Woche
</br>
```
Ich sagte:
|A| < |B| ==> es gibt x ∈ E s.d. A u {x} ∈ M
Das ist zwar nicht falsch, aber nicht die ganze Aussage.
Es hätte so lauten sollen:
|A| < |B| ==> es gibt x ∈ B\A s.d. A u {x} ∈ M
```
- Pollard-Rho: Die Rolle der Primzahlen und die Funktion `φ(n)`.
### Anmerkung ###
Wir haben mal kurz über Editoren für Notizen geredet. Einerseits gibt es Word (iiiiii) und **LaTeX** (schönes Rendering, nicht so schöne Syntax).
Dann gibt es immer plaintext. Aber eine Stufe besser ist **Markdown**. Markdown hat die folgenden Vorteile:
- Nur plaintext Dateien (d.h. keine riesige XML-Objekte im Hintergrund).
- Sehr simple Syntax (bspw. `**fett**`, `_kursiv_`, usw.).
- **Keine Kompilation** nötig—nur ein guter Renderer.
- Komplexe Textformats mit sehr intuitiver Syntax möglich:
- Überschriften
- Listen
- Tabellen. Z. B. man gibt
```
| Objekt | Kosten | Wert |
| :----: | -----: | ---: |
| Apfel | 1,30€ | 301 |
| Orange | 2€ | 440 |
```
ein und bekommt
| Objekt | Kosten | Wert |
| :----: | -----: | ---: |
| Apfel | 1,30€ | 301 |
| Orange | 2€ | 440 |
raus.
- Code Blocks (in diversen Sprachen). Z. B. man gibt
```
'''java
public class HelloWorld {
public static void main (String[] args) {
System.out.println("Hello World!");
}
}
'''
```
(mit Backticks statt `'''`) und bekommt
```java
public class HelloWorld {
public static void main (String[] args) {
System.out.println("Hello World!");
}
}
```
raus.
- URIs
- interne Verlinkungen!
- sogar Mathe-Formeln mit (simplem) LaTeX-Code
Man braucht lediglich einen Renderer für Vorschau-Zwecken.
Hier ein paar Empfehlungen:
- VSCode + passende markdown Extensions (alles gratis)
- Typora (nicht gratis, aber für mich hat es sich gelohnt). Siehe bspw. <https://support.typora.io/Math>. Der Editor rendert sogar LaTeX-Formeln, und hat einen WYSIWYG-Modus.
- online Editoren wie
- https://cryptpad.linxx.net -> Markdown-Folien
- https://dillinger.io
- In Git-Repos (wie dieser hier!) werden **md**-Dateien automatisch gerendert!
### Nächste Woche/n ###
- Keine Übung, sondern die Klausur! Viel Erfolg!