Compare commits
71 Commits
6920944cdf
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 32ef695c87 | |||
| 1ee5e7415b | |||
| b1a467b2e4 | |||
| 9f807d2a21 | |||
| de4bd64e77 | |||
| 0c61a29375 | |||
| bd355098cc | |||
| 278e3713c8 | |||
| de238fede9 | |||
| 3c965eda7b | |||
| 56c22a568c | |||
| c1f346b80e | |||
| 2d96666bec | |||
| 7d07f4317e | |||
| 2bd07544f3 | |||
| 7b456d177e | |||
| 1e934dc3ef | |||
| a7c7179edb | |||
| 5c43419890 | |||
| c2cb11a141 | |||
| 01ef8c5758 | |||
| 4001551c9c | |||
| 17711327ef | |||
| 3d05f7ae1d | |||
| aaa0b7a124 | |||
| 48c47f61b7 | |||
| ad354b3b64 | |||
| 1b73ec263b | |||
| 15fe1b04d4 | |||
| f6401f0dfc | |||
| f1200dfc25 | |||
| f877ffc9e7 | |||
| ac119a0b29 | |||
| 8cba2fdf13 | |||
| 3032840a1d | |||
| 48fb136436 | |||
| efacd73e51 | |||
| ba394993e0 | |||
| 059f9d8742 | |||
| 21f61d71c3 | |||
| f3db0660f2 | |||
| 77b2f40215 | |||
| 4cc4410c19 | |||
| 3791220cee | |||
| c6149c230a | |||
| 3b8f80cff9 | |||
| e3c3bbec37 | |||
| f45781be71 | |||
| 56a93bbac9 | |||
| a93b59539f | |||
| 304b8315f3 | |||
| 828000a2ac | |||
| 026cd6addf | |||
| ea36c82728 | |||
| 7cfaf253b3 | |||
| d79b10e190 | |||
| 8e59bc941f | |||
| 2a5986d490 | |||
| 036c87f829 | |||
| 4fa02a4962 | |||
| 38b477e0ad | |||
| 8acb2157ab | |||
| d454f71bfa | |||
| 17ea04cfee | |||
| 301a9c87be | |||
| d8f6c802b2 | |||
| 99a194dfc8 | |||
| 670fd1b73e | |||
| c0bc69450c | |||
| 3e8b3c157d | |||
| a83315e3e6 |
@@ -21,6 +21,8 @@ Siehe Moodle!
|
||||
|
||||
## Code ##
|
||||
|
||||
Im Unterordner [`code/rust`](./code/rust)
|
||||
(und evtl. [`code/python`](./code/python))
|
||||
werden ggf. Implementierungen von den Algorithmen zu finden sein.
|
||||
In den Unterordnern
|
||||
[`code/rust`](./code/rust)
|
||||
und
|
||||
[`code/python`](./code/python) (etwas ausführlicher)
|
||||
sind Implementierungen von einigen Algorithmen bzw. Datenstrukturen zu finden sein.
|
||||
|
||||
@@ -12,7 +12,6 @@ omit =
|
||||
**/__init__.py
|
||||
# ignore main.py
|
||||
main.py
|
||||
# TODO: increase code-coverage:
|
||||
precision = 0
|
||||
exclude_lines =
|
||||
pragma: no cover
|
||||
|
||||
5
code/python/.gitignore
vendored
5
code/python/.gitignore
vendored
@@ -26,6 +26,11 @@
|
||||
!/models/*-schema.yaml
|
||||
!/models/README.md
|
||||
|
||||
!/docs
|
||||
!/docs/*/
|
||||
!/docs/*/Models/
|
||||
!/docs/**/*.md
|
||||
|
||||
!/tests
|
||||
!/tests/**/
|
||||
!/tests/**/*.py
|
||||
|
||||
@@ -10,7 +10,7 @@ die Methoden mit Daten ausprobieren.
|
||||
## Voraussetzungen ##
|
||||
|
||||
1. Der Python-Compiler **`^3.10.*`** wird benötigt.
|
||||
2. Es ist auch empfehlenswert, **`justfile`** zu installieren (siehe <https://github.com/casey/just#installation>).
|
||||
2. Das **`justfile`**-Tool wird benötigt (siehe <https://github.com/casey/just#installation>).
|
||||
|
||||
## Build -> Test -> Run ##
|
||||
|
||||
@@ -18,29 +18,18 @@ In einem IDE in dem Repo zu diesem Ordner navigieren.
|
||||
</br>
|
||||
Eine bash-Konsole aufmachen und folgende Befehle ausführen:
|
||||
|
||||
Wer das **justfile**-Tool hat:
|
||||
```bash
|
||||
# Zeige alle Befehle:
|
||||
just
|
||||
# Zur Installation der Requirements (nur nach Änderungen):
|
||||
just build;
|
||||
# Zur Installation der Requirements (nur und immer nach Änderungen nötig):
|
||||
just build
|
||||
# Zur Ausführung der unit tests:
|
||||
just tests;
|
||||
just tests
|
||||
# Zur Ausführung des Programms
|
||||
just run;
|
||||
just run
|
||||
# Zur Bereinigung aller Artefakte
|
||||
just clean;
|
||||
just clean
|
||||
```
|
||||
Wer das justfile-Tool hat:
|
||||
```bash
|
||||
# Zur Installation der Requirements (nur nach Änderungen):
|
||||
python3 -m pip install -r requirements.txt;
|
||||
# Zur Ausführung der unit tests:
|
||||
python3 -m pytest tests --cache-clear --verbose -k test_;
|
||||
# Zur Ausführung des Programms:
|
||||
python3 main.py
|
||||
```
|
||||
Auf Windows verwendet man `py -3` od. `py -310` statt `python3`.
|
||||
|
||||
Man kann auch mit einem guten Editor/IDE die Tests einzeln ausführen.
|
||||
|
||||
|
||||
@@ -1,17 +1,59 @@
|
||||
## Beispiel für Seminarwoche 9 (Blatt 8)
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# NOTE:
|
||||
# Diese Datei enthält Angaben für konkrete Fälle
|
||||
# für die zu demonstrierenden Algorithmen.
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Beispiele für Seminarwoche 2 (Blatt 1)
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- name: TARJAN
|
||||
nodes: [a,b,c]
|
||||
edges: [[a, c], [c, a], [b, c]]
|
||||
- name: TARJAN
|
||||
nodes: [1, 2, 3, 4, 5, 6, 7, 8]
|
||||
edges: [
|
||||
[1, 2],
|
||||
[1, 3],
|
||||
[2, 4],
|
||||
[2, 5],
|
||||
[3, 5],
|
||||
[3, 6],
|
||||
[3, 8],
|
||||
[4, 5],
|
||||
[4, 7],
|
||||
[5, 1],
|
||||
[5, 8],
|
||||
[6, 8],
|
||||
[7, 8],
|
||||
[8, 6],
|
||||
]
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Beispiele für Seminarwoche 9 (Blatt 8)
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- name: TSP
|
||||
dist: [
|
||||
dist: &ref_dist [
|
||||
[0, 7, 4, 3],
|
||||
[7, 0, 5, 6],
|
||||
[2, 5, 0, 5],
|
||||
[2, 7, 4, 0],
|
||||
]
|
||||
optimise: MIN
|
||||
- name: TSP
|
||||
dist: *ref_dist
|
||||
optimise: MAX
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Beispiele für Seminarwoche 10 (Blatt 9)
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- name: HIRSCHBERG
|
||||
word1: 'happily ever after'
|
||||
word2: 'apples'
|
||||
once: true
|
||||
once: false
|
||||
- name: HIRSCHBERG
|
||||
word1: 'happily'
|
||||
word2: 'applses'
|
||||
@@ -28,3 +70,131 @@
|
||||
word1: 'ANSTRENGEN'
|
||||
word2: 'ANSPANNEN'
|
||||
once: false
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Beispiele für Seminarwoche 11 (Blatt 10)
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- name: RUCKSACK
|
||||
algorithm: GREEDY
|
||||
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: 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
|
||||
algorithm: BRANCH-AND-BOUND
|
||||
max-cost: 90
|
||||
items: [
|
||||
'Sonnenblumenkerne',
|
||||
'Buchweizen',
|
||||
'Rote Beete',
|
||||
'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
|
||||
|
||||
@@ -6,8 +6,13 @@ info:
|
||||
ADS2 an der Universität Leipzig (Sommersemester 2022)
|
||||
implementiert.
|
||||
options:
|
||||
# log-level: DEBUG
|
||||
log-level: INFO
|
||||
verbose: &ref_verbose true
|
||||
tarjan:
|
||||
verbose: *ref_verbose
|
||||
tsp:
|
||||
verbose: true
|
||||
verbose: *ref_verbose
|
||||
hirschberg:
|
||||
# standardwerte sind (1, 1) und (2, 1):
|
||||
penality-gap: 1
|
||||
@@ -17,9 +22,25 @@ options:
|
||||
diagonal: 0
|
||||
horizontal: 1
|
||||
vertical: 2
|
||||
# verbose: []
|
||||
verbose:
|
||||
- COSTS
|
||||
- MOVES
|
||||
show:
|
||||
# - ATOMS
|
||||
- TREE
|
||||
show: []
|
||||
# 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
|
||||
|
||||
2
code/python/dist/VERSION
vendored
2
code/python/dist/VERSION
vendored
@@ -1 +1 @@
|
||||
0.1.0
|
||||
0.3.1
|
||||
|
||||
9
code/python/docs/commands/Models/Command.md
Normal file
9
code/python/docs/commands/Models/Command.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Command
|
||||
## Properties
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**name** | [**EnumAlgorithmNames**](EnumAlgorithmNames.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)
|
||||
|
||||
10
code/python/docs/commands/Models/CommandEuklid.md
Normal file
10
code/python/docs/commands/Models/CommandEuklid.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# 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)
|
||||
|
||||
10
code/python/docs/commands/Models/CommandGenetic.md
Normal file
10
code/python/docs/commands/Models/CommandGenetic.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# 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)
|
||||
|
||||
12
code/python/docs/commands/Models/CommandHirschberg.md
Normal file
12
code/python/docs/commands/Models/CommandHirschberg.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# CommandHirschberg
|
||||
## Properties
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**name** | [**EnumAlgorithmNames**](EnumAlgorithmNames.md) | | [default to null]
|
||||
**word1** | [**String**](string.md) | Word that gets placed vertically in algorithm. | [default to null]
|
||||
**word2** | [**String**](string.md) | Word that gets placed horizontally in algorithm | [default to null]
|
||||
**once** | [**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)
|
||||
|
||||
12
code/python/docs/commands/Models/CommandPollard.md
Normal file
12
code/python/docs/commands/Models/CommandPollard.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# 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)
|
||||
|
||||
16
code/python/docs/commands/Models/CommandRandomWalk.md
Normal file
16
code/python/docs/commands/Models/CommandRandomWalk.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# 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)
|
||||
|
||||
15
code/python/docs/commands/Models/CommandRucksack.md
Normal file
15
code/python/docs/commands/Models/CommandRucksack.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# CommandRucksack
|
||||
## Properties
|
||||
|
||||
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]
|
||||
**costs** | [**List**](number.md) | Array of cost for each item (e.g. volume, weight, price, time, etc.). | [default to null]
|
||||
**values** | [**List**](number.md) | Value extracted from each item (e.g. energy, profit, etc.). | [default to null]
|
||||
**items** | [**List**](string.md) | Optional names of the items (if empty, defaults to 1-based indexes). | [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)
|
||||
|
||||
11
code/python/docs/commands/Models/CommandTarjan.md
Normal file
11
code/python/docs/commands/Models/CommandTarjan.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# CommandTarjan
|
||||
## Properties
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**name** | [**EnumAlgorithmNames**](EnumAlgorithmNames.md) | | [default to null]
|
||||
**nodes** | [**List**](anyOf<integer,number,string>.md) | | [default to null]
|
||||
**edges** | [**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)
|
||||
|
||||
11
code/python/docs/commands/Models/CommandTsp.md
Normal file
11
code/python/docs/commands/Models/CommandTsp.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# CommandTsp
|
||||
## Properties
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**name** | [**EnumAlgorithmNames**](EnumAlgorithmNames.md) | | [default to null]
|
||||
**dist** | [**List**](array.md) | | [default to null]
|
||||
**optimise** | [**EnumOptimiseMode**](EnumOptimiseMode.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)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# 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)
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# 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)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# 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)
|
||||
|
||||
8
code/python/docs/commands/Models/EnumAlgorithmNames.md
Normal file
8
code/python/docs/commands/Models/EnumAlgorithmNames.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# EnumAlgorithmNames
|
||||
## 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)
|
||||
|
||||
8
code/python/docs/commands/Models/EnumLandscapeMetric.md
Normal file
8
code/python/docs/commands/Models/EnumLandscapeMetric.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# 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)
|
||||
|
||||
8
code/python/docs/commands/Models/EnumOptimiseMode.md
Normal file
8
code/python/docs/commands/Models/EnumOptimiseMode.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# EnumOptimiseMode
|
||||
## 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)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# 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)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# EnumRucksackAlgorithm
|
||||
## 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)
|
||||
|
||||
8
code/python/docs/commands/Models/EnumWalkMode.md
Normal file
8
code/python/docs/commands/Models/EnumWalkMode.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# 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)
|
||||
|
||||
38
code/python/docs/commands/README.md
Normal file
38
code/python/docs/commands/README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Documentation for Schemata for command instructions
|
||||
|
||||
<a name="documentation-for-api-endpoints"></a>
|
||||
## Documentation for API Endpoints
|
||||
|
||||
All URIs are relative to *http://.*
|
||||
|
||||
Class | Method | HTTP request | Description
|
||||
------------ | ------------- | ------------- | -------------
|
||||
|
||||
|
||||
<a name="documentation-for-models"></a>
|
||||
## 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>
|
||||
## Documentation for Authorization
|
||||
|
||||
All endpoints do not require authorization.
|
||||
18
code/python/docs/config/Models/AppOptions.md
Normal file
18
code/python/docs/config/Models/AppOptions.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# AppOptions
|
||||
## Properties
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**logMinuslevel** | [**EnumLogLevel**](EnumLogLevel.md) | | [default to null]
|
||||
**verbose** | [**Boolean**](boolean.md) | Global setting for verbosity. | [optional] [default to false]
|
||||
**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]
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
13
code/python/docs/config/Models/AppOptionsHirschberg.md
Normal file
13
code/python/docs/config/Models/AppOptionsHirschberg.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# AppOptionsHirschberg
|
||||
## Properties
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**penalityMinusmismatch** | [**BigDecimal**](number.md) | | [default to 1]
|
||||
**penalityMinusgap** | [**BigDecimal**](number.md) | | [default to 1]
|
||||
**moveMinuspriorities** | [**AppOptions_hirschberg_move_priorities**](AppOptions_hirschberg_move_priorities.md) | | [default to null]
|
||||
**verbose** | [**List**](EnumHirschbergVerbosity.md) | | [optional] [default to []]
|
||||
**show** | [**List**](EnumHirschbergShow.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)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# AppOptionsHirschbergMovePriorities
|
||||
## Properties
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**diagonal** | [**Integer**](integer.md) | | [optional] [default to 0]
|
||||
**horizontal** | [**Integer**](integer.md) | | [optional] [default to 1]
|
||||
**vertical** | [**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)
|
||||
|
||||
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)
|
||||
|
||||
9
code/python/docs/config/Models/AppOptionsTarjan.md
Normal file
9
code/python/docs/config/Models/AppOptionsTarjan.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# AppOptionsTarjan
|
||||
## Properties
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**verbose** | [**Boolean**](boolean.md) | | [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)
|
||||
|
||||
10
code/python/docs/config/Models/Config.md
Normal file
10
code/python/docs/config/Models/Config.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Config
|
||||
## Properties
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**info** | [**Info**](Info.md) | | [default to null]
|
||||
**options** | [**AppOptions**](AppOptions.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)
|
||||
|
||||
8
code/python/docs/config/Models/EnumHirschbergShow.md
Normal file
8
code/python/docs/config/Models/EnumHirschbergShow.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# EnumHirschbergShow
|
||||
## 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)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# EnumHirschbergVerbosity
|
||||
## 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)
|
||||
|
||||
8
code/python/docs/config/Models/EnumLogLevel.md
Normal file
8
code/python/docs/config/Models/EnumLogLevel.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# EnumLogLevel
|
||||
## 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)
|
||||
|
||||
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)
|
||||
|
||||
11
code/python/docs/config/Models/Info.md
Normal file
11
code/python/docs/config/Models/Info.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Info
|
||||
## Properties
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**title** | [**String**](string.md) | | [default to null]
|
||||
**description** | [**String**](string.md) | | [default to null]
|
||||
**author** | [**String**](string.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)
|
||||
|
||||
31
code/python/docs/config/README.md
Normal file
31
code/python/docs/config/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Documentation for Schemata for config models
|
||||
|
||||
<a name="documentation-for-api-endpoints"></a>
|
||||
## Documentation for API Endpoints
|
||||
|
||||
All URIs are relative to *http://.*
|
||||
|
||||
Class | Method | HTTP request | Description
|
||||
------------ | ------------- | ------------- | -------------
|
||||
|
||||
|
||||
<a name="documentation-for-models"></a>
|
||||
## Documentation for Models
|
||||
|
||||
- [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)
|
||||
|
||||
|
||||
<a name="documentation-for-authorization"></a>
|
||||
## Documentation for Authorization
|
||||
|
||||
All endpoints do not require authorization.
|
||||
@@ -1,4 +1,4 @@
|
||||
set shell := [ "bash", "-uc" ]
|
||||
# set shell := [ "bash", "-uc" ]
|
||||
_default:
|
||||
@- just --unsorted --choose
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -12,6 +12,7 @@ _default:
|
||||
|
||||
PYTHON := if os_family() == "windows" { "py -3" } else { "python3" }
|
||||
GEN_MODELS := "datamodel-codegen"
|
||||
GEN_MODELS_DOCUMENTATION := "openapi-generator"
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Macros
|
||||
@@ -56,6 +57,12 @@ _generate-models path name:
|
||||
--input {{path}}/{{name}}-schema.yaml \
|
||||
--output {{path}}/generated/{{name}}.py
|
||||
|
||||
_generate-models-documentation path_schema path_docs name:
|
||||
@- {{GEN_MODELS_DOCUMENTATION}} generate \
|
||||
--input-spec {{path_schema}}/{{name}}-schema.yaml \
|
||||
--generator-name markdown \
|
||||
--output "{{path_docs}}/{{name}}"
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# TARGETS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -64,16 +71,30 @@ _generate-models path name:
|
||||
# TARGETS: build
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
build: _build-requirements _build-skip-requirements
|
||||
_build-skip-requirements: build-models
|
||||
_build-requirements:
|
||||
build:
|
||||
@just build-requirements
|
||||
@just _check-system-requirements
|
||||
@just build-models
|
||||
build-requirements:
|
||||
@{{PYTHON}} -m pip install --disable-pip-version-check -r requirements.txt
|
||||
build-models: _check-system-requirements _build-models-nochecks
|
||||
_build-models-nochecks:
|
||||
build-models:
|
||||
@echo "Generate data models from schemata."
|
||||
@just _delete-if-folder-exists "models/generated"
|
||||
@just _create-folder-if-not-exists "models/generated"
|
||||
@- just _generate-models "models" "config"
|
||||
@- just _generate-models "models" "commands"
|
||||
build-documentation:
|
||||
@echo "Generate documentations data models from schemata."
|
||||
@just _delete-if-folder-exists "docs"
|
||||
@just _create-folder-if-not-exists "docs"
|
||||
@- just _generate-models-documentation "models" "docs" "config"
|
||||
@- just _generate-models-documentation "models" "docs" "commands"
|
||||
@- just _clean-all-files ".openapi-generator*"
|
||||
@- just _clean-all-folders ".openapi-generator*"
|
||||
|
||||
dist:
|
||||
@just build
|
||||
@just build-documentation
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# TARGETS: run
|
||||
@@ -172,3 +193,7 @@ _check-system-requirements:
|
||||
echo "Command '{{GEN_MODELS}}' did not work. Ensure that the installation of 'datamodel-code-generator' worked and that system paths are set." \
|
||||
exit 1; \
|
||||
fi
|
||||
@if ! ( {{GEN_MODELS_DOCUMENTATION}} --help >> /dev/null 2> /dev/null ); then \
|
||||
echo "Command '{{GEN_MODELS_DOCUMENTATION}}' did not work. Ensure that the installation of 'datamodel-code-generator' worked and that system paths are set." \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
@@ -11,43 +11,31 @@ import sys
|
||||
os.chdir(os.path.join(os.path.dirname(__file__)));
|
||||
sys.path.insert(0, os.getcwd());
|
||||
|
||||
from src.thirdparty.maths import *;
|
||||
|
||||
from models.generated.config import *;
|
||||
from models.generated.commands import *;
|
||||
from src.core.log import *;
|
||||
from src.setup.config import *;
|
||||
from src.models.graphs.graph import *;
|
||||
from src.algorithms.tarjan.algorithms import *;
|
||||
from src.algorithms.tsp import *;
|
||||
from src.algorithms.hirschberg import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL CONSTANTS/VARIABLES
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#
|
||||
from src.models.config import *;
|
||||
from src.core import log;
|
||||
from src.setup import config;
|
||||
from src import api;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# MAIN METHOD
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def enter():
|
||||
for command in COMMANDS:
|
||||
if isinstance(command, CommandTsp):
|
||||
tsp_algorithm(
|
||||
dist = np.asarray(command.dist, dtype=float),
|
||||
optimise = min if command.optimise == EnumTSPOptimise.min else max,
|
||||
verbose = OPTIONS.tsp.verbose,
|
||||
);
|
||||
elif isinstance(command, CommandHirschberg):
|
||||
hirschberg_algorithm(
|
||||
X = command.word1,
|
||||
Y = command.word2,
|
||||
once = command.once,
|
||||
verb = OPTIONS.hirschberg.verbose,
|
||||
show = OPTIONS.hirschberg.show,
|
||||
);
|
||||
def enter(*args: str):
|
||||
# set logging level:
|
||||
log.configure_logging(config.LOG_LEVEL);
|
||||
|
||||
# process inputs:
|
||||
if len(args) == 0:
|
||||
# Führe befehle in Assets aus:
|
||||
for command in config.COMMANDS:
|
||||
result = api.run_command(command);
|
||||
# ignored if log-level >> DEBUG
|
||||
log.log_result(result, debug=True);
|
||||
else:
|
||||
# Führe CLI-Befehl aus:
|
||||
result = api.run_command_from_json(args[0]);
|
||||
# ignored if log-level >> DEBUG
|
||||
log.log_result(result, debug=True);
|
||||
return;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -55,4 +43,7 @@ def enter():
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
if __name__ == '__main__':
|
||||
enter();
|
||||
sys.tracebacklimit = 0;
|
||||
# NOTE: necessary for Windows, to ensure that console output is rendered correctly:
|
||||
os.system('');
|
||||
enter(*sys.argv[1:]);
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
version: 0.1.0
|
||||
version: 0.3.1
|
||||
title: Schemata for command instructions
|
||||
servers: []
|
||||
servers:
|
||||
- url: "."
|
||||
paths: {}
|
||||
components:
|
||||
schemas:
|
||||
@@ -22,14 +23,15 @@ components:
|
||||
Command:
|
||||
description: |-
|
||||
Instructions for command to call
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
properties: &ref_command_properties
|
||||
properties:
|
||||
name:
|
||||
$ref: '#/components/schemas/EnumAlgorithmNames'
|
||||
additionalProperties: true
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Command - Algorithm: Tarjan
|
||||
# Algorithm: Tarjan
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
CommandTarjan:
|
||||
description: |-
|
||||
@@ -37,12 +39,31 @@ components:
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
- nodes
|
||||
- edges
|
||||
properties:
|
||||
<<: *ref_command_properties
|
||||
# required:
|
||||
# properties:
|
||||
name:
|
||||
$ref: '#/components/schemas/EnumAlgorithmNames'
|
||||
nodes:
|
||||
type: array
|
||||
items:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: number
|
||||
- type: string
|
||||
edges:
|
||||
type: array
|
||||
items:
|
||||
type: array
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
items:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: number
|
||||
- type: string
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Command - Algorithm: TSP
|
||||
# Algorithm: TSP
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
CommandTsp:
|
||||
description: |-
|
||||
@@ -53,7 +74,8 @@ components:
|
||||
- optimise
|
||||
- dist
|
||||
properties:
|
||||
<<: *ref_command_properties
|
||||
name:
|
||||
$ref: '#/components/schemas/EnumAlgorithmNames'
|
||||
dist:
|
||||
type: array
|
||||
items:
|
||||
@@ -61,9 +83,9 @@ components:
|
||||
items:
|
||||
type: number
|
||||
optimise:
|
||||
$ref: '#/components/schemas/EnumTSPOptimise'
|
||||
$ref: '#/components/schemas/EnumOptimiseMode'
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Command - Algorithm: Hirschberg
|
||||
# Algorithm: Hirschberg
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
CommandHirschberg:
|
||||
description: |-
|
||||
@@ -74,7 +96,8 @@ components:
|
||||
- word1
|
||||
- word2
|
||||
properties:
|
||||
<<: *ref_command_properties
|
||||
name:
|
||||
$ref: '#/components/schemas/EnumAlgorithmNames'
|
||||
word1:
|
||||
description: Word that gets placed vertically in algorithm.
|
||||
type: string
|
||||
@@ -84,6 +107,192 @@ components:
|
||||
once:
|
||||
type: boolean
|
||||
default: false
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Algorithm: Rucksack Branch & Bound
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
CommandRucksack:
|
||||
description: |-
|
||||
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:
|
||||
type: boolean
|
||||
default: false
|
||||
max-cost:
|
||||
description: Upper bound for total cost of rucksack.
|
||||
type: number
|
||||
minimum: 0
|
||||
costs:
|
||||
description: Array of cost for each item (e.g. volume, weight, price, time, etc.).
|
||||
type: array
|
||||
items:
|
||||
type: number
|
||||
exclusiveMinimum: 0
|
||||
values:
|
||||
description: Value extracted from each item (e.g. energy, profit, etc.).
|
||||
type: array
|
||||
items:
|
||||
type: number
|
||||
items:
|
||||
description: Optional names of the items (if empty, defaults to 1-based indexes).
|
||||
type: array
|
||||
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
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -95,13 +304,69 @@ components:
|
||||
- TARJAN
|
||||
- TSP
|
||||
- HIRSCHBERG
|
||||
- RUCKSACK
|
||||
- RANDOM-WALK
|
||||
- GENETIC
|
||||
- EUKLID
|
||||
- POLLARD-RHO
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Enum TSP - Optimise Mode
|
||||
# Enum Optimise Mode
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
EnumTSPOptimise:
|
||||
EnumOptimiseMode:
|
||||
description: |-
|
||||
Enumeration of optimisation options for TSP
|
||||
Enumeration of optimisation modi.
|
||||
type: string
|
||||
enum:
|
||||
- MIN
|
||||
- MAX
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Enum Rucksack mode for algorithm
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
EnumRucksackAlgorithm:
|
||||
description: |-
|
||||
Enumeration of mode for Rucksack problem
|
||||
type: string
|
||||
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
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
version: 0.1.0
|
||||
version: 0.3.1
|
||||
title: Schemata for config models
|
||||
servers: []
|
||||
servers:
|
||||
- url: "."
|
||||
paths: {}
|
||||
components:
|
||||
schemas:
|
||||
@@ -10,7 +11,7 @@ components:
|
||||
# Config
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Config:
|
||||
descripton: |-
|
||||
description: |-
|
||||
Data model for all parts of the configuration.
|
||||
type: object
|
||||
required:
|
||||
@@ -48,9 +49,30 @@ components:
|
||||
Options pertaining to the rudimentary setup of the app.
|
||||
type: object
|
||||
required:
|
||||
- log-level
|
||||
- tsp
|
||||
- tarjan
|
||||
- hirschberg
|
||||
- rucksack
|
||||
- random-walk
|
||||
- genetic
|
||||
- euklid
|
||||
- pollard-rho
|
||||
properties:
|
||||
log-level:
|
||||
$ref: '#/components/schemas/EnumLogLevel'
|
||||
verbose:
|
||||
description: Global setting for verbosity.
|
||||
type: boolean
|
||||
default: false
|
||||
tarjan:
|
||||
type: object
|
||||
required:
|
||||
- verbose
|
||||
properties:
|
||||
verbose:
|
||||
type: boolean
|
||||
default: false
|
||||
tsp:
|
||||
type: object
|
||||
required:
|
||||
@@ -65,8 +87,6 @@ components:
|
||||
- penality-mismatch
|
||||
- penality-gap
|
||||
- move-priorities
|
||||
- verbose
|
||||
- show
|
||||
properties:
|
||||
penality-mismatch:
|
||||
type: number
|
||||
@@ -99,6 +119,60 @@ components:
|
||||
items:
|
||||
$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
|
||||
properties:
|
||||
verbose:
|
||||
type: boolean
|
||||
default: false
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Enum LogLevel
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
EnumLogLevel:
|
||||
description: |-
|
||||
Enumeration of settings for log level.
|
||||
type: string
|
||||
enum:
|
||||
- INFO
|
||||
- DEBUG
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Enum Hirschberg - Verbosity options
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -114,8 +188,18 @@ components:
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
EnumHirschbergShow:
|
||||
description: |-
|
||||
Enumeration of verbosity options for Hirschberg
|
||||
Enumeration of display 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "uni-leipzig-ads-2-2022"
|
||||
version = "1.0.0"
|
||||
version = "0.3.1"
|
||||
description = "Zusatzcode, um Algorithmen und Datenstrukturen im Kurs ADS2 zu demonstrieren."
|
||||
authors = [ "Raj Dahya" ]
|
||||
maintainers = [ "raj_mathe" ]
|
||||
|
||||
@@ -23,6 +23,7 @@ lazy-load>=0.8.2
|
||||
pyyaml>=6.0
|
||||
pydantic>=1.9.0
|
||||
datamodel-code-generator>=0.13.0
|
||||
openapi-generator-cli>=4.3.1
|
||||
|
||||
# misc
|
||||
lorem>=0.1.1
|
||||
|
||||
16
code/python/src/algorithms/euklid/__init__.py
Normal file
16
code/python/src/algorithms/euklid/__init__.py
Normal file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.algorithms.euklid.algorithms import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'euklidean_algorithm',
|
||||
];
|
||||
97
code/python/src/algorithms/euklid/algorithms.py
Normal file
97
code/python/src/algorithms/euklid/algorithms.py
Normal file
@@ -0,0 +1,97 @@
|
||||
#!/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;
|
||||
56
code/python/src/algorithms/euklid/display.py
Normal file
56
code/python/src/algorithms/euklid/display.py
Normal file
@@ -0,0 +1,56 @@
|
||||
#!/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' ;
|
||||
16
code/python/src/algorithms/genetic/__init__.py
Normal file
16
code/python/src/algorithms/genetic/__init__.py
Normal file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.algorithms.genetic.algorithms import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'genetic_algorithm',
|
||||
];
|
||||
38
code/python/src/algorithms/genetic/algorithms.py
Normal file
38
code/python/src/algorithms/genetic/algorithms.py
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/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;
|
||||
30
code/python/src/algorithms/genetic/display.py
Normal file
30
code/python/src/algorithms/genetic/display.py
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/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 '';
|
||||
@@ -6,7 +6,6 @@
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.algorithms.hirschberg.algorithms import *;
|
||||
from src.models.hirschberg.penalties import *;
|
||||
from src.algorithms.hirschberg.display import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -14,5 +13,6 @@ from src.algorithms.hirschberg.display import *;
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'simple_algorithm',
|
||||
'hirschberg_algorithm',
|
||||
];
|
||||
|
||||
@@ -31,8 +31,7 @@ __all__ = [
|
||||
def simple_algorithm(
|
||||
X: str,
|
||||
Y: str,
|
||||
verb: List[EnumHirschbergVerbosity] = [],
|
||||
show: List[EnumHirschbergShow] = [],
|
||||
verbose: List[EnumHirschbergVerbosity] = [],
|
||||
) -> Tuple[str, str]:
|
||||
'''
|
||||
Dieser Algorithmus berechnet die Edit-Distanzen + optimale Richtungen ein Mal.
|
||||
@@ -41,8 +40,8 @@ def simple_algorithm(
|
||||
Costs, Moves = compute_cost_matrix(X = '-' + X, Y = '-' + Y);
|
||||
path = reconstruct_optimal_path(Moves=Moves);
|
||||
word_x, word_y = reconstruct_words(X = '-' + X, Y = '-' + Y, moves=[Moves[coord] for coord in path], path=path);
|
||||
if verb != []:
|
||||
repr = display_cost_matrix(Costs=Costs, path=path, X = '-' + X, Y = '-' + Y, verb=verb);
|
||||
if verbose != []:
|
||||
repr = display_cost_matrix(Costs=Costs, path=path, X = '-' + X, Y = '-' + Y, verbose=verbose);
|
||||
display = word_y + f'\n{"-"*len(word_x)}\n' + word_x;
|
||||
print(f'\n{repr}\n\n\x1b[1mOptimales Alignment:\x1b[0m\n\n{display}\n');
|
||||
return word_x, word_y;
|
||||
@@ -50,8 +49,7 @@ def simple_algorithm(
|
||||
def hirschberg_algorithm(
|
||||
X: str,
|
||||
Y: str,
|
||||
once: bool = False,
|
||||
verb: List[EnumHirschbergVerbosity] = [],
|
||||
verbose: List[EnumHirschbergVerbosity] = [],
|
||||
show: List[EnumHirschbergShow] = [],
|
||||
) -> Tuple[str, str]:
|
||||
'''
|
||||
@@ -64,16 +62,12 @@ def hirschberg_algorithm(
|
||||
Daraus wird unmittelbar ein optimales Alignment bestimmt.
|
||||
Des Weiteren werden Zeitkosten durch Divide-and-Conquer klein gehalten.
|
||||
'''
|
||||
# ggf. nur den simplen Algorithmus ausführen:
|
||||
if once:
|
||||
return simple_algorithm(X=X, Y=Y, verb=verb, show=show);
|
||||
|
||||
align = hirschberg_algorithm_step(X=X, Y=Y, depth=1, verb=verb, show=show);
|
||||
align = hirschberg_algorithm_step(X=X, Y=Y, depth=1, verbose=verbose, show=show);
|
||||
word_x = align.as_string1();
|
||||
word_y = align.as_string2();
|
||||
|
||||
# verbose output hier behandeln (irrelevant für Algorithmus):
|
||||
if verb != []:
|
||||
if verbose != []:
|
||||
if EnumHirschbergShow.tree in show:
|
||||
display = align.astree(braces=True);
|
||||
else:
|
||||
@@ -88,7 +82,7 @@ def hirschberg_algorithm_step(
|
||||
X: str,
|
||||
Y: str,
|
||||
depth: int = 0,
|
||||
verb: List[EnumHirschbergVerbosity] = [],
|
||||
verbose: List[EnumHirschbergVerbosity] = [],
|
||||
show: List[EnumHirschbergShow] = [],
|
||||
) -> Alignment:
|
||||
'''
|
||||
@@ -106,8 +100,8 @@ def hirschberg_algorithm_step(
|
||||
word_x, word_y = reconstruct_words(X = '-' + X, Y = '-' + Y, moves=[Moves[coord] for coord in path], path=path);
|
||||
|
||||
# verbose output hier behandeln (irrelevant für Algorithmus):
|
||||
if verb != [] and (EnumHirschbergShow.atoms in show):
|
||||
repr = display_cost_matrix(Costs=Costs, path=path, X = '-' + X, Y = '-' + Y, verb=verb);
|
||||
if verbose != [] and (EnumHirschbergShow.atoms in show):
|
||||
repr = display_cost_matrix(Costs=Costs, path=path, X = '-' + X, Y = '-' + Y, verbose=verbose);
|
||||
print(f'\n\x1b[1mRekursionstiefe: {depth}\x1b[0m\n\n{repr}')
|
||||
|
||||
return AlignmentBasic(word1=word_x, word2=word_y);
|
||||
@@ -127,7 +121,7 @@ def hirschberg_algorithm_step(
|
||||
Costs2, Moves2 = compute_cost_matrix(X = '-' + X2, Y = '-' + Y2);
|
||||
|
||||
# verbose output hier behandeln (irrelevant für Algorithmus):
|
||||
if verb != []:
|
||||
if verbose != []:
|
||||
path1, path2 = reconstruct_optimal_path_halves(Costs1=Costs1, Costs2=Costs2, Moves1=Moves1, Moves2=Moves2);
|
||||
repr = display_cost_matrix_halves(
|
||||
Costs1 = Costs1,
|
||||
@@ -138,7 +132,7 @@ def hirschberg_algorithm_step(
|
||||
X2 = '-' + X2,
|
||||
Y1 = '-' + Y1,
|
||||
Y2 = '-' + Y2,
|
||||
verb = verb,
|
||||
verbose = verbose,
|
||||
);
|
||||
print(f'\n\x1b[1mRekursionstiefe: {depth}\x1b[0m\n\n{repr}')
|
||||
|
||||
@@ -146,8 +140,8 @@ def hirschberg_algorithm_step(
|
||||
coord1, coord2 = get_optimal_transition(Costs1=Costs1, Costs2=Costs2);
|
||||
p = coord1[0];
|
||||
# Divide and Conquer ausführen:
|
||||
align_left = hirschberg_algorithm_step(X=X[:p], Y=Y[:n], depth=depth+1, verb=verb, show=show);
|
||||
align_right = hirschberg_algorithm_step(X=X[p:], Y=Y[n:], depth=depth+1, verb=verb, show=show);
|
||||
align_left = hirschberg_algorithm_step(X=X[:p], Y=Y[:n], depth=depth+1, verbose=verbose, show=show);
|
||||
align_right = hirschberg_algorithm_step(X=X[p:], Y=Y[n:], depth=depth+1, verbose=verbose, show=show);
|
||||
|
||||
# Resultate zusammensetzen:
|
||||
return AlignmentPair(left=align_left, right=align_right);
|
||||
|
||||
@@ -30,7 +30,7 @@ def represent_cost_matrix(
|
||||
path: List[Tuple[int, int]],
|
||||
X: str,
|
||||
Y: str,
|
||||
verb: List[EnumHirschbergVerbosity],
|
||||
verbose: List[EnumHirschbergVerbosity],
|
||||
pad: bool = False,
|
||||
) -> np.ndarray: # NDArray[(Any, Any), Any]:
|
||||
m = len(X); # display vertically
|
||||
@@ -55,12 +55,12 @@ def represent_cost_matrix(
|
||||
table[-3, 3:(3+n)] = '--';
|
||||
table[3:(3+m), -1] = '|';
|
||||
|
||||
if EnumHirschbergVerbosity.costs in verb:
|
||||
if EnumHirschbergVerbosity.costs in verbose:
|
||||
table[3:(3+m), 3:(3+n)] = Costs.copy();
|
||||
if EnumHirschbergVerbosity.moves in verb:
|
||||
if EnumHirschbergVerbosity.moves in verbose:
|
||||
for (i, j) in path:
|
||||
table[3 + i, 3 + j] = f'\x1b[31;4;1m{table[3 + i, 3 + j]}\x1b[0m';
|
||||
elif EnumHirschbergVerbosity.moves in verb:
|
||||
elif EnumHirschbergVerbosity.moves in verbose:
|
||||
table[3:(3+m), 3:(3+n)] = '\x1b[2m.\x1b[0m';
|
||||
for (i, j) in path:
|
||||
table[3 + i, 3 + j] = '\x1b[31;1m*\x1b[0m';
|
||||
@@ -72,7 +72,7 @@ def display_cost_matrix(
|
||||
path: List[Tuple[int, int]],
|
||||
X: str,
|
||||
Y: str,
|
||||
verb: EnumHirschbergVerbosity,
|
||||
verbose: EnumHirschbergVerbosity,
|
||||
) -> str:
|
||||
'''
|
||||
Zeigt Kostenmatrix + optimalen Pfad.
|
||||
@@ -85,7 +85,7 @@ def display_cost_matrix(
|
||||
@returns
|
||||
- eine 'printable' Darstellung der Matrix mit den Strings X, Y + Indexes.
|
||||
'''
|
||||
table = represent_cost_matrix(Costs=Costs, path=path, X=X, Y=Y, verb=verb);
|
||||
table = represent_cost_matrix(Costs=Costs, path=path, X=X, Y=Y, verbose=verbose);
|
||||
# benutze pandas-Dataframe + tabulate, um schöner darzustellen:
|
||||
repr = tabulate(pd.DataFrame(table), showindex=False, stralign='center', tablefmt='plain');
|
||||
return repr;
|
||||
@@ -99,7 +99,7 @@ def display_cost_matrix_halves(
|
||||
X2: str,
|
||||
Y1: str,
|
||||
Y2: str,
|
||||
verb: EnumHirschbergVerbosity,
|
||||
verbose: EnumHirschbergVerbosity,
|
||||
) -> str:
|
||||
'''
|
||||
Zeigt Kostenmatrix + optimalen Pfad für Schritt im D & C Hirschberg-Algorithmus
|
||||
@@ -112,8 +112,8 @@ def display_cost_matrix_halves(
|
||||
@returns
|
||||
- eine 'printable' Darstellung der Matrix mit den Strings X, Y + Indexes.
|
||||
'''
|
||||
table1 = represent_cost_matrix(Costs=Costs1, path=path1, X=X1, Y=Y1, verb=verb, pad=True);
|
||||
table2 = represent_cost_matrix(Costs=Costs2, path=path2, X=X2, Y=Y2, verb=verb, pad=True);
|
||||
table1 = represent_cost_matrix(Costs=Costs1, path=path1, X=X1, Y=Y1, verbose=verbose, pad=True);
|
||||
table2 = represent_cost_matrix(Costs=Costs2, path=path2, X=X2, Y=Y2, verbose=verbose, pad=True);
|
||||
|
||||
# merge Taellen:
|
||||
table = np.concatenate([table1[:, :-1], table2[::-1, ::-1]], axis=1);
|
||||
|
||||
17
code/python/src/algorithms/pollard_rho/__init__.py
Normal file
17
code/python/src/algorithms/pollard_rho/__init__.py
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/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',
|
||||
];
|
||||
144
code/python/src/algorithms/pollard_rho/algorithms.py
Normal file
144
code/python/src/algorithms/pollard_rho/algorithms.py
Normal file
@@ -0,0 +1,144 @@
|
||||
#!/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;
|
||||
65
code/python/src/algorithms/pollard_rho/display.py
Normal file
65
code/python/src/algorithms/pollard_rho/display.py
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/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;
|
||||
18
code/python/src/algorithms/random_walk/__init__.py
Normal file
18
code/python/src/algorithms/random_walk/__init__.py
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/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',
|
||||
];
|
||||
247
code/python/src/algorithms/random_walk/algorithms.py
Normal file
247
code/python/src/algorithms/random_walk/algorithms.py
Normal file
@@ -0,0 +1,247 @@
|
||||
#!/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);
|
||||
30
code/python/src/algorithms/random_walk/display.py
Normal file
30
code/python/src/algorithms/random_walk/display.py
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/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 '';
|
||||
17
code/python/src/algorithms/rucksack/__init__.py
Normal file
17
code/python/src/algorithms/rucksack/__init__.py
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.algorithms.rucksack.algorithms import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'rucksack_greedy_algorithm',
|
||||
'rucksack_branch_and_bound_algorithm',
|
||||
];
|
||||
262
code/python/src/algorithms/rucksack/algorithms.py
Normal file
262
code/python/src/algorithms/rucksack/algorithms.py
Normal file
@@ -0,0 +1,262 @@
|
||||
#!/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.rucksack import *;
|
||||
from src.models.stacks import *;
|
||||
from src.algorithms.rucksack.display import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'rucksack_greedy_algorithm',
|
||||
'rucksack_branch_and_bound_algorithm',
|
||||
];
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHOD greedy algorithm
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def rucksack_greedy_algorithm(
|
||||
max_cost: float,
|
||||
costs: np.ndarray,
|
||||
values: np.ndarray,
|
||||
items: np.ndarray,
|
||||
fractional: bool,
|
||||
verbose: bool,
|
||||
) -> Solution:
|
||||
'''
|
||||
Durch den Greedy-Algorithm wird der optimale Wert eines Rucksacks
|
||||
unter Rücksicht der Kapizitätsschranke eingeschätzt.
|
||||
|
||||
NOTE: Wenn man `fractional = True` verwendet, liefert der Algorithmus
|
||||
eine obere Schranke des maximalen Wertes beim Originalproblem.
|
||||
'''
|
||||
# sortiere daten:
|
||||
order = get_sort_order(costs=costs, values=values);
|
||||
|
||||
# verbose output hier behandeln (irrelevant für Algorithmus):
|
||||
if verbose:
|
||||
repr = display_order(order=order, costs=costs, values=values, items=items, one_based=True);
|
||||
print('');
|
||||
print('\x1b[1mRucksack Problem - Greedy\x1b[0m');
|
||||
print('');
|
||||
print(repr);
|
||||
print('');
|
||||
|
||||
# führe greedy aus:
|
||||
n = len(costs);
|
||||
cost_total = 0;
|
||||
choice = [ 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);
|
||||
# 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);
|
||||
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
|
||||
soln = Solution(
|
||||
order = order,
|
||||
choice = choice,
|
||||
items = items[rucksack].tolist(),
|
||||
costs = costs[rucksack].tolist(),
|
||||
values = values[rucksack].tolist(),
|
||||
);
|
||||
|
||||
# verbose output hier behandeln (irrelevant für Algorithmus):
|
||||
if verbose:
|
||||
repr_rucksack = display_rucksack(items=items, costs=costs, values=values, choice=choice);
|
||||
print('\x1b[1mEingeschätzte Lösung\x1b[0m');
|
||||
print('');
|
||||
print(f'Mask: [{", ".join(map(str, soln.choice))}]');
|
||||
print('Rucksack:')
|
||||
print(repr_rucksack);
|
||||
print('');
|
||||
|
||||
# Lösung ausgeben
|
||||
return soln;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHOD branch and bound algorithm
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def rucksack_branch_and_bound_algorithm(
|
||||
max_cost: float,
|
||||
costs: np.ndarray,
|
||||
values: np.ndarray,
|
||||
items: np.ndarray,
|
||||
verbose: bool,
|
||||
) -> Solution:
|
||||
'''
|
||||
Durch Branch & Bound wird der optimale Wert eines Rucksacks
|
||||
unter Rücksicht der Kapizitätsschranke exakt und effizienter bestimmt.
|
||||
'''
|
||||
|
||||
order = get_sort_order(costs=costs, values=values);
|
||||
|
||||
# verbose output hier behandeln (irrelevant für Algorithmus):
|
||||
if verbose:
|
||||
repr = display_order(order=order, costs=costs, values=values, items=items, one_based=True);
|
||||
print('');
|
||||
print('\x1b[1mRucksack Problem - Branch & Bound\x1b[0m');
|
||||
print('');
|
||||
print(repr);
|
||||
print('');
|
||||
|
||||
logged_steps = [];
|
||||
step: Step;
|
||||
mask = empty_mask(n=len(costs));
|
||||
bound = np.inf;
|
||||
S = Stack();
|
||||
S.push(mask);
|
||||
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):
|
||||
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();
|
||||
# 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;
|
||||
# Branch sonst
|
||||
else:
|
||||
B, C = A.split();
|
||||
S.push(B);
|
||||
# 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:
|
||||
S.push(C);
|
||||
|
||||
# Aspekte der Lösung speichern
|
||||
rucksack = mask.indexes_one; # Indexes von Items im Rucksack
|
||||
soln = Solution(
|
||||
order = order,
|
||||
choice = mask.choice,
|
||||
items = items[rucksack].tolist(),
|
||||
values = values[rucksack].tolist(),
|
||||
costs = costs[rucksack].tolist(),
|
||||
);
|
||||
|
||||
# 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('');
|
||||
print('\x1b[1mLösung\x1b[0m');
|
||||
print('');
|
||||
print(f'Mask: [{", ".join(map(str, soln.choice))}]');
|
||||
print('Rucksack:');
|
||||
print(repr_rucksack);
|
||||
print('');
|
||||
|
||||
# Lösung ausgeben
|
||||
return soln;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# AUXILIARY METHOD resort
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def get_sort_order(costs: np.ndarray, values: np.ndarray) -> List[int]:
|
||||
'''
|
||||
Sortiert Daten absteigend nach values/costs.
|
||||
'''
|
||||
n = len(costs);
|
||||
indexes = list(range(n));
|
||||
margin = [ value/cost for cost, value in zip(costs, values) ];
|
||||
order = sorted(indexes, key=lambda i: -margin[i]);
|
||||
return order;
|
||||
|
||||
def estimate_lower_bound(
|
||||
mask: Mask,
|
||||
max_cost: float,
|
||||
costs: np.ndarray,
|
||||
values: np.ndarray,
|
||||
items: np.ndarray,
|
||||
) -> Tuple[float, List[Fraction], List[int], Optional[Mask]]:
|
||||
'''
|
||||
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.
|
||||
'''
|
||||
indexes_one = mask.indexes_one;
|
||||
indexes_unset = mask.indexes_unset;
|
||||
n = len(mask);
|
||||
choice = np.zeros(shape=(n,), dtype=Fraction);
|
||||
order = np.asarray(range(n));
|
||||
|
||||
# Berechnungen bei Items mit bekanntem Status in Rucksack:
|
||||
value_rucksack = sum(values[indexes_one]);
|
||||
cost_rucksack = sum(costs[indexes_one]);
|
||||
choice[indexes_one] = Fraction(1);
|
||||
|
||||
# Für Rest des Rucksacks (Items mit unbekanntem Status):
|
||||
cost_rest = max_cost - cost_rucksack;
|
||||
state = None;
|
||||
# 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);
|
||||
choice[indexes_unset] = Fraction(1);
|
||||
value_rest = sum(values[indexes_unset]);
|
||||
elif min(costs[indexes_unset]) > cost_rest:
|
||||
state = mask.pad(MaskValue.ZERO);
|
||||
choice[indexes_unset] = Fraction(0);
|
||||
value_rest = 0;
|
||||
# Sonst mit Greedy-Algorithmus lösen:
|
||||
# NOTE: Lösung ist eine Überschätzung des max-Wertes.
|
||||
else:
|
||||
soln_rest = rucksack_greedy_algorithm(
|
||||
max_cost = cost_rest, # <- Kapazität = Restgewicht
|
||||
costs = costs[indexes_unset],
|
||||
values = values[indexes_unset],
|
||||
items = items[indexes_unset],
|
||||
fractional = True,
|
||||
verbose = False,
|
||||
);
|
||||
choice[indexes_unset] = soln_rest.choice;
|
||||
value_rest = soln_rest.total_value;
|
||||
# Berechne Permutation für Teilrucksack
|
||||
permute_part(order, indexes=indexes_unset, order=soln_rest.order, in_place=True);
|
||||
|
||||
# Einschätzung des max-Wertes:
|
||||
value_max_est = value_rucksack + value_rest;
|
||||
|
||||
# Ausgabe mit -1 multiplizieren (weil maximiert wird):
|
||||
return -value_max_est, choice.tolist(), order.tolist(), state;
|
||||
174
code/python/src/algorithms/rucksack/display.py
Normal file
174
code/python/src/algorithms/rucksack/display.py
Normal file
@@ -0,0 +1,174 @@
|
||||
#!/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.utils import *;
|
||||
from src.setup import config;
|
||||
from models.generated.config import *;
|
||||
from src.models.stacks import *;
|
||||
from src.models.rucksack import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'display_order',
|
||||
'display_rucksack',
|
||||
'display_branch_and_bound',
|
||||
'display_sum',
|
||||
];
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHOD display order
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def display_order(
|
||||
order: List[int],
|
||||
costs: np.ndarray,
|
||||
values: np.ndarray,
|
||||
items: np.ndarray,
|
||||
one_based: bool = False,
|
||||
) -> str:
|
||||
table = pd.DataFrame({
|
||||
'items': items,
|
||||
'order': iperm(order),
|
||||
'values': values,
|
||||
'costs': costs,
|
||||
'margin': [f'{value/cost:.6f}' for cost, value in zip(costs, values)],
|
||||
}) \
|
||||
.reset_index(drop=True);
|
||||
if one_based:
|
||||
table['order'] += 1;
|
||||
# benutze pandas-Dataframe + tabulate, um schöner darzustellen:
|
||||
repr = tabulate(
|
||||
table,
|
||||
headers=['item', 'greedy order', 'value', 'cost', 'value/cost'],
|
||||
showindex=False,
|
||||
colalign=('left', 'center', 'center', 'center', 'right'),
|
||||
tablefmt='rst'
|
||||
);
|
||||
return repr;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHOD display rucksack
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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'],
|
||||
});
|
||||
repr = tabulate(
|
||||
table,
|
||||
headers=['item', 'nr', 'cost', 'value'],
|
||||
showindex=False,
|
||||
colalign=('left', 'center', 'center', 'center'),
|
||||
tablefmt='rst'
|
||||
);
|
||||
return repr;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# 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);
|
||||
|
||||
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);
|
||||
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',
|
||||
});
|
||||
|
||||
table = pd.DataFrame(rows).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'],
|
||||
showindex=False,
|
||||
colalign=('right', 'right', 'left', 'right', 'center', 'left'),
|
||||
tablefmt='simple'
|
||||
);
|
||||
return repr;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHOD display sum
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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)) ];
|
||||
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));
|
||||
|
||||
if as_maximum:
|
||||
return f'\x1b[2m=\x1b[0m {expr}';
|
||||
return f'\x1b[2m= -(\x1b[0m{expr}\x1b[2m)\x1b[0m';
|
||||
@@ -8,6 +8,7 @@
|
||||
from __future__ import annotations;
|
||||
|
||||
from src.thirdparty.types import *;
|
||||
from src.thirdparty.maths import *;
|
||||
|
||||
from src.core.log import *;
|
||||
from src.models.stacks import *;
|
||||
@@ -34,18 +35,31 @@ class State(Enum):
|
||||
# Tarjan Algorithm
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def tarjan_algorithm(G: Graph, debug: bool = False) -> List[Any]:
|
||||
def tarjan_algorithm(G: Graph, verbose: bool = False) -> List[Any]:
|
||||
'''
|
||||
# Tarjan Algorithm #
|
||||
Runs the Tarjan-Algorithm to compute the strongly connected components.
|
||||
'''
|
||||
# initialise state - mark all nodes as UNTOUCHED:
|
||||
ctx = Context(G, debug=debug);
|
||||
ctx = Context(G);
|
||||
# loop through all nodes and carry out Tarjan-Algorithm, provided node not already visitted.
|
||||
for u in G.nodes:
|
||||
if ctx.get_state(u) == State.UNTOUCHED:
|
||||
tarjan_visit(G, u, ctx);
|
||||
|
||||
if verbose:
|
||||
repr = ctx.repr();
|
||||
print('');
|
||||
print(f'\x1b[1mZusammenfassung der Ausführung des Tarjan-Algorithmus\x1b[0m');
|
||||
print('');
|
||||
print(repr);
|
||||
print('');
|
||||
print('\x1b[1mStark zshgd Komponenten:\x1b[0m')
|
||||
print('');
|
||||
for component in ctx.components:
|
||||
print(component);
|
||||
print('');
|
||||
|
||||
return ctx.components;
|
||||
|
||||
def tarjan_visit(G: Graph, u: Any, ctx: Context):
|
||||
@@ -107,15 +121,15 @@ class NodeInformation(NodeInformationDefault):
|
||||
@dataclass
|
||||
class ContextDefault:
|
||||
max_index: int = field(default=0);
|
||||
debug: bool = field(default=False);
|
||||
verbose: bool = field(default=False);
|
||||
stack: Stack = field(default_factory=lambda: Stack());
|
||||
components: list[list[Any]] = field(default_factory=lambda: []);
|
||||
infos: dict[Any, NodeInformation] = field(default_factory=lambda: dict());
|
||||
components: list[list[Any]] = field(default_factory=list);
|
||||
infos: dict[Any, NodeInformation] = field(default_factory=dict);
|
||||
finished: List[Any] = field(default_factory=list);
|
||||
|
||||
class Context(ContextDefault):
|
||||
def __init__(self, G: Graph, debug: bool):
|
||||
def __init__(self, G: Graph):
|
||||
super().__init__();
|
||||
self.debug = debug;
|
||||
self.infos = { u: NodeInformation(u) for u in G.nodes };
|
||||
|
||||
def push(self, u: Any):
|
||||
@@ -161,7 +175,22 @@ class Context(ContextDefault):
|
||||
return self.get_info(u).index;
|
||||
|
||||
def log_info(self, u: Any):
|
||||
if not self.debug:
|
||||
return;
|
||||
info = self.get_info(u);
|
||||
log_debug(info);
|
||||
self.finished.append(u);
|
||||
|
||||
def repr(self) -> str:
|
||||
table = pd.DataFrame([ self.infos[u] for u in self.finished ]) \
|
||||
.drop(columns='state');
|
||||
table = table[['node', 'index', 'least_index']];
|
||||
# benutze pandas-Dataframe + tabulate, um schöner darzustellen:
|
||||
repr = tabulate(
|
||||
table,
|
||||
headers = {
|
||||
'Knoten': 'node',
|
||||
'Idx': 'index',
|
||||
'min. Idx': 'least_index',
|
||||
},
|
||||
showindex = False,
|
||||
stralign = 'center',
|
||||
tablefmt = 'grid',
|
||||
);
|
||||
return repr;
|
||||
|
||||
51
code/python/src/api.py
Normal file
51
code/python/src/api.py
Normal file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.thirdparty.code import *;
|
||||
|
||||
from models.generated.commands import *;
|
||||
from src.models.config import *
|
||||
from src.endpoints import *;
|
||||
from src.core.calls import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'run_command',
|
||||
'run_command_from_json',
|
||||
];
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# API METHODS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@run_safely(tag='api-from-json')
|
||||
def run_command_from_json(command_json: str) -> Result[CallResult, CallError]:
|
||||
command = command_from_json(command_json);
|
||||
return run_command(command);
|
||||
|
||||
@run_safely(tag='api-from-command')
|
||||
def run_command(command: Command) -> Result[CallResult, CallError]:
|
||||
if isinstance(command, CommandTarjan):
|
||||
return endpoint_tarjan(command);
|
||||
if isinstance(command, CommandTsp):
|
||||
return endpoint_tsp(command);
|
||||
elif isinstance(command, CommandHirschberg):
|
||||
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.');
|
||||
149
code/python/src/core/calls.py
Normal file
149
code/python/src/core/calls.py
Normal file
@@ -0,0 +1,149 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from __future__ import annotations;
|
||||
|
||||
from src.thirdparty.code import *;
|
||||
from src.thirdparty.misc import *;
|
||||
from src.thirdparty.run import *;
|
||||
from src.thirdparty.types import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'CallResult',
|
||||
'CallError',
|
||||
'run_safely',
|
||||
];
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# CONSTANTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
# local usage only
|
||||
T = TypeVar('T');
|
||||
V = TypeVar('V');
|
||||
E = TypeVar('E', bound=list);
|
||||
ARGS = ParamSpec('ARGS');
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# CLASS Trace for debugging only!
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@dataclass
|
||||
class CallResult(): # pragma: no cover
|
||||
'''
|
||||
An auxiliary class which keeps track of the latest return value during calls.
|
||||
'''
|
||||
action_taken: bool = field(default=False);
|
||||
message: Optional[Any] = field(default=None);
|
||||
|
||||
@dataclass
|
||||
class CallErrorRaw(): # pragma: no cover
|
||||
timestamp: str = field();
|
||||
tag: str = field();
|
||||
errors: List[str] = field(default_factory=list);
|
||||
|
||||
class CallError(CallErrorRaw):
|
||||
'''
|
||||
An auxiliary class which keeps track of potentially multiple errors during calls.
|
||||
'''
|
||||
timestamp: str;
|
||||
tag: str;
|
||||
errors: List[str];
|
||||
|
||||
def __init__(self, tag: str, err: Any = Nothing()):
|
||||
self.timestamp = str(datetime.now());
|
||||
self.tag = tag;
|
||||
self.errors = [];
|
||||
if isinstance(err, list):
|
||||
for e in err:
|
||||
self.append(e);
|
||||
else:
|
||||
self.append(err);
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self.errors);
|
||||
|
||||
def append(self, e: Any):
|
||||
if isinstance(e, Nothing):
|
||||
return;
|
||||
if isinstance(e, Some):
|
||||
e = e.unwrap();
|
||||
self.errors.append(str(e));
|
||||
|
||||
def extend(self, E: CallError):
|
||||
self.errors.extend(E.errors);
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f'CallError(tag=\'{self.tag}\', errors={self.errors})';
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.__repr__();
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# DECORATOR - forces methods to run safely
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def run_safely(tag: Union[str, None] = None, error_message: Union[str, None] = None):
|
||||
'''
|
||||
Creates a decorator for an action to perform it safely.
|
||||
|
||||
@inputs (parameters)
|
||||
- `tag` - optional string to aid error tracking.
|
||||
- `error_message` - optional string for an error message.
|
||||
|
||||
### Example usage ###
|
||||
```py
|
||||
@run_safely(tag='recognise int', error_message='unrecognise string')
|
||||
def action1(x: str) -> Result[int, CallError]:
|
||||
return Ok(int(x));
|
||||
|
||||
assert action1('5') == Ok(5);
|
||||
result = action1('not a number');
|
||||
assert isinstance(result, Err);
|
||||
err = result.unwrap_err();
|
||||
assert isinstance(err, CallError);
|
||||
assert err.tag == 'recognise int';
|
||||
assert err.errors == ['unrecognise string'];
|
||||
|
||||
@run_safely('recognise int')
|
||||
def action2(x: str) -> Result[int, CallError]:
|
||||
return Ok(int(x));
|
||||
|
||||
assert action2('5') == Ok(5);
|
||||
result = action2('not a number');
|
||||
assert isinstance(result, Err);
|
||||
err = result.unwrap_err();
|
||||
assert isinstance(err, CallError);
|
||||
assert err.tag == 'recognise int';
|
||||
assert len(err.errors) == 1;
|
||||
```
|
||||
NOTE: in the second example, err.errors is a list containing
|
||||
the stringified Exception generated when calling `int('not a number')`.
|
||||
'''
|
||||
def dec(action: Callable[ARGS, Result[V, CallError]]) -> Callable[ARGS, Result[V, CallError]]:
|
||||
'''
|
||||
Wraps action with return type Result[..., CallError],
|
||||
so that it is performed safely a promise,
|
||||
catching any internal exceptions as an Err(...)-component of the Result.
|
||||
'''
|
||||
@wraps(action)
|
||||
def wrapped_action(*_, **__) -> Result[V, CallError]:
|
||||
# NOTE: intercept Exceptions first, then flatten:
|
||||
return Result.of(lambda: action(*_, **__)) \
|
||||
.or_else(
|
||||
lambda err: Err(CallError(
|
||||
tag = tag or action.__name__,
|
||||
err = error_message or err
|
||||
))
|
||||
) \
|
||||
.and_then(lambda V: V);
|
||||
return wrapped_action;
|
||||
return dec;
|
||||
@@ -5,60 +5,93 @@
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#
|
||||
from src.thirdparty.code import *;
|
||||
from src.thirdparty.log import *;
|
||||
from src.thirdparty.types import *;
|
||||
|
||||
from src.core.calls import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'LOG_LEVELS',
|
||||
'configure_logging',
|
||||
'log_info',
|
||||
'log_debug',
|
||||
'log_warn',
|
||||
'log_error',
|
||||
'log_fatal',
|
||||
'log_result',
|
||||
'log_dev',
|
||||
];
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHODS logging
|
||||
# CONSTANTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def log_info(*text: str):
|
||||
'''
|
||||
Prints an info message
|
||||
'''
|
||||
for line in text:
|
||||
print("[\x1b[94;1mINFO\x1b[0m] {}".format(line));
|
||||
_LOGGING_DEBUG_FILE: str = 'logs/debug.log';
|
||||
|
||||
class LOG_LEVELS(Enum): # pragma: no cover
|
||||
INFO = logging.INFO;
|
||||
DEBUG = logging.DEBUG;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHODS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def configure_logging(level: LOG_LEVELS): # pragma: no cover
|
||||
logging.basicConfig(
|
||||
format = '[\x1b[1m%(levelname)s\x1b[0m] %(message)s',
|
||||
level = level.value,
|
||||
);
|
||||
return;
|
||||
|
||||
def log_debug(*text: str):
|
||||
'''
|
||||
Prints a debug message
|
||||
'''
|
||||
for line in text:
|
||||
print("[\x1b[96;1mDEBUG\x1b[95;0m] {}".format(line));
|
||||
return;
|
||||
def log_debug(*messages: Any):
|
||||
logging.debug(*messages);
|
||||
|
||||
def log_warn(*text: str):
|
||||
'''
|
||||
Prints a warning message
|
||||
'''
|
||||
for line in text:
|
||||
print("[\x1b[93;1mWARNING\x1b[0m] {}".format(line));
|
||||
return;
|
||||
def log_info(*messages: Any):
|
||||
logging.info(*messages);
|
||||
|
||||
def log_error(*text: str):
|
||||
'''
|
||||
Prints an error message
|
||||
'''
|
||||
for line in text:
|
||||
print("[\x1b[91;1mERROR\x1b[0m] {}".format(line));
|
||||
return;
|
||||
def log_warn(*messages: Any):
|
||||
logging.warning(*messages);
|
||||
|
||||
def log_fatal(*text: str):
|
||||
'''
|
||||
Prints a fatal error message + crashes
|
||||
'''
|
||||
for line in text:
|
||||
print("[\x1b[91;1mFATAL\x1b[0m] {}".format(line));
|
||||
def log_error(*messages: Any):
|
||||
logging.error(*messages);
|
||||
|
||||
def log_fatal(*messages: Any):
|
||||
logging.fatal(*messages);
|
||||
exit(1);
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Special Methods
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def log_result(result: Result[CallResult, CallError], debug: bool = False):
|
||||
'''
|
||||
Logs safely encapsulated result of call as either debug/info or error.
|
||||
|
||||
@inputs
|
||||
- `result` - the result of the call.
|
||||
- `debug = False` (default) - if the result is okay, will be logged as an INFO message.
|
||||
- `debug = True` - if the result is okay, will be logged as a DEBUG message.
|
||||
'''
|
||||
if isinstance(result, Ok):
|
||||
value = result.unwrap();
|
||||
if debug:
|
||||
log_debug(asdict(value));
|
||||
else:
|
||||
log_info(asdict(value));
|
||||
else:
|
||||
err = result.unwrap_err();
|
||||
log_error(asdict(err));
|
||||
return;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# DEBUG LOGGING FOR DEVELOPMENT
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def log_dev(*messages: Any): # pragma: no cover
|
||||
with open(_LOGGING_DEBUG_FILE, 'a') as fp:
|
||||
print(*messages, file=fp);
|
||||
|
||||
47
code/python/src/core/utils.py
Normal file
47
code/python/src/core/utils.py
Normal file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.thirdparty.code import *;
|
||||
from src.thirdparty.maths import *;
|
||||
from src.thirdparty.types import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'iperm',
|
||||
'permute_part',
|
||||
];
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHODS permutations
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def iperm(order: List[int]) -> List[int]:
|
||||
'''
|
||||
Computes the inverse of a permutation.
|
||||
'''
|
||||
perm = list(enumerate(order));
|
||||
uorder = list(map(lambda x: x[0], sorted(perm, key=lambda x: x[1])));
|
||||
return uorder;
|
||||
|
||||
def permute_part(
|
||||
x: np.ndarray,
|
||||
indexes: List[int],
|
||||
order: List[int],
|
||||
in_place: bool = True,
|
||||
) -> np.ndarray:
|
||||
'''
|
||||
Permutes a part of a list by a relative permutation for that part of the list.
|
||||
'''
|
||||
if not in_place:
|
||||
x = x[:];
|
||||
part = x[indexes];
|
||||
part[:] = part[order];
|
||||
x[indexes] = part;
|
||||
return x;
|
||||
30
code/python/src/endpoints/__init__.py
Normal file
30
code/python/src/endpoints/__init__.py
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'endpoint_hirschberg',
|
||||
'endpoint_tarjan',
|
||||
'endpoint_tsp',
|
||||
'endpoint_rucksack',
|
||||
'endpoint_random_walk',
|
||||
'endpoint_genetic',
|
||||
'endpoint_euklid',
|
||||
'endpoint_pollard_rho',
|
||||
];
|
||||
34
code/python/src/endpoints/ep_algorithm_euklid.py
Normal file
34
code/python/src/endpoints/ep_algorithm_euklid.py
Normal file
@@ -0,0 +1,34 @@
|
||||
#!/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));
|
||||
34
code/python/src/endpoints/ep_algorithm_genetic.py
Normal file
34
code/python/src/endpoints/ep_algorithm_genetic.py
Normal file
@@ -0,0 +1,34 @@
|
||||
#!/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));
|
||||
42
code/python/src/endpoints/ep_algorithm_hirschberg.py
Normal file
42
code/python/src/endpoints/ep_algorithm_hirschberg.py
Normal file
@@ -0,0 +1,42 @@
|
||||
#!/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.hirschberg import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'endpoint_hirschberg',
|
||||
];
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ENDPOINT
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@run_safely()
|
||||
def endpoint_hirschberg(command: CommandHirschberg) -> Result[CallResult, CallError]:
|
||||
if command.once:
|
||||
result = simple_algorithm(
|
||||
X = command.word1,
|
||||
Y = command.word2,
|
||||
verbose = config.OPTIONS.hirschberg.verbose,
|
||||
);
|
||||
else:
|
||||
result = hirschberg_algorithm(
|
||||
X = command.word1,
|
||||
Y = command.word2,
|
||||
verbose = config.OPTIONS.hirschberg.verbose,
|
||||
show = config.OPTIONS.hirschberg.show,
|
||||
);
|
||||
return Ok(CallResult(action_taken=True, message=result));
|
||||
46
code/python/src/endpoints/ep_algorithm_pollard_rho.py
Normal file
46
code/python/src/endpoints/ep_algorithm_pollard_rho.py
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/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));
|
||||
75
code/python/src/endpoints/ep_algorithm_random_walk.py
Normal file
75
code/python/src/endpoints/ep_algorithm_random_walk.py
Normal file
@@ -0,0 +1,75 @@
|
||||
#!/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));
|
||||
54
code/python/src/endpoints/ep_algorithm_rucksack.py
Normal file
54
code/python/src/endpoints/ep_algorithm_rucksack.py
Normal file
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.thirdparty.code import *;
|
||||
from src.thirdparty.maths import *;
|
||||
|
||||
from models.generated.commands import *;
|
||||
from src.core.calls import *;
|
||||
from src.setup import config;
|
||||
from src.algorithms.rucksack import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'endpoint_rucksack',
|
||||
];
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ENDPOINT
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@run_safely()
|
||||
def endpoint_rucksack(command: CommandRucksack) -> Result[CallResult, CallError]:
|
||||
n = len(command.costs);
|
||||
assert len(command.values) == n, 'Number of values and costs must coincide!';
|
||||
assert len(command.items) in [0, n], f'Number of items must be 0 or {n}!';
|
||||
command.items = command.items or [ str(index + 1) for index in range(n) ];
|
||||
match command.algorithm:
|
||||
case EnumRucksackAlgorithm.greedy:
|
||||
result = rucksack_greedy_algorithm(
|
||||
max_cost = command.max_cost,
|
||||
costs = np.asarray(command.costs[:]),
|
||||
values = np.asarray(command.values[:]),
|
||||
items = np.asarray(command.items[:]),
|
||||
fractional = command.allow_fractional,
|
||||
verbose = config.OPTIONS.rucksack.verbose,
|
||||
);
|
||||
case EnumRucksackAlgorithm.branch_and_bound:
|
||||
result = rucksack_branch_and_bound_algorithm(
|
||||
max_cost = command.max_cost,
|
||||
costs = np.asarray(command.costs[:]),
|
||||
values = np.asarray(command.values[:]),
|
||||
items = np.asarray(command.items[:]),
|
||||
verbose = config.OPTIONS.rucksack.verbose,
|
||||
);
|
||||
case _ as alg:
|
||||
raise Exception(f'No algorithm implemented for {alg.value}.');
|
||||
return Ok(CallResult(action_taken=True, message=result));
|
||||
37
code/python/src/endpoints/ep_algorithm_tarjan.py
Normal file
37
code/python/src/endpoints/ep_algorithm_tarjan.py
Normal file
@@ -0,0 +1,37 @@
|
||||
#!/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.graphs import *;
|
||||
from src.algorithms.tarjan import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'endpoint_tarjan',
|
||||
];
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ENDPOINT
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@run_safely()
|
||||
def endpoint_tarjan(command: CommandTarjan) -> Result[CallResult, CallError]:
|
||||
result = tarjan_algorithm(
|
||||
G = Graph(
|
||||
nodes=command.nodes,
|
||||
edges=list(map(tuple, command.edges)),
|
||||
),
|
||||
verbose = config.OPTIONS.tarjan.verbose
|
||||
);
|
||||
return Ok(CallResult(action_taken=True, message=result));
|
||||
35
code/python/src/endpoints/ep_algorithm_tsp.py
Normal file
35
code/python/src/endpoints/ep_algorithm_tsp.py
Normal file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.thirdparty.code import *;
|
||||
from src.thirdparty.maths import *;
|
||||
|
||||
from models.generated.commands import *;
|
||||
from src.core.calls import *;
|
||||
from src.setup import config;
|
||||
from src.algorithms.tsp import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'endpoint_tsp',
|
||||
];
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ENDPOINT
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@run_safely()
|
||||
def endpoint_tsp(command: CommandTsp) -> Result[CallResult, CallError]:
|
||||
result = tsp_algorithm(
|
||||
dist = np.asarray(command.dist, dtype=float),
|
||||
optimise = min if command.optimise == EnumOptimiseMode.min else max,
|
||||
verbose = config.OPTIONS.tsp.verbose,
|
||||
);
|
||||
return Ok(CallResult(action_taken=True, message=result));
|
||||
19
code/python/src/models/config/__init__.py
Normal file
19
code/python/src/models/config/__init__.py
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.models.config.app import *;
|
||||
from src.models.config.commands import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'log_level',
|
||||
'command_from_json',
|
||||
'interpret_command',
|
||||
];
|
||||
31
code/python/src/models/config/app.py
Normal file
31
code/python/src/models/config/app.py
Normal file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from models.generated.config import AppOptions;
|
||||
from models.generated.config import EnumLogLevel;
|
||||
from src.core.log import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'log_level',
|
||||
];
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHODS log level
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def log_level(options: AppOptions) -> LOG_LEVELS:
|
||||
match options.log_level:
|
||||
case EnumLogLevel.debug:
|
||||
return LOG_LEVELS.DEBUG;
|
||||
case EnumLogLevel.info:
|
||||
return LOG_LEVELS.INFO;
|
||||
case _:
|
||||
return LOG_LEVELS.INFO;
|
||||
55
code/python/src/models/config/commands.py
Normal file
55
code/python/src/models/config/commands.py
Normal file
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.thirdparty.config import *;
|
||||
|
||||
from models.generated.commands import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'command_from_json',
|
||||
'interpret_command',
|
||||
];
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHODS Convert to appropriate command type
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def command_from_json(command_json: str) -> Command:
|
||||
try:
|
||||
instructions = json.loads(command_json);
|
||||
except:
|
||||
raise Exception('Invalid json!');
|
||||
try:
|
||||
command = Command(**instructions);
|
||||
except:
|
||||
raise Exception('Invalid instruction format - consult schema!');
|
||||
command = interpret_command(command);
|
||||
return command;
|
||||
|
||||
def interpret_command(command: Command) -> Command:
|
||||
match command.name:
|
||||
case EnumAlgorithmNames.tarjan:
|
||||
return CommandTarjan(**command.dict());
|
||||
case EnumAlgorithmNames.tsp:
|
||||
return CommandTsp(**command.dict());
|
||||
case EnumAlgorithmNames.hirschberg:
|
||||
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!');
|
||||
16
code/python/src/models/euklid/__init__.py
Normal file
16
code/python/src/models/euklid/__init__.py
Normal file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.models.euklid.logging import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'Step',
|
||||
];
|
||||
30
code/python/src/models/euklid/logging.py
Normal file
30
code/python/src/models/euklid/logging.py
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/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();
|
||||
0
code/python/src/models/genetic/__init__.py
Normal file
0
code/python/src/models/genetic/__init__.py
Normal file
@@ -7,6 +7,7 @@
|
||||
|
||||
from __future__ import annotations;
|
||||
|
||||
from models.generated.commands import *;
|
||||
from src.thirdparty.types import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -28,7 +29,8 @@ class Graph(object):
|
||||
nodes: list[Any];
|
||||
edges: list[tuple[Any,Any]]
|
||||
|
||||
def __init__(self, nodes: list[Any], edges: list[tuple[Any,Any]]):
|
||||
def __init__(self, nodes: list[Any], edges: list[Tuple[Any, Any]]):
|
||||
assert all(len(edge) == 2 for edge in edges);
|
||||
self.nodes = nodes;
|
||||
self.edges = edges;
|
||||
return;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.thirdparty.types import *;
|
||||
from src.setup.config import *;
|
||||
from src.setup import config;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
@@ -23,6 +23,6 @@ __all__ = [
|
||||
class Directions(Enum):
|
||||
UNSET = -1;
|
||||
# Prioritäten hier setzen
|
||||
DIAGONAL = OPTIONS.hirschberg.move_priorities.diagonal;
|
||||
HORIZONTAL = OPTIONS.hirschberg.move_priorities.horizontal;
|
||||
VERTICAL = OPTIONS.hirschberg.move_priorities.vertical;
|
||||
DIAGONAL = config.OPTIONS.hirschberg.move_priorities.diagonal;
|
||||
HORIZONTAL = config.OPTIONS.hirschberg.move_priorities.horizontal;
|
||||
VERTICAL = config.OPTIONS.hirschberg.move_priorities.vertical;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.thirdparty.types import *;
|
||||
from src.setup.config import *;
|
||||
from src.setup import config;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
@@ -22,7 +22,7 @@ __all__ = [
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def gap_penalty(x: str):
|
||||
return OPTIONS.hirschberg.penality_gap;
|
||||
return config.OPTIONS.hirschberg.penality_gap;
|
||||
|
||||
def missmatch_penalty(x: str, y: str):
|
||||
return 0 if x == y else OPTIONS.hirschberg.penality_mismatch;
|
||||
return 0 if x == y else config.OPTIONS.hirschberg.penality_mismatch;
|
||||
|
||||
16
code/python/src/models/pollard_rho/__init__.py
Normal file
16
code/python/src/models/pollard_rho/__init__.py
Normal file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.models.pollard_rho.logging import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'Step',
|
||||
];
|
||||
26
code/python/src/models/pollard_rho/logging.py
Normal file
26
code/python/src/models/pollard_rho/logging.py
Normal file
@@ -0,0 +1,26 @@
|
||||
#!/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);
|
||||
18
code/python/src/models/random_walk/__init__.py
Normal file
18
code/python/src/models/random_walk/__init__.py
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/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',
|
||||
];
|
||||
124
code/python/src/models/random_walk/landscape.py
Normal file
124
code/python/src/models/random_walk/landscape.py
Normal file
@@ -0,0 +1,124 @@
|
||||
#!/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.');
|
||||
32
code/python/src/models/random_walk/logging.py
Normal file
32
code/python/src/models/random_walk/logging.py
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/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);
|
||||
23
code/python/src/models/rucksack/__init__.py
Normal file
23
code/python/src/models/rucksack/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.models.rucksack.mask import *;
|
||||
from src.models.rucksack.solution import *;
|
||||
from src.models.rucksack.logging import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'empty_mask',
|
||||
'MaskValue',
|
||||
'Mask',
|
||||
'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();
|
||||
solution: Optional[Mask] = field();
|
||||
move: EnumBranchAndBoundMove = field(default=EnumBranchAndBoundMove.NONE);
|
||||
92
code/python/src/models/rucksack/mask.py
Normal file
92
code/python/src/models/rucksack/mask.py
Normal file
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from __future__ import annotations;
|
||||
|
||||
from src.thirdparty.maths import *;
|
||||
from src.thirdparty.types import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'empty_mask',
|
||||
'MaskValue',
|
||||
'Mask',
|
||||
];
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ENUMS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class MaskValue(Enum):
|
||||
ZERO = 0;
|
||||
ONE = 1;
|
||||
UNSET = '*';
|
||||
|
||||
class Mask():
|
||||
index: int;
|
||||
values: List[MaskValue];
|
||||
|
||||
def __init__(self, values: List[MaskValue]):
|
||||
self.values = values;
|
||||
if MaskValue.UNSET in values:
|
||||
self.index = values.index(MaskValue.UNSET);
|
||||
else:
|
||||
self.index = -1;
|
||||
return;
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self.values);
|
||||
|
||||
def __str__(self) -> str:
|
||||
return ''.join([ str(m.value) for m in self.values ]);
|
||||
|
||||
@property
|
||||
def choice(self) -> List[Fraction]:
|
||||
assert all(x != MaskValue.UNSET for x in self.values);
|
||||
return [ Fraction(x.value) for x in self.values ];
|
||||
|
||||
@property
|
||||
def indexes_set(self) -> List[int]:
|
||||
return [i for i, value in enumerate(self.values) if value != MaskValue.UNSET];
|
||||
|
||||
@property
|
||||
def indexes_one(self) -> List[int]:
|
||||
return [i for i, value in enumerate(self.values) if value == MaskValue.ONE];
|
||||
|
||||
@property
|
||||
def indexes_zero(self) -> List[int]:
|
||||
return [i for i, value in enumerate(self.values) if value == MaskValue.ZERO];
|
||||
|
||||
@property
|
||||
def indexes_unset(self) -> List[int]:
|
||||
return [i for i, value in enumerate(self.values) if value == MaskValue.UNSET];
|
||||
|
||||
def splittable(self) -> bool:
|
||||
return self.index >= 0;
|
||||
|
||||
def split(self) -> Tuple[Mask, Mask]:
|
||||
vector1 = self.values[:];
|
||||
vector1[self.index] = MaskValue.ZERO;
|
||||
vector2 = self.values[:];
|
||||
vector2[self.index] = MaskValue.ONE;
|
||||
return Mask(vector1), Mask(vector2);
|
||||
|
||||
def pad(self, x: MaskValue) -> Mask:
|
||||
'''
|
||||
Pads unset values with a give by given value.
|
||||
'''
|
||||
return Mask([ x if u == MaskValue.UNSET else u for u in self.values ]);
|
||||
|
||||
@property
|
||||
def support(self) -> List[int]:
|
||||
return [ i for i, v in enumerate(self.values) if v == MaskValue.ONE ];
|
||||
|
||||
def empty_mask(n: int):
|
||||
return Mask([MaskValue.UNSET for _ in range(n)]);
|
||||
44
code/python/src/models/rucksack/solution.py
Normal file
44
code/python/src/models/rucksack/solution.py
Normal file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from __future__ import annotations;
|
||||
|
||||
from src.thirdparty.maths import *;
|
||||
from src.thirdparty.types import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'Solution',
|
||||
];
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ENUMS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@dataclass
|
||||
class SolutionRaw():
|
||||
order: List[int] = field();
|
||||
choice: List[Fraction] = field();
|
||||
items: List[str] = field();
|
||||
values: List[float] = field(repr=False);
|
||||
costs: List[float] = field(repr=False);
|
||||
|
||||
class Solution(SolutionRaw):
|
||||
@property
|
||||
def support(self) -> List[float]:
|
||||
return [ i for i, v in enumerate(self.choice) if v > 0 ];
|
||||
|
||||
@property
|
||||
def total_weight(self) -> float:
|
||||
return sum([ self.choice[i]*x for (i, x) in zip(self.support, self.costs) ]);
|
||||
|
||||
@property
|
||||
def total_value(self) -> float:
|
||||
return sum([ self.choice[i]*x for (i, x) in zip(self.support, self.values) ]);
|
||||
@@ -39,6 +39,13 @@ class Stack:
|
||||
def __contains__(self, value: Any) -> bool:
|
||||
return value in self.elements;
|
||||
|
||||
def __iter__(self) -> Generator[Any, None, None]:
|
||||
for value in self.elements:
|
||||
yield value;
|
||||
|
||||
def __str__(self) -> str:
|
||||
return ', '.join([str(value) for value in self.elements[::-1]]);
|
||||
|
||||
def push(self, value: Any):
|
||||
'''
|
||||
add element to stack
|
||||
@@ -68,3 +75,6 @@ class Stack:
|
||||
checks if element in stack:
|
||||
'''
|
||||
return element in self.elements;
|
||||
|
||||
def empty(self) -> bool:
|
||||
return len(self) == 0;
|
||||
|
||||
@@ -12,6 +12,8 @@ from src.thirdparty.types import *;
|
||||
|
||||
from models.generated.config import *;
|
||||
from models.generated.commands import *;
|
||||
from src.core.log import *;
|
||||
from src.models.config import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
@@ -41,21 +43,16 @@ def load_assets_config(path: str) -> Config: # pragma: no cover
|
||||
return Config(**assets);
|
||||
|
||||
def create_commands(path: str) -> List[Command]: # pragma: no cover
|
||||
commands = [];
|
||||
with open(path, 'r') as fp:
|
||||
assets = yaml_load(fp, Loader=yaml_FullLoader);
|
||||
for command in assets:
|
||||
match Command(**command).name:
|
||||
case EnumAlgorithmNames.tarjan:
|
||||
commands.append(CommandTarjan(**command));
|
||||
case EnumAlgorithmNames.tsp:
|
||||
commands.append(CommandTsp(**command));
|
||||
case EnumAlgorithmNames.hirschberg:
|
||||
commands.append(CommandHirschberg(**command));
|
||||
return commands;
|
||||
return [
|
||||
interpret_command(Command(**instruction))
|
||||
for instruction in assets or []
|
||||
];
|
||||
|
||||
# use lazy loaing to ensure that values only loaded (once) when used
|
||||
CONFIG: Config = lazy(load_assets_config, path=PATH_ASSETS_CONFIG);
|
||||
INFO: Info = lazy(lambda x: x.info, CONFIG);
|
||||
OPTIONS: AppOptions = lazy(lambda x: x.options, CONFIG);
|
||||
COMMANDS: List[Command] = lazy(create_commands, path=PATH_ASSETS_COMMANDS);
|
||||
CONFIG: Config = lazy(load_assets_config, path=PATH_ASSETS_CONFIG);
|
||||
INFO: Info = lazy(lambda x: x.info, CONFIG);
|
||||
OPTIONS: AppOptions = lazy(lambda x: x.options, CONFIG);
|
||||
LOG_LEVEL: LOG_LEVELS = lazy(log_level, OPTIONS);
|
||||
COMMANDS: List[Command] = lazy(create_commands, path=PATH_ASSETS_COMMANDS);
|
||||
|
||||
18
code/python/src/thirdparty/log.py
vendored
Normal file
18
code/python/src/thirdparty/log.py
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
import logging;
|
||||
from logging import LogRecord;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'logging',
|
||||
'LogRecord',
|
||||
];
|
||||
10
code/python/src/thirdparty/maths.py
vendored
10
code/python/src/thirdparty/maths.py
vendored
@@ -5,10 +5,15 @@
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -16,9 +21,14 @@ from tabulate import tabulate;
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'Fraction',
|
||||
'math',
|
||||
'np',
|
||||
'random_binomial',
|
||||
'random_binary',
|
||||
'pd',
|
||||
'random',
|
||||
'uniform',
|
||||
'uniform_random_choice',
|
||||
'tabulate',
|
||||
];
|
||||
|
||||
8
code/python/src/thirdparty/misc.py
vendored
8
code/python/src/thirdparty/misc.py
vendored
@@ -5,6 +5,10 @@
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from datetime import datetime;
|
||||
from datetime import timedelta;
|
||||
from itertools import product as itertools_product;
|
||||
import lorem;
|
||||
import re;
|
||||
from textwrap import dedent;
|
||||
|
||||
@@ -13,6 +17,10 @@ from textwrap import dedent;
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'datetime',
|
||||
'timedelta',
|
||||
'itertools_product',
|
||||
'lorem',
|
||||
're',
|
||||
'dedent',
|
||||
];
|
||||
|
||||
22
code/python/src/thirdparty/plots.py
vendored
Normal file
22
code/python/src/thirdparty/plots.py
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
#!/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',
|
||||
];
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user