From ac119a0b295b25aec073a878273b88929440c53a Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Mon, 20 Jun 2022 15:55:43 +0200 Subject: [PATCH 01/20] woche12 > master: schemata - neue commands --- code/python/models/commands-schema.yaml | 41 +++++++++++++++++++++++++ code/python/models/config-schema.yaml | 18 +++++++++++ 2 files changed, 59 insertions(+) diff --git a/code/python/models/commands-schema.yaml b/code/python/models/commands-schema.yaml index 4b76e19..1e954cc 100644 --- a/code/python/models/commands-schema.yaml +++ b/code/python/models/commands-schema.yaml @@ -115,11 +115,14 @@ components: Instructions for execution of Branch & Bound-Algorithm for the Rucksack-Problem type: object required: + - name - algorithm - max-cost - costs - values properties: + name: + $ref: '#/components/schemas/EnumAlgorithmNames' algorithm: $ref: '#/components/schemas/EnumRucksackAlgorithm' allow-fractional: @@ -146,6 +149,42 @@ components: items: type: string default: [] + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + # 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 + - number + properties: + name: + $ref: '#/components/schemas/EnumAlgorithmNames' + number: + type: integer + exclusiveMinimum: 0 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Enum Algorithm Names # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -158,6 +197,8 @@ components: - TSP - HIRSCHBERG - RUCKSACK + - EUKLID + - POLLARD-RHO # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Enum Optimise Mode # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/code/python/models/config-schema.yaml b/code/python/models/config-schema.yaml index 8829837..450ad5f 100644 --- a/code/python/models/config-schema.yaml +++ b/code/python/models/config-schema.yaml @@ -54,6 +54,8 @@ components: - tarjan - hirschberg - rucksack + - euklid + - pollard-rho properties: log-level: $ref: '#/components/schemas/EnumLogLevel' @@ -127,6 +129,22 @@ components: items: $ref: '#/components/schemas/EnumRucksackShow' default: [] + 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 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From f877ffc9e7db37bf5ff6a9afd8149d67e6cbce1d Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Mon, 20 Jun 2022 15:56:17 +0200 Subject: [PATCH 02/20] woche12 > master: code py - ep angelegt (stubs) --- code/python/src/algorithms/euklid/__init__.py | 16 +++++++++ .../src/algorithms/euklid/algorithms.py | 33 ++++++++++++++++++ code/python/src/algorithms/euklid/display.py | 0 .../src/algorithms/hirschberg/__init__.py | 1 - .../src/algorithms/pollard_rho/__init__.py | 16 +++++++++ .../src/algorithms/pollard_rho/algorithms.py | 32 +++++++++++++++++ .../src/algorithms/pollard_rho/display.py | 0 code/python/src/api.py | 4 +++ code/python/src/endpoints/__init__.py | 4 +++ .../src/endpoints/ep_algorithm_euklid.py | 34 +++++++++++++++++++ .../src/endpoints/ep_algorithm_pollard_rho.py | 33 ++++++++++++++++++ code/python/src/models/config/commands.py | 6 +++- code/python/src/models/euklid.py/__init__.py | 15 ++++++++ 13 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 code/python/src/algorithms/euklid/__init__.py create mode 100644 code/python/src/algorithms/euklid/algorithms.py create mode 100644 code/python/src/algorithms/euklid/display.py create mode 100644 code/python/src/algorithms/pollard_rho/__init__.py create mode 100644 code/python/src/algorithms/pollard_rho/algorithms.py create mode 100644 code/python/src/algorithms/pollard_rho/display.py create mode 100644 code/python/src/endpoints/ep_algorithm_euklid.py create mode 100644 code/python/src/endpoints/ep_algorithm_pollard_rho.py create mode 100644 code/python/src/models/euklid.py/__init__.py diff --git a/code/python/src/algorithms/euklid/__init__.py b/code/python/src/algorithms/euklid/__init__.py new file mode 100644 index 0000000..dca246d --- /dev/null +++ b/code/python/src/algorithms/euklid/__init__.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from src.algorithms.euklid.algorithms import *; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'euklidean_algorithm', +]; diff --git a/code/python/src/algorithms/euklid/algorithms.py b/code/python/src/algorithms/euklid/algorithms.py new file mode 100644 index 0000000..bf3e1cc --- /dev/null +++ b/code/python/src/algorithms/euklid/algorithms.py @@ -0,0 +1,33 @@ +#!/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, +): + return; diff --git a/code/python/src/algorithms/euklid/display.py b/code/python/src/algorithms/euklid/display.py new file mode 100644 index 0000000..e69de29 diff --git a/code/python/src/algorithms/hirschberg/__init__.py b/code/python/src/algorithms/hirschberg/__init__.py index 997e89c..0837c21 100644 --- a/code/python/src/algorithms/hirschberg/__init__.py +++ b/code/python/src/algorithms/hirschberg/__init__.py @@ -6,7 +6,6 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ from src.algorithms.hirschberg.algorithms import *; -from src.models.hirschberg.penalties import *; from src.algorithms.hirschberg.display import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/code/python/src/algorithms/pollard_rho/__init__.py b/code/python/src/algorithms/pollard_rho/__init__.py new file mode 100644 index 0000000..b072b7e --- /dev/null +++ b/code/python/src/algorithms/pollard_rho/__init__.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from src.algorithms.pollard_rho.algorithms import *; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'pollard_rho_algorithm', +]; diff --git a/code/python/src/algorithms/pollard_rho/algorithms.py b/code/python/src/algorithms/pollard_rho/algorithms.py new file mode 100644 index 0000000..4b1f56a --- /dev/null +++ b/code/python/src/algorithms/pollard_rho/algorithms.py @@ -0,0 +1,32 @@ +#!/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.euklid.display import *; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'pollard_rho_algorithm', +]; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHOD pollard's rho algorithm +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def pollard_rho_algorithm( + n: int, + verbose: bool = False, +): + return; diff --git a/code/python/src/algorithms/pollard_rho/display.py b/code/python/src/algorithms/pollard_rho/display.py new file mode 100644 index 0000000..e69de29 diff --git a/code/python/src/api.py b/code/python/src/api.py index 28ad4e2..6d3239c 100644 --- a/code/python/src/api.py +++ b/code/python/src/api.py @@ -40,4 +40,8 @@ def run_command(command: Command) -> Result[CallResult, CallError]: return endpoint_hirschberg(command); elif isinstance(command, CommandRucksack): return endpoint_rucksack(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.'); diff --git a/code/python/src/endpoints/__init__.py b/code/python/src/endpoints/__init__.py index 4ca27f3..cfb4e27 100644 --- a/code/python/src/endpoints/__init__.py +++ b/code/python/src/endpoints/__init__.py @@ -9,6 +9,8 @@ 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_euklid import *; +from src.endpoints.ep_algorithm_pollard_rho import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # EXPORTS @@ -19,4 +21,6 @@ __all__ = [ 'endpoint_tarjan', 'endpoint_tsp', 'endpoint_rucksack', + 'endpoint_euklid', + 'endpoint_pollard_rho', ]; diff --git a/code/python/src/endpoints/ep_algorithm_euklid.py b/code/python/src/endpoints/ep_algorithm_euklid.py new file mode 100644 index 0000000..7b19904 --- /dev/null +++ b/code/python/src/endpoints/ep_algorithm_euklid.py @@ -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], + b = command.numbers[1], + verbose = config.OPTIONS.tsp.verbose, + ); + return Ok(CallResult(action_taken=True, message=result)); diff --git a/code/python/src/endpoints/ep_algorithm_pollard_rho.py b/code/python/src/endpoints/ep_algorithm_pollard_rho.py new file mode 100644 index 0000000..eba2cc4 --- /dev/null +++ b/code/python/src/endpoints/ep_algorithm_pollard_rho.py @@ -0,0 +1,33 @@ +#!/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]: + result = pollard_rho_algorithm( + n = command.number, + verbose = config.OPTIONS.tsp.verbose, + ); + return Ok(CallResult(action_taken=True, message=result)); diff --git a/code/python/src/models/config/commands.py b/code/python/src/models/config/commands.py index f5d6aef..39e0b4a 100644 --- a/code/python/src/models/config/commands.py +++ b/code/python/src/models/config/commands.py @@ -44,4 +44,8 @@ def interpret_command(command: Command) -> Command: return CommandHirschberg(**command.dict()); case EnumAlgorithmNames.rucksack: return CommandRucksack(**command.dict()); - raise command; + 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!'); diff --git a/code/python/src/models/euklid.py/__init__.py b/code/python/src/models/euklid.py/__init__.py new file mode 100644 index 0000000..cee1f46 --- /dev/null +++ b/code/python/src/models/euklid.py/__init__.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# from src.models.euklid. import *; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ +]; From f1200dfc25784fab5822cc4d8cc46a033effa308 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Mon, 20 Jun 2022 16:46:35 +0200 Subject: [PATCH 03/20] woche12 > master: code py - euklid alg implementiert --- .../src/algorithms/euklid/algorithms.py | 71 ++++++++++++++++++- code/python/src/algorithms/euklid/display.py | 56 +++++++++++++++ .../src/endpoints/ep_algorithm_euklid.py | 4 +- .../models/{euklid.py => euklid}/__init__.py | 3 +- code/python/src/models/euklid/logging.py | 30 ++++++++ 5 files changed, 158 insertions(+), 6 deletions(-) rename code/python/src/models/{euklid.py => euklid}/__init__.py (90%) create mode 100644 code/python/src/models/euklid/logging.py diff --git a/code/python/src/algorithms/euklid/algorithms.py b/code/python/src/algorithms/euklid/algorithms.py index bf3e1cc..d853809 100644 --- a/code/python/src/algorithms/euklid/algorithms.py +++ b/code/python/src/algorithms/euklid/algorithms.py @@ -10,7 +10,7 @@ from src.thirdparty.maths import *; from models.generated.config import *; from src.core.utils import *; -# from src.models.euklid import *; +from src.models.euklid import *; from src.algorithms.euklid.display import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -29,5 +29,70 @@ def euklidean_algorithm( a: int, b: int, verbose: bool = False, -): - return; +) -> 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; diff --git a/code/python/src/algorithms/euklid/display.py b/code/python/src/algorithms/euklid/display.py index e69de29..59eab86 100644 --- a/code/python/src/algorithms/euklid/display.py +++ b/code/python/src/algorithms/euklid/display.py @@ -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' ; diff --git a/code/python/src/endpoints/ep_algorithm_euklid.py b/code/python/src/endpoints/ep_algorithm_euklid.py index 7b19904..79aece4 100644 --- a/code/python/src/endpoints/ep_algorithm_euklid.py +++ b/code/python/src/endpoints/ep_algorithm_euklid.py @@ -27,8 +27,8 @@ __all__ = [ @run_safely() def endpoint_euklid(command: CommandEuklid) -> Result[CallResult, CallError]: result = euklidean_algorithm( - a = command.numbers[0], - b = command.numbers[1], + a = command.numbers[0].__root__, + b = command.numbers[1].__root__, verbose = config.OPTIONS.tsp.verbose, ); return Ok(CallResult(action_taken=True, message=result)); diff --git a/code/python/src/models/euklid.py/__init__.py b/code/python/src/models/euklid/__init__.py similarity index 90% rename from code/python/src/models/euklid.py/__init__.py rename to code/python/src/models/euklid/__init__.py index cee1f46..fd2630f 100644 --- a/code/python/src/models/euklid.py/__init__.py +++ b/code/python/src/models/euklid/__init__.py @@ -5,11 +5,12 @@ # IMPORTS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# from src.models.euklid. import *; +from src.models.euklid.logging import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # EXPORTS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ __all__ = [ + 'Step', ]; diff --git a/code/python/src/models/euklid/logging.py b/code/python/src/models/euklid/logging.py new file mode 100644 index 0000000..086b26c --- /dev/null +++ b/code/python/src/models/euklid/logging.py @@ -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(); From f6401f0dfc286a9fbd7210ecbe30c95abee9cff9 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Mon, 20 Jun 2022 16:49:46 +0200 Subject: [PATCH 04/20] woche12 > master: code py - assets --- code/python/assets/commands.yaml | 29 +++++++++++++++++------------ code/python/assets/config.yaml | 22 +++++++++++++--------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/code/python/assets/commands.yaml b/code/python/assets/commands.yaml index 791ff66..523fa64 100644 --- a/code/python/assets/commands.yaml +++ b/code/python/assets/commands.yaml @@ -89,10 +89,8 @@ 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] + costs: [3, 4, 5, 2, 1] + values: [8, 7, 8, 3, 2] - name: RUCKSACK algorithm: BRANCH-AND-BOUND max-cost: 460 @@ -103,10 +101,8 @@ 'Schokolade', 'Apfelringe', ] - costs: - [220, 80, 140, 90, 100] - values: - [100, 10, 70, 80, 100] + costs: [220, 80, 140, 90, 100] + values: [100, 10, 70, 80, 100] - name: RUCKSACK algorithm: BRANCH-AND-BOUND max-cost: 90 @@ -117,7 +113,16 @@ 'Hirse', 'Sellerie', ] - costs: - [30, 10, 50, 10, 80] - values: - [17, 14, 17, 5, 25] + costs: [30, 10, 50, 10, 80] + values: [17, 14, 17, 5, 25] + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Beispiele für Seminarwoche 12 +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- name: EUKLID + numbers: + - 2017 + - 58 +- name: POLLARD-RHO + number: 534767 diff --git a/code/python/assets/config.yaml b/code/python/assets/config.yaml index a18cf06..75becb8 100644 --- a/code/python/assets/config.yaml +++ b/code/python/assets/config.yaml @@ -26,13 +26,17 @@ options: verbose: - COSTS - MOVES - # show: [] - show: - # - ATOMS - - TREE + show: [] + # show: + # - ATOMS + # - TREE rucksack: - verbose: true - # show: [] - show: - - ALL-WEIGHTS - - ALL-SUMS + verbose: *ref_verbose + show: [] + # show: + # - ALL-WEIGHTS + # - ALL-SUMS + euklid: + verbose: *ref_verbose + pollard-rho: + verbose: *ref_verbose From 15fe1b04d4503f39a6a7ccc94532968cb70248a4 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Mon, 20 Jun 2022 17:24:00 +0200 Subject: [PATCH 05/20] woche12 > master: code py - pollards rho implementiert --- .../src/algorithms/euklid/algorithms.py | 1 - .../src/algorithms/pollard_rho/algorithms.py | 48 +++++++++++++++++-- .../src/algorithms/pollard_rho/display.py | 42 ++++++++++++++++ .../src/endpoints/ep_algorithm_pollard_rho.py | 1 + .../python/src/models/pollard_rho/__init__.py | 16 +++++++ code/python/src/models/pollard_rho/logging.py | 26 ++++++++++ 6 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 code/python/src/models/pollard_rho/__init__.py create mode 100644 code/python/src/models/pollard_rho/logging.py diff --git a/code/python/src/algorithms/euklid/algorithms.py b/code/python/src/algorithms/euklid/algorithms.py index d853809..5befa63 100644 --- a/code/python/src/algorithms/euklid/algorithms.py +++ b/code/python/src/algorithms/euklid/algorithms.py @@ -94,5 +94,4 @@ def euklidean_algorithm( 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; diff --git a/code/python/src/algorithms/pollard_rho/algorithms.py b/code/python/src/algorithms/pollard_rho/algorithms.py index 4b1f56a..0067ca7 100644 --- a/code/python/src/algorithms/pollard_rho/algorithms.py +++ b/code/python/src/algorithms/pollard_rho/algorithms.py @@ -10,8 +10,8 @@ from src.thirdparty.maths import *; from models.generated.config import *; from src.core.utils import *; -# from src.models.pollard_rho import *; -from src.algorithms.euklid.display import *; +from src.models.pollard_rho import *; +from src.algorithms.pollard_rho.display import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # EXPORTS @@ -27,6 +27,48 @@ __all__ = [ def pollard_rho_algorithm( n: int, + x_init: int = 2, verbose: bool = False, ): - return; + d = 1; + x = y = x_init; + steps = []; + steps.append(Step(x=x, y=y)); + success = False; + f = lambda _: fct(_, n=n); + while True: + x = f(x); + y = f(f(y)); + d = math.gcd(abs(x-y), n); + steps.append(Step(x=x, y=y, d=d)); + if d == 1: + continue; + elif d < n: + success = True; + break; + else: + success = False; + break; + + if verbose: + repr = display_table(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; diff --git a/code/python/src/algorithms/pollard_rho/display.py b/code/python/src/algorithms/pollard_rho/display.py index e69de29..7528211 100644 --- a/code/python/src/algorithms/pollard_rho/display.py +++ b/code/python/src/algorithms/pollard_rho/display.py @@ -0,0 +1,42 @@ +#!/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', +]; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHOD display table +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def display_table(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 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; diff --git a/code/python/src/endpoints/ep_algorithm_pollard_rho.py b/code/python/src/endpoints/ep_algorithm_pollard_rho.py index eba2cc4..2d23363 100644 --- a/code/python/src/endpoints/ep_algorithm_pollard_rho.py +++ b/code/python/src/endpoints/ep_algorithm_pollard_rho.py @@ -28,6 +28,7 @@ __all__ = [ def endpoint_pollard_rho(command: CommandPollard) -> Result[CallResult, CallError]: result = pollard_rho_algorithm( n = command.number, + x_init = command.x_init, verbose = config.OPTIONS.tsp.verbose, ); return Ok(CallResult(action_taken=True, message=result)); diff --git a/code/python/src/models/pollard_rho/__init__.py b/code/python/src/models/pollard_rho/__init__.py new file mode 100644 index 0000000..c914672 --- /dev/null +++ b/code/python/src/models/pollard_rho/__init__.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from src.models.pollard_rho.logging import *; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'Step', +]; diff --git a/code/python/src/models/pollard_rho/logging.py b/code/python/src/models/pollard_rho/logging.py new file mode 100644 index 0000000..8819c56 --- /dev/null +++ b/code/python/src/models/pollard_rho/logging.py @@ -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: int = field(); + d: Optional[int] = field(default=None); From 1b73ec263b0ee1c44ef8ded580b869376ba02233 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Mon, 20 Jun 2022 17:24:28 +0200 Subject: [PATCH 06/20] =?UTF-8?q?woche12=20>=20master:=20code=20py=20-=20s?= =?UTF-8?q?chema=20f=C3=BCr=20pollards=20rho=20mit=20x-init?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/python/models/commands-schema.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/python/models/commands-schema.yaml b/code/python/models/commands-schema.yaml index 1e954cc..8b15999 100644 --- a/code/python/models/commands-schema.yaml +++ b/code/python/models/commands-schema.yaml @@ -185,6 +185,10 @@ components: number: type: integer exclusiveMinimum: 0 + x-init: + type: integer + default: 2 + minimum: 2 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Enum Algorithm Names # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From ad354b3b64c093e91bec05075b06662494a4b238 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Mon, 20 Jun 2022 17:24:37 +0200 Subject: [PATCH 07/20] =?UTF-8?q?woche12=20>=20master:=20code=20py=20-=20a?= =?UTF-8?q?ssets=20f=C3=BCr=20pollards=20rho=20mit=20x-init?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/python/assets/commands.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/code/python/assets/commands.yaml b/code/python/assets/commands.yaml index 523fa64..2de94d8 100644 --- a/code/python/assets/commands.yaml +++ b/code/python/assets/commands.yaml @@ -126,3 +126,4 @@ - 58 - name: POLLARD-RHO number: 534767 + x-init: 5 From 48c47f61b74314e0e17e96c757e5dfb50cb15eba Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Mon, 20 Jun 2022 17:33:20 +0200 Subject: [PATCH 08/20] woche12 > master: code py - VERSION up --- code/python/dist/VERSION | 2 +- code/python/models/commands-schema.yaml | 2 +- code/python/models/config-schema.yaml | 2 +- code/python/pyproject.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/python/dist/VERSION b/code/python/dist/VERSION index 0ea3a94..0d91a54 100644 --- a/code/python/dist/VERSION +++ b/code/python/dist/VERSION @@ -1 +1 @@ -0.2.0 +0.3.0 diff --git a/code/python/models/commands-schema.yaml b/code/python/models/commands-schema.yaml index 8b15999..7e36eab 100644 --- a/code/python/models/commands-schema.yaml +++ b/code/python/models/commands-schema.yaml @@ -1,6 +1,6 @@ openapi: 3.0.3 info: - version: 0.2.0 + version: 0.3.0 title: Schemata for command instructions servers: - url: "." diff --git a/code/python/models/config-schema.yaml b/code/python/models/config-schema.yaml index 450ad5f..6383931 100644 --- a/code/python/models/config-schema.yaml +++ b/code/python/models/config-schema.yaml @@ -1,6 +1,6 @@ openapi: 3.0.3 info: - version: 0.2.0 + version: 0.3.0 title: Schemata for config models servers: - url: "." diff --git a/code/python/pyproject.toml b/code/python/pyproject.toml index ecb93f7..2d34469 100644 --- a/code/python/pyproject.toml +++ b/code/python/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uni-leipzig-ads-2-2022" -version = "0.2.0" +version = "0.3.0" description = "Zusatzcode, um Algorithmen und Datenstrukturen im Kurs ADS2 zu demonstrieren." authors = [ "Raj Dahya" ] maintainers = [ "raj_mathe" ] From aaa0b7a12430a9d1a4e0d946610402d5fa959462 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Mon, 20 Jun 2022 17:33:29 +0200 Subject: [PATCH 09/20] woche12 > master: code py - documentation --- code/python/docs/commands/Models/CommandEuklid.md | 10 ++++++++++ code/python/docs/commands/Models/CommandPollard.md | 11 +++++++++++ code/python/docs/commands/Models/CommandRucksack.md | 1 + code/python/docs/commands/README.md | 2 ++ code/python/docs/config/Models/AppOptions.md | 2 ++ 5 files changed, 26 insertions(+) create mode 100644 code/python/docs/commands/Models/CommandEuklid.md create mode 100644 code/python/docs/commands/Models/CommandPollard.md diff --git a/code/python/docs/commands/Models/CommandEuklid.md b/code/python/docs/commands/Models/CommandEuklid.md new file mode 100644 index 0000000..71a8852 --- /dev/null +++ b/code/python/docs/commands/Models/CommandEuklid.md @@ -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) + diff --git a/code/python/docs/commands/Models/CommandPollard.md b/code/python/docs/commands/Models/CommandPollard.md new file mode 100644 index 0000000..8541020 --- /dev/null +++ b/code/python/docs/commands/Models/CommandPollard.md @@ -0,0 +1,11 @@ +# CommandPollard +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**name** | [**EnumAlgorithmNames**](EnumAlgorithmNames.md) | | [default to null] +**number** | [**Integer**](integer.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) + diff --git a/code/python/docs/commands/Models/CommandRucksack.md b/code/python/docs/commands/Models/CommandRucksack.md index bae4f88..f61d4d6 100644 --- a/code/python/docs/commands/Models/CommandRucksack.md +++ b/code/python/docs/commands/Models/CommandRucksack.md @@ -3,6 +3,7 @@ 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] diff --git a/code/python/docs/commands/README.md b/code/python/docs/commands/README.md index d9004fd..54e7d2e 100644 --- a/code/python/docs/commands/README.md +++ b/code/python/docs/commands/README.md @@ -13,7 +13,9 @@ Class | Method | HTTP request | Description ## Documentation for Models - [Command](.//Models/Command.md) + - [CommandEuklid](.//Models/CommandEuklid.md) - [CommandHirschberg](.//Models/CommandHirschberg.md) + - [CommandPollard](.//Models/CommandPollard.md) - [CommandRucksack](.//Models/CommandRucksack.md) - [CommandTarjan](.//Models/CommandTarjan.md) - [CommandTsp](.//Models/CommandTsp.md) diff --git a/code/python/docs/config/Models/AppOptions.md b/code/python/docs/config/Models/AppOptions.md index b100ef5..c2b9d20 100644 --- a/code/python/docs/config/Models/AppOptions.md +++ b/code/python/docs/config/Models/AppOptions.md @@ -9,6 +9,8 @@ Name | Type | Description | Notes **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] +**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) From 3d05f7ae1df64aa6629ee0bd00942a4e90b1757b Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Tue, 21 Jun 2022 17:24:30 +0200 Subject: [PATCH 10/20] =?UTF-8?q?woche12=20>=20master:=20code=20py=20-=20s?= =?UTF-8?q?chemata=20f=C3=BCr=20walks=20+=20genetic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/python/models/commands-schema.yaml | 111 ++++++++++++++++++++++++ code/python/models/config-schema.yaml | 18 ++++ 2 files changed, 129 insertions(+) diff --git a/code/python/models/commands-schema.yaml b/code/python/models/commands-schema.yaml index 7e36eab..3ef6114 100644 --- a/code/python/models/commands-schema.yaml +++ b/code/python/models/commands-schema.yaml @@ -150,6 +150,51 @@ components: 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' + annealing: + 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: @@ -190,6 +235,44 @@ components: default: 2 minimum: 2 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + # Data-type Landscape Geometry, Landscape Values + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + DataTypeLandscapeGeometry: + description: |- + Structure for the geometry of a fitness landscape + type: object + required: + - neighbourhoods + - values + properties: + neighbourhoods: + $ref: '#/components/schemas/DataTypeLandscapeNeighbourhoods' + 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 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EnumAlgorithmNames: @@ -201,6 +284,8 @@ components: - TSP - HIRSCHBERG - RUCKSACK + - RANDOM-WALK + - GENETIC - EUKLID - POLLARD-RHO # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -223,3 +308,29 @@ components: enum: - GREEDY - BRANCH-AND-BOUND + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + # 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 diff --git a/code/python/models/config-schema.yaml b/code/python/models/config-schema.yaml index 6383931..5e1d465 100644 --- a/code/python/models/config-schema.yaml +++ b/code/python/models/config-schema.yaml @@ -54,6 +54,8 @@ components: - tarjan - hirschberg - rucksack + - random-walk + - genetic - euklid - pollard-rho properties: @@ -129,6 +131,22 @@ components: 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: From 17711327ef57b8b88dbf15ae773a9370bbc0564e Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Tue, 21 Jun 2022 17:24:40 +0200 Subject: [PATCH 11/20] =?UTF-8?q?woche12=20>=20master:=20code=20py=20-=20c?= =?UTF-8?q?onfig=20erg=C3=A4nzt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/python/assets/config.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/python/assets/config.yaml b/code/python/assets/config.yaml index 75becb8..5842dfa 100644 --- a/code/python/assets/config.yaml +++ b/code/python/assets/config.yaml @@ -36,6 +36,10 @@ options: # show: # - ALL-WEIGHTS # - ALL-SUMS + genetic: + verbose: *ref_verbose + random-walk: + verbose: *ref_verbose euklid: verbose: *ref_verbose pollard-rho: From 4001551c9ca2ce68baf06afb74fc8dd546675372 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Tue, 21 Jun 2022 17:25:39 +0200 Subject: [PATCH 12/20] =?UTF-8?q?woche12=20>=20master:=20code=20py=20-=20l?= =?UTF-8?q?eere=20EPs=20f=C3=BCr=20walks=20+=20genetic=20hinzugef=C3=BCgt?= =?UTF-8?q?=20(stubs)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../python/src/algorithms/genetic/__init__.py | 16 ++++ .../src/algorithms/genetic/algorithms.py | 38 ++++++++ code/python/src/algorithms/genetic/display.py | 30 +++++++ .../src/algorithms/random_walk/__init__.py | 18 ++++ .../src/algorithms/random_walk/algorithms.py | 75 ++++++++++++++++ .../src/algorithms/random_walk/display.py | 30 +++++++ code/python/src/api.py | 4 + code/python/src/endpoints/__init__.py | 4 + .../src/endpoints/ep_algorithm_euklid.py | 2 +- .../src/endpoints/ep_algorithm_genetic.py | 34 +++++++ .../src/endpoints/ep_algorithm_pollard_rho.py | 2 +- .../src/endpoints/ep_algorithm_random_walk.py | 59 ++++++++++++ .../src/endpoints/ep_algorithm_rucksack.py | 2 +- code/python/src/models/config/commands.py | 4 + code/python/src/models/genetic/__init__.py | 0 .../python/src/models/random_walk/__init__.py | 16 ++++ .../src/models/random_walk/landscape.py | 90 +++++++++++++++++++ code/python/src/thirdparty/misc.py | 4 +- 18 files changed, 424 insertions(+), 4 deletions(-) create mode 100644 code/python/src/algorithms/genetic/__init__.py create mode 100644 code/python/src/algorithms/genetic/algorithms.py create mode 100644 code/python/src/algorithms/genetic/display.py create mode 100644 code/python/src/algorithms/random_walk/__init__.py create mode 100644 code/python/src/algorithms/random_walk/algorithms.py create mode 100644 code/python/src/algorithms/random_walk/display.py create mode 100644 code/python/src/endpoints/ep_algorithm_genetic.py create mode 100644 code/python/src/endpoints/ep_algorithm_random_walk.py create mode 100644 code/python/src/models/genetic/__init__.py create mode 100644 code/python/src/models/random_walk/__init__.py create mode 100644 code/python/src/models/random_walk/landscape.py diff --git a/code/python/src/algorithms/genetic/__init__.py b/code/python/src/algorithms/genetic/__init__.py new file mode 100644 index 0000000..b859d69 --- /dev/null +++ b/code/python/src/algorithms/genetic/__init__.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from src.algorithms.genetic.algorithms import *; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'genetic_algorithm', +]; diff --git a/code/python/src/algorithms/genetic/algorithms.py b/code/python/src/algorithms/genetic/algorithms.py new file mode 100644 index 0000000..5c360b7 --- /dev/null +++ b/code/python/src/algorithms/genetic/algorithms.py @@ -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; diff --git a/code/python/src/algorithms/genetic/display.py b/code/python/src/algorithms/genetic/display.py new file mode 100644 index 0000000..1057a07 --- /dev/null +++ b/code/python/src/algorithms/genetic/display.py @@ -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 ''; diff --git a/code/python/src/algorithms/random_walk/__init__.py b/code/python/src/algorithms/random_walk/__init__.py new file mode 100644 index 0000000..fef358a --- /dev/null +++ b/code/python/src/algorithms/random_walk/__init__.py @@ -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', +]; diff --git a/code/python/src/algorithms/random_walk/algorithms.py b/code/python/src/algorithms/random_walk/algorithms.py new file mode 100644 index 0000000..001b5c4 --- /dev/null +++ b/code/python/src/algorithms/random_walk/algorithms.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from src.thirdparty.types import *; +from src.thirdparty.maths 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', +]; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHOD adaptive walk +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def adaptive_walk_algorithm( + landscape: Landscape, + r: float, + optimise: EnumOptimiseMode, + verbose: bool, +): + ''' + Führt den Adapative-Walk Algorithmus aus, um ein lokales Minimum zu bestimmen. + ''' + log_warn('Noch nicht implementiert!'); + return; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHOD gradient walk +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def gradient_walk_algorithm( + landscape: Landscape, + r: float, + optimise: EnumOptimiseMode, + verbose: bool, +): + ''' + Führt den Gradient-Descent (bzw. Ascent) Algorithmus aus, um ein lokales Minimum zu bestimmen. + ''' + log_warn('Noch nicht implementiert!'); + return; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHOD metropolis walk +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def metropolis_walk_algorithm( + landscape: Landscape, + r: float, + annealing: bool, + optimise: EnumOptimiseMode, + verbose: bool, +): + ''' + Führt den Metropolis-Walk Algorithmus aus, um ein lokales Minimum zu bestimmen. + ''' + log_warn('Noch nicht implementiert!'); + return; diff --git a/code/python/src/algorithms/random_walk/display.py b/code/python/src/algorithms/random_walk/display.py new file mode 100644 index 0000000..a929937 --- /dev/null +++ b/code/python/src/algorithms/random_walk/display.py @@ -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 ''; diff --git a/code/python/src/api.py b/code/python/src/api.py index 6d3239c..984e489 100644 --- a/code/python/src/api.py +++ b/code/python/src/api.py @@ -40,6 +40,10 @@ def run_command(command: Command) -> Result[CallResult, CallError]: return endpoint_hirschberg(command); elif isinstance(command, CommandRucksack): return endpoint_rucksack(command); + elif isinstance(command, CommandRandomWalk): + return endpoint_random_walk(command); + elif isinstance(command, CommandGenetic): + return endpoint_genetic(command); elif isinstance(command, CommandEuklid): return endpoint_euklid(command); elif isinstance(command, CommandPollard): diff --git a/code/python/src/endpoints/__init__.py b/code/python/src/endpoints/__init__.py index cfb4e27..1bb1e79 100644 --- a/code/python/src/endpoints/__init__.py +++ b/code/python/src/endpoints/__init__.py @@ -9,6 +9,8 @@ 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 *; @@ -21,6 +23,8 @@ __all__ = [ 'endpoint_tarjan', 'endpoint_tsp', 'endpoint_rucksack', + 'endpoint_random_walk', + 'endpoint_genetic', 'endpoint_euklid', 'endpoint_pollard_rho', ]; diff --git a/code/python/src/endpoints/ep_algorithm_euklid.py b/code/python/src/endpoints/ep_algorithm_euklid.py index 79aece4..2794710 100644 --- a/code/python/src/endpoints/ep_algorithm_euklid.py +++ b/code/python/src/endpoints/ep_algorithm_euklid.py @@ -29,6 +29,6 @@ def endpoint_euklid(command: CommandEuklid) -> Result[CallResult, CallError]: result = euklidean_algorithm( a = command.numbers[0].__root__, b = command.numbers[1].__root__, - verbose = config.OPTIONS.tsp.verbose, + verbose = config.OPTIONS.euklid.verbose, ); return Ok(CallResult(action_taken=True, message=result)); diff --git a/code/python/src/endpoints/ep_algorithm_genetic.py b/code/python/src/endpoints/ep_algorithm_genetic.py new file mode 100644 index 0000000..bac82d1 --- /dev/null +++ b/code/python/src/endpoints/ep_algorithm_genetic.py @@ -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)); diff --git a/code/python/src/endpoints/ep_algorithm_pollard_rho.py b/code/python/src/endpoints/ep_algorithm_pollard_rho.py index 2d23363..4674c9c 100644 --- a/code/python/src/endpoints/ep_algorithm_pollard_rho.py +++ b/code/python/src/endpoints/ep_algorithm_pollard_rho.py @@ -29,6 +29,6 @@ def endpoint_pollard_rho(command: CommandPollard) -> Result[CallResult, CallErro result = pollard_rho_algorithm( n = command.number, x_init = command.x_init, - verbose = config.OPTIONS.tsp.verbose, + verbose = config.OPTIONS.pollard_rho.verbose, ); return Ok(CallResult(action_taken=True, message=result)); diff --git a/code/python/src/endpoints/ep_algorithm_random_walk.py b/code/python/src/endpoints/ep_algorithm_random_walk.py new file mode 100644 index 0000000..37b5953 --- /dev/null +++ b/code/python/src/endpoints/ep_algorithm_random_walk.py @@ -0,0 +1,59 @@ +#!/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]: + landscape = Landscape( + values = command.landscape.values, + metric = command.landscape.neighbourhoods.metric, + ); + match command.algorithm: + case EnumWalkMode.adaptive: + result = adaptive_walk_algorithm( + landscape = landscape, + r = command.landscape.neighbourhoods.radius, + optimise = command.optimise, + verbose = config.OPTIONS.random_walk.verbose + ); + case EnumWalkMode.gradient: + result = gradient_walk_algorithm( + landscape = landscape, + r = command.landscape.neighbourhoods.radius, + optimise = command.optimise, + verbose = config.OPTIONS.random_walk.verbose + ); + case EnumWalkMode.metropolis: + result = metropolis_walk_algorithm( + landscape = landscape, + r = command.landscape.neighbourhoods.radius, + 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)); diff --git a/code/python/src/endpoints/ep_algorithm_rucksack.py b/code/python/src/endpoints/ep_algorithm_rucksack.py index 0fa4793..9f800c1 100644 --- a/code/python/src/endpoints/ep_algorithm_rucksack.py +++ b/code/python/src/endpoints/ep_algorithm_rucksack.py @@ -50,5 +50,5 @@ def endpoint_rucksack(command: CommandRucksack) -> Result[CallResult, CallError] verbose = config.OPTIONS.rucksack.verbose, ); case _ as alg: - raise Exception(f'No algorithm implemented for {alg.value}.') + raise Exception(f'No algorithm implemented for {alg.value}.'); return Ok(CallResult(action_taken=True, message=result)); diff --git a/code/python/src/models/config/commands.py b/code/python/src/models/config/commands.py index 39e0b4a..9d1eb51 100644 --- a/code/python/src/models/config/commands.py +++ b/code/python/src/models/config/commands.py @@ -44,6 +44,10 @@ def interpret_command(command: Command) -> Command: return CommandHirschberg(**command.dict()); case EnumAlgorithmNames.rucksack: return CommandRucksack(**command.dict()); + case EnumAlgorithmNames.random_walk: + return CommandRandomWalk(**command.dict()); + case EnumAlgorithmNames.genetic: + return CommandGenetic(**command.dict()); case EnumAlgorithmNames.euklid: return CommandEuklid(**command.dict()); case EnumAlgorithmNames.pollard_rho: diff --git a/code/python/src/models/genetic/__init__.py b/code/python/src/models/genetic/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/code/python/src/models/random_walk/__init__.py b/code/python/src/models/random_walk/__init__.py new file mode 100644 index 0000000..a5bdd2f --- /dev/null +++ b/code/python/src/models/random_walk/__init__.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from src.models.random_walk.landscape import *; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'Landscape', +]; diff --git a/code/python/src/models/random_walk/landscape.py b/code/python/src/models/random_walk/landscape.py new file mode 100644 index 0000000..131a941 --- /dev/null +++ b/code/python/src/models/random_walk/landscape.py @@ -0,0 +1,90 @@ +#!/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; + _metric: EnumLandscapeMetric; + _radius: float; + + def __init__( + self, + values: DataTypeLandscapeValues, + metric: EnumLandscapeMetric = EnumLandscapeMetric.maximum, + ): + self._fct = convert_to_nparray(values); + self._metric = metric; + return; + + @property + def shape(self) -> tuple: + return self._fct.shape; + + @property + def dim(self) -> int: + return len(self._fct.shape); + + def fitness(self, *x: int) -> float: + return self._fct[x]; + + def neighbourhood(self, *x: int, r: float, strict: bool = False) -> List[tuple]: + 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.'); diff --git a/code/python/src/thirdparty/misc.py b/code/python/src/thirdparty/misc.py index 8476b32..1aa4dd4 100644 --- a/code/python/src/thirdparty/misc.py +++ b/code/python/src/thirdparty/misc.py @@ -7,6 +7,7 @@ from datetime import datetime; from datetime import timedelta; +from itertools import product as itertools_product; import lorem; import re; from textwrap import dedent; @@ -16,9 +17,10 @@ from textwrap import dedent; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ __all__ = [ - 'lorem', 'datetime', 'timedelta', + 'itertools_product', + 'lorem', 're', 'dedent', ]; From 01ef8c5758653b5dd7303cc0c6ed2ddac1eb26fe Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Tue, 21 Jun 2022 19:01:13 +0200 Subject: [PATCH 13/20] woche12 > master: code py - schema --- code/python/models/commands-schema.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/code/python/models/commands-schema.yaml b/code/python/models/commands-schema.yaml index 3ef6114..753eac2 100644 --- a/code/python/models/commands-schema.yaml +++ b/code/python/models/commands-schema.yaml @@ -170,9 +170,21 @@ components: $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 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -243,10 +255,16 @@ components: 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: From c2cb11a141a9d2501473e1b72d227e95d8d53493 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Tue, 21 Jun 2022 19:01:59 +0200 Subject: [PATCH 14/20] =?UTF-8?q?woche12=20>=20master:=20code=20py=20-=20v?= =?UTF-8?q?orberechnungen=20gem=C3=A4=C3=9F=20modell?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/endpoints/ep_algorithm_random_walk.py | 16 +++++++++++++ .../src/models/random_walk/landscape.py | 24 +++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/code/python/src/endpoints/ep_algorithm_random_walk.py b/code/python/src/endpoints/ep_algorithm_random_walk.py index 37b5953..0324f03 100644 --- a/code/python/src/endpoints/ep_algorithm_random_walk.py +++ b/code/python/src/endpoints/ep_algorithm_random_walk.py @@ -27,15 +27,28 @@ __all__ = [ @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 ); @@ -43,6 +56,7 @@ def endpoint_random_walk(command: CommandRandomWalk) -> Result[CallResult, CallE result = gradient_walk_algorithm( landscape = landscape, r = command.landscape.neighbourhoods.radius, + coords_init = coords_init, optimise = command.optimise, verbose = config.OPTIONS.random_walk.verbose ); @@ -50,6 +64,8 @@ def endpoint_random_walk(command: CommandRandomWalk) -> Result[CallResult, CallE 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 diff --git a/code/python/src/models/random_walk/landscape.py b/code/python/src/models/random_walk/landscape.py index 131a941..dad9239 100644 --- a/code/python/src/models/random_walk/landscape.py +++ b/code/python/src/models/random_walk/landscape.py @@ -27,16 +27,23 @@ __all__ = [ 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 @@ -47,14 +54,27 @@ class Landscape(): 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); + def fitness(self, *x: int) -> float: return self._fct[x]; + 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 - 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) ] + + [ 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: From 5c4341989037f2870702434524751c356b6d8128 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Tue, 21 Jun 2022 19:02:41 +0200 Subject: [PATCH 15/20] woche12 > master: code py - imports von random methoden --- code/python/src/thirdparty/maths.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/python/src/thirdparty/maths.py b/code/python/src/thirdparty/maths.py index 8bf9eef..86b5ac4 100644 --- a/code/python/src/thirdparty/maths.py +++ b/code/python/src/thirdparty/maths.py @@ -10,6 +10,8 @@ import math; import numpy as np; import pandas as pd; import random; +from random import uniform; +from random import choice as uniform_random_choice; from tabulate import tabulate; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -22,5 +24,7 @@ __all__ = [ 'np', 'pd', 'random', + 'uniform', + 'uniform_random_choice', 'tabulate', ]; From a7c7179edb09dff21a45bb2322893cfcec5af397 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Tue, 21 Jun 2022 19:02:59 +0200 Subject: [PATCH 16/20] woche12 > master: code py - rohe implementierung der walks --- .../src/algorithms/random_walk/algorithms.py | 143 +++++++++++++++++- 1 file changed, 137 insertions(+), 6 deletions(-) diff --git a/code/python/src/algorithms/random_walk/algorithms.py b/code/python/src/algorithms/random_walk/algorithms.py index 001b5c4..7a8ed45 100644 --- a/code/python/src/algorithms/random_walk/algorithms.py +++ b/code/python/src/algorithms/random_walk/algorithms.py @@ -32,14 +32,50 @@ __all__ = [ 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. ''' - log_warn('Noch nicht implementiert!'); - return; + + # 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 + x = coords_init; + fx = f(x); + fy = fx; + N = nbhd(x); + + # führe walk aus: + while True: + # 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); + else: + # Nichts machen! + pass; + + # Nur dann (erfolgreich) abbrechen, wenn f-Wert lokal Min: + if fx <= min([f(y) for y in N], default=fx): + break; + + return x; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # METHOD gradient walk @@ -48,14 +84,56 @@ def adaptive_walk_algorithm( 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. ''' - log_warn('Noch nicht implementiert!'); - return; + + # 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 + 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: + while True: + # 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]; + else: + # Nichts machen! + pass; + + # Nur dann (erfolgreich) abbrechen, wenn f-Wert lokal Min: + if fx <= min([f(y) for y in N], default=fx): + break; + + return x; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # METHOD metropolis walk @@ -64,6 +142,8 @@ def gradient_walk_algorithm( def metropolis_walk_algorithm( landscape: Landscape, r: float, + coords_init: tuple, + T: float, annealing: bool, optimise: EnumOptimiseMode, verbose: bool, @@ -71,5 +151,56 @@ def metropolis_walk_algorithm( ''' Führt den Metropolis-Walk Algorithmus aus, um ein lokales Minimum zu bestimmen. ''' - log_warn('Noch nicht implementiert!'); - return; + + # 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 + x = coords_init; + fx = f(x); + fy = fx; + nbhd_x = nbhd(x); + + # führe walk aus: + k = 0; + while True: + # Wähle zufälligen Punkt und berechne fitness-Wert: + y = uniform_random_choice(nbhd_x); + r = uniform(0,1); + fy = f(y); + + # Nur dann aktualisieren, wenn sich f-Wert verbessert: + if fy < fx or r < math.exp(-(fy-fx)/T): + # Punkt + Umgebung + f-Wert aktualisieren + x = y; + fx = fy; + nbhd_x = nbhd(x); + else: + # Nichts machen! + pass; + + # »Temperatur« ggf. abkühlen: + if annealing: + T = cool_temperature(T, k); + + # Nur dann (erfolgreich) abbrechen, wenn f-Wert lokal Min: + if fx <= min([f(y) for y in nbhd_x], default=fx): + break; + + k += 1; + + return x; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# AUXILIARY METHODS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def cool_temperature(T: float, k: int, const: float = 1.) -> float: + harm = const*(k + 1); + return T/(1 + T/harm); From 1e934dc3efbee2830298274bdd1063e9b94a524f Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Thu, 30 Jun 2022 05:42:54 +0200 Subject: [PATCH 17/20] =?UTF-8?q?woche12=20>=20master:=20code=20py=20-=20t?= =?UTF-8?q?hirdparty=20imports=20f=C3=BCr=20mathe+plots?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/python/src/thirdparty/maths.py | 4 ++++ code/python/src/thirdparty/plots.py | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 code/python/src/thirdparty/plots.py diff --git a/code/python/src/thirdparty/maths.py b/code/python/src/thirdparty/maths.py index 86b5ac4..21f4cce 100644 --- a/code/python/src/thirdparty/maths.py +++ b/code/python/src/thirdparty/maths.py @@ -8,6 +8,8 @@ from fractions import Fraction; import math; import numpy as np; +from numpy.random import binomial as random_binomial; +random_binary = lambda p: (random_binomial(1, p) == 1); import pandas as pd; import random; from random import uniform; @@ -22,6 +24,8 @@ __all__ = [ 'Fraction', 'math', 'np', + 'random_binomial', + 'random_binary', 'pd', 'random', 'uniform', diff --git a/code/python/src/thirdparty/plots.py b/code/python/src/thirdparty/plots.py new file mode 100644 index 0000000..c05a8fe --- /dev/null +++ b/code/python/src/thirdparty/plots.py @@ -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', +]; From 7b456d177eb7d88ba57a6eee8d0823110576734c Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Thu, 30 Jun 2022 05:43:10 +0200 Subject: [PATCH 18/20] =?UTF-8?q?woche12=20>=20master:=20code=20py=20-=20l?= =?UTF-8?q?ogging=20f=C3=BCr=20random=20walk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../python/src/models/random_walk/__init__.py | 2 ++ code/python/src/models/random_walk/logging.py | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 code/python/src/models/random_walk/logging.py diff --git a/code/python/src/models/random_walk/__init__.py b/code/python/src/models/random_walk/__init__.py index a5bdd2f..250313e 100644 --- a/code/python/src/models/random_walk/__init__.py +++ b/code/python/src/models/random_walk/__init__.py @@ -6,6 +6,7 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ from src.models.random_walk.landscape import *; +from src.models.random_walk.logging import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # EXPORTS @@ -13,4 +14,5 @@ from src.models.random_walk.landscape import *; __all__ = [ 'Landscape', + 'Step', ]; diff --git a/code/python/src/models/random_walk/logging.py b/code/python/src/models/random_walk/logging.py new file mode 100644 index 0000000..3bf8953 --- /dev/null +++ b/code/python/src/models/random_walk/logging.py @@ -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); From 2bd07544f35466d42627efcb75537b862181a9f9 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Thu, 30 Jun 2022 05:44:16 +0200 Subject: [PATCH 19/20] =?UTF-8?q?woche12=20>=20master:=20code=20py=20-=20r?= =?UTF-8?q?andom=20walks=20erg=C3=A4nzt=20-=20stopkriterien=20-=20logging?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/algorithms/random_walk/algorithms.py | 71 +++++++++++++++---- .../src/models/random_walk/landscape.py | 14 ++++ 2 files changed, 70 insertions(+), 15 deletions(-) diff --git a/code/python/src/algorithms/random_walk/algorithms.py b/code/python/src/algorithms/random_walk/algorithms.py index 7a8ed45..744b594 100644 --- a/code/python/src/algorithms/random_walk/algorithms.py +++ b/code/python/src/algorithms/random_walk/algorithms.py @@ -5,8 +5,9 @@ # IMPORTS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -from src.thirdparty.types import *; 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 *; @@ -25,6 +26,12 @@ __all__ = [ 'metropolis_walk_algorithm', ]; +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# CONSTANTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +MAX_ITERATIONS = 1000; # um endlose Schleifen zu verhindern + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # METHOD adaptive walk # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -50,13 +57,15 @@ def adaptive_walk_algorithm( label = lambda x: landscape.label(*x); # initialisiere + steps = []; x = coords_init; fx = f(x); fy = fx; N = nbhd(x); # führe walk aus: - while True: + k = 0; + while k < MAX_ITERATIONS: # Wähle zufälligen Punkt und berechne fitness-Wert: y = uniform_random_choice(N); fy = f(y); @@ -67,14 +76,20 @@ def adaptive_walk_algorithm( x = y; fx = fy; N = nbhd(x); + step = Step(coords=x, label=label(x), improved=True, changed=True); else: - # Nichts machen! - pass; + # 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; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -102,6 +117,7 @@ def gradient_walk_algorithm( label = lambda x: landscape.label(*x); # initialisiere + steps = []; x = coords_init; fx = landscape.fitness(*x); fy = fx; @@ -111,7 +127,8 @@ def gradient_walk_algorithm( Z = [y for y, fy in zip(N, f_values) if fy == fmin]; # führe walk aus: - while True: + 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; @@ -125,14 +142,20 @@ def gradient_walk_algorithm( 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 machen! - pass; + # 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; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -161,46 +184,64 @@ def metropolis_walk_algorithm( 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; - while True: + n_unchanged = 0; + while k < MAX_ITERATIONS: # Wähle zufälligen Punkt und berechne fitness-Wert: y = uniform_random_choice(nbhd_x); - r = uniform(0,1); fy = f(y); + p = math.exp(-abs(fy-fx)/T); + u = random_binary(p); - # Nur dann aktualisieren, wenn sich f-Wert verbessert: - if fy < fx or r < math.exp(-(fy-fx)/T): + # 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 machen! - pass; + # 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 fx <= min([f(y) for y in nbhd_x], default=fx): + 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 = 1.) -> float: +def cool_temperature(T: float, k: int, const: float = 2.) -> float: harm = const*(k + 1); return T/(1 + T/harm); diff --git a/code/python/src/models/random_walk/landscape.py b/code/python/src/models/random_walk/landscape.py index dad9239..9332daa 100644 --- a/code/python/src/models/random_walk/landscape.py +++ b/code/python/src/models/random_walk/landscape.py @@ -58,9 +58,23 @@ class Landscape(): 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); From 7d07f4317ef7f5ee0e854bf9a6615b8b33042b7c Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Thu, 30 Jun 2022 06:24:10 +0200 Subject: [PATCH 20/20] =?UTF-8?q?woche12=20>=20master:=20code=20py=20-=20p?= =?UTF-8?q?ollards=20rho=20mit=20log-wachstum=20f=C3=BCr=20y?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/algorithms/pollard_rho/algorithms.py | 29 ++++++++++++++----- .../src/algorithms/pollard_rho/display.py | 4 +-- code/python/src/models/pollard_rho/logging.py | 2 +- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/code/python/src/algorithms/pollard_rho/algorithms.py b/code/python/src/algorithms/pollard_rho/algorithms.py index 0067ca7..493d9ca 100644 --- a/code/python/src/algorithms/pollard_rho/algorithms.py +++ b/code/python/src/algorithms/pollard_rho/algorithms.py @@ -30,24 +30,37 @@ def pollard_rho_algorithm( x_init: int = 2, verbose: bool = False, ): - d = 1; - x = y = x_init; steps = []; - steps.append(Step(x=x, y=y)); 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); - y = f(f(y)); + # 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)); - if d == 1: + + # Abbruchkriterien prüfen: + if d == 1: # weitermachen, solange d == 1 + k += 1; continue; - elif d < n: - success = True; + elif d == n: # versagt + success = False; break; else: - success = False; + success = True; break; if verbose: diff --git a/code/python/src/algorithms/pollard_rho/display.py b/code/python/src/algorithms/pollard_rho/display.py index 7528211..6ff792e 100644 --- a/code/python/src/algorithms/pollard_rho/display.py +++ b/code/python/src/algorithms/pollard_rho/display.py @@ -27,14 +27,14 @@ def display_table(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 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)'], + headers=['i', 'x(i)', 'y(i) = x([log₂(i)])', 'gcd(|x - y|,n)'], showindex=False, colalign=('right', 'right', 'right', 'center'), tablefmt='simple', diff --git a/code/python/src/models/pollard_rho/logging.py b/code/python/src/models/pollard_rho/logging.py index 8819c56..0bc4463 100644 --- a/code/python/src/models/pollard_rho/logging.py +++ b/code/python/src/models/pollard_rho/logging.py @@ -22,5 +22,5 @@ __all__ = [ @dataclass class Step(): x: int = field(); - y: int = field(); + y: Optional[int] = field(default=None); d: Optional[int] = field(default=None);