Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/python docstrings for sd estimator #176

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .ball_collision import BallCollision
from .ball_collision import BallCollision
from .bjmm_dw import BJMMdw
from .bjmm_pdw import BJMMpdw
from .bjmm import BJMM, BJMMd2, BJMMd3
Expand Down
120 changes: 67 additions & 53 deletions cryptographic_estimators/SDEstimator/SDAlgorithms/ball_collision.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,43 +19,47 @@
from ...base_algorithm import optimal_parameter
from ...SDEstimator.sd_algorithm import SDAlgorithm
from ...SDEstimator.sd_problem import SDProblem
from ...SDEstimator.sd_helper import _gaussian_elimination_complexity, _mem_matrix, _list_merge_complexity, binom, log2, inf, min_max
from ...SDEstimator.sd_helper import (
_gaussian_elimination_complexity,
_mem_matrix,
_list_merge_complexity,
binom,
log2,
inf,
min_max,
)
from types import SimpleNamespace
from ..sd_constants import *
from ..SDWorkfactorModels.ball_collision import BallCollisionScipyModel


class BallCollision(SDAlgorithm):
def __init__(self, problem: SDProblem, **kwargs):
"""
Complexity estimate of the ball collision decoding algorithm
"""Complexity estimate of the ball collision decoding algorithm.

Introduced in [BLP11]_.

expected weight distribution::
Expected weight distribution:

+------------------+---------+---------+-------------+-------------+
| <-+ n - k - l +->|<- l/2 ->|<- l/2 ->|<--+ k/2 +-->|<--+ k/2 +-->|
| w - 2p - 2pl | pl | pl | p | p |
+------------------+---------+---------+-------------+-------------+

INPUT:

- ``problem`` -- SDProblem object including all necessary parameters
Args:
problem (SDProblem): An SDProblem object including all necessary parameters.

EXAMPLES::

sage: from cryptographic_estimators.SDEstimator.SDAlgorithms import BallCollision
sage: from cryptographic_estimators.SDEstimator import SDProblem
sage: BallCollision(SDProblem(n=100,k=50,w=10))
Examples:
>>> from cryptographic_estimators.SDEstimator.SDAlgorithms import BallCollision
>>> from cryptographic_estimators.SDEstimator import SDProblem
>>> BallCollision(SDProblem(n=100,k=50,w=10))
Ball Collision estimator for syndrome decoding problem with (n,k,w) = (100,50,10) over Finite Field of size 2

"""
super(BallCollision, self).__init__(problem, **kwargs)
n, k, w = self.problem.get_parameters()

self.set_parameter_ranges("p", 0, w // 2)
self._name="BallCollision"
self._name = "BallCollision"
s = self.full_domain
self.set_parameter_ranges("l", 0, min_max(300, n - k, s))
self.set_parameter_ranges("pl", 0, min_max(10, w, s))
Expand All @@ -65,80 +69,92 @@ def __init__(self, problem: SDProblem, **kwargs):

@optimal_parameter
def l(self):
"""
Return the optimal parameter $l$ used in the algorithm optimization

EXAMPLES::
"""Return the optimal parameter $l$ used in the algorithm optimization.

sage: from cryptographic_estimators.SDEstimator.SDAlgorithms import BallCollision
sage: from cryptographic_estimators.SDEstimator import SDProblem
sage: A = BallCollision(SDProblem(n=100,k=50,w=10))
sage: A.l()
Examples:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does this napoleon extension for sphincs work? standard html doc generation via sphincs required capital spelling of EXAMPLES and TESTS and a double colon followed by a blank line? Maybe we should investigate this first to avoid later changes?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Napoleon creates and intermediary step to create the appropriate docstring expected by Sphinx.

>>> from cryptographic_estimators.SDEstimator.SDAlgorithms import BallCollision
>>> from cryptographic_estimators.SDEstimator import SDProblem
>>> A = BallCollision(SDProblem(n=100,k=50,w=10))
>>> A.l()
7
"""
return self._get_optimal_parameter("l")

@optimal_parameter
def p(self):
"""
Return the optimal parameter $p$ used in the algorithm optimization

EXAMPLES::
"""Return the optimal parameter $p$ used in the algorithm optimization.

sage: from cryptographic_estimators.SDEstimator.SDAlgorithms import BallCollision
sage: from cryptographic_estimators.SDEstimator import SDProblem
sage: A = BallCollision(SDProblem(n=100,k=50,w=10))
sage: A.p()
Examples:
>>> from cryptographic_estimators.SDEstimator.SDAlgorithms import BallCollision
>>> from cryptographic_estimators.SDEstimator import SDProblem
>>> A = BallCollision(SDProblem(n=100,k=50,w=10))
>>> A.p()
2
"""
return self._get_optimal_parameter("p")

@optimal_parameter
def pl(self):
"""
Return the optimal parameter $pl$ used in the algorithm optimization
"""Return the optimal parameter $pl$ used in the algorithm optimization.

sage: from cryptographic_estimators.SDEstimator.SDAlgorithms import BallCollision
sage: from cryptographic_estimators.SDEstimator import SDProblem
sage: A = BallCollision(SDProblem(n=100,k=50,w=10))
sage: A.pl()
Examples:
>>> from cryptographic_estimators.SDEstimator.SDAlgorithms import BallCollision
>>> from cryptographic_estimators.SDEstimator import SDProblem
>>> A = BallCollision(SDProblem(n=100,k=50,w=10))
>>> A.pl()
0

"""
return self._get_optimal_parameter("pl")

def _are_parameters_invalid(self, parameters: dict):
"""
return if the parameter set `parameters` is invalid
"""Returns whether the provided parameter set is invalid.

Args:
parameters (dict): The parameter set to be checked.

Returns:
bool: True if the parameter set is invalid, False otherwise.
"""
n, k, w = self.problem.get_parameters()
par = SimpleNamespace(**parameters)
k1 = k // 2
if par.p > w // 2 or k1 < par.p or par.pl > par.l // 2 or n - k - par.l < w - 2 * par.p - 2 * par.pl or w < 2 * par.p + 2 * par.pl:
if (
par.p > w // 2
or k1 < par.p
or par.pl > par.l // 2
or n - k - par.l < w - 2 * par.p - 2 * par.pl
or w < 2 * par.p + 2 * par.pl
):
return True
return False

def _valid_choices(self):
"""
Generator which yields on each call a new set of valid parameters based on the `_parameter_ranges` and already
set parameters in `_optimal_parameters`
"""Generator which yields on each call a new set of valid parameters based on the `_parameter_ranges` and already set parameters in `_optimal_parameters`.
"""
new_ranges = self._fix_ranges_for_already_set_parameters()
n, k, w = self.problem.get_parameters()
start_p = new_ranges["p"]["min"]+(new_ranges["p"]["min"] % 2)
for p in range(start_p, min(w // 2, new_ranges["p"]["max"])+1, 2):
for l in range(new_ranges["l"]["min"], min(n - k - (w - 2 * p), new_ranges["l"]["max"])+1):
for pl in range(new_ranges["pl"]["min"], min(l//2, new_ranges["pl"]["max"], (w-2*p)//2)+1):
indices = {"p": p, "pl": pl, "l": l,
"r": self._optimal_parameters["r"]}
start_p = new_ranges["p"]["min"] + (new_ranges["p"]["min"] % 2)
for p in range(start_p, min(w // 2, new_ranges["p"]["max"]) + 1, 2):
for l in range(
new_ranges["l"]["min"],
min(n - k - (w - 2 * p), new_ranges["l"]["max"]) + 1,
):
for pl in range(
new_ranges["pl"]["min"],
min(l // 2, new_ranges["pl"]["max"], (w - 2 * p) // 2) + 1,
):
indices = {
"p": p,
"pl": pl,
"l": l,
"r": self._optimal_parameters["r"],
}
if self._are_parameters_invalid(indices):
continue
yield indices

def _time_and_memory_complexity(self, parameters: dict, verbose_information=None):
"""
Computes the expected runtime and memory consumption for a given parameter set.
"""Computes the expected runtime and memory consumption for a given parameter set.
"""
n, k, w = self.problem.get_parameters()
par = SimpleNamespace(**parameters)
Expand Down Expand Up @@ -169,7 +185,5 @@ def _time_and_memory_complexity(self, parameters: dict, verbose_information=None
return time, memory

def __repr__(self):
"""
"""
rep = "Ball Collision estimator for " + str(self.problem)
return rep
Loading
Loading