diff --git a/code/python/models/commands-schema.yaml b/code/python/models/commands-schema.yaml index 753eac2..c7f43c1 100644 --- a/code/python/models/commands-schema.yaml +++ b/code/python/models/commands-schema.yaml @@ -235,6 +235,7 @@ components: type: object required: - name + - growth - number properties: name: @@ -242,6 +243,8 @@ components: number: type: integer exclusiveMinimum: 0 + growth: + $ref: '#/components/schemas/EnumPollardGrowthRate' x-init: type: integer default: 2 @@ -327,6 +330,21 @@ components: - GREEDY - BRANCH-AND-BOUND # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + # Enum Type for choice of growth rate in Pollard Algorithm + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + EnumPollardGrowthRate: + description: |- + Via the 'tail-chasing' period finding method in Pollard's rho algorithm, + the difference between the indexes of the pseudo-random sequence + can be chosen to growth according to different rates, e.g. + + - `LINEAR` - choose `x[k]` and `x[2k]` + - `EXPONENTIAL` - choose `x[k]` and `x[2^{k}]` + type: string + enum: + - LINEAR + - EXPONENTIAL + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Enum Type of walk mode for fitness walk algorithm # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EnumWalkMode: diff --git a/code/python/src/algorithms/pollard_rho/__init__.py b/code/python/src/algorithms/pollard_rho/__init__.py index b072b7e..02e9d53 100644 --- a/code/python/src/algorithms/pollard_rho/__init__.py +++ b/code/python/src/algorithms/pollard_rho/__init__.py @@ -12,5 +12,6 @@ from src.algorithms.pollard_rho.algorithms import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ __all__ = [ - 'pollard_rho_algorithm', + 'pollard_rho_algorithm_linear', + 'pollard_rho_algorithm_exponential', ]; diff --git a/code/python/src/algorithms/pollard_rho/algorithms.py b/code/python/src/algorithms/pollard_rho/algorithms.py index 493d9ca..814b26d 100644 --- a/code/python/src/algorithms/pollard_rho/algorithms.py +++ b/code/python/src/algorithms/pollard_rho/algorithms.py @@ -18,14 +18,71 @@ from src.algorithms.pollard_rho.display import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ __all__ = [ - 'pollard_rho_algorithm', + 'pollard_rho_algorithm_linear', + 'pollard_rho_algorithm_exponential', ]; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# METHOD pollard's rho algorithm +# METHOD pollard's rho algorithm - with linear grwoth # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -def pollard_rho_algorithm( +def pollard_rho_algorithm_linear( + n: int, + x_init: int = 2, + verbose: bool = False, +): + steps = []; + success = False; + f = lambda _: fct(_, n=n); + + d = 1; + x = y = x_init; + steps.append(Step(x=x)); + k = 0; + k_next = 1; + + while True: + # aktualisiere x: x = f(x_prev): + x = f(x); + # aktualisiere y: y = f(f(y_prev)): + y = f(f(y)); + + # ggT berechnen: + d = math.gcd(abs(x-y), n); + steps.append(Step(x=x, y=y, d=d)); + + # Abbruchkriterien prüfen: + if d == 1: # weitermachen, solange d == 1 + k += 1; + continue; + elif d == n: # versagt + success = False; + break; + else: + success = True; + break; + + if verbose: + repr = display_table_linear(steps=steps); + print(''); + print('\x1b[1mEuklidescher Algorithmus\x1b[0m'); + print(''); + print(repr); + print(''); + if success: + print('\x1b[1mBerechneter Faktor:\x1b[0m'); + print(''); + print(f'd = \x1b[1m{d}\x1b[0m.'); + else: + print('\x1b[91mKein (Prim)faktor erkannt!\x1b[0m'); + print(''); + return d; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHOD pollard's rho algorithm - with exponential grwoth +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def pollard_rho_algorithm_exponential( n: int, x_init: int = 2, verbose: bool = False, @@ -64,7 +121,7 @@ def pollard_rho_algorithm( break; if verbose: - repr = display_table(steps=steps); + repr = display_table_exponential(steps=steps); print(''); print('\x1b[1mEuklidescher Algorithmus\x1b[0m'); print(''); diff --git a/code/python/src/algorithms/pollard_rho/display.py b/code/python/src/algorithms/pollard_rho/display.py index 6ff792e..f913fdf 100644 --- a/code/python/src/algorithms/pollard_rho/display.py +++ b/code/python/src/algorithms/pollard_rho/display.py @@ -16,14 +16,37 @@ from src.models.pollard_rho import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ __all__ = [ - 'display_table', + 'display_table_linear', + 'display_table_exponential', ]; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# METHOD display table +# METHOD display table - linear # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -def display_table(steps: List[Step]) -> str: +def display_table_linear(steps: List[Step]) -> str: + table = pd.DataFrame({ + 'i': [i for i in range(len(steps))], + 'x': [step.x for step in steps], + 'y': [step.y or '-' for step in steps], + 'd': [step.d or '-' for step in steps], + }) \ + .reset_index(drop=True); + # benutze pandas-Dataframe + tabulate, um schöner darzustellen: + repr = tabulate( + table, + headers=['i', 'x(i)', 'y(i) = x(2i)', 'gcd(|x - y|,n)'], + showindex=False, + colalign=('right', 'right', 'right', 'center'), + tablefmt='simple', + ); + return repr; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHOD display table - exponential +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def display_table_exponential(steps: List[Step]) -> str: table = pd.DataFrame({ 'i': [i for i in range(len(steps))], 'x': [step.x for step in steps], diff --git a/code/python/src/endpoints/ep_algorithm_pollard_rho.py b/code/python/src/endpoints/ep_algorithm_pollard_rho.py index 4674c9c..6bcc154 100644 --- a/code/python/src/endpoints/ep_algorithm_pollard_rho.py +++ b/code/python/src/endpoints/ep_algorithm_pollard_rho.py @@ -26,9 +26,21 @@ __all__ = [ @run_safely() def endpoint_pollard_rho(command: CommandPollard) -> Result[CallResult, CallError]: - result = pollard_rho_algorithm( - n = command.number, - x_init = command.x_init, - verbose = config.OPTIONS.pollard_rho.verbose, - ); + match command.growth: + case EnumPollardGrowthRate.linear: + result = pollard_rho_algorithm_linear( + n = command.number, + x_init = command.x_init, + verbose = config.OPTIONS.pollard_rho.verbose, + ); + pass; + case EnumPollardGrowthRate.exponential: + result = pollard_rho_algorithm_exponential( + n = command.number, + x_init = command.x_init, + verbose = config.OPTIONS.pollard_rho.verbose, + ); + pass; + case _ as growth: + raise Exception(f'No algorithm implemented for \x1b[1m{growth.value}\x1b[0m as growth rate.'); return Ok(CallResult(action_taken=True, message=result));